@jfdevelops/multi-step-form-core 1.0.0-alpha.11

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.
@@ -0,0 +1,953 @@
1
+ function comparePartialArray(compareArray, actualArray, formatter) {
2
+ const errors = [];
3
+ const compareSet = new Set(compareArray);
4
+ const printedArray = formatter ? formatter.format(compareArray.map((value) => `${value}`)) : `[${compareArray.join(", ")}]`;
5
+ for (let i = 0; i < actualArray.length; i++) {
6
+ const value = actualArray[i];
7
+ if (!compareSet.has(value)) {
8
+ errors.push(
9
+ `Extra element at index ${i}: "${value}" is not in ${printedArray}`
10
+ );
11
+ }
12
+ }
13
+ const hasAtLeastOne = actualArray.some((v) => compareSet.has(v));
14
+ if (!hasAtLeastOne) {
15
+ errors.push(
16
+ `Array must contain at least one valid element from ${printedArray}`
17
+ );
18
+ }
19
+ if (errors.length > 0) {
20
+ return { status: "error", errors };
21
+ }
22
+ return { status: "success" };
23
+ }
24
+ function printErrors(errors, mapper) {
25
+ const defaultMapper = (e, i) => `❌ ${i + 1}. ${e}`;
26
+ return errors.map((e, i) => defaultMapper(e, i)).join("\n");
27
+ }
28
+ function typedObjectKeys(value) {
29
+ return Object.keys(value);
30
+ }
31
+ function lazy(strings, ...values) {
32
+ return () => String.raw({ raw: strings }, ...values);
33
+ }
34
+ function invariant(condition, message, error = Error) {
35
+ if (!condition) {
36
+ const formatter = new Intl.ListFormat("en", {
37
+ style: "long",
38
+ type: "conjunction"
39
+ });
40
+ const resolvedMessage = typeof message === "function" ? message(formatter) : lazy`${message}`();
41
+ throw new error(resolvedMessage);
42
+ }
43
+ }
44
+ function extractNumber(input) {
45
+ invariant(input.includes("step"), "Can't extract a valid step number since");
46
+ const extracted = input.replace("step", "");
47
+ invariant(/^\d+$/.test(extracted), `Invalid step format: "${input}"`);
48
+ return Number.parseInt(extracted, 10);
49
+ }
50
+ function getStep(resolvedStepValues) {
51
+ return function(options) {
52
+ const { step } = options;
53
+ const stepKey = `step${step}`;
54
+ const data = resolvedStepValues[stepKey];
55
+ return { step, data };
56
+ };
57
+ }
58
+ function createCtxHelper(values, data) {
59
+ return data.reduce((acc, curr) => {
60
+ const stepNumber = extractNumber(curr);
61
+ const { data: data2 } = getStep(values)({
62
+ step: stepNumber
63
+ });
64
+ for (const [key, value] of Object.entries(data2)) {
65
+ if (typeof value === "function" && key !== "update") {
66
+ continue;
67
+ }
68
+ data2[key] = value;
69
+ }
70
+ acc[curr] = data2;
71
+ return acc;
72
+ }, {});
73
+ }
74
+ function createCtx(values, stepData) {
75
+ const formatter = new Intl.ListFormat("en", {
76
+ style: "long",
77
+ type: "disjunction"
78
+ });
79
+ const validStepKeys = Object.keys(values);
80
+ const baseErrorMessage = () => {
81
+ return `"stepData" must be set to an array of available steps (${formatter.format(
82
+ validStepKeys
83
+ )})`;
84
+ };
85
+ if (stepData === "all") {
86
+ let ctx = {};
87
+ for (const key of validStepKeys) {
88
+ ctx = {
89
+ ...ctx,
90
+ [key]: getStep(values)({
91
+ step: extractNumber(key)
92
+ })
93
+ };
94
+ }
95
+ return createCtxHelper(
96
+ values,
97
+ validStepKeys
98
+ );
99
+ }
100
+ if (Array.isArray(stepData)) {
101
+ invariant(
102
+ stepData.every((step) => validStepKeys.includes(step)),
103
+ () => {
104
+ const comparedResults = comparePartialArray(
105
+ stepData,
106
+ validStepKeys.map((key) => extractNumber(key)),
107
+ formatter
108
+ );
109
+ if (comparedResults.status === "error") {
110
+ return `${baseErrorMessage()}. See errors:
111
+ ${printErrors(
112
+ comparedResults.errors
113
+ )}`;
114
+ }
115
+ return baseErrorMessage();
116
+ }
117
+ );
118
+ return createCtxHelper(
119
+ values,
120
+ stepData
121
+ );
122
+ }
123
+ if (typeof stepData === "object") {
124
+ const keys = Object.keys(stepData);
125
+ invariant(
126
+ keys.every((key) => validStepKeys.includes(key)),
127
+ () => {
128
+ const comparedResults = comparePartialArray(
129
+ keys,
130
+ validStepKeys,
131
+ formatter
132
+ );
133
+ if (comparedResults.status === "error") {
134
+ return `${baseErrorMessage()}. See errors:
135
+ ${printErrors(
136
+ comparedResults.errors
137
+ )}`;
138
+ }
139
+ return baseErrorMessage();
140
+ }
141
+ );
142
+ return createCtxHelper(
143
+ values,
144
+ keys
145
+ );
146
+ }
147
+ throw new Error(`${baseErrorMessage()} OR to "all"`);
148
+ }
149
+ function functionalUpdate(updater, input) {
150
+ if (typeof updater === "function") {
151
+ return updater(input);
152
+ }
153
+ return updater;
154
+ }
155
+ const DEFAULT_LOGGER_PREFIX = "MultiStepFormSchema";
156
+ class MultiStepFormLogger {
157
+ debug;
158
+ prefix = DEFAULT_LOGGER_PREFIX;
159
+ includeTimestamp = false;
160
+ throwOnError = false;
161
+ constructor(options) {
162
+ this.debug = options?.debug ?? false;
163
+ if (this.debug && options?.debug) {
164
+ const {
165
+ includeTimestamp = false,
166
+ prefix = DEFAULT_LOGGER_PREFIX,
167
+ throwOnError = false
168
+ } = options;
169
+ this.includeTimestamp = includeTimestamp;
170
+ this.prefix = typeof prefix === "string" ? prefix : prefix(DEFAULT_LOGGER_PREFIX);
171
+ this.throwOnError = throwOnError;
172
+ }
173
+ }
174
+ wrapValue(wrapWith, value) {
175
+ if (wrapWith === "[]") {
176
+ return `[${value}]`;
177
+ }
178
+ if (wrapWith === "{}") {
179
+ return `{${value}}`;
180
+ }
181
+ if (wrapWith === "none") {
182
+ return value;
183
+ }
184
+ throw new Error(
185
+ `The first argument ${wrapWith} is not valid. Valid options include: "[]", "{}", and "none"`
186
+ );
187
+ }
188
+ formatPrefix(options) {
189
+ if (!options) {
190
+ return this.prefix;
191
+ }
192
+ const { action, value, wrapWith } = options;
193
+ if (action === "replace") {
194
+ return this.wrapValue(wrapWith ?? "[]", value);
195
+ }
196
+ const { delimiter } = options;
197
+ if (action === "append") {
198
+ return `${this.wrapValue(
199
+ wrapWith?.originalPrefix ?? "[]",
200
+ this.prefix
201
+ )}${delimiter}${this.wrapValue(
202
+ wrapWith?.addedPrefix ?? "[]",
203
+ value
204
+ )}`.trim();
205
+ }
206
+ if (action === "prepend") {
207
+ return `${this.wrapValue(
208
+ wrapWith?.addedPrefix ?? "[]",
209
+ value
210
+ )}${delimiter}${this.wrapValue(
211
+ wrapWith?.originalPrefix ?? "[]",
212
+ this.prefix
213
+ )}`.trim();
214
+ }
215
+ return this.prefix;
216
+ }
217
+ formatMessage(level, message, options) {
218
+ const {
219
+ includeTimestamp = this.includeTimestamp,
220
+ prefix,
221
+ logLevelOptions
222
+ } = options ?? {};
223
+ const formattedPrefix = this.formatPrefix(prefix);
224
+ const formattedLogLevel = this.wrapValue(
225
+ logLevelOptions?.wrapWith ?? "[]",
226
+ (logLevelOptions?.level ?? level).toUpperCase()
227
+ );
228
+ const formattedMessage = `${formattedPrefix} ${formattedLogLevel} ${message}`;
229
+ if (includeTimestamp) {
230
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
231
+ return `[${timestamp}] ${formattedMessage}`;
232
+ }
233
+ return formattedMessage;
234
+ }
235
+ info(message, options) {
236
+ if (!this.debug) {
237
+ return;
238
+ }
239
+ console.info(this.formatMessage("info", message, options));
240
+ }
241
+ warn(message, options) {
242
+ if (!this.debug) {
243
+ return;
244
+ }
245
+ console.warn(this.formatMessage("warn", message, options));
246
+ }
247
+ error(message, options) {
248
+ if (!this.debug) {
249
+ return;
250
+ }
251
+ const formatted = this.formatMessage("error", message, options);
252
+ console.error(formatted);
253
+ const throwOnError = options?.throw ?? this.throwOnError;
254
+ if (throwOnError) {
255
+ throw new Error(formatted);
256
+ }
257
+ }
258
+ }
259
+ var path;
260
+ ((path2) => {
261
+ function getBy(obj, path3) {
262
+ return path3.split(".").reduce((acc, key) => acc == null ? void 0 : acc[key], obj);
263
+ }
264
+ function setBy(target, path3, value) {
265
+ const keys = path3.split(".");
266
+ let current = target;
267
+ for (let i = 0; i < keys.length; i++) {
268
+ const k = keys[i];
269
+ if (i === keys.length - 1) {
270
+ if (current[k] !== void 0 && typeof current[k] === "object" && typeof value === "object" && value !== null) {
271
+ Object.assign(current[k], value);
272
+ } else {
273
+ current[k] = value;
274
+ }
275
+ } else {
276
+ if (typeof current[k] !== "object" || current[k] === null) {
277
+ current[k] = {};
278
+ }
279
+ current = current[k];
280
+ }
281
+ }
282
+ return current;
283
+ }
284
+ path2.setBy = setBy;
285
+ function normalizePaths(...paths) {
286
+ const sorted = [...paths].sort(
287
+ (a, b) => b.split(".").length - a.split(".").length
288
+ );
289
+ const finalPaths = [];
290
+ for (const path3 of sorted) {
291
+ const isCovered = finalPaths.some((p) => p.startsWith(path3 + "."));
292
+ if (!isCovered) {
293
+ finalPaths.push(path3);
294
+ }
295
+ }
296
+ return finalPaths.reverse();
297
+ }
298
+ path2.normalizePaths = normalizePaths;
299
+ function pickBy(obj, ...paths) {
300
+ const norm = normalizePaths(...paths);
301
+ if (norm.length === 1) {
302
+ return getBy(obj, norm[0]);
303
+ }
304
+ const result = {};
305
+ for (const p of norm) {
306
+ const value = getBy(obj, p);
307
+ setBy(result, p, value);
308
+ }
309
+ return result;
310
+ }
311
+ path2.pickBy = pickBy;
312
+ function createDeep(obj) {
313
+ const paths = [];
314
+ function traverse(current, prefix = "") {
315
+ if (current === null || current === void 0) {
316
+ return;
317
+ }
318
+ if (typeof current !== "object" || Array.isArray(current)) {
319
+ return;
320
+ }
321
+ const keys = Object.keys(current);
322
+ for (const key of keys) {
323
+ const path3 = prefix ? `${prefix}.${key}` : key;
324
+ paths.push(path3);
325
+ const value = current[key];
326
+ if (value !== null && value !== void 0 && typeof value === "object" && !Array.isArray(value)) {
327
+ traverse(value, path3);
328
+ }
329
+ }
330
+ }
331
+ traverse(obj);
332
+ return paths;
333
+ }
334
+ path2.createDeep = createDeep;
335
+ function defaultExpectedFormat(value) {
336
+ if (value === null) return "null";
337
+ if (Array.isArray(value)) return "Array";
338
+ const t = typeof value;
339
+ if (t !== "object") return t;
340
+ const ctor = value?.constructor?.name;
341
+ return ctor && ctor !== "Object" ? ctor : "object";
342
+ }
343
+ function splitPath(path3) {
344
+ if (!path3) return [];
345
+ const parts = [];
346
+ const regex = /[^.[\]]+|\[(\d+)\]/g;
347
+ let m;
348
+ while (m = regex.exec(path3)) {
349
+ parts.push(m[1] ?? m[0]);
350
+ }
351
+ return parts;
352
+ }
353
+ function getTransformFunction(root, path3) {
354
+ if (!root) return void 0;
355
+ if (typeof root === "function") {
356
+ return root;
357
+ }
358
+ const segments = splitPath(path3);
359
+ let node = root;
360
+ let lastFn;
361
+ for (const seg of segments) {
362
+ if (!node) break;
363
+ if (typeof node === "function") {
364
+ lastFn = node;
365
+ break;
366
+ }
367
+ node = node[seg];
368
+ if (typeof node === "function") {
369
+ lastFn = node;
370
+ break;
371
+ }
372
+ }
373
+ return lastFn;
374
+ }
375
+ function formatExpected(rawExpected, path3, cfg) {
376
+ const fn = getTransformFunction(cfg, path3);
377
+ if (fn) return fn(rawExpected, path3);
378
+ return defaultExpectedFormat(rawExpected);
379
+ }
380
+ function isObjectLike(v) {
381
+ return typeof v === "object" && v !== null;
382
+ }
383
+ function deepCompare(expected, actual, basePath, mismatches, options) {
384
+ if (expected === actual) {
385
+ return mismatches;
386
+ }
387
+ if (expected === null || actual === null || typeof expected !== "object" || typeof actual !== "object") {
388
+ const path4 = basePath || "(root)";
389
+ if (typeof expected !== typeof actual) {
390
+ mismatches.push({
391
+ path: path4,
392
+ expected: formatExpected(expected, path4, options.transformExpected),
393
+ actual,
394
+ reason: "type-mismatch"
395
+ });
396
+ return mismatches;
397
+ }
398
+ if (options.includeValueMismatch) {
399
+ mismatches.push({
400
+ path: path4,
401
+ expected: formatExpected(expected, path4, options.transformExpected),
402
+ actual,
403
+ reason: "value-mismatch"
404
+ });
405
+ }
406
+ return mismatches;
407
+ }
408
+ if (Array.isArray(expected) || Array.isArray(actual)) {
409
+ if (!Array.isArray(expected) || !Array.isArray(actual)) {
410
+ const path4 = basePath || "(root)";
411
+ mismatches.push({
412
+ path: path4,
413
+ expected: formatExpected(expected, path4, options.transformExpected),
414
+ actual,
415
+ reason: "type-mismatch"
416
+ });
417
+ return mismatches;
418
+ }
419
+ const maxLen = expected.length;
420
+ for (let i = 0; i < maxLen; i++) {
421
+ const expVal = expected[i];
422
+ const actVal = actual[i];
423
+ const path4 = basePath === "" ? `[${i}]` : `${basePath}[${i}]`;
424
+ deepCompare(expVal, actVal, path4, mismatches, options);
425
+ }
426
+ return mismatches;
427
+ }
428
+ if (isObjectLike(expected) && isObjectLike(actual)) {
429
+ const expKeys = Object.keys(expected);
430
+ const actKeys = Object.keys(actual);
431
+ for (const key of expKeys) {
432
+ const expVal = expected[key];
433
+ const actVal = actual[key];
434
+ const path4 = basePath ? `${basePath}.${key}` : key;
435
+ if (!(key in actual)) {
436
+ mismatches.push({
437
+ path: path4,
438
+ expected: formatExpected(expVal, path4, options.transformExpected),
439
+ actual: void 0,
440
+ reason: "missing-key"
441
+ });
442
+ continue;
443
+ }
444
+ deepCompare(expVal, actVal, path4, mismatches, options);
445
+ }
446
+ for (const key of actKeys) {
447
+ if (!(key in expected)) {
448
+ const path4 = basePath ? `${basePath}.${key}` : key;
449
+ mismatches.push({
450
+ path: path4,
451
+ expected: void 0,
452
+ actual: actual[key],
453
+ reason: "extra-key"
454
+ });
455
+ }
456
+ }
457
+ return mismatches;
458
+ }
459
+ const path3 = basePath || "(root)";
460
+ if (typeof expected !== typeof actual) {
461
+ mismatches.push({
462
+ path: path3,
463
+ expected: formatExpected(expected, path3, options.transformExpected),
464
+ actual,
465
+ reason: "type-mismatch"
466
+ });
467
+ } else if (options.includeValueMismatch) {
468
+ mismatches.push({
469
+ path: path3,
470
+ expected: formatExpected(expected, path3, options.transformExpected),
471
+ actual,
472
+ reason: "value-mismatch"
473
+ });
474
+ }
475
+ return mismatches;
476
+ }
477
+ function equalsAtPaths(obj, paths, actual, options) {
478
+ const expected = pickBy(obj, ...paths);
479
+ const mismatches = [];
480
+ const basePath = paths.length === 1 ? paths[0] : "";
481
+ deepCompare(expected, actual, basePath, mismatches, {
482
+ transformExpected: options?.transformExpected
483
+ });
484
+ return {
485
+ ok: mismatches.length === 0,
486
+ mismatches
487
+ };
488
+ }
489
+ path2.equalsAtPaths = equalsAtPaths;
490
+ function formatValue(v) {
491
+ if (v === void 0) return "undefined";
492
+ if (typeof v === "string") return JSON.stringify(v);
493
+ try {
494
+ return JSON.stringify(v, null, 2);
495
+ } catch {
496
+ return String(v);
497
+ }
498
+ }
499
+ function formatReason(m) {
500
+ switch (m.reason) {
501
+ case "missing-key":
502
+ return "Missing key";
503
+ case "extra-key":
504
+ return "Extra key";
505
+ case "type-mismatch":
506
+ return "Type mismatch";
507
+ case "value-mismatch":
508
+ return "Value mismatch";
509
+ default:
510
+ return m.reason;
511
+ }
512
+ }
513
+ function formatMismatches(result) {
514
+ if (result.ok || result.mismatches.length === 0) {
515
+ return "No mismatches.";
516
+ }
517
+ const lines = [];
518
+ for (const m of result.mismatches) {
519
+ lines.push(
520
+ `
521
+ ● ${formatReason(m)} at "${m.path}":`,
522
+ ` expected: ${formatValue(m.expected)}`,
523
+ ` actual: ${formatValue(m.actual)}`,
524
+ ""
525
+ // blank line between entries
526
+ );
527
+ }
528
+ if (lines.at(-1) === "") {
529
+ lines.pop();
530
+ }
531
+ return lines.join("\n");
532
+ }
533
+ path2.formatMismatches = formatMismatches;
534
+ function printMismatches(result) {
535
+ const msg = formatMismatches(result);
536
+ if (msg !== "No mismatches.") {
537
+ console.error(msg);
538
+ }
539
+ }
540
+ path2.printMismatches = printMismatches;
541
+ function setAtImmutable(root, path3, value) {
542
+ const keys = path3.split(".");
543
+ function helper(current, idx) {
544
+ const key = keys[idx];
545
+ const resolvedCurrent = Array.isArray(current) ? [...current] : { ...current };
546
+ if (idx === keys.length - 1) {
547
+ let clone2 = current && typeof current === "object" ? resolvedCurrent : {};
548
+ clone2 = {
549
+ ...clone2,
550
+ [key]: value
551
+ };
552
+ return clone2;
553
+ }
554
+ const next = current && typeof current === "object" ? current[key] : void 0;
555
+ const updatedChild = helper(next ?? {}, idx + 1);
556
+ let clone = current && typeof current === "object" ? resolvedCurrent : {};
557
+ clone = {
558
+ ...clone,
559
+ [key]: updatedChild
560
+ };
561
+ return clone;
562
+ }
563
+ return helper(root, 0);
564
+ }
565
+ function updateAt(obj, paths, value) {
566
+ const norm = normalizePaths(...paths);
567
+ if (norm.length === 0) return obj;
568
+ let result = obj;
569
+ if (norm.length === 1) {
570
+ const path3 = norm[0];
571
+ result = setAtImmutable(result, path3, value);
572
+ return result;
573
+ }
574
+ for (const path3 of norm) {
575
+ const sub = getBy(value, path3);
576
+ result = setAtImmutable(result, path3, sub);
577
+ }
578
+ return result;
579
+ }
580
+ path2.updateAt = updateAt;
581
+ })(path || (path = {}));
582
+ function runStandardValidation(schema, input) {
583
+ const result = schema["~standard"].validate(input);
584
+ if (result instanceof Promise) {
585
+ throw new TypeError("Schema validation must be synchronous", {
586
+ cause: schema
587
+ });
588
+ }
589
+ if (result.issues) {
590
+ throw new Error(JSON.stringify(result.issues, null, 2));
591
+ }
592
+ return result.value;
593
+ }
594
+ function isValidStepKey(steps, stepKey) {
595
+ return Object.keys(steps).includes(stepKey);
596
+ }
597
+ class MultiStepFormStepSchemaInternal {
598
+ #getValue;
599
+ #setValue;
600
+ get value() {
601
+ return this.#getValue();
602
+ }
603
+ constructor(options) {
604
+ const { getValue, setValue } = options;
605
+ this.#getValue = getValue;
606
+ this.#setValue = setValue;
607
+ }
608
+ handlePostUpdate(value) {
609
+ this.#setValue(this.enrichValues(value));
610
+ }
611
+ createStepUpdaterFnImpl(options) {
612
+ const { targetStep, updater, ctxData, fields: fields2 = "all", debug } = options;
613
+ const logger = new MultiStepFormLogger({
614
+ debug,
615
+ prefix: (value) => `${value}:update${targetStep}`
616
+ });
617
+ logger.info(`${targetStep} will be updated`);
618
+ invariant(
619
+ isValidStepKey(this.value, targetStep),
620
+ `[update]: The target step ${targetStep} isn't a valid step. Please select a valid step`
621
+ );
622
+ const { [targetStep]: currentStep, ...values } = this.value;
623
+ let updatedValue = { ...this.value };
624
+ let ctx = createCtx(updatedValue, [targetStep]);
625
+ if (ctxData) {
626
+ invariant(
627
+ typeof ctxData === "function",
628
+ '[update]: "ctxData" must be a function'
629
+ );
630
+ logger.info('Custom "ctx" will be used');
631
+ const additionalCtx = ctxData({ ctx: values });
632
+ invariant(
633
+ typeof additionalCtx === "object" && Object.keys(additionalCtx).length > 0,
634
+ '[update]: "ctxData" must return an object with keys'
635
+ );
636
+ logger.info(
637
+ `Custom "ctx" consists of the following keys: ${new Intl.ListFormat(
638
+ "en",
639
+ {
640
+ style: "long",
641
+ type: "conjunction"
642
+ }
643
+ ).format(Object.keys(additionalCtx))}`
644
+ );
645
+ ctx = {
646
+ ...ctx,
647
+ ...additionalCtx
648
+ };
649
+ }
650
+ const updated = functionalUpdate(updater, {
651
+ ctx,
652
+ update: this.createHelperFnInputUpdate([targetStep])
653
+ });
654
+ logger.info(`The updated data is ${JSON.stringify(updated, null, 2)}`);
655
+ if (!fields2) {
656
+ invariant(
657
+ typeof updated === "object",
658
+ '[update]: "updater" must be an object or a function that returns an object'
659
+ );
660
+ const stepKeys = Object.keys(this.value);
661
+ const updaterResultKeys = Object.keys(updated);
662
+ invariant(updaterResultKeys.length === stepKeys.length, () => {
663
+ const missingKeys = stepKeys.filter(
664
+ (key) => !updaterResultKeys.includes(key)
665
+ );
666
+ const formatter = new Intl.ListFormat("en", {
667
+ style: "long",
668
+ type: "conjunction"
669
+ });
670
+ return `[update]: "updater" is missing keys ${formatter.format(
671
+ missingKeys
672
+ )}`;
673
+ });
674
+ const paths = path.createDeep(this.value);
675
+ const { mismatches, ok } = path.equalsAtPaths(
676
+ this.value,
677
+ paths,
678
+ updated
679
+ );
680
+ invariant(
681
+ ok && mismatches.length === 0,
682
+ `[update]: found value mismatches in ${path.printMismatches({
683
+ mismatches,
684
+ ok
685
+ })}`
686
+ );
687
+ logger.info("The entire step will be updated");
688
+ updatedValue = {
689
+ ...updatedValue,
690
+ [targetStep]: path.updateAt(updatedValue, paths, updated)
691
+ };
692
+ this.handlePostUpdate(updatedValue);
693
+ logger.info(`The new value is: ${JSON.stringify(updatedValue, null, 2)}`);
694
+ return;
695
+ }
696
+ const currentStepDeepKeys = path.createDeep(currentStep);
697
+ if (Array.isArray(fields2)) {
698
+ const compareResult = comparePartialArray(currentStepDeepKeys, fields2);
699
+ invariant(
700
+ compareResult.status === "success",
701
+ `[update]: Found errors with the provided fields
702
+ ${compareResult.status === "error" ? printErrors(compareResult.errors) : ""}`
703
+ );
704
+ const { mismatches, ok } = path.equalsAtPaths(
705
+ currentStep,
706
+ fields2,
707
+ updated
708
+ );
709
+ invariant(
710
+ ok && mismatches.length === 0,
711
+ `[update]: found value mismatches in ${path.printMismatches({
712
+ ok,
713
+ mismatches
714
+ })}`
715
+ );
716
+ logger.info(
717
+ `The following fields will be updated: ${new Intl.ListFormat("en", {
718
+ type: "conjunction",
719
+ style: "long"
720
+ }).format(fields2)}`
721
+ );
722
+ updatedValue = {
723
+ ...updatedValue,
724
+ [targetStep]: path.updateAt(currentStep, fields2, updated)
725
+ };
726
+ this.handlePostUpdate(updatedValue);
727
+ logger.info(`The new value is: ${JSON.stringify(updatedValue, null, 2)}`);
728
+ return;
729
+ }
730
+ if (typeof fields2 === "object" && Object.keys(fields2).length > 0) {
731
+ const keys = path.createDeep(fields2);
732
+ const compareResult = comparePartialArray(
733
+ currentStepDeepKeys,
734
+ keys
735
+ );
736
+ invariant(
737
+ compareResult.status === "success",
738
+ `[update]: Found errors with the provided fields
739
+ ${compareResult.status === "error" ? printErrors(compareResult.errors) : ""}`
740
+ );
741
+ const { mismatches, ok } = path.equalsAtPaths(
742
+ currentStep,
743
+ keys,
744
+ updated
745
+ );
746
+ invariant(
747
+ ok && mismatches.length === 0,
748
+ `[update]: found value mismatches in ${path.printMismatches({
749
+ ok,
750
+ mismatches
751
+ })}`
752
+ );
753
+ updatedValue = {
754
+ ...updatedValue,
755
+ [targetStep]: path.updateAt(
756
+ currentStep,
757
+ keys,
758
+ updated
759
+ )
760
+ };
761
+ logger.info(
762
+ `The following fields will be updated: ${new Intl.ListFormat("en", {
763
+ type: "conjunction",
764
+ style: "long"
765
+ }).format(Object.keys(fields2))}`
766
+ );
767
+ this.handlePostUpdate(updatedValue);
768
+ logger.info(`The new value is: ${JSON.stringify(updatedValue, null, 2)}`);
769
+ return;
770
+ }
771
+ logger.error('Unsupported value for the "fields" option');
772
+ throw new TypeError(
773
+ `[update]: property "fields" must be set to one of the following: "all", an array of deep paths to update, or an object of paths. Was ${typeof updater}`,
774
+ { cause: updater }
775
+ );
776
+ }
777
+ createStepUpdaterFn(targetStep) {
778
+ return (options) => {
779
+ this.createStepUpdaterFnImpl({ targetStep, ...options });
780
+ };
781
+ }
782
+ update(options) {
783
+ return this.createStepUpdaterFnImpl(options);
784
+ }
785
+ createHelperFnInputUpdate(chosenSteps) {
786
+ if (HelperFnChosenSteps.isAll(chosenSteps)) {
787
+ const stepSpecificUpdateFn = typedObjectKeys(this.value).reduce((acc, key) => {
788
+ acc[key] = this.createStepUpdaterFn(key);
789
+ return acc;
790
+ }, {});
791
+ const update = Object.assign(
792
+ this.update,
793
+ stepSpecificUpdateFn
794
+ );
795
+ return update;
796
+ }
797
+ const validKeys = Object.keys(this.value);
798
+ if (HelperFnChosenSteps.isTuple(chosenSteps, validKeys)) {
799
+ const stepSpecificUpdateFn = chosenSteps.reduce((acc, step) => {
800
+ acc[step] = this.createStepUpdaterFn(step);
801
+ return acc;
802
+ }, {});
803
+ const update = Object.assign(
804
+ this.update,
805
+ stepSpecificUpdateFn
806
+ );
807
+ return update;
808
+ }
809
+ if (HelperFnChosenSteps.isObject(chosenSteps, validKeys)) {
810
+ const stepSpecificUpdateFn = typedObjectKeys(chosenSteps).reduce((acc, key) => {
811
+ acc[key] = this.createStepUpdaterFn(key);
812
+ return acc;
813
+ }, {});
814
+ const update = Object.assign(
815
+ this.update,
816
+ stepSpecificUpdateFn
817
+ );
818
+ return update;
819
+ }
820
+ throw new TypeError(`[update]: ${HelperFnChosenSteps.CATCH_ALL_MESSAGE}`);
821
+ }
822
+ createStepHelperFn(stepData) {
823
+ return (optionsOrFunction, fn) => {
824
+ const createInputUpdateFn = this.createHelperFnInputUpdate(
825
+ stepData
826
+ );
827
+ if (typeof optionsOrFunction === "function") {
828
+ return () => {
829
+ const ctx = createCtx(
830
+ this.value,
831
+ stepData
832
+ );
833
+ return optionsOrFunction({
834
+ ctx,
835
+ update: createInputUpdateFn
836
+ });
837
+ };
838
+ }
839
+ if (typeof optionsOrFunction === "object") {
840
+ return (input) => {
841
+ const ctx = createCtx(
842
+ this.value,
843
+ stepData
844
+ );
845
+ if ("validator" in optionsOrFunction) {
846
+ invariant(
847
+ typeof input === "object",
848
+ "An input is expected since you provided a validator"
849
+ );
850
+ runStandardValidation(
851
+ optionsOrFunction.validator,
852
+ input.data
853
+ );
854
+ let resolvedCtx = ctx;
855
+ if (optionsOrFunction.ctxData) {
856
+ const currentStepKey = stepData[0];
857
+ const { [currentStepKey]: _, ...values } = this.value;
858
+ resolvedCtx = {
859
+ ...resolvedCtx,
860
+ ...optionsOrFunction.ctxData({ ctx: values })
861
+ };
862
+ }
863
+ return fn({
864
+ ctx: resolvedCtx,
865
+ update: createInputUpdateFn,
866
+ ...input
867
+ });
868
+ }
869
+ return fn({
870
+ ctx,
871
+ update: createInputUpdateFn
872
+ });
873
+ };
874
+ }
875
+ throw new Error(
876
+ `The first argument must be a function or an object, (was ${typeof optionsOrFunction})`
877
+ );
878
+ };
879
+ }
880
+ enrichValues(values, additionalProps) {
881
+ let enriched = { ...values };
882
+ for (const [key, stepValue] of Object.entries(enriched)) {
883
+ const [targetStep] = [key];
884
+ const step = Number.parseInt(
885
+ targetStep.replace("step", "")
886
+ );
887
+ enriched[targetStep] = {
888
+ ...stepValue,
889
+ update: this.createStepUpdaterFn(targetStep),
890
+ createHelperFn: this.createStepHelperFn([targetStep]),
891
+ ...additionalProps?.(step)
892
+ };
893
+ }
894
+ return enriched;
895
+ }
896
+ }
897
+ var fields;
898
+ ((fields2) => {
899
+ function resolvedDeepPath(fieldPath, fields3, filler = "defaultValue") {
900
+ const [parent, ...children] = fieldPath.split(".");
901
+ const shared = `${parent}.${filler}`;
902
+ const fullPath = children.length === 0 ? shared : `${shared}.${children.join(".")}`;
903
+ const resolvedValue = path.pickBy(fields3, fullPath);
904
+ return resolvedValue;
905
+ }
906
+ fields2.resolvedDeepPath = resolvedDeepPath;
907
+ })(fields || (fields = {}));
908
+ var HelperFnChosenSteps;
909
+ ((HelperFnChosenSteps2) => {
910
+ HelperFnChosenSteps2.CATCH_ALL_MESSAGE = 'The chosen steps must either be set to on of the following: "all", an array of steps (["step1", "step2", ...]), or an object containing the steps to chose ({ step1: true, step2: true, ...})';
911
+ function isAll(value) {
912
+ return Boolean(value && typeof value === "string" && value === "all");
913
+ }
914
+ HelperFnChosenSteps2.isAll = isAll;
915
+ function isTuple(value, validValues) {
916
+ if (!Array.isArray(value)) {
917
+ return false;
918
+ }
919
+ if (validValues) {
920
+ return value.every((key) => validValues.includes(key));
921
+ }
922
+ return true;
923
+ }
924
+ HelperFnChosenSteps2.isTuple = isTuple;
925
+ function isObject(value, validKeys) {
926
+ if (!value) {
927
+ return false;
928
+ }
929
+ const keys = Object.keys(value);
930
+ if (keys.length === 0) {
931
+ return false;
932
+ }
933
+ if (validKeys && !keys.every((key) => validKeys.includes(key))) {
934
+ return false;
935
+ }
936
+ return Object.entries(value).every(([_, v]) => v === true);
937
+ }
938
+ HelperFnChosenSteps2.isObject = isObject;
939
+ })(HelperFnChosenSteps || (HelperFnChosenSteps = {}));
940
+ export {
941
+ DEFAULT_LOGGER_PREFIX as D,
942
+ HelperFnChosenSteps as H,
943
+ MultiStepFormLogger as M,
944
+ MultiStepFormStepSchemaInternal as a,
945
+ isValidStepKey as b,
946
+ createCtx as c,
947
+ fields as f,
948
+ getStep as g,
949
+ invariant as i,
950
+ path as p,
951
+ runStandardValidation as r
952
+ };
953
+ //# sourceMappingURL=types-CYf1_lBe.js.map