@uploadista/flow-utility-nodes 0.0.13-beta.4 → 0.0.13

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.
@@ -1,8 +1,11 @@
1
- import { a as MergeParams, r as MultiplexParams, s as ConditionalParams, t as ZipParams } from "../zip-node-BbFUu_Oc.cjs";
1
+ import { a as MergeParams, r as MultiplexParams, s as ConditionalParams, t as ZipParams } from "../zip-node-Brh9A17P.cjs";
2
+ import * as _uploadista_core_flow1 from "@uploadista/core/flow";
3
+ import { NodeType, ZipPlugin } from "@uploadista/core/flow";
4
+ import * as zod_v4_core0 from "zod/v4/core";
5
+ import * as zod0 from "zod";
6
+ import { z } from "zod";
2
7
  import * as _uploadista_core_errors0 from "@uploadista/core/errors";
3
8
  import { UploadistaError } from "@uploadista/core/errors";
4
- import * as _uploadista_core_flow2 from "@uploadista/core/flow";
5
- import { ZipPlugin } from "@uploadista/core/flow";
6
9
  import { UploadFile } from "@uploadista/core/types";
7
10
  import { Effect } from "effect";
8
11
  import { UploadServer } from "@uploadista/core/upload";
@@ -12,25 +15,129 @@ declare function createConditionalNode(id: string, {
12
15
  field,
13
16
  operator,
14
17
  value
15
- }: ConditionalParams): Effect.Effect<_uploadista_core_flow2.FlowNode<UploadFile, UploadFile, _uploadista_core_errors0.UploadistaError>, never, never>;
18
+ }: ConditionalParams): Effect.Effect<_uploadista_core_flow1.FlowNodeData & {
19
+ inputSchema: zod0.ZodType<UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<UploadFile, unknown>>;
20
+ outputSchema: zod0.ZodType<UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<UploadFile, unknown>>;
21
+ run: (args: {
22
+ data: UploadFile;
23
+ jobId: string;
24
+ storageId: string;
25
+ flowId: string;
26
+ inputs?: Record<string, unknown>;
27
+ clientId: string | null;
28
+ }) => Effect.Effect<_uploadista_core_flow1.NodeExecutionResult<UploadFile>, _uploadista_core_errors0.UploadistaError, never>;
29
+ condition?: {
30
+ field: string;
31
+ operator: string;
32
+ value: unknown;
33
+ };
34
+ multiInput?: boolean;
35
+ multiOutput?: boolean;
36
+ pausable?: boolean;
37
+ retry?: {
38
+ maxRetries?: number;
39
+ retryDelay?: number;
40
+ exponentialBackoff?: boolean;
41
+ };
42
+ } & {
43
+ type: NodeType;
44
+ }, never, never>;
16
45
  //#endregion
17
46
  //#region src/nodes/merge-node.d.ts
18
47
  declare function createMergeNode(id: string, {
19
48
  strategy,
20
49
  separator: _separator
21
- }: MergeParams): Effect.Effect<_uploadista_core_flow2.FlowNode<Record<string, UploadFile>, UploadFile, UploadistaError>, never, UploadServer>;
50
+ }: MergeParams): Effect.Effect<_uploadista_core_flow1.FlowNodeData & {
51
+ inputSchema: z.ZodType<Record<string, UploadFile>, unknown, z.core.$ZodTypeInternals<Record<string, UploadFile>, unknown>>;
52
+ outputSchema: z.ZodType<UploadFile, unknown, z.core.$ZodTypeInternals<UploadFile, unknown>>;
53
+ run: (args: {
54
+ data: Record<string, UploadFile>;
55
+ jobId: string;
56
+ storageId: string;
57
+ flowId: string;
58
+ inputs?: Record<string, unknown>;
59
+ clientId: string | null;
60
+ }) => Effect.Effect<_uploadista_core_flow1.NodeExecutionResult<UploadFile>, UploadistaError, never>;
61
+ condition?: {
62
+ field: string;
63
+ operator: string;
64
+ value: unknown;
65
+ };
66
+ multiInput?: boolean;
67
+ multiOutput?: boolean;
68
+ pausable?: boolean;
69
+ retry?: {
70
+ maxRetries?: number;
71
+ retryDelay?: number;
72
+ exponentialBackoff?: boolean;
73
+ };
74
+ } & {
75
+ type: NodeType;
76
+ }, never, UploadServer>;
22
77
  //#endregion
23
78
  //#region src/nodes/multiplex-node.d.ts
24
79
  declare function createMultiplexNode(id: string, {
25
80
  outputCount: _outputCount,
26
81
  strategy
27
- }: MultiplexParams): Effect.Effect<_uploadista_core_flow2.FlowNode<UploadFile, UploadFile, UploadistaError>, never, UploadServer>;
82
+ }: MultiplexParams): Effect.Effect<_uploadista_core_flow1.FlowNodeData & {
83
+ inputSchema: zod0.ZodType<UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<UploadFile, unknown>>;
84
+ outputSchema: zod0.ZodType<UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<UploadFile, unknown>>;
85
+ run: (args: {
86
+ data: UploadFile;
87
+ jobId: string;
88
+ storageId: string;
89
+ flowId: string;
90
+ inputs?: Record<string, unknown>;
91
+ clientId: string | null;
92
+ }) => Effect.Effect<_uploadista_core_flow1.NodeExecutionResult<UploadFile>, UploadistaError, never>;
93
+ condition?: {
94
+ field: string;
95
+ operator: string;
96
+ value: unknown;
97
+ };
98
+ multiInput?: boolean;
99
+ multiOutput?: boolean;
100
+ pausable?: boolean;
101
+ retry?: {
102
+ maxRetries?: number;
103
+ retryDelay?: number;
104
+ exponentialBackoff?: boolean;
105
+ };
106
+ } & {
107
+ type: NodeType;
108
+ }, never, UploadServer>;
28
109
  //#endregion
29
110
  //#region src/nodes/zip-node.d.ts
30
111
  declare function createZipNode(id: string, {
31
112
  zipName,
32
113
  includeMetadata
33
- }: ZipParams): Effect.Effect<_uploadista_core_flow2.FlowNode<Record<string, UploadFile>, UploadFile, UploadistaError>, never, UploadServer | ZipPlugin>;
114
+ }: ZipParams): Effect.Effect<_uploadista_core_flow1.FlowNodeData & {
115
+ inputSchema: z.ZodType<Record<string, UploadFile>, unknown, z.core.$ZodTypeInternals<Record<string, UploadFile>, unknown>>;
116
+ outputSchema: z.ZodType<UploadFile, unknown, z.core.$ZodTypeInternals<UploadFile, unknown>>;
117
+ run: (args: {
118
+ data: Record<string, UploadFile>;
119
+ jobId: string;
120
+ storageId: string;
121
+ flowId: string;
122
+ inputs?: Record<string, unknown>;
123
+ clientId: string | null;
124
+ }) => Effect.Effect<_uploadista_core_flow1.NodeExecutionResult<UploadFile>, UploadistaError, never>;
125
+ condition?: {
126
+ field: string;
127
+ operator: string;
128
+ value: unknown;
129
+ };
130
+ multiInput?: boolean;
131
+ multiOutput?: boolean;
132
+ pausable?: boolean;
133
+ retry?: {
134
+ maxRetries?: number;
135
+ retryDelay?: number;
136
+ exponentialBackoff?: boolean;
137
+ };
138
+ } & {
139
+ type: NodeType;
140
+ }, never, UploadServer | ZipPlugin>;
34
141
  //#endregion
35
142
  export { createConditionalNode, createMergeNode, createMultiplexNode, createZipNode };
36
143
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/nodes/conditional-node.ts","../../src/nodes/merge-node.ts","../../src/nodes/multiplex-node.ts","../../src/nodes/zip-node.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;iBASgB,qBAAA;;;;GAEc,oBAAiB,MAAA,CAAA,OAAA,sBAAA,CAAA,SAAA,YAAA,YAAA,wBAAA,CAAA,eAAA;;;iBCI/B,eAAA;;aAES;GAAc,cAAW,MAAA,CAAA,OAAA,sBAAA,CAAA,SAAA,eAAA,aAAA,YAAA,yBAAA;;;iBCLlC,mBAAA;eAEC;;GAA0B,kBAAe,MAAA,CAAA,OAAA,sBAAA,CAAA,SAAA,YAAA,YAAA,yBAAA;;;iBCE1C,aAAA;;;GAEgB,YAAS,MAAA,CAAA,OAAA,sBAAA,CAAA,SAAA,eAAA,aAAA,YAAA,yBAAA,eAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/nodes/conditional-node.ts","../../src/nodes/merge-node.ts","../../src/nodes/multiplex-node.ts","../../src/nodes/zip-node.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;iBASgB,qBAAA;;;;GAEc,oBAAiB,MAAA,CAAA,OAAA,sBAAA,CAAA,YAAA;;;;;;;;;IAF/B,QAAA,EAAA,MAAA,GAAA,IAAqB;EAEjC,CAAA,EAAA,gBAAA,2CAAA,WAAA,CAAA,4CAAA,KAAA,CAAA;EAAO,SAAA,CAAA,EAAA;IAAU,KAAA,EAAA,MAAA;IAAS,QAAA,EAAA,MAAA;IAAiB,KAAA,EAAA,OAAA;;;;;;;;;;;;;;;iBCI/B,eAAA;;aAES;GAAc,cAAW,MAAA,CAAA,OAAA,sBAAA,CAAA,YAAA;;;;;;IDRlC,SAAA,EAAA,MAAA;IAEZ,MAAA,EAAA,MAAA;IAAO,MAAA,CAAA,QAAA,CAAA,MAAA,EAAA,OAAA,CAAA;IAAU,QAAA,EAAA,MAAA,GAAA,IAAA;EAAS,CAAA,EAAA,gBAAA,2CAAA,WAAA,CAAA,iBAAA,EAAA,KAAA,CAAA;EAAiB,SAAA,CAAA,EAAA;;;;;;;;;;;;;;;;;;iBEC/B,mBAAA;eAEC;;GAA0B,kBAAe,MAAA,CAAA,OAAA,sBAAA,CAAA,YAAA;;;;;;;IFL1C,MAAA,EAAA,MAAA;IAEZ,MAAA,CAAA,QAAA,CAAA,MAAA,EAAA,OAAA,CAAA;IAAO,QAAA,EAAA,MAAA,GAAA,IAAA;EAAU,CAAA,EAAA,gBAAA,2CAAA,WAAA,CAAA,iBAAA,EAAA,KAAA,CAAA;EAAS,SAAA,CAAA,EAAA;IAAiB,KAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;iBGK/B,aAAA;;;GAEgB,YAAS,MAAA,CAAA,OAAA,sBAAA,CAAA,YAAA;;;;;;IHTzB,SAAA,EAAA,MAAA;IAEZ,MAAA,EAAA,MAAA;IAAO,MAAA,CAAA,QAAA,CAAA,MAAA,EAAA,OAAA,CAAA;IAAU,QAAA,EAAA,MAAA,GAAA,IAAA;EAAS,CAAA,EAAA,gBAAA,2CAAA,WAAA,CAAA,iBAAA,EAAA,KAAA,CAAA;EAAiB,SAAA,CAAA,EAAA"}
@@ -1,36 +1,143 @@
1
- import { a as MergeParams, r as MultiplexParams, s as ConditionalParams, t as ZipParams } from "../zip-node-bdgJgJHI.mjs";
1
+ import { a as MergeParams, r as MultiplexParams, s as ConditionalParams, t as ZipParams } from "../zip-node-7DDOD4H0.mjs";
2
2
  import * as _uploadista_core_flow1 from "@uploadista/core/flow";
3
- import { ZipPlugin } from "@uploadista/core/flow";
3
+ import { NodeType, ZipPlugin } from "@uploadista/core/flow";
4
4
  import { UploadFile } from "@uploadista/core/types";
5
5
  import { Effect } from "effect";
6
6
  import * as _uploadista_core_errors0 from "@uploadista/core/errors";
7
7
  import { UploadistaError } from "@uploadista/core/errors";
8
8
  import { UploadServer } from "@uploadista/core/upload";
9
+ import * as zod0 from "zod";
10
+ import { z } from "zod";
11
+ import * as zod_v4_core0 from "zod/v4/core";
9
12
 
10
13
  //#region src/nodes/conditional-node.d.ts
11
14
  declare function createConditionalNode(id: string, {
12
15
  field,
13
16
  operator,
14
17
  value
15
- }: ConditionalParams): Effect.Effect<_uploadista_core_flow1.FlowNode<UploadFile, UploadFile, _uploadista_core_errors0.UploadistaError>, never, never>;
18
+ }: ConditionalParams): Effect.Effect<_uploadista_core_flow1.FlowNodeData & {
19
+ inputSchema: zod0.ZodType<UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<UploadFile, unknown>>;
20
+ outputSchema: zod0.ZodType<UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<UploadFile, unknown>>;
21
+ run: (args: {
22
+ data: UploadFile;
23
+ jobId: string;
24
+ storageId: string;
25
+ flowId: string;
26
+ inputs?: Record<string, unknown>;
27
+ clientId: string | null;
28
+ }) => Effect.Effect<_uploadista_core_flow1.NodeExecutionResult<UploadFile>, _uploadista_core_errors0.UploadistaError, never>;
29
+ condition?: {
30
+ field: string;
31
+ operator: string;
32
+ value: unknown;
33
+ };
34
+ multiInput?: boolean;
35
+ multiOutput?: boolean;
36
+ pausable?: boolean;
37
+ retry?: {
38
+ maxRetries?: number;
39
+ retryDelay?: number;
40
+ exponentialBackoff?: boolean;
41
+ };
42
+ } & {
43
+ type: NodeType;
44
+ }, never, never>;
16
45
  //#endregion
17
46
  //#region src/nodes/merge-node.d.ts
18
47
  declare function createMergeNode(id: string, {
19
48
  strategy,
20
49
  separator: _separator
21
- }: MergeParams): Effect.Effect<_uploadista_core_flow1.FlowNode<Record<string, UploadFile>, UploadFile, UploadistaError>, never, UploadServer>;
50
+ }: MergeParams): Effect.Effect<_uploadista_core_flow1.FlowNodeData & {
51
+ inputSchema: z.ZodType<Record<string, UploadFile>, unknown, z.core.$ZodTypeInternals<Record<string, UploadFile>, unknown>>;
52
+ outputSchema: z.ZodType<UploadFile, unknown, z.core.$ZodTypeInternals<UploadFile, unknown>>;
53
+ run: (args: {
54
+ data: Record<string, UploadFile>;
55
+ jobId: string;
56
+ storageId: string;
57
+ flowId: string;
58
+ inputs?: Record<string, unknown>;
59
+ clientId: string | null;
60
+ }) => Effect.Effect<_uploadista_core_flow1.NodeExecutionResult<UploadFile>, UploadistaError, never>;
61
+ condition?: {
62
+ field: string;
63
+ operator: string;
64
+ value: unknown;
65
+ };
66
+ multiInput?: boolean;
67
+ multiOutput?: boolean;
68
+ pausable?: boolean;
69
+ retry?: {
70
+ maxRetries?: number;
71
+ retryDelay?: number;
72
+ exponentialBackoff?: boolean;
73
+ };
74
+ } & {
75
+ type: NodeType;
76
+ }, never, UploadServer>;
22
77
  //#endregion
23
78
  //#region src/nodes/multiplex-node.d.ts
24
79
  declare function createMultiplexNode(id: string, {
25
80
  outputCount: _outputCount,
26
81
  strategy
27
- }: MultiplexParams): Effect.Effect<_uploadista_core_flow1.FlowNode<UploadFile, UploadFile, UploadistaError>, never, UploadServer>;
82
+ }: MultiplexParams): Effect.Effect<_uploadista_core_flow1.FlowNodeData & {
83
+ inputSchema: zod0.ZodType<UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<UploadFile, unknown>>;
84
+ outputSchema: zod0.ZodType<UploadFile, unknown, zod_v4_core0.$ZodTypeInternals<UploadFile, unknown>>;
85
+ run: (args: {
86
+ data: UploadFile;
87
+ jobId: string;
88
+ storageId: string;
89
+ flowId: string;
90
+ inputs?: Record<string, unknown>;
91
+ clientId: string | null;
92
+ }) => Effect.Effect<_uploadista_core_flow1.NodeExecutionResult<UploadFile>, UploadistaError, never>;
93
+ condition?: {
94
+ field: string;
95
+ operator: string;
96
+ value: unknown;
97
+ };
98
+ multiInput?: boolean;
99
+ multiOutput?: boolean;
100
+ pausable?: boolean;
101
+ retry?: {
102
+ maxRetries?: number;
103
+ retryDelay?: number;
104
+ exponentialBackoff?: boolean;
105
+ };
106
+ } & {
107
+ type: NodeType;
108
+ }, never, UploadServer>;
28
109
  //#endregion
29
110
  //#region src/nodes/zip-node.d.ts
30
111
  declare function createZipNode(id: string, {
31
112
  zipName,
32
113
  includeMetadata
33
- }: ZipParams): Effect.Effect<_uploadista_core_flow1.FlowNode<Record<string, UploadFile>, UploadFile, UploadistaError>, never, UploadServer | ZipPlugin>;
114
+ }: ZipParams): Effect.Effect<_uploadista_core_flow1.FlowNodeData & {
115
+ inputSchema: z.ZodType<Record<string, UploadFile>, unknown, z.core.$ZodTypeInternals<Record<string, UploadFile>, unknown>>;
116
+ outputSchema: z.ZodType<UploadFile, unknown, z.core.$ZodTypeInternals<UploadFile, unknown>>;
117
+ run: (args: {
118
+ data: Record<string, UploadFile>;
119
+ jobId: string;
120
+ storageId: string;
121
+ flowId: string;
122
+ inputs?: Record<string, unknown>;
123
+ clientId: string | null;
124
+ }) => Effect.Effect<_uploadista_core_flow1.NodeExecutionResult<UploadFile>, UploadistaError, never>;
125
+ condition?: {
126
+ field: string;
127
+ operator: string;
128
+ value: unknown;
129
+ };
130
+ multiInput?: boolean;
131
+ multiOutput?: boolean;
132
+ pausable?: boolean;
133
+ retry?: {
134
+ maxRetries?: number;
135
+ retryDelay?: number;
136
+ exponentialBackoff?: boolean;
137
+ };
138
+ } & {
139
+ type: NodeType;
140
+ }, never, UploadServer | ZipPlugin>;
34
141
  //#endregion
35
142
  export { createConditionalNode, createMergeNode, createMultiplexNode, createZipNode };
36
143
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/nodes/conditional-node.ts","../../src/nodes/merge-node.ts","../../src/nodes/multiplex-node.ts","../../src/nodes/zip-node.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;iBASgB,qBAAA;;;;GAEc,oBAAiB,MAAA,CAAA,OAAA,sBAAA,CAAA,SAAA,YAAA,YAAA,wBAAA,CAAA,eAAA;;;iBCI/B,eAAA;;aAES;GAAc,cAAW,MAAA,CAAA,OAAA,sBAAA,CAAA,SAAA,eAAA,aAAA,YAAA,yBAAA;;;iBCLlC,mBAAA;eAEC;;GAA0B,kBAAe,MAAA,CAAA,OAAA,sBAAA,CAAA,SAAA,YAAA,YAAA,yBAAA;;;iBCE1C,aAAA;;;GAEgB,YAAS,MAAA,CAAA,OAAA,sBAAA,CAAA,SAAA,eAAA,aAAA,YAAA,yBAAA,eAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/nodes/conditional-node.ts","../../src/nodes/merge-node.ts","../../src/nodes/multiplex-node.ts","../../src/nodes/zip-node.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;iBASgB,qBAAA;;;;GAEc,oBAAiB,MAAA,CAAA,OAAA,sBAAA,CAAA,YAAA;;;;;;;;;IAF/B,QAAA,EAAA,MAAA,GAAA,IAAqB;EAEjC,CAAA,EAAA,gBAAA,2CAAA,WAAA,CAAA,4CAAA,KAAA,CAAA;EAAO,SAAA,CAAA,EAAA;IAAU,KAAA,EAAA,MAAA;IAAS,QAAA,EAAA,MAAA;IAAiB,KAAA,EAAA,OAAA;;;;;;;;;;;;;;;iBCI/B,eAAA;;aAES;GAAc,cAAW,MAAA,CAAA,OAAA,sBAAA,CAAA,YAAA;;;;;;IDRlC,SAAA,EAAA,MAAA;IAEZ,MAAA,EAAA,MAAA;IAAO,MAAA,CAAA,QAAA,CAAA,MAAA,EAAA,OAAA,CAAA;IAAU,QAAA,EAAA,MAAA,GAAA,IAAA;EAAS,CAAA,EAAA,gBAAA,2CAAA,WAAA,CAAA,iBAAA,EAAA,KAAA,CAAA;EAAiB,SAAA,CAAA,EAAA;;;;;;;;;;;;;;;;;;iBEC/B,mBAAA;eAEC;;GAA0B,kBAAe,MAAA,CAAA,OAAA,sBAAA,CAAA,YAAA;;;;;;;IFL1C,MAAA,EAAA,MAAA;IAEZ,MAAA,CAAA,QAAA,CAAA,MAAA,EAAA,OAAA,CAAA;IAAO,QAAA,EAAA,MAAA,GAAA,IAAA;EAAU,CAAA,EAAA,gBAAA,2CAAA,WAAA,CAAA,iBAAA,EAAA,KAAA,CAAA;EAAS,SAAA,CAAA,EAAA;IAAiB,KAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;iBGK/B,aAAA;;;GAEgB,YAAS,MAAA,CAAA,OAAA,sBAAA,CAAA,YAAA;;;;;;IHTzB,SAAA,EAAA,MAAA;IAEZ,MAAA,EAAA,MAAA;IAAO,MAAA,CAAA,QAAA,CAAA,MAAA,EAAA,OAAA,CAAA;IAAU,QAAA,EAAA,MAAA,GAAA,IAAA;EAAS,CAAA,EAAA,gBAAA,2CAAA,WAAA,CAAA,iBAAA,EAAA,KAAA,CAAA;EAAiB,SAAA,CAAA,EAAA"}
@@ -1,2 +1,2 @@
1
- import { a as MergeParams, c as conditionalParamsSchema, i as multiplexParamsSchema, n as zipParamsSchema, o as mergeParamsSchema, r as MultiplexParams, s as ConditionalParams, t as ZipParams } from "../zip-node-BbFUu_Oc.cjs";
1
+ import { a as MergeParams, c as conditionalParamsSchema, i as multiplexParamsSchema, n as zipParamsSchema, o as mergeParamsSchema, r as MultiplexParams, s as ConditionalParams, t as ZipParams } from "../zip-node-Brh9A17P.cjs";
2
2
  export { ConditionalParams, MergeParams, MultiplexParams, ZipParams, conditionalParamsSchema, mergeParamsSchema, multiplexParamsSchema, zipParamsSchema };
@@ -1,2 +1,2 @@
1
- import { a as MergeParams, c as conditionalParamsSchema, i as multiplexParamsSchema, n as zipParamsSchema, o as mergeParamsSchema, r as MultiplexParams, s as ConditionalParams, t as ZipParams } from "../zip-node-bdgJgJHI.mjs";
1
+ import { a as MergeParams, c as conditionalParamsSchema, i as multiplexParamsSchema, n as zipParamsSchema, o as mergeParamsSchema, r as MultiplexParams, s as ConditionalParams, t as ZipParams } from "../zip-node-7DDOD4H0.mjs";
2
2
  export { ConditionalParams, MergeParams, MultiplexParams, ZipParams, conditionalParamsSchema, mergeParamsSchema, multiplexParamsSchema, zipParamsSchema };
@@ -3,19 +3,19 @@ import { z } from "zod";
3
3
  //#region src/types/conditional-node.d.ts
4
4
  declare const conditionalParamsSchema: z.ZodObject<{
5
5
  field: z.ZodEnum<{
6
- size: "size";
7
6
  mimeType: "mimeType";
7
+ size: "size";
8
8
  width: "width";
9
9
  height: "height";
10
10
  extension: "extension";
11
11
  }>;
12
12
  operator: z.ZodEnum<{
13
- startsWith: "startsWith";
14
13
  equals: "equals";
15
14
  notEquals: "notEquals";
16
15
  greaterThan: "greaterThan";
17
16
  lessThan: "lessThan";
18
17
  contains: "contains";
18
+ startsWith: "startsWith";
19
19
  }>;
20
20
  value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
21
21
  }, z.core.$strip>;
@@ -36,8 +36,8 @@ type MergeParams = z.infer<typeof mergeParamsSchema>;
36
36
  declare const multiplexParamsSchema: z.ZodObject<{
37
37
  outputCount: z.ZodNumber;
38
38
  strategy: z.ZodDefault<z.ZodEnum<{
39
- split: "split";
40
39
  copy: "copy";
40
+ split: "split";
41
41
  }>>;
42
42
  }, z.core.$strip>;
43
43
  type MultiplexParams = z.infer<typeof multiplexParamsSchema>;
@@ -51,4 +51,4 @@ declare const zipParamsSchema: z.ZodObject<{
51
51
  type ZipParams = z.infer<typeof zipParamsSchema>;
52
52
  //#endregion
53
53
  export { MergeParams as a, conditionalParamsSchema as c, multiplexParamsSchema as i, zipParamsSchema as n, mergeParamsSchema as o, MultiplexParams as r, ConditionalParams as s, ZipParams as t };
54
- //# sourceMappingURL=zip-node-BbFUu_Oc.d.cts.map
54
+ //# sourceMappingURL=zip-node-7DDOD4H0.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"zip-node-BbFUu_Oc.d.cts","names":[],"sources":["../src/types/conditional-node.ts","../src/types/merge-node.ts","../src/types/multiplex-node.ts","../src/types/zip-node.ts"],"sourcesContent":[],"mappings":";;;cAEa,yBAAuB,CAAA,CAAA;;IAAvB,IAAA,EAAA,MAAA;;;;;;;IAAuB,UAAA,EAAA,YAAA;IAAA,MAAA,EAAA,QAAA;IAaxB,SAAA,EAAA,WAAiB;;;;ECbhB,CAAA,CAAA;;;KDaD,iBAAA,GAAoB,CAAA,CAAE,aAAa;;;cCblC,mBAAiB,CAAA,CAAA;;IDAjB,MAAA,EAAA,QAAA;;;;;;KCMD,WAAA,GAAc,CAAA,CAAE,aAAa;;;cCN5B,uBAAqB,CAAA,CAAA;;EFArB,QAAA,cAAA,UAWX,CAAA;;;;;KENU,eAAA,GAAkB,CAAA,CAAE,aAAa;;;cCLhC,iBAAe,CAAA,CAAA;;EHAf,eAAA,cAWX,aAAA,CAAA;;;KGLU,SAAA,GAAY,CAAA,CAAE,aAAa"}
1
+ {"version":3,"file":"zip-node-7DDOD4H0.d.mts","names":[],"sources":["../src/types/conditional-node.ts","../src/types/merge-node.ts","../src/types/multiplex-node.ts","../src/types/zip-node.ts"],"sourcesContent":[],"mappings":";;;cAEa,yBAAuB,CAAA,CAAA;;IAAvB,QAAA,EAAA,UAAA;;;;;;;IAAuB,MAAA,EAAA,QAAA;IAAA,SAAA,EAAA,WAAA;IAaxB,WAAA,EAAA,aAAiB;;;;ECbhB,CAAA,CAAA;;;KDaD,iBAAA,GAAoB,CAAA,CAAE,aAAa;;;cCblC,mBAAiB,CAAA,CAAA;;IDAjB,MAAA,EAAA,QAAA;;;;;;KCMD,WAAA,GAAc,CAAA,CAAE,aAAa;;;cCN5B,uBAAqB,CAAA,CAAA;;EFArB,QAAA,cAAA,UAWX,CAAA;;;;;KENU,eAAA,GAAkB,CAAA,CAAE,aAAa;;;cCLhC,iBAAe,CAAA,CAAA;;EHAf,eAAA,cAWX,aAAA,CAAA;;;KGLU,SAAA,GAAY,CAAA,CAAE,aAAa"}
@@ -3,19 +3,19 @@ import { z } from "zod";
3
3
  //#region src/types/conditional-node.d.ts
4
4
  declare const conditionalParamsSchema: z.ZodObject<{
5
5
  field: z.ZodEnum<{
6
- size: "size";
7
6
  mimeType: "mimeType";
7
+ size: "size";
8
8
  width: "width";
9
9
  height: "height";
10
10
  extension: "extension";
11
11
  }>;
12
12
  operator: z.ZodEnum<{
13
- startsWith: "startsWith";
14
13
  equals: "equals";
15
14
  notEquals: "notEquals";
16
15
  greaterThan: "greaterThan";
17
16
  lessThan: "lessThan";
18
17
  contains: "contains";
18
+ startsWith: "startsWith";
19
19
  }>;
20
20
  value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
21
21
  }, z.core.$strip>;
@@ -36,8 +36,8 @@ type MergeParams = z.infer<typeof mergeParamsSchema>;
36
36
  declare const multiplexParamsSchema: z.ZodObject<{
37
37
  outputCount: z.ZodNumber;
38
38
  strategy: z.ZodDefault<z.ZodEnum<{
39
- split: "split";
40
39
  copy: "copy";
40
+ split: "split";
41
41
  }>>;
42
42
  }, z.core.$strip>;
43
43
  type MultiplexParams = z.infer<typeof multiplexParamsSchema>;
@@ -51,4 +51,4 @@ declare const zipParamsSchema: z.ZodObject<{
51
51
  type ZipParams = z.infer<typeof zipParamsSchema>;
52
52
  //#endregion
53
53
  export { MergeParams as a, conditionalParamsSchema as c, multiplexParamsSchema as i, zipParamsSchema as n, mergeParamsSchema as o, MultiplexParams as r, ConditionalParams as s, ZipParams as t };
54
- //# sourceMappingURL=zip-node-bdgJgJHI.d.mts.map
54
+ //# sourceMappingURL=zip-node-Brh9A17P.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"zip-node-bdgJgJHI.d.mts","names":[],"sources":["../src/types/conditional-node.ts","../src/types/merge-node.ts","../src/types/multiplex-node.ts","../src/types/zip-node.ts"],"sourcesContent":[],"mappings":";;;cAEa,yBAAuB,CAAA,CAAA;;IAAvB,IAAA,EAAA,MAAA;;;;;;;IAAuB,UAAA,EAAA,YAAA;IAAA,MAAA,EAAA,QAAA;IAaxB,SAAA,EAAA,WAAiB;;;;ECbhB,CAAA,CAAA;;;KDaD,iBAAA,GAAoB,CAAA,CAAE,aAAa;;;cCblC,mBAAiB,CAAA,CAAA;;IDAjB,MAAA,EAAA,QAAA;;;;;;KCMD,WAAA,GAAc,CAAA,CAAE,aAAa;;;cCN5B,uBAAqB,CAAA,CAAA;;EFArB,QAAA,cAAA,UAWX,CAAA;;;;;KENU,eAAA,GAAkB,CAAA,CAAE,aAAa;;;cCLhC,iBAAe,CAAA,CAAA;;EHAf,eAAA,cAWX,aAAA,CAAA;;;KGLU,SAAA,GAAY,CAAA,CAAE,aAAa"}
1
+ {"version":3,"file":"zip-node-Brh9A17P.d.cts","names":[],"sources":["../src/types/conditional-node.ts","../src/types/merge-node.ts","../src/types/multiplex-node.ts","../src/types/zip-node.ts"],"sourcesContent":[],"mappings":";;;cAEa,yBAAuB,CAAA,CAAA;;IAAvB,QAAA,EAAA,UAAA;;;;;;;IAAuB,MAAA,EAAA,QAAA;IAAA,SAAA,EAAA,WAAA;IAaxB,WAAA,EAAA,aAAiB;;;;ECbhB,CAAA,CAAA;;;KDaD,iBAAA,GAAoB,CAAA,CAAE,aAAa;;;cCblC,mBAAiB,CAAA,CAAA;;IDAjB,MAAA,EAAA,QAAA;;;;;;KCMD,WAAA,GAAc,CAAA,CAAE,aAAa;;;cCN5B,uBAAqB,CAAA,CAAA;;EFArB,QAAA,cAAA,UAWX,CAAA;;;;;KENU,eAAA,GAAkB,CAAA,CAAE,aAAa;;;cCLhC,iBAAe,CAAA,CAAA;;EHAf,eAAA,cAWX,aAAA,CAAA;;;KGLU,SAAA,GAAY,CAAA,CAAE,aAAa"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uploadista/flow-utility-nodes",
3
3
  "type": "module",
4
- "version": "0.0.13-beta.4",
4
+ "version": "0.0.13",
5
5
  "description": "Utility nodes for Uploadista Flow",
6
6
  "license": "MIT",
7
7
  "author": "Uploadista",
@@ -20,19 +20,24 @@
20
20
  }
21
21
  },
22
22
  "dependencies": {
23
- "effect": "3.19.2",
23
+ "effect": "3.19.3",
24
24
  "zod": "4.1.12",
25
- "@uploadista/core": "0.0.13-beta.4"
25
+ "@uploadista/core": "0.0.13"
26
26
  },
27
27
  "devDependencies": {
28
- "@types/node": "24.10.0",
29
- "tsdown": "0.16.0",
30
- "@uploadista/typescript-config": "0.0.13-beta.4"
28
+ "@effect/vitest": "0.27.0",
29
+ "@types/node": "24.10.1",
30
+ "tsdown": "0.16.3",
31
+ "vitest": "4.0.8",
32
+ "@uploadista/typescript-config": "0.0.13"
31
33
  },
32
34
  "scripts": {
33
35
  "build": "tsdown",
36
+ "check": "biome check --write ./src",
34
37
  "format": "biome format --write ./src",
35
38
  "lint": "biome lint --write ./src",
36
- "check": "biome check --write ./src"
39
+ "test": "vitest",
40
+ "test:run": "vitest run",
41
+ "test:watch": "vitest --watch"
37
42
  }
38
43
  }
@@ -0,0 +1,779 @@
1
+ import { describe, expect, it } from "@effect/vitest";
2
+ import { UploadistaError } from "@uploadista/core/errors";
3
+ import {
4
+ TestUploadServer,
5
+ TestZipPlugin,
6
+ } from "@uploadista/core/testing";
7
+ import type { UploadFile } from "@uploadista/core/types";
8
+ import { Effect, Layer } from "effect";
9
+ import {
10
+ createConditionalNode,
11
+ createMergeNode,
12
+ createMultiplexNode,
13
+ createZipNode,
14
+ } from "../src/nodes";
15
+
16
+ /**
17
+ * Test utilities for creating sample UploadFile objects
18
+ */
19
+ const createTestUploadFile = (
20
+ id: string,
21
+ overrides?: Partial<UploadFile>,
22
+ ): UploadFile => ({
23
+ id,
24
+ offset: 0,
25
+ size: 1024,
26
+ storage: {
27
+ id: "test-storage",
28
+ type: "memory",
29
+ },
30
+ metadata: {
31
+ mimeType: "text/plain",
32
+ originalName: `file-${id}.txt`,
33
+ extension: "txt",
34
+ },
35
+ creationDate: new Date().toISOString(),
36
+ ...overrides,
37
+ });
38
+
39
+ const createTestImageFile = (
40
+ id: string,
41
+ width: number,
42
+ height: number,
43
+ ): UploadFile =>
44
+ createTestUploadFile(id, {
45
+ metadata: {
46
+ mimeType: "image/jpeg",
47
+ originalName: `image-${id}.jpg`,
48
+ extension: "jpg",
49
+ width,
50
+ height,
51
+ },
52
+ });
53
+
54
+ /**
55
+ * Test layer combining all mocks
56
+ */
57
+ const TestLayer = Layer.mergeAll(TestUploadServer, TestZipPlugin);
58
+
59
+ describe("Utility Nodes", () => {
60
+ describe("ConditionalNode", () => {
61
+ it.effect("should create conditional node with correct properties", () =>
62
+ Effect.gen(function* () {
63
+ const node = yield* createConditionalNode("cond-1", {
64
+ field: "mimeType",
65
+ operator: "equals",
66
+ value: "image/jpeg",
67
+ });
68
+
69
+ expect(node.id).toBe("cond-1");
70
+ expect(node.name).toBe("Conditional Router");
71
+ expect(node.description).toContain("Routes flow based on");
72
+ expect(node.condition).toEqual({
73
+ field: "mimeType",
74
+ operator: "equals",
75
+ value: "image/jpeg",
76
+ });
77
+ }),
78
+ );
79
+
80
+ it.effect("should pass through data unchanged", () =>
81
+ Effect.gen(function* () {
82
+ const node = yield* createConditionalNode("cond-2", {
83
+ field: "size",
84
+ operator: "greaterThan",
85
+ value: 1000,
86
+ });
87
+
88
+ const testFile = createTestUploadFile("test-1");
89
+ const result = yield* node.run({
90
+ data: testFile,
91
+ jobId: "test-job",
92
+ flowId: "test-flow",
93
+ storageId: "test-storage",
94
+ clientId: "test-client",
95
+ });
96
+
97
+ expect(result.type).toBe("complete");
98
+ if (result.type === "complete") {
99
+ expect(result.data).toEqual(testFile);
100
+ }
101
+ }),
102
+ );
103
+
104
+ it.effect("should create node with equals operator", () =>
105
+ Effect.gen(function* () {
106
+ const node = yield* createConditionalNode("cond-equals", {
107
+ field: "extension",
108
+ operator: "equals",
109
+ value: "jpg",
110
+ });
111
+
112
+ expect(node.condition?.operator).toBe("equals");
113
+ }),
114
+ );
115
+
116
+ it.effect("should create node with notEquals operator", () =>
117
+ Effect.gen(function* () {
118
+ const node = yield* createConditionalNode("cond-not-equals", {
119
+ field: "mimeType",
120
+ operator: "notEquals",
121
+ value: "image/png",
122
+ });
123
+
124
+ expect(node.condition?.operator).toBe("notEquals");
125
+ }),
126
+ );
127
+
128
+ it.effect("should create node with greaterThan operator", () =>
129
+ Effect.gen(function* () {
130
+ const node = yield* createConditionalNode("cond-gt", {
131
+ field: "size",
132
+ operator: "greaterThan",
133
+ value: 5000,
134
+ });
135
+
136
+ expect(node.condition?.operator).toBe("greaterThan");
137
+ expect(node.condition?.value).toBe(5000);
138
+ }),
139
+ );
140
+
141
+ it.effect("should create node with lessThan operator", () =>
142
+ Effect.gen(function* () {
143
+ const node = yield* createConditionalNode("cond-lt", {
144
+ field: "width",
145
+ operator: "lessThan",
146
+ value: 1920,
147
+ });
148
+
149
+ expect(node.condition?.operator).toBe("lessThan");
150
+ }),
151
+ );
152
+
153
+ it.effect("should create node with contains operator", () =>
154
+ Effect.gen(function* () {
155
+ const node = yield* createConditionalNode("cond-contains", {
156
+ field: "mimeType",
157
+ operator: "contains",
158
+ value: "image",
159
+ });
160
+
161
+ expect(node.condition?.operator).toBe("contains");
162
+ }),
163
+ );
164
+
165
+ it.effect("should create node with startsWith operator", () =>
166
+ Effect.gen(function* () {
167
+ const node = yield* createConditionalNode("cond-starts", {
168
+ field: "extension",
169
+ operator: "startsWith",
170
+ value: "jp",
171
+ });
172
+
173
+ expect(node.condition?.operator).toBe("startsWith");
174
+ }),
175
+ );
176
+
177
+ it.effect("should work with different field types", () =>
178
+ Effect.gen(function* () {
179
+ const fields: Array<
180
+ "mimeType" | "size" | "width" | "height" | "extension"
181
+ > = ["mimeType", "size", "width", "height", "extension"];
182
+
183
+ for (const field of fields) {
184
+ const node = yield* createConditionalNode(`cond-${field}`, {
185
+ field,
186
+ operator: "equals",
187
+ value: field === "size" ? 1000 : "test",
188
+ });
189
+
190
+ expect(node.condition?.field).toBe(field);
191
+ }
192
+ }),
193
+ );
194
+ });
195
+
196
+ describe("MergeNode", () => {
197
+ it.effect("should merge multiple files using concat strategy", () =>
198
+ Effect.gen(function* () {
199
+ const node = yield* createMergeNode("merge-1", {
200
+ strategy: "concat",
201
+ });
202
+
203
+ const file1 = createTestUploadFile("file-1");
204
+ const file2 = createTestUploadFile("file-2");
205
+ const file3 = createTestUploadFile("file-3");
206
+
207
+ const result = yield* node.run({
208
+ data: {
209
+ input1: file1,
210
+ input2: file2,
211
+ input3: file3,
212
+ },
213
+ jobId: "test-job",
214
+ flowId: "test-flow",
215
+ storageId: "test-storage",
216
+ clientId: "test-client",
217
+ });
218
+
219
+ expect(result.type).toBe("complete");
220
+ if (result.type === "complete") {
221
+ expect(result.data).toBeDefined();
222
+ if (result.data) {
223
+ expect(result.data.metadata?.mimeType).toBe(
224
+ "application/octet-stream",
225
+ );
226
+ expect(result.data.metadata?.extension).toBe("bin");
227
+ expect(result.data.size).toBeGreaterThan(0);
228
+ }
229
+ }
230
+ }).pipe(Effect.provide(TestLayer)),
231
+ );
232
+
233
+ it.effect("should handle single file input", () =>
234
+ Effect.gen(function* () {
235
+ const node = yield* createMergeNode("merge-single", {
236
+ strategy: "concat",
237
+ });
238
+
239
+ const file1 = createTestUploadFile("single-file");
240
+
241
+ const result = yield* node.run({
242
+ data: {
243
+ input1: file1,
244
+ },
245
+ jobId: "test-job",
246
+ flowId: "test-flow",
247
+ storageId: "test-storage",
248
+ clientId: "test-client",
249
+ });
250
+
251
+ expect(result.type).toBe("complete");
252
+ if (result.type === "complete") {
253
+ expect(result.data).toBeDefined();
254
+ expect(result.data.metadata?.mimeType).toBe(
255
+ "application/octet-stream",
256
+ );
257
+ }
258
+ }).pipe(Effect.provide(TestLayer)),
259
+ );
260
+
261
+ it.effect("should fail with no inputs", () =>
262
+ Effect.gen(function* () {
263
+ const node = yield* createMergeNode("merge-empty", {
264
+ strategy: "concat",
265
+ });
266
+
267
+ const result = yield* Effect.either(
268
+ node.run({
269
+ data: {},
270
+ jobId: "test-job",
271
+ flowId: "test-flow",
272
+ storageId: "test-storage",
273
+ clientId: "test-client",
274
+ }),
275
+ );
276
+
277
+ expect(result._tag).toBe("Left");
278
+ if (result._tag === "Left") {
279
+ expect(result.left).toBeInstanceOf(UploadistaError);
280
+ expect(result.left.code).toBe("VALIDATION_ERROR");
281
+ }
282
+ }).pipe(Effect.provide(TestLayer)),
283
+ );
284
+
285
+ it.effect("should fail with null inputs", () =>
286
+ Effect.gen(function* () {
287
+ const node = yield* createMergeNode("merge-null", {
288
+ strategy: "concat",
289
+ });
290
+
291
+ const result = yield* Effect.either(
292
+ node.run({
293
+ data: null as any,
294
+ jobId: "test-job",
295
+ flowId: "test-flow",
296
+ storageId: "test-storage",
297
+ clientId: "test-client",
298
+ }),
299
+ );
300
+
301
+ expect(result._tag).toBe("Left");
302
+ }).pipe(Effect.provide(TestLayer)),
303
+ );
304
+
305
+ it.effect("should fail with unknown strategy", () =>
306
+ Effect.gen(function* () {
307
+ const node = yield* createMergeNode("merge-unknown", {
308
+ strategy: "unknown" as any,
309
+ });
310
+
311
+ const file1 = createTestUploadFile("file-1");
312
+
313
+ const result = yield* Effect.either(
314
+ node.run({
315
+ data: { input1: file1 },
316
+ jobId: "test-job",
317
+ flowId: "test-flow",
318
+ storageId: "test-storage",
319
+ clientId: "test-client",
320
+ }),
321
+ );
322
+
323
+ expect(result._tag).toBe("Left");
324
+ if (result._tag === "Left") {
325
+ expect(result.left).toBeInstanceOf(UploadistaError);
326
+ expect(result.left.body).toContain("Unknown merge strategy");
327
+ }
328
+ }).pipe(Effect.provide(TestLayer)),
329
+ );
330
+
331
+ it.effect("should preserve file order in concat", () =>
332
+ Effect.gen(function* () {
333
+ const node = yield* createMergeNode("merge-order", {
334
+ strategy: "concat",
335
+ });
336
+
337
+ const file1 = createTestUploadFile("first");
338
+ const file2 = createTestUploadFile("second");
339
+ const file3 = createTestUploadFile("third");
340
+
341
+ const result = yield* node.run({
342
+ data: {
343
+ a: file1,
344
+ b: file2,
345
+ c: file3,
346
+ },
347
+ jobId: "test-job",
348
+ flowId: "test-flow",
349
+ storageId: "test-storage",
350
+ clientId: "test-client",
351
+ });
352
+
353
+ expect(result.type).toBe("complete");
354
+ if (result.type === "complete") {
355
+ expect(result.data).toBeDefined();
356
+ expect(result.data.metadata?.originalName).toContain(
357
+ "merged_3_files",
358
+ );
359
+ }
360
+ }).pipe(Effect.provide(TestLayer)),
361
+ );
362
+
363
+ it.effect("should create node with proper metadata", () =>
364
+ Effect.gen(function* () {
365
+ const node = yield* createMergeNode("merge-meta", {
366
+ strategy: "concat",
367
+ });
368
+
369
+ expect(node.id).toBe("merge-meta");
370
+ expect(node.name).toBe("Merge Files");
371
+ expect(node.description).toContain("concat strategy");
372
+ expect(node.multiInput).toBe(true);
373
+ }).pipe(Effect.provide(TestLayer)),
374
+ );
375
+ });
376
+
377
+ describe("MultiplexNode", () => {
378
+ it.effect("should multiplex file using copy strategy", () =>
379
+ Effect.gen(function* () {
380
+ const node = yield* createMultiplexNode("multiplex-1", {
381
+ outputCount: 3,
382
+ strategy: "copy",
383
+ });
384
+
385
+ const testFile = createTestUploadFile("source-file");
386
+
387
+ const result = yield* node.run({
388
+ data: testFile,
389
+ jobId: "test-job",
390
+ flowId: "test-flow",
391
+ storageId: "test-storage",
392
+ clientId: "test-client",
393
+ });
394
+
395
+ expect(result.type).toBe("complete");
396
+ if (result.type === "complete") {
397
+ expect(result.data).toBeDefined();
398
+ expect(result.data.id).not.toBe(testFile.id);
399
+ expect(result.data.metadata?.mimeType).toBe("text/plain");
400
+ }
401
+ }).pipe(Effect.provide(TestLayer)),
402
+ );
403
+
404
+ it.effect("should preserve metadata when copying", () =>
405
+ Effect.gen(function* () {
406
+ const node = yield* createMultiplexNode("multiplex-meta", {
407
+ outputCount: 2,
408
+ strategy: "copy",
409
+ });
410
+
411
+ const testFile = createTestImageFile("image-1", 800, 600);
412
+
413
+ const result = yield* node.run({
414
+ data: testFile,
415
+ jobId: "test-job",
416
+ flowId: "test-flow",
417
+ storageId: "test-storage",
418
+ clientId: "test-client",
419
+ });
420
+
421
+ expect(result.type).toBe("complete");
422
+ if (result.type === "complete") {
423
+ expect(result.data.metadata?.mimeType).toBe("image/jpeg");
424
+ expect(result.data.metadata?.extension).toBe("jpg");
425
+ }
426
+ }).pipe(Effect.provide(TestLayer)),
427
+ );
428
+
429
+ it.effect("should handle metadata as string", () =>
430
+ Effect.gen(function* () {
431
+ const node = yield* createMultiplexNode("multiplex-string-meta", {
432
+ outputCount: 1,
433
+ strategy: "copy",
434
+ });
435
+
436
+ const testFile = createTestUploadFile("file-with-string-meta", {
437
+ metadata: {
438
+ mimeType: "application/pdf",
439
+ originalName: "document.pdf",
440
+ },
441
+ });
442
+
443
+ const result = yield* node.run({
444
+ data: testFile,
445
+ jobId: "test-job",
446
+ flowId: "test-flow",
447
+ storageId: "test-storage",
448
+ clientId: "test-client",
449
+ });
450
+
451
+ expect(result.type).toBe("complete");
452
+ if (result.type === "complete") {
453
+ expect(result.data).toBeDefined();
454
+ }
455
+ }).pipe(Effect.provide(TestLayer)),
456
+ );
457
+
458
+ it.effect("should fail with split strategy", () =>
459
+ Effect.gen(function* () {
460
+ const node = yield* createMultiplexNode("multiplex-split", {
461
+ outputCount: 2,
462
+ strategy: "split",
463
+ });
464
+
465
+ const testFile = createTestUploadFile("test-file");
466
+
467
+ const result = yield* Effect.either(
468
+ node.run({
469
+ data: testFile,
470
+ jobId: "test-job",
471
+ flowId: "test-flow",
472
+ storageId: "test-storage",
473
+ clientId: "test-client",
474
+ }),
475
+ );
476
+
477
+ expect(result._tag).toBe("Left");
478
+ if (result._tag === "Left") {
479
+ expect(result.left).toBeInstanceOf(UploadistaError);
480
+ expect(result.left.body).toContain("Split strategy is not supported");
481
+ }
482
+ }).pipe(Effect.provide(TestLayer)),
483
+ );
484
+
485
+ it.effect("should fail with unknown strategy", () =>
486
+ Effect.gen(function* () {
487
+ const node = yield* createMultiplexNode("multiplex-unknown", {
488
+ outputCount: 2,
489
+ strategy: "invalid" as any,
490
+ });
491
+
492
+ const testFile = createTestUploadFile("test-file");
493
+
494
+ const result = yield* Effect.either(
495
+ node.run({
496
+ data: testFile,
497
+ jobId: "test-job",
498
+ flowId: "test-flow",
499
+ storageId: "test-storage",
500
+ clientId: "test-client",
501
+ }),
502
+ );
503
+
504
+ expect(result._tag).toBe("Left");
505
+ if (result._tag === "Left") {
506
+ expect(result.left).toBeInstanceOf(UploadistaError);
507
+ expect(result.left.body).toContain("Unknown multiplex strategy");
508
+ }
509
+ }).pipe(Effect.provide(TestLayer)),
510
+ );
511
+
512
+ it.effect("should create node with proper metadata", () =>
513
+ Effect.gen(function* () {
514
+ const node = yield* createMultiplexNode("multiplex-props", {
515
+ outputCount: 5,
516
+ strategy: "copy",
517
+ });
518
+
519
+ expect(node.id).toBe("multiplex-props");
520
+ expect(node.name).toBe("Multiplex");
521
+ expect(node.description).toContain("copy strategy");
522
+ expect(node.multiOutput).toBe(true);
523
+ }).pipe(Effect.provide(TestLayer)),
524
+ );
525
+
526
+ it.effect("should handle large files", () =>
527
+ Effect.gen(function* () {
528
+ const node = yield* createMultiplexNode("multiplex-large", {
529
+ outputCount: 2,
530
+ strategy: "copy",
531
+ });
532
+
533
+ const largeFile = createTestUploadFile("large-file", {
534
+ size: 10 * 1024 * 1024, // 10MB
535
+ });
536
+
537
+ const result = yield* node.run({
538
+ data: largeFile,
539
+ jobId: "test-job",
540
+ flowId: "test-flow",
541
+ storageId: "test-storage",
542
+ clientId: "test-client",
543
+ });
544
+
545
+ expect(result.type).toBe("complete");
546
+ if (result.type === "complete") {
547
+ expect(result.data).toBeDefined();
548
+ }
549
+ }).pipe(Effect.provide(TestLayer)),
550
+ );
551
+ });
552
+
553
+ describe("ZipNode", () => {
554
+ it.effect("should create zip from multiple files", () =>
555
+ Effect.gen(function* () {
556
+ const node = yield* createZipNode("zip-1", {
557
+ zipName: "archive.zip",
558
+ includeMetadata: false,
559
+ });
560
+
561
+ const file1 = createTestUploadFile("file-1");
562
+ const file2 = createTestUploadFile("file-2");
563
+ const file3 = createTestUploadFile("file-3");
564
+
565
+ const result = yield* node.run({
566
+ data: {
567
+ input1: file1,
568
+ input2: file2,
569
+ input3: file3,
570
+ },
571
+ jobId: "test-job",
572
+ flowId: "test-flow",
573
+ storageId: "test-storage",
574
+ clientId: "test-client",
575
+ });
576
+
577
+ expect(result.type).toBe("complete");
578
+ if (result.type === "complete") {
579
+ expect(result.data).toBeDefined();
580
+ expect(result.data.metadata?.mimeType).toBe("application/zip");
581
+ expect(result.data.metadata?.extension).toBe("zip");
582
+ expect(result.data.metadata?.fileName).toBe("archive.zip");
583
+ }
584
+ }).pipe(Effect.provide(TestLayer)),
585
+ );
586
+
587
+ it.effect("should include metadata when requested", () =>
588
+ Effect.gen(function* () {
589
+ const node = yield* createZipNode("zip-with-meta", {
590
+ zipName: "files-with-metadata.zip",
591
+ includeMetadata: true,
592
+ });
593
+
594
+ const file1 = createTestImageFile("img-1", 1920, 1080);
595
+ const file2 = createTestImageFile("img-2", 800, 600);
596
+
597
+ const result = yield* node.run({
598
+ data: {
599
+ image1: file1,
600
+ image2: file2,
601
+ },
602
+ jobId: "test-job",
603
+ flowId: "test-flow",
604
+ storageId: "test-storage",
605
+ clientId: "test-client",
606
+ });
607
+
608
+ expect(result.type).toBe("complete");
609
+ if (result.type === "complete") {
610
+ expect(result.data.metadata?.fileName).toBe(
611
+ "files-with-metadata.zip",
612
+ );
613
+ expect(result.data.size).toBeGreaterThan(0);
614
+ }
615
+ }).pipe(Effect.provide(TestLayer)),
616
+ );
617
+
618
+ it.effect("should handle custom zip names", () =>
619
+ Effect.gen(function* () {
620
+ const customName = "my-custom-archive-2024.zip";
621
+ const node = yield* createZipNode("zip-custom-name", {
622
+ zipName: customName,
623
+ includeMetadata: false,
624
+ });
625
+
626
+ const file1 = createTestUploadFile("doc-1");
627
+
628
+ const result = yield* node.run({
629
+ data: { doc: file1 },
630
+ jobId: "test-job",
631
+ flowId: "test-flow",
632
+ storageId: "test-storage",
633
+ clientId: "test-client",
634
+ });
635
+
636
+ expect(result.type).toBe("complete");
637
+ if (result.type === "complete") {
638
+ expect(result.data.metadata?.fileName).toBe(customName);
639
+ expect(result.data.metadata?.originalName).toBe(customName);
640
+ }
641
+ }).pipe(Effect.provide(TestLayer)),
642
+ );
643
+
644
+ it.effect("should fail with no inputs", () =>
645
+ Effect.gen(function* () {
646
+ const node = yield* createZipNode("zip-empty", {
647
+ zipName: "empty.zip",
648
+ includeMetadata: false,
649
+ });
650
+
651
+ const result = yield* Effect.either(
652
+ node.run({
653
+ data: {},
654
+ jobId: "test-job",
655
+ flowId: "test-flow",
656
+ storageId: "test-storage",
657
+ clientId: "test-client",
658
+ }),
659
+ );
660
+
661
+ expect(result._tag).toBe("Left");
662
+ if (result._tag === "Left") {
663
+ expect(result.left).toBeInstanceOf(UploadistaError);
664
+ expect(result.left.code).toBe("VALIDATION_ERROR");
665
+ expect(result.left.body).toContain("No inputs provided to zip node");
666
+ }
667
+ }).pipe(Effect.provide(TestLayer)),
668
+ );
669
+
670
+ it.effect("should fail with null inputs", () =>
671
+ Effect.gen(function* () {
672
+ const node = yield* createZipNode("zip-null", {
673
+ zipName: "null.zip",
674
+ includeMetadata: false,
675
+ });
676
+
677
+ const result = yield* Effect.either(
678
+ node.run({
679
+ data: null as any,
680
+ jobId: "test-job",
681
+ flowId: "test-flow",
682
+ storageId: "test-storage",
683
+ clientId: "test-client",
684
+ }),
685
+ );
686
+
687
+ expect(result._tag).toBe("Left");
688
+ }).pipe(Effect.provide(TestLayer)),
689
+ );
690
+
691
+ it.effect("should create node with proper metadata", () =>
692
+ Effect.gen(function* () {
693
+ const node = yield* createZipNode("zip-props", {
694
+ zipName: "test.zip",
695
+ includeMetadata: true,
696
+ });
697
+
698
+ expect(node.id).toBe("zip-props");
699
+ expect(node.name).toBe("Zip Files");
700
+ expect(node.description).toBe(
701
+ "Combines multiple files into a zip archive",
702
+ );
703
+ expect(node.multiInput).toBe(true);
704
+ }).pipe(Effect.provide(TestLayer)),
705
+ );
706
+
707
+ it.effect("should handle multiple files with different types", () =>
708
+ Effect.gen(function* () {
709
+ const node = yield* createZipNode("zip-mixed", {
710
+ zipName: "mixed-files.zip",
711
+ includeMetadata: false,
712
+ });
713
+
714
+ const textFile = createTestUploadFile("text-file");
715
+ const imageFile = createTestImageFile("image-file", 640, 480);
716
+ const pdfFile = createTestUploadFile("pdf-file", {
717
+ metadata: {
718
+ mimeType: "application/pdf",
719
+ originalName: "document.pdf",
720
+ extension: "pdf",
721
+ },
722
+ });
723
+
724
+ const result = yield* node.run({
725
+ data: {
726
+ text: textFile,
727
+ image: imageFile,
728
+ pdf: pdfFile,
729
+ },
730
+ jobId: "test-job",
731
+ flowId: "test-flow",
732
+ storageId: "test-storage",
733
+ clientId: "test-client",
734
+ });
735
+
736
+ expect(result.type).toBe("complete");
737
+ if (result.type === "complete") {
738
+ expect(result.data).toBeDefined();
739
+ expect(result.data.metadata?.mimeType).toBe("application/zip");
740
+ expect(result.data.size).toBeGreaterThan(0);
741
+ }
742
+ }).pipe(Effect.provide(TestLayer)),
743
+ );
744
+
745
+ it.effect("should process files concurrently", () =>
746
+ Effect.gen(function* () {
747
+ const node = yield* createZipNode("zip-concurrent", {
748
+ zipName: "concurrent.zip",
749
+ includeMetadata: false,
750
+ });
751
+
752
+ // Create many files to test concurrent processing
753
+ const files: Record<string, UploadFile> = {};
754
+ for (let i = 0; i < 10; i++) {
755
+ files[`file${i}`] = createTestUploadFile(`file-${i}`);
756
+ }
757
+
758
+ const startTime = Date.now();
759
+
760
+ const result = yield* node.run({
761
+ data: files,
762
+ jobId: "test-job",
763
+ flowId: "test-flow",
764
+ storageId: "test-storage",
765
+ clientId: "test-client",
766
+ });
767
+
768
+ const duration = Date.now() - startTime;
769
+
770
+ expect(result.type).toBe("complete");
771
+ if (result.type === "complete") {
772
+ expect(result.data).toBeDefined();
773
+ // Should complete reasonably quickly even with 10 files
774
+ expect(duration).toBeLessThan(5000);
775
+ }
776
+ }).pipe(Effect.provide(TestLayer)),
777
+ );
778
+ });
779
+ });
@@ -0,0 +1,39 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ /**
4
+ * Shared vitest configuration template for uploadista-sdk packages
5
+ *
6
+ * This template should be used by all SDK packages to ensure consistent
7
+ * testing configuration across the monorepo.
8
+ *
9
+ * Key features:
10
+ * - Tests in dedicated `tests/` directories (not colocated with src)
11
+ * - Node environment for server-side code
12
+ * - V8 coverage provider
13
+ * - Global test functions available
14
+ * - Effect testing support via @effect/vitest
15
+ *
16
+ * Usage:
17
+ * Copy this file to your package root as `vitest.config.ts` and customize
18
+ * if needed (though most packages should use this as-is).
19
+ */
20
+ export default defineConfig({
21
+ test: {
22
+ globals: true,
23
+ environment: "node",
24
+ include: ["tests/**/*.test.ts"],
25
+ exclude: ["node_modules", "dist"],
26
+ coverage: {
27
+ provider: "v8",
28
+ reporter: ["text", "json", "html"],
29
+ exclude: [
30
+ "node_modules/",
31
+ "dist/",
32
+ "**/*.d.ts",
33
+ "**/*.test.ts",
34
+ "**/*.spec.ts",
35
+ "tests/",
36
+ ],
37
+ },
38
+ },
39
+ });