diff --git a/playground/components/SearchExperience.vue b/playground/components/SearchExperience.vue index fbe197f..de764a3 100644 --- a/playground/components/SearchExperience.vue +++ b/playground/components/SearchExperience.vue @@ -1,5 +1,16 @@ diff --git a/src/runtime/composables/useAisRouter.ts b/src/runtime/composables/useAisRouter.ts index bf0ab98..1e6b2ce 100644 --- a/src/runtime/composables/useAisRouter.ts +++ b/src/runtime/composables/useAisRouter.ts @@ -2,19 +2,64 @@ import { useRouter, useNuxtApp } from "nuxt/app"; import { ref } from "vue"; import type { Ref } from "vue"; import type { RouterProps } from "instantsearch.js/es/middlewares"; +import { parseURL, parseQuery, type ParsedQuery } from "ufo" +import type { LocationQuery } from "#vue-router"; -function stripUndefined(obj: Record) { +type QueryObject = { + [x:string]: QueryObject | string | string[] | number | boolean +} + +const stripUndefined = (obj: Record) => { return Object.fromEntries( - Object.entries(obj).filter(([k, v]) => v !== undefined), - ); + Object.entries(obj).filter(([k, v]) => v !== undefined) + ) } + +const convertToNestedObject = (query: ParsedQuery): QueryObject => { + const result: QueryObject = {} + + Object.keys(query).forEach(key => { + const value = query[key] + const keys = key.split(/[[\]]+/).filter(k => k) + + let currentLevel: QueryObject = result + + keys.forEach((k, index) => { + if (index === keys.length - 1) { + currentLevel[k] = value + } else { + if (!currentLevel[k]) { + // @ts-ignore + currentLevel[k] = isNaN(keys[index + 1]) ? {} : [] + } + // @ts-ignore + currentLevel = currentLevel[k] + } + }); + }); + + return result +} + +const containsBrackets = (obj: LocationQuery) => { + return Object.keys(obj).some(key => key.includes('[') || key.includes(']')) +} + export const useAisRouter = () => { const router = useRouter(); const app = useNuxtApp(); const algoliaRouter: Ref, "router">> = ref({ router: { read() { - const query = router.currentRoute.value.query; + const currentRoute = router.currentRoute.value + let query + if(containsBrackets(currentRoute.query)){ + const urlParsed = parseURL(currentRoute.fullPath) + const queryParsed = parseQuery(urlParsed.search) + query = convertToNestedObject(queryParsed) + } else { + query = currentRoute.query + } const normalizedQuery = Array.isArray(query) ? query[0] : query; return stripUndefined(normalizedQuery); },