@adaptive-ds/assets-optimizer 0.2.0 → 0.2.1

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 (140) hide show
  1. package/changelogs/2026-04-18_v0.2.1.md +5 -0
  2. package/dist/AssetsOptimizeOptions.d.ts +17 -0
  3. package/dist/AssetsOptimizeOptions.d.ts.map +1 -0
  4. package/dist/AssetsOptimizeOptions.js +1 -0
  5. package/dist/AssetsOptimizeResult.d.ts +12 -0
  6. package/dist/AssetsOptimizeResult.d.ts.map +1 -0
  7. package/dist/AssetsOptimizeResult.js +1 -0
  8. package/dist/assetsOptimize.d.ts +4 -0
  9. package/dist/assetsOptimize.d.ts.map +1 -0
  10. package/dist/assetsOptimize.js +61 -0
  11. package/dist/image/ExpectedImage.d.ts +5 -0
  12. package/dist/image/ExpectedImage.d.ts.map +1 -0
  13. package/dist/image/ExpectedImage.js +1 -0
  14. package/dist/image/ImageFormat.d.ts +2 -0
  15. package/dist/image/ImageFormat.d.ts.map +1 -0
  16. package/dist/image/ImageFormat.js +1 -0
  17. package/dist/image/ProcessImagesOptions.d.ts +10 -0
  18. package/dist/image/ProcessImagesOptions.d.ts.map +1 -0
  19. package/dist/image/ProcessImagesOptions.js +1 -0
  20. package/dist/image/TransformSpec.d.ts +8 -0
  21. package/dist/image/TransformSpec.d.ts.map +1 -0
  22. package/dist/image/TransformSpec.js +1 -0
  23. package/dist/image/buildExpectedImages.d.ts +4 -0
  24. package/dist/image/buildExpectedImages.d.ts.map +1 -0
  25. package/dist/image/buildExpectedImages.js +89 -0
  26. package/dist/image/createOutputHash.d.ts +2 -0
  27. package/dist/image/createOutputHash.d.ts.map +1 -0
  28. package/dist/image/createOutputHash.js +4 -0
  29. package/dist/image/createOutputHashForFile.d.ts +2 -0
  30. package/dist/image/createOutputHashForFile.d.ts.map +1 -0
  31. package/dist/image/createOutputHashForFile.js +14 -0
  32. package/dist/image/createRootImageTransform.d.ts +3 -0
  33. package/dist/image/createRootImageTransform.d.ts.map +1 -0
  34. package/dist/image/createRootImageTransform.js +33 -0
  35. package/dist/image/defaultQuality.d.ts +2 -0
  36. package/dist/image/defaultQuality.d.ts.map +1 -0
  37. package/dist/image/defaultQuality.js +1 -0
  38. package/dist/image/imageFormats.d.ts +3 -0
  39. package/dist/image/imageFormats.d.ts.map +1 -0
  40. package/dist/image/imageFormats.js +1 -0
  41. package/dist/image/isImageFormat.d.ts +3 -0
  42. package/dist/image/isImageFormat.d.ts.map +1 -0
  43. package/dist/image/isImageFormat.js +5 -0
  44. package/dist/image/parseTransformSpec.d.ts +3 -0
  45. package/dist/image/parseTransformSpec.d.ts.map +1 -0
  46. package/dist/image/parseTransformSpec.js +26 -0
  47. package/dist/image/processImage.d.ts +3 -0
  48. package/dist/image/processImage.d.ts.map +1 -0
  49. package/dist/image/processImage.js +28 -0
  50. package/dist/image/processImages.d.ts +3 -0
  51. package/dist/image/processImages.d.ts.map +1 -0
  52. package/dist/image/processImages.js +19 -0
  53. package/dist/image/supportedSourceExtensions.d.ts +2 -0
  54. package/dist/image/supportedSourceExtensions.d.ts.map +1 -0
  55. package/dist/image/supportedSourceExtensions.js +1 -0
  56. package/dist/index.d.ts +27 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +26 -0
  59. package/dist/list/AssetListTypes.d.ts +13 -0
  60. package/dist/list/AssetListTypes.d.ts.map +1 -0
  61. package/dist/list/AssetListTypes.js +1 -0
  62. package/dist/list/formatGeneratedCodeFile.d.ts +3 -0
  63. package/dist/list/formatGeneratedCodeFile.d.ts.map +1 -0
  64. package/dist/list/formatGeneratedCodeFile.js +32 -0
  65. package/dist/list/generateImageList.d.ts +3 -0
  66. package/dist/list/generateImageList.d.ts.map +1 -0
  67. package/dist/list/generateImageList.js +85 -0
  68. package/dist/list/generateVideoList.d.ts +3 -0
  69. package/dist/list/generateVideoList.d.ts.map +1 -0
  70. package/dist/list/generateVideoList.js +87 -0
  71. package/dist/list/getAssetKey.d.ts +2 -0
  72. package/dist/list/getAssetKey.d.ts.map +1 -0
  73. package/dist/list/getAssetKey.js +10 -0
  74. package/dist/list/loadExistingAssetList.d.ts +2 -0
  75. package/dist/list/loadExistingAssetList.d.ts.map +1 -0
  76. package/dist/list/loadExistingAssetList.js +23 -0
  77. package/dist/list/sortAssetMap.d.ts +2 -0
  78. package/dist/list/sortAssetMap.d.ts.map +1 -0
  79. package/dist/list/sortAssetMap.js +8 -0
  80. package/dist/rclone/bisync.d.ts +9 -0
  81. package/dist/rclone/bisync.d.ts.map +1 -0
  82. package/dist/rclone/bisync.js +17 -0
  83. package/dist/rclone/runRclone.d.ts +2 -0
  84. package/dist/rclone/runRclone.d.ts.map +1 -0
  85. package/dist/rclone/runRclone.js +13 -0
  86. package/dist/shared/assertNever.d.ts +2 -0
  87. package/dist/shared/assertNever.d.ts.map +1 -0
  88. package/dist/shared/assertNever.js +3 -0
  89. package/dist/shared/dirExists.d.ts +2 -0
  90. package/dist/shared/dirExists.d.ts.map +1 -0
  91. package/dist/shared/dirExists.js +10 -0
  92. package/dist/shared/getOwnPackageName.d.ts +2 -0
  93. package/dist/shared/getOwnPackageName.d.ts.map +1 -0
  94. package/dist/shared/getOwnPackageName.js +21 -0
  95. package/dist/shared/isMissingDirError.d.ts +2 -0
  96. package/dist/shared/isMissingDirError.d.ts.map +1 -0
  97. package/dist/shared/isMissingDirError.js +3 -0
  98. package/dist/shared/listLocalFiles.d.ts +2 -0
  99. package/dist/shared/listLocalFiles.d.ts.map +1 -0
  100. package/dist/shared/listLocalFiles.js +13 -0
  101. package/dist/shared/logger.d.ts +13 -0
  102. package/dist/shared/logger.d.ts.map +1 -0
  103. package/dist/shared/logger.js +47 -0
  104. package/dist/shared/printSummary.d.ts +4 -0
  105. package/dist/shared/printSummary.d.ts.map +1 -0
  106. package/dist/shared/printSummary.js +25 -0
  107. package/dist/shared/walkFiles.d.ts +2 -0
  108. package/dist/shared/walkFiles.d.ts.map +1 -0
  109. package/dist/shared/walkFiles.js +17 -0
  110. package/dist/video/ProcessVideosOptions.d.ts +11 -0
  111. package/dist/video/ProcessVideosOptions.d.ts.map +1 -0
  112. package/dist/video/ProcessVideosOptions.js +1 -0
  113. package/dist/video/createVideoArgs.d.ts +3 -0
  114. package/dist/video/createVideoArgs.d.ts.map +1 -0
  115. package/dist/video/createVideoArgs.js +77 -0
  116. package/dist/video/createVideoPreviewArgs.d.ts +2 -0
  117. package/dist/video/createVideoPreviewArgs.d.ts.map +1 -0
  118. package/dist/video/createVideoPreviewArgs.js +18 -0
  119. package/dist/video/createVideoPreviewPath.d.ts +2 -0
  120. package/dist/video/createVideoPreviewPath.d.ts.map +1 -0
  121. package/dist/video/createVideoPreviewPath.js +3 -0
  122. package/dist/video/ensureVideoPreviews.d.ts +4 -0
  123. package/dist/video/ensureVideoPreviews.d.ts.map +1 -0
  124. package/dist/video/ensureVideoPreviews.js +30 -0
  125. package/dist/video/getAvailableVideoEncoders.d.ts +3 -0
  126. package/dist/video/getAvailableVideoEncoders.d.ts.map +1 -0
  127. package/dist/video/getAvailableVideoEncoders.js +36 -0
  128. package/dist/video/processLocalVideos.d.ts +4 -0
  129. package/dist/video/processLocalVideos.d.ts.map +1 -0
  130. package/dist/video/processLocalVideos.js +26 -0
  131. package/dist/video/processVideos.d.ts +3 -0
  132. package/dist/video/processVideos.d.ts.map +1 -0
  133. package/dist/video/processVideos.js +10 -0
  134. package/dist/video/runFfmpeg.d.ts +3 -0
  135. package/dist/video/runFfmpeg.d.ts.map +1 -0
  136. package/dist/video/runFfmpeg.js +26 -0
  137. package/dist/video/supportedVideoSourceExtensions.d.ts +2 -0
  138. package/dist/video/supportedVideoSourceExtensions.d.ts.map +1 -0
  139. package/dist/video/supportedVideoSourceExtensions.js +1 -0
  140. package/package.json +1 -1
@@ -0,0 +1,5 @@
1
+ ## [0.2.1] - 2026-04-18
2
+
3
+ ### 🐛 Bug Fixes
4
+
5
+ - *(build)* Include dist dir in published packages
@@ -0,0 +1,17 @@
1
+ export interface AssetsOptimizeOptions {
2
+ cwd?: string;
3
+ logLevel?: 0 | 1 | 2 | 3;
4
+ processImages?: boolean;
5
+ imageOriginalsDir?: string;
6
+ imageOptimizedDir?: string;
7
+ allowRootImageFiles?: boolean;
8
+ imageListOutputPath?: string;
9
+ generateImageList?: boolean;
10
+ processVideos?: boolean;
11
+ videoOriginalsDir?: string;
12
+ videoOptimizedDir?: string;
13
+ videoListOutputPath?: string;
14
+ generateVideoList?: boolean;
15
+ videoPreviewQuality?: number;
16
+ }
17
+ //# sourceMappingURL=AssetsOptimizeOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetsOptimizeOptions.d.ts","sourceRoot":"","sources":["../src/AssetsOptimizeOptions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACxB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ export interface AssetsOptimizeResult {
2
+ processed: string[];
3
+ skippedExisting: string[];
4
+ skippedRootFiles: string[];
5
+ warnings: string[];
6
+ deletedLocal: string[];
7
+ processedVideos: string[];
8
+ skippedExistingVideos: string[];
9
+ processedVideoPreviews: string[];
10
+ skippedExistingVideoPreviews: string[];
11
+ }
12
+ //# sourceMappingURL=AssetsOptimizeResult.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetsOptimizeResult.d.ts","sourceRoot":"","sources":["../src/AssetsOptimizeResult.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,qBAAqB,EAAE,MAAM,EAAE,CAAA;IAC/B,sBAAsB,EAAE,MAAM,EAAE,CAAA;IAChC,4BAA4B,EAAE,MAAM,EAAE,CAAA;CACvC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { AssetsOptimizeOptions } from "./AssetsOptimizeOptions.js";
2
+ import type { AssetsOptimizeResult } from "./AssetsOptimizeResult.js";
3
+ export declare function assetsOptimize(options?: AssetsOptimizeOptions): Promise<AssetsOptimizeResult>;
4
+ //# sourceMappingURL=assetsOptimize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assetsOptimize.d.ts","sourceRoot":"","sources":["../src/assetsOptimize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAQrE,wBAAsB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAyDvG"}
@@ -0,0 +1,61 @@
1
+ import path from "node:path";
2
+ import { processImages } from "./image/processImages.js";
3
+ import { generateImageList } from "./list/generateImageList.js";
4
+ import { generateVideoList } from "./list/generateVideoList.js";
5
+ import { createLogger } from "./shared/logger.js";
6
+ import { printSummary } from "./shared/printSummary.js";
7
+ import { processVideos } from "./video/processVideos.js";
8
+ export async function assetsOptimize(options = {}) {
9
+ const cwd = path.resolve(options.cwd ?? process.cwd());
10
+ const processImagesEnabled = options.processImages !== false;
11
+ const processVideosEnabled = options.processVideos !== false;
12
+ const imageOriginalsDir = path.resolve(cwd, options.imageOriginalsDir ?? "images");
13
+ const imageOptimizedDir = path.resolve(cwd, options.imageOptimizedDir ?? "public/images");
14
+ const imageListOutputPath = path.resolve(cwd, options.imageListOutputPath ?? "src/app/assets/imageList.ts");
15
+ const videoOriginalsDir = path.resolve(cwd, options.videoOriginalsDir ?? "videos");
16
+ const videoOptimizedDir = path.resolve(cwd, options.videoOptimizedDir ?? "public/videos");
17
+ const videoListOutputPath = path.resolve(cwd, options.videoListOutputPath ?? "src/app/assets/videoList.ts");
18
+ const logger = createLogger(options.logLevel);
19
+ const result = {
20
+ processed: [],
21
+ skippedExisting: [],
22
+ skippedRootFiles: [],
23
+ warnings: [],
24
+ deletedLocal: [],
25
+ processedVideos: [],
26
+ skippedExistingVideos: [],
27
+ processedVideoPreviews: [],
28
+ skippedExistingVideoPreviews: [],
29
+ };
30
+ await Promise.all([
31
+ processImagesEnabled
32
+ ? processImages({
33
+ imageOriginalsDir,
34
+ imageOptimizedDir,
35
+ allowRootImageFiles: options.allowRootImageFiles === true,
36
+ result,
37
+ logger,
38
+ })
39
+ : Promise.resolve(),
40
+ processVideosEnabled
41
+ ? processVideos({
42
+ cwd,
43
+ videoOriginalsDir,
44
+ videoOptimizedDir,
45
+ videoPreviewQuality: options.videoPreviewQuality ?? 80,
46
+ result,
47
+ logger,
48
+ })
49
+ : Promise.resolve(),
50
+ ]);
51
+ await Promise.all([
52
+ options.generateImageList === false
53
+ ? Promise.resolve()
54
+ : generateImageList(imageOptimizedDir, imageListOutputPath, undefined, logger),
55
+ options.generateVideoList === false
56
+ ? Promise.resolve()
57
+ : generateVideoList(videoOptimizedDir, videoListOutputPath, undefined, logger),
58
+ ]);
59
+ printSummary(result, logger);
60
+ return result;
61
+ }
@@ -0,0 +1,5 @@
1
+ export interface ExpectedImage {
2
+ localPath: string;
3
+ fileName: string;
4
+ }
5
+ //# sourceMappingURL=ExpectedImage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpectedImage.d.ts","sourceRoot":"","sources":["../../src/image/ExpectedImage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export type ImageFormat = "jpg" | "png" | "webp" | "avif";
2
+ //# sourceMappingURL=ImageFormat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageFormat.d.ts","sourceRoot":"","sources":["../../src/image/ImageFormat.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { AssetsOptimizeResult } from "../AssetsOptimizeResult.js";
2
+ import type { Logger } from "../shared/logger.js";
3
+ export interface ProcessImagesOptions {
4
+ imageOriginalsDir: string;
5
+ imageOptimizedDir: string;
6
+ allowRootImageFiles: boolean;
7
+ result: AssetsOptimizeResult;
8
+ logger: Logger;
9
+ }
10
+ //# sourceMappingURL=ProcessImagesOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProcessImagesOptions.d.ts","sourceRoot":"","sources":["../../src/image/ProcessImagesOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,MAAM,WAAW,oBAAoB;IACnC,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,mBAAmB,EAAE,OAAO,CAAA;IAC5B,MAAM,EAAE,oBAAoB,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAA;CACf"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { ImageFormat } from "./ImageFormat.js";
2
+ export interface TransformSpec {
3
+ width: number;
4
+ height: number;
5
+ format: ImageFormat;
6
+ normalized: string;
7
+ }
8
+ //# sourceMappingURL=TransformSpec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TransformSpec.d.ts","sourceRoot":"","sources":["../../src/image/TransformSpec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEnD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;CACnB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { AssetsOptimizeResult } from "../AssetsOptimizeResult.js";
2
+ import { type ExpectedImage } from "./ExpectedImage.js";
3
+ export declare function buildExpectedImages(originalsDir: string, optimizedDir: string, result: AssetsOptimizeResult, allowRootImageFiles?: boolean): Promise<ExpectedImage[]>;
4
+ //# sourceMappingURL=buildExpectedImages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildExpectedImages.d.ts","sourceRoot":"","sources":["../../src/image/buildExpectedImages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAItE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAKvD,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,oBAAoB,EAC5B,mBAAmB,UAAQ,GAC1B,OAAO,CAAC,aAAa,EAAE,CAAC,CA0F1B"}
@@ -0,0 +1,89 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { walkFiles } from "../shared/walkFiles.js";
4
+ import { createOutputHash } from "./createOutputHash.js";
5
+ import { createRootImageTransform } from "./createRootImageTransform.js";
6
+ import {} from "./ExpectedImage.js";
7
+ import { parseTransformSpec } from "./parseTransformSpec.js";
8
+ import { processImage } from "./processImage.js";
9
+ import { supportedSourceExtensions } from "./supportedSourceExtensions.js";
10
+ export async function buildExpectedImages(originalsDir, optimizedDir, result, allowRootImageFiles = false) {
11
+ const dirEntries = await fs.readdir(originalsDir, { withFileTypes: true });
12
+ const expectedImages = [];
13
+ for (const entry of dirEntries) {
14
+ const entryPath = path.join(originalsDir, entry.name);
15
+ if (entry.isFile()) {
16
+ if (!allowRootImageFiles) {
17
+ result.skippedRootFiles.push(entry.name);
18
+ result.warnings.push(`Skipped root original file: ${entry.name}`);
19
+ console.warn(`Skipped root original file: ${entry.name}`);
20
+ continue;
21
+ }
22
+ const extension = path.extname(entry.name).toLowerCase();
23
+ if (!supportedSourceExtensions.has(extension)) {
24
+ result.warnings.push(`Skipped unsupported root source file: ${entry.name}`);
25
+ console.warn(`Skipped unsupported root source file: ${entry.name}`);
26
+ continue;
27
+ }
28
+ const sourceBuffer = await fs.readFile(entryPath);
29
+ const transform = createRootImageTransform(entryPath, sourceBuffer);
30
+ if (!transform) {
31
+ result.warnings.push(`Skipped root source file with unsupported output format: ${entry.name}`);
32
+ console.warn(`Skipped root source file with unsupported output format: ${entry.name}`);
33
+ continue;
34
+ }
35
+ const hash = createOutputHash(sourceBuffer, transform.normalized);
36
+ const baseName = path.parse(entryPath).name;
37
+ const fileName = `${baseName}_${hash}.${transform.format}`;
38
+ const outputPath = path.join(optimizedDir, fileName);
39
+ expectedImages.push({
40
+ fileName,
41
+ localPath: outputPath,
42
+ });
43
+ try {
44
+ await fs.access(outputPath);
45
+ result.skippedExisting.push(fileName);
46
+ }
47
+ catch {
48
+ await processImage(sourceBuffer, outputPath, transform);
49
+ result.processed.push(fileName);
50
+ }
51
+ continue;
52
+ }
53
+ if (!entry.isDirectory()) {
54
+ continue;
55
+ }
56
+ const transform = parseTransformSpec(entry.name);
57
+ if (!transform) {
58
+ result.warnings.push(`Skipped folder with invalid transform name: ${entry.name}`);
59
+ console.warn(`Skipped folder with invalid transform name: ${entry.name}`);
60
+ continue;
61
+ }
62
+ for (const sourceFile of await walkFiles(entryPath)) {
63
+ const extension = path.extname(sourceFile).toLowerCase();
64
+ if (!supportedSourceExtensions.has(extension)) {
65
+ result.warnings.push(`Skipped unsupported source file: ${path.relative(originalsDir, sourceFile)}`);
66
+ console.warn(`Skipped unsupported source file: ${path.relative(originalsDir, sourceFile)}`);
67
+ continue;
68
+ }
69
+ const sourceBuffer = await fs.readFile(sourceFile);
70
+ const hash = createOutputHash(sourceBuffer, transform.normalized);
71
+ const baseName = path.parse(sourceFile).name;
72
+ const fileName = `${baseName}_${hash}.${transform.format}`;
73
+ const outputPath = path.join(optimizedDir, fileName);
74
+ expectedImages.push({
75
+ fileName,
76
+ localPath: outputPath,
77
+ });
78
+ try {
79
+ await fs.access(outputPath);
80
+ result.skippedExisting.push(fileName);
81
+ }
82
+ catch {
83
+ await processImage(sourceBuffer, outputPath, transform);
84
+ result.processed.push(fileName);
85
+ }
86
+ }
87
+ }
88
+ return expectedImages;
89
+ }
@@ -0,0 +1,2 @@
1
+ export declare function createOutputHash(sourceBuffer: Buffer, transformSpec: string): string;
2
+ //# sourceMappingURL=createOutputHash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createOutputHash.d.ts","sourceRoot":"","sources":["../../src/image/createOutputHash.ts"],"names":[],"mappings":"AAEA,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAEpF"}
@@ -0,0 +1,4 @@
1
+ import { createHash } from "node:crypto";
2
+ export function createOutputHash(sourceBuffer, transformSpec) {
3
+ return createHash("sha256").update(sourceBuffer).update(transformSpec).digest("hex").slice(0, 8);
4
+ }
@@ -0,0 +1,2 @@
1
+ export declare function createOutputHashForFile(sourcePath: string, transformSpec: string): Promise<string>;
2
+ //# sourceMappingURL=createOutputHashForFile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createOutputHashForFile.d.ts","sourceRoot":"","sources":["../../src/image/createOutputHashForFile.ts"],"names":[],"mappings":"AAGA,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAaxG"}
@@ -0,0 +1,14 @@
1
+ import { createHash } from "node:crypto";
2
+ import fs from "node:fs";
3
+ export async function createOutputHashForFile(sourcePath, transformSpec) {
4
+ const hash = createHash("sha256");
5
+ await new Promise((resolve, reject) => {
6
+ const stream = fs.createReadStream(sourcePath);
7
+ stream.on("data", (chunk) => {
8
+ hash.update(chunk);
9
+ });
10
+ stream.on("end", resolve);
11
+ stream.on("error", reject);
12
+ });
13
+ return hash.update(transformSpec).digest("hex").slice(0, 8);
14
+ }
@@ -0,0 +1,3 @@
1
+ import type { TransformSpec } from "./TransformSpec.js";
2
+ export declare function createRootImageTransform(sourceFile: string, sourceBuffer: Buffer): TransformSpec | null;
3
+ //# sourceMappingURL=createRootImageTransform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createRootImageTransform.d.ts","sourceRoot":"","sources":["../../src/image/createRootImageTransform.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAiBvG"}
@@ -0,0 +1,33 @@
1
+ import { imageSize } from "image-size";
2
+ import path from "node:path";
3
+ export function createRootImageTransform(sourceFile, sourceBuffer) {
4
+ const format = getOutputFormat(path.extname(sourceFile).toLowerCase());
5
+ if (!format) {
6
+ return null;
7
+ }
8
+ const dimensions = imageSize(sourceBuffer);
9
+ if (!dimensions.width || !dimensions.height) {
10
+ return null;
11
+ }
12
+ return {
13
+ width: dimensions.width,
14
+ height: dimensions.height,
15
+ format,
16
+ normalized: `root_${dimensions.width}x${dimensions.height}_${format}`,
17
+ };
18
+ }
19
+ function getOutputFormat(extension) {
20
+ switch (extension) {
21
+ case ".jpg":
22
+ case ".jpeg":
23
+ return "jpg";
24
+ case ".png":
25
+ return "png";
26
+ case ".webp":
27
+ return "webp";
28
+ case ".avif":
29
+ return "avif";
30
+ default:
31
+ return null;
32
+ }
33
+ }
@@ -0,0 +1,2 @@
1
+ export declare const defaultQuality = 80;
2
+ //# sourceMappingURL=defaultQuality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultQuality.d.ts","sourceRoot":"","sources":["../../src/image/defaultQuality.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,KAAK,CAAA"}
@@ -0,0 +1 @@
1
+ export const defaultQuality = 80;
@@ -0,0 +1,3 @@
1
+ import type { ImageFormat } from "./ImageFormat.js";
2
+ export declare const imageFormats: Set<ImageFormat>;
3
+ //# sourceMappingURL=imageFormats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageFormats.d.ts","sourceRoot":"","sources":["../../src/image/imageFormats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEnD,eAAO,MAAM,YAAY,kBAAuD,CAAA"}
@@ -0,0 +1 @@
1
+ export const imageFormats = new Set(["jpg", "png", "webp", "avif"]);
@@ -0,0 +1,3 @@
1
+ import { type ImageFormat } from "./ImageFormat.js";
2
+ export declare function isImageFormat(value: string): value is ImageFormat;
3
+ //# sourceMappingURL=isImageFormat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isImageFormat.d.ts","sourceRoot":"","sources":["../../src/image/isImageFormat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGnD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,WAAW,CAEjE"}
@@ -0,0 +1,5 @@
1
+ import {} from "./ImageFormat.js";
2
+ import { imageFormats } from "./imageFormats.js";
3
+ export function isImageFormat(value) {
4
+ return imageFormats.has(value);
5
+ }
@@ -0,0 +1,3 @@
1
+ import type { TransformSpec } from "./TransformSpec.js";
2
+ export declare function parseTransformSpec(dirName: string): TransformSpec | null;
3
+ //# sourceMappingURL=parseTransformSpec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseTransformSpec.d.ts","sourceRoot":"","sources":["../../src/image/parseTransformSpec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA4BxE"}
@@ -0,0 +1,26 @@
1
+ import { isImageFormat } from "./isImageFormat.js";
2
+ export function parseTransformSpec(dirName) {
3
+ const match = /^(?<width>\d+)x(?<height>\d+)_(?<format>jpg|png|webp|avif)$/.exec(dirName);
4
+ if (!match?.groups) {
5
+ return null;
6
+ }
7
+ const { width: widthValue, height: heightValue, format: formatValue } = match.groups;
8
+ if (!widthValue || !heightValue || !formatValue) {
9
+ return null;
10
+ }
11
+ const width = Number.parseInt(widthValue, 10);
12
+ const height = Number.parseInt(heightValue, 10);
13
+ if (!isImageFormat(formatValue)) {
14
+ return null;
15
+ }
16
+ const format = formatValue;
17
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
18
+ return null;
19
+ }
20
+ return {
21
+ width,
22
+ height,
23
+ format,
24
+ normalized: `${width}x${height}_${format}`,
25
+ };
26
+ }
@@ -0,0 +1,3 @@
1
+ import type { TransformSpec } from "./TransformSpec.js";
2
+ export declare function processImage(sourceBuffer: Buffer, outputPath: string, transform: TransformSpec, quality?: number): Promise<void>;
3
+ //# sourceMappingURL=processImage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processImage.d.ts","sourceRoot":"","sources":["../../src/image/processImage.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,aAAa,EACxB,OAAO,SAAiB,GACvB,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
@@ -0,0 +1,28 @@
1
+ import sharp from "sharp";
2
+ import { assertNever } from "../shared/assertNever.js";
3
+ import { defaultQuality } from "./defaultQuality.js";
4
+ export async function processImage(sourceBuffer, outputPath, transform, quality = defaultQuality) {
5
+ let pipeline = sharp(sourceBuffer, { animated: false }).rotate().resize({
6
+ width: transform.width,
7
+ height: transform.height,
8
+ fit: "inside",
9
+ withoutEnlargement: true,
10
+ });
11
+ switch (transform.format) {
12
+ case "jpg":
13
+ pipeline = pipeline.jpeg({ quality });
14
+ break;
15
+ case "png":
16
+ pipeline = pipeline.png({ quality });
17
+ break;
18
+ case "webp":
19
+ pipeline = pipeline.webp({ quality });
20
+ break;
21
+ case "avif":
22
+ pipeline = pipeline.avif({ quality });
23
+ break;
24
+ default:
25
+ assertNever(transform.format);
26
+ }
27
+ await pipeline.toFile(outputPath);
28
+ }
@@ -0,0 +1,3 @@
1
+ import type { ProcessImagesOptions } from "./ProcessImagesOptions.js";
2
+ export declare function processImages(options: ProcessImagesOptions): Promise<void>;
3
+ //# sourceMappingURL=processImages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processImages.d.ts","sourceRoot":"","sources":["../../src/image/processImages.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAErE,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhF"}
@@ -0,0 +1,19 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { listLocalFiles } from "../shared/listLocalFiles.js";
4
+ import { buildExpectedImages } from "./buildExpectedImages.js";
5
+ export async function processImages(options) {
6
+ const { allowRootImageFiles, imageOptimizedDir, imageOriginalsDir, result } = options;
7
+ await fs.mkdir(imageOriginalsDir, { recursive: true });
8
+ await fs.mkdir(imageOptimizedDir, { recursive: true });
9
+ const expectedImages = await buildExpectedImages(imageOriginalsDir, imageOptimizedDir, result, allowRootImageFiles);
10
+ const expectedFileNames = new Set(expectedImages.map((image) => image.fileName));
11
+ const localOptimizedFiles = await listLocalFiles(imageOptimizedDir);
12
+ for (const localFile of localOptimizedFiles) {
13
+ const relativeFile = path.relative(imageOptimizedDir, localFile);
14
+ if (!expectedFileNames.has(relativeFile) && !relativeFile.startsWith(".")) {
15
+ await fs.rm(localFile, { force: true });
16
+ result.deletedLocal.push(relativeFile);
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,2 @@
1
+ export declare const supportedSourceExtensions: Set<string>;
2
+ //# sourceMappingURL=supportedSourceExtensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supportedSourceExtensions.d.ts","sourceRoot":"","sources":["../../src/image/supportedSourceExtensions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,aAAgF,CAAA"}
@@ -0,0 +1 @@
1
+ export const supportedSourceExtensions = new Set([".jpg", ".jpeg", ".png", ".webp", ".avif", ".tif", ".tiff", ".gif"]);
@@ -0,0 +1,27 @@
1
+ export * from "./AssetsOptimizeOptions.js";
2
+ export * from "./AssetsOptimizeResult.js";
3
+ export * from "./image/buildExpectedImages.js";
4
+ export * from "./image/createOutputHash.js";
5
+ export * from "./image/defaultQuality.js";
6
+ export * from "./image/ExpectedImage.js";
7
+ export * from "./image/ImageFormat.js";
8
+ export * from "./image/parseTransformSpec.js";
9
+ export * from "./image/processImage.js";
10
+ export * from "./image/processImages.js";
11
+ export * from "./image/ProcessImagesOptions.js";
12
+ export * from "./image/supportedSourceExtensions.js";
13
+ export * from "./image/TransformSpec.js";
14
+ export * from "./list/AssetListTypes.js";
15
+ export * from "./list/generateImageList.js";
16
+ export * from "./list/generateVideoList.js";
17
+ export * from "./assetsOptimize.js";
18
+ export * from "./rclone/bisync.js";
19
+ export * from "./rclone/runRclone.js";
20
+ export * from "./shared/listLocalFiles.js";
21
+ export * from "./shared/printSummary.js";
22
+ export * from "./shared/walkFiles.js";
23
+ export * from "./video/createVideoPreviewPath.js";
24
+ export * from "./video/ensureVideoPreviews.js";
25
+ export * from "./video/processVideos.js";
26
+ export * from "./video/ProcessVideosOptions.js";
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,sCAAsC,CAAA;AACpD,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mCAAmC,CAAA;AACjD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ export * from "./AssetsOptimizeOptions.js";
2
+ export * from "./AssetsOptimizeResult.js";
3
+ export * from "./image/buildExpectedImages.js";
4
+ export * from "./image/createOutputHash.js";
5
+ export * from "./image/defaultQuality.js";
6
+ export * from "./image/ExpectedImage.js";
7
+ export * from "./image/ImageFormat.js";
8
+ export * from "./image/parseTransformSpec.js";
9
+ export * from "./image/processImage.js";
10
+ export * from "./image/processImages.js";
11
+ export * from "./image/ProcessImagesOptions.js";
12
+ export * from "./image/supportedSourceExtensions.js";
13
+ export * from "./image/TransformSpec.js";
14
+ export * from "./list/AssetListTypes.js";
15
+ export * from "./list/generateImageList.js";
16
+ export * from "./list/generateVideoList.js";
17
+ export * from "./assetsOptimize.js";
18
+ export * from "./rclone/bisync.js";
19
+ export * from "./rclone/runRclone.js";
20
+ export * from "./shared/listLocalFiles.js";
21
+ export * from "./shared/printSummary.js";
22
+ export * from "./shared/walkFiles.js";
23
+ export * from "./video/createVideoPreviewPath.js";
24
+ export * from "./video/ensureVideoPreviews.js";
25
+ export * from "./video/processVideos.js";
26
+ export * from "./video/ProcessVideosOptions.js";
@@ -0,0 +1,13 @@
1
+ export interface ImageType {
2
+ path: string;
3
+ width: number;
4
+ height: number;
5
+ alt: string;
6
+ mimeType?: string;
7
+ }
8
+ export interface VideoType {
9
+ path: string;
10
+ mimeType?: string;
11
+ image: ImageType;
12
+ }
13
+ //# sourceMappingURL=AssetListTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetListTypes.d.ts","sourceRoot":"","sources":["../../src/list/AssetListTypes.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;CACjB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { Logger } from "../shared/logger.js";
2
+ export declare function formatGeneratedCodeFile(outputPath: string, logger?: Logger): Promise<void>;
3
+ //# sourceMappingURL=formatGeneratedCodeFile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatGeneratedCodeFile.d.ts","sourceRoot":"","sources":["../../src/list/formatGeneratedCodeFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChG"}