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/AGENTS.md
CHANGED
|
@@ -1,132 +1,132 @@
|
|
|
1
|
-
# AGENTS.md
|
|
2
|
-
|
|
3
|
-
Bu depo **JSkelet** framework'ünün kaynağıdır: Express 5 + EJS sunucu render,
|
|
4
|
-
vanilla JS island'lar, Tailwind v4 ve süreç belleğinde yaşayan HTML TTL cache.
|
|
5
|
-
React ve TypeScript yok; düz JavaScript + JSDoc.
|
|
6
|
-
|
|
7
|
-
Bir JSkelet **uygulamasında** çalışıyorsan (framework'ün kendisinde değil), aynı
|
|
8
|
-
kuralların uygulama tarafı karşılıkları için [docs/](./docs/README.md) yeterli;
|
|
9
|
-
özellikle 03, 05 ve 07.
|
|
10
|
-
|
|
11
|
-
## Değişiklik yapmadan önce
|
|
12
|
-
|
|
13
|
-
Framework'ün davranışını değiştiren bir iş alıyorsan ilgili belgeyi oku. Bu
|
|
14
|
-
dosyalar kararların **gerekçelerini** taşıyor ve çoğu "iyileştirme" fikri orada
|
|
15
|
-
zaten tartışılmış:
|
|
16
|
-
|
|
17
|
-
| Dokunacağın yer | Önce oku |
|
|
18
|
-
| --- | --- |
|
|
19
|
-
| `src/server/render.js`, şablonlar | [04-render-ve-sablonlar.md](./docs/04-render-ve-sablonlar.md) |
|
|
20
|
-
| `src/server/html-cache.js`, `route()` | [06-cache.md](./docs/06-cache.md) |
|
|
21
|
-
| `src/server/create-app.js`, middleware | [02-mimari.md](./docs/02-mimari.md) |
|
|
22
|
-
| `src/client/**` | [05-islands.md](./docs/05-islands.md) |
|
|
23
|
-
| `src/build/**` | [08-build.md](./docs/08-build.md) |
|
|
24
|
-
| `src/config/**` | [07-yapilandirma.md](./docs/07-yapilandirma.md) |
|
|
25
|
-
| `src/dev-server.mjs`, `src/server/dev/**` | [09-dev-araclari.md](./docs/09-dev-araclari.md) |
|
|
26
|
-
|
|
27
|
-
Belgeler iki dilde: Türkçesi `docs/`, İngilizcesi `docs/en/` altında ve
|
|
28
|
-
dosyalar birebir eşlenik. Bir belgeyi değiştirdiysen karşılığını da güncelle;
|
|
29
|
-
pazarlama sitesi (`examples/marketing`) bu dosyaları doğrudan `/docs` altında
|
|
30
|
-
servis ettiği için eksik kalan çeviri kullanıcıya görünür.
|
|
31
|
-
|
|
32
|
-
## Doğrulama
|
|
33
|
-
|
|
34
|
-
**Lint yeterli, tam build zorunlu değil.**
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
npm run lint
|
|
38
|
-
npm test # desen derleyicisi ve HTML cache için birim testler
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Davranış değiştiren bir iş yaptıysan örneklerden biriyle uçtan uca dene:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
npm --prefix examples/blog install # ilk seferde
|
|
45
|
-
npm --prefix examples/blog run build
|
|
46
|
-
npm --prefix examples/blog run start # ayrı terminalde
|
|
47
|
-
node examples/blog/smoke.mjs
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
`examples/blog` bilinçli olarak framework'ün her yüzeyini kullanır (dinamik
|
|
51
|
-
route, tüm config bölümleri, fragment, form, prewarm, RSS/sitemap, dört island).
|
|
52
|
-
Bir şeyi bozduysan smoke testi genelde yakalar.
|
|
53
|
-
|
|
54
|
-
## Mimari kurallar
|
|
55
|
-
|
|
56
|
-
**Framework domain bilgisi taşımaz.** `src/` altında hiçbir yerde uygulamaya
|
|
57
|
-
özel URL, marka adı, metin ya da veri şekli olmaz. Uygulamaya ait mantık
|
|
58
|
-
`hooks` üzerinden gelir (`metadata`, `layoutContext`, `notFound`,
|
|
59
|
-
`prewarmPaths`), görünen adlar `brand` üzerinden.
|
|
60
|
-
|
|
61
|
-
**Yol hesabı tek yerde.** Hiçbir modül `../..` sayarak dizin bulmaz;
|
|
62
|
-
`getConfig().dirs` kullanılır. Framework `node_modules/` içine girdiğinde
|
|
63
|
-
göreli yol sayan her satır bozulur.
|
|
64
|
-
|
|
65
|
-
**Yapılandırma hatası siteyi düşürmez.** Bozuk bir `jskelet.config.mjs`, hata
|
|
66
|
-
veren bir `headers()` ya da fırlatan bir hook uyarı basar ve varsayılana döner.
|
|
67
|
-
|
|
68
|
-
**Build çıktısı olmadan da ayağa kalkar.** `asset()` manifest yoksa hash'siz
|
|
69
|
-
yola döner, `hasAsset()` false olur ve layout etiketi basmaz. `jskelet build`
|
|
70
|
-
unutulduğunda hata değil, stilsiz ama çalışan bir sayfa görülür.
|
|
71
|
-
|
|
72
|
-
**Opsiyonel bağımlılıklar sessizce atlanır.** `sharp`, `postcss`,
|
|
73
|
-
`@phosphor-icons/core` yoksa ilgili build adımı çalışmaz. Peer bağımlılıklar
|
|
74
|
-
**uygulamanın** `node_modules`'ünden çözülmeli: `src/build/resolve-peer.mjs`
|
|
75
|
-
içindeki `importFromApp` / `tryImportFromApp` kullanılır, doğrudan `import
|
|
76
|
-
"postcss"` yazılmaz.
|
|
77
|
-
|
|
78
|
-
**Middleware sırası sözleşmedir.** `src/server/create-app.js` başındaki
|
|
79
|
-
numaralı yorum sırayı ve her konumun gerekçesini anlatır. Sıra değiştirmek
|
|
80
|
-
sessiz bozulmalara yol açar; değiştiriyorsan yorumu da güncelle.
|
|
81
|
-
|
|
82
|
-
**Cache'lenen HTML herkese aynı gider.** Kişiye özel hiçbir şey `route()` ile
|
|
83
|
-
render edilen sayfaya girmez. Tema gibi kararlar client'ta, kullanıcıya özel
|
|
84
|
-
parçalar ayrı ve `no-store` işaretli fragment uçlarında.
|
|
85
|
-
|
|
86
|
-
## Kod stili
|
|
87
|
-
|
|
88
|
-
- **JSDoc zorunlu**: dışa açık her fonksiyonda parametre ve dönüş tipleri.
|
|
89
|
-
- **Yorumlar Türkçe** ve *neden*i anlatır. Kodun ne yaptığını tekrar eden yorum
|
|
90
|
-
yazma; bir kararın gerekçesini, bir takası ya da bir tuzağı yaz.
|
|
91
|
-
- Sunucu ve build tarafı `node:` önekli çekirdek modülleri kullanır.
|
|
92
|
-
- `src/client/**` tarayıcıda çalışır: Node API'si, `process` (build sırasında
|
|
93
|
-
değiştirilen `clientEnv` dışında) ve senkron ağ yok.
|
|
94
|
-
- Yeni bir dışa açık yüzey ekliyorsan `package.json` → `exports` ve
|
|
95
|
-
`src/index.js` / `src/client/index.js` barrel'larını güncelle; belgelerde
|
|
96
|
-
yalnızca `exports` haritasındaki belirteçler kullanılır (`jskelet`,
|
|
97
|
-
`jskelet/client`, `jskelet/html`, `jskelet/tags`).
|
|
98
|
-
|
|
99
|
-
## EJS tuzakları
|
|
100
|
-
|
|
101
|
-
- `include` **async**'tir: `await include('partials/x')` yalnızca şablonun kendi
|
|
102
|
-
gövdesinde çalışır. Bir `forEach` callback'i içinde derleme hatası verir —
|
|
103
|
-
`for` döngüsü kullan.
|
|
104
|
-
- `views/components/**` altındaki her named export otomatik olarak şablon local'i
|
|
105
|
-
olur; import gerekmez. Bileşenler EJS değil, HTML string döndüren
|
|
106
|
-
fonksiyonlardır.
|
|
107
|
-
- Şablona giden her kullanıcı verisi `<%= %>` ile ya da `esc()` üzerinden
|
|
108
|
-
geçmeli; `<%- %>` yalnızca güvenli bildiğin HTML için.
|
|
109
|
-
|
|
110
|
-
## Tailwind
|
|
111
|
-
|
|
112
|
-
Sınıf taraması `styles/globals.css` içindeki `@source` direktiflerine bağlıdır
|
|
113
|
-
ve otomatik tespit `source(none)` ile kapatılmıştır. Sınıf kullanmaya başladığın
|
|
114
|
-
yeni bir dizin varsa oraya bir `@source` satırı eklemek gerekir; yoksa sınıflar
|
|
115
|
-
sessizce çıktıdan düşer.
|
|
116
|
-
|
|
117
|
-
## Örnekleri güncel tut
|
|
118
|
-
|
|
119
|
-
Framework'ün genel yüzeyini değiştirdiysen (`route()` imzası, hook adları,
|
|
120
|
-
config alanları, client API'si) `examples/minimal`, `examples/blog` ve
|
|
121
|
-
`examples/marketing`'i de güncelle. Örnekler belgelerdeki kod parçalarının kaynağı; kaymaları en hızlı
|
|
122
|
-
fark edilen yer orası.
|
|
123
|
-
|
|
124
|
-
## Windows notları
|
|
125
|
-
|
|
126
|
-
Bu depo Windows üzerinde geliştiriliyor ve iki tuzak tekrar tekrar çıkıyor:
|
|
127
|
-
|
|
128
|
-
- `--import` argümanı modül belirteci bekler. `H:\...` gibi mutlak bir yol `h:`
|
|
129
|
-
şemalı URL sanılıp reddedilir; `pathToFileURL(...).href` kullan.
|
|
130
|
-
- `fs.watch` bir dosya yazıldığında komşuları için de olay üretebiliyor. Dev
|
|
131
|
-
sunucusu bu yüzden olayları `mtime` karşılaştırmasıyla eler; watcher mantığını
|
|
132
|
-
değiştirirken bu elemeyi kaldırma.
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Bu depo **JSkelet** framework'ünün kaynağıdır: Express 5 + EJS sunucu render,
|
|
4
|
+
vanilla JS island'lar, Tailwind v4 ve süreç belleğinde yaşayan HTML TTL cache.
|
|
5
|
+
React ve TypeScript yok; düz JavaScript + JSDoc.
|
|
6
|
+
|
|
7
|
+
Bir JSkelet **uygulamasında** çalışıyorsan (framework'ün kendisinde değil), aynı
|
|
8
|
+
kuralların uygulama tarafı karşılıkları için [docs/](./docs/README.md) yeterli;
|
|
9
|
+
özellikle 03, 05 ve 07.
|
|
10
|
+
|
|
11
|
+
## Değişiklik yapmadan önce
|
|
12
|
+
|
|
13
|
+
Framework'ün davranışını değiştiren bir iş alıyorsan ilgili belgeyi oku. Bu
|
|
14
|
+
dosyalar kararların **gerekçelerini** taşıyor ve çoğu "iyileştirme" fikri orada
|
|
15
|
+
zaten tartışılmış:
|
|
16
|
+
|
|
17
|
+
| Dokunacağın yer | Önce oku |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `src/server/render.js`, şablonlar | [04-render-ve-sablonlar.md](./docs/04-render-ve-sablonlar.md) |
|
|
20
|
+
| `src/server/html-cache.js`, `route()` | [06-cache.md](./docs/06-cache.md) |
|
|
21
|
+
| `src/server/create-app.js`, middleware | [02-mimari.md](./docs/02-mimari.md) |
|
|
22
|
+
| `src/client/**` | [05-islands.md](./docs/05-islands.md) |
|
|
23
|
+
| `src/build/**` | [08-build.md](./docs/08-build.md) |
|
|
24
|
+
| `src/config/**` | [07-yapilandirma.md](./docs/07-yapilandirma.md) |
|
|
25
|
+
| `src/dev-server.mjs`, `src/server/dev/**` | [09-dev-araclari.md](./docs/09-dev-araclari.md) |
|
|
26
|
+
|
|
27
|
+
Belgeler iki dilde: Türkçesi `docs/`, İngilizcesi `docs/en/` altında ve
|
|
28
|
+
dosyalar birebir eşlenik. Bir belgeyi değiştirdiysen karşılığını da güncelle;
|
|
29
|
+
pazarlama sitesi (`examples/marketing`) bu dosyaları doğrudan `/docs` altında
|
|
30
|
+
servis ettiği için eksik kalan çeviri kullanıcıya görünür.
|
|
31
|
+
|
|
32
|
+
## Doğrulama
|
|
33
|
+
|
|
34
|
+
**Lint yeterli, tam build zorunlu değil.**
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm run lint
|
|
38
|
+
npm test # desen derleyicisi ve HTML cache için birim testler
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Davranış değiştiren bir iş yaptıysan örneklerden biriyle uçtan uca dene:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm --prefix examples/blog install # ilk seferde
|
|
45
|
+
npm --prefix examples/blog run build
|
|
46
|
+
npm --prefix examples/blog run start # ayrı terminalde
|
|
47
|
+
node examples/blog/smoke.mjs
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`examples/blog` bilinçli olarak framework'ün her yüzeyini kullanır (dinamik
|
|
51
|
+
route, tüm config bölümleri, fragment, form, prewarm, RSS/sitemap, dört island).
|
|
52
|
+
Bir şeyi bozduysan smoke testi genelde yakalar.
|
|
53
|
+
|
|
54
|
+
## Mimari kurallar
|
|
55
|
+
|
|
56
|
+
**Framework domain bilgisi taşımaz.** `src/` altında hiçbir yerde uygulamaya
|
|
57
|
+
özel URL, marka adı, metin ya da veri şekli olmaz. Uygulamaya ait mantık
|
|
58
|
+
`hooks` üzerinden gelir (`metadata`, `layoutContext`, `notFound`,
|
|
59
|
+
`prewarmPaths`), görünen adlar `brand` üzerinden.
|
|
60
|
+
|
|
61
|
+
**Yol hesabı tek yerde.** Hiçbir modül `../..` sayarak dizin bulmaz;
|
|
62
|
+
`getConfig().dirs` kullanılır. Framework `node_modules/` içine girdiğinde
|
|
63
|
+
göreli yol sayan her satır bozulur.
|
|
64
|
+
|
|
65
|
+
**Yapılandırma hatası siteyi düşürmez.** Bozuk bir `jskelet.config.mjs`, hata
|
|
66
|
+
veren bir `headers()` ya da fırlatan bir hook uyarı basar ve varsayılana döner.
|
|
67
|
+
|
|
68
|
+
**Build çıktısı olmadan da ayağa kalkar.** `asset()` manifest yoksa hash'siz
|
|
69
|
+
yola döner, `hasAsset()` false olur ve layout etiketi basmaz. `jskelet build`
|
|
70
|
+
unutulduğunda hata değil, stilsiz ama çalışan bir sayfa görülür.
|
|
71
|
+
|
|
72
|
+
**Opsiyonel bağımlılıklar sessizce atlanır.** `sharp`, `postcss`,
|
|
73
|
+
`@phosphor-icons/core` yoksa ilgili build adımı çalışmaz. Peer bağımlılıklar
|
|
74
|
+
**uygulamanın** `node_modules`'ünden çözülmeli: `src/build/resolve-peer.mjs`
|
|
75
|
+
içindeki `importFromApp` / `tryImportFromApp` kullanılır, doğrudan `import
|
|
76
|
+
"postcss"` yazılmaz.
|
|
77
|
+
|
|
78
|
+
**Middleware sırası sözleşmedir.** `src/server/create-app.js` başındaki
|
|
79
|
+
numaralı yorum sırayı ve her konumun gerekçesini anlatır. Sıra değiştirmek
|
|
80
|
+
sessiz bozulmalara yol açar; değiştiriyorsan yorumu da güncelle.
|
|
81
|
+
|
|
82
|
+
**Cache'lenen HTML herkese aynı gider.** Kişiye özel hiçbir şey `route()` ile
|
|
83
|
+
render edilen sayfaya girmez. Tema gibi kararlar client'ta, kullanıcıya özel
|
|
84
|
+
parçalar ayrı ve `no-store` işaretli fragment uçlarında.
|
|
85
|
+
|
|
86
|
+
## Kod stili
|
|
87
|
+
|
|
88
|
+
- **JSDoc zorunlu**: dışa açık her fonksiyonda parametre ve dönüş tipleri.
|
|
89
|
+
- **Yorumlar Türkçe** ve *neden*i anlatır. Kodun ne yaptığını tekrar eden yorum
|
|
90
|
+
yazma; bir kararın gerekçesini, bir takası ya da bir tuzağı yaz.
|
|
91
|
+
- Sunucu ve build tarafı `node:` önekli çekirdek modülleri kullanır.
|
|
92
|
+
- `src/client/**` tarayıcıda çalışır: Node API'si, `process` (build sırasında
|
|
93
|
+
değiştirilen `clientEnv` dışında) ve senkron ağ yok.
|
|
94
|
+
- Yeni bir dışa açık yüzey ekliyorsan `package.json` → `exports` ve
|
|
95
|
+
`src/index.js` / `src/client/index.js` barrel'larını güncelle; belgelerde
|
|
96
|
+
yalnızca `exports` haritasındaki belirteçler kullanılır (`jskelet`,
|
|
97
|
+
`jskelet/client`, `jskelet/html`, `jskelet/tags`).
|
|
98
|
+
|
|
99
|
+
## EJS tuzakları
|
|
100
|
+
|
|
101
|
+
- `include` **async**'tir: `await include('partials/x')` yalnızca şablonun kendi
|
|
102
|
+
gövdesinde çalışır. Bir `forEach` callback'i içinde derleme hatası verir —
|
|
103
|
+
`for` döngüsü kullan.
|
|
104
|
+
- `views/components/**` altındaki her named export otomatik olarak şablon local'i
|
|
105
|
+
olur; import gerekmez. Bileşenler EJS değil, HTML string döndüren
|
|
106
|
+
fonksiyonlardır.
|
|
107
|
+
- Şablona giden her kullanıcı verisi `<%= %>` ile ya da `esc()` üzerinden
|
|
108
|
+
geçmeli; `<%- %>` yalnızca güvenli bildiğin HTML için.
|
|
109
|
+
|
|
110
|
+
## Tailwind
|
|
111
|
+
|
|
112
|
+
Sınıf taraması `styles/globals.css` içindeki `@source` direktiflerine bağlıdır
|
|
113
|
+
ve otomatik tespit `source(none)` ile kapatılmıştır. Sınıf kullanmaya başladığın
|
|
114
|
+
yeni bir dizin varsa oraya bir `@source` satırı eklemek gerekir; yoksa sınıflar
|
|
115
|
+
sessizce çıktıdan düşer.
|
|
116
|
+
|
|
117
|
+
## Örnekleri güncel tut
|
|
118
|
+
|
|
119
|
+
Framework'ün genel yüzeyini değiştirdiysen (`route()` imzası, hook adları,
|
|
120
|
+
config alanları, client API'si) `examples/minimal`, `examples/blog` ve
|
|
121
|
+
`examples/marketing`'i de güncelle. Örnekler belgelerdeki kod parçalarının kaynağı; kaymaları en hızlı
|
|
122
|
+
fark edilen yer orası.
|
|
123
|
+
|
|
124
|
+
## Windows notları
|
|
125
|
+
|
|
126
|
+
Bu depo Windows üzerinde geliştiriliyor ve iki tuzak tekrar tekrar çıkıyor:
|
|
127
|
+
|
|
128
|
+
- `--import` argümanı modül belirteci bekler. `H:\...` gibi mutlak bir yol `h:`
|
|
129
|
+
şemalı URL sanılıp reddedilir; `pathToFileURL(...).href` kullan.
|
|
130
|
+
- `fs.watch` bir dosya yazıldığında komşuları için de olay üretebiliyor. Dev
|
|
131
|
+
sunucusu bu yüzden olayları `mtime` karşılaştırmasıyla eler; watcher mantığını
|
|
132
|
+
değiştirirken bu elemeyi kaldırma.
|
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,14 @@ one is listed under a **Breaking** heading.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Cloudflare analytics in the cache panel no longer asks for an open-ended
|
|
14
|
+
window. Queries used only `datetime_geq`, so Cloudflare closed the range at
|
|
15
|
+
query time and a default 24h lookback became `1d` plus network delay — Free
|
|
16
|
+
zones reject anything wider than one day. Both ends are now pinned from the
|
|
17
|
+
same clock (`datetime_leq` included).
|
|
18
|
+
|
|
11
19
|
### Added
|
|
12
20
|
|
|
13
21
|
- `cache().query`, a pattern → allowlist mapping that decides which query
|
|
@@ -33,6 +41,13 @@ one is listed under a **Breaking** heading.
|
|
|
33
41
|
hours, and every banned or unauthorised response is a `404` rather than a 401
|
|
34
42
|
that would confirm the panel exists. The panel is excluded from indexing,
|
|
35
43
|
prewarming and navigation speculation.
|
|
44
|
+
- A language picker in the cache panel header, Turkish and English. The first
|
|
45
|
+
visit follows the browser's language, the choice is kept in `localStorage` and
|
|
46
|
+
carries over to the login page, and switching costs no request. To keep this
|
|
47
|
+
from leaking UI concerns into the server, an `/action` response now returns
|
|
48
|
+
`{ ok, code, params }` instead of an English sentence and the panel builds the
|
|
49
|
+
text — the framework's log and API stay in one language while the panel
|
|
50
|
+
speaks two.
|
|
36
51
|
- Cloudflare cache management, from the panel and from code. Set
|
|
37
52
|
`JSKELET_CLOUDFLARE_KEY` and `JSKELET_CLOUDFLARE_ZONE_ID` (or
|
|
38
53
|
`cache().cloudflare`) and the panel gains the CDN tier next to the origin one:
|
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Ayberk Enis and JSkelet contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ayberk Enis and JSkelet contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/bin/jskelet.mjs
CHANGED
|
@@ -1,104 +1,104 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* JSkelet CLI.
|
|
4
|
-
*
|
|
5
|
-
* jskelet dev build watch + sunucu, canlı yenileme, dev overlay
|
|
6
|
-
* jskelet build tek seferlik prod build (fontlar, sprite, CSS, JS, görseller)
|
|
7
|
-
* jskelet start prod sunucu (build eksikse önce üretir)
|
|
8
|
-
* jskelet init bulunduğun dizine minimal iskelet kurar
|
|
9
|
-
*
|
|
10
|
-
* Alt komutlar ayrı süreçlerde çalışır. Sebep: `dev` iki uzun ömürlü süreci
|
|
11
|
-
* (build watch + sunucu) yönetiyor ve sunucunun ESM resolve hook'larına
|
|
12
|
-
* (`--import`) ihtiyacı var; bunlar süreç başlarken kurulmak zorunda.
|
|
13
|
-
*/
|
|
14
|
-
import { spawn } from "node:child_process";
|
|
15
|
-
import fs from "node:fs";
|
|
16
|
-
import path from "node:path";
|
|
17
|
-
import process from "node:process";
|
|
18
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
19
|
-
|
|
20
|
-
const SRC = path.resolve(fileURLToPath(import.meta.url), "..", "..", "src");
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* `--import` bir modül **belirteci** bekler, dosya yolu değil. Windows'ta
|
|
24
|
-
* `H:\...` mutlak yolu `h:` şemalı bir URL sanılıp reddediliyor; file:// URL'e
|
|
25
|
-
* çevirmek her platformda doğru.
|
|
26
|
-
*/
|
|
27
|
-
const REGISTER = pathToFileURL(path.join(SRC, "runtime", "register.mjs")).href;
|
|
28
|
-
|
|
29
|
-
const [command, ...rest] = process.argv.slice(2);
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* `.env` yalnızca varsa geçilir: `--env-file-if-exists` dosya yokken de bir
|
|
33
|
-
* bildirim satırı basıyor ve bu satır dev çıktısında hata gibi görünüyor.
|
|
34
|
-
* `--import` alias hook'larını kurar; uygulama kodu `@/…` yazabilsin diye.
|
|
35
|
-
*
|
|
36
|
-
* @param {string} file
|
|
37
|
-
* @param {{ env?: Record<string, string>, args?: string[], hooks?: boolean }} [options]
|
|
38
|
-
* @returns {import('node:child_process').ChildProcess}
|
|
39
|
-
*/
|
|
40
|
-
function run(file, options = {}) {
|
|
41
|
-
const args = [
|
|
42
|
-
...(fs.existsSync(path.join(process.cwd(), ".env"))
|
|
43
|
-
? ["--env-file=.env"]
|
|
44
|
-
: []),
|
|
45
|
-
...(options.hooks === false ? [] : ["--import", REGISTER]),
|
|
46
|
-
file,
|
|
47
|
-
...(options.args ?? []),
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
return spawn(process.execPath, args, {
|
|
51
|
-
stdio: "inherit",
|
|
52
|
-
env: { ...process.env, ...(options.env ?? {}) },
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** @param {import('node:child_process').ChildProcess} child */
|
|
57
|
-
function exitWith(child) {
|
|
58
|
-
child.on("exit", (code) => process.exit(code ?? 0));
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
switch (command) {
|
|
62
|
-
case "dev": {
|
|
63
|
-
exitWith(run(path.join(SRC, "dev-server.mjs"), { hooks: false, args: rest }));
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
case "build": {
|
|
68
|
-
exitWith(
|
|
69
|
-
run(path.join(SRC, "build", "build.mjs"), {
|
|
70
|
-
env: { NODE_ENV: process.env.NODE_ENV ?? "production" },
|
|
71
|
-
args: rest,
|
|
72
|
-
}),
|
|
73
|
-
);
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
case "start": {
|
|
78
|
-
exitWith(
|
|
79
|
-
run(path.join(SRC, "start.mjs"), {
|
|
80
|
-
env: { NODE_ENV: process.env.NODE_ENV ?? "production" },
|
|
81
|
-
args: rest,
|
|
82
|
-
}),
|
|
83
|
-
);
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
case "init": {
|
|
88
|
-
const { init } = await import("../src/init.mjs");
|
|
89
|
-
await init(process.cwd());
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
default: {
|
|
94
|
-
const known = command ? `unknown command: ${command}\n\n` : "";
|
|
95
|
-
process.stderr.write(
|
|
96
|
-
`${known}usage: jskelet <dev|build|start|init>\n\n` +
|
|
97
|
-
" dev build watch + server (live reload, dev overlay)\n" +
|
|
98
|
-
" build production build\n" +
|
|
99
|
-
" start production server\n" +
|
|
100
|
-
" init scaffold a minimal skeleton in the current directory\n",
|
|
101
|
-
);
|
|
102
|
-
process.exit(command ? 1 : 0);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
2
|
+
/**
|
|
3
|
+
* JSkelet CLI.
|
|
4
|
+
*
|
|
5
|
+
* jskelet dev build watch + sunucu, canlı yenileme, dev overlay
|
|
6
|
+
* jskelet build tek seferlik prod build (fontlar, sprite, CSS, JS, görseller)
|
|
7
|
+
* jskelet start prod sunucu (build eksikse önce üretir)
|
|
8
|
+
* jskelet init bulunduğun dizine minimal iskelet kurar
|
|
9
|
+
*
|
|
10
|
+
* Alt komutlar ayrı süreçlerde çalışır. Sebep: `dev` iki uzun ömürlü süreci
|
|
11
|
+
* (build watch + sunucu) yönetiyor ve sunucunun ESM resolve hook'larına
|
|
12
|
+
* (`--import`) ihtiyacı var; bunlar süreç başlarken kurulmak zorunda.
|
|
13
|
+
*/
|
|
14
|
+
import { spawn } from "node:child_process";
|
|
15
|
+
import fs from "node:fs";
|
|
16
|
+
import path from "node:path";
|
|
17
|
+
import process from "node:process";
|
|
18
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
19
|
+
|
|
20
|
+
const SRC = path.resolve(fileURLToPath(import.meta.url), "..", "..", "src");
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* `--import` bir modül **belirteci** bekler, dosya yolu değil. Windows'ta
|
|
24
|
+
* `H:\...` mutlak yolu `h:` şemalı bir URL sanılıp reddediliyor; file:// URL'e
|
|
25
|
+
* çevirmek her platformda doğru.
|
|
26
|
+
*/
|
|
27
|
+
const REGISTER = pathToFileURL(path.join(SRC, "runtime", "register.mjs")).href;
|
|
28
|
+
|
|
29
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* `.env` yalnızca varsa geçilir: `--env-file-if-exists` dosya yokken de bir
|
|
33
|
+
* bildirim satırı basıyor ve bu satır dev çıktısında hata gibi görünüyor.
|
|
34
|
+
* `--import` alias hook'larını kurar; uygulama kodu `@/…` yazabilsin diye.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} file
|
|
37
|
+
* @param {{ env?: Record<string, string>, args?: string[], hooks?: boolean }} [options]
|
|
38
|
+
* @returns {import('node:child_process').ChildProcess}
|
|
39
|
+
*/
|
|
40
|
+
function run(file, options = {}) {
|
|
41
|
+
const args = [
|
|
42
|
+
...(fs.existsSync(path.join(process.cwd(), ".env"))
|
|
43
|
+
? ["--env-file=.env"]
|
|
44
|
+
: []),
|
|
45
|
+
...(options.hooks === false ? [] : ["--import", REGISTER]),
|
|
46
|
+
file,
|
|
47
|
+
...(options.args ?? []),
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
return spawn(process.execPath, args, {
|
|
51
|
+
stdio: "inherit",
|
|
52
|
+
env: { ...process.env, ...(options.env ?? {}) },
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** @param {import('node:child_process').ChildProcess} child */
|
|
57
|
+
function exitWith(child) {
|
|
58
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
switch (command) {
|
|
62
|
+
case "dev": {
|
|
63
|
+
exitWith(run(path.join(SRC, "dev-server.mjs"), { hooks: false, args: rest }));
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
case "build": {
|
|
68
|
+
exitWith(
|
|
69
|
+
run(path.join(SRC, "build", "build.mjs"), {
|
|
70
|
+
env: { NODE_ENV: process.env.NODE_ENV ?? "production" },
|
|
71
|
+
args: rest,
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
case "start": {
|
|
78
|
+
exitWith(
|
|
79
|
+
run(path.join(SRC, "start.mjs"), {
|
|
80
|
+
env: { NODE_ENV: process.env.NODE_ENV ?? "production" },
|
|
81
|
+
args: rest,
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
case "init": {
|
|
88
|
+
const { init } = await import("../src/init.mjs");
|
|
89
|
+
await init(process.cwd());
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
default: {
|
|
94
|
+
const known = command ? `unknown command: ${command}\n\n` : "";
|
|
95
|
+
process.stderr.write(
|
|
96
|
+
`${known}usage: jskelet <dev|build|start|init>\n\n` +
|
|
97
|
+
" dev build watch + server (live reload, dev overlay)\n" +
|
|
98
|
+
" build production build\n" +
|
|
99
|
+
" start production server\n" +
|
|
100
|
+
" init scaffold a minimal skeleton in the current directory\n",
|
|
101
|
+
);
|
|
102
|
+
process.exit(command ? 1 : 0);
|
|
103
|
+
}
|
|
104
|
+
}
|