jskelet 0.2.5 → 0.3.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.
Files changed (106) hide show
  1. package/AGENTS.md +132 -132
  2. package/CHANGELOG.md +403 -383
  3. package/LICENSE +21 -21
  4. package/bin/jskelet.mjs +103 -103
  5. package/docs/01-baslangic.md +285 -285
  6. package/docs/02-mimari.md +293 -287
  7. package/docs/03-routing.md +486 -480
  8. package/docs/04-render-ve-sablonlar.md +490 -490
  9. package/docs/05-islands.md +482 -482
  10. package/docs/06-cache.md +1231 -1209
  11. package/docs/07-yapilandirma.md +44 -21
  12. package/docs/08-build.md +366 -366
  13. package/docs/09-dev-araclari.md +335 -335
  14. package/docs/10-dagitim.md +329 -329
  15. package/docs/11-tasima.md +1 -0
  16. package/docs/12-panel-ve-oturum.md +384 -384
  17. package/docs/README.md +105 -105
  18. package/docs/en/01-getting-started.md +292 -292
  19. package/docs/en/02-architecture.md +311 -305
  20. package/docs/en/03-routing.md +503 -497
  21. package/docs/en/04-rendering.md +504 -504
  22. package/docs/en/05-islands.md +492 -492
  23. package/docs/en/06-caching.md +1197 -1198
  24. package/docs/en/07-configuration.md +1009 -986
  25. package/docs/en/08-build.md +383 -383
  26. package/docs/en/09-dev-tools.md +342 -342
  27. package/docs/en/10-deployment.md +332 -332
  28. package/docs/en/11-migration.md +360 -359
  29. package/docs/en/12-dashboards-and-sessions.md +392 -392
  30. package/docs/en/README.md +112 -112
  31. package/package.json +102 -102
  32. package/src/build/ensure-build.mjs +15 -15
  33. package/src/build/paths.mjs +143 -143
  34. package/src/build/resolve-peer.mjs +36 -36
  35. package/src/build/tasks/client.mjs +268 -268
  36. package/src/build/tasks/css.mjs +124 -124
  37. package/src/build/tasks/fonts.mjs +146 -146
  38. package/src/build/tasks/icons.mjs +224 -224
  39. package/src/build/tasks/images.mjs +244 -244
  40. package/src/build/tasks/precompress.mjs +78 -78
  41. package/src/client/{cache-panel → admin}/i18n.js +756 -670
  42. package/src/client/{cache-panel → admin}/login.html +74 -74
  43. package/src/client/{cache-panel → admin}/panel.css +804 -756
  44. package/src/client/admin/panel.html +486 -0
  45. package/src/client/{cache-panel → admin}/panel.js +1242 -915
  46. package/src/client/devtools/report.html +185 -185
  47. package/src/client/devtools/report.js +725 -725
  48. package/src/client/dom.js +95 -95
  49. package/src/client/form.js +192 -192
  50. package/src/client/index.js +35 -35
  51. package/src/client/registry.js +297 -297
  52. package/src/client/safe-image.js +91 -91
  53. package/src/client/store.js +36 -36
  54. package/src/client/swap.js +188 -188
  55. package/src/config/defaults.js +16 -7
  56. package/src/config/index.js +38 -22
  57. package/src/config/pattern.js +107 -107
  58. package/src/http/control-flow.js +71 -71
  59. package/src/http/cookies.js +257 -257
  60. package/src/http/request-cache.js +46 -46
  61. package/src/http/request-context.js +162 -162
  62. package/src/index.js +83 -83
  63. package/src/init.mjs +221 -221
  64. package/src/log.mjs +58 -0
  65. package/src/runtime/alias-hooks.mjs +119 -119
  66. package/src/runtime/register.mjs +4 -4
  67. package/src/server/admin/actions.js +229 -0
  68. package/src/server/admin/auth.js +125 -0
  69. package/src/server/admin/event-log.js +151 -0
  70. package/src/server/admin/gate.js +209 -0
  71. package/src/server/admin/inventory.js +188 -0
  72. package/src/server/admin/mount.js +56 -0
  73. package/src/server/admin/router.js +216 -0
  74. package/src/server/admin/snapshot.js +126 -0
  75. package/src/server/assets.js +147 -147
  76. package/src/server/cache-deps.js +42 -42
  77. package/src/server/cloudflare.js +607 -607
  78. package/src/server/create-app.js +295 -291
  79. package/src/server/data-cache.js +462 -462
  80. package/src/server/dev/report.js +369 -369
  81. package/src/server/dev/socket.js +170 -170
  82. package/src/server/dev/version-check.mjs +139 -139
  83. package/src/server/html-cache.js +817 -817
  84. package/src/server/metadata.js +102 -102
  85. package/src/server/middleware/compression.js +205 -205
  86. package/src/server/middleware/csrf.js +134 -134
  87. package/src/server/middleware/dev-gate.js +62 -62
  88. package/src/server/middleware/headers.js +37 -37
  89. package/src/server/middleware/redirects.js +32 -32
  90. package/src/server/middleware/static-precompressed.js +100 -100
  91. package/src/server/middleware/trailing-slash.js +53 -0
  92. package/src/server/middleware/upstream-proxy.js +141 -141
  93. package/src/server/prewarm.js +601 -601
  94. package/src/server/redis.js +569 -569
  95. package/src/server/router.js +128 -128
  96. package/src/server/status-page.js +164 -164
  97. package/src/server/upstream-limiter.js +376 -376
  98. package/src/server/upstream-tracking.js +166 -166
  99. package/src/start.mjs +7 -7
  100. package/src/templates/layout.ejs +44 -44
  101. package/src/version.mjs +31 -31
  102. package/src/views/components/loader.js +85 -85
  103. package/src/views/helpers/html.js +102 -102
  104. package/src/views/helpers/tags.js +245 -245
  105. package/src/client/cache-panel/panel.html +0 -308
  106. package/src/server/cache-panel.js +0 -759
@@ -1,162 +1,162 @@
1
- /**
2
- * İstek başına yaşayan bağlam.
3
- *
4
- * `request-cache.js` ile aynı desen: `AsyncLocalStorage`, bağlam yoksa her şey
5
- * sessizce devre dışı. Ayrı bir modül olmasının sebebi, taşıdığı bilginin
6
- * memoizasyondan farklı olması — burada tutulanlar bir isteğin **cache'lenip
7
- * cache'lenemeyeceğine** dair kararlar:
8
- *
9
- * private → route açıkça "bu sayfa kişiye özel" dedi
10
- * tainted → controller cookie/Authorization okudu, yani çıktı kullanıcıya
11
- * bağlı olabilir; HTML cache'e yazmak sızıntı olur
12
- * csrfToken → bu istek için üretilmiş token; `csrfField()` şablonda basar
13
- * res → token cookie'sini yazabilmek için; başka hiçbir şey için
14
- * kullanılmaz, şablonlara yanıt nesnesi sızmaz
15
- *
16
- * `tainted` bir tahmin değil, gözlem: `markTainted()` yalnızca gerçekten
17
- * kimliğe dokunan bir erişimden sonra çağrılır (bkz. `guardRequest`).
18
- */
19
- import { AsyncLocalStorage } from "node:async_hooks";
20
-
21
- /**
22
- * @typedef {object} RequestContext
23
- * @property {boolean} private Route `private: true` ile mi kaydedildi.
24
- * @property {boolean} tainted Kimliğe bağlı bir veri okundu mu.
25
- * @property {string[]} taintReasons Hangi erişimler işaretledi (teşhis için).
26
- * @property {string | null} csrfToken
27
- * @property {import('express').Response | null} res
28
- */
29
-
30
- /** @type {AsyncLocalStorage<RequestContext>} */
31
- const storage = new AsyncLocalStorage();
32
-
33
- /**
34
- * @param {{ private?: boolean, res?: import('express').Response }} [initial]
35
- * @returns {RequestContext}
36
- */
37
- export function createRequestContext(initial = {}) {
38
- return {
39
- private: initial.private === true,
40
- tainted: false,
41
- taintReasons: [],
42
- csrfToken: null,
43
- res: initial.res ?? null,
44
- };
45
- }
46
-
47
- /**
48
- * İsteği verilen bağlam içinde çalıştırır.
49
- *
50
- * @template T
51
- * @param {RequestContext} context
52
- * @param {() => T} run
53
- * @returns {T}
54
- */
55
- export function withRequestContext(context, run) {
56
- return storage.run(context, run);
57
- }
58
-
59
- /**
60
- * @returns {RequestContext | undefined}
61
- */
62
- export function getRequestContext() {
63
- return storage.getStore();
64
- }
65
-
66
- /**
67
- * Çıktının kullanıcıya bağlı olduğunu bildirir. Bağlam yoksa (script, build,
68
- * fragment dışı kullanım) sessizce yok sayılır.
69
- *
70
- * @param {string} reason Teşhis mesajında görünecek erişim adı.
71
- */
72
- export function markTainted(reason) {
73
- const context = storage.getStore();
74
- if (!context) return;
75
-
76
- context.tainted = true;
77
- if (!context.taintReasons.includes(reason)) {
78
- context.taintReasons.push(reason);
79
- }
80
- }
81
-
82
-
83
- /** Okunması çıktıyı kullanıcıya bağlayan başlıklar. */
84
- const SENSITIVE_HEADERS = new Set([
85
- "cookie",
86
- "authorization",
87
- "proxy-authorization",
88
- ]);
89
-
90
- /** Okunması çıktıyı kullanıcıya bağlayan `req` alanları. */
91
- const SENSITIVE_PROPS = new Set(["cookies", "signedCookies", "session", "user"]);
92
-
93
- /**
94
- * @param {Record<string, unknown>} headers
95
- * @returns {Record<string, unknown>}
96
- */
97
- function guardHeaders(headers) {
98
- return new Proxy(headers, {
99
- get(target, prop, receiver) {
100
- if (typeof prop === "string" && SENSITIVE_HEADERS.has(prop.toLowerCase())) {
101
- markTainted(`req.headers.${prop}`);
102
- }
103
- return Reflect.get(target, prop, receiver);
104
- },
105
- });
106
- }
107
-
108
- /**
109
- * Controller'a giden `req`'i kimliğe dokunan erişimleri işaretleyen bir Proxy
110
- * ile sarar.
111
- *
112
- * Neden gerekli: HTML cache anahtarı yalnızca yol + query. Cookie okuyan bir
113
- * controller cache'lenebilir bir route'a bağlanmışsa bir kullanıcının HTML'i
114
- * bir başkasına servis edilir ve bu hiçbir yerde hata olarak görünmez.
115
- * İşaretleme, sessiz sızıntıyı gürültülü bir uyarıya çeviriyor.
116
- *
117
- * Kapsam bilinçli olarak dar: yalnızca *okuma* yakalanır, yazma ve metot
118
- * çağrıları hedefe dokunulmadan geçer. Proxy'nin prototipi korunduğu için
119
- * `req instanceof IncomingMessage` gibi kontroller etkilenmez.
120
- *
121
- * @param {import('express').Request} req
122
- * @returns {import('express').Request}
123
- */
124
- export function guardRequest(req) {
125
- /** @type {Record<string, unknown> | null} */
126
- let headersProxy = null;
127
-
128
- return new Proxy(req, {
129
- get(target, prop, receiver) {
130
- if (prop === "headers" || prop === "headersDistinct") {
131
- const raw = Reflect.get(target, prop, receiver);
132
- if (!raw || typeof raw !== "object") return raw;
133
- if (prop === "headers") {
134
- headersProxy ??= guardHeaders(/** @type {Record<string, unknown>} */ (raw));
135
- return headersProxy;
136
- }
137
- return guardHeaders(/** @type {Record<string, unknown>} */ (raw));
138
- }
139
-
140
- if (prop === "get" || prop === "header") {
141
- const original = Reflect.get(target, prop, receiver);
142
- if (typeof original !== "function") return original;
143
- return function guardedHeaderLookup(/** @type {string} */ name) {
144
- if (typeof name === "string" && SENSITIVE_HEADERS.has(name.toLowerCase())) {
145
- markTainted(`req.get("${name}")`);
146
- }
147
- return original.call(target, name);
148
- };
149
- }
150
-
151
- if (typeof prop === "string" && SENSITIVE_PROPS.has(prop)) {
152
- markTainted(`req.${prop}`);
153
- }
154
-
155
- const value = Reflect.get(target, prop, receiver);
156
- // Express metotları kendi iç alanlarına `this` üzerinden erişiyor;
157
- // proxy'yi receiver olarak bırakmak bu erişimleri de yakalayıp
158
- // gereksiz işaretlemeye yol açar.
159
- return typeof value === "function" ? value.bind(target) : value;
160
- },
161
- });
162
- }
1
+ /**
2
+ * İstek başına yaşayan bağlam.
3
+ *
4
+ * `request-cache.js` ile aynı desen: `AsyncLocalStorage`, bağlam yoksa her şey
5
+ * sessizce devre dışı. Ayrı bir modül olmasının sebebi, taşıdığı bilginin
6
+ * memoizasyondan farklı olması — burada tutulanlar bir isteğin **cache'lenip
7
+ * cache'lenemeyeceğine** dair kararlar:
8
+ *
9
+ * private → route açıkça "bu sayfa kişiye özel" dedi
10
+ * tainted → controller cookie/Authorization okudu, yani çıktı kullanıcıya
11
+ * bağlı olabilir; HTML cache'e yazmak sızıntı olur
12
+ * csrfToken → bu istek için üretilmiş token; `csrfField()` şablonda basar
13
+ * res → token cookie'sini yazabilmek için; başka hiçbir şey için
14
+ * kullanılmaz, şablonlara yanıt nesnesi sızmaz
15
+ *
16
+ * `tainted` bir tahmin değil, gözlem: `markTainted()` yalnızca gerçekten
17
+ * kimliğe dokunan bir erişimden sonra çağrılır (bkz. `guardRequest`).
18
+ */
19
+ import { AsyncLocalStorage } from "node:async_hooks";
20
+
21
+ /**
22
+ * @typedef {object} RequestContext
23
+ * @property {boolean} private Route `private: true` ile mi kaydedildi.
24
+ * @property {boolean} tainted Kimliğe bağlı bir veri okundu mu.
25
+ * @property {string[]} taintReasons Hangi erişimler işaretledi (teşhis için).
26
+ * @property {string | null} csrfToken
27
+ * @property {import('express').Response | null} res
28
+ */
29
+
30
+ /** @type {AsyncLocalStorage<RequestContext>} */
31
+ const storage = new AsyncLocalStorage();
32
+
33
+ /**
34
+ * @param {{ private?: boolean, res?: import('express').Response }} [initial]
35
+ * @returns {RequestContext}
36
+ */
37
+ export function createRequestContext(initial = {}) {
38
+ return {
39
+ private: initial.private === true,
40
+ tainted: false,
41
+ taintReasons: [],
42
+ csrfToken: null,
43
+ res: initial.res ?? null,
44
+ };
45
+ }
46
+
47
+ /**
48
+ * İsteği verilen bağlam içinde çalıştırır.
49
+ *
50
+ * @template T
51
+ * @param {RequestContext} context
52
+ * @param {() => T} run
53
+ * @returns {T}
54
+ */
55
+ export function withRequestContext(context, run) {
56
+ return storage.run(context, run);
57
+ }
58
+
59
+ /**
60
+ * @returns {RequestContext | undefined}
61
+ */
62
+ export function getRequestContext() {
63
+ return storage.getStore();
64
+ }
65
+
66
+ /**
67
+ * Çıktının kullanıcıya bağlı olduğunu bildirir. Bağlam yoksa (script, build,
68
+ * fragment dışı kullanım) sessizce yok sayılır.
69
+ *
70
+ * @param {string} reason Teşhis mesajında görünecek erişim adı.
71
+ */
72
+ export function markTainted(reason) {
73
+ const context = storage.getStore();
74
+ if (!context) return;
75
+
76
+ context.tainted = true;
77
+ if (!context.taintReasons.includes(reason)) {
78
+ context.taintReasons.push(reason);
79
+ }
80
+ }
81
+
82
+
83
+ /** Okunması çıktıyı kullanıcıya bağlayan başlıklar. */
84
+ const SENSITIVE_HEADERS = new Set([
85
+ "cookie",
86
+ "authorization",
87
+ "proxy-authorization",
88
+ ]);
89
+
90
+ /** Okunması çıktıyı kullanıcıya bağlayan `req` alanları. */
91
+ const SENSITIVE_PROPS = new Set(["cookies", "signedCookies", "session", "user"]);
92
+
93
+ /**
94
+ * @param {Record<string, unknown>} headers
95
+ * @returns {Record<string, unknown>}
96
+ */
97
+ function guardHeaders(headers) {
98
+ return new Proxy(headers, {
99
+ get(target, prop, receiver) {
100
+ if (typeof prop === "string" && SENSITIVE_HEADERS.has(prop.toLowerCase())) {
101
+ markTainted(`req.headers.${prop}`);
102
+ }
103
+ return Reflect.get(target, prop, receiver);
104
+ },
105
+ });
106
+ }
107
+
108
+ /**
109
+ * Controller'a giden `req`'i kimliğe dokunan erişimleri işaretleyen bir Proxy
110
+ * ile sarar.
111
+ *
112
+ * Neden gerekli: HTML cache anahtarı yalnızca yol + query. Cookie okuyan bir
113
+ * controller cache'lenebilir bir route'a bağlanmışsa bir kullanıcının HTML'i
114
+ * bir başkasına servis edilir ve bu hiçbir yerde hata olarak görünmez.
115
+ * İşaretleme, sessiz sızıntıyı gürültülü bir uyarıya çeviriyor.
116
+ *
117
+ * Kapsam bilinçli olarak dar: yalnızca *okuma* yakalanır, yazma ve metot
118
+ * çağrıları hedefe dokunulmadan geçer. Proxy'nin prototipi korunduğu için
119
+ * `req instanceof IncomingMessage` gibi kontroller etkilenmez.
120
+ *
121
+ * @param {import('express').Request} req
122
+ * @returns {import('express').Request}
123
+ */
124
+ export function guardRequest(req) {
125
+ /** @type {Record<string, unknown> | null} */
126
+ let headersProxy = null;
127
+
128
+ return new Proxy(req, {
129
+ get(target, prop, receiver) {
130
+ if (prop === "headers" || prop === "headersDistinct") {
131
+ const raw = Reflect.get(target, prop, receiver);
132
+ if (!raw || typeof raw !== "object") return raw;
133
+ if (prop === "headers") {
134
+ headersProxy ??= guardHeaders(/** @type {Record<string, unknown>} */ (raw));
135
+ return headersProxy;
136
+ }
137
+ return guardHeaders(/** @type {Record<string, unknown>} */ (raw));
138
+ }
139
+
140
+ if (prop === "get" || prop === "header") {
141
+ const original = Reflect.get(target, prop, receiver);
142
+ if (typeof original !== "function") return original;
143
+ return function guardedHeaderLookup(/** @type {string} */ name) {
144
+ if (typeof name === "string" && SENSITIVE_HEADERS.has(name.toLowerCase())) {
145
+ markTainted(`req.get("${name}")`);
146
+ }
147
+ return original.call(target, name);
148
+ };
149
+ }
150
+
151
+ if (typeof prop === "string" && SENSITIVE_PROPS.has(prop)) {
152
+ markTainted(`req.${prop}`);
153
+ }
154
+
155
+ const value = Reflect.get(target, prop, receiver);
156
+ // Express metotları kendi iç alanlarına `this` üzerinden erişiyor;
157
+ // proxy'yi receiver olarak bırakmak bu erişimleri de yakalayıp
158
+ // gereksiz işaretlemeye yol açar.
159
+ return typeof value === "function" ? value.bind(target) : value;
160
+ },
161
+ });
162
+ }
package/src/index.js CHANGED
@@ -1,83 +1,83 @@
1
- /**
2
- * JSkelet sunucu tarafı genel API'si.
3
- *
4
- * `import { route, notFound } from "jskelet"` — route dosyaları ve
5
- * controller'lar bu yüzeyi kullanır. Alt yollardan (`jskelet/server`)
6
- * ithal etmek de mümkün; buradaki liste "kararlı" sayılan yüzeydir.
7
- */
8
- export {
9
- route,
10
- fragment,
11
- renderPage,
12
- renderView,
13
- renderNotFound,
14
- } from "./server/render.js";
15
- export { renderStatusPage, statusFromError } from "./server/status-page.js";
16
- export { createApp, startServer } from "./server/create-app.js";
17
- export {
18
- notFound,
19
- redirect,
20
- permanentRedirect,
21
- seeOther,
22
- isNotFoundError,
23
- isRedirectError,
24
- NotFoundError,
25
- RedirectError,
26
- } from "./http/control-flow.js";
27
- export { cache, withRequestCache } from "./http/request-cache.js";
28
- export {
29
- clearCookie,
30
- getSignedCookie,
31
- parseCookies,
32
- randomToken,
33
- safeEqual,
34
- serializeCookie,
35
- setCookie,
36
- setSignedCookie,
37
- } from "./http/cookies.js";
38
- export { reportUpstreamFailure } from "./server/upstream-tracking.js";
39
- export { asset, hasAsset, optimizedImage, getSpriteIds } from "./server/assets.js";
40
- export { headHints } from "./server/head-hints.js";
41
- export { renderHeadMeta } from "./server/metadata.js";
42
- export {
43
- clearHtmlCache,
44
- dropHtmlCacheKey,
45
- getHtmlCacheEntries,
46
- getHtmlCacheSize,
47
- invalidateHtmlCache,
48
- withHtmlCache,
49
- } from "./server/html-cache.js";
50
- export {
51
- clearDataCache,
52
- dataCache,
53
- dropDataCacheKey,
54
- getDataCacheEntries,
55
- getDataCacheSize,
56
- getDataCacheStats,
57
- withDataCache,
58
- } from "./server/data-cache.js";
59
- // Paylaşımlı önbellek kademesinin durumu. Bağlantı kurulmamışken de güvenle
60
- // çağrılır; healthcheck uçları bunu okuyor.
61
- // `getRedisDetails()` bağlantının nereye kurulduğunu ve hangi türleri
62
- // paylaştığını söyler (şifre asla dönmez); `inspectRedis()` tür başına anahtar
63
- // sayar — bir `SCAN` turu olduğu için istek yolunda çağrılmamalı.
64
- export { getRedisDetails, getRedisStatus, inspectRedis } from "./server/redis.js";
65
- // CDN kademesi. JSkelet'in önbelleği origin önbelleği; ziyaretçinin gördüğü
66
- // kopya edge'de duruyor. Bir içeriği gerçekten tazelemek için ikisini birlikte
67
- // düşürmek gerekiyor: `invalidateHtmlCache()` + `purgeCloudflare()`.
68
- export {
69
- cloudflareConfigured,
70
- fetchCacheAnalytics,
71
- fetchCloudflareOverview,
72
- fetchPathEdges,
73
- getCloudflareStatus,
74
- purgeCloudflare,
75
- toCloudflareUrls,
76
- } from "./server/cloudflare.js";
77
- // Upstream hız freninin host başına durumu: healthcheck ve teşhis uçları için.
78
- export { getUpstreamLimiterStatus } from "./server/upstream-limiter.js";
79
- export { prewarm, prewarmProgress } from "./server/prewarm.js";
80
- export { createProxy } from "./server/middleware/upstream-proxy.js";
81
- export { getConfig, loadConfig } from "./config/index.js";
82
- export { attrs, cn, cx, esc, jsonScript } from "./views/helpers/html.js";
83
- export { csrfField, icon, image, link, preloadImage } from "./views/helpers/tags.js";
1
+ /**
2
+ * JSkelet sunucu tarafı genel API'si.
3
+ *
4
+ * `import { route, notFound } from "jskelet"` — route dosyaları ve
5
+ * controller'lar bu yüzeyi kullanır. Alt yollardan (`jskelet/server`)
6
+ * ithal etmek de mümkün; buradaki liste "kararlı" sayılan yüzeydir.
7
+ */
8
+ export {
9
+ route,
10
+ fragment,
11
+ renderPage,
12
+ renderView,
13
+ renderNotFound,
14
+ } from "./server/render.js";
15
+ export { renderStatusPage, statusFromError } from "./server/status-page.js";
16
+ export { createApp, startServer } from "./server/create-app.js";
17
+ export {
18
+ notFound,
19
+ redirect,
20
+ permanentRedirect,
21
+ seeOther,
22
+ isNotFoundError,
23
+ isRedirectError,
24
+ NotFoundError,
25
+ RedirectError,
26
+ } from "./http/control-flow.js";
27
+ export { cache, withRequestCache } from "./http/request-cache.js";
28
+ export {
29
+ clearCookie,
30
+ getSignedCookie,
31
+ parseCookies,
32
+ randomToken,
33
+ safeEqual,
34
+ serializeCookie,
35
+ setCookie,
36
+ setSignedCookie,
37
+ } from "./http/cookies.js";
38
+ export { reportUpstreamFailure } from "./server/upstream-tracking.js";
39
+ export { asset, hasAsset, optimizedImage, getSpriteIds } from "./server/assets.js";
40
+ export { headHints } from "./server/head-hints.js";
41
+ export { renderHeadMeta } from "./server/metadata.js";
42
+ export {
43
+ clearHtmlCache,
44
+ dropHtmlCacheKey,
45
+ getHtmlCacheEntries,
46
+ getHtmlCacheSize,
47
+ invalidateHtmlCache,
48
+ withHtmlCache,
49
+ } from "./server/html-cache.js";
50
+ export {
51
+ clearDataCache,
52
+ dataCache,
53
+ dropDataCacheKey,
54
+ getDataCacheEntries,
55
+ getDataCacheSize,
56
+ getDataCacheStats,
57
+ withDataCache,
58
+ } from "./server/data-cache.js";
59
+ // Paylaşımlı önbellek kademesinin durumu. Bağlantı kurulmamışken de güvenle
60
+ // çağrılır; healthcheck uçları bunu okuyor.
61
+ // `getRedisDetails()` bağlantının nereye kurulduğunu ve hangi türleri
62
+ // paylaştığını söyler (şifre asla dönmez); `inspectRedis()` tür başına anahtar
63
+ // sayar — bir `SCAN` turu olduğu için istek yolunda çağrılmamalı.
64
+ export { getRedisDetails, getRedisStatus, inspectRedis } from "./server/redis.js";
65
+ // CDN kademesi. JSkelet'in önbelleği origin önbelleği; ziyaretçinin gördüğü
66
+ // kopya edge'de duruyor. Bir içeriği gerçekten tazelemek için ikisini birlikte
67
+ // düşürmek gerekiyor: `invalidateHtmlCache()` + `purgeCloudflare()`.
68
+ export {
69
+ cloudflareConfigured,
70
+ fetchCacheAnalytics,
71
+ fetchCloudflareOverview,
72
+ fetchPathEdges,
73
+ getCloudflareStatus,
74
+ purgeCloudflare,
75
+ toCloudflareUrls,
76
+ } from "./server/cloudflare.js";
77
+ // Upstream hız freninin host başına durumu: healthcheck ve teşhis uçları için.
78
+ export { getUpstreamLimiterStatus } from "./server/upstream-limiter.js";
79
+ export { prewarm, prewarmProgress } from "./server/prewarm.js";
80
+ export { createProxy } from "./server/middleware/upstream-proxy.js";
81
+ export { getConfig, loadConfig } from "./config/index.js";
82
+ export { attrs, cn, cx, esc, jsonScript } from "./views/helpers/html.js";
83
+ export { csrfField, icon, image, link, preloadImage } from "./views/helpers/tags.js";