jskelet 0.2.4 → 0.2.5

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 (91) hide show
  1. package/AGENTS.md +132 -132
  2. package/CHANGELOG.md +8 -0
  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 +287 -287
  7. package/docs/03-routing.md +480 -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 +1209 -1209
  11. package/docs/08-build.md +366 -366
  12. package/docs/09-dev-araclari.md +335 -335
  13. package/docs/10-dagitim.md +329 -329
  14. package/docs/12-panel-ve-oturum.md +384 -384
  15. package/docs/README.md +105 -105
  16. package/docs/en/01-getting-started.md +292 -292
  17. package/docs/en/02-architecture.md +305 -305
  18. package/docs/en/03-routing.md +497 -497
  19. package/docs/en/04-rendering.md +504 -504
  20. package/docs/en/05-islands.md +492 -492
  21. package/docs/en/06-caching.md +1239 -1239
  22. package/docs/en/07-configuration.md +986 -986
  23. package/docs/en/08-build.md +383 -383
  24. package/docs/en/09-dev-tools.md +342 -342
  25. package/docs/en/10-deployment.md +332 -332
  26. package/docs/en/11-migration.md +359 -359
  27. package/docs/en/12-dashboards-and-sessions.md +392 -392
  28. package/docs/en/README.md +112 -112
  29. package/package.json +102 -102
  30. package/src/build/ensure-build.mjs +15 -15
  31. package/src/build/paths.mjs +143 -143
  32. package/src/build/resolve-peer.mjs +36 -36
  33. package/src/build/tasks/client.mjs +268 -268
  34. package/src/build/tasks/css.mjs +124 -124
  35. package/src/build/tasks/fonts.mjs +146 -146
  36. package/src/build/tasks/icons.mjs +224 -224
  37. package/src/build/tasks/images.mjs +244 -244
  38. package/src/build/tasks/precompress.mjs +78 -78
  39. package/src/client/cache-panel/i18n.js +670 -670
  40. package/src/client/cache-panel/login.html +74 -74
  41. package/src/client/cache-panel/panel.css +756 -756
  42. package/src/client/cache-panel/panel.html +308 -308
  43. package/src/client/cache-panel/panel.js +915 -915
  44. package/src/client/devtools/report.html +185 -185
  45. package/src/client/devtools/report.js +725 -725
  46. package/src/client/dom.js +95 -95
  47. package/src/client/form.js +192 -192
  48. package/src/client/index.js +35 -35
  49. package/src/client/registry.js +297 -297
  50. package/src/client/safe-image.js +91 -91
  51. package/src/client/store.js +36 -36
  52. package/src/client/swap.js +188 -188
  53. package/src/config/pattern.js +107 -107
  54. package/src/http/control-flow.js +71 -71
  55. package/src/http/cookies.js +257 -257
  56. package/src/http/request-cache.js +46 -46
  57. package/src/http/request-context.js +162 -162
  58. package/src/index.js +83 -83
  59. package/src/init.mjs +221 -221
  60. package/src/runtime/alias-hooks.mjs +119 -119
  61. package/src/runtime/register.mjs +4 -4
  62. package/src/server/assets.js +147 -147
  63. package/src/server/cache-deps.js +42 -42
  64. package/src/server/cache-panel.js +759 -759
  65. package/src/server/cloudflare.js +607 -595
  66. package/src/server/create-app.js +291 -291
  67. package/src/server/data-cache.js +462 -462
  68. package/src/server/dev/report.js +369 -369
  69. package/src/server/dev/socket.js +170 -170
  70. package/src/server/dev/version-check.mjs +139 -139
  71. package/src/server/html-cache.js +817 -817
  72. package/src/server/metadata.js +102 -102
  73. package/src/server/middleware/compression.js +205 -205
  74. package/src/server/middleware/csrf.js +134 -134
  75. package/src/server/middleware/dev-gate.js +62 -62
  76. package/src/server/middleware/headers.js +37 -37
  77. package/src/server/middleware/redirects.js +32 -32
  78. package/src/server/middleware/static-precompressed.js +100 -100
  79. package/src/server/middleware/upstream-proxy.js +141 -141
  80. package/src/server/prewarm.js +601 -601
  81. package/src/server/redis.js +569 -569
  82. package/src/server/router.js +128 -128
  83. package/src/server/status-page.js +164 -164
  84. package/src/server/upstream-limiter.js +376 -376
  85. package/src/server/upstream-tracking.js +166 -166
  86. package/src/start.mjs +7 -7
  87. package/src/templates/layout.ejs +44 -44
  88. package/src/version.mjs +31 -31
  89. package/src/views/components/loader.js +85 -85
  90. package/src/views/helpers/html.js +102 -102
  91. package/src/views/helpers/tags.js +245 -245
@@ -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";