create-taserjs 0.1.12 → 0.2.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 (189) hide show
  1. package/README.md +8 -44
  2. package/dist/cli-CBhdDKHU.cjs +1398 -0
  3. package/dist/cli-hL7a4VS0.js +1237 -0
  4. package/dist/cli-hL7a4VS0.js.map +1 -0
  5. package/dist/cli.cjs +4 -0
  6. package/dist/cli.d.cts +4 -0
  7. package/dist/cli.d.cts.map +1 -0
  8. package/dist/cli.d.ts +4 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +3 -0
  11. package/dist/index.cjs +25 -0
  12. package/dist/index.d.cts +119 -0
  13. package/dist/index.d.cts.map +1 -0
  14. package/dist/index.d.ts +119 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +2 -0
  17. package/package.json +39 -9
  18. package/src/addons/drizzle/index.ts +37 -40
  19. package/src/addons/kysely/index.ts +19 -22
  20. package/src/addons/pino/index.ts +2 -2
  21. package/src/addons/prisma/index.ts +18 -22
  22. package/src/addons/registry.ts +37 -73
  23. package/src/addons/types.ts +12 -13
  24. package/src/addons/validators.ts +22 -23
  25. package/src/addons/winston/index.ts +3 -3
  26. package/src/cli.ts +96 -56
  27. package/src/commands/create.ts +118 -249
  28. package/src/core/package-manager.ts +36 -55
  29. package/src/core/scaffold-engine.ts +100 -75
  30. package/src/core/targets.ts +19 -55
  31. package/src/core/types.ts +18 -53
  32. package/src/index.ts +8 -0
  33. package/src/templates/base.ts +139 -51
  34. package/dist/cjs/_virtual/_rolldown/runtime.cjs +0 -23
  35. package/dist/cjs/addons/arktype/index.cjs +0 -6
  36. package/dist/cjs/addons/arktype/index.cjs.map +0 -1
  37. package/dist/cjs/addons/arktype/index.d.cts +0 -1
  38. package/dist/cjs/addons/drizzle/index.cjs +0 -131
  39. package/dist/cjs/addons/drizzle/index.cjs.map +0 -1
  40. package/dist/cjs/addons/drizzle/index.d.cts +0 -2
  41. package/dist/cjs/addons/kysely/index.cjs +0 -103
  42. package/dist/cjs/addons/kysely/index.cjs.map +0 -1
  43. package/dist/cjs/addons/kysely/index.d.cts +0 -2
  44. package/dist/cjs/addons/pino/index.cjs +0 -30
  45. package/dist/cjs/addons/pino/index.cjs.map +0 -1
  46. package/dist/cjs/addons/pino/index.d.cts +0 -2
  47. package/dist/cjs/addons/prisma/index.cjs +0 -133
  48. package/dist/cjs/addons/prisma/index.cjs.map +0 -1
  49. package/dist/cjs/addons/prisma/index.d.cts +0 -2
  50. package/dist/cjs/addons/registry.cjs +0 -65
  51. package/dist/cjs/addons/registry.cjs.map +0 -1
  52. package/dist/cjs/addons/registry.d.cts +0 -5
  53. package/dist/cjs/addons/types.d.cts +0 -16
  54. package/dist/cjs/addons/valibot/index.cjs +0 -6
  55. package/dist/cjs/addons/valibot/index.cjs.map +0 -1
  56. package/dist/cjs/addons/valibot/index.d.cts +0 -1
  57. package/dist/cjs/addons/validators.cjs +0 -38
  58. package/dist/cjs/addons/validators.cjs.map +0 -1
  59. package/dist/cjs/addons/validators.d.cts +0 -5
  60. package/dist/cjs/addons/winston/index.cjs +0 -34
  61. package/dist/cjs/addons/winston/index.cjs.map +0 -1
  62. package/dist/cjs/addons/winston/index.d.cts +0 -2
  63. package/dist/cjs/addons/zod/index.cjs +0 -6
  64. package/dist/cjs/addons/zod/index.cjs.map +0 -1
  65. package/dist/cjs/addons/zod/index.d.cts +0 -1
  66. package/dist/cjs/cli.cjs +0 -65
  67. package/dist/cjs/cli.cjs.map +0 -1
  68. package/dist/cjs/cli.d.cts +0 -2
  69. package/dist/cjs/commands/create.cjs +0 -332
  70. package/dist/cjs/commands/create.cjs.map +0 -1
  71. package/dist/cjs/commands/create.d.cts +0 -14
  72. package/dist/cjs/core/json-output.cjs +0 -16
  73. package/dist/cjs/core/json-output.cjs.map +0 -1
  74. package/dist/cjs/core/json-output.d.cts +0 -4
  75. package/dist/cjs/core/package-manager.cjs +0 -56
  76. package/dist/cjs/core/package-manager.cjs.map +0 -1
  77. package/dist/cjs/core/package-manager.d.cts +0 -8
  78. package/dist/cjs/core/parse-options.cjs +0 -95
  79. package/dist/cjs/core/parse-options.cjs.map +0 -1
  80. package/dist/cjs/core/parse-options.d.cts +0 -35
  81. package/dist/cjs/core/project-config.cjs +0 -23
  82. package/dist/cjs/core/project-config.cjs.map +0 -1
  83. package/dist/cjs/core/project-config.d.cts +0 -2
  84. package/dist/cjs/core/resolve-packages.cjs +0 -58
  85. package/dist/cjs/core/resolve-packages.cjs.map +0 -1
  86. package/dist/cjs/core/resolve-packages.d.cts +0 -2
  87. package/dist/cjs/core/scaffold-engine.cjs +0 -72
  88. package/dist/cjs/core/scaffold-engine.cjs.map +0 -1
  89. package/dist/cjs/core/scaffold-engine.d.cts +0 -2
  90. package/dist/cjs/core/targets.cjs +0 -171
  91. package/dist/cjs/core/targets.cjs.map +0 -1
  92. package/dist/cjs/core/targets.d.cts +0 -49
  93. package/dist/cjs/core/types.cjs +0 -52
  94. package/dist/cjs/core/types.cjs.map +0 -1
  95. package/dist/cjs/core/types.d.cts +0 -57
  96. package/dist/cjs/core/validate-project-name.cjs +0 -44
  97. package/dist/cjs/core/validate-project-name.cjs.map +0 -1
  98. package/dist/cjs/core/validate-project-name.d.cts +0 -1
  99. package/dist/cjs/frameworks/index.cjs +0 -116
  100. package/dist/cjs/frameworks/index.cjs.map +0 -1
  101. package/dist/cjs/frameworks/index.d.cts +0 -18
  102. package/dist/cjs/scaffold.d.cts +0 -3
  103. package/dist/cjs/templates/base.cjs +0 -97
  104. package/dist/cjs/templates/base.cjs.map +0 -1
  105. package/dist/cjs/templates/base.d.cts +0 -9
  106. package/dist/cjs/types.d.cts +0 -1
  107. package/dist/esm/addons/arktype/index.d.ts +0 -1
  108. package/dist/esm/addons/arktype/index.js +0 -7
  109. package/dist/esm/addons/arktype/index.js.map +0 -1
  110. package/dist/esm/addons/drizzle/index.d.ts +0 -2
  111. package/dist/esm/addons/drizzle/index.js +0 -131
  112. package/dist/esm/addons/drizzle/index.js.map +0 -1
  113. package/dist/esm/addons/kysely/index.d.ts +0 -2
  114. package/dist/esm/addons/kysely/index.js +0 -103
  115. package/dist/esm/addons/kysely/index.js.map +0 -1
  116. package/dist/esm/addons/pino/index.d.ts +0 -2
  117. package/dist/esm/addons/pino/index.js +0 -30
  118. package/dist/esm/addons/pino/index.js.map +0 -1
  119. package/dist/esm/addons/prisma/index.d.ts +0 -2
  120. package/dist/esm/addons/prisma/index.js +0 -133
  121. package/dist/esm/addons/prisma/index.js.map +0 -1
  122. package/dist/esm/addons/registry.d.ts +0 -5
  123. package/dist/esm/addons/registry.js +0 -63
  124. package/dist/esm/addons/registry.js.map +0 -1
  125. package/dist/esm/addons/types.d.ts +0 -16
  126. package/dist/esm/addons/valibot/index.d.ts +0 -1
  127. package/dist/esm/addons/valibot/index.js +0 -7
  128. package/dist/esm/addons/valibot/index.js.map +0 -1
  129. package/dist/esm/addons/validators.d.ts +0 -5
  130. package/dist/esm/addons/validators.js +0 -36
  131. package/dist/esm/addons/validators.js.map +0 -1
  132. package/dist/esm/addons/winston/index.d.ts +0 -2
  133. package/dist/esm/addons/winston/index.js +0 -34
  134. package/dist/esm/addons/winston/index.js.map +0 -1
  135. package/dist/esm/addons/zod/index.d.ts +0 -1
  136. package/dist/esm/addons/zod/index.js +0 -7
  137. package/dist/esm/addons/zod/index.js.map +0 -1
  138. package/dist/esm/cli.d.ts +0 -2
  139. package/dist/esm/cli.js +0 -62
  140. package/dist/esm/cli.js.map +0 -1
  141. package/dist/esm/commands/create.d.ts +0 -14
  142. package/dist/esm/commands/create.js +0 -327
  143. package/dist/esm/commands/create.js.map +0 -1
  144. package/dist/esm/core/json-output.d.ts +0 -4
  145. package/dist/esm/core/json-output.js +0 -14
  146. package/dist/esm/core/json-output.js.map +0 -1
  147. package/dist/esm/core/package-manager.d.ts +0 -8
  148. package/dist/esm/core/package-manager.js +0 -53
  149. package/dist/esm/core/package-manager.js.map +0 -1
  150. package/dist/esm/core/parse-options.d.ts +0 -35
  151. package/dist/esm/core/parse-options.js +0 -89
  152. package/dist/esm/core/parse-options.js.map +0 -1
  153. package/dist/esm/core/project-config.d.ts +0 -2
  154. package/dist/esm/core/project-config.js +0 -21
  155. package/dist/esm/core/project-config.js.map +0 -1
  156. package/dist/esm/core/resolve-packages.d.ts +0 -2
  157. package/dist/esm/core/resolve-packages.js +0 -58
  158. package/dist/esm/core/resolve-packages.js.map +0 -1
  159. package/dist/esm/core/scaffold-engine.d.ts +0 -2
  160. package/dist/esm/core/scaffold-engine.js +0 -70
  161. package/dist/esm/core/scaffold-engine.js.map +0 -1
  162. package/dist/esm/core/targets.d.ts +0 -49
  163. package/dist/esm/core/targets.js +0 -166
  164. package/dist/esm/core/targets.js.map +0 -1
  165. package/dist/esm/core/types.d.ts +0 -57
  166. package/dist/esm/core/types.js +0 -45
  167. package/dist/esm/core/types.js.map +0 -1
  168. package/dist/esm/core/validate-project-name.d.ts +0 -1
  169. package/dist/esm/core/validate-project-name.js +0 -42
  170. package/dist/esm/core/validate-project-name.js.map +0 -1
  171. package/dist/esm/frameworks/index.d.ts +0 -18
  172. package/dist/esm/frameworks/index.js +0 -112
  173. package/dist/esm/frameworks/index.js.map +0 -1
  174. package/dist/esm/scaffold.d.ts +0 -3
  175. package/dist/esm/templates/base.d.ts +0 -9
  176. package/dist/esm/templates/base.js +0 -91
  177. package/dist/esm/templates/base.js.map +0 -1
  178. package/dist/esm/types.d.ts +0 -1
  179. package/src/addons/arktype/index.ts +0 -3
  180. package/src/addons/valibot/index.ts +0 -3
  181. package/src/addons/zod/index.ts +0 -3
  182. package/src/core/json-output.ts +0 -13
  183. package/src/core/parse-options.ts +0 -167
  184. package/src/core/project-config.ts +0 -32
  185. package/src/core/resolve-packages.ts +0 -69
  186. package/src/core/validate-project-name.ts +0 -55
  187. package/src/frameworks/index.ts +0 -120
  188. package/src/scaffold.ts +0 -3
  189. package/src/types.ts +0 -12
package/src/cli.ts CHANGED
@@ -1,62 +1,102 @@
1
1
  #!/usr/bin/env node
2
- import { parseArgs } from "node:util";
2
+ import yargs from "yargs";
3
+ import { hideBin } from "yargs/helpers";
4
+ import { runCreateCommand, type RunCreateCommandOptions } from "./commands/create.js";
5
+ import type {
6
+ DbDriver,
7
+ DbOdm,
8
+ DeployTarget,
9
+ LoggerId,
10
+ Runtime,
11
+ ValidatorId,
12
+ } from "./core/types.js";
3
13
 
4
- import * as p from "@clack/prompts";
5
- import color from "picocolors";
14
+ export async function run(argv: string[] = hideBin(process.argv)): Promise<void> {
15
+ const parser = yargs(argv)
16
+ .scriptName("create-taserjs")
17
+ .usage("$0 [dir] [options]")
18
+ .command(
19
+ "$0 [dir]",
20
+ "Scaffold a new Taser.js application",
21
+ (y: any) =>
22
+ y
23
+ .positional("dir", {
24
+ type: "string",
25
+ description: "Directory or project name",
26
+ })
27
+ .option("preset", {
28
+ alias: "p",
29
+ type: "string",
30
+ description: "Deployment preset",
31
+ })
32
+ .option("runtime", {
33
+ type: "string",
34
+ description: "Runtime override (node, bun, deno)",
35
+ })
36
+ .option("validator", {
37
+ alias: "v",
38
+ type: "string",
39
+ choices: ["zod", "valibot", "arktype", "none"],
40
+ description: "Standard Schema validator",
41
+ })
42
+ .option("db", {
43
+ type: "string",
44
+ choices: ["drizzle", "prisma", "kysely", "none"],
45
+ description: "Database ORM / Query builder",
46
+ })
47
+ .option("driver", {
48
+ type: "string",
49
+ choices: ["sqlite", "postgres", "mysql"],
50
+ description: "Database driver",
51
+ })
52
+ .option("logger", {
53
+ alias: "l",
54
+ type: "string",
55
+ choices: ["pino", "winston", "none"],
56
+ description: "Logger addon",
57
+ })
58
+ .option("skip-install", {
59
+ type: "boolean",
60
+ description: "Skip dependency installation",
61
+ default: false,
62
+ })
63
+ .option("yes", {
64
+ alias: "y",
65
+ type: "boolean",
66
+ description: "Skip prompts and use defaults",
67
+ default: false,
68
+ }),
69
+ async (args: any) => {
70
+ const createOpts: RunCreateCommandOptions = {
71
+ targetDir: args.dir as string | undefined,
72
+ projectName: args.dir as string | undefined,
73
+ preset: args.preset as DeployTarget | undefined,
74
+ runtime: args.runtime as Runtime | undefined,
75
+ validator: (args.validator === "none" ? undefined : args.validator) as
76
+ | ValidatorId
77
+ | undefined,
78
+ db: (args.db === "none" ? undefined : args.db) as DbOdm | undefined,
79
+ driver: args.driver as DbDriver | undefined,
80
+ logger: (args.logger === "none" ? undefined : args.logger) as LoggerId | undefined,
81
+ skipInstall: Boolean(args.skipInstall),
82
+ interactive: !args.yes,
83
+ };
84
+ await runCreateCommand(createOpts);
85
+ },
86
+ )
87
+ .help()
88
+ .alias("help", "h")
89
+ .version()
90
+ .alias("version", "V")
91
+ .strict()
92
+ .exitProcess(false);
6
93
 
7
- import { buildParsedArgsFromCli, runCreateCommand } from "./commands/create.js";
8
- import { printJsonError } from "./core/json-output.js";
94
+ await parser.parse();
95
+ }
9
96
 
10
- async function main(): Promise<void> {
11
- const { values, positionals } = parseArgs({
12
- args: process.argv.slice(2),
13
- options: {
14
- preset: { type: "string", short: "p" },
15
- db: { type: "string" },
16
- logger: { type: "string" },
17
- validator: { type: "string" },
18
- framework: { type: "string" },
19
- runtime: { type: "string" },
20
- y: { type: "boolean", short: "y" },
21
- noInstall: { type: "boolean" },
22
- json: { type: "boolean" },
23
- },
24
- allowPositionals: true,
97
+ if (process.argv[1] && process.argv[1].endsWith("cli.js")) {
98
+ run().catch((err: unknown) => {
99
+ console.error(err instanceof Error ? err.message : String(err));
100
+ process.exit(1);
25
101
  });
26
-
27
- const parsed = buildParsedArgsFromCli(
28
- {
29
- ...(values.preset !== undefined ? { preset: values.preset } : {}),
30
- ...(values.db !== undefined ? { db: values.db } : {}),
31
- ...(values.logger !== undefined ? { logger: values.logger } : {}),
32
- ...(values.validator !== undefined ? { validator: values.validator } : {}),
33
- ...(values.framework !== undefined ? { framework: values.framework } : {}),
34
- ...(values.runtime !== undefined ? { runtime: values.runtime } : {}),
35
- ...(values.y !== undefined ? { y: values.y } : {}),
36
- ...(values.noInstall !== undefined ? { noInstall: values.noInstall } : {}),
37
- ...(values.json !== undefined ? { json: values.json } : {}),
38
- },
39
- positionals,
40
- );
41
-
42
- if (!parsed.json) {
43
- console.clear();
44
- p.intro(color.bgCyan(color.black(" create-taserjs ")));
45
- }
46
-
47
- try {
48
- await runCreateCommand(parsed);
49
- } catch (error) {
50
- const message = error instanceof Error ? error.message : String(error);
51
- if (parsed.json) {
52
- printJsonError(message);
53
- process.exit(1);
54
- }
55
- throw error;
56
- }
57
102
  }
58
-
59
- main().catch((error: unknown) => {
60
- console.error(error);
61
- process.exit(1);
62
- });
@@ -1,67 +1,61 @@
1
1
  import path from "node:path";
2
-
3
2
  import * as p from "@clack/prompts";
4
- import color from "picocolors";
5
-
6
- import { getCapabilitiesCatalog } from "../addons/registry.js";
7
- import {
8
- printCapabilitiesCatalog,
9
- printJsonError,
10
- printScaffoldResult,
11
- } from "../core/json-output.js";
12
- import {
13
- parseDbFlag,
14
- parseFrameworkFlag,
15
- parseLoggerFlag,
16
- parsePresetFlag,
17
- parseRuntimeFlag,
18
- parseValidatorFlag,
19
- type ParsedCreateArgs,
20
- resolveScaffoldDefaults,
21
- } from "../core/parse-options.js";
3
+ import pc from "picocolors";
4
+ import { resolveUserAgent, runScript } from "../core/package-manager.js";
22
5
  import { scaffoldProject } from "../core/scaffold-engine.js";
23
- import { allowedRuntimeOverrides } from "../core/targets.js";
6
+ import { allowedRuntimeOverrides, DEFAULT_DEPLOY } from "../core/targets.js";
24
7
  import type {
25
8
  DbDriver,
26
9
  DbOdm,
27
10
  DeployTarget,
28
11
  LoggerId,
12
+ Runtime,
13
+ ScaffoldOptions,
29
14
  ScaffoldResult,
30
15
  ValidatorId,
31
16
  } from "../core/types.js";
32
- import { DB_DRIVERS, DB_ODMS, DEPLOY_TARGETS, LOGGERS, VALIDATORS } from "../core/types.js";
33
- import { validateProjectName } from "../core/validate-project-name.js";
34
- import { resolveUserAgent, runScript } from "../core/package-manager.js";
35
-
36
- function isDeployTarget(value: unknown): value is DeployTarget {
37
- return typeof value === "string" && (DEPLOY_TARGETS as readonly string[]).includes(value);
38
- }
39
-
40
- function isDbOdm(value: unknown): value is DbOdm {
41
- return typeof value === "string" && (DB_ODMS as readonly string[]).includes(value);
42
- }
43
-
44
- function isDbDriver(value: unknown): value is DbDriver {
45
- return typeof value === "string" && (DB_DRIVERS as readonly string[]).includes(value);
17
+ import { DEPLOY_TARGETS } from "../core/types.js";
18
+
19
+ const DEPLOY_LABELS: Record<DeployTarget, string> = {
20
+ none: "None (Standalone Vite SSR)",
21
+ "node-server": "Node.js server (Nitro)",
22
+ "node-cluster": "Node.js cluster (Nitro)",
23
+ bun: "Bun (Nitro)",
24
+ "deno-server": "Deno (Nitro)",
25
+ "deno-deploy": "Deno Deploy (Nitro)",
26
+ "cloudflare-module": "Cloudflare Workers (Nitro)",
27
+ vercel: "Vercel (Nitro)",
28
+ "aws-lambda": "AWS Lambda (Nitro)",
29
+ netlify: "Netlify (Nitro)",
30
+ };
31
+
32
+ export interface RunCreateCommandOptions {
33
+ projectName?: string | undefined;
34
+ preset?: DeployTarget | undefined;
35
+ runtime?: Runtime | undefined;
36
+ db?: DbOdm | undefined;
37
+ driver?: DbDriver | undefined;
38
+ logger?: LoggerId | undefined;
39
+ validator?: ValidatorId | undefined;
40
+ skipInstall?: boolean | undefined;
41
+ interactive?: boolean | undefined;
42
+ targetDir?: string | undefined;
43
+ packageVersions?: Record<string, string> | undefined;
46
44
  }
47
45
 
48
- function isLoggerId(value: unknown): value is LoggerId {
49
- return typeof value === "string" && (LOGGERS as readonly string[]).includes(value);
50
- }
51
-
52
- function isValidatorId(value: unknown): value is ValidatorId {
53
- return typeof value === "string" && (VALIDATORS as readonly string[]).includes(value);
54
- }
55
-
56
- async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedCreateArgs> {
46
+ export async function promptInteractiveOptions(
47
+ defaults: RunCreateCommandOptions,
48
+ ): Promise<RunCreateCommandOptions> {
57
49
  const projectName =
58
- args.projectName ??
50
+ defaults.projectName ??
59
51
  (await p.text({
60
52
  message: "Project name",
61
53
  placeholder: "my-taser-app",
62
54
  defaultValue: "my-taser-app",
63
55
  validate(value) {
64
- return validateProjectName(value);
56
+ if (!value || value.trim().length === 0) return "Project name cannot be empty";
57
+ if (/[^a-zA-Z0-9_-]/.test(value)) return "Project name contains invalid characters";
58
+ return undefined;
65
59
  },
66
60
  }));
67
61
 
@@ -70,69 +64,32 @@ async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedC
70
64
  process.exit(0);
71
65
  }
72
66
 
73
- const framework =
74
- args.framework ??
75
- (await p.select({
76
- message: "Host framework",
77
- options: [
78
- { value: "none", label: "None", hint: "Taser.js Fetch (default)" },
79
- { value: "hono", label: "Hono" },
80
- { value: "express", label: "Express" },
81
- { value: "fastify", label: "Fastify" },
82
- ],
83
- initialValue: "none",
84
- }));
85
-
86
- if (p.isCancel(framework)) {
87
- p.cancel("Scaffold cancelled.");
88
- process.exit(0);
89
- }
90
-
91
- const DEPLOY_LABELS: Record<DeployTarget, string> = {
92
- none: "None (Standalone Vite)",
93
- "node-server": "Node.js server",
94
- "node-cluster": "Node.js cluster",
95
- bun: "Bun",
96
- "deno-server": "Deno",
97
- "deno-deploy": "Deno Deploy",
98
- "cloudflare-module": "Cloudflare Workers",
99
- vercel: "Vercel",
100
- "aws-lambda": "AWS Lambda",
101
- netlify: "Netlify",
102
- };
103
-
104
- const DEPLOY_HINTS: Partial<Record<DeployTarget, string>> = {
105
- none: "standalone Vite, no Nitro",
106
- };
107
-
108
67
  const preset =
109
- args.preset ??
68
+ defaults.preset ??
110
69
  (await p.select({
111
70
  message: "Deployment target",
112
- // oxlint-disable-next-line oxc/no-map-spread
113
71
  options: DEPLOY_TARGETS.map((id) => ({
114
72
  value: id,
115
73
  label: DEPLOY_LABELS[id],
116
- ...(DEPLOY_HINTS[id] ? { hint: DEPLOY_HINTS[id] } : {}),
117
74
  })),
118
- initialValue: "node-server",
75
+ initialValue: "none",
119
76
  }));
120
77
 
121
- if (p.isCancel(preset) || !isDeployTarget(preset)) {
78
+ if (p.isCancel(preset)) {
122
79
  p.cancel("Scaffold cancelled.");
123
80
  process.exit(0);
124
81
  }
125
82
 
126
- let runtime: import("../core/types.js").Runtime | undefined;
127
- const runtimeOverrides = allowedRuntimeOverrides(preset);
83
+ let runtime: Runtime | undefined;
84
+ const runtimeOverrides = allowedRuntimeOverrides(preset as DeployTarget);
128
85
  if (runtimeOverrides.length > 0) {
129
86
  const runtimeChoice =
130
- args.runtime ??
87
+ defaults.runtime ??
131
88
  (await p.select({
132
- message: "Runtime",
89
+ message: "Runtime override",
133
90
  options: [
134
91
  ...runtimeOverrides.map((rt) => ({ value: rt, label: rt })),
135
- { value: "default", label: `Preset default`, hint: "no override" },
92
+ { value: "default", label: "Preset default", hint: "no override" },
136
93
  ],
137
94
  initialValue: "default",
138
95
  }));
@@ -141,14 +98,33 @@ async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedC
141
98
  p.cancel("Scaffold cancelled.");
142
99
  process.exit(0);
143
100
  }
101
+ runtime = runtimeChoice === "default" ? undefined : (runtimeChoice as Runtime);
102
+ }
103
+
104
+ const validatorChoice =
105
+ defaults.validator ??
106
+ (await p.select({
107
+ message: "Standard Schema Validator",
108
+ options: [
109
+ { value: "none", label: "None", hint: "default" },
110
+ { value: "zod", label: "Zod" },
111
+ { value: "valibot", label: "Valibot" },
112
+ { value: "arktype", label: "Arktype" },
113
+ ],
114
+ initialValue: "none",
115
+ }));
144
116
 
145
- runtime = runtimeChoice === "default" ? undefined : runtimeChoice;
117
+ if (p.isCancel(validatorChoice)) {
118
+ p.cancel("Scaffold cancelled.");
119
+ process.exit(0);
146
120
  }
147
121
 
122
+ const validator = validatorChoice === "none" ? undefined : (validatorChoice as ValidatorId);
123
+
148
124
  const dbChoice =
149
- args.db ??
125
+ defaults.db ??
150
126
  (await p.select({
151
- message: "Database",
127
+ message: "Database ORM / Query Builder",
152
128
  options: [
153
129
  { value: "none", label: "None", hint: "default" },
154
130
  { value: "drizzle", label: "Drizzle" },
@@ -166,10 +142,10 @@ async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedC
166
142
  let db: DbOdm | undefined;
167
143
  let driver: DbDriver | undefined;
168
144
 
169
- if (dbChoice !== "none" && isDbOdm(dbChoice)) {
170
- db = dbChoice;
145
+ if (dbChoice !== "none") {
146
+ db = dbChoice as DbOdm;
171
147
  const driverChoice =
172
- args.driver ??
148
+ defaults.driver ??
173
149
  (await p.select({
174
150
  message: "Database driver",
175
151
  options: [
@@ -180,15 +156,15 @@ async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedC
180
156
  initialValue: "sqlite",
181
157
  }));
182
158
 
183
- if (p.isCancel(driverChoice) || !isDbDriver(driverChoice)) {
159
+ if (p.isCancel(driverChoice)) {
184
160
  p.cancel("Scaffold cancelled.");
185
161
  process.exit(0);
186
162
  }
187
- driver = driverChoice;
163
+ driver = driverChoice as DbDriver;
188
164
  }
189
165
 
190
166
  const loggerChoice =
191
- args.logger ??
167
+ defaults.logger ??
192
168
  (await p.select({
193
169
  message: "Logger",
194
170
  options: [
@@ -204,175 +180,68 @@ async function promptInteractiveOptions(args: ParsedCreateArgs): Promise<ParsedC
204
180
  process.exit(0);
205
181
  }
206
182
 
207
- const logger =
208
- loggerChoice === "none" ? undefined : isLoggerId(loggerChoice) ? loggerChoice : undefined;
209
-
210
- const validatorChoice =
211
- args.validator ??
212
- (await p.select({
213
- message: "Validator",
214
- options: [
215
- { value: "none", label: "None", hint: "default" },
216
- { value: "zod", label: "Zod" },
217
- { value: "arktype", label: "Arktype" },
218
- { value: "valibot", label: "Valibot" },
219
- ],
220
- initialValue: "none",
221
- }));
222
-
223
- if (p.isCancel(validatorChoice)) {
224
- p.cancel("Scaffold cancelled.");
225
- process.exit(0);
226
- }
227
-
228
- const validator =
229
- validatorChoice === "none"
230
- ? undefined
231
- : isValidatorId(validatorChoice)
232
- ? validatorChoice
233
- : undefined;
183
+ const logger = loggerChoice === "none" ? undefined : (loggerChoice as LoggerId);
234
184
 
235
185
  return {
236
186
  projectName: String(projectName).trim(),
237
- framework,
238
- preset,
239
- ...(runtime !== undefined ? { runtime } : {}),
240
- yes: args.yes,
241
- noInstall: args.noInstall,
242
- json: args.json,
243
- ...(db ? { db, driver: driver! } : {}),
244
- ...(logger ? { logger } : {}),
187
+ preset: preset as DeployTarget,
188
+ ...(runtime ? { runtime } : {}),
245
189
  ...(validator ? { validator } : {}),
190
+ ...(db ? { db, driver } : {}),
191
+ ...(logger ? { logger } : {}),
192
+ skipInstall: defaults.skipInstall,
246
193
  };
247
194
  }
248
195
 
249
196
  export async function runCreateCommand(
250
- args: ParsedCreateArgs,
251
- ): Promise<ScaffoldResult | undefined> {
252
- if (args.json && !args.projectName) {
253
- printCapabilitiesCatalog(getCapabilitiesCatalog());
254
- return undefined;
255
- }
197
+ args: RunCreateCommandOptions = {},
198
+ ): Promise<ScaffoldResult> {
199
+ const isInteractive =
200
+ args.interactive ?? (Boolean(process.stdout.isTTY) && process.env.NODE_ENV !== "test");
256
201
 
257
- const cwd = process.cwd();
258
- const interactive = !args.yes;
259
- const resolved = interactive
202
+ const resolved = isInteractive
260
203
  ? await promptInteractiveOptions(args)
261
204
  : {
262
205
  ...args,
263
- projectName: args.projectName?.trim(),
264
- preset: args.preset ?? "node-server",
206
+ projectName: args.projectName ?? "my-taser-app",
207
+ preset: args.preset ?? DEFAULT_DEPLOY,
265
208
  };
266
209
 
267
- if (!resolved.projectName) {
268
- const message = "Project name is required";
269
- if (args.json) {
270
- printJsonError(message);
271
- process.exit(1);
272
- }
273
- throw new Error(message);
274
- }
275
-
276
- const nameError = validateProjectName(resolved.projectName, cwd);
277
- if (nameError) {
278
- if (args.json) {
279
- printJsonError(nameError);
280
- process.exit(1);
281
- }
282
- throw new Error(nameError);
283
- }
284
-
285
- const targetDir = path.resolve(cwd, resolved.projectName);
286
- const scaffoldCtx = resolveScaffoldDefaults({
287
- ...resolved,
288
- projectName: resolved.projectName,
289
- });
290
- scaffoldCtx.targetDir = targetDir;
291
-
292
- if (!args.json) {
293
- const spinner = p.spinner();
294
- spinner.start("Scaffolding project");
295
- try {
296
- const result = await scaffoldProject({
297
- ...scaffoldCtx,
298
- targetDir,
299
- skipInstall: args.noInstall,
300
- agent: resolveUserAgent(),
301
- });
302
- spinner.stop("Project created");
303
- const cdPath = path.relative(cwd, targetDir) || ".";
304
- p.note([`cd ${cdPath}`, runScript(resolveUserAgent(), "dev")].join("\n"), "Next steps");
305
- p.outro(color.green("Done."));
306
- return result;
307
- } catch (error) {
308
- spinner.stop("Scaffold failed");
309
- throw error;
310
- }
311
- }
210
+ const cwd = process.cwd();
211
+ const projectName = resolved.projectName || "my-taser-app";
212
+ const targetDir = args.targetDir
213
+ ? path.resolve(cwd, args.targetDir)
214
+ : path.resolve(cwd, projectName);
312
215
 
313
- const result = await scaffoldProject({
314
- ...scaffoldCtx,
216
+ const scaffoldOpts: ScaffoldOptions = {
217
+ projectName,
315
218
  targetDir,
316
- skipInstall: args.noInstall,
317
- agent: resolveUserAgent(),
318
- });
319
- printScaffoldResult(result);
320
- return result;
321
- }
322
-
323
- export function buildParsedArgsFromCli(
324
- values: {
325
- preset?: string;
326
- framework?: string;
327
- runtime?: string;
328
- db?: string;
329
- logger?: string;
330
- validator?: string;
331
- y?: boolean;
332
- noInstall?: boolean;
333
- json?: boolean;
334
- },
335
- positionals: string[],
336
- ): ParsedCreateArgs {
337
- const args: ParsedCreateArgs = {
338
- yes: values.y ?? false,
339
- noInstall: values.noInstall ?? false,
340
- json: values.json ?? false,
219
+ ...(resolved.preset !== undefined ? { preset: resolved.preset } : {}),
220
+ ...(resolved.runtime !== undefined ? { runtime: resolved.runtime } : {}),
221
+ ...(resolved.validator !== undefined ? { validator: resolved.validator } : {}),
222
+ ...(resolved.db !== undefined ? { db: resolved.db } : {}),
223
+ ...(resolved.driver !== undefined ? { driver: resolved.driver } : {}),
224
+ ...(resolved.logger !== undefined ? { logger: resolved.logger } : {}),
225
+ ...(args.packageVersions !== undefined ? { packageVersions: args.packageVersions } : {}),
226
+ skipInstall: resolved.skipInstall ?? process.env.NODE_ENV === "test",
341
227
  };
342
228
 
343
- if (positionals[0]) {
344
- args.projectName = positionals[0];
345
- }
346
-
347
- if (values.preset) {
348
- const parsed = parsePresetFlag(values.preset);
349
- args.preset = parsed.preset;
350
- if (parsed.warning && !args.json) {
351
- console.warn(`warning: ${parsed.warning}`);
229
+ if (isInteractive) {
230
+ const s = p.spinner();
231
+ s.start("Scaffolding project");
232
+ const result = await scaffoldProject(scaffoldOpts);
233
+ s.stop("Project created");
234
+
235
+ const agent = resolveUserAgent();
236
+ p.outro(pc.green("Done!"));
237
+ console.log(`\nNext steps:`);
238
+ console.log(` cd ${path.relative(cwd, targetDir) || "."}`);
239
+ if (scaffoldOpts.skipInstall) {
240
+ console.log(` ${runScript(agent, "install")}`);
352
241
  }
242
+ console.log(` ${runScript(agent, "dev")}\n`);
243
+ return result;
353
244
  }
354
245
 
355
- if (values.framework) {
356
- args.framework = parseFrameworkFlag(values.framework);
357
- }
358
-
359
- if (values.runtime) {
360
- args.runtime = parseRuntimeFlag(values.runtime);
361
- }
362
-
363
- if (values.db) {
364
- const parsed = parseDbFlag(values.db);
365
- args.db = parsed.db;
366
- args.driver = parsed.driver;
367
- }
368
-
369
- if (values.logger) {
370
- args.logger = parseLoggerFlag(values.logger);
371
- }
372
-
373
- if (values.validator) {
374
- args.validator = parseValidatorFlag(values.validator);
375
- }
376
-
377
- return args;
246
+ return await scaffoldProject(scaffoldOpts);
378
247
  }