mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
4988b42362574d18aaf2d6272627ea10160b1670
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
eb338ae859 |
feat(core): add registry schema + TS types (#252)
* feat(core): add registry schema + TS types
PR 1/17 of the catalog system rollout. Foundation for a shadcn-style
registry with three item tiers: examples (full projects), blocks
(sub-compositions), components (effect snippets).
## What
- TS types: RegistryItem (discriminated union of ExampleItem/BlockItem/
ComponentItem), RegistryManifest, FileTarget, ItemType, FileType
- JSON Schemas: schemas/registry.json, schemas/registry-item.json
- Compile-time exhaustiveness asserts on ITEM_TYPES/FILE_TYPES so adding
to the TS union without updating the constant stops compiling
- Drift-guard test: schema enums must equal ITEM_TYPES/FILE_TYPES by
set-equality; exactly 2 distinct type enums in registry-item.json
- Public API via new ./registry export path plus re-exports from root;
schemas exposed via ./schemas/registry.json export for external tooling
## Why
- Every downstream PR (resolver, installer, hyperframes add, docs
codegen, CI previews, skill, catalog command) builds on these types
- Getting the shape right now avoids painful migrations later
## How
- Discriminated union enforces that components do not have dimensions
or duration and examples/blocks must have them (schema mirrors via
if/then/else on the type discriminant)
- target path pattern rejects .. segments, Unix absolute paths, and
Windows drive letters (defense-in-depth; CLI validates at runtime in
PR 3)
- name pattern requires alphanumeric start and end (no trailing hyphens)
- Optional metadata: version, author, license, deprecated, minCliVersion
- additionalProperties: false on nested objects (catches typos on
critical fields) but relaxed on top-level RegistryItem (allows
third-party custom metadata in PR 15 custom registries)
## Test plan
- [x] Unit tests: 11 new tests covering type guards, discriminant
narrowing, schema/TS drift guards, schema \$id sanity, optional
metadata acceptance, and compile-time checks (via @ts-expect-error)
- [x] bun run test in packages/core: 445 passed (was 434 on main,
+11 from this PR)
- [x] bunx oxfmt and bunx oxlint: clean
- [x] bun run typecheck: clean
- [ ] Manual testing: N/A (types + schemas only)
- [ ] Documentation updated: per-item doc pages land in PR 9 (codegen
from these manifests); guide updates in PR 10+
## Breaking / migration
None. Pure additive — new module, new export paths, no existing
surface touched.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(core): remove version field + hyperframes:demo file type
Address review feedback from Miguel:
- Remove `version` from RegistryItemBase + schema. Per shadcn model,
the registry is versioned by git tags, not per-item. The adversarial
review added it; the original design doc was correct.
- Remove `hyperframes:demo` from FileType union + FILE_TYPES constant
+ schema. Demo files exist on disk for the CI preview pipeline but
are NOT installed to user projects and should not appear in
registry-item.json files[]. Neither shadcn nor Remotion has a
dedicated demo file type — demos are just compositions.
- Add `required: ["type"]` to the if-condition in the schema's
allOf discriminant (Miguel's nit — makes the condition self-
contained)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): add shader-transitions to Dockerfile.test
PR #251 added packages/shader-transitions/ to the workspace but didn't
update Dockerfile.test to COPY its package.json. This caused
`bun install --frozen-lockfile` to fail in the regression Docker build:
bun saw a lockfile referencing @hyperframes/shader-transitions but the
package.json wasn't present in the container, so it wanted to remove
the entry — triggering "lockfile had changes."
Verified: Docker build passes with `--no-cache` after this fix.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
5655dabff6 |
feat: allow clip animation + ship <hyperframes-player> web component (#209)
## Summary Two independent initiatives that improve agent DX and expand HyperFrames' reach. ### Initiative 1: Fix the Clip Animation Footgun - `gsap_animates_clip_element` lint rule now uses smart detection — only errors when GSAP animates `visibility` or `display` on a clip element - All other properties (opacity, transform, x, y, scale, etc.) are allowed silently - This was the #1 agent failure in QA (10/10 agents hit it on v0.2.1) ### Initiative 2: `<hyperframes-player>` Web Component - New `@hyperframes/player` package — zero dependencies, 3.3KB gzipped - Iframe-based web component with Shadow DOM for perfect isolation - Video-like API: `play()`, `pause()`, `seek()`, `currentTime`, `duration`, events - Controls overlay with play/pause, scrubber (mouse + touch), time display, auto-hide - Full docs page at `docs/packages/player.mdx` ## Before / After ### Clip animation lint **Before (10/10 agents hit this):** ``` ✗ gsap_animates_clip_element: GSAP animation targets a clip element. Selector "#title" resolves to element <div id="title" class="clip">. The framework manages clip visibility — animate an inner wrapper instead. Fix: Wrap content in a child <div> and target that with GSAP. ``` **After (only errors on actual conflicts):** ``` # This passes lint — no error: tl.from("#title", { opacity: 0, y: -50, scale: 0.8 }, 0); # This still errors — actual conflict with runtime: tl.to("#title", { visibility: "hidden" }, 3); ✗ gsap_animates_clip_element: GSAP animation sets visibility on a clip element. Fix: Remove the visibility/display tween. Use opacity for fade effects. ``` ### Embeddable player **Before:** No way to embed a composition in a web page. **After:** ```html <script src="https://cdn.jsdelivr.net/npm/@hyperframes/player"></script> <hyperframes-player src="./composition/index.html" controls></hyperframes-player> ``` ```js const player = document.querySelector('hyperframes-player'); player.play(); player.pause(); player.seek(2.5); player.addEventListener('ready', (e) => console.log('Duration:', e.detail.duration)); ``` ## Test plan - [x] 427 core tests pass (20 GSAP lint tests with smart detection) - [x] 7 player tests pass (formatTime + element registration) - [x] TypeScript compiles cleanly (core + player) - [x] Lint: GSAP animating clip with safe props → 0 errors - [x] Lint: GSAP animating clip with `visibility` → 1 error (correct) - [x] Player builds to 3.3KB gzipped ESM - [x] Lockfile updated for CI - [x] Docs page added at `docs/packages/player.mdx` |
||
|
|
110ea12597 |
fix(core,engine,producer): handle id-less media in sub-composition renders (#96)
## What Move the id-less media fix into the shared timing compiler so producer can resolve durations for sub-composition videos before inlining, then carry the merged result through engine parsing, regression coverage, and the regression Docker image used in CI. This PR now does five concrete things: - assigns stable ids to id-less media in core `compileTimingAttrs()` so unresolved duration injection can target them - keeps the engine-side `parseVideoElements()` support for `video[src]` plus the newer `data-duration` / natural-duration fallback from `main` - makes producer prefer sub-composition media metadata over the later inlined-document parse when the same media id appears in both places - makes `sub-composition-video` a runnable regression test by fixing its metadata and checking in the missing `output/compiled.html` snapshot - removes the stale `pnpm-workspace.yaml` copy step from `Dockerfile.test`, so regression CI builds the Bun-based test image from the current workspace layout ## Why - media without an explicit `id` could not participate in unresolved-duration resolution early enough - producer could lose the resolved sub-composition timing by overwriting it with the later inlined parse - the regression fixture intended to cover this case was not actually running in CI because its `meta.json` was incomplete and the required compiled snapshot was missing - the regression image definition still expected a deleted `pnpm-workspace.yaml`, so GitHub Actions failed before the test shard could start Putting the id-generation step in core makes the behavior reusable instead of relying on producer-only HTML patching. ## How ### Shared compiler - core `compileTimingAttrs()` now auto-assigns stable ids to id-less `video` / `audio` tags - those generated ids are returned in `unresolved`, so `injectDurations()` can add `data-duration` and `data-end` to the same media element later in the pipeline - added core tests that cover auto-id assignment and duration injection for generated ids ### Producer - when producer combines `subVideos` / `subAudios` with the media re-parsed from the final inlined HTML, it now lets the sub-composition metadata win - this preserves the resolved/clamped timing already computed for nested media instead of overwriting it with the later parse - `sub-composition-video` now has valid regression metadata and a checked-in `output/compiled.html` snapshot so CI actually executes it ### Engine - resolved the merge conflict in `videoFrameExtractor` by keeping the broader `video[src]` parsing from this branch and the `data-duration` / natural-duration fallback that landed on `main` - added a focused engine unit test for videos without ids ### CI image - `Dockerfile.test` now copies only `package.json` and `bun.lock` at the workspace root before `bun install --frozen-lockfile` - this matches the current monorepo layout and removes the obsolete pnpm-era dependency on `pnpm-workspace.yaml` ## Test plan - [x] `bun run --filter @hyperframes/core test` - [x] `bun run --filter @hyperframes/engine test` - [x] `bun run --filter @hyperframes/producer test --update --sequential sub-composition-video` - [x] `bun run --filter @hyperframes/producer test --sequential sub-composition-video` - [x] Browser check with `agent-browser` against the compiled fixture page (`http://127.0.0.1:8123/compiled.html`) - [x] Clean tracked-only Docker build of `Dockerfile.test` with the PR version of the file applied ## Notes - Latest regression workflow is green on `main`, but before this PR the `sub-composition-video` fixture was being skipped by the harness rather than exercised end to end. - The CI Docker fix was validated from a tracked-only export to avoid local untracked worktree artifacts affecting the result. |
||
|
|
e746debb1a |
fix(ci): generate font data in Docker build instead of committing
The generated font data is a pure function of the generator script + @fontsource package versions — no reason to store 566KB of base64 blobs in git. Generate it during the Docker test image build instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
94e25443ae |
build: migrate from pnpm to bun as package manager (#28)
## Summary - Replace pnpm with bun for dependency installation, script running, and ad-hoc execution - Keep pnpm for publish workflow only (`publishConfig` overrides + `--provenance`) - `bun install` replaces `pnpm install` (~4-5x faster cold installs) - `bun run` replaces `pnpm run` (~28x less startup overhead) - `bunx` replaces `npx` in lefthook hooks - CI workflows updated (`oven-sh/setup-bun@v2` + `actions/setup-node@v4`) - `pnpm-lock.yaml` removed, `bun.lock` generated - `pnpm-workspace.yaml` kept for publish compatibility - CLI source code (`packages/cli/src/`) unchanged — shipped to end users who may not have bun Part 5/5 of [VA-851](https://linear.app/heygen/issue/VA-851/pre-migration-configure-eslint-prettier-and-conventional-commits) ## Test plan - [x] `bun run lint` — 0 errors - [x] `bun run format:check` — all files pass - [x] `bun run build` — all 5 packages build - [x] 330 core tests pass - [x] 18 engine tests pass - [x] `publish.yml` unchanged (pnpm stays for npm publishing) - [x] No `bunx`/`bun run` references in shipped source code (`packages/*/src/`) |
||
|
|
04c48d5bc5 |
ci(regression): add Docker-based regression test pipeline
Port the regression test infrastructure from the internal repo to OSS. Runs golden-baseline visual/audio comparisons inside Docker for deterministic results. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |