jskelet 0.2.3 → 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.
- package/AGENTS.md +132 -132
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -21
- package/bin/jskelet.mjs +103 -103
- package/docs/01-baslangic.md +285 -285
- package/docs/02-mimari.md +287 -287
- package/docs/03-routing.md +480 -480
- package/docs/04-render-ve-sablonlar.md +490 -490
- package/docs/05-islands.md +482 -482
- package/docs/06-cache.md +1209 -1202
- package/docs/08-build.md +366 -366
- package/docs/09-dev-araclari.md +335 -335
- package/docs/10-dagitim.md +329 -329
- package/docs/12-panel-ve-oturum.md +384 -384
- package/docs/README.md +105 -105
- package/docs/en/01-getting-started.md +292 -292
- package/docs/en/02-architecture.md +305 -305
- package/docs/en/03-routing.md +497 -497
- package/docs/en/04-rendering.md +504 -504
- package/docs/en/05-islands.md +492 -492
- package/docs/en/06-caching.md +1239 -1232
- package/docs/en/07-configuration.md +986 -986
- package/docs/en/08-build.md +383 -383
- package/docs/en/09-dev-tools.md +342 -342
- package/docs/en/10-deployment.md +332 -332
- package/docs/en/11-migration.md +359 -359
- package/docs/en/12-dashboards-and-sessions.md +392 -392
- package/docs/en/README.md +112 -112
- package/package.json +102 -102
- package/src/build/ensure-build.mjs +15 -15
- package/src/build/paths.mjs +143 -143
- package/src/build/resolve-peer.mjs +36 -36
- package/src/build/tasks/client.mjs +268 -268
- package/src/build/tasks/css.mjs +124 -124
- package/src/build/tasks/fonts.mjs +146 -146
- package/src/build/tasks/icons.mjs +224 -224
- package/src/build/tasks/images.mjs +244 -244
- package/src/build/tasks/precompress.mjs +78 -78
- package/src/client/cache-panel/i18n.js +670 -0
- package/src/client/cache-panel/login.html +74 -71
- package/src/client/cache-panel/panel.css +756 -740
- package/src/client/cache-panel/panel.html +308 -307
- package/src/client/cache-panel/panel.js +915 -808
- package/src/client/devtools/report.html +185 -185
- package/src/client/devtools/report.js +725 -725
- package/src/client/dom.js +95 -95
- package/src/client/form.js +192 -192
- package/src/client/index.js +35 -35
- package/src/client/registry.js +297 -297
- package/src/client/safe-image.js +91 -91
- package/src/client/store.js +36 -36
- package/src/client/swap.js +188 -188
- package/src/config/pattern.js +107 -107
- package/src/http/control-flow.js +71 -71
- package/src/http/cookies.js +257 -257
- package/src/http/request-cache.js +46 -46
- package/src/http/request-context.js +162 -162
- package/src/index.js +83 -83
- package/src/init.mjs +221 -221
- package/src/runtime/alias-hooks.mjs +119 -119
- package/src/runtime/register.mjs +4 -4
- package/src/server/assets.js +147 -147
- package/src/server/cache-deps.js +42 -42
- package/src/server/cache-panel.js +759 -738
- package/src/server/cloudflare.js +607 -595
- package/src/server/create-app.js +291 -291
- package/src/server/data-cache.js +462 -462
- package/src/server/dev/report.js +369 -369
- package/src/server/dev/socket.js +170 -170
- package/src/server/dev/version-check.mjs +139 -139
- package/src/server/html-cache.js +817 -817
- 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 +62 -62
- package/src/server/middleware/headers.js +37 -37
- package/src/server/middleware/redirects.js +32 -32
- package/src/server/middleware/static-precompressed.js +100 -100
- package/src/server/middleware/upstream-proxy.js +141 -141
- package/src/server/prewarm.js +601 -601
- package/src/server/redis.js +569 -569
- package/src/server/router.js +128 -128
- package/src/server/status-page.js +164 -164
- package/src/server/upstream-limiter.js +376 -376
- package/src/server/upstream-tracking.js +166 -166
- package/src/start.mjs +7 -7
- package/src/templates/layout.ejs +44 -44
- package/src/version.mjs +31 -31
- package/src/views/components/loader.js +85 -85
- package/src/views/helpers/html.js +102 -102
- package/src/views/helpers/tags.js +245 -245
package/src/config/pattern.js
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `next.config` `source`/`destination` sözdiziminin küçük bir derleyicisi.
|
|
3
|
-
*
|
|
4
|
-
* Desteklenen biçimler:
|
|
5
|
-
* `/haber/:slug` → tek segment yakalar
|
|
6
|
-
* `/:path*` → sıfır veya daha fazla segment yakalar
|
|
7
|
-
* `/:path*.svg` → joker + sabit son ek (uzantı kuralları böyle yazılır)
|
|
8
|
-
* `/etiket-:slug` → segment ortasında parametre
|
|
9
|
-
*
|
|
10
|
-
* Yakalanan değerler `destination` içindeki aynı adlı `:param`'lara yazılır.
|
|
11
|
-
* Next'in tam `path-to-regexp` yüzeyi değil; config'te fiilen kullanılan alt
|
|
12
|
-
* küme bilinçli olarak seçildi ve tanınmayan bir sözdizimi sessizce literal
|
|
13
|
-
* kabul edilmez, uyarı üretir.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/** @typedef {{ regex: RegExp, keys: string[], source: string }} CompiledPattern */
|
|
17
|
-
|
|
18
|
-
const PARAM = /^:([A-Za-z_][A-Za-z0-9_]*)(\*)?/;
|
|
19
|
-
|
|
20
|
-
/** @param {string} text */
|
|
21
|
-
function escapeLiteral(text) {
|
|
22
|
-
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @param {string} source
|
|
27
|
-
* @returns {CompiledPattern | null}
|
|
28
|
-
*/
|
|
29
|
-
export function compilePattern(source) {
|
|
30
|
-
if (typeof source !== "string" || !source.startsWith("/")) {
|
|
31
|
-
console.warn(`[config] invalid source (must start with \`/\`): ${source}`);
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** @type {string[]} */
|
|
36
|
-
const keys = [];
|
|
37
|
-
let pattern = "";
|
|
38
|
-
let index = 0;
|
|
39
|
-
|
|
40
|
-
while (index < source.length) {
|
|
41
|
-
const char = source[index];
|
|
42
|
-
|
|
43
|
-
if (char !== ":") {
|
|
44
|
-
pattern += escapeLiteral(char);
|
|
45
|
-
index += 1;
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const match = source.slice(index).match(PARAM);
|
|
50
|
-
if (!match) {
|
|
51
|
-
pattern += escapeLiteral(char);
|
|
52
|
-
index += 1;
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const [raw, name, wildcard] = match;
|
|
57
|
-
keys.push(name);
|
|
58
|
-
|
|
59
|
-
if (!wildcard) {
|
|
60
|
-
// Tek segmentli parametre segment sınırını aşmaz.
|
|
61
|
-
pattern += "([^/]+)";
|
|
62
|
-
index += raw.length;
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Joker parametre segment sınırlarını aşar ve **sıfır** segment de
|
|
67
|
-
// yakalar: `/hesabim/:path*` kuralı `/hesabim`i de kapsamalı, aksi hâlde
|
|
68
|
-
// bir bölümün tamamını kapatmak isteyen kural kök yolu atlıyor. Bunun için
|
|
69
|
-
// hemen öncesindeki `/` de opsiyonele alınır.
|
|
70
|
-
const trailingSlash = pattern.endsWith("/");
|
|
71
|
-
pattern = trailingSlash ? `${pattern.slice(0, -1)}(?:/(.*))?` : `${pattern}(.*)`;
|
|
72
|
-
index += raw.length;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return { regex: new RegExp(`^${pattern}$`), keys, source };
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @param {CompiledPattern} compiled
|
|
80
|
-
* @param {string} pathname
|
|
81
|
-
* @returns {Record<string, string> | null}
|
|
82
|
-
*/
|
|
83
|
-
export function matchPattern(compiled, pathname) {
|
|
84
|
-
const match = compiled.regex.exec(pathname);
|
|
85
|
-
if (!match) return null;
|
|
86
|
-
|
|
87
|
-
/** @type {Record<string, string>} */
|
|
88
|
-
const params = {};
|
|
89
|
-
compiled.keys.forEach((key, i) => {
|
|
90
|
-
params[key] = match[i + 1] ?? "";
|
|
91
|
-
});
|
|
92
|
-
return params;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* `destination` içindeki `:param` yer tutucularını doldurur.
|
|
97
|
-
*
|
|
98
|
-
* @param {string} destination
|
|
99
|
-
* @param {Record<string, string>} params
|
|
100
|
-
* @returns {string}
|
|
101
|
-
*/
|
|
102
|
-
export function fillDestination(destination, params) {
|
|
103
|
-
return destination.replace(
|
|
104
|
-
/:([A-Za-z_][A-Za-z0-9_]*)(\*)?/g,
|
|
105
|
-
(raw, name) => params[name] ?? raw,
|
|
106
|
-
);
|
|
107
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* `next.config` `source`/`destination` sözdiziminin küçük bir derleyicisi.
|
|
3
|
+
*
|
|
4
|
+
* Desteklenen biçimler:
|
|
5
|
+
* `/haber/:slug` → tek segment yakalar
|
|
6
|
+
* `/:path*` → sıfır veya daha fazla segment yakalar
|
|
7
|
+
* `/:path*.svg` → joker + sabit son ek (uzantı kuralları böyle yazılır)
|
|
8
|
+
* `/etiket-:slug` → segment ortasında parametre
|
|
9
|
+
*
|
|
10
|
+
* Yakalanan değerler `destination` içindeki aynı adlı `:param`'lara yazılır.
|
|
11
|
+
* Next'in tam `path-to-regexp` yüzeyi değil; config'te fiilen kullanılan alt
|
|
12
|
+
* küme bilinçli olarak seçildi ve tanınmayan bir sözdizimi sessizce literal
|
|
13
|
+
* kabul edilmez, uyarı üretir.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** @typedef {{ regex: RegExp, keys: string[], source: string }} CompiledPattern */
|
|
17
|
+
|
|
18
|
+
const PARAM = /^:([A-Za-z_][A-Za-z0-9_]*)(\*)?/;
|
|
19
|
+
|
|
20
|
+
/** @param {string} text */
|
|
21
|
+
function escapeLiteral(text) {
|
|
22
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} source
|
|
27
|
+
* @returns {CompiledPattern | null}
|
|
28
|
+
*/
|
|
29
|
+
export function compilePattern(source) {
|
|
30
|
+
if (typeof source !== "string" || !source.startsWith("/")) {
|
|
31
|
+
console.warn(`[config] invalid source (must start with \`/\`): ${source}`);
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @type {string[]} */
|
|
36
|
+
const keys = [];
|
|
37
|
+
let pattern = "";
|
|
38
|
+
let index = 0;
|
|
39
|
+
|
|
40
|
+
while (index < source.length) {
|
|
41
|
+
const char = source[index];
|
|
42
|
+
|
|
43
|
+
if (char !== ":") {
|
|
44
|
+
pattern += escapeLiteral(char);
|
|
45
|
+
index += 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const match = source.slice(index).match(PARAM);
|
|
50
|
+
if (!match) {
|
|
51
|
+
pattern += escapeLiteral(char);
|
|
52
|
+
index += 1;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const [raw, name, wildcard] = match;
|
|
57
|
+
keys.push(name);
|
|
58
|
+
|
|
59
|
+
if (!wildcard) {
|
|
60
|
+
// Tek segmentli parametre segment sınırını aşmaz.
|
|
61
|
+
pattern += "([^/]+)";
|
|
62
|
+
index += raw.length;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Joker parametre segment sınırlarını aşar ve **sıfır** segment de
|
|
67
|
+
// yakalar: `/hesabim/:path*` kuralı `/hesabim`i de kapsamalı, aksi hâlde
|
|
68
|
+
// bir bölümün tamamını kapatmak isteyen kural kök yolu atlıyor. Bunun için
|
|
69
|
+
// hemen öncesindeki `/` de opsiyonele alınır.
|
|
70
|
+
const trailingSlash = pattern.endsWith("/");
|
|
71
|
+
pattern = trailingSlash ? `${pattern.slice(0, -1)}(?:/(.*))?` : `${pattern}(.*)`;
|
|
72
|
+
index += raw.length;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { regex: new RegExp(`^${pattern}$`), keys, source };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {CompiledPattern} compiled
|
|
80
|
+
* @param {string} pathname
|
|
81
|
+
* @returns {Record<string, string> | null}
|
|
82
|
+
*/
|
|
83
|
+
export function matchPattern(compiled, pathname) {
|
|
84
|
+
const match = compiled.regex.exec(pathname);
|
|
85
|
+
if (!match) return null;
|
|
86
|
+
|
|
87
|
+
/** @type {Record<string, string>} */
|
|
88
|
+
const params = {};
|
|
89
|
+
compiled.keys.forEach((key, i) => {
|
|
90
|
+
params[key] = match[i + 1] ?? "";
|
|
91
|
+
});
|
|
92
|
+
return params;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* `destination` içindeki `:param` yer tutucularını doldurur.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} destination
|
|
99
|
+
* @param {Record<string, string>} params
|
|
100
|
+
* @returns {string}
|
|
101
|
+
*/
|
|
102
|
+
export function fillDestination(destination, params) {
|
|
103
|
+
return destination.replace(
|
|
104
|
+
/:([A-Za-z_][A-Za-z0-9_]*)(\*)?/g,
|
|
105
|
+
(raw, name) => params[name] ?? raw,
|
|
106
|
+
);
|
|
107
|
+
}
|
package/src/http/control-flow.js
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `next/navigation` içindeki notFound/redirect kontrol akışının karşılığı.
|
|
3
|
-
* Derinlerdeki bir fonksiyon throw eder, Express error handler yakalar.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export class NotFoundError extends Error {
|
|
7
|
-
constructor(message = "Not Found") {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = "NotFoundError";
|
|
10
|
-
this.statusCode = 404;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class RedirectError extends Error {
|
|
15
|
-
/**
|
|
16
|
-
* @param {string} location
|
|
17
|
-
* @param {301 | 302 | 303 | 307 | 308} [statusCode]
|
|
18
|
-
*/
|
|
19
|
-
constructor(location, statusCode = 307) {
|
|
20
|
-
super(`Redirect to ${location}`);
|
|
21
|
-
this.name = "RedirectError";
|
|
22
|
-
this.location = location;
|
|
23
|
-
this.statusCode = statusCode;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** @returns {never} */
|
|
28
|
-
export function notFound() {
|
|
29
|
-
throw new NotFoundError();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @param {string} location
|
|
34
|
-
* @returns {never}
|
|
35
|
-
*/
|
|
36
|
-
export function permanentRedirect(location) {
|
|
37
|
-
throw new RedirectError(location, 308);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {string} location
|
|
42
|
-
* @returns {never}
|
|
43
|
-
*/
|
|
44
|
-
export function redirect(location) {
|
|
45
|
-
throw new RedirectError(location, 307);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* POST sonrası yönlendirme (303 See Other).
|
|
50
|
-
*
|
|
51
|
-
* `redirect()` 307 kullanır ve 307 **metodu korur**: bir POST handler'ından
|
|
52
|
-
* çağrıldığında tarayıcı hedefe yeniden POST eder. Form gönderiminden sonra
|
|
53
|
-
* sayfayı GET olarak açmak — yani geri tuşunun formu yeniden göndermediği
|
|
54
|
-
* klasik "post/redirect/get" akışı — 303 gerektiriyor.
|
|
55
|
-
*
|
|
56
|
-
* @param {string} location
|
|
57
|
-
* @returns {never}
|
|
58
|
-
*/
|
|
59
|
-
export function seeOther(location) {
|
|
60
|
-
throw new RedirectError(location, 303);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** @param {unknown} error */
|
|
64
|
-
export function isNotFoundError(error) {
|
|
65
|
-
return error instanceof NotFoundError;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** @param {unknown} error */
|
|
69
|
-
export function isRedirectError(error) {
|
|
70
|
-
return error instanceof RedirectError;
|
|
71
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* `next/navigation` içindeki notFound/redirect kontrol akışının karşılığı.
|
|
3
|
+
* Derinlerdeki bir fonksiyon throw eder, Express error handler yakalar.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class NotFoundError extends Error {
|
|
7
|
+
constructor(message = "Not Found") {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "NotFoundError";
|
|
10
|
+
this.statusCode = 404;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class RedirectError extends Error {
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} location
|
|
17
|
+
* @param {301 | 302 | 303 | 307 | 308} [statusCode]
|
|
18
|
+
*/
|
|
19
|
+
constructor(location, statusCode = 307) {
|
|
20
|
+
super(`Redirect to ${location}`);
|
|
21
|
+
this.name = "RedirectError";
|
|
22
|
+
this.location = location;
|
|
23
|
+
this.statusCode = statusCode;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** @returns {never} */
|
|
28
|
+
export function notFound() {
|
|
29
|
+
throw new NotFoundError();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} location
|
|
34
|
+
* @returns {never}
|
|
35
|
+
*/
|
|
36
|
+
export function permanentRedirect(location) {
|
|
37
|
+
throw new RedirectError(location, 308);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} location
|
|
42
|
+
* @returns {never}
|
|
43
|
+
*/
|
|
44
|
+
export function redirect(location) {
|
|
45
|
+
throw new RedirectError(location, 307);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* POST sonrası yönlendirme (303 See Other).
|
|
50
|
+
*
|
|
51
|
+
* `redirect()` 307 kullanır ve 307 **metodu korur**: bir POST handler'ından
|
|
52
|
+
* çağrıldığında tarayıcı hedefe yeniden POST eder. Form gönderiminden sonra
|
|
53
|
+
* sayfayı GET olarak açmak — yani geri tuşunun formu yeniden göndermediği
|
|
54
|
+
* klasik "post/redirect/get" akışı — 303 gerektiriyor.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} location
|
|
57
|
+
* @returns {never}
|
|
58
|
+
*/
|
|
59
|
+
export function seeOther(location) {
|
|
60
|
+
throw new RedirectError(location, 303);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** @param {unknown} error */
|
|
64
|
+
export function isNotFoundError(error) {
|
|
65
|
+
return error instanceof NotFoundError;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** @param {unknown} error */
|
|
69
|
+
export function isRedirectError(error) {
|
|
70
|
+
return error instanceof RedirectError;
|
|
71
|
+
}
|