@adaptive-ds/assets-optimizer 0.1.0 → 0.2.0

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @adaptive-ds/assets-optimizer
2
2
 
3
- Process, hash, sync, and clean image assets for web projects that keep originals outside git and use R2 as the canonical store, with a separate pass for web videos.
3
+ Process, hash, sync, and clean image assets for web projects that keep originals outside git and optionally sync through any `rclone` remote, with a separate pass for web videos.
4
4
 
5
5
  This package is built for a workflow with two local directories:
6
6
 
@@ -11,7 +11,7 @@ This package is built for a workflow with two local directories:
11
11
 
12
12
  It is designed for projects where:
13
13
 
14
- - originals live in R2 and are synced locally
14
+ - originals may live on an `rclone` remote and be synced locally
15
15
  - optimized outputs should be deterministic and aggressively cacheable
16
16
  - output filenames should change when either the source file or the transform changes
17
17
  - old optimized files should be removed locally and remotely
@@ -19,8 +19,16 @@ It is designed for projects where:
19
19
 
20
20
  ## Diagrams
21
21
 
22
+ ### Overview
23
+
22
24
  ![Overview](docs/arch/overview_v1.excalidraw.svg)
25
+
26
+ ### Images
27
+
23
28
  ![Image process](docs/arch/process_image_v1.excalidraw.svg)
29
+
30
+ ### Videos
31
+
24
32
  ![Video process](docs/arch/process_video_v1.excalidraw.svg)
25
33
 
26
34
  ## What It Does
@@ -28,20 +36,20 @@ It is designed for projects where:
28
36
  `assetsOptimize()` performs the full asset pipeline:
29
37
 
30
38
  1. Resolves the project name from `package.json.name`
31
- 2. Uses that as the bucket base path on your `rclone` remote
32
- 3. Syncs originals between R2 and `images`
39
+ 2. If `rcloneRemote` is configured, uses that project name as the base path on the remote
40
+ 3. If `rcloneRemote` is configured, syncs originals between the remote and `images`
33
41
  4. Scans transform folders like `1920x1080_jpg`
34
42
  5. Processes matching image source files with `sharp`
35
43
  6. Writes flat optimized images into `public/images`
36
44
  7. Names image files as `<basename>_<hash>.<ext>`
37
45
  8. Skips already-generated images
38
46
  9. Deletes stale optimized images locally
39
- 10. Uploads missing optimized images to R2 with cache headers
40
- 11. Deletes stale optimized images from R2
47
+ 10. If `rcloneRemote` is configured, uploads missing optimized images to the remote with cache headers
48
+ 11. If `rcloneRemote` is configured, deletes stale optimized images from the remote
41
49
  12. Runs a separate optional video pass from `videos` to `public/videos`
42
50
  13. Generates a `.jpg` preview beside each processed video using the processed video dimensions
43
51
  14. Keeps video filenames unchanged and skips any processed video or preview that already exists
44
- 15. Uploads missing processed videos and previews to R2 without deleting manual variants
52
+ 15. If `rcloneRemote` is configured, uploads missing processed videos and previews to the remote without deleting manual variants
45
53
  16. Generates `src/app/assets/imageList.ts` and `src/app/assets/videoList.ts` by default
46
54
  17. Prints a clear summary of what changed
47
55
 
@@ -95,8 +103,8 @@ public/videos/
95
103
  Video behavior:
96
104
 
97
105
  - if both local `videos` and remote `video-originals` are missing, the video pass does nothing
98
- - source videos sync through `video-originals`
99
- - processed videos sync through `video-processed`
106
+ - if `rcloneRemote` is configured, source videos sync through `video-originals`
107
+ - if `rcloneRemote` is configured, processed videos sync through `video-processed`
100
108
  - missing processed videos are created with `ffmpeg`
101
109
  - missing preview images are created as `.jpg` files beside processed videos
102
110
  - existing processed videos are skipped and preserved as manual transformations
@@ -150,21 +158,21 @@ If you call `assetsOptimize()` with no arguments, it uses:
150
158
  - `imageOptimizedDir`: `./public/images`
151
159
  - `allowRootImageFiles`: `false`
152
160
  - `processVideos`: `true`
153
- - `videosDir`: `./videos`
154
- - `processedVideosDir`: `./public/videos`
161
+ - `videoOriginalsDir`: `./videos`
162
+ - `videoOptimizedDir`: `./public/videos`
155
163
  - `imageListOutputPath`: `./src/app/assets/imageList.ts`
156
164
  - `videoListOutputPath`: `./src/app/assets/videoList.ts`
157
165
  - `generateImageList`: `true`
158
166
  - `generateVideoList`: `true`
159
167
  - `videoPreviewQuality`: `80`
160
- - `rcloneRemote`: `leo`
168
+ - `rcloneRemote`: not set
161
169
  - `remoteImageOriginalsDir`: `image-originals`
162
170
  - `remoteImageOptimizedDir`: `image-processed`
163
171
  - `remoteVideoOriginalsDir`: `video-originals`
164
172
  - `remoteVideoProcessedDir`: `video-processed`
165
173
  - `cacheControlHeader`: `public,max-age=31536000,immutable`
166
174
 
167
- So for a project named `moramontage`, the remote paths become:
175
+ If you set `rcloneRemote` to `leo` for a project named `moramontage`, the remote paths become:
168
176
 
169
177
  - `leo:moramontage/image-originals`
170
178
  - `leo:moramontage/image-processed`
@@ -189,6 +197,8 @@ await assetsOptimize()
189
197
 
190
198
  This generates optimized images, processed videos, video preview JPGs, `imageList.ts`, and `videoList.ts` in one run. Existing image alt text and existing video preview alt text are preserved when the generated files already exist.
191
199
 
200
+ When `rcloneRemote` is omitted, all remote sync, upload, and cleanup steps are skipped.
201
+
192
202
  ## API
193
203
 
194
204
  ```ts
@@ -203,6 +213,7 @@ const result = await assetsOptimize(options)
203
213
  interface OptimizeImagesWebOptions {
204
214
  cwd?: string
205
215
  projectName?: string
216
+ logLevel?: 0 | 1 | 2 | 3
206
217
  processImages?: boolean
207
218
  imageOriginalsDir?: string
208
219
  imageOptimizedDir?: string
@@ -211,8 +222,8 @@ interface OptimizeImagesWebOptions {
211
222
  imageListImportPath?: string
212
223
  generateImageList?: boolean
213
224
  processVideos?: boolean
214
- videosDir?: string
215
- processedVideosDir?: string
225
+ videoOriginalsDir?: string
226
+ videoOptimizedDir?: string
216
227
  videoListOutputPath?: string
217
228
  videoListImportPath?: string
218
229
  generateVideoList?: boolean
@@ -226,6 +237,13 @@ interface OptimizeImagesWebOptions {
226
237
  }
227
238
  ```
228
239
 
240
+ `logLevel` controls runtime logging:
241
+
242
+ - `0`: no logs
243
+ - `1`: summary plus explicit worked-on files
244
+ - `2`: level 1 plus all CLI calls
245
+ - `3`: level 2 plus command output
246
+
229
247
  ### `OptimizeImagesWebResult`
230
248
 
231
249
  ```ts
@@ -252,12 +270,15 @@ interface OptimizeImagesWebResult {
252
270
  import { assetsOptimize } from "@adaptive-ds/assets-optimizer"
253
271
 
254
272
  await assetsOptimize({
273
+ logLevel: 1,
255
274
  processImages: true,
256
275
  imageOriginalsDir: "./assets/originals",
257
276
  imageOptimizedDir: "./assets/optimized",
258
277
  allowRootImageFiles: false,
259
278
  imageListOutputPath: "./src/app/assets/imageList.ts",
260
279
  processVideos: true,
280
+ videoOriginalsDir: "./videos",
281
+ videoOptimizedDir: "./public/videos",
261
282
  videoListOutputPath: "./src/app/assets/videoList.ts",
262
283
  videoPreviewQuality: 80,
263
284
  rcloneRemote: "leo",
package/bun.lock CHANGED
@@ -3,7 +3,7 @@
3
3
  "configVersion": 1,
4
4
  "workspaces": {
5
5
  "": {
6
- "name": "@adaptive-ds/optimize-images-web",
6
+ "name": "@adaptive-ds/assets-optimizer",
7
7
  "dependencies": {
8
8
  "image-size": "^2.0.2",
9
9
  "sharp": "^0.34.5",
@@ -17,25 +17,25 @@
17
17
  },
18
18
  },
19
19
  "packages": {
20
- "@biomejs/biome": ["@biomejs/biome@2.4.11", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.11", "@biomejs/cli-darwin-x64": "2.4.11", "@biomejs/cli-linux-arm64": "2.4.11", "@biomejs/cli-linux-arm64-musl": "2.4.11", "@biomejs/cli-linux-x64": "2.4.11", "@biomejs/cli-linux-x64-musl": "2.4.11", "@biomejs/cli-win32-arm64": "2.4.11", "@biomejs/cli-win32-x64": "2.4.11" }, "bin": { "biome": "bin/biome" } }, "sha512-nWxHX8tf3Opb/qRgZpBbsTOqOodkbrkJ7S+JxJAruxOReaDPPmPuLBAGQ8vigyUgo0QBB+oQltNEAvalLcjggA=="],
20
+ "@biomejs/biome": ["@biomejs/biome@2.4.12", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.12", "@biomejs/cli-darwin-x64": "2.4.12", "@biomejs/cli-linux-arm64": "2.4.12", "@biomejs/cli-linux-arm64-musl": "2.4.12", "@biomejs/cli-linux-x64": "2.4.12", "@biomejs/cli-linux-x64-musl": "2.4.12", "@biomejs/cli-win32-arm64": "2.4.12", "@biomejs/cli-win32-x64": "2.4.12" }, "bin": { "biome": "bin/biome" } }, "sha512-Rro7adQl3NLq/zJCIL98eElXKI8eEiBtoeu5TbXF/U3qbjuSc7Jb5rjUbeHHcquDWeSf3HnGP7XI5qGrlRk/pA=="],
21
21
 
22
- "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wOt+ed+L2dgZanWyL6i29qlXMc088N11optzpo10peayObBaAshbTcxKUchzEMp9QSY8rh5h6VfAFE3WTS1rqg=="],
22
+ "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BnMU4Pc3ciEVteVpZ0BK33MLr7X57F5w1dwDLDn+/iy/yTrA4Q/N2yftidFtsA4vrDh0FMXDpacNV/Tl3fbmng=="],
23
23
 
24
- "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-gZ6zR8XmZlExfi/Pz/PffmdpWOQ8Qhy7oBztgkR8/ylSRyLwfRPSadmiVCV8WQ8PoJ2MWUy2fgID9zmtgUUJmw=="],
24
+ "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-x9uJ0bI1rJsWICp3VH8w/5PnAVD3A7SqzDpbrfoUQX1QyWrK5jSU4fRLo/wSgGeplCivbxBRKmt5Xq4/nWvq8A=="],
25
25
 
26
- "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-avdJaEElXrKceK0va9FkJ4P5ci3N01TGkc6ni3P8l3BElqbOz42Wg2IyX3gbh0ZLEd4HVKEIrmuVu/AMuSeFFA=="],
26
+ "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-tOwuCuZZtKi1jVzbk/5nXmIsziOB6yqN8c9r9QM0EJYPU6DpQWf11uBOSCfFKKM4H3d9ZoarvlgMfbcuD051Pw=="],
27
27
 
28
- "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-+Sbo1OAmlegtdwqFE8iOxFIWLh1B3OEgsuZfBpyyN/kWuqZ8dx9ZEes6zVnDMo+zRHF2wLynRVhoQmV7ohxl2Q=="],
28
+ "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-FhfpkAAlKL6kwvcVap0Hgp4AhZmtd3YImg0kK1jd7C/aSoh4SfsB2f++yG1rU0lr8Y5MCFJrcSkmssiL9Xnnig=="],
29
29
 
30
- "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.11", "", { "os": "linux", "cpu": "x64" }, "sha512-TagWV0iomp5LnEnxWFg4nQO+e52Fow349vaX0Q/PIcX6Zhk4GGBgp3qqZ8PVkpC+cuehRctMf3+6+FgQ8jCEFQ=="],
30
+ "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.12", "", { "os": "linux", "cpu": "x64" }, "sha512-8pFeAnLU9QdW9jCIslB/v82bI0lhBmz2ZAKc8pVMFPO0t0wAHsoEkrUQUbMkIorTRIjbqyNZHA3lEXavsPWYSw=="],
31
31
 
32
- "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.11", "", { "os": "linux", "cpu": "x64" }, "sha512-bexd2IklK7ZgPhrz6jXzpIL6dEAH9MlJU1xGTrypx+FICxrXUp4CqtwfiuoDKse+UlgAlWtzML3jrMqeEAHEhA=="],
32
+ "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.12", "", { "os": "linux", "cpu": "x64" }, "sha512-dwTIgZrGutzhkQCuvHynCkyW6hJxUuyZqKKO0YNfaS2GUoRO+tOvxXZqZB6SkWAOdfZTzwaw8IEdUnIkHKHoew=="],
33
33
 
34
- "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-RJhaTnY8byzxDt4bDVb7AFPHkPcjOPK3xBip4ZRTrN3TEfyhjLRm3r3mqknqydgVTB74XG8l4jMLwEACEeihVg=="],
34
+ "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-B0DLnx0vA9ya/3v7XyCaP+/lCpnbWbMOfUFFve+xb5OxyYvdHaS55YsSddr228Y+JAFk58agCuZTsqNiw2a6ig=="],
35
35
 
36
- "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.11", "", { "os": "win32", "cpu": "x64" }, "sha512-A8D3JM/00C2KQgUV3oj8Ba15EHEYwebAGCy5Sf9GAjr5Y3+kJIYOiESoqRDeuRZueuMdCsbLZIUqmPhpYXJE9A=="],
36
+ "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.12", "", { "os": "win32", "cpu": "x64" }, "sha512-yMckRzTyZ83hkk8iDFWswqSdU8tvZxspJKnYNh7JZr/zhZNOlzH13k4ecboU6MurKExCe2HUkH75pGI/O2JwGA=="],
37
37
 
38
- "@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
38
+ "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
39
39
 
40
40
  "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
41
41
 
@@ -103,7 +103,7 @@
103
103
 
104
104
  "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
105
105
 
106
- "typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
106
+ "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
107
107
 
108
108
  "undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
109
109
  }
@@ -0,0 +1,32 @@
1
+ ## [0.2.0] - 2026-04-18
2
+
3
+ ### 🚀 Features
4
+
5
+ - Init project, ts, biome, git, license, readme, src
6
+ - *(video)* Add video processing, separate code into image/video/shared folders
7
+ - Rename project to @adaptive-ds/assets-optimizer
8
+ - *(list)* Generate image/video list, rename main function to assetsOptimize
9
+ - Allow specifying logging level, allow skipping remote if not configured
10
+ - *(rclone)* Add rclone functions to be used by consumers
11
+
12
+ ### 🐛 Bug Fixes
13
+
14
+ - *(ts)* Remove deprecated downlevelIteration, configure lib rootDir
15
+
16
+ ### 🤖 CI
17
+
18
+ - Setup github oidc publishing
19
+
20
+ ### 🚜 Refactor
21
+
22
+ - Simplify, remove clone remote calls, should be done by callers
23
+
24
+ ### 📚 Documentation
25
+
26
+ - *(readme)* Update, add explanation diagrams
27
+ - *(readme)* Replace r2 with rclone remote
28
+ - *(readme)* Add headings for diagrams
29
+
30
+ ### ⚙️ Miscellaneous Tasks
31
+
32
+ - Add release script, format code with biome, add package metadata
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptive-ds/assets-optimizer",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "main": "./dist/index.js",
5
5
  "dependencies": {
6
6
  "image-size": "^2.0.2",
@@ -1,8 +0,0 @@
1
- {
2
- "folders": [
3
- {
4
- "path": "."
5
- }
6
- ],
7
- "settings": {}
8
- }