tina4-nodejs 3.0.0-rc.2

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 (119) hide show
  1. package/BENCHMARK_REPORT.md +96 -0
  2. package/CARBONAH.md +140 -0
  3. package/CLAUDE.md +599 -0
  4. package/COMPARISON.md +194 -0
  5. package/README.md +595 -0
  6. package/package.json +59 -0
  7. package/packages/cli/src/bin.ts +110 -0
  8. package/packages/cli/src/commands/init.ts +194 -0
  9. package/packages/cli/src/commands/migrate.ts +96 -0
  10. package/packages/cli/src/commands/migrateCreate.ts +59 -0
  11. package/packages/cli/src/commands/routes.ts +61 -0
  12. package/packages/cli/src/commands/serve.ts +58 -0
  13. package/packages/cli/src/commands/test.ts +83 -0
  14. package/packages/core/gallery/auth/meta.json +1 -0
  15. package/packages/core/gallery/auth/src/routes/api/gallery/auth/login/post.ts +22 -0
  16. package/packages/core/gallery/auth/src/routes/api/gallery/auth/verify/get.ts +16 -0
  17. package/packages/core/gallery/auth/src/routes/gallery/auth/get.ts +97 -0
  18. package/packages/core/gallery/database/meta.json +1 -0
  19. package/packages/core/gallery/database/src/routes/api/gallery/db/notes/get.ts +13 -0
  20. package/packages/core/gallery/database/src/routes/api/gallery/db/notes/post.ts +17 -0
  21. package/packages/core/gallery/database/src/routes/api/gallery/db/tables/get.ts +23 -0
  22. package/packages/core/gallery/error-overlay/meta.json +1 -0
  23. package/packages/core/gallery/error-overlay/src/routes/api/gallery/crash/get.ts +17 -0
  24. package/packages/core/gallery/orm/meta.json +1 -0
  25. package/packages/core/gallery/orm/src/routes/api/gallery/products/get.ts +12 -0
  26. package/packages/core/gallery/orm/src/routes/api/gallery/products/post.ts +7 -0
  27. package/packages/core/gallery/queue/meta.json +1 -0
  28. package/packages/core/gallery/queue/src/routes/api/gallery/queue/produce/post.ts +16 -0
  29. package/packages/core/gallery/queue/src/routes/api/gallery/queue/status/get.ts +10 -0
  30. package/packages/core/gallery/rest-api/meta.json +1 -0
  31. package/packages/core/gallery/rest-api/src/routes/api/gallery/hello/get.ts +6 -0
  32. package/packages/core/gallery/rest-api/src/routes/api/gallery/hello/post.ts +7 -0
  33. package/packages/core/gallery/templates/meta.json +1 -0
  34. package/packages/core/gallery/templates/src/routes/gallery/page/get.ts +15 -0
  35. package/packages/core/gallery/templates/src/templates/gallery_page.twig +257 -0
  36. package/packages/core/public/css/tina4.css +2463 -0
  37. package/packages/core/public/css/tina4.min.css +1 -0
  38. package/packages/core/public/favicon.ico +0 -0
  39. package/packages/core/public/images/logo.svg +5 -0
  40. package/packages/core/public/images/tina4-logo-icon.webp +0 -0
  41. package/packages/core/public/js/frond.min.js +420 -0
  42. package/packages/core/public/js/tina4-dev-admin.min.js +327 -0
  43. package/packages/core/public/js/tina4.min.js +93 -0
  44. package/packages/core/public/swagger/index.html +90 -0
  45. package/packages/core/public/swagger/oauth2-redirect.html +63 -0
  46. package/packages/core/src/ai.ts +359 -0
  47. package/packages/core/src/api.ts +248 -0
  48. package/packages/core/src/auth.ts +287 -0
  49. package/packages/core/src/cache.ts +121 -0
  50. package/packages/core/src/constants.ts +48 -0
  51. package/packages/core/src/container.ts +90 -0
  52. package/packages/core/src/devAdmin.ts +2024 -0
  53. package/packages/core/src/devMailbox.ts +316 -0
  54. package/packages/core/src/dotenv.ts +172 -0
  55. package/packages/core/src/errorOverlay.test.ts +122 -0
  56. package/packages/core/src/errorOverlay.ts +278 -0
  57. package/packages/core/src/events.ts +112 -0
  58. package/packages/core/src/fakeData.ts +309 -0
  59. package/packages/core/src/graphql.ts +812 -0
  60. package/packages/core/src/health.ts +31 -0
  61. package/packages/core/src/htmlElement.ts +172 -0
  62. package/packages/core/src/i18n.ts +136 -0
  63. package/packages/core/src/index.ts +88 -0
  64. package/packages/core/src/logger.ts +226 -0
  65. package/packages/core/src/messenger.ts +822 -0
  66. package/packages/core/src/middleware.ts +138 -0
  67. package/packages/core/src/queue.ts +481 -0
  68. package/packages/core/src/queueBackends/kafkaBackend.ts +348 -0
  69. package/packages/core/src/queueBackends/rabbitmqBackend.ts +479 -0
  70. package/packages/core/src/rateLimiter.ts +107 -0
  71. package/packages/core/src/request.ts +189 -0
  72. package/packages/core/src/response.ts +146 -0
  73. package/packages/core/src/routeDiscovery.ts +87 -0
  74. package/packages/core/src/router.ts +398 -0
  75. package/packages/core/src/scss.ts +366 -0
  76. package/packages/core/src/server.ts +610 -0
  77. package/packages/core/src/service.ts +380 -0
  78. package/packages/core/src/session.ts +480 -0
  79. package/packages/core/src/sessionHandlers/mongoHandler.ts +286 -0
  80. package/packages/core/src/sessionHandlers/valkeyHandler.ts +184 -0
  81. package/packages/core/src/static.ts +58 -0
  82. package/packages/core/src/testing.ts +233 -0
  83. package/packages/core/src/types.ts +98 -0
  84. package/packages/core/src/watcher.ts +37 -0
  85. package/packages/core/src/websocket.ts +408 -0
  86. package/packages/core/src/wsdl.ts +546 -0
  87. package/packages/core/templates/errors/302.twig +14 -0
  88. package/packages/core/templates/errors/401.twig +9 -0
  89. package/packages/core/templates/errors/403.twig +29 -0
  90. package/packages/core/templates/errors/404.twig +29 -0
  91. package/packages/core/templates/errors/500.twig +38 -0
  92. package/packages/core/templates/errors/502.twig +9 -0
  93. package/packages/core/templates/errors/503.twig +12 -0
  94. package/packages/core/templates/errors/base.twig +37 -0
  95. package/packages/frond/src/engine.ts +1475 -0
  96. package/packages/frond/src/index.ts +2 -0
  97. package/packages/orm/src/adapters/firebird.ts +455 -0
  98. package/packages/orm/src/adapters/mssql.ts +440 -0
  99. package/packages/orm/src/adapters/mysql.ts +355 -0
  100. package/packages/orm/src/adapters/postgres.ts +362 -0
  101. package/packages/orm/src/adapters/sqlite.ts +270 -0
  102. package/packages/orm/src/autoCrud.ts +231 -0
  103. package/packages/orm/src/baseModel.ts +536 -0
  104. package/packages/orm/src/database.ts +321 -0
  105. package/packages/orm/src/fakeData.ts +118 -0
  106. package/packages/orm/src/index.ts +49 -0
  107. package/packages/orm/src/migration.ts +392 -0
  108. package/packages/orm/src/model.ts +56 -0
  109. package/packages/orm/src/query.ts +113 -0
  110. package/packages/orm/src/seeder.ts +120 -0
  111. package/packages/orm/src/sqlTranslation.ts +272 -0
  112. package/packages/orm/src/types.ts +110 -0
  113. package/packages/orm/src/validation.ts +93 -0
  114. package/packages/swagger/src/generator.ts +189 -0
  115. package/packages/swagger/src/index.ts +2 -0
  116. package/packages/swagger/src/ui.ts +48 -0
  117. package/skills/tina4-developer.skill +0 -0
  118. package/skills/tina4-js.skill +0 -0
  119. package/skills/tina4-maintainer.skill +0 -0
package/CLAUDE.md ADDED
@@ -0,0 +1,599 @@
1
+ # CLAUDE.md — AI Developer Guide for tina4-nodejs (v3.0.0)
2
+
3
+ > This file helps AI assistants (Claude, Copilot, Cursor, etc.) understand and work on this codebase effectively.
4
+
5
+ ## What This Project Is
6
+
7
+ Tina4 for Node.js/TypeScript v3.0.0 — a convention-over-configuration structural paradigm. **Not a framework.** The developer writes TypeScript; Tina4 is invisible infrastructure.
8
+
9
+ The philosophy: zero ceremony, batteries included, file system as source of truth.
10
+
11
+ ## Repository Layout
12
+
13
+ ```
14
+ tina4-nodejs/
15
+ packages/
16
+ cli/ # tina4nodejs CLI (npx tina4nodejs init, npx tina4nodejs serve)
17
+ core/ # HTTP server, router, route discovery, middleware, events, AI, testing
18
+ src/
19
+ ai.ts # AI coding tool detection and context scaffolding
20
+ auth.ts # Authentication helpers
21
+ cache.ts # In-memory caching
22
+ constants.ts # HTTP status codes and content type constants
23
+ devAdmin.ts # Dev toolbar + admin dashboard (replaces floating button)
24
+ devMailbox.ts # Dev mailbox for local email testing
25
+ dotenv.ts # .env file loading
26
+ errorOverlay.ts # Rich debug error overlay (Catppuccin Mocha theme)
27
+ events.ts # Observer-pattern event system
28
+ fakeData.ts # Core fake data generator (PRNG-based, zero deps)
29
+ graphql.ts # GraphQL engine
30
+ health.ts # Health check endpoint
31
+ htmlElement.ts # Programmatic HTML element builder
32
+ i18n.ts # Internationalization / localization
33
+ logger.ts # Structured logging
34
+ messenger.ts # Messaging system
35
+ queue.ts # Queue system
36
+ rateLimiter.ts # Rate limiting middleware
37
+ scss.ts # SCSS compilation
38
+ service.ts # Service layer helpers
39
+ session.ts # Session management
40
+ testing.ts # Inline testing framework (attach tests to functions)
41
+ websocket.ts # WebSocket support
42
+ wsdl.ts # WSDL / SOAP support
43
+ orm/ # Database adapters, models, auto-CRUD, query builder, seeding
44
+ src/
45
+ adapters/
46
+ sqlite.ts # SQLite via better-sqlite3 (default)
47
+ postgres.ts # PostgreSQL adapter
48
+ mysql.ts # MySQL adapter
49
+ mssql.ts # MSSQL / SQL Server adapter
50
+ firebird.ts # Firebird adapter
51
+ baseModel.ts # Base model class
52
+ fakeData.ts # ORM-aware fake data (extends core, field-type heuristics)
53
+ seeder.ts # Database seeding (seedTable, seedOrm)
54
+ sqlTranslation.ts # Cross-engine SQL translator + query cache
55
+ swagger/ # OpenAPI spec generator, Swagger UI
56
+ twig/ # Optional Twig template engine
57
+ test/
58
+ run-all.ts # Test runner — executes all 43 test files
59
+ integration.ts # Full integration test
60
+ *.test.ts # 42 individual test files covering all subsystems
61
+ plan/
62
+ FEATURES.md # Feature tracking and roadmap
63
+ ```
64
+
65
+ This is an **npm workspaces monorepo**. All packages are in `packages/*`.
66
+
67
+ ## Tech Stack
68
+
69
+ - **Language:** TypeScript (strict mode, ES2022 target, Node16 module resolution)
70
+ - **Runtime:** Node.js 20+ (ESM only, `"type": "module"` everywhere)
71
+ - **HTTP:** Native `node:http` — no Express, no Fastify
72
+ - **Database:** SQLite via `better-sqlite3` (default), with adapters for Postgres, MySQL, MSSQL/SQL Server, and Firebird
73
+ - **Templates:** Twig via `twig` npm package (optional)
74
+ - **Dev tooling:** `tsx` for runtime TS execution, `esbuild` for builds
75
+ - **Testing:** 43 test files via `tsx test/run-all.ts`
76
+
77
+ ## Key Commands
78
+
79
+ ```bash
80
+ npm install # Install all workspace dependencies
81
+ npm test # Run all 43 test files via test/run-all.ts
82
+ npm run build # Build all packages to dist/
83
+ npm run clean # Remove all dist/ directories
84
+ ```
85
+
86
+ ## How to Run Locally
87
+
88
+ ```bash
89
+ npx tsx packages/cli/src/bin.ts serve # Start server from monorepo root
90
+ npx tsx packages/cli/src/bin.ts --help # CLI help
91
+ ```
92
+
93
+ Or create a test project:
94
+ ```bash
95
+ npx tsx packages/cli/src/bin.ts init my-test
96
+ ```
97
+
98
+ ## Package Details
99
+
100
+ ### @tina4/core (`packages/core/`)
101
+ The HTTP foundation. Handles request/response lifecycle, route matching, middleware, events, AI context, error overlays, HTML building, and inline testing.
102
+
103
+ **Key files:**
104
+ - `server.ts` — Server startup, integrates ORM + Swagger + Twig on boot
105
+ - `router.ts` — Pattern matching with `{id}` dynamic params and `{...slug}` catch-all
106
+ - `routeDiscovery.ts` — Scans `src/routes/` recursively, maps files to endpoints (converts `[id]` dirs to `{id}` URL patterns)
107
+ - `request.ts` — Wraps `IncomingMessage`, adds `.params`, `.query`, `.body`
108
+ - `response.ts` — Wraps `ServerResponse`, adds `.json()`, `.html()`, `.status()`, `.send()`, `.redirect()`
109
+ - `middleware.ts` — Chain runner, built-in CORS and request logger
110
+ - `static.ts` — Serves files from `public/` with MIME type detection
111
+ - `watcher.ts` — `fs.watch` for hot-reload in dev mode
112
+ - `types.ts` — All shared type definitions (`Tina4Request`, `Tina4Response`, `RouteHandler`, etc.)
113
+ - `events.ts` — Observer-pattern event system (`Events.on`, `emit`, `once`, `off`, `clear`)
114
+ - `ai.ts` — AI coding tool detection and context scaffolding (`detectAi`, `installAiContext`, `aiStatusReport`)
115
+ - `errorOverlay.ts` — Rich debug error page for dev mode (`renderErrorOverlay`, `renderProductionError`, `isDebugMode`)
116
+ - `htmlElement.ts` — Programmatic HTML builder (`HtmlElement`, `htmlElement`, `addHtmlHelpers`)
117
+ - `testing.ts` — Inline testing framework (`tests`, `assertEqual`, `assertThrows`, `runAllTests`)
118
+ - `fakeData.ts` — Core fake data generator (names, emails, addresses, UUIDs, etc.)
119
+ - `constants.ts` — HTTP status codes (`HTTP_OK`, `HTTP_NOT_FOUND`, etc.) and content types (`APPLICATION_JSON`, `TEXT_HTML`, etc.)
120
+ - `devAdmin.ts` — Dev toolbar (fixed bottom bar injected into HTML pages) and admin dashboard at `/_dev/`
121
+ - `auth.ts` — Authentication helpers
122
+ - `cache.ts` — In-memory caching
123
+ - `session.ts` — Session management with pluggable handlers
124
+ - `websocket.ts` — WebSocket support
125
+ - `queue.ts` — Queue system with pluggable backends
126
+ - `graphql.ts` — GraphQL engine
127
+ - `i18n.ts` — Internationalization / localization
128
+ - `logger.ts` — Structured logging
129
+ - `rateLimiter.ts` — Rate limiting middleware
130
+ - `dotenv.ts` — `.env` file loading
131
+ - `health.ts` — Health check endpoint
132
+ - `scss.ts` — SCSS compilation
133
+ - `messenger.ts` — Messaging system
134
+ - `service.ts` — Service layer helpers
135
+ - `wsdl.ts` — WSDL / SOAP support
136
+
137
+ ### @tina4/orm (`packages/orm/`)
138
+ Database layer with auto-CRUD generation, seeding, fake data, and SQL translation.
139
+
140
+ **Key files:**
141
+ - `database.ts` — Adapter manager, `initDatabase()` factory
142
+ - `adapters/sqlite.ts` — `better-sqlite3` implementation of `DatabaseAdapter` interface
143
+ - `adapters/postgres.ts` — PostgreSQL adapter
144
+ - `adapters/mysql.ts` — MySQL adapter
145
+ - `adapters/mssql.ts` — MSSQL / SQL Server adapter (`mssql` or `sqlserver` scheme)
146
+ - `adapters/firebird.ts` — Firebird adapter
147
+ - `model.ts` — Discovers models from `src/models/`, reads `static tableName` and `static fields`
148
+ - `migration.ts` — Schema sync on startup (creates tables, adds columns, warns on destructive changes)
149
+ - `autoCrud.ts` — Generates GET/POST/PUT/DELETE route handlers for each model
150
+ - `query.ts` — Builds SQL from `?filter[field]=value`, `?sort=-name`, `?page=2&limit=10`
151
+ - `validation.ts` — Validates request bodies against model field definitions
152
+ - `types.ts` — `FieldDefinition`, `ModelDefinition`, `DatabaseAdapter`, `QueryOptions`
153
+ - `fakeData.ts` — ORM-aware fake data extending core (adds `forField()` with column-name heuristics)
154
+ - `seeder.ts` — Database seeding (`seedTable` for raw SQL, `seedOrm` for model-based)
155
+ - `sqlTranslation.ts` — Cross-engine SQL translator (`SQLTranslator`) and TTL query cache (`QueryCache`)
156
+
157
+ ### @tina4/swagger (`packages/swagger/`)
158
+ Auto-generates OpenAPI 3.0 docs.
159
+
160
+ **Key files:**
161
+ - `generator.ts` — Produces OpenAPI spec from route table + model definitions
162
+ - `ui.ts` — Serves Swagger UI HTML (CDN-based) at `/swagger` and spec at `/swagger/openapi.json`
163
+
164
+ ### @tina4/twig (`packages/twig/`)
165
+ Optional server-side template rendering.
166
+
167
+ **Key files:**
168
+ - `engine.ts` — Wraps the `twig` npm package, `renderTemplate(path, data)`
169
+ - `middleware.ts` — Adds `res.render(template, data)` to response objects
170
+
171
+ ### tina4 CLI (`packages/cli/`)
172
+ Developer-facing CLI commands.
173
+
174
+ **Key files:**
175
+ - `bin.ts` — Entry point, command dispatch (`init`, `serve`, `--help`)
176
+ - `commands/init.ts` — Scaffolds a new project directory with sample files
177
+ - `commands/serve.ts` — Starts dev server with hot-reload via `@tina4/core`
178
+
179
+ ## Module: Events (`packages/core/src/events.ts`)
180
+
181
+ Observer-pattern event system for decoupled communication. All methods are static on the `Events` class. Listeners run synchronously in priority order (higher priority first). One-time listeners auto-remove after firing.
182
+
183
+ ```typescript
184
+ import { Events } from "@tina4/core";
185
+
186
+ // Register a listener (optional priority — higher runs first)
187
+ Events.on("user.created", (user) => {
188
+ console.log(`Welcome ${(user as any).name}!`);
189
+ }, 10);
190
+
191
+ // One-time listener (auto-removes after first fire)
192
+ Events.once("app.ready", () => console.log("App started!"));
193
+
194
+ // Emit an event — returns array of listener results
195
+ const results = Events.emit("user.created", { name: "Alice" });
196
+
197
+ // Remove a specific listener or all listeners for an event
198
+ Events.off("user.created", specificHandler);
199
+ Events.off("user.created"); // removes all
200
+
201
+ // Introspection
202
+ Events.listeners("user.created"); // callback[]
203
+ Events.events(); // all registered event names
204
+
205
+ // Clear everything
206
+ Events.clear();
207
+ ```
208
+
209
+ ## Module: AI (`packages/core/src/ai.ts`)
210
+
211
+ Detects AI coding tools (Claude Code, Cursor, Copilot, Windsurf, Aider, Cline, Codex) by checking for their config files/directories. Can scaffold a universal Tina4 context document into each tool's expected location.
212
+
213
+ ```typescript
214
+ import { detectAi, installAiContext, aiStatusReport } from "@tina4/core";
215
+
216
+ // Detect which AI tools are present in a project directory
217
+ const tools = detectAi(".");
218
+ // → [{ name: "claude-code", description: "Claude Code (Anthropic CLI)",
219
+ // configFile: "CLAUDE.md", status: "detected" }, ...]
220
+
221
+ // Install context files for all detected tools (creates CLAUDE.md, .cursorules, etc.)
222
+ const created = installAiContext(".", { force: false });
223
+ // → ["CLAUDE.md", ".cursorules"]
224
+
225
+ // Install for ALL known tools, not just detected ones
226
+ import { installAllAiContext } from "@tina4/core";
227
+ installAllAiContext(".", true); // force overwrite
228
+
229
+ // Print a human-readable status report
230
+ console.log(aiStatusReport("."));
231
+ ```
232
+
233
+ ## Module: Error Overlay (`packages/core/src/errorOverlay.ts`)
234
+
235
+ Rich HTML error page for development mode. Uses Catppuccin Mocha colour palette, shows syntax-highlighted source context around the error line, stack trace with source preview, request details, and environment info. Controlled by `TINA4_DEBUG` env var.
236
+
237
+ ```typescript
238
+ import { renderErrorOverlay, renderProductionError, isDebugMode } from "@tina4/core";
239
+
240
+ // In a route error handler:
241
+ try {
242
+ await handler(req, res);
243
+ } catch (err) {
244
+ const html = isDebugMode()
245
+ ? renderErrorOverlay(err as Error, req) // full debug overlay
246
+ : renderProductionError(500, "Internal Server Error"); // safe production page
247
+ res.html(html, 500);
248
+ }
249
+
250
+ // isDebugMode() returns true when TINA4_DEBUG is "true"
251
+ ```
252
+
253
+ ## Module: HtmlElement (`packages/core/src/htmlElement.ts`)
254
+
255
+ Programmatic HTML builder that avoids string concatenation. Three usage patterns: direct construction, builder-pattern functions, and helper injection.
256
+
257
+ ```typescript
258
+ import { HtmlElement, htmlElement, addHtmlHelpers } from "@tina4/core";
259
+
260
+ // Direct construction
261
+ const el = new HtmlElement("div", { class: "card" }, ["Hello"]);
262
+ el.toString(); // '<div class="card">Hello</div>'
263
+
264
+ // Builder pattern — returns a callable that accepts attrs/children
265
+ const div = htmlElement("div");
266
+ const card = div({ class: "card" }, "Hello");
267
+ card.toString(); // '<div class="card">Hello</div>'
268
+
269
+ // Nesting
270
+ const page = htmlElement("div")(
271
+ htmlElement("h1")("Title"),
272
+ htmlElement("p")("Body text"),
273
+ );
274
+
275
+ // Helper injection — adds _div, _p, _a, _span, etc. to an object
276
+ const h: Record<string, any> = {};
277
+ addHtmlHelpers(h);
278
+ const html = h._div({ class: "card" },
279
+ h._h1("Title"),
280
+ h._p({ class: "body" }, "Content"),
281
+ h._img({ src: "/logo.png", alt: "Logo" }), // void tags self-close
282
+ );
283
+ html.toString();
284
+ ```
285
+
286
+ Void tags (`br`, `hr`, `img`, `input`, `meta`, etc.) render without closing tags. Boolean attributes render as bare names (`disabled` not `disabled="true"`).
287
+
288
+ ## Module: Inline Testing (`packages/core/src/testing.ts`)
289
+
290
+ Attach test assertions directly to functions. Tests are registered globally and run with `runAllTests()`. No external test runner needed.
291
+
292
+ ```typescript
293
+ import { tests, assertEqual, assertThrows, assertTrue, assertFalse, runAllTests, resetTests } from "@tina4/core";
294
+
295
+ // Decorate a function with inline tests
296
+ const add = tests(
297
+ assertEqual([5, 3], 8), // add(5, 3) === 8
298
+ assertEqual([0, 0], 0), // add(0, 0) === 0
299
+ assertThrows(Error, [null]), // add(null) throws Error
300
+ )(function add(a: number, b: number | null = null): number {
301
+ if (b === null) throw new Error("b required");
302
+ return a + b;
303
+ });
304
+
305
+ // The original function works normally
306
+ add(2, 3); // 5
307
+
308
+ // Run all registered tests
309
+ const results = runAllTests({ quiet: false, failfast: false });
310
+ // → { passed: 3, failed: 0, errors: 0, details: [...] }
311
+
312
+ // Additional assertion types
313
+ assertTrue([someArgs]); // result is truthy
314
+ assertFalse([someArgs]); // result is falsy
315
+
316
+ // Reset registry between test runs
317
+ resetTests();
318
+ ```
319
+
320
+ ## Module: Seeder / FakeData (`packages/orm/src/seeder.ts`, `packages/orm/src/fakeData.ts`)
321
+
322
+ Database seeding with fake data generation. The ORM `FakeData` extends core `FakeData` (which provides names, emails, addresses, etc.) and adds `forField()` for auto-generating values based on ORM field definitions with column-name heuristics.
323
+
324
+ ```typescript
325
+ import { FakeData, seedTable, seedOrm } from "@tina4/orm";
326
+
327
+ // FakeData — deterministic with optional seed
328
+ const fake = new FakeData(42);
329
+ fake.name(); // fullName alias
330
+ fake.email(); // realistic email
331
+ fake.phone(); // phone number
332
+ fake.integer(1, 100);
333
+ fake.numeric(0, 1000, 2); // float alias
334
+ fake.datetime(2020, 2025); // Date object
335
+ fake.boolean();
336
+ fake.uuid();
337
+ fake.address();
338
+ fake.company();
339
+ fake.sentence(5);
340
+ fake.paragraph(3);
341
+
342
+ // forField() — auto-generates based on FieldDefinition + column name heuristics
343
+ fake.forField({ type: "string", maxLength: 50 }, "email"); // generates email
344
+ fake.forField({ type: "integer", min: 0, max: 100 }); // random integer
345
+ fake.forField({ type: "boolean" }); // true/false
346
+
347
+ // seedTable — raw SQL inserts with generator functions
348
+ await seedTable(db, "users", 50, {
349
+ name: () => fake.name(),
350
+ email: () => fake.email(),
351
+ role: "user", // static values also accepted
352
+ }, { active: true }); // overrides applied to every row
353
+
354
+ // seedOrm — auto-seed from model field definitions
355
+ import User from "./src/models/User.js";
356
+ await seedOrm(User, 100, { role: "user" }, 42); // optional seed for determinism
357
+ ```
358
+
359
+ Column-name heuristics in `forField()`: columns named `email`, `phone`, `name`, `address`, `city`, `country`, `company`, `url`, `uuid`, `ip`, `currency`, etc. get contextually appropriate fake data.
360
+
361
+ ## Module: SQL Translation (`packages/orm/src/sqlTranslation.ts`)
362
+
363
+ Cross-engine SQL dialect translator and in-memory query cache. All translator methods are static on `SQLTranslator`. The `QueryCache` provides TTL-based caching with LRU eviction.
364
+
365
+ ```typescript
366
+ import { SQLTranslator, QueryCache } from "@tina4/orm";
367
+
368
+ // Firebird: LIMIT/OFFSET → ROWS X TO Y
369
+ SQLTranslator.limitToRows("SELECT * FROM users LIMIT 10 OFFSET 5");
370
+ // → "SELECT * FROM users ROWS 6 TO 15"
371
+
372
+ // MSSQL: LIMIT → TOP N
373
+ SQLTranslator.limitToTop("SELECT * FROM users LIMIT 10");
374
+ // → "SELECT TOP 10 * FROM users"
375
+
376
+ // MySQL/MSSQL: || concatenation → CONCAT()
377
+ SQLTranslator.concatPipesToFunc("first_name || ' ' || last_name");
378
+ // → "CONCAT(first_name, ' ', last_name)"
379
+
380
+ // Boolean to integer (Firebird)
381
+ SQLTranslator.booleanToInt("WHERE active = TRUE");
382
+ // → "WHERE active = 1"
383
+
384
+ // ILIKE → LOWER() LIKE LOWER()
385
+ SQLTranslator.ilikeToLike("WHERE name ILIKE '%alice%'");
386
+ // → "WHERE LOWER(name) LIKE LOWER('%alice%')"
387
+
388
+ // Auto-increment DDL translation
389
+ SQLTranslator.autoIncrementSyntax(ddl, "postgresql"); // AUTOINCREMENT → SERIAL PRIMARY KEY
390
+ SQLTranslator.autoIncrementSyntax(ddl, "mysql"); // → AUTO_INCREMENT
391
+ SQLTranslator.autoIncrementSyntax(ddl, "mssql"); // → IDENTITY(1,1)
392
+
393
+ // Placeholder style conversion
394
+ SQLTranslator.placeholderStyle("SELECT * FROM t WHERE id = ?", ":"); // → :1
395
+ SQLTranslator.placeholderStyle("SELECT * FROM t WHERE id = ?", "%s"); // → %s
396
+
397
+ // RETURNING clause parsing
398
+ SQLTranslator.parseReturning("INSERT INTO t (x) VALUES (1) RETURNING id, name");
399
+ // → { sql: "INSERT INTO t (x) VALUES (1)", columns: ["id", "name"] }
400
+
401
+ // QueryCache — TTL-based in-memory cache
402
+ const cache = new QueryCache({ defaultTtl: 60, maxSize: 1000 });
403
+
404
+ const key = QueryCache.queryKey("SELECT * FROM users WHERE id = ?", [42]);
405
+ cache.set(key, [{ id: 42, name: "Alice" }], 30); // TTL 30 seconds
406
+ cache.get(key); // → [{ id: 42, name: "Alice" }] or undefined if expired
407
+ cache.has(key); // true/false
408
+ cache.delete(key);
409
+ cache.sweep(); // remove all expired entries
410
+ cache.clear(); // remove everything
411
+
412
+ // Get-or-set pattern
413
+ const rows = cache.remember(key, 60, () => db.execute(sql, params));
414
+ ```
415
+
416
+ ## Conventions You Must Follow
417
+
418
+ ### Route Files
419
+ - Located in `src/routes/`
420
+ - Filename = HTTP method: `get.ts`, `post.ts`, `put.ts`, `delete.ts`, `patch.ts`
421
+ - Directory path = URL path: `src/routes/api/users/[id]/get.ts` → `GET /api/users/{id}`
422
+ - Dynamic params use bracket notation in filenames: `[id]`, `[...slug]` (converted to `{id}`, `{...slug}` in URL patterns)
423
+ - **Must export** a default async function:
424
+ ```typescript
425
+ export default async function (req: Tina4Request, res: Tina4Response) {}
426
+ ```
427
+ - **Optionally export** a `meta` object for Swagger:
428
+ ```typescript
429
+ export const meta = { summary: "...", tags: ["..."] };
430
+ ```
431
+ - **Optionally export** a `template` string to render a Twig template:
432
+ ```typescript
433
+ export const template = "page.twig"; // renders src/templates/page.twig
434
+ ```
435
+ The route handler provides data; the template renders the HTML. Use `res.template("name.twig", data)` for programmatic template rendering.
436
+
437
+ ### Model Files
438
+ - Located in `src/models/`
439
+ - Export a default class with `static tableName` and `static fields`:
440
+ ```typescript
441
+ export default class User {
442
+ static tableName = "users";
443
+ static fields = {
444
+ id: { type: "integer" as const, primaryKey: true, autoIncrement: true },
445
+ name: { type: "string" as const, required: true },
446
+ };
447
+ }
448
+ ```
449
+ - Field types: `"string"`, `"text"`, `"integer"`, `"number"`, `"boolean"`, `"datetime"`
450
+ - Field options: `primaryKey`, `autoIncrement`, `required`, `default`, `minLength`, `maxLength`, `min`, `max`, `pattern`
451
+ - Table name should be lowercase plural (e.g., `"users"`, `"products"`)
452
+
453
+ ### File-based routes override auto-CRUD
454
+ If both a file route and an auto-CRUD route match, the file route wins.
455
+
456
+ ### All packages use barrel exports
457
+ Every package has an `index.ts` that re-exports the public API. Import from the package, not from internal paths.
458
+
459
+ ### ESM everywhere
460
+ All code is ESM. Use `.js` extensions in import paths (TypeScript convention for Node16 module resolution):
461
+ ```typescript
462
+ import { Router } from "./router.js"; // .js even though the file is .ts
463
+ ```
464
+
465
+ ## Architecture Decisions
466
+
467
+ 1. **Native `node:http`** — No framework dependency. Zero overhead.
468
+ 2. **`tsx` for dev** — No build step needed during development. TypeScript runs directly.
469
+ 3. **Convention-based models** — `static fields = {}` over decorators. No special TypeScript config needed.
470
+ 4. **CDN for Swagger UI** — Keeps install under 8MB. Single HTML file loads from unpkg.com.
471
+ 5. **Process restart for hot-reload** — Simpler and more reliable than HMR with ESM.
472
+ 6. **SQLite default** — `better-sqlite3` is synchronous and fast. Full adapters for Postgres, MySQL, MSSQL/SQL Server, and Firebird.
473
+ 7. **CLI named `tina4nodejs`** (primary) with `tina4` as alias — So `npx tina4nodejs init` or `npx tina4 init` both work.
474
+ 8. **Event system** — Static `Events` class, synchronous dispatch, priority ordering, zero deps.
475
+ 9. **Inline testing** — Tests as decorators on functions, no external test runner for unit-level checks.
476
+ 10. **SQL translation** — Dialect differences handled at runtime via `SQLTranslator` static methods, not at query-build time.
477
+ 11. **Error overlay** — Dev-only rich HTML error page, controlled by `TINA4_DEBUG` env var.
478
+ 12. **AI context scaffolding** — Auto-detect and install context files for all major AI coding tools.
479
+ 13. **Dev toolbar** — Fixed bottom bar injected into HTML pages in dev mode, showing route info, request ID, version. Admin dashboard at `/_dev/`.
480
+ 14. **Default port 7148** — Config priority: explicit config > `PORT` env var > 7148. Default host: `0.0.0.0`.
481
+
482
+ ## Database Configuration
483
+
484
+ ### Connection string format
485
+ Set `DATABASE_URL` in your `.env` file using `driver://host:port/database` format:
486
+
487
+ ```bash
488
+ # SQLite (default if nothing configured)
489
+ DATABASE_URL=sqlite:///path/to/db.sqlite
490
+ DATABASE_URL=sqlite://./data/tina4.db
491
+
492
+ # PostgreSQL
493
+ DATABASE_URL=postgres://localhost:5432/mydb
494
+ DATABASE_URL=postgresql://localhost:5432/mydb
495
+
496
+ # MySQL
497
+ DATABASE_URL=mysql://localhost:3306/mydb
498
+
499
+ # MSSQL / SQL Server (both schemes work)
500
+ DATABASE_URL=mssql://localhost:1433/mydb
501
+ DATABASE_URL=sqlserver://localhost:1433/mydb
502
+
503
+ # Firebird
504
+ DATABASE_URL=firebird://localhost:3050/mydb
505
+ ```
506
+
507
+ ### Credentials
508
+ Credentials can be embedded in the URL or provided separately:
509
+
510
+ ```bash
511
+ # In the URL
512
+ DATABASE_URL=postgres://user:pass@localhost:5432/mydb
513
+
514
+ # Or as separate env vars (merged when URL has no credentials)
515
+ DATABASE_URL=postgres://localhost:5432/mydb
516
+ DATABASE_USERNAME=myuser
517
+ DATABASE_PASSWORD=mypass
518
+ ```
519
+
520
+ Credential priority: `config.user` > `config.username` > `DATABASE_USERNAME` env var.
521
+
522
+ ### Programmatic configuration
523
+ ```typescript
524
+ import { initDatabase } from "@tina4/orm";
525
+
526
+ await initDatabase({ url: "postgres://localhost:5432/mydb" });
527
+ // or
528
+ await initDatabase({ type: "postgres", host: "localhost", port: 5432, database: "mydb", username: "user", password: "pass" });
529
+ ```
530
+
531
+ ### Available adapters
532
+ | Adapter | Scheme(s) | Package |
533
+ |---------|-----------|---------|
534
+ | SQLite | `sqlite://` | `better-sqlite3` |
535
+ | PostgreSQL | `postgres://`, `postgresql://` | `pg` |
536
+ | MySQL | `mysql://` | `mysql2` |
537
+ | MSSQL | `mssql://`, `sqlserver://` | `tedious` |
538
+ | Firebird | `firebird://` | `node-firebird` |
539
+
540
+ ## Testing
541
+
542
+ Run tests with:
543
+ ```bash
544
+ npm test
545
+ ```
546
+
547
+ This executes `test/run-all.ts` which runs all 43 test files:
548
+ - `test/integration.ts` — Full integration test (creates a temp project, starts a real server, runs assertions)
549
+ - `test/*.test.ts` — 42 individual test files covering all subsystems (ORM, routing, middleware, database drivers, sessions, queues, WebSocket, GraphQL, i18n, etc.)
550
+
551
+ **Always run tests after making changes.** All tests must pass.
552
+
553
+ When adding new features, add a corresponding `test/<feature>.test.ts` file.
554
+
555
+ ## Common Tasks
556
+
557
+ ### Adding a new feature to @tina4/core
558
+ 1. Create the file in `packages/core/src/`
559
+ 2. Export it from `packages/core/src/index.ts`
560
+ 3. If it needs integration with server startup, add it to `server.ts`
561
+ 4. Add test assertions to `test/integration.ts`
562
+
563
+ ### Adding a new database adapter
564
+ 1. Create `packages/orm/src/adapters/<name>.ts` implementing `DatabaseAdapter`
565
+ 2. Add the case to `initDatabase()` in `packages/orm/src/database.ts`
566
+ 3. Add the dependency to `packages/orm/package.json`
567
+
568
+ ### Adding a new CLI command
569
+ 1. Create `packages/cli/src/commands/<name>.ts`
570
+ 2. Add the case to the switch in `packages/cli/src/bin.ts`
571
+
572
+ ### Adding a new model field type
573
+ 1. Update `FieldType` in `packages/orm/src/types.ts`
574
+ 2. Update `fieldTypeToSQLite()` in `packages/orm/src/adapters/sqlite.ts`
575
+ 3. Update `fieldToSchemaProperty()` in `packages/swagger/src/generator.ts`
576
+ 4. Update validation in `packages/orm/src/validation.ts`
577
+
578
+ ## Roadmap (Not Yet Implemented)
579
+
580
+ - Bun runtime compatibility
581
+
582
+ ## Don'ts
583
+
584
+ - **Don't add Express, Fastify, or any HTTP framework** — we use native `node:http`
585
+ - **Don't use decorators** — convention-based models with static properties
586
+ - **Don't add CommonJS** — everything is ESM (`"type": "module"`)
587
+ - **Don't bundle `swagger-ui-dist`** — we load Swagger UI from CDN to stay under 8MB
588
+ - **Don't break the 43 test files** — run `npm test` before committing
589
+ - **Don't add unnecessary dependencies** — minimal footprint is a core principle
590
+ - **Don't use `url.parse()`** — use the WHATWG `URL` constructor instead (deprecated in Node 20+)
591
+
592
+ ## Tina4 Maintainer Skill
593
+ Always read and follow the instructions in .claude/skills/tina4-maintainer/SKILL.md when working on this codebase. Read its referenced files in .claude/skills/tina4-maintainer/references/ as needed for specific subsystems.
594
+
595
+ ## Tina4 Developer Skill
596
+ Always read and follow the instructions in .claude/skills/tina4-developer/SKILL.md when building applications with this framework. Read its referenced files in .claude/skills/tina4-developer/references/ as needed.
597
+
598
+ ## Tina4-js Frontend Skill
599
+ Always read and follow the instructions in .claude/skills/tina4-js/SKILL.md when working with tina4-js frontend code. Read its referenced files in .claude/skills/tina4-js/references/ as needed.