@mapomodule/utils 1.0.0 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/debounce.js +19 -0
- package/dist/debounce.js.map +1 -0
- package/dist/deepMerge.js +31 -0
- package/dist/deepMerge.js.map +1 -0
- package/dist/formatDate.js +23 -0
- package/dist/formatDate.js.map +1 -0
- package/dist/formatters.js +43 -0
- package/dist/formatters.js.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonSchema/conditionals.js +326 -0
- package/dist/jsonSchema/conditionals.js.map +1 -0
- package/dist/jsonSchema/index.js +3 -0
- package/dist/jsonSchema/index.js.map +1 -0
- package/dist/jsonSchema/resolve.js +133 -0
- package/dist/jsonSchema/resolve.js.map +1 -0
- package/dist/jsonSchema/types.js +2 -0
- package/dist/jsonSchema/types.js.map +1 -0
- package/dist/menuHelpers.js +56 -0
- package/dist/menuHelpers.js.map +1 -0
- package/dist/nestedValue.js +53 -0
- package/dist/nestedValue.js.map +1 -0
- package/dist/normalizeEndpoint.js +39 -0
- package/dist/normalizeEndpoint.js.map +1 -0
- package/dist/objectDiff.js +58 -0
- package/dist/objectDiff.js.map +1 -0
- package/dist/objectHelpers.js +93 -0
- package/dist/objectHelpers.js.map +1 -0
- package/dist/slotNamespace.js +15 -0
- package/dist/slotNamespace.js.map +1 -0
- package/dist/types/debounce.d.ts +11 -0
- package/dist/types/debounce.d.ts.map +1 -0
- package/dist/types/deepMerge.d.ts +12 -0
- package/dist/types/deepMerge.d.ts.map +1 -0
- package/dist/types/formatDate.d.ts +11 -0
- package/dist/types/formatDate.d.ts.map +1 -0
- package/dist/types/formatters.d.ts +15 -0
- package/dist/types/formatters.d.ts.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/jsonSchema/conditionals.d.ts +40 -0
- package/dist/types/jsonSchema/conditionals.d.ts.map +1 -0
- package/dist/types/jsonSchema/index.d.ts +15 -0
- package/dist/types/jsonSchema/index.d.ts.map +1 -0
- package/dist/types/jsonSchema/resolve.d.ts +41 -0
- package/dist/types/jsonSchema/resolve.d.ts.map +1 -0
- package/dist/types/jsonSchema/types.d.ts +43 -0
- package/dist/types/jsonSchema/types.d.ts.map +1 -0
- package/dist/types/menuHelpers.d.ts +22 -0
- package/dist/types/menuHelpers.d.ts.map +1 -0
- package/dist/types/nestedValue.d.ts +25 -0
- package/dist/types/nestedValue.d.ts.map +1 -0
- package/dist/types/normalizeEndpoint.d.ts +28 -0
- package/dist/types/normalizeEndpoint.d.ts.map +1 -0
- package/dist/types/objectDiff.d.ts +12 -0
- package/dist/types/objectDiff.d.ts.map +1 -0
- package/dist/types/objectHelpers.d.ts +33 -0
- package/dist/types/objectHelpers.d.ts.map +1 -0
- package/dist/types/slotNamespace.d.ts +12 -0
- package/dist/types/slotNamespace.d.ts.map +1 -0
- package/package.json +41 -7
- package/CHANGELOG.md +0 -182
- package/helpers/cssVariables.js +0 -12
- package/helpers/datetime.js +0 -68
- package/helpers/debounce.js +0 -42
- package/helpers/formatters.js +0 -52
- package/helpers/menu.js +0 -15
- package/helpers/objHelpers.js +0 -118
- package/helpers/slots.js +0 -9
- package/index.js +0 -13
- package/loaders/dummy-loader.js +0 -1
- package/plugins/v-draggable-modals.js +0 -39
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/jsonSchema/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Return the maximum nesting depth of a MenuNode tree (root = depth 1). */
|
|
2
|
+
export function calcMaxMenuNestDepth(nodes, depth = 1) {
|
|
3
|
+
if (!nodes.length)
|
|
4
|
+
return depth - 1;
|
|
5
|
+
let max = depth;
|
|
6
|
+
for (const node of nodes) {
|
|
7
|
+
if (node.children.length) {
|
|
8
|
+
const child = calcMaxMenuNestDepth(node.children, depth + 1);
|
|
9
|
+
if (child > max)
|
|
10
|
+
max = child;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return max;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Builds a hierarchical menu tree from flat route records.
|
|
17
|
+
*
|
|
18
|
+
* Routes are included only when they define a `meta.label` and are not marked
|
|
19
|
+
* as hidden. Parent-child relationships are resolved through `meta.parent`.
|
|
20
|
+
*
|
|
21
|
+
* @param routes Flat list of normalized router records.
|
|
22
|
+
* @returns Root menu nodes with nested children.
|
|
23
|
+
*/
|
|
24
|
+
export function buildRouteTree(routes) {
|
|
25
|
+
const nodeMap = new Map();
|
|
26
|
+
for (const route of routes) {
|
|
27
|
+
const { label, icon, hidden, sidebarFooter } = route.meta ?? {};
|
|
28
|
+
if (!label || hidden)
|
|
29
|
+
continue;
|
|
30
|
+
nodeMap.set(route.path, {
|
|
31
|
+
link: route.path,
|
|
32
|
+
label,
|
|
33
|
+
icon: icon ?? "i-lucide-circle-dot",
|
|
34
|
+
children: [],
|
|
35
|
+
meta: route.meta ?? {},
|
|
36
|
+
sidebarFooter: Boolean(sidebarFooter),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const roots = [];
|
|
40
|
+
for (const route of routes) {
|
|
41
|
+
const { label, hidden, parent } = route.meta ?? {};
|
|
42
|
+
if (!label || hidden)
|
|
43
|
+
continue;
|
|
44
|
+
const node = nodeMap.get(route.path);
|
|
45
|
+
if (parent) {
|
|
46
|
+
const parentKey = String(parent).startsWith("/") ? parent : `/${parent}`;
|
|
47
|
+
if (nodeMap.has(parentKey)) {
|
|
48
|
+
nodeMap.get(parentKey).children.push(node);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
roots.push(node);
|
|
53
|
+
}
|
|
54
|
+
return roots;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=menuHelpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menuHelpers.js","sourceRoot":"","sources":["../src/menuHelpers.ts"],"names":[],"mappings":"AAWA,4EAA4E;AAC5E,MAAM,UAAU,oBAAoB,CAAC,KAAiB,EAAE,KAAK,GAAG,CAAC;IAC/D,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,GAAG,CAAC,CAAC;IACpC,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAC7D,IAAI,KAAK,GAAG,GAAG;gBAAE,GAAG,GAAG,KAAK,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,MAA+B;IAC5D,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE5C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,KAAK,IAAI,MAAM;YAAE,SAAS;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK;YACL,IAAI,EAAE,IAAI,IAAI,qBAAqB;YACnC,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;YACtB,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC;SACtC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,KAAK,IAAI,MAAM;YAAE,SAAS;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAE,CAAC;QACtC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC;YACzE,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5C,SAAS;YACX,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads a value from an object using a dot-notation path.
|
|
3
|
+
*
|
|
4
|
+
* @param obj Source object to traverse.
|
|
5
|
+
* @param path Dot-notation path (for example, `"user.profile.name"`).
|
|
6
|
+
* @returns The nested value, or `undefined` when the path cannot be fully resolved.
|
|
7
|
+
*/
|
|
8
|
+
export function getNestedValue(obj, path) {
|
|
9
|
+
return path.split(".").reduce((current, key) => {
|
|
10
|
+
if (current == null || typeof current !== "object")
|
|
11
|
+
return undefined;
|
|
12
|
+
return current[key];
|
|
13
|
+
}, obj);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* In-place version for Vue reactive proxies. Mutates obj directly so Vue's
|
|
17
|
+
* reactivity system tracks the change. Creates missing intermediate objects.
|
|
18
|
+
*/
|
|
19
|
+
export function setNestedValueMutating(obj, path, value) {
|
|
20
|
+
const keys = path.split(".");
|
|
21
|
+
let current = obj;
|
|
22
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
23
|
+
const key = keys[i];
|
|
24
|
+
if (current[key] == null || typeof current[key] !== "object") {
|
|
25
|
+
current[key] = {};
|
|
26
|
+
}
|
|
27
|
+
current = current[key];
|
|
28
|
+
}
|
|
29
|
+
current[keys[keys.length - 1]] = value;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns a new object with `value` assigned at the given dot-notation path.
|
|
33
|
+
*
|
|
34
|
+
* Existing nested objects along the path are shallow-cloned to preserve immutability.
|
|
35
|
+
*
|
|
36
|
+
* @param obj Source object.
|
|
37
|
+
* @param path Dot-notation path where the value should be set.
|
|
38
|
+
* @param value Value to assign at the target path.
|
|
39
|
+
* @returns A new object with the updated nested value.
|
|
40
|
+
*/
|
|
41
|
+
export function setNestedValue(obj, path, value) {
|
|
42
|
+
const keys = path.split(".");
|
|
43
|
+
const result = { ...obj };
|
|
44
|
+
let current = result;
|
|
45
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
46
|
+
const key = keys[i];
|
|
47
|
+
current[key] = { ...current[key] };
|
|
48
|
+
current = current[key];
|
|
49
|
+
}
|
|
50
|
+
current[keys[keys.length - 1]] = value;
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=nestedValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nestedValue.js","sourceRoot":"","sources":["../src/nestedValue.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,GAAY,EAAE,IAAY;IACvD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;QAC7C,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACrE,OAAQ,OAAmC,CAAC,GAAG,CAAC,CAAC;IACnD,CAAC,EAAE,GAAG,CAAC,CAAC;AACV,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAA4B,EAC5B,IAAY,EACZ,KAAc;IAEd,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,OAAO,GAA4B,GAAG,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,GAAG,CAA4B,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;AACzC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAM,EACN,IAAY,EACZ,KAAc;IAEd,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,EAAE,GAAG,GAAG,EAA6B,CAAC;IACrD,IAAI,OAAO,GAAG,MAAM,CAAC;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAI,OAAO,CAAC,GAAG,CAA6B,EAAE,CAAC;QAChE,OAAO,GAAG,OAAO,CAAC,GAAG,CAA4B,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACvC,OAAO,MAAW,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensures an API endpoint path has exactly one leading and one trailing slash.
|
|
3
|
+
* Query strings are preserved unchanged — the slash is inserted before the `?`.
|
|
4
|
+
* Used by `useCrud` to normalize user-provided endpoint paths before making requests.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* normalizeEndpoint('api/articles') // '/api/articles/'
|
|
8
|
+
* normalizeEndpoint('/api/articles') // '/api/articles/'
|
|
9
|
+
* normalizeEndpoint('/api/articles/') // '/api/articles/'
|
|
10
|
+
* normalizeEndpoint('/api/articles/?q=1') // '/api/articles/?q=1'
|
|
11
|
+
*/
|
|
12
|
+
export function normalizeEndpoint(endpoint) {
|
|
13
|
+
const qIdx = endpoint.indexOf("?");
|
|
14
|
+
const path = qIdx >= 0 ? endpoint.slice(0, qIdx) : endpoint;
|
|
15
|
+
const query = qIdx >= 0 ? endpoint.slice(qIdx) : "";
|
|
16
|
+
const stripped = path.replace(/^\/+|\/+$/g, "");
|
|
17
|
+
return `/${stripped}/${query}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Splits an endpoint string into its clean path and parsed query params.
|
|
21
|
+
* Useful when an endpoint carries baked-in params (e.g. `?fields=id,title`) that
|
|
22
|
+
* must be merged into request params while CRUD mutations target the bare path.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* splitEndpointParams('/api/articles/?fields=id,title')
|
|
26
|
+
* { path: '/api/articles/', params: { fields: 'id,title' } }
|
|
27
|
+
* splitEndpointParams('/api/articles/')
|
|
28
|
+
* { path: '/api/articles/', params: {} }
|
|
29
|
+
*/
|
|
30
|
+
export function splitEndpointParams(endpoint) {
|
|
31
|
+
const qIdx = endpoint.indexOf("?");
|
|
32
|
+
if (qIdx < 0)
|
|
33
|
+
return { path: endpoint, params: {} };
|
|
34
|
+
return {
|
|
35
|
+
path: endpoint.slice(0, qIdx),
|
|
36
|
+
params: Object.fromEntries(new URLSearchParams(endpoint.slice(qIdx + 1))),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=normalizeEndpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalizeEndpoint.js","sourceRoot":"","sources":["../src/normalizeEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAChD,OAAO,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;AACjC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAIlD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACpD,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;QAC7B,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;KAC1E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
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 compares two arrays, including nested arrays and plain objects.
|
|
9
|
+
*/
|
|
10
|
+
function arraysDeepEqual(a, b) {
|
|
11
|
+
if (a.length !== b.length)
|
|
12
|
+
return false;
|
|
13
|
+
return a.every((item, i) => {
|
|
14
|
+
const bItem = b[i];
|
|
15
|
+
if (Array.isArray(item) && Array.isArray(bItem))
|
|
16
|
+
return arraysDeepEqual(item, bItem);
|
|
17
|
+
if (isPlainObject(item) && isPlainObject(bItem))
|
|
18
|
+
return Object.keys(objectDiff(item, bItem)).length === 0;
|
|
19
|
+
return Object.is(item, bItem);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Computes a deep diff between two objects and returns only changed fields.
|
|
24
|
+
*
|
|
25
|
+
* Nested objects are diffed recursively. Arrays are compared deeply and, when changed,
|
|
26
|
+
* are returned as the full current array value.
|
|
27
|
+
*
|
|
28
|
+
* @param base Base object used as the comparison reference.
|
|
29
|
+
* @param current Current object to compare against `base`.
|
|
30
|
+
* @returns A partial object containing only keys whose values differ from `base`.
|
|
31
|
+
*/
|
|
32
|
+
export function objectDiff(base, current) {
|
|
33
|
+
const diff = {};
|
|
34
|
+
const allKeys = new Set([
|
|
35
|
+
...Object.keys(base),
|
|
36
|
+
...Object.keys(current),
|
|
37
|
+
]);
|
|
38
|
+
for (const key of allKeys) {
|
|
39
|
+
const baseVal = base[key];
|
|
40
|
+
const currentVal = current[key];
|
|
41
|
+
if (isPlainObject(baseVal) && isPlainObject(currentVal)) {
|
|
42
|
+
const nested = objectDiff(baseVal, currentVal);
|
|
43
|
+
if (Object.keys(nested).length > 0) {
|
|
44
|
+
diff[key] = nested;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (Array.isArray(baseVal) && Array.isArray(currentVal)) {
|
|
48
|
+
if (!arraysDeepEqual(baseVal, currentVal)) {
|
|
49
|
+
diff[key] = currentVal;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (!Object.is(baseVal, currentVal)) {
|
|
53
|
+
diff[key] = currentVal;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return diff;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=objectDiff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objectDiff.js","sourceRoot":"","sources":["../src/objectDiff.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;;GAEG;AACH,SAAS,eAAe,CAAC,CAAY,EAAE,CAAY;IACjD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACzB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAC7C,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC;YAC7C,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QAC3D,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAmB,IAAO,EAAE,OAAU;IAC9D,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC;QACtB,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QACpB,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;KACxB,CAAiB,CAAC;IAEnB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAI,IAAgC,CAAC,GAAa,CAAC,CAAC;QACjE,MAAM,UAAU,GAAI,OAAmC,CAAC,GAAa,CAAC,CAAC;QACvE,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;YACxD,MAAM,MAAM,GAAG,UAAU,CACvB,OAAkC,EAClC,UAAqC,CACtC,CAAC;YACF,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAoB,CAAC;YACnC,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;gBAC1C,IAAI,CAAC,GAAG,CAAC,GAAG,UAAwB,CAAC;YACvC,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC,GAAG,CAAC,GAAG,UAAwB,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const VUE_RAW_FLAG = "__v_raw";
|
|
2
|
+
function unwrapVueRaw(value) {
|
|
3
|
+
if (value === null || typeof value !== "object")
|
|
4
|
+
return value;
|
|
5
|
+
const maybeRaw = value[VUE_RAW_FLAG];
|
|
6
|
+
if (maybeRaw && maybeRaw !== value) {
|
|
7
|
+
return unwrapVueRaw(maybeRaw);
|
|
8
|
+
}
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Deep-clones a value and returns a detached copy.
|
|
13
|
+
*
|
|
14
|
+
* The function first unwraps Vue reactive proxies (when present), then:
|
|
15
|
+
* - uses `structuredClone` when available
|
|
16
|
+
* - falls back to recursive cloning for plain objects/arrays
|
|
17
|
+
*
|
|
18
|
+
* The recursive fallback does not support circular references.
|
|
19
|
+
*/
|
|
20
|
+
export function deepClone(value) {
|
|
21
|
+
const raw = unwrapVueRaw(value);
|
|
22
|
+
if (raw === null || typeof raw !== "object")
|
|
23
|
+
return raw;
|
|
24
|
+
if (typeof globalThis !== "undefined" && "structuredClone" in globalThis) {
|
|
25
|
+
try {
|
|
26
|
+
return structuredClone(raw);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Fall through to recursive clone.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(raw))
|
|
33
|
+
return raw.map(deepClone);
|
|
34
|
+
const result = {};
|
|
35
|
+
for (const key of Object.keys(raw)) {
|
|
36
|
+
result[key] = deepClone(raw[key]);
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Type guard that returns true when `value` is a browser `File`.
|
|
42
|
+
*/
|
|
43
|
+
export function isFile(value) {
|
|
44
|
+
return typeof File !== "undefined" && value instanceof File;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Type guard that returns true when `value` is a browser `Blob`.
|
|
48
|
+
*/
|
|
49
|
+
export function isBlob(value) {
|
|
50
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Type guard that returns true when `value` is either a `File` or a `Blob`.
|
|
54
|
+
*/
|
|
55
|
+
export function isFileOrBlob(value) {
|
|
56
|
+
return isFile(value) || isBlob(value);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Return all dot-notation paths in `obj` where the predicate is truthy.
|
|
60
|
+
*/
|
|
61
|
+
export function findPropPaths(obj, predicate, _prefix = "") {
|
|
62
|
+
if (obj === null || typeof obj !== "object")
|
|
63
|
+
return [];
|
|
64
|
+
const paths = [];
|
|
65
|
+
for (const key of Object.keys(obj)) {
|
|
66
|
+
const path = _prefix ? `${_prefix}.${key}` : key;
|
|
67
|
+
const val = obj[key];
|
|
68
|
+
if (predicate(val)) {
|
|
69
|
+
paths.push(path);
|
|
70
|
+
}
|
|
71
|
+
else if (val !== null && typeof val === "object") {
|
|
72
|
+
paths.push(...findPropPaths(val, predicate, path));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return paths;
|
|
76
|
+
}
|
|
77
|
+
/** Return all paths in `obj` that hold a File or Blob. */
|
|
78
|
+
export function filesInObject(obj) {
|
|
79
|
+
return findPropPaths(obj, isFileOrBlob);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Return a shallow copy of `obj` containing only the listed top-level keys.
|
|
83
|
+
*/
|
|
84
|
+
export function filterObj(obj, keys) {
|
|
85
|
+
const result = {};
|
|
86
|
+
for (const key of keys) {
|
|
87
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
88
|
+
result[key] = obj[key];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=objectHelpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objectHelpers.js","sourceRoot":"","sources":["../src/objectHelpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a namespaced view of slots, including only those that start with the given prefix.
|
|
3
|
+
*
|
|
4
|
+
* Filtered slot names are normalized by removing the prefix from the slot key.
|
|
5
|
+
*
|
|
6
|
+
* @param slots Source Vue slots object.
|
|
7
|
+
* @param prefix Prefix used to select which slots to include.
|
|
8
|
+
* @returns A new `Slots` object containing only prefixed slots, renamed without the prefix.
|
|
9
|
+
*/
|
|
10
|
+
export function slotNamespace(slots, prefix) {
|
|
11
|
+
return Object.fromEntries(Object.entries(slots)
|
|
12
|
+
.filter(([name]) => name.startsWith(prefix))
|
|
13
|
+
.map(([name, fn]) => [name.slice(prefix.length), fn]));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=slotNamespace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slotNamespace.js","sourceRoot":"","sources":["../src/slotNamespace.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,MAAc;IACxD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SAClB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;SAC3C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAC/C,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
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 declare function debounce<A extends unknown[]>(fn: (...args: A) => unknown, ms: number): (...args: A) => void;
|
|
11
|
+
//# sourceMappingURL=debounce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../src/debounce.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,EAAE,EAC1C,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,EAC3B,EAAE,EAAE,MAAM,GACT,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,IAAI,CAQtB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deeply merges `override` into `base` and returns a new object.
|
|
3
|
+
*
|
|
4
|
+
* Nested plain objects are merged recursively, while other values replace
|
|
5
|
+
* the corresponding base value when the override value is not `undefined`.
|
|
6
|
+
*
|
|
7
|
+
* @param base Base object.
|
|
8
|
+
* @param override Partial object with values that should override `base`.
|
|
9
|
+
* @returns A new object containing the merged result.
|
|
10
|
+
*/
|
|
11
|
+
export declare function deepMerge<T extends Record<string, unknown>>(base: T, override: Partial<T>): T;
|
|
12
|
+
//# sourceMappingURL=deepMerge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepMerge.d.ts","sourceRoot":"","sources":["../../src/deepMerge.ts"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,GACnB,CAAC,CAeH"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a date using a token-based pattern.
|
|
3
|
+
*
|
|
4
|
+
* Supported tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`.
|
|
5
|
+
*
|
|
6
|
+
* @param date Date value as a `Date` instance or parseable date string.
|
|
7
|
+
* @param format Output format pattern. Defaults to `"YYYY-MM-DD"`.
|
|
8
|
+
* @returns Formatted date string, or an empty string if the input date is invalid.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatDate(date: string | Date, format?: string): string;
|
|
11
|
+
//# sourceMappingURL=formatDate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatDate.d.ts","sourceRoot":"","sources":["../../src/formatDate.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,SAAe,GAAG,MAAM,CAW7E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a byte count as a human-readable string (ported from Mapo v1).
|
|
3
|
+
*
|
|
4
|
+
* @param bytes Number of bytes.
|
|
5
|
+
* @param si Use metric (powers of 1000, "kB/MB") instead of binary (powers of 1024, "KiB/MiB"). Default `false`.
|
|
6
|
+
* @param dp Decimal places. Default `1`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function humanFileSize(bytes: number, si?: boolean, dp?: number): string;
|
|
9
|
+
/**
|
|
10
|
+
* Convert a string into a URL-safe slug: lowercase, accents stripped,
|
|
11
|
+
* non-alphanumerics collapsed into single dashes (ported from Mapo v1).
|
|
12
|
+
* Camomilla folder payloads require a `slug` derived from the title.
|
|
13
|
+
*/
|
|
14
|
+
export declare function slugify(str: string | null | undefined): string;
|
|
15
|
+
//# sourceMappingURL=formatters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/formatters.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAQ,EAAE,EAAE,SAAI,GAAG,MAAM,CAuBvE;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAa9D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
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 { humanFileSize, slugify } from "./formatters.js";
|
|
7
|
+
export { debounce } from "./debounce.js";
|
|
8
|
+
export { slotNamespace } from "./slotNamespace.js";
|
|
9
|
+
export { buildRouteTree, calcMaxMenuNestDepth } from "./menuHelpers.js";
|
|
10
|
+
export type { MenuNode } from "./menuHelpers.js";
|
|
11
|
+
export { normalizeEndpoint, splitEndpointParams } from "./normalizeEndpoint.js";
|
|
12
|
+
export type { JSONSchema } from "./jsonSchema/index.js";
|
|
13
|
+
export { matchesSchema, applyConditionals, hasConditionals, resolveSchema, extractDefs, getDefaultForSchema, } from "./jsonSchema/index.js";
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","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,aAAa,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACzD,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;AACxE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAChF,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,WAAW,EACX,mBAAmB,GACpB,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { JSONSchema } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Evaluates whether `value` satisfies all constraints in `schema`.
|
|
4
|
+
* Handles `required`, `properties`, `not`, `allOf`, `anyOf`, `oneOf`,
|
|
5
|
+
* `dependentRequired`, and nested `if/then/else` rules.
|
|
6
|
+
*
|
|
7
|
+
* @param value - The data value to validate.
|
|
8
|
+
* @param schema - The JSON Schema node to validate against.
|
|
9
|
+
* @returns `true` if the value conforms to the schema.
|
|
10
|
+
*/
|
|
11
|
+
export declare function matchesSchema(value: unknown, schema: JSONSchema): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Evaluates all conditional keywords in `schema` against `value` and returns
|
|
14
|
+
* an effective schema with the appropriate branches merged in.
|
|
15
|
+
*
|
|
16
|
+
* Supported conditional keywords:
|
|
17
|
+
* - `if / then / else` (top-level and inside `allOf`)
|
|
18
|
+
* - `dependentSchemas` / `dependentRequired`
|
|
19
|
+
*
|
|
20
|
+
* Iteration is repeated up to {@link MAX_CONDITIONAL_PASSES} times to handle cascading
|
|
21
|
+
* conditionals where a merged branch introduces new `if` rules. Stops early when the
|
|
22
|
+
* schema stabilises between iterations.
|
|
23
|
+
*
|
|
24
|
+
* @param schema - The base schema to evaluate.
|
|
25
|
+
* @param value - The current form data used to resolve conditionals.
|
|
26
|
+
* @param resolver - Optional function to resolve `$ref` pointers inside branches.
|
|
27
|
+
* @returns A new schema with all applicable branches merged.
|
|
28
|
+
*/
|
|
29
|
+
export declare function applyConditionals(schema: JSONSchema, value: unknown, resolver?: (s: JSONSchema) => JSONSchema): JSONSchema;
|
|
30
|
+
/**
|
|
31
|
+
* Returns `true` if the schema contains any conditional keywords that could
|
|
32
|
+
* affect the visible set of properties at runtime.
|
|
33
|
+
*
|
|
34
|
+
* Checked keywords: `if`, `dependentSchemas`, `dependentRequired`, and
|
|
35
|
+
* any `if` entries nested inside `allOf`.
|
|
36
|
+
*
|
|
37
|
+
* @param schema - The schema to inspect.
|
|
38
|
+
*/
|
|
39
|
+
export declare function hasConditionals(schema: JSONSchema): boolean;
|
|
40
|
+
//# sourceMappingURL=conditionals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditionals.d.ts","sourceRoot":"","sources":["../../../src/jsonSchema/conditionals.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA+F7C;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAuCzE;AAoFD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,OAAO,EACd,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,UAAU,GACvC,UAAU,CAiGZ;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAU3D"}
|