create-taserjs 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +22 -0
  3. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  4. package/dist/cjs/addons/drizzle/index.cjs +124 -0
  5. package/dist/cjs/addons/drizzle/index.cjs.map +1 -0
  6. package/dist/cjs/addons/drizzle/index.d.cts +2 -0
  7. package/dist/cjs/addons/kysely/index.cjs +96 -0
  8. package/dist/cjs/addons/kysely/index.cjs.map +1 -0
  9. package/dist/cjs/addons/kysely/index.d.cts +2 -0
  10. package/dist/cjs/addons/pino/index.cjs +30 -0
  11. package/dist/cjs/addons/pino/index.cjs.map +1 -0
  12. package/dist/cjs/addons/pino/index.d.cts +2 -0
  13. package/dist/cjs/addons/prisma/index.cjs +66 -0
  14. package/dist/cjs/addons/prisma/index.cjs.map +1 -0
  15. package/dist/cjs/addons/prisma/index.d.cts +2 -0
  16. package/dist/cjs/addons/registry.cjs +52 -0
  17. package/dist/cjs/addons/registry.cjs.map +1 -0
  18. package/dist/cjs/addons/registry.d.cts +5 -0
  19. package/dist/cjs/addons/types.d.cts +16 -0
  20. package/dist/cjs/addons/winston/index.cjs +34 -0
  21. package/dist/cjs/addons/winston/index.cjs.map +1 -0
  22. package/dist/cjs/addons/winston/index.d.cts +2 -0
  23. package/dist/cjs/cli.cjs +56 -0
  24. package/dist/cjs/cli.cjs.map +1 -0
  25. package/dist/cjs/cli.d.cts +2 -0
  26. package/dist/cjs/commands/create.cjs +243 -0
  27. package/dist/cjs/commands/create.cjs.map +1 -0
  28. package/dist/cjs/commands/create.d.cts +11 -0
  29. package/dist/cjs/core/json-output.cjs +16 -0
  30. package/dist/cjs/core/json-output.cjs.map +1 -0
  31. package/dist/cjs/core/json-output.d.cts +4 -0
  32. package/dist/cjs/core/package-manager.cjs +64 -0
  33. package/dist/cjs/core/package-manager.cjs.map +1 -0
  34. package/dist/cjs/core/package-manager.d.cts +7 -0
  35. package/dist/cjs/core/parse-options.cjs +59 -0
  36. package/dist/cjs/core/parse-options.cjs.map +1 -0
  37. package/dist/cjs/core/parse-options.d.cts +18 -0
  38. package/dist/cjs/core/project-config.cjs +18 -0
  39. package/dist/cjs/core/project-config.cjs.map +1 -0
  40. package/dist/cjs/core/project-config.d.cts +2 -0
  41. package/dist/cjs/core/resolve-packages.cjs +52 -0
  42. package/dist/cjs/core/resolve-packages.cjs.map +1 -0
  43. package/dist/cjs/core/resolve-packages.d.cts +5 -0
  44. package/dist/cjs/core/scaffold-engine.cjs +73 -0
  45. package/dist/cjs/core/scaffold-engine.cjs.map +1 -0
  46. package/dist/cjs/core/scaffold-engine.d.cts +2 -0
  47. package/dist/cjs/core/types.cjs +27 -0
  48. package/dist/cjs/core/types.cjs.map +1 -0
  49. package/dist/cjs/core/types.d.cts +37 -0
  50. package/dist/cjs/core/validate-project-name.cjs +45 -0
  51. package/dist/cjs/core/validate-project-name.cjs.map +1 -0
  52. package/dist/cjs/core/validate-project-name.d.cts +1 -0
  53. package/dist/cjs/frameworks/index.cjs +106 -0
  54. package/dist/cjs/frameworks/index.cjs.map +1 -0
  55. package/dist/cjs/frameworks/index.d.cts +3 -0
  56. package/dist/cjs/scaffold.d.cts +3 -0
  57. package/dist/cjs/templates/base.cjs +186 -0
  58. package/dist/cjs/templates/base.cjs.map +1 -0
  59. package/dist/cjs/templates/base.d.cts +12 -0
  60. package/dist/cjs/types.d.cts +1 -0
  61. package/dist/esm/addons/drizzle/index.d.ts +2 -0
  62. package/dist/esm/addons/drizzle/index.js +124 -0
  63. package/dist/esm/addons/drizzle/index.js.map +1 -0
  64. package/dist/esm/addons/kysely/index.d.ts +2 -0
  65. package/dist/esm/addons/kysely/index.js +96 -0
  66. package/dist/esm/addons/kysely/index.js.map +1 -0
  67. package/dist/esm/addons/pino/index.d.ts +2 -0
  68. package/dist/esm/addons/pino/index.js +30 -0
  69. package/dist/esm/addons/pino/index.js.map +1 -0
  70. package/dist/esm/addons/prisma/index.d.ts +2 -0
  71. package/dist/esm/addons/prisma/index.js +66 -0
  72. package/dist/esm/addons/prisma/index.js.map +1 -0
  73. package/dist/esm/addons/registry.d.ts +5 -0
  74. package/dist/esm/addons/registry.js +50 -0
  75. package/dist/esm/addons/registry.js.map +1 -0
  76. package/dist/esm/addons/types.d.ts +16 -0
  77. package/dist/esm/addons/winston/index.d.ts +2 -0
  78. package/dist/esm/addons/winston/index.js +34 -0
  79. package/dist/esm/addons/winston/index.js.map +1 -0
  80. package/dist/esm/cli.d.ts +2 -0
  81. package/dist/esm/cli.js +53 -0
  82. package/dist/esm/cli.js.map +1 -0
  83. package/dist/esm/commands/create.d.ts +11 -0
  84. package/dist/esm/commands/create.js +238 -0
  85. package/dist/esm/commands/create.js.map +1 -0
  86. package/dist/esm/core/json-output.d.ts +4 -0
  87. package/dist/esm/core/json-output.js +14 -0
  88. package/dist/esm/core/json-output.js.map +1 -0
  89. package/dist/esm/core/package-manager.d.ts +7 -0
  90. package/dist/esm/core/package-manager.js +62 -0
  91. package/dist/esm/core/package-manager.js.map +1 -0
  92. package/dist/esm/core/parse-options.d.ts +18 -0
  93. package/dist/esm/core/parse-options.js +56 -0
  94. package/dist/esm/core/parse-options.js.map +1 -0
  95. package/dist/esm/core/project-config.d.ts +2 -0
  96. package/dist/esm/core/project-config.js +16 -0
  97. package/dist/esm/core/project-config.js.map +1 -0
  98. package/dist/esm/core/resolve-packages.d.ts +5 -0
  99. package/dist/esm/core/resolve-packages.js +52 -0
  100. package/dist/esm/core/resolve-packages.js.map +1 -0
  101. package/dist/esm/core/scaffold-engine.d.ts +2 -0
  102. package/dist/esm/core/scaffold-engine.js +71 -0
  103. package/dist/esm/core/scaffold-engine.js.map +1 -0
  104. package/dist/esm/core/types.d.ts +37 -0
  105. package/dist/esm/core/types.js +23 -0
  106. package/dist/esm/core/types.js.map +1 -0
  107. package/dist/esm/core/validate-project-name.d.ts +1 -0
  108. package/dist/esm/core/validate-project-name.js +43 -0
  109. package/dist/esm/core/validate-project-name.js.map +1 -0
  110. package/dist/esm/frameworks/index.d.ts +3 -0
  111. package/dist/esm/frameworks/index.js +105 -0
  112. package/dist/esm/frameworks/index.js.map +1 -0
  113. package/dist/esm/scaffold.d.ts +3 -0
  114. package/dist/esm/templates/base.d.ts +12 -0
  115. package/dist/esm/templates/base.js +178 -0
  116. package/dist/esm/templates/base.js.map +1 -0
  117. package/dist/esm/types.d.ts +1 -0
  118. package/package.json +45 -0
  119. package/src/addons/drizzle/index.ts +145 -0
  120. package/src/addons/kysely/index.ts +111 -0
  121. package/src/addons/pino/index.ts +30 -0
  122. package/src/addons/prisma/index.ts +81 -0
  123. package/src/addons/registry.ts +73 -0
  124. package/src/addons/types.ts +19 -0
  125. package/src/addons/winston/index.ts +34 -0
  126. package/src/cli.ts +57 -0
  127. package/src/commands/create.ts +253 -0
  128. package/src/core/json-output.ts +13 -0
  129. package/src/core/package-manager.ts +68 -0
  130. package/src/core/parse-options.ts +97 -0
  131. package/src/core/project-config.ts +27 -0
  132. package/src/core/resolve-packages.ts +62 -0
  133. package/src/core/scaffold-engine.ts +82 -0
  134. package/src/core/types.ts +51 -0
  135. package/src/core/validate-project-name.ts +59 -0
  136. package/src/frameworks/index.ts +111 -0
  137. package/src/scaffold.ts +3 -0
  138. package/src/templates/base.ts +209 -0
  139. package/src/types.ts +9 -0
@@ -0,0 +1,82 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises'
2
+ import path from 'node:path'
3
+
4
+ import { collectBootBindings, resolveAddons } from '../addons/registry.js'
5
+ import { indexTemplate, taserTsTemplate } from '../frameworks/index.js'
6
+ import { installPackages, resolveUserAgent } from './package-manager.js'
7
+ import { writeProjectConfig } from './project-config.js'
8
+ import { resolvePackages } from './resolve-packages.js'
9
+ import type { ScaffoldOptions, ScaffoldResult } from './types.js'
10
+ import {
11
+ contextTemplate,
12
+ gitignoreTemplate,
13
+ healthRouteTemplate,
14
+ indexRouteTemplate,
15
+ packageJsonTemplate,
16
+ rootLayoutTemplate,
17
+ starterManifestTemplate,
18
+ tsconfigTemplate,
19
+ tsdownConfigTemplate,
20
+ } from '../templates/base.js'
21
+
22
+ async function write(filePath: string, contents: string): Promise<void> {
23
+ await mkdir(path.dirname(filePath), { recursive: true })
24
+ await writeFile(filePath, contents, 'utf8')
25
+ }
26
+
27
+ export async function scaffoldProject(options: ScaffoldOptions): Promise<ScaffoldResult> {
28
+ const root = options.targetDir
29
+ const ctx = {
30
+ projectName: options.projectName,
31
+ targetDir: root,
32
+ framework: options.framework,
33
+ ...(options.db ? { db: options.db, driver: options.driver } : {}),
34
+ ...(options.logger ? { logger: options.logger } : {}),
35
+ }
36
+
37
+ const addons = resolveAddons(ctx)
38
+ const packages = resolvePackages(ctx)
39
+ const bootBindings = collectBootBindings(ctx)
40
+
41
+ await write(path.join(root, 'package.json'), packageJsonTemplate(options.projectName, packages.scripts))
42
+ await write(path.join(root, 'tsconfig.json'), tsconfigTemplate())
43
+ await write(path.join(root, 'tsdown.config.ts'), tsdownConfigTemplate())
44
+ await write(path.join(root, '.gitignore'), gitignoreTemplate())
45
+ await write(path.join(root, 'src/context.ts'), contextTemplate(bootBindings))
46
+ await write(path.join(root, 'src/taser.ts'), taserTsTemplate(options.framework))
47
+ await write(path.join(root, 'src/index.ts'), indexTemplate(options.framework))
48
+ await write(path.join(root, 'src/routes/$.ts'), rootLayoutTemplate())
49
+ await write(path.join(root, 'src/routes/index.get.ts'), indexRouteTemplate())
50
+ await write(path.join(root, 'src/routes/health.get.ts'), healthRouteTemplate(ctx))
51
+ await write(path.join(root, 'src/routeManifest.gen.ts'), starterManifestTemplate())
52
+
53
+ for (const addon of addons) {
54
+ await addon.apply(ctx, (filePath, contents) => write(path.join(root, filePath), contents))
55
+ }
56
+
57
+ await writeProjectConfig(root, ctx)
58
+
59
+ if (options.skipInstall) {
60
+ return {
61
+ projectName: ctx.projectName,
62
+ targetDir: root,
63
+ framework: ctx.framework,
64
+ ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),
65
+ ...(ctx.logger ? { logger: ctx.logger } : {}),
66
+ }
67
+ }
68
+
69
+ const agent = options.agent ?? resolveUserAgent()
70
+ await installPackages(agent, root, {
71
+ dependencies: packages.dependencies,
72
+ devDependencies: packages.devDependencies,
73
+ })
74
+
75
+ return {
76
+ projectName: ctx.projectName,
77
+ targetDir: root,
78
+ framework: ctx.framework,
79
+ ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),
80
+ ...(ctx.logger ? { logger: ctx.logger } : {}),
81
+ }
82
+ }
@@ -0,0 +1,51 @@
1
+ import type { Agent } from 'package-manager-detector'
2
+
3
+ export type Framework = 'node' | 'express' | 'hono' | 'fastify'
4
+
5
+ export const FRAMEWORKS: readonly Framework[] = ['node', 'express', 'hono', 'fastify']
6
+
7
+ export type DbOdm = 'drizzle' | 'prisma' | 'kysely'
8
+
9
+ export const DB_ODMS: readonly DbOdm[] = ['drizzle', 'prisma', 'kysely']
10
+
11
+ export type DbDriver = 'postgres' | 'sqlite' | 'mysql'
12
+
13
+ export const DB_DRIVERS: readonly DbDriver[] = ['postgres', 'sqlite', 'mysql']
14
+
15
+ export const DEFAULT_DB_DRIVER: DbDriver = 'sqlite'
16
+
17
+ export type LoggerId = 'pino' | 'winston'
18
+
19
+ export const LOGGERS: readonly LoggerId[] = ['pino', 'winston']
20
+
21
+ export type PackageGroups = {
22
+ dependencies: string[]
23
+ devDependencies: string[]
24
+ scripts: Record<string, string>
25
+ }
26
+
27
+ export type ScaffoldContext = {
28
+ projectName: string
29
+ targetDir: string
30
+ framework: Framework
31
+ db?: DbOdm
32
+ driver?: DbDriver
33
+ logger?: LoggerId
34
+ }
35
+
36
+ export type ScaffoldOptions = ScaffoldContext & {
37
+ skipInstall?: boolean
38
+ agent?: Agent
39
+ }
40
+
41
+ export type ScaffoldResult = ScaffoldContext
42
+
43
+ export type CapabilitiesCatalog = {
44
+ frameworks: Framework[]
45
+ db: {
46
+ odms: DbOdm[]
47
+ drivers: DbDriver[]
48
+ defaultDriver: DbDriver
49
+ }
50
+ loggers: LoggerId[]
51
+ }
@@ -0,0 +1,59 @@
1
+ import path from 'node:path'
2
+
3
+ const RESERVED_WINDOWS_NAMES = new Set([
4
+ 'CON',
5
+ 'PRN',
6
+ 'AUX',
7
+ 'NVR',
8
+ 'NULL',
9
+ 'COM1',
10
+ 'COM2',
11
+ 'COM3',
12
+ 'COM4',
13
+ 'COM5',
14
+ 'COM6',
15
+ 'COM7',
16
+ 'COM8',
17
+ 'COM9',
18
+ 'LPT1',
19
+ 'LPT2',
20
+ 'LPT3',
21
+ 'LPT4',
22
+ 'LPT5',
23
+ 'LPT6',
24
+ 'LPT7',
25
+ 'LPT8',
26
+ 'LPT9',
27
+ ])
28
+
29
+ export function validateProjectName(name: string, cwd = process.cwd()): string | undefined {
30
+ const trimmed = name.trim()
31
+ if (!trimmed) {
32
+ return 'Project name is required'
33
+ }
34
+
35
+ if (trimmed.includes('..')) {
36
+ return 'Project name cannot contain ".."'
37
+ }
38
+
39
+ if (trimmed.includes('/') || trimmed.includes('\\')) {
40
+ return 'Project name cannot contain path separators'
41
+ }
42
+
43
+ if (trimmed.startsWith('.') || trimmed.endsWith('.')) {
44
+ return 'Project name cannot start or end with a dot'
45
+ }
46
+
47
+ const baseName = trimmed.split('.')[0]?.toUpperCase()
48
+ if (baseName && RESERVED_WINDOWS_NAMES.has(baseName)) {
49
+ return `Project name "${trimmed}" is reserved on Windows`
50
+ }
51
+
52
+ const targetDir = path.resolve(cwd, trimmed)
53
+ const relative = path.relative(cwd, targetDir)
54
+ if (relative.startsWith('..') || path.isAbsolute(relative)) {
55
+ return 'Project name resolves outside the current directory'
56
+ }
57
+
58
+ return undefined
59
+ }
@@ -0,0 +1,111 @@
1
+ import type { Framework } from '../core/types.js'
2
+
3
+ export function indexTemplate(framework: Framework): string {
4
+ switch (framework) {
5
+ case 'express':
6
+ return `import express from 'express'
7
+ import { createExpressHandler } from '@taserjs/adapter-express'
8
+
9
+ import { routeManifest } from '#src/routeManifest.gen.js'
10
+ import { t } from '#src/taser.js'
11
+
12
+ const router = t.create(routeManifest)
13
+
14
+ const taser = createExpressHandler(router)
15
+ const app = express()
16
+ taser.mount('/api{/*splat}', app)
17
+
18
+ const port = Number(process.env.PORT ?? 3000)
19
+ app.listen(port, () => {
20
+ console.log(\`Express listening on http://localhost:\${port}\`)
21
+ })
22
+ `
23
+ case 'hono':
24
+ return `import { serve } from '@hono/node-server'
25
+ import { Hono } from 'hono'
26
+
27
+ import { routeManifest } from '#src/routeManifest.gen.js'
28
+ import { t } from '#src/taser.js'
29
+
30
+ const router = t.create(routeManifest)
31
+
32
+ const app = new Hono()
33
+ const api = router.base('/api')
34
+ app.all('/api/*', c => api.native(c).fetch(c.req.raw))
35
+
36
+ const port = Number(process.env.PORT ?? 3000)
37
+ serve({ fetch: app.fetch, port }, () => {
38
+ console.log(\`Hono listening on http://localhost:\${port}\`)
39
+ })
40
+ `
41
+ case 'fastify':
42
+ return `import Fastify from 'fastify'
43
+ import { createFastifyHandler } from '@taserjs/adapter-fastify'
44
+
45
+ import { routeManifest } from '#src/routeManifest.gen.js'
46
+ import { t } from '#src/taser.js'
47
+
48
+ const router = t.create(routeManifest)
49
+
50
+ const taser = createFastifyHandler(router)
51
+ const app = Fastify()
52
+ taser.mount('/api/*', app)
53
+
54
+ const port = Number(process.env.PORT ?? 3000)
55
+ await app.listen({ port })
56
+ console.log(\`Fastify listening on http://localhost:\${port}\`)
57
+ `
58
+ case 'node':
59
+ default:
60
+ return `import { createServer } from 'node:http'
61
+ import { createNodeHandler } from '@taserjs/adapter-node'
62
+
63
+ import { routeManifest } from '#src/routeManifest.gen.js'
64
+ import { t } from '#src/taser.js'
65
+
66
+ const router = t.create(routeManifest)
67
+
68
+ const taser = createNodeHandler(router)
69
+ const app = createServer()
70
+ taser.mount('/api/*', app)
71
+
72
+ const port = Number(process.env.PORT ?? 3000)
73
+ app.listen(port, () => {
74
+ console.log(\`Node listening on http://localhost:\${port}\`)
75
+ })
76
+ `
77
+ }
78
+ }
79
+
80
+ export function taserTsTemplate(framework: Framework = 'node'): string {
81
+ if (framework === 'hono') {
82
+ return `import type { Context } from 'hono'
83
+ import { createTaserApp, type InferAppContext } from '@taserjs/router'
84
+
85
+ import { context } from '#src/context.js'
86
+
87
+ declare module '@taserjs/router' {
88
+ interface RouterRegister {
89
+ NativeContext: Context
90
+ }
91
+ }
92
+
93
+ export const t = createTaserApp({
94
+ response: { validate: true },
95
+ }).context(context)
96
+
97
+ export type AppContext = InferAppContext<typeof context>
98
+ `
99
+ }
100
+
101
+ return `import { createTaserApp, type InferAppContext } from '@taserjs/router'
102
+
103
+ import { context } from '#src/context.js'
104
+
105
+ export const t = createTaserApp({
106
+ response: { validate: true },
107
+ }).context(context)
108
+
109
+ export type AppContext = InferAppContext<typeof context>
110
+ `
111
+ }
@@ -0,0 +1,3 @@
1
+ export { scaffoldProject } from './core/scaffold-engine.js'
2
+ export { getPackageGroups, resolvePackages } from './core/resolve-packages.js'
3
+ export type { Framework, ScaffoldOptions, ScaffoldResult, PackageGroups } from './core/types.js'
@@ -0,0 +1,209 @@
1
+ import type { BootBinding } from '../addons/types.js'
2
+ import type { ScaffoldContext } from '../core/types.js'
3
+
4
+ export function packageJsonTemplate(projectName: string, scripts: Record<string, string> = {}): string {
5
+ const pkg = {
6
+ name: projectName,
7
+ version: '1.0.0',
8
+ private: true,
9
+ type: 'module',
10
+ imports: {
11
+ '#src/*': './src/*',
12
+ },
13
+ scripts: {
14
+ 'dev': 'run-p dev:server dev:taser',
15
+ 'dev:server': 'tsx watch src/index.ts',
16
+ 'dev:taser': 'taser watch',
17
+ 'start': 'tsx src/index.ts',
18
+ 'generate': 'taser generate',
19
+ 'build': 'taser generate && tsdown build',
20
+ 'serve': 'node dist/index.js',
21
+ 'typecheck': 'tsc --noEmit -p tsconfig.json',
22
+ ...scripts,
23
+ },
24
+ }
25
+
26
+ return `${JSON.stringify(pkg, null, 2)}\n`
27
+ }
28
+
29
+ export function tsdownConfigTemplate(): string {
30
+ return `import { defineConfig } from 'tsdown'
31
+
32
+ export default defineConfig({
33
+ entry: ['./src/index.ts'],
34
+ format: 'esm',
35
+ platform: 'node',
36
+ target: 'node20',
37
+ outDir: 'dist',
38
+ clean: true,
39
+ sourcemap: true,
40
+ })
41
+ `
42
+ }
43
+
44
+ export function tsconfigTemplate(): string {
45
+ return `${JSON.stringify({
46
+ compilerOptions: {
47
+ target: 'ES2022',
48
+ lib: ['ES2022', 'DOM'],
49
+ module: 'ESNext',
50
+ moduleResolution: 'bundler',
51
+ paths: {
52
+ '#src/*': ['./src/*'],
53
+ },
54
+ strict: true,
55
+ skipLibCheck: true,
56
+ verbatimModuleSyntax: true,
57
+ isolatedModules: true,
58
+ noEmit: true,
59
+ types: ['node'],
60
+ },
61
+ include: ['src'],
62
+ }, null, 2)}\n`
63
+ }
64
+
65
+ export function gitignoreTemplate(): string {
66
+ return `node_modules
67
+ dist
68
+ .DS_Store
69
+ *.log
70
+ .env
71
+ local.db
72
+ drizzle
73
+ `
74
+ }
75
+
76
+ export function contextTemplate(bindings: BootBinding[]): string {
77
+ const imports = bindings.map(
78
+ binding => `import { ${binding.factoryName} } from '${binding.importPath}'`,
79
+ )
80
+
81
+ const bootBody = bindings.length > 0
82
+ ? bindings.map(binding => ` ${binding.key}: ${binding.factoryName}(),`).join('\n')
83
+ : ''
84
+
85
+ const bootBlock = bindings.length > 0
86
+ ? ` boot: () => ({\n${bootBody}\n }),`
87
+ : ''
88
+
89
+ const importBlock = imports.length > 0 ? `${imports.join('\n')}\n\n` : ''
90
+
91
+ return `${importBlock}import { createContext } from '@taserjs/router'
92
+
93
+ export const context = createContext({
94
+ ${bootBlock}
95
+ request: () => ({
96
+ requestId: crypto.randomUUID(),
97
+ }),
98
+ })
99
+ `
100
+ }
101
+
102
+ export function rootLayoutTemplate(): string {
103
+ return `import { bodyLimit } from '@taserjs/router/body-limit'
104
+ import { secureHeaders } from '@taserjs/router/secure-headers'
105
+
106
+ import { t } from '#src/taser.js'
107
+
108
+ export const Middleware = t.middleware('/$')
109
+ .use(secureHeaders())
110
+ .use(bodyLimit({ maxSize: 1_000_000 }))
111
+ `
112
+ }
113
+
114
+ export function indexRouteTemplate(): string {
115
+ return `import { t } from '#src/taser.js'
116
+
117
+ export const Route = t.get('/').handler((ctx) => {
118
+ return ctx.reply.json({ message: 'Welcome to Taser' })
119
+ })
120
+ `
121
+ }
122
+
123
+ export function healthRouteTemplate(ctx: ScaffoldContext): string {
124
+ const lines: string[] = []
125
+
126
+ if (ctx.logger) {
127
+ lines.push(' ctx.logger.info(\'health check\')')
128
+ }
129
+
130
+ if (ctx.db) {
131
+ lines.push(' // ctx.db is available from context boot')
132
+ }
133
+
134
+ const body = lines.length > 0 ? `${lines.join('\n')}\n` : ''
135
+
136
+ return `import { t } from '#src/taser.js'
137
+
138
+ export const Route = t.get('/health').handler((ctx) => {
139
+ ${body} return ctx.reply.json({ ok: true })
140
+ })
141
+ `
142
+ }
143
+
144
+ /** Minimal placeholder until `taser generate` runs. */
145
+ export function starterManifestTemplate(): string {
146
+ return `/* eslint-disable */
147
+ // Run \`pnpm generate\` (taser generate) to replace this file.
148
+ import { Middleware as RootSplatLayoutImport } from './routes/$.js'
149
+ import { Route as RootIndexGetRouteImport } from './routes/index.get.js'
150
+ import { Route as HealthGetRouteImport } from './routes/health.get.js'
151
+
152
+ export const routeManifest = {
153
+ layouts: {
154
+ '/$': {
155
+ middlewares: RootSplatLayoutImport,
156
+ },
157
+ },
158
+ routes: {
159
+ '/': {
160
+ GET: {
161
+ layoutChain: ['/$'],
162
+ route: RootIndexGetRouteImport,
163
+ },
164
+ },
165
+ '/health': {
166
+ GET: {
167
+ layoutChain: ['/$'],
168
+ route: HealthGetRouteImport,
169
+ },
170
+ },
171
+ },
172
+ } as const
173
+
174
+ export type RoutePathGen = '/' | '/health'
175
+ export type LayoutIdGen = '/$'
176
+ export type LayoutTreeGen = {
177
+ '/$': {
178
+ parent: null
179
+ middlewares: typeof RootSplatLayoutImport
180
+ }
181
+ }
182
+ export type RouteByPathMethodGen = {
183
+ '/': {
184
+ GET: {
185
+ parent: '/$'
186
+ layoutChain: ['/$']
187
+ route: typeof RootIndexGetRouteImport
188
+ }
189
+ }
190
+ '/health': {
191
+ GET: {
192
+ parent: '/$'
193
+ layoutChain: ['/$']
194
+ route: typeof HealthGetRouteImport
195
+ }
196
+ }
197
+ }
198
+ export type RouteManifest = typeof routeManifest
199
+
200
+ declare module '@taserjs/router' {
201
+ interface RouterRegister {
202
+ RoutePath: RoutePathGen
203
+ LayoutId: LayoutIdGen
204
+ LayoutTree: LayoutTreeGen
205
+ RouteByPathMethod: RouteByPathMethodGen
206
+ }
207
+ }
208
+ `
209
+ }
package/src/types.ts ADDED
@@ -0,0 +1,9 @@
1
+ export type {
2
+ Framework,
3
+ DbOdm,
4
+ DbDriver,
5
+ LoggerId,
6
+ ScaffoldOptions,
7
+ ScaffoldResult,
8
+ PackageGroups,
9
+ } from './core/types.js'