@jfdevelops/multi-step-form-core 1.0.0-alpha.17 → 1.0.0-alpha.18

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.
Files changed (147) hide show
  1. package/dist/_internals.cjs +14 -0
  2. package/dist/_internals.d.cts +4 -0
  3. package/dist/_internals.d.mts +4 -0
  4. package/dist/_internals.mjs +5 -0
  5. package/dist/index.cjs +49 -0
  6. package/dist/index.d.cts +14 -0
  7. package/dist/index.d.mts +14 -0
  8. package/dist/index.mjs +16 -0
  9. package/dist/internals/step-schema.cjs +389 -0
  10. package/dist/internals/step-schema.cjs.map +1 -0
  11. package/dist/internals/step-schema.d.cts +41 -0
  12. package/dist/internals/step-schema.d.cts.map +1 -0
  13. package/dist/internals/step-schema.d.mts +41 -0
  14. package/dist/internals/step-schema.d.mts.map +1 -0
  15. package/dist/internals/step-schema.mjs +389 -0
  16. package/dist/internals/step-schema.mjs.map +1 -0
  17. package/dist/internals/utils.cjs +94 -0
  18. package/dist/internals/utils.cjs.map +1 -0
  19. package/dist/internals/utils.d.cts +27 -0
  20. package/dist/internals/utils.d.cts.map +1 -0
  21. package/dist/internals/utils.d.mts +27 -0
  22. package/dist/internals/utils.d.mts.map +1 -0
  23. package/dist/internals/utils.mjs +91 -0
  24. package/dist/internals/utils.mjs.map +1 -0
  25. package/dist/observable.cjs +44 -0
  26. package/dist/observable.cjs.map +1 -0
  27. package/dist/observable.d.cts +26 -0
  28. package/dist/observable.d.cts.map +1 -0
  29. package/dist/observable.d.mts +26 -0
  30. package/dist/observable.d.mts.map +1 -0
  31. package/dist/observable.mjs +44 -0
  32. package/dist/observable.mjs.map +1 -0
  33. package/dist/schema.cjs +68 -0
  34. package/dist/schema.cjs.map +1 -0
  35. package/dist/schema.d.cts +28 -0
  36. package/dist/schema.d.cts.map +1 -0
  37. package/dist/schema.d.mts +28 -0
  38. package/dist/schema.d.mts.map +1 -0
  39. package/dist/schema.mjs +67 -0
  40. package/dist/schema.mjs.map +1 -0
  41. package/dist/steps/fields.cjs +23 -0
  42. package/dist/steps/fields.cjs.map +1 -0
  43. package/dist/steps/fields.d.cts +18 -0
  44. package/dist/steps/fields.d.cts.map +1 -0
  45. package/dist/steps/fields.d.mts +18 -0
  46. package/dist/steps/fields.d.mts.map +1 -0
  47. package/dist/steps/fields.mjs +18 -0
  48. package/dist/steps/fields.mjs.map +1 -0
  49. package/dist/steps/index.cjs +4 -0
  50. package/dist/steps/index.mjs +6 -0
  51. package/dist/steps/schema.cjs +194 -0
  52. package/dist/steps/schema.cjs.map +1 -0
  53. package/dist/steps/schema.d.cts +124 -0
  54. package/dist/steps/schema.d.cts.map +1 -0
  55. package/dist/steps/schema.d.mts +124 -0
  56. package/dist/steps/schema.d.mts.map +1 -0
  57. package/dist/steps/schema.mjs +194 -0
  58. package/dist/steps/schema.mjs.map +1 -0
  59. package/dist/steps/types.cjs +33 -0
  60. package/dist/steps/types.cjs.map +1 -0
  61. package/dist/steps/types.d.cts +332 -0
  62. package/dist/steps/types.d.cts.map +1 -0
  63. package/dist/steps/types.d.mts +332 -0
  64. package/dist/steps/types.d.mts.map +1 -0
  65. package/dist/steps/types.mjs +27 -0
  66. package/dist/steps/types.mjs.map +1 -0
  67. package/dist/steps/utils.cjs +96 -0
  68. package/dist/steps/utils.cjs.map +1 -0
  69. package/dist/steps/utils.d.cts +10 -0
  70. package/dist/steps/utils.d.cts.map +1 -0
  71. package/dist/steps/utils.d.mts +10 -0
  72. package/dist/steps/utils.d.mts.map +1 -0
  73. package/dist/steps/utils.mjs +94 -0
  74. package/dist/steps/utils.mjs.map +1 -0
  75. package/dist/storage.cjs +68 -0
  76. package/dist/storage.cjs.map +1 -0
  77. package/dist/storage.d.cts +33 -0
  78. package/dist/storage.d.cts.map +1 -0
  79. package/dist/storage.d.mts +33 -0
  80. package/dist/storage.d.mts.map +1 -0
  81. package/dist/storage.mjs +67 -0
  82. package/dist/storage.mjs.map +1 -0
  83. package/dist/subscribable.cjs +25 -0
  84. package/dist/subscribable.cjs.map +1 -0
  85. package/dist/subscribable.d.cts +14 -0
  86. package/dist/subscribable.d.cts.map +1 -0
  87. package/dist/subscribable.d.mts +14 -0
  88. package/dist/subscribable.d.mts.map +1 -0
  89. package/dist/subscribable.mjs +24 -0
  90. package/dist/subscribable.mjs.map +1 -0
  91. package/dist/utils/casing.cjs +63 -0
  92. package/dist/utils/casing.cjs.map +1 -0
  93. package/dist/utils/casing.d.cts +40 -0
  94. package/dist/utils/casing.d.cts.map +1 -0
  95. package/dist/utils/casing.d.mts +40 -0
  96. package/dist/utils/casing.d.mts.map +1 -0
  97. package/dist/utils/casing.mjs +57 -0
  98. package/dist/utils/casing.mjs.map +1 -0
  99. package/dist/utils/field-types.cjs +23 -0
  100. package/dist/utils/field-types.cjs.map +1 -0
  101. package/dist/utils/field-types.d.cts +11 -0
  102. package/dist/utils/field-types.d.cts.map +1 -0
  103. package/dist/utils/field-types.d.mts +11 -0
  104. package/dist/utils/field-types.d.mts.map +1 -0
  105. package/dist/utils/field-types.mjs +20 -0
  106. package/dist/utils/field-types.mjs.map +1 -0
  107. package/dist/utils/helpers.cjs +30 -0
  108. package/dist/utils/helpers.cjs.map +1 -0
  109. package/dist/utils/helpers.mjs +27 -0
  110. package/dist/utils/helpers.mjs.map +1 -0
  111. package/dist/utils/invariant.cjs +18 -0
  112. package/dist/utils/invariant.cjs.map +1 -0
  113. package/dist/utils/invariant.d.cts +5 -0
  114. package/dist/utils/invariant.d.cts.map +1 -0
  115. package/dist/utils/invariant.d.mts +5 -0
  116. package/dist/utils/invariant.d.mts.map +1 -0
  117. package/dist/utils/invariant.mjs +17 -0
  118. package/dist/utils/invariant.mjs.map +1 -0
  119. package/dist/utils/logger.cjs +58 -0
  120. package/dist/utils/logger.cjs.map +1 -0
  121. package/dist/utils/logger.d.cts +53 -0
  122. package/dist/utils/logger.d.cts.map +1 -0
  123. package/dist/utils/logger.d.mts +53 -0
  124. package/dist/utils/logger.d.mts.map +1 -0
  125. package/dist/utils/logger.mjs +56 -0
  126. package/dist/utils/logger.mjs.map +1 -0
  127. package/dist/utils/path.cjs +331 -0
  128. package/dist/utils/path.cjs.map +1 -0
  129. package/dist/utils/path.d.cts +139 -0
  130. package/dist/utils/path.d.cts.map +1 -0
  131. package/dist/utils/path.d.mts +139 -0
  132. package/dist/utils/path.d.mts.map +1 -0
  133. package/dist/utils/path.mjs +325 -0
  134. package/dist/utils/path.mjs.map +1 -0
  135. package/dist/utils/types.d.cts +25 -0
  136. package/dist/utils/types.d.cts.map +1 -0
  137. package/dist/utils/types.d.mts +25 -0
  138. package/dist/utils/types.d.mts.map +1 -0
  139. package/dist/utils/validator.cjs +12 -0
  140. package/dist/utils/validator.cjs.map +1 -0
  141. package/dist/utils/validator.d.cts +77 -0
  142. package/dist/utils/validator.d.cts.map +1 -0
  143. package/dist/utils/validator.d.mts +77 -0
  144. package/dist/utils/validator.d.mts.map +1 -0
  145. package/dist/utils/validator.mjs +11 -0
  146. package/dist/utils/validator.mjs.map +1 -0
  147. package/package.json +1 -1
@@ -0,0 +1,139 @@
1
+ import { DeepKeys, unionHelpers } from "./types.cjs";
2
+
3
+ //#region src/utils/path.d.ts
4
+ declare namespace path {
5
+ type getBy<T, TPath extends string> = TPath extends `${infer K}.${infer Rest}` ? K extends keyof T ? getBy<T[K], Rest> : never : TPath extends keyof T ? T[TPath] : never;
6
+ type buildFromPath<T, P extends string> = P extends `${infer K}.${infer Rest}` ? { [Key in K]: buildFromPath<getBy<T, K>, Rest> } : P extends keyof T ? { [Key in P]: T[P] } : never;
7
+ /**
8
+ * Does P have any ancestor path in All? (i.e. some Q in All such that Q is a
9
+ * strict prefix of P)
10
+ */
11
+ type hasAncestor<P extends string, All extends string> = true extends (All extends string ? All extends P ? false : P extends `${All}.${string}` ? true : false : never) ? true : false;
12
+ /**
13
+ * Normalize a union of paths by removing those that have an ancestor path
14
+ * also in the union.
15
+ *
16
+ * Example:
17
+ * NormalizePaths<'foo.bar.baz' | 'foo.bar'> -> 'foo.bar'
18
+ * NormalizePaths<'foo.bar' | 'other'> -> 'foo.bar' | 'other'
19
+ */
20
+ type normalize<Paths extends string, All extends string = Paths> = Paths extends string ? hasAncestor<Paths, All> extends true ? never : Paths : never;
21
+ type distributeAndBuild<T, Paths extends string> = Paths extends unknown ? buildFromPath<T, Paths> : never;
22
+ export type generateObjectConfig<T> = { [K in keyof T]: T[K] extends object ?
23
+ // K's value is an object: allow stopping at K, or going deeper
24
+ { [P in K]: true } | { [P in K]: generateObjectConfig<T[K]> } : { [P in K]: true } }[keyof T];
25
+ export type objectToPath<O> = { [K in keyof O]: O[K] extends true ? K & string : O[K] extends object ? `${K & string}.${objectToPath<O[K]>}` : never }[keyof O];
26
+ /**
27
+ * Pick by paths:
28
+ * - Normalize the paths (remove descendants when parent also present)
29
+ * - If only one normalized path:
30
+ * return GetByPath<T, P> (relative type)
31
+ * - If multiple:
32
+ * intersect root-built shapes for each normalized path
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * type User = {
37
+ * foo: {
38
+ * bar: {
39
+ * baz: number;
40
+ * qux: string;
41
+ * };
42
+ * };
43
+ * other: string;
44
+ * };
45
+ *
46
+ * type Test1 = PickByPaths<User, 'foo.bar'>;
47
+ * // { baz: number; qux: string } ✅ relative object at foo.bar
48
+ *
49
+ * type Test2 = PickByPaths<User, 'foo.bar.baz'>;
50
+ * // number ✅ leaf type
51
+ *
52
+ * type Test3 = PickByPaths<User, 'foo.bar' | 'other'>;
53
+ * // { foo: { bar: { baz: number; qux: string } } } & { other: string } ✅
54
+ *
55
+ * type Test4 = PickByPaths<User, 'foo.bar.baz' | 'foo.bar' | 'other'>;
56
+ * // { baz: number; qux: string } ✅ parent 'foo.bar' wins, relative
57
+ * ```
58
+ */
59
+ export type pickBy<T, Paths extends DeepKeys<T>> = normalize<Paths> extends infer normalized extends string ? unionHelpers.is<normalized> extends true ? unionHelpers.toIntersection<distributeAndBuild<T, normalized>> : getBy<T, normalized> : never;
60
+ function getBy(obj: any, path: string): any;
61
+ export function setBy<def extends Record<string, unknown>, path$1 extends DeepKeys<def>>(target: def, path: path$1, value: unknown): def;
62
+ export function normalizePaths(...paths: string[]): string[];
63
+ /**
64
+ * pickByPaths:
65
+ * - paths can be a union of string literals
66
+ * - return type is PickByPaths<T, Paths>
67
+ */
68
+ export function pickBy<def, paths extends DeepKeys<def>>(obj: def, ...paths: paths[]): pickBy<def, paths>;
69
+ /**
70
+ * Creates an array of all deep paths in an object.
71
+ * Recursively traverses the object and returns all possible dot-separated paths.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * const obj = {
76
+ * foo: {
77
+ * bar: {
78
+ * baz: 1,
79
+ * qux: 2
80
+ * }
81
+ * },
82
+ * other: 'value'
83
+ * };
84
+ *
85
+ * createPaths(obj);
86
+ * // ['foo', 'foo.bar', 'foo.bar.baz', 'foo.bar.qux', 'other']
87
+ * ```
88
+ */
89
+ export function createDeep<T>(obj: T): DeepKeys<T>[];
90
+ export type MismatchReason = 'value-mismatch' | 'type-mismatch' | 'missing-key' | 'extra-key';
91
+ export interface Mismatch {
92
+ path: string;
93
+ expected: unknown;
94
+ actual: unknown;
95
+ reason: MismatchReason;
96
+ }
97
+ export interface CompareResult {
98
+ ok: boolean;
99
+ mismatches: Mismatch[];
100
+ }
101
+ type ExpectedTransformFn<TValue = unknown> = (value: TValue, path: string) => unknown;
102
+ /**
103
+ * Transform config:
104
+ * - a single function: applies to the whole T
105
+ * - or an object shaped like T, where values are either:
106
+ * - functions (apply at/under that node)
107
+ * - nested objects continuing the shape
108
+ */
109
+ export type ExpectedTransformConfig<T, V = unknown> = ExpectedTransformFn<V> | { [K in keyof T]?: ExpectedTransformConfig<T[K], T[K]> };
110
+ export interface EqualsOptions<T> {
111
+ /**
112
+ * How to transform the "expected" field in mismatches.
113
+ * If omitted, a default type-ish formatting is used.
114
+ */
115
+ transformExpected?: ExpectedTransformConfig<T>;
116
+ }
117
+ export function equalsAtPaths<def, paths extends DeepKeys<def>>(obj: def, paths: paths[], actual: pickBy<def, paths>, options?: EqualsOptions<def>): CompareResult;
118
+ /**
119
+ * Turn a CompareResult into a pretty error string.
120
+ */
121
+ export function formatMismatches(result: CompareResult): string;
122
+ /**
123
+ * Convenience: log to console.error.
124
+ */
125
+ export function printMismatches(result: CompareResult): void;
126
+ export function findMissingPaths<obj extends Record<string, unknown>, path$1 extends DeepKeys<obj>>(obj: obj, paths: Array<path$1>, actual: pickBy<obj, path$1>): Array<DeepKeys<obj>>;
127
+ export type updateAtOptions<T extends Record<string, unknown>, path$1 extends DeepKeys<T>> = {
128
+ obj: T;
129
+ paths: Array<path$1>;
130
+ value: pickBy<T, path$1>;
131
+ partial?: boolean;
132
+ };
133
+ export function joinAtPath<obj extends Record<string, unknown>, path$1 extends DeepKeys<obj>>(paths: Array<path$1>, obj: obj, value: pickBy<obj, path$1>): pickBy<obj, path$1> | undefined;
134
+ export function updateAt<obj extends Record<string, unknown>, path$1 extends DeepKeys<obj>>(options: updateAtOptions<obj, path$1>): obj;
135
+ export {};
136
+ }
137
+ //#endregion
138
+ export { path };
139
+ //# sourceMappingURL=path.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.cts","names":[],"sources":["../../src/utils/path.ts"],"sourcesContent":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ import { DeepKeys, unionHelpers } from "./types.mjs";
2
+
3
+ //#region src/utils/path.d.ts
4
+ declare namespace path {
5
+ type getBy<T, TPath extends string> = TPath extends `${infer K}.${infer Rest}` ? K extends keyof T ? getBy<T[K], Rest> : never : TPath extends keyof T ? T[TPath] : never;
6
+ type buildFromPath<T, P extends string> = P extends `${infer K}.${infer Rest}` ? { [Key in K]: buildFromPath<getBy<T, K>, Rest> } : P extends keyof T ? { [Key in P]: T[P] } : never;
7
+ /**
8
+ * Does P have any ancestor path in All? (i.e. some Q in All such that Q is a
9
+ * strict prefix of P)
10
+ */
11
+ type hasAncestor<P extends string, All extends string> = true extends (All extends string ? All extends P ? false : P extends `${All}.${string}` ? true : false : never) ? true : false;
12
+ /**
13
+ * Normalize a union of paths by removing those that have an ancestor path
14
+ * also in the union.
15
+ *
16
+ * Example:
17
+ * NormalizePaths<'foo.bar.baz' | 'foo.bar'> -> 'foo.bar'
18
+ * NormalizePaths<'foo.bar' | 'other'> -> 'foo.bar' | 'other'
19
+ */
20
+ type normalize<Paths extends string, All extends string = Paths> = Paths extends string ? hasAncestor<Paths, All> extends true ? never : Paths : never;
21
+ type distributeAndBuild<T, Paths extends string> = Paths extends unknown ? buildFromPath<T, Paths> : never;
22
+ export type generateObjectConfig<T> = { [K in keyof T]: T[K] extends object ?
23
+ // K's value is an object: allow stopping at K, or going deeper
24
+ { [P in K]: true } | { [P in K]: generateObjectConfig<T[K]> } : { [P in K]: true } }[keyof T];
25
+ export type objectToPath<O> = { [K in keyof O]: O[K] extends true ? K & string : O[K] extends object ? `${K & string}.${objectToPath<O[K]>}` : never }[keyof O];
26
+ /**
27
+ * Pick by paths:
28
+ * - Normalize the paths (remove descendants when parent also present)
29
+ * - If only one normalized path:
30
+ * return GetByPath<T, P> (relative type)
31
+ * - If multiple:
32
+ * intersect root-built shapes for each normalized path
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * type User = {
37
+ * foo: {
38
+ * bar: {
39
+ * baz: number;
40
+ * qux: string;
41
+ * };
42
+ * };
43
+ * other: string;
44
+ * };
45
+ *
46
+ * type Test1 = PickByPaths<User, 'foo.bar'>;
47
+ * // { baz: number; qux: string } ✅ relative object at foo.bar
48
+ *
49
+ * type Test2 = PickByPaths<User, 'foo.bar.baz'>;
50
+ * // number ✅ leaf type
51
+ *
52
+ * type Test3 = PickByPaths<User, 'foo.bar' | 'other'>;
53
+ * // { foo: { bar: { baz: number; qux: string } } } & { other: string } ✅
54
+ *
55
+ * type Test4 = PickByPaths<User, 'foo.bar.baz' | 'foo.bar' | 'other'>;
56
+ * // { baz: number; qux: string } ✅ parent 'foo.bar' wins, relative
57
+ * ```
58
+ */
59
+ export type pickBy<T, Paths extends DeepKeys<T>> = normalize<Paths> extends infer normalized extends string ? unionHelpers.is<normalized> extends true ? unionHelpers.toIntersection<distributeAndBuild<T, normalized>> : getBy<T, normalized> : never;
60
+ function getBy(obj: any, path: string): any;
61
+ export function setBy<def extends Record<string, unknown>, path$1 extends DeepKeys<def>>(target: def, path: path$1, value: unknown): def;
62
+ export function normalizePaths(...paths: string[]): string[];
63
+ /**
64
+ * pickByPaths:
65
+ * - paths can be a union of string literals
66
+ * - return type is PickByPaths<T, Paths>
67
+ */
68
+ export function pickBy<def, paths extends DeepKeys<def>>(obj: def, ...paths: paths[]): pickBy<def, paths>;
69
+ /**
70
+ * Creates an array of all deep paths in an object.
71
+ * Recursively traverses the object and returns all possible dot-separated paths.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * const obj = {
76
+ * foo: {
77
+ * bar: {
78
+ * baz: 1,
79
+ * qux: 2
80
+ * }
81
+ * },
82
+ * other: 'value'
83
+ * };
84
+ *
85
+ * createPaths(obj);
86
+ * // ['foo', 'foo.bar', 'foo.bar.baz', 'foo.bar.qux', 'other']
87
+ * ```
88
+ */
89
+ export function createDeep<T>(obj: T): DeepKeys<T>[];
90
+ export type MismatchReason = 'value-mismatch' | 'type-mismatch' | 'missing-key' | 'extra-key';
91
+ export interface Mismatch {
92
+ path: string;
93
+ expected: unknown;
94
+ actual: unknown;
95
+ reason: MismatchReason;
96
+ }
97
+ export interface CompareResult {
98
+ ok: boolean;
99
+ mismatches: Mismatch[];
100
+ }
101
+ type ExpectedTransformFn<TValue = unknown> = (value: TValue, path: string) => unknown;
102
+ /**
103
+ * Transform config:
104
+ * - a single function: applies to the whole T
105
+ * - or an object shaped like T, where values are either:
106
+ * - functions (apply at/under that node)
107
+ * - nested objects continuing the shape
108
+ */
109
+ export type ExpectedTransformConfig<T, V = unknown> = ExpectedTransformFn<V> | { [K in keyof T]?: ExpectedTransformConfig<T[K], T[K]> };
110
+ export interface EqualsOptions<T> {
111
+ /**
112
+ * How to transform the "expected" field in mismatches.
113
+ * If omitted, a default type-ish formatting is used.
114
+ */
115
+ transformExpected?: ExpectedTransformConfig<T>;
116
+ }
117
+ export function equalsAtPaths<def, paths extends DeepKeys<def>>(obj: def, paths: paths[], actual: pickBy<def, paths>, options?: EqualsOptions<def>): CompareResult;
118
+ /**
119
+ * Turn a CompareResult into a pretty error string.
120
+ */
121
+ export function formatMismatches(result: CompareResult): string;
122
+ /**
123
+ * Convenience: log to console.error.
124
+ */
125
+ export function printMismatches(result: CompareResult): void;
126
+ export function findMissingPaths<obj extends Record<string, unknown>, path$1 extends DeepKeys<obj>>(obj: obj, paths: Array<path$1>, actual: pickBy<obj, path$1>): Array<DeepKeys<obj>>;
127
+ export type updateAtOptions<T extends Record<string, unknown>, path$1 extends DeepKeys<T>> = {
128
+ obj: T;
129
+ paths: Array<path$1>;
130
+ value: pickBy<T, path$1>;
131
+ partial?: boolean;
132
+ };
133
+ export function joinAtPath<obj extends Record<string, unknown>, path$1 extends DeepKeys<obj>>(paths: Array<path$1>, obj: obj, value: pickBy<obj, path$1>): pickBy<obj, path$1> | undefined;
134
+ export function updateAt<obj extends Record<string, unknown>, path$1 extends DeepKeys<obj>>(options: updateAtOptions<obj, path$1>): obj;
135
+ export {};
136
+ }
137
+ //#endregion
138
+ export { path };
139
+ //# sourceMappingURL=path.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.mts","names":[],"sources":["../../src/utils/path.ts"],"sourcesContent":[],"mappings":"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"}
@@ -0,0 +1,325 @@
1
+ //#region src/utils/path.ts
2
+ let path;
3
+ (function(_path) {
4
+ function getBy(obj, path$1) {
5
+ return path$1.split(".").reduce((acc, key) => acc == null ? void 0 : acc[key], obj);
6
+ }
7
+ function setBy(target, path$1, value) {
8
+ const keys = path$1.split(".");
9
+ let current = target;
10
+ for (let i = 0; i < keys.length; i++) {
11
+ const k = keys[i];
12
+ if (i === keys.length - 1) if (current[k] !== void 0 && typeof current[k] === "object" && typeof value === "object" && value !== null) Object.assign(current[k], value);
13
+ else current[k] = value;
14
+ else {
15
+ if (typeof current[k] !== "object" || current[k] === null) current[k] = {};
16
+ current = current[k];
17
+ }
18
+ }
19
+ return current;
20
+ }
21
+ _path.setBy = setBy;
22
+ function normalizePaths(...paths) {
23
+ const sorted = [...paths].sort((a, b) => b.split(".").length - a.split(".").length);
24
+ const finalPaths = [];
25
+ for (const path$1 of sorted) if (!finalPaths.some((p) => p.startsWith(path$1 + "."))) finalPaths.push(path$1);
26
+ return finalPaths.reverse();
27
+ }
28
+ _path.normalizePaths = normalizePaths;
29
+ function pickBy(obj, ...paths) {
30
+ const norm = normalizePaths(...paths);
31
+ if (norm.length === 1) return getBy(obj, norm[0]);
32
+ const result = {};
33
+ for (const p of norm) setBy(result, p, getBy(obj, p));
34
+ return result;
35
+ }
36
+ _path.pickBy = pickBy;
37
+ function createDeep(obj) {
38
+ const paths = [];
39
+ function traverse(current, prefix = "") {
40
+ if (current === null || current === void 0) return;
41
+ if (typeof current !== "object" || Array.isArray(current)) return;
42
+ const keys = Object.keys(current);
43
+ for (const key of keys) {
44
+ const path$1 = prefix ? `${prefix}.${key}` : key;
45
+ paths.push(path$1);
46
+ const value = current[key];
47
+ if (value !== null && value !== void 0 && typeof value === "object" && !Array.isArray(value)) traverse(value, path$1);
48
+ }
49
+ }
50
+ traverse(obj);
51
+ return paths;
52
+ }
53
+ _path.createDeep = createDeep;
54
+ function defaultExpectedFormat(value) {
55
+ if (value === null) return "null";
56
+ if (Array.isArray(value)) return "Array";
57
+ const t = typeof value;
58
+ if (t !== "object") return t;
59
+ const ctor = value?.constructor?.name;
60
+ return ctor && ctor !== "Object" ? ctor : "object";
61
+ }
62
+ function splitPath(path$1) {
63
+ if (!path$1) return [];
64
+ const parts = [];
65
+ const regex = /[^.[\]]+|\[(\d+)\]/g;
66
+ let m;
67
+ while (m = regex.exec(path$1)) parts.push(m[1] ?? m[0]);
68
+ return parts;
69
+ }
70
+ function getTransformFunction(root, path$1) {
71
+ if (!root) return void 0;
72
+ if (typeof root === "function") return root;
73
+ const segments = splitPath(path$1);
74
+ let node = root;
75
+ let lastFn;
76
+ for (const seg of segments) {
77
+ if (!node) break;
78
+ if (typeof node === "function") {
79
+ lastFn = node;
80
+ break;
81
+ }
82
+ node = node[seg];
83
+ if (typeof node === "function") {
84
+ lastFn = node;
85
+ break;
86
+ }
87
+ }
88
+ return lastFn;
89
+ }
90
+ function formatExpected(rawExpected, path$1, cfg) {
91
+ const fn = getTransformFunction(cfg, path$1);
92
+ if (fn) return fn(rawExpected, path$1);
93
+ return defaultExpectedFormat(rawExpected);
94
+ }
95
+ function isObjectLike(v) {
96
+ return typeof v === "object" && v !== null;
97
+ }
98
+ function deepCompare(expected, actual, basePath, mismatches, options) {
99
+ if (expected === actual) return mismatches;
100
+ if (expected === null || actual === null || typeof expected !== "object" || typeof actual !== "object") {
101
+ const path$2 = basePath || "(root)";
102
+ if (typeof expected !== typeof actual) {
103
+ mismatches.push({
104
+ path: path$2,
105
+ expected: formatExpected(expected, path$2, options.transformExpected),
106
+ actual,
107
+ reason: "type-mismatch"
108
+ });
109
+ return mismatches;
110
+ }
111
+ if (options.includeValueMismatch) mismatches.push({
112
+ path: path$2,
113
+ expected: formatExpected(expected, path$2, options.transformExpected),
114
+ actual,
115
+ reason: "value-mismatch"
116
+ });
117
+ return mismatches;
118
+ }
119
+ if (Array.isArray(expected) || Array.isArray(actual)) {
120
+ if (!Array.isArray(expected) || !Array.isArray(actual)) {
121
+ const path$2 = basePath || "(root)";
122
+ mismatches.push({
123
+ path: path$2,
124
+ expected: formatExpected(expected, path$2, options.transformExpected),
125
+ actual,
126
+ reason: "type-mismatch"
127
+ });
128
+ return mismatches;
129
+ }
130
+ const maxLen = expected.length;
131
+ for (let i = 0; i < maxLen; i++) {
132
+ const expVal = expected[i];
133
+ const actVal = actual[i];
134
+ deepCompare(expVal, actVal, basePath === "" ? `[${i}]` : `${basePath}[${i}]`, mismatches, options);
135
+ }
136
+ return mismatches;
137
+ }
138
+ if (isObjectLike(expected) && isObjectLike(actual)) {
139
+ const expKeys = Object.keys(expected);
140
+ const actKeys = Object.keys(actual);
141
+ for (const key of expKeys) {
142
+ const expVal = expected[key];
143
+ const actVal = actual[key];
144
+ const path$2 = basePath ? `${basePath}.${key}` : key;
145
+ if (!(key in actual)) {
146
+ mismatches.push({
147
+ path: path$2,
148
+ expected: formatExpected(expVal, path$2, options.transformExpected),
149
+ actual: void 0,
150
+ reason: "missing-key"
151
+ });
152
+ continue;
153
+ }
154
+ deepCompare(expVal, actVal, path$2, mismatches, options);
155
+ }
156
+ for (const key of actKeys) if (!(key in expected)) {
157
+ const path$2 = basePath ? `${basePath}.${key}` : key;
158
+ mismatches.push({
159
+ path: path$2,
160
+ expected: void 0,
161
+ actual: actual[key],
162
+ reason: "extra-key"
163
+ });
164
+ }
165
+ return mismatches;
166
+ }
167
+ const path$1 = basePath || "(root)";
168
+ if (typeof expected !== typeof actual) mismatches.push({
169
+ path: path$1,
170
+ expected: formatExpected(expected, path$1, options.transformExpected),
171
+ actual,
172
+ reason: "type-mismatch"
173
+ });
174
+ else if (options.includeValueMismatch) mismatches.push({
175
+ path: path$1,
176
+ expected: formatExpected(expected, path$1, options.transformExpected),
177
+ actual,
178
+ reason: "value-mismatch"
179
+ });
180
+ return mismatches;
181
+ }
182
+ function equalsAtPaths(obj, paths, actual, options) {
183
+ const expected = pickBy(obj, ...paths);
184
+ const mismatches = [];
185
+ deepCompare(expected, actual, paths.length === 1 ? paths[0] : "", mismatches, { transformExpected: options?.transformExpected });
186
+ return {
187
+ ok: mismatches.length === 0,
188
+ mismatches
189
+ };
190
+ }
191
+ _path.equalsAtPaths = equalsAtPaths;
192
+ function formatValue(v) {
193
+ if (v === void 0) return "undefined";
194
+ if (typeof v === "string") return JSON.stringify(v);
195
+ try {
196
+ return JSON.stringify(v, null, 2);
197
+ } catch {
198
+ return String(v);
199
+ }
200
+ }
201
+ function formatReason(m) {
202
+ switch (m.reason) {
203
+ case "missing-key": return "Missing key";
204
+ case "extra-key": return "Extra key";
205
+ case "type-mismatch": return "Type mismatch";
206
+ case "value-mismatch": return "Value mismatch";
207
+ default: return m.reason;
208
+ }
209
+ }
210
+ function formatMismatches(result) {
211
+ if (result.ok || result.mismatches.length === 0) return "No mismatches.";
212
+ const lines = [];
213
+ for (const m of result.mismatches) lines.push(`\n● ${formatReason(m)} at "${m.path}":`, ` expected: ${formatValue(m.expected)}`, ` actual: ${formatValue(m.actual)}`, "");
214
+ if (lines.at(-1) === "") lines.pop();
215
+ return lines.join("\n");
216
+ }
217
+ _path.formatMismatches = formatMismatches;
218
+ function printMismatches(result) {
219
+ const msg = formatMismatches(result);
220
+ if (msg !== "No mismatches.") console.error(msg);
221
+ }
222
+ _path.printMismatches = printMismatches;
223
+ function setAtImmutable(root, path$1, value) {
224
+ const keys = path$1.split(".");
225
+ function helper(current, idx) {
226
+ const key = keys[idx];
227
+ const resolvedCurrent = Array.isArray(current) ? [...current] : { ...current };
228
+ if (idx === keys.length - 1) {
229
+ let clone$1 = current && typeof current === "object" ? resolvedCurrent : {};
230
+ clone$1 = {
231
+ ...clone$1,
232
+ [key]: value
233
+ };
234
+ return clone$1;
235
+ }
236
+ const updatedChild = helper((current && typeof current === "object" ? current[key] : void 0) ?? {}, idx + 1);
237
+ let clone = current && typeof current === "object" ? resolvedCurrent : {};
238
+ clone = {
239
+ ...clone,
240
+ [key]: updatedChild
241
+ };
242
+ return clone;
243
+ }
244
+ return helper(root, 0);
245
+ }
246
+ function findMissingPaths(obj, paths, actual) {
247
+ const keys = [];
248
+ for (const path$1 of paths) {
249
+ const expectedKeys = createDeep(pickBy(obj, path$1));
250
+ const actualKeys = createDeep(actual);
251
+ const missingKeys = expectedKeys.filter((key) => !actualKeys.includes(key)).map((key) => `${path$1}.${key}`);
252
+ keys.push(...missingKeys);
253
+ }
254
+ return keys;
255
+ }
256
+ _path.findMissingPaths = findMissingPaths;
257
+ function getPathThatMatter(path$1) {
258
+ const [, ...rest] = path$1.split(".defaultValue.");
259
+ return rest.join(".");
260
+ }
261
+ function joinAtPath(paths, obj, value) {
262
+ if (paths.length === 1) {
263
+ const [path$1] = paths;
264
+ const missingData = pickBy(obj, ...paths);
265
+ return setBy(value, getPathThatMatter(path$1), missingData);
266
+ }
267
+ if (paths.length > 1) {
268
+ let resolvedValue = {};
269
+ for (const path$1 of paths) {
270
+ const pathThatMatters = getPathThatMatter(path$1);
271
+ const missing = joinAtPath([path$1], obj, value);
272
+ const valueAtPathThatMatters = getBy(obj, path$1);
273
+ if (Object.keys(resolvedValue).length > 0 && valueAtPathThatMatters !== "undefined") {
274
+ const dataAtPath = pickBy(obj, path$1);
275
+ const [key] = pathThatMatters.split(".");
276
+ if (typeof dataAtPath === "object") {
277
+ if (missing) resolvedValue = {
278
+ ...resolvedValue,
279
+ [key]: {
280
+ ...resolvedValue[key],
281
+ ...missing
282
+ }
283
+ };
284
+ }
285
+ continue;
286
+ }
287
+ if (missing) resolvedValue = {
288
+ ...resolvedValue,
289
+ ...missing
290
+ };
291
+ }
292
+ return resolvedValue;
293
+ }
294
+ }
295
+ _path.joinAtPath = joinAtPath;
296
+ function updateAt(options) {
297
+ const { obj, partial, paths, value } = options;
298
+ const norm = normalizePaths(...paths);
299
+ if (norm.length === 0) return obj;
300
+ let result = obj;
301
+ let resolvedValue = value;
302
+ if (partial) {
303
+ const missingData = joinAtPath(findMissingPaths(obj, paths, value), obj, resolvedValue);
304
+ resolvedValue = {
305
+ ...resolvedValue,
306
+ ...missingData
307
+ };
308
+ }
309
+ if (norm.length === 1) {
310
+ const path$1 = norm[0];
311
+ result = setAtImmutable(result, path$1, resolvedValue);
312
+ return result;
313
+ }
314
+ for (const path$1 of norm) {
315
+ const sub = getBy(value, path$1);
316
+ result = setAtImmutable(result, path$1, sub);
317
+ }
318
+ return result;
319
+ }
320
+ _path.updateAt = updateAt;
321
+ })(path || (path = {}));
322
+
323
+ //#endregion
324
+ export { path };
325
+ //# sourceMappingURL=path.mjs.map