From aa80fe8cc03ab5b736de33baa7ed324b683c1ad5 Mon Sep 17 00:00:00 2001 From: jycouet Date: Sat, 25 Nov 2023 13:07:28 +0100 Subject: [PATCH] :sparkles: NEW: add path_base management with a boolean to use $app/paths as a prefix or not --- .changeset/thick-colts-listen.md | 5 + .../vite-plugin-kit-routes/src/lib/plugin.ts | 30 +- .../src/lib/plugins.spec.ts | 352 +++++++++++++++++- .../vite-plugin-kit-routes/svelte.config.js | 3 + .../vite-plugin-kit-routes/vite.config.ts | 1 + 5 files changed, 387 insertions(+), 4 deletions(-) create mode 100644 .changeset/thick-colts-listen.md diff --git a/.changeset/thick-colts-listen.md b/.changeset/thick-colts-listen.md new file mode 100644 index 000000000..75915d603 --- /dev/null +++ b/.changeset/thick-colts-listen.md @@ -0,0 +1,5 @@ +--- +'vite-plugin-kit-routes': patch +--- + +add path_base management with a boolean to use $app/paths as a prefix or not diff --git a/packages/vite-plugin-kit-routes/src/lib/plugin.ts b/packages/vite-plugin-kit-routes/src/lib/plugin.ts index 7b1768323..801bed14f 100644 --- a/packages/vite-plugin-kit-routes/src/lib/plugin.ts +++ b/packages/vite-plugin-kit-routes/src/lib/plugin.ts @@ -56,6 +56,28 @@ export type Options = { */ default_type?: string + /** + * In case you have set a `base` in your `svelte.config.js`, you can set `path_base: true` + * to have it in your routes. + * + * FYI, in your `svelte.config.js`: + * ```js + * const config = { + * kit: { + * adapter: adapter(), + * paths: { + * base: '/yop', + * } + * } + * } + * + * export default config + * ``` + * + * @default false + */ + path_base?: boolean + /** * when `without` _(default)_, paths doesn't get a last argument to set extra search params * @@ -396,15 +418,17 @@ export const fileToMetadata = ( return `params.${c.name} = params.${c.name} ?? ${c.default}; ` }) + const pathBaesStr = options?.path_base ? '${base}' : '' + let prop = '' if (params.length > 0) { prop = `"${keyToUse}": (${params.join(', ')}) => ` + ` {${paramsDefaults.length > 0 ? `\n ${paramsDefaults.join('\n ')}` : ''} - return \`${toRet}${actionsFormat}${fullSP}\` + return \`${pathBaesStr}${toRet}${actionsFormat}${fullSP}\` }` } else { - prop = `"${keyToUse}": \`${toRet}\`` + prop = `"${keyToUse}": \`${pathBaesStr}${toRet}\`` } return { keyToUse, prop, paramsFromPath } @@ -603,7 +627,7 @@ export const run = (options?: Options) => { * This file was generated by 'vite-plugin-kit-routes' * * >> DO NOT EDIT THIS FILE MANUALLY << - */ + */${options?.path_base ? `\nimport { base } from '$app/paths'` : ''} `, // consts options?.format === 'variables' 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 4603aaa17..7ac7b33b8 100644 --- a/packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts +++ b/packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts @@ -513,11 +513,361 @@ describe('run()', () => { `) }) - it('post_update_run', () => { + it('style variables', () => { const generated_file_path = 'src/test/ROUTES_test3.ts' + run({ + generated_file_path, + format: 'variables', + PAGES: { + subGroup2: { + explicit_search_params: { + first: { + required: true, + }, + }, + }, + lang_contract: { + extra_search_params: 'with', + }, + lang_site: { + // extra_search_params: 'with', + explicit_search_params: { limit: { type: 'number' } }, + params: { + // yop: { type: 'number' }, + }, + extra_search_params: 'with', + }, + lang_site_id: { + explicit_search_params: { limit: { type: 'number' }, demo: { type: 'string' } }, + params: { + id: { type: 'string', default: '"Vienna"' }, + lang: { type: "'fr' | 'hu' | undefined", default: '"fr"' }, + }, + }, + lang_site_contract_siteId_contractId: { + explicit_search_params: { limit: { type: 'number' } }, + }, + }, + SERVERS: { + // site: { + // params: { } + // } + // yop: {}, + }, + ACTIONS: { + lang_site_contract_siteId_contractId: { + explicit_search_params: { + extra: { type: "'A' | 'B'", default: '"A"' }, + }, + }, + }, + ...commonConfig, + }) + + expect(read(generated_file_path)).toMatchInlineSnapshot(` + "/** + * This file was generated by 'vite-plugin-kit-routes' + * + * >> DO NOT EDIT THIS FILE MANUALLY << + */ + + export const PAGES__ROOT = \`/\` + export const PAGES_subGroup = \`/subGroup\` + export const PAGES_subGroup2 = (params: {first: (string | number)}) => { + return \`/subGroup2\${appendSp({ first: params.first })}\` + } + export const PAGES_lang_contract = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}, sp?: Record) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/contract\${appendSp(sp)}\` + } + export const PAGES_lang_contract_id = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), id: (string | number)}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/contract/\${params.id}\` + } + export const PAGES_lang_gp_one = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/gp/one\` + } + export const PAGES_lang_gp_two = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/gp/two\` + } + export const PAGES_lang_main = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/main\` + } + export const PAGES_lang_match_id_int = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), id: (string | number)}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/match/\${params.id}\` + } + export const PAGES_lang_site = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), limit?: (number)}= {}, sp?: Record) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/site\${appendSp({...sp, limit: params.limit })}\` + } + export const PAGES_lang_site_id = (params: {lang?: ('fr' | 'hu' | undefined), id?: (string), limit?: (number), demo?: (string)}= {}) => { + params.lang = params.lang ?? \\"fr\\"; + params.id = params.id ?? \\"Vienna\\"; + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/site/\${params.id}\${appendSp({ limit: params.limit, demo: params.demo })}\` + } + export const PAGES_lang_site_contract_siteId_contractId = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), siteId: (string | number), contractId: (string | number), limit?: (number)}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/site_contract/\${params.siteId}-\${params.contractId}\${appendSp({ limit: params.limit })}\` + } + export const PAGES_a_rest_z = (params: {rest: (string | number)[]}) => { + return \`/a/\${params.rest?.join('/')}/z\` + } + export const PAGES_lay_normal = \`/lay/normal\` + export const PAGES_lay_root_layout = \`/lay/root-layout\` + export const PAGES_lay_skip = \`/lay/skip\` + + export const SERVERS_lang_contract = (method: 'GET' | 'POST', params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/contract\` + } + export const SERVERS_lang_site = (method: 'GET', params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/site\` + } + export const SERVERS_api_graphql = (method: 'GET' | 'POST') => { + return \`/api/graphql\` + } + + export const ACTIONS_lang_contract_id = (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), id: (string | number)}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/contract/\${params.id}\` + } + export const ACTIONS_lang_site = (action: 'action1' | 'action2', params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/site?/\${action}\` + } + export const ACTIONS_lang_site_contract_siteId_contractId = (action: 'sendSomething', params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), siteId: (string | number), contractId: (string | number), extra?: ('A' | 'B')}) => { + params.extra = params.extra ?? \\"A\\"; + return \`\${params?.lang ? \`/\${params?.lang}\`: ''}/site_contract/\${params.siteId}-\${params.contractId}?/\${action}\${appendSp({ extra: params.extra })}\` + } + + export const LINKS_twitter = \`https:/twitter.com/jycouet\` + export const LINKS_twitter_post = (params: {name: (string | number), id: (string | number)}) => { + return \`https:/twitter.com/\${params.name}/status/\${params.id}\` + } + export const LINKS_gravatar = (params: {str: (string | number), s?: (number), d?: (\\"retro\\" | \\"identicon\\")}) => { + params.s = params.s ?? 75; + params.d = params.d ?? \\"identicon\\"; + return \`https:/www.gravatar.com/avatar/\${params.str}\${appendSp({ s: params.s, d: params.d })}\` + } + + const appendSp = (sp?: Record) => { + if (sp === undefined) return '' + const mapping = Object.entries(sp) + .filter(c => c[1] !== undefined) + .map(c => [c[0], String(c[1])]) + + const formated = new URLSearchParams(mapping).toString() + if (formated) { + return \`?\${formated}\` + } + return '' + } + + + /** + * 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, \\"paths\\" it will be typed! + * } + * }) + * \`\`\` + */ + export type KIT_ROUTES = { + PAGES: { '_ROOT': never, 'subGroup': never, 'subGroup2': never, 'lang_contract': 'lang', 'lang_contract_id': 'lang' | 'id', 'lang_gp_one': 'lang', 'lang_gp_two': 'lang', 'lang_main': 'lang', 'lang_match_id_int': 'lang' | 'id', 'lang_site': 'lang', 'lang_site_id': 'lang' | 'id', 'lang_site_contract_siteId_contractId': 'lang' | 'siteId' | 'contractId', 'a_rest_z': 'rest', 'lay_normal': never, 'lay_root_layout': never, 'lay_skip': never } + SERVERS: { 'lang_contract': 'lang', 'lang_site': 'lang', 'api_graphql': never } + ACTIONS: { 'lang_contract_id': 'lang' | 'id', 'lang_site': 'lang', 'lang_site_contract_siteId_contractId': 'lang' | 'siteId' | 'contractId' } + LINKS: { 'twitter': never, 'twitter_post': 'name' | 'id', 'gravatar': 'str' } + Params: { first: never, lang: never, id: never, limit: never, demo: never, siteId: never, contractId: never, rest: never, extra: never, name: never, str: never, s: never, d: never } + } + " + `) + }) + + it('post_update_run', () => { + const generated_file_path = 'src/test/ROUTES_test4.ts' run({ generated_file_path, post_update_run: 'echo done', }) }) + + it('with_ase', () => { + const generated_file_path = 'src/test/ROUTES_test5.ts' + run({ + generated_file_path, + format: '_', + path_base: true, + PAGES: { + subGroup2: { + explicit_search_params: { + first: { + required: true, + }, + }, + }, + lang_contract: { + extra_search_params: 'with', + }, + lang_site: { + // extra_search_params: 'with', + explicit_search_params: { limit: { type: 'number' } }, + params: { + // yop: { type: 'number' }, + }, + extra_search_params: 'with', + }, + lang_site_id: { + explicit_search_params: { limit: { type: 'number' }, demo: { type: 'string' } }, + params: { + id: { type: 'string', default: '"Vienna"' }, + lang: { type: "'fr' | 'hu' | undefined", default: '"fr"' }, + }, + }, + lang_site_contract_siteId_contractId: { + explicit_search_params: { limit: { type: 'number' } }, + }, + }, + SERVERS: { + // site: { + // params: { } + // } + // yop: {}, + }, + ACTIONS: { + lang_site_contract_siteId_contractId: { + explicit_search_params: { + extra: { type: "'A' | 'B'", default: '"A"' }, + }, + }, + }, + ...commonConfig, + }) + + expect(read(generated_file_path)).toMatchInlineSnapshot(` + "/** + * This file was generated by 'vite-plugin-kit-routes' + * + * >> DO NOT EDIT THIS FILE MANUALLY << + */ + import { base } from '$app/paths' + + export const PAGES = { + \\"_ROOT\\": \`\${base}/\`, + \\"subGroup\\": \`\${base}/subGroup\`, + \\"subGroup2\\": (params: {first: (string | number)}) => { + return \`\${base}/subGroup2\${appendSp({ first: params.first })}\` + }, + \\"lang_contract\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}, sp?: Record) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/contract\${appendSp(sp)}\` + }, + \\"lang_contract_id\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), id: (string | number)}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/contract/\${params.id}\` + }, + \\"lang_gp_one\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/gp/one\` + }, + \\"lang_gp_two\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/gp/two\` + }, + \\"lang_main\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/main\` + }, + \\"lang_match_id_int\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), id: (string | number)}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/match/\${params.id}\` + }, + \\"lang_site\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), limit?: (number)}= {}, sp?: Record) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/site\${appendSp({...sp, limit: params.limit })}\` + }, + \\"lang_site_id\\": (params: {lang?: ('fr' | 'hu' | undefined), id?: (string), limit?: (number), demo?: (string)}= {}) => { + params.lang = params.lang ?? \\"fr\\"; + params.id = params.id ?? \\"Vienna\\"; + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/site/\${params.id}\${appendSp({ limit: params.limit, demo: params.demo })}\` + }, + \\"lang_site_contract_siteId_contractId\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), siteId: (string | number), contractId: (string | number), limit?: (number)}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/site_contract/\${params.siteId}-\${params.contractId}\${appendSp({ limit: params.limit })}\` + }, + \\"a_rest_z\\": (params: {rest: (string | number)[]}) => { + return \`\${base}/a/\${params.rest?.join('/')}/z\` + }, + \\"lay_normal\\": \`\${base}/lay/normal\`, + \\"lay_root_layout\\": \`\${base}/lay/root-layout\`, + \\"lay_skip\\": \`\${base}/lay/skip\` + } + + export const SERVERS = { + \\"lang_contract\\": (method: 'GET' | 'POST', params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/contract\` + }, + \\"lang_site\\": (method: 'GET', params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/site\` + }, + \\"api_graphql\\": (method: 'GET' | 'POST') => { + return \`\${base}/api/graphql\` + } + } + + export const ACTIONS = { + \\"lang_contract_id\\": (params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), id: (string | number)}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/contract/\${params.id}\` + }, + \\"lang_site\\": (action: 'action1' | 'action2', params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string)}= {}) => { + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/site?/\${action}\` + }, + \\"lang_site_contract_siteId_contractId\\": (action: 'sendSomething', params: {lang?: ('fr' | 'en' | 'hu' | 'at' | string), siteId: (string | number), contractId: (string | number), extra?: ('A' | 'B')}) => { + params.extra = params.extra ?? \\"A\\"; + return \`\${base}\${params?.lang ? \`/\${params?.lang}\`: ''}/site_contract/\${params.siteId}-\${params.contractId}?/\${action}\${appendSp({ extra: params.extra })}\` + } + } + + export const LINKS = { + \\"twitter\\": \`\${base}https:/twitter.com/jycouet\`, + \\"twitter_post\\": (params: {name: (string | number), id: (string | number)}) => { + return \`\${base}https:/twitter.com/\${params.name}/status/\${params.id}\` + }, + \\"gravatar\\": (params: {str: (string | number), s?: (number), d?: (\\"retro\\" | \\"identicon\\")}) => { + params.s = params.s ?? 75; + params.d = params.d ?? \\"identicon\\"; + return \`\${base}https:/www.gravatar.com/avatar/\${params.str}\${appendSp({ s: params.s, d: params.d })}\` + } + } + + const appendSp = (sp?: Record) => { + if (sp === undefined) return '' + const mapping = Object.entries(sp) + .filter(c => c[1] !== undefined) + .map(c => [c[0], String(c[1])]) + + const formated = new URLSearchParams(mapping).toString() + if (formated) { + return \`?\${formated}\` + } + return '' + } + + + /** + * 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, \\"paths\\" it will be typed! + * } + * }) + * \`\`\` + */ + export type KIT_ROUTES = { + PAGES: { '_ROOT': never, 'subGroup': never, 'subGroup2': never, 'lang_contract': 'lang', 'lang_contract_id': 'lang' | 'id', 'lang_gp_one': 'lang', 'lang_gp_two': 'lang', 'lang_main': 'lang', 'lang_match_id_int': 'lang' | 'id', 'lang_site': 'lang', 'lang_site_id': 'lang' | 'id', 'lang_site_contract_siteId_contractId': 'lang' | 'siteId' | 'contractId', 'a_rest_z': 'rest', 'lay_normal': never, 'lay_root_layout': never, 'lay_skip': never } + SERVERS: { 'lang_contract': 'lang', 'lang_site': 'lang', 'api_graphql': never } + ACTIONS: { 'lang_contract_id': 'lang' | 'id', 'lang_site': 'lang', 'lang_site_contract_siteId_contractId': 'lang' | 'siteId' | 'contractId' } + LINKS: { 'twitter': never, 'twitter_post': 'name' | 'id', 'gravatar': 'str' } + Params: { first: never, lang: never, id: never, limit: never, demo: never, siteId: never, contractId: never, rest: never, extra: never, name: never, str: never, s: never, d: never } + } + " + `) + }) }) diff --git a/packages/vite-plugin-kit-routes/svelte.config.js b/packages/vite-plugin-kit-routes/svelte.config.js index 18b471666..f606f0baa 100644 --- a/packages/vite-plugin-kit-routes/svelte.config.js +++ b/packages/vite-plugin-kit-routes/svelte.config.js @@ -12,6 +12,9 @@ const config = { // If your environment is not supported or you settled on a specific environment, switch out the adapter. // See https://kit.svelte.dev/docs/adapters for more information about adapters. adapter: adapter(), + // paths: { + // base: '/yop', + // }, }, } diff --git a/packages/vite-plugin-kit-routes/vite.config.ts b/packages/vite-plugin-kit-routes/vite.config.ts index 2dc6dd526..2e824bfc5 100644 --- a/packages/vite-plugin-kit-routes/vite.config.ts +++ b/packages/vite-plugin-kit-routes/vite.config.ts @@ -11,6 +11,7 @@ export default defineConfig({ kitRoutes({ format: '_', logs: ['update', 'errors'], + // path_base: true, // default_type: 'string', // extra_search_params: 'with', // generated_file_path: 'src/lib/another_path_for_the_file.ts',