create-taserjs 0.1.12 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -44
- package/dist/cli-9fkoNOJg.js +1237 -0
- package/dist/cli-9fkoNOJg.js.map +1 -0
- package/dist/cli-DkZddFtU.cjs +1398 -0
- package/dist/cli.cjs +4 -0
- package/dist/cli.d.cts +4 -0
- package/dist/cli.d.cts.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +3 -0
- package/dist/index.cjs +25 -0
- package/dist/index.d.cts +119 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/package.json +39 -9
- package/src/addons/drizzle/index.ts +37 -40
- package/src/addons/kysely/index.ts +19 -22
- package/src/addons/pino/index.ts +2 -2
- package/src/addons/prisma/index.ts +18 -22
- package/src/addons/registry.ts +37 -73
- package/src/addons/types.ts +12 -13
- package/src/addons/validators.ts +22 -23
- package/src/addons/winston/index.ts +3 -3
- package/src/cli.ts +96 -56
- package/src/commands/create.ts +118 -249
- package/src/core/package-manager.ts +36 -55
- package/src/core/scaffold-engine.ts +100 -75
- package/src/core/targets.ts +20 -56
- package/src/core/types.ts +18 -53
- package/src/index.ts +8 -0
- package/src/templates/base.ts +139 -51
- package/dist/cjs/_virtual/_rolldown/runtime.cjs +0 -23
- package/dist/cjs/addons/arktype/index.cjs +0 -6
- package/dist/cjs/addons/arktype/index.cjs.map +0 -1
- package/dist/cjs/addons/arktype/index.d.cts +0 -1
- package/dist/cjs/addons/drizzle/index.cjs +0 -131
- package/dist/cjs/addons/drizzle/index.cjs.map +0 -1
- package/dist/cjs/addons/drizzle/index.d.cts +0 -2
- package/dist/cjs/addons/kysely/index.cjs +0 -103
- package/dist/cjs/addons/kysely/index.cjs.map +0 -1
- package/dist/cjs/addons/kysely/index.d.cts +0 -2
- package/dist/cjs/addons/pino/index.cjs +0 -30
- package/dist/cjs/addons/pino/index.cjs.map +0 -1
- package/dist/cjs/addons/pino/index.d.cts +0 -2
- package/dist/cjs/addons/prisma/index.cjs +0 -133
- package/dist/cjs/addons/prisma/index.cjs.map +0 -1
- package/dist/cjs/addons/prisma/index.d.cts +0 -2
- package/dist/cjs/addons/registry.cjs +0 -65
- package/dist/cjs/addons/registry.cjs.map +0 -1
- package/dist/cjs/addons/registry.d.cts +0 -5
- package/dist/cjs/addons/types.d.cts +0 -16
- package/dist/cjs/addons/valibot/index.cjs +0 -6
- package/dist/cjs/addons/valibot/index.cjs.map +0 -1
- package/dist/cjs/addons/valibot/index.d.cts +0 -1
- package/dist/cjs/addons/validators.cjs +0 -38
- package/dist/cjs/addons/validators.cjs.map +0 -1
- package/dist/cjs/addons/validators.d.cts +0 -5
- package/dist/cjs/addons/winston/index.cjs +0 -34
- package/dist/cjs/addons/winston/index.cjs.map +0 -1
- package/dist/cjs/addons/winston/index.d.cts +0 -2
- package/dist/cjs/addons/zod/index.cjs +0 -6
- package/dist/cjs/addons/zod/index.cjs.map +0 -1
- package/dist/cjs/addons/zod/index.d.cts +0 -1
- package/dist/cjs/cli.cjs +0 -65
- package/dist/cjs/cli.cjs.map +0 -1
- package/dist/cjs/cli.d.cts +0 -2
- package/dist/cjs/commands/create.cjs +0 -332
- package/dist/cjs/commands/create.cjs.map +0 -1
- package/dist/cjs/commands/create.d.cts +0 -14
- package/dist/cjs/core/json-output.cjs +0 -16
- package/dist/cjs/core/json-output.cjs.map +0 -1
- package/dist/cjs/core/json-output.d.cts +0 -4
- package/dist/cjs/core/package-manager.cjs +0 -56
- package/dist/cjs/core/package-manager.cjs.map +0 -1
- package/dist/cjs/core/package-manager.d.cts +0 -8
- package/dist/cjs/core/parse-options.cjs +0 -95
- package/dist/cjs/core/parse-options.cjs.map +0 -1
- package/dist/cjs/core/parse-options.d.cts +0 -35
- package/dist/cjs/core/project-config.cjs +0 -23
- package/dist/cjs/core/project-config.cjs.map +0 -1
- package/dist/cjs/core/project-config.d.cts +0 -2
- package/dist/cjs/core/resolve-packages.cjs +0 -58
- package/dist/cjs/core/resolve-packages.cjs.map +0 -1
- package/dist/cjs/core/resolve-packages.d.cts +0 -2
- package/dist/cjs/core/scaffold-engine.cjs +0 -72
- package/dist/cjs/core/scaffold-engine.cjs.map +0 -1
- package/dist/cjs/core/scaffold-engine.d.cts +0 -2
- package/dist/cjs/core/targets.cjs +0 -171
- package/dist/cjs/core/targets.cjs.map +0 -1
- package/dist/cjs/core/targets.d.cts +0 -49
- package/dist/cjs/core/types.cjs +0 -52
- package/dist/cjs/core/types.cjs.map +0 -1
- package/dist/cjs/core/types.d.cts +0 -57
- package/dist/cjs/core/validate-project-name.cjs +0 -44
- package/dist/cjs/core/validate-project-name.cjs.map +0 -1
- package/dist/cjs/core/validate-project-name.d.cts +0 -1
- package/dist/cjs/frameworks/index.cjs +0 -116
- package/dist/cjs/frameworks/index.cjs.map +0 -1
- package/dist/cjs/frameworks/index.d.cts +0 -18
- package/dist/cjs/scaffold.d.cts +0 -3
- package/dist/cjs/templates/base.cjs +0 -97
- package/dist/cjs/templates/base.cjs.map +0 -1
- package/dist/cjs/templates/base.d.cts +0 -9
- package/dist/cjs/types.d.cts +0 -1
- package/dist/esm/addons/arktype/index.d.ts +0 -1
- package/dist/esm/addons/arktype/index.js +0 -7
- package/dist/esm/addons/arktype/index.js.map +0 -1
- package/dist/esm/addons/drizzle/index.d.ts +0 -2
- package/dist/esm/addons/drizzle/index.js +0 -131
- package/dist/esm/addons/drizzle/index.js.map +0 -1
- package/dist/esm/addons/kysely/index.d.ts +0 -2
- package/dist/esm/addons/kysely/index.js +0 -103
- package/dist/esm/addons/kysely/index.js.map +0 -1
- package/dist/esm/addons/pino/index.d.ts +0 -2
- package/dist/esm/addons/pino/index.js +0 -30
- package/dist/esm/addons/pino/index.js.map +0 -1
- package/dist/esm/addons/prisma/index.d.ts +0 -2
- package/dist/esm/addons/prisma/index.js +0 -133
- package/dist/esm/addons/prisma/index.js.map +0 -1
- package/dist/esm/addons/registry.d.ts +0 -5
- package/dist/esm/addons/registry.js +0 -63
- package/dist/esm/addons/registry.js.map +0 -1
- package/dist/esm/addons/types.d.ts +0 -16
- package/dist/esm/addons/valibot/index.d.ts +0 -1
- package/dist/esm/addons/valibot/index.js +0 -7
- package/dist/esm/addons/valibot/index.js.map +0 -1
- package/dist/esm/addons/validators.d.ts +0 -5
- package/dist/esm/addons/validators.js +0 -36
- package/dist/esm/addons/validators.js.map +0 -1
- package/dist/esm/addons/winston/index.d.ts +0 -2
- package/dist/esm/addons/winston/index.js +0 -34
- package/dist/esm/addons/winston/index.js.map +0 -1
- package/dist/esm/addons/zod/index.d.ts +0 -1
- package/dist/esm/addons/zod/index.js +0 -7
- package/dist/esm/addons/zod/index.js.map +0 -1
- package/dist/esm/cli.d.ts +0 -2
- package/dist/esm/cli.js +0 -62
- package/dist/esm/cli.js.map +0 -1
- package/dist/esm/commands/create.d.ts +0 -14
- package/dist/esm/commands/create.js +0 -327
- package/dist/esm/commands/create.js.map +0 -1
- package/dist/esm/core/json-output.d.ts +0 -4
- package/dist/esm/core/json-output.js +0 -14
- package/dist/esm/core/json-output.js.map +0 -1
- package/dist/esm/core/package-manager.d.ts +0 -8
- package/dist/esm/core/package-manager.js +0 -53
- package/dist/esm/core/package-manager.js.map +0 -1
- package/dist/esm/core/parse-options.d.ts +0 -35
- package/dist/esm/core/parse-options.js +0 -89
- package/dist/esm/core/parse-options.js.map +0 -1
- package/dist/esm/core/project-config.d.ts +0 -2
- package/dist/esm/core/project-config.js +0 -21
- package/dist/esm/core/project-config.js.map +0 -1
- package/dist/esm/core/resolve-packages.d.ts +0 -2
- package/dist/esm/core/resolve-packages.js +0 -58
- package/dist/esm/core/resolve-packages.js.map +0 -1
- package/dist/esm/core/scaffold-engine.d.ts +0 -2
- package/dist/esm/core/scaffold-engine.js +0 -70
- package/dist/esm/core/scaffold-engine.js.map +0 -1
- package/dist/esm/core/targets.d.ts +0 -49
- package/dist/esm/core/targets.js +0 -166
- package/dist/esm/core/targets.js.map +0 -1
- package/dist/esm/core/types.d.ts +0 -57
- package/dist/esm/core/types.js +0 -45
- package/dist/esm/core/types.js.map +0 -1
- package/dist/esm/core/validate-project-name.d.ts +0 -1
- package/dist/esm/core/validate-project-name.js +0 -42
- package/dist/esm/core/validate-project-name.js.map +0 -1
- package/dist/esm/frameworks/index.d.ts +0 -18
- package/dist/esm/frameworks/index.js +0 -112
- package/dist/esm/frameworks/index.js.map +0 -1
- package/dist/esm/scaffold.d.ts +0 -3
- package/dist/esm/templates/base.d.ts +0 -9
- package/dist/esm/templates/base.js +0 -91
- package/dist/esm/templates/base.js.map +0 -1
- package/dist/esm/types.d.ts +0 -1
- package/src/addons/arktype/index.ts +0 -3
- package/src/addons/valibot/index.ts +0 -3
- package/src/addons/zod/index.ts +0 -3
- package/src/core/json-output.ts +0 -13
- package/src/core/parse-options.ts +0 -167
- package/src/core/project-config.ts +0 -32
- package/src/core/resolve-packages.ts +0 -69
- package/src/core/validate-project-name.ts +0 -55
- package/src/frameworks/index.ts +0 -120
- package/src/scaffold.ts +0 -3
- package/src/types.ts +0 -12
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
//#region src/frameworks/index.ts
|
|
2
|
-
function serverEntryTemplate(framework) {
|
|
3
|
-
switch (framework) {
|
|
4
|
-
case "hono": return {
|
|
5
|
-
fileName: "src/server.ts",
|
|
6
|
-
content: `import { Hono } from 'hono'
|
|
7
|
-
|
|
8
|
-
const app = new Hono()
|
|
9
|
-
|
|
10
|
-
app.get('/host', (c) => {
|
|
11
|
-
return c.text('Hello from Hono host!')
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
export default app
|
|
15
|
-
`
|
|
16
|
-
};
|
|
17
|
-
case "express": return {
|
|
18
|
-
fileName: "src/server.node.ts",
|
|
19
|
-
content: `import express from 'express'
|
|
20
|
-
|
|
21
|
-
const app = express()
|
|
22
|
-
|
|
23
|
-
app.get('/host', (_req, res) => {
|
|
24
|
-
res.json({ message: 'Hello from Express host!' })
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
export default app
|
|
28
|
-
`
|
|
29
|
-
};
|
|
30
|
-
case "fastify": return {
|
|
31
|
-
fileName: "src/server.node.ts",
|
|
32
|
-
content: `import Fastify from 'fastify'
|
|
33
|
-
|
|
34
|
-
const app = Fastify()
|
|
35
|
-
|
|
36
|
-
app.get('/host', async () => {
|
|
37
|
-
return { message: 'Hello from Fastify host!' }
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
await app.ready()
|
|
41
|
-
|
|
42
|
-
export default app.routing
|
|
43
|
-
`
|
|
44
|
-
};
|
|
45
|
-
default: return null;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
var FRAMEWORK_ENTRIES = {
|
|
49
|
-
none: {
|
|
50
|
-
id: "none",
|
|
51
|
-
serverEntry: null,
|
|
52
|
-
deps: [],
|
|
53
|
-
devDeps: []
|
|
54
|
-
},
|
|
55
|
-
hono: {
|
|
56
|
-
id: "hono",
|
|
57
|
-
serverEntry: serverEntryTemplate("hono"),
|
|
58
|
-
deps: ["hono"],
|
|
59
|
-
devDeps: []
|
|
60
|
-
},
|
|
61
|
-
express: {
|
|
62
|
-
id: "express",
|
|
63
|
-
serverEntry: serverEntryTemplate("express"),
|
|
64
|
-
deps: ["express"],
|
|
65
|
-
devDeps: ["@types/express"]
|
|
66
|
-
},
|
|
67
|
-
fastify: {
|
|
68
|
-
id: "fastify",
|
|
69
|
-
serverEntry: serverEntryTemplate("fastify"),
|
|
70
|
-
deps: ["fastify"],
|
|
71
|
-
devDeps: []
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
function nitroConfigTemplate(nitroPreset) {
|
|
75
|
-
return `import { defineConfig } from 'nitro/config'
|
|
76
|
-
|
|
77
|
-
export default defineConfig({
|
|
78
|
-
preset: '${nitroPreset}',
|
|
79
|
-
})
|
|
80
|
-
`;
|
|
81
|
-
}
|
|
82
|
-
function viteConfigTemplate(preset) {
|
|
83
|
-
if (preset === "none") return `import { defineConfig } from 'vite'
|
|
84
|
-
import { taser } from '@taserjs/router-plugin/vite'
|
|
85
|
-
|
|
86
|
-
export default defineConfig({
|
|
87
|
-
plugins: [taser()],
|
|
88
|
-
})
|
|
89
|
-
`;
|
|
90
|
-
return `import { defineConfig } from 'vite'
|
|
91
|
-
import { nitro } from 'nitro/vite'
|
|
92
|
-
import { taser } from '@taserjs/router-plugin/vite'
|
|
93
|
-
|
|
94
|
-
export default defineConfig({
|
|
95
|
-
plugins: [taser(), nitro()],
|
|
96
|
-
})
|
|
97
|
-
`;
|
|
98
|
-
}
|
|
99
|
-
function taserTsTemplate() {
|
|
100
|
-
return `import { createTaserApp } from '@taserjs/router'
|
|
101
|
-
|
|
102
|
-
import { context } from './context.js'
|
|
103
|
-
|
|
104
|
-
export default createTaserApp({
|
|
105
|
-
response: { validate: true },
|
|
106
|
-
}).context(context)
|
|
107
|
-
`;
|
|
108
|
-
}
|
|
109
|
-
//#endregion
|
|
110
|
-
export { FRAMEWORK_ENTRIES, nitroConfigTemplate, serverEntryTemplate, taserTsTemplate, viteConfigTemplate };
|
|
111
|
-
|
|
112
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { DeployTarget, Framework } from \"../core/types.js\";\n\nexport function serverEntryTemplate(\n framework: Framework,\n): { fileName: string; content: string } | null {\n switch (framework) {\n case \"hono\":\n return {\n fileName: \"src/server.ts\",\n content: `import { Hono } from 'hono'\n\nconst app = new Hono()\n\napp.get('/host', (c) => {\n return c.text('Hello from Hono host!')\n})\n\nexport default app\n`,\n };\n case \"express\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import express from 'express'\n\nconst app = express()\n\napp.get('/host', (_req, res) => {\n res.json({ message: 'Hello from Express host!' })\n})\n\nexport default app\n`,\n };\n case \"fastify\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import Fastify from 'fastify'\n\nconst app = Fastify()\n\napp.get('/host', async () => {\n return { message: 'Hello from Fastify host!' }\n})\n\nawait app.ready()\n\nexport default app.routing\n`,\n };\n default:\n return null;\n }\n}\n\nexport type FrameworkEntry = {\n id: Framework;\n serverEntry: { fileName: string; content: string } | null;\n deps: string[];\n devDeps: string[];\n};\n\nexport const FRAMEWORK_ENTRIES: Record<Framework, FrameworkEntry> = {\n none: { id: \"none\", serverEntry: null, deps: [], devDeps: [] },\n hono: { id: \"hono\", serverEntry: serverEntryTemplate(\"hono\"), deps: [\"hono\"], devDeps: [] },\n express: {\n id: \"express\",\n serverEntry: serverEntryTemplate(\"express\"),\n deps: [\"express\"],\n devDeps: [\"@types/express\"],\n },\n fastify: {\n id: \"fastify\",\n // srvx bridges the Fastify Node handler to fetch (see compose codegen).\n serverEntry: serverEntryTemplate(\"fastify\"),\n deps: [\"fastify\"],\n devDeps: [],\n },\n};\n\nexport function nitroConfigTemplate(nitroPreset: string): string {\n return `import { defineConfig } from 'nitro/config'\n\nexport default defineConfig({\n preset: '${nitroPreset}',\n})\n`;\n}\n\nexport function viteConfigTemplate(preset?: DeployTarget): string {\n if (preset === \"none\") {\n return `import { defineConfig } from 'vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser()],\n})\n`;\n }\n\n return `import { defineConfig } from 'vite'\nimport { nitro } from 'nitro/vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser(), nitro()],\n})\n`;\n}\n\nexport function taserTsTemplate(): string {\n return `import { createTaserApp } from '@taserjs/router'\n\nimport { context } from './context.js'\n\nexport default createTaserApp({\n response: { validate: true },\n}).context(context)\n`;\n}\n"],"mappings":";AAEA,SAAgB,oBACd,WAC8C;CAC9C,QAAQ,WAAR;EACE,KAAK,QACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;;;EAYX;EACF,SACE,OAAO;CACX;AACF;AASA,IAAa,oBAAuD;CAClE,MAAM;EAAE,IAAI;EAAQ,aAAa;EAAM,MAAM,CAAC;EAAG,SAAS,CAAC;CAAE;CAC7D,MAAM;EAAE,IAAI;EAAQ,aAAa,oBAAoB,MAAM;EAAG,MAAM,CAAC,MAAM;EAAG,SAAS,CAAC;CAAE;CAC1F,SAAS;EACP,IAAI;EACJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC,gBAAgB;CAC5B;CACA,SAAS;EACP,IAAI;EAEJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC;CACZ;AACF;AAEA,SAAgB,oBAAoB,aAA6B;CAC/D,OAAO;;;aAGI,YAAY;;;AAGzB;AAEA,SAAgB,mBAAmB,QAA+B;CAChE,IAAI,WAAW,QACb,OAAO;;;;;;;CAST,OAAO;;;;;;;;AAQT;AAEA,SAAgB,kBAA0B;CACxC,OAAO;;;;;;;;AAQT"}
|
package/dist/esm/scaffold.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { BootBinding } from '../addons/types.js';
|
|
2
|
-
import { ScaffoldContext } from '../core/types.js';
|
|
3
|
-
export declare function packageJsonTemplate(projectName: string, scripts?: Record<string, string>): string;
|
|
4
|
-
export declare function tsconfigTemplate(): string;
|
|
5
|
-
export declare function gitignoreTemplate(): string;
|
|
6
|
-
export declare function contextTemplate(bindings: BootBinding[]): string;
|
|
7
|
-
export declare function rootLayoutTemplate(): string;
|
|
8
|
-
export declare function indexRouteTemplate(): string;
|
|
9
|
-
export declare function healthRouteTemplate(ctx: ScaffoldContext): string;
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
//#region src/templates/base.ts
|
|
2
|
-
function packageJsonTemplate(projectName, scripts = {}) {
|
|
3
|
-
const pkg = {
|
|
4
|
-
name: projectName,
|
|
5
|
-
version: "1.0.0",
|
|
6
|
-
private: true,
|
|
7
|
-
type: "module",
|
|
8
|
-
scripts: {
|
|
9
|
-
dev: "vite",
|
|
10
|
-
build: "vite build",
|
|
11
|
-
typecheck: "tsc --noEmit -p tsconfig.json",
|
|
12
|
-
"taser:generate": "taser generate",
|
|
13
|
-
...scripts
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
return `${JSON.stringify(pkg, null, 2)}\n`;
|
|
17
|
-
}
|
|
18
|
-
function tsconfigTemplate() {
|
|
19
|
-
return `${JSON.stringify({
|
|
20
|
-
compilerOptions: {
|
|
21
|
-
target: "ES2022",
|
|
22
|
-
module: "NodeNext",
|
|
23
|
-
strict: true,
|
|
24
|
-
skipLibCheck: true,
|
|
25
|
-
verbatimModuleSyntax: true,
|
|
26
|
-
isolatedModules: true,
|
|
27
|
-
noEmit: true
|
|
28
|
-
},
|
|
29
|
-
include: ["src", ".taser/types/**/*.d.ts"]
|
|
30
|
-
}, null, 2)}\n`;
|
|
31
|
-
}
|
|
32
|
-
function gitignoreTemplate() {
|
|
33
|
-
return `node_modules
|
|
34
|
-
dist
|
|
35
|
-
.output
|
|
36
|
-
.taser
|
|
37
|
-
.DS_Store
|
|
38
|
-
*.log
|
|
39
|
-
.env
|
|
40
|
-
local.db
|
|
41
|
-
drizzle
|
|
42
|
-
`;
|
|
43
|
-
}
|
|
44
|
-
function contextTemplate(bindings) {
|
|
45
|
-
const imports = bindings.map((binding) => `import { ${binding.factoryName} } from '${binding.importPath}'`);
|
|
46
|
-
const bootBody = bindings.length > 0 ? bindings.map((binding) => ` ${binding.key}: ${binding.factoryName}(),`).join("\n") : "";
|
|
47
|
-
const bootBlock = bindings.length > 0 ? ` boot: () => ({\n${bootBody}\n }),` : "";
|
|
48
|
-
return `${imports.length > 0 ? `${imports.join("\n")}\n\n` : ""}import { createContext } from '@taserjs/router'
|
|
49
|
-
|
|
50
|
-
export const context = createContext({
|
|
51
|
-
${bootBlock}
|
|
52
|
-
request: () => ({
|
|
53
|
-
requestId: crypto.randomUUID(),
|
|
54
|
-
}),
|
|
55
|
-
})
|
|
56
|
-
`;
|
|
57
|
-
}
|
|
58
|
-
function rootLayoutTemplate() {
|
|
59
|
-
return `import { cors } from '@taserjs/router/cors'
|
|
60
|
-
import { t } from '@taserjs/router'
|
|
61
|
-
|
|
62
|
-
export default t.layout('/*')
|
|
63
|
-
.use(cors())
|
|
64
|
-
`;
|
|
65
|
-
}
|
|
66
|
-
function indexRouteTemplate() {
|
|
67
|
-
return `import { t } from '@taserjs/router'
|
|
68
|
-
import { json } from '@taserjs/router/reply'
|
|
69
|
-
|
|
70
|
-
export default t.get('/').handler((_ctx) => {
|
|
71
|
-
return json({ message: 'Welcome to Taser.js' })
|
|
72
|
-
})
|
|
73
|
-
`;
|
|
74
|
-
}
|
|
75
|
-
function healthRouteTemplate(ctx) {
|
|
76
|
-
const lines = [];
|
|
77
|
-
if (ctx.logger) lines.push(" ctx.logger.info('health check')");
|
|
78
|
-
if (ctx.db) lines.push(" // ctx.db is available from context boot");
|
|
79
|
-
const body = lines.length > 0 ? `${lines.join("\n")}\n` : "";
|
|
80
|
-
return `import { t } from '@taserjs/router'
|
|
81
|
-
import { json } from '@taserjs/router/reply'
|
|
82
|
-
|
|
83
|
-
export default t.get('/health').handler(${lines.length > 0 ? "(ctx)" : "(_ctx)"} => {
|
|
84
|
-
${body} return json({ ok: true })
|
|
85
|
-
})
|
|
86
|
-
`;
|
|
87
|
-
}
|
|
88
|
-
//#endregion
|
|
89
|
-
export { contextTemplate, gitignoreTemplate, healthRouteTemplate, indexRouteTemplate, packageJsonTemplate, rootLayoutTemplate, tsconfigTemplate };
|
|
90
|
-
|
|
91
|
-
//# sourceMappingURL=base.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../../src/templates/base.ts"],"sourcesContent":["import type { BootBinding } from \"../addons/types.js\";\nimport type { ScaffoldContext } from \"../core/types.js\";\n\nexport function packageJsonTemplate(\n projectName: string,\n scripts: Record<string, string> = {},\n): string {\n const pkg = {\n name: projectName,\n version: \"1.0.0\",\n private: true,\n type: \"module\",\n scripts: {\n dev: \"vite\",\n build: \"vite build\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n \"taser:generate\": \"taser generate\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n },\n include: [\"src\", \".taser/types/**/*.d.ts\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.output\n.taser\n.DS_Store\n*.log\n.env\nlocal.db\ndrizzle\n`;\n}\n\nexport function contextTemplate(bindings: BootBinding[]): string {\n const imports = bindings.map(\n (binding) => `import { ${binding.factoryName} } from '${binding.importPath}'`,\n );\n\n const bootBody =\n bindings.length > 0\n ? bindings.map((binding) => ` ${binding.key}: ${binding.factoryName}(),`).join(\"\\n\")\n : \"\";\n\n const bootBlock = bindings.length > 0 ? ` boot: () => ({\\n${bootBody}\\n }),` : \"\";\n\n const importBlock = imports.length > 0 ? `${imports.join(\"\\n\")}\\n\\n` : \"\";\n\n return `${importBlock}import { createContext } from '@taserjs/router'\n\nexport const context = createContext({\n${bootBlock}\n request: () => ({\n requestId: crypto.randomUUID(),\n }),\n})\n`;\n}\n\nexport function rootLayoutTemplate(): string {\n return `import { cors } from '@taserjs/router/cors'\nimport { t } from '@taserjs/router'\n\nexport default t.layout('/*')\n .use(cors())\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { t } from '@taserjs/router'\nimport { json } from '@taserjs/router/reply'\n\nexport default t.get('/').handler((_ctx) => {\n return json({ message: 'Welcome to Taser.js' })\n})\n`;\n}\n\nexport function healthRouteTemplate(ctx: ScaffoldContext): string {\n const lines: string[] = [];\n\n if (ctx.logger) {\n lines.push(\" ctx.logger.info('health check')\");\n }\n\n if (ctx.db) {\n lines.push(\" // ctx.db is available from context boot\");\n }\n\n const body = lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n const ctxArg = lines.length > 0 ? \"(ctx)\" : \"(_ctx)\";\n\n return `import { t } from '@taserjs/router'\nimport { json } from '@taserjs/router/reply'\n\nexport default t.get('/health').handler(${ctxArg} => {\n${body} return json({ ok: true })\n})\n`;\n}\n"],"mappings":";AAGA,SAAgB,oBACd,aACA,UAAkC,CAAC,GAC3B;CACR,MAAM,MAAM;EACV,MAAM;EACN,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS;GACP,KAAK;GACL,OAAO;GACP,WAAW;GACX,kBAAkB;GAClB,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;EACV;EACA,SAAS,CAAC,OAAO,wBAAwB;CAC3C,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;;;AAUT;AAEA,SAAgB,gBAAgB,UAAiC;CAC/D,MAAM,UAAU,SAAS,KACtB,YAAY,YAAY,QAAQ,YAAY,WAAW,QAAQ,WAAW,EAC7E;CAEA,MAAM,WACJ,SAAS,SAAS,IACd,SAAS,KAAK,YAAY,OAAO,QAAQ,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC,CAAC,KAAK,IAAI,IACpF;CAEN,MAAM,YAAY,SAAS,SAAS,IAAI,qBAAqB,SAAS,WAAW;CAIjF,OAAO,GAFa,QAAQ,SAAS,IAAI,GAAG,QAAQ,KAAK,IAAI,EAAE,QAAQ,GAEjD;;;EAGtB,UAAU;;;;;;AAMZ;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;AAMT;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;AAOT;AAEA,SAAgB,oBAAoB,KAA8B;CAChE,MAAM,QAAkB,CAAC;CAEzB,IAAI,IAAI,QACN,MAAM,KAAK,mCAAmC;CAGhD,IAAI,IAAI,IACN,MAAM,KAAK,4CAA4C;CAGzD,MAAM,OAAO,MAAM,SAAS,IAAI,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM;CAG1D,OAAO;;;0CAFQ,MAAM,SAAS,IAAI,UAAU,SAKG;EAC/C,KAAK;;;AAGP"}
|
package/dist/esm/types.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type { DbDriver, DbOdm, DeployTarget, Framework, LoggerId, PackageGroups, Runtime, ScaffoldOptions, ScaffoldResult, ValidatorId, } from './core/types.js';
|
package/src/addons/zod/index.ts
DELETED
package/src/core/json-output.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { CapabilitiesCatalog, ScaffoldResult } from "./types.js";
|
|
2
|
-
|
|
3
|
-
export function printCapabilitiesCatalog(catalog: CapabilitiesCatalog): void {
|
|
4
|
-
console.log(JSON.stringify(catalog, null, 2));
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function printScaffoldResult(result: ScaffoldResult): void {
|
|
8
|
-
console.log(JSON.stringify(result, null, 2));
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function printJsonError(message: string): void {
|
|
12
|
-
console.error(JSON.stringify({ error: message }));
|
|
13
|
-
}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DB_DRIVERS,
|
|
3
|
-
DB_ODMS,
|
|
4
|
-
DEFAULT_DB_DRIVER,
|
|
5
|
-
FRAMEWORKS,
|
|
6
|
-
LOGGERS,
|
|
7
|
-
RUNTIMES,
|
|
8
|
-
VALIDATORS,
|
|
9
|
-
type DbDriver,
|
|
10
|
-
type DbOdm,
|
|
11
|
-
type DeployTarget,
|
|
12
|
-
type Framework,
|
|
13
|
-
type LoggerId,
|
|
14
|
-
type Runtime,
|
|
15
|
-
type ScaffoldContext,
|
|
16
|
-
type ValidatorId,
|
|
17
|
-
} from "./types.js";
|
|
18
|
-
import {
|
|
19
|
-
DEFAULT_DEPLOY,
|
|
20
|
-
isCuratedDeploy,
|
|
21
|
-
resolveDeployEntry,
|
|
22
|
-
validateCombination,
|
|
23
|
-
} from "./targets.js";
|
|
24
|
-
|
|
25
|
-
export type ParsedCreateArgs = {
|
|
26
|
-
projectName?: string;
|
|
27
|
-
framework?: Framework;
|
|
28
|
-
/** Deployment target — a Nitro preset id. */
|
|
29
|
-
preset?: string;
|
|
30
|
-
runtime?: Runtime;
|
|
31
|
-
db?: DbOdm;
|
|
32
|
-
driver?: DbDriver;
|
|
33
|
-
logger?: LoggerId;
|
|
34
|
-
validator?: ValidatorId;
|
|
35
|
-
yes: boolean;
|
|
36
|
-
noInstall: boolean;
|
|
37
|
-
json: boolean;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
function isFramework(value: string): value is Framework {
|
|
41
|
-
return (FRAMEWORKS as readonly string[]).includes(value);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function isRuntime(value: string): value is Runtime {
|
|
45
|
-
return (RUNTIMES as readonly string[]).includes(value);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function isDbOdm(value: string): value is DbOdm {
|
|
49
|
-
return (DB_ODMS as readonly string[]).includes(value);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function isDbDriver(value: string): value is DbDriver {
|
|
53
|
-
return (DB_DRIVERS as readonly string[]).includes(value);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function isLoggerId(value: string): value is LoggerId {
|
|
57
|
-
return (LOGGERS as readonly string[]).includes(value);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function isValidatorId(value: string): value is ValidatorId {
|
|
61
|
-
return (VALIDATORS as readonly string[]).includes(value);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function parseDbFlag(value: string): { db: DbOdm; driver: DbDriver } {
|
|
65
|
-
const [odm, driver] = value.split(":");
|
|
66
|
-
if (!odm || !isDbOdm(odm)) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
`Invalid --db value "${value}". Use drizzle, prisma, or kysely (optionally with :postgres, :sqlite, or :mysql).`,
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (driver === undefined || driver === "") {
|
|
73
|
-
return { db: odm, driver: DEFAULT_DB_DRIVER };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!isDbDriver(driver)) {
|
|
77
|
-
throw new Error(`Invalid database driver "${driver}". Use postgres, sqlite, or mysql.`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return { db: odm, driver };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function parseFrameworkFlag(value: string): Framework {
|
|
84
|
-
if (!isFramework(value)) {
|
|
85
|
-
throw new Error(`Invalid --framework "${value}". Use ${FRAMEWORKS.join(", ")}.`);
|
|
86
|
-
}
|
|
87
|
-
return value;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Accepts curated deploy targets verbatim; unknown ids pass through to Nitro.
|
|
92
|
-
* Returns a warning for passthrough ids so callers can surface it.
|
|
93
|
-
*/
|
|
94
|
-
export function parsePresetFlag(value: string): { preset: string; warning?: string } {
|
|
95
|
-
if (!isCuratedDeploy(value)) {
|
|
96
|
-
if (!/^[a-z0-9][a-z0-9-_]*$/i.test(value)) {
|
|
97
|
-
throw new Error(`Invalid --preset "${value}".`);
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
preset: value,
|
|
101
|
-
warning: `"${value}" is not a curated Taser.js deploy target; passing it through to Nitro as-is.`,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
return { preset: value };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function parseRuntimeFlag(value: string): Runtime {
|
|
108
|
-
if (!isRuntime(value)) {
|
|
109
|
-
throw new Error(`Invalid --runtime "${value}". Use node, bun, or deno.`);
|
|
110
|
-
}
|
|
111
|
-
return value;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function parseLoggerFlag(value: string): LoggerId {
|
|
115
|
-
if (!isLoggerId(value)) {
|
|
116
|
-
throw new Error(`Invalid --logger "${value}". Use pino or winston.`);
|
|
117
|
-
}
|
|
118
|
-
return value;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function parseValidatorFlag(value: string): ValidatorId {
|
|
122
|
-
if (!isValidatorId(value)) {
|
|
123
|
-
throw new Error(`Invalid --validator "${value}". Use zod, arktype, or valibot.`);
|
|
124
|
-
}
|
|
125
|
-
return value;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function resolveScaffoldDefaults(args: ParsedCreateArgs): ScaffoldContext {
|
|
129
|
-
const framework: Framework = args.framework ?? "none";
|
|
130
|
-
const preset = args.preset ?? DEFAULT_DEPLOY;
|
|
131
|
-
|
|
132
|
-
if (!args.projectName) {
|
|
133
|
-
throw new Error("Project name is required");
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Throws with a precise reason when runtime × framework × deploy clash.
|
|
137
|
-
const combination = validateCombination(args.runtime, framework, preset);
|
|
138
|
-
if (!combination.ok) {
|
|
139
|
-
throw new Error(combination.reason);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const result: ScaffoldContext = {
|
|
143
|
-
projectName: args.projectName.trim(),
|
|
144
|
-
targetDir: "",
|
|
145
|
-
framework,
|
|
146
|
-
preset: preset as DeployTarget,
|
|
147
|
-
...(args.runtime !== undefined ? { runtime: args.runtime } : {}),
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
if (args.db) {
|
|
151
|
-
result.db = args.db;
|
|
152
|
-
result.driver = args.driver ?? DEFAULT_DB_DRIVER;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (args.logger) {
|
|
156
|
-
result.logger = args.logger;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (args.validator) {
|
|
160
|
-
result.validator = args.validator;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return result;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/** Re-exported for CLI layers that need to warn about passthrough presets. */
|
|
167
|
-
export { resolveDeployEntry };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { writeFile } from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
import type { ScaffoldContext } from "./types.js";
|
|
5
|
-
|
|
6
|
-
export async function writeProjectConfig(root: string, ctx: ScaffoldContext): Promise<void> {
|
|
7
|
-
const config: Record<string, string> = {
|
|
8
|
-
framework: ctx.framework ?? "none",
|
|
9
|
-
preset: ctx.preset ?? "node-server",
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
if (ctx.runtime) {
|
|
13
|
-
config.runtime = ctx.runtime;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (ctx.db) {
|
|
17
|
-
config.db = ctx.db;
|
|
18
|
-
if (ctx.driver) {
|
|
19
|
-
config.driver = ctx.driver;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (ctx.logger) {
|
|
24
|
-
config.logger = ctx.logger;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (ctx.validator) {
|
|
28
|
-
config.validator = ctx.validator;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
await writeFile(path.join(root, ".taser.json"), `${JSON.stringify(config, null, 2)}\n`, "utf8");
|
|
32
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { resolveAddons } from "../addons/registry.js";
|
|
2
|
-
import { FRAMEWORK_ENTRIES } from "../frameworks/index.js";
|
|
3
|
-
import type { PackageGroups, ScaffoldContext } from "../core/types.js";
|
|
4
|
-
import { resolveDeployEntry } from "./targets.js";
|
|
5
|
-
|
|
6
|
-
const BASE_DEPENDENCIES = ["@taserjs/router", "dotenv", "srvx"];
|
|
7
|
-
|
|
8
|
-
/** Runtime-agnostic build/dev tooling every scaffolded project needs. */
|
|
9
|
-
const BASE_DEV_DEPENDENCIES = [
|
|
10
|
-
"@taserjs/router-plugin",
|
|
11
|
-
"@taserjs/router-cli",
|
|
12
|
-
"typescript@^5.9.3",
|
|
13
|
-
"vite@^8.1.5",
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
function runtimeDevDeps(ctx: ScaffoldContext): string[] {
|
|
17
|
-
const { entry } = resolveDeployEntry(ctx.preset ?? "node-server");
|
|
18
|
-
const effective = ctx.runtime ?? entry.impliedRuntime;
|
|
19
|
-
switch (effective) {
|
|
20
|
-
case "bun":
|
|
21
|
-
return ["@types/bun"];
|
|
22
|
-
case "deno":
|
|
23
|
-
return []; // Deno ships its own tooling and types.
|
|
24
|
-
case "workerd":
|
|
25
|
-
return ["@cloudflare/workers-types"];
|
|
26
|
-
case "node":
|
|
27
|
-
default:
|
|
28
|
-
return ["@types/node"];
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function resolvePackages(ctx: ScaffoldContext): PackageGroups {
|
|
33
|
-
const frameworkEntry = FRAMEWORK_ENTRIES[ctx.framework ?? "none"];
|
|
34
|
-
const { entry: deployEntry } = resolveDeployEntry(ctx.preset ?? "node-server");
|
|
35
|
-
|
|
36
|
-
const dependencies = [...BASE_DEPENDENCIES, ...frameworkEntry.deps];
|
|
37
|
-
const nitroDevDeps = ctx.preset === "none" ? [] : ["nitro"];
|
|
38
|
-
const devDependencies = [
|
|
39
|
-
...BASE_DEV_DEPENDENCIES,
|
|
40
|
-
...nitroDevDeps,
|
|
41
|
-
...runtimeDevDeps(ctx),
|
|
42
|
-
...deployEntry.devDeps,
|
|
43
|
-
...frameworkEntry.devDeps,
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
const scripts: Record<string, string> = {};
|
|
47
|
-
if (deployEntry.startScript) {
|
|
48
|
-
if (ctx.preset === "none" && ctx.runtime === "bun") {
|
|
49
|
-
scripts.start = "bun dist/serve.mjs";
|
|
50
|
-
} else {
|
|
51
|
-
scripts.start = deployEntry.startScript;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const addons = resolveAddons(ctx);
|
|
56
|
-
for (const addon of addons) {
|
|
57
|
-
dependencies.push(...addon.dependencies(ctx));
|
|
58
|
-
devDependencies.push(...addon.devDependencies(ctx));
|
|
59
|
-
if (addon.scripts) {
|
|
60
|
-
Object.assign(scripts, addon.scripts(ctx));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
dependencies: [...new Set(dependencies)],
|
|
66
|
-
devDependencies: [...new Set(devDependencies)],
|
|
67
|
-
scripts,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
|
|
3
|
-
const RESERVED_WINDOWS_NAMES = new Set([
|
|
4
|
-
"CON",
|
|
5
|
-
"PRN",
|
|
6
|
-
"AUX",
|
|
7
|
-
"NVR",
|
|
8
|
-
"NULL",
|
|
9
|
-
"COM1",
|
|
10
|
-
"COM2",
|
|
11
|
-
"COM3",
|
|
12
|
-
"COM4",
|
|
13
|
-
"COM5",
|
|
14
|
-
"COM6",
|
|
15
|
-
"COM7",
|
|
16
|
-
"COM8",
|
|
17
|
-
"COM9",
|
|
18
|
-
"LPT1",
|
|
19
|
-
"LPT2",
|
|
20
|
-
"LPT3",
|
|
21
|
-
"LPT4",
|
|
22
|
-
"LPT5",
|
|
23
|
-
"LPT6",
|
|
24
|
-
"LPT7",
|
|
25
|
-
"LPT8",
|
|
26
|
-
"LPT9",
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
export function validateProjectName(name: string, cwd = process.cwd()): string | undefined {
|
|
30
|
-
const trimmed = name.trim();
|
|
31
|
-
if (!trimmed) {
|
|
32
|
-
return "Project name is required";
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (trimmed.includes("..")) {
|
|
36
|
-
return 'Project name cannot contain ".."';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (trimmed.startsWith(".") || trimmed.endsWith(".")) {
|
|
40
|
-
return "Project name cannot start or end with a dot";
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const baseName = trimmed.split(".")[0]?.toUpperCase();
|
|
44
|
-
if (baseName && RESERVED_WINDOWS_NAMES.has(baseName)) {
|
|
45
|
-
return `Project name "${trimmed}" is reserved on Windows`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const targetDir = path.resolve(cwd, trimmed);
|
|
49
|
-
const relative = path.relative(cwd, targetDir);
|
|
50
|
-
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
51
|
-
return "Project name resolves outside the current directory";
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return undefined;
|
|
55
|
-
}
|