@middlewr/contracts 0.0.26 → 0.0.28

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.
@@ -73,6 +73,59 @@ export declare const LinkSchema: z.ZodObject<{
73
73
  frame_color: z.ZodString;
74
74
  frame_text_color: z.ZodString;
75
75
  }, z.core.$strip>>;
76
+ link_type: z.ZodDefault<z.ZodEnum<{
77
+ redirect: "redirect";
78
+ rules: "rules";
79
+ }>>;
80
+ rule_graph: z.ZodOptional<z.ZodNullable<z.ZodObject<{
81
+ entry: z.ZodString;
82
+ nodes: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
83
+ id: z.ZodString;
84
+ type: z.ZodLiteral<"condition">;
85
+ position: z.ZodObject<{
86
+ x: z.ZodNumber;
87
+ y: z.ZodNumber;
88
+ }, z.core.$strip>;
89
+ field: z.ZodString;
90
+ operator: z.ZodEnum<{
91
+ eq: "eq";
92
+ neq: "neq";
93
+ in: "in";
94
+ not_in: "not_in";
95
+ contains: "contains";
96
+ not_contains: "not_contains";
97
+ gt: "gt";
98
+ lt: "lt";
99
+ gte: "gte";
100
+ lte: "lte";
101
+ regex: "regex";
102
+ }>;
103
+ value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodNumber]>;
104
+ outputs: z.ZodObject<{
105
+ true: z.ZodNullable<z.ZodString>;
106
+ false: z.ZodNullable<z.ZodString>;
107
+ }, z.core.$strip>;
108
+ }, z.core.$strip>, z.ZodObject<{
109
+ id: z.ZodString;
110
+ type: z.ZodLiteral<"split">;
111
+ position: z.ZodObject<{
112
+ x: z.ZodNumber;
113
+ y: z.ZodNumber;
114
+ }, z.core.$strip>;
115
+ variants: z.ZodArray<z.ZodObject<{
116
+ weight: z.ZodNumber;
117
+ target: z.ZodNullable<z.ZodString>;
118
+ }, z.core.$strip>>;
119
+ }, z.core.$strip>, z.ZodObject<{
120
+ id: z.ZodString;
121
+ type: z.ZodLiteral<"destination">;
122
+ position: z.ZodObject<{
123
+ x: z.ZodNumber;
124
+ y: z.ZodNumber;
125
+ }, z.core.$strip>;
126
+ url: z.ZodString;
127
+ }, z.core.$strip>], "type">>;
128
+ }, z.core.$strip>>>;
76
129
  tags: z.ZodArray<z.ZodObject<{
77
130
  id: z.ZodString;
78
131
  workspace_id: z.ZodString;
@@ -124,6 +177,59 @@ export declare const CreateLinkInputSchema: z.ZodObject<{
124
177
  frame_text_color: z.ZodString;
125
178
  }, z.core.$strip>>>;
126
179
  tag_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
180
+ link_type: z.ZodOptional<z.ZodEnum<{
181
+ redirect: "redirect";
182
+ rules: "rules";
183
+ }>>;
184
+ rule_graph: z.ZodOptional<z.ZodNullable<z.ZodObject<{
185
+ entry: z.ZodString;
186
+ nodes: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
187
+ id: z.ZodString;
188
+ type: z.ZodLiteral<"condition">;
189
+ position: z.ZodObject<{
190
+ x: z.ZodNumber;
191
+ y: z.ZodNumber;
192
+ }, z.core.$strip>;
193
+ field: z.ZodString;
194
+ operator: z.ZodEnum<{
195
+ eq: "eq";
196
+ neq: "neq";
197
+ in: "in";
198
+ not_in: "not_in";
199
+ contains: "contains";
200
+ not_contains: "not_contains";
201
+ gt: "gt";
202
+ lt: "lt";
203
+ gte: "gte";
204
+ lte: "lte";
205
+ regex: "regex";
206
+ }>;
207
+ value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodNumber]>;
208
+ outputs: z.ZodObject<{
209
+ true: z.ZodNullable<z.ZodString>;
210
+ false: z.ZodNullable<z.ZodString>;
211
+ }, z.core.$strip>;
212
+ }, z.core.$strip>, z.ZodObject<{
213
+ id: z.ZodString;
214
+ type: z.ZodLiteral<"split">;
215
+ position: z.ZodObject<{
216
+ x: z.ZodNumber;
217
+ y: z.ZodNumber;
218
+ }, z.core.$strip>;
219
+ variants: z.ZodArray<z.ZodObject<{
220
+ weight: z.ZodNumber;
221
+ target: z.ZodNullable<z.ZodString>;
222
+ }, z.core.$strip>>;
223
+ }, z.core.$strip>, z.ZodObject<{
224
+ id: z.ZodString;
225
+ type: z.ZodLiteral<"destination">;
226
+ position: z.ZodObject<{
227
+ x: z.ZodNumber;
228
+ y: z.ZodNumber;
229
+ }, z.core.$strip>;
230
+ url: z.ZodString;
231
+ }, z.core.$strip>], "type">>;
232
+ }, z.core.$strip>>>;
127
233
  }, z.core.$strip>;
128
234
  export declare const UpdateLinkInputSchema: z.ZodObject<{
129
235
  original_url: z.ZodOptional<z.ZodString>;
@@ -168,6 +274,59 @@ export declare const UpdateLinkInputSchema: z.ZodObject<{
168
274
  frame_text_color: z.ZodString;
169
275
  }, z.core.$strip>>>;
170
276
  tag_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
277
+ link_type: z.ZodOptional<z.ZodEnum<{
278
+ redirect: "redirect";
279
+ rules: "rules";
280
+ }>>;
281
+ rule_graph: z.ZodOptional<z.ZodNullable<z.ZodObject<{
282
+ entry: z.ZodString;
283
+ nodes: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
284
+ id: z.ZodString;
285
+ type: z.ZodLiteral<"condition">;
286
+ position: z.ZodObject<{
287
+ x: z.ZodNumber;
288
+ y: z.ZodNumber;
289
+ }, z.core.$strip>;
290
+ field: z.ZodString;
291
+ operator: z.ZodEnum<{
292
+ eq: "eq";
293
+ neq: "neq";
294
+ in: "in";
295
+ not_in: "not_in";
296
+ contains: "contains";
297
+ not_contains: "not_contains";
298
+ gt: "gt";
299
+ lt: "lt";
300
+ gte: "gte";
301
+ lte: "lte";
302
+ regex: "regex";
303
+ }>;
304
+ value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodNumber]>;
305
+ outputs: z.ZodObject<{
306
+ true: z.ZodNullable<z.ZodString>;
307
+ false: z.ZodNullable<z.ZodString>;
308
+ }, z.core.$strip>;
309
+ }, z.core.$strip>, z.ZodObject<{
310
+ id: z.ZodString;
311
+ type: z.ZodLiteral<"split">;
312
+ position: z.ZodObject<{
313
+ x: z.ZodNumber;
314
+ y: z.ZodNumber;
315
+ }, z.core.$strip>;
316
+ variants: z.ZodArray<z.ZodObject<{
317
+ weight: z.ZodNumber;
318
+ target: z.ZodNullable<z.ZodString>;
319
+ }, z.core.$strip>>;
320
+ }, z.core.$strip>, z.ZodObject<{
321
+ id: z.ZodString;
322
+ type: z.ZodLiteral<"destination">;
323
+ position: z.ZodObject<{
324
+ x: z.ZodNumber;
325
+ y: z.ZodNumber;
326
+ }, z.core.$strip>;
327
+ url: z.ZodString;
328
+ }, z.core.$strip>], "type">>;
329
+ }, z.core.$strip>>>;
171
330
  }, z.core.$strip>;
172
331
  export declare const LinkFiltersSchema: z.ZodObject<{
173
332
  search: z.ZodOptional<z.ZodString>;
@@ -252,6 +411,59 @@ export declare const PaginatedLinksSchema: z.ZodObject<{
252
411
  frame_color: z.ZodString;
253
412
  frame_text_color: z.ZodString;
254
413
  }, z.core.$strip>>;
414
+ link_type: z.ZodDefault<z.ZodEnum<{
415
+ redirect: "redirect";
416
+ rules: "rules";
417
+ }>>;
418
+ rule_graph: z.ZodOptional<z.ZodNullable<z.ZodObject<{
419
+ entry: z.ZodString;
420
+ nodes: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
421
+ id: z.ZodString;
422
+ type: z.ZodLiteral<"condition">;
423
+ position: z.ZodObject<{
424
+ x: z.ZodNumber;
425
+ y: z.ZodNumber;
426
+ }, z.core.$strip>;
427
+ field: z.ZodString;
428
+ operator: z.ZodEnum<{
429
+ eq: "eq";
430
+ neq: "neq";
431
+ in: "in";
432
+ not_in: "not_in";
433
+ contains: "contains";
434
+ not_contains: "not_contains";
435
+ gt: "gt";
436
+ lt: "lt";
437
+ gte: "gte";
438
+ lte: "lte";
439
+ regex: "regex";
440
+ }>;
441
+ value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodNumber]>;
442
+ outputs: z.ZodObject<{
443
+ true: z.ZodNullable<z.ZodString>;
444
+ false: z.ZodNullable<z.ZodString>;
445
+ }, z.core.$strip>;
446
+ }, z.core.$strip>, z.ZodObject<{
447
+ id: z.ZodString;
448
+ type: z.ZodLiteral<"split">;
449
+ position: z.ZodObject<{
450
+ x: z.ZodNumber;
451
+ y: z.ZodNumber;
452
+ }, z.core.$strip>;
453
+ variants: z.ZodArray<z.ZodObject<{
454
+ weight: z.ZodNumber;
455
+ target: z.ZodNullable<z.ZodString>;
456
+ }, z.core.$strip>>;
457
+ }, z.core.$strip>, z.ZodObject<{
458
+ id: z.ZodString;
459
+ type: z.ZodLiteral<"destination">;
460
+ position: z.ZodObject<{
461
+ x: z.ZodNumber;
462
+ y: z.ZodNumber;
463
+ }, z.core.$strip>;
464
+ url: z.ZodString;
465
+ }, z.core.$strip>], "type">>;
466
+ }, z.core.$strip>>>;
255
467
  tags: z.ZodArray<z.ZodObject<{
256
468
  id: z.ZodString;
257
469
  workspace_id: z.ZodString;
@@ -266,4 +478,26 @@ export declare const PaginatedLinksSchema: z.ZodObject<{
266
478
  per_page: z.ZodNumber;
267
479
  total_pages: z.ZodNumber;
268
480
  }, z.core.$strip>;
481
+ export declare const LinkJobSchema: z.ZodObject<{
482
+ id: z.ZodString;
483
+ workspace_id: z.ZodString;
484
+ type: z.ZodString;
485
+ status: z.ZodEnum<{
486
+ pending: "pending";
487
+ processing: "processing";
488
+ completed: "completed";
489
+ failed: "failed";
490
+ }>;
491
+ total_rows: z.ZodNumber;
492
+ succeeded_count: z.ZodNumber;
493
+ failed_count: z.ZodNumber;
494
+ error: z.ZodNullable<z.ZodString>;
495
+ created_by_id: z.ZodString;
496
+ created_at: z.ZodDate;
497
+ completed_at: z.ZodNullable<z.ZodDate>;
498
+ }, z.core.$strip>;
499
+ export declare const LinkJobIdParamSchema: z.ZodObject<{
500
+ workspace_id: z.ZodString;
501
+ job_id: z.ZodString;
502
+ }, z.core.$strip>;
269
503
  //# sourceMappingURL=links.schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"links.schema.d.ts","sourceRoot":"","sources":["../../src/links.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;iBAU/B,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BrB,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BhC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2BhC,CAAC;AAMH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAe5B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM/B,CAAC"}
1
+ {"version":3,"file":"links.schema.d.ts","sourceRoot":"","sources":["../../src/links.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;iBAU/B,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4BrB,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiC5B,CAAC;AAEP,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkC5B,CAAC;AAMP,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAe5B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM/B,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;iBAYxB,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;iBAG/B,CAAC"}
@@ -0,0 +1,97 @@
1
+ import { z } from 'zod';
2
+ export declare const RuleGraphNodeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3
+ id: z.ZodString;
4
+ type: z.ZodLiteral<"condition">;
5
+ position: z.ZodObject<{
6
+ x: z.ZodNumber;
7
+ y: z.ZodNumber;
8
+ }, z.core.$strip>;
9
+ field: z.ZodString;
10
+ operator: z.ZodEnum<{
11
+ eq: "eq";
12
+ neq: "neq";
13
+ in: "in";
14
+ not_in: "not_in";
15
+ contains: "contains";
16
+ not_contains: "not_contains";
17
+ gt: "gt";
18
+ lt: "lt";
19
+ gte: "gte";
20
+ lte: "lte";
21
+ regex: "regex";
22
+ }>;
23
+ value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodNumber]>;
24
+ outputs: z.ZodObject<{
25
+ true: z.ZodNullable<z.ZodString>;
26
+ false: z.ZodNullable<z.ZodString>;
27
+ }, z.core.$strip>;
28
+ }, z.core.$strip>, z.ZodObject<{
29
+ id: z.ZodString;
30
+ type: z.ZodLiteral<"split">;
31
+ position: z.ZodObject<{
32
+ x: z.ZodNumber;
33
+ y: z.ZodNumber;
34
+ }, z.core.$strip>;
35
+ variants: z.ZodArray<z.ZodObject<{
36
+ weight: z.ZodNumber;
37
+ target: z.ZodNullable<z.ZodString>;
38
+ }, z.core.$strip>>;
39
+ }, z.core.$strip>, z.ZodObject<{
40
+ id: z.ZodString;
41
+ type: z.ZodLiteral<"destination">;
42
+ position: z.ZodObject<{
43
+ x: z.ZodNumber;
44
+ y: z.ZodNumber;
45
+ }, z.core.$strip>;
46
+ url: z.ZodString;
47
+ }, z.core.$strip>], "type">;
48
+ export declare const RuleGraphSchema: z.ZodNullable<z.ZodObject<{
49
+ entry: z.ZodString;
50
+ nodes: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
51
+ id: z.ZodString;
52
+ type: z.ZodLiteral<"condition">;
53
+ position: z.ZodObject<{
54
+ x: z.ZodNumber;
55
+ y: z.ZodNumber;
56
+ }, z.core.$strip>;
57
+ field: z.ZodString;
58
+ operator: z.ZodEnum<{
59
+ eq: "eq";
60
+ neq: "neq";
61
+ in: "in";
62
+ not_in: "not_in";
63
+ contains: "contains";
64
+ not_contains: "not_contains";
65
+ gt: "gt";
66
+ lt: "lt";
67
+ gte: "gte";
68
+ lte: "lte";
69
+ regex: "regex";
70
+ }>;
71
+ value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodNumber]>;
72
+ outputs: z.ZodObject<{
73
+ true: z.ZodNullable<z.ZodString>;
74
+ false: z.ZodNullable<z.ZodString>;
75
+ }, z.core.$strip>;
76
+ }, z.core.$strip>, z.ZodObject<{
77
+ id: z.ZodString;
78
+ type: z.ZodLiteral<"split">;
79
+ position: z.ZodObject<{
80
+ x: z.ZodNumber;
81
+ y: z.ZodNumber;
82
+ }, z.core.$strip>;
83
+ variants: z.ZodArray<z.ZodObject<{
84
+ weight: z.ZodNumber;
85
+ target: z.ZodNullable<z.ZodString>;
86
+ }, z.core.$strip>>;
87
+ }, z.core.$strip>, z.ZodObject<{
88
+ id: z.ZodString;
89
+ type: z.ZodLiteral<"destination">;
90
+ position: z.ZodObject<{
91
+ x: z.ZodNumber;
92
+ y: z.ZodNumber;
93
+ }, z.core.$strip>;
94
+ url: z.ZodString;
95
+ }, z.core.$strip>], "type">>;
96
+ }, z.core.$strip>>;
97
+ //# sourceMappingURL=rules.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.schema.d.ts","sourceRoot":"","sources":["../../src/rules.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA8CxB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAA8F,CAAC;AAE/H,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBASb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@middlewr/contracts",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
package/src/index.ts CHANGED
@@ -16,7 +16,15 @@ import {
16
16
  WorkspaceIdParamSchema,
17
17
  } from './common.schema';
18
18
  import { CreateDomainInputSchema, DomainSchema, UpdateDomainInputSchema } from './domains.schema';
19
- import { CreateLinkInputSchema, LinkFiltersSchema, LinkSchema, PaginatedLinksSchema, UpdateLinkInputSchema } from './links.schema';
19
+ import {
20
+ CreateLinkInputSchema,
21
+ LinkFiltersSchema,
22
+ LinkJobIdParamSchema,
23
+ LinkJobSchema,
24
+ LinkSchema,
25
+ PaginatedLinksSchema,
26
+ UpdateLinkInputSchema,
27
+ } from './links.schema';
20
28
  import { CreateTagInputSchema, TagSchema, UpdateTagInputSchema } from './tags.schema';
21
29
  import { SignInInputSchema, UpdateUserInputSchema, UserSchema } from './users.schema';
22
30
  import {
@@ -38,6 +46,7 @@ export * from './billing.schema';
38
46
  export * from './common.schema';
39
47
  export * from './domains.schema';
40
48
  export * from './links.schema';
49
+ export * from './rules.schema';
41
50
  export * from './tags.schema';
42
51
  // Re-export all schemas
43
52
  export * from './users.schema';
@@ -179,6 +188,16 @@ export const linksContract = {
179
188
  .route({ method: 'GET', path: '/api/workspaces/{workspace_id}/links/{link_id}/edge/status' })
180
189
  .input(LinkIdParamSchema)
181
190
  .output(z.object({ synced: z.boolean() })),
191
+
192
+ getJob: oc
193
+ .route({ method: 'GET', path: '/api/workspaces/{workspace_id}/jobs/{job_id}' })
194
+ .input(LinkJobIdParamSchema)
195
+ .output(LinkJobSchema),
196
+
197
+ jobResults: oc
198
+ .route({ method: 'GET', path: '/api/workspaces/{workspace_id}/jobs/{job_id}/results' })
199
+ .input(LinkJobIdParamSchema)
200
+ .output(z.object({ url: z.string() })),
182
201
  };
183
202
 
184
203
  // Tags contract
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ import { RuleGraphSchema } from './rules.schema';
3
4
  import { TagSchema } from './tags.schema';
4
5
 
5
6
  const DotStyleSchema = z.enum(['square', 'dots', 'rounded', 'classy', 'classy-rounded', 'extra-rounded']);
@@ -43,65 +44,81 @@ export const LinkSchema = z.object({
43
44
  created_at: z.coerce.date(),
44
45
  updated_at: z.coerce.date().nullable(),
45
46
  qr_code_settings: QrCodeSettingsSchema.nullable(),
47
+ link_type: z.enum(['redirect', 'rules']).default('redirect'),
48
+ rule_graph: RuleGraphSchema.optional(),
46
49
  tags: z.array(TagSchema),
47
50
  });
48
51
 
49
- export const CreateLinkInputSchema = z.object({
50
- original_url: z.string().url().max(2048),
51
- domain_id: z.string().uuid().optional(),
52
- short_code: z
53
- .string()
54
- .min(3)
55
- .max(50)
56
- .regex(/^[a-zA-Z0-9-]+$/)
57
- .optional(),
58
- title: z.string().max(255).optional(),
59
- description: z.string().max(2000).optional(),
60
- utm_source: z.string().max(255).optional(),
61
- utm_medium: z.string().max(255).optional(),
62
- utm_campaign: z.string().max(255).optional(),
63
- utm_term: z.string().max(255).optional(),
64
- utm_content: z.string().max(255).optional(),
65
- password: z.string().min(4).max(100).optional(),
66
- starts_at: z.coerce.date().optional(),
67
- expires_at: z.coerce.date().optional(),
68
- fallback_url: z.string().url().max(2048).optional(),
69
- redirect_type: z.coerce
70
- .number()
71
- .refine((v) => [301, 302, 307, 308].includes(v))
72
- .optional(),
73
- qr_code_settings: QrCodeSettingsSchema.nullable().optional(),
74
- tag_ids: z.array(z.string().uuid()).optional(),
75
- });
52
+ export const CreateLinkInputSchema = z
53
+ .object({
54
+ original_url: z.string().url().max(2048),
55
+ domain_id: z.string().uuid().optional(),
56
+ short_code: z
57
+ .string()
58
+ .min(3)
59
+ .max(50)
60
+ .regex(/^[a-zA-Z0-9-]+$/)
61
+ .optional(),
62
+ title: z.string().max(255).optional(),
63
+ description: z.string().max(2000).optional(),
64
+ utm_source: z.string().max(255).optional(),
65
+ utm_medium: z.string().max(255).optional(),
66
+ utm_campaign: z.string().max(255).optional(),
67
+ utm_term: z.string().max(255).optional(),
68
+ utm_content: z.string().max(255).optional(),
69
+ password: z.string().min(4).max(100).optional(),
70
+ starts_at: z.coerce.date().optional(),
71
+ expires_at: z.coerce.date().optional(),
72
+ fallback_url: z.string().url().max(2048).optional(),
73
+ redirect_type: z.coerce
74
+ .number()
75
+ .refine((v) => [301, 302, 307, 308].includes(v))
76
+ .optional(),
77
+ qr_code_settings: QrCodeSettingsSchema.nullable().optional(),
78
+ tag_ids: z.array(z.string().uuid()).optional(),
79
+ link_type: z.enum(['redirect', 'rules']).optional(),
80
+ rule_graph: RuleGraphSchema.optional(),
81
+ })
82
+ .refine((data) => data.link_type !== 'rules' || data.rule_graph != null, {
83
+ message: 'rule_graph is required when link_type is "rules"',
84
+ path: ['rule_graph'],
85
+ });
76
86
 
77
- export const UpdateLinkInputSchema = z.object({
78
- original_url: z.string().url().max(2048).optional(),
79
- domain_id: z.string().uuid().optional(),
80
- short_code: z
81
- .string()
82
- .min(3)
83
- .max(50)
84
- .regex(/^[a-zA-Z0-9-]+$/)
85
- .optional(),
86
- title: z.string().max(255).nullable().optional(),
87
- description: z.string().max(2000).nullable().optional(),
88
- utm_source: z.string().max(255).nullable().optional(),
89
- utm_medium: z.string().max(255).nullable().optional(),
90
- utm_campaign: z.string().max(255).nullable().optional(),
91
- utm_term: z.string().max(255).nullable().optional(),
92
- utm_content: z.string().max(255).nullable().optional(),
93
- password: z.string().min(4).max(100).nullable().optional(),
94
- starts_at: z.coerce.date().nullable().optional(),
95
- expires_at: z.coerce.date().nullable().optional(),
96
- fallback_url: z.string().url().max(2048).nullable().optional(),
97
- is_active: z.boolean().optional(),
98
- redirect_type: z.coerce
99
- .number()
100
- .refine((v) => [301, 302, 307, 308].includes(v))
101
- .optional(),
102
- qr_code_settings: QrCodeSettingsSchema.nullable().optional(),
103
- tag_ids: z.array(z.string().uuid()).optional(),
104
- });
87
+ export const UpdateLinkInputSchema = z
88
+ .object({
89
+ original_url: z.string().url().max(2048).optional(),
90
+ domain_id: z.string().uuid().optional(),
91
+ short_code: z
92
+ .string()
93
+ .min(3)
94
+ .max(50)
95
+ .regex(/^[a-zA-Z0-9-]+$/)
96
+ .optional(),
97
+ title: z.string().max(255).nullable().optional(),
98
+ description: z.string().max(2000).nullable().optional(),
99
+ utm_source: z.string().max(255).nullable().optional(),
100
+ utm_medium: z.string().max(255).nullable().optional(),
101
+ utm_campaign: z.string().max(255).nullable().optional(),
102
+ utm_term: z.string().max(255).nullable().optional(),
103
+ utm_content: z.string().max(255).nullable().optional(),
104
+ password: z.string().min(4).max(100).nullable().optional(),
105
+ starts_at: z.coerce.date().nullable().optional(),
106
+ expires_at: z.coerce.date().nullable().optional(),
107
+ fallback_url: z.string().url().max(2048).nullable().optional(),
108
+ is_active: z.boolean().optional(),
109
+ redirect_type: z.coerce
110
+ .number()
111
+ .refine((v) => [301, 302, 307, 308].includes(v))
112
+ .optional(),
113
+ qr_code_settings: QrCodeSettingsSchema.nullable().optional(),
114
+ tag_ids: z.array(z.string().uuid()).optional(),
115
+ link_type: z.enum(['redirect', 'rules']).optional(),
116
+ rule_graph: RuleGraphSchema.optional(),
117
+ })
118
+ .refine((data) => data.link_type !== 'rules' || data.rule_graph != null, {
119
+ message: 'rule_graph is required when link_type is "rules"',
120
+ path: ['rule_graph'],
121
+ });
105
122
 
106
123
  const stringToBoolean = z
107
124
  .union([z.boolean(), z.enum(['true', 'false'])])
@@ -131,3 +148,22 @@ export const PaginatedLinksSchema = z.object({
131
148
  per_page: z.number().int(),
132
149
  total_pages: z.number().int(),
133
150
  });
151
+
152
+ export const LinkJobSchema = z.object({
153
+ id: z.string().uuid(),
154
+ workspace_id: z.string().uuid(),
155
+ type: z.string(),
156
+ status: z.enum(['pending', 'processing', 'completed', 'failed']),
157
+ total_rows: z.number().int(),
158
+ succeeded_count: z.number().int(),
159
+ failed_count: z.number().int(),
160
+ error: z.string().nullable(),
161
+ created_by_id: z.string().uuid(),
162
+ created_at: z.date(),
163
+ completed_at: z.date().nullable(),
164
+ });
165
+
166
+ export const LinkJobIdParamSchema = z.object({
167
+ workspace_id: z.string().uuid(),
168
+ job_id: z.string().uuid(),
169
+ });
@@ -0,0 +1,58 @@
1
+ import { z } from 'zod';
2
+
3
+ const RULE_OPERATORS = ['eq', 'neq', 'in', 'not_in', 'contains', 'not_contains', 'gt', 'lt', 'gte', 'lte', 'regex'] as const;
4
+ const VALID_FIELD_PREFIXES = ['cf.', 'request.', 'edge.', 'time.'];
5
+
6
+ const PositionSchema = z.object({
7
+ x: z.number(),
8
+ y: z.number(),
9
+ });
10
+
11
+ const ConditionNodeSchema = z.object({
12
+ id: z.string(),
13
+ type: z.literal('condition'),
14
+ position: PositionSchema,
15
+ field: z.string().refine((f) => VALID_FIELD_PREFIXES.some((p) => f.startsWith(p)), {
16
+ message: 'Field must start with cf., request., edge., or time.',
17
+ }),
18
+ operator: z.enum(RULE_OPERATORS),
19
+ value: z.union([z.string(), z.array(z.string()), z.number()]),
20
+ outputs: z.object({
21
+ true: z.string().nullable(),
22
+ false: z.string().nullable(),
23
+ }),
24
+ });
25
+
26
+ const SplitNodeSchema = z.object({
27
+ id: z.string(),
28
+ type: z.literal('split'),
29
+ position: PositionSchema,
30
+ variants: z
31
+ .array(
32
+ z.object({
33
+ weight: z.number().min(1).max(100),
34
+ target: z.string().nullable(),
35
+ }),
36
+ )
37
+ .min(2),
38
+ });
39
+
40
+ const DestinationNodeSchema = z.object({
41
+ id: z.string(),
42
+ type: z.literal('destination'),
43
+ position: PositionSchema,
44
+ url: z.string().url(),
45
+ });
46
+
47
+ export const RuleGraphNodeSchema = z.discriminatedUnion('type', [ConditionNodeSchema, SplitNodeSchema, DestinationNodeSchema]);
48
+
49
+ export const RuleGraphSchema = z
50
+ .object({
51
+ entry: z.string(),
52
+ nodes: z.record(z.string(), RuleGraphNodeSchema),
53
+ })
54
+ .refine((data) => data.nodes[data.entry] !== undefined, {
55
+ message: 'Entry node must reference an existing node in the graph',
56
+ path: ['entry'],
57
+ })
58
+ .nullable();