create-taserjs 0.0.4 → 0.0.5

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.
@@ -19,7 +19,10 @@ 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() }),\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\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"}
@@ -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"}
@@ -19,7 +19,10 @@ 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() }),\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\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"}
@@ -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.5",
4
4
  "description": "Scaffold a new Taser application",
5
5
  "license": "ISC",
6
6
  "repository": {
@@ -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> = {};
@@ -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
  `;