@uploadista/flow-images-nodes 0.0.20-beta.7 → 0.0.20-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,6 @@
1
1
  # @uploadista/flow-images-nodes
2
2
 
3
- Base image processing nodes for Uploadista flows. Provides foundational image operations.
4
-
5
- ## Overview
6
-
7
- Base image nodes define interfaces and common operations:
8
-
9
- - **Image Descriptions**: Extract metadata from images
10
- - **Optimization**: Basic compression and format conversion
11
- - **Background Removal**: Remove image backgrounds
12
- - **Resizing**: Scale images
13
- - **URL Resolution**: Load images from URLs
3
+ Image processing nodes for Uploadista flows. Provides resizing, optimization, transformations, and AI-powered operations.
14
4
 
15
5
  ## Installation
16
6
 
@@ -20,98 +10,224 @@ npm install @uploadista/flow-images-nodes
20
10
  pnpm add @uploadista/flow-images-nodes
21
11
  ```
22
12
 
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import {
17
+ createResizeNode,
18
+ createOptimizeNode,
19
+ createTransformImageNode,
20
+ createRemoveBackgroundNode,
21
+ createDescribeImageNode,
22
+ } from "@uploadista/flow-images-nodes";
23
+ ```
24
+
23
25
  ## Node Types
24
26
 
25
- ### Describe Image
27
+ ### Resize Node
26
28
 
27
- Extract image metadata.
29
+ Scale images to specific dimensions.
28
30
 
29
31
  ```typescript
30
- {
31
- type: "describe-image",
32
- params: {}
33
- }
32
+ import { createResizeNode } from "@uploadista/flow-images-nodes";
33
+
34
+ // Resize to specific dimensions
35
+ const resizeNode = yield* createResizeNode("resize-1", {
36
+ width: 800,
37
+ height: 600,
38
+ fit: "cover",
39
+ });
40
+
41
+ // Resize width only, maintain aspect ratio
42
+ const widthOnlyNode = yield* createResizeNode("resize-2", {
43
+ width: 1200,
44
+ fit: "contain",
45
+ });
46
+
47
+ // With streaming mode for large files
48
+ const streamingNode = yield* createResizeNode("resize-3", {
49
+ width: 800,
50
+ height: 600,
51
+ fit: "cover",
52
+ }, {
53
+ mode: "streaming",
54
+ naming: { mode: "auto" },
55
+ });
34
56
  ```
35
57
 
36
- Output: Image metadata (dimensions, format, etc)
58
+ #### Parameters
37
59
 
38
- ### Optimize
60
+ | Parameter | Type | Required | Description |
61
+ |-----------|------|----------|-------------|
62
+ | `width` | `number` | No* | Target width in pixels |
63
+ | `height` | `number` | No* | Target height in pixels |
64
+ | `fit` | `"contain" \| "cover" \| "fill"` | Yes | How the image fits within dimensions |
39
65
 
40
- Compress and convert images.
66
+ *At least one of `width` or `height` must be specified.
67
+
68
+ #### Options
69
+
70
+ | Option | Type | Default | Description |
71
+ |--------|------|---------|-------------|
72
+ | `mode` | `"auto" \| "buffered" \| "streaming"` | `"auto"` | Processing mode |
73
+ | `keepOutput` | `boolean` | `false` | Keep output in flow results |
74
+ | `naming` | `FileNamingConfig` | - | File naming configuration |
75
+
76
+ ### Optimize Node
77
+
78
+ Compress and convert image formats.
41
79
 
42
80
  ```typescript
43
- {
44
- type: "optimize",
45
- params: {
46
- quality: 85, // 1-100
47
- format: "webp" // jpeg, png, webp, avif
48
- }
49
- }
81
+ import { createOptimizeNode } from "@uploadista/flow-images-nodes";
82
+
83
+ // Convert to WebP with quality 80
84
+ const optimizeNode = yield* createOptimizeNode("optimize-1", {
85
+ quality: 80,
86
+ format: "webp",
87
+ });
88
+
89
+ // Maximum compression with AVIF
90
+ const avifNode = yield* createOptimizeNode("optimize-2", {
91
+ quality: 75,
92
+ format: "avif",
93
+ });
94
+
95
+ // High quality JPEG for compatibility
96
+ const jpegNode = yield* createOptimizeNode("optimize-3", {
97
+ quality: 90,
98
+ format: "jpeg",
99
+ }, {
100
+ naming: { mode: "auto" },
101
+ });
50
102
  ```
51
103
 
52
- ### Remove Background
104
+ #### Parameters
105
+
106
+ | Parameter | Type | Required | Description |
107
+ |-----------|------|----------|-------------|
108
+ | `quality` | `number` (0-100) | Yes | Image quality percentage |
109
+ | `format` | `"jpeg" \| "webp" \| "png" \| "avif"` | Yes | Output image format |
110
+
111
+ ### Transform Image Node
53
112
 
54
- Remove image backgrounds.
113
+ Apply multiple transformations in sequence.
55
114
 
56
115
  ```typescript
57
- {
58
- type: "remove-background",
59
- params: {
60
- padding: 0,
61
- format: "png"
62
- }
63
- }
116
+ import { createTransformImageNode } from "@uploadista/flow-images-nodes";
117
+
118
+ // Chain multiple transformations
119
+ const transformNode = yield* createTransformImageNode("transform-1", {
120
+ transformations: [
121
+ { type: "resize", width: 800, height: 600, fit: "cover" },
122
+ { type: "brightness", value: 10 },
123
+ { type: "sharpen" },
124
+ ],
125
+ });
126
+
127
+ // Add watermark
128
+ const watermarkNode = yield* createTransformImageNode("transform-2", {
129
+ transformations: [
130
+ { type: "resize", width: 1200, fit: "contain" },
131
+ {
132
+ type: "watermark",
133
+ imagePath: "https://example.com/watermark.png",
134
+ position: "bottom-right",
135
+ opacity: 0.5,
136
+ },
137
+ ],
138
+ });
139
+
140
+ // Apply filters
141
+ const filterNode = yield* createTransformImageNode("transform-3", {
142
+ transformations: [
143
+ { type: "grayscale" },
144
+ { type: "contrast", value: 20 },
145
+ ],
146
+ });
64
147
  ```
65
148
 
66
- ### Resize
149
+ #### Transformation Types
67
150
 
68
- Scale images to dimensions.
151
+ | Type | Parameters | Description |
152
+ |------|------------|-------------|
153
+ | `resize` | `width?`, `height?`, `fit` | Resize image |
154
+ | `blur` | `sigma` (0.3-1000) | Apply Gaussian blur |
155
+ | `rotate` | `angle`, `background?` | Rotate by degrees |
156
+ | `flip` | `direction` | Flip horizontal/vertical |
157
+ | `grayscale` | - | Convert to grayscale |
158
+ | `sepia` | - | Apply sepia tone |
159
+ | `brightness` | `value` (-100 to 100) | Adjust brightness |
160
+ | `contrast` | `value` (-100 to 100) | Adjust contrast |
161
+ | `sharpen` | `sigma?` | Apply sharpening |
162
+ | `watermark` | `imagePath`, `position`, `opacity` | Add watermark |
163
+ | `logo` | `imagePath`, `position`, `scale` | Add logo overlay |
164
+ | `text` | `text`, `position`, `fontSize`, `color` | Add text overlay |
165
+
166
+ ### Remove Background Node
167
+
168
+ AI-powered background removal.
69
169
 
70
170
  ```typescript
71
- {
72
- type: "resize",
73
- params: {
74
- width: 800,
75
- height: 600,
76
- fit: "cover" // cover, contain, fill
77
- }
78
- }
171
+ import { createRemoveBackgroundNode } from "@uploadista/flow-images-nodes";
172
+
173
+ // Remove background with default settings
174
+ const removeBgNode = yield* createRemoveBackgroundNode("remove-bg-1");
175
+
176
+ // With custom credential and naming
177
+ const customNode = yield* createRemoveBackgroundNode("remove-bg-2", {
178
+ credentialId: "my-replicate-credential",
179
+ naming: { mode: "auto" },
180
+ });
79
181
  ```
80
182
 
81
- ### Wait for URL
183
+ #### Parameters
82
184
 
83
- Load image from URL.
185
+ | Parameter | Type | Required | Default | Description |
186
+ |-----------|------|----------|---------|-------------|
187
+ | `credentialId` | `string` | No | - | AI service credential ID |
188
+ | `keepOutput` | `boolean` | No | `false` | Keep output in flow results |
189
+ | `naming` | `FileNamingConfig` | No | - | File naming (auto suffix: `nobg`) |
190
+
191
+ ### Describe Image Node
192
+
193
+ Extract image description using AI.
84
194
 
85
195
  ```typescript
86
- {
87
- type: "wait-for-url",
88
- params: {
89
- timeout: 30000
90
- }
91
- }
196
+ import { createDescribeImageNode } from "@uploadista/flow-images-nodes";
197
+
198
+ // Describe image content
199
+ const describeNode = yield* createDescribeImageNode("describe-1");
200
+
201
+ // With custom credential
202
+ const customDescribeNode = yield* createDescribeImageNode("describe-2", {
203
+ credentialId: "my-ai-credential",
204
+ keepOutput: true,
205
+ });
92
206
  ```
93
207
 
94
- ## Use Cases
208
+ #### Parameters
209
+
210
+ | Parameter | Type | Required | Default | Description |
211
+ |-----------|------|----------|---------|-------------|
212
+ | `credentialId` | `string` | No | - | AI service credential ID |
213
+ | `keepOutput` | `boolean` | No | `false` | Keep output in flow results |
214
+
215
+ ## Streaming Modes
95
216
 
96
- - Extract metadata for indexing
97
- - Normalize image formats
98
- - Create responsive variants
99
- - Remove backgrounds for product images
100
- - Load external images into pipeline
217
+ All transform nodes support three processing modes:
218
+
219
+ | Mode | Description | When to Use |
220
+ |------|-------------|-------------|
221
+ | `auto` | Selects streaming for files > 1MB | Default, recommended |
222
+ | `buffered` | Loads entire file into memory | Small files |
223
+ | `streaming` | Processes file as chunks | Large files, memory-constrained |
101
224
 
102
225
  ## Related Packages
103
226
 
104
227
  - [@uploadista/flow-images-sharp](../sharp) - Sharp implementation (Node.js)
105
- - [@uploadista/flow-images-photon](../photon) - Cloudflare Photon (edge)
228
+ - [@uploadista/flow-images-photon](../photon) - Cloudflare Photon (Edge)
106
229
  - [@uploadista/flow-images-replicate](../replicate) - AI operations
107
- - [@uploadista/server](../../servers/server) - Upload server
108
230
 
109
231
  ## License
110
232
 
111
233
  See [LICENSE](../../../LICENSE) in the main repository.
112
-
113
- ## See Also
114
-
115
- - [FLOW_NODES.md](../FLOW_NODES.md) - All available nodes
116
- - [Sharp Node](../sharp/README.md) - Node.js image processing
117
- - [Photon Node](../photon/README.md) - Edge image processing
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- let e=require(`@uploadista/core/errors`),t=require(`@uploadista/core/flow`),n=require(`@uploadista/core/types`),r=require(`effect`),i=require(`@uploadista/core`),a=require(`@uploadista/core/upload`);function o(t,n={}){let{maxWaitTime:i=1e4,retryDelay:a=500}=n;return r.Effect.gen(function*(){let n=Date.now();for(;Date.now()-n<i;){let e=yield*r.Effect.tryPromise(()=>fetch(t,{method:`HEAD`})).pipe(r.Effect.catchAll(()=>r.Effect.succeed(null)));if(e?.ok){yield*r.Effect.logInfo(`URL ${t} is now available`);return}e?yield*r.Effect.logDebug(`URL not ready yet (${e.status}), retrying...`):yield*r.Effect.logDebug(`URL check failed, retrying...`),yield*r.Effect.sleep(a)}return yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL ${t} not available after ${i}ms`}).toEffect()})}function s(i,{credentialId:a,keepOutput:s}={}){return r.Effect.gen(function*(){let c=yield*t.ImageAiPlugin;return yield*(0,t.createFlowNode)({id:i,name:`Describe Image`,description:`Describes the image using AI`,type:t.NodeType.process,nodeTypeId:`describe-image`,outputTypeId:t.IMAGE_DESCRIPTION_OUTPUT_TYPE_ID,keepOutput:s,inputSchema:n.uploadFileSchema,outputSchema:t.imageDescriptionOutputSchema,circuitBreaker:{enabled:!0,failureThreshold:5,resetTimeout:6e4,fallback:{type:`skip`,passThrough:!0}},run:({data:n,flowId:s,jobId:l,clientId:u})=>r.Effect.gen(function*(){let d={flowId:s,nodeId:i,jobId:l},f=n.url;if(!f)return yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for describe image operation`}).toEffect();yield*r.Effect.logInfo(`Describing image for file ${n.id} at URL: ${f}`),yield*o(f);let p={clientId:u,credentialId:a},m=yield*c.describeImage(f,p).pipe(r.Effect.catchAll(t=>r.Effect.gen(function*(){return yield*r.Effect.logError(`Failed to describe image`,t),yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to describe image`}).toEffect()})));return yield*r.Effect.logInfo(`Successfully described image for file ${n.id}`),(0,t.completeNodeExecution)({description:m.description,flow:d})})})})}const c={jpeg:`image/jpeg`,webp:`image/webp`,png:`image/png`,avif:`image/avif`},l={jpeg:`jpg`,webp:`webp`,png:`png`,avif:`avif`};function u(e,{quality:n,format:a},o){return r.Effect.gen(function*(){let s=yield*t.ImagePlugin,u=s.supportsStreaming??!1,d=o?.mode??`buffered`,f=d===`buffered`?`buffered`:u?d:`buffered`,p=r=>{let i=c[a],s=l[a],u=r.metadata?.fileName,d;if(u&&typeof u==`string`)if(o?.naming){let i={...o.naming,autoSuffix:o.naming.autoSuffix??(e=>e.format??a)};d=`${(0,t.getBaseName)((0,t.applyFileNaming)(r,(0,t.buildNamingContext)(r,{flowId:r.flow?.flowId??``,jobId:r.flow?.jobId??``,nodeId:e,nodeType:`optimize`},{format:a,quality:n}),i))}.${s}`}else d=u.replace(/\.[^.]+$/,`.${s}`);return{newType:i,newFileName:d}};return yield*(0,t.createTransformNode)({id:e,name:`Optimize`,description:`Optimizes an image for web delivery`,nodeTypeId:`optimize-image`,outputTypeId:t.STORAGE_OUTPUT_TYPE_ID,keepOutput:o?.keepOutput,nodeType:`optimize`,namingVars:{format:a,quality:n},mode:f,streamingConfig:o?.streamingConfig,transform:(e,t)=>r.Effect.map(s.optimize(e,{quality:n,format:a}),e=>{let{newType:n,newFileName:r}=p(t);return{bytes:e,type:n,fileName:r}}),streamingTransform:s.optimizeStream?(e,t)=>{let o=s.optimizeStream;if(!o)throw i.UploadistaError.fromCode(`UNKNOWN_ERROR`);return r.Effect.gen(function*(){let r=yield*o(e,{quality:n,format:a}),{newType:i,newFileName:s}=p(t);return{stream:r,type:i,fileName:s}})}:void 0})})}function d(i,{credentialId:s,keepOutput:c,naming:l}={}){return r.Effect.gen(function*(){let u=yield*t.ImageAiPlugin,d=yield*a.UploadServer;return yield*(0,t.createFlowNode)({id:i,name:`Remove Background`,description:`Removes the background from an image`,type:t.NodeType.process,nodeTypeId:`remove-background`,outputTypeId:t.STORAGE_OUTPUT_TYPE_ID,keepOutput:c,inputSchema:n.uploadFileSchema,outputSchema:n.uploadFileSchema,circuitBreaker:{enabled:!0,failureThreshold:5,resetTimeout:6e4,fallback:{type:`skip`,passThrough:!0}},run:({data:n,flowId:a,jobId:c,storageId:f,clientId:p})=>r.Effect.gen(function*(){let m={flowId:a,nodeId:i,jobId:c},h=n.url;if(!h)return yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for remove background operation`}).toEffect();yield*r.Effect.logInfo(`Removing background for file ${n.id} at URL: ${n.url}`),yield*o(h);let g={clientId:p,credentialId:s},{outputUrl:_}=yield*u.removeBackground(h,g).pipe(r.Effect.catchAll(t=>r.Effect.gen(function*(){return yield*r.Effect.logError(`Failed to remove background`,t),yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to remove background from image`}).toEffect()}))),{type:v,fileName:y,metadata:b,metadataJson:x}=(0,t.resolveUploadMetadata)(n.metadata),S=y;if(l){let e={...l,autoSuffix:l.autoSuffix??(()=>`nobg`)};S=(0,t.applyFileNaming)(n,(0,t.buildNamingContext)(n,{flowId:a,jobId:c,nodeId:i,nodeType:`remove-background`}),e)}yield*r.Effect.logInfo(`Uploading processed file to storage`);let C=yield*d.uploadFromUrl({storageId:f,size:0,type:v,fileName:S,lastModified:0,metadata:x,flow:m},p,_).pipe(r.Effect.catchAll(t=>r.Effect.gen(function*(){return yield*r.Effect.logError(`Failed to upload processed file`,t),yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to upload processed file`}).toEffect()})));yield*r.Effect.logInfo(`Successfully removed background for file ${n.id}`);let w=b?{...b,...S!==y&&{fileName:S,originalName:S,name:S,extension:S.split(`.`).pop()||b.extension}}:C.metadata;return(0,t.completeNodeExecution)(w?{...C,metadata:w}:C)})})})}function f(e,{width:n,height:i,fit:a},o){return r.Effect.gen(function*(){let s=yield*t.ImagePlugin,c=s.supportsStreaming??!1,l=o?.mode??`auto`,u=l===`buffered`?`buffered`:c?l:`buffered`,d=o?.naming?{...o.naming,autoSuffix:o.naming.autoSuffix??(e=>`${e.width??n}x${e.height??i}`)}:void 0;return yield*(0,t.createTransformNode)({id:e,name:`Resize`,description:`Resizes an image to the specified dimensions`,nodeTypeId:`resize-image`,outputTypeId:t.STORAGE_OUTPUT_TYPE_ID,keepOutput:o?.keepOutput,naming:d,nodeType:`resize`,namingVars:{width:n,height:i},mode:u,streamingConfig:o?.streamingConfig,transform:e=>s.resize(e,{height:i,width:n,fit:a}),streamingTransform:s.resizeStream?e=>r.Effect.gen(function*(){let t=s.resizeStream;if(!t)throw Error(`resizeStream not available`);return{stream:yield*t(e,{width:n,height:i,fit:a})}}):void 0})})}function p(e,t,n){return r.Effect.reduce(n,t,(t,n)=>e.transform(t,n))}function m(e,t,n){let i=e.transformStream;return i?r.Effect.reduce(n,t,(e,t)=>r.Effect.flatMap(i(e,t),e=>r.Effect.succeed(e))):r.Effect.gen(function*(){let i=[];yield*r.Stream.runForEach(t,e=>r.Effect.sync(()=>{i.push(e)}));let a=i.reduce((e,t)=>e+t.byteLength,0),o=new Uint8Array(a),s=0;for(let e of i)o.set(e,s),s+=e.byteLength;let c=yield*p(e,o,n);return r.Stream.make(c)})}function h(e,{transformations:n},i){return r.Effect.gen(function*(){let a=yield*t.ImagePlugin,o=a.supportsStreaming??!1,s=i?.mode??`auto`,c=n.some(e=>e.type===`watermark`||e.type===`logo`||e.type===`text`),l=s===`buffered`?`buffered`:o&&!c?s:`buffered`,u=i?.naming?{...i.naming,autoSuffix:i.naming.autoSuffix??(()=>`transformed`)}:void 0;return yield*(0,t.createTransformNode)({id:e,name:`Transform Image`,description:`Apply ${n.length} transformation${n.length===1?``:`s`} to the image`,nodeTypeId:`transform-image`,outputTypeId:t.STORAGE_OUTPUT_TYPE_ID,keepOutput:i?.keepOutput,naming:u,nodeType:`transform-image`,mode:l,streamingConfig:i?.streamingConfig,transform:e=>p(a,e,n),streamingTransform:o&&!c?e=>r.Effect.gen(function*(){return{stream:yield*m(a,e,n)}}):void 0})})}exports.createDescribeImageNode=s,exports.createOptimizeNode=u,exports.createRemoveBackgroundNode=d,exports.createResizeNode=f,exports.createTransformImageNode=h,exports.waitForUrlAvailability=o;
1
+ let e=require(`@uploadista/core/errors`),t=require(`@uploadista/core/flow`),n=require(`@uploadista/core/types`),r=require(`effect`),i=require(`@uploadista/core`),a=require(`@uploadista/core/upload`);function o(t,n={}){let{maxWaitTime:i=1e4,retryDelay:a=500}=n;return r.Effect.gen(function*(){let n=Date.now();for(;Date.now()-n<i;){let e=yield*r.Effect.tryPromise(()=>fetch(t,{method:`HEAD`})).pipe(r.Effect.catchAll(()=>r.Effect.succeed(null)));if(e?.ok){yield*r.Effect.logInfo(`URL ${t} is now available`);return}e?yield*r.Effect.logDebug(`URL not ready yet (${e.status}), retrying...`):yield*r.Effect.logDebug(`URL check failed, retrying...`),yield*r.Effect.sleep(a)}return yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL ${t} not available after ${i}ms`}).toEffect()})}function s(i,{credentialId:a,keepOutput:s}={}){return r.Effect.gen(function*(){let c=yield*t.ImageAiPlugin;return yield*(0,t.createFlowNode)({id:i,name:`Describe Image`,description:`Describes the image using AI`,type:t.NodeType.process,nodeTypeId:`describe-image`,outputTypeId:t.IMAGE_DESCRIPTION_OUTPUT_TYPE_ID,keepOutput:s,inputSchema:n.uploadFileSchema,outputSchema:t.imageDescriptionOutputSchema,circuitBreaker:{enabled:!0,failureThreshold:5,resetTimeout:6e4,fallback:{type:`skip`,passThrough:!0}},run:({data:n,flowId:s,jobId:l,clientId:u})=>r.Effect.gen(function*(){let d={flowId:s,nodeId:i,jobId:l},f=n.url;if(!f)return yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for describe image operation`}).toEffect();yield*r.Effect.logInfo(`Describing image for file ${n.id} at URL: ${f}`),yield*o(f);let p={clientId:u,credentialId:a},m=yield*c.describeImage(f,p).pipe(r.Effect.catchAll(t=>r.Effect.gen(function*(){return yield*r.Effect.logError(`Failed to describe image`,t),yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to describe image`}).toEffect()})));return yield*r.Effect.logInfo(`Successfully described image for file ${n.id}`),(0,t.completeNodeExecution)({description:m.description,flow:d})})})})}const c={jpeg:`image/jpeg`,webp:`image/webp`,png:`image/png`,avif:`image/avif`},l={jpeg:`jpg`,webp:`webp`,png:`png`,avif:`avif`};function u(e,{quality:n,format:a},o){return r.Effect.gen(function*(){let s=yield*t.ImagePlugin,u=s.supportsStreaming??!1,d=o?.mode??`buffered`,f=d===`buffered`?`buffered`:u?d:`buffered`,p=r=>{let i=c[a],s=l[a],u=r.metadata?.fileName,d;if(u&&typeof u==`string`)if(o?.naming){let i={...o.naming,autoSuffix:o.naming.autoSuffix??(e=>e.format??a)};d=`${(0,t.getBaseName)((0,t.applyFileNaming)(r,(0,t.buildNamingContext)(r,{flowId:r.flow?.flowId??``,jobId:r.flow?.jobId??``,nodeId:e,nodeType:`optimize`},{format:a,quality:n}),i))}.${s}`}else d=u.replace(/\.[^.]+$/,`.${s}`);return{newType:i,newFileName:d}};return yield*(0,t.createTransformNode)({id:e,name:`Optimize`,description:`Optimizes an image for web delivery`,nodeTypeId:`optimize-image`,outputTypeId:t.STORAGE_OUTPUT_TYPE_ID,keepOutput:o?.keepOutput,nodeType:`optimize`,namingVars:{format:a,quality:n},mode:f,streamingConfig:o?.streamingConfig,transform:(e,t)=>r.Effect.map(s.optimize(e,{quality:n,format:a}),e=>{let{newType:n,newFileName:r}=p(t);return{bytes:e,type:n,fileName:r}}),streamingTransform:s.optimizeStream?(e,t)=>{let o=s.optimizeStream;if(!o)throw i.UploadistaError.fromCode(`UNKNOWN_ERROR`);return r.Effect.gen(function*(){let r=yield*o(e,{quality:n,format:a}),{newType:i,newFileName:s}=p(t);return{stream:r,type:i,fileName:s}})}:void 0})})}function d(i,{credentialId:s,keepOutput:c,naming:l}={}){return r.Effect.gen(function*(){let u=yield*t.ImageAiPlugin,d=yield*a.UploadEngine;return yield*(0,t.createFlowNode)({id:i,name:`Remove Background`,description:`Removes the background from an image`,type:t.NodeType.process,nodeTypeId:`remove-background`,outputTypeId:t.STORAGE_OUTPUT_TYPE_ID,keepOutput:c,inputSchema:n.uploadFileSchema,outputSchema:n.uploadFileSchema,circuitBreaker:{enabled:!0,failureThreshold:5,resetTimeout:6e4,fallback:{type:`skip`,passThrough:!0}},run:({data:n,flowId:a,jobId:c,storageId:f,clientId:p})=>r.Effect.gen(function*(){let m={flowId:a,nodeId:i,jobId:c},h=n.url;if(!h)return yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for remove background operation`}).toEffect();yield*r.Effect.logInfo(`Removing background for file ${n.id} at URL: ${n.url}`),yield*o(h);let g={clientId:p,credentialId:s},{outputUrl:_}=yield*u.removeBackground(h,g).pipe(r.Effect.catchAll(t=>r.Effect.gen(function*(){return yield*r.Effect.logError(`Failed to remove background`,t),yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to remove background from image`}).toEffect()}))),{type:v,fileName:y,metadata:b,metadataJson:x}=(0,t.resolveUploadMetadata)(n.metadata),S=y;if(l){let e={...l,autoSuffix:l.autoSuffix??(()=>`nobg`)};S=(0,t.applyFileNaming)(n,(0,t.buildNamingContext)(n,{flowId:a,jobId:c,nodeId:i,nodeType:`remove-background`}),e)}yield*r.Effect.logInfo(`Uploading processed file to storage`);let C=yield*d.uploadFromUrl({storageId:f,size:0,type:v,fileName:S,lastModified:0,metadata:x,flow:m},p,_).pipe(r.Effect.catchAll(t=>r.Effect.gen(function*(){return yield*r.Effect.logError(`Failed to upload processed file`,t),yield*e.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to upload processed file`}).toEffect()})));yield*r.Effect.logInfo(`Successfully removed background for file ${n.id}`);let w=b?{...b,...S!==y&&{fileName:S,originalName:S,name:S,extension:S.split(`.`).pop()||b.extension}}:C.metadata;return(0,t.completeNodeExecution)(w?{...C,metadata:w}:C)})})})}function f(e,{width:n,height:i,fit:a},o){return r.Effect.gen(function*(){let s=yield*t.ImagePlugin,c=s.supportsStreaming??!1,l=o?.mode??`auto`,u=l===`buffered`?`buffered`:c?l:`buffered`,d=o?.naming?{...o.naming,autoSuffix:o.naming.autoSuffix??(e=>`${e.width??n}x${e.height??i}`)}:void 0;return yield*(0,t.createTransformNode)({id:e,name:`Resize`,description:`Resizes an image to the specified dimensions`,nodeTypeId:`resize-image`,outputTypeId:t.STORAGE_OUTPUT_TYPE_ID,keepOutput:o?.keepOutput,naming:d,nodeType:`resize`,namingVars:{width:n,height:i},mode:u,streamingConfig:o?.streamingConfig,transform:e=>s.resize(e,{height:i,width:n,fit:a}),streamingTransform:s.resizeStream?e=>r.Effect.gen(function*(){let t=s.resizeStream;if(!t)throw Error(`resizeStream not available`);return{stream:yield*t(e,{width:n,height:i,fit:a})}}):void 0})})}function p(e,t,n){return r.Effect.reduce(n,t,(t,n)=>e.transform(t,n))}function m(e,t,n){let i=e.transformStream;return i?r.Effect.reduce(n,t,(e,t)=>r.Effect.flatMap(i(e,t),e=>r.Effect.succeed(e))):r.Effect.gen(function*(){let i=[];yield*r.Stream.runForEach(t,e=>r.Effect.sync(()=>{i.push(e)}));let a=i.reduce((e,t)=>e+t.byteLength,0),o=new Uint8Array(a),s=0;for(let e of i)o.set(e,s),s+=e.byteLength;let c=yield*p(e,o,n);return r.Stream.make(c)})}function h(e,{transformations:n},i){return r.Effect.gen(function*(){let a=yield*t.ImagePlugin,o=a.supportsStreaming??!1,s=i?.mode??`auto`,c=n.some(e=>e.type===`watermark`||e.type===`logo`||e.type===`text`),l=s===`buffered`?`buffered`:o&&!c?s:`buffered`,u=i?.naming?{...i.naming,autoSuffix:i.naming.autoSuffix??(()=>`transformed`)}:void 0;return yield*(0,t.createTransformNode)({id:e,name:`Transform Image`,description:`Apply ${n.length} transformation${n.length===1?``:`s`} to the image`,nodeTypeId:`transform-image`,outputTypeId:t.STORAGE_OUTPUT_TYPE_ID,keepOutput:i?.keepOutput,naming:u,nodeType:`transform-image`,mode:l,streamingConfig:i?.streamingConfig,transform:e=>p(a,e,n),streamingTransform:o&&!c?e=>r.Effect.gen(function*(){return{stream:yield*m(a,e,n)}}):void 0})})}exports.createDescribeImageNode=s,exports.createOptimizeNode=u,exports.createRemoveBackgroundNode=d,exports.createResizeNode=f,exports.createTransformImageNode=h,exports.waitForUrlAvailability=o;
package/dist/index.d.cts CHANGED
@@ -5,7 +5,7 @@ import * as zod0 from "zod";
5
5
  import { UploadistaError as UploadistaError$1 } from "@uploadista/core/errors";
6
6
  import { FileNamingConfig, ImageAiPlugin, ImagePlugin, NodeType, OptimizeParams, ResizeParams, StreamingConfig, TransformImageParams, TransformMode } from "@uploadista/core/flow";
7
7
  import { Effect } from "effect";
8
- import { UploadServer } from "@uploadista/core/upload";
8
+ import { UploadEngine } from "@uploadista/core/upload";
9
9
 
10
10
  //#region src/describe-image-node.d.ts
11
11
  declare function createDescribeImageNode(id: string, {
@@ -223,7 +223,7 @@ declare function createOptimizeNode(id: string, {
223
223
  circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
224
224
  } & {
225
225
  type: _uploadista_core0.NodeType;
226
- }, UploadistaError, ImagePlugin | _uploadista_core0.UploadServer>;
226
+ }, UploadistaError, _uploadista_core0.UploadEngine | ImagePlugin>;
227
227
  //#endregion
228
228
  //#region src/remove-background-node.d.ts
229
229
  /**
@@ -374,7 +374,7 @@ declare function createRemoveBackgroundNode(id: string, {
374
374
  circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
375
375
  } & {
376
376
  type: NodeType.process;
377
- }, UploadistaError$1, ImageAiPlugin | UploadServer>;
377
+ }, UploadistaError$1, UploadEngine | ImageAiPlugin>;
378
378
  //#endregion
379
379
  //#region src/resize-node.d.ts
380
380
  /**
@@ -448,7 +448,7 @@ declare function createResizeNode(id: string, {
448
448
  circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
449
449
  } & {
450
450
  type: _uploadista_core0.NodeType;
451
- }, _uploadista_core0.UploadistaError, ImagePlugin | _uploadista_core0.UploadServer>;
451
+ }, _uploadista_core0.UploadistaError, _uploadista_core0.UploadEngine | ImagePlugin>;
452
452
  //#endregion
453
453
  //#region src/transform-image-node.d.ts
454
454
  /**
@@ -547,7 +547,7 @@ declare function createTransformImageNode(id: string, {
547
547
  circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
548
548
  } & {
549
549
  type: _uploadista_core0.NodeType;
550
- }, UploadistaError$1, ImagePlugin | _uploadista_core0.UploadServer>;
550
+ }, UploadistaError$1, _uploadista_core0.UploadEngine | ImagePlugin>;
551
551
  //#endregion
552
552
  //#region src/wait-for-url.d.ts
553
553
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-node.ts","../src/transform-image-node.ts","../src/wait-for-url.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-node.ts","../src/transform-image-node.ts","../src/wait-for-url.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { UploadistaError } from "@uploadista/core/errors";
2
2
  import { FileNamingConfig, ImageAiPlugin, ImagePlugin, NodeType, OptimizeParams, ResizeParams, StreamingConfig, TransformImageParams, TransformMode } from "@uploadista/core/flow";
3
3
  import { Effect } from "effect";
4
- import * as _uploadista_core0 from "@uploadista/core";
4
+ import * as _uploadista_core5 from "@uploadista/core";
5
5
  import { UploadistaError as UploadistaError$1 } from "@uploadista/core";
6
- import { UploadServer } from "@uploadista/core/upload";
7
- import * as zod_v4_core0 from "zod/v4/core";
8
- import * as zod0 from "zod";
6
+ import { UploadEngine } from "@uploadista/core/upload";
7
+ import * as zod_v4_core1 from "zod/v4/core";
8
+ import * as zod1 from "zod";
9
9
 
10
10
  //#region src/describe-image-node.d.ts
11
11
  declare function createDescribeImageNode(id: string, {
@@ -14,8 +14,8 @@ declare function createDescribeImageNode(id: string, {
14
14
  }?: {
15
15
  credentialId?: string;
16
16
  keepOutput?: boolean;
17
- }): Effect.Effect<_uploadista_core0.FlowNodeData & {
18
- inputSchema: zod0.ZodType<{
17
+ }): Effect.Effect<_uploadista_core5.FlowNodeData & {
18
+ inputSchema: zod1.ZodType<{
19
19
  id: string;
20
20
  offset: number;
21
21
  storage: {
@@ -47,7 +47,7 @@ declare function createDescribeImageNode(id: string, {
47
47
  spanId: string;
48
48
  traceFlags: number;
49
49
  } | undefined;
50
- }, unknown, zod_v4_core0.$ZodTypeInternals<{
50
+ }, unknown, zod_v4_core1.$ZodTypeInternals<{
51
51
  id: string;
52
52
  offset: number;
53
53
  storage: {
@@ -80,11 +80,11 @@ declare function createDescribeImageNode(id: string, {
80
80
  traceFlags: number;
81
81
  } | undefined;
82
82
  }, unknown>>;
83
- outputSchema: zod0.ZodType<{
83
+ outputSchema: zod1.ZodType<{
84
84
  description: string;
85
85
  confidence?: number | undefined;
86
86
  metadata?: Record<string, unknown> | undefined;
87
- }, unknown, zod_v4_core0.$ZodTypeInternals<{
87
+ }, unknown, zod_v4_core1.$ZodTypeInternals<{
88
88
  description: string;
89
89
  confidence?: number | undefined;
90
90
  metadata?: Record<string, unknown> | undefined;
@@ -128,7 +128,7 @@ declare function createDescribeImageNode(id: string, {
128
128
  flowId: string;
129
129
  inputs?: Record<string, unknown>;
130
130
  clientId: string | null;
131
- }) => Effect.Effect<_uploadista_core0.NodeExecutionResult<{
131
+ }) => Effect.Effect<_uploadista_core5.NodeExecutionResult<{
132
132
  description: string;
133
133
  confidence?: number | undefined;
134
134
  metadata?: Record<string, unknown> | undefined;
@@ -146,7 +146,7 @@ declare function createDescribeImageNode(id: string, {
146
146
  retryDelay?: number;
147
147
  exponentialBackoff?: boolean;
148
148
  };
149
- circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
149
+ circuitBreaker?: _uploadista_core5.FlowCircuitBreakerConfig;
150
150
  } & {
151
151
  type: NodeType.process;
152
152
  }, UploadistaError, ImageAiPlugin>;
@@ -196,17 +196,17 @@ declare function createOptimizeNode(id: string, {
196
196
  naming?: FileNamingConfig;
197
197
  mode?: TransformMode;
198
198
  streamingConfig?: StreamingConfig;
199
- }): Effect.Effect<_uploadista_core0.FlowNodeData & {
200
- inputSchema: zod0.ZodType<_uploadista_core0.UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<_uploadista_core0.UploadFile, unknown>>;
201
- outputSchema: zod0.ZodType<_uploadista_core0.UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<_uploadista_core0.UploadFile, unknown>>;
199
+ }): Effect.Effect<_uploadista_core5.FlowNodeData & {
200
+ inputSchema: zod1.ZodType<_uploadista_core5.UploadFile, unknown, zod_v4_core1.$ZodTypeInternals<_uploadista_core5.UploadFile, unknown>>;
201
+ outputSchema: zod1.ZodType<_uploadista_core5.UploadFile, unknown, zod_v4_core1.$ZodTypeInternals<_uploadista_core5.UploadFile, unknown>>;
202
202
  run: (args: {
203
- data: _uploadista_core0.UploadFile;
203
+ data: _uploadista_core5.UploadFile;
204
204
  jobId: string;
205
205
  storageId: string;
206
206
  flowId: string;
207
207
  inputs?: Record<string, unknown>;
208
208
  clientId: string | null;
209
- }) => Effect.Effect<_uploadista_core0.NodeExecutionResult<_uploadista_core0.UploadFile>, UploadistaError$1, never>;
209
+ }) => Effect.Effect<_uploadista_core5.NodeExecutionResult<_uploadista_core5.UploadFile>, UploadistaError$1, never>;
210
210
  condition?: {
211
211
  field: string;
212
212
  operator: string;
@@ -220,10 +220,10 @@ declare function createOptimizeNode(id: string, {
220
220
  retryDelay?: number;
221
221
  exponentialBackoff?: boolean;
222
222
  };
223
- circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
223
+ circuitBreaker?: _uploadista_core5.FlowCircuitBreakerConfig;
224
224
  } & {
225
- type: _uploadista_core0.NodeType;
226
- }, UploadistaError$1, ImagePlugin | _uploadista_core0.UploadServer>;
225
+ type: _uploadista_core5.NodeType;
226
+ }, UploadistaError$1, _uploadista_core5.UploadEngine | ImagePlugin>;
227
227
  //#endregion
228
228
  //#region src/remove-background-node.d.ts
229
229
  /**
@@ -251,8 +251,8 @@ declare function createRemoveBackgroundNode(id: string, {
251
251
  credentialId?: string;
252
252
  keepOutput?: boolean;
253
253
  naming?: FileNamingConfig;
254
- }): Effect.Effect<_uploadista_core0.FlowNodeData & {
255
- inputSchema: zod0.ZodType<{
254
+ }): Effect.Effect<_uploadista_core5.FlowNodeData & {
255
+ inputSchema: zod1.ZodType<{
256
256
  id: string;
257
257
  offset: number;
258
258
  storage: {
@@ -284,7 +284,7 @@ declare function createRemoveBackgroundNode(id: string, {
284
284
  spanId: string;
285
285
  traceFlags: number;
286
286
  } | undefined;
287
- }, unknown, zod_v4_core0.$ZodTypeInternals<{
287
+ }, unknown, zod_v4_core1.$ZodTypeInternals<{
288
288
  id: string;
289
289
  offset: number;
290
290
  storage: {
@@ -317,7 +317,7 @@ declare function createRemoveBackgroundNode(id: string, {
317
317
  traceFlags: number;
318
318
  } | undefined;
319
319
  }, unknown>>;
320
- outputSchema: zod0.ZodType<_uploadista_core0.UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<_uploadista_core0.UploadFile, unknown>>;
320
+ outputSchema: zod1.ZodType<_uploadista_core5.UploadFile, unknown, zod_v4_core1.$ZodTypeInternals<_uploadista_core5.UploadFile, unknown>>;
321
321
  run: (args: {
322
322
  data: {
323
323
  id: string;
@@ -357,7 +357,7 @@ declare function createRemoveBackgroundNode(id: string, {
357
357
  flowId: string;
358
358
  inputs?: Record<string, unknown>;
359
359
  clientId: string | null;
360
- }) => Effect.Effect<_uploadista_core0.NodeExecutionResult<_uploadista_core0.UploadFile>, UploadistaError, never>;
360
+ }) => Effect.Effect<_uploadista_core5.NodeExecutionResult<_uploadista_core5.UploadFile>, UploadistaError, never>;
361
361
  condition?: {
362
362
  field: string;
363
363
  operator: string;
@@ -371,10 +371,10 @@ declare function createRemoveBackgroundNode(id: string, {
371
371
  retryDelay?: number;
372
372
  exponentialBackoff?: boolean;
373
373
  };
374
- circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
374
+ circuitBreaker?: _uploadista_core5.FlowCircuitBreakerConfig;
375
375
  } & {
376
376
  type: NodeType.process;
377
- }, UploadistaError, ImageAiPlugin | UploadServer>;
377
+ }, UploadistaError, UploadEngine | ImageAiPlugin>;
378
378
  //#endregion
379
379
  //#region src/resize-node.d.ts
380
380
  /**
@@ -421,17 +421,17 @@ declare function createResizeNode(id: string, {
421
421
  naming?: FileNamingConfig;
422
422
  mode?: TransformMode;
423
423
  streamingConfig?: StreamingConfig;
424
- }): Effect.Effect<_uploadista_core0.FlowNodeData & {
425
- inputSchema: zod0.ZodType<_uploadista_core0.UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<_uploadista_core0.UploadFile, unknown>>;
426
- outputSchema: zod0.ZodType<_uploadista_core0.UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<_uploadista_core0.UploadFile, unknown>>;
424
+ }): Effect.Effect<_uploadista_core5.FlowNodeData & {
425
+ inputSchema: zod1.ZodType<_uploadista_core5.UploadFile, unknown, zod_v4_core1.$ZodTypeInternals<_uploadista_core5.UploadFile, unknown>>;
426
+ outputSchema: zod1.ZodType<_uploadista_core5.UploadFile, unknown, zod_v4_core1.$ZodTypeInternals<_uploadista_core5.UploadFile, unknown>>;
427
427
  run: (args: {
428
- data: _uploadista_core0.UploadFile;
428
+ data: _uploadista_core5.UploadFile;
429
429
  jobId: string;
430
430
  storageId: string;
431
431
  flowId: string;
432
432
  inputs?: Record<string, unknown>;
433
433
  clientId: string | null;
434
- }) => Effect.Effect<_uploadista_core0.NodeExecutionResult<_uploadista_core0.UploadFile>, _uploadista_core0.UploadistaError, never>;
434
+ }) => Effect.Effect<_uploadista_core5.NodeExecutionResult<_uploadista_core5.UploadFile>, _uploadista_core5.UploadistaError, never>;
435
435
  condition?: {
436
436
  field: string;
437
437
  operator: string;
@@ -445,10 +445,10 @@ declare function createResizeNode(id: string, {
445
445
  retryDelay?: number;
446
446
  exponentialBackoff?: boolean;
447
447
  };
448
- circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
448
+ circuitBreaker?: _uploadista_core5.FlowCircuitBreakerConfig;
449
449
  } & {
450
- type: _uploadista_core0.NodeType;
451
- }, _uploadista_core0.UploadistaError, ImagePlugin | _uploadista_core0.UploadServer>;
450
+ type: _uploadista_core5.NodeType;
451
+ }, _uploadista_core5.UploadistaError, _uploadista_core5.UploadEngine | ImagePlugin>;
452
452
  //#endregion
453
453
  //#region src/transform-image-node.d.ts
454
454
  /**
@@ -520,17 +520,17 @@ declare function createTransformImageNode(id: string, {
520
520
  naming?: FileNamingConfig;
521
521
  mode?: TransformMode;
522
522
  streamingConfig?: StreamingConfig;
523
- }): Effect.Effect<_uploadista_core0.FlowNodeData & {
524
- inputSchema: zod0.ZodType<_uploadista_core0.UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<_uploadista_core0.UploadFile, unknown>>;
525
- outputSchema: zod0.ZodType<_uploadista_core0.UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<_uploadista_core0.UploadFile, unknown>>;
523
+ }): Effect.Effect<_uploadista_core5.FlowNodeData & {
524
+ inputSchema: zod1.ZodType<_uploadista_core5.UploadFile, unknown, zod_v4_core1.$ZodTypeInternals<_uploadista_core5.UploadFile, unknown>>;
525
+ outputSchema: zod1.ZodType<_uploadista_core5.UploadFile, unknown, zod_v4_core1.$ZodTypeInternals<_uploadista_core5.UploadFile, unknown>>;
526
526
  run: (args: {
527
- data: _uploadista_core0.UploadFile;
527
+ data: _uploadista_core5.UploadFile;
528
528
  jobId: string;
529
529
  storageId: string;
530
530
  flowId: string;
531
531
  inputs?: Record<string, unknown>;
532
532
  clientId: string | null;
533
- }) => Effect.Effect<_uploadista_core0.NodeExecutionResult<_uploadista_core0.UploadFile>, UploadistaError, never>;
533
+ }) => Effect.Effect<_uploadista_core5.NodeExecutionResult<_uploadista_core5.UploadFile>, UploadistaError, never>;
534
534
  condition?: {
535
535
  field: string;
536
536
  operator: string;
@@ -544,10 +544,10 @@ declare function createTransformImageNode(id: string, {
544
544
  retryDelay?: number;
545
545
  exponentialBackoff?: boolean;
546
546
  };
547
- circuitBreaker?: _uploadista_core0.FlowCircuitBreakerConfig;
547
+ circuitBreaker?: _uploadista_core5.FlowCircuitBreakerConfig;
548
548
  } & {
549
- type: _uploadista_core0.NodeType;
550
- }, UploadistaError, ImagePlugin | _uploadista_core0.UploadServer>;
549
+ type: _uploadista_core5.NodeType;
550
+ }, UploadistaError, _uploadista_core5.UploadEngine | ImagePlugin>;
551
551
  //#endregion
552
552
  //#region src/wait-for-url.d.ts
553
553
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-node.ts","../src/transform-image-node.ts","../src/wait-for-url.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-node.ts","../src/transform-image-node.ts","../src/wait-for-url.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{UploadistaError as e}from"@uploadista/core/errors";import{IMAGE_DESCRIPTION_OUTPUT_TYPE_ID as t,ImageAiPlugin as n,ImagePlugin as r,NodeType as i,STORAGE_OUTPUT_TYPE_ID as a,applyFileNaming as o,buildNamingContext as s,completeNodeExecution as c,createFlowNode as l,createTransformNode as u,getBaseName as d,imageDescriptionOutputSchema as f,resolveUploadMetadata as p}from"@uploadista/core/flow";import{uploadFileSchema as m}from"@uploadista/core/types";import{Effect as h,Stream as g}from"effect";import{UploadistaError as _}from"@uploadista/core";import{UploadServer as v}from"@uploadista/core/upload";function y(t,n={}){let{maxWaitTime:r=1e4,retryDelay:i=500}=n;return h.gen(function*(){let n=Date.now();for(;Date.now()-n<r;){let e=yield*h.tryPromise(()=>fetch(t,{method:`HEAD`})).pipe(h.catchAll(()=>h.succeed(null)));if(e?.ok){yield*h.logInfo(`URL ${t} is now available`);return}e?yield*h.logDebug(`URL not ready yet (${e.status}), retrying...`):yield*h.logDebug(`URL check failed, retrying...`),yield*h.sleep(i)}return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL ${t} not available after ${r}ms`}).toEffect()})}function b(r,{credentialId:a,keepOutput:o}={}){return h.gen(function*(){let s=yield*n;return yield*l({id:r,name:`Describe Image`,description:`Describes the image using AI`,type:i.process,nodeTypeId:`describe-image`,outputTypeId:t,keepOutput:o,inputSchema:m,outputSchema:f,circuitBreaker:{enabled:!0,failureThreshold:5,resetTimeout:6e4,fallback:{type:`skip`,passThrough:!0}},run:({data:t,flowId:n,jobId:i,clientId:o})=>h.gen(function*(){let l={flowId:n,nodeId:r,jobId:i},u=t.url;if(!u)return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for describe image operation`}).toEffect();yield*h.logInfo(`Describing image for file ${t.id} at URL: ${u}`),yield*y(u);let d={clientId:o,credentialId:a},f=yield*s.describeImage(u,d).pipe(h.catchAll(t=>h.gen(function*(){return yield*h.logError(`Failed to describe image`,t),yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to describe image`}).toEffect()})));return yield*h.logInfo(`Successfully described image for file ${t.id}`),c({description:f.description,flow:l})})})})}const x={jpeg:`image/jpeg`,webp:`image/webp`,png:`image/png`,avif:`image/avif`},S={jpeg:`jpg`,webp:`webp`,png:`png`,avif:`avif`};function C(e,{quality:t,format:n},i){return h.gen(function*(){let c=yield*r,l=c.supportsStreaming??!1,f=i?.mode??`buffered`,p=f===`buffered`?`buffered`:l?f:`buffered`,m=r=>{let a=x[n],c=S[n],l=r.metadata?.fileName,u;if(l&&typeof l==`string`)if(i?.naming){let a={...i.naming,autoSuffix:i.naming.autoSuffix??(e=>e.format??n)};u=`${d(o(r,s(r,{flowId:r.flow?.flowId??``,jobId:r.flow?.jobId??``,nodeId:e,nodeType:`optimize`},{format:n,quality:t}),a))}.${c}`}else u=l.replace(/\.[^.]+$/,`.${c}`);return{newType:a,newFileName:u}};return yield*u({id:e,name:`Optimize`,description:`Optimizes an image for web delivery`,nodeTypeId:`optimize-image`,outputTypeId:a,keepOutput:i?.keepOutput,nodeType:`optimize`,namingVars:{format:n,quality:t},mode:p,streamingConfig:i?.streamingConfig,transform:(e,r)=>h.map(c.optimize(e,{quality:t,format:n}),e=>{let{newType:t,newFileName:n}=m(r);return{bytes:e,type:t,fileName:n}}),streamingTransform:c.optimizeStream?(e,r)=>{let i=c.optimizeStream;if(!i)throw _.fromCode(`UNKNOWN_ERROR`);return h.gen(function*(){let a=yield*i(e,{quality:t,format:n}),{newType:o,newFileName:s}=m(r);return{stream:a,type:o,fileName:s}})}:void 0})})}function w(t,{credentialId:r,keepOutput:u,naming:d}={}){return h.gen(function*(){let f=yield*n,g=yield*v;return yield*l({id:t,name:`Remove Background`,description:`Removes the background from an image`,type:i.process,nodeTypeId:`remove-background`,outputTypeId:a,keepOutput:u,inputSchema:m,outputSchema:m,circuitBreaker:{enabled:!0,failureThreshold:5,resetTimeout:6e4,fallback:{type:`skip`,passThrough:!0}},run:({data:n,flowId:i,jobId:a,storageId:l,clientId:u})=>h.gen(function*(){let m={flowId:i,nodeId:t,jobId:a},_=n.url;if(!_)return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for remove background operation`}).toEffect();yield*h.logInfo(`Removing background for file ${n.id} at URL: ${n.url}`),yield*y(_);let v={clientId:u,credentialId:r},{outputUrl:b}=yield*f.removeBackground(_,v).pipe(h.catchAll(t=>h.gen(function*(){return yield*h.logError(`Failed to remove background`,t),yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to remove background from image`}).toEffect()}))),{type:x,fileName:S,metadata:C,metadataJson:w}=p(n.metadata),T=S;if(d){let e={...d,autoSuffix:d.autoSuffix??(()=>`nobg`)};T=o(n,s(n,{flowId:i,jobId:a,nodeId:t,nodeType:`remove-background`}),e)}yield*h.logInfo(`Uploading processed file to storage`);let E=yield*g.uploadFromUrl({storageId:l,size:0,type:x,fileName:T,lastModified:0,metadata:w,flow:m},u,b).pipe(h.catchAll(t=>h.gen(function*(){return yield*h.logError(`Failed to upload processed file`,t),yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to upload processed file`}).toEffect()})));yield*h.logInfo(`Successfully removed background for file ${n.id}`);let D=C?{...C,...T!==S&&{fileName:T,originalName:T,name:T,extension:T.split(`.`).pop()||C.extension}}:E.metadata;return c(D?{...E,metadata:D}:E)})})})}function T(e,{width:t,height:n,fit:i},o){return h.gen(function*(){let s=yield*r,c=s.supportsStreaming??!1,l=o?.mode??`auto`,d=l===`buffered`?`buffered`:c?l:`buffered`,f=o?.naming?{...o.naming,autoSuffix:o.naming.autoSuffix??(e=>`${e.width??t}x${e.height??n}`)}:void 0;return yield*u({id:e,name:`Resize`,description:`Resizes an image to the specified dimensions`,nodeTypeId:`resize-image`,outputTypeId:a,keepOutput:o?.keepOutput,naming:f,nodeType:`resize`,namingVars:{width:t,height:n},mode:d,streamingConfig:o?.streamingConfig,transform:e=>s.resize(e,{height:n,width:t,fit:i}),streamingTransform:s.resizeStream?e=>h.gen(function*(){let r=s.resizeStream;if(!r)throw Error(`resizeStream not available`);return{stream:yield*r(e,{width:t,height:n,fit:i})}}):void 0})})}function E(e,t,n){return h.reduce(n,t,(t,n)=>e.transform(t,n))}function D(e,t,n){let r=e.transformStream;return r?h.reduce(n,t,(e,t)=>h.flatMap(r(e,t),e=>h.succeed(e))):h.gen(function*(){let r=[];yield*g.runForEach(t,e=>h.sync(()=>{r.push(e)}));let i=r.reduce((e,t)=>e+t.byteLength,0),a=new Uint8Array(i),o=0;for(let e of r)a.set(e,o),o+=e.byteLength;let s=yield*E(e,a,n);return g.make(s)})}function O(e,{transformations:t},n){return h.gen(function*(){let i=yield*r,o=i.supportsStreaming??!1,s=n?.mode??`auto`,c=t.some(e=>e.type===`watermark`||e.type===`logo`||e.type===`text`),l=s===`buffered`?`buffered`:o&&!c?s:`buffered`,d=n?.naming?{...n.naming,autoSuffix:n.naming.autoSuffix??(()=>`transformed`)}:void 0;return yield*u({id:e,name:`Transform Image`,description:`Apply ${t.length} transformation${t.length===1?``:`s`} to the image`,nodeTypeId:`transform-image`,outputTypeId:a,keepOutput:n?.keepOutput,naming:d,nodeType:`transform-image`,mode:l,streamingConfig:n?.streamingConfig,transform:e=>E(i,e,t),streamingTransform:o&&!c?e=>h.gen(function*(){return{stream:yield*D(i,e,t)}}):void 0})})}export{b as createDescribeImageNode,C as createOptimizeNode,w as createRemoveBackgroundNode,T as createResizeNode,O as createTransformImageNode,y as waitForUrlAvailability};
1
+ import{UploadistaError as e}from"@uploadista/core/errors";import{IMAGE_DESCRIPTION_OUTPUT_TYPE_ID as t,ImageAiPlugin as n,ImagePlugin as r,NodeType as i,STORAGE_OUTPUT_TYPE_ID as a,applyFileNaming as o,buildNamingContext as s,completeNodeExecution as c,createFlowNode as l,createTransformNode as u,getBaseName as d,imageDescriptionOutputSchema as f,resolveUploadMetadata as p}from"@uploadista/core/flow";import{uploadFileSchema as m}from"@uploadista/core/types";import{Effect as h,Stream as g}from"effect";import{UploadistaError as _}from"@uploadista/core";import{UploadEngine as v}from"@uploadista/core/upload";function y(t,n={}){let{maxWaitTime:r=1e4,retryDelay:i=500}=n;return h.gen(function*(){let n=Date.now();for(;Date.now()-n<r;){let e=yield*h.tryPromise(()=>fetch(t,{method:`HEAD`})).pipe(h.catchAll(()=>h.succeed(null)));if(e?.ok){yield*h.logInfo(`URL ${t} is now available`);return}e?yield*h.logDebug(`URL not ready yet (${e.status}), retrying...`):yield*h.logDebug(`URL check failed, retrying...`),yield*h.sleep(i)}return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL ${t} not available after ${r}ms`}).toEffect()})}function b(r,{credentialId:a,keepOutput:o}={}){return h.gen(function*(){let s=yield*n;return yield*l({id:r,name:`Describe Image`,description:`Describes the image using AI`,type:i.process,nodeTypeId:`describe-image`,outputTypeId:t,keepOutput:o,inputSchema:m,outputSchema:f,circuitBreaker:{enabled:!0,failureThreshold:5,resetTimeout:6e4,fallback:{type:`skip`,passThrough:!0}},run:({data:t,flowId:n,jobId:i,clientId:o})=>h.gen(function*(){let l={flowId:n,nodeId:r,jobId:i},u=t.url;if(!u)return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for describe image operation`}).toEffect();yield*h.logInfo(`Describing image for file ${t.id} at URL: ${u}`),yield*y(u);let d={clientId:o,credentialId:a},f=yield*s.describeImage(u,d).pipe(h.catchAll(t=>h.gen(function*(){return yield*h.logError(`Failed to describe image`,t),yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to describe image`}).toEffect()})));return yield*h.logInfo(`Successfully described image for file ${t.id}`),c({description:f.description,flow:l})})})})}const x={jpeg:`image/jpeg`,webp:`image/webp`,png:`image/png`,avif:`image/avif`},S={jpeg:`jpg`,webp:`webp`,png:`png`,avif:`avif`};function C(e,{quality:t,format:n},i){return h.gen(function*(){let c=yield*r,l=c.supportsStreaming??!1,f=i?.mode??`buffered`,p=f===`buffered`?`buffered`:l?f:`buffered`,m=r=>{let a=x[n],c=S[n],l=r.metadata?.fileName,u;if(l&&typeof l==`string`)if(i?.naming){let a={...i.naming,autoSuffix:i.naming.autoSuffix??(e=>e.format??n)};u=`${d(o(r,s(r,{flowId:r.flow?.flowId??``,jobId:r.flow?.jobId??``,nodeId:e,nodeType:`optimize`},{format:n,quality:t}),a))}.${c}`}else u=l.replace(/\.[^.]+$/,`.${c}`);return{newType:a,newFileName:u}};return yield*u({id:e,name:`Optimize`,description:`Optimizes an image for web delivery`,nodeTypeId:`optimize-image`,outputTypeId:a,keepOutput:i?.keepOutput,nodeType:`optimize`,namingVars:{format:n,quality:t},mode:p,streamingConfig:i?.streamingConfig,transform:(e,r)=>h.map(c.optimize(e,{quality:t,format:n}),e=>{let{newType:t,newFileName:n}=m(r);return{bytes:e,type:t,fileName:n}}),streamingTransform:c.optimizeStream?(e,r)=>{let i=c.optimizeStream;if(!i)throw _.fromCode(`UNKNOWN_ERROR`);return h.gen(function*(){let a=yield*i(e,{quality:t,format:n}),{newType:o,newFileName:s}=m(r);return{stream:a,type:o,fileName:s}})}:void 0})})}function w(t,{credentialId:r,keepOutput:u,naming:d}={}){return h.gen(function*(){let f=yield*n,g=yield*v;return yield*l({id:t,name:`Remove Background`,description:`Removes the background from an image`,type:i.process,nodeTypeId:`remove-background`,outputTypeId:a,keepOutput:u,inputSchema:m,outputSchema:m,circuitBreaker:{enabled:!0,failureThreshold:5,resetTimeout:6e4,fallback:{type:`skip`,passThrough:!0}},run:({data:n,flowId:i,jobId:a,storageId:l,clientId:u})=>h.gen(function*(){let m={flowId:i,nodeId:t,jobId:a},_=n.url;if(!_)return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for remove background operation`}).toEffect();yield*h.logInfo(`Removing background for file ${n.id} at URL: ${n.url}`),yield*y(_);let v={clientId:u,credentialId:r},{outputUrl:b}=yield*f.removeBackground(_,v).pipe(h.catchAll(t=>h.gen(function*(){return yield*h.logError(`Failed to remove background`,t),yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to remove background from image`}).toEffect()}))),{type:x,fileName:S,metadata:C,metadataJson:w}=p(n.metadata),T=S;if(d){let e={...d,autoSuffix:d.autoSuffix??(()=>`nobg`)};T=o(n,s(n,{flowId:i,jobId:a,nodeId:t,nodeType:`remove-background`}),e)}yield*h.logInfo(`Uploading processed file to storage`);let E=yield*g.uploadFromUrl({storageId:l,size:0,type:x,fileName:T,lastModified:0,metadata:w,flow:m},u,b).pipe(h.catchAll(t=>h.gen(function*(){return yield*h.logError(`Failed to upload processed file`,t),yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to upload processed file`}).toEffect()})));yield*h.logInfo(`Successfully removed background for file ${n.id}`);let D=C?{...C,...T!==S&&{fileName:T,originalName:T,name:T,extension:T.split(`.`).pop()||C.extension}}:E.metadata;return c(D?{...E,metadata:D}:E)})})})}function T(e,{width:t,height:n,fit:i},o){return h.gen(function*(){let s=yield*r,c=s.supportsStreaming??!1,l=o?.mode??`auto`,d=l===`buffered`?`buffered`:c?l:`buffered`,f=o?.naming?{...o.naming,autoSuffix:o.naming.autoSuffix??(e=>`${e.width??t}x${e.height??n}`)}:void 0;return yield*u({id:e,name:`Resize`,description:`Resizes an image to the specified dimensions`,nodeTypeId:`resize-image`,outputTypeId:a,keepOutput:o?.keepOutput,naming:f,nodeType:`resize`,namingVars:{width:t,height:n},mode:d,streamingConfig:o?.streamingConfig,transform:e=>s.resize(e,{height:n,width:t,fit:i}),streamingTransform:s.resizeStream?e=>h.gen(function*(){let r=s.resizeStream;if(!r)throw Error(`resizeStream not available`);return{stream:yield*r(e,{width:t,height:n,fit:i})}}):void 0})})}function E(e,t,n){return h.reduce(n,t,(t,n)=>e.transform(t,n))}function D(e,t,n){let r=e.transformStream;return r?h.reduce(n,t,(e,t)=>h.flatMap(r(e,t),e=>h.succeed(e))):h.gen(function*(){let r=[];yield*g.runForEach(t,e=>h.sync(()=>{r.push(e)}));let i=r.reduce((e,t)=>e+t.byteLength,0),a=new Uint8Array(i),o=0;for(let e of r)a.set(e,o),o+=e.byteLength;let s=yield*E(e,a,n);return g.make(s)})}function O(e,{transformations:t},n){return h.gen(function*(){let i=yield*r,o=i.supportsStreaming??!1,s=n?.mode??`auto`,c=t.some(e=>e.type===`watermark`||e.type===`logo`||e.type===`text`),l=s===`buffered`?`buffered`:o&&!c?s:`buffered`,d=n?.naming?{...n.naming,autoSuffix:n.naming.autoSuffix??(()=>`transformed`)}:void 0;return yield*u({id:e,name:`Transform Image`,description:`Apply ${t.length} transformation${t.length===1?``:`s`} to the image`,nodeTypeId:`transform-image`,outputTypeId:a,keepOutput:n?.keepOutput,naming:d,nodeType:`transform-image`,mode:l,streamingConfig:n?.streamingConfig,transform:e=>E(i,e,t),streamingTransform:o&&!c?e=>h.gen(function*(){return{stream:yield*D(i,e,t)}}):void 0})})}export{b as createDescribeImageNode,C as createOptimizeNode,w as createRemoveBackgroundNode,T as createResizeNode,O as createTransformImageNode,y as waitForUrlAvailability};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["formatToMimeType: Record<OptimizeParams[\"format\"], string>","formatToExtension: Record<OptimizeParams[\"format\"], string>","effectiveMode: TransformMode","newFileName: string | undefined","namingConfig: FileNamingConfig","UploadistaError","namingConfig: FileNamingConfig","effectiveMode: TransformMode","namingConfig: FileNamingConfig | undefined","chunks: Uint8Array[]","effectiveMode: TransformMode","namingConfig: FileNamingConfig | undefined"],"sources":["../src/wait-for-url.ts","../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-node.ts","../src/transform-image-node.ts"],"sourcesContent":["import { UploadistaError } from \"@uploadista/core/errors\";\nimport { Effect } from \"effect\";\n\n/**\n * Waits for a URL to become available by periodically checking its accessibility.\n * This is useful when a file has just been uploaded and may not be immediately\n * accessible due to CDN propagation or storage consistency delays.\n *\n * @param url - The URL to check for availability\n * @param options - Configuration options\n * @param options.maxWaitTime - Maximum time to wait in milliseconds (default: 10000)\n * @param options.retryDelay - Delay between retries in milliseconds (default: 500)\n * @returns Effect that succeeds when URL is available or fails with UploadistaError\n */\nexport function waitForUrlAvailability(\n url: string,\n options: {\n maxWaitTime?: number;\n retryDelay?: number;\n } = {},\n): Effect.Effect<void, UploadistaError> {\n const { maxWaitTime = 10000, retryDelay = 500 } = options;\n\n return Effect.gen(function* () {\n const startTime = Date.now();\n\n while (Date.now() - startTime < maxWaitTime) {\n const response = yield* Effect.tryPromise(() =>\n fetch(url, { method: \"HEAD\" }),\n ).pipe(Effect.catchAll(() => Effect.succeed(null)));\n\n if (response?.ok) {\n yield* Effect.logInfo(`URL ${url} is now available`);\n return;\n }\n\n if (response) {\n yield* Effect.logDebug(\n `URL not ready yet (${response.status}), retrying...`,\n );\n } else {\n yield* Effect.logDebug(`URL check failed, retrying...`);\n }\n\n yield* Effect.sleep(retryDelay);\n }\n\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause: `URL ${url} not available after ${maxWaitTime}ms`,\n }).toEffect();\n });\n}\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport {\n completeNodeExecution,\n createFlowNode,\n IMAGE_DESCRIPTION_OUTPUT_TYPE_ID,\n ImageAiPlugin,\n imageDescriptionOutputSchema,\n NodeType,\n} from \"@uploadista/core/flow\";\nimport { uploadFileSchema } from \"@uploadista/core/types\";\n\nimport { Effect } from \"effect\";\nimport { waitForUrlAvailability } from \"./wait-for-url\";\n\nexport function createDescribeImageNode(\n id: string,\n { credentialId, keepOutput }: { credentialId?: string; keepOutput?: boolean } = {},\n) {\n return Effect.gen(function* () {\n const imageAiService = yield* ImageAiPlugin;\n\n return yield* createFlowNode({\n id,\n name: \"Describe Image\",\n description: \"Describes the image using AI\",\n type: NodeType.process,\n nodeTypeId: \"describe-image\",\n outputTypeId: IMAGE_DESCRIPTION_OUTPUT_TYPE_ID,\n keepOutput,\n inputSchema: uploadFileSchema,\n outputSchema: imageDescriptionOutputSchema,\n // AI service - enable circuit breaker with skip fallback\n circuitBreaker: {\n enabled: true,\n failureThreshold: 5,\n resetTimeout: 60000,\n fallback: { type: \"skip\", passThrough: true },\n },\n run: ({ data: file, flowId, jobId, clientId }) => {\n return Effect.gen(function* () {\n const flow = {\n flowId,\n nodeId: id,\n jobId,\n };\n\n const fileUrl = file.url;\n\n // Validate input\n if (!fileUrl) {\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause: \"URL is required for describe image operation\",\n }).toEffect();\n }\n\n yield* Effect.logInfo(\n `Describing image for file ${file.id} at URL: ${fileUrl}`,\n );\n\n // Wait for URL to be available with retry mechanism\n yield* waitForUrlAvailability(fileUrl);\n\n // Build context for ImageAI plugin\n const context = {\n clientId,\n credentialId,\n };\n\n // Describe image with error handling\n const result = yield* imageAiService\n .describeImage(fileUrl, context)\n .pipe(\n Effect.catchAll((error) =>\n Effect.gen(function* () {\n yield* Effect.logError(\"Failed to describe image\", error);\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause:\n error instanceof Error\n ? error.message\n : \"Failed to describe image\",\n }).toEffect();\n }),\n ),\n );\n\n yield* Effect.logInfo(\n `Successfully described image for file ${file.id}`,\n );\n\n // Return structured image description output (not UploadFile)\n return completeNodeExecution({\n description: result.description,\n flow,\n });\n });\n },\n });\n });\n}\n","import { UploadistaError } from \"@uploadista/core\";\nimport {\n applyFileNaming,\n buildNamingContext,\n createTransformNode,\n type FileNamingConfig,\n getBaseName,\n ImagePlugin,\n type OptimizeParams,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformMode,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n// Map image format to MIME type\nconst formatToMimeType: Record<OptimizeParams[\"format\"], string> = {\n jpeg: \"image/jpeg\",\n webp: \"image/webp\",\n png: \"image/png\",\n avif: \"image/avif\",\n};\n\n// Map image format to file extension\nconst formatToExtension: Record<OptimizeParams[\"format\"], string> = {\n jpeg: \"jpg\",\n webp: \"webp\",\n png: \"png\",\n avif: \"avif\",\n};\n\n/**\n * Creates an optimize node that optimizes images for web delivery.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large images. In streaming mode, the image is read and processed\n * incrementally, reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Optimize parameters (quality, format)\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `${format}`)\n * @param options.mode - Transform mode: \"buffered\" (default), \"streaming\", or \"auto\"\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Buffered mode (default) - \"photo.jpg\" -> \"photo-webp.webp\"\n * const optimize = yield* createOptimizeNode(\"opt-1\", { quality: 80, format: \"webp\" }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Streaming mode for large files\n * const optimizeStreaming = yield* createOptimizeNode(\"opt-2\", { quality: 80, format: \"webp\" }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Auto mode - uses streaming for files > 1MB\n * const optimizeAuto = yield* createOptimizeNode(\"opt-3\", { quality: 80, format: \"webp\" }, {\n * mode: \"auto\",\n * streamingConfig: { fileSizeThreshold: 1_048_576 },\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createOptimizeNode(\n id: string,\n { quality, format }: OptimizeParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = imageService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"buffered\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Helper to build output metadata from optimized result\n const buildOutputMetadata = (file: {\n metadata?: Record<string, unknown>;\n flow?: { flowId?: string; jobId?: string };\n }) => {\n const newType = formatToMimeType[format];\n const newExtension = formatToExtension[format];\n\n // Get original fileName\n const fileName = file.metadata?.fileName;\n let newFileName: string | undefined;\n\n if (fileName && typeof fileName === \"string\") {\n // Apply naming if configured\n if (options?.naming) {\n const namingConfig: FileNamingConfig = {\n ...options.naming,\n autoSuffix:\n options.naming.autoSuffix ?? ((ctx) => ctx.format ?? format),\n };\n const namingContext = buildNamingContext(\n file as Parameters<typeof buildNamingContext>[0],\n {\n flowId: file.flow?.flowId ?? \"\",\n jobId: file.flow?.jobId ?? \"\",\n nodeId: id,\n nodeType: \"optimize\",\n },\n { format, quality },\n );\n // Apply naming to get base name with suffix\n const namedFile = applyFileNaming(\n file as Parameters<typeof applyFileNaming>[0],\n namingContext,\n namingConfig,\n );\n // Replace extension with new format extension\n newFileName = `${getBaseName(namedFile)}.${newExtension}`;\n } else {\n // No naming config, just update extension\n newFileName = fileName.replace(/\\.[^.]+$/, `.${newExtension}`);\n }\n }\n\n return { newType, newFileName };\n };\n\n return yield* createTransformNode({\n id,\n name: \"Optimize\",\n description: \"Optimizes an image for web delivery\",\n nodeTypeId: \"optimize-image\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n // Note: naming is handled in transform since format changes extension\n nodeType: \"optimize\",\n namingVars: { format, quality },\n mode: effectiveMode,\n streamingConfig: options?.streamingConfig,\n // Buffered transform (used when mode is \"buffered\" or \"auto\" selects buffered)\n transform: (inputBytes, file) =>\n Effect.map(\n imageService.optimize(inputBytes, { quality, format }),\n (optimizedBytes) => {\n const { newType, newFileName } = buildOutputMetadata(file);\n return {\n bytes: optimizedBytes,\n type: newType,\n fileName: newFileName,\n } as\n | Uint8Array\n | { bytes: Uint8Array; type: string; fileName?: string };\n },\n ),\n // Streaming transform (used when mode is \"streaming\" or \"auto\" selects streaming)\n streamingTransform: imageService.optimizeStream\n ? (inputStream, file) => {\n const optimizeStreamFn = imageService.optimizeStream;\n if (!optimizeStreamFn) {\n throw UploadistaError.fromCode(\"UNKNOWN_ERROR\");\n }\n return Effect.gen(function* () {\n // Use the streaming optimization\n const outputStream = yield* optimizeStreamFn(inputStream, {\n quality,\n format,\n });\n\n const { newType, newFileName } = buildOutputMetadata(file);\n\n return {\n stream: outputStream,\n type: newType,\n fileName: newFileName,\n };\n });\n }\n : undefined,\n });\n });\n}\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport {\n applyFileNaming,\n buildNamingContext,\n completeNodeExecution,\n createFlowNode,\n type FileNamingConfig,\n ImageAiPlugin,\n NodeType,\n resolveUploadMetadata,\n STORAGE_OUTPUT_TYPE_ID,\n} from \"@uploadista/core/flow\";\nimport { uploadFileSchema } from \"@uploadista/core/types\";\nimport { UploadServer } from \"@uploadista/core/upload\";\nimport { Effect } from \"effect\";\nimport { waitForUrlAvailability } from \"./wait-for-url\";\n\n/**\n * Creates a remove-background node that removes backgrounds from images using AI.\n *\n * @param id - Unique node identifier\n * @param options - Optional configuration\n * @param options.credentialId - Optional credential ID for AI service\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `nobg`)\n *\n * @example\n * ```typescript\n * // With auto-naming: \"photo.jpg\" -> \"photo-nobg.jpg\"\n * const node = yield* createRemoveBackgroundNode(\"remove-bg-1\", {\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createRemoveBackgroundNode(\n id: string,\n { credentialId, keepOutput, naming }: { credentialId?: string; keepOutput?: boolean; naming?: FileNamingConfig } = {},\n) {\n return Effect.gen(function* () {\n const imageAiService = yield* ImageAiPlugin;\n const uploadServer = yield* UploadServer;\n\n return yield* createFlowNode({\n id,\n name: \"Remove Background\",\n description: \"Removes the background from an image\",\n type: NodeType.process,\n nodeTypeId: \"remove-background\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput,\n inputSchema: uploadFileSchema,\n outputSchema: uploadFileSchema,\n // AI service - enable circuit breaker with skip fallback\n circuitBreaker: {\n enabled: true,\n failureThreshold: 5,\n resetTimeout: 60000,\n fallback: { type: \"skip\", passThrough: true },\n },\n run: ({ data: file, flowId, jobId, storageId, clientId }) => {\n return Effect.gen(function* () {\n const flow = {\n flowId,\n nodeId: id,\n jobId,\n };\n\n const fileUrl = file.url;\n\n // Validate input\n if (!fileUrl) {\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause: \"URL is required for remove background operation\",\n }).toEffect();\n }\n\n yield* Effect.logInfo(\n `Removing background for file ${file.id} at URL: ${file.url}`,\n );\n\n // Wait for URL to be available with retry mechanism\n yield* waitForUrlAvailability(fileUrl);\n\n // Build context for ImageAI plugin\n const context = {\n clientId,\n credentialId,\n };\n\n // Remove background with error handling\n const backgroundRemovalResult = yield* imageAiService\n .removeBackground(fileUrl, context)\n .pipe(\n Effect.catchAll((error) =>\n Effect.gen(function* () {\n yield* Effect.logError(\"Failed to remove background\", error);\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause:\n error instanceof Error\n ? error.message\n : \"Failed to remove background from image\",\n }).toEffect();\n }),\n ),\n );\n\n const { outputUrl } = backgroundRemovalResult;\n const { type, fileName, metadata, metadataJson } =\n resolveUploadMetadata(file.metadata);\n\n // Apply file naming if configured\n let outputFileName = fileName;\n if (naming) {\n const namingConfig: FileNamingConfig = {\n ...naming,\n autoSuffix: naming.autoSuffix ?? (() => \"nobg\"),\n };\n const namingContext = buildNamingContext(\n file,\n {\n flowId,\n jobId,\n nodeId: id,\n nodeType: \"remove-background\",\n },\n );\n outputFileName = applyFileNaming(file, namingContext, namingConfig);\n }\n\n yield* Effect.logInfo(`Uploading processed file to storage`);\n\n // Upload the transformed bytes back to the upload server with error handling\n const result = yield* uploadServer\n .uploadFromUrl(\n {\n storageId,\n size: 0,\n type,\n fileName: outputFileName,\n lastModified: 0,\n metadata: metadataJson,\n flow,\n },\n clientId,\n outputUrl,\n )\n .pipe(\n Effect.catchAll((error) =>\n Effect.gen(function* () {\n yield* Effect.logError(\n \"Failed to upload processed file\",\n error,\n );\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause:\n error instanceof Error\n ? error.message\n : \"Failed to upload processed file\",\n }).toEffect();\n }),\n ),\n );\n\n yield* Effect.logInfo(\n `Successfully removed background for file ${file.id}`,\n );\n\n // Update metadata with new filename if naming was applied\n const updatedMetadata = metadata\n ? {\n ...metadata,\n ...(outputFileName !== fileName && {\n fileName: outputFileName,\n originalName: outputFileName,\n name: outputFileName,\n extension: outputFileName.split(\".\").pop() || metadata.extension,\n }),\n }\n : result.metadata;\n\n return completeNodeExecution(\n updatedMetadata\n ? {\n ...result,\n metadata: updatedMetadata,\n }\n : result,\n );\n });\n },\n });\n });\n}\n","import {\n createTransformNode,\n type FileNamingConfig,\n ImagePlugin,\n type ResizeParams,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformMode,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n/**\n * Creates a resize node that resizes images to specified dimensions.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large images. In streaming mode, the image is read and processed\n * incrementally, reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Resize parameters (width, height, fit)\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `${width}x${height}`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 1MB, otherwise buffered\n * const resize = yield* createResizeNode(\"resize-1\", { width: 800, height: 600 }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const resizeBuffered = yield* createResizeNode(\"resize-2\", { width: 800, height: 600 }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const resizeStreaming = yield* createResizeNode(\"resize-3\", { width: 800, height: 600 }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createResizeNode(\n id: string,\n { width, height, fit }: ResizeParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = imageService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Build naming config with auto suffix for resize\n const namingConfig: FileNamingConfig | undefined = options?.naming\n ? {\n ...options.naming,\n // Provide default auto suffix generator for resize nodes\n autoSuffix:\n options.naming.autoSuffix ??\n ((ctx) => `${ctx.width ?? width}x${ctx.height ?? height}`),\n }\n : undefined;\n\n return yield* createTransformNode({\n id,\n name: \"Resize\",\n description: \"Resizes an image to the specified dimensions\",\n nodeTypeId: \"resize-image\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n naming: namingConfig,\n nodeType: \"resize\",\n namingVars: { width, height },\n mode: effectiveMode,\n streamingConfig: options?.streamingConfig,\n // Buffered transform (used when mode is \"buffered\" or \"auto\" selects buffered)\n transform: (inputBytes) =>\n imageService.resize(inputBytes, { height, width, fit }),\n // Streaming transform (used when mode is \"streaming\" or \"auto\" selects streaming)\n streamingTransform: imageService.resizeStream\n ? (inputStream) =>\n Effect.gen(function* () {\n const resizeStreamFn = imageService.resizeStream;\n if (!resizeStreamFn) {\n throw new Error(\"resizeStream not available\");\n }\n const outputStream = yield* resizeStreamFn(inputStream, {\n width,\n height,\n fit,\n });\n return { stream: outputStream };\n })\n : undefined,\n });\n });\n}\n","import {\n createTransformNode,\n type FileNamingConfig,\n ImagePlugin,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformImageParams,\n type TransformMode,\n} from \"@uploadista/core/flow\";\nimport type { UploadistaError } from \"@uploadista/core/errors\";\nimport { Effect, Stream } from \"effect\";\n\n/**\n * Apply a chain of transformations to an image by reducing over the transformations array.\n * Each transformation receives the output of the previous transformation as input.\n *\n * @param imageService - The image plugin service to use for transformations\n * @param inputBytes - The input image bytes\n * @param transformations - Array of transformations to apply in sequence\n * @returns Effect that resolves to the final transformed image bytes\n */\nfunction applyTransformationChain(\n imageService: ReturnType<typeof ImagePlugin.of>,\n inputBytes: Uint8Array,\n transformations: TransformImageParams[\"transformations\"],\n) {\n return Effect.reduce(transformations, inputBytes, (bytes, transformation) =>\n imageService.transform(bytes, transformation),\n );\n}\n\n/**\n * Apply a chain of transformations using streaming where possible.\n * Falls back to buffered processing for transformations that don't support streaming.\n *\n * @param imageService - The image plugin service to use for transformations\n * @param inputStream - The input image as a stream\n * @param transformations - Array of transformations to apply in sequence\n * @returns Effect that resolves to the final transformed image stream\n */\nfunction applyStreamingTransformationChain(\n imageService: ReturnType<typeof ImagePlugin.of>,\n inputStream: Stream.Stream<Uint8Array, UploadistaError>,\n transformations: TransformImageParams[\"transformations\"],\n): Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError> {\n const transformStreamFn = imageService.transformStream;\n\n if (!transformStreamFn) {\n // If streaming not supported, collect to buffer and use buffered chain\n return Effect.gen(function* () {\n // Collect stream to buffer\n const chunks: Uint8Array[] = [];\n yield* Stream.runForEach(inputStream, (chunk) =>\n Effect.sync(() => {\n chunks.push(chunk);\n }),\n );\n const totalLength = chunks.reduce((sum, c) => sum + c.byteLength, 0);\n const inputBuffer = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n inputBuffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n // Apply transformations\n const result = yield* applyTransformationChain(\n imageService,\n inputBuffer,\n transformations,\n );\n return Stream.make(result);\n });\n }\n\n // Apply each transformation in sequence using streaming\n return Effect.reduce(\n transformations,\n inputStream,\n (currentStream, transformation) =>\n Effect.flatMap(\n transformStreamFn(currentStream, transformation),\n (outputStream) => Effect.succeed(outputStream),\n ),\n );\n}\n\n/**\n * Creates a transform image node that applies multiple transformations sequentially.\n *\n * This node enables complex image processing workflows by chaining multiple transformations\n * together. Each transformation is applied to the output of the previous transformation,\n * allowing for powerful image manipulation pipelines.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large images. In streaming mode, each transformation is applied in sequence\n * using streaming where supported.\n *\n * Supported transformations include:\n * - Basic: resize, blur, rotate, flip\n * - Filters: grayscale, sepia, brightness, contrast\n * - Effects: sharpen\n * - Advanced: watermark, logo, text (streaming not supported for these)\n *\n * Note: Watermark and logo transformations require imagePath to be a valid URL.\n * Images will be fetched from the provided URL during transformation.\n * Streaming mode is not supported for watermark, logo, and text transformations;\n * these will cause fallback to buffered mode.\n *\n * @param id - Unique identifier for this node\n * @param params - Parameters including the transformations array\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `transformed`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 1MB, otherwise buffered\n * const node = yield* createTransformImageNode(\"transform-1\", {\n * transformations: [\n * { type: 'resize', width: 800, height: 600, fit: 'cover' },\n * { type: 'brightness', value: 20 }\n * ]\n * }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const nodeBuffered = yield* createTransformImageNode(\"transform-2\", {\n * transformations: [\n * { type: 'resize', width: 800, height: 600, fit: 'cover' },\n * { type: 'blur', sigma: 5 }\n * ]\n * }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const nodeStreaming = yield* createTransformImageNode(\"transform-3\", {\n * transformations: [{ type: 'grayscale' }]\n * }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createTransformImageNode(\n id: string,\n { transformations }: TransformImageParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = imageService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // Check if any transformations don't support streaming\n const hasUnsupportedTransformations = transformations.some(\n (t) => t.type === \"watermark\" || t.type === \"logo\" || t.type === \"text\",\n );\n\n // If streaming requested but not supported or unsupported transformations, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming && !hasUnsupportedTransformations\n ? requestedMode\n : \"buffered\";\n\n // Build naming config with auto suffix for transform-image\n const namingConfig: FileNamingConfig | undefined = options?.naming\n ? {\n ...options.naming,\n autoSuffix: options.naming.autoSuffix ?? (() => \"transformed\"),\n }\n : undefined;\n\n return yield* createTransformNode({\n id,\n name: \"Transform Image\",\n description: `Apply ${transformations.length} transformation${transformations.length === 1 ? \"\" : \"s\"} to the image`,\n nodeTypeId: \"transform-image\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n naming: namingConfig,\n nodeType: \"transform-image\",\n mode: effectiveMode,\n streamingConfig: options?.streamingConfig,\n // Buffered transform (used when mode is \"buffered\" or \"auto\" selects buffered)\n transform: (inputBytes) =>\n applyTransformationChain(imageService, inputBytes, transformations),\n // Streaming transform (used when mode is \"streaming\" or \"auto\" selects streaming)\n streamingTransform:\n supportsStreaming && !hasUnsupportedTransformations\n ? (inputStream) =>\n Effect.gen(function* () {\n const outputStream =\n yield* applyStreamingTransformationChain(\n imageService,\n inputStream,\n transformations,\n );\n return { stream: outputStream };\n })\n : undefined,\n });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["formatToMimeType: Record<OptimizeParams[\"format\"], string>","formatToExtension: Record<OptimizeParams[\"format\"], string>","effectiveMode: TransformMode","newFileName: string | undefined","namingConfig: FileNamingConfig","UploadistaError","namingConfig: FileNamingConfig","effectiveMode: TransformMode","namingConfig: FileNamingConfig | undefined","chunks: Uint8Array[]","effectiveMode: TransformMode","namingConfig: FileNamingConfig | undefined"],"sources":["../src/wait-for-url.ts","../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-node.ts","../src/transform-image-node.ts"],"sourcesContent":["import { UploadistaError } from \"@uploadista/core/errors\";\nimport { Effect } from \"effect\";\n\n/**\n * Waits for a URL to become available by periodically checking its accessibility.\n * This is useful when a file has just been uploaded and may not be immediately\n * accessible due to CDN propagation or storage consistency delays.\n *\n * @param url - The URL to check for availability\n * @param options - Configuration options\n * @param options.maxWaitTime - Maximum time to wait in milliseconds (default: 10000)\n * @param options.retryDelay - Delay between retries in milliseconds (default: 500)\n * @returns Effect that succeeds when URL is available or fails with UploadistaError\n */\nexport function waitForUrlAvailability(\n url: string,\n options: {\n maxWaitTime?: number;\n retryDelay?: number;\n } = {},\n): Effect.Effect<void, UploadistaError> {\n const { maxWaitTime = 10000, retryDelay = 500 } = options;\n\n return Effect.gen(function* () {\n const startTime = Date.now();\n\n while (Date.now() - startTime < maxWaitTime) {\n const response = yield* Effect.tryPromise(() =>\n fetch(url, { method: \"HEAD\" }),\n ).pipe(Effect.catchAll(() => Effect.succeed(null)));\n\n if (response?.ok) {\n yield* Effect.logInfo(`URL ${url} is now available`);\n return;\n }\n\n if (response) {\n yield* Effect.logDebug(\n `URL not ready yet (${response.status}), retrying...`,\n );\n } else {\n yield* Effect.logDebug(`URL check failed, retrying...`);\n }\n\n yield* Effect.sleep(retryDelay);\n }\n\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause: `URL ${url} not available after ${maxWaitTime}ms`,\n }).toEffect();\n });\n}\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport {\n completeNodeExecution,\n createFlowNode,\n IMAGE_DESCRIPTION_OUTPUT_TYPE_ID,\n ImageAiPlugin,\n imageDescriptionOutputSchema,\n NodeType,\n} from \"@uploadista/core/flow\";\nimport { uploadFileSchema } from \"@uploadista/core/types\";\n\nimport { Effect } from \"effect\";\nimport { waitForUrlAvailability } from \"./wait-for-url\";\n\nexport function createDescribeImageNode(\n id: string,\n { credentialId, keepOutput }: { credentialId?: string; keepOutput?: boolean } = {},\n) {\n return Effect.gen(function* () {\n const imageAiService = yield* ImageAiPlugin;\n\n return yield* createFlowNode({\n id,\n name: \"Describe Image\",\n description: \"Describes the image using AI\",\n type: NodeType.process,\n nodeTypeId: \"describe-image\",\n outputTypeId: IMAGE_DESCRIPTION_OUTPUT_TYPE_ID,\n keepOutput,\n inputSchema: uploadFileSchema,\n outputSchema: imageDescriptionOutputSchema,\n // AI service - enable circuit breaker with skip fallback\n circuitBreaker: {\n enabled: true,\n failureThreshold: 5,\n resetTimeout: 60000,\n fallback: { type: \"skip\", passThrough: true },\n },\n run: ({ data: file, flowId, jobId, clientId }) => {\n return Effect.gen(function* () {\n const flow = {\n flowId,\n nodeId: id,\n jobId,\n };\n\n const fileUrl = file.url;\n\n // Validate input\n if (!fileUrl) {\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause: \"URL is required for describe image operation\",\n }).toEffect();\n }\n\n yield* Effect.logInfo(\n `Describing image for file ${file.id} at URL: ${fileUrl}`,\n );\n\n // Wait for URL to be available with retry mechanism\n yield* waitForUrlAvailability(fileUrl);\n\n // Build context for ImageAI plugin\n const context = {\n clientId,\n credentialId,\n };\n\n // Describe image with error handling\n const result = yield* imageAiService\n .describeImage(fileUrl, context)\n .pipe(\n Effect.catchAll((error) =>\n Effect.gen(function* () {\n yield* Effect.logError(\"Failed to describe image\", error);\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause:\n error instanceof Error\n ? error.message\n : \"Failed to describe image\",\n }).toEffect();\n }),\n ),\n );\n\n yield* Effect.logInfo(\n `Successfully described image for file ${file.id}`,\n );\n\n // Return structured image description output (not UploadFile)\n return completeNodeExecution({\n description: result.description,\n flow,\n });\n });\n },\n });\n });\n}\n","import { UploadistaError } from \"@uploadista/core\";\nimport {\n applyFileNaming,\n buildNamingContext,\n createTransformNode,\n type FileNamingConfig,\n getBaseName,\n ImagePlugin,\n type OptimizeParams,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformMode,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n// Map image format to MIME type\nconst formatToMimeType: Record<OptimizeParams[\"format\"], string> = {\n jpeg: \"image/jpeg\",\n webp: \"image/webp\",\n png: \"image/png\",\n avif: \"image/avif\",\n};\n\n// Map image format to file extension\nconst formatToExtension: Record<OptimizeParams[\"format\"], string> = {\n jpeg: \"jpg\",\n webp: \"webp\",\n png: \"png\",\n avif: \"avif\",\n};\n\n/**\n * Creates an optimize node that optimizes images for web delivery.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large images. In streaming mode, the image is read and processed\n * incrementally, reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Optimize parameters (quality, format)\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `${format}`)\n * @param options.mode - Transform mode: \"buffered\" (default), \"streaming\", or \"auto\"\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Buffered mode (default) - \"photo.jpg\" -> \"photo-webp.webp\"\n * const optimize = yield* createOptimizeNode(\"opt-1\", { quality: 80, format: \"webp\" }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Streaming mode for large files\n * const optimizeStreaming = yield* createOptimizeNode(\"opt-2\", { quality: 80, format: \"webp\" }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Auto mode - uses streaming for files > 1MB\n * const optimizeAuto = yield* createOptimizeNode(\"opt-3\", { quality: 80, format: \"webp\" }, {\n * mode: \"auto\",\n * streamingConfig: { fileSizeThreshold: 1_048_576 },\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createOptimizeNode(\n id: string,\n { quality, format }: OptimizeParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = imageService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"buffered\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Helper to build output metadata from optimized result\n const buildOutputMetadata = (file: {\n metadata?: Record<string, unknown>;\n flow?: { flowId?: string; jobId?: string };\n }) => {\n const newType = formatToMimeType[format];\n const newExtension = formatToExtension[format];\n\n // Get original fileName\n const fileName = file.metadata?.fileName;\n let newFileName: string | undefined;\n\n if (fileName && typeof fileName === \"string\") {\n // Apply naming if configured\n if (options?.naming) {\n const namingConfig: FileNamingConfig = {\n ...options.naming,\n autoSuffix:\n options.naming.autoSuffix ?? ((ctx) => ctx.format ?? format),\n };\n const namingContext = buildNamingContext(\n file as Parameters<typeof buildNamingContext>[0],\n {\n flowId: file.flow?.flowId ?? \"\",\n jobId: file.flow?.jobId ?? \"\",\n nodeId: id,\n nodeType: \"optimize\",\n },\n { format, quality },\n );\n // Apply naming to get base name with suffix\n const namedFile = applyFileNaming(\n file as Parameters<typeof applyFileNaming>[0],\n namingContext,\n namingConfig,\n );\n // Replace extension with new format extension\n newFileName = `${getBaseName(namedFile)}.${newExtension}`;\n } else {\n // No naming config, just update extension\n newFileName = fileName.replace(/\\.[^.]+$/, `.${newExtension}`);\n }\n }\n\n return { newType, newFileName };\n };\n\n return yield* createTransformNode({\n id,\n name: \"Optimize\",\n description: \"Optimizes an image for web delivery\",\n nodeTypeId: \"optimize-image\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n // Note: naming is handled in transform since format changes extension\n nodeType: \"optimize\",\n namingVars: { format, quality },\n mode: effectiveMode,\n streamingConfig: options?.streamingConfig,\n // Buffered transform (used when mode is \"buffered\" or \"auto\" selects buffered)\n transform: (inputBytes, file) =>\n Effect.map(\n imageService.optimize(inputBytes, { quality, format }),\n (optimizedBytes) => {\n const { newType, newFileName } = buildOutputMetadata(file);\n return {\n bytes: optimizedBytes,\n type: newType,\n fileName: newFileName,\n } as\n | Uint8Array\n | { bytes: Uint8Array; type: string; fileName?: string };\n },\n ),\n // Streaming transform (used when mode is \"streaming\" or \"auto\" selects streaming)\n streamingTransform: imageService.optimizeStream\n ? (inputStream, file) => {\n const optimizeStreamFn = imageService.optimizeStream;\n if (!optimizeStreamFn) {\n throw UploadistaError.fromCode(\"UNKNOWN_ERROR\");\n }\n return Effect.gen(function* () {\n // Use the streaming optimization\n const outputStream = yield* optimizeStreamFn(inputStream, {\n quality,\n format,\n });\n\n const { newType, newFileName } = buildOutputMetadata(file);\n\n return {\n stream: outputStream,\n type: newType,\n fileName: newFileName,\n };\n });\n }\n : undefined,\n });\n });\n}\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport {\n applyFileNaming,\n buildNamingContext,\n completeNodeExecution,\n createFlowNode,\n type FileNamingConfig,\n ImageAiPlugin,\n NodeType,\n resolveUploadMetadata,\n STORAGE_OUTPUT_TYPE_ID,\n} from \"@uploadista/core/flow\";\nimport { uploadFileSchema } from \"@uploadista/core/types\";\nimport { UploadEngine } from \"@uploadista/core/upload\";\nimport { Effect } from \"effect\";\nimport { waitForUrlAvailability } from \"./wait-for-url\";\n\n/**\n * Creates a remove-background node that removes backgrounds from images using AI.\n *\n * @param id - Unique node identifier\n * @param options - Optional configuration\n * @param options.credentialId - Optional credential ID for AI service\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `nobg`)\n *\n * @example\n * ```typescript\n * // With auto-naming: \"photo.jpg\" -> \"photo-nobg.jpg\"\n * const node = yield* createRemoveBackgroundNode(\"remove-bg-1\", {\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createRemoveBackgroundNode(\n id: string,\n {\n credentialId,\n keepOutput,\n naming,\n }: {\n credentialId?: string;\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n } = {},\n) {\n return Effect.gen(function* () {\n const imageAiService = yield* ImageAiPlugin;\n const uploadEngine = yield* UploadEngine;\n\n return yield* createFlowNode({\n id,\n name: \"Remove Background\",\n description: \"Removes the background from an image\",\n type: NodeType.process,\n nodeTypeId: \"remove-background\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput,\n inputSchema: uploadFileSchema,\n outputSchema: uploadFileSchema,\n // AI service - enable circuit breaker with skip fallback\n circuitBreaker: {\n enabled: true,\n failureThreshold: 5,\n resetTimeout: 60000,\n fallback: { type: \"skip\", passThrough: true },\n },\n run: ({ data: file, flowId, jobId, storageId, clientId }) => {\n return Effect.gen(function* () {\n const flow = {\n flowId,\n nodeId: id,\n jobId,\n };\n\n const fileUrl = file.url;\n\n // Validate input\n if (!fileUrl) {\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause: \"URL is required for remove background operation\",\n }).toEffect();\n }\n\n yield* Effect.logInfo(\n `Removing background for file ${file.id} at URL: ${file.url}`,\n );\n\n // Wait for URL to be available with retry mechanism\n yield* waitForUrlAvailability(fileUrl);\n\n // Build context for ImageAI plugin\n const context = {\n clientId,\n credentialId,\n };\n\n // Remove background with error handling\n const backgroundRemovalResult = yield* imageAiService\n .removeBackground(fileUrl, context)\n .pipe(\n Effect.catchAll((error) =>\n Effect.gen(function* () {\n yield* Effect.logError(\"Failed to remove background\", error);\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause:\n error instanceof Error\n ? error.message\n : \"Failed to remove background from image\",\n }).toEffect();\n }),\n ),\n );\n\n const { outputUrl } = backgroundRemovalResult;\n const { type, fileName, metadata, metadataJson } =\n resolveUploadMetadata(file.metadata);\n\n // Apply file naming if configured\n let outputFileName = fileName;\n if (naming) {\n const namingConfig: FileNamingConfig = {\n ...naming,\n autoSuffix: naming.autoSuffix ?? (() => \"nobg\"),\n };\n const namingContext = buildNamingContext(file, {\n flowId,\n jobId,\n nodeId: id,\n nodeType: \"remove-background\",\n });\n outputFileName = applyFileNaming(file, namingContext, namingConfig);\n }\n\n yield* Effect.logInfo(`Uploading processed file to storage`);\n\n // Upload the transformed bytes back to the upload server with error handling\n const result = yield* uploadEngine\n .uploadFromUrl(\n {\n storageId,\n size: 0,\n type,\n fileName: outputFileName,\n lastModified: 0,\n metadata: metadataJson,\n flow,\n },\n clientId,\n outputUrl,\n )\n .pipe(\n Effect.catchAll((error) =>\n Effect.gen(function* () {\n yield* Effect.logError(\n \"Failed to upload processed file\",\n error,\n );\n return yield* UploadistaError.fromCode(\"FLOW_NODE_ERROR\", {\n cause:\n error instanceof Error\n ? error.message\n : \"Failed to upload processed file\",\n }).toEffect();\n }),\n ),\n );\n\n yield* Effect.logInfo(\n `Successfully removed background for file ${file.id}`,\n );\n\n // Update metadata with new filename if naming was applied\n const updatedMetadata = metadata\n ? {\n ...metadata,\n ...(outputFileName !== fileName && {\n fileName: outputFileName,\n originalName: outputFileName,\n name: outputFileName,\n extension:\n outputFileName.split(\".\").pop() || metadata.extension,\n }),\n }\n : result.metadata;\n\n return completeNodeExecution(\n updatedMetadata\n ? {\n ...result,\n metadata: updatedMetadata,\n }\n : result,\n );\n });\n },\n });\n });\n}\n","import {\n createTransformNode,\n type FileNamingConfig,\n ImagePlugin,\n type ResizeParams,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformMode,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n/**\n * Creates a resize node that resizes images to specified dimensions.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large images. In streaming mode, the image is read and processed\n * incrementally, reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Resize parameters (width, height, fit)\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `${width}x${height}`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 1MB, otherwise buffered\n * const resize = yield* createResizeNode(\"resize-1\", { width: 800, height: 600 }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const resizeBuffered = yield* createResizeNode(\"resize-2\", { width: 800, height: 600 }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const resizeStreaming = yield* createResizeNode(\"resize-3\", { width: 800, height: 600 }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createResizeNode(\n id: string,\n { width, height, fit }: ResizeParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = imageService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Build naming config with auto suffix for resize\n const namingConfig: FileNamingConfig | undefined = options?.naming\n ? {\n ...options.naming,\n // Provide default auto suffix generator for resize nodes\n autoSuffix:\n options.naming.autoSuffix ??\n ((ctx) => `${ctx.width ?? width}x${ctx.height ?? height}`),\n }\n : undefined;\n\n return yield* createTransformNode({\n id,\n name: \"Resize\",\n description: \"Resizes an image to the specified dimensions\",\n nodeTypeId: \"resize-image\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n naming: namingConfig,\n nodeType: \"resize\",\n namingVars: { width, height },\n mode: effectiveMode,\n streamingConfig: options?.streamingConfig,\n // Buffered transform (used when mode is \"buffered\" or \"auto\" selects buffered)\n transform: (inputBytes) =>\n imageService.resize(inputBytes, { height, width, fit }),\n // Streaming transform (used when mode is \"streaming\" or \"auto\" selects streaming)\n streamingTransform: imageService.resizeStream\n ? (inputStream) =>\n Effect.gen(function* () {\n const resizeStreamFn = imageService.resizeStream;\n if (!resizeStreamFn) {\n throw new Error(\"resizeStream not available\");\n }\n const outputStream = yield* resizeStreamFn(inputStream, {\n width,\n height,\n fit,\n });\n return { stream: outputStream };\n })\n : undefined,\n });\n });\n}\n","import {\n createTransformNode,\n type FileNamingConfig,\n ImagePlugin,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformImageParams,\n type TransformMode,\n} from \"@uploadista/core/flow\";\nimport type { UploadistaError } from \"@uploadista/core/errors\";\nimport { Effect, Stream } from \"effect\";\n\n/**\n * Apply a chain of transformations to an image by reducing over the transformations array.\n * Each transformation receives the output of the previous transformation as input.\n *\n * @param imageService - The image plugin service to use for transformations\n * @param inputBytes - The input image bytes\n * @param transformations - Array of transformations to apply in sequence\n * @returns Effect that resolves to the final transformed image bytes\n */\nfunction applyTransformationChain(\n imageService: ReturnType<typeof ImagePlugin.of>,\n inputBytes: Uint8Array,\n transformations: TransformImageParams[\"transformations\"],\n) {\n return Effect.reduce(transformations, inputBytes, (bytes, transformation) =>\n imageService.transform(bytes, transformation),\n );\n}\n\n/**\n * Apply a chain of transformations using streaming where possible.\n * Falls back to buffered processing for transformations that don't support streaming.\n *\n * @param imageService - The image plugin service to use for transformations\n * @param inputStream - The input image as a stream\n * @param transformations - Array of transformations to apply in sequence\n * @returns Effect that resolves to the final transformed image stream\n */\nfunction applyStreamingTransformationChain(\n imageService: ReturnType<typeof ImagePlugin.of>,\n inputStream: Stream.Stream<Uint8Array, UploadistaError>,\n transformations: TransformImageParams[\"transformations\"],\n): Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError> {\n const transformStreamFn = imageService.transformStream;\n\n if (!transformStreamFn) {\n // If streaming not supported, collect to buffer and use buffered chain\n return Effect.gen(function* () {\n // Collect stream to buffer\n const chunks: Uint8Array[] = [];\n yield* Stream.runForEach(inputStream, (chunk) =>\n Effect.sync(() => {\n chunks.push(chunk);\n }),\n );\n const totalLength = chunks.reduce((sum, c) => sum + c.byteLength, 0);\n const inputBuffer = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n inputBuffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n // Apply transformations\n const result = yield* applyTransformationChain(\n imageService,\n inputBuffer,\n transformations,\n );\n return Stream.make(result);\n });\n }\n\n // Apply each transformation in sequence using streaming\n return Effect.reduce(\n transformations,\n inputStream,\n (currentStream, transformation) =>\n Effect.flatMap(\n transformStreamFn(currentStream, transformation),\n (outputStream) => Effect.succeed(outputStream),\n ),\n );\n}\n\n/**\n * Creates a transform image node that applies multiple transformations sequentially.\n *\n * This node enables complex image processing workflows by chaining multiple transformations\n * together. Each transformation is applied to the output of the previous transformation,\n * allowing for powerful image manipulation pipelines.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large images. In streaming mode, each transformation is applied in sequence\n * using streaming where supported.\n *\n * Supported transformations include:\n * - Basic: resize, blur, rotate, flip\n * - Filters: grayscale, sepia, brightness, contrast\n * - Effects: sharpen\n * - Advanced: watermark, logo, text (streaming not supported for these)\n *\n * Note: Watermark and logo transformations require imagePath to be a valid URL.\n * Images will be fetched from the provided URL during transformation.\n * Streaming mode is not supported for watermark, logo, and text transformations;\n * these will cause fallback to buffered mode.\n *\n * @param id - Unique identifier for this node\n * @param params - Parameters including the transformations array\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `transformed`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 1MB, otherwise buffered\n * const node = yield* createTransformImageNode(\"transform-1\", {\n * transformations: [\n * { type: 'resize', width: 800, height: 600, fit: 'cover' },\n * { type: 'brightness', value: 20 }\n * ]\n * }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const nodeBuffered = yield* createTransformImageNode(\"transform-2\", {\n * transformations: [\n * { type: 'resize', width: 800, height: 600, fit: 'cover' },\n * { type: 'blur', sigma: 5 }\n * ]\n * }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const nodeStreaming = yield* createTransformImageNode(\"transform-3\", {\n * transformations: [{ type: 'grayscale' }]\n * }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createTransformImageNode(\n id: string,\n { transformations }: TransformImageParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = imageService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // Check if any transformations don't support streaming\n const hasUnsupportedTransformations = transformations.some(\n (t) => t.type === \"watermark\" || t.type === \"logo\" || t.type === \"text\",\n );\n\n // If streaming requested but not supported or unsupported transformations, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming && !hasUnsupportedTransformations\n ? requestedMode\n : \"buffered\";\n\n // Build naming config with auto suffix for transform-image\n const namingConfig: FileNamingConfig | undefined = options?.naming\n ? {\n ...options.naming,\n autoSuffix: options.naming.autoSuffix ?? (() => \"transformed\"),\n }\n : undefined;\n\n return yield* createTransformNode({\n id,\n name: \"Transform Image\",\n description: `Apply ${transformations.length} transformation${transformations.length === 1 ? \"\" : \"s\"} to the image`,\n nodeTypeId: \"transform-image\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n naming: namingConfig,\n nodeType: \"transform-image\",\n mode: effectiveMode,\n streamingConfig: options?.streamingConfig,\n // Buffered transform (used when mode is \"buffered\" or \"auto\" selects buffered)\n transform: (inputBytes) =>\n applyTransformationChain(imageService, inputBytes, transformations),\n // Streaming transform (used when mode is \"streaming\" or \"auto\" selects streaming)\n streamingTransform:\n supportsStreaming && !hasUnsupportedTransformations\n ? (inputStream) =>\n Effect.gen(function* () {\n const outputStream =\n yield* applyStreamingTransformationChain(\n imageService,\n inputStream,\n transformations,\n );\n return { stream: outputStream };\n })\n : undefined,\n });\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uploadista/flow-images-nodes",
3
3
  "type": "module",
4
- "version": "0.0.20-beta.7",
4
+ "version": "0.0.20-beta.8",
5
5
  "description": "Image processing nodes for Uploadista Flow",
6
6
  "license": "MIT",
7
7
  "author": "Uploadista",
@@ -14,7 +14,7 @@
14
14
  }
15
15
  },
16
16
  "dependencies": {
17
- "@uploadista/core": "0.0.20-beta.7"
17
+ "@uploadista/core": "0.0.20-beta.8"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "effect": "^3.0.0",
@@ -22,15 +22,15 @@
22
22
  },
23
23
  "devDependencies": {
24
24
  "@effect/vitest": "0.27.0",
25
- "@types/node": "24.10.3",
26
- "effect": "3.19.11",
27
- "tsdown": "0.17.2",
25
+ "@types/node": "24.10.4",
26
+ "effect": "3.19.12",
27
+ "tsdown": "0.18.0",
28
28
  "vitest": "4.0.15",
29
- "zod": "4.1.13",
30
- "@uploadista/typescript-config": "0.0.20-beta.7"
29
+ "zod": "4.2.0",
30
+ "@uploadista/typescript-config": "0.0.20-beta.8"
31
31
  },
32
32
  "scripts": {
33
- "build": "tsdown",
33
+ "build": "tsc --noEmit && tsdown",
34
34
  "check": "biome check --write ./src",
35
35
  "format": "biome format --write ./src",
36
36
  "lint": "biome lint --write ./src",
@@ -11,7 +11,7 @@ import {
11
11
  STORAGE_OUTPUT_TYPE_ID,
12
12
  } from "@uploadista/core/flow";
13
13
  import { uploadFileSchema } from "@uploadista/core/types";
14
- import { UploadServer } from "@uploadista/core/upload";
14
+ import { UploadEngine } from "@uploadista/core/upload";
15
15
  import { Effect } from "effect";
16
16
  import { waitForUrlAvailability } from "./wait-for-url";
17
17
 
@@ -34,11 +34,19 @@ import { waitForUrlAvailability } from "./wait-for-url";
34
34
  */
35
35
  export function createRemoveBackgroundNode(
36
36
  id: string,
37
- { credentialId, keepOutput, naming }: { credentialId?: string; keepOutput?: boolean; naming?: FileNamingConfig } = {},
37
+ {
38
+ credentialId,
39
+ keepOutput,
40
+ naming,
41
+ }: {
42
+ credentialId?: string;
43
+ keepOutput?: boolean;
44
+ naming?: FileNamingConfig;
45
+ } = {},
38
46
  ) {
39
47
  return Effect.gen(function* () {
40
48
  const imageAiService = yield* ImageAiPlugin;
41
- const uploadServer = yield* UploadServer;
49
+ const uploadEngine = yield* UploadEngine;
42
50
 
43
51
  return yield* createFlowNode({
44
52
  id,
@@ -115,22 +123,19 @@ export function createRemoveBackgroundNode(
115
123
  ...naming,
116
124
  autoSuffix: naming.autoSuffix ?? (() => "nobg"),
117
125
  };
118
- const namingContext = buildNamingContext(
119
- file,
120
- {
121
- flowId,
122
- jobId,
123
- nodeId: id,
124
- nodeType: "remove-background",
125
- },
126
- );
126
+ const namingContext = buildNamingContext(file, {
127
+ flowId,
128
+ jobId,
129
+ nodeId: id,
130
+ nodeType: "remove-background",
131
+ });
127
132
  outputFileName = applyFileNaming(file, namingContext, namingConfig);
128
133
  }
129
134
 
130
135
  yield* Effect.logInfo(`Uploading processed file to storage`);
131
136
 
132
137
  // Upload the transformed bytes back to the upload server with error handling
133
- const result = yield* uploadServer
138
+ const result = yield* uploadEngine
134
139
  .uploadFromUrl(
135
140
  {
136
141
  storageId,
@@ -173,7 +178,8 @@ export function createRemoveBackgroundNode(
173
178
  fileName: outputFileName,
174
179
  originalName: outputFileName,
175
180
  name: outputFileName,
176
- extension: outputFileName.split(".").pop() || metadata.extension,
181
+ extension:
182
+ outputFileName.split(".").pop() || metadata.extension,
177
183
  }),
178
184
  }
179
185
  : result.metadata;
@@ -3,7 +3,7 @@ import { UploadistaError } from "@uploadista/core/errors";
3
3
  import {
4
4
  TestImageAiPlugin,
5
5
  TestImagePlugin,
6
- TestUploadServer,
6
+ TestUploadEngine,
7
7
  } from "@uploadista/core/testing";
8
8
  import type { UploadFile } from "@uploadista/core/types";
9
9
  import { Effect, Layer } from "effect";
@@ -45,7 +45,7 @@ const createTestUploadFile = (overrides?: Partial<UploadFile>): UploadFile => ({
45
45
  const TestLayer = Layer.mergeAll(
46
46
  TestImagePlugin,
47
47
  TestImageAiPlugin,
48
- TestUploadServer,
48
+ TestUploadEngine,
49
49
  );
50
50
 
51
51
  // Mock fetch for URL availability tests