Repository navigation
feat(studio): load GSAP from the CLI's bundled copy by default - #6256
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
Edit accuracy: accurate 271 (base branch 271), smooth 144 of thoseThe gate passes. Quarantined, measured but not gated (0) Unstable (2)
|
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
The bundled-file route's exact filename/package allowlist and loopback HTTP restriction look sound, and the relevant hosted tests ran green. One render-path gap remains: the new mirror setting is applied only to the entry HTML, not to missing GSAP scripts in nested compositions. I left the reproducer and requested regression coverage inline. This head is also currently conflicted with main; that is an independent merge gate. — Jerrai
| /** Renders follow the same `HYPERFRAMES_GSAP_BASE_URL` mirror as Studio preview. */ | ||
| function renderGsapDist(): string { | ||
| try { | ||
| return gsapCdnDist(undefined, normalizeGsapBaseUrl(process.env.HYPERFRAMES_GSAP_BASE_URL)); |
There was a problem hiding this comment.
The render mirror only applies when rewriteUnresolvableGsapToCdn is called on the entry document (compileForRender, line 2030). A supported data-composition-src scene is read by parseSubCompositions and passed straight to compileHtmlFile (lines 793–799), then its local <script src="node_modules/gsap/dist/gsap.min.js"> is hoisted into the assembled render. If that local path is missing, inlineExternalScripts only fetches HTTP URLs, so setting HYPERFRAMES_GSAP_BASE_URL never supplies GSAP for the nested scene. Please apply the same missing-local rewrite to nested composition HTML before compilation/hoisting, and cover a nested render with the mirror configured. — Jerrai
Studio preview now loads the GSAP, CustomEase and MotionPathPlugin scripts it adds from files the CLI ships and serves same-origin at /api/vendor/npm, instead of jsDelivr. HYPERFRAMES_GSAP_BASE_URL still wins when set, and a composition on another GSAP version gets its plugin from jsDelivr. Renders now honor HYPERFRAMES_GSAP_BASE_URL when they replace a missing local GSAP script, and the setting accepts plain http only for loopback hosts. Closes #6205 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…source The Windows CI lane installs with the hoisted linker, so gsap is not under packages/core/node_modules there. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
A sub-composition's missing local gsap/dist script was hoisted into the render unchanged, so HYPERFRAMES_GSAP_BASE_URL (and the jsDelivr fallback) only reached the entry document. Run the same rewrite on every sub-composition before it is compiled, resolving its path the way the inliner will hoist it. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
ec7502a to
0bd8136
Compare
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
The successor closes my nested-render gap: each mounted sub-composition is rewritten before compilation, including recursive scenes and the direct-disk fallback, while the sibling-first asset lookup preserves a local copy. The new one- and two-depth render tests exercise the mirror path. The rebase left the previously reviewed vendor route and loopback restriction intact. Exact-head producer unit tests, support tests, build, lint and typecheck ran green; the initial Windows browserManager.test.ts probe-timing failure passed on rerun and does not touch this diff. No CODEOWNER match. This is approval of the code, not merge or release authorization. — Jerrai
What
HyperFrames Studio now loads the GSAP scripts it adds to previews (GSAP core, CustomEase, MotionPathPlugin) from files the CLI ships, served by the preview server itself, instead of from jsDelivr. Opening a project in
npx hyperframes previewno longer makes a jsDelivr request for these scripts.This also picks up both follow-ups from the review of #6247: renders now honor
HYPERFRAMES_GSAP_BASE_URL, and the setting accepts plainhttp://only for loopback hosts.Why
#6205: Studio requested
MotionPathPlugin.min.jsfrom jsDelivr every time the editor opened, which fails offline and on restricted networks and sends a third-party request from a local editor. #6247 added an opt-in mirror, but the default still went to jsDelivr.Related work
Closes #6205
Builds on #6247, which added
HYPERFRAMES_GSAP_BASE_URLand routed every Studio load site (preview document, sub-compositions, the soft-reload loader and the editor preload) through one setting. This PR changes the default behind that setting.How
Lookup order (
packages/studio-server/src/routes/preview.ts):HYPERFRAMES_GSAP_BASE_URL, when set. Unchanged, still no public fallback.gsapLocalRoot(a same-origin path, passed likeruntimeUrl).Shipping the files.
packages/cli/scripts/build-copy.mjscopiesgsap.min.js,CustomEase.min.jsandMotionPathPlugin.min.jsfrom the workspace's installed gsap intodist/vendor/npm/[email protected]/dist/. The build fails if the installed gsap version differs fromGSAP_CDN_VERSION, so the two cannot drift silently. No new runtime dependency.Serving them.
studioServer.tsserves/api/vendor/npm/:pkg/dist/:file, modeled on/api/runtime.js. It answers only the three files at the bundled version and returns 404 for anything else. When running from source it falls back to core's installed gsap, and if no files are found it passes nogsapLocalRoot, so preview keeps using jsDelivr instead of breaking.Root-relative values (
packages/core/src/gsapCdn.ts).normalizeGsapBaseUrlstill rejects root-relative values, which is right for the env var. A newnormalizeGsapLocalRootvalidates the adapter's path (no//host, backslash, query or fragment).gsapCdnDisttreats a root-relative base as the local copy, which holds only3.15.0: any other version, such as an authored[email protected], resolves to jsDelivr. The server-written meta tag carries the root, so the browser loaders ingsapSoftReload.tsand the editor preload follow the same rule without changes.Renders (review note 1).
htmlCompiler.tsused to rewrite a missing localgsap/dist/*script to jsDelivr. It now usesHYPERFRAMES_GSAP_BASE_URLwhen set. The compiler already downloads and inlines remote scripts, so the render fetches GSAP from the mirror at compile time. The same rewrite runs on every sub-composition mounted withdata-composition-src, at any depth, before it is compiled and hoisted. A sub-composition's script path is checked the way the inliner resolves it (a sibling file first, then the project root), so a copy that exists next to the scene is kept. An invalid value fails the render with the same configuration error Studio gives. The value is read only when a rewrite is needed, so a bad value cannot fail renders that never touch it. Renders do not use the CLI's bundled copy: they compile outside the preview server, so there is no same-origin root to point at.Plain http (review note 2).
normalizeGsapBaseUrlnow acceptshttp://only forlocalhost,127.0.0.0/8and::1, and requires HTTPS for any other host. This covers both Studio and renders.Not changed, on purpose. URLs authored in a composition stay as written, including the jsDelivr GSAP tag in the
inittemplates. When Studio writes the first animation into a file that has no GSAP, it still writes the jsDelivr URL, because that file has to render outside Studio. The docs now say both.Before
Studio on
mainwithHYPERFRAMES_GSAP_BASE_URLunset, opened in headless Chromium against a project that vendors GSAP locally. Every request the page and its preview iframe made was recorded; opening the editor requestsMotionPathPlugin.min.jsfrom jsDelivr.After
Same project, same browser, this branch. The plugin comes from the preview server at
/api/vendor/npm, and no request leaves the preview server's origin.Test plan
New tests (19 of them fail when the source changes are reverted to
main):preview.test.tscovers the root document, sub-composition and MotionPathPlugin injection.studioServer.previewAssets.test.tsexercises the real CLI server, fetches all three files from the route, and checks the 404s.gsapCdn.test.ts,preview.test.tsandgsapSoftReload.test.ts(editor preload with a3.14.2runtime).preview.test.tsandstudioServer.previewAssets.test.ts.gsapCdn.test.tsandpreview.test.ts.htmlCompiler.test.tschecks that the mirror is fetched and inlined, that jsDelivr is kept when no mirror is set, and that invalid values fail. It also covers a missing GSAP script in a sub-composition and in a sub-composition of a sub-composition (both fail without the fix), and a sub-composition whose GSAP exists next to it (kept, nothing fetched).Run locally:
bun run build,bun run lint,bun run format:check,bun run --filter '*' typecheck,bun run typecheck:scripts,bun run verify:packed-manifests,bun run check:cli-lazy-deps: all pass.lateVisibleImageGrading, timed out because the local test sandbox blocks loopback listening; it does not touch this code.3.15.0builds with their license headers intact.🤖 Generated with Claude Code