jskelet 0.6.2 → 0.6.4
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/CHANGELOG.md +32 -0
- package/README.md +2 -0
- package/docs/02-mimari.md +1 -0
- package/docs/04-render-ve-sablonlar.md +9 -3
- package/docs/06-cache.md +53 -9
- package/docs/07-yapilandirma.md +1208 -1191
- package/docs/08-build.md +2 -1
- package/docs/10-dagitim.md +16 -6
- package/docs/12-panel-ve-oturum.md +2 -1
- package/docs/en/02-architecture.md +2 -1
- package/docs/en/04-rendering.md +9 -3
- package/docs/en/06-caching.md +54 -9
- package/docs/en/07-configuration.md +24 -9
- package/docs/en/08-build.md +2 -1
- package/docs/en/10-deployment.md +17 -6
- package/docs/en/12-dashboards-and-sessions.md +2 -1
- package/package.json +1 -1
- package/src/config/defaults.js +541 -518
- package/src/config/index.js +1500 -1456
- package/src/init.mjs +2 -0
- package/src/server/cache-blob.js +70 -0
- package/src/server/cache-control.js +45 -0
- package/src/server/data-cache.js +118 -27
- package/src/server/disk-cache.js +233 -0
- package/src/server/html-cache.js +90 -16
- package/src/server/image-optimizer.js +95 -2
- package/src/server/logs/file-sink.js +159 -32
- package/src/server/logs/pipeline.js +10 -3
- package/src/server/middleware/static-precompressed.js +31 -10
- package/src/server/og-image.js +17 -4
- package/src/server/prewarm.js +25 -1
- package/src/server/redis.js +31 -12
- package/src/server/render.js +910 -910
- package/types/config/defaults.d.ts +21 -1
- package/types/config/index.d.ts +14 -0
- package/types/server/cache-blob.d.ts +13 -0
- package/types/server/cache-control.d.ts +28 -0
- package/types/server/data-cache.d.ts +9 -0
- package/types/server/disk-cache.d.ts +36 -0
- package/types/server/html-cache.d.ts +26 -3
- package/types/server/logs/file-sink.d.ts +16 -5
- package/types/server/og-image.d.ts +5 -0
- package/types/server/redis.d.ts +2 -1
|
@@ -131,6 +131,12 @@ export declare const CLASSIC_PREWARM_KEYS: string[];
|
|
|
131
131
|
* `vary.host` kopyası sayı tavanının altında da RSS'i şişirir.
|
|
132
132
|
*/
|
|
133
133
|
export declare const DEFAULT_HTML_CACHE_MAX_ENTRIES = 500;
|
|
134
|
+
/**
|
|
135
|
+
* Edge taze penceresi bittikten sonra eski HTML'in sunulacağı süre (saniye).
|
|
136
|
+
* `cache().staleWhileRevalidate`. 0 ise `stale-while-revalidate` direktifi
|
|
137
|
+
* basılmaz. Süreç içi HTML cache'in stale penceresinden bağımsızdır.
|
|
138
|
+
*/
|
|
139
|
+
export declare const DEFAULT_STALE_WHILE_REVALIDATE = 60;
|
|
134
140
|
/** `cache().maxEntries` için sert tavan. Üstü uyarıyla bu değere çekilir. */
|
|
135
141
|
export declare const HTML_CACHE_MAX_ENTRIES_CEILING = 800;
|
|
136
142
|
/**
|
|
@@ -139,6 +145,17 @@ export declare const HTML_CACHE_MAX_ENTRIES_CEILING = 800;
|
|
|
139
145
|
* saklanmaz, yanıt yine gider.
|
|
140
146
|
*/
|
|
141
147
|
export declare const HTML_CACHE_BYTE_BUDGET: number;
|
|
148
|
+
/**
|
|
149
|
+
* Süreç içi veri önbelleğinin JSON bayt tavanı (64 MB). Sayı tavanı
|
|
150
|
+
* şişman gövdeleri tutmaz; config yükseltemez. Tek değer bütçeden büyükse
|
|
151
|
+
* saklanmaz, çağıran sonucu yine alır.
|
|
152
|
+
*/
|
|
153
|
+
export declare const DATA_CACHE_BYTE_BUDGET: number;
|
|
154
|
+
/**
|
|
155
|
+
* Uzak görsel disk önbelleğinin tavanı (256 MB). `.jskelet/image-cache/`
|
|
156
|
+
* bu boyutu aşınca en eski dosya düşer. Config yükseltemez.
|
|
157
|
+
*/
|
|
158
|
+
export declare const IMAGE_CACHE_BYTE_BUDGET: number;
|
|
142
159
|
/** `cache().data.maxEntries` için sert tavan. Uzun kuyruk burada durur, HTML'de değil. */
|
|
143
160
|
export declare const DATA_CACHE_MAX_ENTRIES_CEILING = 20000;
|
|
144
161
|
/**
|
|
@@ -262,7 +279,10 @@ export declare const DEFAULT_LOGS: {
|
|
|
262
279
|
enabled: boolean;
|
|
263
280
|
/** Proje köküne göre relative. */
|
|
264
281
|
dir: string;
|
|
265
|
-
/**
|
|
282
|
+
/**
|
|
283
|
+
* Artık kullanılmıyor. Parçalar en fazla 5 dakika durur; alan çözülen
|
|
284
|
+
* config'te durur ki eski okuyucular kırılmasın.
|
|
285
|
+
*/
|
|
266
286
|
rotate: "daily";
|
|
267
287
|
};
|
|
268
288
|
s3: {
|
package/types/config/index.d.ts
CHANGED
|
@@ -45,11 +45,19 @@ export type LogsConfig = {
|
|
|
45
45
|
* Sink'lere giden kayıt türleri.
|
|
46
46
|
*/
|
|
47
47
|
kinds: LogKind[];
|
|
48
|
+
/**
|
|
49
|
+
* `rotate` durur; dosya parçaları en fazla 5 dakika tutulur.
|
|
50
|
+
*/
|
|
48
51
|
file: {
|
|
49
52
|
enabled: boolean;
|
|
50
53
|
dir: string;
|
|
51
54
|
rotate: "daily";
|
|
52
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Mühürlenen zstd parçasını uygulamanın seçtiği yere aktarır. Hata
|
|
58
|
+
* siteyi düşürmez.
|
|
59
|
+
*/
|
|
60
|
+
drainLog: import('../server/logs/file-sink.js').DrainLog | null;
|
|
53
61
|
s3: {
|
|
54
62
|
enabled: boolean;
|
|
55
63
|
bucket: string | null;
|
|
@@ -116,6 +124,12 @@ export type ResolvedConfig = {
|
|
|
116
124
|
* HTML önbelleğinin girdi sınırı.
|
|
117
125
|
*/
|
|
118
126
|
htmlMaxEntries: number;
|
|
127
|
+
/**
|
|
128
|
+
* Edge taze penceresi bittikten sonra
|
|
129
|
+
* eski HTML'in sunulacağı süre (saniye). 0 ise direktif basılmaz. Süreç içi
|
|
130
|
+
* HTML cache'in stale penceresinden bağımsızdır.
|
|
131
|
+
*/
|
|
132
|
+
staleWhileRevalidate: number;
|
|
119
133
|
/**
|
|
120
134
|
* Upstream veri önbelleği ayarları.
|
|
121
135
|
*/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Küçük gövde düz `string` döner (çağıran senkron yazabilsin). Büyük gövde
|
|
3
|
+
* brotli bitince çözülen bir Promise.
|
|
4
|
+
*
|
|
5
|
+
* @param {unknown} value
|
|
6
|
+
* @returns {string | Buffer | Promise<string | Buffer> | null}
|
|
7
|
+
*/
|
|
8
|
+
export declare function encodeCacheValue(value: unknown): string | Buffer | Promise<string | Buffer> | null;
|
|
9
|
+
/**
|
|
10
|
+
* @param {Buffer | string} raw
|
|
11
|
+
* @returns {unknown}
|
|
12
|
+
*/
|
|
13
|
+
export declare function decodeCacheValue(raw: Buffer | string): unknown;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tarayıcıya `max-age=0`, edge'e `CDN-Cache-Control`.
|
|
3
|
+
*
|
|
4
|
+
* `s-maxage` yazılmaz: Cloudflare `max-age=0` ile birlikte görünce nesneyi
|
|
5
|
+
* EXPIRED sayar. `must-revalidate`, `proxy-revalidate` ve `no-cache` aynı
|
|
6
|
+
* yanıtta stale penceresini keser; burada üretilmez. `s-maxage`'e dönen bir
|
|
7
|
+
* anahtar da yok — o mod aynı EXPIRED sonucunu geri getirir.
|
|
8
|
+
*
|
|
9
|
+
* Süreç içi HTML cache (`X-JSkelet-Cache: STALE`) ayrı katmandır; bu modül
|
|
10
|
+
* ona dokunmaz. Görsel optimizer kendi `max-age` + `stale-while-revalidate`
|
|
11
|
+
* yolunu kullanır.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* @param {number} maxAge Edge'in taze penceresi (saniye). HTML'de route TTL.
|
|
15
|
+
* @param {number} staleWhileRevalidate Taze pencere bitince eski kopyanın
|
|
16
|
+
* sunulacağı süre. 0 ise direktif basılmaz.
|
|
17
|
+
* @returns {{ cacheControl: string, cdnCacheControl: string }}
|
|
18
|
+
*/
|
|
19
|
+
export declare function edgeCacheControl(maxAge: number, staleWhileRevalidate: number): {
|
|
20
|
+
cacheControl: string;
|
|
21
|
+
cdnCacheControl: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* @param {import('express').Response} res
|
|
25
|
+
* @param {number} maxAge
|
|
26
|
+
* @param {number} staleWhileRevalidate
|
|
27
|
+
*/
|
|
28
|
+
export declare function setEdgeCacheHeaders(res: import('express').Response, maxAge: number, staleWhileRevalidate: number): void;
|
|
@@ -2,6 +2,7 @@ export type DataEntry = {
|
|
|
2
2
|
value: unknown;
|
|
3
3
|
expiresAt: number;
|
|
4
4
|
staleUntil: number;
|
|
5
|
+
bytes: number;
|
|
5
6
|
};
|
|
6
7
|
/**
|
|
7
8
|
* Süreç ömrü boyunca biriken sayaçlar.
|
|
@@ -90,6 +91,14 @@ export declare function clearDataCache(prefix?: string): number;
|
|
|
90
91
|
export declare function dropDataCacheKey(key: string): boolean;
|
|
91
92
|
/** @returns {number} */
|
|
92
93
|
export declare function getDataCacheSize(): number;
|
|
94
|
+
/**
|
|
95
|
+
* Bellek freninin bayt tavanını geçici olarak değiştirir. Testler LRU
|
|
96
|
+
* tahliyesini küçük bir değerle doğrular; `null` üretim tavanına döner.
|
|
97
|
+
*
|
|
98
|
+
* @param {number | null} bytes
|
|
99
|
+
* @returns {void}
|
|
100
|
+
*/
|
|
101
|
+
export declare function setDataCacheByteBudget(bytes: number | null): void;
|
|
93
102
|
/**
|
|
94
103
|
* Süreç başından beri biriken sayaçlar. `produced` kotaya yazılan tek sayıdır:
|
|
95
104
|
* geri kalan her şey upstream'e hiç gitmemiş bir okuma.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string | null} root Mutlak dizin, ya da config yoluna dönmek için `null`.
|
|
3
|
+
*/
|
|
4
|
+
export declare function setDiskCacheRootForTests(root: string | null): void;
|
|
5
|
+
/**
|
|
6
|
+
* @param {"html" | "data"} kind
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
9
|
+
export declare function diskShares(kind: "html" | "data"): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* @param {"html" | "data"} kind
|
|
12
|
+
* @param {string} key
|
|
13
|
+
* @returns {Promise<unknown | null>}
|
|
14
|
+
*/
|
|
15
|
+
export declare function diskGetJson(kind: "html" | "data", key: string): Promise<unknown | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Ateşle-unut. Dönüş değeri testler bekleyebilsin diye durur; istek yolu
|
|
18
|
+
* beklemez.
|
|
19
|
+
*
|
|
20
|
+
* @param {"html" | "data"} kind
|
|
21
|
+
* @param {string} key
|
|
22
|
+
* @param {unknown} value
|
|
23
|
+
* @returns {Promise<void>}
|
|
24
|
+
*/
|
|
25
|
+
export declare function diskSetJson(kind: "html" | "data", key: string, value: unknown): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* @param {"html" | "data"} kind
|
|
28
|
+
* @param {string[]} keys
|
|
29
|
+
*/
|
|
30
|
+
export declare function diskDrop(kind: "html" | "data", keys: string[]): void;
|
|
31
|
+
/**
|
|
32
|
+
* @param {"html" | "data"} kind
|
|
33
|
+
* @param {(key: string) => boolean} [match] Verilmezse türün tamamı silinir.
|
|
34
|
+
* @returns {Promise<number>}
|
|
35
|
+
*/
|
|
36
|
+
export declare function diskDropMatching(kind: "html" | "data", match?: (key: string) => boolean): Promise<number>;
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
* (L1) **birincil kalır**: `read()` senkron, sıkıştırılmış gövdeler girdiyle
|
|
27
27
|
* birlikte ve tutarlılık makinesi (`tokens`, `purgedDeps`) tek proseste. Redis
|
|
28
28
|
* yalnızca L1'de bulunmayan bir yol için render'ı atlatır ve invalidation'ı
|
|
29
|
-
* diğer node'lara duyurur. Redis
|
|
30
|
-
*
|
|
29
|
+
* diğer node'lara duyurur. Redis yoksa aynı kayıt `.jskelet/cache/<buildId>/`
|
|
30
|
+
* altına yazılır; bu tek makinenin yeniden açılışını karşılar, kümeyi değil.
|
|
31
31
|
*/
|
|
32
32
|
export type HtmlEntry = {
|
|
33
33
|
html: string;
|
|
@@ -144,9 +144,10 @@ export declare function dropHtmlCacheKey(key: string): boolean;
|
|
|
144
144
|
* açılmaz.
|
|
145
145
|
*
|
|
146
146
|
* @param {string} [onlyHost]
|
|
147
|
-
* @returns {{ path: string, host: string }[]}
|
|
147
|
+
* @returns {{ key: string, path: string, host: string }[]}
|
|
148
148
|
*/
|
|
149
149
|
export declare function takeInvalidatedTargets(onlyHost?: string): {
|
|
150
|
+
key: string;
|
|
150
151
|
path: string;
|
|
151
152
|
host: string;
|
|
152
153
|
}[];
|
|
@@ -190,11 +191,33 @@ export declare function isHtmlCacheFresh(pathname: string, req?: {
|
|
|
190
191
|
headers?: Record<string, unknown>;
|
|
191
192
|
get?: (name: string) => string | undefined;
|
|
192
193
|
}): boolean;
|
|
194
|
+
/**
|
|
195
|
+
* Bu anahtarın girdisi hâlâ taze mi? Süre dolumu ısıtması anahtarı bildiği
|
|
196
|
+
* için yol taraması yapmaz. Soft-bayat (`expiresAt === 0`) taze sayılmaz:
|
|
197
|
+
* ziyaretçi arada yenilediyse yeni `expiresAt` taze döner ve HTTP atlanır.
|
|
198
|
+
*
|
|
199
|
+
* @param {string} key
|
|
200
|
+
* @returns {boolean}
|
|
201
|
+
*/
|
|
202
|
+
export declare function isHtmlCacheKeyFresh(key: string): boolean;
|
|
203
|
+
/**
|
|
204
|
+
* Girdide en fazla bir sıkıştırılmış gövde durur. Yeni kodlama eskisinin
|
|
205
|
+
* yerini alır; ham HTML kalır. Bayt sayacı `noteHtmlCacheGrowth` ile işlenir.
|
|
206
|
+
*
|
|
207
|
+
* @param {Map<string, Buffer>} encoded
|
|
208
|
+
* @param {string} encoding
|
|
209
|
+
* @param {Buffer} buffer
|
|
210
|
+
* @returns {void}
|
|
211
|
+
*/
|
|
212
|
+
export declare function rememberHtmlEncoding(encoded: Map<string, Buffer>, encoding: string, buffer: Buffer): void;
|
|
193
213
|
/**
|
|
194
214
|
* Erken tazeleme penceresine girmiş (veya TTL'i dolmuş) trafiksiz girdileri
|
|
195
215
|
* soft-bayatlatır ve ısıtma kuyruğuna alır. HTTP ısıtması producer'sız
|
|
196
216
|
* çalıştığı için soft-bayat şart: taze HIT yenileme tetiklemez.
|
|
197
217
|
*
|
|
218
|
+
* Tur başına en fazla `EARLY_SWEEP_MARK_BUDGET` girdi. Önce süresi en yakın
|
|
219
|
+
* dolacak olan; kota dolunca kalanlar bir sonraki tura kalır.
|
|
220
|
+
*
|
|
198
221
|
* @returns {number} İşaretlenen girdi sayısı.
|
|
199
222
|
*/
|
|
200
223
|
export declare function sweepEarlyExpiry(): number;
|
|
@@ -1,17 +1,28 @@
|
|
|
1
|
+
export type LogChunk = {
|
|
2
|
+
body: Buffer;
|
|
3
|
+
encoding: "zstd";
|
|
4
|
+
bytes: number;
|
|
5
|
+
lines: number;
|
|
6
|
+
at: number;
|
|
7
|
+
};
|
|
1
8
|
export type LogSink = {
|
|
2
9
|
write: (entry: Record<string, unknown>) => Promise<void>;
|
|
3
10
|
flush: () => Promise<void>;
|
|
4
11
|
close: () => Promise<void>;
|
|
5
12
|
};
|
|
13
|
+
export type DrainLog = (chunk: LogChunk) => void | Promise<void>;
|
|
14
|
+
/** Diskteki parçaların ömrü. Config yükseltemez. */
|
|
15
|
+
export declare const FILE_LOG_RETENTION_MS: number;
|
|
6
16
|
/**
|
|
7
|
-
* @
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @param {{ root: string, dir: string }} options
|
|
17
|
+
* @param {{ root: string, dir: string, persist?: boolean,
|
|
18
|
+
* retentionMs?: number, drainLog?: DrainLog | null }} options
|
|
19
|
+
* `persist: false` diske yazmaz; yalnız `drainLog` çağrılır.
|
|
12
20
|
* @returns {LogSink}
|
|
13
21
|
*/
|
|
14
22
|
export declare function createFileSink(options: {
|
|
15
23
|
root: string;
|
|
16
24
|
dir: string;
|
|
25
|
+
persist?: boolean;
|
|
26
|
+
retentionMs?: number;
|
|
27
|
+
drainLog?: DrainLog | null;
|
|
17
28
|
}): LogSink;
|
|
@@ -94,6 +94,11 @@ export declare function buildOgSvg(options?: OgCardOptions & {
|
|
|
94
94
|
export declare function ogImage(options?: OgImageOptions): Promise<OgImageResult>;
|
|
95
95
|
/**
|
|
96
96
|
* Express yanıtına OG görseli basar.
|
|
97
|
+
*
|
|
98
|
+
* Varsayılan edge penceresi 86400 / 604800'tür ve HTML TTL'ye bağlı değildir.
|
|
99
|
+
* `cacheControl` verilirse yalnızca `Cache-Control` yazılır;
|
|
100
|
+
* `CDN-Cache-Control` basılmaz.
|
|
101
|
+
*
|
|
97
102
|
* @param {import('express').Response} res
|
|
98
103
|
* @param {OgImageOptions} [options]
|
|
99
104
|
* @returns {Promise<OgImageResult>}
|
package/types/server/redis.d.ts
CHANGED
|
@@ -56,7 +56,8 @@ export declare function cacheKey(kind: "html" | "data", key: string): string;
|
|
|
56
56
|
export declare function redisGetJson(key: string): Promise<any | null>;
|
|
57
57
|
/**
|
|
58
58
|
* Ateşle-unut yazma. İsteğin yanıt yolunda beklenmez: HTML zaten L1'e
|
|
59
|
-
* yazıldı, Redis kopyası yalnızca diğer node'lar için.
|
|
59
|
+
* yazıldı, Redis kopyası yalnızca diğer node'lar için. 1 KB ve üstü gövdeler
|
|
60
|
+
* brotli ile yazılır; okuma düz JSON'u da kabul eder.
|
|
60
61
|
*
|
|
61
62
|
* @param {string} key
|
|
62
63
|
* @param {unknown} value
|