fix(schema-form): extract the clone-spine walk and drop the unused ui-primitives dependency
This commit is contained in:
@@ -20,7 +20,6 @@
|
|||||||
},
|
},
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@deepseek-ai/dsh-client-ui-primitives": "workspace:^",
|
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"schemastery": "^3.18.0"
|
"schemastery": "^3.18.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -117,7 +117,13 @@ export function getPath(value: unknown, path: readonly string[]): unknown {
|
|||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether a draft explicitly carries the path (its presence marks a user override). */
|
/**
|
||||||
|
* Whether a draft explicitly carries the path (its presence marks a user
|
||||||
|
* override, independent of the value stored there).
|
||||||
|
* @param value - root value (draft or fallback layer).
|
||||||
|
* @param path - key path from the root; array indexes as strings.
|
||||||
|
* @returns whether the path's final key exists on its parent.
|
||||||
|
*/
|
||||||
export function hasPath(value: unknown, path: readonly string[]): boolean {
|
export function hasPath(value: unknown, path: readonly string[]): boolean {
|
||||||
if (path.length === 0) return value !== undefined
|
if (path.length === 0) return value !== undefined
|
||||||
const parent = getPath(value, path.slice(0, -1))
|
const parent = getPath(value, path.slice(0, -1))
|
||||||
@@ -134,15 +140,12 @@ function cloneContainer(container: unknown, key: string): Record<string, unknown
|
|||||||
return /^\d+$/.test(key) ? [] : {}
|
return /^\d+$/.test(key) ? [] : {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Clone the container spine down to the leaf's parent, materializing missing intermediates. */
|
||||||
* Immutably set a nested value, materializing missing intermediate containers.
|
function cloneSpine(root: Record<string, unknown>, path: readonly string[]): {
|
||||||
* @param root - draft root (never mutated).
|
result: Record<string, unknown>
|
||||||
* @param path - non-empty key path.
|
parent: Record<string, unknown> | unknown[]
|
||||||
* @param value - value to store at the path.
|
leaf: string
|
||||||
* @returns the new draft root.
|
} {
|
||||||
*/
|
|
||||||
export function setPath(root: Record<string, unknown>, path: readonly string[], value: unknown): Record<string, unknown> {
|
|
||||||
if (path.length === 0) throw new Error('schema-form: setPath needs a non-empty path')
|
|
||||||
const result = { ...root }
|
const result = { ...root }
|
||||||
let target: Record<string, unknown> | unknown[] = result
|
let target: Record<string, unknown> | unknown[] = result
|
||||||
for (let i = 0; i < path.length - 1; i++) {
|
for (let i = 0; i < path.length - 1; i++) {
|
||||||
@@ -155,9 +158,21 @@ export function setPath(root: Record<string, unknown>, path: readonly string[],
|
|||||||
else (target)[key] = child
|
else (target)[key] = child
|
||||||
target = child
|
target = child
|
||||||
}
|
}
|
||||||
const leaf = path[path.length - 1] as string
|
return { result, parent: target, leaf: path[path.length - 1] as string }
|
||||||
if (Array.isArray(target)) target[Number(leaf)] = value
|
}
|
||||||
else (target)[leaf] = value
|
|
||||||
|
/**
|
||||||
|
* Immutably set a nested value, materializing missing intermediate containers.
|
||||||
|
* @param root - draft root (never mutated).
|
||||||
|
* @param path - non-empty key path.
|
||||||
|
* @param value - value to store at the path.
|
||||||
|
* @returns the new draft root.
|
||||||
|
*/
|
||||||
|
export function setPath(root: Record<string, unknown>, path: readonly string[], value: unknown): Record<string, unknown> {
|
||||||
|
if (path.length === 0) throw new Error('schema-form: setPath needs a non-empty path')
|
||||||
|
const { result, parent, leaf } = cloneSpine(root, path)
|
||||||
|
if (Array.isArray(parent)) parent[Number(leaf)] = value
|
||||||
|
else parent[leaf] = value
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,20 +187,8 @@ export function setPath(root: Record<string, unknown>, path: readonly string[],
|
|||||||
export function deletePath(root: Record<string, unknown>, path: readonly string[]): Record<string, unknown> {
|
export function deletePath(root: Record<string, unknown>, path: readonly string[]): Record<string, unknown> {
|
||||||
if (path.length === 0) throw new Error('schema-form: deletePath needs a non-empty path')
|
if (path.length === 0) throw new Error('schema-form: deletePath needs a non-empty path')
|
||||||
if (!hasPath(root, path)) return root
|
if (!hasPath(root, path)) return root
|
||||||
const result = { ...root }
|
const { result, parent, leaf } = cloneSpine(root, path)
|
||||||
let target: Record<string, unknown> | unknown[] = result
|
if (Array.isArray(parent)) parent.splice(Number(leaf), 1)
|
||||||
for (let i = 0; i < path.length - 1; i++) {
|
else Reflect.deleteProperty(parent, leaf)
|
||||||
const key = path[i] as string
|
|
||||||
const child = cloneContainer(
|
|
||||||
Array.isArray(target) ? target[Number(key)] : (target)[key],
|
|
||||||
path[i + 1] as string,
|
|
||||||
)
|
|
||||||
if (Array.isArray(target)) target[Number(key)] = child
|
|
||||||
else (target)[key] = child
|
|
||||||
target = child
|
|
||||||
}
|
|
||||||
const leaf = path[path.length - 1] as string
|
|
||||||
if (Array.isArray(target)) target.splice(Number(leaf), 1)
|
|
||||||
else Reflect.deleteProperty(target, leaf)
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,6 @@
|
|||||||
"src"
|
"src"
|
||||||
],
|
],
|
||||||
"references": [
|
"references": [
|
||||||
{
|
|
||||||
"path": "../ui-primitives"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "../../../vendor/schemastery"
|
"path": "../../../vendor/schemastery"
|
||||||
},
|
},
|
||||||
|
|||||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -956,9 +956,6 @@ importers:
|
|||||||
|
|
||||||
packages/client/schema-form:
|
packages/client/schema-form:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@deepseek-ai/dsh-client-ui-primitives':
|
|
||||||
specifier: workspace:^
|
|
||||||
version: link:../ui-primitives
|
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
version: 18.3.1
|
version: 18.3.1
|
||||||
|
|||||||
Reference in New Issue
Block a user