From 0f355ffe6560231567fae117825b5352ecbcc129 Mon Sep 17 00:00:00 2001 From: jycouet Date: Fri, 24 Nov 2023 00:02:27 +0100 Subject: [PATCH 1/4] bump watch-and-run --- .changeset/curvy-eggs-deliver.md | 5 +++++ packages/vite-plugin-striper/package.json | 3 ++- packages/vite-plugin-watch-and-run/src/lib/index.ts | 6 +++--- pnpm-lock.yaml | 3 +++ 4 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 .changeset/curvy-eggs-deliver.md diff --git a/.changeset/curvy-eggs-deliver.md b/.changeset/curvy-eggs-deliver.md new file mode 100644 index 000000000..d911cc1ba --- /dev/null +++ b/.changeset/curvy-eggs-deliver.md @@ -0,0 +1,5 @@ +--- +'vite-plugin-watch-and-run': patch +--- + +add absolutePath in second param of run as info diff --git a/packages/vite-plugin-striper/package.json b/packages/vite-plugin-striper/package.json index a33ed712f..62d3922d6 100644 --- a/packages/vite-plugin-striper/package.json +++ b/packages/vite-plugin-striper/package.json @@ -42,7 +42,8 @@ "dependencies": { "@babel/parser": "^7.23.0", "@kitql/helpers": "workspace:*", - "recast": "^0.23.4" + "recast": "^0.23.4", + "vite-plugin-watch-and-run": "workspace:*" }, "sideEffects": false, "publishConfig": { diff --git a/packages/vite-plugin-watch-and-run/src/lib/index.ts b/packages/vite-plugin-watch-and-run/src/lib/index.ts index d5b73ed7b..aaada3482 100644 --- a/packages/vite-plugin-watch-and-run/src/lib/index.ts +++ b/packages/vite-plugin-watch-and-run/src/lib/index.ts @@ -31,7 +31,7 @@ export type Options = { /** * run command (npm run gen for example!) */ - run: string | ((server: ViteDevServer) => void | Promise) + run: string | ((server: ViteDevServer, absolutePath: string | null) => void | Promise) /** * Delay before running the run command (in ms) @@ -65,7 +65,7 @@ export type WatchKind = KindWithPath | KindWithoutPath export type StateDetail = { kind: WatchKind[] logs: LogType[] - run: string | ((server: ViteDevServer) => void | Promise) + run: string | ((server: ViteDevServer, absolutePath: string | null) => void | Promise) delay: number isRunning: boolean watchFile?: (filepath: string) => boolean | Promise @@ -179,7 +179,7 @@ async function watcher( setTimeout(async () => { // if the run value is a function, we just have to call it and we're done if (typeof info.run === 'function') { - const promise = info.run(server) + const promise = info.run(server, absolutePath) try { if (promise) { await promise diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08ae2cfbf..93a5b7a8e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -234,6 +234,9 @@ importers: recast: specifier: ^0.23.4 version: 0.23.4 + vite-plugin-watch-and-run: + specifier: workspace:* + version: link:../vite-plugin-watch-and-run/dist devDependencies: '@sveltejs/adapter-auto': specifier: 2.1.0 From 2e28faa94dee546295af04c0faa23704d0f775e7 Mon Sep 17 00:00:00 2001 From: jycouet Date: Fri, 24 Nov 2023 00:02:34 +0100 Subject: [PATCH 2/4] init --- .../vite-plugin-striper/src/lib/plugin.ts | 107 ++++++++++++++---- ...orm.spec.ts => transformDecorator.spec.ts} | 44 +++---- .../{transform.ts => transformDecorator.ts} | 2 +- .../src/lib/transformWarningThrow.spec.ts | 45 ++++++++ .../src/lib/transformWarningThrow.ts | 47 ++++++++ .../src/routes/+page.svelte | 3 + .../src/routes/demoThrowClass/+server.ts | 6 + .../src/routes/demoThrowRandom/+server.ts | 6 + packages/vite-plugin-striper/vite.config.ts | 6 +- 9 files changed, 218 insertions(+), 48 deletions(-) rename packages/vite-plugin-striper/src/lib/{transform.spec.ts => transformDecorator.spec.ts} (76%) rename packages/vite-plugin-striper/src/lib/{transform.ts => transformDecorator.ts} (97%) create mode 100644 packages/vite-plugin-striper/src/lib/transformWarningThrow.spec.ts create mode 100644 packages/vite-plugin-striper/src/lib/transformWarningThrow.ts create mode 100644 packages/vite-plugin-striper/src/routes/demoThrowClass/+server.ts create mode 100644 packages/vite-plugin-striper/src/routes/demoThrowRandom/+server.ts diff --git a/packages/vite-plugin-striper/src/lib/plugin.ts b/packages/vite-plugin-striper/src/lib/plugin.ts index 5fd6523ca..aea6a87c5 100644 --- a/packages/vite-plugin-striper/src/lib/plugin.ts +++ b/packages/vite-plugin-striper/src/lib/plugin.ts @@ -1,14 +1,26 @@ import { green, Log, yellow } from '@kitql/helpers' import type { Plugin } from 'vite' +import watch_and_run from 'vite-plugin-watch-and-run' -import { transform } from './transform.js' +import { transformDecorator } from './transformDecorator.js' +import { transformWarningThrow, type WarningThrow } from './transformWarningThrow.js' export type ViteStriperOptions = { /** * for example: `['BackendMethod']` */ - decorators: string[] + decorators?: string[] + /** + * If true, skip warnings if a throw is not a class. + * + * Default: `true` + */ + log_warning_on_throw_is_not_a_class?: boolean + + /** + * internal usage ;-) + */ debug?: boolean } @@ -30,34 +42,79 @@ export type ViteStriperOptions = { * ``` * */ -export function striper(options: ViteStriperOptions): Plugin { +export function striper(options?: ViteStriperOptions): Plugin[] { const log = new Log('striper') + let listOrThrow: WarningThrow[] = [] + return [ + { + name: 'vite-plugin-striper-decorator', + enforce: 'pre', - return { - name: 'vite-plugin-striper', - enforce: 'pre', + buildStart: () => { + listOrThrow = [] + }, - transform: async (code, filepath, option) => { - // Don't transform server-side code - if (option?.ssr) { - return - } - // files are only in ts - if (!filepath.endsWith('.ts')) { - return - } + transform: async (code, filepath, option) => { + const logWarningThrow = + options?.log_warning_on_throw_is_not_a_class === undefined || + options?.log_warning_on_throw_is_not_a_class === true - const { transformed, ...rest } = await transform(code, options.decorators ?? []) + if (logWarningThrow) { + const prjPath = process.cwd() + // Only file in our project + if (filepath.startsWith(prjPath)) { + const { list } = await transformWarningThrow(filepath, code, logWarningThrow) + listOrThrow.push( + ...list.map(item => ({ ...item, pathFile: filepath.replace(prjPath, '') })), + ) + } + } - if (options?.debug && transformed) { - log.info(` -${green('-----')} after transform of ${yellow(filepath)} -${rest.code} -${green('-----')} -`) - } + // Don't transform server-side code + if (option?.ssr) { + return + } + // files are only in ts + if (!filepath.endsWith('.ts')) { + return + } - return rest + if (options && (options?.decorators ?? []).length > 0) { + const { transformed, ...rest } = await transformDecorator(code, options.decorators ?? []) + + if (options?.debug && transformed) { + log.info( + `` + + `${green('-----')} after transform of ${yellow(filepath)}` + + `${rest.code}` + + `${green('-----')}` + + ``, + ) + } + + return rest + } + + return + }, + + buildEnd: async () => { + listOrThrow.forEach(item => { + log.error( + `Throw is not a new class in ${yellow(item.pathFile)}:${yellow(String(item.line))}`, + ) + }) + }, }, - } + + // Run the thing when any change in a +page.svelte (add, remove, ...) + watch_and_run([ + { + name: 'kit-routes-watch', + logs: [], + watch: ['**/*.ts'], + run: server => {}, + }, + ]), + ] } diff --git a/packages/vite-plugin-striper/src/lib/transform.spec.ts b/packages/vite-plugin-striper/src/lib/transformDecorator.spec.ts similarity index 76% rename from packages/vite-plugin-striper/src/lib/transform.spec.ts rename to packages/vite-plugin-striper/src/lib/transformDecorator.spec.ts index 95cb0ae1f..166e85a00 100644 --- a/packages/vite-plugin-striper/src/lib/transform.spec.ts +++ b/packages/vite-plugin-striper/src/lib/transformDecorator.spec.ts @@ -1,9 +1,10 @@ -import { expect, it } from 'vitest' +import { describe, expect, it } from 'vitest' -import { transform } from './transform.js' +import { transformDecorator } from './transformDecorator.js' -it('should empty @BackendMethod and clean imports', async () => { - const code = `import { Allow, BackendMethod, remult } from "remult"; +describe('decorator', () => { + it('should empty @BackendMethod and clean imports', async () => { + const code = `import { Allow, BackendMethod, remult } from "remult"; import { Task } from "./task"; import { AUTH_SECRET } from "$env/static/private"; @@ -34,9 +35,9 @@ export class TasksController { } ` - const transformed = await transform(code, ['BackendMethod']) + const transformed = await transformDecorator(code, ['BackendMethod']) - expect(transformed).toMatchInlineSnapshot(` + expect(transformed).toMatchInlineSnapshot(` { "code": "import { Allow, BackendMethod } from \\"remult\\"; @@ -56,10 +57,10 @@ export class TasksController { "transformed": true, } `) -}) + }) -it('should not crash if there is an error in the original file', async () => { - const code = `import { Allow, BackendMethod, remult } from "remult"; + it('should not crash if there is an error in the original file', async () => { + const code = `import { Allow, BackendMethod, remult } from "remult"; import { Task } from "./task"; import { AUTH_SECRET } from "$env/static/private"; @@ -71,9 +72,9 @@ export class TasksController { } ` - const transformed = await transform(code, ['BackendMethod']) + const transformed = await transformDecorator(code, ['BackendMethod']) - expect(transformed).toMatchInlineSnapshot(` + expect(transformed).toMatchInlineSnapshot(` { "code": "import { Allow, BackendMethod, remult } from \\"remult\\"; import { Task } from \\"./task\\"; @@ -89,10 +90,10 @@ export class TasksController { "transformed": false, } `) -}) + }) -it('should not do anything as there is no @BackendMethod', async () => { - const code = `import { Allow, BackendMethod, remult } from "remult"; + it('should not do anything as there is no @BackendMethod', async () => { + const code = `import { Allow, BackendMethod, remult } from "remult"; import { Task } from "./task"; import { AUTH_SECRET } from "$env/static/private"; @@ -112,9 +113,9 @@ export class TasksController { } ` - const transformed = await transform(code, ['BackendMethod']) + const transformed = await transformDecorator(code, ['BackendMethod']) - expect(transformed).toMatchInlineSnapshot(` + expect(transformed).toMatchInlineSnapshot(` { "code": "import { Allow, BackendMethod, remult } from \\"remult\\"; import { Task } from \\"./task\\"; @@ -140,10 +141,10 @@ export class TasksController { "transformed": false, } `) -}) + }) -it('should strip also unused methods', async () => { - const code = `import { TOP_SECRET, TOP_SECRET_NOT_USED } from '$env/static/private'; + it('should strip also unused methods', async () => { + const code = `import { TOP_SECRET, TOP_SECRET_NOT_USED } from '$env/static/private'; import { stry0 } from '@kitql/helper'; import { BackendMethod, Entity, Fields, remult } from 'remult'; @@ -171,9 +172,9 @@ it('should strip also unused methods', async () => { } ` - const transformed = await transform(code, ['BackendMethod']) + const transformed = await transformDecorator(code, ['BackendMethod']) - expect(transformed).toMatchInlineSnapshot(` + expect(transformed).toMatchInlineSnapshot(` { "code": "import { BackendMethod, Entity, Fields } from \\"remult\\"; @@ -192,4 +193,5 @@ it('should strip also unused methods', async () => { "transformed": true, } `) + }) }) diff --git a/packages/vite-plugin-striper/src/lib/transform.ts b/packages/vite-plugin-striper/src/lib/transformDecorator.ts similarity index 97% rename from packages/vite-plugin-striper/src/lib/transform.ts rename to packages/vite-plugin-striper/src/lib/transformDecorator.ts index f34aa8e2f..9db05c190 100644 --- a/packages/vite-plugin-striper/src/lib/transform.ts +++ b/packages/vite-plugin-striper/src/lib/transformDecorator.ts @@ -4,7 +4,7 @@ import { prettyPrint } from 'recast' const { visit } = recast.types -export const transform = async (code: string, decorators_to_strip: string[]) => { +export const transformDecorator = async (code: string, decorators_to_strip: string[]) => { try { const codeParsed = parse(code ?? '', { plugins: ['typescript', 'importAssertions', 'decorators-legacy'], diff --git a/packages/vite-plugin-striper/src/lib/transformWarningThrow.spec.ts b/packages/vite-plugin-striper/src/lib/transformWarningThrow.spec.ts new file mode 100644 index 000000000..8785e7c88 --- /dev/null +++ b/packages/vite-plugin-striper/src/lib/transformWarningThrow.spec.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from 'vitest' + +import { transformWarningThrow } from './transformWarningThrow.js' + +describe('warning on throw is not a class', () => { + it('should not warn', async () => { + const code = `import type { RequestHandler } from './$types' + + export const GET: RequestHandler = async () => { + throw new Error('Not implemented') + return new Response() + }` + + const transformed = await transformWarningThrow('myfile', code, true) + + expect(transformed).toMatchInlineSnapshot(` + { + "list": [], + } + `) + }) + + it('should warn', async () => { + const code = `import type { RequestHandler } from './$types' + + export const GET: RequestHandler = async () => { + throw 7 + return new Response() + } + ` + + const transformed = await transformWarningThrow('myfile', code, true) + + expect(transformed).toMatchInlineSnapshot(` + { + "list": [ + { + "line": 4, + "pathFile": "myfile", + }, + ], + } + `) + }) +}) diff --git a/packages/vite-plugin-striper/src/lib/transformWarningThrow.ts b/packages/vite-plugin-striper/src/lib/transformWarningThrow.ts new file mode 100644 index 000000000..70e06c74d --- /dev/null +++ b/packages/vite-plugin-striper/src/lib/transformWarningThrow.ts @@ -0,0 +1,47 @@ +import { parse } from '@babel/parser' +import * as recast from 'recast' +import { prettyPrint } from 'recast' + +const { visit } = recast.types + +export type WarningThrow = { + pathFile: string + line: number +} + +export const transformWarningThrow = async ( + pathFile: string, + code: string, + log_warning_on_throw_is_not_a_class: boolean, +) => { + try { + const codeParsed = parse(code ?? '', { + plugins: ['typescript', 'importAssertions', 'decorators-legacy'], + sourceType: 'module', + }).program as recast.types.namedTypes.Program + + let list: WarningThrow[] = [] + + visit(codeParsed, { + visitFunction(path) { + // Existing code for processing functions... + this.traverse(path) + }, + visitThrowStatement(path) { + if (log_warning_on_throw_is_not_a_class) { + const thrownExpr = path.node.argument + // Check if thrownExpr is not a class + if (thrownExpr && thrownExpr.type !== 'NewExpression') { + list.push({ pathFile, line: path.node.loc?.start.line ?? 0 }) + } + } + this.traverse(path) + }, + }) + + return { list } + } catch (error) { + // if anything happens, just return the original code + return { list: [] } + } +} diff --git a/packages/vite-plugin-striper/src/routes/+page.svelte b/packages/vite-plugin-striper/src/routes/+page.svelte index e965047ad..54964ccf9 100644 --- a/packages/vite-plugin-striper/src/routes/+page.svelte +++ b/packages/vite-plugin-striper/src/routes/+page.svelte @@ -1 +1,4 @@ Hello + +ThrowClass +ThrowRandom diff --git a/packages/vite-plugin-striper/src/routes/demoThrowClass/+server.ts b/packages/vite-plugin-striper/src/routes/demoThrowClass/+server.ts new file mode 100644 index 000000000..206030381 --- /dev/null +++ b/packages/vite-plugin-striper/src/routes/demoThrowClass/+server.ts @@ -0,0 +1,6 @@ +import type { RequestHandler } from './$types' + +export const GET: RequestHandler = async () => { + throw new Error('Not implemented') + return new Response() +} diff --git a/packages/vite-plugin-striper/src/routes/demoThrowRandom/+server.ts b/packages/vite-plugin-striper/src/routes/demoThrowRandom/+server.ts new file mode 100644 index 000000000..f4d16d54e --- /dev/null +++ b/packages/vite-plugin-striper/src/routes/demoThrowRandom/+server.ts @@ -0,0 +1,6 @@ +// Here is the file? + +export const GET = async () => { + throw 7 + return new Response() +} diff --git a/packages/vite-plugin-striper/vite.config.ts b/packages/vite-plugin-striper/vite.config.ts index b4713153d..c01b7bb4c 100644 --- a/packages/vite-plugin-striper/vite.config.ts +++ b/packages/vite-plugin-striper/vite.config.ts @@ -4,7 +4,11 @@ import { defineConfig } from 'vite' import { striper } from './src/lib/plugin.js' export default defineConfig({ - plugins: [striper(), sveltekit()], + plugins: [ + striper({ log_warning_on_throw_is_not_a_class: true }), + // + sveltekit(), + ], test: { include: ['src/**/*.{test,spec}.{js,ts}'], }, From ae4ec321ba283168fcaa7a4082a037b865accd7b Mon Sep 17 00:00:00 2001 From: jycouet Date: Fri, 24 Nov 2023 00:15:00 +0100 Subject: [PATCH 3/4] quick and dirty --- .../vite-plugin-striper/src/lib/plugin.ts | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/vite-plugin-striper/src/lib/plugin.ts b/packages/vite-plugin-striper/src/lib/plugin.ts index aea6a87c5..5e024da9f 100644 --- a/packages/vite-plugin-striper/src/lib/plugin.ts +++ b/packages/vite-plugin-striper/src/lib/plugin.ts @@ -1,4 +1,5 @@ import { green, Log, yellow } from '@kitql/helpers' +import { readFileSync } from 'node:fs' import type { Plugin } from 'vite' import watch_and_run from 'vite-plugin-watch-and-run' @@ -45,6 +46,10 @@ export type ViteStriperOptions = { export function striper(options?: ViteStriperOptions): Plugin[] { const log = new Log('striper') let listOrThrow: WarningThrow[] = [] + const logWarningThrow = + options?.log_warning_on_throw_is_not_a_class === undefined || + options?.log_warning_on_throw_is_not_a_class === true + return [ { name: 'vite-plugin-striper-decorator', @@ -55,10 +60,6 @@ export function striper(options?: ViteStriperOptions): Plugin[] { }, transform: async (code, filepath, option) => { - const logWarningThrow = - options?.log_warning_on_throw_is_not_a_class === undefined || - options?.log_warning_on_throw_is_not_a_class === true - if (logWarningThrow) { const prjPath = process.cwd() // Only file in our project @@ -113,7 +114,32 @@ export function striper(options?: ViteStriperOptions): Plugin[] { name: 'kit-routes-watch', logs: [], watch: ['**/*.ts'], - run: server => {}, + run: async (server, absolutePath) => { + if (logWarningThrow) { + const prjPath = process.cwd() + + // Only file in our project + if (absolutePath && absolutePath.startsWith(prjPath)) { + const code = readFileSync(absolutePath, { encoding: 'utf8' }) + + const { list } = await transformWarningThrow( + absolutePath + '?' + new Date().toISOString(), + code, + logWarningThrow, + ) + listOrThrow.push( + ...list.map(item => ({ ...item, pathFile: absolutePath.replace(prjPath, '') })), + ) + listOrThrow.forEach(item => { + log.error( + `Throw is not a new class in ${yellow(item.pathFile)}:${yellow( + String(item.line), + )}`, + ) + }) + } + } + }, }, ]), ] From e6fb40a6c0648da39bf7762a1ddf144db63148a8 Mon Sep 17 00:00:00 2001 From: jycouet Date: Fri, 24 Nov 2023 00:16:38 +0100 Subject: [PATCH 4/4] enter pre mode --- .changeset/pre.json | 16 ++++++++++++++++ .changeset/quiet-horses-drop.md | 5 +++++ 2 files changed, 21 insertions(+) create mode 100644 .changeset/pre.json create mode 100644 .changeset/quiet-horses-drop.md diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..adb854d68 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,16 @@ +{ + "mode": "pre", + "tag": "next", + "initialVersions": { + "@kitql-old/all-in": "0.9.6", + "create-kitql": "0.0.2", + "eslint-config-kitql": "0.0.2", + "@kitql/handles": "0.1.3", + "@kitql/helpers": "0.8.4", + "vite-plugin-kit-routes": "0.1.0", + "vite-plugin-striper": "0.0.4", + "vite-plugin-watch-and-run": "1.4.3", + "website": "1.1.2" + }, + "changesets": [] +} diff --git a/.changeset/quiet-horses-drop.md b/.changeset/quiet-horses-drop.md new file mode 100644 index 000000000..354d16be8 --- /dev/null +++ b/.changeset/quiet-horses-drop.md @@ -0,0 +1,5 @@ +--- +'vite-plugin-striper': patch +--- + +add log_warning_on_throw_is_not_a_class option