refactor: share config path traversal helper

This commit is contained in:
Peter Steinberger
2026-03-26 22:29:27 +00:00
parent 5445bc68b9
commit ff47ad58fc

View File

@@ -15,49 +15,75 @@ function isForbiddenKey(key: string | number): boolean {
return typeof key === "string" && FORBIDDEN_KEYS.has(key);
}
export function setPathValue(
type PathContainer = {
current: Record<string, unknown> | unknown[];
lastKey: string | number;
};
function resolvePathContainer(
obj: Record<string, unknown> | unknown[],
path: Array<string | number>,
value: unknown,
) {
if (path.length === 0) {
return;
}
if (path.some(isForbiddenKey)) {
return;
createMissing: boolean,
): PathContainer | null {
if (path.length === 0 || path.some(isForbiddenKey)) {
return null;
}
let current: Record<string, unknown> | unknown[] = obj;
for (let i = 0; i < path.length - 1; i += 1) {
const key = path[i];
const nextKey = path[i + 1];
if (typeof key === "number") {
if (!Array.isArray(current)) {
return;
return null;
}
if (current[key] == null) {
if (!createMissing) {
return null;
}
current[key] = typeof nextKey === "number" ? [] : ({} as Record<string, unknown>);
}
current = current[key] as Record<string, unknown> | unknown[];
} else {
if (typeof current !== "object" || current == null) {
return;
}
const record = current as Record<string, unknown>;
if (record[key] == null) {
record[key] = typeof nextKey === "number" ? [] : ({} as Record<string, unknown>);
}
current = record[key] as Record<string, unknown> | unknown[];
continue;
}
if (typeof current !== "object" || current == null) {
return null;
}
const record = current as Record<string, unknown>;
if (record[key] == null) {
if (!createMissing) {
return null;
}
record[key] = typeof nextKey === "number" ? [] : ({} as Record<string, unknown>);
}
current = record[key] as Record<string, unknown> | unknown[];
}
const lastKey = path[path.length - 1];
if (typeof lastKey === "number") {
if (Array.isArray(current)) {
current[lastKey] = value;
return {
current,
lastKey: path[path.length - 1],
};
}
export function setPathValue(
obj: Record<string, unknown> | unknown[],
path: Array<string | number>,
value: unknown,
) {
const container = resolvePathContainer(obj, path, true);
if (!container) {
return;
}
if (typeof container.lastKey === "number") {
if (Array.isArray(container.current)) {
container.current[container.lastKey] = value;
}
return;
}
if (typeof current === "object" && current != null) {
(current as Record<string, unknown>)[lastKey] = value;
if (typeof container.current === "object" && container.current != null) {
(container.current as Record<string, unknown>)[container.lastKey] = value;
}
}
@@ -65,38 +91,18 @@ export function removePathValue(
obj: Record<string, unknown> | unknown[],
path: Array<string | number>,
) {
if (path.length === 0) {
const container = resolvePathContainer(obj, path, false);
if (!container) {
return;
}
if (path.some(isForbiddenKey)) {
return;
}
let current: Record<string, unknown> | unknown[] = obj;
for (let i = 0; i < path.length - 1; i += 1) {
const key = path[i];
if (typeof key === "number") {
if (!Array.isArray(current)) {
return;
}
current = current[key] as Record<string, unknown> | unknown[];
} else {
if (typeof current !== "object" || current == null) {
return;
}
current = (current as Record<string, unknown>)[key] as Record<string, unknown> | unknown[];
}
if (current == null) {
return;
}
}
const lastKey = path[path.length - 1];
if (typeof lastKey === "number") {
if (Array.isArray(current)) {
current.splice(lastKey, 1);
if (typeof container.lastKey === "number") {
if (Array.isArray(container.current)) {
container.current.splice(container.lastKey, 1);
}
return;
}
if (typeof current === "object" && current != null) {
delete (current as Record<string, unknown>)[lastKey];
if (typeof container.current === "object" && container.current != null) {
delete (container.current as Record<string, unknown>)[container.lastKey];
}
}