jskelet 0.5.4 → 0.6.0
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/AGENTS.md +18 -13
- package/CHANGELOG.md +387 -385
- package/README.md +9 -7
- package/bin/jskelet.mjs +24 -10
- package/docs/01-baslangic.md +4 -3
- package/docs/02-mimari.md +4 -3
- package/docs/03-routing.md +11 -6
- package/docs/04-render-ve-sablonlar.md +35 -43
- package/docs/05-islands.md +12 -8
- package/docs/07-yapilandirma.md +53 -25
- package/docs/08-build.md +40 -18
- package/docs/09-dev-araclari.md +5 -1
- package/docs/10-dagitim.md +6 -1
- package/docs/11-tasima.md +51 -17
- package/docs/12-panel-ve-oturum.md +10 -4
- package/docs/README.md +7 -5
- package/docs/en/01-getting-started.md +4 -3
- package/docs/en/02-architecture.md +5 -5
- package/docs/en/03-routing.md +12 -7
- package/docs/en/04-rendering.md +47 -59
- package/docs/en/05-islands.md +13 -8
- package/docs/en/07-configuration.md +55 -27
- package/docs/en/08-build.md +43 -21
- package/docs/en/09-dev-tools.md +6 -1
- package/docs/en/10-deployment.md +6 -1
- package/docs/en/11-migration.md +51 -16
- package/docs/en/12-dashboards-and-sessions.md +9 -4
- package/docs/en/README.md +7 -5
- package/package.json +49 -14
- package/src/build/tasks/client.mjs +91 -10
- package/src/build/tasks/icons.mjs +152 -18
- package/src/client/index.js +2 -2
- package/src/compile/codegen.js +4 -0
- package/src/compile/compile-all.js +12 -21
- package/src/compile/expr.js +5 -0
- package/src/compile/parse.js +64 -8
- package/src/compile/resolve.js +3 -0
- package/src/config/defaults.js +12 -2
- package/src/config/index.js +31 -3
- package/src/dev-server.mjs +26 -3
- package/src/http/cookies-entry.js +1 -0
- package/src/http/cookies.js +18 -0
- package/src/logo.png +0 -0
- package/src/migrate/apply.mjs +262 -0
- package/src/migrate/babel.mjs +79 -0
- package/src/migrate/classify.mjs +155 -0
- package/src/migrate/config.mjs +126 -0
- package/src/migrate/fs-walk.mjs +191 -0
- package/src/migrate/parse.mjs +26 -0
- package/src/migrate/scan.mjs +177 -0
- package/src/migrate/transform/expr-source.mjs +168 -0
- package/src/migrate/transform/island.mjs +67 -0
- package/src/migrate/transform/jsx-to-component.mjs +302 -0
- package/src/migrate/transform/jsx-to-jsk.mjs +330 -0
- package/src/migrate/transform/page-split.mjs +435 -0
- package/src/migrate/write.mjs +81 -0
- package/src/migrate.mjs +171 -0
- package/src/server/auth/handoff.js +94 -11
- package/src/server/create-app.js +28 -10
- package/src/server/ejs-adapter.js +59 -0
- package/src/server/image-optimizer.js +94 -26
- package/src/server/port-guard.js +255 -0
- package/src/server/render.js +27 -9
- package/src/server/status-page.js +105 -4
- package/src/start.mjs +18 -3
- package/src/templates/layout.ejs +8 -28
- package/src/templates/layout.jsk +30 -0
- package/src/templates/layout.render.js +41 -0
- package/src/views/helpers/tags.js +86 -3
- package/types/build/resolve-peer.d.mts +13 -0
- package/types/client/dom.d.ts +55 -0
- package/types/client/form.d.ts +19 -0
- package/types/client/index.d.ts +20 -0
- package/types/client/registry.d.ts +53 -0
- package/types/client/safe-image.d.ts +19 -0
- package/types/client/shared-cookie.d.ts +82 -0
- package/types/client/store.d.ts +18 -0
- package/types/client/swap.d.ts +46 -0
- package/types/compile/codegen.d.ts +32 -0
- package/types/compile/compile-all.d.ts +42 -0
- package/types/compile/errors.d.ts +30 -0
- package/types/compile/expr.d.ts +67 -0
- package/types/compile/index.d.ts +10 -0
- package/types/compile/parse.d.ts +82 -0
- package/types/compile/resolve.d.ts +46 -0
- package/types/compile/scan-exports.d.ts +9 -0
- package/types/config/defaults.d.ts +449 -0
- package/types/config/index.d.ts +299 -0
- package/types/config/pattern.d.ts +38 -0
- package/types/http/control-flow.d.ts +45 -0
- package/types/http/cookies-entry.d.ts +5 -0
- package/types/http/cookies.d.ts +113 -0
- package/types/http/request-cache.d.ts +13 -0
- package/types/http/request-context.d.ts +67 -0
- package/types/http/shared-cookie.d.ts +73 -0
- package/types/index.d.ts +30 -0
- package/types/log.d.mts +153 -0
- package/types/server/admin/actions.d.ts +16 -0
- package/types/server/admin/auth.d.ts +52 -0
- package/types/server/admin/event-log.d.ts +38 -0
- package/types/server/admin/gate.d.ts +43 -0
- package/types/server/admin/inventory.d.ts +40 -0
- package/types/server/admin/mount.d.ts +6 -0
- package/types/server/admin/router.d.ts +6 -0
- package/types/server/admin/snapshot.d.ts +6 -0
- package/types/server/assets.d.ts +47 -0
- package/types/server/auth/handoff.d.ts +12 -0
- package/types/server/cache-deps.d.ts +16 -0
- package/types/server/cache-vary.d.ts +30 -0
- package/types/server/cloudflare.d.ts +163 -0
- package/types/server/create-app.d.ts +25 -0
- package/types/server/data-cache.d.ts +116 -0
- package/types/server/dev/devtools.d.ts +44 -0
- package/types/server/dev/report.d.ts +229 -0
- package/types/server/dev/socket.d.ts +17 -0
- package/types/server/dev/version-check.d.mts +15 -0
- package/types/server/ejs-adapter.d.ts +11 -0
- package/types/server/head-hints.d.ts +40 -0
- package/types/server/html-cache.d.ts +173 -0
- package/types/server/image-optimizer.d.ts +68 -0
- package/types/server/logs/access-middleware.d.ts +7 -0
- package/types/server/logs/file-sink.d.ts +17 -0
- package/types/server/logs/pipeline.d.ts +37 -0
- package/types/server/logs/s3-put.d.ts +85 -0
- package/types/server/logs/s3-sink.d.ts +26 -0
- package/types/server/metadata.d.ts +38 -0
- package/types/server/middleware/compression.d.ts +17 -0
- package/types/server/middleware/csrf.d.ts +4 -0
- package/types/server/middleware/dev-gate.d.ts +2 -0
- package/types/server/middleware/headers.d.ts +2 -0
- package/types/server/middleware/redirects.d.ts +2 -0
- package/types/server/middleware/static-precompressed.d.ts +5 -0
- package/types/server/middleware/trailing-slash.d.ts +11 -0
- package/types/server/middleware/upstream-proxy.d.ts +21 -0
- package/types/server/og-image.d.ts +149 -0
- package/types/server/port-guard.d.ts +50 -0
- package/types/server/prewarm.d.ts +128 -0
- package/types/server/redis.d.ts +163 -0
- package/types/server/render.d.ts +101 -0
- package/types/server/router.d.ts +5 -0
- package/types/server/status-page.d.ts +24 -0
- package/types/server/upstream-limiter.d.ts +123 -0
- package/types/server/upstream-tracking.d.ts +42 -0
- package/types/shared/cookie-domain.d.ts +29 -0
- package/types/templates/layout.render.d.ts +7 -0
- package/types/version.d.mts +10 -0
- package/types/views/components/loader.d.ts +5 -0
- package/types/views/helpers/html.d.ts +39 -0
- package/types/views/helpers/tags.d.ts +127 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isıtmanın canlı durumu. Dev araçları bunu okuyup ilerlemeyi gösterir;
|
|
3
|
+
* üretimde kimse okumazsa da maliyeti bir nesnedir.
|
|
4
|
+
*/
|
|
5
|
+
export declare const prewarmProgress: {
|
|
6
|
+
active: boolean;
|
|
7
|
+
done: number;
|
|
8
|
+
total: number;
|
|
9
|
+
ok: number;
|
|
10
|
+
failed: number;
|
|
11
|
+
/** @type {number | null} */
|
|
12
|
+
startedAt: number | null;
|
|
13
|
+
/** @type {number | null} */
|
|
14
|
+
finishedAt: number | null;
|
|
15
|
+
/**
|
|
16
|
+
* Denenen her yolun sonucu; dev panelindeki Prewarming sekmesi bunu listeler.
|
|
17
|
+
* @type {{ path: string, status: number, ms: number, bytes: number,
|
|
18
|
+
* cache: string | null, error: string | null }[]}
|
|
19
|
+
*/
|
|
20
|
+
entries: {
|
|
21
|
+
path: string;
|
|
22
|
+
status: number;
|
|
23
|
+
ms: number;
|
|
24
|
+
bytes: number;
|
|
25
|
+
cache: string | null;
|
|
26
|
+
error: string | null;
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* İstek ısıtma turunun kendi isteği mi? Yalnızca tur çalışırken ve istek
|
|
31
|
+
* ısıtmanın user-agent'ıyla geldiğinde doğru; gerçek trafiğin hataları her
|
|
32
|
+
* zaman loglanmaya devam eder.
|
|
33
|
+
*
|
|
34
|
+
* @param {{ get?: (name: string) => string | undefined } | null | undefined} req
|
|
35
|
+
* @returns {boolean}
|
|
36
|
+
*/
|
|
37
|
+
export declare function isPrewarmRequest(req: {
|
|
38
|
+
get?: (name: string) => string | undefined;
|
|
39
|
+
} | null | undefined): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Isıtma turuna ait bir uyarıyı loglamak yerine sayar.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} message Gruplama anahtarı; yol adı içermemeli.
|
|
44
|
+
* @returns {boolean} `true` ise sayıldı, çağıran taraf loglamamalı.
|
|
45
|
+
*/
|
|
46
|
+
export declare function suppressForPrewarm(message: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Bastırılan bir istek hatasını sayaca ekler. Yığın izi saklanmaz: özet
|
|
49
|
+
* satırının amacı "neyin bozulduğunu" göstermek, hatayı ayıklamak değil.
|
|
50
|
+
*
|
|
51
|
+
* @param {number} status
|
|
52
|
+
* @param {unknown} error
|
|
53
|
+
* @returns {void}
|
|
54
|
+
*/
|
|
55
|
+
export declare function notePrewarmError(status: number, error: unknown): void;
|
|
56
|
+
/**
|
|
57
|
+
* Bir turda ısıtılacak dilimi seçer: önce `priority` eşleşenler, sonra
|
|
58
|
+
* kuyruğun sırası gelen parçası. Dışa açık olması bilinçli — sıralama ve
|
|
59
|
+
* rotasyon, tur çalışmadan doğrulanabilen tek davranış.
|
|
60
|
+
*
|
|
61
|
+
* @param {string[]} all
|
|
62
|
+
* @param {number} limit
|
|
63
|
+
* @param {boolean} rotate
|
|
64
|
+
* @returns {string[]}
|
|
65
|
+
*/
|
|
66
|
+
export declare function selectPrewarmPaths(all: string[], limit: number, rotate?: boolean): string[];
|
|
67
|
+
/**
|
|
68
|
+
* @param {{ origin: string, quiet?: boolean, paths?: string[] }} options
|
|
69
|
+
* `paths` verilirse hook çağrılmaz, yalnızca o yollar ısıtılır (dev
|
|
70
|
+
* panelindeki "tekrar dene" bunu kullanır).
|
|
71
|
+
* @returns {Promise<{ ok: number, failed: number, total: number, elapsed: number }>}
|
|
72
|
+
*/
|
|
73
|
+
export declare function prewarm({ origin, quiet, paths: only }: {
|
|
74
|
+
origin: string;
|
|
75
|
+
quiet?: boolean;
|
|
76
|
+
paths?: string[];
|
|
77
|
+
}): Promise<{
|
|
78
|
+
ok: number;
|
|
79
|
+
failed: number;
|
|
80
|
+
total: number;
|
|
81
|
+
elapsed: number;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* HTML içindeki aynı-origin `<a href>` yollarını DOM sırasıyla (üstten alta)
|
|
85
|
+
* toplar. Speculation Rules ile aynı muafiyetler: `nofollow`, `_blank`,
|
|
86
|
+
* `data-no-prefetch`, `prewarmSkip`, `navigation.exclude`.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} html
|
|
89
|
+
* @param {{ limit?: number, basePath?: string }} [options]
|
|
90
|
+
* @returns {string[]}
|
|
91
|
+
*/
|
|
92
|
+
export declare function extractSameOriginLinks(html: string, options?: {
|
|
93
|
+
limit?: number;
|
|
94
|
+
basePath?: string;
|
|
95
|
+
}): string[];
|
|
96
|
+
/**
|
|
97
|
+
* Ziyaret ısıtması açık mı? `PREWARM=0` her iki modu da keser.
|
|
98
|
+
*
|
|
99
|
+
* @returns {boolean}
|
|
100
|
+
*/
|
|
101
|
+
export declare function isOnVisitPrewarm(): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Yanıt gövdesindeki linkleri soğuksa kuyruğa alır. İstek yolunu bloklamamak
|
|
104
|
+
* için `route()` bunu `queueMicrotask` ile çağırır.
|
|
105
|
+
*
|
|
106
|
+
* @param {string} html
|
|
107
|
+
* @param {{ path: string, req?: { get?: (name: string) => string | undefined,
|
|
108
|
+
* headers?: Record<string, unknown> } }} context
|
|
109
|
+
* @returns {void}
|
|
110
|
+
*/
|
|
111
|
+
export declare function noteVisitWarm(html: string, context: {
|
|
112
|
+
path: string;
|
|
113
|
+
req?: {
|
|
114
|
+
get?: (name: string) => string | undefined;
|
|
115
|
+
headers?: Record<string, unknown>;
|
|
116
|
+
};
|
|
117
|
+
}): void;
|
|
118
|
+
/**
|
|
119
|
+
* Açılışta ısıtmayı tetikler. `listen` geri çağrısından çağrılır.
|
|
120
|
+
* `onVisit` modunda klasik zamanlayıcı yok; yine de erken-TTL invalidation
|
|
121
|
+
* drain'i çalışır — soft-bayatlayan sweeper'ın kuyruğu boşalmasın.
|
|
122
|
+
*
|
|
123
|
+
* @param {{ port: number }} options
|
|
124
|
+
* @returns {void}
|
|
125
|
+
*/
|
|
126
|
+
export declare function startPrewarm({ port }: {
|
|
127
|
+
port: number;
|
|
128
|
+
}): void;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
export type RedisConfig = import('../config/index.js').RedisConfig;
|
|
2
|
+
export type CacheEvent = {
|
|
3
|
+
type: string;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Bağlantıyı kurar. `createApp()` config yüklendikten sonra bir kez çağırır.
|
|
8
|
+
*
|
|
9
|
+
* `ioredis` opsiyonel peer bağımlılık ve **uygulamanın** node_modules'ünden
|
|
10
|
+
* çözülür: framework `file:`/workspace bağlantısıyla kuruluysa düz bir
|
|
11
|
+
* `import "ioredis"` framework'ün kendi ağacına bakar.
|
|
12
|
+
*
|
|
13
|
+
* @param {import('../config/index.js').ResolvedConfig} config
|
|
14
|
+
* @returns {Promise<boolean>} Bağlantı kuruldu mu.
|
|
15
|
+
*/
|
|
16
|
+
export declare function connectRedis(config: import('../config/index.js').ResolvedConfig): Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* Önbellek olaylarına abone olur. Önbellek modülleri yükleme anında çağırır;
|
|
19
|
+
* bağlantı sonradan kurulsa da kayıt geçerli kalır.
|
|
20
|
+
*
|
|
21
|
+
* Dinleyici **yalnızca yerel** işi yapmalı: yeniden yayın yapan bir dinleyici
|
|
22
|
+
* iki node arasında sonsuz mesaj döngüsü üretir.
|
|
23
|
+
*
|
|
24
|
+
* @param {(event: CacheEvent) => void} listener
|
|
25
|
+
*/
|
|
26
|
+
export declare function onCacheEvent(listener: (event: CacheEvent) => void): void;
|
|
27
|
+
/**
|
|
28
|
+
* Olayı diğer node'lara duyurur. Ateşle-unut: yayın hatası çağıranı
|
|
29
|
+
* etkilemez, yerel invalidation zaten yapıldı.
|
|
30
|
+
*
|
|
31
|
+
* @param {CacheEvent} event
|
|
32
|
+
*/
|
|
33
|
+
export declare function publishCacheEvent(event: CacheEvent): void;
|
|
34
|
+
/**
|
|
35
|
+
* Bu tür için paylaşım açık mı. `html`/`data` ayrı ayrı kapatılabiliyor:
|
|
36
|
+
* veri önbelleğini paylaşmak neredeyse her zaman kazançlı, HTML gövdelerini
|
|
37
|
+
* paylaşmak girdi başına yüz kilobayt trafik demek.
|
|
38
|
+
*
|
|
39
|
+
* @param {"html" | "data"} kind
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
42
|
+
export declare function redisShares(kind: "html" | "data"): boolean;
|
|
43
|
+
/** @returns {boolean} */
|
|
44
|
+
export declare function redisSharesEncoded(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* @param {"html" | "data"} kind
|
|
47
|
+
* @param {string} key
|
|
48
|
+
* @returns {string}
|
|
49
|
+
*/
|
|
50
|
+
export declare function cacheKey(kind: "html" | "data", key: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* @param {string} key
|
|
53
|
+
* @returns {Promise<any | null>} Girdi yoksa, ayrıştırılamıyorsa ya da Redis
|
|
54
|
+
* hata verirse `null` — hepsi "miss" sayılır.
|
|
55
|
+
*/
|
|
56
|
+
export declare function redisGetJson(key: string): Promise<any | null>;
|
|
57
|
+
/**
|
|
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.
|
|
60
|
+
*
|
|
61
|
+
* @param {string} key
|
|
62
|
+
* @param {unknown} value
|
|
63
|
+
* @param {number} ttlMs
|
|
64
|
+
*/
|
|
65
|
+
export declare function redisSetJson(key: string, value: unknown, ttlMs: number): void;
|
|
66
|
+
/**
|
|
67
|
+
* @param {string[]} keys
|
|
68
|
+
*/
|
|
69
|
+
export declare function redisDrop(keys: string[]): void;
|
|
70
|
+
/**
|
|
71
|
+
* Bir isim alanını tarar ve eşleşen anahtarları düşürür.
|
|
72
|
+
*
|
|
73
|
+
* `KEYS` **kullanılmaz**: tek komutta tüm keyspace'i tarayıp sunucuyu bloklar.
|
|
74
|
+
* `SCAN` kursoru parça parça döner; bu yüzden işlem atomik değil, ama
|
|
75
|
+
* invalidation'ın atomik olması gerekmiyor.
|
|
76
|
+
*
|
|
77
|
+
* @param {"html" | "data"} kind
|
|
78
|
+
* @param {(key: string) => boolean} [match] Anahtarın **önek sonrası** kısmına
|
|
79
|
+
* uygulanır; verilmezse tür altındaki her şey düşer.
|
|
80
|
+
* @returns {Promise<number>} Düşürülen anahtar sayısı.
|
|
81
|
+
*/
|
|
82
|
+
export declare function redisDropMatching(kind: "html" | "data", match?: (key: string) => boolean): Promise<number>;
|
|
83
|
+
/**
|
|
84
|
+
* Dev raporu için durum özeti. Bağlantı yoksa da güvenle çağrılabilir.
|
|
85
|
+
*
|
|
86
|
+
* @returns {{ enabled: boolean, connected: boolean, keyPrefix: string,
|
|
87
|
+
* buildId: string, errors: number, bypassed: boolean }}
|
|
88
|
+
*/
|
|
89
|
+
export declare function getRedisStatus(): {
|
|
90
|
+
enabled: boolean;
|
|
91
|
+
connected: boolean;
|
|
92
|
+
keyPrefix: string;
|
|
93
|
+
buildId: string;
|
|
94
|
+
errors: number;
|
|
95
|
+
bypassed: boolean;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Bağlantının **nereye** kurulduğu ve hangi ayarlarla çalıştığı.
|
|
99
|
+
*
|
|
100
|
+
* Şifre asla dönmez: bağlantı URL'i `redis://user:pass@host` biçiminde
|
|
101
|
+
* olabiliyor ve panelin işi adresi göstermek, sırrı değil. Ayrıştırılamayan
|
|
102
|
+
* bir URL için adres `"custom"` olur — bozuk bir değer teşhis ucunu
|
|
103
|
+
* düşürmemeli.
|
|
104
|
+
*
|
|
105
|
+
* @returns {{ address: string, secure: boolean, db: string | null,
|
|
106
|
+
* namespace: string, keyPrefix: string, html: boolean, data: boolean,
|
|
107
|
+
* storeEncoded: boolean, events: boolean, commandTimeoutMs: number,
|
|
108
|
+
* subscribed: boolean }}
|
|
109
|
+
*/
|
|
110
|
+
export declare function getRedisDetails(): {
|
|
111
|
+
address: string;
|
|
112
|
+
secure: boolean;
|
|
113
|
+
db: string | null;
|
|
114
|
+
namespace: string;
|
|
115
|
+
keyPrefix: string;
|
|
116
|
+
html: boolean;
|
|
117
|
+
data: boolean;
|
|
118
|
+
storeEncoded: boolean;
|
|
119
|
+
events: boolean;
|
|
120
|
+
commandTimeoutMs: number;
|
|
121
|
+
subscribed: boolean;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Paylaşımlı kademede gerçekten **ne durduğunu** sayar: tür başına anahtar
|
|
125
|
+
* sayısı ve sunucunun bildirdiği bellek kullanımı.
|
|
126
|
+
*
|
|
127
|
+
* Ayrı bir çağrı olması gerekiyor. Sayım `SCAN` turu demek ve panelin döküm
|
|
128
|
+
* ucu birkaç saniyede bir yenileniyor; her turda tüm keyspace'i taramak
|
|
129
|
+
* Redis'i teşhis uğruna yormak olurdu. Panel bunu düğmeye basınca çağırır.
|
|
130
|
+
*
|
|
131
|
+
* @returns {Promise<{ ok: boolean, html: number, data: number,
|
|
132
|
+
* usedMemory: string | null, totalKeys: number | null }>}
|
|
133
|
+
*/
|
|
134
|
+
export declare function inspectRedis(): Promise<{
|
|
135
|
+
ok: boolean;
|
|
136
|
+
html: number;
|
|
137
|
+
data: number;
|
|
138
|
+
usedMemory: string | null;
|
|
139
|
+
totalKeys: number | null;
|
|
140
|
+
}>;
|
|
141
|
+
/**
|
|
142
|
+
* Bağlantıları kapatır. `SIGTERM` sonrası uçuştaki komutların bitmesi
|
|
143
|
+
* beklenir (`quit`), zorla kesilmez.
|
|
144
|
+
*
|
|
145
|
+
* @returns {Promise<void>}
|
|
146
|
+
*/
|
|
147
|
+
export declare function disconnectRedis(): Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* Testler için: sahte bir istemci enjekte eder. Gerçek bir Redis'e bağlanmadan
|
|
150
|
+
* serileştirme ve olay yollarının doğrulanabilmesi gerekiyor.
|
|
151
|
+
*
|
|
152
|
+
* @param {any} fake `null` → katman kapatılır.
|
|
153
|
+
* @param {Partial<RedisConfig>} [overrides]
|
|
154
|
+
*/
|
|
155
|
+
export declare function setRedisClientForTests(fake: any, overrides?: Partial<RedisConfig>): void;
|
|
156
|
+
/**
|
|
157
|
+
* Testler için: abone kanalından gelmiş gibi olay besler. `originId`
|
|
158
|
+
* verilmezse uzak bir node varsayılır; kendi kimliğini taşıyan bir yayını
|
|
159
|
+
* olduğu gibi geri vermek de mümkün olmalı — eleme testi buna dayanıyor.
|
|
160
|
+
*
|
|
161
|
+
* @param {CacheEvent} event
|
|
162
|
+
*/
|
|
163
|
+
export declare function emitRemoteCacheEventForTests(event: CacheEvent): void;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uygulama geliştirirken bileşen dosyaları değişince kayıt yenilenmeli.
|
|
3
|
+
* Dev sunucusu süreci yeniden başlattığı için normalde gerekmez; gömülü
|
|
4
|
+
* kullanımlar (test, script) için dışa açık.
|
|
5
|
+
*
|
|
6
|
+
* @returns {void}
|
|
7
|
+
*/
|
|
8
|
+
export declare function resetRenderEngine(): void;
|
|
9
|
+
/**
|
|
10
|
+
* Layout kullanmadan tek bir şablon render eder. Fragment/partial uçları
|
|
11
|
+
* ve e-posta şablonları bunu kullanır.
|
|
12
|
+
*
|
|
13
|
+
* Öncelik: derlenmiş `.jsk` → `.ejs`. İstek anında şablon derlenmez.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} view `views/` altındaki yol, uzantısız (örn. "pages/home")
|
|
16
|
+
* @param {object} [data]
|
|
17
|
+
* @returns {Promise<string>}
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderView(view: string, data?: object): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Sayfayı layout içinde render eder.
|
|
22
|
+
*
|
|
23
|
+
* @param {{ view: string, data?: object, metadata?: object, head?: string,
|
|
24
|
+
* bodyClass?: string, entries?: string[], styles?: string[],
|
|
25
|
+
* pathname?: string }} page
|
|
26
|
+
* @returns {Promise<string>}
|
|
27
|
+
*/
|
|
28
|
+
export declare function renderPage(page: {
|
|
29
|
+
view: string;
|
|
30
|
+
data?: object;
|
|
31
|
+
metadata?: object;
|
|
32
|
+
head?: string;
|
|
33
|
+
bodyClass?: string;
|
|
34
|
+
entries?: string[];
|
|
35
|
+
styles?: string[];
|
|
36
|
+
pathname?: string;
|
|
37
|
+
}): Promise<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Controller'ı çalıştırıp yanıtı yazar; notFound/redirect kontrol akışını,
|
|
40
|
+
* HTML cache'ini ve hata yönetimini üstlenir.
|
|
41
|
+
*
|
|
42
|
+
* `private: true` kişiye özel sayfaları public cache yolundan tamamen ayırır:
|
|
43
|
+
* HTML cache devre dışı kalır, config'in `cache.html` deseni bu kararı
|
|
44
|
+
* ezemez, yanıt `no-store` ile ve ETag'siz gider. Dashboard tipi sayfalarda
|
|
45
|
+
* bu bayrak olmadan çalışmak, bir kullanıcının HTML'inin bir başkasına
|
|
46
|
+
* servis edilmesi anlamına gelir.
|
|
47
|
+
*
|
|
48
|
+
* @param {(ctx: { params: object, query: object, pathname: string,
|
|
49
|
+
* req: import('express').Request }) => Promise<object>} controller
|
|
50
|
+
* @param {{ revalidate?: number, private?: boolean }} [options]
|
|
51
|
+
* @returns {import('express').RequestHandler}
|
|
52
|
+
*/
|
|
53
|
+
export declare function route(controller: (ctx: {
|
|
54
|
+
params: object;
|
|
55
|
+
query: object;
|
|
56
|
+
pathname: string;
|
|
57
|
+
req: import('express').Request;
|
|
58
|
+
}) => Promise<object>, options?: {
|
|
59
|
+
revalidate?: number;
|
|
60
|
+
private?: boolean;
|
|
61
|
+
}): import('express').RequestHandler;
|
|
62
|
+
/**
|
|
63
|
+
* Layout'suz, asla cache'lenmeyen parça yanıtı.
|
|
64
|
+
*
|
|
65
|
+
* Fragment uçları (tablo sayfası, sekme paneli, canlı tazelenen kart) her
|
|
66
|
+
* projede elle yazılıyor ve `no-store` yazmayı unutmak sessiz bir sızıntıya
|
|
67
|
+
* dönüşüyor. Burada politika sabit: HTML cache'e hiç uğramaz, `no-store` ile
|
|
68
|
+
* ve ETag'siz gider.
|
|
69
|
+
*
|
|
70
|
+
* Hata durumunda tüm sayfa yerine küçük bir hata parçası döner: takas edilen
|
|
71
|
+
* bölge bir hata sayfasının tamamını içine almasın.
|
|
72
|
+
*
|
|
73
|
+
* @param {(ctx: { params: object, query: object, pathname: string,
|
|
74
|
+
* req: import('express').Request }) => Promise<{ view: string, data?: object,
|
|
75
|
+
* status?: number } | string>} controller
|
|
76
|
+
* @returns {import('express').RequestHandler}
|
|
77
|
+
*/
|
|
78
|
+
export declare function fragment(controller: (ctx: {
|
|
79
|
+
params: object;
|
|
80
|
+
query: object;
|
|
81
|
+
pathname: string;
|
|
82
|
+
req: import('express').Request;
|
|
83
|
+
}) => Promise<{
|
|
84
|
+
view: string;
|
|
85
|
+
data?: object;
|
|
86
|
+
status?: number;
|
|
87
|
+
} | string>): import('express').RequestHandler;
|
|
88
|
+
export type Produced = {
|
|
89
|
+
html: string;
|
|
90
|
+
status: number;
|
|
91
|
+
degraded?: boolean;
|
|
92
|
+
storable?: boolean;
|
|
93
|
+
retryAfter?: number;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* 404 sayfası. `renderStatusPage(404)` için kısayol; route dosyalarında en sık
|
|
97
|
+
* ihtiyaç duyulan durum bu olduğu için ayrı bir ad taşımaya devam ediyor.
|
|
98
|
+
*
|
|
99
|
+
* @returns {Promise<string>}
|
|
100
|
+
*/
|
|
101
|
+
export declare function renderNotFound(): Promise<string>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durum koduna karşılık gelen sayfayı üretir. Hiçbir koşulda fırlatmaz:
|
|
3
|
+
* hata sayfasının kendisi patlarsa ziyaretçi boş yanıt görür, bu yüzden her
|
|
4
|
+
* başarısızlık gömülü HTML'e düşer.
|
|
5
|
+
*
|
|
6
|
+
* Development'ta 5xx yanıtları `hooks.error` ve gömülü 500 sayfasını atlar;
|
|
7
|
+
* yığın izini içeren bir teşhis sayfası döner. Production'da ayrıntı
|
|
8
|
+
* gösterilmez — sunucu içi ziyaretçiye açılmaz.
|
|
9
|
+
*
|
|
10
|
+
* @param {number} status
|
|
11
|
+
* @param {{ error?: unknown }} [options]
|
|
12
|
+
* @returns {Promise<string>}
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderStatusPage(status: number, options?: {
|
|
15
|
+
error?: unknown;
|
|
16
|
+
}): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Bir hatadan HTTP durum kodu çıkarır. Uygulama kodu `error.statusCode` ya da
|
|
19
|
+
* `error.status` ile kendi kodunu bildirebilir; tanınmayan her şey 500'dür.
|
|
20
|
+
*
|
|
21
|
+
* @param {unknown} error
|
|
22
|
+
* @returns {number}
|
|
23
|
+
*/
|
|
24
|
+
export declare function statusFromError(error: unknown): number;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
export type HostState = {
|
|
2
|
+
host: string;
|
|
3
|
+
/**
|
|
4
|
+
* Config'te verilen tavan; AIMD bunun üstüne çıkmaz.
|
|
5
|
+
*/
|
|
6
|
+
maxRate: number;
|
|
7
|
+
/**
|
|
8
|
+
* Azalmanın dibi; 0'a inip tamamen kilitlenmesin.
|
|
9
|
+
*/
|
|
10
|
+
minRate: number;
|
|
11
|
+
/**
|
|
12
|
+
* Saniyedeki izin — AIMD bunu oynatır.
|
|
13
|
+
*/
|
|
14
|
+
rate: number;
|
|
15
|
+
/**
|
|
16
|
+
* Kovanın boyu: kısa patlamalara verilen tolerans.
|
|
17
|
+
*/
|
|
18
|
+
burst: number;
|
|
19
|
+
/**
|
|
20
|
+
* Aynı anda uçabilecek çağrı sayısı.
|
|
21
|
+
*/
|
|
22
|
+
concurrency: number;
|
|
23
|
+
tokens: number;
|
|
24
|
+
refilledAt: number;
|
|
25
|
+
/**
|
|
26
|
+
* Uçuştaki çağrı.
|
|
27
|
+
*/
|
|
28
|
+
active: number;
|
|
29
|
+
/**
|
|
30
|
+
* Boş yuva bekleyenler.
|
|
31
|
+
*/
|
|
32
|
+
waiters: (() => void)[];
|
|
33
|
+
/**
|
|
34
|
+
* Admission sırası (FIFO).
|
|
35
|
+
*/
|
|
36
|
+
chain: Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* `Retry-After` boyunca kova tamamen durur.
|
|
39
|
+
*/
|
|
40
|
+
blockedUntil: number;
|
|
41
|
+
consecutiveFailures: number;
|
|
42
|
+
/**
|
|
43
|
+
* Devre kesicinin açık kaldığı an.
|
|
44
|
+
*/
|
|
45
|
+
bypassUntil: number;
|
|
46
|
+
/**
|
|
47
|
+
* Son AIMD kararının zamanı.
|
|
48
|
+
*/
|
|
49
|
+
adjustedAt: number;
|
|
50
|
+
/**
|
|
51
|
+
* Kaç kez 429/503 görüldü (teşhis için).
|
|
52
|
+
*/
|
|
53
|
+
throttled: number;
|
|
54
|
+
/**
|
|
55
|
+
* Devre kesici kaç çağrıyı hiç göndermedi.
|
|
56
|
+
*/
|
|
57
|
+
rejected: number;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* `createApp()` config yüklendikten sonra bir kez çağırır. Ayar değiştiğinde
|
|
61
|
+
* host durumları sıfırlanır: eski `maxRate`'e göre ayarlanmış bir `rate`
|
|
62
|
+
* yeni tavanın üstünde kalabilir.
|
|
63
|
+
*
|
|
64
|
+
* @param {Record<string, unknown> | undefined} config `cache().upstream`
|
|
65
|
+
* @returns {void}
|
|
66
|
+
*/
|
|
67
|
+
export declare function configureUpstreamLimiter(config: Record<string, unknown> | undefined): void;
|
|
68
|
+
/**
|
|
69
|
+
* Çağrı için izin alır. `null` dönerse fren kapalı ya da host çözülemedi;
|
|
70
|
+
* `blocked` dönerse devre kesici açık ve çağrı hiç yapılmamalı.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} url
|
|
73
|
+
* @returns {Promise<{ blocked: boolean, host: string, release: () => void } | null>}
|
|
74
|
+
*/
|
|
75
|
+
export declare function limitUpstream(url: string): Promise<{
|
|
76
|
+
blocked: boolean;
|
|
77
|
+
host: string;
|
|
78
|
+
release: () => void;
|
|
79
|
+
} | null>;
|
|
80
|
+
/**
|
|
81
|
+
* Yanıtın hıza etkisini işler. 429/503 hızı yarıya indirir ve `Retry-After`
|
|
82
|
+
* varsa kovayı o süre boyunca tamamen durdurur; başarı sayaçları sıfırlar.
|
|
83
|
+
*
|
|
84
|
+
* @param {string} host
|
|
85
|
+
* @param {number} status `0` → ağ hatası (yanıt gelmedi).
|
|
86
|
+
* @param {string | null} [retryAfter] `Retry-After` başlığı.
|
|
87
|
+
* @returns {void}
|
|
88
|
+
*/
|
|
89
|
+
export declare function noteUpstreamResponse(host: string, status: number, retryAfter?: string | null): void;
|
|
90
|
+
/**
|
|
91
|
+
* Dev paneli ve teşhis için host başına durum. Fren kapalıysa boş dizi.
|
|
92
|
+
*
|
|
93
|
+
* @returns {{ host: string, rate: number, maxRate: number, concurrency: number,
|
|
94
|
+
* active: number, throttled: number, rejected: number, bypassed: boolean,
|
|
95
|
+
* blockedMs: number, bypassedMs: number }[]}
|
|
96
|
+
*/
|
|
97
|
+
export declare function getUpstreamLimiterStatus(): {
|
|
98
|
+
host: string;
|
|
99
|
+
rate: number;
|
|
100
|
+
maxRate: number;
|
|
101
|
+
concurrency: number;
|
|
102
|
+
active: number;
|
|
103
|
+
throttled: number;
|
|
104
|
+
rejected: number;
|
|
105
|
+
bypassed: boolean;
|
|
106
|
+
blockedMs: number;
|
|
107
|
+
bypassedMs: number;
|
|
108
|
+
}[];
|
|
109
|
+
/**
|
|
110
|
+
* Freni bekleten en uzun süre. Isıtma turunun tekrar denemesi bunu kullanıyor:
|
|
111
|
+
* sabit bir bekleme, kesici 10 saniye açıkken 2 saniye sonra tekrar denemek
|
|
112
|
+
* demekti — yani aynı 429'u peşin peşin almak.
|
|
113
|
+
*
|
|
114
|
+
* @returns {number} ms; fren kapalıysa ya da bekleyen bir şey yoksa 0.
|
|
115
|
+
*/
|
|
116
|
+
export declare function upstreamCooldownMs(): number;
|
|
117
|
+
/**
|
|
118
|
+
* Testler için: ayarları verip tüm host durumlarını sıfırlar.
|
|
119
|
+
*
|
|
120
|
+
* @param {Record<string, unknown>} [config]
|
|
121
|
+
* @returns {void}
|
|
122
|
+
*/
|
|
123
|
+
export declare function resetUpstreamLimiterForTests(config?: Record<string, unknown>): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type UpstreamFailure = {
|
|
2
|
+
status: number;
|
|
3
|
+
path: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* @param {UpstreamFailure} failure
|
|
7
|
+
* @returns {void}
|
|
8
|
+
*/
|
|
9
|
+
export declare function reportUpstreamFailure(failure: UpstreamFailure): void;
|
|
10
|
+
/**
|
|
11
|
+
* @param {number} status
|
|
12
|
+
* @returns {boolean}
|
|
13
|
+
*/
|
|
14
|
+
export declare function isTransientStatus(status: number): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* `globalThis.fetch`i sarıp **geçici** upstream hatalarını kendiliğinden
|
|
17
|
+
* bildirir.
|
|
18
|
+
*
|
|
19
|
+
* Gerekçesi pratik: `reportUpstreamFailure()` sözleşmesi uygulamanın HTTP
|
|
20
|
+
* istemcisine bir satır eklemeyi gerektiriyor ve o satır yazılmadığında
|
|
21
|
+
* framework rate limit'i hiç göremiyor — veri gelmediği için `notFound()`
|
|
22
|
+
* çağıran sayfa 404 olarak servis ediliyordu. Otomatik izleme bu bilgiyi
|
|
23
|
+
* varsayılan hâle getirir; elle çağrı hâlâ geçerli ve tekilleştirilir.
|
|
24
|
+
*
|
|
25
|
+
* Yalnızca geçici durumlar bildirilir. `404`/`403` gibi deterministik
|
|
26
|
+
* cevaplar birçok API'de "böyle bir kayıt yok" anlamına geliyor ve onları
|
|
27
|
+
* otomatik olarak "eksik veri" saymak her sayfada yanlış uyarı üretirdi.
|
|
28
|
+
*
|
|
29
|
+
* Kendi sunucumuza yapılan istekler atlanır: ısıtma turu ve sağlık kontrolü
|
|
30
|
+
* upstream değil.
|
|
31
|
+
*
|
|
32
|
+
* @returns {void}
|
|
33
|
+
*/
|
|
34
|
+
export declare function trackUpstreamFetch(): void;
|
|
35
|
+
/**
|
|
36
|
+
* @param {() => T} run
|
|
37
|
+
* @returns {T}
|
|
38
|
+
* @template T
|
|
39
|
+
*/
|
|
40
|
+
export declare function withUpstreamTracking<T>(run: () => T): T;
|
|
41
|
+
/** @returns {UpstreamFailure[]} */
|
|
42
|
+
export declare function getUpstreamFailures(): UpstreamFailure[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paylaşımlı cookie Domain seçimi — sunucu ve istemci aynı kuralları kullanır.
|
|
3
|
+
*
|
|
4
|
+
* `brand.sharedCookieRoots` örn. `[".investvio.com", ".localhost"]`.
|
|
5
|
+
* Host bu köklerden birine uyuyorsa Domain olarak o kök yazılır.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} host Host veya Host:port.
|
|
9
|
+
* @returns {string} Lowercase, portsuz.
|
|
10
|
+
*/
|
|
11
|
+
export declare function stripHostPort(host: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Kökü `Domain=` biçimine getirir (başında nokta).
|
|
14
|
+
*
|
|
15
|
+
* @param {unknown} root
|
|
16
|
+
* @returns {string | null}
|
|
17
|
+
*/
|
|
18
|
+
export declare function normalizeCookieRoot(root: unknown): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} hostname Portsuz hostname.
|
|
21
|
+
* @param {Iterable<string>} roots `brand.sharedCookieRoots`.
|
|
22
|
+
* @returns {string | null} `Domain` değeri (başında nokta) ya da eşleşme yoksa null.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveSharedCookieDomain(hostname: string, roots: Iterable<string>): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Paylaşımlı cookie için önerilen üst sınır. JWT / büyük token buraya
|
|
27
|
+
* sığmaz — kısa session id koyun; aksi halde handoff veya host-only cookie.
|
|
28
|
+
*/
|
|
29
|
+
export declare const SHARED_COOKIE_WARN_BYTES = 512;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** @generated by scripts/compile-framework-layout.mjs — do not edit */
|
|
2
|
+
/**
|
|
3
|
+
* @param {Record<string, unknown>} data
|
|
4
|
+
* @param {Record<string, any>} helpers
|
|
5
|
+
* @returns {string}
|
|
6
|
+
*/
|
|
7
|
+
export declare function render(data: Record<string, unknown>, helpers: Record<string, any>): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** @type {string} */
|
|
2
|
+
export declare const FRAMEWORK_VERSION: string;
|
|
3
|
+
/** Paket adı: sürüm kontrolü hangi kayıt defteri girdisine bakacağını buradan bilir. */
|
|
4
|
+
export declare const FRAMEWORK_PACKAGE: any;
|
|
5
|
+
/** Künye alanları: yönetim panelinin footer'ı bunları basıyor. */
|
|
6
|
+
export declare const FRAMEWORK_LICENSE: any;
|
|
7
|
+
/** @type {string} */
|
|
8
|
+
export declare const FRAMEWORK_NODE_RANGE: string;
|
|
9
|
+
/** @type {string} */
|
|
10
|
+
export declare const FRAMEWORK_HOMEPAGE: string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metin içeriği ve attribute değerleri için kaçış.
|
|
3
|
+
* @param {unknown} value
|
|
4
|
+
* @returns {string}
|
|
5
|
+
*/
|
|
6
|
+
export declare function esc(value: unknown): string;
|
|
7
|
+
/**
|
|
8
|
+
* `<script type="application/ld+json">` gövdesi için güvenli JSON.
|
|
9
|
+
* `</script`, `<!--` ve U+2028/2029 kaçırılır.
|
|
10
|
+
* @param {unknown} value
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
export declare function jsonScript(value: unknown): string;
|
|
14
|
+
/**
|
|
15
|
+
* Attribute nesnesini string'e çevirir. `false`/`null`/`undefined` atlanır,
|
|
16
|
+
* `true` boolean attribute olarak yazılır.
|
|
17
|
+
* @param {Record<string, unknown>} attrs
|
|
18
|
+
* @returns {string}
|
|
19
|
+
*/
|
|
20
|
+
export declare function attrs(attrs: Record<string, unknown>): string;
|
|
21
|
+
/**
|
|
22
|
+
* `clsx` karşılığı — koşullu sınıf birleştirme, çakışma çözümü yok.
|
|
23
|
+
* @param {...unknown} inputs
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
export declare function cx(...inputs: unknown[]): string;
|
|
27
|
+
/**
|
|
28
|
+
* `lib/ui/cn.js` ile aynı davranış: birleştir, sonra Tailwind çakışmalarını çöz.
|
|
29
|
+
*
|
|
30
|
+
* `tailwind-merge` çalışma zamanı bağımlılığı olarak korunur çünkü sınıf
|
|
31
|
+
* hesabı **yalnızca sunucuda** yapılır — client bundle'a hiç girmez, dolayısıyla
|
|
32
|
+
* sayfa ağırlığına etkisi yoktur. Elle yazılmış bir grup tablosu ise
|
|
33
|
+
* `border-2` + `border-transparent` gibi genişlik/renk çiftlerini birbirine
|
|
34
|
+
* karıştırıp sınıf düşürdüğü için görsel regresyon üretiyordu.
|
|
35
|
+
*
|
|
36
|
+
* @param {...unknown} inputs
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
export declare function cn(...inputs: unknown[]): string;
|