jskelet 0.2.2 → 0.2.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/CHANGELOG.md +375 -315
- package/docs/03-routing.md +4 -0
- package/docs/06-cache.md +154 -10
- package/docs/07-yapilandirma.md +63 -2
- package/docs/en/03-routing.md +4 -0
- package/docs/en/06-caching.md +154 -11
- package/docs/en/07-configuration.md +65 -2
- package/package.json +1 -1
- package/src/client/cache-panel/i18n.js +670 -0
- package/src/client/cache-panel/login.html +23 -12
- package/src/client/cache-panel/panel.css +314 -6
- package/src/client/cache-panel/panel.html +205 -30
- package/src/client/cache-panel/panel.js +605 -29
- package/src/config/defaults.js +31 -0
- package/src/config/index.js +87 -2
- package/src/index.js +16 -1
- package/src/log.mjs +25 -0
- package/src/server/cache-panel.js +294 -40
- package/src/server/cloudflare.js +595 -0
- package/src/server/redis.js +108 -0
- package/src/server/render.js +74 -2
- package/src/version.mjs +9 -0
|
@@ -5,16 +5,19 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<meta name="robots" content="noindex, nofollow, noarchive, nosnippet" />
|
|
7
7
|
<meta name="referrer" content="no-referrer" />
|
|
8
|
-
<title>Cache</title>
|
|
8
|
+
<title>Cache · JSkelet</title>
|
|
9
|
+
<link rel="icon" href="logo.png" />
|
|
9
10
|
<link rel="stylesheet" href="panel.css" />
|
|
10
11
|
</head>
|
|
11
12
|
<body class="login">
|
|
12
13
|
<form id="form" autocomplete="off">
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
</
|
|
14
|
+
<div class="brand">
|
|
15
|
+
<img src="logo.png" alt="" width="30" height="30" />
|
|
16
|
+
<span class="wordmark">JSkelet</span>
|
|
17
|
+
<span id="language"></span>
|
|
18
|
+
</div>
|
|
19
|
+
<h1 data-i18n="login.title">Cache panel</h1>
|
|
20
|
+
<p data-i18n-html="login.lead"></p>
|
|
18
21
|
<input
|
|
19
22
|
id="password"
|
|
20
23
|
type="password"
|
|
@@ -22,18 +25,29 @@
|
|
|
22
25
|
maxlength="64"
|
|
23
26
|
spellcheck="false"
|
|
24
27
|
autocomplete="off"
|
|
25
|
-
|
|
28
|
+
data-i18n-ph="login.placeholder"
|
|
26
29
|
autofocus
|
|
27
30
|
/>
|
|
28
|
-
<button class="primary" type="submit">Unlock</button>
|
|
31
|
+
<button class="primary" type="submit" data-i18n="login.submit">Unlock</button>
|
|
29
32
|
<p class="error" id="error"></p>
|
|
33
|
+
<p class="hint m0" data-i18n="login.hint"></p>
|
|
30
34
|
</form>
|
|
31
35
|
|
|
32
36
|
<script type="module">
|
|
37
|
+
import { applyTranslations, languageSelect, t } from "./i18n.js";
|
|
38
|
+
|
|
33
39
|
const form = document.getElementById("form");
|
|
34
40
|
const input = document.getElementById("password");
|
|
35
41
|
const error = document.getElementById("error");
|
|
36
42
|
|
|
43
|
+
// Giriş sayfasında da seçici var: panele girmeden önce dilini seçen biri
|
|
44
|
+
// içeride aynı dili bulmalı, tercih `localStorage`'da taşınıyor.
|
|
45
|
+
document
|
|
46
|
+
.getElementById("language")
|
|
47
|
+
.append(languageSelect(() => applyTranslations()));
|
|
48
|
+
|
|
49
|
+
applyTranslations();
|
|
50
|
+
|
|
37
51
|
form.addEventListener("submit", async (event) => {
|
|
38
52
|
event.preventDefault();
|
|
39
53
|
error.textContent = "";
|
|
@@ -51,10 +65,7 @@
|
|
|
51
65
|
|
|
52
66
|
// Yasaklandıysa sunucu artık 404 dönüyor; kalan deneme sayısı
|
|
53
67
|
// bilinçli olarak bildirilmiyor.
|
|
54
|
-
error.textContent =
|
|
55
|
-
response.status === 404
|
|
56
|
-
? "Too many attempts."
|
|
57
|
-
: "Invalid password.";
|
|
68
|
+
error.textContent = t(response.status === 404 ? "login.tooMany" : "login.invalid");
|
|
58
69
|
input.value = "";
|
|
59
70
|
input.focus();
|
|
60
71
|
});
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
--line: #23272f;
|
|
20
20
|
--text: #e7e9ee;
|
|
21
21
|
--muted: #8b93a1;
|
|
22
|
-
|
|
22
|
+
/* Pazarlama sitesiyle aynı vurgu: cyan. */
|
|
23
|
+
--accent: #22d3ee;
|
|
23
24
|
--ok: #4ade80;
|
|
24
25
|
--warn: #fbbf24;
|
|
25
26
|
--bad: #f87171;
|
|
@@ -33,6 +34,8 @@ body {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
body {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: column;
|
|
36
39
|
min-height: 100vh;
|
|
37
40
|
background:
|
|
38
41
|
radial-gradient(1200px 600px at 20% -10%, #16202f 0%, transparent 60%),
|
|
@@ -78,6 +81,10 @@ a {
|
|
|
78
81
|
box-shadow: 0 24px 60px rgb(0 0 0 / 45%);
|
|
79
82
|
}
|
|
80
83
|
|
|
84
|
+
.login .brand {
|
|
85
|
+
margin-bottom: 16px;
|
|
86
|
+
}
|
|
87
|
+
|
|
81
88
|
.login h1 {
|
|
82
89
|
margin: 0 0 6px;
|
|
83
90
|
font-size: 18px;
|
|
@@ -134,14 +141,120 @@ header {
|
|
|
134
141
|
z-index: 5;
|
|
135
142
|
}
|
|
136
143
|
|
|
137
|
-
header
|
|
138
|
-
|
|
144
|
+
header .spacer {
|
|
145
|
+
flex: 1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* ------------------------------------------------------------------ marka */
|
|
149
|
+
|
|
150
|
+
.brand {
|
|
151
|
+
display: flex;
|
|
152
|
+
gap: 9px;
|
|
153
|
+
align-items: center;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.brand img,
|
|
157
|
+
.foot-brand img {
|
|
158
|
+
object-fit: contain;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.wordmark {
|
|
139
162
|
font-size: 15px;
|
|
140
|
-
font-weight:
|
|
163
|
+
font-weight: 700;
|
|
164
|
+
letter-spacing: -0.03em;
|
|
141
165
|
}
|
|
142
166
|
|
|
143
|
-
|
|
144
|
-
|
|
167
|
+
.badge {
|
|
168
|
+
padding: 2px 8px;
|
|
169
|
+
border: 1px solid color-mix(in oklab, var(--accent) 35%, var(--line));
|
|
170
|
+
border-radius: 999px;
|
|
171
|
+
background: color-mix(in oklab, var(--accent) 12%, transparent);
|
|
172
|
+
color: color-mix(in oklab, var(--accent) 85%, var(--text));
|
|
173
|
+
font-family: ui-monospace, monospace;
|
|
174
|
+
font-size: 11px;
|
|
175
|
+
font-weight: 700;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.crumbs {
|
|
179
|
+
display: flex;
|
|
180
|
+
gap: 8px;
|
|
181
|
+
align-items: center;
|
|
182
|
+
padding-left: 12px;
|
|
183
|
+
border-left: 1px solid var(--line);
|
|
184
|
+
color: var(--text);
|
|
185
|
+
font-size: 13px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* ------------------------------------------------------------------ footer */
|
|
189
|
+
|
|
190
|
+
footer {
|
|
191
|
+
display: flex;
|
|
192
|
+
flex-wrap: wrap;
|
|
193
|
+
gap: 12px 20px;
|
|
194
|
+
align-items: center;
|
|
195
|
+
justify-content: space-between;
|
|
196
|
+
margin-top: auto;
|
|
197
|
+
padding: 18px 20px;
|
|
198
|
+
border-top: 1px solid var(--line);
|
|
199
|
+
background: rgb(18 20 26 / 60%);
|
|
200
|
+
color: var(--muted);
|
|
201
|
+
font-size: 12px;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.foot-brand {
|
|
205
|
+
display: flex;
|
|
206
|
+
gap: 8px;
|
|
207
|
+
align-items: center;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.foot-brand .wordmark {
|
|
211
|
+
font-size: 13px;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.foot-links {
|
|
215
|
+
display: flex;
|
|
216
|
+
flex-wrap: wrap;
|
|
217
|
+
gap: 10px;
|
|
218
|
+
align-items: center;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.foot-links a {
|
|
222
|
+
color: var(--muted);
|
|
223
|
+
text-decoration: none;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.foot-links a:hover {
|
|
227
|
+
color: var(--accent);
|
|
228
|
+
text-decoration: underline;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.dot {
|
|
232
|
+
color: color-mix(in oklab, var(--line) 80%, var(--muted));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.live {
|
|
236
|
+
display: inline-flex;
|
|
237
|
+
gap: 7px;
|
|
238
|
+
align-items: center;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.pulse {
|
|
242
|
+
width: 7px;
|
|
243
|
+
height: 7px;
|
|
244
|
+
border-radius: 999px;
|
|
245
|
+
background: var(--ok);
|
|
246
|
+
box-shadow: 0 0 0 0 color-mix(in oklab, var(--ok) 60%, transparent);
|
|
247
|
+
animation: pulse 2.4s ease-out infinite;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@keyframes pulse {
|
|
251
|
+
70% {
|
|
252
|
+
box-shadow: 0 0 0 6px transparent;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
100% {
|
|
256
|
+
box-shadow: 0 0 0 0 transparent;
|
|
257
|
+
}
|
|
145
258
|
}
|
|
146
259
|
|
|
147
260
|
.chip {
|
|
@@ -322,6 +435,173 @@ label.check {
|
|
|
322
435
|
font-size: 12px;
|
|
323
436
|
}
|
|
324
437
|
|
|
438
|
+
.m0 {
|
|
439
|
+
margin: 0;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/* ------------------------------------------------ anahtar/değer ve ölçüler */
|
|
443
|
+
|
|
444
|
+
.kv {
|
|
445
|
+
display: grid;
|
|
446
|
+
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
|
|
447
|
+
gap: 10px 20px;
|
|
448
|
+
margin: 0;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.kv > div {
|
|
452
|
+
display: flex;
|
|
453
|
+
gap: 10px;
|
|
454
|
+
align-items: baseline;
|
|
455
|
+
justify-content: space-between;
|
|
456
|
+
padding-bottom: 7px;
|
|
457
|
+
border-bottom: 1px solid color-mix(in oklab, var(--line) 60%, transparent);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.kv dt {
|
|
461
|
+
color: var(--muted);
|
|
462
|
+
font-size: 12px;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.kv dd {
|
|
466
|
+
margin: 0;
|
|
467
|
+
font-family: ui-monospace, monospace;
|
|
468
|
+
font-size: 12.5px;
|
|
469
|
+
overflow-wrap: anywhere;
|
|
470
|
+
text-align: right;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.kv dd.on {
|
|
474
|
+
color: var(--ok);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.kv dd.off {
|
|
478
|
+
color: var(--muted);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.kv dd.bad {
|
|
482
|
+
color: var(--bad);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.meter + .meter {
|
|
486
|
+
margin-top: 16px;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.meter-head {
|
|
490
|
+
display: flex;
|
|
491
|
+
gap: 12px;
|
|
492
|
+
align-items: baseline;
|
|
493
|
+
justify-content: space-between;
|
|
494
|
+
margin-bottom: 7px;
|
|
495
|
+
font-size: 12.5px;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.meter-head span:first-child {
|
|
499
|
+
color: var(--muted);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.bar {
|
|
503
|
+
height: 8px;
|
|
504
|
+
border-radius: 999px;
|
|
505
|
+
background: #0d0f14;
|
|
506
|
+
overflow: hidden;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.bar > span {
|
|
510
|
+
display: block;
|
|
511
|
+
width: 0;
|
|
512
|
+
height: 100%;
|
|
513
|
+
border-radius: 999px;
|
|
514
|
+
background: linear-gradient(
|
|
515
|
+
90deg,
|
|
516
|
+
color-mix(in oklab, var(--accent) 70%, transparent),
|
|
517
|
+
var(--accent)
|
|
518
|
+
);
|
|
519
|
+
transition: width 0.3s ease;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.bar > span.warn {
|
|
523
|
+
background: linear-gradient(90deg, color-mix(in oklab, var(--warn) 70%, transparent), var(--warn));
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.bar > span.bad {
|
|
527
|
+
background: linear-gradient(90deg, color-mix(in oklab, var(--bad) 70%, transparent), var(--bad));
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/* ------------------------------------------------------- analitik dökümü */
|
|
531
|
+
|
|
532
|
+
.report {
|
|
533
|
+
margin-top: 14px;
|
|
534
|
+
border: 1px solid var(--line);
|
|
535
|
+
border-radius: var(--radius);
|
|
536
|
+
overflow: hidden;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.report table {
|
|
540
|
+
font-size: 12px;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.report .note {
|
|
544
|
+
padding: 9px 12px;
|
|
545
|
+
border-top: 1px solid var(--line);
|
|
546
|
+
color: var(--muted);
|
|
547
|
+
font-size: 11.5px;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/* Header'daki seçici bir form alanı gibi değil, yanındaki chip'ler gibi
|
|
551
|
+
görünmeli: panelin üst şeridi durum bilgisi taşıyor, kontrol değil. */
|
|
552
|
+
select.lang {
|
|
553
|
+
padding: 5px 7px;
|
|
554
|
+
border: 1px solid var(--line);
|
|
555
|
+
border-radius: 7px;
|
|
556
|
+
background: #0d0f14;
|
|
557
|
+
color: var(--muted);
|
|
558
|
+
font: inherit;
|
|
559
|
+
font-size: 11.5px;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
select.lang:hover {
|
|
563
|
+
color: var(--text);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
select {
|
|
567
|
+
padding: 8px 11px;
|
|
568
|
+
border: 1px solid var(--line);
|
|
569
|
+
border-radius: 8px;
|
|
570
|
+
background: #0d0f14;
|
|
571
|
+
color: var(--text);
|
|
572
|
+
font: inherit;
|
|
573
|
+
font-size: 12.5px;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/* --------------------------------------------------------------- öneri kutusu */
|
|
577
|
+
|
|
578
|
+
.suggest {
|
|
579
|
+
padding: 14px 16px;
|
|
580
|
+
border: 1px dashed color-mix(in oklab, var(--accent) 40%, var(--line));
|
|
581
|
+
border-radius: var(--radius);
|
|
582
|
+
background: color-mix(in oklab, var(--accent) 6%, transparent);
|
|
583
|
+
font-size: 12.5px;
|
|
584
|
+
line-height: 1.6;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
.suggest pre {
|
|
588
|
+
margin: 12px 0 0;
|
|
589
|
+
padding: 10px 12px;
|
|
590
|
+
border: 1px solid var(--line);
|
|
591
|
+
border-radius: 8px;
|
|
592
|
+
background: #0d0f14;
|
|
593
|
+
overflow-x: auto;
|
|
594
|
+
font-size: 12px;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.suggest code {
|
|
598
|
+
color: color-mix(in oklab, var(--accent) 75%, var(--text));
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
.suggest .hint {
|
|
602
|
+
margin-top: 12px;
|
|
603
|
+
}
|
|
604
|
+
|
|
325
605
|
/* -------------------------------------------------------------- sekme/tablo */
|
|
326
606
|
|
|
327
607
|
.tabs {
|
|
@@ -380,6 +660,34 @@ td.key {
|
|
|
380
660
|
overflow-wrap: anywhere;
|
|
381
661
|
}
|
|
382
662
|
|
|
663
|
+
td.key a {
|
|
664
|
+
color: inherit;
|
|
665
|
+
text-decoration: none;
|
|
666
|
+
border-bottom: 1px dotted color-mix(in oklab, var(--accent) 55%, transparent);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
td.key a:hover {
|
|
670
|
+
color: var(--accent);
|
|
671
|
+
border-bottom-color: var(--accent);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/* Kopyalanabilir anahtar: buton gibi davranır, metin gibi görünür. */
|
|
675
|
+
button.as-text {
|
|
676
|
+
padding: 0;
|
|
677
|
+
border: none;
|
|
678
|
+
border-bottom: 1px dotted transparent;
|
|
679
|
+
border-radius: 0;
|
|
680
|
+
background: none;
|
|
681
|
+
color: inherit;
|
|
682
|
+
font: inherit;
|
|
683
|
+
text-align: left;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
button.as-text:hover:not(:disabled) {
|
|
687
|
+
color: var(--accent);
|
|
688
|
+
border-bottom-color: color-mix(in oklab, var(--accent) 55%, transparent);
|
|
689
|
+
}
|
|
690
|
+
|
|
383
691
|
td.num {
|
|
384
692
|
text-align: right;
|
|
385
693
|
white-space: nowrap;
|