tina4-nodejs 3.13.108 → 3.13.109
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 +2 -2
- package/package.json +1 -1
- package/packages/cli/dist/bin.js +28 -6
- package/packages/core/dist/index.js +28 -6
- package/packages/core/src/cache.ts +64 -11
- package/packages/orm/dist/index.js +28 -6
package/CLAUDE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# CLAUDE.md - AI Developer Guide for tina4-nodejs (v3.13.
|
|
1
|
+
# CLAUDE.md - AI Developer Guide for tina4-nodejs (v3.13.109)
|
|
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.13.
|
|
7
|
+
Tina4 for Node.js/TypeScript v3.13.109 - 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
|
|
package/package.json
CHANGED
package/packages/cli/dist/bin.js
CHANGED
|
@@ -17767,11 +17767,32 @@ function varyFields(raw) {
|
|
|
17767
17767
|
const text = Array.isArray(raw) ? raw.join(",") : String(raw);
|
|
17768
17768
|
return text.split(",").map((f) => f.trim().toLowerCase()).filter((f) => f !== "");
|
|
17769
17769
|
}
|
|
17770
|
-
function
|
|
17770
|
+
function cacheControlTokens(raw) {
|
|
17771
|
+
const text = Array.isArray(raw) ? raw.join(",") : String(raw ?? "");
|
|
17772
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
17773
|
+
for (const token of text.split(",")) {
|
|
17774
|
+
const name = token.split("=")[0].trim().toLowerCase();
|
|
17775
|
+
if (name !== "") tokens.add(name);
|
|
17776
|
+
}
|
|
17777
|
+
return tokens;
|
|
17778
|
+
}
|
|
17779
|
+
function sharedCacheAllowed(cacheControl) {
|
|
17780
|
+
const directives = cacheControlTokens(cacheControl);
|
|
17781
|
+
return SHARED_CACHE_DIRECTIVES.some((directive) => directives.has(directive));
|
|
17782
|
+
}
|
|
17783
|
+
function hasSetCookie(raw) {
|
|
17784
|
+
if (raw === void 0 || raw === null) return false;
|
|
17785
|
+
if (Array.isArray(raw)) return raw.length > 0;
|
|
17786
|
+
return String(raw) !== "";
|
|
17787
|
+
}
|
|
17788
|
+
function mayStore(req2, vary, cacheControl, setCookie) {
|
|
17771
17789
|
if (vary.includes("*")) return false;
|
|
17772
|
-
|
|
17773
|
-
|
|
17774
|
-
|
|
17790
|
+
const directives = cacheControlTokens(cacheControl);
|
|
17791
|
+
if (NO_STORE_DIRECTIVES.some((directive) => directives.has(directive))) return false;
|
|
17792
|
+
if (requestHeader(req2, "authorization") !== void 0) return sharedCacheAllowed(cacheControl);
|
|
17793
|
+
if (requestHeader(req2, "cookie") !== void 0) return sharedCacheAllowed(cacheControl);
|
|
17794
|
+
if (hasSetCookie(setCookie)) return sharedCacheAllowed(cacheControl);
|
|
17795
|
+
return true;
|
|
17775
17796
|
}
|
|
17776
17797
|
function varyMatches(entry, req2) {
|
|
17777
17798
|
const vary = entry.vary ?? [];
|
|
@@ -17804,7 +17825,7 @@ function responseCache(config) {
|
|
|
17804
17825
|
let captured = false;
|
|
17805
17826
|
res.raw.end = function(chunk, ...args) {
|
|
17806
17827
|
const vary = varyFields(res.raw.getHeader("Vary"));
|
|
17807
|
-
if (!captured && allowedCodes.has(res.raw.statusCode) && mayStore(req2, vary, res.raw.getHeader("Cache-Control"))) {
|
|
17828
|
+
if (!captured && allowedCodes.has(res.raw.statusCode) && mayStore(req2, vary, res.raw.getHeader("Cache-Control"), res.raw.getHeader("Set-Cookie"))) {
|
|
17808
17829
|
captured = true;
|
|
17809
17830
|
const body = typeof chunk === "string" ? chunk : chunk?.toString() ?? "";
|
|
17810
17831
|
const contentType = String(res.raw.getHeader("Content-Type") ?? "application/octet-stream");
|
|
@@ -17891,7 +17912,7 @@ function _resetBackend() {
|
|
|
17891
17912
|
_explicitResponseBackends.clear();
|
|
17892
17913
|
_defaultTtl = null;
|
|
17893
17914
|
}
|
|
17894
|
-
var MemoryBackend, RespClient, RedisBackend, ValkeyBackend, FileBackend, MemcachedClient, MemcachedBackend, MongoBackend, DatabaseBackend, _responseBackend, _responseBackendPromise, _explicitResponseBackends, SHARED_CACHE_DIRECTIVES, _defaultBackend, _defaultBackendPromise, _defaultTtl;
|
|
17915
|
+
var MemoryBackend, RespClient, RedisBackend, ValkeyBackend, FileBackend, MemcachedClient, MemcachedBackend, MongoBackend, DatabaseBackend, _responseBackend, _responseBackendPromise, _explicitResponseBackends, SHARED_CACHE_DIRECTIVES, NO_STORE_DIRECTIVES, _defaultBackend, _defaultBackendPromise, _defaultTtl;
|
|
17895
17916
|
var init_cache = __esm({
|
|
17896
17917
|
"../core/src/cache.ts"() {
|
|
17897
17918
|
"use strict";
|
|
@@ -19057,6 +19078,7 @@ ${data}\r
|
|
|
19057
19078
|
_responseBackendPromise = null;
|
|
19058
19079
|
_explicitResponseBackends = /* @__PURE__ */ new Map();
|
|
19059
19080
|
SHARED_CACHE_DIRECTIVES = ["public", "s-maxage", "must-revalidate"];
|
|
19081
|
+
NO_STORE_DIRECTIVES = ["no-store", "private", "no-cache"];
|
|
19060
19082
|
_defaultBackend = null;
|
|
19061
19083
|
_defaultBackendPromise = null;
|
|
19062
19084
|
_defaultTtl = null;
|
|
@@ -17766,11 +17766,32 @@ function varyFields(raw) {
|
|
|
17766
17766
|
const text = Array.isArray(raw) ? raw.join(",") : String(raw);
|
|
17767
17767
|
return text.split(",").map((f) => f.trim().toLowerCase()).filter((f) => f !== "");
|
|
17768
17768
|
}
|
|
17769
|
-
function
|
|
17769
|
+
function cacheControlTokens(raw) {
|
|
17770
|
+
const text = Array.isArray(raw) ? raw.join(",") : String(raw ?? "");
|
|
17771
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
17772
|
+
for (const token of text.split(",")) {
|
|
17773
|
+
const name = token.split("=")[0].trim().toLowerCase();
|
|
17774
|
+
if (name !== "") tokens.add(name);
|
|
17775
|
+
}
|
|
17776
|
+
return tokens;
|
|
17777
|
+
}
|
|
17778
|
+
function sharedCacheAllowed(cacheControl) {
|
|
17779
|
+
const directives = cacheControlTokens(cacheControl);
|
|
17780
|
+
return SHARED_CACHE_DIRECTIVES.some((directive) => directives.has(directive));
|
|
17781
|
+
}
|
|
17782
|
+
function hasSetCookie(raw) {
|
|
17783
|
+
if (raw === void 0 || raw === null) return false;
|
|
17784
|
+
if (Array.isArray(raw)) return raw.length > 0;
|
|
17785
|
+
return String(raw) !== "";
|
|
17786
|
+
}
|
|
17787
|
+
function mayStore(req2, vary, cacheControl, setCookie) {
|
|
17770
17788
|
if (vary.includes("*")) return false;
|
|
17771
|
-
|
|
17772
|
-
|
|
17773
|
-
|
|
17789
|
+
const directives = cacheControlTokens(cacheControl);
|
|
17790
|
+
if (NO_STORE_DIRECTIVES.some((directive) => directives.has(directive))) return false;
|
|
17791
|
+
if (requestHeader(req2, "authorization") !== void 0) return sharedCacheAllowed(cacheControl);
|
|
17792
|
+
if (requestHeader(req2, "cookie") !== void 0) return sharedCacheAllowed(cacheControl);
|
|
17793
|
+
if (hasSetCookie(setCookie)) return sharedCacheAllowed(cacheControl);
|
|
17794
|
+
return true;
|
|
17774
17795
|
}
|
|
17775
17796
|
function varyMatches(entry, req2) {
|
|
17776
17797
|
const vary = entry.vary ?? [];
|
|
@@ -17803,7 +17824,7 @@ function responseCache(config) {
|
|
|
17803
17824
|
let captured = false;
|
|
17804
17825
|
res.raw.end = function(chunk, ...args) {
|
|
17805
17826
|
const vary = varyFields(res.raw.getHeader("Vary"));
|
|
17806
|
-
if (!captured && allowedCodes.has(res.raw.statusCode) && mayStore(req2, vary, res.raw.getHeader("Cache-Control"))) {
|
|
17827
|
+
if (!captured && allowedCodes.has(res.raw.statusCode) && mayStore(req2, vary, res.raw.getHeader("Cache-Control"), res.raw.getHeader("Set-Cookie"))) {
|
|
17807
17828
|
captured = true;
|
|
17808
17829
|
const body = typeof chunk === "string" ? chunk : chunk?.toString() ?? "";
|
|
17809
17830
|
const contentType = String(res.raw.getHeader("Content-Type") ?? "application/octet-stream");
|
|
@@ -17890,7 +17911,7 @@ function _resetBackend() {
|
|
|
17890
17911
|
_explicitResponseBackends.clear();
|
|
17891
17912
|
_defaultTtl = null;
|
|
17892
17913
|
}
|
|
17893
|
-
var MemoryBackend, RespClient, RedisBackend, ValkeyBackend, FileBackend, MemcachedClient, MemcachedBackend, MongoBackend, DatabaseBackend, _responseBackend, _responseBackendPromise, _explicitResponseBackends, SHARED_CACHE_DIRECTIVES, _defaultBackend, _defaultBackendPromise, _defaultTtl;
|
|
17914
|
+
var MemoryBackend, RespClient, RedisBackend, ValkeyBackend, FileBackend, MemcachedClient, MemcachedBackend, MongoBackend, DatabaseBackend, _responseBackend, _responseBackendPromise, _explicitResponseBackends, SHARED_CACHE_DIRECTIVES, NO_STORE_DIRECTIVES, _defaultBackend, _defaultBackendPromise, _defaultTtl;
|
|
17894
17915
|
var init_cache = __esm({
|
|
17895
17916
|
"src/cache.ts"() {
|
|
17896
17917
|
"use strict";
|
|
@@ -19056,6 +19077,7 @@ ${data}\r
|
|
|
19056
19077
|
_responseBackendPromise = null;
|
|
19057
19078
|
_explicitResponseBackends = /* @__PURE__ */ new Map();
|
|
19058
19079
|
SHARED_CACHE_DIRECTIVES = ["public", "s-maxage", "must-revalidate"];
|
|
19080
|
+
NO_STORE_DIRECTIVES = ["no-store", "private", "no-cache"];
|
|
19059
19081
|
_defaultBackend = null;
|
|
19060
19082
|
_defaultBackendPromise = null;
|
|
19061
19083
|
_defaultTtl = null;
|
|
@@ -1629,6 +1629,14 @@ export function _getResponseBackend(config?: ResponseCacheConfig): Promise<Cache
|
|
|
1629
1629
|
*/
|
|
1630
1630
|
const SHARED_CACHE_DIRECTIVES = ["public", "s-maxage", "must-revalidate"];
|
|
1631
1631
|
|
|
1632
|
+
/**
|
|
1633
|
+
* Response directives that forbid storing the response here (RFC 9111 s3):
|
|
1634
|
+
* `no-store` forbids storage in any cache, `private` and `no-cache` in a shared
|
|
1635
|
+
* one. Before this was honoured a handler had no way to keep a response out of
|
|
1636
|
+
* the cache — setting the correct standard header did nothing.
|
|
1637
|
+
*/
|
|
1638
|
+
const NO_STORE_DIRECTIVES = ["no-store", "private", "no-cache"];
|
|
1639
|
+
|
|
1632
1640
|
/** Case-insensitive request header lookup. */
|
|
1633
1641
|
function requestHeader(req: { headers?: Record<string, unknown> }, name: string): string | undefined {
|
|
1634
1642
|
const headers = req?.headers;
|
|
@@ -1650,22 +1658,67 @@ function varyFields(raw: unknown): string[] {
|
|
|
1650
1658
|
}
|
|
1651
1659
|
|
|
1652
1660
|
/**
|
|
1653
|
-
*
|
|
1661
|
+
* The lower-cased Cache-Control directive NAMES on a header value, as a set.
|
|
1654
1662
|
*
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1657
|
-
*
|
|
1658
|
-
|
|
1659
|
-
|
|
1663
|
+
* Parsed as comma-separated tokens with any `=value` stripped, rather than by
|
|
1664
|
+
* substring search, so `no-cache="Set-Cookie"` is recognised as `no-cache` and
|
|
1665
|
+
* a directive name never matches as a fragment of a longer one.
|
|
1666
|
+
*/
|
|
1667
|
+
function cacheControlTokens(raw: unknown): Set<string> {
|
|
1668
|
+
const text = Array.isArray(raw) ? raw.join(",") : String(raw ?? "");
|
|
1669
|
+
const tokens = new Set<string>();
|
|
1670
|
+
for (const token of text.split(",")) {
|
|
1671
|
+
const name = token.split("=")[0].trim().toLowerCase();
|
|
1672
|
+
if (name !== "") tokens.add(name);
|
|
1673
|
+
}
|
|
1674
|
+
return tokens;
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
/** Does the response Cache-Control carry a directive that lets a SHARED cache store it? */
|
|
1678
|
+
function sharedCacheAllowed(cacheControl: unknown): boolean {
|
|
1679
|
+
const directives = cacheControlTokens(cacheControl);
|
|
1680
|
+
return SHARED_CACHE_DIRECTIVES.some((directive) => directives.has(directive));
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
/** Is a Set-Cookie response header present? Any non-empty value (it may be an array). */
|
|
1684
|
+
function hasSetCookie(raw: unknown): boolean {
|
|
1685
|
+
if (raw === undefined || raw === null) return false;
|
|
1686
|
+
if (Array.isArray(raw)) return raw.length > 0;
|
|
1687
|
+
return String(raw) !== "";
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* May a SHARED cache store this response? (RFC 9111 s3, s4.1)
|
|
1660
1692
|
*
|
|
1661
1693
|
* s4.1 — a stored response whose Vary contains "*" "always fails to match", so
|
|
1662
1694
|
* storing one is pointless.
|
|
1695
|
+
*
|
|
1696
|
+
* s3 — a shared cache may store a response only when it is not marked
|
|
1697
|
+
* un-storable and is not built for one specific caller:
|
|
1698
|
+
*
|
|
1699
|
+
* - `no-store`/`private`/`no-cache` on the response forbid storing it here, so a
|
|
1700
|
+
* handler can always opt a body out of the cache with the standard header.
|
|
1701
|
+
* - The key is method + URL only, and on Node the cache answers BEFORE the auth
|
|
1702
|
+
* gate, so a response built for one caller replays to whoever asks for that URL
|
|
1703
|
+
* next. Authorization marks such a caller — and so does a session Cookie on the
|
|
1704
|
+
* request (Tina4's own session mechanism IS a cookie), and a Set-Cookie on the
|
|
1705
|
+
* response (it installs a per-caller session). All three are storable only when
|
|
1706
|
+
* the response opts in with an explicit shared-cache directive, which keeps a
|
|
1707
|
+
* genuinely public page cacheable for cookie-bearing browsers.
|
|
1663
1708
|
*/
|
|
1664
|
-
function mayStore(
|
|
1709
|
+
function mayStore(
|
|
1710
|
+
req: { headers?: Record<string, unknown> },
|
|
1711
|
+
vary: string[],
|
|
1712
|
+
cacheControl: unknown,
|
|
1713
|
+
setCookie: unknown,
|
|
1714
|
+
): boolean {
|
|
1665
1715
|
if (vary.includes("*")) return false;
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1716
|
+
const directives = cacheControlTokens(cacheControl);
|
|
1717
|
+
if (NO_STORE_DIRECTIVES.some((directive) => directives.has(directive))) return false;
|
|
1718
|
+
if (requestHeader(req, "authorization") !== undefined) return sharedCacheAllowed(cacheControl);
|
|
1719
|
+
if (requestHeader(req, "cookie") !== undefined) return sharedCacheAllowed(cacheControl);
|
|
1720
|
+
if (hasSetCookie(setCookie)) return sharedCacheAllowed(cacheControl);
|
|
1721
|
+
return true;
|
|
1669
1722
|
}
|
|
1670
1723
|
|
|
1671
1724
|
/**
|
|
@@ -1722,7 +1775,7 @@ export function responseCache(config?: ResponseCacheConfig): Middleware {
|
|
|
1722
1775
|
res.raw.end = function (chunk?: any, ...args: any[]) {
|
|
1723
1776
|
const vary = varyFields(res.raw.getHeader("Vary"));
|
|
1724
1777
|
if (!captured && allowedCodes.has(res.raw.statusCode)
|
|
1725
|
-
&& mayStore(req as any, vary, res.raw.getHeader("Cache-Control"))) {
|
|
1778
|
+
&& mayStore(req as any, vary, res.raw.getHeader("Cache-Control"), res.raw.getHeader("Set-Cookie"))) {
|
|
1726
1779
|
captured = true;
|
|
1727
1780
|
const body = typeof chunk === "string" ? chunk : chunk?.toString() ?? "";
|
|
1728
1781
|
const contentType = String(res.raw.getHeader("Content-Type") ?? "application/octet-stream");
|
|
@@ -6909,11 +6909,32 @@ function varyFields(raw) {
|
|
|
6909
6909
|
const text = Array.isArray(raw) ? raw.join(",") : String(raw);
|
|
6910
6910
|
return text.split(",").map((f) => f.trim().toLowerCase()).filter((f) => f !== "");
|
|
6911
6911
|
}
|
|
6912
|
-
function
|
|
6912
|
+
function cacheControlTokens(raw) {
|
|
6913
|
+
const text = Array.isArray(raw) ? raw.join(",") : String(raw ?? "");
|
|
6914
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
6915
|
+
for (const token of text.split(",")) {
|
|
6916
|
+
const name = token.split("=")[0].trim().toLowerCase();
|
|
6917
|
+
if (name !== "") tokens.add(name);
|
|
6918
|
+
}
|
|
6919
|
+
return tokens;
|
|
6920
|
+
}
|
|
6921
|
+
function sharedCacheAllowed(cacheControl) {
|
|
6922
|
+
const directives = cacheControlTokens(cacheControl);
|
|
6923
|
+
return SHARED_CACHE_DIRECTIVES.some((directive) => directives.has(directive));
|
|
6924
|
+
}
|
|
6925
|
+
function hasSetCookie(raw) {
|
|
6926
|
+
if (raw === void 0 || raw === null) return false;
|
|
6927
|
+
if (Array.isArray(raw)) return raw.length > 0;
|
|
6928
|
+
return String(raw) !== "";
|
|
6929
|
+
}
|
|
6930
|
+
function mayStore(req2, vary, cacheControl, setCookie) {
|
|
6913
6931
|
if (vary.includes("*")) return false;
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6932
|
+
const directives = cacheControlTokens(cacheControl);
|
|
6933
|
+
if (NO_STORE_DIRECTIVES.some((directive) => directives.has(directive))) return false;
|
|
6934
|
+
if (requestHeader(req2, "authorization") !== void 0) return sharedCacheAllowed(cacheControl);
|
|
6935
|
+
if (requestHeader(req2, "cookie") !== void 0) return sharedCacheAllowed(cacheControl);
|
|
6936
|
+
if (hasSetCookie(setCookie)) return sharedCacheAllowed(cacheControl);
|
|
6937
|
+
return true;
|
|
6917
6938
|
}
|
|
6918
6939
|
function varyMatches(entry, req2) {
|
|
6919
6940
|
const vary = entry.vary ?? [];
|
|
@@ -6946,7 +6967,7 @@ function responseCache(config) {
|
|
|
6946
6967
|
let captured = false;
|
|
6947
6968
|
res.raw.end = function(chunk, ...args) {
|
|
6948
6969
|
const vary = varyFields(res.raw.getHeader("Vary"));
|
|
6949
|
-
if (!captured && allowedCodes.has(res.raw.statusCode) && mayStore(req2, vary, res.raw.getHeader("Cache-Control"))) {
|
|
6970
|
+
if (!captured && allowedCodes.has(res.raw.statusCode) && mayStore(req2, vary, res.raw.getHeader("Cache-Control"), res.raw.getHeader("Set-Cookie"))) {
|
|
6950
6971
|
captured = true;
|
|
6951
6972
|
const body = typeof chunk === "string" ? chunk : chunk?.toString() ?? "";
|
|
6952
6973
|
const contentType = String(res.raw.getHeader("Content-Type") ?? "application/octet-stream");
|
|
@@ -7033,7 +7054,7 @@ function _resetBackend() {
|
|
|
7033
7054
|
_explicitResponseBackends.clear();
|
|
7034
7055
|
_defaultTtl = null;
|
|
7035
7056
|
}
|
|
7036
|
-
var MemoryBackend, RespClient, RedisBackend, ValkeyBackend, FileBackend, MemcachedClient, MemcachedBackend, MongoBackend, DatabaseBackend, _responseBackend, _responseBackendPromise, _explicitResponseBackends, SHARED_CACHE_DIRECTIVES, _defaultBackend, _defaultBackendPromise, _defaultTtl;
|
|
7057
|
+
var MemoryBackend, RespClient, RedisBackend, ValkeyBackend, FileBackend, MemcachedClient, MemcachedBackend, MongoBackend, DatabaseBackend, _responseBackend, _responseBackendPromise, _explicitResponseBackends, SHARED_CACHE_DIRECTIVES, NO_STORE_DIRECTIVES, _defaultBackend, _defaultBackendPromise, _defaultTtl;
|
|
7037
7058
|
var init_cache = __esm({
|
|
7038
7059
|
"../core/src/cache.ts"() {
|
|
7039
7060
|
"use strict";
|
|
@@ -8199,6 +8220,7 @@ ${data}\r
|
|
|
8199
8220
|
_responseBackendPromise = null;
|
|
8200
8221
|
_explicitResponseBackends = /* @__PURE__ */ new Map();
|
|
8201
8222
|
SHARED_CACHE_DIRECTIVES = ["public", "s-maxage", "must-revalidate"];
|
|
8223
|
+
NO_STORE_DIRECTIVES = ["no-store", "private", "no-cache"];
|
|
8202
8224
|
_defaultBackend = null;
|
|
8203
8225
|
_defaultBackendPromise = null;
|
|
8204
8226
|
_defaultTtl = null;
|