Skip to content

Commit

Permalink
🎉 NEW: kit-routes is born (#403)
Browse files Browse the repository at this point in the history
* 🎉 NEW: kit-routes is born

* 🐛 FIX: get the last version of watch-and-run

* 👌 FIX: prettier

* 🎉 NEW: watch can look at an array of globs now

* 🚧 UPDATE: I need to commit sometime!

* 🚧 NEW: PAGES / SERVERS / ACTIONS

* 🚧 UPDATE: tune generated_file_path location

* 💥 REMOVE: ROUTE2

* 🚧 RENAME: vite plugin to kitRoutes

* ♻️ UPDATE: locations
  • Loading branch information
jycouet authored Nov 1, 2023
1 parent 7f2d8da commit 3d4c5bc
Show file tree
Hide file tree
Showing 30 changed files with 588 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-lies-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vite-plugin-watch-and-run': patch
---

watch can look at an array of globs now
5 changes: 5 additions & 0 deletions .changeset/polite-ghosts-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vite-plugin-kit-routes': patch
---

init plugin
3 changes: 3 additions & 0 deletions packages/vite-plugin-kit-routes/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
extends: ['eslint-config-kitql'],
}
11 changes: 11 additions & 0 deletions packages/vite-plugin-kit-routes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.DS_Store
node_modules
/build
/dist
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
1 change: 1 addition & 0 deletions packages/vite-plugin-kit-routes/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
1 change: 1 addition & 0 deletions packages/vite-plugin-kit-routes/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# vite-plugin-kit-routes
5 changes: 5 additions & 0 deletions packages/vite-plugin-kit-routes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# ⚡vite-plugin-watch-and-run

_Part of [KitQL](https://github.com/jycouet/kitql#kitql), a set of tools helping **you** building efficient apps in a fast way._

### 👉 Check the [⚡Doc⚡](https://kitql.dev/docs/tools/06_vite-plugin-kit-routes)
65 changes: 65 additions & 0 deletions packages/vite-plugin-kit-routes/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"name": "vite-plugin-kit-routes",
"description": "vite-plugin that will help you maintain your routes in a single file",
"keywords": [
"vite"
],
"version": "0.0.1",
"license": "MIT",
"type": "module",
"repository": {
"type": "git",
"url": "https://github.com/jycouet/kitql",
"directory": "packages/vite-plugin-kit-routes",
"homepage": "https://github.com/jycouet/kitql/tree/main/packages/vite-plugin-kit-routes#readme"
},
"scripts": {
"prepare": "svelte-kit sync",
"dev": "vite dev",
"build": "vite build && svelte-package && node ../../scripts/package.js",
"preview": "vite preview",
"package": "svelte-package && publint",
"check": "svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
"test": "vitest",
"test:ci": "vitest --coverage",
"lint": "kitql-lint",
"format": "kitql-lint --fix"
},
"devDependencies": {
"eslint-config-kitql": "workspace:*",
"@sveltejs/adapter-auto": "2.1.0",
"@sveltejs/kit": "1.25.2",
"@sveltejs/package": "2.2.2",
"publint": "0.2.4",
"svelte": "4.2.1",
"svelte-check": "3.5.2",
"tslib": "2.6.2",
"typescript": "5.2.2",
"vite": "4.4.2",
"vitest": "0.34.6"
},
"dependencies": {
"@kitql/helpers": "workspace:*",
"vite-plugin-watch-and-run": "workspace:*"
},
"sideEffects": false,
"publishConfig": {
"directory": "dist",
"access": "public"
},
"files": [
"dist",
"!dist/**/*.test.*",
"!dist/**/*.spec.*"
],
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js",
"svelte": "./dist/index.js"
}
}
}
12 changes: 12 additions & 0 deletions packages/vite-plugin-kit-routes/src/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface Platform {}
}
}

export {}
12 changes: 12 additions & 0 deletions packages/vite-plugin-kit-routes/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div>%sveltekit.body%</div>
</body>
</html>
30 changes: 30 additions & 0 deletions packages/vite-plugin-kit-routes/src/lib/ROUTES.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const PAGES = {
'/': (sp?: Record<string, string>) => {
return `/${appendSp(sp)}`
},
'/site/[id]': (id: string, sp?: Record<string, string>) => {
return `/site/${id}${appendSp(sp)}`
},
'/site/[param]/[yop]': (param: string, yop: string, sp?: Record<string, string>) => {
return `/site/${param}/${yop}${appendSp(sp)}`
},
}

// TODO: SERVERS methods?
export const SERVERS = {
'/site/[id]/one': (id: string, sp?: Record<string, string>) => {
return `/site/${id}/one${appendSp(sp)}`
},
}

// TODO: name actions
export const ACTIONS = {
'/site/[id]/two/[hello]': (id: string, hello: string) => {
return `/site/${id}/two/${hello}`
},
}

const appendSp = (sp?: Record<string, string>) => {
if (sp === undefined) return ''
return `?${new URLSearchParams(sp || {}).toString()}`
}
26 changes: 26 additions & 0 deletions packages/vite-plugin-kit-routes/src/lib/fs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'

export function read(pathFile: string) {
return readFileSync(pathFile, { encoding: 'utf8' })
}

export function write(pathFile: string, data: string[]) {
const fullDataToWrite = Array.isArray(data) ? data.join('\n') : data
createFolderIfNotExists(dirname(pathFile))
// Don't write if nothing changed!
if (existsSync(pathFile)) {
const currentFileData = read(pathFile)
if (fullDataToWrite === currentFileData) {
return false
}
}
writeFileSync(join(pathFile), fullDataToWrite)
return true
}

function createFolderIfNotExists(dir: string) {
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true })
}
}
150 changes: 150 additions & 0 deletions packages/vite-plugin-kit-routes/src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { readdirSync } from 'fs'
import { spawn } from 'node:child_process'
import { green, Log, yellow } from '@kitql/helpers'
import type { Plugin } from 'vite'
import watch_and_run from 'vite-plugin-watch-and-run'
import { write } from './fs.js'

export type Options = {
/**
* run command after file updated
*
* @example
* ```ts
* 'npm exec prettier ./src/lib/ROUTES.ts -- -w'
* ```
*/
post_update_run?: string

/**
* @default 'src/lib/ROUTES.ts'
*/
generated_file_path?: string
}

function generated_file_path(params?: Options) {
return params?.generated_file_path ?? 'src/lib/ROUTES.ts'
}

// const routes_path = 'src/lib/ROUTES.ts'
const log = new Log('Kit Routes')

const getFiles = (dirPath: string, lookFor: '+page.svelte' | '+page.server.ts' | '+server.ts') => {
const files = readdirSync(dirPath, { recursive: true }) as string[]
return files
.filter(file => file.endsWith(lookFor))
.map(file => `/` + file.replace(`/${lookFor}`, '').replace(lookFor, ''))
}

export function extractParamsFromPath(path: string): string[] {
// Use a regular expression to match parameter placeholders like '[param]'
const paramPattern = /\[([^\]]+)]/g
const params = []

let match
while ((match = paramPattern.exec(path)) !== null) {
// The matched parameter name is in the first capturing group
params.push(match[1])
}

return params
}

const run = (params?: Options) => {
const files_pages = getFiles(`${process.cwd()}/src/routes`, '+page.svelte')
const files_server_pages = getFiles(`${process.cwd()}/src/routes`, '+page.server.ts')
const files_server = getFiles(`${process.cwd()}/src/routes`, '+server.ts')

const result = write(generated_file_path(params), [
`export const PAGES = {
${files_pages
.map(file_path => {
const params = extractParamsFromPath(file_path).map(c => `${c}: string`)
params.push(`sp?: Record<string, string>`)
return (
`"${file_path}": (${params.join(', ')}) => ` +
`{ return \`${file_path.replaceAll('[', '${').replaceAll(']', '}')}\${appendSp(sp)}\` }`
)
})
.join(',\n ')}
}
// TODO: SERVERS methods?
export const SERVERS = {
${files_server
.map(file_path => {
const params = extractParamsFromPath(file_path).map(c => `${c}: string`)
params.push(`sp?: Record<string, string>`)
return (
`"${file_path}": (${params.join(', ')}) => ` +
`{ return \`${file_path.replaceAll('[', '${').replaceAll(']', '}')}\${appendSp(sp)}\` }`
)
})
.join(',\n ')}
}
// TODO: name actions
export const ACTIONS = {
${files_server_pages
.map(file_path => {
const params = extractParamsFromPath(file_path).map(c => `${c}: string`)
return (
`"${file_path}": (${params.join(', ')}) => ` +
`{ return \`${file_path.replaceAll('[', '${').replaceAll(']', '}')}\` }`
)
})
.join(',\n ')}
}
const appendSp = (sp?: Record<string, string>) => {
if (sp === undefined) return ''
return \`?\${new URLSearchParams(sp || {}).toString()}\`
}
`,
])

// TODO: optimize this later. We want to write the new file only if different after prettier?! (having a tmp file somewhere?)
if (params?.post_update_run) {
log.info(`${yellow(`post_update_run`)} "${green(params?.post_update_run)}" running...`)
const child = spawn(params.post_update_run, { shell: true })
child.stdout.on('data', data => {
if (data.toString()) {
log.info(data.toString())
}
})
child.stderr.on('data', data => {
log.error(data.toString())
})
child.on('close', code => {
if (result) {
log.success(`${yellow(generated_file_path(params))} updated`)
}
})
} else {
if (result) {
log.success(`${yellow(generated_file_path(params))} updated`)
}
}
}

export function kitRoutes(params?: Options): Plugin[] {
return [
// Run the thing at startup
{
name: 'kit-routes',
configureServer() {
run(params)
},
},

// Run the thing when any change in a +page.svelte (add, remove, ...)
watch_and_run([
{
name: 'kit-routes-watch',
logs: [],
watch: ['**/+page.svelte', '**/+page.server.ts', '**/+server.ts'],
run: () => run(params),
},
]),
]
}
31 changes: 31 additions & 0 deletions packages/vite-plugin-kit-routes/src/lib/plugins.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { describe, expect, it } from 'vitest'
import { extractParamsFromPath } from './index.js'

describe('vite-plugin-kit-routes', () => {
it('get id', async () => {
expect(extractParamsFromPath('/site/[id]')).toMatchInlineSnapshot(`
[
"id",
]
`)
})

it('get params & id', async () => {
expect(extractParamsFromPath('/site/[param]/[id]')).toMatchInlineSnapshot(`
[
"param",
"id",
]
`)
})

it('get params & id', async () => {
expect(extractParamsFromPath('/[param]site/[yop](group)/[id]')).toMatchInlineSnapshot(`
[
"param",
"yop",
"id",
]
`)
})
})
20 changes: 20 additions & 0 deletions packages/vite-plugin-kit-routes/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import { PAGES } from '$lib/ROUTES.js'
</script>

<svelte:head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css" />
</svelte:head>

<h1>vite-plugin-kit-routes</h1>

<hr />

<ul>
<a href={PAGES['/']()}>Home</a>
<a href={PAGES['/site/[param]/[yop]']('param', 'yop', { limit: '2' })}>Another route</a>
</ul>

<hr />

<slot />
1 change: 1 addition & 0 deletions packages/vite-plugin-kit-routes/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h2>Home</h2>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h2>site [id]</h2>
Loading

1 comment on commit 3d4c5bc

@vercel
Copy link

@vercel vercel bot commented on 3d4c5bc Nov 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

kitql – ./

kitql.vercel.app
kitql-jycouet.vercel.app
www.kitql.dev
kitql-git-main-jycouet.vercel.app
kitql.dev

Please sign in to comment.