diff --git a/.changeset/soft-lions-compare.md b/.changeset/soft-lions-compare.md new file mode 100644 index 000000000..758a14eda --- /dev/null +++ b/.changeset/soft-lions-compare.md @@ -0,0 +1,5 @@ +--- +'vite-plugin-kit-routes': patch +--- + +fix: default params in LINKS are now taken into account diff --git a/packages/vite-plugin-kit-routes/src/lib/ROUTES.ts b/packages/vite-plugin-kit-routes/src/lib/ROUTES.ts index 12509f22d..6886ad190 100644 --- a/packages/vite-plugin-kit-routes/src/lib/ROUTES.ts +++ b/packages/vite-plugin-kit-routes/src/lib/ROUTES.ts @@ -38,10 +38,10 @@ export const PAGES = { return `${params?.lang ? `/${params?.lang}` : ''}/site${appendSp({ limit: params.limit })}` }, lang_site_id: ( - params: { lang?: 'fr' | 'hu' | undefined; id?: string; limit?: number; demo?: string } = {}, + params: { lang?: 'fr' | 'hu' | undefined; id?: number; limit?: number; demo?: string } = {}, ) => { params.lang = params.lang ?? 'fr' - params.id = params.id ?? '7' + params.id = params.id ?? 7 return `${params?.lang ? `/${params?.lang}` : ''}/site/${params.id}${appendSp({ limit: params.limit, demo: params.demo, @@ -96,6 +96,7 @@ export const ACTIONS = { extra?: 'A' | 'B' }, ) => { + params.extra = params.extra ?? 'A' return `${params?.lang ? `/${params?.lang}` : ''}/site_contract/${params.siteId}-${ params.contractId }?/${action}${appendSp({ extra: params.extra })}` @@ -104,13 +105,13 @@ export const ACTIONS = { export const LINKS = { twitter: `https:/twitter.com/jycouet`, - mailto: (params: { email: string | number }) => { - return `mailto:${params.email}` + twitter_post: (params: { name: string | number; id: string | number }) => { + return `https:/twitter.com/${params.name}/status/${params.id}` }, - twitter_post: (params: { name: string | number; id: string | number; limit?: number }) => { - return `https:/twitter.com/${params.name}/status/${params.id}${appendSp({ - limit: params.limit, - })}` + gravatar: (params: { id: string; s?: number; d?: 'retro' | 'identicon' }) => { + params.s = params.s ?? 75 + params.d = params.d ?? 'identicon' + return `https:/www.gravatar.com/avatar/${params.id}${appendSp({ s: params.s, d: params.d })}` }, } @@ -146,24 +147,24 @@ export type KIT_ROUTES = { PAGES: { _ROOT: never subGroup: never - subGroup2: 'first' + 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' | 'limit' - lang_site_id: 'lang' | 'id' | 'limit' | 'demo' - lang_site_contract_siteId_contractId: 'lang' | 'siteId' | 'contractId' | 'limit' + lang_site: 'lang' + lang_site_id: 'lang' | 'id' + lang_site_contract_siteId_contractId: 'lang' | 'siteId' | 'contractId' } 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' | 'extra' + lang_site_contract_siteId_contractId: 'lang' | 'siteId' | 'contractId' } - LINKS: { twitter: never; mailto: 'email'; twitter_post: 'name' | 'id' | 'limit' } + LINKS: { twitter: never; twitter_post: 'name' | 'id'; gravatar: 'id' } Params: { first: never lang: never @@ -173,7 +174,8 @@ export type KIT_ROUTES = { siteId: never contractId: never extra: never - email: never name: never + s: never + d: never } } diff --git a/packages/vite-plugin-kit-routes/src/lib/fs.ts b/packages/vite-plugin-kit-routes/src/lib/fs.ts index 97c466dd8..6a4f47fed 100644 --- a/packages/vite-plugin-kit-routes/src/lib/fs.ts +++ b/packages/vite-plugin-kit-routes/src/lib/fs.ts @@ -10,7 +10,10 @@ export function read(pathFile: string) { export function write(pathFile: string, data: string[]) { const fullDataToWrite = Array.isArray(data) ? data.join('\n') : data - createFolderIfNotExists(dirname(pathFile)) + + // createFolderIfNotExists + mkdirSync(dirname(pathFile), { recursive: true }) + // Don't write if nothing changed! if (existsSync(pathFile)) { const currentFileData = read(pathFile) @@ -21,9 +24,3 @@ export function write(pathFile: string, data: string[]) { writeFileSync(join(pathFile), fullDataToWrite) return true } - -function createFolderIfNotExists(dir: string) { - if (!existsSync(dir)) { - mkdirSync(dir, { recursive: true }) - } -} diff --git a/packages/vite-plugin-kit-routes/src/lib/plugin.ts b/packages/vite-plugin-kit-routes/src/lib/plugin.ts index 764c3864e..aa5ee2505 100644 --- a/packages/vite-plugin-kit-routes/src/lib/plugin.ts +++ b/packages/vite-plugin-kit-routes/src/lib/plugin.ts @@ -1,5 +1,5 @@ import { parse } from '@babel/parser' -import { green, Log, red, yellow } from '@kitql/helpers' +import { gray, green, Log, red, yellow } from '@kitql/helpers' import { readdirSync } from 'fs' import { spawn } from 'node:child_process' import * as recast from 'recast' @@ -73,15 +73,18 @@ export type Options = { * // ✅ Twitter * * // reference to link with params! (Like svelteKit routes add [ ] to specify params) - * mailto: 'mailto:[email]', - * // ✅ Mail + * twitter_post: 'https://twitter.com/[name]/status/[id]', + * // ✅ Twitter Post * * // reference to link with params & search params! - * twitter_post: { - * href: 'https://twitter.com/[name]/status/[id]', - * explicit_search_params: { limit: { type: 'number' } } - * } - * // ✅ Twitter Post + * gravatar: { + * href: 'https://www.gravatar.com/avatar/[id]', + * explicit_search_params: { + * s: { type: 'number', default: 75 }, + * d: { type: '"retro" | "identicon"', default: '"identicon"' }, + * }, + * }, + * // ✅ logo * } * } * ``` @@ -112,7 +115,7 @@ export type CustomPath = { * limit: { // name of the search param * required?: true | false, // default: false * type: 'number', // default: 'string | number' - * default: '12', // default: undefined + * default: 12, // default: undefined * } * } */ @@ -123,7 +126,7 @@ export type CustomPath = { * params { * id: { // name of the param (if you set the plugin `kitRoutes`, it will be typed!) * type: 'number', // default: 'string | number' - * default: '12', // default: undefined + * default: 12, // default: undefined * } * } */ @@ -148,7 +151,15 @@ export type OverrideParam = { export type ExtendParam = { type?: string - default?: string + /** + * You have to double escape strings. + * + * @example + * { type: 'number', default: 75 } + * of + * { type: 'string', default: '"jycouet"' } + */ + default?: any } export type ExplicitSearchParam = ExtendParam & { @@ -243,7 +254,14 @@ const getFileKeys = ( }[] } -type Param = { name: string; optional: boolean; matcher?: string; type?: string; default?: string } +type Param = { + name: string + optional: boolean + matcher?: string + type?: string + default?: any + fromPath?: boolean +} export const fileToMetadata = ( original: string, @@ -334,7 +352,12 @@ export const fileToMetadata = ( const explicit_search_params_to_function: string[] = [] if (customConf.explicit_search_params) { Object.entries(customConf.explicit_search_params).forEach(sp => { - paramsFromPath.push({ name: sp[0], optional: !sp[1].required, type: sp[1].type }) + paramsFromPath.push({ + name: sp[0], + optional: !sp[1].required, + type: sp[1].type, + default: sp[1].default, + }) explicit_search_params_to_function.push(`${sp[0]}: params.${sp[0]}`) }) } @@ -374,7 +397,7 @@ export const fileToMetadata = ( // } // } - return `params.${c.name} = params.${c.name} ?? ${additionalByStore}'${c.default}'; ` + return `params.${c.name} = params.${c.name} ?? ${additionalByStore}${c.default}; ` }) let prop = '' @@ -405,11 +428,13 @@ export function extractParamsFromPath(path: string): Param[] { name: matcher[0], optional: isOptional, matcher: matcher[1], + fromPath: true, }) } else { params.push({ name: match[1], optional: isOptional, + fromPath: true, }) } } @@ -602,9 +627,10 @@ ${objTypes return ` ${c.type}: { ${c.files .map(d => { return `'${d.keyToUse}': ${ - d.paramsFromPath.length === 0 + d.paramsFromPath.filter(e => e.fromPath === true).length === 0 ? 'never' : d.paramsFromPath + .filter(e => e.fromPath === true) .map(e => { return `'${e.name}'` }) @@ -711,6 +737,17 @@ ${objTypes child.on('close', code => { if (result) { log.success(`${yellow(generated_file_path(options))} updated`) + // TODO later + // log.info( + // `⚠️ Warning ${yellow(`href="/about"`)} detected ` + + // `in ${gray('/src/lib/component/menu.svelte')} is not safe. ` + + // `You could use: ${green(`href={PAGES['/about']}`)}`, + // ) + // log.info( + // `⚠️ Warning ${yellow(`action="?/save"`)} detected ` + + // `in ${gray('/routes/card/+page.svelte')} is not safe. ` + + // `You could use: ${green(`href={ACTION['/card']('save')}`)}`, + // ) } }) } else { 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 46d57dec8..63474b4ad 100644 --- a/packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts +++ b/packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts @@ -8,6 +8,7 @@ describe('vite-plugin-kit-routes', () => { expect(extractParamsFromPath('/site/[id]')).toMatchInlineSnapshot(` [ { + "fromPath": true, "name": "id", "optional": false, }, @@ -19,10 +20,12 @@ describe('vite-plugin-kit-routes', () => { expect(extractParamsFromPath('/site/[param]/[id]')).toMatchInlineSnapshot(` [ { + "fromPath": true, "name": "param", "optional": false, }, { + "fromPath": true, "name": "id", "optional": false, }, @@ -34,14 +37,17 @@ describe('vite-plugin-kit-routes', () => { expect(extractParamsFromPath('/[param]site/[yop](group)/[id]')).toMatchInlineSnapshot(` [ { + "fromPath": true, "name": "param", "optional": false, }, { + "fromPath": true, "name": "yop", "optional": false, }, { + "fromPath": true, "name": "id", "optional": false, }, @@ -53,6 +59,7 @@ describe('vite-plugin-kit-routes', () => { expect(extractParamsFromPath('/lang/[[lang]]')).toMatchInlineSnapshot(` [ { + "fromPath": true, "name": "lang", "optional": true, }, @@ -149,8 +156,8 @@ describe('vite-plugin-kit-routes', () => { subscriptions_snapshot_id: { explicit_search_params: { limit: { type: 'number' } }, params: { - snapshot: { type: 'string', default: 'snapshot' }, - id: { type: 'string', default: 'id' }, + snapshot: { type: 'string', default: '"snapshot"' }, + id: { type: 'string', default: '"id"' }, }, }, }, @@ -176,12 +183,15 @@ describe('run()', () => { twitter: 'https://twitter.com/jycouet', // reference to link with params! - mailto: 'mailto:[email]', + twitter_post: 'https://twitter.com/[name]/status/[id]', // reference to link with params & search params! - twitter_post: { - href: 'https://twitter.com/[name]/status/[id]', - explicit_search_params: { limit: { type: 'number' } }, + gravatar: { + href: 'https://www.gravatar.com/avatar/[id]', + explicit_search_params: { + s: { type: 'number', default: 75 }, + d: { type: '"retro" | "identicon"', default: '"identicon"' }, + }, }, }, override_params: { @@ -216,8 +226,8 @@ describe('run()', () => { lang_site_id: { explicit_search_params: { limit: { type: 'number' }, demo: { type: 'string' } }, params: { - id: { type: 'string', default: '7' }, - lang: { type: "'fr' | 'hu' | undefined", default: 'fr' }, + id: { type: 'number', default: 7 }, + lang: { type: "'fr' | 'hu' | undefined", default: '"fr"' }, }, }, lang_site_contract_siteId_contractId: { @@ -274,9 +284,9 @@ describe('run()', () => { \\"lang_site\\": (params: {lang?: 'fr' | 'en' | 'hu' | 'at' | string, limit?: number}= {}, sp?: Record) => { return \`\${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 ?? '7'; + \\"lang_site_id\\": (params: {lang?: 'fr' | 'hu' | undefined, id?: number, limit?: number, demo?: string}= {}) => { + params.lang = params.lang ?? \\"fr\\"; + params.id = params.id ?? 7; return \`\${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}) => { @@ -304,17 +314,20 @@ describe('run()', () => { return \`\${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 \`\${params?.lang ? \`/\${params?.lang}\`: ''}/site_contract/\${params.siteId}-\${params.contractId}?/\${action}\${appendSp({ extra: params.extra })}\` } } export const LINKS = { \\"twitter\\": \`https:/twitter.com/jycouet\`, - \\"mailto\\": (params: {email: string | number}) => { - return \`mailto:\${params.email}\` + \\"twitter_post\\": (params: {name: string | number, id: string | number}) => { + return \`https:/twitter.com/\${params.name}/status/\${params.id}\` }, - \\"twitter_post\\": (params: {name: string | number, id: string | number, limit?: number}) => { - return \`https:/twitter.com/\${params.name}/status/\${params.id}\${appendSp({ limit: params.limit })}\` + \\"gravatar\\": (params: {id: string | number, s?: number, d?: \\"retro\\" | \\"identicon\\"}) => { + params.s = params.s ?? 75; + params.d = params.d ?? \\"identicon\\"; + return \`https:/www.gravatar.com/avatar/\${params.id}\${appendSp({ s: params.s, d: params.d })}\` } } @@ -348,11 +361,11 @@ describe('run()', () => { * \`\`\` */ export type KIT_ROUTES = { - PAGES: { '_ROOT': never, 'subGroup': never, 'subGroup2': 'first', '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' | 'limit', 'lang_site_id': 'lang' | 'id' | 'limit' | 'demo', 'lang_site_contract_siteId_contractId': 'lang' | 'siteId' | 'contractId' | 'limit' } + 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' } 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' | 'extra' } - LINKS: { 'twitter': never, 'mailto': 'email', 'twitter_post': 'name' | 'id' | 'limit' } - Params: { first: never, lang: never, id: never, limit: never, demo: never, siteId: never, contractId: never, extra: never, email: never, name: 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': 'id' } + Params: { first: never, lang: never, id: never, limit: never, demo: never, siteId: never, contractId: never, extra: never, name: never, s: never, d: never } } " `) @@ -431,11 +444,13 @@ describe('run()', () => { export const LINKS = { \\"twitter\\": \`https:/twitter.com/jycouet\`, - \\"mailto\\": (params: {email: string | number}) => { - return \`mailto:\${params.email}\` + \\"twitter_post\\": (params: {name: string | number, id: string | number}) => { + return \`https:/twitter.com/\${params.name}/status/\${params.id}\` }, - \\"twitter_post\\": (params: {name: string | number, id: string | number, limit?: number}) => { - return \`https:/twitter.com/\${params.name}/status/\${params.id}\${appendSp({ limit: params.limit })}\` + \\"gravatar\\": (params: {id: string | number, s?: number, d?: \\"retro\\" | \\"identicon\\"}) => { + params.s = params.s ?? 75; + params.d = params.d ?? \\"identicon\\"; + return \`https:/www.gravatar.com/avatar/\${params.id}\${appendSp({ s: params.s, d: params.d })}\` } } @@ -472,8 +487,8 @@ describe('run()', () => { PAGES: { '/': 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' } 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, 'mailto': 'email', 'twitter_post': 'name' | 'id' | 'limit' } - Params: { lang: never, id: never, siteId: never, contractId: never, email: never, name: never, limit: never } + LINKS: { 'twitter': never, 'twitter_post': 'name' | 'id', 'gravatar': 'id' } + Params: { lang: never, id: never, siteId: never, contractId: never, name: never, s: never, d: never } } " `) diff --git a/packages/vite-plugin-kit-routes/src/routes/+layout.svelte b/packages/vite-plugin-kit-routes/src/routes/+layout.svelte index e56fa75a0..683517427 100644 --- a/packages/vite-plugin-kit-routes/src/routes/+layout.svelte +++ b/packages/vite-plugin-kit-routes/src/routes/+layout.svelte @@ -72,12 +72,11 @@ LINKS: TwiX | -Send a mail | -TwiX - + + TwiX Post + +| +demo links
diff --git a/packages/vite-plugin-kit-routes/vite.config.ts b/packages/vite-plugin-kit-routes/vite.config.ts index d3293b231..559572077 100644 --- a/packages/vite-plugin-kit-routes/vite.config.ts +++ b/packages/vite-plugin-kit-routes/vite.config.ts @@ -33,8 +33,8 @@ export default defineConfig({ lang_site_id: { explicit_search_params: { limit: { type: 'number' }, demo: { type: 'string' } }, params: { - id: { type: 'string', default: '7' }, - lang: { type: "'fr' | 'hu' | undefined", default: 'fr' }, + id: { type: 'number', default: 7 }, + lang: { type: "'fr' | 'hu' | undefined", default: '"fr"' }, }, }, lang_site_contract_siteId_contractId: { @@ -50,7 +50,7 @@ export default defineConfig({ ACTIONS: { lang_site_contract_siteId_contractId: { explicit_search_params: { - extra: { type: "'A' | 'B'", default: 'A' }, + extra: { type: "'A' | 'B'", default: '"A"' }, }, }, }, @@ -59,12 +59,18 @@ export default defineConfig({ twitter: 'https://twitter.com/jycouet', // reference to link with params! - mailto: 'mailto:[email]', + twitter_post: 'https://twitter.com/[name]/status/[id]', // reference to link with params & search params! - twitter_post: { - href: 'https://twitter.com/[name]/status/[id]', - explicit_search_params: { limit: { type: 'number' } }, + gravatar: { + href: 'https://www.gravatar.com/avatar/[id]', + params: { + id: { type: 'string' }, + }, + explicit_search_params: { + s: { type: 'number', default: 75 }, + d: { type: '"retro" | "identicon"', default: '"identicon"' }, + }, }, }, diff --git a/website/src/pages/docs/tools/06_vite-plugin-kit-routes.mdx b/website/src/pages/docs/tools/06_vite-plugin-kit-routes.mdx index f6c0a63cb..df4ca84f8 100644 --- a/website/src/pages/docs/tools/06_vite-plugin-kit-routes.mdx +++ b/website/src/pages/docs/tools/06_vite-plugin-kit-routes.mdx @@ -83,10 +83,10 @@ available in your `$lib/ROUTES.ts` generated file _(always in sync)_. -Send me a mail +Twitter -Send me a mail +Twitter ``` ```svelte filename="LINKS - with params & search params*" {2, 11} @@ -140,7 +140,7 @@ your `+page.svelte` | `+server.ts` | `+page.server.ts`. You can make use of `ctrl + space` to discover config options. 🎉 -- What kind of person are you: `PAGES['/terms']` or `PAGES.terms` ? +- What kind of person are you: `PAGES['/info/terms']` or `PAGES.info_terms` ? _You can choose anyway_ 😜 @@ -210,15 +210,18 @@ kitRoutes({ // ✅ Twitter // reference to link with params! (Like svelteKit routes add [ ] to specify params) - mailto: 'mailto:[email]', - // ✅ Mail + twitter_post: 'https://twitter.com/[name]/status/[id]', + // ✅ Twitter Post // reference to link with params & search params! - twitter_post: { - href: 'https://twitter.com/[name]/status/[id]', - explicit_search_params: { limit: { type: 'number' } } + gravatar: { + href: 'https://www.gravatar.com/avatar/[id]', + explicit_search_params: { + s: { type: 'number', default: 75 }, + d: { type: '"retro" | "identicon"', default: '"identicon"' } + } } - // ✅ Twitter Post + // ✅ logo } }) ```