tina4-nodejs 3.10.68 → 3.10.70
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 +5 -3
- package/package.json +1 -1
- package/packages/core/src/response.ts +34 -0
- package/packages/core/src/types.ts +2 -0
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.70)
|
|
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.70 — The Intelligent Native Application 4ramework. A convention-over-configuration structural paradigm. 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
|
|
|
@@ -240,6 +240,7 @@ req.cookies: Record<string, string> // parsed from Cookie header
|
|
|
240
240
|
req.contentType: string // from content-type header
|
|
241
241
|
req.query: Record<string, string> // query string params
|
|
242
242
|
response.xml(content, status?): Tina4Response
|
|
243
|
+
response.stream(generator, contentType?: string, status?: number): void // SSE/streaming
|
|
243
244
|
```
|
|
244
245
|
|
|
245
246
|
### Queue
|
|
@@ -677,7 +678,7 @@ When adding new features, add a corresponding `test/<feature>.test.ts` file.
|
|
|
677
678
|
|
|
678
679
|
## v3 Features Summary
|
|
679
680
|
|
|
680
|
-
- **
|
|
681
|
+
- **45 built-in features**, zero third-party dependencies
|
|
681
682
|
- **1,812 tests** passing across all modules
|
|
682
683
|
- **Race-safe `getNextId()`** with atomic sequence table (`tina4_sequences`) for SQLite/MySQL/MSSQL; PostgreSQL auto-creates sequences
|
|
683
684
|
- **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)
|
|
@@ -695,6 +696,7 @@ When adding new features, add a corresponding `test/<feature>.test.ts` file.
|
|
|
695
696
|
- **SameSite=Lax** default on session cookies (`TINA4_SESSION_SAMESITE`)
|
|
696
697
|
- **`tina4 init`** generates Dockerfile and .dockerignore
|
|
697
698
|
- **Gallery**: 7 interactive examples with Try It deploy at `/_dev/`
|
|
699
|
+
- **SSE/Streaming**: `response.stream()` for Server-Sent Events — pass an async generator, framework handles chunked transfer encoding and keep-alive
|
|
698
700
|
|
|
699
701
|
## Don'ts
|
|
700
702
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tina4-nodejs",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.70",
|
|
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"],
|
|
@@ -242,6 +242,40 @@ export function createResponse(res: ServerResponse): Tina4Response {
|
|
|
242
242
|
return response.render(name, data, status, templateDir);
|
|
243
243
|
};
|
|
244
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Stream response from an async generator for Server-Sent Events (SSE).
|
|
247
|
+
*
|
|
248
|
+
* Usage:
|
|
249
|
+
* export default async function (req, res) {
|
|
250
|
+
* res.stream(async function* () {
|
|
251
|
+
* for (let i = 0; i < 10; i++) {
|
|
252
|
+
* yield `data: message ${i}\n\n`;
|
|
253
|
+
* await new Promise(r => setTimeout(r, 1000));
|
|
254
|
+
* }
|
|
255
|
+
* }());
|
|
256
|
+
* }
|
|
257
|
+
*/
|
|
258
|
+
(response as any).stream = async function (
|
|
259
|
+
source: AsyncIterable<string | Buffer>,
|
|
260
|
+
contentType: string = "text/event-stream",
|
|
261
|
+
): Promise<Tina4Response> {
|
|
262
|
+
if (res.headersSent) return response;
|
|
263
|
+
res.writeHead(200, {
|
|
264
|
+
"Content-Type": contentType,
|
|
265
|
+
"Cache-Control": "no-cache",
|
|
266
|
+
"Connection": "keep-alive",
|
|
267
|
+
"X-Accel-Buffering": "no",
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
for await (const chunk of source) {
|
|
271
|
+
const data = typeof chunk === "string" ? chunk : chunk.toString();
|
|
272
|
+
res.write(data);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
res.end();
|
|
276
|
+
return response;
|
|
277
|
+
};
|
|
278
|
+
|
|
245
279
|
return response;
|
|
246
280
|
}
|
|
247
281
|
|
|
@@ -54,6 +54,8 @@ export interface Tina4ResponseMethods {
|
|
|
54
54
|
error(code: string, message: string, status?: number): Tina4Response;
|
|
55
55
|
render(template: string, data?: Record<string, unknown>, status?: number, templateDir?: string): Promise<Tina4Response>;
|
|
56
56
|
template(name: string, data?: Record<string, unknown>, status?: number, templateDir?: string): Promise<Tina4Response>;
|
|
57
|
+
/** Stream response from an async generator (SSE or chunked). */
|
|
58
|
+
stream(source: AsyncIterable<string | Buffer>, contentType?: string): Promise<Tina4Response>;
|
|
57
59
|
/** The underlying ServerResponse for advanced use */
|
|
58
60
|
raw: ServerResponse;
|
|
59
61
|
}
|