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