tina4-nodejs 3.10.34 → 3.10.40

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tina4-nodejs",
3
- "version": "3.10.34",
3
+ "version": "3.10.40",
4
4
  "type": "module",
5
5
  "description": "This is not a framework. Tina4 for Node.js/TypeScript — zero deps, 38 built-in features.",
6
6
  "keywords": ["tina4", "framework", "web", "api", "orm", "graphql", "websocket", "typescript"],
@@ -7,6 +7,7 @@ import { migrateRollback } from "./commands/migrateRollback.js";
7
7
  import { listRoutes } from "./commands/routes.js";
8
8
  import { runTests } from "./commands/test.js";
9
9
  import { generate } from "./commands/generate.js";
10
+ import { runSeeds } from "./commands/seed.js";
10
11
 
11
12
  const args = process.argv.slice(2);
12
13
  const command = args[0];
@@ -24,7 +25,8 @@ const HELP = `
24
25
  tina4nodejs routes List all registered routes
25
26
  tina4nodejs test [file] Run project tests
26
27
  tina4nodejs generate <what> <name> Generate scaffolding (model, route, migration, middleware)
27
- tina4nodejs ai Detect AI coding tools and install context
28
+ tina4nodejs seed [file] Run database seed files from src/seeds/
29
+ tina4nodejs ai Install AI coding assistant context files
28
30
  tina4nodejs help Show this help message
29
31
 
30
32
  Options:
@@ -78,35 +80,20 @@ async function main(): Promise<void> {
78
80
  await generate(what, genName);
79
81
  break;
80
82
  }
83
+ case "seed": {
84
+ await runSeeds(args[1]);
85
+ break;
86
+ }
81
87
  case "ai": {
82
- const { detectAi, installAiContext, installAllAiContext, aiStatusReport } = await import("../../core/src/ai.js");
88
+ const { showMenu, installSelected, installAll } = await import("../../core/src/ai.js");
83
89
  const root = args[1] || ".";
84
- const installAll = args.includes("--all");
85
- const force = args.includes("--force");
86
90
 
87
- // Show status
88
- console.log(aiStatusReport(root));
89
-
90
- // Install context
91
- if (installAll) {
92
- const created = installAllAiContext(root, force);
93
- if (created.length > 0) {
94
- console.log("Installed AI context files:");
95
- for (const f of created) {
96
- console.log(` + ${f}`);
97
- }
98
- } else {
99
- console.log("All AI context files already exist (use --force to overwrite).");
100
- }
91
+ if (args.includes("--all")) {
92
+ installAll(root);
101
93
  } else {
102
- const created = installAiContext(root, { force });
103
- if (created.length > 0) {
104
- console.log("Installed AI context files:");
105
- for (const f of created) {
106
- console.log(` + ${f}`);
107
- }
108
- } else {
109
- console.log("No new AI context files needed.");
94
+ const selection = await showMenu(root);
95
+ if (selection) {
96
+ installSelected(root, selection);
110
97
  }
111
98
  }
112
99
  break;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * CLI command: seed — Run database seed files.
3
+ *
4
+ * Scans src/seeds/ for .ts files and executes them with tsx in alphabetical order.
5
+ */
6
+ import { existsSync, readdirSync } from "node:fs";
7
+ import { resolve, join } from "node:path";
8
+ import { execSync } from "node:child_process";
9
+
10
+ export async function runSeeds(seedPath?: string): Promise<void> {
11
+ const cwd = process.cwd();
12
+ const seedDir = resolve(cwd, "src/seeds");
13
+
14
+ // If a specific seed file is provided, run it directly
15
+ if (seedPath) {
16
+ const file = resolve(seedPath);
17
+ if (!existsSync(file)) {
18
+ console.error(` Error: Seed file not found: ${seedPath}`);
19
+ process.exit(1);
20
+ }
21
+ console.log(` Running seed: ${seedPath}\n`);
22
+ try {
23
+ execSync(`npx tsx "${file}"`, { cwd, stdio: "inherit" });
24
+ } catch {
25
+ process.exit(1);
26
+ }
27
+ return;
28
+ }
29
+
30
+ // Auto-discover seed files in src/seeds/
31
+ if (!existsSync(seedDir)) {
32
+ console.log(" No seeds directory found.");
33
+ console.log(" Create seed files in src/seeds/ (e.g. src/seeds/001-users.ts)");
34
+ return;
35
+ }
36
+
37
+ let seedFiles: string[];
38
+ try {
39
+ seedFiles = readdirSync(seedDir)
40
+ .filter((f) => f.endsWith(".ts"))
41
+ .sort()
42
+ .map((f) => join(seedDir, f));
43
+ } catch {
44
+ console.log(" Could not read src/seeds/ directory.");
45
+ return;
46
+ }
47
+
48
+ if (seedFiles.length === 0) {
49
+ console.log(" No seed files found in src/seeds/");
50
+ return;
51
+ }
52
+
53
+ console.log(` Found ${seedFiles.length} seed file(s)\n`);
54
+
55
+ let failed = false;
56
+ for (const file of seedFiles) {
57
+ const relative = file.replace(cwd + "/", "");
58
+ console.log(` Seeding: ${relative}`);
59
+ try {
60
+ execSync(`npx tsx "${file}"`, { cwd, stdio: "inherit" });
61
+ } catch {
62
+ failed = true;
63
+ }
64
+ }
65
+
66
+ if (failed) {
67
+ console.error("\n Some seeds failed.");
68
+ process.exit(1);
69
+ }
70
+
71
+ console.log("\n All seeds completed.");
72
+ }
@@ -36,8 +36,9 @@ export async function serveProject(options: ServeOptions): Promise<void> {
36
36
  const watcher = watchForChanges(watchDirs, async () => {
37
37
  try {
38
38
  const { discoverRoutes } = await import("@tina4/core");
39
- const routes = await discoverRoutes(routesDir);
39
+ // Clear routes BEFORE re-discovery to avoid stale duplicates
40
40
  server.router.clear();
41
+ const routes = await discoverRoutes(routesDir);
41
42
  for (const route of routes) {
42
43
  server.router.addRoute(route);
43
44
  }