mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-07 10:06:21 +00:00
Introduces sdkCutoverPersist(): when STUDIO_SDK_CUTOVER_ENABLED is set, inline-style PatchOps are routed through the SDK session's in-memory document model instead of the server patch-element API. The SDK serialize() result is written back through the same writeProjectFile + editHistory.recordEdit path, so the on-disk output is identical to the legacy route. - packages/studio/src/utils/sdkCutover.ts (new): sdkCutoverPersist() + shouldUseSdkCutover() guard; domEditSaveTimestampRef.current is stamped on each write to suppress the echo file-change reload. - packages/studio/src/components/editor/manualEditingAvailability.ts: adds STUDIO_SDK_CUTOVER_ENABLED flag (default false); changes STUDIO_SDK_SHADOW_ENABLED default to false now that cutover is available. - packages/studio/src/hooks/useSdkSession.ts: adds optional domEditSaveTimestampRef param; self-write suppress window (SELF_WRITE_SUPPRESS_MS) gates file-change reloads so SDK writes don't echo back as external edits. - packages/studio/src/App.tsx: passes domEditSaveTimestampRef to useSdkSession so the suppress window can gate reloads triggered by SDK cutover writes. - Test coverage: sdkCutover.test.ts (new, 141 lines) + useDomEditSession.test.ts (new, 50 lines) — guard function + happy-path assertions. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { shouldUseSdkCutover } from "../utils/sdkCutover";
|
|
import type { PatchOperation } from "../utils/sourcePatcher";
|
|
|
|
const styleOp = (property: string, value: string): PatchOperation => ({
|
|
type: "inline-style",
|
|
property,
|
|
value,
|
|
});
|
|
|
|
const attrOp = (property: string, value: string): PatchOperation => ({
|
|
type: "attribute",
|
|
property,
|
|
value,
|
|
});
|
|
|
|
describe("shouldUseSdkCutover", () => {
|
|
it("returns false when flag is disabled", () => {
|
|
expect(shouldUseSdkCutover(false, true, "hf-abc", [styleOp("color", "red")])).toBe(false);
|
|
});
|
|
|
|
it("returns false when no SDK session", () => {
|
|
expect(shouldUseSdkCutover(true, false, "hf-abc", [styleOp("color", "red")])).toBe(false);
|
|
});
|
|
|
|
it("returns false when selection has no hfId", () => {
|
|
expect(shouldUseSdkCutover(true, true, null, [styleOp("color", "red")])).toBe(false);
|
|
expect(shouldUseSdkCutover(true, true, undefined, [styleOp("color", "red")])).toBe(false);
|
|
});
|
|
|
|
it("returns false when ops array is empty", () => {
|
|
expect(shouldUseSdkCutover(true, true, "hf-abc", [])).toBe(false);
|
|
});
|
|
|
|
it("returns true when all conditions met with supported op types", () => {
|
|
expect(shouldUseSdkCutover(true, true, "hf-abc", [styleOp("color", "red")])).toBe(true);
|
|
expect(
|
|
shouldUseSdkCutover(true, true, "hf-abc", [styleOp("color", "red"), attrOp("data-x", "1")]),
|
|
).toBe(true);
|
|
});
|
|
});
|