From 09da5db4368430bf004055d67b2cdb466513a70f Mon Sep 17 00:00:00 2001 From: James Date: Sun, 3 May 2026 00:51:49 +0000 Subject: [PATCH] refactor(core): apply /simplify findings on validation PR - core.types.ts: export COMPOSITION_VARIABLE_TYPES, a runtime tuple of every CompositionVariableType variant guarded by `as const satisfies readonly CompositionVariableType[]`. Adding a new variant to the union without also adding it to the tuple becomes a compile error rather than silent drift in callers that maintain their own list. - composition.ts (lint rule): the local `new Set(["string","number","color","boolean","enum"])` now derives from COMPOSITION_VARIABLE_TYPES instead of duplicating the list. - index.ts: export COMPOSITION_VARIABLE_TYPES alongside the rest of the variable type guards. Reuse + efficiency reviews otherwise clean. The other reuse finding (loadProjectHtml helper to dedupe readFileSync + ensureDOMParser across 3 callers) is real but reaches files outside this PR's scope; it's a better fit as a follow-up cleanup once the variable-feature stack lands. All 48 composition lint tests + 49 core suite tests still green. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/core/src/core.types.ts | 14 ++++++++++++++ packages/core/src/index.ts | 1 + packages/core/src/lint/rules/composition.ts | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/core/src/core.types.ts b/packages/core/src/core.types.ts index 36f3c2dc7..929fef6de 100644 --- a/packages/core/src/core.types.ts +++ b/packages/core/src/core.types.ts @@ -88,6 +88,20 @@ export interface TimelineCompositionElement extends TimelineElementBase { // Composition Variable Types export type CompositionVariableType = "string" | "number" | "color" | "boolean" | "enum"; +/** + * Runtime list of every valid `CompositionVariableType`. Use this anywhere + * a Set/array of valid type strings is needed (lint rules, validators). + * The `satisfies` guard turns adding a new variant to the union without + * also adding it here into a compile error. + */ +export const COMPOSITION_VARIABLE_TYPES = [ + "string", + "number", + "color", + "boolean", + "enum", +] as const satisfies readonly CompositionVariableType[]; + export interface CompositionVariableBase { id: string; type: CompositionVariableType; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 4c66cef33..8a0906552 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -38,6 +38,7 @@ export { CANVAS_DIMENSIONS, TIMELINE_COLORS, DEFAULT_DURATIONS, + COMPOSITION_VARIABLE_TYPES, isTextElement, isMediaElement, isCompositionElement, diff --git a/packages/core/src/lint/rules/composition.ts b/packages/core/src/lint/rules/composition.ts index a7909d5b9..0f02b1a4a 100644 --- a/packages/core/src/lint/rules/composition.ts +++ b/packages/core/src/lint/rules/composition.ts @@ -1,5 +1,6 @@ import type { LintContext, HyperframeLintFinding } from "../context"; import { findHtmlTag, readAttr, readJsonAttr, truncateSnippet } from "../utils"; +import { COMPOSITION_VARIABLE_TYPES } from "../../core.types"; // Agent guidance thresholds: warning-only nudges for files/tracks that become hard // to inspect and revise reliably in a single composition. @@ -475,7 +476,7 @@ export const compositionRules: Array<(ctx: LintContext) => HyperframeLintFinding } const findings: HyperframeLintFinding[] = []; - const knownTypes = new Set(["string", "number", "color", "boolean", "enum"]); + const knownTypes = new Set(COMPOSITION_VARIABLE_TYPES); for (let i = 0; i < parsed.length; i += 1) { const entry = parsed[i]; if (!entry || typeof entry !== "object" || Array.isArray(entry)) {