@uploadista/flow-images-nodes 0.0.8 → 0.0.9

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/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`@uploadista/core/errors`);c=s(c);let l=require(`@uploadista/core/flow`);l=s(l);let u=require(`@uploadista/core/types`);u=s(u);let d=require(`effect`);d=s(d);let f=require(`@uploadista/core/upload`);f=s(f);function p(e,t={}){let{maxWaitTime:n=1e4,retryDelay:r=500}=t;return d.Effect.gen(function*(){let t=Date.now();for(;Date.now()-t<n;){let t=yield*d.Effect.tryPromise(()=>fetch(e,{method:`HEAD`})).pipe(d.Effect.catchAll(()=>d.Effect.succeed(null)));if(t?.ok){yield*d.Effect.logInfo(`URL ${e} is now available`);return}t?yield*d.Effect.logDebug(`URL not ready yet (${t.status}), retrying...`):yield*d.Effect.logDebug(`URL check failed, retrying...`),yield*d.Effect.sleep(r)}return yield*c.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL ${e} not available after ${n}ms`}).toEffect()})}function m(e,{credentialId:t}={}){return d.Effect.gen(function*(){let n=yield*l.ImageAiPlugin;return yield*(0,l.createFlowNode)({id:e,name:`Describe Image`,description:`Describes the image using AI`,type:l.NodeType.process,inputSchema:u.uploadFileSchema,outputSchema:u.uploadFileSchema,run:({data:r,flowId:i,jobId:a,clientId:o})=>d.Effect.gen(function*(){let s={flowId:i,nodeId:e,jobId:a},u=r.url;if(!u)return yield*c.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for describe image operation`}).toEffect();yield*d.Effect.logInfo(`Describing image for file ${r.id} at URL: ${u}`),yield*p(u);let f={clientId:o,credentialId:t},{description:m}=yield*n.describeImage(u,f).pipe(d.Effect.catchAll(e=>d.Effect.gen(function*(){return yield*d.Effect.logError(`Failed to describe image`,e),yield*c.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:e instanceof Error?e.message:`Failed to describe image`}).toEffect()}))),{metadata:h}=(0,l.resolveUploadMetadata)(r.metadata),g={...r.metadata,...h,description:m};return yield*d.Effect.logInfo(`Successfully described image for file ${r.id}`),(0,l.completeNodeExecution)(g?{...r,metadata:g,flow:s}:r)})})})}const h={jpeg:`image/jpeg`,webp:`image/webp`,png:`image/png`,avif:`image/avif`},g={jpeg:`jpg`,webp:`webp`,png:`png`,avif:`avif`};function _(e,{quality:t,format:n}){return d.Effect.gen(function*(){let r=yield*l.ImagePlugin;return yield*(0,l.createTransformNode)({id:e,name:`Optimize`,description:`Optimizes an image for web delivery`,transform:(e,i)=>d.Effect.map(r.optimize(e,{quality:t,format:n}),e=>{let t=h[n],r=g[n],a=i.metadata?.fileName;return{bytes:e,type:t,fileName:a&&typeof a==`string`?a.replace(/\.[^.]+$/,`.${r}`):void 0}})})})}function v(e,{credentialId:t}={}){return d.Effect.gen(function*(){let n=yield*l.ImageAiPlugin,r=yield*f.UploadServer;return yield*(0,l.createFlowNode)({id:e,name:`Remove Background`,description:`Removes the background from an image`,type:l.NodeType.process,inputSchema:u.uploadFileSchema,outputSchema:u.uploadFileSchema,run:({data:i,flowId:a,jobId:o,storageId:s,clientId:u})=>d.Effect.gen(function*(){let f={flowId:a,nodeId:e,jobId:o},m=i.url;if(!m)return yield*c.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for remove background operation`}).toEffect();yield*d.Effect.logInfo(`Removing background for file ${i.id} at URL: ${i.url}`),yield*p(m);let h={clientId:u,credentialId:t},{outputUrl:g}=yield*n.removeBackground(m,h).pipe(d.Effect.catchAll(e=>d.Effect.gen(function*(){return yield*d.Effect.logError(`Failed to remove background`,e),yield*c.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:e instanceof Error?e.message:`Failed to remove background from image`}).toEffect()}))),{type:_,fileName:v,metadata:y,metadataJson:b}=(0,l.resolveUploadMetadata)(i.metadata);yield*d.Effect.logInfo(`Uploading processed file to storage`);let x=yield*r.uploadFromUrl({storageId:s,size:0,type:_,fileName:v,lastModified:0,metadata:b,flow:f},u,g).pipe(d.Effect.catchAll(e=>d.Effect.gen(function*(){return yield*d.Effect.logError(`Failed to upload processed file`,e),yield*c.UploadistaError.fromCode(`FLOW_NODE_ERROR`,{cause:e instanceof Error?e.message:`Failed to upload processed file`}).toEffect()})));return yield*d.Effect.logInfo(`Successfully removed background for file ${i.id}`),(0,l.completeNodeExecution)(y?{...x,metadata:y}:x)})})})}function y(e,{width:t,height:n,fit:r}){return d.Effect.gen(function*(){let i=yield*l.ImagePlugin;return yield*(0,l.createTransformNode)({id:e,name:`Resize`,description:`Resizes an image to the specified dimensions`,transform:e=>i.resize(e,{height:n,width:t,fit:r})})})}exports.createDescribeImageNode=m,exports.createOptimizeNode=_,exports.createRemoveBackgroundNode=v,exports.createResizeNode=y,exports.waitForUrlAvailability=p;
1
+ let e=require(`@uploadista/core/errors`),t=require(`@uploadista/core/flow`),n=require(`@uploadista/core/types`),r=require(`effect`),i=require(`@uploadista/core/upload`);function a(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 o(i,{credentialId:o}={}){return r.Effect.gen(function*(){let s=yield*t.ImageAiPlugin;return yield*(0,t.createFlowNode)({id:i,name:`Describe Image`,description:`Describes the image using AI`,type:t.NodeType.process,inputSchema:n.uploadFileSchema,outputSchema:n.uploadFileSchema,run:({data:n,flowId:c,jobId:l,clientId:u})=>r.Effect.gen(function*(){let d={flowId:c,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*a(f);let p={clientId:u,credentialId:o},{description:m}=yield*s.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()}))),{metadata:h}=(0,t.resolveUploadMetadata)(n.metadata),g={...n.metadata,...h,description:m};return yield*r.Effect.logInfo(`Successfully described image for file ${n.id}`),(0,t.completeNodeExecution)(g?{...n,metadata:g,flow:d}:n)})})})}const s={jpeg:`image/jpeg`,webp:`image/webp`,png:`image/png`,avif:`image/avif`},c={jpeg:`jpg`,webp:`webp`,png:`png`,avif:`avif`};function l(e,{quality:n,format:i}){return r.Effect.gen(function*(){let a=yield*t.ImagePlugin;return yield*(0,t.createTransformNode)({id:e,name:`Optimize`,description:`Optimizes an image for web delivery`,transform:(e,t)=>r.Effect.map(a.optimize(e,{quality:n,format:i}),e=>{let n=s[i],r=c[i],a=t.metadata?.fileName;return{bytes:e,type:n,fileName:a&&typeof a==`string`?a.replace(/\.[^.]+$/,`.${r}`):void 0}})})})}function u(o,{credentialId:s}={}){return r.Effect.gen(function*(){let c=yield*t.ImageAiPlugin,l=yield*i.UploadServer;return yield*(0,t.createFlowNode)({id:o,name:`Remove Background`,description:`Removes the background from an image`,type:t.NodeType.process,inputSchema:n.uploadFileSchema,outputSchema:n.uploadFileSchema,run:({data:n,flowId:i,jobId:u,storageId:d,clientId:f})=>r.Effect.gen(function*(){let p={flowId:i,nodeId:o,jobId:u},m=n.url;if(!m)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*a(m);let h={clientId:f,credentialId:s},{outputUrl:g}=yield*c.removeBackground(m,h).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:_,fileName:v,metadata:y,metadataJson:b}=(0,t.resolveUploadMetadata)(n.metadata);yield*r.Effect.logInfo(`Uploading processed file to storage`);let x=yield*l.uploadFromUrl({storageId:d,size:0,type:_,fileName:v,lastModified:0,metadata:b,flow:p},f,g).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()})));return yield*r.Effect.logInfo(`Successfully removed background for file ${n.id}`),(0,t.completeNodeExecution)(y?{...x,metadata:y}:x)})})})}function d(e,{width:n,height:i,fit:a}){return r.Effect.gen(function*(){let r=yield*t.ImagePlugin;return yield*(0,t.createTransformNode)({id:e,name:`Resize`,description:`Resizes an image to the specified dimensions`,transform:e=>r.resize(e,{height:i,width:n,fit:a})})})}exports.createDescribeImageNode=o,exports.createOptimizeNode=l,exports.createRemoveBackgroundNode=u,exports.createResizeNode=d,exports.waitForUrlAvailability=a;
package/dist/index.d.cts CHANGED
@@ -1,172 +1,33 @@
1
- import * as _uploadista_core_flow0 from "@uploadista/core/flow";
2
- import { ImageAiPlugin, ImagePlugin, OptimizeParams, ResizeParams } from "@uploadista/core/flow";
3
- import * as _uploadista_core_errors0 from "@uploadista/core/errors";
4
- import { UploadistaError } from "@uploadista/core/errors";
5
1
  import { Effect } from "effect";
6
- import * as _uploadista_core_types0 from "@uploadista/core/types";
7
- import * as _uploadista_core_upload0 from "@uploadista/core/upload";
8
- import { UploadServer } from "@uploadista/core/upload";
2
+ import { OptimizeParams, ResizeParams } from "@uploadista/core/flow";
3
+ import { UploadistaError } from "@uploadista/core/errors";
9
4
 
10
5
  //#region src/describe-image-node.d.ts
11
6
  declare function createDescribeImageNode(id: string, {
12
7
  credentialId
13
8
  }?: {
14
9
  credentialId?: string;
15
- }): Effect.Effect<_uploadista_core_flow0.FlowNode<{
16
- id: string;
17
- offset: number;
18
- storage: {
19
- id: string;
20
- type: string;
21
- path?: string | undefined;
22
- uploadId?: string | undefined;
23
- bucket?: string | undefined;
24
- };
25
- size?: number | undefined;
26
- metadata?: Record<string, string | number | boolean> | undefined;
27
- creationDate?: string | undefined;
28
- url?: string | undefined;
29
- sizeIsDeferred?: boolean | undefined;
30
- checksum?: string | undefined;
31
- checksumAlgorithm?: string | undefined;
32
- flow?: {
33
- flowId: string;
34
- nodeId: string;
35
- jobId: string;
36
- } | undefined;
37
- }, {
38
- id: string;
39
- offset: number;
40
- storage: {
41
- id: string;
42
- type: string;
43
- path?: string | undefined;
44
- uploadId?: string | undefined;
45
- bucket?: string | undefined;
46
- };
47
- size?: number | undefined;
48
- metadata?: Record<string, string | number | boolean> | undefined;
49
- creationDate?: string | undefined;
50
- url?: string | undefined;
51
- sizeIsDeferred?: boolean | undefined;
52
- checksum?: string | undefined;
53
- checksumAlgorithm?: string | undefined;
54
- flow?: {
55
- flowId: string;
56
- nodeId: string;
57
- jobId: string;
58
- } | undefined;
59
- } | {
60
- metadata: {
61
- description: string;
62
- };
63
- flow: {
64
- flowId: string;
65
- nodeId: string;
66
- jobId: string;
67
- };
68
- id: string;
69
- offset: number;
70
- storage: {
71
- id: string;
72
- type: string;
73
- path?: string | undefined;
74
- uploadId?: string | undefined;
75
- bucket?: string | undefined;
76
- };
77
- size?: number | undefined;
78
- creationDate?: string | undefined;
79
- url?: string | undefined;
80
- sizeIsDeferred?: boolean | undefined;
81
- checksum?: string | undefined;
82
- checksumAlgorithm?: string | undefined;
83
- }, UploadistaError>, never, ImageAiPlugin>;
10
+ }): Effect.Effect<any, unknown, unknown>;
84
11
  //#endregion
85
12
  //#region src/optimize-node.d.ts
86
13
  declare function createOptimizeNode(id: string, {
87
14
  quality,
88
15
  format
89
- }: OptimizeParams): Effect.Effect<_uploadista_core_flow0.FlowNode<{
90
- id: string;
91
- offset: number;
92
- storage: {
93
- id: string;
94
- type: string;
95
- path?: string | undefined;
96
- uploadId?: string | undefined;
97
- bucket?: string | undefined;
98
- };
99
- size?: number | undefined;
100
- metadata?: Record<string, string | number | boolean> | undefined;
101
- creationDate?: string | undefined;
102
- url?: string | undefined;
103
- sizeIsDeferred?: boolean | undefined;
104
- checksum?: string | undefined;
105
- checksumAlgorithm?: string | undefined;
106
- flow?: {
107
- flowId: string;
108
- nodeId: string;
109
- jobId: string;
110
- } | undefined;
111
- }, _uploadista_core_types0.UploadFile, _uploadista_core_errors0.UploadistaError>, never, ImagePlugin | _uploadista_core_upload0.UploadServer>;
16
+ }: OptimizeParams): Effect.Effect<any, unknown, unknown>;
112
17
  //#endregion
113
18
  //#region src/remove-background-node.d.ts
114
19
  declare function createRemoveBackgroundNode(id: string, {
115
20
  credentialId
116
21
  }?: {
117
22
  credentialId?: string;
118
- }): Effect.Effect<_uploadista_core_flow0.FlowNode<{
119
- id: string;
120
- offset: number;
121
- storage: {
122
- id: string;
123
- type: string;
124
- path?: string | undefined;
125
- uploadId?: string | undefined;
126
- bucket?: string | undefined;
127
- };
128
- size?: number | undefined;
129
- metadata?: Record<string, string | number | boolean> | undefined;
130
- creationDate?: string | undefined;
131
- url?: string | undefined;
132
- sizeIsDeferred?: boolean | undefined;
133
- checksum?: string | undefined;
134
- checksumAlgorithm?: string | undefined;
135
- flow?: {
136
- flowId: string;
137
- nodeId: string;
138
- jobId: string;
139
- } | undefined;
140
- }, _uploadista_core_types0.UploadFile, UploadistaError>, never, ImageAiPlugin | UploadServer>;
23
+ }): Effect.Effect<any, unknown, unknown>;
141
24
  //#endregion
142
25
  //#region src/resize-node.d.ts
143
26
  declare function createResizeNode(id: string, {
144
27
  width,
145
28
  height,
146
29
  fit
147
- }: ResizeParams): Effect.Effect<_uploadista_core_flow0.FlowNode<{
148
- id: string;
149
- offset: number;
150
- storage: {
151
- id: string;
152
- type: string;
153
- path?: string | undefined;
154
- uploadId?: string | undefined;
155
- bucket?: string | undefined;
156
- };
157
- size?: number | undefined;
158
- metadata?: Record<string, string | number | boolean> | undefined;
159
- creationDate?: string | undefined;
160
- url?: string | undefined;
161
- sizeIsDeferred?: boolean | undefined;
162
- checksum?: string | undefined;
163
- checksumAlgorithm?: string | undefined;
164
- flow?: {
165
- flowId: string;
166
- nodeId: string;
167
- jobId: string;
168
- } | undefined;
169
- }, _uploadista_core_types0.UploadFile, _uploadista_core_errors0.UploadistaError>, never, ImagePlugin | _uploadista_core_upload0.UploadServer>;
30
+ }: ResizeParams): Effect.Effect<any, unknown, unknown>;
170
31
  //#endregion
171
32
  //#region src/wait-for-url.d.ts
172
33
  /**
@@ -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/wait-for-url.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;iBAagB,uBAAA;;;;IAEkC,MAAA,CAAA,8BAAA;;;;;IAFlC,IAAA,EAAA,MAAA;IAEZ,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;2BAA8C;;EAAA,YAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,GAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ECQlC,IAAA,CAAA,EAAA;IAEZ,MAAA,EAAA,MAAA;IAAS,MAAA,EAAA,MAAA;IAAU,KAAA,EAAA,MAAA;;;;;;;IAAc,IAAA,EAAA,MAAA;IAAA,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ECZrB,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAEZ,QAAA,CAAA,QAAA,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,GAAA,SAAA;;;;sBAA8C,SAAA;;;IAAA,MAAA,EAAA,MAAA;IAAA,MAAA,EAAA,MAAA;;;;ECRlC,QAAA,EAAA;IAEZ,WAAA,EAAA,MAAA;EAAO,CAAA;EAAQ,IAAA,EAAA;IAAO,MAAA,EAAA,MAAA;;;;;;;IAAY,EAAA,EAAA,MAAA;IAAA,IAAA,EAAA,MAAA;;;;ECKtB,CAAA;;;;;;;;;;iBHSA,kBAAA;;;GAEO,iBAAc,MAAA,CAAA,8BAAA;;;;;;;;IDZrB,MAAA,CAAA,EAAA,MAAA,GAAA,SAAuB;EAEnC,CAAA;;;;0BAA8C;;EAAA,QAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,iBAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ICQlC,KAAA,EAAA,MAAA;EAEZ,CAAA,GAAA,SAAA;CAAS,+EAAA,EAAA,KAAA,aAAA,wCAAA,CAAA;;;iBCZG,0BAAA;;;;IAEkC,MAAA,CAAA,8BAAA;;;;IFFlC,EAAA,EAAA,MAAA;IAEZ,IAAA,EAAA,MAAA;;;;;;EAA8C,QAAA,CAAA,QAAA,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,GAAA,SAAA;EAAA,YAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ECQlC,iBAAA,CAAA,EAAA,MAAkB,GAAA,SAAA;EAE9B,IAAA,CAAA,EAAA;IAAS,MAAA,EAAA,MAAA;IAAU,MAAA,EAAA,MAAA;;;;;;iBElBP,gBAAA;;;;GAEU,eAAY,MAAA,CAAA,8BAAA;;;;;;;;IHItB,MAAA,CAAA,EAAA,MAAA,GAAA,SAAuB;EAEnC,CAAA;;;;0BAA8C;;EAAA,QAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,iBAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ICQlC,KAAA,EAAA,MAAA;EAEZ,CAAA,GAAA,SAAA;CAAS,+EAAA,EAAA,KAAA,aAAA,wCAAA,CAAA;;;;;;;;;;;ADZb;;;iBICgB,sBAAA;;;IAMb,MAAA,CAAO,aAAa"}
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/wait-for-url.ts"],"sourcesContent":[],"mappings":";;;;;iBAagB,uBAAA;;;;IAEkC,MAAA,CAAA;;;iBCQlC,kBAAA;;;GAEO,iBAAc,MAAA,CAAA;;;iBCZrB,0BAAA;;;;IAEkC,MAAA,CAAA;;;iBCRlC,gBAAA;;;;GAEU,eAAY,MAAA,CAAA;;;;;;AHItC;;;;ACUA;;;;AAEqC,iBGXrB,sBAAA,CHWqB,GAAA,EAAA,MAAA,EAAA,QAAA,EAAA;EAAA,WAAA,CAAA,EAAA,MAAA;;IGLlC,MAAA,CAAO,aAAa"}
@@ -0,0 +1,50 @@
1
+ import { UploadistaError } from "@uploadista/core/errors";
2
+ import { OptimizeParams, ResizeParams } from "@uploadista/core/flow";
3
+ import { Effect } from "effect";
4
+
5
+ //#region src/describe-image-node.d.ts
6
+ declare function createDescribeImageNode(id: string, {
7
+ credentialId
8
+ }?: {
9
+ credentialId?: string;
10
+ }): Effect.Effect<any, unknown, unknown>;
11
+ //#endregion
12
+ //#region src/optimize-node.d.ts
13
+ declare function createOptimizeNode(id: string, {
14
+ quality,
15
+ format
16
+ }: OptimizeParams): Effect.Effect<any, unknown, unknown>;
17
+ //#endregion
18
+ //#region src/remove-background-node.d.ts
19
+ declare function createRemoveBackgroundNode(id: string, {
20
+ credentialId
21
+ }?: {
22
+ credentialId?: string;
23
+ }): Effect.Effect<any, unknown, unknown>;
24
+ //#endregion
25
+ //#region src/resize-node.d.ts
26
+ declare function createResizeNode(id: string, {
27
+ width,
28
+ height,
29
+ fit
30
+ }: ResizeParams): Effect.Effect<any, unknown, unknown>;
31
+ //#endregion
32
+ //#region src/wait-for-url.d.ts
33
+ /**
34
+ * Waits for a URL to become available by periodically checking its accessibility.
35
+ * This is useful when a file has just been uploaded and may not be immediately
36
+ * accessible due to CDN propagation or storage consistency delays.
37
+ *
38
+ * @param url - The URL to check for availability
39
+ * @param options - Configuration options
40
+ * @param options.maxWaitTime - Maximum time to wait in milliseconds (default: 10000)
41
+ * @param options.retryDelay - Delay between retries in milliseconds (default: 500)
42
+ * @returns Effect that succeeds when URL is available or fails with UploadistaError
43
+ */
44
+ declare function waitForUrlAvailability(url: string, options?: {
45
+ maxWaitTime?: number;
46
+ retryDelay?: number;
47
+ }): Effect.Effect<void, UploadistaError>;
48
+ //#endregion
49
+ export { createDescribeImageNode, createOptimizeNode, createRemoveBackgroundNode, createResizeNode, waitForUrlAvailability };
50
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +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/wait-for-url.ts"],"sourcesContent":[],"mappings":";;;;;iBAagB,uBAAA;;;;IAEkC,MAAA,CAAA;;;iBCQlC,kBAAA;;;GAEO,iBAAc,MAAA,CAAA;;;iBCZrB,0BAAA;;;;IAEkC,MAAA,CAAA;;;iBCRlC,gBAAA;;;;GAEU,eAAY,MAAA,CAAA;;;;;;AHItC;;;;ACUA;;;;AAEqC,iBGXrB,sBAAA,CHWqB,GAAA,EAAA,MAAA,EAAA,QAAA,EAAA;EAAA,WAAA,CAAA,EAAA,MAAA;;IGLlC,MAAA,CAAO,aAAa"}
@@ -1,2 +1,2 @@
1
1
  import{UploadistaError as e}from"@uploadista/core/errors";import{ImageAiPlugin as t,ImagePlugin as n,NodeType as r,completeNodeExecution as i,createFlowNode as a,createTransformNode as o,resolveUploadMetadata as s}from"@uploadista/core/flow";import{uploadFileSchema as c}from"@uploadista/core/types";import{Effect as l}from"effect";import{UploadServer as u}from"@uploadista/core/upload";function d(t,n={}){let{maxWaitTime:r=1e4,retryDelay:i=500}=n;return l.gen(function*(){let n=Date.now();for(;Date.now()-n<r;){let e=yield*l.tryPromise(()=>fetch(t,{method:`HEAD`})).pipe(l.catchAll(()=>l.succeed(null)));if(e?.ok){yield*l.logInfo(`URL ${t} is now available`);return}e?yield*l.logDebug(`URL not ready yet (${e.status}), retrying...`):yield*l.logDebug(`URL check failed, retrying...`),yield*l.sleep(i)}return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL ${t} not available after ${r}ms`}).toEffect()})}function f(n,{credentialId:o}={}){return l.gen(function*(){let u=yield*t;return yield*a({id:n,name:`Describe Image`,description:`Describes the image using AI`,type:r.process,inputSchema:c,outputSchema:c,run:({data:t,flowId:r,jobId:a,clientId:c})=>l.gen(function*(){let f={flowId:r,nodeId:n,jobId:a},p=t.url;if(!p)return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for describe image operation`}).toEffect();yield*l.logInfo(`Describing image for file ${t.id} at URL: ${p}`),yield*d(p);let m={clientId:c,credentialId:o},{description:h}=yield*u.describeImage(p,m).pipe(l.catchAll(t=>l.gen(function*(){return yield*l.logError(`Failed to describe image`,t),yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:t instanceof Error?t.message:`Failed to describe image`}).toEffect()}))),{metadata:g}=s(t.metadata),_={...t.metadata,...g,description:h};return yield*l.logInfo(`Successfully described image for file ${t.id}`),i(_?{...t,metadata:_,flow:f}:t)})})})}const p={jpeg:`image/jpeg`,webp:`image/webp`,png:`image/png`,avif:`image/avif`},m={jpeg:`jpg`,webp:`webp`,png:`png`,avif:`avif`};function h(e,{quality:t,format:r}){return l.gen(function*(){let i=yield*n;return yield*o({id:e,name:`Optimize`,description:`Optimizes an image for web delivery`,transform:(e,n)=>l.map(i.optimize(e,{quality:t,format:r}),e=>{let t=p[r],i=m[r],a=n.metadata?.fileName;return{bytes:e,type:t,fileName:a&&typeof a==`string`?a.replace(/\.[^.]+$/,`.${i}`):void 0}})})})}function g(n,{credentialId:o}={}){return l.gen(function*(){let f=yield*t,p=yield*u;return yield*a({id:n,name:`Remove Background`,description:`Removes the background from an image`,type:r.process,inputSchema:c,outputSchema:c,run:({data:t,flowId:r,jobId:a,storageId:c,clientId:u})=>l.gen(function*(){let m={flowId:r,nodeId:n,jobId:a},h=t.url;if(!h)return yield*e.fromCode(`FLOW_NODE_ERROR`,{cause:`URL is required for remove background operation`}).toEffect();yield*l.logInfo(`Removing background for file ${t.id} at URL: ${t.url}`),yield*d(h);let g={clientId:u,credentialId:o},{outputUrl:_}=yield*f.removeBackground(h,g).pipe(l.catchAll(t=>l.gen(function*(){return yield*l.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:v,fileName:y,metadata:b,metadataJson:x}=s(t.metadata);yield*l.logInfo(`Uploading processed file to storage`);let S=yield*p.uploadFromUrl({storageId:c,size:0,type:v,fileName:y,lastModified:0,metadata:x,flow:m},u,_).pipe(l.catchAll(t=>l.gen(function*(){return yield*l.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()})));return yield*l.logInfo(`Successfully removed background for file ${t.id}`),i(b?{...S,metadata:b}:S)})})})}function _(e,{width:t,height:r,fit:i}){return l.gen(function*(){let a=yield*n;return yield*o({id:e,name:`Resize`,description:`Resizes an image to the specified dimensions`,transform:e=>a.resize(e,{height:r,width:t,fit:i})})})}export{f as createDescribeImageNode,h as createOptimizeNode,g as createRemoveBackgroundNode,_ as createResizeNode,d as waitForUrlAvailability};
2
- //# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["formatToMimeType: Record<OptimizeParams[\"format\"], string>","formatToExtension: Record<OptimizeParams[\"format\"], string>"],"sources":["../src/wait-for-url.ts","../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-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 ImageAiPlugin,\n NodeType,\n resolveUploadMetadata,\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 }: { credentialId?: string } = {},\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 inputSchema: uploadFileSchema,\n outputSchema: uploadFileSchema,\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 { description } = 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 const { metadata } = resolveUploadMetadata(file.metadata);\n\n // add description to metadata\n const newMetadata = {\n ...file.metadata,\n ...metadata,\n description,\n };\n\n yield* Effect.logInfo(\n `Successfully described image for file ${file.id}`,\n );\n\n return completeNodeExecution(\n newMetadata\n ? {\n ...file,\n metadata: newMetadata,\n flow,\n }\n : file,\n );\n });\n },\n });\n });\n}\n","import {\n createTransformNode,\n ImagePlugin,\n type OptimizeParams,\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\nexport function createOptimizeNode(\n id: string,\n { quality, format }: OptimizeParams,\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n return yield* createTransformNode({\n id,\n name: \"Optimize\",\n description: \"Optimizes an image for web delivery\",\n transform: (inputBytes, file) =>\n Effect.map(\n imageService.optimize(inputBytes, { quality, format }),\n (optimizedBytes) => {\n // Return bytes with updated metadata if format changes\n const newType = formatToMimeType[format];\n const newExtension = formatToExtension[format];\n\n // Update file extension if format changed\n const fileName = file.metadata?.fileName;\n const newFileName =\n fileName && typeof fileName === \"string\"\n ? fileName.replace(/\\.[^.]+$/, `.${newExtension}`)\n : undefined;\n\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 });\n });\n}\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport {\n completeNodeExecution,\n createFlowNode,\n ImageAiPlugin,\n NodeType,\n resolveUploadMetadata,\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\nexport function createRemoveBackgroundNode(\n id: string,\n { credentialId }: { credentialId?: string } = {},\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 inputSchema: uploadFileSchema,\n outputSchema: uploadFileSchema,\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 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,\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 return completeNodeExecution(\n metadata\n ? {\n ...result,\n metadata,\n }\n : result,\n );\n });\n },\n });\n });\n}\n","import {\n createTransformNode,\n ImagePlugin,\n type ResizeParams,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\nexport function createResizeNode(\n id: string,\n { width, height, fit }: ResizeParams,\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n return yield* createTransformNode({\n id,\n name: \"Resize\",\n description: \"Resizes an image to the specified dimensions\",\n transform: (inputBytes) =>\n imageService.resize(inputBytes, { height, width, fit }),\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.8",
4
+ "version": "0.0.9",
5
5
  "description": "Image processing nodes for Uploadista Flow",
6
6
  "license": "MIT",
7
7
  "author": "Uploadista",
@@ -13,14 +13,14 @@
13
13
  }
14
14
  },
15
15
  "dependencies": {
16
- "effect": "3.18.4",
16
+ "effect": "3.19.0",
17
17
  "zod": "4.1.12",
18
- "@uploadista/core": "0.0.8"
18
+ "@uploadista/core": "0.0.9"
19
19
  },
20
20
  "devDependencies": {
21
- "@types/node": "24.9.1",
22
- "tsdown": "0.15.10",
23
- "@uploadista/typescript-config": "0.0.8"
21
+ "@types/node": "24.10.0",
22
+ "tsdown": "0.16.0",
23
+ "@uploadista/typescript-config": "0.0.9"
24
24
  },
25
25
  "scripts": {
26
26
  "build": "tsdown",
package/dist/index.d.ts DELETED
@@ -1,189 +0,0 @@
1
- import * as _uploadista_core_errors0 from "@uploadista/core/errors";
2
- import { UploadistaError } from "@uploadista/core/errors";
3
- import * as _uploadista_core_flow0 from "@uploadista/core/flow";
4
- import { ImageAiPlugin, ImagePlugin, OptimizeParams, ResizeParams } from "@uploadista/core/flow";
5
- import * as _uploadista_core_types0 from "@uploadista/core/types";
6
- import { Effect } from "effect";
7
- import * as _uploadista_core_upload0 from "@uploadista/core/upload";
8
- import { UploadServer } from "@uploadista/core/upload";
9
-
10
- //#region src/describe-image-node.d.ts
11
- declare function createDescribeImageNode(id: string, {
12
- credentialId
13
- }?: {
14
- credentialId?: string;
15
- }): Effect.Effect<_uploadista_core_flow0.FlowNode<{
16
- id: string;
17
- offset: number;
18
- storage: {
19
- id: string;
20
- type: string;
21
- path?: string | undefined;
22
- uploadId?: string | undefined;
23
- bucket?: string | undefined;
24
- };
25
- size?: number | undefined;
26
- metadata?: Record<string, string | number | boolean> | undefined;
27
- creationDate?: string | undefined;
28
- url?: string | undefined;
29
- sizeIsDeferred?: boolean | undefined;
30
- checksum?: string | undefined;
31
- checksumAlgorithm?: string | undefined;
32
- flow?: {
33
- flowId: string;
34
- nodeId: string;
35
- jobId: string;
36
- } | undefined;
37
- }, {
38
- id: string;
39
- offset: number;
40
- storage: {
41
- id: string;
42
- type: string;
43
- path?: string | undefined;
44
- uploadId?: string | undefined;
45
- bucket?: string | undefined;
46
- };
47
- size?: number | undefined;
48
- metadata?: Record<string, string | number | boolean> | undefined;
49
- creationDate?: string | undefined;
50
- url?: string | undefined;
51
- sizeIsDeferred?: boolean | undefined;
52
- checksum?: string | undefined;
53
- checksumAlgorithm?: string | undefined;
54
- flow?: {
55
- flowId: string;
56
- nodeId: string;
57
- jobId: string;
58
- } | undefined;
59
- } | {
60
- metadata: {
61
- description: string;
62
- };
63
- flow: {
64
- flowId: string;
65
- nodeId: string;
66
- jobId: string;
67
- };
68
- id: string;
69
- offset: number;
70
- storage: {
71
- id: string;
72
- type: string;
73
- path?: string | undefined;
74
- uploadId?: string | undefined;
75
- bucket?: string | undefined;
76
- };
77
- size?: number | undefined;
78
- creationDate?: string | undefined;
79
- url?: string | undefined;
80
- sizeIsDeferred?: boolean | undefined;
81
- checksum?: string | undefined;
82
- checksumAlgorithm?: string | undefined;
83
- }, UploadistaError>, never, ImageAiPlugin>;
84
- //#endregion
85
- //#region src/optimize-node.d.ts
86
- declare function createOptimizeNode(id: string, {
87
- quality,
88
- format
89
- }: OptimizeParams): Effect.Effect<_uploadista_core_flow0.FlowNode<{
90
- id: string;
91
- offset: number;
92
- storage: {
93
- id: string;
94
- type: string;
95
- path?: string | undefined;
96
- uploadId?: string | undefined;
97
- bucket?: string | undefined;
98
- };
99
- size?: number | undefined;
100
- metadata?: Record<string, string | number | boolean> | undefined;
101
- creationDate?: string | undefined;
102
- url?: string | undefined;
103
- sizeIsDeferred?: boolean | undefined;
104
- checksum?: string | undefined;
105
- checksumAlgorithm?: string | undefined;
106
- flow?: {
107
- flowId: string;
108
- nodeId: string;
109
- jobId: string;
110
- } | undefined;
111
- }, _uploadista_core_types0.UploadFile, _uploadista_core_errors0.UploadistaError>, never, ImagePlugin | _uploadista_core_upload0.UploadServer>;
112
- //#endregion
113
- //#region src/remove-background-node.d.ts
114
- declare function createRemoveBackgroundNode(id: string, {
115
- credentialId
116
- }?: {
117
- credentialId?: string;
118
- }): Effect.Effect<_uploadista_core_flow0.FlowNode<{
119
- id: string;
120
- offset: number;
121
- storage: {
122
- id: string;
123
- type: string;
124
- path?: string | undefined;
125
- uploadId?: string | undefined;
126
- bucket?: string | undefined;
127
- };
128
- size?: number | undefined;
129
- metadata?: Record<string, string | number | boolean> | undefined;
130
- creationDate?: string | undefined;
131
- url?: string | undefined;
132
- sizeIsDeferred?: boolean | undefined;
133
- checksum?: string | undefined;
134
- checksumAlgorithm?: string | undefined;
135
- flow?: {
136
- flowId: string;
137
- nodeId: string;
138
- jobId: string;
139
- } | undefined;
140
- }, _uploadista_core_types0.UploadFile, UploadistaError>, never, ImageAiPlugin | UploadServer>;
141
- //#endregion
142
- //#region src/resize-node.d.ts
143
- declare function createResizeNode(id: string, {
144
- width,
145
- height,
146
- fit
147
- }: ResizeParams): Effect.Effect<_uploadista_core_flow0.FlowNode<{
148
- id: string;
149
- offset: number;
150
- storage: {
151
- id: string;
152
- type: string;
153
- path?: string | undefined;
154
- uploadId?: string | undefined;
155
- bucket?: string | undefined;
156
- };
157
- size?: number | undefined;
158
- metadata?: Record<string, string | number | boolean> | undefined;
159
- creationDate?: string | undefined;
160
- url?: string | undefined;
161
- sizeIsDeferred?: boolean | undefined;
162
- checksum?: string | undefined;
163
- checksumAlgorithm?: string | undefined;
164
- flow?: {
165
- flowId: string;
166
- nodeId: string;
167
- jobId: string;
168
- } | undefined;
169
- }, _uploadista_core_types0.UploadFile, _uploadista_core_errors0.UploadistaError>, never, ImagePlugin | _uploadista_core_upload0.UploadServer>;
170
- //#endregion
171
- //#region src/wait-for-url.d.ts
172
- /**
173
- * Waits for a URL to become available by periodically checking its accessibility.
174
- * This is useful when a file has just been uploaded and may not be immediately
175
- * accessible due to CDN propagation or storage consistency delays.
176
- *
177
- * @param url - The URL to check for availability
178
- * @param options - Configuration options
179
- * @param options.maxWaitTime - Maximum time to wait in milliseconds (default: 10000)
180
- * @param options.retryDelay - Delay between retries in milliseconds (default: 500)
181
- * @returns Effect that succeeds when URL is available or fails with UploadistaError
182
- */
183
- declare function waitForUrlAvailability(url: string, options?: {
184
- maxWaitTime?: number;
185
- retryDelay?: number;
186
- }): Effect.Effect<void, UploadistaError>;
187
- //#endregion
188
- export { createDescribeImageNode, createOptimizeNode, createRemoveBackgroundNode, createResizeNode, waitForUrlAvailability };
189
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-node.ts","../src/wait-for-url.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;iBAagB,uBAAA;;;;IAEkC,MAAA,CAAA,8BAAA;;;;;IAFlC,IAAA,EAAA,MAAA;IAEZ,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;2BAA8C;;EAAA,YAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,GAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ECQlC,IAAA,CAAA,EAAA;IAEZ,MAAA,EAAA,MAAA;IAAS,MAAA,EAAA,MAAA;IAAU,KAAA,EAAA,MAAA;;;;;;;IAAc,IAAA,EAAA,MAAA;IAAA,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ECZrB,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAEZ,QAAA,CAAA,QAAA,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,GAAA,SAAA;;;;sBAA8C,SAAA;;;IAAA,MAAA,EAAA,MAAA;IAAA,MAAA,EAAA,MAAA;;;;ECRlC,QAAA,EAAA;IAEZ,WAAA,EAAA,MAAA;EAAO,CAAA;EAAQ,IAAA,EAAA;IAAO,MAAA,EAAA,MAAA;;;;;;;IAAY,EAAA,EAAA,MAAA;IAAA,IAAA,EAAA,MAAA;;;;ECKtB,CAAA;;;;;;;;;;iBHSA,kBAAA;;;GAEO,iBAAc,MAAA,CAAA,8BAAA;;;;;;;;IDZrB,MAAA,CAAA,EAAA,MAAA,GAAA,SAAuB;EAEnC,CAAA;;;;0BAA8C;;EAAA,QAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,iBAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ICQlC,KAAA,EAAA,MAAA;EAEZ,CAAA,GAAA,SAAA;CAAS,+EAAA,EAAA,KAAA,aAAA,wCAAA,CAAA;;;iBCZG,0BAAA;;;;IAEkC,MAAA,CAAA,8BAAA;;;;IFFlC,EAAA,EAAA,MAAA;IAEZ,IAAA,EAAA,MAAA;;;;;;EAA8C,QAAA,CAAA,QAAA,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,GAAA,SAAA;EAAA,YAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ECQlC,iBAAA,CAAA,EAAA,MAAkB,GAAA,SAAA;EAE9B,IAAA,CAAA,EAAA;IAAS,MAAA,EAAA,MAAA;IAAU,MAAA,EAAA,MAAA;;;;;;iBElBP,gBAAA;;;;GAEU,eAAY,MAAA,CAAA,8BAAA;;;;;;;;IHItB,MAAA,CAAA,EAAA,MAAA,GAAA,SAAuB;EAEnC,CAAA;;;;0BAA8C;;EAAA,QAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,iBAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;;;ICQlC,KAAA,EAAA,MAAA;EAEZ,CAAA,GAAA,SAAA;CAAS,+EAAA,EAAA,KAAA,aAAA,wCAAA,CAAA;;;;;;;;;;;ADZb;;;iBICgB,sBAAA;;;IAMb,MAAA,CAAO,aAAa"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["formatToMimeType: Record<OptimizeParams[\"format\"], string>","formatToExtension: Record<OptimizeParams[\"format\"], string>"],"sources":["../src/wait-for-url.ts","../src/describe-image-node.ts","../src/optimize-node.ts","../src/remove-background-node.ts","../src/resize-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 ImageAiPlugin,\n NodeType,\n resolveUploadMetadata,\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 }: { credentialId?: string } = {},\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 inputSchema: uploadFileSchema,\n outputSchema: uploadFileSchema,\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 { description } = 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 const { metadata } = resolveUploadMetadata(file.metadata);\n\n // add description to metadata\n const newMetadata = {\n ...file.metadata,\n ...metadata,\n description,\n };\n\n yield* Effect.logInfo(\n `Successfully described image for file ${file.id}`,\n );\n\n return completeNodeExecution(\n newMetadata\n ? {\n ...file,\n metadata: newMetadata,\n flow,\n }\n : file,\n );\n });\n },\n });\n });\n}\n","import {\n createTransformNode,\n ImagePlugin,\n type OptimizeParams,\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\nexport function createOptimizeNode(\n id: string,\n { quality, format }: OptimizeParams,\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n return yield* createTransformNode({\n id,\n name: \"Optimize\",\n description: \"Optimizes an image for web delivery\",\n transform: (inputBytes, file) =>\n Effect.map(\n imageService.optimize(inputBytes, { quality, format }),\n (optimizedBytes) => {\n // Return bytes with updated metadata if format changes\n const newType = formatToMimeType[format];\n const newExtension = formatToExtension[format];\n\n // Update file extension if format changed\n const fileName = file.metadata?.fileName;\n const newFileName =\n fileName && typeof fileName === \"string\"\n ? fileName.replace(/\\.[^.]+$/, `.${newExtension}`)\n : undefined;\n\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 });\n });\n}\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport {\n completeNodeExecution,\n createFlowNode,\n ImageAiPlugin,\n NodeType,\n resolveUploadMetadata,\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\nexport function createRemoveBackgroundNode(\n id: string,\n { credentialId }: { credentialId?: string } = {},\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 inputSchema: uploadFileSchema,\n outputSchema: uploadFileSchema,\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 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,\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 return completeNodeExecution(\n metadata\n ? {\n ...result,\n metadata,\n }\n : result,\n );\n });\n },\n });\n });\n}\n","import {\n createTransformNode,\n ImagePlugin,\n type ResizeParams,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\nexport function createResizeNode(\n id: string,\n { width, height, fit }: ResizeParams,\n) {\n return Effect.gen(function* () {\n const imageService = yield* ImagePlugin;\n\n return yield* createTransformNode({\n id,\n name: \"Resize\",\n description: \"Resizes an image to the specified dimensions\",\n transform: (inputBytes) =>\n imageService.resize(inputBytes, { height, width, fit }),\n });\n });\n}\n"],"mappings":"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"}