@waypointjs/core 0.1.5 → 0.1.6
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 +121 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -8
- package/dist/index.d.ts +40 -8
- package/dist/index.js +121 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5,11 +5,15 @@ var middleware = require('zustand/middleware');
|
|
|
5
5
|
var zod = require('zod');
|
|
6
6
|
|
|
7
7
|
// src/conditions.ts
|
|
8
|
-
function resolveFieldValue(path, data, externalVars) {
|
|
8
|
+
function resolveFieldValue(path, data, externalVars, skippedSteps) {
|
|
9
9
|
if (path.startsWith("$ext.")) {
|
|
10
10
|
const varId = path.slice(5);
|
|
11
11
|
return externalVars[varId];
|
|
12
12
|
}
|
|
13
|
+
if (path.startsWith("$step.") && path.endsWith(".skipped")) {
|
|
14
|
+
const stepId2 = path.slice(6, -8);
|
|
15
|
+
return skippedSteps?.includes(stepId2) ?? false;
|
|
16
|
+
}
|
|
13
17
|
const dotIndex = path.indexOf(".");
|
|
14
18
|
if (dotIndex === -1) return void 0;
|
|
15
19
|
const stepId = path.slice(0, dotIndex);
|
|
@@ -65,8 +69,8 @@ function evaluateOperator(operator, actual, expected) {
|
|
|
65
69
|
return false;
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
|
-
function evaluateRule(rule, data, externalVars, externalEnums) {
|
|
69
|
-
const actual = resolveFieldValue(rule.field, data, externalVars);
|
|
72
|
+
function evaluateRule(rule, data, externalVars, externalEnums, skippedSteps) {
|
|
73
|
+
const actual = resolveFieldValue(rule.field, data, externalVars, skippedSteps);
|
|
70
74
|
if ((rule.operator === "inEnum" || rule.operator === "notInEnum") && externalEnums) {
|
|
71
75
|
const enumDef = externalEnums.find((e) => e.id === String(rule.value));
|
|
72
76
|
const values = enumDef?.values.map((v) => String(v.value)) ?? [];
|
|
@@ -74,20 +78,20 @@ function evaluateRule(rule, data, externalVars, externalEnums) {
|
|
|
74
78
|
}
|
|
75
79
|
return evaluateOperator(rule.operator, actual, rule.value);
|
|
76
80
|
}
|
|
77
|
-
function evaluateConditionGroup(group, data, externalVars, externalEnums) {
|
|
81
|
+
function evaluateConditionGroup(group, data, externalVars, externalEnums, skippedSteps) {
|
|
78
82
|
const ruleResults = group.rules.map(
|
|
79
|
-
(rule) => evaluateRule(rule, data, externalVars, externalEnums)
|
|
83
|
+
(rule) => evaluateRule(rule, data, externalVars, externalEnums, skippedSteps)
|
|
80
84
|
);
|
|
81
85
|
const groupResults = (group.groups ?? []).map(
|
|
82
|
-
(subGroup) => evaluateConditionGroup(subGroup, data, externalVars, externalEnums)
|
|
86
|
+
(subGroup) => evaluateConditionGroup(subGroup, data, externalVars, externalEnums, skippedSteps)
|
|
83
87
|
);
|
|
84
88
|
const allResults = [...ruleResults, ...groupResults];
|
|
85
89
|
if (allResults.length === 0) return true;
|
|
86
90
|
return group.combinator === "and" ? allResults.every(Boolean) : allResults.some(Boolean);
|
|
87
91
|
}
|
|
88
|
-
function isVisible(visibleWhen, data, externalVars, externalEnums) {
|
|
92
|
+
function isVisible(visibleWhen, data, externalVars, externalEnums, skippedSteps) {
|
|
89
93
|
if (!visibleWhen) return true;
|
|
90
|
-
return evaluateConditionGroup(visibleWhen, data, externalVars, externalEnums);
|
|
94
|
+
return evaluateConditionGroup(visibleWhen, data, externalVars, externalEnums, skippedSteps);
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
// src/tree-resolver.ts
|
|
@@ -111,22 +115,32 @@ function findMissingBlockingVars(externalVariables, externalVars, visibleSteps)
|
|
|
111
115
|
return value === void 0 || value === null;
|
|
112
116
|
}).map((extVar) => extVar.id);
|
|
113
117
|
}
|
|
114
|
-
function resolveTree(schema, data, externalVars, externalEnums) {
|
|
118
|
+
function resolveTree(schema, data, externalVars, externalEnums, skippedSteps) {
|
|
115
119
|
const visibleSteps = [];
|
|
116
120
|
const hiddenSteps = [];
|
|
117
121
|
for (const stepDef of schema.steps) {
|
|
118
|
-
const stepVisible = isVisible(stepDef.visibleWhen, data, externalVars, externalEnums);
|
|
122
|
+
const stepVisible = isVisible(stepDef.visibleWhen, data, externalVars, externalEnums, skippedSteps);
|
|
119
123
|
const resolvedFields = stepDef.fields.map((fieldDef) => {
|
|
120
124
|
let resolvedOptions;
|
|
121
125
|
if (fieldDef.externalEnumId && externalEnums) {
|
|
122
126
|
const enumDef = externalEnums.find((e) => e.id === fieldDef.externalEnumId);
|
|
123
127
|
resolvedOptions = enumDef?.values;
|
|
124
128
|
}
|
|
129
|
+
let resolvedDefaultValue;
|
|
130
|
+
if (fieldDef.dynamicDefault && fieldDef.dynamicDefault.length > 0) {
|
|
131
|
+
for (const rule of fieldDef.dynamicDefault) {
|
|
132
|
+
if (evaluateConditionGroup(rule.when, data, externalVars, externalEnums, skippedSteps)) {
|
|
133
|
+
resolvedDefaultValue = rule.value;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
125
138
|
return {
|
|
126
139
|
definition: fieldDef,
|
|
127
|
-
visible: isVisible(fieldDef.visibleWhen, data, externalVars, externalEnums),
|
|
140
|
+
visible: isVisible(fieldDef.visibleWhen, data, externalVars, externalEnums, skippedSteps),
|
|
128
141
|
dependenciesMet: areDependenciesMet(fieldDef.dependsOn, data, externalVars),
|
|
129
|
-
resolvedOptions
|
|
142
|
+
resolvedOptions,
|
|
143
|
+
resolvedDefaultValue
|
|
130
144
|
};
|
|
131
145
|
});
|
|
132
146
|
const resolvedStep = {
|
|
@@ -193,7 +207,7 @@ function getResolvedTree(state) {
|
|
|
193
207
|
if (!state.schema) {
|
|
194
208
|
return { steps: [], hiddenSteps: [], missingExternalVars: [] };
|
|
195
209
|
}
|
|
196
|
-
return resolveTree(state.schema, state.data, state.externalVars);
|
|
210
|
+
return resolveTree(state.schema, state.data, state.externalVars, void 0, state.skippedSteps);
|
|
197
211
|
}
|
|
198
212
|
function getCurrentStep(state) {
|
|
199
213
|
if (!state.currentStepId) return void 0;
|
|
@@ -225,6 +239,7 @@ var initialState = {
|
|
|
225
239
|
externalVars: {},
|
|
226
240
|
currentStepId: null,
|
|
227
241
|
history: [],
|
|
242
|
+
skippedSteps: [],
|
|
228
243
|
isSubmitting: false,
|
|
229
244
|
completed: false
|
|
230
245
|
};
|
|
@@ -240,6 +255,7 @@ function buildStateCreator() {
|
|
|
240
255
|
externalVars,
|
|
241
256
|
currentStepId: firstStepId,
|
|
242
257
|
history: firstStepId ? [firstStepId] : [],
|
|
258
|
+
skippedSteps: [],
|
|
243
259
|
isSubmitting: false,
|
|
244
260
|
completed: false
|
|
245
261
|
});
|
|
@@ -281,6 +297,16 @@ function buildStateCreator() {
|
|
|
281
297
|
setCompleted(b) {
|
|
282
298
|
set({ completed: b });
|
|
283
299
|
},
|
|
300
|
+
skipStep(stepId) {
|
|
301
|
+
set((state) => ({
|
|
302
|
+
skippedSteps: state.skippedSteps.includes(stepId) ? state.skippedSteps : [...state.skippedSteps, stepId]
|
|
303
|
+
}));
|
|
304
|
+
},
|
|
305
|
+
unskipStep(stepId) {
|
|
306
|
+
set((state) => ({
|
|
307
|
+
skippedSteps: state.skippedSteps.filter((id) => id !== stepId)
|
|
308
|
+
}));
|
|
309
|
+
},
|
|
284
310
|
truncateHistoryAt(stepId) {
|
|
285
311
|
set((state) => {
|
|
286
312
|
const idx = state.history.indexOf(stepId);
|
|
@@ -319,6 +345,7 @@ function createRuntimeStore(options = {}) {
|
|
|
319
345
|
data: state.data,
|
|
320
346
|
currentStepId: state.currentStepId,
|
|
321
347
|
history: state.history,
|
|
348
|
+
skippedSteps: state.skippedSteps,
|
|
322
349
|
completed: state.completed
|
|
323
350
|
})
|
|
324
351
|
})
|
|
@@ -335,7 +362,13 @@ var customValidatorRegistry = {};
|
|
|
335
362
|
function registerCustomValidator(id, fn) {
|
|
336
363
|
customValidatorRegistry[id] = fn;
|
|
337
364
|
}
|
|
338
|
-
function
|
|
365
|
+
function resolveRuleValue(rule, data) {
|
|
366
|
+
if (rule.refField && data) {
|
|
367
|
+
return resolveFieldValue(rule.refField, data, {});
|
|
368
|
+
}
|
|
369
|
+
return rule.value;
|
|
370
|
+
}
|
|
371
|
+
function buildFieldSchema(field, externalEnums, data) {
|
|
339
372
|
const rules = field.validation ?? [];
|
|
340
373
|
const isRequired = rules.some((r) => r.type === "required");
|
|
341
374
|
const isNumeric = field.type === "number";
|
|
@@ -353,28 +386,47 @@ function buildFieldSchema(field, externalEnums) {
|
|
|
353
386
|
let numSchema = zod.z.coerce.number({
|
|
354
387
|
invalid_type_error: "Must be a number"
|
|
355
388
|
});
|
|
389
|
+
const numRefineRules = [];
|
|
356
390
|
for (const rule of rules) {
|
|
391
|
+
const rv = resolveRuleValue(rule, data);
|
|
392
|
+
const isRef = !!rule.refField;
|
|
357
393
|
if (rule.type === "min" || rule.type === "greaterThanOrEqual") {
|
|
358
|
-
const n = Number(
|
|
359
|
-
if (!isNaN(n))
|
|
394
|
+
const n = Number(rv);
|
|
395
|
+
if (!isNaN(n)) {
|
|
396
|
+
if (isRef) numRefineRules.push({ fn: (v) => v >= n, message: rule.message });
|
|
397
|
+
else numSchema = numSchema.gte(n, rule.message);
|
|
398
|
+
}
|
|
360
399
|
} else if (rule.type === "max" || rule.type === "lessThanOrEqual") {
|
|
361
|
-
const n = Number(
|
|
362
|
-
if (!isNaN(n))
|
|
400
|
+
const n = Number(rv);
|
|
401
|
+
if (!isNaN(n)) {
|
|
402
|
+
if (isRef) numRefineRules.push({ fn: (v) => v <= n, message: rule.message });
|
|
403
|
+
else numSchema = numSchema.lte(n, rule.message);
|
|
404
|
+
}
|
|
363
405
|
} else if (rule.type === "greaterThan") {
|
|
364
|
-
const n = Number(
|
|
365
|
-
if (!isNaN(n))
|
|
406
|
+
const n = Number(rv);
|
|
407
|
+
if (!isNaN(n)) {
|
|
408
|
+
if (isRef) numRefineRules.push({ fn: (v) => v > n, message: rule.message });
|
|
409
|
+
else numSchema = numSchema.gt(n, rule.message);
|
|
410
|
+
}
|
|
366
411
|
} else if (rule.type === "lessThan") {
|
|
367
|
-
const n = Number(
|
|
368
|
-
if (!isNaN(n))
|
|
412
|
+
const n = Number(rv);
|
|
413
|
+
if (!isNaN(n)) {
|
|
414
|
+
if (isRef) numRefineRules.push({ fn: (v) => v < n, message: rule.message });
|
|
415
|
+
else numSchema = numSchema.lt(n, rule.message);
|
|
416
|
+
}
|
|
369
417
|
} else if (rule.type === "equals") {
|
|
370
|
-
const n = Number(
|
|
371
|
-
if (!isNaN(n))
|
|
418
|
+
const n = Number(rv);
|
|
419
|
+
if (!isNaN(n)) numRefineRules.push({ fn: (v) => v === n, message: rule.message });
|
|
372
420
|
} else if (rule.type === "notEquals") {
|
|
373
|
-
const n = Number(
|
|
374
|
-
if (!isNaN(n))
|
|
421
|
+
const n = Number(rv);
|
|
422
|
+
if (!isNaN(n)) numRefineRules.push({ fn: (v) => v !== n, message: rule.message });
|
|
375
423
|
}
|
|
376
424
|
}
|
|
377
|
-
|
|
425
|
+
let numFinal = isRequired ? numSchema : numSchema.optional();
|
|
426
|
+
for (const { fn, message } of numRefineRules) {
|
|
427
|
+
numFinal = numFinal.refine((v) => v == null || fn(v), message);
|
|
428
|
+
}
|
|
429
|
+
return numFinal;
|
|
378
430
|
}
|
|
379
431
|
let strSchema = zod.z.string();
|
|
380
432
|
const refineRules = [];
|
|
@@ -404,54 +456,70 @@ function buildFieldSchema(field, externalEnums) {
|
|
|
404
456
|
strSchema = strSchema.regex(new RegExp(String(rule.value)), rule.message);
|
|
405
457
|
}
|
|
406
458
|
break;
|
|
407
|
-
case "equals":
|
|
408
|
-
|
|
409
|
-
|
|
459
|
+
case "equals": {
|
|
460
|
+
const rv = resolveRuleValue(rule, data);
|
|
461
|
+
if (rv !== void 0) {
|
|
462
|
+
const eq = String(rv);
|
|
410
463
|
refineRules.push({ fn: (v) => String(v) === eq, message: rule.message });
|
|
411
464
|
}
|
|
412
465
|
break;
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
466
|
+
}
|
|
467
|
+
case "notEquals": {
|
|
468
|
+
const rv = resolveRuleValue(rule, data);
|
|
469
|
+
if (rv !== void 0) {
|
|
470
|
+
const neq = String(rv);
|
|
416
471
|
refineRules.push({ fn: (v) => String(v) !== neq, message: rule.message });
|
|
417
472
|
}
|
|
418
473
|
break;
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
474
|
+
}
|
|
475
|
+
case "greaterThan": {
|
|
476
|
+
const rv = resolveRuleValue(rule, data);
|
|
477
|
+
if (rv !== void 0) {
|
|
478
|
+
const gt = Number(rv);
|
|
422
479
|
refineRules.push({ fn: (v) => Number(v) > gt, message: rule.message });
|
|
423
480
|
}
|
|
424
481
|
break;
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
482
|
+
}
|
|
483
|
+
case "greaterThanOrEqual": {
|
|
484
|
+
const rv = resolveRuleValue(rule, data);
|
|
485
|
+
if (rv !== void 0) {
|
|
486
|
+
const gte = Number(rv);
|
|
428
487
|
refineRules.push({ fn: (v) => Number(v) >= gte, message: rule.message });
|
|
429
488
|
}
|
|
430
489
|
break;
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
490
|
+
}
|
|
491
|
+
case "lessThan": {
|
|
492
|
+
const rv = resolveRuleValue(rule, data);
|
|
493
|
+
if (rv !== void 0) {
|
|
494
|
+
const lt = Number(rv);
|
|
434
495
|
refineRules.push({ fn: (v) => Number(v) < lt, message: rule.message });
|
|
435
496
|
}
|
|
436
497
|
break;
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
498
|
+
}
|
|
499
|
+
case "lessThanOrEqual": {
|
|
500
|
+
const rv = resolveRuleValue(rule, data);
|
|
501
|
+
if (rv !== void 0) {
|
|
502
|
+
const lte = Number(rv);
|
|
440
503
|
refineRules.push({ fn: (v) => Number(v) <= lte, message: rule.message });
|
|
441
504
|
}
|
|
442
505
|
break;
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
506
|
+
}
|
|
507
|
+
case "contains": {
|
|
508
|
+
const rv = resolveRuleValue(rule, data);
|
|
509
|
+
if (rv !== void 0) {
|
|
510
|
+
const sub = String(rv);
|
|
446
511
|
refineRules.push({ fn: (v) => String(v).includes(sub), message: rule.message });
|
|
447
512
|
}
|
|
448
513
|
break;
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
514
|
+
}
|
|
515
|
+
case "notContains": {
|
|
516
|
+
const rv = resolveRuleValue(rule, data);
|
|
517
|
+
if (rv !== void 0) {
|
|
518
|
+
const nsub = String(rv);
|
|
452
519
|
refineRules.push({ fn: (v) => !String(v).includes(nsub), message: rule.message });
|
|
453
520
|
}
|
|
454
521
|
break;
|
|
522
|
+
}
|
|
455
523
|
case "matches":
|
|
456
524
|
if (rule.value !== void 0 && rule.value !== null) {
|
|
457
525
|
const rx = new RegExp(String(rule.value));
|
|
@@ -489,11 +557,11 @@ function buildFieldSchema(field, externalEnums) {
|
|
|
489
557
|
}
|
|
490
558
|
return finalSchema;
|
|
491
559
|
}
|
|
492
|
-
function buildZodSchema(fields, externalEnums) {
|
|
560
|
+
function buildZodSchema(fields, externalEnums, data) {
|
|
493
561
|
const shape = {};
|
|
494
562
|
for (const resolvedField of fields) {
|
|
495
563
|
if (!resolvedField.visible) continue;
|
|
496
|
-
shape[resolvedField.definition.id] = buildFieldSchema(resolvedField.definition, externalEnums);
|
|
564
|
+
shape[resolvedField.definition.id] = buildFieldSchema(resolvedField.definition, externalEnums, data);
|
|
497
565
|
}
|
|
498
566
|
return zod.z.object(shape);
|
|
499
567
|
}
|