@mapomodule/utils 1.0.0-alpha.9 → 2.0.0-beta.1

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 (66) hide show
  1. package/README.md +33 -0
  2. package/dist/debounce.js +19 -0
  3. package/dist/debounce.js.map +1 -0
  4. package/dist/deepMerge.js +31 -0
  5. package/dist/deepMerge.js.map +1 -0
  6. package/dist/formatDate.js +23 -0
  7. package/dist/formatDate.js.map +1 -0
  8. package/dist/index.js +11 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/jsonSchema/conditionals.js +326 -0
  11. package/dist/jsonSchema/conditionals.js.map +1 -0
  12. package/dist/jsonSchema/index.js +3 -0
  13. package/dist/jsonSchema/index.js.map +1 -0
  14. package/dist/jsonSchema/resolve.js +133 -0
  15. package/dist/jsonSchema/resolve.js.map +1 -0
  16. package/dist/jsonSchema/types.js +2 -0
  17. package/dist/jsonSchema/types.js.map +1 -0
  18. package/dist/menuHelpers.js +56 -0
  19. package/dist/menuHelpers.js.map +1 -0
  20. package/dist/nestedValue.js +53 -0
  21. package/dist/nestedValue.js.map +1 -0
  22. package/dist/normalizeEndpoint.js +39 -0
  23. package/dist/normalizeEndpoint.js.map +1 -0
  24. package/dist/objectDiff.js +58 -0
  25. package/dist/objectDiff.js.map +1 -0
  26. package/dist/objectHelpers.js +93 -0
  27. package/dist/objectHelpers.js.map +1 -0
  28. package/dist/slotNamespace.js +15 -0
  29. package/dist/slotNamespace.js.map +1 -0
  30. package/dist/types/debounce.d.ts +11 -0
  31. package/dist/types/debounce.d.ts.map +1 -0
  32. package/dist/types/deepMerge.d.ts +12 -0
  33. package/dist/types/deepMerge.d.ts.map +1 -0
  34. package/dist/types/formatDate.d.ts +11 -0
  35. package/dist/types/formatDate.d.ts.map +1 -0
  36. package/dist/types/index.d.ts +13 -0
  37. package/dist/types/index.d.ts.map +1 -0
  38. package/dist/types/jsonSchema/conditionals.d.ts +40 -0
  39. package/dist/types/jsonSchema/conditionals.d.ts.map +1 -0
  40. package/dist/types/jsonSchema/index.d.ts +15 -0
  41. package/dist/types/jsonSchema/index.d.ts.map +1 -0
  42. package/dist/types/jsonSchema/resolve.d.ts +41 -0
  43. package/dist/types/jsonSchema/resolve.d.ts.map +1 -0
  44. package/dist/types/jsonSchema/types.d.ts +43 -0
  45. package/dist/types/jsonSchema/types.d.ts.map +1 -0
  46. package/dist/types/menuHelpers.d.ts +22 -0
  47. package/dist/types/menuHelpers.d.ts.map +1 -0
  48. package/dist/types/nestedValue.d.ts +25 -0
  49. package/dist/types/nestedValue.d.ts.map +1 -0
  50. package/dist/types/normalizeEndpoint.d.ts +28 -0
  51. package/dist/types/normalizeEndpoint.d.ts.map +1 -0
  52. package/dist/types/objectDiff.d.ts +12 -0
  53. package/dist/types/objectDiff.d.ts.map +1 -0
  54. package/dist/types/objectHelpers.d.ts +33 -0
  55. package/dist/types/objectHelpers.d.ts.map +1 -0
  56. package/dist/types/slotNamespace.d.ts +12 -0
  57. package/dist/types/slotNamespace.d.ts.map +1 -0
  58. package/package.json +40 -9
  59. package/CHANGELOG.md +0 -22
  60. package/LICENSE.md +0 -20
  61. package/helpers/auth.js +0 -21
  62. package/helpers/debounce.js +0 -18
  63. package/helpers/formatters.js +0 -27
  64. package/helpers/objHelpers.js +0 -53
  65. package/index.js +0 -11
  66. package/loaders/dummy-loader.js +0 -1
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # @mapomodule/utils
2
+
3
+ Typed utility helpers shared across all `@mapomodule/*` packages.
4
+
5
+ ## Utilities
6
+
7
+ | Export | Description |
8
+ | ------------------- | ---------------------------------------------------------------------------------------------------------- |
9
+ | `deepMerge` | Recursively merges two plain objects |
10
+ | `getNestedValue` | Reads a value from a dotted path (e.g. `"user.address.city"`) |
11
+ | `setNestedValue` | Returns a new object with a value set at a dotted path |
12
+ | `objectDiff` | Returns only the keys that differ between two objects — used for differential PATCH requests |
13
+ | `formatDate` | Formats a `Date` or ISO string with a token-based format string (`YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`) |
14
+ | `debounce` | Returns a debounced version of a function |
15
+ | `slotNamespace` | Filters and strips a prefix from a Vue `Slots` object — used to forward a slot subset to a child component |
16
+ | `buildRouteTree` | Converts a flat `RouteRecordNormalized[]` into a nested `MenuNode[]` tree for sidebar rendering |
17
+ | `normalizeEndpoint` | Ensures an API endpoint string has exactly one leading and one trailing slash — used by `useCrud` |
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pnpm add @mapomodule/utils
23
+ ```
24
+
25
+ ## Dev workflow
26
+
27
+ ```bash
28
+ pnpm dev:utils # from monorepo root — tsc --watch
29
+ ```
30
+
31
+ ---
32
+
33
+ > The helpers in this package are ported from the Mapo v1 legacy codebase. As v2 development progresses, individual helpers may be added, removed, or replaced — and the package itself may be dissolved if its contents are better placed elsewhere.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Creates a debounced wrapper that delays invocation until calls stop for `ms` milliseconds.
3
+ *
4
+ * Each new call clears the pending timer, so only the last call in a burst is executed.
5
+ *
6
+ * @param fn Function to debounce.
7
+ * @param ms Debounce delay in milliseconds.
8
+ * @returns A debounced function with the same argument signature as `fn`.
9
+ */
10
+ export function debounce(fn, ms) {
11
+ let timer;
12
+ return function (...args) {
13
+ clearTimeout(timer);
14
+ timer = setTimeout(() => {
15
+ fn.apply(this, args);
16
+ }, ms);
17
+ };
18
+ }
19
+ //# sourceMappingURL=debounce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.js","sourceRoot":"","sources":["../src/debounce.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CACtB,EAA2B,EAC3B,EAAU;IAEV,IAAI,KAAgD,CAAC;IACrD,OAAO,UAAyB,GAAG,IAAO;QACxC,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Returns true when `val` is a non-null plain object (excluding arrays).
3
+ */
4
+ function isPlainObject(val) {
5
+ return typeof val === "object" && val !== null && !Array.isArray(val);
6
+ }
7
+ /**
8
+ * Deeply merges `override` into `base` and returns a new object.
9
+ *
10
+ * Nested plain objects are merged recursively, while other values replace
11
+ * the corresponding base value when the override value is not `undefined`.
12
+ *
13
+ * @param base Base object.
14
+ * @param override Partial object with values that should override `base`.
15
+ * @returns A new object containing the merged result.
16
+ */
17
+ export function deepMerge(base, override) {
18
+ const result = { ...base };
19
+ for (const key of Object.keys(override)) {
20
+ const baseVal = result[key];
21
+ const overrideVal = override[key];
22
+ if (isPlainObject(baseVal) && isPlainObject(overrideVal)) {
23
+ result[key] = deepMerge(baseVal, overrideVal);
24
+ }
25
+ else if (overrideVal !== undefined) {
26
+ result[key] = overrideVal;
27
+ }
28
+ }
29
+ return result;
30
+ }
31
+ //# sourceMappingURL=deepMerge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepMerge.js","sourceRoot":"","sources":["../src/deepMerge.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,SAAS,aAAa,CAAC,GAAY;IACjC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CACvB,IAAO,EACP,QAAoB;IAEpB,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAmB,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;YACzD,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CACrB,OAAkC,EAClC,WAAsC,CACzB,CAAC;QAClB,CAAC;aAAM,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,GAAG,WAAyB,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,23 @@
1
+ const pad = (n) => String(n).padStart(2, "0");
2
+ /**
3
+ * Formats a date using a token-based pattern.
4
+ *
5
+ * Supported tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`.
6
+ *
7
+ * @param date Date value as a `Date` instance or parseable date string.
8
+ * @param format Output format pattern. Defaults to `"YYYY-MM-DD"`.
9
+ * @returns Formatted date string, or an empty string if the input date is invalid.
10
+ */
11
+ export function formatDate(date, format = "YYYY-MM-DD") {
12
+ const d = typeof date === "string" ? new Date(date) : date;
13
+ if (isNaN(d.getTime()))
14
+ return "";
15
+ return format
16
+ .replace("YYYY", String(d.getFullYear()))
17
+ .replace("MM", pad(d.getMonth() + 1))
18
+ .replace("DD", pad(d.getDate()))
19
+ .replace("HH", pad(d.getHours()))
20
+ .replace("mm", pad(d.getMinutes()))
21
+ .replace("ss", pad(d.getSeconds()));
22
+ }
23
+ //# sourceMappingURL=formatDate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatDate.js","sourceRoot":"","sources":["../src/formatDate.ts"],"names":[],"mappings":"AAAA,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,IAAmB,EAAE,MAAM,GAAG,YAAY;IACnE,MAAM,CAAC,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3D,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,OAAO,MAAM;SACV,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;SACxC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;SACpC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;SAC/B,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;SAChC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;SAClC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AACxC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ export { deepMerge } from "./deepMerge.js";
2
+ export { deepClone, isFile, isBlob, isFileOrBlob, findPropPaths, filesInObject, filterObj, } from "./objectHelpers.js";
3
+ export { getNestedValue, setNestedValue, setNestedValueMutating, } from "./nestedValue.js";
4
+ export { objectDiff } from "./objectDiff.js";
5
+ export { formatDate } from "./formatDate.js";
6
+ export { debounce } from "./debounce.js";
7
+ export { slotNamespace } from "./slotNamespace.js";
8
+ export { buildRouteTree, calcMaxMenuNestDepth } from "./menuHelpers.js";
9
+ export { normalizeEndpoint, splitEndpointParams } from "./normalizeEndpoint.js";
10
+ export { matchesSchema, applyConditionals, hasConditionals, resolveSchema, extractDefs, getDefaultForSchema, } from "./jsonSchema/index.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EACL,SAAS,EACT,MAAM,EACN,MAAM,EACN,YAAY,EACZ,aAAa,EACb,aAAa,EACb,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EACd,cAAc,EACd,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,WAAW,EACX,mBAAmB,GACpB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,326 @@
1
+ // Cherry-picked from structured-widget-editor (MIT License, Copyright (c) 2026 bnznamco)
2
+ // Source: https://github.com/bnznamco/structured-widget-editor/blob/main/src/conditionals.js
3
+ // Modifications: converted to TypeScript, added type annotations.
4
+ /**
5
+ * Maximum number of resolution passes for cascading conditionals: a merged branch
6
+ * may introduce new `if` rules, so we iterate until the schema stabilises or this
7
+ * cap is hit (whichever comes first).
8
+ */
9
+ const MAX_CONDITIONAL_PASSES = 8;
10
+ /**
11
+ * Returns `true` if `value` is a non-null object that contains `key` with a
12
+ * non-empty, non-null, non-undefined value.
13
+ */
14
+ function isPresent(value, key) {
15
+ if (value == null || typeof value !== "object")
16
+ return false;
17
+ if (!(key in value))
18
+ return false;
19
+ const v = value[key];
20
+ return v !== undefined && v !== null && v !== "";
21
+ }
22
+ /**
23
+ * Checks whether a single property value satisfies the constraints defined by
24
+ * a JSON Schema node (type, const, enum, numeric/string bounds, not, etc.).
25
+ */
26
+ function matchesPropertyConstraint(value, constraint) {
27
+ if (!constraint || typeof constraint !== "object")
28
+ return true;
29
+ if ("const" in constraint)
30
+ return value === constraint.const;
31
+ if (Array.isArray(constraint.enum))
32
+ return constraint.enum.includes(value);
33
+ if (constraint.type) {
34
+ const t = constraint.type;
35
+ if (t === "string" && typeof value !== "string")
36
+ return false;
37
+ if (t === "number" && typeof value !== "number")
38
+ return false;
39
+ if (t === "integer" &&
40
+ (typeof value !== "number" || !Number.isInteger(value)))
41
+ return false;
42
+ if (t === "boolean" && typeof value !== "boolean")
43
+ return false;
44
+ if (t === "null" && value !== null)
45
+ return false;
46
+ if (t === "array" && !Array.isArray(value))
47
+ return false;
48
+ if (t === "object" &&
49
+ (value == null || typeof value !== "object" || Array.isArray(value)))
50
+ return false;
51
+ }
52
+ if (typeof value === "number") {
53
+ if (typeof constraint.minimum === "number" && value < constraint.minimum)
54
+ return false;
55
+ if (typeof constraint.maximum === "number" && value > constraint.maximum)
56
+ return false;
57
+ if (typeof constraint.exclusiveMinimum === "number" &&
58
+ value <= constraint.exclusiveMinimum)
59
+ return false;
60
+ if (typeof constraint.exclusiveMaximum === "number" &&
61
+ value >= constraint.exclusiveMaximum)
62
+ return false;
63
+ if (typeof constraint.multipleOf === "number" &&
64
+ constraint.multipleOf > 0) {
65
+ const q = value / constraint.multipleOf;
66
+ if (Math.abs(q - Math.round(q)) > 1e-9)
67
+ return false;
68
+ }
69
+ }
70
+ if (typeof value === "string") {
71
+ if (typeof constraint.minLength === "number" &&
72
+ value.length < constraint.minLength)
73
+ return false;
74
+ if (typeof constraint.maxLength === "number" &&
75
+ value.length > constraint.maxLength)
76
+ return false;
77
+ if (typeof constraint.pattern === "string") {
78
+ try {
79
+ if (!new RegExp(constraint.pattern).test(value))
80
+ return false;
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ }
87
+ if (constraint.not)
88
+ return !matchesSchema(value, constraint.not);
89
+ return true;
90
+ }
91
+ /**
92
+ * Evaluates whether `value` satisfies all constraints in `schema`.
93
+ * Handles `required`, `properties`, `not`, `allOf`, `anyOf`, `oneOf`,
94
+ * `dependentRequired`, and nested `if/then/else` rules.
95
+ *
96
+ * @param value - The data value to validate.
97
+ * @param schema - The JSON Schema node to validate against.
98
+ * @returns `true` if the value conforms to the schema.
99
+ */
100
+ export function matchesSchema(value, schema) {
101
+ if (!schema || typeof schema !== "object")
102
+ return true;
103
+ if (Array.isArray(schema.required)) {
104
+ for (const k of schema.required) {
105
+ if (!isPresent(value, k))
106
+ return false;
107
+ }
108
+ }
109
+ if (schema.properties && typeof schema.properties === "object") {
110
+ for (const [k, constraint] of Object.entries(schema.properties)) {
111
+ if (value == null || !(k in value))
112
+ continue;
113
+ if (!matchesPropertyConstraint(value[k], constraint))
114
+ return false;
115
+ }
116
+ }
117
+ if (schema.not && matchesSchema(value, schema.not))
118
+ return false;
119
+ if (Array.isArray(schema.allOf) &&
120
+ !schema.allOf.every((s) => matchesSchema(value, s)))
121
+ return false;
122
+ if (Array.isArray(schema.anyOf) &&
123
+ !schema.anyOf.some((s) => matchesSchema(value, s)))
124
+ return false;
125
+ if (Array.isArray(schema.oneOf)) {
126
+ const matched = schema.oneOf.filter((s) => matchesSchema(value, s)).length;
127
+ if (matched !== 1)
128
+ return false;
129
+ }
130
+ return true;
131
+ }
132
+ /**
133
+ * Inserts `newEntries` into the `properties` map immediately after `anchorKey`.
134
+ * If `anchorKey` is `null` or not found, entries are appended at the end.
135
+ * Existing keys that appear in `newEntries` are moved to the anchor position
136
+ * rather than duplicated.
137
+ */
138
+ function insertAfter(properties, anchorKey, newEntries) {
139
+ const existingKeys = Object.keys(properties);
140
+ const anchorIdx = anchorKey ? existingKeys.indexOf(anchorKey) : -1;
141
+ if (anchorIdx === -1) {
142
+ const out = { ...properties };
143
+ for (const [k, v] of newEntries)
144
+ out[k] = v;
145
+ return out;
146
+ }
147
+ const out = {};
148
+ for (let i = 0; i < existingKeys.length; i++) {
149
+ const key = existingKeys[i];
150
+ out[key] = properties[key];
151
+ if (i === anchorIdx) {
152
+ for (const [k, v] of newEntries) {
153
+ if (!(k in properties))
154
+ out[k] = v;
155
+ }
156
+ }
157
+ }
158
+ for (const [k, v] of newEntries) {
159
+ if (k in properties)
160
+ out[k] = v;
161
+ }
162
+ return out;
163
+ }
164
+ /**
165
+ * Merges a conditional branch schema into `target` in-place.
166
+ * Properties are inserted after `anchorKey` to preserve visual ordering.
167
+ * `required`, `allOf`, `dependentSchemas`, and `dependentRequired` are merged
168
+ * additively rather than replaced.
169
+ */
170
+ function mergeBranch(target, branch, anchorKey) {
171
+ if (!branch || typeof branch !== "object")
172
+ return target;
173
+ if (branch.properties) {
174
+ const merged = [];
175
+ for (const [k, v] of Object.entries(branch.properties)) {
176
+ const existing = target.properties?.[k];
177
+ merged.push([k, existing ? { ...existing, ...v } : v]);
178
+ }
179
+ target.properties = insertAfter(target.properties || {}, anchorKey, merged);
180
+ }
181
+ if (Array.isArray(branch.required)) {
182
+ const set = new Set(target.required || []);
183
+ for (const k of branch.required)
184
+ set.add(k);
185
+ target.required = Array.from(set);
186
+ }
187
+ if (branch.allOf)
188
+ target.allOf = [...(target.allOf || []), ...branch.allOf];
189
+ if (branch.if)
190
+ target.allOf = [
191
+ ...(target.allOf || []),
192
+ { if: branch.if, then: branch.then, else: branch.else },
193
+ ];
194
+ if (branch.dependentSchemas)
195
+ target.dependentSchemas = {
196
+ ...(target.dependentSchemas || {}),
197
+ ...branch.dependentSchemas,
198
+ };
199
+ if (branch.dependentRequired)
200
+ target.dependentRequired = {
201
+ ...(target.dependentRequired || {}),
202
+ ...branch.dependentRequired,
203
+ };
204
+ return target;
205
+ }
206
+ /**
207
+ * Evaluates all conditional keywords in `schema` against `value` and returns
208
+ * an effective schema with the appropriate branches merged in.
209
+ *
210
+ * Supported conditional keywords:
211
+ * - `if / then / else` (top-level and inside `allOf`)
212
+ * - `dependentSchemas` / `dependentRequired`
213
+ *
214
+ * Iteration is repeated up to {@link MAX_CONDITIONAL_PASSES} times to handle cascading
215
+ * conditionals where a merged branch introduces new `if` rules. Stops early when the
216
+ * schema stabilises between iterations.
217
+ *
218
+ * @param schema - The base schema to evaluate.
219
+ * @param value - The current form data used to resolve conditionals.
220
+ * @param resolver - Optional function to resolve `$ref` pointers inside branches.
221
+ * @returns A new schema with all applicable branches merged.
222
+ */
223
+ export function applyConditionals(schema, value, resolver) {
224
+ const resolve = typeof resolver === "function" ? resolver : (s) => s;
225
+ if (!schema || typeof schema !== "object")
226
+ return schema;
227
+ if (schema.type !== "object" && !schema.properties)
228
+ return schema;
229
+ const effective = {
230
+ ...schema,
231
+ properties: { ...(schema.properties || {}) },
232
+ required: Array.isArray(schema.required) ? [...schema.required] : [],
233
+ };
234
+ const safeValue = value && typeof value === "object" ? value : {};
235
+ const anchorOf = (ifClause) => {
236
+ if (!ifClause || typeof ifClause !== "object")
237
+ return null;
238
+ const props = ifClause.properties && Object.keys(ifClause.properties);
239
+ if (props && props.length)
240
+ return props[0];
241
+ if (Array.isArray(ifClause.required) && ifClause.required.length)
242
+ return ifClause.required[0];
243
+ return null;
244
+ };
245
+ const rules = [];
246
+ if (effective.if) {
247
+ rules.push({
248
+ if: effective.if,
249
+ then: effective.then,
250
+ else: effective.else,
251
+ anchor: anchorOf(effective.if),
252
+ });
253
+ }
254
+ if (Array.isArray(effective.allOf)) {
255
+ for (const entry of effective.allOf) {
256
+ if (entry && typeof entry === "object" && entry.if) {
257
+ rules.push({
258
+ if: entry.if,
259
+ then: entry.then,
260
+ else: entry.else,
261
+ anchor: anchorOf(entry.if),
262
+ });
263
+ }
264
+ else if (entry &&
265
+ typeof entry === "object" &&
266
+ (entry.properties || entry.required)) {
267
+ mergeBranch(effective, entry, null);
268
+ }
269
+ }
270
+ }
271
+ for (let i = 0; i < MAX_CONDITIONAL_PASSES; i++) {
272
+ const before = JSON.stringify({
273
+ p: effective.properties,
274
+ r: effective.required,
275
+ });
276
+ for (const rule of rules) {
277
+ const matched = matchesSchema(safeValue, rule.if);
278
+ const branch = matched ? rule.then : rule.else;
279
+ if (branch)
280
+ mergeBranch(effective, resolve(branch), rule.anchor);
281
+ }
282
+ if (effective.dependentSchemas) {
283
+ for (const [key, branch] of Object.entries(effective.dependentSchemas)) {
284
+ if (isPresent(safeValue, key))
285
+ mergeBranch(effective, resolve(branch), key);
286
+ }
287
+ }
288
+ if (effective.dependentRequired) {
289
+ for (const [key, requiredKeys] of Object.entries(effective.dependentRequired)) {
290
+ if (isPresent(safeValue, key) && Array.isArray(requiredKeys)) {
291
+ const set = new Set(effective.required || []);
292
+ for (const k of requiredKeys)
293
+ set.add(k);
294
+ effective.required = Array.from(set);
295
+ }
296
+ }
297
+ }
298
+ const after = JSON.stringify({
299
+ p: effective.properties,
300
+ r: effective.required,
301
+ });
302
+ if (after === before)
303
+ break;
304
+ }
305
+ return effective;
306
+ }
307
+ /**
308
+ * Returns `true` if the schema contains any conditional keywords that could
309
+ * affect the visible set of properties at runtime.
310
+ *
311
+ * Checked keywords: `if`, `dependentSchemas`, `dependentRequired`, and
312
+ * any `if` entries nested inside `allOf`.
313
+ *
314
+ * @param schema - The schema to inspect.
315
+ */
316
+ export function hasConditionals(schema) {
317
+ if (!schema || typeof schema !== "object")
318
+ return false;
319
+ if (schema.if || schema.dependentSchemas || schema.dependentRequired)
320
+ return true;
321
+ if (Array.isArray(schema.allOf)) {
322
+ return schema.allOf.some((e) => e && typeof e === "object" && (e.if || e.dependentSchemas));
323
+ }
324
+ return false;
325
+ }
326
+ //# sourceMappingURL=conditionals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditionals.js","sourceRoot":"","sources":["../../src/jsonSchema/conditionals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { matchesSchema, applyConditionals, hasConditionals, } from "./conditionals.js";
2
+ export { resolveSchema, extractDefs, getDefaultForSchema } from "./resolve.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jsonSchema/index.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,133 @@
1
+ // Cherry-picked from structured-widget-editor (MIT License, Copyright (c) 2026 bnznamco)
2
+ // Source: https://github.com/bnznamco/structured-widget-editor/blob/main/src/SchemaForm.vue (resolveSchema method)
3
+ // Modifications: extracted as standalone function, converted to TypeScript.
4
+ /** Maximum recursion depth allowed when resolving nested schema references. */
5
+ const MAX_RESOLVE_DEPTH = 32;
6
+ /**
7
+ * Recursively resolves a JSON Schema by following `$ref`, `anyOf`, and `oneOf` pointers.
8
+ *
9
+ * - `$ref` is dereferenced against the provided `defs` map.
10
+ * - `anyOf` / `oneOf` with a single non-null branch is unwrapped; nullable schemas
11
+ * are marked with `_nullable: true`.
12
+ * - A `oneOf` paired with a `discriminator` is returned as-is (handled by union editors).
13
+ *
14
+ * @param schema - The schema node to resolve.
15
+ * @param defs - Flat map of reusable definitions (`$defs` / `definitions`).
16
+ * @param seen - WeakSet used to detect circular references across recursive calls.
17
+ * @param depth - Current recursion depth; capped at {@link MAX_RESOLVE_DEPTH}.
18
+ * @returns The fully resolved schema node.
19
+ */
20
+ export function resolveSchema(schema, defs, seen = new WeakSet(), depth = 0) {
21
+ if (!schema)
22
+ return { type: "string" };
23
+ // Cycle guard: self-referential schemas (e.g. nested comments, tree categories)
24
+ // would recurse infinitely. Return a stripped-down object node instead.
25
+ if (seen.has(schema) || depth > MAX_RESOLVE_DEPTH) {
26
+ const { $ref: _ref, anyOf: _ao, oneOf: _oo, ...rest } = schema;
27
+ return { type: "object", ...rest };
28
+ }
29
+ seen.add(schema);
30
+ if (schema.$ref) {
31
+ const refPath = schema.$ref
32
+ .replace(/^#\/\$defs\//, "")
33
+ .replace(/^#\/definitions\//, "");
34
+ const resolved = defs[refPath];
35
+ if (!resolved)
36
+ return { type: "string", title: refPath };
37
+ const { $ref: _ref, ...rest } = schema;
38
+ return { ...resolveSchema(resolved, defs, seen, depth + 1), ...rest };
39
+ }
40
+ if (schema.anyOf) {
41
+ const nonNull = schema.anyOf.filter((s) => s.type !== "null");
42
+ const hasNull = schema.anyOf.some((s) => s.type === "null");
43
+ if (hasNull && nonNull.length === 1) {
44
+ // Optional field pattern: `anyOf: [T, null]` → unwrap T, mark nullable
45
+ const resolved = resolveSchema(nonNull[0], defs, seen, depth + 1);
46
+ return {
47
+ ...resolved,
48
+ _nullable: true,
49
+ title: schema.title ?? resolved.title,
50
+ default: "default" in schema ? schema.default : null,
51
+ };
52
+ }
53
+ if (nonNull.length >= 1)
54
+ return resolveSchema(nonNull[0], defs, seen, depth + 1);
55
+ }
56
+ // oneOf + discriminator → pass through as-is (handled by UnionEditor / MapoRepeater templates)
57
+ if (schema.oneOf && schema.discriminator)
58
+ return schema;
59
+ if (schema.oneOf) {
60
+ const nonNull = schema.oneOf.filter((s) => s.type !== "null");
61
+ const hasNull = schema.oneOf.some((s) => s.type === "null");
62
+ if (hasNull && nonNull.length === 1) {
63
+ // Optional field pattern: `oneOf: [T, null]` → unwrap T, mark nullable
64
+ const resolved = resolveSchema(nonNull[0], defs, seen, depth + 1);
65
+ return {
66
+ ...resolved,
67
+ _nullable: true,
68
+ title: schema.title ?? resolved.title,
69
+ default: "default" in schema ? schema.default : null,
70
+ };
71
+ }
72
+ if (nonNull.length >= 1)
73
+ return resolveSchema(nonNull[0], defs, seen, depth + 1);
74
+ }
75
+ return schema;
76
+ }
77
+ /**
78
+ * Extracts the reusable definitions map from a root JSON Schema.
79
+ * Supports both the modern `$defs` keyword and the legacy `definitions` keyword.
80
+ *
81
+ * @param schema - The root schema object.
82
+ * @returns A flat record of named sub-schemas.
83
+ */
84
+ export function extractDefs(schema) {
85
+ return schema.$defs ?? schema.definitions ?? {};
86
+ }
87
+ /**
88
+ * Derives a sensible empty/zero default value for a given JSON Schema node.
89
+ *
90
+ * If the schema declares an explicit `default`, that value is deep-cloned and returned.
91
+ * Otherwise, a type-appropriate zero value is produced:
92
+ * - `object` → object with per-property defaults
93
+ * - `array` → `[]`
94
+ * - `string` → `""`
95
+ * - `integer` / `number` → `0`
96
+ * - `boolean` → `false`
97
+ * - `relation` → `null` (or `[]` when `multiple: true`)
98
+ *
99
+ * @param schema - The resolved schema node.
100
+ * @returns The default value inferred from the schema type.
101
+ */
102
+ export function getDefaultForSchema(schema) {
103
+ if ("default" in schema)
104
+ return structuredClone(schema.default);
105
+ if (schema.type === "object") {
106
+ const obj = {};
107
+ for (const [key, prop] of Object.entries(schema.properties || {})) {
108
+ if ("default" in prop)
109
+ obj[key] = structuredClone(prop.default);
110
+ else if (prop.type === "string")
111
+ obj[key] = "";
112
+ else if (prop.type === "integer" || prop.type === "number")
113
+ obj[key] = 0;
114
+ else if (prop.type === "boolean")
115
+ obj[key] = false;
116
+ else if (prop.type === "array")
117
+ obj[key] = [];
118
+ }
119
+ return obj;
120
+ }
121
+ if (schema.type === "array")
122
+ return [];
123
+ if (schema.type === "string")
124
+ return "";
125
+ if (schema.type === "integer" || schema.type === "number")
126
+ return 0;
127
+ if (schema.type === "boolean")
128
+ return false;
129
+ if (schema.type === "relation")
130
+ return schema.multiple ? [] : null;
131
+ return null;
132
+ }
133
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/jsonSchema/resolve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/jsonSchema/types.ts"],"names":[],"mappings":""}