tina4-nodejs 3.1.1 → 3.1.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.
package/README.md CHANGED
@@ -27,17 +27,22 @@
27
27
 
28
28
  ---
29
29
 
30
- ## Quickstart
30
+ ## Quick Start
31
31
 
32
32
  ```bash
33
- npm install tina4-nodejs
34
- npx tina4nodejs init my-app
35
- cd my-app
36
- npx tina4nodejs serve
37
- # -> http://localhost:7148
33
+ # Install the Tina4 CLI
34
+ cargo install tina4 # or download binary from https://github.com/tina4stack/tina4/releases
35
+
36
+ # Create a project
37
+ tina4 init nodejs ./my-app
38
+
39
+ # Run it
40
+ cd my-app && tina4 serve
38
41
  ```
39
42
 
40
- That's it. Zero configuration, zero classes, zero boilerplate.
43
+ Open http://localhost:7148 your app is running.
44
+
45
+ > **Alternative** (without Rust CLI): `npm install tina4-nodejs` then create `app.ts`
41
46
 
42
47
  ---
43
48
 
@@ -298,23 +303,24 @@ export default async function (request: Tina4Request, response: Tina4Response) {
298
303
  }
299
304
 
300
305
  // Programmatic: src/routes/webhooks.ts
301
- import { get, post, noauth, secured, middleware } from "tina4-nodejs";
306
+ import { get, post } from "tina4-nodejs";
302
307
 
303
308
  get("/api/items", async (request, response) => {
304
309
  response({items: []}, HTTP_OK);
305
310
  });
306
311
 
307
- noauth(
308
- post("/api/webhook", async (request, response) => {
309
- response({ok: true}, HTTP_OK);
310
- })
311
- );
312
+ // POST routes require auth by default; GET routes are public by default.
313
+ // Use JSDoc @noauth / @secured annotations to override:
312
314
 
313
- secured(
314
- get("/api/admin/stats", async (request, response) => {
315
- response({secret: true}, HTTP_OK);
316
- })
317
- );
315
+ /** @noauth */
316
+ post("/api/webhook", async (request, response) => {
317
+ response({ok: true}, HTTP_OK);
318
+ });
319
+
320
+ /** @secured */
321
+ get("/api/admin/stats", async (request, response) => {
322
+ response({secret: true}, HTTP_OK);
323
+ });
318
324
  ```
319
325
 
320
326
  Path parameter types: `{id}` (string), `[id]` (file-based), `[...slug]` (catch-all).
@@ -358,7 +364,7 @@ db.execute("INSERT INTO users (name, email) VALUES (?, ?)", ["Alice", "alice@tes
358
364
  ### Middleware
359
365
 
360
366
  ```typescript
361
- import { middleware } from "tina4-nodejs";
367
+ import { get } from "tina4-nodejs";
362
368
 
363
369
  const authCheck = async (request: Tina4Request, response: Tina4Response, next: Function) => {
364
370
  if (!request.headers.authorization) {
@@ -367,21 +373,18 @@ const authCheck = async (request: Tina4Request, response: Tina4Response, next: F
367
373
  return next();
368
374
  };
369
375
 
370
- middleware(authCheck,
371
- get("/protected", async (request, response) => {
372
- response({secret: true}, HTTP_OK);
373
- })
374
- );
376
+ get("/protected", async (request, response) => {
377
+ response({secret: true}, HTTP_OK);
378
+ }, [authCheck]);
375
379
  ```
376
380
 
377
381
  ### JWT Authentication
378
382
 
379
383
  ```typescript
380
- import { Auth } from "tina4-nodejs";
384
+ import { createToken, validateToken } from "tina4-nodejs";
381
385
 
382
- const auth = new Auth({secret: "your-secret"});
383
- const token = auth.createToken({userId: 42});
384
- const payload = auth.validateToken(token);
386
+ const token = createToken({userId: 42}, "your-secret");
387
+ const payload = validateToken(token, "your-secret");
385
388
  ```
386
389
 
387
390
  POST/PUT/PATCH/DELETE routes require `Authorization: Bearer <token>` by default. Use `noauth()` to make public, `secured()` to protect GET routes.
@@ -398,13 +401,16 @@ Backend: file (default). Set via `TINA4_SESSION_HANDLER` in `.env`.
398
401
  ### Queues
399
402
 
400
403
  ```typescript
401
- import { Queue, Producer, Consumer } from "tina4-nodejs";
404
+ import { Queue } from "tina4-nodejs";
402
405
 
403
- new Producer(new Queue({topic: "emails"})).produce({to: "alice@example.com"});
406
+ const queue = new Queue({ topic: "emails" });
407
+ queue.push({ to: "alice@example.com" });
404
408
 
405
- new Consumer(new Queue({topic: "emails"})).onMessage((msg) => {
406
- sendEmail(msg.data);
407
- });
409
+ const job = queue.pop();
410
+ if (job) {
411
+ sendEmail(job.data);
412
+ job.complete();
413
+ }
408
414
  ```
409
415
 
410
416
  ### GraphQL
@@ -420,12 +426,14 @@ gql.registerRoute("/graphql"); // GET = GraphiQL IDE, POST = queries
420
426
  ### WebSocket
421
427
 
422
428
  ```typescript
423
- import { WebSocketManager } from "tina4-nodejs";
429
+ import { WebSocketServer } from "tina4-nodejs";
424
430
 
425
- const ws = new WebSocketManager();
431
+ const wss = new WebSocketServer({ port: 8080 });
426
432
 
427
- ws.route("/ws/chat", async (connection, message) => {
428
- await ws.broadcast("/ws/chat", `User said: ${message}`);
433
+ wss.on("connection", (client) => {
434
+ client.on("message", (msg) => {
435
+ wss.broadcast(`User said: ${msg}`);
436
+ });
429
437
  });
430
438
  ```
431
439
 
@@ -489,25 +497,26 @@ const result = await api.sendRequest("/users/42");
489
497
  ### Data Seeder
490
498
 
491
499
  ```typescript
492
- import { Fake, seedModel } from "tina4-nodejs";
500
+ import { FakeData } from "tina4-nodejs";
493
501
 
494
- const fake = new Fake();
502
+ const fake = new FakeData();
495
503
  fake.name(); // "Alice Johnson"
496
504
  fake.email(); // "alice.johnson@example.com"
497
505
 
498
- seedModel(User, {count: 50});
506
+ // Seed via ORM package:
507
+ // import { seedOrm } from "@tina4/orm";
508
+ // await seedOrm(User, 50);
499
509
  ```
500
510
 
501
511
  ### Response Cache
502
512
 
503
513
  ```typescript
504
- import { cached } from "tina4-nodejs";
514
+ import { get, responseCache } from "tina4-nodejs";
505
515
 
506
- cached(60,
507
- get("/api/stats", async (request, response) => {
508
- response(computeExpensiveStats(), HTTP_OK);
509
- })
510
- );
516
+ // Apply response cache as middleware with 60-second TTL
517
+ get("/api/stats", async (request, response) => {
518
+ response(computeExpensiveStats(), HTTP_OK);
519
+ }, [responseCache({ ttl: 60 })]);
511
520
  ```
512
521
 
513
522
  ### SCSS, Localization
@@ -519,7 +528,7 @@ cached(60,
519
528
 
520
529
  ## Dev Mode
521
530
 
522
- Set `TINA4_DEBUG_LEVEL=DEBUG` in `.env` to enable:
531
+ Set `TINA4_DEBUG=true` in `.env` to enable:
523
532
 
524
533
  - **Live reload** -- browser auto-refreshes on code changes
525
534
  - **CSS hot-reload** -- SCSS changes apply without page refresh
@@ -604,7 +613,8 @@ SECRET=your-jwt-secret
604
613
  DATABASE_URL=sqlite:///data/app.db
605
614
  DATABASE_USERNAME=admin # Separate credentials for networked databases
606
615
  DATABASE_PASSWORD=secret
607
- TINA4_DEBUG_LEVEL=DEBUG # DEBUG, INFO, WARNING, ERROR, ALL
616
+ TINA4_DEBUG=true # Enable dev toolbar, error overlay
617
+ TINA4_LOG_LEVEL=ALL # ALL, DEBUG, INFO, WARNING, ERROR
608
618
  TINA4_LANGUAGE=en # en, fr, af, zh, ja, es
609
619
  TINA4_SESSION_HANDLER=SessionFileHandler
610
620
  SWAGGER_TITLE=My API
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tina4-nodejs",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
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"],
@@ -1,258 +0,0 @@
1
- # Tina4 v3 — Comprehensive Benchmark Report
2
-
3
- **Date:** 2026-03-21 | **Machine:** Apple M3, macOS, 16GB RAM
4
- **Tool:** hey (https://github.com/rakyll/hey) | **Config:** 5000 requests, 50 concurrent, 5 runs (median)
5
- **Warm-up:** 500 requests discarded before each test | **Mode:** All frameworks in production mode
6
-
7
- ---
8
-
9
- ## Overall Ranking — JSON Endpoint
10
-
11
- | # | Framework | Language | JSON req/s | List req/s | Deploy Size | Deps | Features |
12
- |---|-----------|---------|:---------:|:---------:|:----------:|:----:|:--------:|
13
- | 1 | Node.js raw http | Node.js | 86,662 | 24,598 | 0 KB | 0 | 1/38 |
14
- | 2 | Fastify | Node.js | 79,505 | 23,395 | 2 MB | 10+ | 5/38 |
15
- | 3 | Koa | Node.js | 60,400 | 23,433 | 1 MB | 5 | 3/38 |
16
- | 4 | **Tina4 Node.js** | **Node.js** | **57,035** | **25,088** | **1.8 MB** | **0** | **38/38** |
17
- | 5 | Express | Node.js | 56,687 | 20,720 | 2 MB | 3 | 4/38 |
18
- | 6 | **Tina4 PHP** | **PHP** | **27,299** | **16,555** | **1.0 MB** | **0** | **38/38** |
19
- | 7 | **Tina4 Python** | **Python** | **16,233** | **5,858** | **2.4 MB** | **0** | **38/38** |
20
- | 8 | Starlette | Python | 15,978 | 7,493 | 505 KB | 4 | 6/38 |
21
- | 9 | FastAPI | Python | 11,886 | 2,464 | 4.8 MB | 12+ | 8/38 |
22
- | 10 | Sinatra | Ruby | 9,732 | 5,996 | 5 MB | 5 | 4/38 |
23
- | 11 | **Tina4 Ruby** | **Ruby** | **9,504** | **7,648** | **892 KB** | **0** | **38/38** |
24
- | 12 | Slim | PHP | 5,033 | 4,520 | 1.3 MB | 10+ | 6/38 |
25
- | 13 | Flask | Python | 4,767 | 1,644 | 4.2 MB | 6 | 7/38 |
26
- | 14 | Django | Python | 3,747 | 3,305 | 25 MB | 20+ | 22/38 |
27
- | 15 | Symfony | PHP | 1,840 | 1,702 | 11 MB | 30+ | 8/38 |
28
- | 16 | Bottle | Python | 1,251 | 676 | 200 KB | 0 | 5/38 |
29
- | 17 | Laravel | PHP | 370 | 364 | 77 MB | 50+ | 25/38 |
30
-
31
- ---
32
-
33
- ## Per-Language Breakdown
34
-
35
- ### Python
36
-
37
- | Framework | JSON req/s | List req/s | Deploy | Deps | Features | vs Tina4 |
38
- |-----------|:---------:|:---------:|:------:|:----:|:--------:|:--------:|
39
- | **Tina4 Python** | **16,233** | **5,858** | **2.4 MB** | **0** | **38/38** | **baseline** |
40
- | Starlette | 15,978 | 7,493 | 505 KB | 4 | 6/38 | 0.98x |
41
- | FastAPI | 11,886 | 2,464 | 4.8 MB | 12+ | 8/38 | 0.73x |
42
- | Flask | 4,767 | 1,644 | 4.2 MB | 6 | 7/38 | 0.29x |
43
- | Django | 3,747 | 3,305 | 25 MB | 20+ | 22/38 | 0.23x |
44
- | Bottle | 1,251 | 676 | 200 KB | 0 | 5/38 | 0.08x |
45
-
46
- **Tina4 Python** is #1 in Python. Matches Starlette (which uses uvicorn's C parser), 3.4x faster than Flask, 4.3x faster than Django.
47
-
48
- ### PHP
49
-
50
- | Framework | JSON req/s | List req/s | Deploy | Deps | Features | vs Tina4 |
51
- |-----------|:---------:|:---------:|:------:|:----:|:--------:|:--------:|
52
- | **Tina4 PHP** | **27,299** | **16,555** | **1.0 MB** | **0** | **38/38** | **baseline** |
53
- | Slim | 5,033 | 4,520 | 1.3 MB | 10+ | 6/38 | 0.18x |
54
- | Symfony | 1,840 | 1,702 | 11 MB | 30+ | 8/38 | 0.07x |
55
- | Laravel | 370 | 364 | 77 MB | 50+ | 25/38 | 0.01x |
56
-
57
- **Tina4 PHP** dominates. 5.4x faster than Slim, 14.8x faster than Symfony, 73.8x faster than Laravel. 77x smaller than Laravel.
58
-
59
- ### Ruby
60
-
61
- | Framework | JSON req/s | List req/s | Deploy | Deps | Features | vs Tina4 |
62
- |-----------|:---------:|:---------:|:------:|:----:|:--------:|:--------:|
63
- | Sinatra | 9,732 | 5,996 | 5 MB | 5 | 4/38 | 1.02x |
64
- | **Tina4 Ruby** | **9,504** | **7,648** | **892 KB** | **0** | **38/38** | **baseline** |
65
-
66
- **Tina4 Ruby** matches Sinatra on JSON (within noise), beats it on large payloads (7,648 vs 5,996). Ships 38 features vs 4.
67
-
68
- ### Node.js
69
-
70
- | Framework | JSON req/s | List req/s | Deploy | Deps | Features | vs Tina4 |
71
- |-----------|:---------:|:---------:|:------:|:----:|:--------:|:--------:|
72
- | Node.js raw | 86,662 | 24,598 | 0 KB | 0 | 1/38 | 1.52x |
73
- | Fastify | 79,505 | 23,395 | 2 MB | 10+ | 5/38 | 1.39x |
74
- | Koa | 60,400 | 23,433 | 1 MB | 5 | 3/38 | 1.06x |
75
- | **Tina4 Node.js** | **57,035** | **25,088** | **1.8 MB** | **0** | **38/38** | **baseline** |
76
- | Express | 56,687 | 20,720 | 2 MB | 3 | 4/38 | 0.99x |
77
-
78
- **Tina4 Node.js** beats Express (57K vs 57K), matches Koa. Fastest on large payloads (25,088 — highest of all Node.js frameworks).
79
-
80
- ---
81
-
82
- ## Deployment Size Comparison
83
-
84
- | Framework | Size | vs Tina4 | Files |
85
- |-----------|:----:|:--------:|:-----:|
86
- | **Tina4 Ruby** | **892 KB** | — | ~65 |
87
- | **Tina4 PHP** | **1.0 MB** | — | ~52 |
88
- | **Tina4 Node.js** | **1.8 MB** | — | ~71 |
89
- | **Tina4 Python** | **2.4 MB** | — | ~65 |
90
- | Bottle | 200 KB | 0.08x | 1 |
91
- | Starlette | 505 KB | 0.2x | ~30 |
92
- | Slim | 1.3 MB | 1x | ~100 |
93
- | Express | 2 MB | 1x | ~50 |
94
- | Flask + deps | 4.2 MB | 2x | ~200 |
95
- | FastAPI + deps | 4.8 MB | 2x | ~300 |
96
- | Sinatra + deps | 5 MB | 2x | ~100 |
97
- | Symfony | 11 MB | 10x | ~2000 |
98
- | Django | 25 MB | 10x | ~5000 |
99
- | Laravel | 77 MB | 77x | ~10000 |
100
-
101
- ---
102
-
103
- ## CO2 Emissions per 1000 Requests
104
-
105
- Based on: 15W TDP × (1000/req_per_sec) seconds × 475g CO2/kWh grid average
106
-
107
- | Framework | JSON req/s | Time for 1000 req | Energy (Wh) | CO2 (g) | vs Tina4 |
108
- |-----------|:---------:|:----------------:|:----------:|:------:|:--------:|
109
- | Node.js raw | 86,662 | 0.012s | 0.00005 | 0.023 | 0.3x |
110
- | Fastify | 79,505 | 0.013s | 0.00005 | 0.025 | 0.3x |
111
- | **Tina4 Node.js** | **57,035** | **0.018s** | **0.00007** | **0.035** | **baseline** |
112
- | Express | 56,687 | 0.018s | 0.00007 | 0.035 | 1.0x |
113
- | **Tina4 PHP** | **27,299** | **0.037s** | **0.00015** | **0.073** | **baseline** |
114
- | **Tina4 Python** | **16,233** | **0.062s** | **0.00026** | **0.122** | **baseline** |
115
- | Starlette | 15,978 | 0.063s | 0.00026 | 0.124 | 1.0x |
116
- | FastAPI | 11,886 | 0.084s | 0.00035 | 0.167 | 1.4x |
117
- | Sinatra | 9,732 | 0.103s | 0.00043 | 0.204 | 1.7x |
118
- | **Tina4 Ruby** | **9,504** | **0.105s** | **0.00044** | **0.209** | **baseline** |
119
- | Slim | 5,033 | 0.199s | 0.00083 | 0.394 | 5.4x |
120
- | Flask | 4,767 | 0.210s | 0.00087 | 0.416 | 3.4x |
121
- | Django | 3,747 | 0.267s | 0.00111 | 0.529 | 4.3x |
122
- | Symfony | 1,840 | 0.543s | 0.00226 | 1.076 | 14.7x |
123
- | Bottle | 1,251 | 0.799s | 0.00333 | 1.584 | 13.0x |
124
- | Laravel | 370 | 2.703s | 0.01126 | 5.349 | 73.3x |
125
-
126
- **Laravel emits 73x more CO2 per request than Tina4 PHP.**
127
-
128
- At scale (1M requests/day):
129
- - Tina4 PHP: **73g CO2/day** (26.6 kg/year)
130
- - Laravel: **5,349g CO2/day** (1,952 kg/year) — **1.9 tonnes of CO2 per year more**
131
-
132
- ---
133
-
134
- ## Feature Comparison (38 features)
135
-
136
- | Feature | Tina4 | Django | Laravel | Flask | FastAPI | Express | Sinatra | Slim | Symfony |
137
- |---------|:-----:|:------:|:-------:|:-----:|:-------:|:-------:|:-------:|:----:|:-------:|
138
- | **Total** | **38** | **22** | **25** | **7** | **8** | **4** | **4** | **6** | **8** |
139
- | Zero deps | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
140
- | ORM | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
141
- | 5 DB drivers | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
142
- | JWT auth | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
143
- | Queue system | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
144
- | WebSocket | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
145
- | GraphQL | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
146
- | SOAP/WSDL | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
147
- | Swagger/OpenAPI | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
148
- | Template engine | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ |
149
- | CSS framework | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
150
- | Dev dashboard | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
151
- | Gallery/examples | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
152
- | AI assistant | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
153
- | 4 languages | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
154
-
155
- ---
156
-
157
- ## Methodology
158
-
159
- ### How to reproduce
160
- ```bash
161
- cd tina4-python
162
- python benchmarks/benchmark.py --runs 5
163
- ```
164
-
165
- ### What we measured
166
- - **JSON endpoint**: Returns `{"message": "Hello, World!", "framework": "..."}` — tests routing + JSON serialization
167
- - **List endpoint**: Returns 100 items with id/name/price — tests JSON serialization of larger payloads
168
-
169
- ### Production mode
170
- All frameworks run with debug/development mode OFF:
171
- - Tina4: `TINA4_DEBUG=false`
172
- - Flask: `FLASK_ENV=production`
173
- - Django: `DEBUG=False`
174
- - Laravel: `APP_DEBUG=false`
175
- - Express/Fastify/Koa: `NODE_ENV=production`
176
- - Sinatra: `environment=production`
177
- - PHP: `display_errors=Off`
178
-
179
- ### Server types
180
- - **Tina4 Python**: built-in asyncio (zero deps)
181
- - **Tina4 PHP**: PHP built-in server (`php -S`)
182
- - **Tina4 Ruby**: WEBrick
183
- - **Tina4 Node.js**: Node.js http.createServer
184
- - **Flask**: Werkzeug
185
- - **Starlette/FastAPI**: uvicorn (with httptools C parser)
186
- - **Django**: runserver
187
- - **Laravel**: artisan serve (PHP built-in)
188
- - **Symfony**: PHP built-in server
189
- - **Slim**: PHP built-in server
190
- - **Express/Fastify/Koa**: Node.js http
191
- - **Sinatra**: Puma
192
-
193
- ### Variance
194
- Individual run values are reported alongside medians. Variance of >20% between runs is flagged. The median of 5 runs provides a reliable central estimate.
195
-
196
- ### Limitations
197
- - All tests use development servers (not production WSGI/ASGI servers)
198
- - Production deployments with gunicorn/uvicorn/php-fpm/puma would improve all frameworks
199
- - Results are specific to Apple M3 — different hardware will produce different absolute numbers
200
- - Relative rankings should be consistent across hardware
201
-
202
- ---
203
-
204
- ## Cross-Platform Support
205
-
206
- All 4 Tina4 frameworks run on:
207
- - ✅ macOS (Intel + Apple Silicon)
208
- - ✅ Linux (x86_64 + ARM64)
209
- - ✅ Windows (10/11)
210
- - ✅ Docker (any base image)
211
- - ✅ WSL2
212
-
213
- No C extensions. No native binaries. No compile step. Pure Python/PHP/Ruby/JavaScript.
214
-
215
- ---
216
-
217
- *Generated by Tina4 Benchmark Suite v3.0.0 — https://tina4.com*
218
-
219
- ---
220
-
221
- ## Ruby — Updated Results (2026-03-21)
222
-
223
- | Framework | JSON req/s | List req/s | Server | Deps | Features |
224
- |-----------|:---------:|:---------:|--------|:----:|:--------:|
225
- | Roda | 20,964 | 12,265 | Puma | 1 | 3/38 |
226
- | Sinatra | 9,909 | 7,229 | Puma | 5 | 4/38 |
227
- | **Tina4 Ruby** | **8,139** | **6,427** | **WEBrick** | **0** | **38/38** |
228
- | Rails | 4,754 | 4,052 | Puma | 69 | 24/38 |
229
-
230
- **Tina4 Ruby on WEBrick is 1.7x faster than Rails on Puma** — with 38 features vs 24, zero deps vs 69.
231
-
232
- ---
233
-
234
- ## Dev vs Production — Tina4 All Frameworks (2026-03-21)
235
-
236
- | Framework | Dev Server | Dev JSON/s | Prod Server | Prod JSON/s | Prod List/s | Change |
237
- |-----------|-----------|:---------:|-------------|:---------:|:---------:|:------:|
238
- | **Tina4 PHP** | php -S | 27,299 | php + OPcache | **27,486** | **16,628** | ~same |
239
- | **Tina4 Ruby** | WEBrick | 8,139 | Puma | **22,784** | **12,504** | **2.8x ↑** |
240
- | **Tina4 Node.js** | http single | 57,035 | cluster (8 workers) | 12,488 | **16,958** | ↓ burst |
241
- | **Tina4 Python** | asyncio | 16,233 | uvicorn | 9,801 | 5,221 | ↓ burst |
242
-
243
- ### Key Insights
244
-
245
- 1. **Ruby benefits most from production server** — Puma's multi-threaded C-optimized HTTP parser gives 2.8x improvement over WEBrick
246
- 2. **PHP is already fast** — built-in `php -S` is surprisingly competitive; OPcache helps with complex apps but not simple JSON endpoints
247
- 3. **Python's asyncio server is faster than uvicorn for bursts** — our hand-rolled asyncio server has less overhead than uvicorn's libuv event loop for short-lived connections
248
- 4. **Node.js cluster adds IPC overhead** — for burst benchmarks on a single machine, the inter-process communication cost of 8 workers outweighs the parallelism benefit
249
-
250
- ### When production servers help
251
-
252
- Production servers excel under **sustained high concurrency** (thousands of simultaneous connections), **long-running requests** (database queries, file uploads), and **multi-core utilization** (real traffic from many clients). Burst benchmarks from a single client on localhost don't show these advantages.
253
-
254
- ### Recommendation
255
-
256
- - `tina4 serve` — for development (toolbar, reload, gallery)
257
- - `tina4 serve --production` — for deployment (auto-installs best server)
258
- - Production benchmarks should use sustained load tests (wrk2, k6) not burst tests (hey, ab)
package/CARBONAH.md DELETED
@@ -1,140 +0,0 @@
1
- # Carbonah Green Benchmark Report
2
-
3
- > Tina4 Node.js v3 — Test Results
4
- > Date: 2026-03-21
5
- > Rating: **A+**
6
-
7
- ---
8
-
9
- ## Summary
10
-
11
- | Metric | Value |
12
- |--------|-------|
13
- | Total Tests | 1,669 |
14
- | Passed | 1,669 |
15
- | Failed | 0 |
16
- | Errors | 0 |
17
- | Status | **PASS** |
18
-
19
- ---
20
-
21
- ## Per-Module Breakdown
22
-
23
- | Module | Tests | Status |
24
- |--------|-------|--------|
25
- | Integration (end-to-end) | 37 | PASS |
26
- | Smoke | 97 | PASS |
27
- | Router | 30 | PASS |
28
- | Auth | 45 | PASS |
29
- | ORM | 28 | PASS |
30
- | Database | 26 | PASS |
31
- | Migration | 27 | PASS |
32
- | Session | 30 | PASS |
33
- | Session Handlers | 18 | PASS |
34
- | Queue | 28 | PASS |
35
- | Queue Backends | 20 | PASS |
36
- | Swagger | 54 | PASS |
37
- | WSDL | 42 | PASS |
38
- | GraphQL | 36 | PASS |
39
- | WebSocket | 74 | PASS |
40
- | I18n | 18 | PASS |
41
- | FakeData/Seeder | 51 | PASS |
42
- | SCSS | 19 | PASS |
43
- | Frond | 130 | PASS |
44
- | Events | 39 | PASS |
45
- | AI | 30 | PASS |
46
- | Response | 47 | PASS |
47
- | SQL Translation | 54 | PASS |
48
- | HtmlElement | 24 | PASS |
49
- | Form Token | 19 | PASS |
50
- | Post Protection | 29 | PASS |
51
- | DotEnv | 19 | PASS |
52
- | CORS | 5 | PASS |
53
- | Rate Limiter | 8 | PASS |
54
- | Health | 6 | PASS |
55
- | Log | 13 | PASS |
56
- | Service Runner | 49 | PASS |
57
- | Messenger | 48 | PASS |
58
- | DevAdmin | 47 | PASS |
59
-
60
- ---
61
-
62
- ## Feature Parity
63
-
64
- 78/78 features implemented — 100% parity with Python, PHP, and Ruby.
65
-
66
- | Category | Features |
67
- |----------|----------|
68
- | Core | Router, Middleware, CORS, Rate Limiter, Health Check, DotEnv, Logging |
69
- | Database | Multi-driver abstraction, ORM, Migrations, Seeder/FakeData, SQL Translation |
70
- | Auth | JWT tokens, Password hashing, API key validation, POST protection, Form tokens |
71
- | API | Swagger/OpenAPI, GraphQL, WSDL/SOAP |
72
- | Templates | Frond (Twig-compatible), SCSS compilation, HtmlElement builder |
73
- | Communication | Queue (memory/RabbitMQ/Kafka), WebSocket, Messenger, Session (file/Redis/Mongo) |
74
- | Dev Tools | Error Overlay, DevAdmin, Hot reload (via Rust CLI), AI context scaffolding |
75
- | Architecture | Events (pub/sub), DI Container, Response Cache, Inline Testing, Service Runner |
76
- | I18n | Localization with JSON translation files |
77
-
78
- ---
79
-
80
- ## CO2 Report
81
-
82
- | Metric | Value |
83
- |--------|-------|
84
- | Test Execution Time | 18.00s |
85
- | CPU Time (user+sys) | ~12s (34 separate tsx processes) |
86
- | Peak Memory | ~64 MB |
87
- | Platform | Apple Silicon (ARM64) |
88
- | Estimated TDP | 15W |
89
- | Energy per Run | 0.0000750 kWh |
90
- | CO2 per Run (world avg 475g/kWh) | 0.038g CO2 |
91
- | CO2 per Test | 0.000030g CO2 |
92
- | Annual CI Estimate (10 runs/day) | 0.139g CO2/year |
93
- | Equivalent | ~0.7m of driving a car |
94
-
95
- ### Efficiency Metrics
96
-
97
- | Metric | Value |
98
- |--------|-------|
99
- | Tests per Second | 89.5 |
100
- | Tests per Watt-second | 5.97 |
101
- | Zero-dep Core | No unnecessary computation |
102
- | Note | Higher time due to 34 separate tsx process starts; single-process would be faster |
103
-
104
- ### Carbon Comparison (per full test suite run)
105
-
106
- | Framework | Time | CO2/Run | Tests/sec |
107
- |-----------|------|---------|-----------|
108
- | Python | 12.83s | 0.025g | 118.2 |
109
- | PHP | 8.25s | 0.017g | 152.1 |
110
- | Ruby | 6.86s | 0.014g | 221.0 |
111
- | Node.js | 18.00s | 0.038g | 89.5 |
112
- | **Total (6,183 tests)** | **45.94s** | **0.094g** | — |
113
-
114
- ---
115
-
116
- ## Carbonah Rating Criteria
117
-
118
- | Criterion | Score | Notes |
119
- |-----------|-------|-------|
120
- | Test Coverage | 1,669 tests | All passing |
121
- | Zero Dependencies | Core has no third-party deps | stdlib only |
122
- | Feature Parity | 78/78 | 100% cross-framework |
123
- | Code Quality | Clean, DRY, separation of concerns | Enforced via CLAUDE.md |
124
- | Documentation | CLAUDE.md + plan docs | Up to date |
125
-
126
- **Overall Rating: A+**
127
-
128
- ---
129
-
130
- ## How to Reproduce
131
-
132
- ```bash
133
- cd tina4-nodejs
134
- npm install
135
- for f in test/*.ts; do npx tsx "$f"; done
136
- ```
137
-
138
- ---
139
-
140
- *Generated by Tina4 v3 CI — https://tina4.com*
package/COMPARISON.md DELETED
@@ -1,206 +0,0 @@
1
- # Tina4 v3 — Framework Feature & Performance Report
2
-
3
- **Date:** 2026-03-21 | **Goal:** Outperform the competition on features and close the performance gap
4
-
5
- ---
6
-
7
- ## Performance Benchmarks
8
-
9
- ### Python — Tina4 vs Competition
10
-
11
- Real HTTP benchmarks — identical JSON endpoint, 5000 requests, 50 concurrent.
12
-
13
- | Framework | JSON req/s | 100-item list req/s | Server | Deps |
14
- |-----------|:---------:|:-------------------:|--------|:----:|
15
- | **Tina4 Python 3.0** | **16,233** | **5,858** | **built-in** | **0** |
16
- | Starlette 0.52 | 15,978 | 7,493 | uvicorn (C) | 4 |
17
- | FastAPI 0.115 | 11,886 | 2,464 | uvicorn (C) | 12+ |
18
- | Flask 3.1 | 4,767 | 1,644 | Werkzeug | 6 |
19
- | Django 5.2 | 3,747 | 3,305 | runserver | 20+ |
20
- | Bottle 0.13 | 1,251 | 676 | built-in | 0 |
21
-
22
- ### PHP — Tina4 vs Competition
23
-
24
- Real HTTP benchmarks — identical JSON endpoint, 5000 requests, 50 concurrent.
25
-
26
- | Framework | JSON req/s | 100-item list req/s | Server | Deps |
27
- |-----------|:---------:|:-------------------:|--------|:----:|
28
- | **Tina4 PHP 3.0** | **27,299** | **16,555** | **built-in** | **0** |
29
- | Slim 4 | 5,033 | 4,520 | built-in | 10+ |
30
- | Symfony 7 | 1,840 | 1,702 | built-in | 30+ |
31
- | Laravel 11 | 370 | 364 | artisan | 50+ |
32
-
33
- ### Ruby — Tina4 vs Competition
34
-
35
- Real HTTP benchmarks — identical JSON endpoint, 5000 requests, 50 concurrent.
36
-
37
- | Framework | JSON req/s | 100-item list req/s | Server | Deps |
38
- |-----------|:---------:|:-------------------:|--------|:----:|
39
- | Roda | 20,964 | 12,265 | Puma | 1 |
40
- | Sinatra | 9,909 | 7,229 | Puma | 5 |
41
- | **Tina4 Ruby 3.0** | **9,504** | **7,648** | **WEBrick** | **0** |
42
- | Rails 7 | 4,754 | 4,052 | Puma | 69 |
43
-
44
- ### Node.js — Tina4 vs Competition
45
-
46
- Real HTTP benchmarks — identical JSON endpoint, 5000 requests, 50 concurrent.
47
-
48
- | Framework | JSON req/s | 100-item list req/s | Server | Deps |
49
- |-----------|:---------:|:-------------------:|--------|:----:|
50
- | Node.js raw http | 86,662 | 24,598 | http | 0 |
51
- | Fastify | 79,505 | 23,395 | http | 10+ |
52
- | Koa | 60,400 | 23,433 | http | 5 |
53
- | **Tina4 Node.js 3.0** | **57,035** | **25,088** | **http** | **0** |
54
- | Express 5 | 56,687 | 20,720 | http | 3 |
55
-
56
- ### Production Server Results
57
-
58
- | Framework | Dev Server | Dev JSON/s | Prod Server | Prod JSON/s | Change |
59
- |-----------|-----------|:---------:|-------------|:---------:|:------:|
60
- | **Tina4 PHP** | php -S | 27,299 | php + OPcache | **27,486** | ~same |
61
- | **Tina4 Ruby** | WEBrick | 8,139 | Puma | **22,784** | **2.8x** |
62
- | **Tina4 Node.js** | http single | 57,035 | cluster (8 workers) | 12,488 | see note |
63
- | **Tina4 Python** | asyncio | 16,233 | uvicorn | 9,801 | see note |
64
-
65
- Note: Production servers excel under sustained high concurrency. Burst benchmarks from localhost don't show their full advantage.
66
-
67
- ---
68
-
69
- ## Out-of-Box Feature Comparison (38 features)
70
-
71
- ✅ = ships with core install, no extra packages | ❌ = requires additional install
72
-
73
- ### Python Frameworks
74
-
75
- | Feature | Tina4 | Flask | FastAPI | Django | Starlette | Bottle |
76
- |---------|:-----:|:-----:|:-------:|:------:|:---------:|:------:|
77
- | **CORE WEB** | | | | | | |
78
- | Routing (decorators) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
79
- | Typed path parameters | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
80
- | Middleware system | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
81
- | Static file serving | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
82
- | CORS built-in | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
83
- | Rate limiting | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
84
- | WebSocket | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
85
- | **DATA** | | | | | | |
86
- | ORM | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
87
- | 5 database drivers | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
88
- | Migrations | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
89
- | Seeder / fake data | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
90
- | Sessions | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ |
91
- | Response caching | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
92
- | **AUTH** | | | | | | |
93
- | JWT built-in | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
94
- | Password hashing | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
95
- | CSRF protection | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
96
- | **FRONTEND** | | | | | | |
97
- | Template engine | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ |
98
- | CSS framework | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
99
- | SCSS compiler | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
100
- | Frontend JS helpers | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
101
- | **API** | | | | | | |
102
- | Swagger/OpenAPI | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
103
- | GraphQL | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
104
- | SOAP/WSDL | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
105
- | HTTP client | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
106
- | Queue system | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
107
- | **DEV EXPERIENCE** | | | | | | |
108
- | CLI scaffolding | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
109
- | Dev admin dashboard | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
110
- | Error overlay | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ |
111
- | Live reload | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
112
- | Auto-CRUD generator | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
113
- | Gallery / examples | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
114
- | AI assistant context | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
115
- | Inline testing | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
116
- | **ARCHITECTURE** | | | | | | |
117
- | Zero dependencies | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
118
- | Dependency injection | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
119
- | Event system | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ |
120
- | i18n / translations | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
121
- | HTML builder | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
122
-
123
- ### Feature Count — Python
124
-
125
- | Framework | Features | Deps | JSON req/s |
126
- |-----------|:-------:|:----:|:---------:|
127
- | **Tina4** | **38/38** | **0** | **16,233** |
128
- | Django | 22/38 | 20+ | 3,747 |
129
- | Flask | 7/38 | 6 | 4,767 |
130
- | FastAPI | 8/38 | 12+ | 11,886 |
131
- | Starlette | 6/38 | 4 | 15,978 |
132
- | Bottle | 5/38 | 0 | 1,251 |
133
-
134
- ### Cross-Language Feature Count
135
-
136
- | Framework | Language | Features | Deps |
137
- |-----------|---------|:-------:|:----:|
138
- | **Tina4** | Python/PHP/Ruby/Node.js | **38/38** | **0** |
139
- | Laravel | PHP | 25/38 | 50+ |
140
- | Rails | Ruby | 24/38 | 40+ |
141
- | Django | Python | 22/38 | 20+ |
142
- | NestJS | Node.js | 16/38 | 20+ |
143
- | FastAPI | Python | 8/38 | 12+ |
144
- | Flask | Python | 7/38 | 6 |
145
- | Starlette | Python | 6/38 | 4 |
146
- | Bottle | Python | 5/38 | 0 |
147
- | Express | Node.js | 4/38 | 3 |
148
- | Sinatra | Ruby | 4/38 | 5 |
149
-
150
- ---
151
-
152
- ## Tina4 Performance Roadmap
153
-
154
- ### v3.0 — Achieved
155
- - [x] Pre-compile Frond templates (2.8x render improvement)
156
- - [x] Production server auto-detection (uvicorn/Puma/cluster)
157
- - [x] DB query caching (TINA4_DB_CACHE=true, 4x speedup)
158
- - [x] ORM relationships with eager loading
159
-
160
- ### v3.1 — Next
161
- - [ ] Compiled template bytecode (match Jinja2 speed)
162
- - [ ] Connection pooling for database adapters
163
- - [ ] HTTP/2 support in built-in server
164
- - [ ] Response streaming for large payloads
165
-
166
- ### v3.2 — Future
167
- - [ ] HTTP/3 (QUIC) support
168
- - [ ] gRPC built-in
169
- - [ ] Edge runtime support (Cloudflare Workers, Deno Deploy)
170
-
171
- ---
172
-
173
- ## Deployment Size
174
-
175
- | Framework | Core Size | With Deps | Competitors |
176
- |-----------|:---------:|:---------:|------------|
177
- | Tina4 Python | ~2.4 MB | 2.4 MB (0 deps) | Django 25 MB, Flask 4.2 MB |
178
- | Tina4 PHP | ~1.0 MB | 1.0 MB (0 deps) | Laravel 50+ MB, Symfony 30+ MB |
179
- | Tina4 Ruby | ~892 KB | 892 KB (0 deps) | Rails 40+ MB, Sinatra 5 MB |
180
- | Tina4 Node.js | ~1.8 MB | 1.8 MB (0 deps) | Express 2 MB, NestJS 20+ MB |
181
-
182
- Zero dependencies means core size **is** deployment size. No `node_modules` bloat, no `vendor/` sprawl, no `site-packages` explosion.
183
-
184
- ---
185
-
186
- ## Cross-Platform Support
187
-
188
- All 4 Tina4 frameworks run on:
189
-
190
- - **macOS** (Intel + Apple Silicon)
191
- - **Linux** (x86_64 + ARM64)
192
- - **Windows** (10/11)
193
- - **Docker** (any base image with the language runtime)
194
- - **WSL2**
195
-
196
- No C extensions, no native binaries, no compile step required. Pure Python/PHP/Ruby/JavaScript.
197
-
198
- ---
199
-
200
- ## Notes
201
-
202
- - Performance numbers are from `hey` benchmarks (5000 requests, 50 concurrent) on Apple M3
203
- - Production server results included: `tina4 serve --production` auto-installs the best server per language
204
- - Tina4's competitive advantage is **features per dependency** — 38 features with 0 deps
205
- - Total test suite: **6,183 tests** across all 4 languages (Python 1633, PHP 1304, Ruby 1577, Node.js 1669)
206
- - The zero-dep philosophy means Tina4 works anywhere Python/PHP/Ruby/Node.js runs — no compiler needed, no native extensions, no build step