tina4-nodejs 3.10.41 → 3.10.44
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 +3 -3
- package/README.md +1 -1
- package/package.json +1 -1
- package/packages/cli/src/bin.ts +48 -4
- package/packages/cli/src/commands/generate.ts +800 -103
- package/packages/cli/src/commands/serve.ts +1 -0
- package/packages/core/src/ai.ts +488 -108
- package/packages/core/src/devAdmin.ts +643 -98
- package/packages/core/src/index.ts +3 -2
- package/packages/core/src/metrics.ts +52 -0
- package/packages/core/src/server.ts +40 -5
- package/packages/core/src/testClient.ts +187 -0
- package/packages/orm/src/adapters/sqlite.ts +7 -3
- package/packages/orm/src/baseModel.ts +17 -5
package/CLAUDE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# CLAUDE.md — AI Developer Guide for tina4-nodejs (v3.10.
|
|
1
|
+
# CLAUDE.md — AI Developer Guide for tina4-nodejs (v3.10.42)
|
|
2
2
|
|
|
3
3
|
> This file helps AI assistants (Claude, Copilot, Cursor, etc.) understand and work on this codebase effectively.
|
|
4
4
|
|
|
5
5
|
## What This Project Is
|
|
6
6
|
|
|
7
|
-
Tina4 for Node.js/TypeScript v3.10.
|
|
7
|
+
Tina4 for Node.js/TypeScript v3.10.42 — a convention-over-configuration structural paradigm. **Not a framework.** The developer writes TypeScript; Tina4 is invisible infrastructure.
|
|
8
8
|
|
|
9
9
|
The philosophy: zero ceremony, batteries included, file system as source of truth.
|
|
10
10
|
|
|
@@ -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
|
-
- **
|
|
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/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<p align="center">54 built-in features. Zero dependencies. One import, everything works.</p>
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://www.npmjs.com/package/tina4-nodejs"><img src="https://img.shields.io/npm/v/tina4-nodejs?color=7b1fa2&label=npm" alt="npm"></a>
|
|
9
|
-
<img src="https://img.shields.io/badge/tests-1%
|
|
9
|
+
<img src="https://img.shields.io/badge/tests-1%2C812%20passing-brightgreen" alt="Tests">
|
|
10
10
|
<img src="https://img.shields.io/badge/features-54-blue" alt="Features">
|
|
11
11
|
<img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="Zero Deps">
|
|
12
12
|
<a href="https://tina4.com"><img src="https://img.shields.io/badge/docs-tina4.com-7b1fa2" alt="Docs"></a>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tina4-nodejs",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.44",
|
|
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"],
|
package/packages/cli/src/bin.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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": {
|