create-taserjs 0.0.4 → 0.0.6

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 (33) hide show
  1. package/dist/cjs/addons/registry.cjs +0 -3
  2. package/dist/cjs/addons/registry.cjs.map +1 -1
  3. package/dist/cjs/addons/validators.cjs +7 -4
  4. package/dist/cjs/addons/validators.cjs.map +1 -1
  5. package/dist/cjs/core/resolve-packages.cjs +1 -1
  6. package/dist/cjs/core/resolve-packages.cjs.map +1 -1
  7. package/dist/cjs/core/scaffold-engine.cjs +2 -22
  8. package/dist/cjs/core/scaffold-engine.cjs.map +1 -1
  9. package/dist/cjs/frameworks/index.cjs +7 -26
  10. package/dist/cjs/frameworks/index.cjs.map +1 -1
  11. package/dist/cjs/frameworks/index.d.cts +1 -1
  12. package/dist/cjs/templates/base.cjs +10 -6
  13. package/dist/cjs/templates/base.cjs.map +1 -1
  14. package/dist/esm/addons/registry.js +0 -3
  15. package/dist/esm/addons/registry.js.map +1 -1
  16. package/dist/esm/addons/validators.js +7 -4
  17. package/dist/esm/addons/validators.js.map +1 -1
  18. package/dist/esm/core/resolve-packages.js +1 -1
  19. package/dist/esm/core/resolve-packages.js.map +1 -1
  20. package/dist/esm/core/scaffold-engine.js +2 -22
  21. package/dist/esm/core/scaffold-engine.js.map +1 -1
  22. package/dist/esm/frameworks/index.d.ts +1 -1
  23. package/dist/esm/frameworks/index.js +7 -26
  24. package/dist/esm/frameworks/index.js.map +1 -1
  25. package/dist/esm/templates/base.js +10 -6
  26. package/dist/esm/templates/base.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/addons/registry.ts +0 -15
  29. package/src/addons/validators.ts +7 -4
  30. package/src/core/resolve-packages.ts +1 -1
  31. package/src/core/scaffold-engine.ts +2 -16
  32. package/src/frameworks/index.ts +7 -35
  33. package/src/templates/base.ts +11 -7
@@ -45,14 +45,11 @@ function resolveAddons(ctx) {
45
45
  if (!loggerAddon) throw new Error(`Unknown logger addon "${ctx.logger}"`);
46
46
  selected.push(loggerAddon);
47
47
  }
48
- if (selected.filter((addon) => addon.category === "database").length > 1) throw new Error("Only one database addon can be selected");
49
- if (selected.filter((addon) => addon.category === "logger").length > 1) throw new Error("Only one logger addon can be selected");
50
48
  if (ctx.validator) {
51
49
  const validatorAddon = VALIDATOR_ADDONS.find((addon) => addon.id === ctx.validator);
52
50
  if (!validatorAddon) throw new Error(`Unknown validator addon "${ctx.validator}"`);
53
51
  selected.push(validatorAddon);
54
52
  }
55
- if (selected.filter((addon) => addon.category === "validator").length > 1) throw new Error("Only one validator addon can be selected");
56
53
  return selected;
57
54
  }
58
55
  function collectBootBindings(ctx) {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.cjs","names":[],"sources":["../../../src/addons/registry.ts"],"sourcesContent":["import { arktypeAddon } from \"./arktype/index.js\";\nimport { drizzleAddon } from \"./drizzle/index.js\";\nimport { kyselyAddon } from \"./kysely/index.js\";\nimport { pinoAddon } from \"./pino/index.js\";\nimport { prismaAddon } from \"./prisma/index.js\";\nimport { valibotAddon } from \"./valibot/index.js\";\nimport { winstonAddon } from \"./winston/index.js\";\nimport { zodAddon } from \"./zod/index.js\";\nimport type { AddonDefinition } from \"./types.js\";\nimport type { CapabilitiesCatalog, ScaffoldContext } from \"../core/types.js\";\nimport {\n DB_DRIVERS,\n DB_ODMS,\n DEFAULT_DB_DRIVER,\n LOGGERS,\n PROJECT_TYPES,\n VALIDATORS,\n} from \"../core/types.js\";\n\nconst ALL_ADDONS: AddonDefinition[] = [\n drizzleAddon,\n prismaAddon,\n kyselyAddon,\n pinoAddon,\n winstonAddon,\n zodAddon,\n arktypeAddon,\n valibotAddon,\n];\n\nconst DB_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"database\");\nconst LOGGER_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"logger\");\nconst VALIDATOR_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"validator\");\n\nexport function getCapabilitiesCatalog(): CapabilitiesCatalog {\n return {\n types: [...PROJECT_TYPES],\n db: {\n odms: [...DB_ODMS],\n drivers: [...DB_DRIVERS],\n defaultDriver: DEFAULT_DB_DRIVER,\n },\n loggers: [...LOGGERS],\n validators: [...VALIDATORS],\n };\n}\n\nexport function resolveAddons(ctx: ScaffoldContext): AddonDefinition[] {\n const selected: AddonDefinition[] = [];\n\n if (ctx.db) {\n const dbAddon = DB_ADDONS.find((addon) => addon.id === ctx.db);\n if (!dbAddon) {\n throw new Error(`Unknown database addon \"${ctx.db}\"`);\n }\n selected.push(dbAddon);\n }\n\n if (ctx.logger) {\n const loggerAddon = LOGGER_ADDONS.find((addon) => addon.id === ctx.logger);\n if (!loggerAddon) {\n throw new Error(`Unknown logger addon \"${ctx.logger}\"`);\n }\n selected.push(loggerAddon);\n }\n\n const dbCount = selected.filter((addon) => addon.category === \"database\").length;\n if (dbCount > 1) {\n throw new Error(\"Only one database addon can be selected\");\n }\n\n const loggerCount = selected.filter((addon) => addon.category === \"logger\").length;\n if (loggerCount > 1) {\n throw new Error(\"Only one logger addon can be selected\");\n }\n\n if (ctx.validator) {\n const validatorAddon = VALIDATOR_ADDONS.find((addon) => addon.id === ctx.validator);\n if (!validatorAddon) {\n throw new Error(`Unknown validator addon \"${ctx.validator}\"`);\n }\n selected.push(validatorAddon);\n }\n\n const validatorCount = selected.filter((addon) => addon.category === \"validator\").length;\n if (validatorCount > 1) {\n throw new Error(\"Only one validator addon can be selected\");\n }\n\n return selected;\n}\n\nexport function collectBootBindings(ctx: ScaffoldContext) {\n return resolveAddons(ctx)\n .map((addon) => addon.bootBinding?.(ctx))\n .filter((v): v is NonNullable<typeof v> => Boolean(v));\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAM,aAAgC;CACpC,gBAAA;CACA,gBAAA;CACA,gBAAA;CACA,gBAAA;CACA,gBAAA;CACA,gBAAA;CACA,cAAA;CACA,gBAAA;AACF;AAEA,IAAM,YAAY,WAAW,QAAQ,UAAU,MAAM,aAAa,UAAU;AAC5E,IAAM,gBAAgB,WAAW,QAAQ,UAAU,MAAM,aAAa,QAAQ;AAC9E,IAAM,mBAAmB,WAAW,QAAQ,UAAU,MAAM,aAAa,WAAW;AAEpF,SAAgB,yBAA8C;CAC5D,OAAO;EACL,OAAO,CAAC,GAAG,cAAA,aAAa;EACxB,IAAI;GACF,MAAM,CAAC,GAAG,cAAA,OAAO;GACjB,SAAS,CAAC,GAAG,cAAA,UAAU;GACvB,eAAe,cAAA;EACjB;EACA,SAAS,CAAC,GAAG,cAAA,OAAO;EACpB,YAAY,CAAC,GAAG,cAAA,UAAU;CAC5B;AACF;AAEA,SAAgB,cAAc,KAAyC;CACrE,MAAM,WAA8B,CAAC;CAErC,IAAI,IAAI,IAAI;EACV,MAAM,UAAU,UAAU,MAAM,UAAU,MAAM,OAAO,IAAI,EAAE;EAC7D,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,2BAA2B,IAAI,GAAG,EAAE;EAEtD,SAAS,KAAK,OAAO;CACvB;CAEA,IAAI,IAAI,QAAQ;EACd,MAAM,cAAc,cAAc,MAAM,UAAU,MAAM,OAAO,IAAI,MAAM;EACzE,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,yBAAyB,IAAI,OAAO,EAAE;EAExD,SAAS,KAAK,WAAW;CAC3B;CAGA,IADgB,SAAS,QAAQ,UAAU,MAAM,aAAa,UAAU,CAAC,CAAC,SAC5D,GACZ,MAAM,IAAI,MAAM,yCAAyC;CAI3D,IADoB,SAAS,QAAQ,UAAU,MAAM,aAAa,QAAQ,CAAC,CAAC,SAC1D,GAChB,MAAM,IAAI,MAAM,uCAAuC;CAGzD,IAAI,IAAI,WAAW;EACjB,MAAM,iBAAiB,iBAAiB,MAAM,UAAU,MAAM,OAAO,IAAI,SAAS;EAClF,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,4BAA4B,IAAI,UAAU,EAAE;EAE9D,SAAS,KAAK,cAAc;CAC9B;CAGA,IADuB,SAAS,QAAQ,UAAU,MAAM,aAAa,WAAW,CAAC,CAAC,SAC7D,GACnB,MAAM,IAAI,MAAM,0CAA0C;CAG5D,OAAO;AACT;AAEA,SAAgB,oBAAoB,KAAsB;CACxD,OAAO,cAAc,GAAG,CAAC,CACtB,KAAK,UAAU,MAAM,cAAc,GAAG,CAAC,CAAC,CACxC,QAAQ,MAAkC,QAAQ,CAAC,CAAC;AACzD"}
1
+ {"version":3,"file":"registry.cjs","names":[],"sources":["../../../src/addons/registry.ts"],"sourcesContent":["import { arktypeAddon } from \"./arktype/index.js\";\nimport { drizzleAddon } from \"./drizzle/index.js\";\nimport { kyselyAddon } from \"./kysely/index.js\";\nimport { pinoAddon } from \"./pino/index.js\";\nimport { prismaAddon } from \"./prisma/index.js\";\nimport { valibotAddon } from \"./valibot/index.js\";\nimport { winstonAddon } from \"./winston/index.js\";\nimport { zodAddon } from \"./zod/index.js\";\nimport type { AddonDefinition } from \"./types.js\";\nimport type { CapabilitiesCatalog, ScaffoldContext } from \"../core/types.js\";\nimport {\n DB_DRIVERS,\n DB_ODMS,\n DEFAULT_DB_DRIVER,\n LOGGERS,\n PROJECT_TYPES,\n VALIDATORS,\n} from \"../core/types.js\";\n\nconst ALL_ADDONS: AddonDefinition[] = [\n drizzleAddon,\n prismaAddon,\n kyselyAddon,\n pinoAddon,\n winstonAddon,\n zodAddon,\n arktypeAddon,\n valibotAddon,\n];\n\nconst DB_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"database\");\nconst LOGGER_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"logger\");\nconst VALIDATOR_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"validator\");\n\nexport function getCapabilitiesCatalog(): CapabilitiesCatalog {\n return {\n types: [...PROJECT_TYPES],\n db: {\n odms: [...DB_ODMS],\n drivers: [...DB_DRIVERS],\n defaultDriver: DEFAULT_DB_DRIVER,\n },\n loggers: [...LOGGERS],\n validators: [...VALIDATORS],\n };\n}\n\nexport function resolveAddons(ctx: ScaffoldContext): AddonDefinition[] {\n const selected: AddonDefinition[] = [];\n\n if (ctx.db) {\n const dbAddon = DB_ADDONS.find((addon) => addon.id === ctx.db);\n if (!dbAddon) {\n throw new Error(`Unknown database addon \"${ctx.db}\"`);\n }\n selected.push(dbAddon);\n }\n\n if (ctx.logger) {\n const loggerAddon = LOGGER_ADDONS.find((addon) => addon.id === ctx.logger);\n if (!loggerAddon) {\n throw new Error(`Unknown logger addon \"${ctx.logger}\"`);\n }\n selected.push(loggerAddon);\n }\n\n if (ctx.validator) {\n const validatorAddon = VALIDATOR_ADDONS.find((addon) => addon.id === ctx.validator);\n if (!validatorAddon) {\n throw new Error(`Unknown validator addon \"${ctx.validator}\"`);\n }\n selected.push(validatorAddon);\n }\n\n return selected;\n}\n\nexport function collectBootBindings(ctx: ScaffoldContext) {\n return resolveAddons(ctx)\n .map((addon) => addon.bootBinding?.(ctx))\n .filter((v): v is NonNullable<typeof v> => Boolean(v));\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAM,aAAgC;CACpC,gBAAA;CACA,gBAAA;CACA,gBAAA;CACA,gBAAA;CACA,gBAAA;CACA,gBAAA;CACA,cAAA;CACA,gBAAA;AACF;AAEA,IAAM,YAAY,WAAW,QAAQ,UAAU,MAAM,aAAa,UAAU;AAC5E,IAAM,gBAAgB,WAAW,QAAQ,UAAU,MAAM,aAAa,QAAQ;AAC9E,IAAM,mBAAmB,WAAW,QAAQ,UAAU,MAAM,aAAa,WAAW;AAEpF,SAAgB,yBAA8C;CAC5D,OAAO;EACL,OAAO,CAAC,GAAG,cAAA,aAAa;EACxB,IAAI;GACF,MAAM,CAAC,GAAG,cAAA,OAAO;GACjB,SAAS,CAAC,GAAG,cAAA,UAAU;GACvB,eAAe,cAAA;EACjB;EACA,SAAS,CAAC,GAAG,cAAA,OAAO;EACpB,YAAY,CAAC,GAAG,cAAA,UAAU;CAC5B;AACF;AAEA,SAAgB,cAAc,KAAyC;CACrE,MAAM,WAA8B,CAAC;CAErC,IAAI,IAAI,IAAI;EACV,MAAM,UAAU,UAAU,MAAM,UAAU,MAAM,OAAO,IAAI,EAAE;EAC7D,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,2BAA2B,IAAI,GAAG,EAAE;EAEtD,SAAS,KAAK,OAAO;CACvB;CAEA,IAAI,IAAI,QAAQ;EACd,MAAM,cAAc,cAAc,MAAM,UAAU,MAAM,OAAO,IAAI,MAAM;EACzE,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,yBAAyB,IAAI,OAAO,EAAE;EAExD,SAAS,KAAK,WAAW;CAC3B;CAEA,IAAI,IAAI,WAAW;EACjB,MAAM,iBAAiB,iBAAiB,MAAM,UAAU,MAAM,OAAO,IAAI,SAAS;EAClF,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,4BAA4B,IAAI,UAAU,EAAE;EAE9D,SAAS,KAAK,cAAc;CAC9B;CAEA,OAAO;AACT;AAEA,SAAgB,oBAAoB,KAAsB;CACxD,OAAO,cAAc,GAAG,CAAC,CACtB,KAAK,UAAU,MAAM,cAAc,GAAG,CAAC,CAAC,CACxC,QAAQ,MAAkC,QAAQ,CAAC,CAAC;AACzD"}
@@ -6,20 +6,23 @@ var IMPORT_LINES = {
6
6
  };
7
7
  var VALIDATION_BLOCK_TEMPLATE = {
8
8
  zod: `, {
9
- query: z.object({ name: z.string() }),
9
+ query: z.object({ name: z.string().default('Taser') }),
10
10
  }`,
11
11
  arktype: `, {
12
- query: type({ name: 'string' }),
12
+ query: type({ 'name?': 'string = "Taser"' }),
13
13
  }`,
14
14
  valibot: `, {
15
- query: v.object({ name: v.string() }),
15
+ query: v.object({ name: v.optional(v.string(), 'Taser') }),
16
16
  }`
17
17
  };
18
18
  var ROUTE_TEMPLATE = (validator) => `import { reply } from '@taserjs/router'
19
19
  import { t } from '#src/taser.js'
20
20
  ${IMPORT_LINES[validator]}
21
21
 
22
- export const Route = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]}).handler((ctx) => {
22
+ const GET = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]})
23
+
24
+ export type RouteContext = typeof GET.$Infer.Context
25
+ export const Route = GET.handler((ctx) => {
23
26
  return reply.json({ message: \`Hello, \${ctx.query.name}!\` })
24
27
  })
25
28
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"validators.cjs","names":[],"sources":["../../../src/addons/validators.ts"],"sourcesContent":["import type { ValidatorId } from \"../core/types\";\nimport type { AddonDefinition } from \"./types\";\n\nexport const IMPORT_LINES: Record<ValidatorId, string> = {\n zod: `import { z } from 'zod'`,\n arktype: `import { type } from 'arktype'`,\n valibot: `import * as v from 'valibot'`,\n};\n\nexport const VALIDATION_BLOCK_TEMPLATE: Record<ValidatorId, string> = {\n zod: `, {\n query: z.object({ name: z.string() }),\n}`,\n arktype: `, {\n query: type({ name: 'string' }),\n}`,\n valibot: `, {\n query: v.object({ name: v.string() }),\n}`,\n};\n\nconst ROUTE_TEMPLATE = (validator: ValidatorId) => `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n${IMPORT_LINES[validator]}\n\nexport const Route = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]}).handler((ctx) => {\n return reply.json({ message: \\`Hello, \\${ctx.query.name}!\\` })\n})\n`;\n\nexport const ValidatorAddon = (validator: ValidatorId): AddonDefinition => {\n return {\n id: validator,\n category: \"validator\",\n dependencies: () => [validator],\n devDependencies: () => [],\n apply: (ctx, write) => write(\"src/routes/index.get.ts\", ROUTE_TEMPLATE(validator)),\n };\n};\n"],"mappings":";AAGA,IAAa,eAA4C;CACvD,KAAK;CACL,SAAS;CACT,SAAS;AACX;AAEA,IAAa,4BAAyD;CACpE,KAAK;;;CAGL,SAAS;;;CAGT,SAAS;;;AAGX;AAEA,IAAM,kBAAkB,cAA2B;;EAEjD,aAAa,WAAW;;gCAEM,0BAA0B,WAAW;;;;AAKrE,IAAa,kBAAkB,cAA4C;CACzE,OAAO;EACL,IAAI;EACJ,UAAU;EACV,oBAAoB,CAAC,SAAS;EAC9B,uBAAuB,CAAC;EACxB,QAAQ,KAAK,UAAU,MAAM,2BAA2B,eAAe,SAAS,CAAC;CACnF;AACF"}
1
+ {"version":3,"file":"validators.cjs","names":[],"sources":["../../../src/addons/validators.ts"],"sourcesContent":["import type { ValidatorId } from \"../core/types\";\nimport type { AddonDefinition } from \"./types\";\n\nexport const IMPORT_LINES: Record<ValidatorId, string> = {\n zod: `import { z } from 'zod'`,\n arktype: `import { type } from 'arktype'`,\n valibot: `import * as v from 'valibot'`,\n};\n\nexport const VALIDATION_BLOCK_TEMPLATE: Record<ValidatorId, string> = {\n zod: `, {\n query: z.object({ name: z.string().default('Taser') }),\n}`,\n arktype: `, {\n query: type({ 'name?': 'string = \"Taser\"' }),\n}`,\n valibot: `, {\n query: v.object({ name: v.optional(v.string(), 'Taser') }),\n}`,\n};\n\nconst ROUTE_TEMPLATE = (validator: ValidatorId) => `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n${IMPORT_LINES[validator]}\n\nconst GET = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]})\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler((ctx) => {\n return reply.json({ message: \\`Hello, \\${ctx.query.name}!\\` })\n})\n`;\n\nexport const ValidatorAddon = (validator: ValidatorId): AddonDefinition => {\n return {\n id: validator,\n category: \"validator\",\n dependencies: () => [validator],\n devDependencies: () => [],\n apply: (ctx, write) => write(\"src/routes/index.get.ts\", ROUTE_TEMPLATE(validator)),\n };\n};\n"],"mappings":";AAGA,IAAa,eAA4C;CACvD,KAAK;CACL,SAAS;CACT,SAAS;AACX;AAEA,IAAa,4BAAyD;CACpE,KAAK;;;CAGL,SAAS;;;CAGT,SAAS;;;AAGX;AAEA,IAAM,kBAAkB,cAA2B;;EAEjD,aAAa,WAAW;;uBAEH,0BAA0B,WAAW;;;;;;;AAQ5D,IAAa,kBAAkB,cAA4C;CACzE,OAAO;EACL,IAAI;EACJ,UAAU;EACV,oBAAoB,CAAC,SAAS;EAC9B,uBAAuB,CAAC;EACxB,QAAQ,KAAK,UAAU,MAAM,2BAA2B,eAAe,SAAS,CAAC;CACnF;AACF"}
@@ -7,7 +7,7 @@ function typePackages(type) {
7
7
  "npm-run-all2",
8
8
  "tsdown",
9
9
  "tsx",
10
- "typescript",
10
+ "typescript@^5.9.3",
11
11
  "@types/node"
12
12
  ];
13
13
  const scripts = {};
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-packages.cjs","names":[],"sources":["../../../src/core/resolve-packages.ts"],"sourcesContent":["import { resolveAddons } from \"../addons/registry.js\";\nimport type { PackageGroups, ProjectType, ScaffoldContext } from \"../core/types.js\";\n\nfunction typePackages(type: ProjectType): PackageGroups {\n const dependencies = [\"@taserjs/router\", \"dotenv\"];\n const devDependencies = [\n \"@taserjs/router-cli\",\n \"npm-run-all2\",\n \"tsdown\",\n \"tsx\",\n \"typescript\",\n \"@types/node\",\n ];\n const scripts: Record<string, string> = {};\n\n switch (type) {\n case \"express\":\n dependencies.push(\"@taserjs/adapter-express\", \"express\");\n devDependencies.push(\"@types/express\");\n break;\n case \"fastify\":\n dependencies.push(\"@taserjs/adapter-fastify\", \"fastify\");\n break;\n case \"hono\":\n dependencies.push(\"@hono/node-server\", \"hono\");\n break;\n case \"bun\":\n // Bun has native TypeScript and runtime execution\n devDependencies.push(\"@types/bun\");\n scripts[\"dev:server\"] = \"bun --watch src/index.ts\";\n scripts.start = \"bun src/index.ts\";\n scripts.serve = \"bun dist/index.mjs\";\n break;\n case \"deno\":\n scripts[\"dev:server\"] = \"deno run --watch --allow-net --allow-env --allow-read src/index.ts\";\n scripts.start = \"deno run --allow-net --allow-env --allow-read src/index.ts\";\n scripts.serve = \"deno run --allow-net --allow-env --allow-read dist/index.mjs\";\n break;\n case \"aws-lambda\":\n dependencies.push(\"hono\");\n devDependencies.push(\"@types/aws-lambda\");\n break;\n case \"cloudflare-workers\": {\n // Cloudflare workers uses wrangler\n const cfDevDeps = devDependencies.filter((d) => d !== \"tsx\");\n cfDevDeps.push(\"wrangler\", \"@cloudflare/workers-types\");\n devDependencies.length = 0;\n devDependencies.push(...cfDevDeps);\n scripts[\"dev:server\"] = \"wrangler dev\";\n scripts.deploy = \"wrangler deploy\";\n break;\n }\n case \"netlify\":\n dependencies.push(\"hono\", \"@netlify/functions\");\n break;\n case \"vercel\":\n dependencies.push(\"hono\");\n devDependencies.push(\"@vercel/node\");\n break;\n case \"azure-functions\":\n dependencies.push(\"hono\", \"@azure/functions\", \"@marplex/hono-azurefunc-adapter\");\n break;\n case \"google-cloud-run\":\n case \"node\":\n default:\n dependencies.push(\"@hono/node-server\");\n break;\n }\n\n return { dependencies, devDependencies, scripts };\n}\n\nexport function resolvePackages(ctx: ScaffoldContext): PackageGroups {\n const base = typePackages(ctx.type);\n const addons = resolveAddons(ctx);\n\n const dependencies = [...base.dependencies];\n const devDependencies = [...base.devDependencies];\n const scripts = { ...base.scripts };\n\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\nexport function getPackageGroups(\n type: ProjectType,\n): Omit<PackageGroups, \"scripts\"> & { scripts?: Record<string, string> } {\n const groups = typePackages(type);\n return groups;\n}\n"],"mappings":";;AAGA,SAAS,aAAa,MAAkC;CACtD,MAAM,eAAe,CAAC,mBAAmB,QAAQ;CACjD,MAAM,kBAAkB;EACtB;EACA;EACA;EACA;EACA;EACA;CACF;CACA,MAAM,UAAkC,CAAC;CAEzC,QAAQ,MAAR;EACE,KAAK;GACH,aAAa,KAAK,4BAA4B,SAAS;GACvD,gBAAgB,KAAK,gBAAgB;GACrC;EACF,KAAK;GACH,aAAa,KAAK,4BAA4B,SAAS;GACvD;EACF,KAAK;GACH,aAAa,KAAK,qBAAqB,MAAM;GAC7C;EACF,KAAK;GAEH,gBAAgB,KAAK,YAAY;GACjC,QAAQ,gBAAgB;GACxB,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB;EACF,KAAK;GACH,QAAQ,gBAAgB;GACxB,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB;EACF,KAAK;GACH,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,mBAAmB;GACxC;EACF,KAAK,sBAAsB;GAEzB,MAAM,YAAY,gBAAgB,QAAQ,MAAM,MAAM,KAAK;GAC3D,UAAU,KAAK,YAAY,2BAA2B;GACtD,gBAAgB,SAAS;GACzB,gBAAgB,KAAK,GAAG,SAAS;GACjC,QAAQ,gBAAgB;GACxB,QAAQ,SAAS;GACjB;EACF;EACA,KAAK;GACH,aAAa,KAAK,QAAQ,oBAAoB;GAC9C;EACF,KAAK;GACH,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,cAAc;GACnC;EACF,KAAK;GACH,aAAa,KAAK,QAAQ,oBAAoB,iCAAiC;GAC/E;EAGF,SACE,aAAa,KAAK,mBAAmB;CAEzC;CAEA,OAAO;EAAE;EAAc;EAAiB;CAAQ;AAClD;AAEA,SAAgB,gBAAgB,KAAqC;CACnE,MAAM,OAAO,aAAa,IAAI,IAAI;CAClC,MAAM,SAAS,iBAAA,cAAc,GAAG;CAEhC,MAAM,eAAe,CAAC,GAAG,KAAK,YAAY;CAC1C,MAAM,kBAAkB,CAAC,GAAG,KAAK,eAAe;CAChD,MAAM,UAAU,EAAE,GAAG,KAAK,QAAQ;CAElC,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.cjs","names":[],"sources":["../../../src/core/resolve-packages.ts"],"sourcesContent":["import { resolveAddons } from \"../addons/registry.js\";\nimport type { PackageGroups, ProjectType, ScaffoldContext } from \"../core/types.js\";\n\nfunction typePackages(type: ProjectType): PackageGroups {\n const dependencies = [\"@taserjs/router\", \"dotenv\"];\n const devDependencies = [\n \"@taserjs/router-cli\",\n \"npm-run-all2\",\n \"tsdown\",\n \"tsx\",\n \"typescript@^5.9.3\",\n \"@types/node\",\n ];\n const scripts: Record<string, string> = {};\n\n switch (type) {\n case \"express\":\n dependencies.push(\"@taserjs/adapter-express\", \"express\");\n devDependencies.push(\"@types/express\");\n break;\n case \"fastify\":\n dependencies.push(\"@taserjs/adapter-fastify\", \"fastify\");\n break;\n case \"hono\":\n dependencies.push(\"@hono/node-server\", \"hono\");\n break;\n case \"bun\":\n // Bun has native TypeScript and runtime execution\n devDependencies.push(\"@types/bun\");\n scripts[\"dev:server\"] = \"bun --watch src/index.ts\";\n scripts.start = \"bun src/index.ts\";\n scripts.serve = \"bun dist/index.mjs\";\n break;\n case \"deno\":\n scripts[\"dev:server\"] = \"deno run --watch --allow-net --allow-env --allow-read src/index.ts\";\n scripts.start = \"deno run --allow-net --allow-env --allow-read src/index.ts\";\n scripts.serve = \"deno run --allow-net --allow-env --allow-read dist/index.mjs\";\n break;\n case \"aws-lambda\":\n dependencies.push(\"hono\");\n devDependencies.push(\"@types/aws-lambda\");\n break;\n case \"cloudflare-workers\": {\n // Cloudflare workers uses wrangler\n const cfDevDeps = devDependencies.filter((d) => d !== \"tsx\");\n cfDevDeps.push(\"wrangler\", \"@cloudflare/workers-types\");\n devDependencies.length = 0;\n devDependencies.push(...cfDevDeps);\n scripts[\"dev:server\"] = \"wrangler dev\";\n scripts.deploy = \"wrangler deploy\";\n break;\n }\n case \"netlify\":\n dependencies.push(\"hono\", \"@netlify/functions\");\n break;\n case \"vercel\":\n dependencies.push(\"hono\");\n devDependencies.push(\"@vercel/node\");\n break;\n case \"azure-functions\":\n dependencies.push(\"hono\", \"@azure/functions\", \"@marplex/hono-azurefunc-adapter\");\n break;\n case \"google-cloud-run\":\n case \"node\":\n default:\n dependencies.push(\"@hono/node-server\");\n break;\n }\n\n return { dependencies, devDependencies, scripts };\n}\n\nexport function resolvePackages(ctx: ScaffoldContext): PackageGroups {\n const base = typePackages(ctx.type);\n const addons = resolveAddons(ctx);\n\n const dependencies = [...base.dependencies];\n const devDependencies = [...base.devDependencies];\n const scripts = { ...base.scripts };\n\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\nexport function getPackageGroups(\n type: ProjectType,\n): Omit<PackageGroups, \"scripts\"> & { scripts?: Record<string, string> } {\n const groups = typePackages(type);\n return groups;\n}\n"],"mappings":";;AAGA,SAAS,aAAa,MAAkC;CACtD,MAAM,eAAe,CAAC,mBAAmB,QAAQ;CACjD,MAAM,kBAAkB;EACtB;EACA;EACA;EACA;EACA;EACA;CACF;CACA,MAAM,UAAkC,CAAC;CAEzC,QAAQ,MAAR;EACE,KAAK;GACH,aAAa,KAAK,4BAA4B,SAAS;GACvD,gBAAgB,KAAK,gBAAgB;GACrC;EACF,KAAK;GACH,aAAa,KAAK,4BAA4B,SAAS;GACvD;EACF,KAAK;GACH,aAAa,KAAK,qBAAqB,MAAM;GAC7C;EACF,KAAK;GAEH,gBAAgB,KAAK,YAAY;GACjC,QAAQ,gBAAgB;GACxB,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB;EACF,KAAK;GACH,QAAQ,gBAAgB;GACxB,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB;EACF,KAAK;GACH,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,mBAAmB;GACxC;EACF,KAAK,sBAAsB;GAEzB,MAAM,YAAY,gBAAgB,QAAQ,MAAM,MAAM,KAAK;GAC3D,UAAU,KAAK,YAAY,2BAA2B;GACtD,gBAAgB,SAAS;GACzB,gBAAgB,KAAK,GAAG,SAAS;GACjC,QAAQ,gBAAgB;GACxB,QAAQ,SAAS;GACjB;EACF;EACA,KAAK;GACH,aAAa,KAAK,QAAQ,oBAAoB;GAC9C;EACF,KAAK;GACH,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,cAAc;GACnC;EACF,KAAK;GACH,aAAa,KAAK,QAAQ,oBAAoB,iCAAiC;GAC/E;EAGF,SACE,aAAa,KAAK,mBAAmB;CAEzC;CAEA,OAAO;EAAE;EAAc;EAAiB;CAAQ;AAClD;AAEA,SAAgB,gBAAgB,KAAqC;CACnE,MAAM,OAAO,aAAa,IAAI,IAAI;CAClC,MAAM,SAAS,iBAAA,cAAc,GAAG;CAEhC,MAAM,eAAe,CAAC,GAAG,KAAK,YAAY;CAC1C,MAAM,kBAAkB,CAAC,GAAG,KAAK,eAAe;CAChD,MAAM,UAAU,EAAE,GAAG,KAAK,QAAQ;CAElC,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"}
@@ -69,33 +69,13 @@ async function scaffoldProject(options) {
69
69
  await (0, node_fs_promises.copyFile)(node_path.default.join(root, ".env.example"), node_path.default.join(root, ".env"));
70
70
  } catch {}
71
71
  await require_project_config.writeProjectConfig(root, ctx);
72
- if (options.skipInstall) return {
73
- projectName: ctx.projectName,
74
- targetDir: root,
75
- type: ctx.type,
76
- ...ctx.db ? {
77
- db: ctx.db,
78
- driver: ctx.driver
79
- } : {},
80
- ...ctx.logger ? { logger: ctx.logger } : {},
81
- ...ctx.validator ? { validator: ctx.validator } : {}
82
- };
72
+ if (options.skipInstall) return ctx;
83
73
  const agent = options.agent ?? require_package_manager.resolveUserAgent();
84
74
  await require_package_manager.installPackages(agent, root, {
85
75
  dependencies: packages.dependencies,
86
76
  devDependencies: packages.devDependencies
87
77
  });
88
- return {
89
- projectName: ctx.projectName,
90
- targetDir: root,
91
- type: ctx.type,
92
- ...ctx.db ? {
93
- db: ctx.db,
94
- driver: ctx.driver
95
- } : {},
96
- ...ctx.logger ? { logger: ctx.logger } : {},
97
- ...ctx.validator ? { validator: ctx.validator } : {}
98
- };
78
+ return ctx;
99
79
  }
100
80
  //#endregion
101
81
  exports.scaffoldProject = scaffoldProject;
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold-engine.cjs","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 { indexTemplate, taserTsTemplate } from \"../frameworks/index.js\";\nimport { installPackages, resolveUserAgent } from \"./package-manager.js\";\nimport { writeProjectConfig } from \"./project-config.js\";\nimport { resolvePackages } from \"./resolve-packages.js\";\nimport type { ScaffoldOptions, ScaffoldResult } from \"./types.js\";\nimport {\n contextTemplate,\n gitignoreTemplate,\n healthRouteTemplate,\n indexRouteTemplate,\n packageJsonTemplate,\n rootLayoutTemplate,\n starterManifestTemplate,\n tsconfigTemplate,\n tsdownConfigTemplate,\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 ctx = {\n projectName: options.projectName,\n targetDir: root,\n type: options.type,\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\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, \"tsdown.config.ts\"), tsdownConfigTemplate());\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(options.type));\n await write(path.join(root, \"src/index.ts\"), indexTemplate(options.type));\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 await write(path.join(root, \"src/routeManifest.gen.ts\"), starterManifestTemplate());\n\n if (options.type === \"cloudflare-workers\") {\n await write(\n path.join(root, \"wrangler.jsonc\"),\n JSON.stringify(\n {\n $schema: \"node_modules/wrangler/config-schema.json\",\n name: options.projectName,\n main: \"src/index.ts\",\n compatibility_date: \"2024-11-01\",\n },\n null,\n 2,\n ) + \"\\n\",\n );\n }\n\n if (options.type === \"vercel\") {\n await write(\n path.join(root, \"vercel.json\"),\n JSON.stringify(\n {\n rewrites: [{ source: \"/(.*)\", destination: \"/src/index.ts\" }],\n },\n null,\n 2,\n ) + \"\\n\",\n );\n }\n\n if (options.type === \"azure-functions\") {\n await write(\n path.join(root, \"host.json\"),\n JSON.stringify(\n {\n version: \"2.0\",\n logging: {\n applicationInsights: {\n samplingSettings: {\n isEnabled: true,\n excludedTypes: \"Request\",\n },\n },\n },\n extensionBundle: {\n id: \"Microsoft.Azure.Functions.ExtensionBundle\",\n version: \"[4.*, 5.0.0)\",\n },\n extensions: {\n http: {\n routePrefix: \"\",\n },\n },\n },\n null,\n 2,\n ) + \"\\n\",\n );\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 {\n projectName: ctx.projectName,\n targetDir: root,\n type: ctx.type,\n ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),\n ...(ctx.logger ? { logger: ctx.logger } : {}),\n ...(ctx.validator ? { validator: ctx.validator } : {}),\n };\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 {\n projectName: ctx.projectName,\n targetDir: root,\n type: ctx.type,\n ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),\n ...(ctx.logger ? { logger: ctx.logger } : {}),\n ...(ctx.validator ? { validator: ctx.validator } : {}),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"scaffold-engine.cjs","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 { indexTemplate, taserTsTemplate } from \"../frameworks/index.js\";\nimport { installPackages, resolveUserAgent } from \"./package-manager.js\";\nimport { writeProjectConfig } from \"./project-config.js\";\nimport { resolvePackages } from \"./resolve-packages.js\";\nimport type { ScaffoldOptions, ScaffoldResult } from \"./types.js\";\nimport {\n contextTemplate,\n gitignoreTemplate,\n healthRouteTemplate,\n indexRouteTemplate,\n packageJsonTemplate,\n rootLayoutTemplate,\n starterManifestTemplate,\n tsconfigTemplate,\n tsdownConfigTemplate,\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 ctx = {\n projectName: options.projectName,\n targetDir: root,\n type: options.type,\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\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, \"tsdown.config.ts\"), tsdownConfigTemplate());\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(options.type));\n await write(path.join(root, \"src/index.ts\"), indexTemplate(options.type));\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 await write(path.join(root, \"src/routeManifest.gen.ts\"), starterManifestTemplate());\n\n if (options.type === \"cloudflare-workers\") {\n await write(\n path.join(root, \"wrangler.jsonc\"),\n JSON.stringify(\n {\n $schema: \"node_modules/wrangler/config-schema.json\",\n name: options.projectName,\n main: \"src/index.ts\",\n compatibility_date: \"2024-11-01\",\n },\n null,\n 2,\n ) + \"\\n\",\n );\n }\n\n if (options.type === \"vercel\") {\n await write(\n path.join(root, \"vercel.json\"),\n JSON.stringify(\n {\n rewrites: [{ source: \"/(.*)\", destination: \"/src/index.ts\" }],\n },\n null,\n 2,\n ) + \"\\n\",\n );\n }\n\n if (options.type === \"azure-functions\") {\n await write(\n path.join(root, \"host.json\"),\n JSON.stringify(\n {\n version: \"2.0\",\n logging: {\n applicationInsights: {\n samplingSettings: {\n isEnabled: true,\n excludedTypes: \"Request\",\n },\n },\n },\n extensionBundle: {\n id: \"Microsoft.Azure.Functions.ExtensionBundle\",\n version: \"[4.*, 5.0.0)\",\n },\n extensions: {\n http: {\n routePrefix: \"\",\n },\n },\n },\n null,\n 2,\n ) + \"\\n\",\n );\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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"}
@@ -31,7 +31,7 @@ import { t } from '#src/taser.js'
31
31
  const router = t.create(routeManifest)
32
32
 
33
33
  const app = new Hono()
34
- app.all('/*', c => router.native(c).fetch(c.req.raw))
34
+ app.all('/*', c => router.fetch(c.req.raw))
35
35
 
36
36
  const port = Number(process.env.PORT ?? 3000)
37
37
  serve({ fetch: app.fetch, port }, () => {
@@ -93,7 +93,7 @@ import { t } from '#src/taser.js'
93
93
  const router = t.create(routeManifest)
94
94
 
95
95
  const app = new Hono()
96
- app.all('/*', c => router.native(c).fetch(c.req.raw))
96
+ app.all('/*', c => router.fetch(c.req.raw))
97
97
 
98
98
  export const handler = handle(app)
99
99
  `;
@@ -121,7 +121,7 @@ import { t } from '#src/taser.js'
121
121
  const router = t.create(routeManifest)
122
122
 
123
123
  const app = new Hono()
124
- app.all('/*', c => router.native(c).fetch(c.req.raw))
124
+ app.all('/*', c => router.fetch(c.req.raw))
125
125
 
126
126
  export default handle(app)
127
127
  `;
@@ -136,7 +136,7 @@ import { t } from '#src/taser.js'
136
136
  const router = t.create(routeManifest)
137
137
 
138
138
  const app = new Hono()
139
- app.all('/*', c => router.native(c).fetch(c.req.raw))
139
+ app.all('/*', c => router.fetch(c.req.raw))
140
140
 
141
141
  export default handle(app)
142
142
  `;
@@ -152,7 +152,7 @@ import { t } from '#src/taser.js'
152
152
  const router = t.create(routeManifest)
153
153
 
154
154
  const honoApp = new Hono()
155
- honoApp.all('/*', c => router.native(c).fetch(c.req.raw))
155
+ honoApp.all('/*', c => router.fetch(c.req.raw))
156
156
 
157
157
  app.http('httpTrigger', {
158
158
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],
@@ -191,33 +191,14 @@ serve({ fetch: router.fetch, port }, () => {
191
191
  `;
192
192
  }
193
193
  }
194
- function taserTsTemplate(type = "node") {
195
- if (type === "hono" || type === "aws-lambda" || type === "netlify" || type === "vercel" || type === "azure-functions") return `import type { Context } from 'hono'
196
- import { createTaserApp, type InferAppContext } from '@taserjs/router'
194
+ function taserTsTemplate(_type = "node") {
195
+ return `import { createTaserApp } from '@taserjs/router'
197
196
 
198
197
  import { context } from '#src/context.js'
199
198
 
200
- declare module '@taserjs/router' {
201
- interface RouterRegister {
202
- NativeContext: Context
203
- }
204
- }
205
-
206
199
  export const t = createTaserApp({
207
200
  response: { validate: true },
208
201
  }).context(context)
209
-
210
- export type AppContext = InferAppContext<typeof context>
211
- `;
212
- return `import { createTaserApp, type InferAppContext } from '@taserjs/router'
213
-
214
- import { context } from '#src/context.js'
215
-
216
- export const t = createTaserApp({
217
- response: { validate: true },
218
- }).context(context)
219
-
220
- export type AppContext = InferAppContext<typeof context>
221
202
  `;
222
203
  }
223
204
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { ProjectType } from \"../core/types.js\";\n\nexport function indexTemplate(type: ProjectType): string {\n switch (type) {\n case \"express\":\n return `import 'dotenv/config'\n\nimport express from 'express'\nimport { createExpressHandler } from '@taserjs/adapter-express'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createExpressHandler(router)\nconst app = express()\ntaser.mount('/{*splat}', app)\n\nconst port = Number(process.env.PORT ?? 3000)\napp.listen(port, () => {\n console.log(\\`Express listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"hono\":\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\nimport { Hono } from 'hono'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.native(c).fetch(c.req.raw))\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: app.fetch, port }, () => {\n console.log(\\`Hono listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"fastify\":\n return `import 'dotenv/config'\n\nimport Fastify from 'fastify'\nimport { createFastifyHandler } from '@taserjs/adapter-fastify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createFastifyHandler(router)\nconst app = Fastify()\ntaser.mount('/*', app)\n\nconst port = Number(process.env.PORT ?? 3000)\nawait app.listen({ port })\nconsole.log(\\`Fastify listening on http://localhost:\\${port}\\`)\n`;\n case \"bun\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 3000)\n\nexport default {\n port,\n fetch(request: Request) {\n return router.fetch(request)\n },\n}\n`;\n case \"deno\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 8000)\nDeno.serve({ port }, (request: Request) => router.fetch(request))\n`;\n case \"aws-lambda\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/aws-lambda'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.native(c).fetch(c.req.raw))\n\nexport const handler = handle(app)\n`;\n case \"cloudflare-workers\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nexport default {\n fetch(request: Request, env: unknown, ctx: unknown) {\n return router.fetch(request, env, ctx)\n },\n}\n`;\n case \"netlify\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/netlify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.native(c).fetch(c.req.raw))\n\nexport default handle(app)\n`;\n case \"vercel\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/vercel'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.native(c).fetch(c.req.raw))\n\nexport default handle(app)\n`;\n case \"azure-functions\":\n return `import 'dotenv/config'\n\nimport { app } from '@azure/functions'\nimport { Hono } from 'hono'\nimport { azureHonoHandler } from '@marplex/hono-azurefunc-adapter'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst honoApp = new Hono()\nhonoApp.all('/*', c => router.native(c).fetch(c.req.raw))\n\napp.http('httpTrigger', {\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],\n authLevel: 'anonymous',\n route: '{*proxy}',\n handler: azureHonoHandler(honoApp.fetch),\n})\n`;\n case \"google-cloud-run\":\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 8080)\nserve({ fetch: router.fetch, port }, () => {\n console.log(\\`Cloud Run listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"node\":\n default:\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: router.fetch, port }, () => {\n console.log(\\`Node listening on http://localhost:\\${port}\\`)\n})\n`;\n }\n}\n\nexport function taserTsTemplate(type: ProjectType = \"node\"): string {\n if (\n type === \"hono\" ||\n type === \"aws-lambda\" ||\n type === \"netlify\" ||\n type === \"vercel\" ||\n type === \"azure-functions\"\n ) {\n return `import type { Context } from 'hono'\nimport { createTaserApp, type InferAppContext } from '@taserjs/router'\n\nimport { context } from '#src/context.js'\n\ndeclare module '@taserjs/router' {\n interface RouterRegister {\n NativeContext: Context\n }\n}\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n\nexport type AppContext = InferAppContext<typeof context>\n`;\n }\n\n return `import { createTaserApp, type InferAppContext } from '@taserjs/router'\n\nimport { context } from '#src/context.js'\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n\nexport type AppContext = InferAppContext<typeof context>\n`;\n}\n"],"mappings":";AAEA,SAAgB,cAAc,MAA2B;CACvD,QAAQ,MAAR;EACE,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;;;EAmBT,KAAK,QACH,OAAO;;;;;;;;;;;;;;;;;;EAkBT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;;EAkBT,KAAK,OACH,OAAO;;;;;;;;;;;;;;;;EAgBT,KAAK,QACH,OAAO;;;;;;;;;;EAUT,KAAK,cACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,sBACH,OAAO;;;;;;;;;;;;;EAaT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,UACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,mBACH,OAAO;;;;;;;;;;;;;;;;;;;;;EAqBT,KAAK,oBACH,OAAO;;;;;;;;;;;;;;EAeT,SACE,OAAO;;;;;;;;;;;;;;CAcX;AACF;AAEA,SAAgB,gBAAgB,OAAoB,QAAgB;CAClE,IACE,SAAS,UACT,SAAS,gBACT,SAAS,aACT,SAAS,YACT,SAAS,mBAET,OAAO;;;;;;;;;;;;;;;;;CAmBT,OAAO;;;;;;;;;;AAUT"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { ProjectType } from \"../core/types.js\";\n\nexport function indexTemplate(type: ProjectType): string {\n switch (type) {\n case \"express\":\n return `import 'dotenv/config'\n\nimport express from 'express'\nimport { createExpressHandler } from '@taserjs/adapter-express'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createExpressHandler(router)\nconst app = express()\ntaser.mount('/{*splat}', app)\n\nconst port = Number(process.env.PORT ?? 3000)\napp.listen(port, () => {\n console.log(\\`Express listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"hono\":\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\nimport { Hono } from 'hono'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.fetch(c.req.raw))\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: app.fetch, port }, () => {\n console.log(\\`Hono listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"fastify\":\n return `import 'dotenv/config'\n\nimport Fastify from 'fastify'\nimport { createFastifyHandler } from '@taserjs/adapter-fastify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createFastifyHandler(router)\nconst app = Fastify()\ntaser.mount('/*', app)\n\nconst port = Number(process.env.PORT ?? 3000)\nawait app.listen({ port })\nconsole.log(\\`Fastify listening on http://localhost:\\${port}\\`)\n`;\n case \"bun\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 3000)\n\nexport default {\n port,\n fetch(request: Request) {\n return router.fetch(request)\n },\n}\n`;\n case \"deno\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 8000)\nDeno.serve({ port }, (request: Request) => router.fetch(request))\n`;\n case \"aws-lambda\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/aws-lambda'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.fetch(c.req.raw))\n\nexport const handler = handle(app)\n`;\n case \"cloudflare-workers\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nexport default {\n fetch(request: Request, env: unknown, ctx: unknown) {\n return router.fetch(request, env, ctx)\n },\n}\n`;\n case \"netlify\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/netlify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.fetch(c.req.raw))\n\nexport default handle(app)\n`;\n case \"vercel\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/vercel'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.fetch(c.req.raw))\n\nexport default handle(app)\n`;\n case \"azure-functions\":\n return `import 'dotenv/config'\n\nimport { app } from '@azure/functions'\nimport { Hono } from 'hono'\nimport { azureHonoHandler } from '@marplex/hono-azurefunc-adapter'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst honoApp = new Hono()\nhonoApp.all('/*', c => router.fetch(c.req.raw))\n\napp.http('httpTrigger', {\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],\n authLevel: 'anonymous',\n route: '{*proxy}',\n handler: azureHonoHandler(honoApp.fetch),\n})\n`;\n case \"google-cloud-run\":\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 8080)\nserve({ fetch: router.fetch, port }, () => {\n console.log(\\`Cloud Run listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"node\":\n default:\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: router.fetch, port }, () => {\n console.log(\\`Node listening on http://localhost:\\${port}\\`)\n})\n`;\n }\n}\n\nexport function taserTsTemplate(_type: ProjectType = \"node\"): string {\n return `import { createTaserApp } from '@taserjs/router'\n\nimport { context } from '#src/context.js'\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n`;\n}\n"],"mappings":";AAEA,SAAgB,cAAc,MAA2B;CACvD,QAAQ,MAAR;EACE,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;;;EAmBT,KAAK,QACH,OAAO;;;;;;;;;;;;;;;;;;EAkBT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;;EAkBT,KAAK,OACH,OAAO;;;;;;;;;;;;;;;;EAgBT,KAAK,QACH,OAAO;;;;;;;;;;EAUT,KAAK,cACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,sBACH,OAAO;;;;;;;;;;;;;EAaT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,UACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,mBACH,OAAO;;;;;;;;;;;;;;;;;;;;;EAqBT,KAAK,oBACH,OAAO;;;;;;;;;;;;;;EAeT,SACE,OAAO;;;;;;;;;;;;;;CAcX;AACF;AAEA,SAAgB,gBAAgB,QAAqB,QAAgB;CACnE,OAAO;;;;;;;;AAQT"}
@@ -1,3 +1,3 @@
1
1
  import { ProjectType } from '../core/types.js';
2
2
  export declare function indexTemplate(type: ProjectType): string;
3
- export declare function taserTsTemplate(type?: ProjectType): string;
3
+ export declare function taserTsTemplate(_type?: ProjectType): string;
@@ -73,21 +73,22 @@ ${bootBlock}
73
73
  `;
74
74
  }
75
75
  function rootLayoutTemplate() {
76
- return `import { bodyLimit } from '@taserjs/router/body-limit'
77
- import { secureHeaders } from '@taserjs/router/secure-headers'
76
+ return `import { cors } from '@taserjs/router/cors'
78
77
 
79
78
  import { t } from '#src/taser.js'
80
79
 
81
80
  export const Middleware = t.middleware('/$')
82
- .use(secureHeaders())
83
- .use(bodyLimit({ maxSize: 1_000_000 }))
81
+ .use(cors())
84
82
  `;
85
83
  }
86
84
  function indexRouteTemplate() {
87
85
  return `import { reply } from '@taserjs/router'
88
86
  import { t } from '#src/taser.js'
89
87
 
90
- export const Route = t.get('/').handler(() => {
88
+ const GET = t.get('/')
89
+
90
+ export type RouteContext = typeof GET.$Infer.Context
91
+ export const Route = GET.handler((_ctx) => {
91
92
  return reply.json({ message: 'Welcome to Taser' })
92
93
  })
93
94
  `;
@@ -100,7 +101,10 @@ function healthRouteTemplate(ctx) {
100
101
  return `import { reply } from '@taserjs/router'
101
102
  import { t } from '#src/taser.js'
102
103
 
103
- export const Route = t.get('/health').handler(${lines.length > 0 ? "(ctx)" : "()"} => {
104
+ const GET = t.get('/health')
105
+
106
+ export type RouteContext = typeof GET.$Infer.Context
107
+ export const Route = GET.handler(${lines.length > 0 ? "(ctx)" : "(_ctx)"} => {
104
108
  ${body} return reply.json({ ok: true })
105
109
  })
106
110
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"base.cjs","names":[],"sources":["../../../src/templates/base.ts"],"sourcesContent":["import type { BootBinding } from \"../addons/types.js\";\nimport type { ScaffoldContext } from \"../core/types.js\";\n\nexport function packageJsonTemplate(\n projectName: string,\n scripts: Record<string, string> = {},\n): string {\n const pkg = {\n name: projectName,\n version: \"1.0.0\",\n private: true,\n type: \"module\",\n imports: {\n \"#src/*\": \"./src/*\",\n },\n scripts: {\n dev: \"run-p dev:server dev:taser\",\n \"dev:server\": \"tsx watch src/index.ts\",\n \"dev:taser\": \"taser watch\",\n start: \"tsx src/index.ts\",\n generate: \"taser generate\",\n build: \"taser generate && tsdown\",\n serve: \"node dist/index.mjs\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsdownConfigTemplate(): string {\n return `import { defineConfig } from 'tsdown'\n\nexport default defineConfig({\n entry: ['./src/index.ts'],\n platform: 'node',\n outDir: 'dist',\n clean: true,\n sourcemap: true,\n})\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n paths: {\n \"#src/*\": [\"./src/*\"],\n },\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n types: [\"node\"],\n },\n include: [\"src\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.DS_Store\n*.log\n.env\nlocal.db\ndrizzle\n`;\n}\n\nexport function contextTemplate(bindings: BootBinding[]): string {\n const imports = bindings.map(\n (binding) => `import { ${binding.factoryName} } from '${binding.importPath}'`,\n );\n\n const bootBody =\n bindings.length > 0\n ? bindings.map((binding) => ` ${binding.key}: ${binding.factoryName}(),`).join(\"\\n\")\n : \"\";\n\n const bootBlock = bindings.length > 0 ? ` boot: () => ({\\n${bootBody}\\n }),` : \"\";\n\n const importBlock = imports.length > 0 ? `${imports.join(\"\\n\")}\\n\\n` : \"\";\n\n return `${importBlock}import { createContext } from '@taserjs/router'\n\nexport const context = createContext({\n${bootBlock}\n request: () => ({\n requestId: crypto.randomUUID(),\n }),\n})\n`;\n}\n\nexport function rootLayoutTemplate(): string {\n return `import { bodyLimit } from '@taserjs/router/body-limit'\nimport { secureHeaders } from '@taserjs/router/secure-headers'\n\nimport { t } from '#src/taser.js'\n\nexport const Middleware = t.middleware('/$')\n .use(secureHeaders())\n .use(bodyLimit({ maxSize: 1_000_000 }))\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n\nexport const Route = t.get('/').handler(() => {\n return reply.json({ message: 'Welcome to Taser' })\n})\n`;\n}\n\nexport function healthRouteTemplate(ctx: ScaffoldContext): string {\n const lines: string[] = [];\n\n if (ctx.logger) {\n lines.push(\" ctx.logger.info('health check')\");\n }\n\n if (ctx.db) {\n lines.push(\" // ctx.db is available from context boot\");\n }\n\n const body = lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n const ctxArg = lines.length > 0 ? \"(ctx)\" : \"()\";\n\n return `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n\nexport const Route = t.get('/health').handler(${ctxArg} => {\n${body} return reply.json({ ok: true })\n})\n`;\n}\n\n/** Minimal placeholder until `taser generate` runs. */\nexport function starterManifestTemplate(): string {\n return `/* eslint-disable */\n// Run \\`pnpm generate\\` (taser generate) to replace this file.\nimport { Middleware as RootSplatLayoutImport } from './routes/$.js'\nimport { Route as RootIndexGetRouteImport } from './routes/index.get.js'\nimport { Route as HealthGetRouteImport } from './routes/health.get.js'\n\nexport const routeManifest = {\n layouts: {\n '/$': {\n middlewares: RootSplatLayoutImport,\n },\n },\n routes: {\n '/': {\n GET: {\n layoutChain: ['/$'],\n route: RootIndexGetRouteImport,\n },\n },\n '/health': {\n GET: {\n layoutChain: ['/$'],\n route: HealthGetRouteImport,\n },\n },\n },\n} as const\n\nexport type RoutePathGen = '/' | '/health'\nexport type LayoutIdGen = '/$'\nexport type LayoutTreeGen = {\n '/$': {\n parent: null\n middlewares: typeof RootSplatLayoutImport\n }\n}\nexport type RouteByPathMethodGen = {\n '/': {\n GET: {\n parent: '/$'\n layoutChain: ['/$']\n route: typeof RootIndexGetRouteImport\n }\n }\n '/health': {\n GET: {\n parent: '/$'\n layoutChain: ['/$']\n route: typeof HealthGetRouteImport\n }\n }\n}\nexport type RouteManifest = typeof routeManifest\n\ndeclare module '@taserjs/router' {\n interface RouterRegister {\n RoutePath: RoutePathGen\n LayoutId: LayoutIdGen\n LayoutTree: LayoutTreeGen\n RouteByPathMethod: RouteByPathMethodGen\n }\n}\n`;\n}\n"],"mappings":";AAGA,SAAgB,oBACd,aACA,UAAkC,CAAC,GAC3B;CACR,MAAM,MAAM;EACV,MAAM;EACN,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS,EACP,UAAU,UACZ;EACA,SAAS;GACP,KAAK;GACL,cAAc;GACd,aAAa;GACb,OAAO;GACP,UAAU;GACV,OAAO;GACP,OAAO;GACP,WAAW;GACX,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,uBAA+B;CAC7C,OAAO;;;;;;;;;;AAUT;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,OAAO,EACL,UAAU,CAAC,SAAS,EACtB;GACA,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;GACR,OAAO,CAAC,MAAM;EAChB;EACA,SAAS,CAAC,KAAK;CACjB,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;AAQT;AAEA,SAAgB,gBAAgB,UAAiC;CAC/D,MAAM,UAAU,SAAS,KACtB,YAAY,YAAY,QAAQ,YAAY,WAAW,QAAQ,WAAW,EAC7E;CAEA,MAAM,WACJ,SAAS,SAAS,IACd,SAAS,KAAK,YAAY,OAAO,QAAQ,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC,CAAC,KAAK,IAAI,IACpF;CAEN,MAAM,YAAY,SAAS,SAAS,IAAI,qBAAqB,SAAS,WAAW;CAIjF,OAAO,GAFa,QAAQ,SAAS,IAAI,GAAG,QAAQ,KAAK,IAAI,EAAE,QAAQ,GAEjD;;;EAGtB,UAAU;;;;;;AAMZ;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;;;AAST;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;AAOT;AAEA,SAAgB,oBAAoB,KAA8B;CAChE,MAAM,QAAkB,CAAC;CAEzB,IAAI,IAAI,QACN,MAAM,KAAK,mCAAmC;CAGhD,IAAI,IAAI,IACN,MAAM,KAAK,4CAA4C;CAGzD,MAAM,OAAO,MAAM,SAAS,IAAI,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM;CAG1D,OAAO;;;gDAFQ,MAAM,SAAS,IAAI,UAAU,KAKS;EACrD,KAAK;;;AAGP;;AAGA,SAAgB,0BAAkC;CAChD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT"}
1
+ {"version":3,"file":"base.cjs","names":[],"sources":["../../../src/templates/base.ts"],"sourcesContent":["import type { BootBinding } from \"../addons/types.js\";\nimport type { ScaffoldContext } from \"../core/types.js\";\n\nexport function packageJsonTemplate(\n projectName: string,\n scripts: Record<string, string> = {},\n): string {\n const pkg = {\n name: projectName,\n version: \"1.0.0\",\n private: true,\n type: \"module\",\n imports: {\n \"#src/*\": \"./src/*\",\n },\n scripts: {\n dev: \"run-p dev:server dev:taser\",\n \"dev:server\": \"tsx watch src/index.ts\",\n \"dev:taser\": \"taser watch\",\n start: \"tsx src/index.ts\",\n generate: \"taser generate\",\n build: \"taser generate && tsdown\",\n serve: \"node dist/index.mjs\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsdownConfigTemplate(): string {\n return `import { defineConfig } from 'tsdown'\n\nexport default defineConfig({\n entry: ['./src/index.ts'],\n platform: 'node',\n outDir: 'dist',\n clean: true,\n sourcemap: true,\n})\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n paths: {\n \"#src/*\": [\"./src/*\"],\n },\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n types: [\"node\"],\n },\n include: [\"src\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.DS_Store\n*.log\n.env\nlocal.db\ndrizzle\n`;\n}\n\nexport function contextTemplate(bindings: BootBinding[]): string {\n const imports = bindings.map(\n (binding) => `import { ${binding.factoryName} } from '${binding.importPath}'`,\n );\n\n const bootBody =\n bindings.length > 0\n ? bindings.map((binding) => ` ${binding.key}: ${binding.factoryName}(),`).join(\"\\n\")\n : \"\";\n\n const bootBlock = bindings.length > 0 ? ` boot: () => ({\\n${bootBody}\\n }),` : \"\";\n\n const importBlock = imports.length > 0 ? `${imports.join(\"\\n\")}\\n\\n` : \"\";\n\n return `${importBlock}import { createContext } from '@taserjs/router'\n\nexport const context = createContext({\n${bootBlock}\n request: () => ({\n requestId: crypto.randomUUID(),\n }),\n})\n`;\n}\n\nexport function rootLayoutTemplate(): string {\n return `import { cors } from '@taserjs/router/cors'\n\nimport { t } from '#src/taser.js'\n\nexport const Middleware = t.middleware('/$')\n .use(cors())\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n\nconst GET = t.get('/')\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler((_ctx) => {\n return reply.json({ message: 'Welcome to Taser' })\n})\n`;\n}\n\nexport function healthRouteTemplate(ctx: ScaffoldContext): string {\n const lines: string[] = [];\n\n if (ctx.logger) {\n lines.push(\" ctx.logger.info('health check')\");\n }\n\n if (ctx.db) {\n lines.push(\" // ctx.db is available from context boot\");\n }\n\n const body = lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n const ctxArg = lines.length > 0 ? \"(ctx)\" : \"(_ctx)\";\n\n return `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n\nconst GET = t.get('/health')\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler(${ctxArg} => {\n${body} return reply.json({ ok: true })\n})\n`;\n}\n\n/** Minimal placeholder until `taser generate` runs. */\nexport function starterManifestTemplate(): string {\n return `/* eslint-disable */\n// Run \\`pnpm generate\\` (taser generate) to replace this file.\nimport { Middleware as RootSplatLayoutImport } from './routes/$.js'\nimport { Route as RootIndexGetRouteImport } from './routes/index.get.js'\nimport { Route as HealthGetRouteImport } from './routes/health.get.js'\n\nexport const routeManifest = {\n layouts: {\n '/$': {\n middlewares: RootSplatLayoutImport,\n },\n },\n routes: {\n '/': {\n GET: {\n layoutChain: ['/$'],\n route: RootIndexGetRouteImport,\n },\n },\n '/health': {\n GET: {\n layoutChain: ['/$'],\n route: HealthGetRouteImport,\n },\n },\n },\n} as const\n\nexport type RoutePathGen = '/' | '/health'\nexport type LayoutIdGen = '/$'\nexport type LayoutTreeGen = {\n '/$': {\n parent: null\n middlewares: typeof RootSplatLayoutImport\n }\n}\nexport type RouteByPathMethodGen = {\n '/': {\n GET: {\n parent: '/$'\n layoutChain: ['/$']\n route: typeof RootIndexGetRouteImport\n }\n }\n '/health': {\n GET: {\n parent: '/$'\n layoutChain: ['/$']\n route: typeof HealthGetRouteImport\n }\n }\n}\nexport type RouteManifest = typeof routeManifest\n\ndeclare module '@taserjs/router' {\n interface RouterRegister {\n RoutePath: RoutePathGen\n LayoutId: LayoutIdGen\n LayoutTree: LayoutTreeGen\n RouteByPathMethod: RouteByPathMethodGen\n }\n}\n`;\n}\n"],"mappings":";AAGA,SAAgB,oBACd,aACA,UAAkC,CAAC,GAC3B;CACR,MAAM,MAAM;EACV,MAAM;EACN,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS,EACP,UAAU,UACZ;EACA,SAAS;GACP,KAAK;GACL,cAAc;GACd,aAAa;GACb,OAAO;GACP,UAAU;GACV,OAAO;GACP,OAAO;GACP,WAAW;GACX,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,uBAA+B;CAC7C,OAAO;;;;;;;;;;AAUT;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,OAAO,EACL,UAAU,CAAC,SAAS,EACtB;GACA,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;GACR,OAAO,CAAC,MAAM;EAChB;EACA,SAAS,CAAC,KAAK;CACjB,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;AAQT;AAEA,SAAgB,gBAAgB,UAAiC;CAC/D,MAAM,UAAU,SAAS,KACtB,YAAY,YAAY,QAAQ,YAAY,WAAW,QAAQ,WAAW,EAC7E;CAEA,MAAM,WACJ,SAAS,SAAS,IACd,SAAS,KAAK,YAAY,OAAO,QAAQ,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC,CAAC,KAAK,IAAI,IACpF;CAEN,MAAM,YAAY,SAAS,SAAS,IAAI,qBAAqB,SAAS,WAAW;CAIjF,OAAO,GAFa,QAAQ,SAAS,IAAI,GAAG,QAAQ,KAAK,IAAI,EAAE,QAAQ,GAEjD;;;EAGtB,UAAU;;;;;;AAMZ;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;AAOT;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;;;;AAUT;AAEA,SAAgB,oBAAoB,KAA8B;CAChE,MAAM,QAAkB,CAAC;CAEzB,IAAI,IAAI,QACN,MAAM,KAAK,mCAAmC;CAGhD,IAAI,IAAI,IACN,MAAM,KAAK,4CAA4C;CAGzD,MAAM,OAAO,MAAM,SAAS,IAAI,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM;CAG1D,OAAO;;;;;;mCAFQ,MAAM,SAAS,IAAI,UAAU,SAQJ;EACxC,KAAK;;;AAGP;;AAGA,SAAgB,0BAAkC;CAChD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT"}
@@ -45,14 +45,11 @@ function resolveAddons(ctx) {
45
45
  if (!loggerAddon) throw new Error(`Unknown logger addon "${ctx.logger}"`);
46
46
  selected.push(loggerAddon);
47
47
  }
48
- if (selected.filter((addon) => addon.category === "database").length > 1) throw new Error("Only one database addon can be selected");
49
- if (selected.filter((addon) => addon.category === "logger").length > 1) throw new Error("Only one logger addon can be selected");
50
48
  if (ctx.validator) {
51
49
  const validatorAddon = VALIDATOR_ADDONS.find((addon) => addon.id === ctx.validator);
52
50
  if (!validatorAddon) throw new Error(`Unknown validator addon "${ctx.validator}"`);
53
51
  selected.push(validatorAddon);
54
52
  }
55
- if (selected.filter((addon) => addon.category === "validator").length > 1) throw new Error("Only one validator addon can be selected");
56
53
  return selected;
57
54
  }
58
55
  function collectBootBindings(ctx) {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":[],"sources":["../../../src/addons/registry.ts"],"sourcesContent":["import { arktypeAddon } from \"./arktype/index.js\";\nimport { drizzleAddon } from \"./drizzle/index.js\";\nimport { kyselyAddon } from \"./kysely/index.js\";\nimport { pinoAddon } from \"./pino/index.js\";\nimport { prismaAddon } from \"./prisma/index.js\";\nimport { valibotAddon } from \"./valibot/index.js\";\nimport { winstonAddon } from \"./winston/index.js\";\nimport { zodAddon } from \"./zod/index.js\";\nimport type { AddonDefinition } from \"./types.js\";\nimport type { CapabilitiesCatalog, ScaffoldContext } from \"../core/types.js\";\nimport {\n DB_DRIVERS,\n DB_ODMS,\n DEFAULT_DB_DRIVER,\n LOGGERS,\n PROJECT_TYPES,\n VALIDATORS,\n} from \"../core/types.js\";\n\nconst ALL_ADDONS: AddonDefinition[] = [\n drizzleAddon,\n prismaAddon,\n kyselyAddon,\n pinoAddon,\n winstonAddon,\n zodAddon,\n arktypeAddon,\n valibotAddon,\n];\n\nconst DB_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"database\");\nconst LOGGER_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"logger\");\nconst VALIDATOR_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"validator\");\n\nexport function getCapabilitiesCatalog(): CapabilitiesCatalog {\n return {\n types: [...PROJECT_TYPES],\n db: {\n odms: [...DB_ODMS],\n drivers: [...DB_DRIVERS],\n defaultDriver: DEFAULT_DB_DRIVER,\n },\n loggers: [...LOGGERS],\n validators: [...VALIDATORS],\n };\n}\n\nexport function resolveAddons(ctx: ScaffoldContext): AddonDefinition[] {\n const selected: AddonDefinition[] = [];\n\n if (ctx.db) {\n const dbAddon = DB_ADDONS.find((addon) => addon.id === ctx.db);\n if (!dbAddon) {\n throw new Error(`Unknown database addon \"${ctx.db}\"`);\n }\n selected.push(dbAddon);\n }\n\n if (ctx.logger) {\n const loggerAddon = LOGGER_ADDONS.find((addon) => addon.id === ctx.logger);\n if (!loggerAddon) {\n throw new Error(`Unknown logger addon \"${ctx.logger}\"`);\n }\n selected.push(loggerAddon);\n }\n\n const dbCount = selected.filter((addon) => addon.category === \"database\").length;\n if (dbCount > 1) {\n throw new Error(\"Only one database addon can be selected\");\n }\n\n const loggerCount = selected.filter((addon) => addon.category === \"logger\").length;\n if (loggerCount > 1) {\n throw new Error(\"Only one logger addon can be selected\");\n }\n\n if (ctx.validator) {\n const validatorAddon = VALIDATOR_ADDONS.find((addon) => addon.id === ctx.validator);\n if (!validatorAddon) {\n throw new Error(`Unknown validator addon \"${ctx.validator}\"`);\n }\n selected.push(validatorAddon);\n }\n\n const validatorCount = selected.filter((addon) => addon.category === \"validator\").length;\n if (validatorCount > 1) {\n throw new Error(\"Only one validator addon can be selected\");\n }\n\n return selected;\n}\n\nexport function collectBootBindings(ctx: ScaffoldContext) {\n return resolveAddons(ctx)\n .map((addon) => addon.bootBinding?.(ctx))\n .filter((v): v is NonNullable<typeof v> => Boolean(v));\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAM,aAAgC;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,IAAM,YAAY,WAAW,QAAQ,UAAU,MAAM,aAAa,UAAU;AAC5E,IAAM,gBAAgB,WAAW,QAAQ,UAAU,MAAM,aAAa,QAAQ;AAC9E,IAAM,mBAAmB,WAAW,QAAQ,UAAU,MAAM,aAAa,WAAW;AAEpF,SAAgB,yBAA8C;CAC5D,OAAO;EACL,OAAO,CAAC,GAAG,aAAa;EACxB,IAAI;GACF,MAAM,CAAC,GAAG,OAAO;GACjB,SAAS,CAAC,GAAG,UAAU;GACvB,eAAe;EACjB;EACA,SAAS,CAAC,GAAG,OAAO;EACpB,YAAY,CAAC,GAAG,UAAU;CAC5B;AACF;AAEA,SAAgB,cAAc,KAAyC;CACrE,MAAM,WAA8B,CAAC;CAErC,IAAI,IAAI,IAAI;EACV,MAAM,UAAU,UAAU,MAAM,UAAU,MAAM,OAAO,IAAI,EAAE;EAC7D,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,2BAA2B,IAAI,GAAG,EAAE;EAEtD,SAAS,KAAK,OAAO;CACvB;CAEA,IAAI,IAAI,QAAQ;EACd,MAAM,cAAc,cAAc,MAAM,UAAU,MAAM,OAAO,IAAI,MAAM;EACzE,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,yBAAyB,IAAI,OAAO,EAAE;EAExD,SAAS,KAAK,WAAW;CAC3B;CAGA,IADgB,SAAS,QAAQ,UAAU,MAAM,aAAa,UAAU,CAAC,CAAC,SAC5D,GACZ,MAAM,IAAI,MAAM,yCAAyC;CAI3D,IADoB,SAAS,QAAQ,UAAU,MAAM,aAAa,QAAQ,CAAC,CAAC,SAC1D,GAChB,MAAM,IAAI,MAAM,uCAAuC;CAGzD,IAAI,IAAI,WAAW;EACjB,MAAM,iBAAiB,iBAAiB,MAAM,UAAU,MAAM,OAAO,IAAI,SAAS;EAClF,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,4BAA4B,IAAI,UAAU,EAAE;EAE9D,SAAS,KAAK,cAAc;CAC9B;CAGA,IADuB,SAAS,QAAQ,UAAU,MAAM,aAAa,WAAW,CAAC,CAAC,SAC7D,GACnB,MAAM,IAAI,MAAM,0CAA0C;CAG5D,OAAO;AACT;AAEA,SAAgB,oBAAoB,KAAsB;CACxD,OAAO,cAAc,GAAG,CAAC,CACtB,KAAK,UAAU,MAAM,cAAc,GAAG,CAAC,CAAC,CACxC,QAAQ,MAAkC,QAAQ,CAAC,CAAC;AACzD"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../../src/addons/registry.ts"],"sourcesContent":["import { arktypeAddon } from \"./arktype/index.js\";\nimport { drizzleAddon } from \"./drizzle/index.js\";\nimport { kyselyAddon } from \"./kysely/index.js\";\nimport { pinoAddon } from \"./pino/index.js\";\nimport { prismaAddon } from \"./prisma/index.js\";\nimport { valibotAddon } from \"./valibot/index.js\";\nimport { winstonAddon } from \"./winston/index.js\";\nimport { zodAddon } from \"./zod/index.js\";\nimport type { AddonDefinition } from \"./types.js\";\nimport type { CapabilitiesCatalog, ScaffoldContext } from \"../core/types.js\";\nimport {\n DB_DRIVERS,\n DB_ODMS,\n DEFAULT_DB_DRIVER,\n LOGGERS,\n PROJECT_TYPES,\n VALIDATORS,\n} from \"../core/types.js\";\n\nconst ALL_ADDONS: AddonDefinition[] = [\n drizzleAddon,\n prismaAddon,\n kyselyAddon,\n pinoAddon,\n winstonAddon,\n zodAddon,\n arktypeAddon,\n valibotAddon,\n];\n\nconst DB_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"database\");\nconst LOGGER_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"logger\");\nconst VALIDATOR_ADDONS = ALL_ADDONS.filter((addon) => addon.category === \"validator\");\n\nexport function getCapabilitiesCatalog(): CapabilitiesCatalog {\n return {\n types: [...PROJECT_TYPES],\n db: {\n odms: [...DB_ODMS],\n drivers: [...DB_DRIVERS],\n defaultDriver: DEFAULT_DB_DRIVER,\n },\n loggers: [...LOGGERS],\n validators: [...VALIDATORS],\n };\n}\n\nexport function resolveAddons(ctx: ScaffoldContext): AddonDefinition[] {\n const selected: AddonDefinition[] = [];\n\n if (ctx.db) {\n const dbAddon = DB_ADDONS.find((addon) => addon.id === ctx.db);\n if (!dbAddon) {\n throw new Error(`Unknown database addon \"${ctx.db}\"`);\n }\n selected.push(dbAddon);\n }\n\n if (ctx.logger) {\n const loggerAddon = LOGGER_ADDONS.find((addon) => addon.id === ctx.logger);\n if (!loggerAddon) {\n throw new Error(`Unknown logger addon \"${ctx.logger}\"`);\n }\n selected.push(loggerAddon);\n }\n\n if (ctx.validator) {\n const validatorAddon = VALIDATOR_ADDONS.find((addon) => addon.id === ctx.validator);\n if (!validatorAddon) {\n throw new Error(`Unknown validator addon \"${ctx.validator}\"`);\n }\n selected.push(validatorAddon);\n }\n\n return selected;\n}\n\nexport function collectBootBindings(ctx: ScaffoldContext) {\n return resolveAddons(ctx)\n .map((addon) => addon.bootBinding?.(ctx))\n .filter((v): v is NonNullable<typeof v> => Boolean(v));\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAM,aAAgC;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,IAAM,YAAY,WAAW,QAAQ,UAAU,MAAM,aAAa,UAAU;AAC5E,IAAM,gBAAgB,WAAW,QAAQ,UAAU,MAAM,aAAa,QAAQ;AAC9E,IAAM,mBAAmB,WAAW,QAAQ,UAAU,MAAM,aAAa,WAAW;AAEpF,SAAgB,yBAA8C;CAC5D,OAAO;EACL,OAAO,CAAC,GAAG,aAAa;EACxB,IAAI;GACF,MAAM,CAAC,GAAG,OAAO;GACjB,SAAS,CAAC,GAAG,UAAU;GACvB,eAAe;EACjB;EACA,SAAS,CAAC,GAAG,OAAO;EACpB,YAAY,CAAC,GAAG,UAAU;CAC5B;AACF;AAEA,SAAgB,cAAc,KAAyC;CACrE,MAAM,WAA8B,CAAC;CAErC,IAAI,IAAI,IAAI;EACV,MAAM,UAAU,UAAU,MAAM,UAAU,MAAM,OAAO,IAAI,EAAE;EAC7D,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,2BAA2B,IAAI,GAAG,EAAE;EAEtD,SAAS,KAAK,OAAO;CACvB;CAEA,IAAI,IAAI,QAAQ;EACd,MAAM,cAAc,cAAc,MAAM,UAAU,MAAM,OAAO,IAAI,MAAM;EACzE,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,yBAAyB,IAAI,OAAO,EAAE;EAExD,SAAS,KAAK,WAAW;CAC3B;CAEA,IAAI,IAAI,WAAW;EACjB,MAAM,iBAAiB,iBAAiB,MAAM,UAAU,MAAM,OAAO,IAAI,SAAS;EAClF,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,4BAA4B,IAAI,UAAU,EAAE;EAE9D,SAAS,KAAK,cAAc;CAC9B;CAEA,OAAO;AACT;AAEA,SAAgB,oBAAoB,KAAsB;CACxD,OAAO,cAAc,GAAG,CAAC,CACtB,KAAK,UAAU,MAAM,cAAc,GAAG,CAAC,CAAC,CACxC,QAAQ,MAAkC,QAAQ,CAAC,CAAC;AACzD"}
@@ -6,20 +6,23 @@ var IMPORT_LINES = {
6
6
  };
7
7
  var VALIDATION_BLOCK_TEMPLATE = {
8
8
  zod: `, {
9
- query: z.object({ name: z.string() }),
9
+ query: z.object({ name: z.string().default('Taser') }),
10
10
  }`,
11
11
  arktype: `, {
12
- query: type({ name: 'string' }),
12
+ query: type({ 'name?': 'string = "Taser"' }),
13
13
  }`,
14
14
  valibot: `, {
15
- query: v.object({ name: v.string() }),
15
+ query: v.object({ name: v.optional(v.string(), 'Taser') }),
16
16
  }`
17
17
  };
18
18
  var ROUTE_TEMPLATE = (validator) => `import { reply } from '@taserjs/router'
19
19
  import { t } from '#src/taser.js'
20
20
  ${IMPORT_LINES[validator]}
21
21
 
22
- export const Route = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]}).handler((ctx) => {
22
+ const GET = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]})
23
+
24
+ export type RouteContext = typeof GET.$Infer.Context
25
+ export const Route = GET.handler((ctx) => {
23
26
  return reply.json({ message: \`Hello, \${ctx.query.name}!\` })
24
27
  })
25
28
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"validators.js","names":[],"sources":["../../../src/addons/validators.ts"],"sourcesContent":["import type { ValidatorId } from \"../core/types\";\nimport type { AddonDefinition } from \"./types\";\n\nexport const IMPORT_LINES: Record<ValidatorId, string> = {\n zod: `import { z } from 'zod'`,\n arktype: `import { type } from 'arktype'`,\n valibot: `import * as v from 'valibot'`,\n};\n\nexport const VALIDATION_BLOCK_TEMPLATE: Record<ValidatorId, string> = {\n zod: `, {\n query: z.object({ name: z.string() }),\n}`,\n arktype: `, {\n query: type({ name: 'string' }),\n}`,\n valibot: `, {\n query: v.object({ name: v.string() }),\n}`,\n};\n\nconst ROUTE_TEMPLATE = (validator: ValidatorId) => `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n${IMPORT_LINES[validator]}\n\nexport const Route = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]}).handler((ctx) => {\n return reply.json({ message: \\`Hello, \\${ctx.query.name}!\\` })\n})\n`;\n\nexport const ValidatorAddon = (validator: ValidatorId): AddonDefinition => {\n return {\n id: validator,\n category: \"validator\",\n dependencies: () => [validator],\n devDependencies: () => [],\n apply: (ctx, write) => write(\"src/routes/index.get.ts\", ROUTE_TEMPLATE(validator)),\n };\n};\n"],"mappings":";AAGA,IAAa,eAA4C;CACvD,KAAK;CACL,SAAS;CACT,SAAS;AACX;AAEA,IAAa,4BAAyD;CACpE,KAAK;;;CAGL,SAAS;;;CAGT,SAAS;;;AAGX;AAEA,IAAM,kBAAkB,cAA2B;;EAEjD,aAAa,WAAW;;gCAEM,0BAA0B,WAAW;;;;AAKrE,IAAa,kBAAkB,cAA4C;CACzE,OAAO;EACL,IAAI;EACJ,UAAU;EACV,oBAAoB,CAAC,SAAS;EAC9B,uBAAuB,CAAC;EACxB,QAAQ,KAAK,UAAU,MAAM,2BAA2B,eAAe,SAAS,CAAC;CACnF;AACF"}
1
+ {"version":3,"file":"validators.js","names":[],"sources":["../../../src/addons/validators.ts"],"sourcesContent":["import type { ValidatorId } from \"../core/types\";\nimport type { AddonDefinition } from \"./types\";\n\nexport const IMPORT_LINES: Record<ValidatorId, string> = {\n zod: `import { z } from 'zod'`,\n arktype: `import { type } from 'arktype'`,\n valibot: `import * as v from 'valibot'`,\n};\n\nexport const VALIDATION_BLOCK_TEMPLATE: Record<ValidatorId, string> = {\n zod: `, {\n query: z.object({ name: z.string().default('Taser') }),\n}`,\n arktype: `, {\n query: type({ 'name?': 'string = \"Taser\"' }),\n}`,\n valibot: `, {\n query: v.object({ name: v.optional(v.string(), 'Taser') }),\n}`,\n};\n\nconst ROUTE_TEMPLATE = (validator: ValidatorId) => `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n${IMPORT_LINES[validator]}\n\nconst GET = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]})\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler((ctx) => {\n return reply.json({ message: \\`Hello, \\${ctx.query.name}!\\` })\n})\n`;\n\nexport const ValidatorAddon = (validator: ValidatorId): AddonDefinition => {\n return {\n id: validator,\n category: \"validator\",\n dependencies: () => [validator],\n devDependencies: () => [],\n apply: (ctx, write) => write(\"src/routes/index.get.ts\", ROUTE_TEMPLATE(validator)),\n };\n};\n"],"mappings":";AAGA,IAAa,eAA4C;CACvD,KAAK;CACL,SAAS;CACT,SAAS;AACX;AAEA,IAAa,4BAAyD;CACpE,KAAK;;;CAGL,SAAS;;;CAGT,SAAS;;;AAGX;AAEA,IAAM,kBAAkB,cAA2B;;EAEjD,aAAa,WAAW;;uBAEH,0BAA0B,WAAW;;;;;;;AAQ5D,IAAa,kBAAkB,cAA4C;CACzE,OAAO;EACL,IAAI;EACJ,UAAU;EACV,oBAAoB,CAAC,SAAS;EAC9B,uBAAuB,CAAC;EACxB,QAAQ,KAAK,UAAU,MAAM,2BAA2B,eAAe,SAAS,CAAC;CACnF;AACF"}
@@ -7,7 +7,7 @@ function typePackages(type) {
7
7
  "npm-run-all2",
8
8
  "tsdown",
9
9
  "tsx",
10
- "typescript",
10
+ "typescript@^5.9.3",
11
11
  "@types/node"
12
12
  ];
13
13
  const scripts = {};
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-packages.js","names":[],"sources":["../../../src/core/resolve-packages.ts"],"sourcesContent":["import { resolveAddons } from \"../addons/registry.js\";\nimport type { PackageGroups, ProjectType, ScaffoldContext } from \"../core/types.js\";\n\nfunction typePackages(type: ProjectType): PackageGroups {\n const dependencies = [\"@taserjs/router\", \"dotenv\"];\n const devDependencies = [\n \"@taserjs/router-cli\",\n \"npm-run-all2\",\n \"tsdown\",\n \"tsx\",\n \"typescript\",\n \"@types/node\",\n ];\n const scripts: Record<string, string> = {};\n\n switch (type) {\n case \"express\":\n dependencies.push(\"@taserjs/adapter-express\", \"express\");\n devDependencies.push(\"@types/express\");\n break;\n case \"fastify\":\n dependencies.push(\"@taserjs/adapter-fastify\", \"fastify\");\n break;\n case \"hono\":\n dependencies.push(\"@hono/node-server\", \"hono\");\n break;\n case \"bun\":\n // Bun has native TypeScript and runtime execution\n devDependencies.push(\"@types/bun\");\n scripts[\"dev:server\"] = \"bun --watch src/index.ts\";\n scripts.start = \"bun src/index.ts\";\n scripts.serve = \"bun dist/index.mjs\";\n break;\n case \"deno\":\n scripts[\"dev:server\"] = \"deno run --watch --allow-net --allow-env --allow-read src/index.ts\";\n scripts.start = \"deno run --allow-net --allow-env --allow-read src/index.ts\";\n scripts.serve = \"deno run --allow-net --allow-env --allow-read dist/index.mjs\";\n break;\n case \"aws-lambda\":\n dependencies.push(\"hono\");\n devDependencies.push(\"@types/aws-lambda\");\n break;\n case \"cloudflare-workers\": {\n // Cloudflare workers uses wrangler\n const cfDevDeps = devDependencies.filter((d) => d !== \"tsx\");\n cfDevDeps.push(\"wrangler\", \"@cloudflare/workers-types\");\n devDependencies.length = 0;\n devDependencies.push(...cfDevDeps);\n scripts[\"dev:server\"] = \"wrangler dev\";\n scripts.deploy = \"wrangler deploy\";\n break;\n }\n case \"netlify\":\n dependencies.push(\"hono\", \"@netlify/functions\");\n break;\n case \"vercel\":\n dependencies.push(\"hono\");\n devDependencies.push(\"@vercel/node\");\n break;\n case \"azure-functions\":\n dependencies.push(\"hono\", \"@azure/functions\", \"@marplex/hono-azurefunc-adapter\");\n break;\n case \"google-cloud-run\":\n case \"node\":\n default:\n dependencies.push(\"@hono/node-server\");\n break;\n }\n\n return { dependencies, devDependencies, scripts };\n}\n\nexport function resolvePackages(ctx: ScaffoldContext): PackageGroups {\n const base = typePackages(ctx.type);\n const addons = resolveAddons(ctx);\n\n const dependencies = [...base.dependencies];\n const devDependencies = [...base.devDependencies];\n const scripts = { ...base.scripts };\n\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\nexport function getPackageGroups(\n type: ProjectType,\n): Omit<PackageGroups, \"scripts\"> & { scripts?: Record<string, string> } {\n const groups = typePackages(type);\n return groups;\n}\n"],"mappings":";;AAGA,SAAS,aAAa,MAAkC;CACtD,MAAM,eAAe,CAAC,mBAAmB,QAAQ;CACjD,MAAM,kBAAkB;EACtB;EACA;EACA;EACA;EACA;EACA;CACF;CACA,MAAM,UAAkC,CAAC;CAEzC,QAAQ,MAAR;EACE,KAAK;GACH,aAAa,KAAK,4BAA4B,SAAS;GACvD,gBAAgB,KAAK,gBAAgB;GACrC;EACF,KAAK;GACH,aAAa,KAAK,4BAA4B,SAAS;GACvD;EACF,KAAK;GACH,aAAa,KAAK,qBAAqB,MAAM;GAC7C;EACF,KAAK;GAEH,gBAAgB,KAAK,YAAY;GACjC,QAAQ,gBAAgB;GACxB,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB;EACF,KAAK;GACH,QAAQ,gBAAgB;GACxB,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB;EACF,KAAK;GACH,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,mBAAmB;GACxC;EACF,KAAK,sBAAsB;GAEzB,MAAM,YAAY,gBAAgB,QAAQ,MAAM,MAAM,KAAK;GAC3D,UAAU,KAAK,YAAY,2BAA2B;GACtD,gBAAgB,SAAS;GACzB,gBAAgB,KAAK,GAAG,SAAS;GACjC,QAAQ,gBAAgB;GACxB,QAAQ,SAAS;GACjB;EACF;EACA,KAAK;GACH,aAAa,KAAK,QAAQ,oBAAoB;GAC9C;EACF,KAAK;GACH,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,cAAc;GACnC;EACF,KAAK;GACH,aAAa,KAAK,QAAQ,oBAAoB,iCAAiC;GAC/E;EAGF,SACE,aAAa,KAAK,mBAAmB;CAEzC;CAEA,OAAO;EAAE;EAAc;EAAiB;CAAQ;AAClD;AAEA,SAAgB,gBAAgB,KAAqC;CACnE,MAAM,OAAO,aAAa,IAAI,IAAI;CAClC,MAAM,SAAS,cAAc,GAAG;CAEhC,MAAM,eAAe,CAAC,GAAG,KAAK,YAAY;CAC1C,MAAM,kBAAkB,CAAC,GAAG,KAAK,eAAe;CAChD,MAAM,UAAU,EAAE,GAAG,KAAK,QAAQ;CAElC,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 type { PackageGroups, ProjectType, ScaffoldContext } from \"../core/types.js\";\n\nfunction typePackages(type: ProjectType): PackageGroups {\n const dependencies = [\"@taserjs/router\", \"dotenv\"];\n const devDependencies = [\n \"@taserjs/router-cli\",\n \"npm-run-all2\",\n \"tsdown\",\n \"tsx\",\n \"typescript@^5.9.3\",\n \"@types/node\",\n ];\n const scripts: Record<string, string> = {};\n\n switch (type) {\n case \"express\":\n dependencies.push(\"@taserjs/adapter-express\", \"express\");\n devDependencies.push(\"@types/express\");\n break;\n case \"fastify\":\n dependencies.push(\"@taserjs/adapter-fastify\", \"fastify\");\n break;\n case \"hono\":\n dependencies.push(\"@hono/node-server\", \"hono\");\n break;\n case \"bun\":\n // Bun has native TypeScript and runtime execution\n devDependencies.push(\"@types/bun\");\n scripts[\"dev:server\"] = \"bun --watch src/index.ts\";\n scripts.start = \"bun src/index.ts\";\n scripts.serve = \"bun dist/index.mjs\";\n break;\n case \"deno\":\n scripts[\"dev:server\"] = \"deno run --watch --allow-net --allow-env --allow-read src/index.ts\";\n scripts.start = \"deno run --allow-net --allow-env --allow-read src/index.ts\";\n scripts.serve = \"deno run --allow-net --allow-env --allow-read dist/index.mjs\";\n break;\n case \"aws-lambda\":\n dependencies.push(\"hono\");\n devDependencies.push(\"@types/aws-lambda\");\n break;\n case \"cloudflare-workers\": {\n // Cloudflare workers uses wrangler\n const cfDevDeps = devDependencies.filter((d) => d !== \"tsx\");\n cfDevDeps.push(\"wrangler\", \"@cloudflare/workers-types\");\n devDependencies.length = 0;\n devDependencies.push(...cfDevDeps);\n scripts[\"dev:server\"] = \"wrangler dev\";\n scripts.deploy = \"wrangler deploy\";\n break;\n }\n case \"netlify\":\n dependencies.push(\"hono\", \"@netlify/functions\");\n break;\n case \"vercel\":\n dependencies.push(\"hono\");\n devDependencies.push(\"@vercel/node\");\n break;\n case \"azure-functions\":\n dependencies.push(\"hono\", \"@azure/functions\", \"@marplex/hono-azurefunc-adapter\");\n break;\n case \"google-cloud-run\":\n case \"node\":\n default:\n dependencies.push(\"@hono/node-server\");\n break;\n }\n\n return { dependencies, devDependencies, scripts };\n}\n\nexport function resolvePackages(ctx: ScaffoldContext): PackageGroups {\n const base = typePackages(ctx.type);\n const addons = resolveAddons(ctx);\n\n const dependencies = [...base.dependencies];\n const devDependencies = [...base.devDependencies];\n const scripts = { ...base.scripts };\n\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\nexport function getPackageGroups(\n type: ProjectType,\n): Omit<PackageGroups, \"scripts\"> & { scripts?: Record<string, string> } {\n const groups = typePackages(type);\n return groups;\n}\n"],"mappings":";;AAGA,SAAS,aAAa,MAAkC;CACtD,MAAM,eAAe,CAAC,mBAAmB,QAAQ;CACjD,MAAM,kBAAkB;EACtB;EACA;EACA;EACA;EACA;EACA;CACF;CACA,MAAM,UAAkC,CAAC;CAEzC,QAAQ,MAAR;EACE,KAAK;GACH,aAAa,KAAK,4BAA4B,SAAS;GACvD,gBAAgB,KAAK,gBAAgB;GACrC;EACF,KAAK;GACH,aAAa,KAAK,4BAA4B,SAAS;GACvD;EACF,KAAK;GACH,aAAa,KAAK,qBAAqB,MAAM;GAC7C;EACF,KAAK;GAEH,gBAAgB,KAAK,YAAY;GACjC,QAAQ,gBAAgB;GACxB,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB;EACF,KAAK;GACH,QAAQ,gBAAgB;GACxB,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB;EACF,KAAK;GACH,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,mBAAmB;GACxC;EACF,KAAK,sBAAsB;GAEzB,MAAM,YAAY,gBAAgB,QAAQ,MAAM,MAAM,KAAK;GAC3D,UAAU,KAAK,YAAY,2BAA2B;GACtD,gBAAgB,SAAS;GACzB,gBAAgB,KAAK,GAAG,SAAS;GACjC,QAAQ,gBAAgB;GACxB,QAAQ,SAAS;GACjB;EACF;EACA,KAAK;GACH,aAAa,KAAK,QAAQ,oBAAoB;GAC9C;EACF,KAAK;GACH,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,cAAc;GACnC;EACF,KAAK;GACH,aAAa,KAAK,QAAQ,oBAAoB,iCAAiC;GAC/E;EAGF,SACE,aAAa,KAAK,mBAAmB;CAEzC;CAEA,OAAO;EAAE;EAAc;EAAiB;CAAQ;AAClD;AAEA,SAAgB,gBAAgB,KAAqC;CACnE,MAAM,OAAO,aAAa,IAAI,IAAI;CAClC,MAAM,SAAS,cAAc,GAAG;CAEhC,MAAM,eAAe,CAAC,GAAG,KAAK,YAAY;CAC1C,MAAM,kBAAkB,CAAC,GAAG,KAAK,eAAe;CAChD,MAAM,UAAU,EAAE,GAAG,KAAK,QAAQ;CAElC,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"}
@@ -67,33 +67,13 @@ async function scaffoldProject(options) {
67
67
  await copyFile(path.join(root, ".env.example"), path.join(root, ".env"));
68
68
  } catch {}
69
69
  await writeProjectConfig(root, ctx);
70
- if (options.skipInstall) return {
71
- projectName: ctx.projectName,
72
- targetDir: root,
73
- type: ctx.type,
74
- ...ctx.db ? {
75
- db: ctx.db,
76
- driver: ctx.driver
77
- } : {},
78
- ...ctx.logger ? { logger: ctx.logger } : {},
79
- ...ctx.validator ? { validator: ctx.validator } : {}
80
- };
70
+ if (options.skipInstall) return ctx;
81
71
  const agent = options.agent ?? resolveUserAgent();
82
72
  await installPackages(agent, root, {
83
73
  dependencies: packages.dependencies,
84
74
  devDependencies: packages.devDependencies
85
75
  });
86
- return {
87
- projectName: ctx.projectName,
88
- targetDir: root,
89
- type: ctx.type,
90
- ...ctx.db ? {
91
- db: ctx.db,
92
- driver: ctx.driver
93
- } : {},
94
- ...ctx.logger ? { logger: ctx.logger } : {},
95
- ...ctx.validator ? { validator: ctx.validator } : {}
96
- };
76
+ return ctx;
97
77
  }
98
78
  //#endregion
99
79
  export { scaffoldProject };
@@ -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 { indexTemplate, taserTsTemplate } from \"../frameworks/index.js\";\nimport { installPackages, resolveUserAgent } from \"./package-manager.js\";\nimport { writeProjectConfig } from \"./project-config.js\";\nimport { resolvePackages } from \"./resolve-packages.js\";\nimport type { ScaffoldOptions, ScaffoldResult } from \"./types.js\";\nimport {\n contextTemplate,\n gitignoreTemplate,\n healthRouteTemplate,\n indexRouteTemplate,\n packageJsonTemplate,\n rootLayoutTemplate,\n starterManifestTemplate,\n tsconfigTemplate,\n tsdownConfigTemplate,\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 ctx = {\n projectName: options.projectName,\n targetDir: root,\n type: options.type,\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\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, \"tsdown.config.ts\"), tsdownConfigTemplate());\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(options.type));\n await write(path.join(root, \"src/index.ts\"), indexTemplate(options.type));\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 await write(path.join(root, \"src/routeManifest.gen.ts\"), starterManifestTemplate());\n\n if (options.type === \"cloudflare-workers\") {\n await write(\n path.join(root, \"wrangler.jsonc\"),\n JSON.stringify(\n {\n $schema: \"node_modules/wrangler/config-schema.json\",\n name: options.projectName,\n main: \"src/index.ts\",\n compatibility_date: \"2024-11-01\",\n },\n null,\n 2,\n ) + \"\\n\",\n );\n }\n\n if (options.type === \"vercel\") {\n await write(\n path.join(root, \"vercel.json\"),\n JSON.stringify(\n {\n rewrites: [{ source: \"/(.*)\", destination: \"/src/index.ts\" }],\n },\n null,\n 2,\n ) + \"\\n\",\n );\n }\n\n if (options.type === \"azure-functions\") {\n await write(\n path.join(root, \"host.json\"),\n JSON.stringify(\n {\n version: \"2.0\",\n logging: {\n applicationInsights: {\n samplingSettings: {\n isEnabled: true,\n excludedTypes: \"Request\",\n },\n },\n },\n extensionBundle: {\n id: \"Microsoft.Azure.Functions.ExtensionBundle\",\n version: \"[4.*, 5.0.0)\",\n },\n extensions: {\n http: {\n routePrefix: \"\",\n },\n },\n },\n null,\n 2,\n ) + \"\\n\",\n );\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 {\n projectName: ctx.projectName,\n targetDir: root,\n type: ctx.type,\n ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),\n ...(ctx.logger ? { logger: ctx.logger } : {}),\n ...(ctx.validator ? { validator: ctx.validator } : {}),\n };\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 {\n projectName: ctx.projectName,\n targetDir: root,\n type: ctx.type,\n ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),\n ...(ctx.logger ? { logger: ctx.logger } : {}),\n ...(ctx.validator ? { validator: ctx.validator } : {}),\n };\n}\n"],"mappings":";;;;;;;;;AAqBA,eAAe,MAAM,UAAkB,UAAiC;CACtE,MAAM,MAAM,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;CACvD,MAAM,UAAU,UAAU,UAAU,MAAM;AAC5C;AAEA,eAAsB,gBAAgB,SAAmD;CACvF,MAAM,OAAO,QAAQ;CACrB,MAAM,MAAM;EACV,aAAa,QAAQ;EACrB,WAAW;EACX,MAAM,QAAQ;EACd,GAAI,QAAQ,KAAK;GAAE,IAAI,QAAQ;GAAI,QAAQ,QAAQ;EAAO,IAAI,CAAC;EAC/D,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EACnD,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;CAC9D;CAEA,MAAM,SAAS,cAAc,GAAG;CAChC,MAAM,WAAW,gBAAgB,GAAG;CACpC,MAAM,eAAe,oBAAoB,GAAG;CAE5C,MAAM,MACJ,KAAK,KAAK,MAAM,cAAc,GAC9B,oBAAoB,QAAQ,aAAa,SAAS,OAAO,CAC3D;CACA,MAAM,MAAM,KAAK,KAAK,MAAM,eAAe,GAAG,iBAAiB,CAAC;CAChE,MAAM,MAAM,KAAK,KAAK,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;CACvE,MAAM,MAAM,KAAK,KAAK,MAAM,YAAY,GAAG,kBAAkB,CAAC;CAC9D,MAAM,MAAM,KAAK,KAAK,MAAM,gBAAgB,GAAG,gBAAgB,YAAY,CAAC;CAC5E,MAAM,MAAM,KAAK,KAAK,MAAM,cAAc,GAAG,gBAAgB,QAAQ,IAAI,CAAC;CAC1E,MAAM,MAAM,KAAK,KAAK,MAAM,cAAc,GAAG,cAAc,QAAQ,IAAI,CAAC;CACxE,MAAM,MAAM,KAAK,KAAK,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;CACpE,MAAM,MAAM,KAAK,KAAK,MAAM,yBAAyB,GAAG,mBAAmB,CAAC;CAC5E,MAAM,MAAM,KAAK,KAAK,MAAM,0BAA0B,GAAG,oBAAoB,GAAG,CAAC;CACjF,MAAM,MAAM,KAAK,KAAK,MAAM,0BAA0B,GAAG,wBAAwB,CAAC;CAElF,IAAI,QAAQ,SAAS,sBACnB,MAAM,MACJ,KAAK,KAAK,MAAM,gBAAgB,GAChC,KAAK,UACH;EACE,SAAS;EACT,MAAM,QAAQ;EACd,MAAM;EACN,oBAAoB;CACtB,GACA,MACA,CACF,IAAI,IACN;CAGF,IAAI,QAAQ,SAAS,UACnB,MAAM,MACJ,KAAK,KAAK,MAAM,aAAa,GAC7B,KAAK,UACH,EACE,UAAU,CAAC;EAAE,QAAQ;EAAS,aAAa;CAAgB,CAAC,EAC9D,GACA,MACA,CACF,IAAI,IACN;CAGF,IAAI,QAAQ,SAAS,mBACnB,MAAM,MACJ,KAAK,KAAK,MAAM,WAAW,GAC3B,KAAK,UACH;EACE,SAAS;EACT,SAAS,EACP,qBAAqB,EACnB,kBAAkB;GAChB,WAAW;GACX,eAAe;EACjB,EACF,EACF;EACA,iBAAiB;GACf,IAAI;GACJ,SAAS;EACX;EACA,YAAY,EACV,MAAM,EACJ,aAAa,GACf,EACF;CACF,GACA,MACA,CACF,IAAI,IACN;CAGF,MAAM,QAAQ,IACZ,OAAO,IAAI,OAAO,UAAU;EAC1B,MAAM,MAAM,MAAM,MAAM,UAAU,aAAa,MAAM,KAAK,KAAK,MAAM,QAAQ,GAAG,QAAQ,CAAC;CAC3F,CAAC,CACH;CAEA,IAAI;EACF,MAAM,SAAS,KAAK,KAAK,MAAM,cAAc,GAAG,KAAK,KAAK,MAAM,MAAM,CAAC;CACzE,QAAQ,CAER;CAEA,MAAM,mBAAmB,MAAM,GAAG;CAElC,IAAI,QAAQ,aACV,OAAO;EACL,aAAa,IAAI;EACjB,WAAW;EACX,MAAM,IAAI;EACV,GAAI,IAAI,KAAK;GAAE,IAAI,IAAI;GAAI,QAAQ,IAAI;EAAO,IAAI,CAAC;EACnD,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;EAC3C,GAAI,IAAI,YAAY,EAAE,WAAW,IAAI,UAAU,IAAI,CAAC;CACtD;CAGF,MAAM,QAAQ,QAAQ,SAAS,iBAAiB;CAChD,MAAM,gBAAgB,OAAO,MAAM;EACjC,cAAc,SAAS;EACvB,iBAAiB,SAAS;CAC5B,CAAC;CAED,OAAO;EACL,aAAa,IAAI;EACjB,WAAW;EACX,MAAM,IAAI;EACV,GAAI,IAAI,KAAK;GAAE,IAAI,IAAI;GAAI,QAAQ,IAAI;EAAO,IAAI,CAAC;EACnD,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;EAC3C,GAAI,IAAI,YAAY,EAAE,WAAW,IAAI,UAAU,IAAI,CAAC;CACtD;AACF"}
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 { indexTemplate, taserTsTemplate } from \"../frameworks/index.js\";\nimport { installPackages, resolveUserAgent } from \"./package-manager.js\";\nimport { writeProjectConfig } from \"./project-config.js\";\nimport { resolvePackages } from \"./resolve-packages.js\";\nimport type { ScaffoldOptions, ScaffoldResult } from \"./types.js\";\nimport {\n contextTemplate,\n gitignoreTemplate,\n healthRouteTemplate,\n indexRouteTemplate,\n packageJsonTemplate,\n rootLayoutTemplate,\n starterManifestTemplate,\n tsconfigTemplate,\n tsdownConfigTemplate,\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 ctx = {\n projectName: options.projectName,\n targetDir: root,\n type: options.type,\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\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, \"tsdown.config.ts\"), tsdownConfigTemplate());\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(options.type));\n await write(path.join(root, \"src/index.ts\"), indexTemplate(options.type));\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 await write(path.join(root, \"src/routeManifest.gen.ts\"), starterManifestTemplate());\n\n if (options.type === \"cloudflare-workers\") {\n await write(\n path.join(root, \"wrangler.jsonc\"),\n JSON.stringify(\n {\n $schema: \"node_modules/wrangler/config-schema.json\",\n name: options.projectName,\n main: \"src/index.ts\",\n compatibility_date: \"2024-11-01\",\n },\n null,\n 2,\n ) + \"\\n\",\n );\n }\n\n if (options.type === \"vercel\") {\n await write(\n path.join(root, \"vercel.json\"),\n JSON.stringify(\n {\n rewrites: [{ source: \"/(.*)\", destination: \"/src/index.ts\" }],\n },\n null,\n 2,\n ) + \"\\n\",\n );\n }\n\n if (options.type === \"azure-functions\") {\n await write(\n path.join(root, \"host.json\"),\n JSON.stringify(\n {\n version: \"2.0\",\n logging: {\n applicationInsights: {\n samplingSettings: {\n isEnabled: true,\n excludedTypes: \"Request\",\n },\n },\n },\n extensionBundle: {\n id: \"Microsoft.Azure.Functions.ExtensionBundle\",\n version: \"[4.*, 5.0.0)\",\n },\n extensions: {\n http: {\n routePrefix: \"\",\n },\n },\n },\n null,\n 2,\n ) + \"\\n\",\n );\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,3 +1,3 @@
1
1
  import { ProjectType } from '../core/types.js';
2
2
  export declare function indexTemplate(type: ProjectType): string;
3
- export declare function taserTsTemplate(type?: ProjectType): string;
3
+ export declare function taserTsTemplate(_type?: ProjectType): string;
@@ -31,7 +31,7 @@ import { t } from '#src/taser.js'
31
31
  const router = t.create(routeManifest)
32
32
 
33
33
  const app = new Hono()
34
- app.all('/*', c => router.native(c).fetch(c.req.raw))
34
+ app.all('/*', c => router.fetch(c.req.raw))
35
35
 
36
36
  const port = Number(process.env.PORT ?? 3000)
37
37
  serve({ fetch: app.fetch, port }, () => {
@@ -93,7 +93,7 @@ import { t } from '#src/taser.js'
93
93
  const router = t.create(routeManifest)
94
94
 
95
95
  const app = new Hono()
96
- app.all('/*', c => router.native(c).fetch(c.req.raw))
96
+ app.all('/*', c => router.fetch(c.req.raw))
97
97
 
98
98
  export const handler = handle(app)
99
99
  `;
@@ -121,7 +121,7 @@ import { t } from '#src/taser.js'
121
121
  const router = t.create(routeManifest)
122
122
 
123
123
  const app = new Hono()
124
- app.all('/*', c => router.native(c).fetch(c.req.raw))
124
+ app.all('/*', c => router.fetch(c.req.raw))
125
125
 
126
126
  export default handle(app)
127
127
  `;
@@ -136,7 +136,7 @@ import { t } from '#src/taser.js'
136
136
  const router = t.create(routeManifest)
137
137
 
138
138
  const app = new Hono()
139
- app.all('/*', c => router.native(c).fetch(c.req.raw))
139
+ app.all('/*', c => router.fetch(c.req.raw))
140
140
 
141
141
  export default handle(app)
142
142
  `;
@@ -152,7 +152,7 @@ import { t } from '#src/taser.js'
152
152
  const router = t.create(routeManifest)
153
153
 
154
154
  const honoApp = new Hono()
155
- honoApp.all('/*', c => router.native(c).fetch(c.req.raw))
155
+ honoApp.all('/*', c => router.fetch(c.req.raw))
156
156
 
157
157
  app.http('httpTrigger', {
158
158
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],
@@ -191,33 +191,14 @@ serve({ fetch: router.fetch, port }, () => {
191
191
  `;
192
192
  }
193
193
  }
194
- function taserTsTemplate(type = "node") {
195
- if (type === "hono" || type === "aws-lambda" || type === "netlify" || type === "vercel" || type === "azure-functions") return `import type { Context } from 'hono'
196
- import { createTaserApp, type InferAppContext } from '@taserjs/router'
194
+ function taserTsTemplate(_type = "node") {
195
+ return `import { createTaserApp } from '@taserjs/router'
197
196
 
198
197
  import { context } from '#src/context.js'
199
198
 
200
- declare module '@taserjs/router' {
201
- interface RouterRegister {
202
- NativeContext: Context
203
- }
204
- }
205
-
206
199
  export const t = createTaserApp({
207
200
  response: { validate: true },
208
201
  }).context(context)
209
-
210
- export type AppContext = InferAppContext<typeof context>
211
- `;
212
- return `import { createTaserApp, type InferAppContext } from '@taserjs/router'
213
-
214
- import { context } from '#src/context.js'
215
-
216
- export const t = createTaserApp({
217
- response: { validate: true },
218
- }).context(context)
219
-
220
- export type AppContext = InferAppContext<typeof context>
221
202
  `;
222
203
  }
223
204
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { ProjectType } from \"../core/types.js\";\n\nexport function indexTemplate(type: ProjectType): string {\n switch (type) {\n case \"express\":\n return `import 'dotenv/config'\n\nimport express from 'express'\nimport { createExpressHandler } from '@taserjs/adapter-express'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createExpressHandler(router)\nconst app = express()\ntaser.mount('/{*splat}', app)\n\nconst port = Number(process.env.PORT ?? 3000)\napp.listen(port, () => {\n console.log(\\`Express listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"hono\":\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\nimport { Hono } from 'hono'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.native(c).fetch(c.req.raw))\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: app.fetch, port }, () => {\n console.log(\\`Hono listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"fastify\":\n return `import 'dotenv/config'\n\nimport Fastify from 'fastify'\nimport { createFastifyHandler } from '@taserjs/adapter-fastify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createFastifyHandler(router)\nconst app = Fastify()\ntaser.mount('/*', app)\n\nconst port = Number(process.env.PORT ?? 3000)\nawait app.listen({ port })\nconsole.log(\\`Fastify listening on http://localhost:\\${port}\\`)\n`;\n case \"bun\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 3000)\n\nexport default {\n port,\n fetch(request: Request) {\n return router.fetch(request)\n },\n}\n`;\n case \"deno\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 8000)\nDeno.serve({ port }, (request: Request) => router.fetch(request))\n`;\n case \"aws-lambda\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/aws-lambda'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.native(c).fetch(c.req.raw))\n\nexport const handler = handle(app)\n`;\n case \"cloudflare-workers\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nexport default {\n fetch(request: Request, env: unknown, ctx: unknown) {\n return router.fetch(request, env, ctx)\n },\n}\n`;\n case \"netlify\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/netlify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.native(c).fetch(c.req.raw))\n\nexport default handle(app)\n`;\n case \"vercel\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/vercel'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.native(c).fetch(c.req.raw))\n\nexport default handle(app)\n`;\n case \"azure-functions\":\n return `import 'dotenv/config'\n\nimport { app } from '@azure/functions'\nimport { Hono } from 'hono'\nimport { azureHonoHandler } from '@marplex/hono-azurefunc-adapter'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst honoApp = new Hono()\nhonoApp.all('/*', c => router.native(c).fetch(c.req.raw))\n\napp.http('httpTrigger', {\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],\n authLevel: 'anonymous',\n route: '{*proxy}',\n handler: azureHonoHandler(honoApp.fetch),\n})\n`;\n case \"google-cloud-run\":\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 8080)\nserve({ fetch: router.fetch, port }, () => {\n console.log(\\`Cloud Run listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"node\":\n default:\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: router.fetch, port }, () => {\n console.log(\\`Node listening on http://localhost:\\${port}\\`)\n})\n`;\n }\n}\n\nexport function taserTsTemplate(type: ProjectType = \"node\"): string {\n if (\n type === \"hono\" ||\n type === \"aws-lambda\" ||\n type === \"netlify\" ||\n type === \"vercel\" ||\n type === \"azure-functions\"\n ) {\n return `import type { Context } from 'hono'\nimport { createTaserApp, type InferAppContext } from '@taserjs/router'\n\nimport { context } from '#src/context.js'\n\ndeclare module '@taserjs/router' {\n interface RouterRegister {\n NativeContext: Context\n }\n}\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n\nexport type AppContext = InferAppContext<typeof context>\n`;\n }\n\n return `import { createTaserApp, type InferAppContext } from '@taserjs/router'\n\nimport { context } from '#src/context.js'\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n\nexport type AppContext = InferAppContext<typeof context>\n`;\n}\n"],"mappings":";AAEA,SAAgB,cAAc,MAA2B;CACvD,QAAQ,MAAR;EACE,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;;;EAmBT,KAAK,QACH,OAAO;;;;;;;;;;;;;;;;;;EAkBT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;;EAkBT,KAAK,OACH,OAAO;;;;;;;;;;;;;;;;EAgBT,KAAK,QACH,OAAO;;;;;;;;;;EAUT,KAAK,cACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,sBACH,OAAO;;;;;;;;;;;;;EAaT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,UACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,mBACH,OAAO;;;;;;;;;;;;;;;;;;;;;EAqBT,KAAK,oBACH,OAAO;;;;;;;;;;;;;;EAeT,SACE,OAAO;;;;;;;;;;;;;;CAcX;AACF;AAEA,SAAgB,gBAAgB,OAAoB,QAAgB;CAClE,IACE,SAAS,UACT,SAAS,gBACT,SAAS,aACT,SAAS,YACT,SAAS,mBAET,OAAO;;;;;;;;;;;;;;;;;CAmBT,OAAO;;;;;;;;;;AAUT"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { ProjectType } from \"../core/types.js\";\n\nexport function indexTemplate(type: ProjectType): string {\n switch (type) {\n case \"express\":\n return `import 'dotenv/config'\n\nimport express from 'express'\nimport { createExpressHandler } from '@taserjs/adapter-express'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createExpressHandler(router)\nconst app = express()\ntaser.mount('/{*splat}', app)\n\nconst port = Number(process.env.PORT ?? 3000)\napp.listen(port, () => {\n console.log(\\`Express listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"hono\":\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\nimport { Hono } from 'hono'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.fetch(c.req.raw))\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: app.fetch, port }, () => {\n console.log(\\`Hono listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"fastify\":\n return `import 'dotenv/config'\n\nimport Fastify from 'fastify'\nimport { createFastifyHandler } from '@taserjs/adapter-fastify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createFastifyHandler(router)\nconst app = Fastify()\ntaser.mount('/*', app)\n\nconst port = Number(process.env.PORT ?? 3000)\nawait app.listen({ port })\nconsole.log(\\`Fastify listening on http://localhost:\\${port}\\`)\n`;\n case \"bun\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 3000)\n\nexport default {\n port,\n fetch(request: Request) {\n return router.fetch(request)\n },\n}\n`;\n case \"deno\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 8000)\nDeno.serve({ port }, (request: Request) => router.fetch(request))\n`;\n case \"aws-lambda\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/aws-lambda'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.fetch(c.req.raw))\n\nexport const handler = handle(app)\n`;\n case \"cloudflare-workers\":\n return `import 'dotenv/config'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nexport default {\n fetch(request: Request, env: unknown, ctx: unknown) {\n return router.fetch(request, env, ctx)\n },\n}\n`;\n case \"netlify\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/netlify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.fetch(c.req.raw))\n\nexport default handle(app)\n`;\n case \"vercel\":\n return `import 'dotenv/config'\n\nimport { Hono } from 'hono'\nimport { handle } from 'hono/vercel'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\napp.all('/*', c => router.fetch(c.req.raw))\n\nexport default handle(app)\n`;\n case \"azure-functions\":\n return `import 'dotenv/config'\n\nimport { app } from '@azure/functions'\nimport { Hono } from 'hono'\nimport { azureHonoHandler } from '@marplex/hono-azurefunc-adapter'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst honoApp = new Hono()\nhonoApp.all('/*', c => router.fetch(c.req.raw))\n\napp.http('httpTrigger', {\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],\n authLevel: 'anonymous',\n route: '{*proxy}',\n handler: azureHonoHandler(honoApp.fetch),\n})\n`;\n case \"google-cloud-run\":\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 8080)\nserve({ fetch: router.fetch, port }, () => {\n console.log(\\`Cloud Run listening on http://localhost:\\${port}\\`)\n})\n`;\n case \"node\":\n default:\n return `import 'dotenv/config'\n\nimport { serve } from '@hono/node-server'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: router.fetch, port }, () => {\n console.log(\\`Node listening on http://localhost:\\${port}\\`)\n})\n`;\n }\n}\n\nexport function taserTsTemplate(_type: ProjectType = \"node\"): string {\n return `import { createTaserApp } from '@taserjs/router'\n\nimport { context } from '#src/context.js'\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n`;\n}\n"],"mappings":";AAEA,SAAgB,cAAc,MAA2B;CACvD,QAAQ,MAAR;EACE,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;;;EAmBT,KAAK,QACH,OAAO;;;;;;;;;;;;;;;;;;EAkBT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;;EAkBT,KAAK,OACH,OAAO;;;;;;;;;;;;;;;;EAgBT,KAAK,QACH,OAAO;;;;;;;;;;EAUT,KAAK,cACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,sBACH,OAAO;;;;;;;;;;;;;EAaT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,UACH,OAAO;;;;;;;;;;;;;;;EAeT,KAAK,mBACH,OAAO;;;;;;;;;;;;;;;;;;;;;EAqBT,KAAK,oBACH,OAAO;;;;;;;;;;;;;;EAeT,SACE,OAAO;;;;;;;;;;;;;;CAcX;AACF;AAEA,SAAgB,gBAAgB,QAAqB,QAAgB;CACnE,OAAO;;;;;;;;AAQT"}
@@ -73,21 +73,22 @@ ${bootBlock}
73
73
  `;
74
74
  }
75
75
  function rootLayoutTemplate() {
76
- return `import { bodyLimit } from '@taserjs/router/body-limit'
77
- import { secureHeaders } from '@taserjs/router/secure-headers'
76
+ return `import { cors } from '@taserjs/router/cors'
78
77
 
79
78
  import { t } from '#src/taser.js'
80
79
 
81
80
  export const Middleware = t.middleware('/$')
82
- .use(secureHeaders())
83
- .use(bodyLimit({ maxSize: 1_000_000 }))
81
+ .use(cors())
84
82
  `;
85
83
  }
86
84
  function indexRouteTemplate() {
87
85
  return `import { reply } from '@taserjs/router'
88
86
  import { t } from '#src/taser.js'
89
87
 
90
- export const Route = t.get('/').handler(() => {
88
+ const GET = t.get('/')
89
+
90
+ export type RouteContext = typeof GET.$Infer.Context
91
+ export const Route = GET.handler((_ctx) => {
91
92
  return reply.json({ message: 'Welcome to Taser' })
92
93
  })
93
94
  `;
@@ -100,7 +101,10 @@ function healthRouteTemplate(ctx) {
100
101
  return `import { reply } from '@taserjs/router'
101
102
  import { t } from '#src/taser.js'
102
103
 
103
- export const Route = t.get('/health').handler(${lines.length > 0 ? "(ctx)" : "()"} => {
104
+ const GET = t.get('/health')
105
+
106
+ export type RouteContext = typeof GET.$Infer.Context
107
+ export const Route = GET.handler(${lines.length > 0 ? "(ctx)" : "(_ctx)"} => {
104
108
  ${body} return reply.json({ ok: true })
105
109
  })
106
110
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":[],"sources":["../../../src/templates/base.ts"],"sourcesContent":["import type { BootBinding } from \"../addons/types.js\";\nimport type { ScaffoldContext } from \"../core/types.js\";\n\nexport function packageJsonTemplate(\n projectName: string,\n scripts: Record<string, string> = {},\n): string {\n const pkg = {\n name: projectName,\n version: \"1.0.0\",\n private: true,\n type: \"module\",\n imports: {\n \"#src/*\": \"./src/*\",\n },\n scripts: {\n dev: \"run-p dev:server dev:taser\",\n \"dev:server\": \"tsx watch src/index.ts\",\n \"dev:taser\": \"taser watch\",\n start: \"tsx src/index.ts\",\n generate: \"taser generate\",\n build: \"taser generate && tsdown\",\n serve: \"node dist/index.mjs\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsdownConfigTemplate(): string {\n return `import { defineConfig } from 'tsdown'\n\nexport default defineConfig({\n entry: ['./src/index.ts'],\n platform: 'node',\n outDir: 'dist',\n clean: true,\n sourcemap: true,\n})\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n paths: {\n \"#src/*\": [\"./src/*\"],\n },\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n types: [\"node\"],\n },\n include: [\"src\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.DS_Store\n*.log\n.env\nlocal.db\ndrizzle\n`;\n}\n\nexport function contextTemplate(bindings: BootBinding[]): string {\n const imports = bindings.map(\n (binding) => `import { ${binding.factoryName} } from '${binding.importPath}'`,\n );\n\n const bootBody =\n bindings.length > 0\n ? bindings.map((binding) => ` ${binding.key}: ${binding.factoryName}(),`).join(\"\\n\")\n : \"\";\n\n const bootBlock = bindings.length > 0 ? ` boot: () => ({\\n${bootBody}\\n }),` : \"\";\n\n const importBlock = imports.length > 0 ? `${imports.join(\"\\n\")}\\n\\n` : \"\";\n\n return `${importBlock}import { createContext } from '@taserjs/router'\n\nexport const context = createContext({\n${bootBlock}\n request: () => ({\n requestId: crypto.randomUUID(),\n }),\n})\n`;\n}\n\nexport function rootLayoutTemplate(): string {\n return `import { bodyLimit } from '@taserjs/router/body-limit'\nimport { secureHeaders } from '@taserjs/router/secure-headers'\n\nimport { t } from '#src/taser.js'\n\nexport const Middleware = t.middleware('/$')\n .use(secureHeaders())\n .use(bodyLimit({ maxSize: 1_000_000 }))\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n\nexport const Route = t.get('/').handler(() => {\n return reply.json({ message: 'Welcome to Taser' })\n})\n`;\n}\n\nexport function healthRouteTemplate(ctx: ScaffoldContext): string {\n const lines: string[] = [];\n\n if (ctx.logger) {\n lines.push(\" ctx.logger.info('health check')\");\n }\n\n if (ctx.db) {\n lines.push(\" // ctx.db is available from context boot\");\n }\n\n const body = lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n const ctxArg = lines.length > 0 ? \"(ctx)\" : \"()\";\n\n return `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n\nexport const Route = t.get('/health').handler(${ctxArg} => {\n${body} return reply.json({ ok: true })\n})\n`;\n}\n\n/** Minimal placeholder until `taser generate` runs. */\nexport function starterManifestTemplate(): string {\n return `/* eslint-disable */\n// Run \\`pnpm generate\\` (taser generate) to replace this file.\nimport { Middleware as RootSplatLayoutImport } from './routes/$.js'\nimport { Route as RootIndexGetRouteImport } from './routes/index.get.js'\nimport { Route as HealthGetRouteImport } from './routes/health.get.js'\n\nexport const routeManifest = {\n layouts: {\n '/$': {\n middlewares: RootSplatLayoutImport,\n },\n },\n routes: {\n '/': {\n GET: {\n layoutChain: ['/$'],\n route: RootIndexGetRouteImport,\n },\n },\n '/health': {\n GET: {\n layoutChain: ['/$'],\n route: HealthGetRouteImport,\n },\n },\n },\n} as const\n\nexport type RoutePathGen = '/' | '/health'\nexport type LayoutIdGen = '/$'\nexport type LayoutTreeGen = {\n '/$': {\n parent: null\n middlewares: typeof RootSplatLayoutImport\n }\n}\nexport type RouteByPathMethodGen = {\n '/': {\n GET: {\n parent: '/$'\n layoutChain: ['/$']\n route: typeof RootIndexGetRouteImport\n }\n }\n '/health': {\n GET: {\n parent: '/$'\n layoutChain: ['/$']\n route: typeof HealthGetRouteImport\n }\n }\n}\nexport type RouteManifest = typeof routeManifest\n\ndeclare module '@taserjs/router' {\n interface RouterRegister {\n RoutePath: RoutePathGen\n LayoutId: LayoutIdGen\n LayoutTree: LayoutTreeGen\n RouteByPathMethod: RouteByPathMethodGen\n }\n}\n`;\n}\n"],"mappings":";AAGA,SAAgB,oBACd,aACA,UAAkC,CAAC,GAC3B;CACR,MAAM,MAAM;EACV,MAAM;EACN,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS,EACP,UAAU,UACZ;EACA,SAAS;GACP,KAAK;GACL,cAAc;GACd,aAAa;GACb,OAAO;GACP,UAAU;GACV,OAAO;GACP,OAAO;GACP,WAAW;GACX,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,uBAA+B;CAC7C,OAAO;;;;;;;;;;AAUT;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,OAAO,EACL,UAAU,CAAC,SAAS,EACtB;GACA,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;GACR,OAAO,CAAC,MAAM;EAChB;EACA,SAAS,CAAC,KAAK;CACjB,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;AAQT;AAEA,SAAgB,gBAAgB,UAAiC;CAC/D,MAAM,UAAU,SAAS,KACtB,YAAY,YAAY,QAAQ,YAAY,WAAW,QAAQ,WAAW,EAC7E;CAEA,MAAM,WACJ,SAAS,SAAS,IACd,SAAS,KAAK,YAAY,OAAO,QAAQ,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC,CAAC,KAAK,IAAI,IACpF;CAEN,MAAM,YAAY,SAAS,SAAS,IAAI,qBAAqB,SAAS,WAAW;CAIjF,OAAO,GAFa,QAAQ,SAAS,IAAI,GAAG,QAAQ,KAAK,IAAI,EAAE,QAAQ,GAEjD;;;EAGtB,UAAU;;;;;;AAMZ;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;;;AAST;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;AAOT;AAEA,SAAgB,oBAAoB,KAA8B;CAChE,MAAM,QAAkB,CAAC;CAEzB,IAAI,IAAI,QACN,MAAM,KAAK,mCAAmC;CAGhD,IAAI,IAAI,IACN,MAAM,KAAK,4CAA4C;CAGzD,MAAM,OAAO,MAAM,SAAS,IAAI,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM;CAG1D,OAAO;;;gDAFQ,MAAM,SAAS,IAAI,UAAU,KAKS;EACrD,KAAK;;;AAGP;;AAGA,SAAgB,0BAAkC;CAChD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT"}
1
+ {"version":3,"file":"base.js","names":[],"sources":["../../../src/templates/base.ts"],"sourcesContent":["import type { BootBinding } from \"../addons/types.js\";\nimport type { ScaffoldContext } from \"../core/types.js\";\n\nexport function packageJsonTemplate(\n projectName: string,\n scripts: Record<string, string> = {},\n): string {\n const pkg = {\n name: projectName,\n version: \"1.0.0\",\n private: true,\n type: \"module\",\n imports: {\n \"#src/*\": \"./src/*\",\n },\n scripts: {\n dev: \"run-p dev:server dev:taser\",\n \"dev:server\": \"tsx watch src/index.ts\",\n \"dev:taser\": \"taser watch\",\n start: \"tsx src/index.ts\",\n generate: \"taser generate\",\n build: \"taser generate && tsdown\",\n serve: \"node dist/index.mjs\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsdownConfigTemplate(): string {\n return `import { defineConfig } from 'tsdown'\n\nexport default defineConfig({\n entry: ['./src/index.ts'],\n platform: 'node',\n outDir: 'dist',\n clean: true,\n sourcemap: true,\n})\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n paths: {\n \"#src/*\": [\"./src/*\"],\n },\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n types: [\"node\"],\n },\n include: [\"src\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.DS_Store\n*.log\n.env\nlocal.db\ndrizzle\n`;\n}\n\nexport function contextTemplate(bindings: BootBinding[]): string {\n const imports = bindings.map(\n (binding) => `import { ${binding.factoryName} } from '${binding.importPath}'`,\n );\n\n const bootBody =\n bindings.length > 0\n ? bindings.map((binding) => ` ${binding.key}: ${binding.factoryName}(),`).join(\"\\n\")\n : \"\";\n\n const bootBlock = bindings.length > 0 ? ` boot: () => ({\\n${bootBody}\\n }),` : \"\";\n\n const importBlock = imports.length > 0 ? `${imports.join(\"\\n\")}\\n\\n` : \"\";\n\n return `${importBlock}import { createContext } from '@taserjs/router'\n\nexport const context = createContext({\n${bootBlock}\n request: () => ({\n requestId: crypto.randomUUID(),\n }),\n})\n`;\n}\n\nexport function rootLayoutTemplate(): string {\n return `import { cors } from '@taserjs/router/cors'\n\nimport { t } from '#src/taser.js'\n\nexport const Middleware = t.middleware('/$')\n .use(cors())\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n\nconst GET = t.get('/')\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler((_ctx) => {\n return reply.json({ message: 'Welcome to Taser' })\n})\n`;\n}\n\nexport function healthRouteTemplate(ctx: ScaffoldContext): string {\n const lines: string[] = [];\n\n if (ctx.logger) {\n lines.push(\" ctx.logger.info('health check')\");\n }\n\n if (ctx.db) {\n lines.push(\" // ctx.db is available from context boot\");\n }\n\n const body = lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n const ctxArg = lines.length > 0 ? \"(ctx)\" : \"(_ctx)\";\n\n return `import { reply } from '@taserjs/router'\nimport { t } from '#src/taser.js'\n\nconst GET = t.get('/health')\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler(${ctxArg} => {\n${body} return reply.json({ ok: true })\n})\n`;\n}\n\n/** Minimal placeholder until `taser generate` runs. */\nexport function starterManifestTemplate(): string {\n return `/* eslint-disable */\n// Run \\`pnpm generate\\` (taser generate) to replace this file.\nimport { Middleware as RootSplatLayoutImport } from './routes/$.js'\nimport { Route as RootIndexGetRouteImport } from './routes/index.get.js'\nimport { Route as HealthGetRouteImport } from './routes/health.get.js'\n\nexport const routeManifest = {\n layouts: {\n '/$': {\n middlewares: RootSplatLayoutImport,\n },\n },\n routes: {\n '/': {\n GET: {\n layoutChain: ['/$'],\n route: RootIndexGetRouteImport,\n },\n },\n '/health': {\n GET: {\n layoutChain: ['/$'],\n route: HealthGetRouteImport,\n },\n },\n },\n} as const\n\nexport type RoutePathGen = '/' | '/health'\nexport type LayoutIdGen = '/$'\nexport type LayoutTreeGen = {\n '/$': {\n parent: null\n middlewares: typeof RootSplatLayoutImport\n }\n}\nexport type RouteByPathMethodGen = {\n '/': {\n GET: {\n parent: '/$'\n layoutChain: ['/$']\n route: typeof RootIndexGetRouteImport\n }\n }\n '/health': {\n GET: {\n parent: '/$'\n layoutChain: ['/$']\n route: typeof HealthGetRouteImport\n }\n }\n}\nexport type RouteManifest = typeof routeManifest\n\ndeclare module '@taserjs/router' {\n interface RouterRegister {\n RoutePath: RoutePathGen\n LayoutId: LayoutIdGen\n LayoutTree: LayoutTreeGen\n RouteByPathMethod: RouteByPathMethodGen\n }\n}\n`;\n}\n"],"mappings":";AAGA,SAAgB,oBACd,aACA,UAAkC,CAAC,GAC3B;CACR,MAAM,MAAM;EACV,MAAM;EACN,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS,EACP,UAAU,UACZ;EACA,SAAS;GACP,KAAK;GACL,cAAc;GACd,aAAa;GACb,OAAO;GACP,UAAU;GACV,OAAO;GACP,OAAO;GACP,WAAW;GACX,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,uBAA+B;CAC7C,OAAO;;;;;;;;;;AAUT;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,OAAO,EACL,UAAU,CAAC,SAAS,EACtB;GACA,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;GACR,OAAO,CAAC,MAAM;EAChB;EACA,SAAS,CAAC,KAAK;CACjB,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;AAQT;AAEA,SAAgB,gBAAgB,UAAiC;CAC/D,MAAM,UAAU,SAAS,KACtB,YAAY,YAAY,QAAQ,YAAY,WAAW,QAAQ,WAAW,EAC7E;CAEA,MAAM,WACJ,SAAS,SAAS,IACd,SAAS,KAAK,YAAY,OAAO,QAAQ,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC,CAAC,KAAK,IAAI,IACpF;CAEN,MAAM,YAAY,SAAS,SAAS,IAAI,qBAAqB,SAAS,WAAW;CAIjF,OAAO,GAFa,QAAQ,SAAS,IAAI,GAAG,QAAQ,KAAK,IAAI,EAAE,QAAQ,GAEjD;;;EAGtB,UAAU;;;;;;AAMZ;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;AAOT;AAEA,SAAgB,qBAA6B;CAC3C,OAAO;;;;;;;;;;AAUT;AAEA,SAAgB,oBAAoB,KAA8B;CAChE,MAAM,QAAkB,CAAC;CAEzB,IAAI,IAAI,QACN,MAAM,KAAK,mCAAmC;CAGhD,IAAI,IAAI,IACN,MAAM,KAAK,4CAA4C;CAGzD,MAAM,OAAO,MAAM,SAAS,IAAI,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM;CAG1D,OAAO;;;;;;mCAFQ,MAAM,SAAS,IAAI,UAAU,SAQJ;EACxC,KAAK;;;AAGP;;AAGA,SAAgB,0BAAkC;CAChD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-taserjs",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Scaffold a new Taser application",
5
5
  "license": "ISC",
6
6
  "repository": {
@@ -64,16 +64,6 @@ export function resolveAddons(ctx: ScaffoldContext): AddonDefinition[] {
64
64
  selected.push(loggerAddon);
65
65
  }
66
66
 
67
- const dbCount = selected.filter((addon) => addon.category === "database").length;
68
- if (dbCount > 1) {
69
- throw new Error("Only one database addon can be selected");
70
- }
71
-
72
- const loggerCount = selected.filter((addon) => addon.category === "logger").length;
73
- if (loggerCount > 1) {
74
- throw new Error("Only one logger addon can be selected");
75
- }
76
-
77
67
  if (ctx.validator) {
78
68
  const validatorAddon = VALIDATOR_ADDONS.find((addon) => addon.id === ctx.validator);
79
69
  if (!validatorAddon) {
@@ -82,11 +72,6 @@ export function resolveAddons(ctx: ScaffoldContext): AddonDefinition[] {
82
72
  selected.push(validatorAddon);
83
73
  }
84
74
 
85
- const validatorCount = selected.filter((addon) => addon.category === "validator").length;
86
- if (validatorCount > 1) {
87
- throw new Error("Only one validator addon can be selected");
88
- }
89
-
90
75
  return selected;
91
76
  }
92
77
 
@@ -9,13 +9,13 @@ export const IMPORT_LINES: Record<ValidatorId, string> = {
9
9
 
10
10
  export const VALIDATION_BLOCK_TEMPLATE: Record<ValidatorId, string> = {
11
11
  zod: `, {
12
- query: z.object({ name: z.string() }),
12
+ query: z.object({ name: z.string().default('Taser') }),
13
13
  }`,
14
14
  arktype: `, {
15
- query: type({ name: 'string' }),
15
+ query: type({ 'name?': 'string = "Taser"' }),
16
16
  }`,
17
17
  valibot: `, {
18
- query: v.object({ name: v.string() }),
18
+ query: v.object({ name: v.optional(v.string(), 'Taser') }),
19
19
  }`,
20
20
  };
21
21
 
@@ -23,7 +23,10 @@ const ROUTE_TEMPLATE = (validator: ValidatorId) => `import { reply } from '@tase
23
23
  import { t } from '#src/taser.js'
24
24
  ${IMPORT_LINES[validator]}
25
25
 
26
- export const Route = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]}).handler((ctx) => {
26
+ const GET = t.get('/'${VALIDATION_BLOCK_TEMPLATE[validator]})
27
+
28
+ export type RouteContext = typeof GET.$Infer.Context
29
+ export const Route = GET.handler((ctx) => {
27
30
  return reply.json({ message: \`Hello, \${ctx.query.name}!\` })
28
31
  })
29
32
  `;
@@ -8,7 +8,7 @@ function typePackages(type: ProjectType): PackageGroups {
8
8
  "npm-run-all2",
9
9
  "tsdown",
10
10
  "tsx",
11
- "typescript",
11
+ "typescript@^5.9.3",
12
12
  "@types/node",
13
13
  ];
14
14
  const scripts: Record<string, string> = {};
@@ -128,14 +128,7 @@ export async function scaffoldProject(options: ScaffoldOptions): Promise<Scaffol
128
128
  await writeProjectConfig(root, ctx);
129
129
 
130
130
  if (options.skipInstall) {
131
- return {
132
- projectName: ctx.projectName,
133
- targetDir: root,
134
- type: ctx.type,
135
- ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),
136
- ...(ctx.logger ? { logger: ctx.logger } : {}),
137
- ...(ctx.validator ? { validator: ctx.validator } : {}),
138
- };
131
+ return ctx as ScaffoldResult;
139
132
  }
140
133
 
141
134
  const agent = options.agent ?? resolveUserAgent();
@@ -144,12 +137,5 @@ export async function scaffoldProject(options: ScaffoldOptions): Promise<Scaffol
144
137
  devDependencies: packages.devDependencies,
145
138
  });
146
139
 
147
- return {
148
- projectName: ctx.projectName,
149
- targetDir: root,
150
- type: ctx.type,
151
- ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),
152
- ...(ctx.logger ? { logger: ctx.logger } : {}),
153
- ...(ctx.validator ? { validator: ctx.validator } : {}),
154
- };
140
+ return ctx as ScaffoldResult;
155
141
  }
@@ -34,7 +34,7 @@ import { t } from '#src/taser.js'
34
34
  const router = t.create(routeManifest)
35
35
 
36
36
  const app = new Hono()
37
- app.all('/*', c => router.native(c).fetch(c.req.raw))
37
+ app.all('/*', c => router.fetch(c.req.raw))
38
38
 
39
39
  const port = Number(process.env.PORT ?? 3000)
40
40
  serve({ fetch: app.fetch, port }, () => {
@@ -100,7 +100,7 @@ import { t } from '#src/taser.js'
100
100
  const router = t.create(routeManifest)
101
101
 
102
102
  const app = new Hono()
103
- app.all('/*', c => router.native(c).fetch(c.req.raw))
103
+ app.all('/*', c => router.fetch(c.req.raw))
104
104
 
105
105
  export const handler = handle(app)
106
106
  `;
@@ -130,7 +130,7 @@ import { t } from '#src/taser.js'
130
130
  const router = t.create(routeManifest)
131
131
 
132
132
  const app = new Hono()
133
- app.all('/*', c => router.native(c).fetch(c.req.raw))
133
+ app.all('/*', c => router.fetch(c.req.raw))
134
134
 
135
135
  export default handle(app)
136
136
  `;
@@ -146,7 +146,7 @@ import { t } from '#src/taser.js'
146
146
  const router = t.create(routeManifest)
147
147
 
148
148
  const app = new Hono()
149
- app.all('/*', c => router.native(c).fetch(c.req.raw))
149
+ app.all('/*', c => router.fetch(c.req.raw))
150
150
 
151
151
  export default handle(app)
152
152
  `;
@@ -163,7 +163,7 @@ import { t } from '#src/taser.js'
163
163
  const router = t.create(routeManifest)
164
164
 
165
165
  const honoApp = new Hono()
166
- honoApp.all('/*', c => router.native(c).fetch(c.req.raw))
166
+ honoApp.all('/*', c => router.fetch(c.req.raw))
167
167
 
168
168
  app.http('httpTrigger', {
169
169
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],
@@ -206,41 +206,13 @@ serve({ fetch: router.fetch, port }, () => {
206
206
  }
207
207
  }
208
208
 
209
- export function taserTsTemplate(type: ProjectType = "node"): string {
210
- if (
211
- type === "hono" ||
212
- type === "aws-lambda" ||
213
- type === "netlify" ||
214
- type === "vercel" ||
215
- type === "azure-functions"
216
- ) {
217
- return `import type { Context } from 'hono'
218
- import { createTaserApp, type InferAppContext } from '@taserjs/router'
219
-
220
- import { context } from '#src/context.js'
221
-
222
- declare module '@taserjs/router' {
223
- interface RouterRegister {
224
- NativeContext: Context
225
- }
226
- }
227
-
228
- export const t = createTaserApp({
229
- response: { validate: true },
230
- }).context(context)
231
-
232
- export type AppContext = InferAppContext<typeof context>
233
- `;
234
- }
235
-
236
- return `import { createTaserApp, type InferAppContext } from '@taserjs/router'
209
+ export function taserTsTemplate(_type: ProjectType = "node"): string {
210
+ return `import { createTaserApp } from '@taserjs/router'
237
211
 
238
212
  import { context } from '#src/context.js'
239
213
 
240
214
  export const t = createTaserApp({
241
215
  response: { validate: true },
242
216
  }).context(context)
243
-
244
- export type AppContext = InferAppContext<typeof context>
245
217
  `;
246
218
  }
@@ -102,14 +102,12 @@ ${bootBlock}
102
102
  }
103
103
 
104
104
  export function rootLayoutTemplate(): string {
105
- return `import { bodyLimit } from '@taserjs/router/body-limit'
106
- import { secureHeaders } from '@taserjs/router/secure-headers'
105
+ return `import { cors } from '@taserjs/router/cors'
107
106
 
108
107
  import { t } from '#src/taser.js'
109
108
 
110
109
  export const Middleware = t.middleware('/$')
111
- .use(secureHeaders())
112
- .use(bodyLimit({ maxSize: 1_000_000 }))
110
+ .use(cors())
113
111
  `;
114
112
  }
115
113
 
@@ -117,7 +115,10 @@ export function indexRouteTemplate(): string {
117
115
  return `import { reply } from '@taserjs/router'
118
116
  import { t } from '#src/taser.js'
119
117
 
120
- export const Route = t.get('/').handler(() => {
118
+ const GET = t.get('/')
119
+
120
+ export type RouteContext = typeof GET.$Infer.Context
121
+ export const Route = GET.handler((_ctx) => {
121
122
  return reply.json({ message: 'Welcome to Taser' })
122
123
  })
123
124
  `;
@@ -135,12 +136,15 @@ export function healthRouteTemplate(ctx: ScaffoldContext): string {
135
136
  }
136
137
 
137
138
  const body = lines.length > 0 ? `${lines.join("\n")}\n` : "";
138
- const ctxArg = lines.length > 0 ? "(ctx)" : "()";
139
+ const ctxArg = lines.length > 0 ? "(ctx)" : "(_ctx)";
139
140
 
140
141
  return `import { reply } from '@taserjs/router'
141
142
  import { t } from '#src/taser.js'
142
143
 
143
- export const Route = t.get('/health').handler(${ctxArg} => {
144
+ const GET = t.get('/health')
145
+
146
+ export type RouteContext = typeof GET.$Infer.Context
147
+ export const Route = GET.handler(${ctxArg} => {
144
148
  ${body} return reply.json({ ok: true })
145
149
  })
146
150
  `;