create-taserjs 0.1.4 → 0.1.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.
@@ -12,16 +12,14 @@ var VALIDATION_BLOCK_TEMPLATE = {
12
12
  valibot: `
13
13
  .query(v.object({ name: v.optional(v.string(), 'Taser') }))`
14
14
  };
15
- var ROUTE_TEMPLATE = (validator) => `import { json } from '@taserjs/router/reply'
16
- import { t } from '#taserjs/router'
15
+ var ROUTE_TEMPLATE = (validator) => `import { t } from '@taserjs/router'
16
+ import { json } from '@taserjs/router/reply'
17
17
  ${IMPORT_LINES[validator]}
18
18
 
19
- const GET = t.get('/')${VALIDATION_BLOCK_TEMPLATE[validator]}
20
-
21
- export type RouteContext = typeof GET.$Infer.Context
22
- export const Route = GET.handler((ctx) => {
23
- return json({ message: \`Hello, \${ctx.query.name}!\` })
24
- })
19
+ export default t.get('/')${VALIDATION_BLOCK_TEMPLATE[validator]}
20
+ .handler((ctx) => {
21
+ return json({ message: \`Hello, \${ctx.query.name}!\` })
22
+ })
25
23
  `;
26
24
  var ValidatorAddon = (validator) => {
27
25
  return {
@@ -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().default('Taser') }))`,\n arktype: `\n .query(type({ 'name?': 'string = \"Taser\"' }))`,\n valibot: `\n .query(v.object({ name: v.optional(v.string(), 'Taser') }))`,\n};\n\nconst ROUTE_TEMPLATE = (validator: ValidatorId) => `import { json } from '@taserjs/router/reply'\nimport { t } from '#taserjs/router'\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 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;;CAEL,SAAS;;CAET,SAAS;;AAEX;AAEA,IAAM,kBAAkB,cAA2B;;EAEjD,aAAa,WAAW;;wBAEF,0BAA0B,WAAW;;;;;;;AAQ7D,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 arktype: `\n .query(type({ 'name?': 'string = \"Taser\"' }))`,\n valibot: `\n .query(v.object({ name: v.optional(v.string(), 'Taser') }))`,\n};\n\nconst ROUTE_TEMPLATE = (validator: ValidatorId) => `import { t } from '@taserjs/router'\nimport { json } from '@taserjs/router/reply'\n${IMPORT_LINES[validator]}\n\nexport default t.get('/')${VALIDATION_BLOCK_TEMPLATE[validator]}\n .handler((ctx) => {\n return 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;;CAEL,SAAS;;CAET,SAAS;;AAEX;AAEA,IAAM,kBAAkB,cAA2B;;EAEjD,aAAa,WAAW;;2BAEC,0BAA0B,WAAW;;;;;AAMhE,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"}
@@ -101,7 +101,7 @@ function taserTsTemplate() {
101
101
 
102
102
  import { context } from './context.js'
103
103
 
104
- export const t = createTaserApp({
104
+ export default createTaserApp({
105
105
  response: { validate: true },
106
106
  }).context(context)
107
107
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { DeployTarget, Framework } from \"../core/types.js\";\n\nexport function serverEntryTemplate(\n framework: Framework,\n): { fileName: string; content: string } | null {\n switch (framework) {\n case \"hono\":\n return {\n fileName: \"src/server.ts\",\n content: `import { Hono } from 'hono'\n\nconst app = new Hono()\n\napp.get('/host', (c) => {\n return c.text('Hello from Hono host!')\n})\n\nexport default app\n`,\n };\n case \"express\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import express from 'express'\n\nconst app = express()\n\napp.get('/host', (_req, res) => {\n res.json({ message: 'Hello from Express host!' })\n})\n\nexport default app\n`,\n };\n case \"fastify\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import Fastify from 'fastify'\n\nconst app = Fastify()\n\napp.get('/host', async () => {\n return { message: 'Hello from Fastify host!' }\n})\n\nawait app.ready()\n\nexport default app.routing\n`,\n };\n default:\n return null;\n }\n}\n\nexport type FrameworkEntry = {\n id: Framework;\n serverEntry: { fileName: string; content: string } | null;\n deps: string[];\n devDeps: string[];\n};\n\nexport const FRAMEWORK_ENTRIES: Record<Framework, FrameworkEntry> = {\n none: { id: \"none\", serverEntry: null, deps: [], devDeps: [] },\n hono: { id: \"hono\", serverEntry: serverEntryTemplate(\"hono\"), deps: [\"hono\"], devDeps: [] },\n express: {\n id: \"express\",\n serverEntry: serverEntryTemplate(\"express\"),\n deps: [\"express\"],\n devDeps: [\"@types/express\"],\n },\n fastify: {\n id: \"fastify\",\n // srvx bridges the Fastify Node handler to fetch (see compose codegen).\n serverEntry: serverEntryTemplate(\"fastify\"),\n deps: [\"fastify\"],\n devDeps: [],\n },\n};\n\nexport function nitroConfigTemplate(nitroPreset: string): string {\n return `import { defineConfig } from 'nitro/config'\n\nexport default defineConfig({\n preset: '${nitroPreset}',\n})\n`;\n}\n\nexport function viteConfigTemplate(preset?: DeployTarget): string {\n if (preset === \"none\") {\n return `import { defineConfig } from 'vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser()],\n})\n`;\n }\n\n return `import { defineConfig } from 'vite'\nimport { nitro } from 'nitro/vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser(), nitro()],\n})\n`;\n}\n\nexport function taserTsTemplate(): string {\n return `import { createTaserApp } from '@taserjs/router'\n\nimport { context } from './context.js'\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n`;\n}\n"],"mappings":";AAEA,SAAgB,oBACd,WAC8C;CAC9C,QAAQ,WAAR;EACE,KAAK,QACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;;;EAYX;EACF,SACE,OAAO;CACX;AACF;AASA,IAAa,oBAAuD;CAClE,MAAM;EAAE,IAAI;EAAQ,aAAa;EAAM,MAAM,CAAC;EAAG,SAAS,CAAC;CAAE;CAC7D,MAAM;EAAE,IAAI;EAAQ,aAAa,oBAAoB,MAAM;EAAG,MAAM,CAAC,MAAM;EAAG,SAAS,CAAC;CAAE;CAC1F,SAAS;EACP,IAAI;EACJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC,gBAAgB;CAC5B;CACA,SAAS;EACP,IAAI;EAEJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC;CACZ;AACF;AAEA,SAAgB,oBAAoB,aAA6B;CAC/D,OAAO;;;aAGI,YAAY;;;AAGzB;AAEA,SAAgB,mBAAmB,QAA+B;CAChE,IAAI,WAAW,QACb,OAAO;;;;;;;CAST,OAAO;;;;;;;;AAQT;AAEA,SAAgB,kBAA0B;CACxC,OAAO;;;;;;;;AAQT"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { DeployTarget, Framework } from \"../core/types.js\";\n\nexport function serverEntryTemplate(\n framework: Framework,\n): { fileName: string; content: string } | null {\n switch (framework) {\n case \"hono\":\n return {\n fileName: \"src/server.ts\",\n content: `import { Hono } from 'hono'\n\nconst app = new Hono()\n\napp.get('/host', (c) => {\n return c.text('Hello from Hono host!')\n})\n\nexport default app\n`,\n };\n case \"express\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import express from 'express'\n\nconst app = express()\n\napp.get('/host', (_req, res) => {\n res.json({ message: 'Hello from Express host!' })\n})\n\nexport default app\n`,\n };\n case \"fastify\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import Fastify from 'fastify'\n\nconst app = Fastify()\n\napp.get('/host', async () => {\n return { message: 'Hello from Fastify host!' }\n})\n\nawait app.ready()\n\nexport default app.routing\n`,\n };\n default:\n return null;\n }\n}\n\nexport type FrameworkEntry = {\n id: Framework;\n serverEntry: { fileName: string; content: string } | null;\n deps: string[];\n devDeps: string[];\n};\n\nexport const FRAMEWORK_ENTRIES: Record<Framework, FrameworkEntry> = {\n none: { id: \"none\", serverEntry: null, deps: [], devDeps: [] },\n hono: { id: \"hono\", serverEntry: serverEntryTemplate(\"hono\"), deps: [\"hono\"], devDeps: [] },\n express: {\n id: \"express\",\n serverEntry: serverEntryTemplate(\"express\"),\n deps: [\"express\"],\n devDeps: [\"@types/express\"],\n },\n fastify: {\n id: \"fastify\",\n // srvx bridges the Fastify Node handler to fetch (see compose codegen).\n serverEntry: serverEntryTemplate(\"fastify\"),\n deps: [\"fastify\"],\n devDeps: [],\n },\n};\n\nexport function nitroConfigTemplate(nitroPreset: string): string {\n return `import { defineConfig } from 'nitro/config'\n\nexport default defineConfig({\n preset: '${nitroPreset}',\n})\n`;\n}\n\nexport function viteConfigTemplate(preset?: DeployTarget): string {\n if (preset === \"none\") {\n return `import { defineConfig } from 'vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser()],\n})\n`;\n }\n\n return `import { defineConfig } from 'vite'\nimport { nitro } from 'nitro/vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser(), nitro()],\n})\n`;\n}\n\nexport function taserTsTemplate(): string {\n return `import { createTaserApp } from '@taserjs/router'\n\nimport { context } from './context.js'\n\nexport default createTaserApp({\n response: { validate: true },\n}).context(context)\n`;\n}\n"],"mappings":";AAEA,SAAgB,oBACd,WAC8C;CAC9C,QAAQ,WAAR;EACE,KAAK,QACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;;;EAYX;EACF,SACE,OAAO;CACX;AACF;AASA,IAAa,oBAAuD;CAClE,MAAM;EAAE,IAAI;EAAQ,aAAa;EAAM,MAAM,CAAC;EAAG,SAAS,CAAC;CAAE;CAC7D,MAAM;EAAE,IAAI;EAAQ,aAAa,oBAAoB,MAAM;EAAG,MAAM,CAAC,MAAM;EAAG,SAAS,CAAC;CAAE;CAC1F,SAAS;EACP,IAAI;EACJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC,gBAAgB;CAC5B;CACA,SAAS;EACP,IAAI;EAEJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC;CACZ;AACF;AAEA,SAAgB,oBAAoB,aAA6B;CAC/D,OAAO;;;aAGI,YAAY;;;AAGzB;AAEA,SAAgB,mBAAmB,QAA+B;CAChE,IAAI,WAAW,QACb,OAAO;;;;;;;CAST,OAAO;;;;;;;;AAQT;AAEA,SAAgB,kBAA0B;CACxC,OAAO;;;;;;;;AAQT"}
@@ -5,7 +5,6 @@ function packageJsonTemplate(projectName, scripts = {}) {
5
5
  version: "1.0.0",
6
6
  private: true,
7
7
  type: "module",
8
- imports: { "#taserjs/router": "./src/taser.ts" },
9
8
  scripts: {
10
9
  dev: "vite",
11
10
  build: "vite build",
@@ -20,7 +19,6 @@ function tsconfigTemplate() {
20
19
  compilerOptions: {
21
20
  target: "ES2022",
22
21
  module: "NodeNext",
23
- paths: { "#taserjs/router": ["./src/taser.ts"] },
24
22
  strict: true,
25
23
  skipLibCheck: true,
26
24
  verbatimModuleSyntax: true,
@@ -58,21 +56,17 @@ ${bootBlock}
58
56
  }
59
57
  function rootLayoutTemplate() {
60
58
  return `import { cors } from '@taserjs/router/cors'
59
+ import { t } from '@taserjs/router'
61
60
 
62
- import { t } from '#taserjs/router'
63
-
64
- export const Middleware = t.middleware('/$')
61
+ export default t.layout('/$')
65
62
  .use(cors())
66
63
  `;
67
64
  }
68
65
  function indexRouteTemplate() {
69
- return `import { json } from '@taserjs/router/reply'
70
- import { t } from '#taserjs/router'
71
-
72
- const GET = t.get('/')
66
+ return `import { t } from '@taserjs/router'
67
+ import { json } from '@taserjs/router/reply'
73
68
 
74
- export type RouteContext = typeof GET.$Infer.Context
75
- export const Route = GET.handler((_ctx) => {
69
+ export default t.get('/').handler((_ctx) => {
76
70
  return json({ message: 'Welcome to Taser' })
77
71
  })
78
72
  `;
@@ -82,13 +76,10 @@ function healthRouteTemplate(ctx) {
82
76
  if (ctx.logger) lines.push(" ctx.logger.info('health check')");
83
77
  if (ctx.db) lines.push(" // ctx.db is available from context boot");
84
78
  const body = lines.length > 0 ? `${lines.join("\n")}\n` : "";
85
- return `import { json } from '@taserjs/router/reply'
86
- import { t } from '#taserjs/router'
87
-
88
- const GET = t.get('/health')
79
+ return `import { t } from '@taserjs/router'
80
+ import { json } from '@taserjs/router/reply'
89
81
 
90
- export type RouteContext = typeof GET.$Infer.Context
91
- export const Route = GET.handler(${lines.length > 0 ? "(ctx)" : "(_ctx)"} => {
82
+ export default t.get('/health').handler(${lines.length > 0 ? "(ctx)" : "(_ctx)"} => {
92
83
  ${body} return json({ ok: true })
93
84
  })
94
85
  `;
@@ -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 \"#taserjs/router\": \"./src/taser.ts\",\n },\n scripts: {\n dev: \"vite\",\n build: \"vite build\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n paths: {\n \"#taserjs/router\": [\"./src/taser.ts\"],\n },\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n },\n include: [\"src\", \".taser/types/**/*.d.ts\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.output\n.taser\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 '#taserjs/router'\n\nexport const Middleware = t.middleware('/$')\n .use(cors())\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { json } from '@taserjs/router/reply'\nimport { t } from '#taserjs/router'\n\nconst GET = t.get('/')\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler((_ctx) => {\n return 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 { json } from '@taserjs/router/reply'\nimport { t } from '#taserjs/router'\n\nconst GET = t.get('/health')\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler(${ctxArg} => {\n${body} return json({ ok: true })\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,mBAAmB,iBACrB;EACA,SAAS;GACP,KAAK;GACL,OAAO;GACP,WAAW;GACX,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,OAAO,EACL,mBAAmB,CAAC,gBAAgB,EACtC;GACA,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;EACV;EACA,SAAS,CAAC,OAAO,wBAAwB;CAC3C,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;;;AAUT;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"}
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 scripts: {\n dev: \"vite\",\n build: \"vite build\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n },\n include: [\"src\", \".taser/types/**/*.d.ts\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.output\n.taser\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'\nimport { t } from '@taserjs/router'\n\nexport default t.layout('/$')\n .use(cors())\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { t } from '@taserjs/router'\nimport { json } from '@taserjs/router/reply'\n\nexport default t.get('/').handler((_ctx) => {\n return 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 { t } from '@taserjs/router'\nimport { json } from '@taserjs/router/reply'\n\nexport default t.get('/health').handler(${ctxArg} => {\n${body} return json({ ok: true })\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;GACP,KAAK;GACL,OAAO;GACP,WAAW;GACX,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;EACV;EACA,SAAS,CAAC,OAAO,wBAAwB;CAC3C,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;;;AAUT;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;;;;;;AAMT;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;;;0CAFQ,MAAM,SAAS,IAAI,UAAU,SAKG;EAC/C,KAAK;;;AAGP"}
@@ -12,16 +12,14 @@ var VALIDATION_BLOCK_TEMPLATE = {
12
12
  valibot: `
13
13
  .query(v.object({ name: v.optional(v.string(), 'Taser') }))`
14
14
  };
15
- var ROUTE_TEMPLATE = (validator) => `import { json } from '@taserjs/router/reply'
16
- import { t } from '#taserjs/router'
15
+ var ROUTE_TEMPLATE = (validator) => `import { t } from '@taserjs/router'
16
+ import { json } from '@taserjs/router/reply'
17
17
  ${IMPORT_LINES[validator]}
18
18
 
19
- const GET = t.get('/')${VALIDATION_BLOCK_TEMPLATE[validator]}
20
-
21
- export type RouteContext = typeof GET.$Infer.Context
22
- export const Route = GET.handler((ctx) => {
23
- return json({ message: \`Hello, \${ctx.query.name}!\` })
24
- })
19
+ export default t.get('/')${VALIDATION_BLOCK_TEMPLATE[validator]}
20
+ .handler((ctx) => {
21
+ return json({ message: \`Hello, \${ctx.query.name}!\` })
22
+ })
25
23
  `;
26
24
  var ValidatorAddon = (validator) => {
27
25
  return {
@@ -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().default('Taser') }))`,\n arktype: `\n .query(type({ 'name?': 'string = \"Taser\"' }))`,\n valibot: `\n .query(v.object({ name: v.optional(v.string(), 'Taser') }))`,\n};\n\nconst ROUTE_TEMPLATE = (validator: ValidatorId) => `import { json } from '@taserjs/router/reply'\nimport { t } from '#taserjs/router'\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 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;;CAEL,SAAS;;CAET,SAAS;;AAEX;AAEA,IAAM,kBAAkB,cAA2B;;EAEjD,aAAa,WAAW;;wBAEF,0BAA0B,WAAW;;;;;;;AAQ7D,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 arktype: `\n .query(type({ 'name?': 'string = \"Taser\"' }))`,\n valibot: `\n .query(v.object({ name: v.optional(v.string(), 'Taser') }))`,\n};\n\nconst ROUTE_TEMPLATE = (validator: ValidatorId) => `import { t } from '@taserjs/router'\nimport { json } from '@taserjs/router/reply'\n${IMPORT_LINES[validator]}\n\nexport default t.get('/')${VALIDATION_BLOCK_TEMPLATE[validator]}\n .handler((ctx) => {\n return 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;;CAEL,SAAS;;CAET,SAAS;;AAEX;AAEA,IAAM,kBAAkB,cAA2B;;EAEjD,aAAa,WAAW;;2BAEC,0BAA0B,WAAW;;;;;AAMhE,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"}
@@ -101,7 +101,7 @@ function taserTsTemplate() {
101
101
 
102
102
  import { context } from './context.js'
103
103
 
104
- export const t = createTaserApp({
104
+ export default createTaserApp({
105
105
  response: { validate: true },
106
106
  }).context(context)
107
107
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { DeployTarget, Framework } from \"../core/types.js\";\n\nexport function serverEntryTemplate(\n framework: Framework,\n): { fileName: string; content: string } | null {\n switch (framework) {\n case \"hono\":\n return {\n fileName: \"src/server.ts\",\n content: `import { Hono } from 'hono'\n\nconst app = new Hono()\n\napp.get('/host', (c) => {\n return c.text('Hello from Hono host!')\n})\n\nexport default app\n`,\n };\n case \"express\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import express from 'express'\n\nconst app = express()\n\napp.get('/host', (_req, res) => {\n res.json({ message: 'Hello from Express host!' })\n})\n\nexport default app\n`,\n };\n case \"fastify\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import Fastify from 'fastify'\n\nconst app = Fastify()\n\napp.get('/host', async () => {\n return { message: 'Hello from Fastify host!' }\n})\n\nawait app.ready()\n\nexport default app.routing\n`,\n };\n default:\n return null;\n }\n}\n\nexport type FrameworkEntry = {\n id: Framework;\n serverEntry: { fileName: string; content: string } | null;\n deps: string[];\n devDeps: string[];\n};\n\nexport const FRAMEWORK_ENTRIES: Record<Framework, FrameworkEntry> = {\n none: { id: \"none\", serverEntry: null, deps: [], devDeps: [] },\n hono: { id: \"hono\", serverEntry: serverEntryTemplate(\"hono\"), deps: [\"hono\"], devDeps: [] },\n express: {\n id: \"express\",\n serverEntry: serverEntryTemplate(\"express\"),\n deps: [\"express\"],\n devDeps: [\"@types/express\"],\n },\n fastify: {\n id: \"fastify\",\n // srvx bridges the Fastify Node handler to fetch (see compose codegen).\n serverEntry: serverEntryTemplate(\"fastify\"),\n deps: [\"fastify\"],\n devDeps: [],\n },\n};\n\nexport function nitroConfigTemplate(nitroPreset: string): string {\n return `import { defineConfig } from 'nitro/config'\n\nexport default defineConfig({\n preset: '${nitroPreset}',\n})\n`;\n}\n\nexport function viteConfigTemplate(preset?: DeployTarget): string {\n if (preset === \"none\") {\n return `import { defineConfig } from 'vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser()],\n})\n`;\n }\n\n return `import { defineConfig } from 'vite'\nimport { nitro } from 'nitro/vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser(), nitro()],\n})\n`;\n}\n\nexport function taserTsTemplate(): string {\n return `import { createTaserApp } from '@taserjs/router'\n\nimport { context } from './context.js'\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n`;\n}\n"],"mappings":";AAEA,SAAgB,oBACd,WAC8C;CAC9C,QAAQ,WAAR;EACE,KAAK,QACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;;;EAYX;EACF,SACE,OAAO;CACX;AACF;AASA,IAAa,oBAAuD;CAClE,MAAM;EAAE,IAAI;EAAQ,aAAa;EAAM,MAAM,CAAC;EAAG,SAAS,CAAC;CAAE;CAC7D,MAAM;EAAE,IAAI;EAAQ,aAAa,oBAAoB,MAAM;EAAG,MAAM,CAAC,MAAM;EAAG,SAAS,CAAC;CAAE;CAC1F,SAAS;EACP,IAAI;EACJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC,gBAAgB;CAC5B;CACA,SAAS;EACP,IAAI;EAEJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC;CACZ;AACF;AAEA,SAAgB,oBAAoB,aAA6B;CAC/D,OAAO;;;aAGI,YAAY;;;AAGzB;AAEA,SAAgB,mBAAmB,QAA+B;CAChE,IAAI,WAAW,QACb,OAAO;;;;;;;CAST,OAAO;;;;;;;;AAQT;AAEA,SAAgB,kBAA0B;CACxC,OAAO;;;;;;;;AAQT"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { DeployTarget, Framework } from \"../core/types.js\";\n\nexport function serverEntryTemplate(\n framework: Framework,\n): { fileName: string; content: string } | null {\n switch (framework) {\n case \"hono\":\n return {\n fileName: \"src/server.ts\",\n content: `import { Hono } from 'hono'\n\nconst app = new Hono()\n\napp.get('/host', (c) => {\n return c.text('Hello from Hono host!')\n})\n\nexport default app\n`,\n };\n case \"express\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import express from 'express'\n\nconst app = express()\n\napp.get('/host', (_req, res) => {\n res.json({ message: 'Hello from Express host!' })\n})\n\nexport default app\n`,\n };\n case \"fastify\":\n return {\n fileName: \"src/server.node.ts\",\n content: `import Fastify from 'fastify'\n\nconst app = Fastify()\n\napp.get('/host', async () => {\n return { message: 'Hello from Fastify host!' }\n})\n\nawait app.ready()\n\nexport default app.routing\n`,\n };\n default:\n return null;\n }\n}\n\nexport type FrameworkEntry = {\n id: Framework;\n serverEntry: { fileName: string; content: string } | null;\n deps: string[];\n devDeps: string[];\n};\n\nexport const FRAMEWORK_ENTRIES: Record<Framework, FrameworkEntry> = {\n none: { id: \"none\", serverEntry: null, deps: [], devDeps: [] },\n hono: { id: \"hono\", serverEntry: serverEntryTemplate(\"hono\"), deps: [\"hono\"], devDeps: [] },\n express: {\n id: \"express\",\n serverEntry: serverEntryTemplate(\"express\"),\n deps: [\"express\"],\n devDeps: [\"@types/express\"],\n },\n fastify: {\n id: \"fastify\",\n // srvx bridges the Fastify Node handler to fetch (see compose codegen).\n serverEntry: serverEntryTemplate(\"fastify\"),\n deps: [\"fastify\"],\n devDeps: [],\n },\n};\n\nexport function nitroConfigTemplate(nitroPreset: string): string {\n return `import { defineConfig } from 'nitro/config'\n\nexport default defineConfig({\n preset: '${nitroPreset}',\n})\n`;\n}\n\nexport function viteConfigTemplate(preset?: DeployTarget): string {\n if (preset === \"none\") {\n return `import { defineConfig } from 'vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser()],\n})\n`;\n }\n\n return `import { defineConfig } from 'vite'\nimport { nitro } from 'nitro/vite'\nimport { taser } from '@taserjs/router-plugin/vite'\n\nexport default defineConfig({\n plugins: [taser(), nitro()],\n})\n`;\n}\n\nexport function taserTsTemplate(): string {\n return `import { createTaserApp } from '@taserjs/router'\n\nimport { context } from './context.js'\n\nexport default createTaserApp({\n response: { validate: true },\n}).context(context)\n`;\n}\n"],"mappings":";AAEA,SAAgB,oBACd,WAC8C;CAC9C,QAAQ,WAAR;EACE,KAAK,QACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;EAUX;EACF,KAAK,WACH,OAAO;GACL,UAAU;GACV,SAAS;;;;;;;;;;;;EAYX;EACF,SACE,OAAO;CACX;AACF;AASA,IAAa,oBAAuD;CAClE,MAAM;EAAE,IAAI;EAAQ,aAAa;EAAM,MAAM,CAAC;EAAG,SAAS,CAAC;CAAE;CAC7D,MAAM;EAAE,IAAI;EAAQ,aAAa,oBAAoB,MAAM;EAAG,MAAM,CAAC,MAAM;EAAG,SAAS,CAAC;CAAE;CAC1F,SAAS;EACP,IAAI;EACJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC,gBAAgB;CAC5B;CACA,SAAS;EACP,IAAI;EAEJ,aAAa,oBAAoB,SAAS;EAC1C,MAAM,CAAC,SAAS;EAChB,SAAS,CAAC;CACZ;AACF;AAEA,SAAgB,oBAAoB,aAA6B;CAC/D,OAAO;;;aAGI,YAAY;;;AAGzB;AAEA,SAAgB,mBAAmB,QAA+B;CAChE,IAAI,WAAW,QACb,OAAO;;;;;;;CAST,OAAO;;;;;;;;AAQT;AAEA,SAAgB,kBAA0B;CACxC,OAAO;;;;;;;;AAQT"}
@@ -5,7 +5,6 @@ function packageJsonTemplate(projectName, scripts = {}) {
5
5
  version: "1.0.0",
6
6
  private: true,
7
7
  type: "module",
8
- imports: { "#taserjs/router": "./src/taser.ts" },
9
8
  scripts: {
10
9
  dev: "vite",
11
10
  build: "vite build",
@@ -20,7 +19,6 @@ function tsconfigTemplate() {
20
19
  compilerOptions: {
21
20
  target: "ES2022",
22
21
  module: "NodeNext",
23
- paths: { "#taserjs/router": ["./src/taser.ts"] },
24
22
  strict: true,
25
23
  skipLibCheck: true,
26
24
  verbatimModuleSyntax: true,
@@ -58,21 +56,17 @@ ${bootBlock}
58
56
  }
59
57
  function rootLayoutTemplate() {
60
58
  return `import { cors } from '@taserjs/router/cors'
59
+ import { t } from '@taserjs/router'
61
60
 
62
- import { t } from '#taserjs/router'
63
-
64
- export const Middleware = t.middleware('/$')
61
+ export default t.layout('/$')
65
62
  .use(cors())
66
63
  `;
67
64
  }
68
65
  function indexRouteTemplate() {
69
- return `import { json } from '@taserjs/router/reply'
70
- import { t } from '#taserjs/router'
71
-
72
- const GET = t.get('/')
66
+ return `import { t } from '@taserjs/router'
67
+ import { json } from '@taserjs/router/reply'
73
68
 
74
- export type RouteContext = typeof GET.$Infer.Context
75
- export const Route = GET.handler((_ctx) => {
69
+ export default t.get('/').handler((_ctx) => {
76
70
  return json({ message: 'Welcome to Taser' })
77
71
  })
78
72
  `;
@@ -82,13 +76,10 @@ function healthRouteTemplate(ctx) {
82
76
  if (ctx.logger) lines.push(" ctx.logger.info('health check')");
83
77
  if (ctx.db) lines.push(" // ctx.db is available from context boot");
84
78
  const body = lines.length > 0 ? `${lines.join("\n")}\n` : "";
85
- return `import { json } from '@taserjs/router/reply'
86
- import { t } from '#taserjs/router'
87
-
88
- const GET = t.get('/health')
79
+ return `import { t } from '@taserjs/router'
80
+ import { json } from '@taserjs/router/reply'
89
81
 
90
- export type RouteContext = typeof GET.$Infer.Context
91
- export const Route = GET.handler(${lines.length > 0 ? "(ctx)" : "(_ctx)"} => {
82
+ export default t.get('/health').handler(${lines.length > 0 ? "(ctx)" : "(_ctx)"} => {
92
83
  ${body} return json({ ok: true })
93
84
  })
94
85
  `;
@@ -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 \"#taserjs/router\": \"./src/taser.ts\",\n },\n scripts: {\n dev: \"vite\",\n build: \"vite build\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n paths: {\n \"#taserjs/router\": [\"./src/taser.ts\"],\n },\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n },\n include: [\"src\", \".taser/types/**/*.d.ts\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.output\n.taser\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 '#taserjs/router'\n\nexport const Middleware = t.middleware('/$')\n .use(cors())\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { json } from '@taserjs/router/reply'\nimport { t } from '#taserjs/router'\n\nconst GET = t.get('/')\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler((_ctx) => {\n return 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 { json } from '@taserjs/router/reply'\nimport { t } from '#taserjs/router'\n\nconst GET = t.get('/health')\n\nexport type RouteContext = typeof GET.$Infer.Context\nexport const Route = GET.handler(${ctxArg} => {\n${body} return json({ ok: true })\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,mBAAmB,iBACrB;EACA,SAAS;GACP,KAAK;GACL,OAAO;GACP,WAAW;GACX,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,OAAO,EACL,mBAAmB,CAAC,gBAAgB,EACtC;GACA,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;EACV;EACA,SAAS,CAAC,OAAO,wBAAwB;CAC3C,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;;;AAUT;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"}
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 scripts: {\n dev: \"vite\",\n build: \"vite build\",\n typecheck: \"tsc --noEmit -p tsconfig.json\",\n ...scripts,\n },\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n strict: true,\n skipLibCheck: true,\n verbatimModuleSyntax: true,\n isolatedModules: true,\n noEmit: true,\n },\n include: [\"src\", \".taser/types/**/*.d.ts\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nexport function gitignoreTemplate(): string {\n return `node_modules\ndist\n.output\n.taser\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'\nimport { t } from '@taserjs/router'\n\nexport default t.layout('/$')\n .use(cors())\n`;\n}\n\nexport function indexRouteTemplate(): string {\n return `import { t } from '@taserjs/router'\nimport { json } from '@taserjs/router/reply'\n\nexport default t.get('/').handler((_ctx) => {\n return 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 { t } from '@taserjs/router'\nimport { json } from '@taserjs/router/reply'\n\nexport default t.get('/health').handler(${ctxArg} => {\n${body} return json({ ok: true })\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;GACP,KAAK;GACL,OAAO;GACP,WAAW;GACX,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UACb;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,cAAc;GACd,sBAAsB;GACtB,iBAAiB;GACjB,QAAQ;EACV;EACA,SAAS,CAAC,OAAO,wBAAwB;CAC3C,GACA,MACA,CACF,EAAE;AACJ;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;;;AAUT;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;;;;;;AAMT;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;;;0CAFQ,MAAM,SAAS,IAAI,UAAU,SAKG;EAC/C,KAAK;;;AAGP"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-taserjs",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Scaffold a new Taser application",
5
5
  "license": "ISC",
6
6
  "repository": {
@@ -32,7 +32,7 @@
32
32
  "typescript": "^5.9.3",
33
33
  "vite": "^8.1.5",
34
34
  "vitest": "^4.1.10",
35
- "@taserjs/router-generator": "0.1.4"
35
+ "@taserjs/router-generator": "0.1.6"
36
36
  },
37
37
  "engines": {
38
38
  "node": ">=20.19"
@@ -16,16 +16,14 @@ export const VALIDATION_BLOCK_TEMPLATE: Record<ValidatorId, string> = {
16
16
  .query(v.object({ name: v.optional(v.string(), 'Taser') }))`,
17
17
  };
18
18
 
19
- const ROUTE_TEMPLATE = (validator: ValidatorId) => `import { json } from '@taserjs/router/reply'
20
- import { t } from '#taserjs/router'
19
+ const ROUTE_TEMPLATE = (validator: ValidatorId) => `import { t } from '@taserjs/router'
20
+ import { json } from '@taserjs/router/reply'
21
21
  ${IMPORT_LINES[validator]}
22
22
 
23
- const GET = t.get('/')${VALIDATION_BLOCK_TEMPLATE[validator]}
24
-
25
- export type RouteContext = typeof GET.$Infer.Context
26
- export const Route = GET.handler((ctx) => {
27
- return json({ message: \`Hello, \${ctx.query.name}!\` })
28
- })
23
+ export default t.get('/')${VALIDATION_BLOCK_TEMPLATE[validator]}
24
+ .handler((ctx) => {
25
+ return json({ message: \`Hello, \${ctx.query.name}!\` })
26
+ })
29
27
  `;
30
28
 
31
29
  export const ValidatorAddon = (validator: ValidatorId): AddonDefinition => {
@@ -113,7 +113,7 @@ export function taserTsTemplate(): string {
113
113
 
114
114
  import { context } from './context.js'
115
115
 
116
- export const t = createTaserApp({
116
+ export default createTaserApp({
117
117
  response: { validate: true },
118
118
  }).context(context)
119
119
  `;
@@ -10,9 +10,6 @@ export function packageJsonTemplate(
10
10
  version: "1.0.0",
11
11
  private: true,
12
12
  type: "module",
13
- imports: {
14
- "#taserjs/router": "./src/taser.ts",
15
- },
16
13
  scripts: {
17
14
  dev: "vite",
18
15
  build: "vite build",
@@ -30,9 +27,6 @@ export function tsconfigTemplate(): string {
30
27
  compilerOptions: {
31
28
  target: "ES2022",
32
29
  module: "NodeNext",
33
- paths: {
34
- "#taserjs/router": ["./src/taser.ts"],
35
- },
36
30
  strict: true,
37
31
  skipLibCheck: true,
38
32
  verbatimModuleSyntax: true,
@@ -86,22 +80,18 @@ ${bootBlock}
86
80
 
87
81
  export function rootLayoutTemplate(): string {
88
82
  return `import { cors } from '@taserjs/router/cors'
83
+ import { t } from '@taserjs/router'
89
84
 
90
- import { t } from '#taserjs/router'
91
-
92
- export const Middleware = t.middleware('/$')
85
+ export default t.layout('/$')
93
86
  .use(cors())
94
87
  `;
95
88
  }
96
89
 
97
90
  export function indexRouteTemplate(): string {
98
- return `import { json } from '@taserjs/router/reply'
99
- import { t } from '#taserjs/router'
91
+ return `import { t } from '@taserjs/router'
92
+ import { json } from '@taserjs/router/reply'
100
93
 
101
- const GET = t.get('/')
102
-
103
- export type RouteContext = typeof GET.$Infer.Context
104
- export const Route = GET.handler((_ctx) => {
94
+ export default t.get('/').handler((_ctx) => {
105
95
  return json({ message: 'Welcome to Taser' })
106
96
  })
107
97
  `;
@@ -121,13 +111,10 @@ export function healthRouteTemplate(ctx: ScaffoldContext): string {
121
111
  const body = lines.length > 0 ? `${lines.join("\n")}\n` : "";
122
112
  const ctxArg = lines.length > 0 ? "(ctx)" : "(_ctx)";
123
113
 
124
- return `import { json } from '@taserjs/router/reply'
125
- import { t } from '#taserjs/router'
126
-
127
- const GET = t.get('/health')
114
+ return `import { t } from '@taserjs/router'
115
+ import { json } from '@taserjs/router/reply'
128
116
 
129
- export type RouteContext = typeof GET.$Infer.Context
130
- export const Route = GET.handler(${ctxArg} => {
117
+ export default t.get('/health').handler(${ctxArg} => {
131
118
  ${body} return json({ ok: true })
132
119
  })
133
120
  `;