create-taserjs 0.1.11 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/README.md +8 -44
  2. package/dist/cli-9fkoNOJg.js +1237 -0
  3. package/dist/cli-9fkoNOJg.js.map +1 -0
  4. package/dist/cli-DkZddFtU.cjs +1398 -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 +20 -56
  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
@@ -0,0 +1,1237 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import path, { dirname, join } from "node:path";
3
+ import { execSync } from "node:child_process";
4
+ import { getUserAgent, resolveCommand } from "package-manager-detector";
5
+ import * as p from "@clack/prompts";
6
+ import pc from "picocolors";
7
+ import yargs from "yargs";
8
+ import { hideBin } from "yargs/helpers";
9
+ //#region src/core/types.ts
10
+ const RUNTIMES = [
11
+ "node",
12
+ "bun",
13
+ "deno"
14
+ ];
15
+ const DEPLOY_TARGETS = [
16
+ "none",
17
+ "node-server",
18
+ "node-cluster",
19
+ "bun",
20
+ "deno-server",
21
+ "deno-deploy",
22
+ "cloudflare-module",
23
+ "vercel",
24
+ "aws-lambda",
25
+ "netlify"
26
+ ];
27
+ const DB_ODMS = [
28
+ "drizzle",
29
+ "prisma",
30
+ "kysely"
31
+ ];
32
+ const DB_DRIVERS = [
33
+ "postgres",
34
+ "sqlite",
35
+ "mysql"
36
+ ];
37
+ const DEFAULT_DB_DRIVER = "sqlite";
38
+ const LOGGERS = ["pino", "winston"];
39
+ const VALIDATORS = [
40
+ "zod",
41
+ "arktype",
42
+ "valibot"
43
+ ];
44
+ //#endregion
45
+ //#region src/addons/drizzle/index.ts
46
+ function schemaSource$1(driver) {
47
+ switch (driver) {
48
+ case "postgres": return `import { pgTable, serial, text } from "drizzle-orm/pg-core";
49
+
50
+ export const users = pgTable("users", {
51
+ id: serial("id").primaryKey(),
52
+ email: text("email").notNull(),
53
+ });
54
+ `;
55
+ case "mysql": return `import { mysqlTable, serial, varchar } from "drizzle-orm/mysql-core";
56
+
57
+ export const users = mysqlTable("users", {
58
+ id: serial("id").primaryKey(),
59
+ email: varchar("email", { length: 255 }).notNull(),
60
+ });
61
+ `;
62
+ default: return `import { sqliteTable, integer, text } from "drizzle-orm/sqlite-core";
63
+
64
+ export const users = sqliteTable("users", {
65
+ id: integer("id").primaryKey({ autoIncrement: true }),
66
+ email: text("email").notNull(),
67
+ });
68
+ `;
69
+ }
70
+ }
71
+ function dbIndexSource$2(driver) {
72
+ switch (driver) {
73
+ case "postgres": return `import { drizzle } from "drizzle-orm/node-postgres";
74
+ import pg from "pg";
75
+ import * as schema from "./schema.js";
76
+
77
+ export function createDb() {
78
+ const pool = new pg.Pool({
79
+ connectionString: process.env.DATABASE_URL,
80
+ });
81
+ return drizzle(pool, { schema });
82
+ }
83
+ `;
84
+ case "mysql": return `import { drizzle } from "drizzle-orm/mysql2";
85
+ import mysql from "mysql2/promise";
86
+ import * as schema from "./schema.js";
87
+
88
+ export function createDb() {
89
+ const pool = mysql.createPool(process.env.DATABASE_URL ?? "");
90
+ return drizzle(pool, { schema, mode: "default" });
91
+ }
92
+ `;
93
+ default: return `import Database from "better-sqlite3";
94
+ import { drizzle } from "drizzle-orm/better-sqlite3";
95
+ import * as schema from "./schema.js";
96
+
97
+ export function createDb() {
98
+ const filePath = (process.env.DATABASE_URL ?? "file:./local.db").replace(/^file:/, "");
99
+ const client = new Database(filePath);
100
+ return drizzle(client, { schema });
101
+ }
102
+ `;
103
+ }
104
+ }
105
+ function drizzleConfigSource(driver) {
106
+ return `import { defineConfig } from "drizzle-kit";
107
+
108
+ export default defineConfig({
109
+ schema: "./src/db/schema.ts",
110
+ out: "./drizzle",
111
+ dialect: "${driver === "postgres" ? "postgresql" : driver === "mysql" ? "mysql" : "sqlite"}",
112
+ dbCredentials: {
113
+ url: process.env.DATABASE_URL ?? "",
114
+ },
115
+ });
116
+ `;
117
+ }
118
+ function envExample$2(driver) {
119
+ switch (driver) {
120
+ case "postgres": return "DATABASE_URL=postgresql://user:password@localhost:5432/mydb\n";
121
+ case "mysql": return "DATABASE_URL=mysql://user:password@localhost:3306/mydb\n";
122
+ default: return "DATABASE_URL=file:./local.db\n";
123
+ }
124
+ }
125
+ function driverPackages$2(driver) {
126
+ switch (driver) {
127
+ case "postgres": return ["pg"];
128
+ case "mysql": return ["mysql2"];
129
+ default: return ["better-sqlite3"];
130
+ }
131
+ }
132
+ function driverDevPackages$2(driver) {
133
+ switch (driver) {
134
+ case "postgres": return ["@types/pg"];
135
+ case "sqlite": return ["@types/better-sqlite3"];
136
+ default: return [];
137
+ }
138
+ }
139
+ const drizzleAddon = {
140
+ id: "drizzle",
141
+ category: "database",
142
+ dependencies(ctx) {
143
+ return ["drizzle-orm", ...driverPackages$2(ctx.driver ?? "sqlite")];
144
+ },
145
+ devDependencies(ctx) {
146
+ return ["drizzle-kit", ...driverDevPackages$2(ctx.driver ?? "sqlite")];
147
+ },
148
+ scripts() {
149
+ return {
150
+ "db:generate": "drizzle-kit generate",
151
+ "db:push": "drizzle-kit push"
152
+ };
153
+ },
154
+ bootBinding() {
155
+ return {
156
+ key: "db",
157
+ importPath: "./db/index.js",
158
+ factoryName: "createDb"
159
+ };
160
+ },
161
+ async apply(ctx, write) {
162
+ const driver = ctx.driver ?? "sqlite";
163
+ await write("src/db/schema.ts", schemaSource$1(driver));
164
+ await write("src/db/index.ts", dbIndexSource$2(driver));
165
+ await write("drizzle.config.ts", drizzleConfigSource(driver));
166
+ await write(".env.example", envExample$2(driver));
167
+ }
168
+ };
169
+ //#endregion
170
+ //#region src/addons/kysely/index.ts
171
+ function schemaTypesSource() {
172
+ return `export interface UserTable {
173
+ id: number;
174
+ email: string;
175
+ }
176
+
177
+ export interface DB {
178
+ users: UserTable;
179
+ }
180
+ `;
181
+ }
182
+ function dbIndexSource$1(driver) {
183
+ switch (driver) {
184
+ case "postgres": return `import { Kysely, PostgresDialect } from "kysely";
185
+ import pg from "pg";
186
+ import type { DB } from "./schema.js";
187
+
188
+ export function createDb() {
189
+ const pool = new pg.Pool({
190
+ connectionString: process.env.DATABASE_URL,
191
+ });
192
+ return new Kysely<DB>({
193
+ dialect: new PostgresDialect({ pool }),
194
+ });
195
+ }
196
+ `;
197
+ case "mysql": return `import { Kysely, MysqlDialect } from "kysely";
198
+ import { createPool } from "mysql2";
199
+ import type { DB } from "./schema.js";
200
+
201
+ export function createDb() {
202
+ const pool = createPool(process.env.DATABASE_URL ?? "");
203
+ return new Kysely<DB>({
204
+ dialect: new MysqlDialect({ pool }),
205
+ });
206
+ }
207
+ `;
208
+ default: return `import Database from "better-sqlite3";
209
+ import { Kysely, SqliteDialect } from "kysely";
210
+ import type { DB } from "./schema.js";
211
+
212
+ export function createDb() {
213
+ const filePath = (process.env.DATABASE_URL ?? "file:./local.db").replace(/^file:/, "");
214
+ const database = new Database(filePath);
215
+ return new Kysely<DB>({
216
+ dialect: new SqliteDialect({ database }),
217
+ });
218
+ }
219
+ `;
220
+ }
221
+ }
222
+ function driverPackages$1(driver) {
223
+ switch (driver) {
224
+ case "postgres": return ["pg"];
225
+ case "mysql": return ["mysql2"];
226
+ default: return ["better-sqlite3"];
227
+ }
228
+ }
229
+ function driverDevPackages$1(driver) {
230
+ switch (driver) {
231
+ case "postgres": return ["@types/pg"];
232
+ case "sqlite": return ["@types/better-sqlite3"];
233
+ default: return [];
234
+ }
235
+ }
236
+ function envExample$1(driver) {
237
+ switch (driver) {
238
+ case "postgres": return "DATABASE_URL=postgresql://user:password@localhost:5432/mydb\n";
239
+ case "mysql": return "DATABASE_URL=mysql://user:password@localhost:3306/mydb\n";
240
+ default: return "DATABASE_URL=file:./local.db\n";
241
+ }
242
+ }
243
+ const kyselyAddon = {
244
+ id: "kysely",
245
+ category: "database",
246
+ dependencies(ctx) {
247
+ return ["kysely", ...driverPackages$1(ctx.driver ?? "sqlite")];
248
+ },
249
+ devDependencies(ctx) {
250
+ return driverDevPackages$1(ctx.driver ?? "sqlite");
251
+ },
252
+ bootBinding() {
253
+ return {
254
+ key: "db",
255
+ importPath: "./db/index.js",
256
+ factoryName: "createDb"
257
+ };
258
+ },
259
+ async apply(ctx, write) {
260
+ const driver = ctx.driver ?? "sqlite";
261
+ await write("src/db/schema.ts", schemaTypesSource());
262
+ await write("src/db/index.ts", dbIndexSource$1(driver));
263
+ await write(".env.example", envExample$1(driver));
264
+ }
265
+ };
266
+ //#endregion
267
+ //#region src/addons/pino/index.ts
268
+ const pinoAddon = {
269
+ id: "pino",
270
+ category: "logger",
271
+ dependencies() {
272
+ return ["pino"];
273
+ },
274
+ devDependencies() {
275
+ return [];
276
+ },
277
+ bootBinding() {
278
+ return {
279
+ key: "logger",
280
+ importPath: "./logger.js",
281
+ factoryName: "createLogger"
282
+ };
283
+ },
284
+ async apply(_ctx, write) {
285
+ await write("src/logger.ts", `import pino from "pino";
286
+
287
+ export function createLogger() {
288
+ return pino({ level: process.env.LOG_LEVEL ?? "info" });
289
+ }
290
+ `);
291
+ }
292
+ };
293
+ //#endregion
294
+ //#region src/addons/prisma/index.ts
295
+ const PRISMA_VERSION = "^7.10.0";
296
+ function prismaPackage(name) {
297
+ return `${name}@${PRISMA_VERSION}`;
298
+ }
299
+ function prismaProvider(driver) {
300
+ switch (driver) {
301
+ case "postgres": return "postgresql";
302
+ case "mysql": return "mysql";
303
+ default: return "sqlite";
304
+ }
305
+ }
306
+ function envExample(driver) {
307
+ switch (driver) {
308
+ case "postgres": return "DATABASE_URL=postgresql://user:password@localhost:5432/mydb\n";
309
+ case "mysql": return "DATABASE_URL=mysql://user:password@localhost:3306/mydb\n";
310
+ default: return "DATABASE_URL=file:./local.db\n";
311
+ }
312
+ }
313
+ function driverPackages(driver) {
314
+ switch (driver) {
315
+ case "postgres": return [prismaPackage("@prisma/adapter-pg"), "pg"];
316
+ case "mysql": return [prismaPackage("@prisma/adapter-mariadb"), "mariadb"];
317
+ default: return [prismaPackage("@prisma/adapter-better-sqlite3"), "better-sqlite3"];
318
+ }
319
+ }
320
+ function driverDevPackages(driver) {
321
+ switch (driver) {
322
+ case "postgres": return ["@types/pg"];
323
+ case "sqlite": return ["@types/better-sqlite3"];
324
+ default: return [];
325
+ }
326
+ }
327
+ function dbIndexSource(driver) {
328
+ switch (driver) {
329
+ case "postgres": return `import { PrismaPg } from "@prisma/adapter-pg";
330
+ import { PrismaClient } from "./prisma/client.js";
331
+
332
+ export function createDb() {
333
+ const adapter = new PrismaPg({
334
+ connectionString: process.env.DATABASE_URL,
335
+ });
336
+ return new PrismaClient({ adapter });
337
+ }
338
+ `;
339
+ case "mysql": return `import { PrismaMariaDb } from "@prisma/adapter-mariadb";
340
+ import { PrismaClient } from "./prisma/client.js";
341
+
342
+ export function createDb() {
343
+ const adapter = new PrismaMariaDb(process.env.DATABASE_URL ?? "mariadb://root:@localhost:3306/mydb");
344
+ return new PrismaClient({ adapter });
345
+ }
346
+ `;
347
+ default: return `import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
348
+ import { PrismaClient } from "./prisma/client.js";
349
+
350
+ export function createDb() {
351
+ const adapter = new PrismaBetterSqlite3({
352
+ url: process.env.DATABASE_URL ?? "file:./local.db",
353
+ });
354
+ return new PrismaClient({ adapter });
355
+ }
356
+ `;
357
+ }
358
+ }
359
+ function prismaConfigSource() {
360
+ return `import "dotenv/config";
361
+ import { defineConfig, env } from "prisma/config";
362
+
363
+ export default defineConfig({
364
+ schema: "prisma/schema.prisma",
365
+ datasource: {
366
+ url: env("DATABASE_URL"),
367
+ },
368
+ });
369
+ `;
370
+ }
371
+ function schemaSource(driver) {
372
+ return `generator client {
373
+ provider = "prisma-client"
374
+ output = "../src/db/prisma"
375
+ }
376
+
377
+ datasource db {
378
+ provider = "${prismaProvider(driver)}"
379
+ }
380
+
381
+ model User {
382
+ id Int @id @default(autoincrement())
383
+ email String
384
+ }
385
+ `;
386
+ }
387
+ const prismaAddon = {
388
+ id: "prisma",
389
+ category: "database",
390
+ dependencies(ctx) {
391
+ const driver = ctx.driver ?? "sqlite";
392
+ return [prismaPackage("@prisma/client"), ...driverPackages(driver)];
393
+ },
394
+ devDependencies(ctx) {
395
+ const driver = ctx.driver ?? "sqlite";
396
+ return [prismaPackage("prisma"), ...driverDevPackages(driver)];
397
+ },
398
+ scripts() {
399
+ return {
400
+ "db:generate": "prisma generate",
401
+ "db:push": "prisma db push"
402
+ };
403
+ },
404
+ bootBinding() {
405
+ return {
406
+ key: "db",
407
+ importPath: "./db/index.js",
408
+ factoryName: "createDb"
409
+ };
410
+ },
411
+ async apply(ctx, write) {
412
+ const driver = ctx.driver ?? "sqlite";
413
+ await write("prisma.config.ts", prismaConfigSource());
414
+ await write("prisma/schema.prisma", schemaSource(driver));
415
+ await write("src/db/index.ts", dbIndexSource(driver));
416
+ await write(".env.example", envExample(driver));
417
+ }
418
+ };
419
+ //#endregion
420
+ //#region src/addons/validators.ts
421
+ const IMPORT_LINES = {
422
+ zod: `import { z } from "zod";`,
423
+ arktype: `import { type } from "arktype";`,
424
+ valibot: `import * as v from "valibot";`
425
+ };
426
+ const QUERY_SCHEMA_EXPR = {
427
+ zod: `z.object({ name: z.string().default("Taser.js") })`,
428
+ arktype: `type({ "name?": 'string = "Taser.js"' })`,
429
+ valibot: `v.object({ name: v.optional(v.string(), "Taser.js") })`
430
+ };
431
+ const ValidatorAddon = (validator) => {
432
+ return {
433
+ id: validator,
434
+ category: "validator",
435
+ dependencies: () => [validator],
436
+ devDependencies: () => [],
437
+ apply: async (_ctx, write) => {
438
+ await write("src/routes/index.get.ts", `import { t } from "@taserjs/router";
439
+ ${IMPORT_LINES[validator]}
440
+
441
+ export default t
442
+ .get("/")
443
+ .query(${QUERY_SCHEMA_EXPR[validator]})
444
+ .handler(({ req }) => {
445
+ return Response.json({ message: \`Hello, \${req.query.name}!\` });
446
+ });
447
+ `);
448
+ }
449
+ };
450
+ };
451
+ //#endregion
452
+ //#region src/addons/registry.ts
453
+ const ADDONS = {
454
+ drizzle: drizzleAddon,
455
+ prisma: prismaAddon,
456
+ kysely: kyselyAddon,
457
+ pino: pinoAddon,
458
+ winston: {
459
+ id: "winston",
460
+ category: "logger",
461
+ dependencies() {
462
+ return ["winston"];
463
+ },
464
+ devDependencies() {
465
+ return [];
466
+ },
467
+ bootBinding() {
468
+ return {
469
+ key: "logger",
470
+ importPath: "./logger.js",
471
+ factoryName: "createLogger"
472
+ };
473
+ },
474
+ async apply(_ctx, write) {
475
+ await write("src/logger.ts", `import winston from "winston";
476
+
477
+ export function createLogger() {
478
+ return winston.createLogger({
479
+ level: process.env.LOG_LEVEL ?? "info",
480
+ format: winston.format.json(),
481
+ transports: [new winston.transports.Console()],
482
+ });
483
+ }
484
+ `);
485
+ }
486
+ },
487
+ zod: ValidatorAddon("zod"),
488
+ arktype: ValidatorAddon("arktype"),
489
+ valibot: ValidatorAddon("valibot")
490
+ };
491
+ function resolveAddons(ctx) {
492
+ const result = [];
493
+ if (ctx.db && ADDONS[ctx.db]) {
494
+ const addon = ADDONS[ctx.db];
495
+ if (addon) result.push(addon);
496
+ }
497
+ if (ctx.logger && ADDONS[ctx.logger]) {
498
+ const addon = ADDONS[ctx.logger];
499
+ if (addon) result.push(addon);
500
+ }
501
+ if (ctx.validator && ADDONS[ctx.validator]) {
502
+ const addon = ADDONS[ctx.validator];
503
+ if (addon) result.push(addon);
504
+ }
505
+ return result;
506
+ }
507
+ function collectBootBindings(ctx) {
508
+ const addons = resolveAddons(ctx);
509
+ const bindings = [];
510
+ for (const addon of addons) if (addon.bootBinding) {
511
+ const binding = addon.bootBinding(ctx);
512
+ if (binding) bindings.push(binding);
513
+ }
514
+ return bindings;
515
+ }
516
+ //#endregion
517
+ //#region src/core/package-manager.ts
518
+ function resolveUserAgent() {
519
+ return getUserAgent() || "pnpm";
520
+ }
521
+ function runScript(agent, script) {
522
+ switch (agent) {
523
+ case "npm": return `npm run ${script}`;
524
+ case "yarn": return `yarn ${script}`;
525
+ case "bun": return `bun run ${script}`;
526
+ default: return `pnpm ${script}`;
527
+ }
528
+ }
529
+ async function installPackages(agent, cwd, packages) {
530
+ if (packages.dependencies.length > 0) {
531
+ const cmd = resolveCommand(agent, "add", packages.dependencies);
532
+ if (cmd) execSync(`${cmd.command} ${cmd.args.join(" ")}`, {
533
+ cwd,
534
+ stdio: "ignore"
535
+ });
536
+ }
537
+ if (packages.devDependencies.length > 0) {
538
+ const cmd = resolveCommand(agent, "add", [...agent === "npm" ? ["--save-dev"] : ["-D"], ...packages.devDependencies]);
539
+ if (cmd) execSync(`${cmd.command} ${cmd.args.join(" ")}`, {
540
+ cwd,
541
+ stdio: "ignore"
542
+ });
543
+ }
544
+ }
545
+ //#endregion
546
+ //#region src/core/targets.ts
547
+ const NITRO_NODE_START = "node .output/server/index.mjs";
548
+ const DEPLOY_ENTRIES = {
549
+ none: {
550
+ id: "none",
551
+ impliedRuntime: "node",
552
+ selfHosted: true,
553
+ startScript: "node dist/serve.mjs",
554
+ devDeps: ["srvx"],
555
+ files: []
556
+ },
557
+ "node-server": {
558
+ id: "node-server",
559
+ impliedRuntime: "node",
560
+ selfHosted: true,
561
+ startScript: NITRO_NODE_START,
562
+ devDeps: ["nitro"],
563
+ files: []
564
+ },
565
+ "node-cluster": {
566
+ id: "node-cluster",
567
+ impliedRuntime: "node",
568
+ selfHosted: true,
569
+ startScript: NITRO_NODE_START,
570
+ devDeps: ["nitro"],
571
+ files: []
572
+ },
573
+ bun: {
574
+ id: "bun",
575
+ impliedRuntime: "bun",
576
+ selfHosted: true,
577
+ startScript: "bun .output/server/index.mjs",
578
+ devDeps: ["nitro", "@types/bun"],
579
+ files: []
580
+ },
581
+ "deno-server": {
582
+ id: "deno-server",
583
+ impliedRuntime: "deno",
584
+ selfHosted: true,
585
+ startScript: "deno run -A .output/server/index.mjs",
586
+ devDeps: ["nitro"],
587
+ files: []
588
+ },
589
+ "deno-deploy": {
590
+ id: "deno-deploy",
591
+ impliedRuntime: "deno",
592
+ selfHosted: false,
593
+ startScript: null,
594
+ devDeps: ["nitro"],
595
+ files: []
596
+ },
597
+ "cloudflare-module": {
598
+ id: "cloudflare-module",
599
+ impliedRuntime: "workerd",
600
+ selfHosted: false,
601
+ startScript: null,
602
+ devDeps: [
603
+ "nitro",
604
+ "wrangler",
605
+ "@cloudflare/workers-types"
606
+ ],
607
+ files: [{
608
+ name: "wrangler.jsonc",
609
+ content: ({ projectName }) => `${JSON.stringify({
610
+ $schema: "node_modules/wrangler/config-schema.json",
611
+ name: projectName,
612
+ main: ".output/server/index.mjs",
613
+ compatibility_date: "2024-11-01"
614
+ }, null, 2)}\n`
615
+ }]
616
+ },
617
+ vercel: {
618
+ id: "vercel",
619
+ impliedRuntime: "node",
620
+ selfHosted: false,
621
+ startScript: null,
622
+ devDeps: ["nitro", "@vercel/node"],
623
+ files: []
624
+ },
625
+ "aws-lambda": {
626
+ id: "aws-lambda",
627
+ impliedRuntime: "node",
628
+ selfHosted: false,
629
+ startScript: null,
630
+ devDeps: ["nitro", "@types/aws-lambda"],
631
+ files: []
632
+ },
633
+ netlify: {
634
+ id: "netlify",
635
+ impliedRuntime: "node",
636
+ selfHosted: false,
637
+ startScript: null,
638
+ devDeps: ["nitro"],
639
+ files: []
640
+ }
641
+ };
642
+ const RUNTIME_OVERRIDES = {
643
+ none: ["node", "bun"],
644
+ "node-server": ["node", "bun"],
645
+ "node-cluster": ["node", "bun"]
646
+ };
647
+ const DEFAULT_DEPLOY = "none";
648
+ function isCuratedDeploy(value) {
649
+ return DEPLOY_TARGETS.includes(value);
650
+ }
651
+ function resolveDeployEntry(id) {
652
+ if (isCuratedDeploy(id)) return {
653
+ entry: DEPLOY_ENTRIES[id],
654
+ curated: true
655
+ };
656
+ return {
657
+ entry: {
658
+ id,
659
+ impliedRuntime: "node",
660
+ selfHosted: false,
661
+ startScript: null,
662
+ devDeps: ["nitro"],
663
+ files: []
664
+ },
665
+ curated: false
666
+ };
667
+ }
668
+ function allowedRuntimeOverrides(id) {
669
+ return RUNTIME_OVERRIDES[id] ?? [];
670
+ }
671
+ function validateCombination(runtimeOverride, deploy) {
672
+ const { entry } = resolveDeployEntry(deploy);
673
+ if (runtimeOverride !== void 0) {
674
+ const allowed = entry.selfHosted ? allowedRuntimeOverrides(entry.id) : [];
675
+ if (!allowed.includes(runtimeOverride)) return {
676
+ ok: false,
677
+ reason: `Runtime "${runtimeOverride}" is not valid for deploy target "${entry.id}". ` + (allowed.length > 0 ? `Allowed overrides: ${allowed.join(", ")}.` : `It implies runtime "${String(entry.impliedRuntime)}".`)
678
+ };
679
+ }
680
+ return {
681
+ ok: true,
682
+ runtime: runtimeOverride ?? entry.impliedRuntime
683
+ };
684
+ }
685
+ //#endregion
686
+ //#region src/templates/base.ts
687
+ function packageJsonTemplate(projectName, scripts = {}) {
688
+ const pkg = {
689
+ name: projectName,
690
+ version: "0.0.1",
691
+ private: true,
692
+ type: "module",
693
+ scripts: {
694
+ dev: "vite",
695
+ build: "vite build",
696
+ start: "node dist/serve.mjs",
697
+ ...scripts
698
+ }
699
+ };
700
+ return `${JSON.stringify(pkg, null, 2)}\n`;
701
+ }
702
+ function tsconfigTemplate() {
703
+ return `${JSON.stringify({
704
+ compilerOptions: {
705
+ target: "ES2022",
706
+ module: "NodeNext",
707
+ moduleResolution: "NodeNext",
708
+ strict: true,
709
+ skipLibCheck: true,
710
+ esModuleInterop: true
711
+ },
712
+ include: [
713
+ "src/**/*",
714
+ "src/.taserjs/**/*",
715
+ "taserjs.config.ts",
716
+ "vite.config.ts",
717
+ "nitro.config.ts"
718
+ ]
719
+ }, null, 2)}\n`;
720
+ }
721
+ function gitignoreTemplate() {
722
+ return `node_modules/
723
+ dist/
724
+ .output/
725
+ .taserjs/
726
+ .env
727
+ .env.*
728
+ !.env.example
729
+ *.log
730
+ local.db
731
+ drizzle/
732
+ `;
733
+ }
734
+ function taserConfigTemplate() {
735
+ return `import { defineConfig } from "@taserjs/cli";
736
+
737
+ export default defineConfig({
738
+ serverDir: "src",
739
+ routesDir: "routes",
740
+ outputDir: ".taserjs",
741
+ app: "taser.ts",
742
+ });
743
+ `;
744
+ }
745
+ function viteConfigTemplate(preset = "none") {
746
+ if (preset === "none") return `import { defineConfig } from "vite";
747
+ import { taser } from "@taserjs/plugin/vite";
748
+
749
+ export default defineConfig({
750
+ plugins: [taser()],
751
+ });
752
+ `;
753
+ return `import { defineConfig } from "vite";
754
+ import { nitro } from "nitro/vite";
755
+ import { taser } from "@taserjs/plugin/vite";
756
+
757
+ export default defineConfig({
758
+ plugins: [taser(), nitro()],
759
+ });
760
+ `;
761
+ }
762
+ function nitroConfigTemplate(preset) {
763
+ return `import { defineConfig } from "nitro/config";
764
+ import { taser } from "@taserjs/plugin/nitro";
765
+
766
+ export default defineConfig({
767
+ preset: "${preset}",
768
+ modules: [taser({ standalone: true })],
769
+ });
770
+ `;
771
+ }
772
+ function contextTemplate(bindings) {
773
+ const imports = bindings.map((b) => `import { ${b.factoryName} } from "${b.importPath}";`);
774
+ const bootBody = bindings.length > 0 ? bindings.map((b) => ` ${b.key}: ${b.factoryName}(),`).join("\n") : "";
775
+ const bootBlock = bindings.length > 0 ? ` boot: () => ({\n${bootBody}\n }),\n` : "";
776
+ return `${imports.length > 0 ? `${imports.join("\n")}\n\n` : ""}import { createContext } from "@taserjs/router";
777
+
778
+ export const context = createContext({
779
+ ${bootBlock} request: () => ({
780
+ requestId: crypto.randomUUID(),
781
+ }),
782
+ });
783
+ `;
784
+ }
785
+ function taserTsTemplate() {
786
+ return `import { defineTaser } from "@taserjs/router";
787
+ import { context } from "./context.js";
788
+
789
+ export default defineTaser().context(context);
790
+ `;
791
+ }
792
+ function rootLayoutTemplate() {
793
+ return `import { t } from "@taserjs/router";
794
+
795
+ export default t.layout("/*").use(async (_args, next) => {
796
+ return await next();
797
+ });
798
+ `;
799
+ }
800
+ function indexRouteTemplate() {
801
+ return `import { t } from "@taserjs/router";
802
+
803
+ export default t.get("/").handler(() => {
804
+ return Response.json({ message: "Welcome to Taser.js!" });
805
+ });
806
+ `;
807
+ }
808
+ function staticRoutesGenTemplate() {
809
+ return `// @ts-nocheck
810
+ import { createTaserApp } from "@taserjs/runtime";
811
+ import taser from "../taser.js";
812
+ import layout_0 from "../routes/$.js";
813
+ import route_0 from "../routes/index.get.js";
814
+
815
+ export type LayoutTree = {
816
+ "/*": typeof layout_0;
817
+ };
818
+
819
+ export const layoutManifest = {
820
+ "/*": layout_0,
821
+ } as const;
822
+
823
+ export const routeManifest = {
824
+ layouts: layoutManifest,
825
+ routes: {
826
+ "/": {
827
+ GET: {
828
+ layouts: ["/*"],
829
+ route: route_0,
830
+ },
831
+ },
832
+ },
833
+ } as const;
834
+
835
+ export type RouteManifest = typeof routeManifest;
836
+
837
+ export const app = createTaserApp(routeManifest, taser);
838
+ export default app;
839
+ export const createApp = (overrideTaser?: typeof taser) =>
840
+ createTaserApp(routeManifest, overrideTaser ?? taser);
841
+
842
+ export type RoutePath = "/";
843
+
844
+ export type LayoutHierarchy = {
845
+ "/*": readonly [];
846
+ };
847
+
848
+ export type RouteByPathMethod = {
849
+ "/": {
850
+ GET: {
851
+ layouts: readonly ["/*"];
852
+ };
853
+ };
854
+ };
855
+
856
+ export type AppContext = typeof taser.$Infer.Context;
857
+
858
+ declare module "@taserjs/router" {
859
+ interface RouterRegister {
860
+ RoutePath: RoutePath;
861
+ LayoutTree: LayoutTree;
862
+ LayoutHierarchy: LayoutHierarchy;
863
+ RouteByPathMethod: RouteByPathMethod;
864
+ AppContext: AppContext;
865
+ }
866
+ }
867
+ `;
868
+ }
869
+ //#endregion
870
+ //#region src/core/scaffold-engine.ts
871
+ async function write(filePath, contents) {
872
+ await mkdir(dirname(filePath), { recursive: true });
873
+ await writeFile(filePath, contents.trimStart(), "utf-8");
874
+ }
875
+ async function scaffoldProject(options) {
876
+ const root = options.targetDir;
877
+ const preset = options.preset ?? "none";
878
+ const combination = validateCombination(options.runtime, preset);
879
+ if (!combination.ok) throw new Error(combination.reason);
880
+ const writtenFiles = [];
881
+ const trackedWrite = async (relPath, contents) => {
882
+ await write(join(root, relPath), contents);
883
+ writtenFiles.push(relPath);
884
+ };
885
+ const addons = resolveAddons(options);
886
+ const bootBindings = collectBootBindings(options);
887
+ const { entry: deployEntry } = resolveDeployEntry(preset);
888
+ const scripts = {};
889
+ if (deployEntry.startScript) scripts.start = deployEntry.startScript;
890
+ const dependencies = ["@taserjs/router", "@taserjs/runtime"];
891
+ const devDependencies = [
892
+ "@taserjs/cli",
893
+ "@taserjs/plugin",
894
+ "typescript",
895
+ "vite"
896
+ ];
897
+ for (const dep of deployEntry.devDeps) devDependencies.push(dep);
898
+ for (const addon of addons) {
899
+ dependencies.push(...addon.dependencies(options));
900
+ devDependencies.push(...addon.devDependencies(options));
901
+ if (addon.scripts) Object.assign(scripts, addon.scripts(options));
902
+ }
903
+ const formatDep = (pkg) => {
904
+ const ver = options.packageVersions?.[pkg];
905
+ return ver ? `${pkg}@${ver}` : pkg;
906
+ };
907
+ const resolvedDeps = [...new Set(dependencies)].map(formatDep);
908
+ const resolvedDevDeps = [...new Set(devDependencies)].map(formatDep);
909
+ await trackedWrite("package.json", packageJsonTemplate(options.projectName, scripts));
910
+ await trackedWrite("tsconfig.json", tsconfigTemplate());
911
+ await trackedWrite(".gitignore", gitignoreTemplate());
912
+ await trackedWrite("taserjs.config.ts", taserConfigTemplate());
913
+ await trackedWrite("vite.config.ts", viteConfigTemplate(preset));
914
+ if (preset !== "none") await trackedWrite("nitro.config.ts", nitroConfigTemplate(preset));
915
+ await Promise.all(deployEntry.files.map(async (file) => {
916
+ const content = typeof file.content === "function" ? file.content({ projectName: options.projectName }) : file.content;
917
+ await trackedWrite(file.name, content);
918
+ }));
919
+ await trackedWrite("src/context.ts", contextTemplate(bootBindings));
920
+ await trackedWrite("src/taser.ts", taserTsTemplate());
921
+ await trackedWrite("src/routes/index.get.ts", indexRouteTemplate());
922
+ await trackedWrite("src/routes/$.ts", rootLayoutTemplate());
923
+ await Promise.all(addons.map(async (addon) => {
924
+ await addon.apply(options, async (relPath, contents) => {
925
+ await trackedWrite(relPath, contents);
926
+ });
927
+ }));
928
+ await trackedWrite("src/.taserjs/routes.gen.ts", staticRoutesGenTemplate());
929
+ if (!options.skipInstall) await installPackages(options.agent ?? resolveUserAgent(), root, {
930
+ dependencies: resolvedDeps,
931
+ devDependencies: resolvedDevDeps
932
+ });
933
+ return {
934
+ ...options,
935
+ files: writtenFiles
936
+ };
937
+ }
938
+ //#endregion
939
+ //#region src/commands/create.ts
940
+ const DEPLOY_LABELS = {
941
+ none: "None (Standalone Vite SSR)",
942
+ "node-server": "Node.js server (Nitro)",
943
+ "node-cluster": "Node.js cluster (Nitro)",
944
+ bun: "Bun (Nitro)",
945
+ "deno-server": "Deno (Nitro)",
946
+ "deno-deploy": "Deno Deploy (Nitro)",
947
+ "cloudflare-module": "Cloudflare Workers (Nitro)",
948
+ vercel: "Vercel (Nitro)",
949
+ "aws-lambda": "AWS Lambda (Nitro)",
950
+ netlify: "Netlify (Nitro)"
951
+ };
952
+ async function promptInteractiveOptions(defaults) {
953
+ const projectName = defaults.projectName ?? await p.text({
954
+ message: "Project name",
955
+ placeholder: "my-taser-app",
956
+ defaultValue: "my-taser-app",
957
+ validate(value) {
958
+ if (!value || value.trim().length === 0) return "Project name cannot be empty";
959
+ if (/[^a-zA-Z0-9_-]/.test(value)) return "Project name contains invalid characters";
960
+ }
961
+ });
962
+ if (p.isCancel(projectName)) {
963
+ p.cancel("Scaffold cancelled.");
964
+ process.exit(0);
965
+ }
966
+ const preset = defaults.preset ?? await p.select({
967
+ message: "Deployment target",
968
+ options: DEPLOY_TARGETS.map((id) => ({
969
+ value: id,
970
+ label: DEPLOY_LABELS[id]
971
+ })),
972
+ initialValue: "none"
973
+ });
974
+ if (p.isCancel(preset)) {
975
+ p.cancel("Scaffold cancelled.");
976
+ process.exit(0);
977
+ }
978
+ let runtime;
979
+ const runtimeOverrides = allowedRuntimeOverrides(preset);
980
+ if (runtimeOverrides.length > 0) {
981
+ const runtimeChoice = defaults.runtime ?? await p.select({
982
+ message: "Runtime override",
983
+ options: [...runtimeOverrides.map((rt) => ({
984
+ value: rt,
985
+ label: rt
986
+ })), {
987
+ value: "default",
988
+ label: "Preset default",
989
+ hint: "no override"
990
+ }],
991
+ initialValue: "default"
992
+ });
993
+ if (p.isCancel(runtimeChoice)) {
994
+ p.cancel("Scaffold cancelled.");
995
+ process.exit(0);
996
+ }
997
+ runtime = runtimeChoice === "default" ? void 0 : runtimeChoice;
998
+ }
999
+ const validatorChoice = defaults.validator ?? await p.select({
1000
+ message: "Standard Schema Validator",
1001
+ options: [
1002
+ {
1003
+ value: "none",
1004
+ label: "None",
1005
+ hint: "default"
1006
+ },
1007
+ {
1008
+ value: "zod",
1009
+ label: "Zod"
1010
+ },
1011
+ {
1012
+ value: "valibot",
1013
+ label: "Valibot"
1014
+ },
1015
+ {
1016
+ value: "arktype",
1017
+ label: "Arktype"
1018
+ }
1019
+ ],
1020
+ initialValue: "none"
1021
+ });
1022
+ if (p.isCancel(validatorChoice)) {
1023
+ p.cancel("Scaffold cancelled.");
1024
+ process.exit(0);
1025
+ }
1026
+ const validator = validatorChoice === "none" ? void 0 : validatorChoice;
1027
+ const dbChoice = defaults.db ?? await p.select({
1028
+ message: "Database ORM / Query Builder",
1029
+ options: [
1030
+ {
1031
+ value: "none",
1032
+ label: "None",
1033
+ hint: "default"
1034
+ },
1035
+ {
1036
+ value: "drizzle",
1037
+ label: "Drizzle"
1038
+ },
1039
+ {
1040
+ value: "prisma",
1041
+ label: "Prisma"
1042
+ },
1043
+ {
1044
+ value: "kysely",
1045
+ label: "Kysely"
1046
+ }
1047
+ ],
1048
+ initialValue: "none"
1049
+ });
1050
+ if (p.isCancel(dbChoice)) {
1051
+ p.cancel("Scaffold cancelled.");
1052
+ process.exit(0);
1053
+ }
1054
+ let db;
1055
+ let driver;
1056
+ if (dbChoice !== "none") {
1057
+ db = dbChoice;
1058
+ const driverChoice = defaults.driver ?? await p.select({
1059
+ message: "Database driver",
1060
+ options: [
1061
+ {
1062
+ value: "sqlite",
1063
+ label: "SQLite",
1064
+ hint: "default"
1065
+ },
1066
+ {
1067
+ value: "postgres",
1068
+ label: "PostgreSQL"
1069
+ },
1070
+ {
1071
+ value: "mysql",
1072
+ label: "MySQL"
1073
+ }
1074
+ ],
1075
+ initialValue: "sqlite"
1076
+ });
1077
+ if (p.isCancel(driverChoice)) {
1078
+ p.cancel("Scaffold cancelled.");
1079
+ process.exit(0);
1080
+ }
1081
+ driver = driverChoice;
1082
+ }
1083
+ const loggerChoice = defaults.logger ?? await p.select({
1084
+ message: "Logger",
1085
+ options: [
1086
+ {
1087
+ value: "none",
1088
+ label: "None",
1089
+ hint: "default"
1090
+ },
1091
+ {
1092
+ value: "pino",
1093
+ label: "Pino"
1094
+ },
1095
+ {
1096
+ value: "winston",
1097
+ label: "Winston"
1098
+ }
1099
+ ],
1100
+ initialValue: "none"
1101
+ });
1102
+ if (p.isCancel(loggerChoice)) {
1103
+ p.cancel("Scaffold cancelled.");
1104
+ process.exit(0);
1105
+ }
1106
+ const logger = loggerChoice === "none" ? void 0 : loggerChoice;
1107
+ return {
1108
+ projectName: String(projectName).trim(),
1109
+ preset,
1110
+ ...runtime ? { runtime } : {},
1111
+ ...validator ? { validator } : {},
1112
+ ...db ? {
1113
+ db,
1114
+ driver
1115
+ } : {},
1116
+ ...logger ? { logger } : {},
1117
+ skipInstall: defaults.skipInstall
1118
+ };
1119
+ }
1120
+ async function runCreateCommand(args = {}) {
1121
+ const isInteractive = args.interactive ?? (Boolean(process.stdout.isTTY) && process.env.NODE_ENV !== "test");
1122
+ const resolved = isInteractive ? await promptInteractiveOptions(args) : {
1123
+ ...args,
1124
+ projectName: args.projectName ?? "my-taser-app",
1125
+ preset: args.preset ?? "none"
1126
+ };
1127
+ const cwd = process.cwd();
1128
+ const projectName = resolved.projectName || "my-taser-app";
1129
+ const targetDir = args.targetDir ? path.resolve(cwd, args.targetDir) : path.resolve(cwd, projectName);
1130
+ const scaffoldOpts = {
1131
+ projectName,
1132
+ targetDir,
1133
+ ...resolved.preset !== void 0 ? { preset: resolved.preset } : {},
1134
+ ...resolved.runtime !== void 0 ? { runtime: resolved.runtime } : {},
1135
+ ...resolved.validator !== void 0 ? { validator: resolved.validator } : {},
1136
+ ...resolved.db !== void 0 ? { db: resolved.db } : {},
1137
+ ...resolved.driver !== void 0 ? { driver: resolved.driver } : {},
1138
+ ...resolved.logger !== void 0 ? { logger: resolved.logger } : {},
1139
+ ...args.packageVersions !== void 0 ? { packageVersions: args.packageVersions } : {},
1140
+ skipInstall: resolved.skipInstall ?? process.env.NODE_ENV === "test"
1141
+ };
1142
+ if (isInteractive) {
1143
+ const s = p.spinner();
1144
+ s.start("Scaffolding project");
1145
+ const result = await scaffoldProject(scaffoldOpts);
1146
+ s.stop("Project created");
1147
+ const agent = resolveUserAgent();
1148
+ p.outro(pc.green("Done!"));
1149
+ console.log(`\nNext steps:`);
1150
+ console.log(` cd ${path.relative(cwd, targetDir) || "."}`);
1151
+ if (scaffoldOpts.skipInstall) console.log(` ${runScript(agent, "install")}`);
1152
+ console.log(` ${runScript(agent, "dev")}\n`);
1153
+ return result;
1154
+ }
1155
+ return await scaffoldProject(scaffoldOpts);
1156
+ }
1157
+ //#endregion
1158
+ //#region src/cli.ts
1159
+ async function run(argv = hideBin(process.argv)) {
1160
+ await yargs(argv).scriptName("create-taserjs").usage("$0 [dir] [options]").command("$0 [dir]", "Scaffold a new Taser.js application", (y) => y.positional("dir", {
1161
+ type: "string",
1162
+ description: "Directory or project name"
1163
+ }).option("preset", {
1164
+ alias: "p",
1165
+ type: "string",
1166
+ description: "Deployment preset"
1167
+ }).option("runtime", {
1168
+ type: "string",
1169
+ description: "Runtime override (node, bun, deno)"
1170
+ }).option("validator", {
1171
+ alias: "v",
1172
+ type: "string",
1173
+ choices: [
1174
+ "zod",
1175
+ "valibot",
1176
+ "arktype",
1177
+ "none"
1178
+ ],
1179
+ description: "Standard Schema validator"
1180
+ }).option("db", {
1181
+ type: "string",
1182
+ choices: [
1183
+ "drizzle",
1184
+ "prisma",
1185
+ "kysely",
1186
+ "none"
1187
+ ],
1188
+ description: "Database ORM / Query builder"
1189
+ }).option("driver", {
1190
+ type: "string",
1191
+ choices: [
1192
+ "sqlite",
1193
+ "postgres",
1194
+ "mysql"
1195
+ ],
1196
+ description: "Database driver"
1197
+ }).option("logger", {
1198
+ alias: "l",
1199
+ type: "string",
1200
+ choices: [
1201
+ "pino",
1202
+ "winston",
1203
+ "none"
1204
+ ],
1205
+ description: "Logger addon"
1206
+ }).option("skip-install", {
1207
+ type: "boolean",
1208
+ description: "Skip dependency installation",
1209
+ default: false
1210
+ }).option("yes", {
1211
+ alias: "y",
1212
+ type: "boolean",
1213
+ description: "Skip prompts and use defaults",
1214
+ default: false
1215
+ }), async (args) => {
1216
+ await runCreateCommand({
1217
+ targetDir: args.dir,
1218
+ projectName: args.dir,
1219
+ preset: args.preset,
1220
+ runtime: args.runtime,
1221
+ validator: args.validator === "none" ? void 0 : args.validator,
1222
+ db: args.db === "none" ? void 0 : args.db,
1223
+ driver: args.driver,
1224
+ logger: args.logger === "none" ? void 0 : args.logger,
1225
+ skipInstall: Boolean(args.skipInstall),
1226
+ interactive: !args.yes
1227
+ });
1228
+ }).help().alias("help", "h").version().alias("version", "V").strict().exitProcess(false).parse();
1229
+ }
1230
+ if (process.argv[1] && process.argv[1].endsWith("cli.js")) run().catch((err) => {
1231
+ console.error(err instanceof Error ? err.message : String(err));
1232
+ process.exit(1);
1233
+ });
1234
+ //#endregion
1235
+ export { VALIDATORS as C, RUNTIMES as S, DB_DRIVERS as _, DEFAULT_DEPLOY as a, DEPLOY_TARGETS as b, isCuratedDeploy as c, installPackages as d, resolveUserAgent as f, resolveAddons as g, collectBootBindings as h, scaffoldProject as i, resolveDeployEntry as l, ADDONS as m, promptInteractiveOptions as n, DEPLOY_ENTRIES as o, runScript as p, runCreateCommand as r, allowedRuntimeOverrides as s, run as t, validateCombination as u, DB_ODMS as v, LOGGERS as x, DEFAULT_DB_DRIVER as y };
1236
+
1237
+ //# sourceMappingURL=cli-9fkoNOJg.js.map