create-taserjs 0.1.0 → 0.1.1

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.
Files changed (45) hide show
  1. package/dist/cjs/addons/prisma/index.cjs +12 -5
  2. package/dist/cjs/addons/prisma/index.cjs.map +1 -1
  3. package/dist/cjs/commands/create.cjs +6 -3
  4. package/dist/cjs/commands/create.cjs.map +1 -1
  5. package/dist/cjs/core/resolve-packages.cjs +11 -3
  6. package/dist/cjs/core/resolve-packages.cjs.map +1 -1
  7. package/dist/cjs/core/scaffold-engine.cjs +2 -2
  8. package/dist/cjs/core/scaffold-engine.cjs.map +1 -1
  9. package/dist/cjs/core/targets.cjs +9 -0
  10. package/dist/cjs/core/targets.cjs.map +1 -1
  11. package/dist/cjs/core/types.cjs +1 -0
  12. package/dist/cjs/core/types.cjs.map +1 -1
  13. package/dist/cjs/core/types.d.cts +1 -1
  14. package/dist/cjs/core/validate-project-name.cjs +0 -1
  15. package/dist/cjs/core/validate-project-name.cjs.map +1 -1
  16. package/dist/cjs/frameworks/index.cjs +10 -3
  17. package/dist/cjs/frameworks/index.cjs.map +1 -1
  18. package/dist/cjs/frameworks/index.d.cts +2 -2
  19. package/dist/esm/addons/prisma/index.js +12 -5
  20. package/dist/esm/addons/prisma/index.js.map +1 -1
  21. package/dist/esm/commands/create.js +6 -3
  22. package/dist/esm/commands/create.js.map +1 -1
  23. package/dist/esm/core/resolve-packages.js +11 -3
  24. package/dist/esm/core/resolve-packages.js.map +1 -1
  25. package/dist/esm/core/scaffold-engine.js +2 -2
  26. package/dist/esm/core/scaffold-engine.js.map +1 -1
  27. package/dist/esm/core/targets.js +9 -0
  28. package/dist/esm/core/targets.js.map +1 -1
  29. package/dist/esm/core/types.d.ts +1 -1
  30. package/dist/esm/core/types.js +1 -0
  31. package/dist/esm/core/types.js.map +1 -1
  32. package/dist/esm/core/validate-project-name.js +0 -1
  33. package/dist/esm/core/validate-project-name.js.map +1 -1
  34. package/dist/esm/frameworks/index.d.ts +2 -2
  35. package/dist/esm/frameworks/index.js +10 -3
  36. package/dist/esm/frameworks/index.js.map +1 -1
  37. package/package.json +2 -2
  38. package/src/addons/prisma/index.ts +12 -5
  39. package/src/commands/create.ts +12 -2
  40. package/src/core/resolve-packages.ts +9 -8
  41. package/src/core/scaffold-engine.ts +3 -3
  42. package/src/core/targets.ts +9 -0
  43. package/src/core/types.ts +2 -0
  44. package/src/core/validate-project-name.ts +0 -4
  45. package/src/frameworks/index.ts +14 -4
@@ -43,8 +43,8 @@ async function promptInteractiveOptions(args) {
43
43
  options: [
44
44
  {
45
45
  value: "none",
46
- label: "Pure Taser",
47
- hint: "default"
46
+ label: "None",
47
+ hint: "Taser Fetch (default)"
48
48
  },
49
49
  {
50
50
  value: "hono",
@@ -66,6 +66,7 @@ async function promptInteractiveOptions(args) {
66
66
  process.exit(0);
67
67
  }
68
68
  const DEPLOY_LABELS = {
69
+ none: "None (Standalone Vite)",
69
70
  "node-server": "Node.js server",
70
71
  "node-cluster": "Node.js cluster",
71
72
  bun: "Bun",
@@ -76,11 +77,13 @@ async function promptInteractiveOptions(args) {
76
77
  "aws-lambda": "AWS Lambda",
77
78
  netlify: "Netlify"
78
79
  };
80
+ const DEPLOY_HINTS = { none: "standalone Vite, no Nitro" };
79
81
  const preset = args.preset ?? await p.select({
80
82
  message: "Deployment target",
81
83
  options: DEPLOY_TARGETS.map((id) => ({
82
84
  value: id,
83
- label: DEPLOY_LABELS[id]
85
+ label: DEPLOY_LABELS[id],
86
+ ...DEPLOY_HINTS[id] ? { hint: DEPLOY_HINTS[id] } : {}
84
87
  })),
85
88
  initialValue: "node-server"
86
89
  });
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","names":[],"sources":["../../../src/commands/create.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\nimport color from \"picocolors\";\n\nimport { getCapabilitiesCatalog } from \"../addons/registry.js\";\nimport {\n printCapabilitiesCatalog,\n printJsonError,\n printScaffoldResult,\n} from \"../core/json-output.js\";\nimport {\n parseDbFlag,\n parseFrameworkFlag,\n parseLoggerFlag,\n parsePresetFlag,\n parseRuntimeFlag,\n parseValidatorFlag,\n type ParsedCreateArgs,\n resolveScaffoldDefaults,\n} from \"../core/parse-options.js\";\nimport { scaffoldProject } from \"../core/scaffold-engine.js\";\nimport { allowedRuntimeOverrides } from \"../core/targets.js\";\nimport type {\n DbDriver,\n DbOdm,\n DeployTarget,\n LoggerId,\n ScaffoldResult,\n ValidatorId,\n} from \"../core/types.js\";\nimport { DB_DRIVERS, DB_ODMS, DEPLOY_TARGETS, LOGGERS, VALIDATORS } from \"../core/types.js\";\nimport { validateProjectName } from \"../core/validate-project-name.js\";\nimport { resolveUserAgent, runScript } from \"../core/package-manager.js\";\n\nfunction isDeployTarget(value: unknown): value is DeployTarget {\n return typeof value === \"string\" && (DEPLOY_TARGETS as readonly string[]).includes(value);\n}\n\nfunction isDbOdm(value: unknown): value is DbOdm {\n return typeof value === \"string\" && (DB_ODMS as readonly string[]).includes(value);\n}\n\nfunction isDbDriver(value: unknown): value is DbDriver {\n return typeof value === \"string\" && (DB_DRIVERS as readonly string[]).includes(value);\n}\n\nfunction isLoggerId(value: unknown): value is LoggerId {\n return typeof value === \"string\" && (LOGGERS as readonly string[]).includes(value);\n}\n\nfunction isValidatorId(value: unknown): value is ValidatorId {\n return typeof value === \"string\" && (VALIDATORS as readonly string[]).includes(value);\n}\n\nasync function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedCreateArgs> {\n const projectName =\n args.projectName ??\n (await p.text({\n message: \"Project name\",\n placeholder: \"my-taser-app\",\n defaultValue: \"my-taser-app\",\n validate(value) {\n return validateProjectName(value);\n },\n }));\n\n if (p.isCancel(projectName)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n const framework =\n args.framework ??\n (await p.select({\n message: \"Host framework\",\n options: [\n { value: \"none\", label: \"Pure Taser\", hint: \"default\" },\n { value: \"hono\", label: \"Hono\" },\n { value: \"express\", label: \"Express\" },\n { value: \"fastify\", label: \"Fastify\" },\n ],\n initialValue: \"none\",\n }));\n\n if (p.isCancel(framework)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n const DEPLOY_LABELS: Record<DeployTarget, string> = {\n \"node-server\": \"Node.js server\",\n \"node-cluster\": \"Node.js cluster\",\n bun: \"Bun\",\n \"deno-server\": \"Deno\",\n \"deno-deploy\": \"Deno Deploy\",\n \"cloudflare-module\": \"Cloudflare Workers\",\n vercel: \"Vercel\",\n \"aws-lambda\": \"AWS Lambda\",\n netlify: \"Netlify\",\n };\n\n const preset =\n args.preset ??\n (await p.select({\n message: \"Deployment target\",\n options: DEPLOY_TARGETS.map((id) => ({ value: id, label: DEPLOY_LABELS[id] })),\n initialValue: \"node-server\",\n }));\n\n if (p.isCancel(preset) || !isDeployTarget(preset)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n let runtime: import(\"../core/types.js\").Runtime | undefined;\n const runtimeOverrides = allowedRuntimeOverrides(preset);\n if (runtimeOverrides.length > 0) {\n const runtimeChoice =\n args.runtime ??\n (await p.select({\n message: \"Runtime\",\n options: [\n ...runtimeOverrides.map((rt) => ({ value: rt, label: rt })),\n { value: \"default\", label: `Preset default`, hint: \"no override\" },\n ],\n initialValue: \"default\",\n }));\n\n if (p.isCancel(runtimeChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n runtime = runtimeChoice === \"default\" ? undefined : runtimeChoice;\n }\n\n const dbChoice =\n args.db ??\n (await p.select({\n message: \"Database\",\n options: [\n { value: \"none\", label: \"None\", hint: \"default\" },\n { value: \"drizzle\", label: \"Drizzle\" },\n { value: \"prisma\", label: \"Prisma\" },\n { value: \"kysely\", label: \"Kysely\" },\n ],\n initialValue: \"none\",\n }));\n\n if (p.isCancel(dbChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n let db: DbOdm | undefined;\n let driver: DbDriver | undefined;\n\n if (dbChoice !== \"none\" && isDbOdm(dbChoice)) {\n db = dbChoice;\n const driverChoice =\n args.driver ??\n (await p.select({\n message: \"Database driver\",\n options: [\n { value: \"sqlite\", label: \"SQLite\", hint: \"default\" },\n { value: \"postgres\", label: \"PostgreSQL\" },\n { value: \"mysql\", label: \"MySQL\" },\n ],\n initialValue: \"sqlite\",\n }));\n\n if (p.isCancel(driverChoice) || !isDbDriver(driverChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n driver = driverChoice;\n }\n\n const loggerChoice =\n args.logger ??\n (await p.select({\n message: \"Logger\",\n options: [\n { value: \"none\", label: \"None\", hint: \"default\" },\n { value: \"pino\", label: \"Pino\" },\n { value: \"winston\", label: \"Winston\" },\n ],\n initialValue: \"none\",\n }));\n\n if (p.isCancel(loggerChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n const logger =\n loggerChoice === \"none\" ? undefined : isLoggerId(loggerChoice) ? loggerChoice : undefined;\n\n const validatorChoice =\n args.validator ??\n (await p.select({\n message: \"Validator\",\n options: [\n { value: \"none\", label: \"None\", hint: \"default\" },\n { value: \"zod\", label: \"Zod\" },\n { value: \"arktype\", label: \"Arktype\" },\n { value: \"valibot\", label: \"Valibot\" },\n ],\n initialValue: \"none\",\n }));\n\n if (p.isCancel(validatorChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n const validator =\n validatorChoice === \"none\"\n ? undefined\n : isValidatorId(validatorChoice)\n ? validatorChoice\n : undefined;\n\n return {\n projectName: String(projectName).trim(),\n framework,\n preset,\n ...(runtime !== undefined ? { runtime } : {}),\n yes: args.yes,\n noInstall: args.noInstall,\n json: args.json,\n ...(db ? { db, driver: driver! } : {}),\n ...(logger ? { logger } : {}),\n ...(validator ? { validator } : {}),\n };\n}\n\nexport async function runCreateCommand(\n args: ParsedCreateArgs,\n): Promise<ScaffoldResult | undefined> {\n if (args.json && !args.projectName) {\n printCapabilitiesCatalog(getCapabilitiesCatalog());\n return undefined;\n }\n\n const cwd = process.cwd();\n const interactive = !args.yes;\n const resolved = interactive\n ? await promptInteractiveOptions(args)\n : {\n ...args,\n projectName: args.projectName?.trim(),\n preset: args.preset ?? \"node-server\",\n };\n\n if (!resolved.projectName) {\n const message = \"Project name is required\";\n if (args.json) {\n printJsonError(message);\n process.exit(1);\n }\n throw new Error(message);\n }\n\n const nameError = validateProjectName(resolved.projectName, cwd);\n if (nameError) {\n if (args.json) {\n printJsonError(nameError);\n process.exit(1);\n }\n throw new Error(nameError);\n }\n\n const targetDir = path.resolve(cwd, resolved.projectName);\n const scaffoldCtx = resolveScaffoldDefaults({\n ...resolved,\n projectName: resolved.projectName,\n });\n scaffoldCtx.targetDir = targetDir;\n\n if (!args.json) {\n const spinner = p.spinner();\n spinner.start(\"Scaffolding project\");\n try {\n const result = await scaffoldProject({\n ...scaffoldCtx,\n targetDir,\n skipInstall: args.noInstall,\n agent: resolveUserAgent(),\n });\n spinner.stop(\"Project created\");\n const cdPath = path.relative(cwd, targetDir) || \".\";\n p.note([`cd ${cdPath}`, runScript(resolveUserAgent(), \"dev\")].join(\"\\n\"), \"Next steps\");\n p.outro(color.green(\"Done.\"));\n return result;\n } catch (error) {\n spinner.stop(\"Scaffold failed\");\n throw error;\n }\n }\n\n const result = await scaffoldProject({\n ...scaffoldCtx,\n targetDir,\n skipInstall: args.noInstall,\n agent: resolveUserAgent(),\n });\n printScaffoldResult(result);\n return result;\n}\n\nexport function buildParsedArgsFromCli(\n values: {\n preset?: string;\n framework?: string;\n runtime?: string;\n db?: string;\n logger?: string;\n validator?: string;\n y?: boolean;\n noInstall?: boolean;\n json?: boolean;\n },\n positionals: string[],\n): ParsedCreateArgs {\n const args: ParsedCreateArgs = {\n yes: values.y ?? false,\n noInstall: values.noInstall ?? false,\n json: values.json ?? false,\n };\n\n if (positionals[0]) {\n args.projectName = positionals[0];\n }\n\n if (values.preset) {\n const parsed = parsePresetFlag(values.preset);\n args.preset = parsed.preset;\n if (parsed.warning && !args.json) {\n console.warn(`warning: ${parsed.warning}`);\n }\n }\n\n if (values.framework) {\n args.framework = parseFrameworkFlag(values.framework);\n }\n\n if (values.runtime) {\n args.runtime = parseRuntimeFlag(values.runtime);\n }\n\n if (values.db) {\n const parsed = parseDbFlag(values.db);\n args.db = parsed.db;\n args.driver = parsed.driver;\n }\n\n if (values.logger) {\n args.logger = parseLoggerFlag(values.logger);\n }\n\n if (values.validator) {\n args.validator = parseValidatorFlag(values.validator);\n }\n\n return args;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"create.js","names":[],"sources":["../../../src/commands/create.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\nimport color from \"picocolors\";\n\nimport { getCapabilitiesCatalog } from \"../addons/registry.js\";\nimport {\n printCapabilitiesCatalog,\n printJsonError,\n printScaffoldResult,\n} from \"../core/json-output.js\";\nimport {\n parseDbFlag,\n parseFrameworkFlag,\n parseLoggerFlag,\n parsePresetFlag,\n parseRuntimeFlag,\n parseValidatorFlag,\n type ParsedCreateArgs,\n resolveScaffoldDefaults,\n} from \"../core/parse-options.js\";\nimport { scaffoldProject } from \"../core/scaffold-engine.js\";\nimport { allowedRuntimeOverrides } from \"../core/targets.js\";\nimport type {\n DbDriver,\n DbOdm,\n DeployTarget,\n LoggerId,\n ScaffoldResult,\n ValidatorId,\n} from \"../core/types.js\";\nimport { DB_DRIVERS, DB_ODMS, DEPLOY_TARGETS, LOGGERS, VALIDATORS } from \"../core/types.js\";\nimport { validateProjectName } from \"../core/validate-project-name.js\";\nimport { resolveUserAgent, runScript } from \"../core/package-manager.js\";\n\nfunction isDeployTarget(value: unknown): value is DeployTarget {\n return typeof value === \"string\" && (DEPLOY_TARGETS as readonly string[]).includes(value);\n}\n\nfunction isDbOdm(value: unknown): value is DbOdm {\n return typeof value === \"string\" && (DB_ODMS as readonly string[]).includes(value);\n}\n\nfunction isDbDriver(value: unknown): value is DbDriver {\n return typeof value === \"string\" && (DB_DRIVERS as readonly string[]).includes(value);\n}\n\nfunction isLoggerId(value: unknown): value is LoggerId {\n return typeof value === \"string\" && (LOGGERS as readonly string[]).includes(value);\n}\n\nfunction isValidatorId(value: unknown): value is ValidatorId {\n return typeof value === \"string\" && (VALIDATORS as readonly string[]).includes(value);\n}\n\nasync function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedCreateArgs> {\n const projectName =\n args.projectName ??\n (await p.text({\n message: \"Project name\",\n placeholder: \"my-taser-app\",\n defaultValue: \"my-taser-app\",\n validate(value) {\n return validateProjectName(value);\n },\n }));\n\n if (p.isCancel(projectName)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n const framework =\n args.framework ??\n (await p.select({\n message: \"Host framework\",\n options: [\n { value: \"none\", label: \"None\", hint: \"Taser Fetch (default)\" },\n { value: \"hono\", label: \"Hono\" },\n { value: \"express\", label: \"Express\" },\n { value: \"fastify\", label: \"Fastify\" },\n ],\n initialValue: \"none\",\n }));\n\n if (p.isCancel(framework)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n const DEPLOY_LABELS: Record<DeployTarget, string> = {\n none: \"None (Standalone Vite)\",\n \"node-server\": \"Node.js server\",\n \"node-cluster\": \"Node.js cluster\",\n bun: \"Bun\",\n \"deno-server\": \"Deno\",\n \"deno-deploy\": \"Deno Deploy\",\n \"cloudflare-module\": \"Cloudflare Workers\",\n vercel: \"Vercel\",\n \"aws-lambda\": \"AWS Lambda\",\n netlify: \"Netlify\",\n };\n\n const DEPLOY_HINTS: Partial<Record<DeployTarget, string>> = {\n none: \"standalone Vite, no Nitro\",\n };\n\n const preset =\n args.preset ??\n (await p.select({\n message: \"Deployment target\",\n // oxlint-disable-next-line oxc/no-map-spread\n options: DEPLOY_TARGETS.map((id) => ({\n value: id,\n label: DEPLOY_LABELS[id],\n ...(DEPLOY_HINTS[id] ? { hint: DEPLOY_HINTS[id] } : {}),\n })),\n initialValue: \"node-server\",\n }));\n\n if (p.isCancel(preset) || !isDeployTarget(preset)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n let runtime: import(\"../core/types.js\").Runtime | undefined;\n const runtimeOverrides = allowedRuntimeOverrides(preset);\n if (runtimeOverrides.length > 0) {\n const runtimeChoice =\n args.runtime ??\n (await p.select({\n message: \"Runtime\",\n options: [\n ...runtimeOverrides.map((rt) => ({ value: rt, label: rt })),\n { value: \"default\", label: `Preset default`, hint: \"no override\" },\n ],\n initialValue: \"default\",\n }));\n\n if (p.isCancel(runtimeChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n runtime = runtimeChoice === \"default\" ? undefined : runtimeChoice;\n }\n\n const dbChoice =\n args.db ??\n (await p.select({\n message: \"Database\",\n options: [\n { value: \"none\", label: \"None\", hint: \"default\" },\n { value: \"drizzle\", label: \"Drizzle\" },\n { value: \"prisma\", label: \"Prisma\" },\n { value: \"kysely\", label: \"Kysely\" },\n ],\n initialValue: \"none\",\n }));\n\n if (p.isCancel(dbChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n let db: DbOdm | undefined;\n let driver: DbDriver | undefined;\n\n if (dbChoice !== \"none\" && isDbOdm(dbChoice)) {\n db = dbChoice;\n const driverChoice =\n args.driver ??\n (await p.select({\n message: \"Database driver\",\n options: [\n { value: \"sqlite\", label: \"SQLite\", hint: \"default\" },\n { value: \"postgres\", label: \"PostgreSQL\" },\n { value: \"mysql\", label: \"MySQL\" },\n ],\n initialValue: \"sqlite\",\n }));\n\n if (p.isCancel(driverChoice) || !isDbDriver(driverChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n driver = driverChoice;\n }\n\n const loggerChoice =\n args.logger ??\n (await p.select({\n message: \"Logger\",\n options: [\n { value: \"none\", label: \"None\", hint: \"default\" },\n { value: \"pino\", label: \"Pino\" },\n { value: \"winston\", label: \"Winston\" },\n ],\n initialValue: \"none\",\n }));\n\n if (p.isCancel(loggerChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n const logger =\n loggerChoice === \"none\" ? undefined : isLoggerId(loggerChoice) ? loggerChoice : undefined;\n\n const validatorChoice =\n args.validator ??\n (await p.select({\n message: \"Validator\",\n options: [\n { value: \"none\", label: \"None\", hint: \"default\" },\n { value: \"zod\", label: \"Zod\" },\n { value: \"arktype\", label: \"Arktype\" },\n { value: \"valibot\", label: \"Valibot\" },\n ],\n initialValue: \"none\",\n }));\n\n if (p.isCancel(validatorChoice)) {\n p.cancel(\"Scaffold cancelled.\");\n process.exit(0);\n }\n\n const validator =\n validatorChoice === \"none\"\n ? undefined\n : isValidatorId(validatorChoice)\n ? validatorChoice\n : undefined;\n\n return {\n projectName: String(projectName).trim(),\n framework,\n preset,\n ...(runtime !== undefined ? { runtime } : {}),\n yes: args.yes,\n noInstall: args.noInstall,\n json: args.json,\n ...(db ? { db, driver: driver! } : {}),\n ...(logger ? { logger } : {}),\n ...(validator ? { validator } : {}),\n };\n}\n\nexport async function runCreateCommand(\n args: ParsedCreateArgs,\n): Promise<ScaffoldResult | undefined> {\n if (args.json && !args.projectName) {\n printCapabilitiesCatalog(getCapabilitiesCatalog());\n return undefined;\n }\n\n const cwd = process.cwd();\n const interactive = !args.yes;\n const resolved = interactive\n ? await promptInteractiveOptions(args)\n : {\n ...args,\n projectName: args.projectName?.trim(),\n preset: args.preset ?? \"node-server\",\n };\n\n if (!resolved.projectName) {\n const message = \"Project name is required\";\n if (args.json) {\n printJsonError(message);\n process.exit(1);\n }\n throw new Error(message);\n }\n\n const nameError = validateProjectName(resolved.projectName, cwd);\n if (nameError) {\n if (args.json) {\n printJsonError(nameError);\n process.exit(1);\n }\n throw new Error(nameError);\n }\n\n const targetDir = path.resolve(cwd, resolved.projectName);\n const scaffoldCtx = resolveScaffoldDefaults({\n ...resolved,\n projectName: resolved.projectName,\n });\n scaffoldCtx.targetDir = targetDir;\n\n if (!args.json) {\n const spinner = p.spinner();\n spinner.start(\"Scaffolding project\");\n try {\n const result = await scaffoldProject({\n ...scaffoldCtx,\n targetDir,\n skipInstall: args.noInstall,\n agent: resolveUserAgent(),\n });\n spinner.stop(\"Project created\");\n const cdPath = path.relative(cwd, targetDir) || \".\";\n p.note([`cd ${cdPath}`, runScript(resolveUserAgent(), \"dev\")].join(\"\\n\"), \"Next steps\");\n p.outro(color.green(\"Done.\"));\n return result;\n } catch (error) {\n spinner.stop(\"Scaffold failed\");\n throw error;\n }\n }\n\n const result = await scaffoldProject({\n ...scaffoldCtx,\n targetDir,\n skipInstall: args.noInstall,\n agent: resolveUserAgent(),\n });\n printScaffoldResult(result);\n return result;\n}\n\nexport function buildParsedArgsFromCli(\n values: {\n preset?: string;\n framework?: string;\n runtime?: string;\n db?: string;\n logger?: string;\n validator?: string;\n y?: boolean;\n noInstall?: boolean;\n json?: boolean;\n },\n positionals: string[],\n): ParsedCreateArgs {\n const args: ParsedCreateArgs = {\n yes: values.y ?? false,\n noInstall: values.noInstall ?? false,\n json: values.json ?? false,\n };\n\n if (positionals[0]) {\n args.projectName = positionals[0];\n }\n\n if (values.preset) {\n const parsed = parsePresetFlag(values.preset);\n args.preset = parsed.preset;\n if (parsed.warning && !args.json) {\n console.warn(`warning: ${parsed.warning}`);\n }\n }\n\n if (values.framework) {\n args.framework = parseFrameworkFlag(values.framework);\n }\n\n if (values.runtime) {\n args.runtime = parseRuntimeFlag(values.runtime);\n }\n\n if (values.db) {\n const parsed = parseDbFlag(values.db);\n args.db = parsed.db;\n args.driver = parsed.driver;\n }\n\n if (values.logger) {\n args.logger = parseLoggerFlag(values.logger);\n }\n\n if (values.validator) {\n args.validator = parseValidatorFlag(values.validator);\n }\n\n return args;\n}\n"],"mappings":"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"}
@@ -2,11 +2,14 @@ import { resolveAddons } from "../addons/registry.js";
2
2
  import { resolveDeployEntry } from "./targets.js";
3
3
  import { FRAMEWORK_ENTRIES } from "../frameworks/index.js";
4
4
  //#region src/core/resolve-packages.ts
5
- var BASE_DEPENDENCIES = ["@taserjs/router", "dotenv"];
5
+ var BASE_DEPENDENCIES = [
6
+ "@taserjs/router",
7
+ "dotenv",
8
+ "srvx"
9
+ ];
6
10
  /** Runtime-agnostic build/dev tooling every scaffolded project needs. */
7
11
  var BASE_DEV_DEPENDENCIES = [
8
12
  "@taserjs/router-plugin",
9
- "nitro",
10
13
  "typescript@^5.9.3",
11
14
  "vite@^8.1.5"
12
15
  ];
@@ -23,14 +26,19 @@ function resolvePackages(ctx) {
23
26
  const frameworkEntry = FRAMEWORK_ENTRIES[ctx.framework ?? "none"];
24
27
  const { entry: deployEntry } = resolveDeployEntry(ctx.preset ?? "node-server");
25
28
  const dependencies = [...BASE_DEPENDENCIES, ...frameworkEntry.deps];
29
+ const nitroDevDeps = ctx.preset === "none" ? [] : ["nitro"];
26
30
  const devDependencies = [
27
31
  ...BASE_DEV_DEPENDENCIES,
32
+ ...nitroDevDeps,
28
33
  ...runtimeDevDeps(ctx),
29
34
  ...deployEntry.devDeps,
30
35
  ...frameworkEntry.devDeps
31
36
  ];
32
37
  const scripts = {};
33
- if (deployEntry.startScript) scripts.start = deployEntry.startScript;
38
+ if (deployEntry.startScript) {
39
+ if (ctx.preset === "none" && ctx.runtime === "bun") scripts.start = "bun dist/serve.mjs";
40
+ else scripts.start = deployEntry.startScript;
41
+ }
34
42
  const addons = resolveAddons(ctx);
35
43
  for (const addon of addons) {
36
44
  dependencies.push(...addon.dependencies(ctx));
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-packages.js","names":[],"sources":["../../../src/core/resolve-packages.ts"],"sourcesContent":["import { resolveAddons } from \"../addons/registry.js\";\nimport { FRAMEWORK_ENTRIES } from \"../frameworks/index.js\";\nimport type { PackageGroups, ScaffoldContext } from \"../core/types.js\";\nimport { resolveDeployEntry } from \"./targets.js\";\n\nconst BASE_DEPENDENCIES = [\"@taserjs/router\", \"dotenv\"];\n\n/** Runtime-agnostic build/dev tooling every scaffolded project needs. */\nconst BASE_DEV_DEPENDENCIES = [\n \"@taserjs/router-plugin\",\n \"nitro\",\n \"typescript@^5.9.3\",\n \"vite@^8.1.5\",\n];\n\nfunction runtimeDevDeps(ctx: ScaffoldContext): string[] {\n const { entry } = resolveDeployEntry(ctx.preset ?? \"node-server\");\n const effective = ctx.runtime ?? entry.impliedRuntime;\n switch (effective) {\n case \"bun\":\n return [\"@types/bun\"];\n case \"deno\":\n return []; // Deno ships its own tooling and types.\n case \"workerd\":\n return [\"@cloudflare/workers-types\"];\n case \"node\":\n default:\n return [\"@types/node\"];\n }\n}\n\nexport function resolvePackages(ctx: ScaffoldContext): PackageGroups {\n const frameworkEntry = FRAMEWORK_ENTRIES[ctx.framework ?? \"none\"];\n const { entry: deployEntry } = resolveDeployEntry(ctx.preset ?? \"node-server\");\n\n const dependencies = [...BASE_DEPENDENCIES, ...frameworkEntry.deps];\n const devDependencies = [\n ...BASE_DEV_DEPENDENCIES,\n ...runtimeDevDeps(ctx),\n ...deployEntry.devDeps,\n ...frameworkEntry.devDeps,\n ];\n\n const scripts: Record<string, string> = {};\n if (deployEntry.startScript) {\n scripts.start = deployEntry.startScript;\n }\n\n const addons = resolveAddons(ctx);\n for (const addon of addons) {\n dependencies.push(...addon.dependencies(ctx));\n devDependencies.push(...addon.devDependencies(ctx));\n if (addon.scripts) {\n Object.assign(scripts, addon.scripts(ctx));\n }\n }\n\n return {\n dependencies: [...new Set(dependencies)],\n devDependencies: [...new Set(devDependencies)],\n scripts,\n };\n}\n"],"mappings":";;;;AAKA,IAAM,oBAAoB,CAAC,mBAAmB,QAAQ;;AAGtD,IAAM,wBAAwB;CAC5B;CACA;CACA;CACA;AACF;AAEA,SAAS,eAAe,KAAgC;CACtD,MAAM,EAAE,UAAU,mBAAmB,IAAI,UAAU,aAAa;CAEhE,QADkB,IAAI,WAAW,MAAM,gBACvC;EACE,KAAK,OACH,OAAO,CAAC,YAAY;EACtB,KAAK,QACH,OAAO,CAAC;EACV,KAAK,WACH,OAAO,CAAC,2BAA2B;EAErC,SACE,OAAO,CAAC,aAAa;CACzB;AACF;AAEA,SAAgB,gBAAgB,KAAqC;CACnE,MAAM,iBAAiB,kBAAkB,IAAI,aAAa;CAC1D,MAAM,EAAE,OAAO,gBAAgB,mBAAmB,IAAI,UAAU,aAAa;CAE7E,MAAM,eAAe,CAAC,GAAG,mBAAmB,GAAG,eAAe,IAAI;CAClE,MAAM,kBAAkB;EACtB,GAAG;EACH,GAAG,eAAe,GAAG;EACrB,GAAG,YAAY;EACf,GAAG,eAAe;CACpB;CAEA,MAAM,UAAkC,CAAC;CACzC,IAAI,YAAY,aACd,QAAQ,QAAQ,YAAY;CAG9B,MAAM,SAAS,cAAc,GAAG;CAChC,KAAK,MAAM,SAAS,QAAQ;EAC1B,aAAa,KAAK,GAAG,MAAM,aAAa,GAAG,CAAC;EAC5C,gBAAgB,KAAK,GAAG,MAAM,gBAAgB,GAAG,CAAC;EAClD,IAAI,MAAM,SACR,OAAO,OAAO,SAAS,MAAM,QAAQ,GAAG,CAAC;CAE7C;CAEA,OAAO;EACL,cAAc,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC;EACvC,iBAAiB,CAAC,GAAG,IAAI,IAAI,eAAe,CAAC;EAC7C;CACF;AACF"}
1
+ {"version":3,"file":"resolve-packages.js","names":[],"sources":["../../../src/core/resolve-packages.ts"],"sourcesContent":["import { resolveAddons } from \"../addons/registry.js\";\nimport { FRAMEWORK_ENTRIES } from \"../frameworks/index.js\";\nimport type { PackageGroups, ScaffoldContext } from \"../core/types.js\";\nimport { resolveDeployEntry } from \"./targets.js\";\n\nconst BASE_DEPENDENCIES = [\"@taserjs/router\", \"dotenv\", \"srvx\"];\n\n/** Runtime-agnostic build/dev tooling every scaffolded project needs. */\nconst BASE_DEV_DEPENDENCIES = [\"@taserjs/router-plugin\", \"typescript@^5.9.3\", \"vite@^8.1.5\"];\n\nfunction runtimeDevDeps(ctx: ScaffoldContext): string[] {\n const { entry } = resolveDeployEntry(ctx.preset ?? \"node-server\");\n const effective = ctx.runtime ?? entry.impliedRuntime;\n switch (effective) {\n case \"bun\":\n return [\"@types/bun\"];\n case \"deno\":\n return []; // Deno ships its own tooling and types.\n case \"workerd\":\n return [\"@cloudflare/workers-types\"];\n case \"node\":\n default:\n return [\"@types/node\"];\n }\n}\n\nexport function resolvePackages(ctx: ScaffoldContext): PackageGroups {\n const frameworkEntry = FRAMEWORK_ENTRIES[ctx.framework ?? \"none\"];\n const { entry: deployEntry } = resolveDeployEntry(ctx.preset ?? \"node-server\");\n\n const dependencies = [...BASE_DEPENDENCIES, ...frameworkEntry.deps];\n const nitroDevDeps = ctx.preset === \"none\" ? [] : [\"nitro\"];\n const devDependencies = [\n ...BASE_DEV_DEPENDENCIES,\n ...nitroDevDeps,\n ...runtimeDevDeps(ctx),\n ...deployEntry.devDeps,\n ...frameworkEntry.devDeps,\n ];\n\n const scripts: Record<string, string> = {};\n if (deployEntry.startScript) {\n if (ctx.preset === \"none\" && ctx.runtime === \"bun\") {\n scripts.start = \"bun dist/serve.mjs\";\n } else {\n scripts.start = deployEntry.startScript;\n }\n }\n\n const addons = resolveAddons(ctx);\n for (const addon of addons) {\n dependencies.push(...addon.dependencies(ctx));\n devDependencies.push(...addon.devDependencies(ctx));\n if (addon.scripts) {\n Object.assign(scripts, addon.scripts(ctx));\n }\n }\n\n return {\n dependencies: [...new Set(dependencies)],\n devDependencies: [...new Set(devDependencies)],\n scripts,\n };\n}\n"],"mappings":";;;;AAKA,IAAM,oBAAoB;CAAC;CAAmB;CAAU;AAAM;;AAG9D,IAAM,wBAAwB;CAAC;CAA0B;CAAqB;AAAa;AAE3F,SAAS,eAAe,KAAgC;CACtD,MAAM,EAAE,UAAU,mBAAmB,IAAI,UAAU,aAAa;CAEhE,QADkB,IAAI,WAAW,MAAM,gBACvC;EACE,KAAK,OACH,OAAO,CAAC,YAAY;EACtB,KAAK,QACH,OAAO,CAAC;EACV,KAAK,WACH,OAAO,CAAC,2BAA2B;EAErC,SACE,OAAO,CAAC,aAAa;CACzB;AACF;AAEA,SAAgB,gBAAgB,KAAqC;CACnE,MAAM,iBAAiB,kBAAkB,IAAI,aAAa;CAC1D,MAAM,EAAE,OAAO,gBAAgB,mBAAmB,IAAI,UAAU,aAAa;CAE7E,MAAM,eAAe,CAAC,GAAG,mBAAmB,GAAG,eAAe,IAAI;CAClE,MAAM,eAAe,IAAI,WAAW,SAAS,CAAC,IAAI,CAAC,OAAO;CAC1D,MAAM,kBAAkB;EACtB,GAAG;EACH,GAAG;EACH,GAAG,eAAe,GAAG;EACrB,GAAG,YAAY;EACf,GAAG,eAAe;CACpB;CAEA,MAAM,UAAkC,CAAC;CACzC,IAAI,YAAY,aAAa;EAC3B,IAAI,IAAI,WAAW,UAAU,IAAI,YAAY,OAC3C,QAAQ,QAAQ;OAEhB,QAAQ,QAAQ,YAAY;CAEhC;CAEA,MAAM,SAAS,cAAc,GAAG;CAChC,KAAK,MAAM,SAAS,QAAQ;EAC1B,aAAa,KAAK,GAAG,MAAM,aAAa,GAAG,CAAC;EAC5C,gBAAgB,KAAK,GAAG,MAAM,gBAAgB,GAAG,CAAC;EAClD,IAAI,MAAM,SACR,OAAO,OAAO,SAAS,MAAM,QAAQ,GAAG,CAAC;CAE7C;CAEA,OAAO;EACL,cAAc,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC;EACvC,iBAAiB,CAAC,GAAG,IAAI,IAAI,eAAe,CAAC;EAC7C;CACF;AACF"}
@@ -38,14 +38,14 @@ async function scaffoldProject(options) {
38
38
  const { entry: deployEntry } = resolveDeployEntry(ctx.preset ?? "node-server");
39
39
  await write(path.join(root, "package.json"), packageJsonTemplate(options.projectName, packages.scripts));
40
40
  await write(path.join(root, "tsconfig.json"), tsconfigTemplate());
41
- await write(path.join(root, "vite.config.ts"), viteConfigTemplate());
41
+ await write(path.join(root, "vite.config.ts"), viteConfigTemplate(ctx.preset));
42
42
  await write(path.join(root, ".gitignore"), gitignoreTemplate());
43
43
  await write(path.join(root, "src/context.ts"), contextTemplate(bootBindings));
44
44
  await write(path.join(root, "src/taser.ts"), taserTsTemplate());
45
45
  await write(path.join(root, "src/routes/$.ts"), rootLayoutTemplate());
46
46
  await write(path.join(root, "src/routes/index.get.ts"), indexRouteTemplate());
47
47
  await write(path.join(root, "src/routes/health.get.ts"), healthRouteTemplate(ctx));
48
- if (ctx.preset !== "node-server") await write(path.join(root, "nitro.config.ts"), nitroConfigTemplate(deployEntry.id));
48
+ if (ctx.preset !== "node-server" && ctx.preset !== "none") await write(path.join(root, "nitro.config.ts"), nitroConfigTemplate(deployEntry.id));
49
49
  await Promise.all(deployEntry.files.map((file) => write(path.join(root, file.name), typeof file.content === "function" ? file.content({ projectName: options.projectName }) : file.content)));
50
50
  const serverEntry = frameworkEntry.serverEntry;
51
51
  if (serverEntry) await write(path.join(root, serverEntry.fileName), serverEntry.content);
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold-engine.js","names":[],"sources":["../../../src/core/scaffold-engine.ts"],"sourcesContent":["import { copyFile, mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { collectBootBindings, resolveAddons } from \"../addons/registry.js\";\nimport { nitroConfigTemplate, taserTsTemplate, viteConfigTemplate } from \"../frameworks/index.js\";\nimport { installPackages, resolveUserAgent } from \"./package-manager.js\";\nimport { writeProjectConfig } from \"./project-config.js\";\nimport { resolvePackages } from \"./resolve-packages.js\";\nimport { resolveDeployEntry, validateCombination } from \"./targets.js\";\nimport { FRAMEWORK_ENTRIES } from \"../frameworks/index.js\";\nimport type { ScaffoldContext, ScaffoldOptions, ScaffoldResult } from \"./types.js\";\nimport {\n contextTemplate,\n gitignoreTemplate,\n healthRouteTemplate,\n indexRouteTemplate,\n packageJsonTemplate,\n rootLayoutTemplate,\n tsconfigTemplate,\n} from \"../templates/base.js\";\n\nasync function write(filePath: string, contents: string): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, contents, \"utf8\");\n}\n\nexport async function scaffoldProject(options: ScaffoldOptions): Promise<ScaffoldResult> {\n const root = options.targetDir;\n const preset = options.preset ?? \"node-server\";\n const framework = options.framework ?? \"none\";\n\n // Guards direct/library callers; the CLI path is validated earlier in\n // resolveScaffoldDefaults. Throws with a precise reason on impossible\n // runtime × framework × deploy combinations.\n const combination = validateCombination(options.runtime, framework, preset);\n if (!combination.ok) {\n throw new Error(combination.reason);\n }\n\n const ctx: ScaffoldContext = {\n projectName: options.projectName,\n targetDir: root,\n framework,\n preset,\n ...(options.runtime !== undefined ? { runtime: options.runtime } : {}),\n ...(options.db ? { db: options.db, driver: options.driver } : {}),\n ...(options.logger ? { logger: options.logger } : {}),\n ...(options.validator ? { validator: options.validator } : {}),\n };\n\n const addons = resolveAddons(ctx);\n const packages = resolvePackages(ctx);\n const bootBindings = collectBootBindings(ctx);\n const frameworkEntry = FRAMEWORK_ENTRIES[framework];\n const { entry: deployEntry } = resolveDeployEntry(ctx.preset ?? \"node-server\");\n\n await write(\n path.join(root, \"package.json\"),\n packageJsonTemplate(options.projectName, packages.scripts),\n );\n await write(path.join(root, \"tsconfig.json\"), tsconfigTemplate());\n await write(path.join(root, \"vite.config.ts\"), viteConfigTemplate());\n await write(path.join(root, \".gitignore\"), gitignoreTemplate());\n await write(path.join(root, \"src/context.ts\"), contextTemplate(bootBindings));\n await write(path.join(root, \"src/taser.ts\"), taserTsTemplate());\n await write(path.join(root, \"src/routes/$.ts\"), rootLayoutTemplate());\n await write(path.join(root, \"src/routes/index.get.ts\"), indexRouteTemplate());\n await write(path.join(root, \"src/routes/health.get.ts\"), healthRouteTemplate(ctx));\n\n // Nitro's default preset is node-server — only emit an explicit config when\n // the deployment target differs.\n if (ctx.preset !== \"node-server\") {\n await write(path.join(root, \"nitro.config.ts\"), nitroConfigTemplate(deployEntry.id));\n }\n\n await Promise.all(\n deployEntry.files.map((file) =>\n write(\n path.join(root, file.name),\n typeof file.content === \"function\"\n ? file.content({ projectName: options.projectName })\n : file.content,\n ),\n ),\n );\n\n const serverEntry = frameworkEntry.serverEntry;\n if (serverEntry) {\n await write(path.join(root, serverEntry.fileName), serverEntry.content);\n }\n\n await Promise.all(\n addons.map(async (addon) => {\n await addon.apply(ctx, (filePath, contents) => write(path.join(root, filePath), contents));\n }),\n );\n\n try {\n await copyFile(path.join(root, \".env.example\"), path.join(root, \".env\"));\n } catch {\n // .env.example was not created\n }\n\n await writeProjectConfig(root, ctx);\n\n if (options.skipInstall) {\n return ctx as ScaffoldResult;\n }\n\n const agent = options.agent ?? resolveUserAgent();\n await installPackages(agent, root, {\n dependencies: packages.dependencies,\n devDependencies: packages.devDependencies,\n });\n\n return ctx as ScaffoldResult;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"scaffold-engine.js","names":[],"sources":["../../../src/core/scaffold-engine.ts"],"sourcesContent":["import { copyFile, mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { collectBootBindings, resolveAddons } from \"../addons/registry.js\";\nimport { nitroConfigTemplate, taserTsTemplate, viteConfigTemplate } from \"../frameworks/index.js\";\nimport { installPackages, resolveUserAgent } from \"./package-manager.js\";\nimport { writeProjectConfig } from \"./project-config.js\";\nimport { resolvePackages } from \"./resolve-packages.js\";\nimport { resolveDeployEntry, validateCombination } from \"./targets.js\";\nimport { FRAMEWORK_ENTRIES } from \"../frameworks/index.js\";\nimport type { ScaffoldContext, ScaffoldOptions, ScaffoldResult } from \"./types.js\";\nimport {\n contextTemplate,\n gitignoreTemplate,\n healthRouteTemplate,\n indexRouteTemplate,\n packageJsonTemplate,\n rootLayoutTemplate,\n tsconfigTemplate,\n} from \"../templates/base.js\";\n\nasync function write(filePath: string, contents: string): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, contents, \"utf8\");\n}\n\nexport async function scaffoldProject(options: ScaffoldOptions): Promise<ScaffoldResult> {\n const root = options.targetDir;\n const preset = options.preset ?? \"node-server\";\n const framework = options.framework ?? \"none\";\n\n // Guards direct/library callers; the CLI path is validated earlier in\n // resolveScaffoldDefaults. Throws with a precise reason on impossible\n // runtime × framework × deploy combinations.\n const combination = validateCombination(options.runtime, framework, preset);\n if (!combination.ok) {\n throw new Error(combination.reason);\n }\n\n const ctx: ScaffoldContext = {\n projectName: options.projectName,\n targetDir: root,\n framework,\n preset,\n ...(options.runtime !== undefined ? { runtime: options.runtime } : {}),\n ...(options.db ? { db: options.db, driver: options.driver } : {}),\n ...(options.logger ? { logger: options.logger } : {}),\n ...(options.validator ? { validator: options.validator } : {}),\n };\n\n const addons = resolveAddons(ctx);\n const packages = resolvePackages(ctx);\n const bootBindings = collectBootBindings(ctx);\n const frameworkEntry = FRAMEWORK_ENTRIES[framework];\n const { entry: deployEntry } = resolveDeployEntry(ctx.preset ?? \"node-server\");\n\n await write(\n path.join(root, \"package.json\"),\n packageJsonTemplate(options.projectName, packages.scripts),\n );\n await write(path.join(root, \"tsconfig.json\"), tsconfigTemplate());\n await write(path.join(root, \"vite.config.ts\"), viteConfigTemplate(ctx.preset));\n await write(path.join(root, \".gitignore\"), gitignoreTemplate());\n await write(path.join(root, \"src/context.ts\"), contextTemplate(bootBindings));\n await write(path.join(root, \"src/taser.ts\"), taserTsTemplate());\n await write(path.join(root, \"src/routes/$.ts\"), rootLayoutTemplate());\n await write(path.join(root, \"src/routes/index.get.ts\"), indexRouteTemplate());\n await write(path.join(root, \"src/routes/health.get.ts\"), healthRouteTemplate(ctx));\n\n // Nitro's default preset is node-server — only emit an explicit config when\n // the deployment target differs. Do not emit for preset \"none\".\n if (ctx.preset !== \"node-server\" && ctx.preset !== \"none\") {\n await write(path.join(root, \"nitro.config.ts\"), nitroConfigTemplate(deployEntry.id));\n }\n\n await Promise.all(\n deployEntry.files.map((file) =>\n write(\n path.join(root, file.name),\n typeof file.content === \"function\"\n ? file.content({ projectName: options.projectName })\n : file.content,\n ),\n ),\n );\n\n const serverEntry = frameworkEntry.serverEntry;\n if (serverEntry) {\n await write(path.join(root, serverEntry.fileName), serverEntry.content);\n }\n\n await Promise.all(\n addons.map(async (addon) => {\n await addon.apply(ctx, (filePath, contents) => write(path.join(root, filePath), contents));\n }),\n );\n\n try {\n await copyFile(path.join(root, \".env.example\"), path.join(root, \".env\"));\n } catch {\n // .env.example was not created\n }\n\n await writeProjectConfig(root, ctx);\n\n if (options.skipInstall) {\n return ctx as ScaffoldResult;\n }\n\n const agent = options.agent ?? resolveUserAgent();\n await installPackages(agent, root, {\n dependencies: packages.dependencies,\n devDependencies: packages.devDependencies,\n });\n\n return ctx as ScaffoldResult;\n}\n"],"mappings":"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"}
@@ -10,6 +10,14 @@ import { DEPLOY_TARGETS } from "./types.js";
10
10
  */
11
11
  var NODE_START = "node .output/server/index.mjs";
12
12
  var DEPLOY_ENTRIES = {
13
+ none: {
14
+ id: "none",
15
+ impliedRuntime: "node",
16
+ selfHosted: true,
17
+ startScript: "node dist/serve.mjs",
18
+ devDeps: [],
19
+ files: []
20
+ },
13
21
  "node-server": {
14
22
  id: "node-server",
15
23
  impliedRuntime: "node",
@@ -93,6 +101,7 @@ var DEPLOY_ENTRIES = {
93
101
  };
94
102
  /** Runtimes a `--runtime` override may select per self-hosted deploy target. */
95
103
  var RUNTIME_OVERRIDES = {
104
+ none: ["node", "bun"],
96
105
  "node-server": ["node", "bun"],
97
106
  "node-cluster": ["node", "bun"]
98
107
  };
@@ -1 +1 @@
1
- {"version":3,"file":"targets.js","names":[],"sources":["../../../src/core/targets.ts"],"sourcesContent":["/**\n * Registry for the three scaffold dimensions — runtime, framework, deploy —\n * plus the compatibility rules between them.\n *\n * Dependency direction: deploy implies the runtime family; the effective\n * runtime constrains which frameworks can run. `--runtime` is an override\n * available only where it is meaningful (self-hosted node-family targets).\n */\nimport { DEPLOY_TARGETS, type DeployTarget, type Framework, type Runtime } from \"./types.js\";\n\nexport type PlatformFile = {\n name: string;\n content: string | ((ctx: { projectName: string }) => string);\n};\n\nexport type DeployEntry = {\n id: DeployTarget;\n /** Runtime this target builds for (\"workerd\" = Cloudflare's V8 runtime). */\n impliedRuntime: Runtime | \"workerd\";\n /** Whether the built output is a long-running server you start locally. */\n selfHosted: boolean;\n /** `start` script value; null for platform-deployed targets. */\n startScript: string | null;\n /** Runtime/platform tooling devDependencies beyond the base set. */\n devDeps: string[];\n files: PlatformFile[];\n};\n\nconst NODE_START = \"node .output/server/index.mjs\";\n\nexport const DEPLOY_ENTRIES: Record<DeployTarget, DeployEntry> = {\n \"node-server\": {\n id: \"node-server\",\n impliedRuntime: \"node\",\n selfHosted: true,\n startScript: NODE_START,\n devDeps: [],\n files: [],\n },\n \"node-cluster\": {\n id: \"node-cluster\",\n impliedRuntime: \"node\",\n selfHosted: true,\n startScript: NODE_START,\n devDeps: [],\n files: [],\n },\n bun: {\n id: \"bun\",\n impliedRuntime: \"bun\",\n selfHosted: true,\n startScript: \"bun .output/server/index.mjs\",\n devDeps: [\"@types/bun\"],\n files: [],\n },\n \"deno-server\": {\n id: \"deno-server\",\n impliedRuntime: \"deno\",\n selfHosted: true,\n startScript: \"deno run -A .output/server/index.mjs\",\n devDeps: [],\n files: [],\n },\n \"deno-deploy\": {\n id: \"deno-deploy\",\n impliedRuntime: \"deno\",\n selfHosted: false,\n startScript: null,\n devDeps: [],\n files: [],\n },\n \"cloudflare-module\": {\n id: \"cloudflare-module\",\n impliedRuntime: \"workerd\",\n selfHosted: false,\n startScript: null,\n devDeps: [\"wrangler\", \"@cloudflare/workers-types\"],\n files: [\n {\n name: \"wrangler.jsonc\",\n content: ({ projectName }) =>\n `${JSON.stringify(\n {\n $schema: \"node_modules/wrangler/config-schema.json\",\n name: projectName,\n main: \".output/server/index.mjs\",\n compatibility_date: \"2024-11-01\",\n },\n null,\n 2,\n )}\\n`,\n },\n ],\n },\n vercel: {\n id: \"vercel\",\n impliedRuntime: \"node\",\n selfHosted: false,\n startScript: null,\n devDeps: [\"@vercel/node\"],\n files: [],\n },\n \"aws-lambda\": {\n id: \"aws-lambda\",\n impliedRuntime: \"node\",\n selfHosted: false,\n startScript: null,\n devDeps: [\"@types/aws-lambda\"],\n files: [],\n },\n netlify: {\n id: \"netlify\",\n impliedRuntime: \"node\",\n selfHosted: false,\n startScript: null,\n devDeps: [],\n files: [],\n },\n};\n\n/** Runtimes a `--runtime` override may select per self-hosted deploy target. */\nconst RUNTIME_OVERRIDES: Partial<Record<DeployTarget, readonly Runtime[]>> = {\n \"node-server\": [\"node\", \"bun\"],\n \"node-cluster\": [\"node\", \"bun\"],\n};\n\nexport const DEFAULT_DEPLOY: DeployTarget = \"node-server\";\nexport const DEFAULT_FRAMEWORK: Framework = \"none\";\n\nexport function isCuratedDeploy(value: string): value is DeployTarget {\n return (DEPLOY_TARGETS as readonly string[]).includes(value);\n}\n\n/**\n * Resolves any preset id to its emission entry. Curated ids come from the\n * registry; unknown strings pass through to Nitro verbatim as non-self-hosted\n * node-family targets.\n */\nexport function resolveDeployEntry(id: string): { entry: DeployEntry; curated: boolean } {\n if (isCuratedDeploy(id)) {\n return { entry: DEPLOY_ENTRIES[id], curated: true };\n }\n return {\n entry: {\n // Cast: passthrough ids are valid Nitro PresetNameInputs by contract.\n id: id as DeployTarget,\n impliedRuntime: \"node\",\n selfHosted: false,\n startScript: null,\n devDeps: [],\n files: [],\n },\n curated: false,\n };\n}\n\n/** Runtime overrides permitted for a deploy target; empty = no override. */\nexport function allowedRuntimeOverrides(id: DeployTarget): readonly Runtime[] {\n return RUNTIME_OVERRIDES[id] ?? [];\n}\n\nexport type CombinationError = { ok: false; reason: string };\nexport type CombinationOk = { ok: true; runtime: Runtime | \"workerd\" };\n\n/**\n * Validates a runtime × framework × deploy combination.\n *\n * @param runtimeOverride explicit `--runtime` selection, if any\n * @param deploy preset id (curated or passthrough)\n */\nexport function validateCombination(\n runtimeOverride: Runtime | undefined,\n framework: Framework,\n deploy: string,\n): CombinationOk | CombinationError {\n const { entry } = resolveDeployEntry(deploy);\n\n if (runtimeOverride !== undefined) {\n const allowed = entry.selfHosted ? allowedRuntimeOverrides(entry.id) : [];\n if (!allowed.includes(runtimeOverride)) {\n return {\n ok: false,\n reason:\n `Runtime \"${runtimeOverride}\" is not valid for deploy target \"${entry.id}\". ` +\n (allowed.length > 0\n ? `Allowed overrides: ${allowed.join(\", \")}.`\n : `It implies runtime \"${String(entry.impliedRuntime)}\".`),\n };\n }\n }\n\n const effective = runtimeOverride ?? entry.impliedRuntime;\n\n if ((framework === \"express\" || framework === \"fastify\") && effective !== \"node\") {\n return {\n ok: false,\n reason: `Framework \"${framework}\" requires the Node runtime, but deploy target \"${entry.id}\" implies \"${String(effective)}\".`,\n };\n }\n\n return { ok: true, runtime: effective };\n}\n"],"mappings":";;;;;;;;;;AA4BA,IAAM,aAAa;AAEnB,IAAa,iBAAoD;CAC/D,eAAe;EACb,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC;EACV,OAAO,CAAC;CACV;CACA,gBAAgB;EACd,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC;EACV,OAAO,CAAC;CACV;CACA,KAAK;EACH,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC,YAAY;EACtB,OAAO,CAAC;CACV;CACA,eAAe;EACb,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC;EACV,OAAO,CAAC;CACV;CACA,eAAe;EACb,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC;EACV,OAAO,CAAC;CACV;CACA,qBAAqB;EACnB,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC,YAAY,2BAA2B;EACjD,OAAO,CACL;GACE,MAAM;GACN,UAAU,EAAE,kBACV,GAAG,KAAK,UACN;IACE,SAAS;IACT,MAAM;IACN,MAAM;IACN,oBAAoB;GACtB,GACA,MACA,CACF,EAAE;EACN,CACF;CACF;CACA,QAAQ;EACN,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC,cAAc;EACxB,OAAO,CAAC;CACV;CACA,cAAc;EACZ,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC,mBAAmB;EAC7B,OAAO,CAAC;CACV;CACA,SAAS;EACP,IAAI;EACJ,gBAAgB;EAChB,YAAY;EACZ,aAAa;EACb,SAAS,CAAC;EACV,OAAO,CAAC;CACV;AACF;;AAGA,IAAM,oBAAuE;CAC3E,eAAe,CAAC,QAAQ,KAAK;CAC7B,gBAAgB,CAAC,QAAQ,KAAK;AAChC;AAEA,IAAa,iBAA+B;AAG5C,SAAgB,gBAAgB,OAAsC;CACpE,OAAQ,eAAqC,SAAS,KAAK;AAC7D;;;;;;AAOA,SAAgB,mBAAmB,IAAsD;CACvF,IAAI,gBAAgB,EAAE,GACpB,OAAO;EAAE,OAAO,eAAe;EAAK,SAAS;CAAK;CAEpD,OAAO;EACL,OAAO;GAED;GACJ,gBAAgB;GAChB,YAAY;GACZ,aAAa;GACb,SAAS,CAAC;GACV,OAAO,CAAC;EACV;EACA,SAAS;CACX;AACF;;AAGA,SAAgB,wBAAwB,IAAsC;CAC5E,OAAO,kBAAkB,OAAO,CAAC;AACnC;;;;;;;AAWA,SAAgB,oBACd,iBACA,WACA,QACkC;CAClC,MAAM,EAAE,UAAU,mBAAmB,MAAM;CAE3C,IAAI,oBAAoB,KAAA,GAAW;EACjC,MAAM,UAAU,MAAM,aAAa,wBAAwB,MAAM,EAAE,IAAI,CAAC;EACxE,IAAI,CAAC,QAAQ,SAAS,eAAe,GACnC,OAAO;GACL,IAAI;GACJ,QACE,YAAY,gBAAgB,oCAAoC,MAAM,GAAG,QACxE,QAAQ,SAAS,IACd,sBAAsB,QAAQ,KAAK,IAAI,EAAE,KACzC,uBAAuB,OAAO,MAAM,cAAc,EAAE;EAC5D;CAEJ;CAEA,MAAM,YAAY,mBAAmB,MAAM;CAE3C,KAAK,cAAc,aAAa,cAAc,cAAc,cAAc,QACxE,OAAO;EACL,IAAI;EACJ,QAAQ,cAAc,UAAU,kDAAkD,MAAM,GAAG,aAAa,OAAO,SAAS,EAAE;CAC5H;CAGF,OAAO;EAAE,IAAI;EAAM,SAAS;CAAU;AACxC"}
1
+ {"version":3,"file":"targets.js","names":[],"sources":["../../../src/core/targets.ts"],"sourcesContent":["/**\n * Registry for the three scaffold dimensions — runtime, framework, deploy —\n * plus the compatibility rules between them.\n *\n * Dependency direction: deploy implies the runtime family; the effective\n * runtime constrains which frameworks can run. `--runtime` is an override\n * available only where it is meaningful (self-hosted node-family targets).\n */\nimport { DEPLOY_TARGETS, type DeployTarget, type Framework, type Runtime } from \"./types.js\";\n\nexport type PlatformFile = {\n name: string;\n content: string | ((ctx: { projectName: string }) => string);\n};\n\nexport type DeployEntry = {\n id: DeployTarget;\n /** Runtime this target builds for (\"workerd\" = Cloudflare's V8 runtime). */\n impliedRuntime: Runtime | \"workerd\";\n /** Whether the built output is a long-running server you start locally. */\n selfHosted: boolean;\n /** `start` script value; null for platform-deployed targets. */\n startScript: string | null;\n /** Runtime/platform tooling devDependencies beyond the base set. */\n devDeps: string[];\n files: PlatformFile[];\n};\n\nconst NODE_START = \"node .output/server/index.mjs\";\n\nexport const DEPLOY_ENTRIES: Record<DeployTarget, DeployEntry> = {\n none: {\n id: \"none\",\n impliedRuntime: \"node\",\n selfHosted: true,\n startScript: \"node dist/serve.mjs\",\n devDeps: [],\n files: [],\n },\n \"node-server\": {\n id: \"node-server\",\n impliedRuntime: \"node\",\n selfHosted: true,\n startScript: NODE_START,\n devDeps: [],\n files: [],\n },\n \"node-cluster\": {\n id: \"node-cluster\",\n impliedRuntime: \"node\",\n selfHosted: true,\n startScript: NODE_START,\n devDeps: [],\n files: [],\n },\n bun: {\n id: \"bun\",\n impliedRuntime: \"bun\",\n selfHosted: true,\n startScript: \"bun .output/server/index.mjs\",\n devDeps: [\"@types/bun\"],\n files: [],\n },\n \"deno-server\": {\n id: \"deno-server\",\n impliedRuntime: \"deno\",\n selfHosted: true,\n startScript: \"deno run -A .output/server/index.mjs\",\n devDeps: [],\n files: [],\n },\n \"deno-deploy\": {\n id: \"deno-deploy\",\n impliedRuntime: \"deno\",\n selfHosted: false,\n startScript: null,\n devDeps: [],\n files: [],\n },\n \"cloudflare-module\": {\n id: \"cloudflare-module\",\n impliedRuntime: \"workerd\",\n selfHosted: false,\n startScript: null,\n devDeps: [\"wrangler\", \"@cloudflare/workers-types\"],\n files: [\n {\n name: \"wrangler.jsonc\",\n content: ({ projectName }) =>\n `${JSON.stringify(\n {\n $schema: \"node_modules/wrangler/config-schema.json\",\n name: projectName,\n main: \".output/server/index.mjs\",\n compatibility_date: \"2024-11-01\",\n },\n null,\n 2,\n )}\\n`,\n },\n ],\n },\n vercel: {\n id: \"vercel\",\n impliedRuntime: \"node\",\n selfHosted: false,\n startScript: null,\n devDeps: [\"@vercel/node\"],\n files: [],\n },\n \"aws-lambda\": {\n id: \"aws-lambda\",\n impliedRuntime: \"node\",\n selfHosted: false,\n startScript: null,\n devDeps: [\"@types/aws-lambda\"],\n files: [],\n },\n netlify: {\n id: \"netlify\",\n impliedRuntime: \"node\",\n selfHosted: false,\n startScript: null,\n devDeps: [],\n files: [],\n },\n};\n\n/** Runtimes a `--runtime` override may select per self-hosted deploy target. */\nconst RUNTIME_OVERRIDES: Partial<Record<DeployTarget, readonly Runtime[]>> = {\n none: [\"node\", \"bun\"],\n \"node-server\": [\"node\", \"bun\"],\n \"node-cluster\": [\"node\", \"bun\"],\n};\n\nexport const DEFAULT_DEPLOY: DeployTarget = \"node-server\";\nexport const DEFAULT_FRAMEWORK: Framework = \"none\";\n\nexport function isCuratedDeploy(value: string): value is DeployTarget {\n return (DEPLOY_TARGETS as readonly string[]).includes(value);\n}\n\n/**\n * Resolves any preset id to its emission entry. Curated ids come from the\n * registry; unknown strings pass through to Nitro verbatim as non-self-hosted\n * node-family targets.\n */\nexport function resolveDeployEntry(id: string): { entry: DeployEntry; curated: boolean } {\n if (isCuratedDeploy(id)) {\n return { entry: DEPLOY_ENTRIES[id], curated: true };\n }\n return {\n entry: {\n // Cast: passthrough ids are valid Nitro PresetNameInputs by contract.\n id: id as DeployTarget,\n impliedRuntime: \"node\",\n selfHosted: false,\n startScript: null,\n devDeps: [],\n files: [],\n },\n curated: false,\n };\n}\n\n/** Runtime overrides permitted for a deploy target; empty = no override. */\nexport function allowedRuntimeOverrides(id: DeployTarget): readonly Runtime[] {\n return RUNTIME_OVERRIDES[id] ?? [];\n}\n\nexport type CombinationError = { ok: false; reason: string };\nexport type CombinationOk = { ok: true; runtime: Runtime | \"workerd\" };\n\n/**\n * Validates a runtime × framework × deploy combination.\n *\n * @param runtimeOverride explicit `--runtime` selection, if any\n * @param deploy preset id (curated or passthrough)\n */\nexport function validateCombination(\n runtimeOverride: Runtime | undefined,\n framework: Framework,\n deploy: string,\n): CombinationOk | CombinationError {\n const { entry } = resolveDeployEntry(deploy);\n\n if (runtimeOverride !== undefined) {\n const allowed = entry.selfHosted ? allowedRuntimeOverrides(entry.id) : [];\n if (!allowed.includes(runtimeOverride)) {\n return {\n ok: false,\n reason:\n `Runtime \"${runtimeOverride}\" is not valid for deploy target \"${entry.id}\". ` +\n (allowed.length > 0\n ? `Allowed overrides: ${allowed.join(\", \")}.`\n : `It implies runtime \"${String(entry.impliedRuntime)}\".`),\n };\n }\n }\n\n const effective = runtimeOverride ?? entry.impliedRuntime;\n\n if ((framework === \"express\" || framework === \"fastify\") && effective !== \"node\") {\n return {\n ok: false,\n reason: `Framework \"${framework}\" requires the Node runtime, but deploy target \"${entry.id}\" implies \"${String(effective)}\".`,\n };\n }\n\n return { ok: true, runtime: effective };\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ export declare const RUNTIMES: readonly Runtime[];
8
8
  * Deployment target. Values are Nitro preset ids (see `nitro/config`
9
9
  * PresetNameInput) so `--preset` passes straight through to Nitro.
10
10
  */
11
- export type DeployTarget = "node-server" | "node-cluster" | "bun" | "deno-server" | "deno-deploy" | "cloudflare-module" | "vercel" | "aws-lambda" | "netlify";
11
+ export type DeployTarget = "none" | "node-server" | "node-cluster" | "bun" | "deno-server" | "deno-deploy" | "cloudflare-module" | "vercel" | "aws-lambda" | "netlify";
12
12
  export declare const DEPLOY_TARGETS: readonly DeployTarget[];
13
13
  export type DbOdm = "drizzle" | "prisma" | "kysely";
14
14
  export declare const DB_ODMS: readonly DbOdm[];
@@ -11,6 +11,7 @@ var RUNTIMES = [
11
11
  "deno"
12
12
  ];
13
13
  var DEPLOY_TARGETS = [
14
+ "none",
14
15
  "node-server",
15
16
  "node-cluster",
16
17
  "bun",
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../../src/core/types.ts"],"sourcesContent":["import type { Agent } from \"package-manager-detector\";\n\n/** Host framework layered on top of pure Taser pass-through dispatch. */\nexport type Framework = \"none\" | \"hono\" | \"express\" | \"fastify\";\n\nexport const FRAMEWORKS: readonly Framework[] = [\"none\", \"hono\", \"express\", \"fastify\"];\n\nexport type Runtime = \"node\" | \"bun\" | \"deno\";\n\nexport const RUNTIMES: readonly Runtime[] = [\"node\", \"bun\", \"deno\"];\n\n/**\n * Deployment target. Values are Nitro preset ids (see `nitro/config`\n * PresetNameInput) so `--preset` passes straight through to Nitro.\n */\nexport type DeployTarget =\n | \"node-server\"\n | \"node-cluster\"\n | \"bun\"\n | \"deno-server\"\n | \"deno-deploy\"\n | \"cloudflare-module\"\n | \"vercel\"\n | \"aws-lambda\"\n | \"netlify\";\n\nexport const DEPLOY_TARGETS: readonly DeployTarget[] = [\n \"node-server\",\n \"node-cluster\",\n \"bun\",\n \"deno-server\",\n \"deno-deploy\",\n \"cloudflare-module\",\n \"vercel\",\n \"aws-lambda\",\n \"netlify\",\n];\n\nexport type DbOdm = \"drizzle\" | \"prisma\" | \"kysely\";\n\nexport const DB_ODMS: readonly DbOdm[] = [\"drizzle\", \"prisma\", \"kysely\"];\n\nexport type DbDriver = \"postgres\" | \"sqlite\" | \"mysql\";\n\nexport const DB_DRIVERS: readonly DbDriver[] = [\"postgres\", \"sqlite\", \"mysql\"];\n\nexport const DEFAULT_DB_DRIVER: DbDriver = \"sqlite\";\n\nexport type LoggerId = \"pino\" | \"winston\";\n\nexport const LOGGERS: readonly LoggerId[] = [\"pino\", \"winston\"];\n\nexport type ValidatorId = \"zod\" | \"arktype\" | \"valibot\";\n\nexport const VALIDATORS: readonly ValidatorId[] = [\"zod\", \"arktype\", \"valibot\"];\n\nexport type PackageGroups = {\n dependencies: string[];\n devDependencies: string[];\n scripts: Record<string, string>;\n};\n\nexport type ScaffoldContext = {\n projectName: string;\n targetDir: string;\n /** Host framework; \"none\" is pure Taser pass-through dispatch. Defaults to \"none\". */\n framework?: Framework;\n /** Deployment target — a Nitro preset id. Defaults to \"node-server\". */\n preset?: DeployTarget;\n /** Set only when explicitly overriding the runtime implied by the preset. */\n runtime?: Runtime;\n db?: DbOdm;\n driver?: DbDriver;\n logger?: LoggerId;\n validator?: ValidatorId;\n};\n\nexport type ScaffoldOptions = ScaffoldContext & {\n skipInstall?: boolean;\n agent?: Agent;\n};\n\nexport type ScaffoldResult = ScaffoldContext;\n\nexport type CapabilitiesCatalog = {\n frameworks: Framework[];\n deployTargets: DeployTarget[];\n runtimes: Runtime[];\n db: {\n odms: DbOdm[];\n drivers: DbDriver[];\n defaultDriver: DbDriver;\n };\n loggers: LoggerId[];\n validators: ValidatorId[];\n};\n"],"mappings":";AAKA,IAAa,aAAmC;CAAC;CAAQ;CAAQ;CAAW;AAAS;AAIrF,IAAa,WAA+B;CAAC;CAAQ;CAAO;AAAM;AAiBlE,IAAa,iBAA0C;CACrD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAIA,IAAa,UAA4B;CAAC;CAAW;CAAU;AAAQ;AAIvE,IAAa,aAAkC;CAAC;CAAY;CAAU;AAAO;AAE7E,IAAa,oBAA8B;AAI3C,IAAa,UAA+B,CAAC,QAAQ,SAAS;AAI9D,IAAa,aAAqC;CAAC;CAAO;CAAW;AAAS"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../../src/core/types.ts"],"sourcesContent":["import type { Agent } from \"package-manager-detector\";\n\n/** Host framework layered on top of pure Taser pass-through dispatch. */\nexport type Framework = \"none\" | \"hono\" | \"express\" | \"fastify\";\n\nexport const FRAMEWORKS: readonly Framework[] = [\"none\", \"hono\", \"express\", \"fastify\"];\n\nexport type Runtime = \"node\" | \"bun\" | \"deno\";\n\nexport const RUNTIMES: readonly Runtime[] = [\"node\", \"bun\", \"deno\"];\n\n/**\n * Deployment target. Values are Nitro preset ids (see `nitro/config`\n * PresetNameInput) so `--preset` passes straight through to Nitro.\n */\nexport type DeployTarget =\n | \"none\"\n | \"node-server\"\n | \"node-cluster\"\n | \"bun\"\n | \"deno-server\"\n | \"deno-deploy\"\n | \"cloudflare-module\"\n | \"vercel\"\n | \"aws-lambda\"\n | \"netlify\";\n\nexport const DEPLOY_TARGETS: readonly DeployTarget[] = [\n \"none\",\n \"node-server\",\n \"node-cluster\",\n \"bun\",\n \"deno-server\",\n \"deno-deploy\",\n \"cloudflare-module\",\n \"vercel\",\n \"aws-lambda\",\n \"netlify\",\n];\n\nexport type DbOdm = \"drizzle\" | \"prisma\" | \"kysely\";\n\nexport const DB_ODMS: readonly DbOdm[] = [\"drizzle\", \"prisma\", \"kysely\"];\n\nexport type DbDriver = \"postgres\" | \"sqlite\" | \"mysql\";\n\nexport const DB_DRIVERS: readonly DbDriver[] = [\"postgres\", \"sqlite\", \"mysql\"];\n\nexport const DEFAULT_DB_DRIVER: DbDriver = \"sqlite\";\n\nexport type LoggerId = \"pino\" | \"winston\";\n\nexport const LOGGERS: readonly LoggerId[] = [\"pino\", \"winston\"];\n\nexport type ValidatorId = \"zod\" | \"arktype\" | \"valibot\";\n\nexport const VALIDATORS: readonly ValidatorId[] = [\"zod\", \"arktype\", \"valibot\"];\n\nexport type PackageGroups = {\n dependencies: string[];\n devDependencies: string[];\n scripts: Record<string, string>;\n};\n\nexport type ScaffoldContext = {\n projectName: string;\n targetDir: string;\n /** Host framework; \"none\" is pure Taser pass-through dispatch. Defaults to \"none\". */\n framework?: Framework;\n /** Deployment target — a Nitro preset id. Defaults to \"node-server\". */\n preset?: DeployTarget;\n /** Set only when explicitly overriding the runtime implied by the preset. */\n runtime?: Runtime;\n db?: DbOdm;\n driver?: DbDriver;\n logger?: LoggerId;\n validator?: ValidatorId;\n};\n\nexport type ScaffoldOptions = ScaffoldContext & {\n skipInstall?: boolean;\n agent?: Agent;\n};\n\nexport type ScaffoldResult = ScaffoldContext;\n\nexport type CapabilitiesCatalog = {\n frameworks: Framework[];\n deployTargets: DeployTarget[];\n runtimes: Runtime[];\n db: {\n odms: DbOdm[];\n drivers: DbDriver[];\n defaultDriver: DbDriver;\n };\n loggers: LoggerId[];\n validators: ValidatorId[];\n};\n"],"mappings":";AAKA,IAAa,aAAmC;CAAC;CAAQ;CAAQ;CAAW;AAAS;AAIrF,IAAa,WAA+B;CAAC;CAAQ;CAAO;AAAM;AAkBlE,IAAa,iBAA0C;CACrD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAIA,IAAa,UAA4B;CAAC;CAAW;CAAU;AAAQ;AAIvE,IAAa,aAAkC;CAAC;CAAY;CAAU;AAAO;AAE7E,IAAa,oBAA8B;AAI3C,IAAa,UAA+B,CAAC,QAAQ,SAAS;AAI9D,IAAa,aAAqC;CAAC;CAAO;CAAW;AAAS"}
@@ -29,7 +29,6 @@ function validateProjectName(name, cwd = process.cwd()) {
29
29
  const trimmed = name.trim();
30
30
  if (!trimmed) return "Project name is required";
31
31
  if (trimmed.includes("..")) return "Project name cannot contain \"..\"";
32
- if (trimmed.includes("/") || trimmed.includes("\\")) return "Project name cannot contain path separators";
33
32
  if (trimmed.startsWith(".") || trimmed.endsWith(".")) return "Project name cannot start or end with a dot";
34
33
  const baseName = trimmed.split(".")[0]?.toUpperCase();
35
34
  if (baseName && RESERVED_WINDOWS_NAMES.has(baseName)) return `Project name "${trimmed}" is reserved on Windows`;
@@ -1 +1 @@
1
- {"version":3,"file":"validate-project-name.js","names":[],"sources":["../../../src/core/validate-project-name.ts"],"sourcesContent":["import path from \"node:path\";\n\nconst RESERVED_WINDOWS_NAMES = new Set([\n \"CON\",\n \"PRN\",\n \"AUX\",\n \"NVR\",\n \"NULL\",\n \"COM1\",\n \"COM2\",\n \"COM3\",\n \"COM4\",\n \"COM5\",\n \"COM6\",\n \"COM7\",\n \"COM8\",\n \"COM9\",\n \"LPT1\",\n \"LPT2\",\n \"LPT3\",\n \"LPT4\",\n \"LPT5\",\n \"LPT6\",\n \"LPT7\",\n \"LPT8\",\n \"LPT9\",\n]);\n\nexport function validateProjectName(name: string, cwd = process.cwd()): string | undefined {\n const trimmed = name.trim();\n if (!trimmed) {\n return \"Project name is required\";\n }\n\n if (trimmed.includes(\"..\")) {\n return 'Project name cannot contain \"..\"';\n }\n\n if (trimmed.includes(\"/\") || trimmed.includes(\"\\\\\")) {\n return \"Project name cannot contain path separators\";\n }\n\n if (trimmed.startsWith(\".\") || trimmed.endsWith(\".\")) {\n return \"Project name cannot start or end with a dot\";\n }\n\n const baseName = trimmed.split(\".\")[0]?.toUpperCase();\n if (baseName && RESERVED_WINDOWS_NAMES.has(baseName)) {\n return `Project name \"${trimmed}\" is reserved on Windows`;\n }\n\n const targetDir = path.resolve(cwd, trimmed);\n const relative = path.relative(cwd, targetDir);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n return \"Project name resolves outside the current directory\";\n }\n\n return undefined;\n}\n"],"mappings":";;AAEA,IAAM,yCAAyB,IAAI,IAAI;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,oBAAoB,MAAc,MAAM,QAAQ,IAAI,GAAuB;CACzF,MAAM,UAAU,KAAK,KAAK;CAC1B,IAAI,CAAC,SACH,OAAO;CAGT,IAAI,QAAQ,SAAS,IAAI,GACvB,OAAO;CAGT,IAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,IAAI,GAChD,OAAO;CAGT,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GACjD,OAAO;CAGT,MAAM,WAAW,QAAQ,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,YAAY;CACpD,IAAI,YAAY,uBAAuB,IAAI,QAAQ,GACjD,OAAO,iBAAiB,QAAQ;CAGlC,MAAM,YAAY,KAAK,QAAQ,KAAK,OAAO;CAC3C,MAAM,WAAW,KAAK,SAAS,KAAK,SAAS;CAC7C,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,WAAW,QAAQ,GACvD,OAAO;AAIX"}
1
+ {"version":3,"file":"validate-project-name.js","names":[],"sources":["../../../src/core/validate-project-name.ts"],"sourcesContent":["import path from \"node:path\";\n\nconst RESERVED_WINDOWS_NAMES = new Set([\n \"CON\",\n \"PRN\",\n \"AUX\",\n \"NVR\",\n \"NULL\",\n \"COM1\",\n \"COM2\",\n \"COM3\",\n \"COM4\",\n \"COM5\",\n \"COM6\",\n \"COM7\",\n \"COM8\",\n \"COM9\",\n \"LPT1\",\n \"LPT2\",\n \"LPT3\",\n \"LPT4\",\n \"LPT5\",\n \"LPT6\",\n \"LPT7\",\n \"LPT8\",\n \"LPT9\",\n]);\n\nexport function validateProjectName(name: string, cwd = process.cwd()): string | undefined {\n const trimmed = name.trim();\n if (!trimmed) {\n return \"Project name is required\";\n }\n\n if (trimmed.includes(\"..\")) {\n return 'Project name cannot contain \"..\"';\n }\n\n if (trimmed.startsWith(\".\") || trimmed.endsWith(\".\")) {\n return \"Project name cannot start or end with a dot\";\n }\n\n const baseName = trimmed.split(\".\")[0]?.toUpperCase();\n if (baseName && RESERVED_WINDOWS_NAMES.has(baseName)) {\n return `Project name \"${trimmed}\" is reserved on Windows`;\n }\n\n const targetDir = path.resolve(cwd, trimmed);\n const relative = path.relative(cwd, targetDir);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n return \"Project name resolves outside the current directory\";\n }\n\n return undefined;\n}\n"],"mappings":";;AAEA,IAAM,yCAAyB,IAAI,IAAI;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,oBAAoB,MAAc,MAAM,QAAQ,IAAI,GAAuB;CACzF,MAAM,UAAU,KAAK,KAAK;CAC1B,IAAI,CAAC,SACH,OAAO;CAGT,IAAI,QAAQ,SAAS,IAAI,GACvB,OAAO;CAGT,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GACjD,OAAO;CAGT,MAAM,WAAW,QAAQ,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,YAAY;CACpD,IAAI,YAAY,uBAAuB,IAAI,QAAQ,GACjD,OAAO,iBAAiB,QAAQ;CAGlC,MAAM,YAAY,KAAK,QAAQ,KAAK,OAAO;CAC3C,MAAM,WAAW,KAAK,SAAS,KAAK,SAAS;CAC7C,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,WAAW,QAAQ,GACvD,OAAO;AAIX"}
@@ -1,4 +1,4 @@
1
- import { Framework } from '../core/types.js';
1
+ import { DeployTarget, Framework } from '../core/types.js';
2
2
  export declare function serverEntryTemplate(framework: Framework): {
3
3
  fileName: string;
4
4
  content: string;
@@ -14,5 +14,5 @@ export type FrameworkEntry = {
14
14
  };
15
15
  export declare const FRAMEWORK_ENTRIES: Record<Framework, FrameworkEntry>;
16
16
  export declare function nitroConfigTemplate(nitroPreset: string): string;
17
- export declare function viteConfigTemplate(): string;
17
+ export declare function viteConfigTemplate(preset?: DeployTarget): string;
18
18
  export declare function taserTsTemplate(): string;
@@ -61,13 +61,13 @@ var FRAMEWORK_ENTRIES = {
61
61
  express: {
62
62
  id: "express",
63
63
  serverEntry: serverEntryTemplate("express"),
64
- deps: ["express", "srvx"],
64
+ deps: ["express"],
65
65
  devDeps: ["@types/express"]
66
66
  },
67
67
  fastify: {
68
68
  id: "fastify",
69
69
  serverEntry: serverEntryTemplate("fastify"),
70
- deps: ["fastify", "srvx"],
70
+ deps: ["fastify"],
71
71
  devDeps: []
72
72
  }
73
73
  };
@@ -79,7 +79,14 @@ export default defineConfig({
79
79
  })
80
80
  `;
81
81
  }
82
- function viteConfigTemplate() {
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
+ `;
83
90
  return `import { defineConfig } from 'vite'
84
91
  import { nitro } from 'nitro/vite'
85
92
  import { taser } from '@taserjs/router-plugin/vite'
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { 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\", \"srvx\"],\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\", \"srvx\"],\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(): string {\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 const t = 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,WAAW,MAAM;EACxB,SAAS,CAAC,gBAAgB;CAC5B;CACA,SAAS;EACP,IAAI;EAEJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,WAAW,MAAM;EACxB,SAAS,CAAC;CACZ;AACF;AAEA,SAAgB,oBAAoB,aAA6B;CAC/D,OAAO;;;aAGI,YAAY;;;AAGzB;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;;AAQT;AAEA,SAAgB,kBAA0B;CACxC,OAAO;;;;;;;;AAQT"}
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 const t = 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-taserjs",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Scaffold a new Taser application",
5
5
  "license": "ISC",
6
6
  "repository": {
@@ -32,7 +32,7 @@
32
32
  "typescript": "^5.9.3",
33
33
  "vite": "^8.1.5",
34
34
  "vitest": "^4.1.10",
35
- "@taserjs/router-generator": "0.1.0"
35
+ "@taserjs/router-generator": "0.1.1"
36
36
  },
37
37
  "engines": {
38
38
  "node": ">=20.19"
@@ -1,6 +1,13 @@
1
1
  import type { AddonDefinition } from "../types.js";
2
2
  import type { DbDriver } from "../../core/types.js";
3
3
 
4
+ /** Latest Prisma ORM v7 release line — keep all @prisma/* packages on this range. */
5
+ const PRISMA_VERSION = "^7.10.0";
6
+
7
+ function prismaPackage(name: string): string {
8
+ return `${name}@${PRISMA_VERSION}`;
9
+ }
10
+
4
11
  function prismaProvider(driver: DbDriver): string {
5
12
  switch (driver) {
6
13
  case "postgres":
@@ -28,12 +35,12 @@ function envExample(driver: DbDriver): string {
28
35
  function driverPackages(driver: DbDriver): string[] {
29
36
  switch (driver) {
30
37
  case "postgres":
31
- return ["@prisma/adapter-pg", "pg"];
38
+ return [prismaPackage("@prisma/adapter-pg"), "pg"];
32
39
  case "mysql":
33
- return ["@prisma/adapter-mariadb", "mariadb"];
40
+ return [prismaPackage("@prisma/adapter-mariadb"), "mariadb"];
34
41
  case "sqlite":
35
42
  default:
36
- return ["@prisma/adapter-better-sqlite3", "better-sqlite3"];
43
+ return [prismaPackage("@prisma/adapter-better-sqlite3"), "better-sqlite3"];
37
44
  }
38
45
  }
39
46
 
@@ -125,11 +132,11 @@ export const prismaAddon: AddonDefinition = {
125
132
  category: "database",
126
133
  dependencies(ctx) {
127
134
  const driver = ctx.driver ?? "sqlite";
128
- return ["@prisma/client", ...driverPackages(driver)];
135
+ return [prismaPackage("@prisma/client"), ...driverPackages(driver)];
129
136
  },
130
137
  devDependencies(ctx) {
131
138
  const driver = ctx.driver ?? "sqlite";
132
- return ["prisma", ...driverDevPackages(driver)];
139
+ return [prismaPackage("prisma"), ...driverDevPackages(driver)];
133
140
  },
134
141
  scripts() {
135
142
  return {
@@ -75,7 +75,7 @@ async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedC
75
75
  (await p.select({
76
76
  message: "Host framework",
77
77
  options: [
78
- { value: "none", label: "Pure Taser", hint: "default" },
78
+ { value: "none", label: "None", hint: "Taser Fetch (default)" },
79
79
  { value: "hono", label: "Hono" },
80
80
  { value: "express", label: "Express" },
81
81
  { value: "fastify", label: "Fastify" },
@@ -89,6 +89,7 @@ async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedC
89
89
  }
90
90
 
91
91
  const DEPLOY_LABELS: Record<DeployTarget, string> = {
92
+ none: "None (Standalone Vite)",
92
93
  "node-server": "Node.js server",
93
94
  "node-cluster": "Node.js cluster",
94
95
  bun: "Bun",
@@ -100,11 +101,20 @@ async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedC
100
101
  netlify: "Netlify",
101
102
  };
102
103
 
104
+ const DEPLOY_HINTS: Partial<Record<DeployTarget, string>> = {
105
+ none: "standalone Vite, no Nitro",
106
+ };
107
+
103
108
  const preset =
104
109
  args.preset ??
105
110
  (await p.select({
106
111
  message: "Deployment target",
107
- options: DEPLOY_TARGETS.map((id) => ({ value: id, label: DEPLOY_LABELS[id] })),
112
+ // oxlint-disable-next-line oxc/no-map-spread
113
+ options: DEPLOY_TARGETS.map((id) => ({
114
+ value: id,
115
+ label: DEPLOY_LABELS[id],
116
+ ...(DEPLOY_HINTS[id] ? { hint: DEPLOY_HINTS[id] } : {}),
117
+ })),
108
118
  initialValue: "node-server",
109
119
  }));
110
120
 
@@ -3,15 +3,10 @@ import { FRAMEWORK_ENTRIES } from "../frameworks/index.js";
3
3
  import type { PackageGroups, ScaffoldContext } from "../core/types.js";
4
4
  import { resolveDeployEntry } from "./targets.js";
5
5
 
6
- const BASE_DEPENDENCIES = ["@taserjs/router", "dotenv"];
6
+ const BASE_DEPENDENCIES = ["@taserjs/router", "dotenv", "srvx"];
7
7
 
8
8
  /** Runtime-agnostic build/dev tooling every scaffolded project needs. */
9
- const BASE_DEV_DEPENDENCIES = [
10
- "@taserjs/router-plugin",
11
- "nitro",
12
- "typescript@^5.9.3",
13
- "vite@^8.1.5",
14
- ];
9
+ const BASE_DEV_DEPENDENCIES = ["@taserjs/router-plugin", "typescript@^5.9.3", "vite@^8.1.5"];
15
10
 
16
11
  function runtimeDevDeps(ctx: ScaffoldContext): string[] {
17
12
  const { entry } = resolveDeployEntry(ctx.preset ?? "node-server");
@@ -34,8 +29,10 @@ export function resolvePackages(ctx: ScaffoldContext): PackageGroups {
34
29
  const { entry: deployEntry } = resolveDeployEntry(ctx.preset ?? "node-server");
35
30
 
36
31
  const dependencies = [...BASE_DEPENDENCIES, ...frameworkEntry.deps];
32
+ const nitroDevDeps = ctx.preset === "none" ? [] : ["nitro"];
37
33
  const devDependencies = [
38
34
  ...BASE_DEV_DEPENDENCIES,
35
+ ...nitroDevDeps,
39
36
  ...runtimeDevDeps(ctx),
40
37
  ...deployEntry.devDeps,
41
38
  ...frameworkEntry.devDeps,
@@ -43,7 +40,11 @@ export function resolvePackages(ctx: ScaffoldContext): PackageGroups {
43
40
 
44
41
  const scripts: Record<string, string> = {};
45
42
  if (deployEntry.startScript) {
46
- scripts.start = deployEntry.startScript;
43
+ if (ctx.preset === "none" && ctx.runtime === "bun") {
44
+ scripts.start = "bun dist/serve.mjs";
45
+ } else {
46
+ scripts.start = deployEntry.startScript;
47
+ }
47
48
  }
48
49
 
49
50
  const addons = resolveAddons(ctx);
@@ -59,7 +59,7 @@ export async function scaffoldProject(options: ScaffoldOptions): Promise<Scaffol
59
59
  packageJsonTemplate(options.projectName, packages.scripts),
60
60
  );
61
61
  await write(path.join(root, "tsconfig.json"), tsconfigTemplate());
62
- await write(path.join(root, "vite.config.ts"), viteConfigTemplate());
62
+ await write(path.join(root, "vite.config.ts"), viteConfigTemplate(ctx.preset));
63
63
  await write(path.join(root, ".gitignore"), gitignoreTemplate());
64
64
  await write(path.join(root, "src/context.ts"), contextTemplate(bootBindings));
65
65
  await write(path.join(root, "src/taser.ts"), taserTsTemplate());
@@ -68,8 +68,8 @@ export async function scaffoldProject(options: ScaffoldOptions): Promise<Scaffol
68
68
  await write(path.join(root, "src/routes/health.get.ts"), healthRouteTemplate(ctx));
69
69
 
70
70
  // Nitro's default preset is node-server — only emit an explicit config when
71
- // the deployment target differs.
72
- if (ctx.preset !== "node-server") {
71
+ // the deployment target differs. Do not emit for preset "none".
72
+ if (ctx.preset !== "node-server" && ctx.preset !== "none") {
73
73
  await write(path.join(root, "nitro.config.ts"), nitroConfigTemplate(deployEntry.id));
74
74
  }
75
75
 
@@ -29,6 +29,14 @@ export type DeployEntry = {
29
29
  const NODE_START = "node .output/server/index.mjs";
30
30
 
31
31
  export const DEPLOY_ENTRIES: Record<DeployTarget, DeployEntry> = {
32
+ none: {
33
+ id: "none",
34
+ impliedRuntime: "node",
35
+ selfHosted: true,
36
+ startScript: "node dist/serve.mjs",
37
+ devDeps: [],
38
+ files: [],
39
+ },
32
40
  "node-server": {
33
41
  id: "node-server",
34
42
  impliedRuntime: "node",
@@ -120,6 +128,7 @@ export const DEPLOY_ENTRIES: Record<DeployTarget, DeployEntry> = {
120
128
 
121
129
  /** Runtimes a `--runtime` override may select per self-hosted deploy target. */
122
130
  const RUNTIME_OVERRIDES: Partial<Record<DeployTarget, readonly Runtime[]>> = {
131
+ none: ["node", "bun"],
123
132
  "node-server": ["node", "bun"],
124
133
  "node-cluster": ["node", "bun"],
125
134
  };