Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/brown-icons-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vite-plugin-kit-routes': patch
---

fix ensurePrefix on ROOT
5 changes: 5 additions & 0 deletions .changeset/heavy-moose-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vite-plugin-kit-routes': patch
---

add generic types to the plugin
53 changes: 50 additions & 3 deletions packages/vite-plugin-kit-routes/src/lib/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

export const PAGES = {
_ROOT: () => {
return `/`
return ensurePrefix(`/`)
},
contract: () => {
return `/contract`
Expand Down Expand Up @@ -59,9 +59,11 @@ export const ACTIONS = {
},
site_contract_siteId_contractId: (
action: 'sendSomething',
params: { siteId: string | number; contractId: string | number },
params: { siteId: string | number; contractId: string | number; extra?: 'A' | 'B' },
) => {
return `/site_contract/${params.siteId}-${params.contractId}?/${action}`
return `/site_contract/${params.siteId}-${params.contractId}?/${action}${appendSp({
extra: params.extra,
})}`
},
}

Expand All @@ -77,3 +79,48 @@ const appendSp = (sp?: Record<string, string | number | undefined>) => {
}
return ''
}

const ensurePrefix = (str: string) => {
if (str.startsWith('/')) {
return str
}
return `/${str}`
}

/**
* Add this type as a generic of the vite plugin `kitRoutes<ROUTES>`.
*
* Full example:
* ```ts
* import type { ROUTES } from '$lib/ROUTES'
* import { kitRoutes } from 'vite-plugin-kit-routes'
*
* kitRoutes<ROUTES>({
* extend: {
* PAGES: {
* // here, "paths" it will be typed!
* }
* }
* })
* ```
*/
export type ROUTES = {
PAGES: {
_ROOT: never
contract: never
contract_id: 'id'
gp_logged_one: never
gp_public_two: never
lang_lang: 'lang'
match_id_int: 'id'
site: 'limit'
site_id: 'id' | 'limit'
site_contract_siteId_contractId: 'siteId' | 'contractId'
}
SERVERS: { contract: never; site: never }
ACTIONS: {
contract_id: 'id'
site: never
site_contract_siteId_contractId: 'siteId' | 'contractId' | 'extra'
}
}
139 changes: 115 additions & 24 deletions packages/vite-plugin-kit-routes/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@ import { read, write } from './fs.js'

const { visit } = recast.types

export type Options = {
export type Options<
T extends {
PAGES: Record<string, string>
SERVERS: Record<string, string>
ACTIONS: Record<string, string>
} = {
PAGES: Record<string, string>
SERVERS: Record<string, string>
ACTIONS: Record<string, string>
},
> = {
/**
* run command after file updated
*
Expand Down Expand Up @@ -47,15 +57,15 @@ export type Options = {
extra_search_params?: 'with' | 'without'

extend?: {
PAGES?: Record<string, CustomPath>
SERVERS?: Record<string, CustomPath>
ACTIONS?: Record<string, CustomPath>
PAGES?: Partial<{ [K in keyof T['PAGES']]: CustomPath<Extract<T['PAGES'][K], string>> }>
SERVERS?: Partial<{ [K in keyof T['SERVERS']]: CustomPath<Extract<T['SERVERS'][K], string>> }>
ACTIONS?: Partial<{ [K in keyof T['ACTIONS']]: CustomPath<Extract<T['ACTIONS'][K], string>> }>
}
}

export type CustomPath = {
export type CustomPath<Params extends string | never = string> = {
explicit_search_params?: Record<string, ExplicitSearchParam>
params?: Record<string, ExtendParam>
params?: Partial<Record<Params, ExtendParam>>
extra_search_params?: 'default' | 'with' | 'without'
}

Expand Down Expand Up @@ -136,8 +146,7 @@ export const fileToMetadata = (
options: Options | undefined,
useWithAppendSp: boolean | undefined,
) => {
const href = original.replace(/\([^)]*\)/g, '').replace(/\/+/g, '/')
let toRet = href
let toRet = original.replace(/\([^)]*\)/g, '').replace(/\/+/g, '/')

const keyToUse = formatKey(original, options)

Expand All @@ -147,6 +156,7 @@ export const fileToMetadata = (
extra_search_params: 'default',
}
if (viteCustomPathConfig && viteCustomPathConfig[keyToUse]) {
// @ts-expect-error
customConf = viteCustomPathConfig[keyToUse]
}

Expand All @@ -157,10 +167,10 @@ export const fileToMetadata = (
Object.entries(customConf.params).forEach(sp => {
for (let i = 0; i < paramsFromPath.length; i++) {
if (paramsFromPath[i].name === sp[0]) {
if (sp[1].type) {
if (sp[1] && sp[1].type) {
paramsFromPath[i].type = sp[1].type
}
if (sp[1].default !== undefined) {
if (sp[1] && sp[1].default !== undefined) {
paramsFromPath[i].default = sp[1].default
// It's becoming optional because it has a default
paramsFromPath[i].optional = true
Expand Down Expand Up @@ -249,7 +259,9 @@ export const fileToMetadata = (
`"${keyToUse}": (${params.join(', ')}) => ` +
` { ` +
`${paramsDefaults.join('')}` +
`return \`${toRet}${actionsFormat}${fullSP}\`` +
`return ${keyToUse === '_ROOT' ? `ensurePrefix(` : ``}` +
`\`${toRet}${actionsFormat}${fullSP}\`` +
`${keyToUse === '_ROOT' ? `)` : ``}` +
` }`

return { keyToUse, prop, paramsFromPath }
Expand Down Expand Up @@ -366,18 +378,20 @@ const run = (options?: Options) => {
log.error(`Can't extend "${green(`${o.type}.`)}${red(key)}" as this path doesn't exist!`)
allOk = false
} else {
Object.entries(cPath.params ?? {}).forEach(p => {
const [pKey] = p
const paramsFromPathFound = found.paramsFromPath.find(c => c.name === pKey)
if (!paramsFromPathFound) {
log.error(
`Can't extend "${green(`${o.type}.${key}.params.`)}${red(
pKey,
)}" as this param doesn't exist!`,
)
allOk = false
}
})
if (cPath) {
Object.entries(cPath.params ?? {}).forEach(p => {
const [pKey] = p
const paramsFromPathFound = found.paramsFromPath.find(c => c.name === pKey)
if (!paramsFromPathFound) {
log.error(
`Can't extend "${green(`${o.type}.${key}.params.`)}${red(
pKey,
)}" as this param doesn't exist!`,
)
allOk = false
}
})
}
}
})
})
Expand All @@ -390,6 +404,7 @@ const run = (options?: Options) => {
* >> DO NOT EDIT THIS FILE MANUALLY <<
*/
`,
// consts
objTypes
.map(c => {
return `export const ${c.type} = {
Expand All @@ -410,7 +425,53 @@ const appendSp = (sp?: Record<string, string | number | undefined>) => {
}
return ''
}

const ensurePrefix = (str: string) => {
if (str.startsWith('/')) {
return str
}
return \`/\${str}\`
}
`,
// types
`
/**
* Add this type as a generic of the vite plugin \`kitRoutes<ROUTES>\`.
*
* Full example:
* \`\`\`ts
* import type { ROUTES } from '$lib/ROUTES'
* import { kitRoutes } from 'vite-plugin-kit-routes'
*
* kitRoutes<ROUTES>({
* extend: {
* PAGES: {
* // here, "paths" it will be typed!
* }
* }
* })
* \`\`\`
*/
export type ROUTES = {
${objTypes
.map(c => {
return ` ${c.type}: { ${c.files
.map(d => {
return `'${d.keyToUse}': ${
d.paramsFromPath.length === 0
? 'never'
: d.paramsFromPath
.map(e => {
return `'${e.name}'`
})
.join(' | ')
}`
})
.join(', ')} }`
})
.join('\n')}
}
`,
])

// TODO: optimize this later. We want to write the new file only if different after prettier?! (having a tmp file somewhere?)
Expand Down Expand Up @@ -441,7 +502,37 @@ const appendSp = (sp?: Record<string, string | number | undefined>) => {
return false
}

export function kitRoutes(options?: Options): Plugin[] {
/**
* First you can start with something simple:
* ```ts
* import { kitRoutes } from 'vite-plugin-kit-routes'
*
* kitRoutes({
* // Conf
* })
* ```
* ---
* Then, you can add the `ROUTES` type... It will be crazy good!
* ```ts
* import type { ROUTES } from '$lib/ROUTES'
* import { kitRoutes } from 'vite-plugin-kit-routes'
*
* kitRoutes<ROUTES>({
* // Conf
* })
* ```
*/
export function kitRoutes<
T extends {
PAGES: Record<string, string>
SERVERS: Record<string, string>
ACTIONS: Record<string, string>
} = {
PAGES: Record<string, string>
SERVERS: Record<string, string>
ACTIONS: Record<string, string>
},
>(options?: Options<T>): Plugin[] {
return [
// Run the thing at startup
{
Expand Down
22 changes: 18 additions & 4 deletions packages/vite-plugin-kit-routes/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { sveltekit } from '@sveltejs/kit/vite'
import type { ROUTES } from '$lib/ROUTES.js'
import { defineConfig } from 'vite'
import { kitRoutes } from './src/lib/index.js'

type TT = 'A' | 'B'
const u: Partial<Record<TT, string>> = {}

export default defineConfig({
plugins: [
sveltekit(),
// demo
kitRoutes({
kitRoutes<ROUTES>({
// for testing
// generated_file_path: 'src/lib/ROUTES2.ts',
post_update_run: 'npm exec prettier ./src/lib/ROUTES.ts -- -w',
Expand All @@ -25,9 +29,19 @@ export default defineConfig({
params: { id: { type: 'string', default: '' } },
},
},
// SERVERS: {
// yop: {},
// },
SERVERS: {
// site: {
// params: { }
// }
// yop: {},
},
ACTIONS: {
site_contract_siteId_contractId: {
explicit_search_params: {
extra: { type: "'A' | 'B'", default: 'A' },
},
},
},
},
}),
],
Expand Down