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.
Files changed (91) hide show
  1. package/AGENTS.md +132 -132
  2. package/CHANGELOG.md +15 -0
  3. package/LICENSE +21 -21
  4. package/bin/jskelet.mjs +103 -103
  5. package/docs/01-baslangic.md +285 -285
  6. package/docs/02-mimari.md +287 -287
  7. package/docs/03-routing.md +480 -480
  8. package/docs/04-render-ve-sablonlar.md +490 -490
  9. package/docs/05-islands.md +482 -482
  10. package/docs/06-cache.md +1209 -1202
  11. package/docs/08-build.md +366 -366
  12. package/docs/09-dev-araclari.md +335 -335
  13. package/docs/10-dagitim.md +329 -329
  14. package/docs/12-panel-ve-oturum.md +384 -384
  15. package/docs/README.md +105 -105
  16. package/docs/en/01-getting-started.md +292 -292
  17. package/docs/en/02-architecture.md +305 -305
  18. package/docs/en/03-routing.md +497 -497
  19. package/docs/en/04-rendering.md +504 -504
  20. package/docs/en/05-islands.md +492 -492
  21. package/docs/en/06-caching.md +1239 -1232
  22. package/docs/en/07-configuration.md +986 -986
  23. package/docs/en/08-build.md +383 -383
  24. package/docs/en/09-dev-tools.md +342 -342
  25. package/docs/en/10-deployment.md +332 -332
  26. package/docs/en/11-migration.md +359 -359
  27. package/docs/en/12-dashboards-and-sessions.md +392 -392
  28. package/docs/en/README.md +112 -112
  29. package/package.json +102 -102
  30. package/src/build/ensure-build.mjs +15 -15
  31. package/src/build/paths.mjs +143 -143
  32. package/src/build/resolve-peer.mjs +36 -36
  33. package/src/build/tasks/client.mjs +268 -268
  34. package/src/build/tasks/css.mjs +124 -124
  35. package/src/build/tasks/fonts.mjs +146 -146
  36. package/src/build/tasks/icons.mjs +224 -224
  37. package/src/build/tasks/images.mjs +244 -244
  38. package/src/build/tasks/precompress.mjs +78 -78
  39. package/src/client/cache-panel/i18n.js +670 -0
  40. package/src/client/cache-panel/login.html +74 -71
  41. package/src/client/cache-panel/panel.css +756 -740
  42. package/src/client/cache-panel/panel.html +308 -307
  43. package/src/client/cache-panel/panel.js +915 -808
  44. package/src/client/devtools/report.html +185 -185
  45. package/src/client/devtools/report.js +725 -725
  46. package/src/client/dom.js +95 -95
  47. package/src/client/form.js +192 -192
  48. package/src/client/index.js +35 -35
  49. package/src/client/registry.js +297 -297
  50. package/src/client/safe-image.js +91 -91
  51. package/src/client/store.js +36 -36
  52. package/src/client/swap.js +188 -188
  53. package/src/config/pattern.js +107 -107
  54. package/src/http/control-flow.js +71 -71
  55. package/src/http/cookies.js +257 -257
  56. package/src/http/request-cache.js +46 -46
  57. package/src/http/request-context.js +162 -162
  58. package/src/index.js +83 -83
  59. package/src/init.mjs +221 -221
  60. package/src/runtime/alias-hooks.mjs +119 -119
  61. package/src/runtime/register.mjs +4 -4
  62. package/src/server/assets.js +147 -147
  63. package/src/server/cache-deps.js +42 -42
  64. package/src/server/cache-panel.js +759 -738
  65. package/src/server/cloudflare.js +607 -595
  66. package/src/server/create-app.js +291 -291
  67. package/src/server/data-cache.js +462 -462
  68. package/src/server/dev/report.js +369 -369
  69. package/src/server/dev/socket.js +170 -170
  70. package/src/server/dev/version-check.mjs +139 -139
  71. package/src/server/html-cache.js +817 -817
  72. package/src/server/metadata.js +102 -102
  73. package/src/server/middleware/compression.js +205 -205
  74. package/src/server/middleware/csrf.js +134 -134
  75. package/src/server/middleware/dev-gate.js +62 -62
  76. package/src/server/middleware/headers.js +37 -37
  77. package/src/server/middleware/redirects.js +32 -32
  78. package/src/server/middleware/static-precompressed.js +100 -100
  79. package/src/server/middleware/upstream-proxy.js +141 -141
  80. package/src/server/prewarm.js +601 -601
  81. package/src/server/redis.js +569 -569
  82. package/src/server/router.js +128 -128
  83. package/src/server/status-page.js +164 -164
  84. package/src/server/upstream-limiter.js +376 -376
  85. package/src/server/upstream-tracking.js +166 -166
  86. package/src/start.mjs +7 -7
  87. package/src/templates/layout.ejs +44 -44
  88. package/src/version.mjs +31 -31
  89. package/src/views/components/loader.js +85 -85
  90. package/src/views/helpers/html.js +102 -102
  91. 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
+ }