@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,63 @@
1
+ import sharp from 'sharp';
2
+ /**
3
+ * Parameter processor function type
4
+ * Takes a Sharp instance and parameter value, returns modified Sharp instance or Promise<Sharp>
5
+ */
6
+ export type ParamProcessor = (image: sharp.Sharp, value: string, allParams: Record<string, string>) => sharp.Sharp | Promise<sharp.Sharp>;
7
+ /**
8
+ * Parameter definition interface
9
+ */
10
+ export interface ParamDefinition {
11
+ /** Short parameter key used in URLs (e.g., 'w', 'h', 'ar') */
12
+ param: string;
13
+ /** Human-readable name */
14
+ name: string;
15
+ /** Detailed description of the parameter */
16
+ description: string;
17
+ /** Example value for documentation */
18
+ example: string;
19
+ /** Default value if not specified */
20
+ defaultValue?: string | number;
21
+ /** Valid values or pattern description */
22
+ validValues?: string[];
23
+ /** Parameter aliases (alternative names) */
24
+ aliases?: string[];
25
+ /** The function that processes this parameter */
26
+ processor?: ParamProcessor;
27
+ /** Whether this parameter requires other parameters to work */
28
+ dependencies?: string[];
29
+ /** Processing order priority (lower = earlier) */
30
+ priority: number;
31
+ }
32
+ /**
33
+ * Complete parameter registry
34
+ * Single source of truth for all image transformation parameters
35
+ */
36
+ export declare const IMAGE_PARAMS: readonly ParamDefinition[];
37
+ /**
38
+ * Helper function to apply resize with all related parameters
39
+ * This is a composite operation that uses w, h, c, g, and b parameters
40
+ */
41
+ export declare const applyResizeComposite: ParamProcessor;
42
+ /**
43
+ * Get parameter definition by param key
44
+ */
45
+ export declare const getParamDefinition: (param: string) => ParamDefinition | undefined;
46
+ /**
47
+ * Get all parameter definitions sorted by priority
48
+ */
49
+ export declare const getParamsByPriority: () => readonly ParamDefinition[];
50
+ /**
51
+ * Get default value for a parameter
52
+ */
53
+ export declare const getParamDefault: (param: string) => string | number | undefined;
54
+ /**
55
+ * Validate if a parameter value is valid
56
+ */
57
+ export declare const isValidParamValue: (param: string, value: string) => boolean;
58
+ /**
59
+ * Export types for external use
60
+ */
61
+ export type ImageParamKey = typeof IMAGE_PARAMS[number]['param'];
62
+ export type ParamRegistry = typeof IMAGE_PARAMS;
63
+ //# sourceMappingURL=param-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"param-registry.d.ts","sourceRoot":"","sources":["../../../src/utils/image/param-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC9B,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iDAAiD;IACjD,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,eAAe,EA2IzC,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAclC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,KAAG,eAAe,GAAG,SAEpE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAO,SAAS,eAAe,EAE9D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,MAAM,GAAG,MAAM,GAAG,SAGjE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,KAAG,OAYhE,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AACjE,MAAM,MAAM,aAAa,GAAG,OAAO,YAAY,CAAC"}
@@ -0,0 +1,196 @@
1
+ import { applyAspectRatio } from './aspect-ratio.js';
2
+ import { applyRotation } from './rotation.js';
3
+ import { applyQuality } from './quality.js';
4
+ import { applyResize } from './resize.js';
5
+ import { applyRoundCorners } from './round-corners.js';
6
+ /**
7
+ * Complete parameter registry
8
+ * Single source of truth for all image transformation parameters
9
+ */
10
+ export const IMAGE_PARAMS = [
11
+ {
12
+ param: 'a',
13
+ name: 'Rotation Angle',
14
+ description: 'Rotates the image by the specified angle in degrees, or use "auto" to auto-rotate based on EXIF orientation data.',
15
+ example: 'a_90',
16
+ validValues: ['auto', '90', '180', '270', 'any numeric angle'],
17
+ processor: async (image, value, allParams) => {
18
+ return applyRotation(image, value, allParams.background);
19
+ },
20
+ priority: 1, // Rotation should happen first
21
+ },
22
+ {
23
+ param: 'ar',
24
+ name: 'Aspect Ratio',
25
+ description: 'Crops the image to a specific aspect ratio (e.g., 16:9, 4:3, 1:1). The image is cropped to match the target ratio while maintaining as much content as possible.',
26
+ example: 'ar_16:9',
27
+ validValues: ['16:9', '4:3', '1:1', '21:9', 'any ratio in W:H format'],
28
+ processor: async (image, value, allParams) => {
29
+ const gravity = (allParams.gravity || 'center');
30
+ return await applyAspectRatio(image, value, gravity);
31
+ },
32
+ dependencies: ['g'],
33
+ priority: 2, // Aspect ratio before resize
34
+ },
35
+ {
36
+ param: 'w',
37
+ name: 'Width',
38
+ description: 'Sets the width of the image in pixels. Can be used independently or with height.',
39
+ example: 'w_300',
40
+ validValues: ['any positive integer'],
41
+ processor: async (image, value, allParams) => {
42
+ // Width is processed together with height in the resize step
43
+ return image;
44
+ },
45
+ priority: 3, // Resize operations
46
+ },
47
+ {
48
+ param: 'h',
49
+ name: 'Height',
50
+ description: 'Sets the height of the image in pixels. Can be used independently or with width.',
51
+ example: 'h_200',
52
+ validValues: ['any positive integer'],
53
+ processor: async (image, value, allParams) => {
54
+ // Height is processed together with width in the resize step
55
+ return image;
56
+ },
57
+ priority: 3, // Resize operations
58
+ },
59
+ {
60
+ param: 'c',
61
+ name: 'Crop Mode',
62
+ description: 'Defines how the image should be resized and cropped. Options: fill (cover entire area with cropping), fit (fit within dimensions maintaining aspect ratio), scale (exact dimensions ignoring aspect ratio), crop (resize and crop to exact dimensions), pad (fit within dimensions and pad with background color).',
63
+ example: 'c_fill',
64
+ defaultValue: 'fill',
65
+ validValues: ['fill', 'fit', 'scale', 'crop', 'pad'],
66
+ aliases: ['lfill', 'fill_pad', 'limit', 'mfit', 'thumb', 'lpad'],
67
+ dependencies: ['w', 'h'],
68
+ processor: async (image, value, allParams) => {
69
+ // Crop mode is applied together with width/height in applyResize
70
+ return image;
71
+ },
72
+ priority: 3, // Resize operations
73
+ },
74
+ {
75
+ param: 'g',
76
+ name: 'Gravity',
77
+ description: 'Defines the focal point when cropping. Options: center/c (center), north/n (top), south/s (bottom), east/e (right), west/w (left), face/faces (face detection), auto (entropy-based).',
78
+ example: 'g_center',
79
+ defaultValue: 'center',
80
+ validValues: ['center', 'north', 'south', 'east', 'west', 'face', 'auto'],
81
+ aliases: ['c', 'n', 's', 'e', 'w', 'faces', 'face_center'],
82
+ processor: async (image, value, allParams) => {
83
+ // Gravity is used by other operations (aspect ratio, resize)
84
+ return image;
85
+ },
86
+ priority: 0, // Config parameter, not a direct operation
87
+ },
88
+ {
89
+ param: 'r',
90
+ name: 'Round Corners',
91
+ description: 'Rounds the corners of the image. Pass a single integer for uniform radius, 1–4 colon-separated integers for per-corner radii (CSS border-radius semantics, clockwise from top-left when 4 values are given), or `max` for a circle/oval.',
92
+ example: 'r_150',
93
+ validValues: ['<integer>', 'v1:v2', 'v1:v2:v3', 'v1:v2:v3:v4', 'max'],
94
+ processor: async (image, value) => applyRoundCorners(image, value),
95
+ priority: 3.5,
96
+ },
97
+ {
98
+ param: 'q',
99
+ name: 'Quality',
100
+ description: 'Sets the quality of the output image (1-100). Lower values create smaller files with reduced quality. Works primarily with lossy formats like JPEG, WebP, and AVIF.',
101
+ example: 'q_80',
102
+ defaultValue: 80,
103
+ validValues: ['1-100', 'auto'],
104
+ processor: async (image, value, allParams) => {
105
+ return applyQuality(image, value);
106
+ },
107
+ priority: 4, // Quality after transformations
108
+ },
109
+ {
110
+ param: 'f',
111
+ name: 'Format',
112
+ description: 'Specifies the output format. Options: avif, webp, jpeg, jpg, png. If not specified, the system automatically selects the optimal format based on browser support and file size comparison.',
113
+ example: 'f_webp',
114
+ defaultValue: 'avif',
115
+ validValues: ['avif', 'webp', 'jpeg', 'jpg', 'png'],
116
+ processor: async (image, value, allParams) => {
117
+ // Format is handled by the Compression class
118
+ return image;
119
+ },
120
+ priority: 5, // Format conversion last
121
+ },
122
+ {
123
+ param: 'b',
124
+ name: 'Background',
125
+ description: 'Sets the background color for padding (when using crop mode "pad") or rotation. Options: transparent, white, black, hex colors (with or without #), or rgb:RRGGBB format.',
126
+ example: 'b_transparent',
127
+ defaultValue: '#ffffff',
128
+ validValues: ['transparent', 'white', 'black', 'hex colors', 'rgb:RRGGBB'],
129
+ aliases: ['bg'],
130
+ processor: async (image, value, allParams) => {
131
+ // Background is used by other operations (rotation, pad)
132
+ return image;
133
+ },
134
+ priority: 0, // Config parameter, not a direct operation
135
+ },
136
+ {
137
+ param: 'bg',
138
+ name: 'Background (Alias)',
139
+ description: 'Alternative parameter name for background color. Identical functionality to "b" parameter.',
140
+ example: 'bg_rgb:FF5733',
141
+ defaultValue: '#ffffff',
142
+ validValues: ['transparent', 'white', 'black', 'hex colors', 'rgb:RRGGBB'],
143
+ processor: async (image, value, allParams) => {
144
+ // Background is used by other operations (rotation, pad)
145
+ return image;
146
+ },
147
+ priority: 0, // Config parameter, not a direct operation
148
+ },
149
+ ];
150
+ /**
151
+ * Helper function to apply resize with all related parameters
152
+ * This is a composite operation that uses w, h, c, g, and b parameters
153
+ */
154
+ export const applyResizeComposite = (image, _value, allParams) => {
155
+ if (!allParams.width && !allParams.height && !allParams.resize) {
156
+ return image;
157
+ }
158
+ return applyResize(image, allParams.resize, (allParams.crop || 'fill'), (allParams.gravity || 'center'), allParams.background, allParams.width, allParams.height);
159
+ };
160
+ /**
161
+ * Get parameter definition by param key
162
+ */
163
+ export const getParamDefinition = (param) => {
164
+ return IMAGE_PARAMS.find(p => p.param === param || p.aliases?.includes(param));
165
+ };
166
+ /**
167
+ * Get all parameter definitions sorted by priority
168
+ */
169
+ export const getParamsByPriority = () => {
170
+ return [...IMAGE_PARAMS].sort((a, b) => a.priority - b.priority);
171
+ };
172
+ /**
173
+ * Get default value for a parameter
174
+ */
175
+ export const getParamDefault = (param) => {
176
+ const def = getParamDefinition(param);
177
+ return def?.defaultValue;
178
+ };
179
+ /**
180
+ * Validate if a parameter value is valid
181
+ */
182
+ export const isValidParamValue = (param, value) => {
183
+ const def = getParamDefinition(param);
184
+ if (!def)
185
+ return false;
186
+ // If no validValues specified, assume any value is valid
187
+ if (!def.validValues || def.validValues.length === 0)
188
+ return true;
189
+ // Check if value matches any valid value or pattern
190
+ return def.validValues.some(valid => {
191
+ if (valid.includes('any'))
192
+ return true; // Pattern like "any positive integer"
193
+ return value === valid || value.startsWith(valid);
194
+ });
195
+ };
196
+ //# sourceMappingURL=param-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"param-registry.js","sourceRoot":"","sources":["../../../src/utils/image/param-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import sharp from 'sharp';
2
+ /**
3
+ * Apply quality settings to an image.
4
+ * Quality is deferred to the final format encoding step in the compression
5
+ * pipeline to avoid stripping alpha channels via premature JPEG conversion.
6
+ */
7
+ export declare const applyQuality: (image: sharp.Sharp, _qualityParam: string | number) => sharp.Sharp;
8
+ //# sourceMappingURL=quality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../../src/utils/image/quality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,OAAO,KAAK,CAAC,KAAK,EAClB,eAAe,MAAM,GAAG,MAAM,KAC7B,KAAK,CAAC,KAER,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Apply quality settings to an image.
3
+ * Quality is deferred to the final format encoding step in the compression
4
+ * pipeline to avoid stripping alpha channels via premature JPEG conversion.
5
+ */
6
+ export const applyQuality = (image, _qualityParam) => {
7
+ return image;
8
+ };
9
+ //# sourceMappingURL=quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.js","sourceRoot":"","sources":["../../../src/utils/image/quality.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAkB,EAClB,aAA8B,EACjB,EAAE;IACf,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import sharp from 'sharp';
2
+ import { CropMode, GravityMode } from './types';
3
+ /**
4
+ * Apply resize transformation to an image
5
+ */
6
+ export declare const applyResize: (image: sharp.Sharp, resizeParam?: string, cropMode?: CropMode, gravity?: GravityMode, background?: string, widthParam?: string, heightParam?: string) => sharp.Sharp;
7
+ //# sourceMappingURL=resize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../../src/utils/image/resize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAIhD;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,KAAK,CAAC,KAAK,EAClB,cAAc,MAAM,EACpB,WAAU,QAAiB,EAC3B,UAAS,WAAsB,EAC/B,aAAa,MAAM,EACnB,aAAa,MAAM,EACnB,cAAc,MAAM,KACnB,KAAK,CAAC,KAkER,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { getSharpPosition } from './gravity.js';
2
+ import { parseBackgroundColor } from './background.js';
3
+ /**
4
+ * Apply resize transformation to an image
5
+ */
6
+ export const applyResize = (image, resizeParam, cropMode = 'fill', gravity = 'center', background, widthParam, heightParam) => {
7
+ // Support both old "WxH" format and new individual width/height params
8
+ let width;
9
+ let height;
10
+ if (resizeParam) {
11
+ const [w, h] = resizeParam.split('x');
12
+ width = w ? parseInt(w, 10) : undefined;
13
+ height = h ? parseInt(h, 10) : undefined;
14
+ }
15
+ // Individual params take precedence
16
+ if (widthParam) {
17
+ width = parseInt(widthParam, 10);
18
+ }
19
+ if (heightParam) {
20
+ height = parseInt(heightParam, 10);
21
+ }
22
+ // If neither width nor height is specified, return image unchanged
23
+ if (width === undefined && height === undefined) {
24
+ return image;
25
+ }
26
+ const resizeOptions = {
27
+ ...(width !== undefined && { width }),
28
+ ...(height !== undefined && { height }),
29
+ };
30
+ switch (cropMode) {
31
+ case 'fill':
32
+ // Resize to fill the entire area, cropping if necessary
33
+ resizeOptions.fit = 'cover';
34
+ resizeOptions.position = getSharpPosition(gravity);
35
+ break;
36
+ case 'fit':
37
+ // Resize to fit within the dimensions, maintaining aspect ratio
38
+ resizeOptions.fit = 'inside';
39
+ resizeOptions.withoutEnlargement = true;
40
+ break;
41
+ case 'scale':
42
+ // Scale to exact dimensions, ignoring aspect ratio
43
+ resizeOptions.fit = 'fill';
44
+ break;
45
+ case 'crop':
46
+ // Resize and crop to exact dimensions, maintaining aspect ratio
47
+ resizeOptions.fit = 'cover';
48
+ resizeOptions.position = getSharpPosition(gravity);
49
+ break;
50
+ case 'pad':
51
+ // Resize to fit within dimensions and pad with background color
52
+ resizeOptions.fit = 'contain';
53
+ resizeOptions.background = parseBackgroundColor(background);
54
+ break;
55
+ default:
56
+ // Default to fill mode
57
+ resizeOptions.fit = 'cover';
58
+ resizeOptions.position = getSharpPosition(gravity);
59
+ }
60
+ return image.resize(resizeOptions);
61
+ };
62
+ //# sourceMappingURL=resize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.js","sourceRoot":"","sources":["../../../src/utils/image/resize.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,KAAkB,EAClB,WAAoB,EACpB,WAAqB,MAAM,EAC3B,UAAuB,QAAQ,EAC/B,UAAmB,EACnB,UAAmB,EACnB,WAAoB,EACP,EAAE;IACf,uEAAuE;IACvE,IAAI,KAAyB,CAAC;IAC9B,IAAI,MAA0B,CAAC;IAE/B,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACxC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3C,CAAC;IAED,oCAAoC;IACpC,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,GAAG,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,mEAAmE;IACnE,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,aAAa,GAAwB;QACzC,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,CAAC;QACrC,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;KACxC,CAAC;IAEF,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,MAAM;YACT,wDAAwD;YACxD,aAAa,CAAC,GAAG,GAAG,OAAO,CAAC;YAC5B,aAAa,CAAC,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACnD,MAAM;QAER,KAAK,KAAK;YACR,gEAAgE;YAChE,aAAa,CAAC,GAAG,GAAG,QAAQ,CAAC;YAC7B,aAAa,CAAC,kBAAkB,GAAG,IAAI,CAAC;YACxC,MAAM;QAER,KAAK,OAAO;YACV,mDAAmD;YACnD,aAAa,CAAC,GAAG,GAAG,MAAM,CAAC;YAC3B,MAAM;QAER,KAAK,MAAM;YACT,gEAAgE;YAChE,aAAa,CAAC,GAAG,GAAG,OAAO,CAAC;YAC5B,aAAa,CAAC,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACnD,MAAM;QAER,KAAK,KAAK;YACR,gEAAgE;YAChE,aAAa,CAAC,GAAG,GAAG,SAAS,CAAC;YAC9B,aAAa,CAAC,UAAU,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;YAC5D,MAAM;QAER;YACE,uBAAuB;YACvB,aAAa,CAAC,GAAG,GAAG,OAAO,CAAC;YAC5B,aAAa,CAAC,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AACrC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import sharp from 'sharp';
2
+ /**
3
+ * Apply rotation transformation to an image
4
+ */
5
+ export declare const applyRotation: (image: sharp.Sharp, rotateParam: string | number, background?: string) => sharp.Sharp;
6
+ //# sourceMappingURL=rotation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../../src/utils/image/rotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;GAEG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,KAAK,CAAC,KAAK,EAClB,aAAa,MAAM,GAAG,MAAM,EAC5B,aAAa,MAAM,KAClB,KAAK,CAAC,KAeR,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { parseBackgroundColor } from './background.js';
2
+ /**
3
+ * Apply rotation transformation to an image
4
+ */
5
+ export const applyRotation = (image, rotateParam, background) => {
6
+ const backgroundColor = parseBackgroundColor(background);
7
+ if (rotateParam === 'auto') {
8
+ // Auto-rotate based on EXIF orientation data
9
+ return image.rotate(undefined, { background: backgroundColor });
10
+ }
11
+ else {
12
+ // Custom angle rotation
13
+ const angle = typeof rotateParam === 'string' ? parseInt(rotateParam) : rotateParam;
14
+ if (!isNaN(angle)) {
15
+ return image.rotate(angle, { background: backgroundColor });
16
+ }
17
+ }
18
+ return image;
19
+ };
20
+ //# sourceMappingURL=rotation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../../src/utils/image/rotation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,KAAkB,EAClB,WAA4B,EAC5B,UAAmB,EACN,EAAE;IACf,MAAM,eAAe,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAEzD,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAC3B,6CAA6C;QAC7C,OAAO,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,wBAAwB;QACxB,MAAM,KAAK,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QACpF,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import sharp from "sharp";
2
+ /**
3
+ * Apply rounded corners to a Sharp image using an SVG alpha mask.
4
+ *
5
+ * Without a background: corners become transparent, use a format that
6
+ * preserves alpha (PNG, WebP, AVIF). JPEG will bake transparency onto black.
7
+ *
8
+ * With a background color: corners are filled with that color instead of
9
+ * becoming transparent, so any output format (including JPEG) works.
10
+ */
11
+ export declare const applyRoundCorners: (image: sharp.Sharp, radiusSpec: string, background?: string) => Promise<sharp.Sharp>;
12
+ //# sourceMappingURL=round-corners.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"round-corners.d.ts","sourceRoot":"","sources":["../../../src/utils/image/round-corners.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAwF1B;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,KAAK,CAAC,KAAK,EAClB,YAAY,MAAM,EAClB,aAAa,MAAM,KAClB,OAAO,CAAC,KAAK,CAAC,KAAK,CA4BrB,CAAC"}
@@ -0,0 +1,102 @@
1
+ import sharp from "sharp";
2
+ import { parseBackgroundColor } from "./background.js";
3
+ /**
4
+ * Expand a Cloudinary-style radius spec to [tl, tr, br, bl] corner values,
5
+ * following CSS border-radius replication rules:
6
+ * 1 value → all four corners the same
7
+ * 2 values → v1 = TL+BR, v2 = TR+BL
8
+ * 3 values → v1 = TL, v2 = TR+BL, v3 = BR
9
+ * 4 values → TL, TR, BR, BL (clockwise from top-left)
10
+ */
11
+ function expandRadii(spec, maxRadius) {
12
+ const parts = spec.split(":").map(Number);
13
+ let tl, tr, br, bl;
14
+ switch (parts.length) {
15
+ case 1:
16
+ tl = tr = br = bl = parts[0];
17
+ break;
18
+ case 2:
19
+ tl = br = parts[0];
20
+ tr = bl = parts[1];
21
+ break;
22
+ case 3:
23
+ tl = parts[0];
24
+ tr = bl = parts[1];
25
+ br = parts[2];
26
+ break;
27
+ default:
28
+ tl = parts[0];
29
+ tr = parts[1];
30
+ br = parts[2];
31
+ bl = parts[3];
32
+ }
33
+ // Clamp each radius so corners never overlap
34
+ const clamp = (v) => Math.min(v, maxRadius);
35
+ return [clamp(tl), clamp(tr), clamp(br), clamp(bl)];
36
+ }
37
+ /**
38
+ * Build an SVG mask with rounded corners sized to the given dimensions.
39
+ * Uses an ellipse for r_max, and an arc-based path for explicit radii.
40
+ */
41
+ function buildMaskSvg(width, height, radiusSpec) {
42
+ const w = width;
43
+ const h = height;
44
+ const maxRadius = Math.floor(Math.min(w, h) / 2);
45
+ if (radiusSpec === "max") {
46
+ const rx = w / 2;
47
+ const ry = h / 2;
48
+ return (`<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}">` +
49
+ `<ellipse cx="${rx}" cy="${ry}" rx="${rx}" ry="${ry}" fill="white"/>` +
50
+ `</svg>`);
51
+ }
52
+ const [tl, tr, br, bl] = expandRadii(radiusSpec, maxRadius);
53
+ // SVG arc path: M tl,0 → top edge → TR arc → right edge → BR arc → bottom edge → BL arc → left edge → TL arc → close
54
+ const path = `M ${tl},0 ` +
55
+ `H ${w - tr} ` +
56
+ `A ${tr},${tr} 0 0 1 ${w},${tr} ` +
57
+ `V ${h - br} ` +
58
+ `A ${br},${br} 0 0 1 ${w - br},${h} ` +
59
+ `H ${bl} ` +
60
+ `A ${bl},${bl} 0 0 1 0,${h - bl} ` +
61
+ `V ${tl} ` +
62
+ `A ${tl},${tl} 0 0 1 ${tl},0 ` +
63
+ `Z`;
64
+ return (`<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}">` +
65
+ `<path d="${path}" fill="white"/>` +
66
+ `</svg>`);
67
+ }
68
+ /**
69
+ * Apply rounded corners to a Sharp image using an SVG alpha mask.
70
+ *
71
+ * Without a background: corners become transparent, use a format that
72
+ * preserves alpha (PNG, WebP, AVIF). JPEG will bake transparency onto black.
73
+ *
74
+ * With a background color: corners are filled with that color instead of
75
+ * becoming transparent, so any output format (including JPEG) works.
76
+ */
77
+ export const applyRoundCorners = async (image, radiusSpec, background) => {
78
+ // Materialize any pending operations (e.g. resize) so we get the actual
79
+ // output dimensions. image.metadata() only returns the *input* dimensions
80
+ // and would produce an oversized mask that Sharp refuses to composite.
81
+ const { data, info } = await image.toBuffer({ resolveWithObject: true });
82
+ const { width, height } = info;
83
+ const svg = buildMaskSvg(width, height, radiusSpec);
84
+ // Apply the mask. Must materialize to a PNG buffer before flattening:
85
+ // Sharp runs flatten BEFORE composite internally, so chaining
86
+ // .composite(...).flatten(...) would flatten first (no-op) and leave
87
+ // the corners created by composite unfilled (they'd bake to black).
88
+ const maskedBuffer = await sharp(data)
89
+ .ensureAlpha()
90
+ .composite([{ input: Buffer.from(svg), blend: "dest-in" }])
91
+ .png()
92
+ .toBuffer();
93
+ // If a background color is specified, fill transparent corners in a new
94
+ // pipeline where flatten sees the alpha produced by the composite above.
95
+ if (background) {
96
+ return sharp(maskedBuffer).flatten({
97
+ background: parseBackgroundColor(background),
98
+ });
99
+ }
100
+ return sharp(maskedBuffer);
101
+ };
102
+ //# sourceMappingURL=round-corners.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"round-corners.js","sourceRoot":"","sources":["../../../src/utils/image/round-corners.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export type { CropMode, GravityMode, ImageFormat, BackgroundColor, TransformParams, ImageAnalysis, OptimizationResult } from '../../types';
2
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/image/types.ts"],"names":[],"mappings":"AACA,YAAY,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,eAAe,EACf,eAAe,EACf,aAAa,EACb,kBAAkB,EACnB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/image/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import pino from "pino";
2
+ /**
3
+ * Serialize any error value into a plain object that survives JSON.stringify.
4
+ *
5
+ * Problem: Error.message / Error.stack / Error.name are non-enumerable, so
6
+ * JSON.stringify(new Error('x')) === '{}'. pino's transport worker thread
7
+ * uses structuredClone / JSON serialization internally, which drops those
8
+ * properties even when stdSerializers are configured.
9
+ *
10
+ * Solution: always call serializeError() before passing an error to pino so
11
+ * the resulting object only contains plain enumerable string fields.
12
+ */
13
+ export declare function serializeError(error: unknown): Record<string, unknown>;
14
+ /**
15
+ * Create a structured logger instance
16
+ * - In development: pretty printed logs with colors
17
+ * - In production: JSON structured logs
18
+ */
19
+ declare const logger: pino.Logger<never, boolean>;
20
+ export default logger;
21
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAqBxB;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsBtE;AAED;;;;GAIG;AACH,QAAA,MAAM,MAAM,6BAwBV,CAAC;AAEH,eAAe,MAAM,CAAC"}