refactor: tighten nitro editor JSON typing with generic path helpers
This commit is contained in:
1 parent
6549ae1959
commit
ca49c6b5a8
1 file changed
+12
-20
@@ -47,8 +47,7 @@ interface NitroVisualization {
|
||||
}
|
||||
|
||||
// The .nitro metadata is untyped JSON from disk; typed only for the fields the
|
||||
// editor reads/writes, with an index signature so the generic path helpers can
|
||||
// traverse arbitrary nested keys.
|
||||
// editor reads/writes. Unknown keys are traversed via the path helpers below.
|
||||
interface NitroMetadata {
|
||||
visualizationType?: string;
|
||||
logicType?: string;
|
||||
@@ -59,19 +58,18 @@ interface NitroMetadata {
|
||||
};
|
||||
};
|
||||
visualizations?: NitroVisualization[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
type JsonObject = Record<string, unknown>;
|
||||
|
||||
function updateNested<T extends JsonObject>(
|
||||
function updateNested<T extends object>(
|
||||
obj: T,
|
||||
path: string,
|
||||
value: unknown,
|
||||
): T {
|
||||
const clone: T = JSON.parse(JSON.stringify(obj));
|
||||
const keys = path.split(".");
|
||||
let current: JsonObject = clone;
|
||||
let current: JsonObject = clone as JsonObject;
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
const next = current[keys[i]];
|
||||
if (!next || typeof next !== "object" || Array.isArray(next)) {
|
||||
@@ -83,14 +81,14 @@ function updateNested<T extends JsonObject>(
|
||||
return clone;
|
||||
}
|
||||
|
||||
function getNested(obj: unknown, path: string, fallback?: unknown): unknown {
|
||||
function getNested<T>(obj: unknown, path: string, fallback: T): T {
|
||||
const keys = path.split(".");
|
||||
let current: unknown = obj;
|
||||
for (const key of keys) {
|
||||
if (current == null || typeof current !== "object") return fallback;
|
||||
current = (current as JsonObject)[key];
|
||||
}
|
||||
return current ?? fallback;
|
||||
return current === undefined ? fallback : (current as T);
|
||||
}
|
||||
|
||||
const ALL_DIRECTIONS = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
@@ -255,14 +253,12 @@ export function NitroEditorDialog({
|
||||
|
||||
// ── Visual tab helpers ──
|
||||
|
||||
const dims = (
|
||||
metadata
|
||||
? getNested(metadata, "logic.model.dimensions", { x: 1, y: 1, z: 0 })
|
||||
: { x: 1, y: 1, z: 0 }
|
||||
) as { x: number; y: number; z: number };
|
||||
const directions = (
|
||||
metadata ? getNested(metadata, "logic.model.directions", [0]) : [0]
|
||||
) as number[];
|
||||
const dims = metadata
|
||||
? getNested(metadata, "logic.model.dimensions", { x: 1, y: 1, z: 0 })
|
||||
: { x: 1, y: 1, z: 0 };
|
||||
const directions = metadata
|
||||
? getNested(metadata, "logic.model.directions", [0])
|
||||
: [0];
|
||||
|
||||
const setDim = (axis: "x" | "y" | "z", value: string) => {
|
||||
const num =
|
||||
@@ -271,11 +267,7 @@ export function NitroEditorDialog({
|
||||
};
|
||||
|
||||
const toggleDirection = (dir: number) => {
|
||||
const current = getNested(
|
||||
metadata,
|
||||
"logic.model.directions",
|
||||
[0],
|
||||
) as number[];
|
||||
const current = getNested(metadata, "logic.model.directions", [0]);
|
||||
const next = current.includes(dir)
|
||||
? current.filter((d: number) => d !== dir)
|
||||
: [...current, dir].sort((a: number, b: number) => a - b);
|
||||
|
||||
Reference in new issue
Block a user