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 @@
1
+ {"version":3,"file":"scaffold-engine.cjs","names":[],"sources":["../../../src/core/scaffold-engine.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { collectBootBindings, resolveAddons } from '../addons/registry.js'\nimport { indexTemplate, taserTsTemplate } from '../frameworks/index.js'\nimport { installPackages, resolveUserAgent } from './package-manager.js'\nimport { writeProjectConfig } from './project-config.js'\nimport { resolvePackages } from './resolve-packages.js'\nimport type { ScaffoldOptions, ScaffoldResult } from './types.js'\nimport {\n contextTemplate,\n gitignoreTemplate,\n healthRouteTemplate,\n indexRouteTemplate,\n packageJsonTemplate,\n rootLayoutTemplate,\n starterManifestTemplate,\n tsconfigTemplate,\n tsdownConfigTemplate,\n} from '../templates/base.js'\n\nasync function write(filePath: string, contents: string): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true })\n await writeFile(filePath, contents, 'utf8')\n}\n\nexport async function scaffoldProject(options: ScaffoldOptions): Promise<ScaffoldResult> {\n const root = options.targetDir\n const ctx = {\n projectName: options.projectName,\n targetDir: root,\n framework: options.framework,\n ...(options.db ? { db: options.db, driver: options.driver } : {}),\n ...(options.logger ? { logger: options.logger } : {}),\n }\n\n const addons = resolveAddons(ctx)\n const packages = resolvePackages(ctx)\n const bootBindings = collectBootBindings(ctx)\n\n await write(path.join(root, 'package.json'), packageJsonTemplate(options.projectName, packages.scripts))\n await write(path.join(root, 'tsconfig.json'), tsconfigTemplate())\n await write(path.join(root, 'tsdown.config.ts'), tsdownConfigTemplate())\n await write(path.join(root, '.gitignore'), gitignoreTemplate())\n await write(path.join(root, 'src/context.ts'), contextTemplate(bootBindings))\n await write(path.join(root, 'src/taser.ts'), taserTsTemplate(options.framework))\n await write(path.join(root, 'src/index.ts'), indexTemplate(options.framework))\n await write(path.join(root, 'src/routes/$.ts'), rootLayoutTemplate())\n await write(path.join(root, 'src/routes/index.get.ts'), indexRouteTemplate())\n await write(path.join(root, 'src/routes/health.get.ts'), healthRouteTemplate(ctx))\n await write(path.join(root, 'src/routeManifest.gen.ts'), starterManifestTemplate())\n\n for (const addon of addons) {\n await addon.apply(ctx, (filePath, contents) => write(path.join(root, filePath), contents))\n }\n\n await writeProjectConfig(root, ctx)\n\n if (options.skipInstall) {\n return {\n projectName: ctx.projectName,\n targetDir: root,\n framework: ctx.framework,\n ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),\n ...(ctx.logger ? { logger: ctx.logger } : {}),\n }\n }\n\n const agent = options.agent ?? resolveUserAgent()\n await installPackages(agent, root, {\n dependencies: packages.dependencies,\n devDependencies: packages.devDependencies,\n })\n\n return {\n projectName: ctx.projectName,\n targetDir: root,\n framework: ctx.framework,\n ...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),\n ...(ctx.logger ? { logger: ctx.logger } : {}),\n }\n}\n"],"mappings":";;;;;;;;;;;AAqBA,eAAe,MAAM,UAAkB,UAAiC;CACtE,OAAA,GAAM,iBAAA,MAAA,CAAM,UAAA,QAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;CACvD,OAAA,GAAM,iBAAA,UAAA,CAAU,UAAU,UAAU,MAAM;AAC5C;AAEA,eAAsB,gBAAgB,SAAmD;CACvF,MAAM,OAAO,QAAQ;CACrB,MAAM,MAAM;EACV,aAAa,QAAQ;EACrB,WAAW;EACX,WAAW,QAAQ;EACnB,GAAI,QAAQ,KAAK;GAAE,IAAI,QAAQ;GAAI,QAAQ,QAAQ;EAAO,IAAI,CAAC;EAC/D,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;CACrD;CAEA,MAAM,SAAS,iBAAA,cAAc,GAAG;CAChC,MAAM,WAAW,yBAAA,gBAAgB,GAAG;CACpC,MAAM,eAAe,iBAAA,oBAAoB,GAAG;CAE5C,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,cAAc,GAAG,aAAA,oBAAoB,QAAQ,aAAa,SAAS,OAAO,CAAC;CACvG,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,eAAe,GAAG,aAAA,iBAAiB,CAAC;CAChE,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,kBAAkB,GAAG,aAAA,qBAAqB,CAAC;CACvE,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,YAAY,GAAG,aAAA,kBAAkB,CAAC;CAC9D,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,gBAAgB,GAAG,aAAA,gBAAgB,YAAY,CAAC;CAC5E,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,cAAc,GAAG,cAAA,gBAAgB,QAAQ,SAAS,CAAC;CAC/E,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,cAAc,GAAG,cAAA,cAAc,QAAQ,SAAS,CAAC;CAC7E,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,iBAAiB,GAAG,aAAA,mBAAmB,CAAC;CACpE,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,yBAAyB,GAAG,aAAA,mBAAmB,CAAC;CAC5E,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,0BAA0B,GAAG,aAAA,oBAAoB,GAAG,CAAC;CACjF,MAAM,MAAM,UAAA,QAAK,KAAK,MAAM,0BAA0B,GAAG,aAAA,wBAAwB,CAAC;CAElF,KAAK,MAAM,SAAS,QAClB,MAAM,MAAM,MAAM,MAAM,UAAU,aAAa,MAAM,UAAA,QAAK,KAAK,MAAM,QAAQ,GAAG,QAAQ,CAAC;CAG3F,MAAM,uBAAA,mBAAmB,MAAM,GAAG;CAElC,IAAI,QAAQ,aACV,OAAO;EACL,aAAa,IAAI;EACjB,WAAW;EACX,WAAW,IAAI;EACf,GAAI,IAAI,KAAK;GAAE,IAAI,IAAI;GAAI,QAAQ,IAAI;EAAO,IAAI,CAAC;EACnD,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;CAC7C;CAGF,MAAM,QAAQ,QAAQ,SAAS,wBAAA,iBAAiB;CAChD,MAAM,wBAAA,gBAAgB,OAAO,MAAM;EACjC,cAAc,SAAS;EACvB,iBAAiB,SAAS;CAC5B,CAAC;CAED,OAAO;EACL,aAAa,IAAI;EACjB,WAAW;EACX,WAAW,IAAI;EACf,GAAI,IAAI,KAAK;GAAE,IAAI,IAAI;GAAI,QAAQ,IAAI;EAAO,IAAI,CAAC;EACnD,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;CAC7C;AACF"}
@@ -0,0 +1,2 @@
1
+ import { ScaffoldOptions, ScaffoldResult } from './types.js';
2
+ export declare function scaffoldProject(options: ScaffoldOptions): Promise<ScaffoldResult>;
@@ -0,0 +1,27 @@
1
+ //#region src/core/types.ts
2
+ var FRAMEWORKS = [
3
+ "node",
4
+ "express",
5
+ "hono",
6
+ "fastify"
7
+ ];
8
+ var DB_ODMS = [
9
+ "drizzle",
10
+ "prisma",
11
+ "kysely"
12
+ ];
13
+ var DB_DRIVERS = [
14
+ "postgres",
15
+ "sqlite",
16
+ "mysql"
17
+ ];
18
+ var DEFAULT_DB_DRIVER = "sqlite";
19
+ var LOGGERS = ["pino", "winston"];
20
+ //#endregion
21
+ exports.DB_DRIVERS = DB_DRIVERS;
22
+ exports.DB_ODMS = DB_ODMS;
23
+ exports.DEFAULT_DB_DRIVER = DEFAULT_DB_DRIVER;
24
+ exports.FRAMEWORKS = FRAMEWORKS;
25
+ exports.LOGGERS = LOGGERS;
26
+
27
+ //# sourceMappingURL=types.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.cjs","names":[],"sources":["../../../src/core/types.ts"],"sourcesContent":["import type { Agent } from 'package-manager-detector'\n\nexport type Framework = 'node' | 'express' | 'hono' | 'fastify'\n\nexport const FRAMEWORKS: readonly Framework[] = ['node', 'express', 'hono', 'fastify']\n\nexport type DbOdm = 'drizzle' | 'prisma' | 'kysely'\n\nexport const DB_ODMS: readonly DbOdm[] = ['drizzle', 'prisma', 'kysely']\n\nexport type DbDriver = 'postgres' | 'sqlite' | 'mysql'\n\nexport const DB_DRIVERS: readonly DbDriver[] = ['postgres', 'sqlite', 'mysql']\n\nexport const DEFAULT_DB_DRIVER: DbDriver = 'sqlite'\n\nexport type LoggerId = 'pino' | 'winston'\n\nexport const LOGGERS: readonly LoggerId[] = ['pino', 'winston']\n\nexport type PackageGroups = {\n dependencies: string[]\n devDependencies: string[]\n scripts: Record<string, string>\n}\n\nexport type ScaffoldContext = {\n projectName: string\n targetDir: string\n framework: Framework\n db?: DbOdm\n driver?: DbDriver\n logger?: LoggerId\n}\n\nexport type ScaffoldOptions = ScaffoldContext & {\n skipInstall?: boolean\n agent?: Agent\n}\n\nexport type ScaffoldResult = ScaffoldContext\n\nexport type CapabilitiesCatalog = {\n frameworks: Framework[]\n db: {\n odms: DbOdm[]\n drivers: DbDriver[]\n defaultDriver: DbDriver\n }\n loggers: LoggerId[]\n}\n"],"mappings":";AAIA,IAAa,aAAmC;CAAC;CAAQ;CAAW;CAAQ;AAAS;AAIrF,IAAa,UAA4B;CAAC;CAAW;CAAU;AAAQ;AAIvE,IAAa,aAAkC;CAAC;CAAY;CAAU;AAAO;AAE7E,IAAa,oBAA8B;AAI3C,IAAa,UAA+B,CAAC,QAAQ,SAAS"}
@@ -0,0 +1,37 @@
1
+ import { Agent } from 'package-manager-detector';
2
+ export type Framework = 'node' | 'express' | 'hono' | 'fastify';
3
+ export declare const FRAMEWORKS: readonly Framework[];
4
+ export type DbOdm = 'drizzle' | 'prisma' | 'kysely';
5
+ export declare const DB_ODMS: readonly DbOdm[];
6
+ export type DbDriver = 'postgres' | 'sqlite' | 'mysql';
7
+ export declare const DB_DRIVERS: readonly DbDriver[];
8
+ export declare const DEFAULT_DB_DRIVER: DbDriver;
9
+ export type LoggerId = 'pino' | 'winston';
10
+ export declare const LOGGERS: readonly LoggerId[];
11
+ export type PackageGroups = {
12
+ dependencies: string[];
13
+ devDependencies: string[];
14
+ scripts: Record<string, string>;
15
+ };
16
+ export type ScaffoldContext = {
17
+ projectName: string;
18
+ targetDir: string;
19
+ framework: Framework;
20
+ db?: DbOdm;
21
+ driver?: DbDriver;
22
+ logger?: LoggerId;
23
+ };
24
+ export type ScaffoldOptions = ScaffoldContext & {
25
+ skipInstall?: boolean;
26
+ agent?: Agent;
27
+ };
28
+ export type ScaffoldResult = ScaffoldContext;
29
+ export type CapabilitiesCatalog = {
30
+ frameworks: Framework[];
31
+ db: {
32
+ odms: DbOdm[];
33
+ drivers: DbDriver[];
34
+ defaultDriver: DbDriver;
35
+ };
36
+ loggers: LoggerId[];
37
+ };
@@ -0,0 +1,45 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ let node_path = require("node:path");
3
+ node_path = require_runtime.__toESM(node_path, 1);
4
+ //#region src/core/validate-project-name.ts
5
+ var RESERVED_WINDOWS_NAMES = /* @__PURE__ */ new Set([
6
+ "CON",
7
+ "PRN",
8
+ "AUX",
9
+ "NVR",
10
+ "NULL",
11
+ "COM1",
12
+ "COM2",
13
+ "COM3",
14
+ "COM4",
15
+ "COM5",
16
+ "COM6",
17
+ "COM7",
18
+ "COM8",
19
+ "COM9",
20
+ "LPT1",
21
+ "LPT2",
22
+ "LPT3",
23
+ "LPT4",
24
+ "LPT5",
25
+ "LPT6",
26
+ "LPT7",
27
+ "LPT8",
28
+ "LPT9"
29
+ ]);
30
+ function validateProjectName(name, cwd = process.cwd()) {
31
+ const trimmed = name.trim();
32
+ if (!trimmed) return "Project name is required";
33
+ if (trimmed.includes("..")) return "Project name cannot contain \"..\"";
34
+ if (trimmed.includes("/") || trimmed.includes("\\")) return "Project name cannot contain path separators";
35
+ if (trimmed.startsWith(".") || trimmed.endsWith(".")) return "Project name cannot start or end with a dot";
36
+ const baseName = trimmed.split(".")[0]?.toUpperCase();
37
+ if (baseName && RESERVED_WINDOWS_NAMES.has(baseName)) return `Project name "${trimmed}" is reserved on Windows`;
38
+ const targetDir = node_path.default.resolve(cwd, trimmed);
39
+ const relative = node_path.default.relative(cwd, targetDir);
40
+ if (relative.startsWith("..") || node_path.default.isAbsolute(relative)) return "Project name resolves outside the current directory";
41
+ }
42
+ //#endregion
43
+ exports.validateProjectName = validateProjectName;
44
+
45
+ //# sourceMappingURL=validate-project-name.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-project-name.cjs","names":[],"sources":["../../../src/core/validate-project-name.ts"],"sourcesContent":["import path from 'node:path'\n\nconst RESERVED_WINDOWS_NAMES = new Set([\n 'CON',\n 'PRN',\n 'AUX',\n 'NVR',\n 'NULL',\n 'COM1',\n 'COM2',\n 'COM3',\n 'COM4',\n 'COM5',\n 'COM6',\n 'COM7',\n 'COM8',\n 'COM9',\n 'LPT1',\n 'LPT2',\n 'LPT3',\n 'LPT4',\n 'LPT5',\n 'LPT6',\n 'LPT7',\n 'LPT8',\n 'LPT9',\n])\n\nexport function validateProjectName(name: string, cwd = process.cwd()): string | undefined {\n const trimmed = name.trim()\n if (!trimmed) {\n return 'Project name is required'\n }\n\n if (trimmed.includes('..')) {\n return 'Project name cannot contain \"..\"'\n }\n\n if (trimmed.includes('/') || trimmed.includes('\\\\')) {\n return 'Project name cannot contain path separators'\n }\n\n if (trimmed.startsWith('.') || trimmed.endsWith('.')) {\n return 'Project name cannot start or end with a dot'\n }\n\n const baseName = trimmed.split('.')[0]?.toUpperCase()\n if (baseName && RESERVED_WINDOWS_NAMES.has(baseName)) {\n return `Project name \"${trimmed}\" is reserved on Windows`\n }\n\n const targetDir = path.resolve(cwd, trimmed)\n const relative = path.relative(cwd, targetDir)\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n return 'Project name resolves outside the current directory'\n }\n\n return undefined\n}\n"],"mappings":";;;;AAEA,IAAM,yCAAyB,IAAI,IAAI;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,oBAAoB,MAAc,MAAM,QAAQ,IAAI,GAAuB;CACzF,MAAM,UAAU,KAAK,KAAK;CAC1B,IAAI,CAAC,SACH,OAAO;CAGT,IAAI,QAAQ,SAAS,IAAI,GACvB,OAAO;CAGT,IAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,IAAI,GAChD,OAAO;CAGT,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GACjD,OAAO;CAGT,MAAM,WAAW,QAAQ,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,YAAY;CACpD,IAAI,YAAY,uBAAuB,IAAI,QAAQ,GACjD,OAAO,iBAAiB,QAAQ;CAGlC,MAAM,YAAY,UAAA,QAAK,QAAQ,KAAK,OAAO;CAC3C,MAAM,WAAW,UAAA,QAAK,SAAS,KAAK,SAAS;CAC7C,IAAI,SAAS,WAAW,IAAI,KAAK,UAAA,QAAK,WAAW,QAAQ,GACvD,OAAO;AAIX"}
@@ -0,0 +1 @@
1
+ export declare function validateProjectName(name: string, cwd?: string): string | undefined;
@@ -0,0 +1,106 @@
1
+ //#region src/frameworks/index.ts
2
+ function indexTemplate(framework) {
3
+ switch (framework) {
4
+ case "express": return `import express from 'express'
5
+ import { createExpressHandler } from '@taserjs/adapter-express'
6
+
7
+ import { routeManifest } from '#src/routeManifest.gen.js'
8
+ import { t } from '#src/taser.js'
9
+
10
+ const router = t.create(routeManifest)
11
+
12
+ const taser = createExpressHandler(router)
13
+ const app = express()
14
+ taser.mount('/api{/*splat}', app)
15
+
16
+ const port = Number(process.env.PORT ?? 3000)
17
+ app.listen(port, () => {
18
+ console.log(\`Express listening on http://localhost:\${port}\`)
19
+ })
20
+ `;
21
+ case "hono": return `import { serve } from '@hono/node-server'
22
+ import { Hono } from 'hono'
23
+
24
+ import { routeManifest } from '#src/routeManifest.gen.js'
25
+ import { t } from '#src/taser.js'
26
+
27
+ const router = t.create(routeManifest)
28
+
29
+ const app = new Hono()
30
+ const api = router.base('/api')
31
+ app.all('/api/*', c => api.native(c).fetch(c.req.raw))
32
+
33
+ const port = Number(process.env.PORT ?? 3000)
34
+ serve({ fetch: app.fetch, port }, () => {
35
+ console.log(\`Hono listening on http://localhost:\${port}\`)
36
+ })
37
+ `;
38
+ case "fastify": return `import Fastify from 'fastify'
39
+ import { createFastifyHandler } from '@taserjs/adapter-fastify'
40
+
41
+ import { routeManifest } from '#src/routeManifest.gen.js'
42
+ import { t } from '#src/taser.js'
43
+
44
+ const router = t.create(routeManifest)
45
+
46
+ const taser = createFastifyHandler(router)
47
+ const app = Fastify()
48
+ taser.mount('/api/*', app)
49
+
50
+ const port = Number(process.env.PORT ?? 3000)
51
+ await app.listen({ port })
52
+ console.log(\`Fastify listening on http://localhost:\${port}\`)
53
+ `;
54
+ default: return `import { createServer } from 'node:http'
55
+ import { createNodeHandler } from '@taserjs/adapter-node'
56
+
57
+ import { routeManifest } from '#src/routeManifest.gen.js'
58
+ import { t } from '#src/taser.js'
59
+
60
+ const router = t.create(routeManifest)
61
+
62
+ const taser = createNodeHandler(router)
63
+ const app = createServer()
64
+ taser.mount('/api/*', app)
65
+
66
+ const port = Number(process.env.PORT ?? 3000)
67
+ app.listen(port, () => {
68
+ console.log(\`Node listening on http://localhost:\${port}\`)
69
+ })
70
+ `;
71
+ }
72
+ }
73
+ function taserTsTemplate(framework = "node") {
74
+ if (framework === "hono") return `import type { Context } from 'hono'
75
+ import { createTaserApp, type InferAppContext } from '@taserjs/router'
76
+
77
+ import { context } from '#src/context.js'
78
+
79
+ declare module '@taserjs/router' {
80
+ interface RouterRegister {
81
+ NativeContext: Context
82
+ }
83
+ }
84
+
85
+ export const t = createTaserApp({
86
+ response: { validate: true },
87
+ }).context(context)
88
+
89
+ export type AppContext = InferAppContext<typeof context>
90
+ `;
91
+ return `import { createTaserApp, type InferAppContext } from '@taserjs/router'
92
+
93
+ import { context } from '#src/context.js'
94
+
95
+ export const t = createTaserApp({
96
+ response: { validate: true },
97
+ }).context(context)
98
+
99
+ export type AppContext = InferAppContext<typeof context>
100
+ `;
101
+ }
102
+ //#endregion
103
+ exports.indexTemplate = indexTemplate;
104
+ exports.taserTsTemplate = taserTsTemplate;
105
+
106
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/frameworks/index.ts"],"sourcesContent":["import type { Framework } from '../core/types.js'\n\nexport function indexTemplate(framework: Framework): string {\n switch (framework) {\n case 'express':\n return `import express from 'express'\nimport { createExpressHandler } from '@taserjs/adapter-express'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createExpressHandler(router)\nconst app = express()\ntaser.mount('/api{/*splat}', app)\n\nconst port = Number(process.env.PORT ?? 3000)\napp.listen(port, () => {\n console.log(\\`Express listening on http://localhost:\\${port}\\`)\n})\n`\n case 'hono':\n return `import { serve } from '@hono/node-server'\nimport { Hono } from 'hono'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst app = new Hono()\nconst api = router.base('/api')\napp.all('/api/*', c => api.native(c).fetch(c.req.raw))\n\nconst port = Number(process.env.PORT ?? 3000)\nserve({ fetch: app.fetch, port }, () => {\n console.log(\\`Hono listening on http://localhost:\\${port}\\`)\n})\n`\n case 'fastify':\n return `import Fastify from 'fastify'\nimport { createFastifyHandler } from '@taserjs/adapter-fastify'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createFastifyHandler(router)\nconst app = Fastify()\ntaser.mount('/api/*', app)\n\nconst port = Number(process.env.PORT ?? 3000)\nawait app.listen({ port })\nconsole.log(\\`Fastify listening on http://localhost:\\${port}\\`)\n`\n case 'node':\n default:\n return `import { createServer } from 'node:http'\nimport { createNodeHandler } from '@taserjs/adapter-node'\n\nimport { routeManifest } from '#src/routeManifest.gen.js'\nimport { t } from '#src/taser.js'\n\nconst router = t.create(routeManifest)\n\nconst taser = createNodeHandler(router)\nconst app = createServer()\ntaser.mount('/api/*', app)\n\nconst port = Number(process.env.PORT ?? 3000)\napp.listen(port, () => {\n console.log(\\`Node listening on http://localhost:\\${port}\\`)\n})\n`\n }\n}\n\nexport function taserTsTemplate(framework: Framework = 'node'): string {\n if (framework === 'hono') {\n return `import type { Context } from 'hono'\nimport { createTaserApp, type InferAppContext } from '@taserjs/router'\n\nimport { context } from '#src/context.js'\n\ndeclare module '@taserjs/router' {\n interface RouterRegister {\n NativeContext: Context\n }\n}\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n\nexport type AppContext = InferAppContext<typeof context>\n`\n }\n\n return `import { createTaserApp, type InferAppContext } from '@taserjs/router'\n\nimport { context } from '#src/context.js'\n\nexport const t = createTaserApp({\n response: { validate: true },\n}).context(context)\n\nexport type AppContext = InferAppContext<typeof context>\n`\n}\n"],"mappings":";AAEA,SAAgB,cAAc,WAA8B;CAC1D,QAAQ,WAAR;EACE,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;;EAiBT,KAAK,QACH,OAAO;;;;;;;;;;;;;;;;;EAiBT,KAAK,WACH,OAAO;;;;;;;;;;;;;;;;EAiBT,SACE,OAAO;;;;;;;;;;;;;;;;;CAiBX;AACF;AAEA,SAAgB,gBAAgB,YAAuB,QAAgB;CACrE,IAAI,cAAc,QAChB,OAAO;;;;;;;;;;;;;;;;;CAmBT,OAAO;;;;;;;;;;AAUT"}
@@ -0,0 +1,3 @@
1
+ import { Framework } from '../core/types.js';
2
+ export declare function indexTemplate(framework: Framework): string;
3
+ export declare function taserTsTemplate(framework?: Framework): string;
@@ -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,186 @@
1
+ //#region src/templates/base.ts
2
+ function packageJsonTemplate(projectName, scripts = {}) {
3
+ const pkg = {
4
+ name: projectName,
5
+ version: "1.0.0",
6
+ private: true,
7
+ type: "module",
8
+ imports: { "#src/*": "./src/*" },
9
+ scripts: {
10
+ "dev": "run-p dev:server dev:taser",
11
+ "dev:server": "tsx watch src/index.ts",
12
+ "dev:taser": "taser watch",
13
+ "start": "tsx src/index.ts",
14
+ "generate": "taser generate",
15
+ "build": "taser generate && tsdown build",
16
+ "serve": "node dist/index.js",
17
+ "typecheck": "tsc --noEmit -p tsconfig.json",
18
+ ...scripts
19
+ }
20
+ };
21
+ return `${JSON.stringify(pkg, null, 2)}\n`;
22
+ }
23
+ function tsdownConfigTemplate() {
24
+ return `import { defineConfig } from 'tsdown'
25
+
26
+ export default defineConfig({
27
+ entry: ['./src/index.ts'],
28
+ format: 'esm',
29
+ platform: 'node',
30
+ target: 'node20',
31
+ outDir: 'dist',
32
+ clean: true,
33
+ sourcemap: true,
34
+ })
35
+ `;
36
+ }
37
+ function tsconfigTemplate() {
38
+ return `${JSON.stringify({
39
+ compilerOptions: {
40
+ target: "ES2022",
41
+ lib: ["ES2022", "DOM"],
42
+ module: "ESNext",
43
+ moduleResolution: "bundler",
44
+ paths: { "#src/*": ["./src/*"] },
45
+ strict: true,
46
+ skipLibCheck: true,
47
+ verbatimModuleSyntax: true,
48
+ isolatedModules: true,
49
+ noEmit: true,
50
+ types: ["node"]
51
+ },
52
+ include: ["src"]
53
+ }, null, 2)}\n`;
54
+ }
55
+ function gitignoreTemplate() {
56
+ return `node_modules
57
+ dist
58
+ .DS_Store
59
+ *.log
60
+ .env
61
+ local.db
62
+ drizzle
63
+ `;
64
+ }
65
+ function contextTemplate(bindings) {
66
+ const imports = bindings.map((binding) => `import { ${binding.factoryName} } from '${binding.importPath}'`);
67
+ const bootBody = bindings.length > 0 ? bindings.map((binding) => ` ${binding.key}: ${binding.factoryName}(),`).join("\n") : "";
68
+ const bootBlock = bindings.length > 0 ? ` boot: () => ({\n${bootBody}\n }),` : "";
69
+ return `${imports.length > 0 ? `${imports.join("\n")}\n\n` : ""}import { createContext } from '@taserjs/router'
70
+
71
+ export const context = createContext({
72
+ ${bootBlock}
73
+ request: () => ({
74
+ requestId: crypto.randomUUID(),
75
+ }),
76
+ })
77
+ `;
78
+ }
79
+ function rootLayoutTemplate() {
80
+ return `import { bodyLimit } from '@taserjs/router/body-limit'
81
+ import { secureHeaders } from '@taserjs/router/secure-headers'
82
+
83
+ import { t } from '#src/taser.js'
84
+
85
+ export const Middleware = t.middleware('/$')
86
+ .use(secureHeaders())
87
+ .use(bodyLimit({ maxSize: 1_000_000 }))
88
+ `;
89
+ }
90
+ function indexRouteTemplate() {
91
+ return `import { t } from '#src/taser.js'
92
+
93
+ export const Route = t.get('/').handler((ctx) => {
94
+ return ctx.reply.json({ message: 'Welcome to Taser' })
95
+ })
96
+ `;
97
+ }
98
+ function healthRouteTemplate(ctx) {
99
+ const lines = [];
100
+ if (ctx.logger) lines.push(" ctx.logger.info('health check')");
101
+ if (ctx.db) lines.push(" // ctx.db is available from context boot");
102
+ return `import { t } from '#src/taser.js'
103
+
104
+ export const Route = t.get('/health').handler((ctx) => {
105
+ ${lines.length > 0 ? `${lines.join("\n")}\n` : ""} return ctx.reply.json({ ok: true })
106
+ })
107
+ `;
108
+ }
109
+ /** Minimal placeholder until `taser generate` runs. */
110
+ function starterManifestTemplate() {
111
+ return `/* eslint-disable */
112
+ // Run \`pnpm generate\` (taser generate) to replace this file.
113
+ import { Middleware as RootSplatLayoutImport } from './routes/$.js'
114
+ import { Route as RootIndexGetRouteImport } from './routes/index.get.js'
115
+ import { Route as HealthGetRouteImport } from './routes/health.get.js'
116
+
117
+ export const routeManifest = {
118
+ layouts: {
119
+ '/$': {
120
+ middlewares: RootSplatLayoutImport,
121
+ },
122
+ },
123
+ routes: {
124
+ '/': {
125
+ GET: {
126
+ layoutChain: ['/$'],
127
+ route: RootIndexGetRouteImport,
128
+ },
129
+ },
130
+ '/health': {
131
+ GET: {
132
+ layoutChain: ['/$'],
133
+ route: HealthGetRouteImport,
134
+ },
135
+ },
136
+ },
137
+ } as const
138
+
139
+ export type RoutePathGen = '/' | '/health'
140
+ export type LayoutIdGen = '/$'
141
+ export type LayoutTreeGen = {
142
+ '/$': {
143
+ parent: null
144
+ middlewares: typeof RootSplatLayoutImport
145
+ }
146
+ }
147
+ export type RouteByPathMethodGen = {
148
+ '/': {
149
+ GET: {
150
+ parent: '/$'
151
+ layoutChain: ['/$']
152
+ route: typeof RootIndexGetRouteImport
153
+ }
154
+ }
155
+ '/health': {
156
+ GET: {
157
+ parent: '/$'
158
+ layoutChain: ['/$']
159
+ route: typeof HealthGetRouteImport
160
+ }
161
+ }
162
+ }
163
+ export type RouteManifest = typeof routeManifest
164
+
165
+ declare module '@taserjs/router' {
166
+ interface RouterRegister {
167
+ RoutePath: RoutePathGen
168
+ LayoutId: LayoutIdGen
169
+ LayoutTree: LayoutTreeGen
170
+ RouteByPathMethod: RouteByPathMethodGen
171
+ }
172
+ }
173
+ `;
174
+ }
175
+ //#endregion
176
+ exports.contextTemplate = contextTemplate;
177
+ exports.gitignoreTemplate = gitignoreTemplate;
178
+ exports.healthRouteTemplate = healthRouteTemplate;
179
+ exports.indexRouteTemplate = indexRouteTemplate;
180
+ exports.packageJsonTemplate = packageJsonTemplate;
181
+ exports.rootLayoutTemplate = rootLayoutTemplate;
182
+ exports.starterManifestTemplate = starterManifestTemplate;
183
+ exports.tsconfigTemplate = tsconfigTemplate;
184
+ exports.tsdownConfigTemplate = tsdownConfigTemplate;
185
+
186
+ //# sourceMappingURL=base.cjs.map
@@ -0,0 +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(projectName: string, scripts: Record<string, string> = {}): 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 build',\n 'serve': 'node dist/index.js',\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 format: 'esm',\n platform: 'node',\n target: 'node20',\n outDir: 'dist',\n clean: true,\n sourcemap: true,\n})\n`\n}\n\nexport function tsconfigTemplate(): string {\n return `${JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n lib: ['ES2022', 'DOM'],\n module: 'ESNext',\n moduleResolution: 'bundler',\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 }, null, 2)}\\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 = bindings.length > 0\n ? bindings.map(binding => ` ${binding.key}: ${binding.factoryName}(),`).join('\\n')\n : ''\n\n const bootBlock = bindings.length > 0\n ? ` boot: () => ({\\n${bootBody}\\n }),`\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 { t } from '#src/taser.js'\n\nexport const Route = t.get('/').handler((ctx) => {\n return ctx.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\n return `import { t } from '#src/taser.js'\n\nexport const Route = t.get('/health').handler((ctx) => {\n${body} return ctx.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,oBAAoB,aAAqB,UAAkC,CAAC,GAAW;CACrG,MAAM,MAAM;EACV,MAAM;EACN,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS,EACP,UAAU,UACZ;EACA,SAAS;GACP,OAAO;GACP,cAAc;GACd,aAAa;GACb,SAAS;GACT,YAAY;GACZ,SAAS;GACT,SAAS;GACT,aAAa;GACb,GAAG;EACL;CACF;CAEA,OAAO,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AACzC;AAEA,SAAgB,uBAA+B;CAC7C,OAAO;;;;;;;;;;;;AAYT;AAEA,SAAgB,mBAA2B;CACzC,OAAO,GAAG,KAAK,UAAU;EACvB,iBAAiB;GACf,QAAQ;GACR,KAAK,CAAC,UAAU,KAAK;GACrB,QAAQ;GACR,kBAAkB;GAClB,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,GAAG,MAAM,CAAC,EAAE;AACd;AAEA,SAAgB,oBAA4B;CAC1C,OAAO;;;;;;;;AAQT;AAEA,SAAgB,gBAAgB,UAAiC;CAC/D,MAAM,UAAU,SAAS,KACvB,YAAW,YAAY,QAAQ,YAAY,WAAW,QAAQ,WAAW,EAC3E;CAEA,MAAM,WAAW,SAAS,SAAS,IAC/B,SAAS,KAAI,YAAW,OAAO,QAAQ,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC,CAAC,KAAK,IAAI,IAClF;CAEJ,MAAM,YAAY,SAAS,SAAS,IAChC,qBAAqB,SAAS,WAC9B;CAIJ,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;;;;;;AAMT;AAEA,SAAgB,oBAAoB,KAA8B;CAChE,MAAM,QAAkB,CAAC;CAEzB,IAAI,IAAI,QACN,MAAM,KAAK,mCAAqC;CAGlD,IAAI,IAAI,IACN,MAAM,KAAK,4CAA4C;CAKzD,OAAO;;;EAFM,MAAM,SAAS,IAAI,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM,GAKrD;;;AAGP;;AAGA,SAAgB,0BAAkC;CAChD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT"}
@@ -0,0 +1,12 @@
1
+ import { BootBinding } from '../addons/types.js';
2
+ import { ScaffoldContext } from '../core/types.js';
3
+ export declare function packageJsonTemplate(projectName: string, scripts?: Record<string, string>): string;
4
+ export declare function tsdownConfigTemplate(): string;
5
+ export declare function tsconfigTemplate(): string;
6
+ export declare function gitignoreTemplate(): string;
7
+ export declare function contextTemplate(bindings: BootBinding[]): string;
8
+ export declare function rootLayoutTemplate(): string;
9
+ export declare function indexRouteTemplate(): string;
10
+ export declare function healthRouteTemplate(ctx: ScaffoldContext): string;
11
+ /** Minimal placeholder until `taser generate` runs. */
12
+ export declare function starterManifestTemplate(): string;
@@ -0,0 +1 @@
1
+ export type { Framework, DbOdm, DbDriver, LoggerId, ScaffoldOptions, ScaffoldResult, PackageGroups, } from './core/types.js';
@@ -0,0 +1,2 @@
1
+ import { AddonDefinition } from '../types.js';
2
+ export declare const drizzleAddon: AddonDefinition;
@@ -0,0 +1,124 @@
1
+ //#region src/addons/drizzle/index.ts
2
+ function schemaSource(driver) {
3
+ switch (driver) {
4
+ case "postgres": return `import { pgTable, serial, text } from 'drizzle-orm/pg-core'
5
+
6
+ export const users = pgTable('users', {
7
+ id: serial('id').primaryKey(),
8
+ email: text('email').notNull(),
9
+ })
10
+ `;
11
+ case "mysql": return `import { mysqlTable, serial, varchar } from 'drizzle-orm/mysql-core'
12
+
13
+ export const users = mysqlTable('users', {
14
+ id: serial('id').primaryKey(),
15
+ email: varchar('email', { length: 255 }).notNull(),
16
+ })
17
+ `;
18
+ default: return `import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core'
19
+
20
+ export const users = sqliteTable('users', {
21
+ id: integer('id').primaryKey({ autoIncrement: true }),
22
+ email: text('email').notNull(),
23
+ })
24
+ `;
25
+ }
26
+ }
27
+ function dbIndexSource(driver) {
28
+ switch (driver) {
29
+ case "postgres": return `import { drizzle } from 'drizzle-orm/node-postgres'
30
+ import pg from 'pg'
31
+
32
+ import * as schema from './schema.js'
33
+
34
+ export function createDb() {
35
+ const pool = new pg.Pool({
36
+ connectionString: process.env.DATABASE_URL,
37
+ })
38
+ return drizzle(pool, { schema })
39
+ }
40
+ `;
41
+ case "mysql": return `import { drizzle } from 'drizzle-orm/mysql2'
42
+ import mysql from 'mysql2/promise'
43
+
44
+ import * as schema from './schema.js'
45
+
46
+ export function createDb() {
47
+ const pool = mysql.createPool(process.env.DATABASE_URL ?? '')
48
+ return drizzle(pool, { schema, mode: 'default' })
49
+ }
50
+ `;
51
+ default: return `import Database from 'better-sqlite3'
52
+ import { drizzle } from 'drizzle-orm/better-sqlite3'
53
+
54
+ import * as schema from './schema.js'
55
+
56
+ export function createDb() {
57
+ const filePath = (process.env.DATABASE_URL ?? 'file:./local.db').replace(/^file:/, '')
58
+ const client = new Database(filePath)
59
+ return drizzle(client, { schema })
60
+ }
61
+ `;
62
+ }
63
+ }
64
+ function drizzleConfigSource(driver) {
65
+ return `import { defineConfig } from 'drizzle-kit'
66
+
67
+ export default defineConfig({
68
+ schema: './src/db/schema.ts',
69
+ out: './drizzle',
70
+ dialect: '${driver === "postgres" ? "postgresql" : driver === "mysql" ? "mysql" : "sqlite"}',
71
+ dbCredentials: {
72
+ url: process.env.DATABASE_URL ?? '',
73
+ },
74
+ })
75
+ `;
76
+ }
77
+ function envExample(driver) {
78
+ switch (driver) {
79
+ case "postgres": return "DATABASE_URL=postgresql://user:password@localhost:5432/mydb\n";
80
+ case "mysql": return "DATABASE_URL=mysql://user:password@localhost:3306/mydb\n";
81
+ default: return "DATABASE_URL=file:./local.db\n";
82
+ }
83
+ }
84
+ function driverPackages(driver) {
85
+ switch (driver) {
86
+ case "postgres": return ["pg"];
87
+ case "mysql": return ["mysql2"];
88
+ default: return ["better-sqlite3"];
89
+ }
90
+ }
91
+ var drizzleAddon = {
92
+ id: "drizzle",
93
+ category: "database",
94
+ dependencies(ctx) {
95
+ return ["drizzle-orm", ...driverPackages(ctx.driver ?? "sqlite")];
96
+ },
97
+ devDependencies() {
98
+ return ["drizzle-kit"];
99
+ },
100
+ scripts() {
101
+ return {
102
+ "db:generate": "drizzle-kit generate",
103
+ "db:push": "drizzle-kit push"
104
+ };
105
+ },
106
+ bootBinding() {
107
+ return {
108
+ key: "db",
109
+ importPath: "./db/index.js",
110
+ factoryName: "createDb"
111
+ };
112
+ },
113
+ async apply(ctx, write) {
114
+ const driver = ctx.driver ?? "sqlite";
115
+ await write("src/db/schema.ts", schemaSource(driver));
116
+ await write("src/db/index.ts", dbIndexSource(driver));
117
+ await write("drizzle.config.ts", drizzleConfigSource(driver));
118
+ await write(".env.example", envExample(driver));
119
+ }
120
+ };
121
+ //#endregion
122
+ export { drizzleAddon };
123
+
124
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/addons/drizzle/index.ts"],"sourcesContent":["import type { AddonDefinition } from '../types.js'\nimport type { DbDriver } from '../../core/types.js'\n\nfunction schemaSource(driver: DbDriver): string {\n switch (driver) {\n case 'postgres':\n return `import { pgTable, serial, text } from 'drizzle-orm/pg-core'\n\nexport const users = pgTable('users', {\n id: serial('id').primaryKey(),\n email: text('email').notNull(),\n})\n`\n case 'mysql':\n return `import { mysqlTable, serial, varchar } from 'drizzle-orm/mysql-core'\n\nexport const users = mysqlTable('users', {\n id: serial('id').primaryKey(),\n email: varchar('email', { length: 255 }).notNull(),\n})\n`\n case 'sqlite':\n default:\n return `import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core'\n\nexport const users = sqliteTable('users', {\n id: integer('id').primaryKey({ autoIncrement: true }),\n email: text('email').notNull(),\n})\n`\n }\n}\n\nfunction dbIndexSource(driver: DbDriver): string {\n switch (driver) {\n case 'postgres':\n return `import { drizzle } from 'drizzle-orm/node-postgres'\nimport pg from 'pg'\n\nimport * as schema from './schema.js'\n\nexport function createDb() {\n const pool = new pg.Pool({\n connectionString: process.env.DATABASE_URL,\n })\n return drizzle(pool, { schema })\n}\n`\n case 'mysql':\n return `import { drizzle } from 'drizzle-orm/mysql2'\nimport mysql from 'mysql2/promise'\n\nimport * as schema from './schema.js'\n\nexport function createDb() {\n const pool = mysql.createPool(process.env.DATABASE_URL ?? '')\n return drizzle(pool, { schema, mode: 'default' })\n}\n`\n case 'sqlite':\n default:\n return `import Database from 'better-sqlite3'\nimport { drizzle } from 'drizzle-orm/better-sqlite3'\n\nimport * as schema from './schema.js'\n\nexport function createDb() {\n const filePath = (process.env.DATABASE_URL ?? 'file:./local.db').replace(/^file:/, '')\n const client = new Database(filePath)\n return drizzle(client, { schema })\n}\n`\n }\n}\n\nfunction drizzleConfigSource(driver: DbDriver): string {\n const dialect = driver === 'postgres' ? 'postgresql' : driver === 'mysql' ? 'mysql' : 'sqlite'\n return `import { defineConfig } from 'drizzle-kit'\n\nexport default defineConfig({\n schema: './src/db/schema.ts',\n out: './drizzle',\n dialect: '${dialect}',\n dbCredentials: {\n url: process.env.DATABASE_URL ?? '',\n },\n})\n`\n}\n\nfunction envExample(driver: DbDriver): string {\n switch (driver) {\n case 'postgres':\n return 'DATABASE_URL=postgresql://user:password@localhost:5432/mydb\\n'\n case 'mysql':\n return 'DATABASE_URL=mysql://user:password@localhost:3306/mydb\\n'\n case 'sqlite':\n default:\n return 'DATABASE_URL=file:./local.db\\n'\n }\n}\n\nfunction driverPackages(driver: DbDriver): string[] {\n switch (driver) {\n case 'postgres':\n return ['pg']\n case 'mysql':\n return ['mysql2']\n case 'sqlite':\n default:\n return ['better-sqlite3']\n }\n}\n\nexport const drizzleAddon: AddonDefinition = {\n id: 'drizzle',\n category: 'database',\n dependencies(ctx) {\n const driver = ctx.driver ?? 'sqlite'\n return ['drizzle-orm', ...driverPackages(driver)]\n },\n devDependencies() {\n return ['drizzle-kit']\n },\n scripts() {\n return {\n 'db:generate': 'drizzle-kit generate',\n 'db:push': 'drizzle-kit push',\n }\n },\n bootBinding() {\n return {\n key: 'db',\n importPath: './db/index.js',\n factoryName: 'createDb',\n }\n },\n async apply(ctx, write) {\n const driver = ctx.driver ?? 'sqlite'\n await write('src/db/schema.ts', schemaSource(driver))\n await write('src/db/index.ts', dbIndexSource(driver))\n await write('drizzle.config.ts', drizzleConfigSource(driver))\n await write('.env.example', envExample(driver))\n },\n}\n"],"mappings":";AAGA,SAAS,aAAa,QAA0B;CAC9C,QAAQ,QAAR;EACE,KAAK,YACH,OAAO;;;;;;;EAOT,KAAK,SACH,OAAO;;;;;;;EAQT,SACE,OAAO;;;;;;;CAOX;AACF;AAEA,SAAS,cAAc,QAA0B;CAC/C,QAAQ,QAAR;EACE,KAAK,YACH,OAAO;;;;;;;;;;;;EAYT,KAAK,SACH,OAAO;;;;;;;;;;EAWT,SACE,OAAO;;;;;;;;;;;CAWX;AACF;AAEA,SAAS,oBAAoB,QAA0B;CAErD,OAAO;;;;;cADS,WAAW,aAAa,eAAe,WAAW,UAAU,UAAU,SAMlE;;;;;;AAMtB;AAEA,SAAS,WAAW,QAA0B;CAC5C,QAAQ,QAAR;EACE,KAAK,YACH,OAAO;EACT,KAAK,SACH,OAAO;EAET,SACE,OAAO;CACX;AACF;AAEA,SAAS,eAAe,QAA4B;CAClD,QAAQ,QAAR;EACE,KAAK,YACH,OAAO,CAAC,IAAI;EACd,KAAK,SACH,OAAO,CAAC,QAAQ;EAElB,SACE,OAAO,CAAC,gBAAgB;CAC5B;AACF;AAEA,IAAa,eAAgC;CAC3C,IAAI;CACJ,UAAU;CACV,aAAa,KAAK;EAEhB,OAAO,CAAC,eAAe,GAAG,eADX,IAAI,UAAU,QACkB,CAAC;CAClD;CACA,kBAAkB;EAChB,OAAO,CAAC,aAAa;CACvB;CACA,UAAU;EACR,OAAO;GACL,eAAe;GACf,WAAW;EACb;CACF;CACA,cAAc;EACZ,OAAO;GACL,KAAK;GACL,YAAY;GACZ,aAAa;EACf;CACF;CACA,MAAM,MAAM,KAAK,OAAO;EACtB,MAAM,SAAS,IAAI,UAAU;EAC7B,MAAM,MAAM,oBAAoB,aAAa,MAAM,CAAC;EACpD,MAAM,MAAM,mBAAmB,cAAc,MAAM,CAAC;EACpD,MAAM,MAAM,qBAAqB,oBAAoB,MAAM,CAAC;EAC5D,MAAM,MAAM,gBAAgB,WAAW,MAAM,CAAC;CAChD;AACF"}
@@ -0,0 +1,2 @@
1
+ import { AddonDefinition } from '../types.js';
2
+ export declare const kyselyAddon: AddonDefinition;