jskelet 0.6.9 → 0.6.10
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 +11 -10
- package/docs/07-yapilandirma.md +22 -22
- package/docs/08-build.md +9 -9
- package/docs/10-dagitim.md +16 -6
- package/docs/en/07-configuration.md +22 -24
- package/docs/en/08-build.md +9 -10
- package/docs/en/10-deployment.md +16 -6
- package/package.json +1 -1
- package/src/build/tasks/assets-upload.mjs +3 -3
- package/src/config/defaults.js +2 -1
- package/src/config/index.js +40 -20
- package/src/server/assets.js +3 -3
- package/types/config/defaults.d.ts +2 -1
- package/types/config/index.d.ts +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,16 +10,17 @@ one is listed under a **Breaking** heading.
|
|
|
10
10
|
|
|
11
11
|
### Added
|
|
12
12
|
|
|
13
|
-
- Optional CDN asset publishing
|
|
14
|
-
`
|
|
15
|
-
|
|
16
|
-
`build
|
|
17
|
-
`
|
|
18
|
-
|
|
19
|
-
`
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
- Optional CDN asset publishing via `build.assets`: `prefix` rewrites
|
|
14
|
+
`asset()` / optimised image URLs (manifest stays relative on disk);
|
|
15
|
+
`upload.bucket` / `keyPrefix` / `region` / `endpoint` come from config only.
|
|
16
|
+
Production `jskelet build` PutObjects `public/assets/` (and optional
|
|
17
|
+
`include` dirs) after precompress. Only credentials are read from env
|
|
18
|
+
(`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_SESSION_TOKEN`, then
|
|
19
|
+
`JSKELET_S3_*`). The Assets upload step always appears on production builds;
|
|
20
|
+
when off it logs a one-line reason (`skipped (no build.assets.upload.bucket)`,
|
|
21
|
+
`skipped (credentials missing)`, …). A URL in `upload.bucket` is rejected
|
|
22
|
+
with a warning (CDN origin belongs in `prefix`). Watch mode never uploads.
|
|
23
|
+
`.br` / `.gz` siblings are skipped.
|
|
23
24
|
|
|
24
25
|
### Changed
|
|
25
26
|
|
package/docs/07-yapilandirma.md
CHANGED
|
@@ -96,10 +96,11 @@ export default {
|
|
|
96
96
|
groups: { charts: ["chart.js"] },
|
|
97
97
|
},
|
|
98
98
|
assets: {
|
|
99
|
-
prefix:
|
|
99
|
+
prefix: "https://static.ornek.com/js",
|
|
100
100
|
upload: {
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
bucket: "static.ornek.com", // S3 bucket adı (noktalı olabilir)
|
|
102
|
+
keyPrefix: "js",
|
|
103
|
+
region: "eu-central-1",
|
|
103
104
|
},
|
|
104
105
|
},
|
|
105
106
|
},
|
|
@@ -628,21 +629,22 @@ değişmez** — asset'ler origin'den servis edilir.
|
|
|
628
629
|
|
|
629
630
|
| Alan | Tip | Varsayılan | Anlamı |
|
|
630
631
|
| --- | --- | --- | --- |
|
|
631
|
-
| `assets.prefix` | `string` | `""` | `asset()`
|
|
632
|
-
| `assets.upload.enabled` | `boolean` | `false` | `true` veya `
|
|
633
|
-
| `assets.upload.bucket` | `string \| null` | `null` |
|
|
634
|
-
| `assets.upload.keyPrefix` | `string` | `""` |
|
|
635
|
-
| `assets.upload.region` | `string` | `us-east-1` |
|
|
636
|
-
| `assets.upload.endpoint` | `string \| null` | `null` | S3-uyumlu API
|
|
632
|
+
| `assets.prefix` | `string` | `""` | CDN origin; `asset()` URL öneki (sonunda `/` yok). Yalnızca config. Manifest diskte göreli kalır. |
|
|
633
|
+
| `assets.upload.enabled` | `boolean` | `false` | `true` veya config'te `bucket` doluysa açılır; açık `false` ezer. |
|
|
634
|
+
| `assets.upload.bucket` | `string \| null` | `null` | **S3 bucket adı** (`static.ornek.com` gibi noktalı adlar geçerli) veya `bucket/key/prefix`. `https://…` şeması kabul edilmez — o `prefix`. |
|
|
635
|
+
| `assets.upload.keyPrefix` | `string` | `""` | Nesne anahtarı öneki; bucket yolunda verilmişse o kazanır (`prefix` takma adı da kabul). |
|
|
636
|
+
| `assets.upload.region` | `string` | `us-east-1` | Config; custom `endpoint` varken varsayılan `auto`. |
|
|
637
|
+
| `assets.upload.endpoint` | `string \| null` | `null` | S3-uyumlu API (R2 / MinIO); config. |
|
|
637
638
|
| `assets.upload.include` | `string[]` | `["assets"]` | `public/` altı dizinler (`assets`, isteğe `fonts`, …). |
|
|
638
639
|
| `assets.upload.cacheControl` | `string` | `public, max-age=31536000, immutable` | PutObject `Cache-Control`. |
|
|
639
640
|
|
|
640
|
-
|
|
641
|
-
`AWS_SECRET_ACCESS_KEY` / `AWS_SESSION_TOKEN
|
|
642
|
-
build'de Assets upload adımı
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
yüklenmez. Ayrıntı: [08-build.md](./08-build.md),
|
|
641
|
+
**Yalnızca credential env'den gelir:** `AWS_ACCESS_KEY_ID` /
|
|
642
|
+
`AWS_SECRET_ACCESS_KEY` / `AWS_SESSION_TOKEN` (yoksa `JSKELET_S3_*`). Prefix,
|
|
643
|
+
bucket, region vb. config'te yazılır. Production build'de Assets upload adımı
|
|
644
|
+
her zaman görünür; kapalıysa `skipped (no build.assets.upload.bucket)` /
|
|
645
|
+
`skipped (credentials missing)` gibi tek satır sebep basılır. Watch'ta adım
|
|
646
|
+
yok. `.br` / `.gz` yüklenmez. Ayrıntı: [08-build.md](./08-build.md),
|
|
647
|
+
[10-dagitim.md](./10-dagitim.md).
|
|
646
648
|
|
|
647
649
|
```js
|
|
648
650
|
build: {
|
|
@@ -657,10 +659,12 @@ build: {
|
|
|
657
659
|
},
|
|
658
660
|
},
|
|
659
661
|
assets: {
|
|
660
|
-
|
|
662
|
+
// HTML: /assets/app.css → https://static.ornek.com/js/assets/app.css
|
|
663
|
+
prefix: "https://static.ornek.com/js",
|
|
661
664
|
upload: {
|
|
662
|
-
|
|
663
|
-
|
|
665
|
+
bucket: "static.ornek.com", // veya "static.ornek.com/js" → keyPrefix js/
|
|
666
|
+
keyPrefix: "js", // S3 key: js/assets/…
|
|
667
|
+
region: "eu-central-1",
|
|
664
668
|
include: ["assets", "fonts"],
|
|
665
669
|
},
|
|
666
670
|
},
|
|
@@ -1228,13 +1232,9 @@ basılmaz.
|
|
|
1228
1232
|
| `DEV_GATE` | `devGate` | kapalı | `1` gate'i açar, `0` config'te açık olsa da kapatır. `DEV_TOKEN` tek başına açmaz. [09](./09-dev-araclari.md) |
|
|
1229
1233
|
| `DEV_TOKEN` | `devGate`, `prewarm` | — | Gate açıkken beklenen sır. Yoksa veya gate kapalıysa site açık kalır. Isıtma, gate açıkken token'ı çerez olarak taşır. [09](./09-dev-araclari.md) |
|
|
1230
1234
|
| `JSKELET_ADMIN` | `createApp` | — | Ayarlıysa yönetim panelini açar; `0` config'te açık olan paneli kapatır. Env config'i ezer, çünkü panel genelde bir arıza sırasında tek seferlik açılır. [06](./06-cache.md) |
|
|
1231
|
-
| `JSKELET_ASSET_PREFIX` | `build.assets.prefix` | — | CDN origin; `asset()` URL'lerine eklenir (sonunda `/` yok) |
|
|
1232
|
-
| `JSKELET_ASSETS_BUCKET` | `build.assets.upload` | — | Asset upload hedefi: bucket veya `bucket/prefix`. Credential ile birlikte production build sonunda PutObject |
|
|
1233
1235
|
| `AWS_ACCESS_KEY_ID` | S3 PutObject | — | Standart AWS imza anahtarı (log + asset upload); `JSKELET_S3_*`'dan önce |
|
|
1234
1236
|
| `AWS_SECRET_ACCESS_KEY` | S3 PutObject | — | Standart AWS imza sırrı |
|
|
1235
1237
|
| `AWS_SESSION_TOKEN` | S3 PutObject | — | Geçici credential (OIDC / STS) |
|
|
1236
|
-
| `AWS_REGION` / `AWS_DEFAULT_REGION` | `build.assets.upload` | — | Asset upload bölgesi |
|
|
1237
|
-
| `AWS_ENDPOINT_URL` | `build.assets.upload` | — | S3-uyumlu endpoint (asset upload) |
|
|
1238
1238
|
| `JSKELET_LOG_BUCKET` | `logs.s3` | — | Log hedefi: bucket ya da `bucket/prefix` yolu. Credential ile birlikte varsa sink otomatik açılır |
|
|
1239
1239
|
| `JSKELET_S3_BUCKET` | `logs.s3` | — | `JSKELET_LOG_BUCKET` yoksa bucket; `JSKELET_S3_KEY_PREFIX` ile birleşir |
|
|
1240
1240
|
| `JSKELET_S3_KEY_PREFIX` | `logs.s3` | — | `JSKELET_S3_BUCKET` ile kullanılır (`bucket/prefix`) |
|
package/docs/08-build.md
CHANGED
|
@@ -35,7 +35,7 @@ Sıra rastgele değil:
|
|
|
35
35
|
adımı yalnızca ham dosyaları kopyalar.
|
|
36
36
|
- **Görseller watch turunda hiç çalışmaz:** `sharp` ile yeniden kodlama pahalı.
|
|
37
37
|
- **Assets upload watch'ta yok:** yalnızca production `jskelet build`; kapalıysa
|
|
38
|
-
yine satır basılır (`skipped (no
|
|
38
|
+
yine satır basılır (`skipped (no build.assets.upload.bucket)` vb.).
|
|
39
39
|
|
|
40
40
|
Görevler yalnızca ilgili yapılandırma varsa çalışır. Font tanımlamayan bir proje
|
|
41
41
|
font adımını hiç görmez; bu, "framework her projeye kendi varsayımlarını
|
|
@@ -78,24 +78,24 @@ dosya adlarını okunur tutuyor. Hash'li olmaları sayesinde bu dosyalara
|
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
- `asset(name)` manifest'te varsa hash'li URL'i, yoksa `/assets/<name>` döner.
|
|
81
|
-
`build.assets.prefix`
|
|
82
|
-
|
|
81
|
+
`build.assets.prefix` doluysa bu göreli yolun önüne CDN origin eklenir
|
|
82
|
+
(manifest diskte göreli kalır).
|
|
83
83
|
- `hasAsset(name)` manifest'te olup olmadığını söyler.
|
|
84
84
|
|
|
85
85
|
### CDN prefix ve S3 upload
|
|
86
86
|
|
|
87
|
-
Varsayılan kapalıdır.
|
|
87
|
+
Varsayılan kapalıdır. Prefix / bucket / keyPrefix config'te; yalnızca
|
|
88
|
+
credential env'den (`AWS_*`, yoksa `JSKELET_S3_*`). Açılınca:
|
|
88
89
|
|
|
89
90
|
1. Production build `public/assets/` (ve `include` listesindeki diğer dizinler)
|
|
90
91
|
altındaki dosyaları S3'e PutObject ile kopyalar.
|
|
91
|
-
2. Çalışma anında `asset()` / optimize görseller `
|
|
92
|
+
2. Çalışma anında `asset()` / optimize görseller `build.assets.prefix` ile
|
|
92
93
|
absolute CDN URL basar. Entry CDN'deyse esbuild chunk'ları göreli yolla aynı
|
|
93
94
|
host'a gider.
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
`
|
|
97
|
-
[
|
|
98
|
-
[10-dagitim.md](./10-dagitim.md).
|
|
96
|
+
Bucket adı noktalı olabilir (`static.ornek.com`); `https://…` şeması
|
|
97
|
+
`prefix`'e yazılır. Config sözlüğü: [07-yapilandirma.md](./07-yapilandirma.md#build).
|
|
98
|
+
Dağıtım notları: [10-dagitim.md](./10-dagitim.md).
|
|
99
99
|
|
|
100
100
|
Build çalışmadıysa uygulama yine ayağa kalkar: `hasAsset()` false olur, layout
|
|
101
101
|
stylesheet ve script etiketlerini hiç basmaz. `jskelet build` unutulduğunda hata
|
package/docs/10-dagitim.md
CHANGED
|
@@ -51,17 +51,27 @@ ayarlamayı düşünmeniz gerekenler:
|
|
|
51
51
|
| `PREWARM_MAX` | Site boyutuna göre | Açılışta ısıtılacak sayfa sayısı |
|
|
52
52
|
| `PREWARM_INTERVAL_SECONDS` | `0` ya da uzun bir değer | Hiç ziyaret edilmeyen sayfaları sıcak tutmak isterseniz |
|
|
53
53
|
| `DEV_GATE` + `DEV_TOKEN` | Yalnızca staging'de | Yayına açılmamış ortamı gizler. Token tek başına siteyi kilitlemez |
|
|
54
|
-
| `JSKELET_S3_*` / `AWS_*` | Access log veya asset'leri S3'e yazıyorsanız |
|
|
55
|
-
| `JSKELET_ASSETS_BUCKET` | Hash'li asset'leri S3/CloudFront'a basıyorsanız | Production `jskelet build` sonunda PutObject; `JSKELET_ASSET_PREFIX` ile HTML CDN URL basar |
|
|
54
|
+
| `JSKELET_S3_*` / `AWS_*` | Access log veya asset'leri S3'e yazıyorsanız | Yalnızca credential; bucket/prefix `jskelet.config.mjs` → `build.assets`. Ayrıntı [07](./07-yapilandirma.md) |
|
|
56
55
|
|
|
57
56
|
### Asset'leri S3 / CloudFront'a basmak
|
|
58
57
|
|
|
59
|
-
Varsayılan kapalıdır.
|
|
58
|
+
Varsayılan kapalıdır. Config'te prefix + bucket; CI'da yalnızca credential:
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
// jskelet.config.mjs
|
|
62
|
+
build: {
|
|
63
|
+
assets: {
|
|
64
|
+
prefix: "https://static.ornek.com/js",
|
|
65
|
+
upload: {
|
|
66
|
+
bucket: "static.ornek.com", // veya "static.ornek.com/js"
|
|
67
|
+
keyPrefix: "js",
|
|
68
|
+
region: "eu-central-1",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
```
|
|
60
73
|
|
|
61
74
|
```bash
|
|
62
|
-
JSKELET_ASSETS_BUCKET=my-app-assets # veya my-app-assets/static
|
|
63
|
-
JSKELET_ASSET_PREFIX=https://dxxxx.cloudfront.net
|
|
64
|
-
AWS_REGION=eu-central-1
|
|
65
75
|
AWS_ACCESS_KEY_ID=…
|
|
66
76
|
AWS_SECRET_ACCESS_KEY=…
|
|
67
77
|
# geçici credential ise:
|
|
@@ -100,10 +100,11 @@ export default {
|
|
|
100
100
|
groups: { charts: ["chart.js"] },
|
|
101
101
|
},
|
|
102
102
|
assets: {
|
|
103
|
-
prefix:
|
|
103
|
+
prefix: "https://static.example.com/js",
|
|
104
104
|
upload: {
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
bucket: "static.example.com", // S3 bucket name (dots are fine)
|
|
106
|
+
keyPrefix: "js",
|
|
107
|
+
region: "eu-central-1",
|
|
107
108
|
},
|
|
108
109
|
},
|
|
109
110
|
},
|
|
@@ -641,23 +642,22 @@ changes** — assets stay on the origin.
|
|
|
641
642
|
|
|
642
643
|
| Field | Type | Default | Meaning |
|
|
643
644
|
| --- | --- | --- | --- |
|
|
644
|
-
| `assets.prefix` | `string` | `""` |
|
|
645
|
-
| `assets.upload.enabled` | `boolean` | `false` | Turns on when `true` or when `
|
|
646
|
-
| `assets.upload.bucket` | `string \| null` | `null` |
|
|
647
|
-
| `assets.upload.keyPrefix` | `string` | `""` | Object key prefix
|
|
648
|
-
| `assets.upload.region` | `string` | `us-east-1` |
|
|
649
|
-
| `assets.upload.endpoint` | `string \| null` | `null` | S3-compatible API
|
|
645
|
+
| `assets.prefix` | `string` | `""` | CDN origin; prefix for `asset()` URLs (no trailing `/`). Config only. The on-disk manifest stays relative. |
|
|
646
|
+
| `assets.upload.enabled` | `boolean` | `false` | Turns on when `true` or when `bucket` is set in config; explicit `false` wins. |
|
|
647
|
+
| `assets.upload.bucket` | `string \| null` | `null` | **S3 bucket name** (dotted names like `static.example.com` are fine) or `bucket/key/prefix`. A `https://…` scheme is rejected — that belongs in `prefix`. |
|
|
648
|
+
| `assets.upload.keyPrefix` | `string` | `""` | Object key prefix; a path on the bucket wins (`prefix` is accepted as an alias). |
|
|
649
|
+
| `assets.upload.region` | `string` | `us-east-1` | Config; defaults to `auto` when `endpoint` is set. |
|
|
650
|
+
| `assets.upload.endpoint` | `string \| null` | `null` | S3-compatible API (R2 / MinIO); config. |
|
|
650
651
|
| `assets.upload.include` | `string[]` | `["assets"]` | Directories under `public/` (`assets`, optionally `fonts`, …). |
|
|
651
652
|
| `assets.upload.cacheControl` | `string` | `public, max-age=31536000, immutable` | PutObject `Cache-Control`. |
|
|
652
653
|
|
|
653
|
-
|
|
654
|
-
`
|
|
655
|
-
|
|
656
|
-
when off it logs a one-line reason such as
|
|
657
|
-
`skipped (no
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
[10-deployment.md](./10-deployment.md).
|
|
654
|
+
**Only credentials come from the environment:** `AWS_ACCESS_KEY_ID` /
|
|
655
|
+
`AWS_SECRET_ACCESS_KEY` / `AWS_SESSION_TOKEN` (else `JSKELET_S3_*`). Prefix,
|
|
656
|
+
bucket, region, etc. are written in the config. On a production build the Assets
|
|
657
|
+
upload step always appears; when off it logs a one-line reason such as
|
|
658
|
+
`skipped (no build.assets.upload.bucket)` or `skipped (credentials missing)`.
|
|
659
|
+
No upload on watch passes. `.br` / `.gz` siblings are not uploaded. Details:
|
|
660
|
+
[08-build.md](./08-build.md), [10-deployment.md](./10-deployment.md).
|
|
661
661
|
|
|
662
662
|
```js
|
|
663
663
|
build: {
|
|
@@ -672,10 +672,12 @@ build: {
|
|
|
672
672
|
},
|
|
673
673
|
},
|
|
674
674
|
assets: {
|
|
675
|
-
|
|
675
|
+
// HTML: /assets/app.css → https://static.example.com/js/assets/app.css
|
|
676
|
+
prefix: "https://static.example.com/js",
|
|
676
677
|
upload: {
|
|
677
|
-
|
|
678
|
-
|
|
678
|
+
bucket: "static.example.com", // or "static.example.com/js" → keyPrefix js/
|
|
679
|
+
keyPrefix: "js", // S3 key: js/assets/…
|
|
680
|
+
region: "eu-central-1",
|
|
679
681
|
include: ["assets", "fonts"],
|
|
680
682
|
},
|
|
681
683
|
},
|
|
@@ -1252,13 +1254,9 @@ and no warning is printed.
|
|
|
1252
1254
|
| `DEV_GATE` | `devGate` | off | `1` turns the gate on, `0` turns it off even when config enabled it. `DEV_TOKEN` alone does not turn it on. [09](./09-dev-tools.md) |
|
|
1253
1255
|
| `DEV_TOKEN` | `devGate`, `prewarm` | — | The secret expected while the gate is on. If it is missing, or the gate is off, the site stays public. Prewarming carries the token as a cookie only while the gate is on. [09](./09-dev-tools.md) |
|
|
1254
1256
|
| `JSKELET_ADMIN` | `createApp` | — | When set, turns the admin panel on; `0` turns off a panel enabled in the config. The env wins because the panel is usually opened once during an incident. [06](./06-caching.md) |
|
|
1255
|
-
| `JSKELET_ASSET_PREFIX` | `build.assets.prefix` | — | CDN origin prepended to `asset()` URLs (no trailing `/`) |
|
|
1256
|
-
| `JSKELET_ASSETS_BUCKET` | `build.assets.upload` | — | Asset upload target: bucket or `bucket/prefix`. With credentials, production build PutObject |
|
|
1257
1257
|
| `AWS_ACCESS_KEY_ID` | S3 PutObject | — | Standard AWS signing key (logs + asset upload); before `JSKELET_S3_*` |
|
|
1258
1258
|
| `AWS_SECRET_ACCESS_KEY` | S3 PutObject | — | Standard AWS signing secret |
|
|
1259
1259
|
| `AWS_SESSION_TOKEN` | S3 PutObject | — | Temporary credentials (OIDC / STS) |
|
|
1260
|
-
| `AWS_REGION` / `AWS_DEFAULT_REGION` | `build.assets.upload` | — | Asset upload region |
|
|
1261
|
-
| `AWS_ENDPOINT_URL` | `build.assets.upload` | — | S3-compatible endpoint (asset upload) |
|
|
1262
1260
|
| `JSKELET_LOG_BUCKET` | `logs.s3` | — | Log target: bucket or `bucket/prefix` path. With credentials, the sink turns on automatically |
|
|
1263
1261
|
| `JSKELET_S3_BUCKET` | `logs.s3` | — | Bucket when `JSKELET_LOG_BUCKET` is unset; joins with `JSKELET_S3_KEY_PREFIX` |
|
|
1264
1262
|
| `JSKELET_S3_KEY_PREFIX` | `logs.s3` | — | Used with `JSKELET_S3_BUCKET` (`bucket/prefix`) |
|
package/docs/en/08-build.md
CHANGED
|
@@ -35,7 +35,7 @@ The order is not arbitrary:
|
|
|
35
35
|
the S3 step copies only the raw files.
|
|
36
36
|
- **Images never run on a watch pass:** re-encoding with `sharp` is expensive.
|
|
37
37
|
- **Assets upload never runs on watch:** only production `jskelet build`; when
|
|
38
|
-
off the step still prints (`skipped (no
|
|
38
|
+
off the step still prints (`skipped (no build.assets.upload.bucket)`, etc.).
|
|
39
39
|
|
|
40
40
|
Tasks only run if the relevant configuration exists. A project that does not
|
|
41
41
|
define any fonts never sees the font step; this is the build-side counterpart of
|
|
@@ -81,25 +81,24 @@ They are passed to templates automatically; in server code,
|
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
- `asset(name)` returns the hashed URL if it is in the manifest, otherwise
|
|
84
|
-
`/assets/<name>`. When `build.assets.prefix`
|
|
85
|
-
|
|
86
|
-
relative).
|
|
84
|
+
`/assets/<name>`. When `build.assets.prefix` is set, that relative path is
|
|
85
|
+
prefixed with the CDN origin (the on-disk manifest stays relative).
|
|
87
86
|
- `hasAsset(name)` tells you whether it is in the manifest.
|
|
88
87
|
|
|
89
88
|
### CDN prefix and S3 upload
|
|
90
89
|
|
|
91
|
-
Off by default.
|
|
90
|
+
Off by default. Prefix / bucket / keyPrefix come from config; only credentials
|
|
91
|
+
come from the environment (`AWS_*`, else `JSKELET_S3_*`). When enabled:
|
|
92
92
|
|
|
93
93
|
1. A production build PutObjects files under `public/assets/` (and any other
|
|
94
94
|
directories in `include`) to S3.
|
|
95
95
|
2. At runtime `asset()` / optimised images emit absolute CDN URLs via
|
|
96
|
-
`
|
|
96
|
+
`build.assets.prefix`. When the entry script is on the CDN, esbuild chunks
|
|
97
97
|
resolve relatively on the same host.
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
`
|
|
101
|
-
[
|
|
102
|
-
[10-deployment.md](./10-deployment.md).
|
|
99
|
+
Bucket names may include dots (`static.example.com`); put `https://…` in
|
|
100
|
+
`prefix`. Config reference: [07-configuration.md](./07-configuration.md#build).
|
|
101
|
+
Deploy notes: [10-deployment.md](./10-deployment.md).
|
|
103
102
|
|
|
104
103
|
If the build has not run, the application still comes up: `hasAsset()` is false
|
|
105
104
|
and the layout never emits the stylesheet and script tags. When `jskelet build`
|
package/docs/en/10-deployment.md
CHANGED
|
@@ -52,17 +52,27 @@ considering in production:
|
|
|
52
52
|
| `PREWARM_MAX` | Depends on site size | Number of pages warmed at startup |
|
|
53
53
|
| `PREWARM_INTERVAL_SECONDS` | `0` or a long value | If you want to keep never-visited pages warm |
|
|
54
54
|
| `DEV_GATE` + `DEV_TOKEN` | Staging only | Hides an environment that is not public yet. The token alone does not lock the site |
|
|
55
|
-
| `JSKELET_S3_*` / `AWS_*` | If you write access logs or assets to S3 | Credentials;
|
|
56
|
-
| `JSKELET_ASSETS_BUCKET` | If you publish hashed assets to S3/CloudFront | PutObject at the end of production `jskelet build`; `JSKELET_ASSET_PREFIX` makes HTML emit CDN URLs |
|
|
55
|
+
| `JSKELET_S3_*` / `AWS_*` | If you write access logs or assets to S3 | Credentials only; bucket/prefix live in `jskelet.config.mjs` → `build.assets`. Details in [07](./07-configuration.md) |
|
|
57
56
|
|
|
58
57
|
### Publishing assets to S3 / CloudFront
|
|
59
58
|
|
|
60
|
-
Off by default.
|
|
59
|
+
Off by default. Prefix + bucket in config; credentials only in CI:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
// jskelet.config.mjs
|
|
63
|
+
build: {
|
|
64
|
+
assets: {
|
|
65
|
+
prefix: "https://static.example.com/js",
|
|
66
|
+
upload: {
|
|
67
|
+
bucket: "static.example.com", // or "static.example.com/js"
|
|
68
|
+
keyPrefix: "js",
|
|
69
|
+
region: "eu-central-1",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
```
|
|
61
74
|
|
|
62
75
|
```bash
|
|
63
|
-
JSKELET_ASSETS_BUCKET=my-app-assets # or my-app-assets/static
|
|
64
|
-
JSKELET_ASSET_PREFIX=https://dxxxx.cloudfront.net
|
|
65
|
-
AWS_REGION=eu-central-1
|
|
66
76
|
AWS_ACCESS_KEY_ID=…
|
|
67
77
|
AWS_SECRET_ACCESS_KEY=…
|
|
68
78
|
# for temporary credentials:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jskelet",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.10",
|
|
4
4
|
"description": "A framework that feels like no framework: Express 5 + build-time .jsk SSR (optional EJS peer), vanilla JS islands, Tailwind v4 and an in-process HTML TTL cache.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -97,13 +97,13 @@ export function assetsUploadSkipReason(config) {
|
|
|
97
97
|
const upload = config.build?.assets?.upload;
|
|
98
98
|
|
|
99
99
|
if (!upload?.enabled) {
|
|
100
|
-
// Bucket yoksa asıl eksik
|
|
100
|
+
// Bucket yoksa asıl eksik alanı söyle — `enabled: false` çoğu zaman
|
|
101
101
|
// bucket tanımlanmadığı için dolaylıdır.
|
|
102
|
-
if (!upload?.bucket) return "no
|
|
102
|
+
if (!upload?.bucket) return "no build.assets.upload.bucket";
|
|
103
103
|
return "build.assets.upload.enabled is false";
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
if (!upload.bucket) return "no
|
|
106
|
+
if (!upload.bucket) return "no build.assets.upload.bucket";
|
|
107
107
|
|
|
108
108
|
if (!readS3CredentialsFromEnv()) return "credentials missing";
|
|
109
109
|
|
package/src/config/defaults.js
CHANGED
|
@@ -498,10 +498,11 @@ export const DEFAULT_BUILD = {
|
|
|
498
498
|
chunkGroup: null,
|
|
499
499
|
},
|
|
500
500
|
assets: {
|
|
501
|
-
/** CDN / CloudFront origin; sonunda `/` yok.
|
|
501
|
+
/** CDN / CloudFront origin; sonunda `/` yok. Yalnızca config. */
|
|
502
502
|
prefix: "",
|
|
503
503
|
upload: {
|
|
504
504
|
enabled: false,
|
|
505
|
+
/** S3 bucket adı (CDN URL değil). Yalnızca config; credential env'den. */
|
|
505
506
|
bucket: null,
|
|
506
507
|
/** Nesne anahtarı öneki (`bucket/path` split'inden veya config). */
|
|
507
508
|
keyPrefix: "",
|
package/src/config/index.js
CHANGED
|
@@ -180,7 +180,7 @@ const CONFIG_FILE = "jskelet.config.mjs";
|
|
|
180
180
|
* @property {string} cacheControl
|
|
181
181
|
*
|
|
182
182
|
* @typedef {object} BuildAssetsConfig
|
|
183
|
-
* @property {string} prefix CDN origin (`
|
|
183
|
+
* @property {string} prefix CDN origin (`build.assets.prefix`); sonunda `/` yok.
|
|
184
184
|
* @property {BuildAssetsUploadConfig} upload
|
|
185
185
|
*
|
|
186
186
|
* @typedef {object} BuildConfig
|
|
@@ -1186,7 +1186,34 @@ function defaultBuildClient() {
|
|
|
1186
1186
|
}
|
|
1187
1187
|
|
|
1188
1188
|
/**
|
|
1189
|
-
* CDN
|
|
1189
|
+
* Asset upload bucket'ı. CDN URL buraya yazılmaz — o `build.assets.prefix`.
|
|
1190
|
+
*
|
|
1191
|
+
* @param {unknown} value
|
|
1192
|
+
* @returns {{ bucket: string | null, prefix: string | null }}
|
|
1193
|
+
*/
|
|
1194
|
+
function normalizeAssetsBucket(value) {
|
|
1195
|
+
const text = typeof value === "string" ? value.trim() : "";
|
|
1196
|
+
if (!text) return { bucket: null, prefix: null };
|
|
1197
|
+
|
|
1198
|
+
// Noktalı bucket adları geçerli (`static.investvio.com`). Reddedilen yalnızca
|
|
1199
|
+
// şemalı URL — CDN origin `build.assets.prefix`'te kalır.
|
|
1200
|
+
if (/^https?:\/\//i.test(text)) {
|
|
1201
|
+
console.warn(
|
|
1202
|
+
"[config] build.assets.upload.bucket looks like a URL — use the S3 " +
|
|
1203
|
+
"bucket name without a scheme (e.g. \"static.investvio.com\" or " +
|
|
1204
|
+
"\"static.investvio.com/js\"); put https://… in build.assets.prefix",
|
|
1205
|
+
);
|
|
1206
|
+
return { bucket: null, prefix: null };
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
return splitS3BucketPath(text);
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* CDN prefix + S3 upload (`build.assets`).
|
|
1214
|
+
*
|
|
1215
|
+
* Prefix / bucket / keyPrefix / region / endpoint **yalnızca config**'ten.
|
|
1216
|
+
* Credential env'den (`AWS_*`, yoksa `JSKELET_S3_*`) — config'e yazılmaz.
|
|
1190
1217
|
*
|
|
1191
1218
|
* @param {unknown} raw
|
|
1192
1219
|
* @returns {BuildAssetsConfig}
|
|
@@ -1201,10 +1228,9 @@ export function normalizeBuildAssets(raw) {
|
|
|
1201
1228
|
console.warn("[config] build.assets must be an object, ignoring it");
|
|
1202
1229
|
}
|
|
1203
1230
|
|
|
1204
|
-
const
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
const prefix = (envPrefix ?? configPrefix).replace(/\/+$/, "");
|
|
1231
|
+
const prefix = (
|
|
1232
|
+
typeof source.prefix === "string" ? source.prefix.trim() : ""
|
|
1233
|
+
).replace(/\/+$/, "");
|
|
1208
1234
|
|
|
1209
1235
|
const uploadRaw =
|
|
1210
1236
|
source.upload != null &&
|
|
@@ -1220,10 +1246,7 @@ export function normalizeBuildAssets(raw) {
|
|
|
1220
1246
|
console.warn("[config] build.assets.upload must be an object, ignoring it");
|
|
1221
1247
|
}
|
|
1222
1248
|
|
|
1223
|
-
const
|
|
1224
|
-
const bucketPath = splitS3BucketPath(
|
|
1225
|
-
envBucket ?? envText(uploadRaw.bucket),
|
|
1226
|
-
);
|
|
1249
|
+
const bucketPath = normalizeAssetsBucket(uploadRaw.bucket);
|
|
1227
1250
|
|
|
1228
1251
|
const configKeyPrefix =
|
|
1229
1252
|
typeof uploadRaw.keyPrefix === "string" && uploadRaw.keyPrefix
|
|
@@ -1236,17 +1259,15 @@ export function normalizeBuildAssets(raw) {
|
|
|
1236
1259
|
: `${uploadRaw.prefix}/`
|
|
1237
1260
|
: DEFAULT_BUILD.assets.upload.keyPrefix;
|
|
1238
1261
|
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1262
|
+
// Bucket yolundaki önek (`my-bucket/js`) `keyPrefix`'i ezer — tek alanda
|
|
1263
|
+
// hem kova hem klasör vermek için.
|
|
1264
|
+
const keyPrefix = bucketPath.prefix ?? configKeyPrefix;
|
|
1265
|
+
|
|
1266
|
+
const endpoint = envText(uploadRaw.endpoint);
|
|
1243
1267
|
|
|
1244
1268
|
// Gerçek AWS'te region imza için gerekir; custom endpoint'te `auto` yaygın.
|
|
1245
1269
|
const region =
|
|
1246
1270
|
envText(uploadRaw.region) ??
|
|
1247
|
-
envText(process.env.AWS_REGION) ??
|
|
1248
|
-
envText(process.env.AWS_DEFAULT_REGION) ??
|
|
1249
|
-
envText(process.env.JSKELET_S3_REGION) ??
|
|
1250
1271
|
(endpoint ? "auto" : DEFAULT_BUILD.assets.upload.region);
|
|
1251
1272
|
|
|
1252
1273
|
/** @type {string[]} */
|
|
@@ -1268,8 +1289,7 @@ export function normalizeBuildAssets(raw) {
|
|
|
1268
1289
|
? uploadRaw.cacheControl.trim()
|
|
1269
1290
|
: DEFAULT_BUILD.assets.upload.cacheControl;
|
|
1270
1291
|
|
|
1271
|
-
//
|
|
1272
|
-
// Açık `enabled: false` ezer.
|
|
1292
|
+
// Config'te bucket varsa `enabled` unutulmuş olsa bile aç. Açık `false` ezer.
|
|
1273
1293
|
const enabled =
|
|
1274
1294
|
uploadRaw.enabled === true ||
|
|
1275
1295
|
(uploadRaw.enabled !== false && Boolean(bucketPath.bucket));
|
|
@@ -1279,7 +1299,7 @@ export function normalizeBuildAssets(raw) {
|
|
|
1279
1299
|
upload: {
|
|
1280
1300
|
enabled,
|
|
1281
1301
|
bucket: bucketPath.bucket,
|
|
1282
|
-
keyPrefix
|
|
1302
|
+
keyPrefix,
|
|
1283
1303
|
region,
|
|
1284
1304
|
endpoint,
|
|
1285
1305
|
include,
|
package/src/server/assets.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* basmaz. Böylece `jskelet build` unutulduğunda hata yerine stilsiz ama
|
|
7
7
|
* çalışan bir sayfa görürsünüz.
|
|
8
8
|
*
|
|
9
|
-
* `build.assets.prefix`
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* `build.assets.prefix` doluysa HTML'e basılan URL'lere CDN origin eklenir;
|
|
10
|
+
* manifest diskte göreli kalır. Dosya sistemi okumaları (`getSpriteIds`)
|
|
11
|
+
* göreli yolu kullanır.
|
|
12
12
|
*/
|
|
13
13
|
import fs from "node:fs";
|
|
14
14
|
import path from "node:path";
|
|
@@ -448,10 +448,11 @@ export declare const DEFAULT_BUILD: {
|
|
|
448
448
|
chunkGroup: ((id: string) => string | null | undefined) | null;
|
|
449
449
|
};
|
|
450
450
|
assets: {
|
|
451
|
-
/** CDN / CloudFront origin; sonunda `/` yok.
|
|
451
|
+
/** CDN / CloudFront origin; sonunda `/` yok. Yalnızca config. */
|
|
452
452
|
prefix: string;
|
|
453
453
|
upload: {
|
|
454
454
|
enabled: boolean;
|
|
455
|
+
/** S3 bucket adı (CDN URL değil). Yalnızca config; credential env'den. */
|
|
455
456
|
bucket: null;
|
|
456
457
|
/** Nesne anahtarı öneki (`bucket/path` split'inden veya config). */
|
|
457
458
|
keyPrefix: string;
|
package/types/config/index.d.ts
CHANGED
|
@@ -241,7 +241,7 @@ export type BuildAssetsUploadConfig = {
|
|
|
241
241
|
};
|
|
242
242
|
export type BuildAssetsConfig = {
|
|
243
243
|
/**
|
|
244
|
-
* CDN origin (`
|
|
244
|
+
* CDN origin (`build.assets.prefix`); sonunda `/` yok.
|
|
245
245
|
*/
|
|
246
246
|
prefix: string;
|
|
247
247
|
upload: BuildAssetsUploadConfig;
|
|
@@ -313,7 +313,10 @@ export type SecurityConfig = {
|
|
|
313
313
|
};
|
|
314
314
|
};
|
|
315
315
|
/**
|
|
316
|
-
* CDN prefix + S3 upload (`build.assets`).
|
|
316
|
+
* CDN prefix + S3 upload (`build.assets`).
|
|
317
|
+
*
|
|
318
|
+
* Prefix / bucket / keyPrefix / region / endpoint **yalnızca config**'ten.
|
|
319
|
+
* Credential env'den (`AWS_*`, yoksa `JSKELET_S3_*`) — config'e yazılmaz.
|
|
317
320
|
*
|
|
318
321
|
* @param {unknown} raw
|
|
319
322
|
* @returns {BuildAssetsConfig}
|