@openinary/core 1.1.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.
Files changed (242) hide show
  1. package/LICENSE +661 -0
  2. package/dist/config/deps.d.ts +14 -0
  3. package/dist/config/deps.d.ts.map +1 -0
  4. package/dist/config/deps.js +2 -0
  5. package/dist/config/deps.js.map +1 -0
  6. package/dist/index.d.ts +27 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +28 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/routes/authenticated.d.ts +4 -0
  11. package/dist/routes/authenticated.d.ts.map +1 -0
  12. package/dist/routes/authenticated.js +130 -0
  13. package/dist/routes/authenticated.js.map +1 -0
  14. package/dist/routes/download-folder.d.ts +4 -0
  15. package/dist/routes/download-folder.d.ts.map +1 -0
  16. package/dist/routes/download-folder.js +101 -0
  17. package/dist/routes/download-folder.js.map +1 -0
  18. package/dist/routes/download-zip.d.ts +15 -0
  19. package/dist/routes/download-zip.d.ts.map +1 -0
  20. package/dist/routes/download-zip.js +147 -0
  21. package/dist/routes/download-zip.js.map +1 -0
  22. package/dist/routes/download.d.ts +4 -0
  23. package/dist/routes/download.d.ts.map +1 -0
  24. package/dist/routes/download.js +83 -0
  25. package/dist/routes/download.js.map +1 -0
  26. package/dist/routes/invalidate.d.ts +4 -0
  27. package/dist/routes/invalidate.d.ts.map +1 -0
  28. package/dist/routes/invalidate.js +114 -0
  29. package/dist/routes/invalidate.js.map +1 -0
  30. package/dist/routes/queue-events.d.ts +4 -0
  31. package/dist/routes/queue-events.d.ts.map +1 -0
  32. package/dist/routes/queue-events.js +125 -0
  33. package/dist/routes/queue-events.js.map +1 -0
  34. package/dist/routes/queue.d.ts +4 -0
  35. package/dist/routes/queue.d.ts.map +1 -0
  36. package/dist/routes/queue.js +130 -0
  37. package/dist/routes/queue.js.map +1 -0
  38. package/dist/routes/storage.d.ts +4 -0
  39. package/dist/routes/storage.d.ts.map +1 -0
  40. package/dist/routes/storage.js +694 -0
  41. package/dist/routes/storage.js.map +1 -0
  42. package/dist/routes/transform-helpers.d.ts +62 -0
  43. package/dist/routes/transform-helpers.d.ts.map +1 -0
  44. package/dist/routes/transform-helpers.js +372 -0
  45. package/dist/routes/transform-helpers.js.map +1 -0
  46. package/dist/routes/transform.d.ts +4 -0
  47. package/dist/routes/transform.d.ts.map +1 -0
  48. package/dist/routes/transform.js +65 -0
  49. package/dist/routes/transform.js.map +1 -0
  50. package/dist/routes/video-status.d.ts +4 -0
  51. package/dist/routes/video-status.d.ts.map +1 -0
  52. package/dist/routes/video-status.js +208 -0
  53. package/dist/routes/video-status.js.map +1 -0
  54. package/dist/services/transform.service.d.ts +71 -0
  55. package/dist/services/transform.service.d.ts.map +1 -0
  56. package/dist/services/transform.service.js +362 -0
  57. package/dist/services/transform.service.js.map +1 -0
  58. package/dist/types.d.ts +82 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/utils/asset-deletion.d.ts +16 -0
  63. package/dist/utils/asset-deletion.d.ts.map +1 -0
  64. package/dist/utils/asset-deletion.js +131 -0
  65. package/dist/utils/asset-deletion.js.map +1 -0
  66. package/dist/utils/cache.d.ts +44 -0
  67. package/dist/utils/cache.d.ts.map +1 -0
  68. package/dist/utils/cache.js +248 -0
  69. package/dist/utils/cache.js.map +1 -0
  70. package/dist/utils/get-unique-file-path.d.ts +8 -0
  71. package/dist/utils/get-unique-file-path.d.ts.map +1 -0
  72. package/dist/utils/get-unique-file-path.js +26 -0
  73. package/dist/utils/get-unique-file-path.js.map +1 -0
  74. package/dist/utils/image/aspect-ratio.d.ts +7 -0
  75. package/dist/utils/image/aspect-ratio.d.ts.map +1 -0
  76. package/dist/utils/image/aspect-ratio.js +40 -0
  77. package/dist/utils/image/aspect-ratio.js.map +1 -0
  78. package/dist/utils/image/background.d.ts +6 -0
  79. package/dist/utils/image/background.d.ts.map +1 -0
  80. package/dist/utils/image/background.js +22 -0
  81. package/dist/utils/image/background.js.map +1 -0
  82. package/dist/utils/image/compression.d.ts +44 -0
  83. package/dist/utils/image/compression.d.ts.map +1 -0
  84. package/dist/utils/image/compression.js +345 -0
  85. package/dist/utils/image/compression.js.map +1 -0
  86. package/dist/utils/image/gravity.d.ts +6 -0
  87. package/dist/utils/image/gravity.d.ts.map +1 -0
  88. package/dist/utils/image/gravity.js +24 -0
  89. package/dist/utils/image/gravity.js.map +1 -0
  90. package/dist/utils/image/index.d.ts +8 -0
  91. package/dist/utils/image/index.d.ts.map +1 -0
  92. package/dist/utils/image/index.js +77 -0
  93. package/dist/utils/image/index.js.map +1 -0
  94. package/dist/utils/image/param-registry.d.ts +63 -0
  95. package/dist/utils/image/param-registry.d.ts.map +1 -0
  96. package/dist/utils/image/param-registry.js +196 -0
  97. package/dist/utils/image/param-registry.js.map +1 -0
  98. package/dist/utils/image/quality.d.ts +8 -0
  99. package/dist/utils/image/quality.d.ts.map +1 -0
  100. package/dist/utils/image/quality.js +9 -0
  101. package/dist/utils/image/quality.js.map +1 -0
  102. package/dist/utils/image/resize.d.ts +7 -0
  103. package/dist/utils/image/resize.d.ts.map +1 -0
  104. package/dist/utils/image/resize.js +62 -0
  105. package/dist/utils/image/resize.js.map +1 -0
  106. package/dist/utils/image/rotation.d.ts +6 -0
  107. package/dist/utils/image/rotation.d.ts.map +1 -0
  108. package/dist/utils/image/rotation.js +20 -0
  109. package/dist/utils/image/rotation.js.map +1 -0
  110. package/dist/utils/image/round-corners.d.ts +12 -0
  111. package/dist/utils/image/round-corners.d.ts.map +1 -0
  112. package/dist/utils/image/round-corners.js +102 -0
  113. package/dist/utils/image/round-corners.js.map +1 -0
  114. package/dist/utils/image/types.d.ts +2 -0
  115. package/dist/utils/image/types.d.ts.map +1 -0
  116. package/dist/utils/image/types.js +2 -0
  117. package/dist/utils/image/types.js.map +1 -0
  118. package/dist/utils/logger.d.ts +21 -0
  119. package/dist/utils/logger.d.ts.map +1 -0
  120. package/dist/utils/logger.js +82 -0
  121. package/dist/utils/logger.js.map +1 -0
  122. package/dist/utils/parser.d.ts +8 -0
  123. package/dist/utils/parser.d.ts.map +1 -0
  124. package/dist/utils/parser.js +226 -0
  125. package/dist/utils/parser.js.map +1 -0
  126. package/dist/utils/signature.d.ts +35 -0
  127. package/dist/utils/signature.d.ts.map +1 -0
  128. package/dist/utils/signature.js +100 -0
  129. package/dist/utils/signature.js.map +1 -0
  130. package/dist/utils/storage/cache.d.ts +41 -0
  131. package/dist/utils/storage/cache.d.ts.map +1 -0
  132. package/dist/utils/storage/cache.js +90 -0
  133. package/dist/utils/storage/cache.js.map +1 -0
  134. package/dist/utils/storage/cloud-storage.d.ts +188 -0
  135. package/dist/utils/storage/cloud-storage.d.ts.map +1 -0
  136. package/dist/utils/storage/cloud-storage.js +514 -0
  137. package/dist/utils/storage/cloud-storage.js.map +1 -0
  138. package/dist/utils/storage/factory.d.ts +10 -0
  139. package/dist/utils/storage/factory.d.ts.map +1 -0
  140. package/dist/utils/storage/factory.js +17 -0
  141. package/dist/utils/storage/factory.js.map +1 -0
  142. package/dist/utils/storage/index.d.ts +7 -0
  143. package/dist/utils/storage/index.d.ts.map +1 -0
  144. package/dist/utils/storage/index.js +8 -0
  145. package/dist/utils/storage/index.js.map +1 -0
  146. package/dist/utils/storage/key-generator.d.ts +11 -0
  147. package/dist/utils/storage/key-generator.d.ts.map +1 -0
  148. package/dist/utils/storage/key-generator.js +23 -0
  149. package/dist/utils/storage/key-generator.js.map +1 -0
  150. package/dist/utils/storage/listing-cache.d.ts +14 -0
  151. package/dist/utils/storage/listing-cache.d.ts.map +1 -0
  152. package/dist/utils/storage/listing-cache.js +29 -0
  153. package/dist/utils/storage/listing-cache.js.map +1 -0
  154. package/dist/utils/storage/s3-client.d.ts +97 -0
  155. package/dist/utils/storage/s3-client.d.ts.map +1 -0
  156. package/dist/utils/storage/s3-client.js +297 -0
  157. package/dist/utils/storage/s3-client.js.map +1 -0
  158. package/dist/utils/storage/stats-tracker.d.ts +45 -0
  159. package/dist/utils/storage/stats-tracker.d.ts.map +1 -0
  160. package/dist/utils/storage/stats-tracker.js +97 -0
  161. package/dist/utils/storage/stats-tracker.js.map +1 -0
  162. package/dist/utils/storage/types.d.ts +2 -0
  163. package/dist/utils/storage/types.d.ts.map +1 -0
  164. package/dist/utils/storage/types.js +2 -0
  165. package/dist/utils/storage/types.js.map +1 -0
  166. package/dist/utils/storage-level.d.ts +66 -0
  167. package/dist/utils/storage-level.d.ts.map +1 -0
  168. package/dist/utils/storage-level.js +106 -0
  169. package/dist/utils/storage-level.js.map +1 -0
  170. package/dist/utils/storage-tree.d.ts +30 -0
  171. package/dist/utils/storage-tree.d.ts.map +1 -0
  172. package/dist/utils/storage-tree.js +81 -0
  173. package/dist/utils/storage-tree.js.map +1 -0
  174. package/dist/utils/upload-signature.d.ts +25 -0
  175. package/dist/utils/upload-signature.d.ts.map +1 -0
  176. package/dist/utils/upload-signature.js +56 -0
  177. package/dist/utils/upload-signature.js.map +1 -0
  178. package/dist/utils/video/auto-downscale.d.ts +12 -0
  179. package/dist/utils/video/auto-downscale.d.ts.map +1 -0
  180. package/dist/utils/video/auto-downscale.js +29 -0
  181. package/dist/utils/video/auto-downscale.js.map +1 -0
  182. package/dist/utils/video/command-builder.d.ts +22 -0
  183. package/dist/utils/video/command-builder.d.ts.map +1 -0
  184. package/dist/utils/video/command-builder.js +79 -0
  185. package/dist/utils/video/command-builder.js.map +1 -0
  186. package/dist/utils/video/config.d.ts +51 -0
  187. package/dist/utils/video/config.d.ts.map +1 -0
  188. package/dist/utils/video/config.js +170 -0
  189. package/dist/utils/video/config.js.map +1 -0
  190. package/dist/utils/video/format.d.ts +22 -0
  191. package/dist/utils/video/format.d.ts.map +1 -0
  192. package/dist/utils/video/format.js +64 -0
  193. package/dist/utils/video/format.js.map +1 -0
  194. package/dist/utils/video/index.d.ts +25 -0
  195. package/dist/utils/video/index.d.ts.map +1 -0
  196. package/dist/utils/video/index.js +104 -0
  197. package/dist/utils/video/index.js.map +1 -0
  198. package/dist/utils/video/param-registry.d.ts +64 -0
  199. package/dist/utils/video/param-registry.d.ts.map +1 -0
  200. package/dist/utils/video/param-registry.js +201 -0
  201. package/dist/utils/video/param-registry.js.map +1 -0
  202. package/dist/utils/video/quality.d.ts +12 -0
  203. package/dist/utils/video/quality.d.ts.map +1 -0
  204. package/dist/utils/video/quality.js +45 -0
  205. package/dist/utils/video/quality.js.map +1 -0
  206. package/dist/utils/video/queue-store.d.ts +51 -0
  207. package/dist/utils/video/queue-store.d.ts.map +1 -0
  208. package/dist/utils/video/queue-store.js +2 -0
  209. package/dist/utils/video/queue-store.js.map +1 -0
  210. package/dist/utils/video/resize.d.ts +7 -0
  211. package/dist/utils/video/resize.d.ts.map +1 -0
  212. package/dist/utils/video/resize.js +40 -0
  213. package/dist/utils/video/resize.js.map +1 -0
  214. package/dist/utils/video/sqlite-video-job-store.d.ts +29 -0
  215. package/dist/utils/video/sqlite-video-job-store.d.ts.map +1 -0
  216. package/dist/utils/video/sqlite-video-job-store.js +320 -0
  217. package/dist/utils/video/sqlite-video-job-store.js.map +1 -0
  218. package/dist/utils/video/thumbnail.d.ts +7 -0
  219. package/dist/utils/video/thumbnail.d.ts.map +1 -0
  220. package/dist/utils/video/thumbnail.js +22 -0
  221. package/dist/utils/video/thumbnail.js.map +1 -0
  222. package/dist/utils/video/trim.d.ts +7 -0
  223. package/dist/utils/video/trim.d.ts.map +1 -0
  224. package/dist/utils/video/trim.js +36 -0
  225. package/dist/utils/video/trim.js.map +1 -0
  226. package/dist/utils/video/types.d.ts +19 -0
  227. package/dist/utils/video/types.d.ts.map +1 -0
  228. package/dist/utils/video/types.js +2 -0
  229. package/dist/utils/video/types.js.map +1 -0
  230. package/dist/utils/video/video-info.d.ts +25 -0
  231. package/dist/utils/video/video-info.d.ts.map +1 -0
  232. package/dist/utils/video/video-info.js +58 -0
  233. package/dist/utils/video/video-info.js.map +1 -0
  234. package/dist/utils/video/video-worker.d.ts +52 -0
  235. package/dist/utils/video/video-worker.d.ts.map +1 -0
  236. package/dist/utils/video/video-worker.js +192 -0
  237. package/dist/utils/video/video-worker.js.map +1 -0
  238. package/dist/utils/video-job-queue.d.ts +62 -0
  239. package/dist/utils/video-job-queue.d.ts.map +1 -0
  240. package/dist/utils/video-job-queue.js +122 -0
  241. package/dist/utils/video-job-queue.js.map +1 -0
  242. package/package.json +51 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aspect-ratio.d.ts","sourceRoot":"","sources":["../../../src/utils/image/aspect-ratio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtC;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAC3B,OAAO,KAAK,CAAC,KAAK,EAClB,aAAa,MAAM,EACnB,UAAS,WAAsB,KAC9B,OAAO,CAAC,KAAK,CAAC,KAAK,CAuCrB,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { getSharpPosition } from './gravity.js';
2
+ /**
3
+ * Apply aspect ratio transformation to an image
4
+ */
5
+ export const applyAspectRatio = async (image, aspectParam, gravity = 'center') => {
6
+ const aspectRatio = aspectParam.split(':');
7
+ if (aspectRatio.length !== 2) {
8
+ return image;
9
+ }
10
+ const targetRatio = parseFloat(aspectRatio[0]) / parseFloat(aspectRatio[1]);
11
+ // Get current image metadata
12
+ const metadata = await image.metadata();
13
+ const currentWidth = metadata.width || 0;
14
+ const currentHeight = metadata.height || 0;
15
+ const currentRatio = currentWidth / currentHeight;
16
+ // Only transform if ratios differ significantly
17
+ if (Math.abs(currentRatio - targetRatio) <= 0.01) {
18
+ return image; // Image already has correct aspect ratio
19
+ }
20
+ let newWidth;
21
+ let newHeight;
22
+ if (currentRatio > targetRatio) {
23
+ // Current image is wider, crop width
24
+ newHeight = currentHeight;
25
+ newWidth = Math.round(newHeight * targetRatio);
26
+ }
27
+ else {
28
+ // Current image is taller, crop height
29
+ newWidth = currentWidth;
30
+ newHeight = Math.round(newWidth / targetRatio);
31
+ }
32
+ // Apply aspect ratio crop with specified gravity
33
+ return image.resize({
34
+ width: newWidth,
35
+ height: newHeight,
36
+ fit: 'cover',
37
+ position: getSharpPosition(gravity)
38
+ });
39
+ };
40
+ //# sourceMappingURL=aspect-ratio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aspect-ratio.js","sourceRoot":"","sources":["../../../src/utils/image/aspect-ratio.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EACnC,KAAkB,EAClB,WAAmB,EACnB,UAAuB,QAAQ,EACT,EAAE;IACxB,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5E,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC;IACxC,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;IACzC,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,YAAY,GAAG,aAAa,CAAC;IAElD,gDAAgD;IAChD,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,WAAW,CAAC,IAAI,IAAI,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC,CAAC,yCAAyC;IACzD,CAAC;IAED,IAAI,QAAgB,CAAC;IACrB,IAAI,SAAiB,CAAC;IAEtB,IAAI,YAAY,GAAG,WAAW,EAAE,CAAC;QAC/B,qCAAqC;QACrC,SAAS,GAAG,aAAa,CAAC;QAC1B,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,WAAW,CAAC,CAAC;IACjD,CAAC;SAAM,CAAC;QACN,uCAAuC;QACvC,QAAQ,GAAG,YAAY,CAAC;QACxB,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,WAAW,CAAC,CAAC;IACjD,CAAC;IAED,iDAAiD;IACjD,OAAO,KAAK,CAAC,MAAM,CAAC;QAClB,KAAK,EAAE,QAAQ;QACf,MAAM,EAAE,SAAS;QACjB,GAAG,EAAE,OAAO;QACZ,QAAQ,EAAE,gBAAgB,CAAC,OAAO,CAAC;KACpC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { BackgroundColor } from './types';
2
+ /**
3
+ * Parse background color from hex format or "transparent" keyword
4
+ */
5
+ export declare const parseBackgroundColor: (background?: string) => BackgroundColor;
6
+ //# sourceMappingURL=background.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../../src/utils/image/background.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,aAAa,MAAM,KAAG,eAoB1D,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Parse background color from hex format or "transparent" keyword
3
+ */
4
+ export const parseBackgroundColor = (background) => {
5
+ if (!background) {
6
+ return { r: 255, g: 255, b: 255, alpha: 1 }; // Default white
7
+ }
8
+ if (background.toLowerCase() === 'transparent') {
9
+ return { r: 0, g: 0, b: 0, alpha: 0 }; // Transparent
10
+ }
11
+ const hex = background.replace('#', '');
12
+ if (hex.length === 6) {
13
+ return {
14
+ r: parseInt(hex.substr(0, 2), 16),
15
+ g: parseInt(hex.substr(2, 2), 16),
16
+ b: parseInt(hex.substr(4, 2), 16),
17
+ alpha: 1
18
+ };
19
+ }
20
+ return { r: 255, g: 255, b: 255, alpha: 1 }; // Default white if invalid
21
+ };
22
+ //# sourceMappingURL=background.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"background.js","sourceRoot":"","sources":["../../../src/utils/image/background.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,UAAmB,EAAmB,EAAE;IAC3E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,gBAAgB;IAC/D,CAAC;IAED,IAAI,UAAU,CAAC,WAAW,EAAE,KAAK,aAAa,EAAE,CAAC;QAC/C,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,cAAc;IACvD,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACxC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;YACjC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;YACjC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;YACjC,KAAK,EAAE,CAAC;SACT,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,2BAA2B;AAC1E,CAAC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { TransformParams, OptimizationResult } from './types';
2
+ export declare class Compression {
3
+ private static readonly FORMAT_PRIORITIES;
4
+ /**
5
+ * Optimizes an image with intelligent compression
6
+ * If format is not explicitly specified, encodes in all supported formats and returns the smallest one
7
+ */
8
+ optimizeForDelivery(inputPath: string, params: TransformParams, userAgent?: string, acceptHeader?: string): Promise<OptimizationResult>;
9
+ /**
10
+ * Prepares the base pipeline with preliminary optimizations
11
+ */
12
+ private preparePipeline;
13
+ /**
14
+ * Applies format encoding to the pipeline
15
+ */
16
+ private applyFormat;
17
+ /**
18
+ * Analyzes image content to optimize compression (simplified for speed)
19
+ */
20
+ private analyzeImage;
21
+ /**
22
+ * Determines optimal format based on content and browser support
23
+ */
24
+ private determineOptimalFormat;
25
+ /**
26
+ * Calculates optimal quality based on content (simplified for speed).
27
+ * If userQuality is provided, it takes precedence over automatic calculation.
28
+ */
29
+ private calculateOptimalQuality;
30
+ /**
31
+ * Determines maximum dimension based on content type
32
+ */
33
+ private getMaxDimension;
34
+ /**
35
+ * Determines the optimal format for a browser without doing full optimization
36
+ * This is used for cache key generation
37
+ */
38
+ determineOptimalFormatForCache(userAgent?: string, acceptHeader?: string, originalFormat?: string): string;
39
+ /**
40
+ * Checks browser support for a format
41
+ */
42
+ private supportsFormat;
43
+ }
44
+ //# sourceMappingURL=compression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../../src/utils/image/compression.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAA8B,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAG1F,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAKvC;IAEF;;;OAGG;IACG,mBAAmB,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,eAAe,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,kBAAkB,CAAC;IA4J9B;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,WAAW;IA4CnB;;OAEG;YACW,YAAY;IAmB1B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAgC9B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAkC/B;;OAEG;IACH,OAAO,CAAC,eAAe;IAMvB;;;OAGG;IACH,8BAA8B,CAC5B,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,EACrB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM;IAwBT;;OAEG;IACH,OAAO,CAAC,cAAc;CAwCvB"}
@@ -0,0 +1,345 @@
1
+ import sharp from 'sharp';
2
+ import logger, { serializeError } from '../logger.js';
3
+ export class Compression {
4
+ static FORMAT_PRIORITIES = {
5
+ avif: { quality: 0.9, savings: 0.7 }, // AVIF: Excellent compression, slightly lower quality acceptable
6
+ webp: { quality: 0.95, savings: 0.6 }, // WebP: Good compression, high quality
7
+ jpeg: { quality: 1.0, savings: 0.3 }, // JPEG: Standard compression, full quality
8
+ png: { quality: 1.0, savings: 0.1 } // PNG: Lossless, minimal compression
9
+ };
10
+ /**
11
+ * Optimizes an image with intelligent compression
12
+ * If format is not explicitly specified, encodes in all supported formats and returns the smallest one
13
+ */
14
+ async optimizeForDelivery(inputPath, params, userAgent, acceptHeader) {
15
+ const originalBuffer = await sharp(inputPath).toBuffer();
16
+ const originalSize = originalBuffer.length;
17
+ // CONTENT ANALYSIS
18
+ const analysis = await this.analyzeImage(inputPath);
19
+ const metadata = await sharp(inputPath).metadata();
20
+ // If format is explicitly specified, use it directly (no size comparison needed)
21
+ if (params.format) {
22
+ const explicitFormat = params.format === 'jpg' ? 'jpeg' : params.format;
23
+ const userQuality = params.quality ? parseInt(String(params.quality)) : undefined;
24
+ const optimalQuality = this.calculateOptimalQuality(analysis, originalSize, explicitFormat, userQuality);
25
+ let pipeline = this.preparePipeline(inputPath, analysis, metadata, originalSize);
26
+ // Apply the explicit format
27
+ pipeline = this.applyFormat(pipeline, explicitFormat, optimalQuality);
28
+ const optimizedBuffer = await pipeline.toBuffer();
29
+ const optimizedSize = optimizedBuffer.length;
30
+ const savings = ((originalSize - optimizedSize) / originalSize) * 100;
31
+ const compressionRatio = originalSize / optimizedSize;
32
+ return {
33
+ buffer: optimizedBuffer,
34
+ format: explicitFormat,
35
+ originalSize,
36
+ optimizedSize,
37
+ savings,
38
+ compressionRatio
39
+ };
40
+ }
41
+ // FORMAT SIZE COMPARISON: Encode in all supported formats and compare sizes
42
+ const supportsAVIF = this.supportsFormat('avif', userAgent, acceptHeader);
43
+ const supportsWebP = this.supportsFormat('webp', userAgent, acceptHeader);
44
+ logger.debug({
45
+ userAgent,
46
+ acceptHeader,
47
+ supportsAVIF,
48
+ supportsWebP
49
+ }, 'Browser format support detection');
50
+ const formatsToTest = [];
51
+ const originalFormat = metadata.format;
52
+ const hasTransparency = metadata.hasAlpha;
53
+ // Modern browsers: Test AVIF, WebP, and JPEG (plus PNG if original is PNG)
54
+ if (supportsAVIF) {
55
+ formatsToTest.push('avif', 'webp', 'jpeg');
56
+ // If original is PNG, also test PNG to compare sizes (AVIF/WebP support transparency too)
57
+ if (originalFormat === 'png') {
58
+ formatsToTest.push('png');
59
+ logger.debug('Testing formats: AVIF, WebP, JPEG, PNG (original is PNG)');
60
+ }
61
+ else {
62
+ logger.debug('Testing formats: AVIF, WebP, JPEG');
63
+ }
64
+ }
65
+ // Browsers with WebP but not AVIF: Test WebP and JPEG (plus PNG if original is PNG)
66
+ else if (supportsWebP) {
67
+ formatsToTest.push('webp', 'jpeg');
68
+ // If original is PNG, also test PNG to compare sizes (WebP supports transparency)
69
+ if (originalFormat === 'png') {
70
+ formatsToTest.push('png');
71
+ logger.debug('Testing formats: WebP, JPEG, PNG (original is PNG)');
72
+ }
73
+ else {
74
+ logger.debug('Testing formats: WebP, JPEG');
75
+ }
76
+ }
77
+ // Older browsers: Use JPEG/PNG (keep original format if PNG for transparency)
78
+ else {
79
+ // Preserve PNG for transparency, otherwise use JPEG
80
+ if (originalFormat === 'png' && hasTransparency) {
81
+ formatsToTest.push('png');
82
+ logger.debug('Testing format: PNG (preserving transparency, legacy browser)');
83
+ }
84
+ else {
85
+ formatsToTest.push('jpeg');
86
+ logger.debug('Testing format: JPEG (legacy browser)');
87
+ }
88
+ }
89
+ // Encode in all formats and compare sizes
90
+ const results = [];
91
+ const userQuality = params.quality ? parseInt(String(params.quality)) : undefined;
92
+ for (const format of formatsToTest) {
93
+ try {
94
+ const quality = this.calculateOptimalQuality(analysis, originalSize, format, userQuality);
95
+ let pipeline = this.preparePipeline(inputPath, analysis, metadata, originalSize);
96
+ pipeline = this.applyFormat(pipeline, format, quality);
97
+ const buffer = await pipeline.toBuffer();
98
+ results.push({
99
+ format,
100
+ buffer,
101
+ size: buffer.length
102
+ });
103
+ }
104
+ catch (error) {
105
+ // If encoding fails for a format, skip it
106
+ logger.debug({ error: serializeError(error), format }, `Failed to encode in ${format}, skipping`);
107
+ }
108
+ }
109
+ // Find the smallest format
110
+ if (results.length === 0) {
111
+ // Fallback: use JPEG
112
+ const quality = this.calculateOptimalQuality(analysis, originalSize, 'jpeg', userQuality);
113
+ let pipeline = this.preparePipeline(inputPath, analysis, metadata, originalSize);
114
+ pipeline = this.applyFormat(pipeline, 'jpeg', quality);
115
+ const buffer = await pipeline.toBuffer();
116
+ return {
117
+ buffer,
118
+ format: 'jpeg',
119
+ originalSize,
120
+ optimizedSize: buffer.length,
121
+ savings: ((originalSize - buffer.length) / originalSize) * 100,
122
+ compressionRatio: originalSize / buffer.length
123
+ };
124
+ }
125
+ // Sort by size and pick the smallest
126
+ results.sort((a, b) => a.size - b.size);
127
+ const bestResult = results[0];
128
+ // Normalize format (jpg -> jpeg)
129
+ const normalizedFormat = bestResult.format === 'jpg' ? 'jpeg' : bestResult.format;
130
+ logger.debug({
131
+ testedFormats: results.map(r => ({ format: r.format, size: r.size })),
132
+ selectedFormat: normalizedFormat,
133
+ selectedSize: bestResult.size,
134
+ originalSize
135
+ }, 'Format size comparison results');
136
+ const savings = ((originalSize - bestResult.size) / originalSize) * 100;
137
+ const compressionRatio = originalSize / bestResult.size;
138
+ return {
139
+ buffer: bestResult.buffer,
140
+ format: normalizedFormat,
141
+ originalSize,
142
+ optimizedSize: bestResult.size,
143
+ savings,
144
+ compressionRatio
145
+ };
146
+ }
147
+ /**
148
+ * Prepares the base pipeline with preliminary optimizations
149
+ */
150
+ preparePipeline(inputPath, analysis, metadata, originalSize) {
151
+ let pipeline = sharp(inputPath);
152
+ // Resolution reduction only for extremely large files
153
+ if (originalSize > 5 * 1024 * 1024) { // > 5MB
154
+ const maxDimension = this.getMaxDimension(analysis);
155
+ if (metadata.width > maxDimension || metadata.height > maxDimension) {
156
+ pipeline = pipeline.resize(maxDimension, maxDimension, {
157
+ fit: 'inside',
158
+ withoutEnlargement: true
159
+ });
160
+ }
161
+ }
162
+ // Remove metadata to save space
163
+ pipeline = pipeline.withMetadata();
164
+ return pipeline;
165
+ }
166
+ /**
167
+ * Applies format encoding to the pipeline
168
+ */
169
+ applyFormat(pipeline, format, quality) {
170
+ switch (format) {
171
+ case 'avif':
172
+ return pipeline.avif({
173
+ quality,
174
+ effort: 1,
175
+ chromaSubsampling: '4:2:0'
176
+ });
177
+ case 'webp':
178
+ return pipeline.webp({
179
+ quality,
180
+ effort: 1,
181
+ smartSubsample: false
182
+ });
183
+ case 'jpeg':
184
+ case 'jpg':
185
+ return pipeline.jpeg({
186
+ quality,
187
+ progressive: false,
188
+ mozjpeg: false,
189
+ chromaSubsampling: '4:2:0'
190
+ });
191
+ case 'png':
192
+ return pipeline.png({
193
+ compressionLevel: 3,
194
+ adaptiveFiltering: false
195
+ });
196
+ default:
197
+ // PNG fallback
198
+ return pipeline.png({
199
+ compressionLevel: 3,
200
+ adaptiveFiltering: false
201
+ });
202
+ }
203
+ }
204
+ /**
205
+ * Analyzes image content to optimize compression (simplified for speed)
206
+ */
207
+ async analyzeImage(inputPath) {
208
+ const image = sharp(inputPath);
209
+ const metadata = await image.metadata();
210
+ // Simplified analysis based only on metadata (no expensive stats calculation)
211
+ const isPhotographic = metadata.channels >= 3; // RGB or more channels
212
+ const hasText = false;
213
+ const hasSharpEdges = false; // Skip expensive edge detection
214
+ const complexity = 0.5; // Default medium complexity
215
+ return {
216
+ hasText,
217
+ hasSharpEdges,
218
+ isPhotographic,
219
+ dominantColors: metadata.channels || 3,
220
+ complexity
221
+ };
222
+ }
223
+ /**
224
+ * Determines optimal format based on content and browser support
225
+ */
226
+ determineOptimalFormat(analysis, fileSize, userAgent, acceptHeader, explicitFormat) {
227
+ // If format is explicitly specified, use it (TypeScript ensures it's valid)
228
+ if (explicitFormat) {
229
+ // Normalize jpg to jpeg
230
+ return explicitFormat === 'jpg' ? 'jpeg' : explicitFormat;
231
+ }
232
+ // Check support for modern formats
233
+ const supportsAVIF = this.supportsFormat('avif', userAgent, acceptHeader);
234
+ const supportsWebP = this.supportsFormat('webp', userAgent, acceptHeader);
235
+ // NEW DEFAULT: Prefer AVIF by default if supported
236
+ if (supportsAVIF) {
237
+ return 'avif';
238
+ }
239
+ // Fallback to WebP if supported
240
+ if (supportsWebP) {
241
+ return 'webp';
242
+ }
243
+ // JPEG fallback for compatibility
244
+ return 'jpeg';
245
+ }
246
+ /**
247
+ * Calculates optimal quality based on content (simplified for speed).
248
+ * If userQuality is provided, it takes precedence over automatic calculation.
249
+ */
250
+ calculateOptimalQuality(analysis, fileSize, format, userQuality) {
251
+ if (userQuality !== undefined && !isNaN(userQuality) && userQuality >= 1 && userQuality <= 100) {
252
+ return userQuality;
253
+ }
254
+ let baseQuality = 85;
255
+ // Simplified format-specific adjustments
256
+ switch (format) {
257
+ case 'avif':
258
+ baseQuality = 80; // AVIF can handle slightly lower quality
259
+ break;
260
+ case 'webp':
261
+ baseQuality = 85;
262
+ break;
263
+ case 'jpeg':
264
+ baseQuality = 90; // Higher quality for JPEG
265
+ break;
266
+ case 'png':
267
+ return 100; // PNG is lossless, no quality adjustment needed
268
+ }
269
+ // Simplified size-based adjustment (less aggressive)
270
+ if (fileSize > 5 * 1024 * 1024)
271
+ baseQuality -= 5; // Only for very large files
272
+ // Limits (higher minimum quality)
273
+ return Math.max(70, Math.min(95, baseQuality));
274
+ }
275
+ /**
276
+ * Determines maximum dimension based on content type
277
+ */
278
+ getMaxDimension(analysis) {
279
+ if (analysis.hasText)
280
+ return 2560; // Text requires higher resolution
281
+ if (analysis.isPhotographic)
282
+ return 1920; // Standard photos
283
+ return 1600; // Other content
284
+ }
285
+ /**
286
+ * Determines the optimal format for a browser without doing full optimization
287
+ * This is used for cache key generation
288
+ */
289
+ determineOptimalFormatForCache(userAgent, acceptHeader, originalFormat) {
290
+ // If format is explicitly specified, we wouldn't call this, but handle it anyway
291
+ const supportsAVIF = this.supportsFormat('avif', userAgent, acceptHeader);
292
+ const supportsWebP = this.supportsFormat('webp', userAgent, acceptHeader);
293
+ // Prefer AVIF if supported (best compression)
294
+ if (supportsAVIF) {
295
+ return 'avif';
296
+ }
297
+ // Fallback to WebP if supported
298
+ if (supportsWebP) {
299
+ return 'webp';
300
+ }
301
+ // For legacy browsers, preserve PNG if original is PNG (for transparency)
302
+ // Otherwise use JPEG
303
+ if (originalFormat === 'png') {
304
+ return 'png';
305
+ }
306
+ return 'jpeg';
307
+ }
308
+ /**
309
+ * Checks browser support for a format
310
+ */
311
+ supportsFormat(format, userAgent, acceptHeader) {
312
+ // First check Accept header - most reliable method
313
+ if (acceptHeader) {
314
+ const acceptLower = acceptHeader.toLowerCase();
315
+ if (format === 'avif' && acceptLower.includes('image/avif')) {
316
+ return true;
317
+ }
318
+ if (format === 'webp' && acceptLower.includes('image/webp')) {
319
+ return true;
320
+ }
321
+ }
322
+ if (!userAgent) {
323
+ // If no user agent, assume modern browser supports AVIF and WebP
324
+ // This handles cases where Accept header might not be sent
325
+ return format === 'avif' || format === 'webp';
326
+ }
327
+ const ua = userAgent.toLowerCase();
328
+ switch (format) {
329
+ case 'avif':
330
+ // Chrome 85+ (released Aug 2020), Firefox 93+ (released Oct 2021), Safari 16+ (released Sep 2022), Edge 122+
331
+ return ((ua.includes('chrome') && !ua.includes('edg') && parseInt(ua.match(/chrome\/(\d+)/)?.[1] || '0') >= 85) ||
332
+ (ua.includes('firefox') && parseInt(ua.match(/firefox\/(\d+)/)?.[1] || '0') >= 93) ||
333
+ (ua.includes('safari') && !ua.includes('chrome') && parseInt(ua.match(/version\/(\d+)/)?.[1] || '0') >= 16) ||
334
+ (ua.includes('edg') && parseInt(ua.match(/edg\/(\d+)/)?.[1] || '0') >= 122));
335
+ case 'webp':
336
+ // Very broad support now - almost all modern browsers
337
+ return !ua.includes('msie') &&
338
+ !ua.includes('trident') &&
339
+ !(ua.includes('edge') && parseInt(ua.match(/edge\/(\d+)/)?.[1] || '0') < 18);
340
+ default:
341
+ return true;
342
+ }
343
+ }
344
+ }
345
+ //# sourceMappingURL=compression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.js","sourceRoot":"","sources":["../../../src/utils/image/compression.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { GravityMode } from './types';
2
+ /**
3
+ * Map gravity to Sharp position values
4
+ */
5
+ export declare const getSharpPosition: (gravity: GravityMode) => string;
6
+ //# sourceMappingURL=gravity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gravity.d.ts","sourceRoot":"","sources":["../../../src/utils/image/gravity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,KAAG,MAmBvD,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Map gravity to Sharp position values
3
+ */
4
+ export const getSharpPosition = (gravity) => {
5
+ switch (gravity) {
6
+ case 'center':
7
+ return 'center';
8
+ case 'north':
9
+ return 'top';
10
+ case 'south':
11
+ return 'bottom';
12
+ case 'east':
13
+ return 'right';
14
+ case 'west':
15
+ return 'left';
16
+ case 'face':
17
+ return 'attention'; // Sharp's attention strategy focuses on interesting features
18
+ case 'auto':
19
+ return 'entropy'; // Sharp's entropy strategy focuses on high-contrast areas
20
+ default:
21
+ return 'center';
22
+ }
23
+ };
24
+ //# sourceMappingURL=gravity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gravity.js","sourceRoot":"","sources":["../../../src/utils/image/gravity.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAoB,EAAU,EAAE;IAC/D,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,OAAO;YACV,OAAO,KAAK,CAAC;QACf,KAAK,OAAO;YACV,OAAO,QAAQ,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC;QACjB,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,WAAW,CAAC,CAAC,6DAA6D;QACnF,KAAK,MAAM;YACT,OAAO,SAAS,CAAC,CAAC,0DAA0D;QAC9E;YACE,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { TransformParams } from './types';
2
+ export * from './types';
3
+ export * from './param-registry';
4
+ /**
5
+ * Transform an image with the specified parameters
6
+ */
7
+ export declare const transformImage: (inputPath: string, params: TransformParams) => Promise<Buffer>;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/image/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA2B1C,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AAEjC;;GAEG;AACH,eAAO,MAAM,cAAc,GAAU,WAAW,MAAM,EAAE,QAAQ,eAAe,KAAG,OAAO,CAAC,MAAM,CAsD/F,CAAC"}
@@ -0,0 +1,77 @@
1
+ import sharp from 'sharp';
2
+ import { readFile } from 'fs/promises';
3
+ import Psd from '@webtoon/psd';
4
+ import { applyAspectRatio } from './aspect-ratio.js';
5
+ import { applyRotation } from './rotation.js';
6
+ import { applyQuality } from './quality.js';
7
+ import { applyResizeComposite } from './param-registry.js';
8
+ import { applyRoundCorners } from './round-corners.js';
9
+ /**
10
+ * Decode a PSD file into a Sharp instance via raw RGBA pixel data.
11
+ * Sharp cannot read PSD natively; @webtoon/psd composites all layers first.
12
+ * The output is encoded as PNG so the temp-file step in processImage can read it.
13
+ */
14
+ async function decodePsd(inputPath) {
15
+ const fileBuffer = await readFile(inputPath);
16
+ const arrayBuffer = fileBuffer.buffer.slice(fileBuffer.byteOffset, fileBuffer.byteOffset + fileBuffer.byteLength);
17
+ const psd = Psd.parse(arrayBuffer);
18
+ const pixelData = await psd.composite();
19
+ return sharp(Buffer.from(pixelData), {
20
+ raw: { width: psd.width, height: psd.height, channels: 4 },
21
+ }).png();
22
+ }
23
+ // Re-export types for backward compatibility
24
+ export * from './types.js';
25
+ export * from './param-registry.js';
26
+ /**
27
+ * Transform an image with the specified parameters
28
+ */
29
+ export const transformImage = async (inputPath, params) => {
30
+ let image = inputPath.toLowerCase().endsWith('.psd')
31
+ ? await decodePsd(inputPath)
32
+ : sharp(inputPath);
33
+ // Convert TransformParams to a record for easier access
34
+ const paramsRecord = {
35
+ ...(params.rotate && { rotate: String(params.rotate) }),
36
+ ...(params.aspect && { aspect: params.aspect }),
37
+ ...(params.width && { width: params.width }),
38
+ ...(params.height && { height: params.height }),
39
+ ...(params.resize && { resize: params.resize }),
40
+ ...(params.crop && { crop: params.crop }),
41
+ ...(params.gravity && { gravity: params.gravity }),
42
+ ...(params.background && { background: params.background }),
43
+ ...(params.quality && { quality: String(params.quality) }),
44
+ ...(params.format && { format: params.format }),
45
+ ...(params.radius && { radius: params.radius }),
46
+ };
47
+ // 1. Apply rotation (if specified)
48
+ if (params.rotate) {
49
+ image = applyRotation(image, params.rotate, params.background);
50
+ }
51
+ // 2. Apply aspect ratio (if specified)
52
+ if (params.aspect) {
53
+ image = await applyAspectRatio(image, params.aspect, params.gravity);
54
+ // Sharp only honors one resize() per pipeline, so a following resize would
55
+ // override the aspect-ratio crop. Materialize the crop into a buffer first.
56
+ if (params.resize || params.width || params.height) {
57
+ image = sharp(await image.toBuffer());
58
+ }
59
+ }
60
+ // 3. Apply resize (if width or height specified)
61
+ if (params.resize || params.width || params.height) {
62
+ image = await applyResizeComposite(image, '', paramsRecord);
63
+ }
64
+ // 4. Apply rounded corners (if specified)
65
+ if (params.radius) {
66
+ image = await applyRoundCorners(image, params.radius, params.background);
67
+ // applyRoundCorners always returns a pipeline backed by a PNG buffer
68
+ // (alpha-capable), so the intermediate toBuffer() in processImage will
69
+ // correctly preserve transparency or the filled background color.
70
+ }
71
+ // 5. Apply quality (if specified)
72
+ if (params.quality) {
73
+ image = applyQuality(image, params.quality);
74
+ }
75
+ return await image.toBuffer();
76
+ };
77
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/image/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,GAAG,MAAM,cAAc,CAAC;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;GAIG;AACH,KAAK,UAAU,SAAS,CAAC,SAAiB;IACxC,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CACzC,UAAU,CAAC,UAAU,EACrB,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU,CAC/B,CAAC;IACjB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC;IACxC,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;QACnC,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE;KAC3D,CAAC,CAAC,GAAG,EAAE,CAAC;AACX,CAAC;AAED,6CAA6C;AAC7C,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AAEjC;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,SAAiB,EAAE,MAAuB,EAAmB,EAAE;IAClG,IAAI,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;QAClD,CAAC,CAAC,MAAM,SAAS,CAAC,SAAS,CAAC;QAC5B,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAErB,wDAAwD;IACxD,MAAM,YAAY,GAA2B;QAC3C,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/C,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QAC5C,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/C,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/C,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QACzC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QAClD,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;QAC3D,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1D,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/C,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;KAChD,CAAC;IAEF,mCAAmC;IACnC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACjE,CAAC;IAED,uCAAuC;IACvC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,KAAK,GAAG,MAAM,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACrE,2EAA2E;QAC3E,4EAA4E;QAC5E,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACnD,KAAK,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACnD,KAAK,GAAG,MAAM,oBAAoB,CAAC,KAAK,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC;IAC9D,CAAC;IAED,0CAA0C;IAC1C,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,KAAK,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QACzE,qEAAqE;QACrE,uEAAuE;QACvE,kEAAkE;IACpE,CAAC;IAED,kCAAkC;IAClC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,KAAK,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC;AAChC,CAAC,CAAC"}