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,188 +1,188 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Route ve view envanteri — admin paneline salt okunur döküm.
|
|
3
|
-
*/
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { getConfig } from "../../config/index.js";
|
|
7
|
-
import { list as listLogs } from "./event-log.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Express router stack'ini dolaşır. İç API kırılgan; yalnızca gözlem için.
|
|
11
|
-
*
|
|
12
|
-
* @param {import('express').Express} app
|
|
13
|
-
* @returns {{ method: string, path: string }[]}
|
|
14
|
-
*/
|
|
15
|
-
export function listExpressRoutes(app) {
|
|
16
|
-
/** @type {{ method: string, path: string }[]} */
|
|
17
|
-
const out = [];
|
|
18
|
-
const stack = /** @type {any} */ (app)?._router?.stack;
|
|
19
|
-
if (!Array.isArray(stack)) return out;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {any[]} layers
|
|
23
|
-
* @param {string} prefix
|
|
24
|
-
*/
|
|
25
|
-
function walk(layers, prefix) {
|
|
26
|
-
for (const layer of layers) {
|
|
27
|
-
if (layer.route) {
|
|
28
|
-
const routePath = joinPath(prefix, layer.route.path);
|
|
29
|
-
const methods = Object.keys(layer.route.methods || {}).filter(
|
|
30
|
-
(name) => layer.route.methods[name],
|
|
31
|
-
);
|
|
32
|
-
for (const method of methods) {
|
|
33
|
-
out.push({ method: method.toUpperCase(), path: routePath });
|
|
34
|
-
}
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (layer.name === "router" && layer.handle?.stack) {
|
|
39
|
-
const mount = layer.regexp ? regexpToPrefix(layer.regexp) : "";
|
|
40
|
-
walk(layer.handle.stack, joinPath(prefix, mount));
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
walk(stack, "");
|
|
46
|
-
return out.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @param {string} a
|
|
51
|
-
* @param {string} b
|
|
52
|
-
* @returns {string}
|
|
53
|
-
*/
|
|
54
|
-
function joinPath(a, b) {
|
|
55
|
-
if (!a) return b || "/";
|
|
56
|
-
if (!b || b === "/") return a || "/";
|
|
57
|
-
return `${a.replace(/\/+$/, "")}/${String(b).replace(/^\/+/, "")}`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Express mount regexp → okunabilir önek. Tam doğruluk şart değil.
|
|
62
|
-
*
|
|
63
|
-
* @param {RegExp} regexp
|
|
64
|
-
* @returns {string}
|
|
65
|
-
*/
|
|
66
|
-
function regexpToPrefix(regexp) {
|
|
67
|
-
const source = regexp.source
|
|
68
|
-
.replace("^\\/", "/")
|
|
69
|
-
.replace("\\/?(?=\\/|$)", "")
|
|
70
|
-
.replace(/\$$/, "")
|
|
71
|
-
.replace(/\\\//g, "/")
|
|
72
|
-
.replace(/\(\?:\(\?=.*$/, "");
|
|
73
|
-
if (!source.startsWith("/")) return "";
|
|
74
|
-
const cleaned = source.replace(/[^a-zA-Z0-9/_\-.:*]/g, "");
|
|
75
|
-
return cleaned || "";
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* `routes/` altındaki (veya config.routes listesindeki) modül dosyaları.
|
|
80
|
-
*
|
|
81
|
-
* @returns {{ file: string, relative: string }[]}
|
|
82
|
-
*/
|
|
83
|
-
export function listRouteModules() {
|
|
84
|
-
const config = getConfig();
|
|
85
|
-
const root = config.root;
|
|
86
|
-
|
|
87
|
-
const files = config.routes
|
|
88
|
-
? config.routes.map((entry) => path.resolve(root, entry))
|
|
89
|
-
: discover(config.dirs.routes);
|
|
90
|
-
|
|
91
|
-
return files.map((file) => ({
|
|
92
|
-
file,
|
|
93
|
-
relative: path.relative(root, file).replaceAll("\\", "/"),
|
|
94
|
-
}));
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* @param {string} dir
|
|
99
|
-
* @param {string[]} [out]
|
|
100
|
-
* @returns {string[]}
|
|
101
|
-
*/
|
|
102
|
-
function discover(dir, out = []) {
|
|
103
|
-
if (!fs.existsSync(dir)) return out;
|
|
104
|
-
|
|
105
|
-
const entries = fs
|
|
106
|
-
.readdirSync(dir, { withFileTypes: true })
|
|
107
|
-
.sort((a, b) => a.name.localeCompare(b.name));
|
|
108
|
-
|
|
109
|
-
for (const entry of entries) {
|
|
110
|
-
const full = path.join(dir, entry.name);
|
|
111
|
-
if (entry.isDirectory()) {
|
|
112
|
-
discover(full, out);
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
if (!/\.(js|mjs)$/.test(entry.name)) continue;
|
|
116
|
-
if (entry.name.startsWith("_")) continue;
|
|
117
|
-
out.push(full);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return out;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* `views/` altındaki şablon ve bileşen dosyaları.
|
|
125
|
-
*
|
|
126
|
-
* @returns {{ relative: string, kind: "ejs" | "js" | "other" }[]}
|
|
127
|
-
*/
|
|
128
|
-
export function listViews() {
|
|
129
|
-
const config = getConfig();
|
|
130
|
-
const root = config.dirs.views;
|
|
131
|
-
/** @type {{ relative: string, kind: "ejs" | "js" | "other" }[]} */
|
|
132
|
-
const out = [];
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* @param {string} dir
|
|
136
|
-
*/
|
|
137
|
-
function walk(dir) {
|
|
138
|
-
if (!fs.existsSync(dir)) return;
|
|
139
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) =>
|
|
140
|
-
a.name.localeCompare(b.name),
|
|
141
|
-
)) {
|
|
142
|
-
const full = path.join(dir, entry.name);
|
|
143
|
-
if (entry.isDirectory()) {
|
|
144
|
-
walk(full);
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
const relative = path.relative(root, full).replaceAll("\\", "/");
|
|
148
|
-
const kind = entry.name.endsWith(".ejs")
|
|
149
|
-
? "ejs"
|
|
150
|
-
: /\.(js|mjs)$/.test(entry.name)
|
|
151
|
-
? "js"
|
|
152
|
-
: "other";
|
|
153
|
-
out.push({ relative, kind });
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
walk(root);
|
|
158
|
-
return out;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Son HTTP log'larından path başına özet.
|
|
163
|
-
*
|
|
164
|
-
* @returns {Record<string, { status: number, ms: number, cache: string | null, at: number, count: number }>}
|
|
165
|
-
*/
|
|
166
|
-
export function routeActivity() {
|
|
167
|
-
/** @type {Record<string, { status: number, ms: number, cache: string | null, at: number, count: number }>} */
|
|
168
|
-
const byPath = {};
|
|
169
|
-
|
|
170
|
-
for (const entry of listLogs(0, 500)) {
|
|
171
|
-
if (entry.kind !== "http") continue;
|
|
172
|
-
const key = typeof entry.route === "string" && entry.route
|
|
173
|
-
? entry.route
|
|
174
|
-
: String(entry.path ?? entry.url ?? "");
|
|
175
|
-
if (!key) continue;
|
|
176
|
-
|
|
177
|
-
const prev = byPath[key];
|
|
178
|
-
byPath[key] = {
|
|
179
|
-
status: Number(entry.status) || 0,
|
|
180
|
-
ms: Number(entry.ms) || 0,
|
|
181
|
-
cache: /** @type {string | null} */ (entry.cache ?? null),
|
|
182
|
-
at: entry.at,
|
|
183
|
-
count: (prev?.count ?? 0) + 1,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return byPath;
|
|
188
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Route ve view envanteri — admin paneline salt okunur döküm.
|
|
3
|
+
*/
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { getConfig } from "../../config/index.js";
|
|
7
|
+
import { list as listLogs } from "./event-log.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Express router stack'ini dolaşır. İç API kırılgan; yalnızca gözlem için.
|
|
11
|
+
*
|
|
12
|
+
* @param {import('express').Express} app
|
|
13
|
+
* @returns {{ method: string, path: string }[]}
|
|
14
|
+
*/
|
|
15
|
+
export function listExpressRoutes(app) {
|
|
16
|
+
/** @type {{ method: string, path: string }[]} */
|
|
17
|
+
const out = [];
|
|
18
|
+
const stack = /** @type {any} */ (app)?._router?.stack;
|
|
19
|
+
if (!Array.isArray(stack)) return out;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {any[]} layers
|
|
23
|
+
* @param {string} prefix
|
|
24
|
+
*/
|
|
25
|
+
function walk(layers, prefix) {
|
|
26
|
+
for (const layer of layers) {
|
|
27
|
+
if (layer.route) {
|
|
28
|
+
const routePath = joinPath(prefix, layer.route.path);
|
|
29
|
+
const methods = Object.keys(layer.route.methods || {}).filter(
|
|
30
|
+
(name) => layer.route.methods[name],
|
|
31
|
+
);
|
|
32
|
+
for (const method of methods) {
|
|
33
|
+
out.push({ method: method.toUpperCase(), path: routePath });
|
|
34
|
+
}
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (layer.name === "router" && layer.handle?.stack) {
|
|
39
|
+
const mount = layer.regexp ? regexpToPrefix(layer.regexp) : "";
|
|
40
|
+
walk(layer.handle.stack, joinPath(prefix, mount));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
walk(stack, "");
|
|
46
|
+
return out.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} a
|
|
51
|
+
* @param {string} b
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
54
|
+
function joinPath(a, b) {
|
|
55
|
+
if (!a) return b || "/";
|
|
56
|
+
if (!b || b === "/") return a || "/";
|
|
57
|
+
return `${a.replace(/\/+$/, "")}/${String(b).replace(/^\/+/, "")}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Express mount regexp → okunabilir önek. Tam doğruluk şart değil.
|
|
62
|
+
*
|
|
63
|
+
* @param {RegExp} regexp
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
66
|
+
function regexpToPrefix(regexp) {
|
|
67
|
+
const source = regexp.source
|
|
68
|
+
.replace("^\\/", "/")
|
|
69
|
+
.replace("\\/?(?=\\/|$)", "")
|
|
70
|
+
.replace(/\$$/, "")
|
|
71
|
+
.replace(/\\\//g, "/")
|
|
72
|
+
.replace(/\(\?:\(\?=.*$/, "");
|
|
73
|
+
if (!source.startsWith("/")) return "";
|
|
74
|
+
const cleaned = source.replace(/[^a-zA-Z0-9/_\-.:*]/g, "");
|
|
75
|
+
return cleaned || "";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* `routes/` altındaki (veya config.routes listesindeki) modül dosyaları.
|
|
80
|
+
*
|
|
81
|
+
* @returns {{ file: string, relative: string }[]}
|
|
82
|
+
*/
|
|
83
|
+
export function listRouteModules() {
|
|
84
|
+
const config = getConfig();
|
|
85
|
+
const root = config.root;
|
|
86
|
+
|
|
87
|
+
const files = config.routes
|
|
88
|
+
? config.routes.map((entry) => path.resolve(root, entry))
|
|
89
|
+
: discover(config.dirs.routes);
|
|
90
|
+
|
|
91
|
+
return files.map((file) => ({
|
|
92
|
+
file,
|
|
93
|
+
relative: path.relative(root, file).replaceAll("\\", "/"),
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} dir
|
|
99
|
+
* @param {string[]} [out]
|
|
100
|
+
* @returns {string[]}
|
|
101
|
+
*/
|
|
102
|
+
function discover(dir, out = []) {
|
|
103
|
+
if (!fs.existsSync(dir)) return out;
|
|
104
|
+
|
|
105
|
+
const entries = fs
|
|
106
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
107
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
108
|
+
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
const full = path.join(dir, entry.name);
|
|
111
|
+
if (entry.isDirectory()) {
|
|
112
|
+
discover(full, out);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (!/\.(js|mjs)$/.test(entry.name)) continue;
|
|
116
|
+
if (entry.name.startsWith("_")) continue;
|
|
117
|
+
out.push(full);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* `views/` altındaki şablon ve bileşen dosyaları.
|
|
125
|
+
*
|
|
126
|
+
* @returns {{ relative: string, kind: "ejs" | "js" | "other" }[]}
|
|
127
|
+
*/
|
|
128
|
+
export function listViews() {
|
|
129
|
+
const config = getConfig();
|
|
130
|
+
const root = config.dirs.views;
|
|
131
|
+
/** @type {{ relative: string, kind: "ejs" | "js" | "other" }[]} */
|
|
132
|
+
const out = [];
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @param {string} dir
|
|
136
|
+
*/
|
|
137
|
+
function walk(dir) {
|
|
138
|
+
if (!fs.existsSync(dir)) return;
|
|
139
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) =>
|
|
140
|
+
a.name.localeCompare(b.name),
|
|
141
|
+
)) {
|
|
142
|
+
const full = path.join(dir, entry.name);
|
|
143
|
+
if (entry.isDirectory()) {
|
|
144
|
+
walk(full);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const relative = path.relative(root, full).replaceAll("\\", "/");
|
|
148
|
+
const kind = entry.name.endsWith(".ejs")
|
|
149
|
+
? "ejs"
|
|
150
|
+
: /\.(js|mjs)$/.test(entry.name)
|
|
151
|
+
? "js"
|
|
152
|
+
: "other";
|
|
153
|
+
out.push({ relative, kind });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
walk(root);
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Son HTTP log'larından path başına özet.
|
|
163
|
+
*
|
|
164
|
+
* @returns {Record<string, { status: number, ms: number, cache: string | null, at: number, count: number }>}
|
|
165
|
+
*/
|
|
166
|
+
export function routeActivity() {
|
|
167
|
+
/** @type {Record<string, { status: number, ms: number, cache: string | null, at: number, count: number }>} */
|
|
168
|
+
const byPath = {};
|
|
169
|
+
|
|
170
|
+
for (const entry of listLogs(0, 500)) {
|
|
171
|
+
if (entry.kind !== "http") continue;
|
|
172
|
+
const key = typeof entry.route === "string" && entry.route
|
|
173
|
+
? entry.route
|
|
174
|
+
: String(entry.path ?? entry.url ?? "");
|
|
175
|
+
if (!key) continue;
|
|
176
|
+
|
|
177
|
+
const prev = byPath[key];
|
|
178
|
+
byPath[key] = {
|
|
179
|
+
status: Number(entry.status) || 0,
|
|
180
|
+
ms: Number(entry.ms) || 0,
|
|
181
|
+
cache: /** @type {string | null} */ (entry.cache ?? null),
|
|
182
|
+
at: entry.at,
|
|
183
|
+
count: (prev?.count ?? 0) + 1,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return byPath;
|
|
188
|
+
}
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Framework yönetim paneli (`/_jskelet/admin`).
|
|
3
|
-
*
|
|
4
|
-
* Dev overlay'den ayrı: `NODE_ENV`'e bakmaz, yalnızca `admin().enabled` /
|
|
5
|
-
* `JSKELET_ADMIN` ile açılır. Kapalıyken modül yüklenmez ve yol yoktur.
|
|
6
|
-
*
|
|
7
|
-
* Şifre süreç başlangıcında üretilir ve log kutusunda bir kez basılır.
|
|
8
|
-
*/
|
|
9
|
-
import process from "node:process";
|
|
10
|
-
import * as log from "../../log.mjs";
|
|
11
|
-
import { getConfig } from "../../config/index.js";
|
|
12
|
-
import { PASSWORD } from "./auth.js";
|
|
13
|
-
import { createAdminRouter } from "./router.js";
|
|
14
|
-
import { configureEventLog, requestLogMiddleware } from "./event-log.js";
|
|
15
|
-
|
|
16
|
-
/** @type {typeof import('../../config/defaults.js').DEFAULT_ADMIN} */
|
|
17
|
-
let settings;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @returns {typeof import('../../config/defaults.js').DEFAULT_ADMIN}
|
|
21
|
-
*/
|
|
22
|
-
function getSettings() {
|
|
23
|
-
return settings;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Paneli uygulamaya bağlar, istek log middleware'ini kurar ve şifreyi loglar.
|
|
28
|
-
*
|
|
29
|
-
* @param {import('express').Express} app
|
|
30
|
-
*/
|
|
31
|
-
export function mountAdmin(app) {
|
|
32
|
-
settings = getConfig().admin;
|
|
33
|
-
|
|
34
|
-
configureEventLog({
|
|
35
|
-
basePath: settings.basePath,
|
|
36
|
-
logSize: settings.logSize,
|
|
37
|
-
prewarmUserAgent: String(getConfig().brand.prewarmUserAgent ?? ""),
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
app.use(settings.basePath, createAdminRouter(getSettings, app));
|
|
41
|
-
// Route'lardan önce mount edilir; `finish` anında Express `req.route`
|
|
42
|
-
// doldurmuş olur. Admin yolları ring'e yazılmaz.
|
|
43
|
-
app.use(requestLogMiddleware());
|
|
44
|
-
|
|
45
|
-
const port = process.env.PORT ?? 3000;
|
|
46
|
-
log.box({
|
|
47
|
-
title: "ADMIN",
|
|
48
|
-
lines: [
|
|
49
|
-
`http://localhost:${port}${settings.basePath}`,
|
|
50
|
-
"",
|
|
51
|
-
`password ${PASSWORD}`,
|
|
52
|
-
"",
|
|
53
|
-
"Valid until this process restarts.",
|
|
54
|
-
],
|
|
55
|
-
});
|
|
56
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Framework yönetim paneli (`/_jskelet/admin`).
|
|
3
|
+
*
|
|
4
|
+
* Dev overlay'den ayrı: `NODE_ENV`'e bakmaz, yalnızca `admin().enabled` /
|
|
5
|
+
* `JSKELET_ADMIN` ile açılır. Kapalıyken modül yüklenmez ve yol yoktur.
|
|
6
|
+
*
|
|
7
|
+
* Şifre süreç başlangıcında üretilir ve log kutusunda bir kez basılır.
|
|
8
|
+
*/
|
|
9
|
+
import process from "node:process";
|
|
10
|
+
import * as log from "../../log.mjs";
|
|
11
|
+
import { getConfig } from "../../config/index.js";
|
|
12
|
+
import { PASSWORD } from "./auth.js";
|
|
13
|
+
import { createAdminRouter } from "./router.js";
|
|
14
|
+
import { configureEventLog, requestLogMiddleware } from "./event-log.js";
|
|
15
|
+
|
|
16
|
+
/** @type {typeof import('../../config/defaults.js').DEFAULT_ADMIN} */
|
|
17
|
+
let settings;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @returns {typeof import('../../config/defaults.js').DEFAULT_ADMIN}
|
|
21
|
+
*/
|
|
22
|
+
function getSettings() {
|
|
23
|
+
return settings;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Paneli uygulamaya bağlar, istek log middleware'ini kurar ve şifreyi loglar.
|
|
28
|
+
*
|
|
29
|
+
* @param {import('express').Express} app
|
|
30
|
+
*/
|
|
31
|
+
export function mountAdmin(app) {
|
|
32
|
+
settings = getConfig().admin;
|
|
33
|
+
|
|
34
|
+
configureEventLog({
|
|
35
|
+
basePath: settings.basePath,
|
|
36
|
+
logSize: settings.logSize,
|
|
37
|
+
prewarmUserAgent: String(getConfig().brand.prewarmUserAgent ?? ""),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
app.use(settings.basePath, createAdminRouter(getSettings, app));
|
|
41
|
+
// Route'lardan önce mount edilir; `finish` anında Express `req.route`
|
|
42
|
+
// doldurmuş olur. Admin yolları ring'e yazılmaz.
|
|
43
|
+
app.use(requestLogMiddleware());
|
|
44
|
+
|
|
45
|
+
const port = process.env.PORT ?? 3000;
|
|
46
|
+
log.box({
|
|
47
|
+
title: "ADMIN",
|
|
48
|
+
lines: [
|
|
49
|
+
`http://localhost:${port}${settings.basePath}`,
|
|
50
|
+
"",
|
|
51
|
+
`password ${PASSWORD}`,
|
|
52
|
+
"",
|
|
53
|
+
"Valid until this process restarts.",
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
}
|