diff --git a/packages/vite-plugin-kit-routes/src/lib/plugin.ts b/packages/vite-plugin-kit-routes/src/lib/plugin.ts index b6f21f54..ebb9e395 100644 --- a/packages/vite-plugin-kit-routes/src/lib/plugin.ts +++ b/packages/vite-plugin-kit-routes/src/lib/plugin.ts @@ -1049,7 +1049,8 @@ ${objTypes return false } -const dolLib = ['$', 'lib'].join('') +// eslint-disable-next-line +let dolLib = ['$', 'lib'].join('') function theEnd( atStart: boolean, diff --git a/packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts b/packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts index 20743088..256fc8fc 100644 --- a/packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts +++ b/packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts @@ -839,6 +839,16 @@ describe('run()', async () => { expect(read(generated_file_path)?.includes("import { base } from '$app/paths'")).toBe(true) expect(read(generated_file_path)?.includes('${base}')).toBe(true) }) + + it('with router hash', async () => { + const generated_file_path = 'src/test/ROUTES_hash.ts' + await run(false, { + generated_file_path, + router_type: 'hash', + }) + + expect(read(generated_file_path)?.includes(`"/": \`#/\``)).toBe(true) + }) }) describe('options', () => { diff --git a/packages/vite-plugin-kit-routes/src/routes/[[lang]]/contract/[id]/+page.svelte b/packages/vite-plugin-kit-routes/src/routes/[[lang]]/contract/[id]/+page.svelte index 336be4b2..fe224946 100644 --- a/packages/vite-plugin-kit-routes/src/routes/[[lang]]/contract/[id]/+page.svelte +++ b/packages/vite-plugin-kit-routes/src/routes/[[lang]]/contract/[id]/+page.svelte @@ -5,10 +5,10 @@ import { route } from '$lib/ROUTES.js' interface Props { - form: FormData; + form: FormData } - let { form }: Props = $props(); + let { form }: Props = $props() const id = $page.params.id diff --git a/packages/vite-plugin-kit-routes/src/routes/[[lang]]/site_contract/[siteId]-[contractId]/+page.svelte b/packages/vite-plugin-kit-routes/src/routes/[[lang]]/site_contract/[siteId]-[contractId]/+page.svelte index 373bdbdf..d7cff21b 100644 --- a/packages/vite-plugin-kit-routes/src/routes/[[lang]]/site_contract/[siteId]-[contractId]/+page.svelte +++ b/packages/vite-plugin-kit-routes/src/routes/[[lang]]/site_contract/[siteId]-[contractId]/+page.svelte @@ -5,10 +5,10 @@ import { route } from '$lib/ROUTES.js' interface Props { - form: FormData; + form: FormData } - let { form }: Props = $props(); + let { form }: Props = $props() const siteId = $page.params.siteId const contractId = $page.params.contractId diff --git a/packages/vite-plugin-kit-routes/src/test/ROUTES_hash.ts b/packages/vite-plugin-kit-routes/src/test/ROUTES_hash.ts new file mode 100644 index 00000000..06ae2e7e --- /dev/null +++ b/packages/vite-plugin-kit-routes/src/test/ROUTES_hash.ts @@ -0,0 +1,213 @@ +/* eslint-disable */ +/** + * This file was generated by 'vite-plugin-kit-routes' + * + * >> DO NOT EDIT THIS FILE MANUALLY << + */ + +/** + * PAGES + */ +const PAGES = { + "/": `#/`, + "/subGroup": `#/subGroup`, + "/subGroup/user": `#/subGroup/user`, + "/subGroup2": `#/subGroup2`, + "/contract": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/contract` + }, + "/contract/[id]": (params: { id: (string | number), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/contract/${params.id}` + }, + "/gp/one": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/gp/one` + }, + "/gp/two": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/gp/two` + }, + "/main": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/main` + }, + "/match/[id=ab]": (params: { id: (Parameters[0]), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/match/${params.id}` + }, + "/match/[id=int]": (params: { id: (Parameters[0]), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/match/${params.id}` + }, + "/site": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site` + }, + "/site/[id]": (params: { id: (string | number), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site/${params.id}` + }, + "/site_contract/[siteId]-[contractId]": (params: { siteId: (string | number), contractId: (string | number), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site_contract/${params.siteId}-${params.contractId}` + }, + "/a/[...rest]/z": (params: { rest: (string | number)[] }) => { + return `#/a/${params.rest?.join('/')}/z` + }, + "/lay/normal": `#/lay/normal`, + "/lay/root-layout": `#/lay/root-layout`, + "/lay/skip": `#/lay/skip`, + "/sp": `#/sp`, + "/spArray": `#/spArray`, + "/spArrayComma": `#/spArrayComma` +} + +/** + * SERVERS + */ +const SERVERS = { + "GET /server_func_get": `#/server_func_get`, + "GET /server_func_get_and_": `#/server_func_get_and_`, + "POST /server_func_post": `#/server_func_post`, + "GET /contract": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/contract` + }, + "POST /contract": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/contract` + }, + "GET /site": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site` + }, + "GET /api/graphql": `#/api/graphql`, + "POST /api/graphql": `#/api/graphql`, + "GET /data/errors/[locale].json": (params: { locale: (string | number) }) => { + return `#/data/errors/${params.locale}.json` + } +} + +/** + * ACTIONS + */ +const ACTIONS = { + "default /contract/[id]": (params: { id: (string | number), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/contract/${params.id}` + }, + "create /site": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site?/create` + }, + "update /site/[id]": (params: { id: (string | number), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site/${params.id}?/update` + }, + "delete /site/[id]": (params: { id: (string | number), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site/${params.id}?/delete` + }, + "noSatisfies /site_contract": (params?: { lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site_contract?/noSatisfies` + }, + "send /site_contract/[siteId]-[contractId]": (params: { siteId: (string | number), contractId: (string | number), lang?: (string | number) }) => { + return `#${params?.lang ? `/${params?.lang}`: ''}/site_contract/${params.siteId}-${params.contractId}?/send` + } +} + +/** + * LINKS + */ +const LINKS = { + +} + +type ParamValue = string | number | undefined + +/** + * Append search params to a string + */ +export const appendSp = (sp?: Record, prefix: '?' | '&' = '?') => { + if (sp === undefined) return '' + + const params = new URLSearchParams() + const append = (n: string, v: ParamValue) => { + if (v !== undefined) { + params.append(n, String(v)) + } + } + + for (const [name, val] of Object.entries(sp)) { + if (Array.isArray(val)) { + for (const v of val) { + append(name, v) + } + } else { + append(name, val) + } + } + + const formatted = params.toString() + if (formatted) { + return `${prefix}${formatted}` + } + return '' +} + +/** + * get the current search params + * + * Could be use like this: + * ``` + * route("/cities", { page: 2 }, { ...currentSP() }) + * ``` + */ +export const currentSp = () => { + const params = new URLSearchParams(window.location.search) + const record: Record = {} + for (const [key, value] of params.entries()) { + record[key] = value + } + return record +} + +// route function helpers +type NonFunctionKeys = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T] +type FunctionKeys = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T] +type FunctionParams = T extends (...args: infer P) => any ? P : never + +const AllObjs = { ...PAGES, ...ACTIONS, ...SERVERS, ...LINKS } +type AllTypes = typeof AllObjs + +export type Routes = keyof AllTypes extends `${string}/${infer Route}` ? `/${Route}` : keyof AllTypes +export const routes = [ + ...new Set(Object.keys(AllObjs).map((route) => /^\/.*|[^ ]?\/.*$/.exec(route)?.[0] ?? route)), +] as Routes[] + +/** + * To be used like this: + * ```ts + * import { route } from '$lib/ROUTES' + * + * route('site_id', { id: 1 }) + * ``` + */ +export function route>(key: T, ...params: FunctionParams): string +export function route>(key: T): string +export function route(key: T, ...params: any[]): string { + if (AllObjs[key] as any instanceof Function) { + const element = (AllObjs as any)[key] as (...args: any[]) => string + return element(...params) + } else { + return AllObjs[key] as string + } +} + +/** +* Add this type as a generic of the vite plugin `kitRoutes`. +* +* Full example: +* ```ts +* import type { KIT_ROUTES } from '$lib/ROUTES' +* import { kitRoutes } from 'vite-plugin-kit-routes' +* +* kitRoutes({ +* PAGES: { +* // here, key of object will be typed! +* } +* }) +* ``` +*/ +export type KIT_ROUTES = { + PAGES: { '/': never, '/subGroup': never, '/subGroup/user': never, '/subGroup2': never, '/contract': 'lang', '/contract/[id]': 'id' | 'lang', '/gp/one': 'lang', '/gp/two': 'lang', '/main': 'lang', '/match/[id=ab]': 'id' | 'lang', '/match/[id=int]': 'id' | 'lang', '/site': 'lang', '/site/[id]': 'id' | 'lang', '/site_contract/[siteId]-[contractId]': 'siteId' | 'contractId' | 'lang', '/a/[...rest]/z': 'rest', '/lay/normal': never, '/lay/root-layout': never, '/lay/skip': never, '/sp': never, '/spArray': never, '/spArrayComma': never } + SERVERS: { 'GET /server_func_get': never, 'GET /server_func_get_and_': never, 'POST /server_func_post': never, 'GET /contract': 'lang', 'POST /contract': 'lang', 'GET /site': 'lang', 'GET /api/graphql': never, 'POST /api/graphql': never, 'GET /data/errors/[locale].json': 'locale' } + ACTIONS: { 'default /contract/[id]': 'id' | 'lang', 'create /site': 'lang', 'update /site/[id]': 'id' | 'lang', 'delete /site/[id]': 'id' | 'lang', 'noSatisfies /site_contract': 'lang', 'send /site_contract/[siteId]-[contractId]': 'siteId' | 'contractId' | 'lang' } + LINKS: Record + Params: { lang: never, id: never, siteId: never, contractId: never, rest: never, locale: never } +}