jskelet 0.6.3 → 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/AGENTS.md +136 -136
- package/CHANGELOG.md +628 -620
- package/LICENSE +21 -21
- package/README.md +2 -0
- package/bin/jskelet.mjs +130 -130
- package/docs/01-baslangic.md +291 -291
- package/docs/02-mimari.md +310 -310
- package/docs/03-routing.md +515 -515
- package/docs/04-render-ve-sablonlar.md +667 -661
- package/docs/05-islands.md +486 -486
- package/docs/06-cache.md +1467 -1443
- package/docs/07-yapilandirma.md +1208 -1197
- package/docs/08-build.md +429 -429
- package/docs/09-dev-araclari.md +364 -364
- package/docs/10-dagitim.md +348 -338
- package/docs/12-panel-ve-oturum.md +479 -478
- package/docs/README.md +83 -83
- package/docs/en/01-getting-started.md +298 -298
- package/docs/en/02-architecture.md +329 -329
- package/docs/en/03-routing.md +531 -531
- package/docs/en/04-rendering.md +675 -669
- package/docs/en/05-islands.md +497 -497
- package/docs/en/06-caching.md +1476 -1453
- package/docs/en/07-configuration.md +1229 -1219
- package/docs/en/08-build.md +447 -447
- package/docs/en/09-dev-tools.md +373 -373
- package/docs/en/10-deployment.md +351 -340
- package/docs/en/11-migration.md +398 -398
- package/docs/en/12-dashboards-and-sessions.md +489 -488
- package/docs/en/README.md +87 -87
- package/package.json +137 -137
- package/src/build/ensure-build.mjs +19 -19
- package/src/build/paths.mjs +153 -153
- package/src/build/resolve-peer.mjs +36 -36
- package/src/build/tasks/client.mjs +349 -349
- package/src/build/tasks/css.mjs +235 -235
- package/src/build/tasks/fonts.mjs +146 -146
- package/src/build/tasks/icons.mjs +357 -357
- package/src/build/tasks/images.mjs +244 -244
- package/src/build/tasks/precompress.mjs +78 -78
- package/src/build/tasks/templates.mjs +20 -20
- package/src/client/admin/i18n.js +764 -764
- package/src/client/admin/login.html +74 -74
- package/src/client/admin/panel.css +809 -809
- package/src/client/admin/panel.html +495 -495
- package/src/client/admin/panel.js +1251 -1251
- package/src/client/devtools/report.html +185 -185
- package/src/client/devtools/report.js +745 -745
- package/src/client/devtools/seo.js +628 -628
- package/src/client/dom.js +95 -95
- package/src/client/form.js +192 -192
- package/src/client/index.js +45 -45
- package/src/client/registry.js +305 -305
- package/src/client/safe-image.js +91 -91
- package/src/client/shared-cookie.js +225 -225
- package/src/client/store.js +36 -36
- package/src/client/swap.js +188 -188
- package/src/compile/codegen.js +336 -336
- package/src/compile/compile-all.js +149 -149
- package/src/compile/errors.js +66 -66
- package/src/compile/expr.js +409 -409
- package/src/compile/index.js +17 -17
- package/src/compile/parse.js +541 -541
- package/src/compile/resolve.js +211 -211
- package/src/compile/scan-exports.js +51 -51
- package/src/config/defaults.js +541 -534
- package/src/config/index.js +1500 -1469
- package/src/config/pattern.js +107 -107
- package/src/generate.mjs +163 -163
- package/src/http/control-flow.js +71 -71
- package/src/http/cookies-entry.js +21 -21
- package/src/http/cookies.js +277 -277
- package/src/http/request-cache.js +46 -46
- package/src/http/request-context.js +165 -165
- package/src/http/shared-cookie.js +178 -178
- package/src/index.js +101 -101
- package/src/init.mjs +232 -230
- package/src/migrate/apply.mjs +262 -262
- package/src/migrate/babel.mjs +79 -79
- package/src/migrate/classify.mjs +155 -155
- package/src/migrate/config.mjs +126 -126
- package/src/migrate/fs-walk.mjs +191 -191
- package/src/migrate/parse.mjs +26 -26
- package/src/migrate/scan.mjs +177 -177
- package/src/migrate/transform/expr-source.mjs +168 -168
- package/src/migrate/transform/island.mjs +67 -67
- package/src/migrate/transform/jsx-to-component.mjs +302 -302
- package/src/migrate/transform/jsx-to-jsk.mjs +330 -330
- package/src/migrate/transform/page-split.mjs +435 -435
- package/src/migrate/write.mjs +81 -81
- package/src/migrate.mjs +171 -171
- package/src/runtime/alias-hooks.mjs +119 -119
- package/src/runtime/register.mjs +4 -4
- package/src/server/admin/actions.js +229 -229
- package/src/server/admin/auth.js +125 -125
- package/src/server/admin/event-log.js +151 -151
- package/src/server/admin/gate.js +209 -209
- package/src/server/admin/inventory.js +188 -188
- package/src/server/admin/mount.js +56 -56
- package/src/server/admin/router.js +216 -216
- package/src/server/admin/snapshot.js +241 -241
- package/src/server/assets.js +147 -147
- package/src/server/auth/handoff.js +309 -309
- package/src/server/cache-blob.js +70 -70
- package/src/server/cache-control.js +45 -0
- package/src/server/cache-deps.js +42 -42
- package/src/server/cache-vary.js +113 -113
- package/src/server/cloudflare.js +607 -607
- package/src/server/create-app.js +366 -366
- package/src/server/data-cache.js +553 -553
- package/src/server/dev/report.js +485 -485
- package/src/server/dev/socket.js +170 -170
- package/src/server/dev/version-check.mjs +139 -139
- package/src/server/disk-cache.js +233 -233
- package/src/server/ejs-adapter.js +59 -59
- package/src/server/html-cache.js +1196 -1196
- package/src/server/image-optimizer.js +500 -500
- package/src/server/logs/access-middleware.js +66 -66
- package/src/server/logs/file-sink.js +193 -193
- package/src/server/logs/pipeline.js +165 -165
- package/src/server/logs/s3-put.js +214 -214
- package/src/server/logs/s3-sink.js +112 -112
- package/src/server/metadata.js +102 -102
- package/src/server/middleware/compression.js +205 -205
- package/src/server/middleware/csrf.js +134 -134
- package/src/server/middleware/dev-gate.js +75 -75
- package/src/server/middleware/headers.js +37 -37
- package/src/server/middleware/redirects.js +32 -32
- package/src/server/middleware/robots-txt.js +341 -341
- package/src/server/middleware/static-precompressed.js +121 -121
- package/src/server/middleware/trailing-slash.js +53 -53
- package/src/server/middleware/upstream-proxy.js +141 -141
- package/src/server/og-image.js +369 -356
- package/src/server/port-guard.js +255 -255
- package/src/server/prewarm.js +1082 -1082
- package/src/server/redis.js +588 -588
- package/src/server/render.js +910 -910
- package/src/server/router.js +157 -157
- package/src/server/status-page.js +265 -265
- package/src/server/upstream-limiter.js +376 -376
- package/src/server/upstream-tracking.js +166 -166
- package/src/shared/cookie-domain.js +66 -66
- package/src/start.mjs +22 -22
- package/src/templates/layout.ejs +30 -30
- package/src/templates/layout.jsk +30 -30
- package/src/version.mjs +31 -31
- package/src/views/components/loader.js +101 -101
- package/src/views/helpers/html.js +102 -102
- package/src/views/helpers/tags.js +375 -375
- package/types/config/defaults.d.ts +6 -0
- package/types/config/index.d.ts +6 -0
- package/types/server/cache-control.d.ts +28 -0
- package/types/server/og-image.d.ts +5 -0
|
@@ -1,178 +1,178 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Alt alan adları arasında paylaşılan cookie yazma.
|
|
3
|
-
*
|
|
4
|
-
* `Secure` protokole bakılır (`https` / `x-forwarded-proto`), `NODE_ENV`'e değil —
|
|
5
|
-
* yerel https veya prod http yanlış bayrak üretmesin.
|
|
6
|
-
*
|
|
7
|
-
* Domain `brand.sharedCookieRoots` ile seçilir. Eşleşme yoksa ya da değer çok
|
|
8
|
-
* büyükse `{ ok: false, handoff: true }` döner; çağıran handoff yoluna düşer.
|
|
9
|
-
*
|
|
10
|
-
* JWT'yi paylaşımlı cookie'ye koymayın: kısa session id koyun.
|
|
11
|
-
*/
|
|
12
|
-
import { getConfig } from "../config/index.js";
|
|
13
|
-
import {
|
|
14
|
-
SHARED_COOKIE_WARN_BYTES,
|
|
15
|
-
resolveSharedCookieDomain,
|
|
16
|
-
stripHostPort,
|
|
17
|
-
} from "../shared/cookie-domain.js";
|
|
18
|
-
import { clearCookie, setCookie } from "./cookies.js";
|
|
19
|
-
|
|
20
|
-
export {
|
|
21
|
-
SHARED_COOKIE_WARN_BYTES,
|
|
22
|
-
resolveSharedCookieDomain,
|
|
23
|
-
stripHostPort,
|
|
24
|
-
} from "../shared/cookie-domain.js";
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param {{ secure?: boolean, protocol?: string,
|
|
28
|
-
* headers?: Record<string, unknown>, get?: (name: string) => string | undefined }} [req]
|
|
29
|
-
* @returns {boolean}
|
|
30
|
-
*/
|
|
31
|
-
export function requestIsHttps(req) {
|
|
32
|
-
if (!req) return false;
|
|
33
|
-
if (req.secure === true) return true;
|
|
34
|
-
if (typeof req.protocol === "string" && req.protocol === "https") return true;
|
|
35
|
-
|
|
36
|
-
const forwarded =
|
|
37
|
-
req.get?.("x-forwarded-proto") ??
|
|
38
|
-
(typeof req.headers?.["x-forwarded-proto"] === "string"
|
|
39
|
-
? req.headers["x-forwarded-proto"]
|
|
40
|
-
: Array.isArray(req.headers?.["x-forwarded-proto"])
|
|
41
|
-
? req.headers["x-forwarded-proto"][0]
|
|
42
|
-
: "");
|
|
43
|
-
const first = String(forwarded ?? "")
|
|
44
|
-
.split(",")[0]
|
|
45
|
-
.trim()
|
|
46
|
-
.toLowerCase();
|
|
47
|
-
return first === "https";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @param {{ headers?: Record<string, unknown>, get?: (name: string) => string | undefined,
|
|
52
|
-
* hostname?: string }} [req]
|
|
53
|
-
* @returns {string}
|
|
54
|
-
*/
|
|
55
|
-
function hostFromReq(req) {
|
|
56
|
-
if (!req) return "";
|
|
57
|
-
const forwarded =
|
|
58
|
-
req.get?.("x-forwarded-host") ??
|
|
59
|
-
(typeof req.headers?.["x-forwarded-host"] === "string"
|
|
60
|
-
? req.headers["x-forwarded-host"]
|
|
61
|
-
: "");
|
|
62
|
-
const raw =
|
|
63
|
-
forwarded ||
|
|
64
|
-
req.get?.("host") ||
|
|
65
|
-
(typeof req.headers?.host === "string" ? req.headers.host : "") ||
|
|
66
|
-
(typeof req.hostname === "string" ? req.hostname : "");
|
|
67
|
-
return stripHostPort(String(raw).split(",")[0]);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @returns {string[]}
|
|
72
|
-
*/
|
|
73
|
-
function configuredRoots() {
|
|
74
|
-
try {
|
|
75
|
-
const roots = getConfig().brand?.sharedCookieRoots;
|
|
76
|
-
return Array.isArray(roots) ? roots.map(String) : [];
|
|
77
|
-
} catch {
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @typedef {import('./cookies.js').CookieOptions} CookieOptions
|
|
84
|
-
*
|
|
85
|
-
* @typedef {object} SharedCookieResult
|
|
86
|
-
* @property {boolean} ok Domain seçildi ve Set-Cookie yazıldı.
|
|
87
|
-
* @property {string | null} domain Yazılan Domain ya da null.
|
|
88
|
-
* @property {boolean} handoff ok değilse çağıran handoff denemeli.
|
|
89
|
-
* @property {string} [reason] Teşhis.
|
|
90
|
-
*/
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Paylaşımlı Domain ile cookie yazar.
|
|
94
|
-
*
|
|
95
|
-
* @param {import('http').ServerResponse & { req?: import('http').IncomingMessage }} res
|
|
96
|
-
* @param {string} name
|
|
97
|
-
* @param {string} value Kısa session id — JWT değil.
|
|
98
|
-
* @param {CookieOptions & { req?: import('http').IncomingMessage, roots?: string[],
|
|
99
|
-
* host?: string }} [options]
|
|
100
|
-
* @returns {SharedCookieResult}
|
|
101
|
-
*/
|
|
102
|
-
export function writeSharedCookie(res, name, value, options = {}) {
|
|
103
|
-
const { req: optReq, roots: optRoots, host: optHost, ...cookieOpts } = options;
|
|
104
|
-
const req = optReq ?? /** @type {{ req?: import('http').IncomingMessage }} */ (res).req;
|
|
105
|
-
const roots = optRoots ?? configuredRoots();
|
|
106
|
-
const host = optHost ? stripHostPort(optHost) : hostFromReq(req);
|
|
107
|
-
const domain = resolveSharedCookieDomain(host, roots);
|
|
108
|
-
|
|
109
|
-
if (!domain) {
|
|
110
|
-
return {
|
|
111
|
-
ok: false,
|
|
112
|
-
domain: null,
|
|
113
|
-
handoff: true,
|
|
114
|
-
reason: "no-matching-root",
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const text = String(value ?? "");
|
|
119
|
-
if (Buffer.byteLength(text, "utf8") > SHARED_COOKIE_WARN_BYTES) {
|
|
120
|
-
console.warn(
|
|
121
|
-
`[cookies] shared cookie "${name}" is ${Buffer.byteLength(text, "utf8")} bytes; ` +
|
|
122
|
-
`prefer a short session id (≤${SHARED_COOKIE_WARN_BYTES}). Large tokens do not belong in shared cookies.`,
|
|
123
|
-
);
|
|
124
|
-
return {
|
|
125
|
-
ok: false,
|
|
126
|
-
domain,
|
|
127
|
-
handoff: true,
|
|
128
|
-
reason: "value-too-large",
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const secure = cookieOpts.secure ?? requestIsHttps(req);
|
|
133
|
-
|
|
134
|
-
setCookie(res, name, text, {
|
|
135
|
-
...cookieOpts,
|
|
136
|
-
domain,
|
|
137
|
-
secure,
|
|
138
|
-
// Paylaşımlı oturum kimliği JS'ye gerekmez; HttpOnly kalsın.
|
|
139
|
-
httpOnly: cookieOpts.httpOnly !== false,
|
|
140
|
-
sameSite: cookieOpts.sameSite ?? "Lax",
|
|
141
|
-
path: cookieOpts.path ?? "/",
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
// Sunucuda document.cookie read-back yok; Domain seçildiyse yazım başarılı sayılır.
|
|
145
|
-
// İstemci `writeSharedCookie` read-back yapar; başarısızsa handoff'a düşer.
|
|
146
|
-
return { ok: true, domain, handoff: false };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Aynı Domain ile cookie siler.
|
|
151
|
-
*
|
|
152
|
-
* @param {import('http').ServerResponse & { req?: import('http').IncomingMessage }} res
|
|
153
|
-
* @param {string} name
|
|
154
|
-
* @param {CookieOptions & { req?: import('http').IncomingMessage, roots?: string[],
|
|
155
|
-
* host?: string }} [options]
|
|
156
|
-
* @returns {SharedCookieResult}
|
|
157
|
-
*/
|
|
158
|
-
export function clearSharedCookie(res, name, options = {}) {
|
|
159
|
-
const { req: optReq, roots: optRoots, host: optHost, ...cookieOpts } = options;
|
|
160
|
-
const req = optReq ?? /** @type {{ req?: import('http').IncomingMessage }} */ (res).req;
|
|
161
|
-
const roots = optRoots ?? configuredRoots();
|
|
162
|
-
const host = optHost ? stripHostPort(optHost) : hostFromReq(req);
|
|
163
|
-
const domain = resolveSharedCookieDomain(host, roots);
|
|
164
|
-
|
|
165
|
-
if (!domain) {
|
|
166
|
-
return { ok: false, domain: null, handoff: false, reason: "no-matching-root" };
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const secure = cookieOpts.secure ?? requestIsHttps(req);
|
|
170
|
-
clearCookie(res, name, {
|
|
171
|
-
...cookieOpts,
|
|
172
|
-
domain,
|
|
173
|
-
secure,
|
|
174
|
-
path: cookieOpts.path ?? "/",
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
return { ok: true, domain, handoff: false };
|
|
178
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Alt alan adları arasında paylaşılan cookie yazma.
|
|
3
|
+
*
|
|
4
|
+
* `Secure` protokole bakılır (`https` / `x-forwarded-proto`), `NODE_ENV`'e değil —
|
|
5
|
+
* yerel https veya prod http yanlış bayrak üretmesin.
|
|
6
|
+
*
|
|
7
|
+
* Domain `brand.sharedCookieRoots` ile seçilir. Eşleşme yoksa ya da değer çok
|
|
8
|
+
* büyükse `{ ok: false, handoff: true }` döner; çağıran handoff yoluna düşer.
|
|
9
|
+
*
|
|
10
|
+
* JWT'yi paylaşımlı cookie'ye koymayın: kısa session id koyun.
|
|
11
|
+
*/
|
|
12
|
+
import { getConfig } from "../config/index.js";
|
|
13
|
+
import {
|
|
14
|
+
SHARED_COOKIE_WARN_BYTES,
|
|
15
|
+
resolveSharedCookieDomain,
|
|
16
|
+
stripHostPort,
|
|
17
|
+
} from "../shared/cookie-domain.js";
|
|
18
|
+
import { clearCookie, setCookie } from "./cookies.js";
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
SHARED_COOKIE_WARN_BYTES,
|
|
22
|
+
resolveSharedCookieDomain,
|
|
23
|
+
stripHostPort,
|
|
24
|
+
} from "../shared/cookie-domain.js";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {{ secure?: boolean, protocol?: string,
|
|
28
|
+
* headers?: Record<string, unknown>, get?: (name: string) => string | undefined }} [req]
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
31
|
+
export function requestIsHttps(req) {
|
|
32
|
+
if (!req) return false;
|
|
33
|
+
if (req.secure === true) return true;
|
|
34
|
+
if (typeof req.protocol === "string" && req.protocol === "https") return true;
|
|
35
|
+
|
|
36
|
+
const forwarded =
|
|
37
|
+
req.get?.("x-forwarded-proto") ??
|
|
38
|
+
(typeof req.headers?.["x-forwarded-proto"] === "string"
|
|
39
|
+
? req.headers["x-forwarded-proto"]
|
|
40
|
+
: Array.isArray(req.headers?.["x-forwarded-proto"])
|
|
41
|
+
? req.headers["x-forwarded-proto"][0]
|
|
42
|
+
: "");
|
|
43
|
+
const first = String(forwarded ?? "")
|
|
44
|
+
.split(",")[0]
|
|
45
|
+
.trim()
|
|
46
|
+
.toLowerCase();
|
|
47
|
+
return first === "https";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {{ headers?: Record<string, unknown>, get?: (name: string) => string | undefined,
|
|
52
|
+
* hostname?: string }} [req]
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
function hostFromReq(req) {
|
|
56
|
+
if (!req) return "";
|
|
57
|
+
const forwarded =
|
|
58
|
+
req.get?.("x-forwarded-host") ??
|
|
59
|
+
(typeof req.headers?.["x-forwarded-host"] === "string"
|
|
60
|
+
? req.headers["x-forwarded-host"]
|
|
61
|
+
: "");
|
|
62
|
+
const raw =
|
|
63
|
+
forwarded ||
|
|
64
|
+
req.get?.("host") ||
|
|
65
|
+
(typeof req.headers?.host === "string" ? req.headers.host : "") ||
|
|
66
|
+
(typeof req.hostname === "string" ? req.hostname : "");
|
|
67
|
+
return stripHostPort(String(raw).split(",")[0]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @returns {string[]}
|
|
72
|
+
*/
|
|
73
|
+
function configuredRoots() {
|
|
74
|
+
try {
|
|
75
|
+
const roots = getConfig().brand?.sharedCookieRoots;
|
|
76
|
+
return Array.isArray(roots) ? roots.map(String) : [];
|
|
77
|
+
} catch {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @typedef {import('./cookies.js').CookieOptions} CookieOptions
|
|
84
|
+
*
|
|
85
|
+
* @typedef {object} SharedCookieResult
|
|
86
|
+
* @property {boolean} ok Domain seçildi ve Set-Cookie yazıldı.
|
|
87
|
+
* @property {string | null} domain Yazılan Domain ya da null.
|
|
88
|
+
* @property {boolean} handoff ok değilse çağıran handoff denemeli.
|
|
89
|
+
* @property {string} [reason] Teşhis.
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Paylaşımlı Domain ile cookie yazar.
|
|
94
|
+
*
|
|
95
|
+
* @param {import('http').ServerResponse & { req?: import('http').IncomingMessage }} res
|
|
96
|
+
* @param {string} name
|
|
97
|
+
* @param {string} value Kısa session id — JWT değil.
|
|
98
|
+
* @param {CookieOptions & { req?: import('http').IncomingMessage, roots?: string[],
|
|
99
|
+
* host?: string }} [options]
|
|
100
|
+
* @returns {SharedCookieResult}
|
|
101
|
+
*/
|
|
102
|
+
export function writeSharedCookie(res, name, value, options = {}) {
|
|
103
|
+
const { req: optReq, roots: optRoots, host: optHost, ...cookieOpts } = options;
|
|
104
|
+
const req = optReq ?? /** @type {{ req?: import('http').IncomingMessage }} */ (res).req;
|
|
105
|
+
const roots = optRoots ?? configuredRoots();
|
|
106
|
+
const host = optHost ? stripHostPort(optHost) : hostFromReq(req);
|
|
107
|
+
const domain = resolveSharedCookieDomain(host, roots);
|
|
108
|
+
|
|
109
|
+
if (!domain) {
|
|
110
|
+
return {
|
|
111
|
+
ok: false,
|
|
112
|
+
domain: null,
|
|
113
|
+
handoff: true,
|
|
114
|
+
reason: "no-matching-root",
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const text = String(value ?? "");
|
|
119
|
+
if (Buffer.byteLength(text, "utf8") > SHARED_COOKIE_WARN_BYTES) {
|
|
120
|
+
console.warn(
|
|
121
|
+
`[cookies] shared cookie "${name}" is ${Buffer.byteLength(text, "utf8")} bytes; ` +
|
|
122
|
+
`prefer a short session id (≤${SHARED_COOKIE_WARN_BYTES}). Large tokens do not belong in shared cookies.`,
|
|
123
|
+
);
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
domain,
|
|
127
|
+
handoff: true,
|
|
128
|
+
reason: "value-too-large",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const secure = cookieOpts.secure ?? requestIsHttps(req);
|
|
133
|
+
|
|
134
|
+
setCookie(res, name, text, {
|
|
135
|
+
...cookieOpts,
|
|
136
|
+
domain,
|
|
137
|
+
secure,
|
|
138
|
+
// Paylaşımlı oturum kimliği JS'ye gerekmez; HttpOnly kalsın.
|
|
139
|
+
httpOnly: cookieOpts.httpOnly !== false,
|
|
140
|
+
sameSite: cookieOpts.sameSite ?? "Lax",
|
|
141
|
+
path: cookieOpts.path ?? "/",
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Sunucuda document.cookie read-back yok; Domain seçildiyse yazım başarılı sayılır.
|
|
145
|
+
// İstemci `writeSharedCookie` read-back yapar; başarısızsa handoff'a düşer.
|
|
146
|
+
return { ok: true, domain, handoff: false };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Aynı Domain ile cookie siler.
|
|
151
|
+
*
|
|
152
|
+
* @param {import('http').ServerResponse & { req?: import('http').IncomingMessage }} res
|
|
153
|
+
* @param {string} name
|
|
154
|
+
* @param {CookieOptions & { req?: import('http').IncomingMessage, roots?: string[],
|
|
155
|
+
* host?: string }} [options]
|
|
156
|
+
* @returns {SharedCookieResult}
|
|
157
|
+
*/
|
|
158
|
+
export function clearSharedCookie(res, name, options = {}) {
|
|
159
|
+
const { req: optReq, roots: optRoots, host: optHost, ...cookieOpts } = options;
|
|
160
|
+
const req = optReq ?? /** @type {{ req?: import('http').IncomingMessage }} */ (res).req;
|
|
161
|
+
const roots = optRoots ?? configuredRoots();
|
|
162
|
+
const host = optHost ? stripHostPort(optHost) : hostFromReq(req);
|
|
163
|
+
const domain = resolveSharedCookieDomain(host, roots);
|
|
164
|
+
|
|
165
|
+
if (!domain) {
|
|
166
|
+
return { ok: false, domain: null, handoff: false, reason: "no-matching-root" };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const secure = cookieOpts.secure ?? requestIsHttps(req);
|
|
170
|
+
clearCookie(res, name, {
|
|
171
|
+
...cookieOpts,
|
|
172
|
+
domain,
|
|
173
|
+
secure,
|
|
174
|
+
path: cookieOpts.path ?? "/",
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return { ok: true, domain, handoff: false };
|
|
178
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,101 +1,101 @@
|
|
|
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 {
|
|
39
|
-
clearSharedCookie,
|
|
40
|
-
requestIsHttps,
|
|
41
|
-
resolveSharedCookieDomain,
|
|
42
|
-
SHARED_COOKIE_WARN_BYTES,
|
|
43
|
-
writeSharedCookie,
|
|
44
|
-
} from "./http/shared-cookie.js";
|
|
45
|
-
export { reportUpstreamFailure } from "./server/upstream-tracking.js";
|
|
46
|
-
export { asset, hasAsset, optimizedImage, getSpriteIds } from "./server/assets.js";
|
|
47
|
-
export { remoteImageUrl, parseAllowedRemoteUrl } from "./server/image-optimizer.js";
|
|
48
|
-
export {
|
|
49
|
-
ImageResponse,
|
|
50
|
-
OG_SIZE,
|
|
51
|
-
buildOgSvg,
|
|
52
|
-
escapeXml,
|
|
53
|
-
ogHandler,
|
|
54
|
-
ogImage,
|
|
55
|
-
sendOgImage,
|
|
56
|
-
wrapText,
|
|
57
|
-
} from "./server/og-image.js";
|
|
58
|
-
export { headHints } from "./server/head-hints.js";
|
|
59
|
-
export { renderHeadMeta } from "./server/metadata.js";
|
|
60
|
-
export {
|
|
61
|
-
clearHtmlCache,
|
|
62
|
-
dropHtmlCacheKey,
|
|
63
|
-
getHtmlCacheEntries,
|
|
64
|
-
getHtmlCacheSize,
|
|
65
|
-
invalidateHtmlCache,
|
|
66
|
-
withHtmlCache,
|
|
67
|
-
} from "./server/html-cache.js";
|
|
68
|
-
export {
|
|
69
|
-
clearDataCache,
|
|
70
|
-
dataCache,
|
|
71
|
-
dropDataCacheKey,
|
|
72
|
-
getDataCacheEntries,
|
|
73
|
-
getDataCacheSize,
|
|
74
|
-
getDataCacheStats,
|
|
75
|
-
withDataCache,
|
|
76
|
-
} from "./server/data-cache.js";
|
|
77
|
-
// Paylaşımlı önbellek kademesinin durumu. Bağlantı kurulmamışken de güvenle
|
|
78
|
-
// çağrılır; healthcheck uçları bunu okuyor.
|
|
79
|
-
// `getRedisDetails()` bağlantının nereye kurulduğunu ve hangi türleri
|
|
80
|
-
// paylaştığını söyler (şifre asla dönmez); `inspectRedis()` tür başına anahtar
|
|
81
|
-
// sayar — bir `SCAN` turu olduğu için istek yolunda çağrılmamalı.
|
|
82
|
-
export { getRedisDetails, getRedisStatus, inspectRedis } from "./server/redis.js";
|
|
83
|
-
// CDN kademesi. JSkelet'in önbelleği origin önbelleği; ziyaretçinin gördüğü
|
|
84
|
-
// kopya edge'de duruyor. Bir içeriği gerçekten tazelemek için ikisini birlikte
|
|
85
|
-
// düşürmek gerekiyor: `invalidateHtmlCache()` + `purgeCloudflare()`.
|
|
86
|
-
export {
|
|
87
|
-
cloudflareConfigured,
|
|
88
|
-
fetchCacheAnalytics,
|
|
89
|
-
fetchCloudflareOverview,
|
|
90
|
-
fetchPathEdges,
|
|
91
|
-
getCloudflareStatus,
|
|
92
|
-
purgeCloudflare,
|
|
93
|
-
toCloudflareUrls,
|
|
94
|
-
} from "./server/cloudflare.js";
|
|
95
|
-
// Upstream hız freninin host başına durumu: healthcheck ve teşhis uçları için.
|
|
96
|
-
export { getUpstreamLimiterStatus } from "./server/upstream-limiter.js";
|
|
97
|
-
export { prewarm, prewarmProgress, extractSameOriginLinks, isOnVisitPrewarm } from "./server/prewarm.js";
|
|
98
|
-
export { createProxy } from "./server/middleware/upstream-proxy.js";
|
|
99
|
-
export { getConfig, loadConfig } from "./config/index.js";
|
|
100
|
-
export { attrs, cn, cx, esc, jsonScript } from "./views/helpers/html.js";
|
|
101
|
-
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 {
|
|
39
|
+
clearSharedCookie,
|
|
40
|
+
requestIsHttps,
|
|
41
|
+
resolveSharedCookieDomain,
|
|
42
|
+
SHARED_COOKIE_WARN_BYTES,
|
|
43
|
+
writeSharedCookie,
|
|
44
|
+
} from "./http/shared-cookie.js";
|
|
45
|
+
export { reportUpstreamFailure } from "./server/upstream-tracking.js";
|
|
46
|
+
export { asset, hasAsset, optimizedImage, getSpriteIds } from "./server/assets.js";
|
|
47
|
+
export { remoteImageUrl, parseAllowedRemoteUrl } from "./server/image-optimizer.js";
|
|
48
|
+
export {
|
|
49
|
+
ImageResponse,
|
|
50
|
+
OG_SIZE,
|
|
51
|
+
buildOgSvg,
|
|
52
|
+
escapeXml,
|
|
53
|
+
ogHandler,
|
|
54
|
+
ogImage,
|
|
55
|
+
sendOgImage,
|
|
56
|
+
wrapText,
|
|
57
|
+
} from "./server/og-image.js";
|
|
58
|
+
export { headHints } from "./server/head-hints.js";
|
|
59
|
+
export { renderHeadMeta } from "./server/metadata.js";
|
|
60
|
+
export {
|
|
61
|
+
clearHtmlCache,
|
|
62
|
+
dropHtmlCacheKey,
|
|
63
|
+
getHtmlCacheEntries,
|
|
64
|
+
getHtmlCacheSize,
|
|
65
|
+
invalidateHtmlCache,
|
|
66
|
+
withHtmlCache,
|
|
67
|
+
} from "./server/html-cache.js";
|
|
68
|
+
export {
|
|
69
|
+
clearDataCache,
|
|
70
|
+
dataCache,
|
|
71
|
+
dropDataCacheKey,
|
|
72
|
+
getDataCacheEntries,
|
|
73
|
+
getDataCacheSize,
|
|
74
|
+
getDataCacheStats,
|
|
75
|
+
withDataCache,
|
|
76
|
+
} from "./server/data-cache.js";
|
|
77
|
+
// Paylaşımlı önbellek kademesinin durumu. Bağlantı kurulmamışken de güvenle
|
|
78
|
+
// çağrılır; healthcheck uçları bunu okuyor.
|
|
79
|
+
// `getRedisDetails()` bağlantının nereye kurulduğunu ve hangi türleri
|
|
80
|
+
// paylaştığını söyler (şifre asla dönmez); `inspectRedis()` tür başına anahtar
|
|
81
|
+
// sayar — bir `SCAN` turu olduğu için istek yolunda çağrılmamalı.
|
|
82
|
+
export { getRedisDetails, getRedisStatus, inspectRedis } from "./server/redis.js";
|
|
83
|
+
// CDN kademesi. JSkelet'in önbelleği origin önbelleği; ziyaretçinin gördüğü
|
|
84
|
+
// kopya edge'de duruyor. Bir içeriği gerçekten tazelemek için ikisini birlikte
|
|
85
|
+
// düşürmek gerekiyor: `invalidateHtmlCache()` + `purgeCloudflare()`.
|
|
86
|
+
export {
|
|
87
|
+
cloudflareConfigured,
|
|
88
|
+
fetchCacheAnalytics,
|
|
89
|
+
fetchCloudflareOverview,
|
|
90
|
+
fetchPathEdges,
|
|
91
|
+
getCloudflareStatus,
|
|
92
|
+
purgeCloudflare,
|
|
93
|
+
toCloudflareUrls,
|
|
94
|
+
} from "./server/cloudflare.js";
|
|
95
|
+
// Upstream hız freninin host başına durumu: healthcheck ve teşhis uçları için.
|
|
96
|
+
export { getUpstreamLimiterStatus } from "./server/upstream-limiter.js";
|
|
97
|
+
export { prewarm, prewarmProgress, extractSameOriginLinks, isOnVisitPrewarm } from "./server/prewarm.js";
|
|
98
|
+
export { createProxy } from "./server/middleware/upstream-proxy.js";
|
|
99
|
+
export { getConfig, loadConfig } from "./config/index.js";
|
|
100
|
+
export { attrs, cn, cx, esc, jsonScript } from "./views/helpers/html.js";
|
|
101
|
+
export { csrfField, icon, image, link, preloadImage } from "./views/helpers/tags.js";
|