fix(sdk): address PR #2098 review feedback on variable CRUD

- validateOp now handles declareVariable/removeVariable (E_NO_ROOT when no
  composition root), matching setVariableValue's existing case — previously
  comp.can() returned E_UNKNOWN_OP for both.
- removeVariable's undo-inverse now tags its {decl, index} reinsert payload
  with __kind: "reinsert" instead of relying on structural "decl"/"index"
  key presence to disambiguate it from a plain declareVariable patch.
  VariableDecl has an open index signature, so a real variable schema could
  legally declare its own "decl"/"index" fields and be misinterpreted by the
  old structural check; a regression test pins the exact collision.
- getVariableValue's return type tightened from `unknown` to
  `string | number | boolean | FontValue | ImageValue | undefined`, matching
  setVariableValue's parameter type for round-trip symmetry. The underlying
  unknown-typed read is cast once at this SDK boundary.
- Added a redo test for declareVariable/removeVariable (existing tests only
  covered undo).
This commit is contained in:
Vance Ingalls
2026-07-09 11:52:12 -07:00
parent 19756faa5d
commit bcda11aa7c
6 changed files with 92 additions and 11 deletions
+19
View File
@@ -625,4 +625,23 @@ describe("variable declarations (Composition API)", () => {
{ id: "brand-color", type: "color", label: "Brand color", default: "#0066cc" },
]);
});
it("declareVariable / removeVariable both support redo after undo", async () => {
const comp = await openComposition(VARIABLES_HTML);
comp.declareVariable({ id: "brand-title", type: "string", label: "Title", default: "Hi" });
comp.undo();
comp.redo();
expect(comp.listVariables()).toEqual([
{ id: "brand-color", type: "color", label: "Brand color", default: "#0066cc" },
{ id: "brand-title", type: "string", label: "Title", default: "Hi" },
]);
comp.removeVariable("brand-color");
comp.undo();
comp.redo();
expect(comp.listVariables()).toEqual([
{ id: "brand-title", type: "string", label: "Title", default: "Hi" },
]);
});
});