tina4-nodejs 3.10.42 → 3.10.45

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/CLAUDE.md CHANGED
@@ -587,7 +587,7 @@ When adding new features, add a corresponding `test/<feature>.test.ts` file.
587
587
 
588
588
  ## v3 Features Summary
589
589
 
590
- - **38 built-in features**, zero third-party dependencies
590
+ - **44 built-in features**, zero third-party dependencies
591
591
  - **1,812 tests** passing across all modules
592
592
  - **Race-safe `getNextId()`** with atomic sequence table (`tina4_sequences`) for SQLite/MySQL/MSSQL; PostgreSQL auto-creates sequences
593
593
  - **Frond template engine optimizations**: pre-compiled regexes, lazy loop context (copy-on-write), filter chain caching, path split caching, inline common filters (11-15% speedup)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tina4-nodejs",
3
- "version": "3.10.42",
3
+ "version": "3.10.45",
4
4
  "type": "module",
5
5
  "description": "Tina4 for Node.js/TypeScript — 54 built-in features, zero dependencies",
6
6
  "keywords": ["tina4", "framework", "web", "api", "orm", "graphql", "websocket", "typescript"],
@@ -8,6 +8,7 @@ import { listRoutes } from "./commands/routes.js";
8
8
  import { runTests } from "./commands/test.js";
9
9
  import { generate } from "./commands/generate.js";
10
10
  import { runSeeds } from "./commands/seed.js";
11
+ import { execSync } from "node:child_process";
11
12
 
12
13
  const args = process.argv.slice(2);
13
14
  const command = args[0];
@@ -24,18 +25,55 @@ const HELP = `
24
25
  tina4nodejs migrate:rollback Roll back the last batch of migrations
25
26
  tina4nodejs routes List all registered routes
26
27
  tina4nodejs test [file] Run project tests
27
- tina4nodejs generate <what> <name> Generate scaffolding (model, route, migration, middleware)
28
28
  tina4nodejs seed [file] Run database seed files from src/seeds/
29
29
  tina4nodejs ai Install AI coding assistant context files
30
30
  tina4nodejs help Show this help message
31
31
 
32
+ Generators:
33
+ tina4nodejs generate model <Name> [--fields "name:string,price:float"]
34
+ tina4nodejs generate route <name> [--model Name]
35
+ tina4nodejs generate crud <Name> [--fields "..."] Model + migration + routes + form + view + test
36
+ tina4nodejs generate migration <description>
37
+ tina4nodejs generate middleware <Name>
38
+ tina4nodejs generate test <name>
39
+ tina4nodejs generate form <Name> [--fields "..."] Form template with inputs matching model fields
40
+ tina4nodejs generate view <Name> [--fields "..."] List + detail templates for viewing records
41
+ tina4nodejs generate auth Login/register/logout routes + User model + templates
42
+
43
+ Field types: string, int, float, bool, text, datetime
44
+ Table names: singular by default (Product → product)
45
+
32
46
  Options:
33
47
  --port <number> Server port (default: 7148)
48
+ --no-browser Don't open the browser on serve
34
49
  --all Install AI context for all tools (with ai command)
35
50
  --force Overwrite existing AI context files (with ai command)
36
51
  --help Show this help message
37
52
  `;
38
53
 
54
+ // ── Port-kill helper ────────────────────────────────────────────────
55
+
56
+ function killProcessOnPort(port: number): boolean {
57
+ try {
58
+ const result = execSync(`lsof -ti :${port}`, { encoding: "utf-8", timeout: 5000 }).trim();
59
+ if (result) {
60
+ const pids = result.split("\n");
61
+ for (const pid of pids) {
62
+ try {
63
+ process.kill(parseInt(pid, 10), "SIGTERM");
64
+ } catch {
65
+ // ignore ProcessLookupError / PermissionError
66
+ }
67
+ }
68
+ console.log(` Killed existing process on port ${port} (PID: ${pids.join(", ")})`);
69
+ return true;
70
+ }
71
+ } catch {
72
+ // lsof not found or no process on port — that's fine
73
+ }
74
+ return false;
75
+ }
76
+
39
77
  async function main(): Promise<void> {
40
78
  switch (command) {
41
79
  case "init": {
@@ -46,7 +84,12 @@ async function main(): Promise<void> {
46
84
  case "serve": {
47
85
  const portIndex = args.indexOf("--port");
48
86
  const port = portIndex !== -1 ? parseInt(args[portIndex + 1], 10) : 7148;
49
- await serveProject({ port });
87
+ const noBrowser = args.includes("--no-browser");
88
+
89
+ // Kill any existing process on the port
90
+ killProcessOnPort(port);
91
+
92
+ await serveProject({ port, noBrowser });
50
93
  break;
51
94
  }
52
95
  case "migrate": {
@@ -76,8 +119,9 @@ async function main(): Promise<void> {
76
119
  }
77
120
  case "generate": {
78
121
  const what = args[1];
79
- const genName = args[2];
80
- await generate(what, genName);
122
+ const genName = args[2] || "";
123
+ const extraArgs = args.slice(3);
124
+ await generate(what, genName, extraArgs);
81
125
  break;
82
126
  }
83
127
  case "seed": {