Files
heygen-com--hyperframes/docs/sdk/reference/composition.mdx
T
wehub-resource-sync 85453da49f
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Docs / Validate docs (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Sync skills to ClawHub / Publish changed skills (push) Waiting to run
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:58:35 +08:00

757 lines
23 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Composition"
description: "The main editing surface returned by openComposition — query, mutate, animate, and serialize a composition."
---
`Composition` is the object returned by [`openComposition`](/sdk/reference/open-composition). Every SDK edit goes through this interface. Typed methods are convenience wrappers over `dispatch()`; all validation runs in `dispatch()` regardless of which entry point you use.
```typescript
import { openComposition } from "@hyperframes/sdk";
import type { Composition } from "@hyperframes/sdk";
const comp: Composition = await openComposition(html);
```
For a practical walkthrough see [Querying and editing](/sdk/guides/querying-and-editing).
---
## Typed edit methods
Typed methods are the recommended way to apply common edits. Each one calls `dispatch()` internally, so all patch events, history, and persistence behavior is identical.
### `setStyle`
```typescript
setStyle(id: HfId, styles: Record<string, string | null>): void
```
Apply inline CSS styles to one element. Use camelCase property names (matching `CSSStyleDeclaration`). Pass `null` as a value to remove that property.
```typescript
comp.setStyle("hf-title", { color: "#FFD60A", fontSize: "96px" });
comp.setStyle("hf-card", { borderRadius: null }); // removes border-radius
```
### `setText`
```typescript
setText(id: HfId, value: string): void
```
Replace the display text of an element. Targets the element's direct text content, not all descendant text.
```typescript
comp.setText("hf-headline", "Product launch — June 2026");
```
### `setAttribute`
```typescript
setAttribute(id: HfId, name: string, value: string | null): void
```
Set or remove an HTML attribute. Pass `null` to remove the attribute entirely.
```typescript
comp.setAttribute("hf-logo", "src", "/assets/logo-v2.png");
comp.setAttribute("hf-video", "autoplay", null); // removes autoplay
```
### `setTiming`
```typescript
setTiming(id: HfId, timing: { start?: number; duration?: number; trackIndex?: number }): void
```
Update the `data-start`, `data-duration`, and/or `data-track` attributes of one element. All fields are optional; omitted fields are left unchanged.
```typescript
comp.setTiming("hf-title", { start: 0.5, duration: 2.5 });
comp.setTiming("hf-cta", { trackIndex: 1 });
```
### `removeElement`
```typescript
removeElement(id: HfId): void
```
Remove an element and all its descendants from the composition. The inverse is an `addElement` of the removed subtree, so `undo()` restores it exactly.
```typescript
comp.removeElement("hf-old-badge");
```
### `addElement`
```typescript
addElement(parent: HfId | null, index: number, html: string): HfId
```
Insert an HTML fragment as a child of `parent` at zero-based sibling `index`. Pass `null` for `parent` to insert at the document body root. The fragment must be single-root and must not contain `<script>` tags. Returns the minted `hf-id` of the inserted root element.
```typescript
const newId = comp.addElement("hf-scene", 0, '<div class="clip">New clip</div>');
comp.setText(newId, "Inserted clip");
```
### `setVariableValue`
```typescript
setVariableValue(id: string, value: string | number | boolean | FontValue | ImageValue): void
```
Update a composition variable. Font variables require a `FontValue` object `{ name, source }`; image variables require an `ImageValue` object `{ url, alt?, fit? }`. Scalar variables accept `string | number | boolean`.
```typescript
comp.setVariableValue("brandColor", "#6C5CE7");
comp.setVariableValue("brandFont", { name: "Inter", source: "https://fonts.googleapis.com/css2?family=Inter" });
comp.setVariableValue("heroImage", { url: "/assets/hero.jpg", fit: "cover" });
```
<Note>
`setVariableValue` only updates a variable's current value — it refuses to create an undeclared variable. Use `declareVariable` to create one.
</Note>
### `getVariableValue`
```typescript
getVariableValue(id: string): string | number | boolean | FontValue | ImageValue | undefined
```
Return a declared variable's current `default` value, or `undefined` if the id is undeclared or has no value set.
```typescript
const color = comp.getVariableValue("brandColor"); // "#6C5CE7"
```
### `listVariables`
```typescript
listVariables(): CompositionVariable[]
```
Return every declared variable's full schema — `id`, `type`, `label`, `default`, and any type-specific fields (`min`/`max`/`step` for numbers, `options` for enums, `source` for fonts, etc). Returns `[]` when the composition declares no variables.
```typescript
for (const v of comp.listVariables()) {
console.log(v.id, v.type, v.default);
}
```
### `declareVariable` / `updateVariableDeclaration` / `removeVariableDeclaration`
```typescript
declareVariable(declaration: CompositionVariable): void
updateVariableDeclaration(id: string, declaration: CompositionVariable): void
removeVariableDeclaration(id: string): void
```
Manage the `data-composition-variables` schema itself. `declareVariable` adds a new
typed declaration (creating the attribute when the composition has none);
`updateVariableDeclaration` replaces an existing declaration wholesale — the id is
immutable, rename by remove + declare; `removeVariableDeclaration` deletes a
declaration (the last removal drops the whole attribute). All three validate via
`can()` (`E_DUPLICATE_VARIABLE`, `E_VARIABLE_NOT_FOUND`, `E_INVALID_ARGS`,
`E_INVALID_VARIABLE_ID` — the id must match `/^[A-Za-z_][A-Za-z0-9_-]*$/` since it
becomes a CSS custom-property name, `data-var-*` value, and CLI `--variables` key;
and `E_FRAGMENT_COMPOSITION`). Declarations live on the composition's declaration
root: the `<html>` element for a full document, or the composition root element
(`[data-composition-id]`) for a template / fragment sub-composition. Despite its
name, `E_FRAGMENT_COMPOSITION` now fires only when the source has **no** root
element at all to carry the schema — a fragment that has a composition root
accepts declarations. (The code is kept for compatibility; the fix is "add a
composition root element", not necessarily "add an `<html>`".)
```typescript
comp.declareVariable({ id: "title", type: "string", label: "Title", default: "Hello" });
comp.updateVariableDeclaration("title", { id: "title", type: "string", label: "Headline", default: "Hello" });
comp.removeVariableDeclaration("title");
```
<Note>`removeVariable(id)` is a shorthand alias of `removeVariableDeclaration(id)`.</Note>
### `getVariableDeclarations` / `getVariableValues` / `validateVariableValues` / `getVariableUsage`
```typescript
getVariableDeclarations(): CompositionVariable[]
getVariableValues(overrides?: Record<string, unknown>): Record<string, unknown>
validateVariableValues(values: Record<string, unknown>): VariableValidationIssue[]
getVariableUsage(): VariableUsageReport
```
Read-only variable APIs (no dispatch). `getVariableDeclarations` returns the typed
schema (same strict filter the render pipeline uses). `getVariableValues` resolves
values exactly like the runtime's `getVariables()` — declared defaults merged under
the given overrides — so callers can predict what a composition script will read for
a given `--variables` payload. `validateVariableValues` runs the same checks as
`--strict-variables` (`undeclared` / `type-mismatch` / `enum-out-of-range`).
`getVariableUsage` statically scans every inline script for `getVariables()` reads
and cross-references the schema: `{ usedIds, unusedDeclarations, undeclaredReads,
scanIncomplete }` — `scanIncomplete` flips when scripts access variables dynamically,
making `usedIds` a lower bound.
### `setPreviewVariables`
```typescript
setPreviewVariables(values: Record<string, unknown> | null): boolean
```
Apply ephemeral variable values to the preview surface (never persisted — use
`setVariableValue` to change a default). Pass `null` to restore declared defaults.
Delegates to the preview adapter's optional `setPreviewVariables`; returns `false`
when no adapter support is available.
### `getElementTimings`
```typescript
getElementTimings(): Record<HfId, ElementTimingSnapshot>
```
Return a map of enter/exit times and active GSAP labels for every timed element. The SDK derives `enterAt`/`exitAt` using `data-duration` when present, falling back to `data-end data-start`. GSAP labels are parsed fresh from the script each call. Elements with no timing attributes are excluded.
```typescript
const timings = comp.getElementTimings();
for (const [id, t] of Object.entries(timings)) {
console.log(id, t.enterAt, t.exitAt, t.labels);
}
```
### `setElementTiming`
```typescript
setElementTiming(map: Record<HfId, { start?: number; duration?: number; trackIndex?: number }>): void
```
Apply a sparse timing map in one batch. All entries are dispatched inside a single `batch()` call so the history sees one undo step. Entries for unknown IDs are silently skipped.
```typescript
comp.setElementTiming({
"hf-title": { start: 0, duration: 2 },
"hf-caption": { start: 1.5, duration: 1.5 },
"hf-cta": { start: 3, duration: 2 },
});
```
### `setHold`
```typescript
setHold(id: HfId, hold: ElasticHold): void
```
Set an elastic hold window — a `{ start, end, fill }` range that either freezes or loops the element during a pause in the timeline.
```typescript
comp.setHold("hf-hero", { start: 2, end: 5, fill: "freeze" });
```
### `addGsapTween`
```typescript
addGsapTween(target: HfId, tween: GsapTweenSpec): string
```
Add a GSAP tween to the composition's timeline targeting the given element. Returns the newly assigned `animationId`.
```typescript
const animId = comp.addGsapTween("hf-title", {
method: "from",
position: 0,
duration: 0.6,
ease: "power3.out",
fromProperties: { opacity: 0, y: 40 },
});
```
### `setGsapTween`
```typescript
setGsapTween(animationId: string, properties: Partial<GsapTweenSpec>): void
```
Update properties on an existing tween. Only the fields you supply are changed; the rest remain.
```typescript
comp.setGsapTween(animId, { ease: "back.out(1.7)", duration: 0.8 });
```
### `removeGsapTween`
```typescript
removeGsapTween(animationId: string): void
```
Remove a tween by animation ID.
```typescript
comp.removeGsapTween(animId);
```
### `addWithKeyframes`
```typescript
addWithKeyframes(
targetSelector: string,
position: number,
duration: number,
keyframes: KeyframeSpec[],
ease?: string,
): string
```
Add a new keyframed tween for `targetSelector` at the given timeline position and duration. Returns the newly minted `animationId`. Position is a number in seconds (not a label-relative string).
```typescript
const animId = comp.addWithKeyframes(
"#hf-logo",
0.5,
1.2,
[
{ percentage: 0, properties: { opacity: 0, scale: 0.8 } },
{ percentage: 100, properties: { opacity: 1, scale: 1 } },
],
"power2.out",
);
```
### `replaceWithKeyframes`
```typescript
replaceWithKeyframes(
animationId: string,
targetSelector: string,
position: number,
duration: number,
keyframes: KeyframeSpec[],
ease?: string,
): string
```
Atomically remove an existing tween and add a replacement keyframed tween. Returns the replacement's `animationId`. Because position-derived IDs renumber after the removal, the returned ID may differ from the input `animationId` — treat the return value as the new canonical ID.
```typescript
const newId = comp.replaceWithKeyframes(
oldAnimId,
"#hf-card",
1.0,
0.8,
[
{ percentage: 0, properties: { x: -100 } },
{ percentage: 100, properties: { x: 0 } },
],
);
```
### `undo` / `redo`
```typescript
undo(): void
redo(): void
```
Step backward or forward through the undo history. No-ops when history is disabled (`history: false` in options) or in embedded mode.
```typescript
comp.setText("hf-title", "Draft");
comp.undo(); // reverts to original text
comp.redo(); // re-applies "Draft"
```
### `canUndo` / `canRedo`
```typescript
canUndo(): boolean
canRedo(): boolean
```
Return `true` when a step in that direction is available. Use to drive the enabled state of undo/redo UI controls.
```typescript
undoButton.disabled = !comp.canUndo();
redoButton.disabled = !comp.canRedo();
```
---
## Query
### `getElements`
```typescript
getElements(): ElementSnapshot[]
```
Return a flat array of all elements in the composition, including elements nested inside sub-compositions. Each `ElementSnapshot` carries the element's `id`, `scopedId`, `tag`, `inlineStyles`, `classNames`, `attributes`, `text`, timing fields, and `animationIds`. The array is a fresh copy; mutations to the returned objects have no effect.
```typescript
const elements = comp.getElements();
const images = elements.filter((el) => el.tag === "img");
```
<Note>
For elements inside inlined sub-compositions, use `scopedId` (e.g. `"hf-host/hf-leaf"`) as the dispatch target, not `id`. Top-level elements have `scopedId === id`.
</Note>
### `getRootElements`
```typescript
getRootElements(): ElementSnapshot[]
```
Return only top-level elements, each carrying its full subtree — no id appears twice (unlike `getElements`, which flattens every nested element into the same array). Use this when you need one entry per top-level clip rather than every element in the tree.
```typescript
const roots = comp.getRootElements();
```
### `getElement`
```typescript
getElement(id: HfId): ElementSnapshot | null
```
Return the snapshot for one element by ID. Accepts both bare IDs (top-level elements) and scoped IDs (sub-composition elements). Returns `null` if no element matches.
```typescript
const el = comp.getElement("hf-title");
if (el) {
console.log(el.tag, el.inlineStyles);
}
```
### `find`
```typescript
find(query: FindQuery): string[]
```
Search elements by structured query. Returns an array of `scopedId` strings for matching elements. All fields in `FindQuery` are optional and combined with AND logic.
| Field | Type | Description |
|-------|------|-------------|
| `tag` | `string` | Exact HTML tag name, lowercase (`"div"`, `"img"`). |
| `text` | `string` | Substring match against the element's `text` field. |
| `name` | `string` | Exact match against `data-name` attribute. |
| `track` | `number` | Exact track index (`data-track`). |
| `composition` | `string` | Filter to elements inside a specific sub-composition host by its `hf-id`. |
```typescript
const headlineIds = comp.find({ name: "headline" });
const allImages = comp.find({ tag: "img" });
const track1Ids = comp.find({ track: 1 });
```
### `getAllAnimationIds`
```typescript
getAllAnimationIds(): Set<string>
```
Return every GSAP tween id parsed from the composition's script, regardless of whether its target selector currently matches a live DOM element. This differs from a given `ElementSnapshot`'s own `animationIds` field, which only lists tweens whose selector resolves to that specific element.
```typescript
const allIds = comp.getAllAnimationIds();
```
---
## Selection
### `selection`
```typescript
selection(): SelectionProxy
```
Return a `SelectionProxy` that resolves `getSelection()` at call time and dispatches operations to all selected elements. The proxy captures the ID list when you call `selection()` — subsequent selection changes do not affect an already-captured proxy.
```typescript
const sel = comp.selection();
sel.setStyle({ opacity: "0.5" });
sel.removeElement(); // removes all currently selected elements
```
### `element`
```typescript
element(id: HfId): ElementHandle
```
Return a curried `ElementHandle` for a single element. The handle stores only the ID string, so there is no stale-reference hazard if the DOM changes between calls.
```typescript
const title = comp.element("hf-title");
title.setText("Hello");
title.setStyle({ fontWeight: "700" });
```
### `getSelection`
```typescript
getSelection(): string[]
```
Return a copy of the current selection as an array of `hf-id` strings. Returns `[]` when nothing is selected.
```typescript
const ids = comp.getSelection();
console.log(`${ids.length} elements selected`);
```
### `setSelection`
```typescript
setSelection(ids: string[]): void
```
Replace the current selection. Fires `selectionchange`. Pass `[]` to clear the selection. Duplicate IDs are deduplicated automatically.
```typescript
comp.setSelection(["hf-title", "hf-subtitle"]);
comp.setSelection([]); // clear
```
---
## Advanced / agent
### `dispatch`
```typescript
dispatch(op: EditOp, opts?: { origin?: unknown }): void
```
Apply a data-shaped edit operation. All typed methods call this internally. Use `dispatch` when you need to apply op types that do not have a typed wrapper, when you are building automation that constructs ops programmatically, or when you need to set a custom `origin`.
```typescript
comp.dispatch({ type: "setStyle", target: "hf-card", styles: { borderRadius: "24px" } });
comp.dispatch({ type: "reorderElements", entries: [{ target: "hf-bg", zIndex: 0 }] });
comp.dispatch({ type: "setCompositionMetadata", width: 1920, height: 1080, duration: 30 });
```
For the full op catalog see [Edit operations](/sdk/reference/edit-operations).
You can also target multiple elements with a single `dispatch` by passing an array to `target`:
```typescript
comp.dispatch({ type: "setText", target: ["hf-title", "hf-subtitle"], value: "Coming soon" });
```
### `batch`
```typescript
batch(fn: () => void, opts?: { origin?: unknown }): void
```
Coalesce multiple dispatches into one undo entry and one `patch` event. If the callback throws, all DOM mutations that ran inside the batch are rolled back atomically and the model is restored to its state before `batch()` was called.
```typescript
comp.batch(() => {
comp.setText("hf-title", "Version 2");
comp.setStyle("hf-title", { color: "#22C55E" });
comp.setTiming("hf-title", { start: 1, duration: 3 });
});
```
### `can`
```typescript
can(op: EditOp): CanResult
```
Dry-run validation. Returns `{ ok: true }` when `dispatch(op)` would succeed, or `{ ok: false, code, message, hint? }` when it would fail or be a no-op.
Use this as a feature-detection gate before rendering controls that depend on GSAP timeline availability, or before showing UI that applies optional edits.
```typescript
const result = comp.can({
type: "setGsapTween",
animationId: "anim-1",
properties: { ease: "power3.out" },
});
if (result.ok) {
comp.setGsapTween("anim-1", { ease: "power3.out" });
} else {
console.warn(result.code, result.message);
}
```
Stable error codes: `E_TARGET_NOT_FOUND`, `E_NO_ROOT`, `E_NO_GSAP_TIMELINE`, `E_NO_GSAP_SCRIPT`.
For the full op catalog see [Edit operations](/sdk/reference/edit-operations).
---
## Events
All `on()` overloads return an unsubscribe function. Call it to remove the listener.
```typescript
on(event: "change", handler: () => void): () => void
on(event: "selectionchange", handler: (ids: string[]) => void): () => void
on(event: "patch", handler: (event: PatchEvent) => void): () => void
on(event: "persist:error", handler: (event: PersistErrorEvent) => void): () => void
```
### `change`
Fires after every committed mutation (whether typed method, `dispatch`, or `batch`). Use this to refresh a canvas or other derived view.
```typescript
const off = comp.on("change", () => {
canvas.render(comp.getElements());
});
off(); // unsubscribe
```
### `selectionchange`
Fires when the selection changes, with the new ID array as the argument.
```typescript
comp.on("selectionchange", (ids) => {
propertiesPanel.show(ids);
});
```
### `patch`
Fires after every committed change with a `PatchEvent` containing RFC 6902 forward and inverse patches, the `origin`, and semantic `opTypes`. Use this to mirror edits into a host history stack, collaboration layer, or audit log.
```typescript
comp.on("patch", ({ patches, inversePatches, origin, opTypes }) => {
if (origin !== ORIGIN_APPLY_PATCHES) {
hostHistory.push({ patches, inversePatches });
}
});
```
<Warning>
Always guard against `ORIGIN_APPLY_PATCHES` in `patch` listeners. Failing to skip that origin causes an infinite loop when your host replays inverse patches back into the SDK via `applyPatches()`.
</Warning>
### `persist:error`
Fires when the persist adapter fails to write. The session continues; edits accumulate in memory and the queue retries on the next mutation.
```typescript
comp.on("persist:error", ({ error }) => {
toast.error(`Autosave failed: ${error.message}`);
});
```
For undo/redo and patch patterns see [Undo, redo, and patches](/sdk/guides/undo-redo-and-patches).
---
## Serialization
### `serialize`
```typescript
serialize(): string
```
Return the current composition as an HTML string reflecting all mutations applied since `openComposition`. The base HTML is never modified; this always returns a fresh serialization of the live document.
```typescript
const updatedHtml = comp.serialize();
await fs.writeFile("output.html", updatedHtml);
```
---
## Embedded extras
These methods are only meaningful in embedded / override mode. See the [embedded override mode guide](/sdk/guides/embedded-override-mode).
### `getOverrides`
```typescript
getOverrides(): OverrideSet
```
Return a copy of the current override set — the sparse delta accumulated on top of the base template. Store this instead of the full HTML when the base template is shared.
```typescript
const delta = comp.getOverrides();
await db.saveUserOverrides(userId, delta);
```
### `applyPatches`
```typescript
applyPatches(patches: readonly JsonPatchOp[], opts?: { origin?: unknown }): void
```
Apply RFC 6902 patches directly to the live document. The default origin is `ORIGIN_APPLY_PATCHES`, which prevents `patch` listeners from forwarding these back in an undo loop. Use this when the host owns the undo stack and needs to replay inverse patches from its own history.
```typescript
// Host undo: replay inverse patches from the host stack
const { inversePatches } = hostHistory.pop();
comp.applyPatches(inversePatches);
```
---
## Lifecycle
### `flush`
```typescript
flush(): Promise<void>
```
Drain the persist queue. Resolves when any pending write has been committed to the adapter. No-op when no persist adapter was provided. Call this before process exit or navigation away to avoid losing queued writes.
```typescript
comp.setText("hf-title", "Final title");
await comp.flush();
comp.dispose();
```
### `dispose`
```typescript
dispose(): void
```
Tear down the session: unsubscribe preview adapter listeners, stop the persist queue, stop the history module, and clear all event handlers. After `dispose()`, the `Composition` object is inert; continued calls produce no-ops or errors.
```typescript
comp.dispose();
```
<Note>
Always call `dispose()` when you are done with a session. Skipping it leaks listeners attached to the preview adapter.
</Note>
---
## Related
<CardGroup cols={2}>
<Card title="openComposition" icon="door-open" href="/sdk/reference/open-composition">
Session factory — all options and modes.
</Card>
<Card title="Edit operations" icon="bolt" href="/sdk/reference/edit-operations">
Full op catalog for dispatch() and can().
</Card>
<Card title="Types reference" icon="file-code" href="/sdk/reference/types">
All exported TypeScript types — ElementSnapshot, PatchEvent, GsapTweenSpec, and more.
</Card>
<Card title="Querying and editing" icon="magnifying-glass" href="/sdk/guides/querying-and-editing">
Practical guide to find, getElements, and typed edits.
</Card>
<Card title="Undo, redo, and patches" icon="arrow-uturn-left" href="/sdk/guides/undo-redo-and-patches">
History, patch events, ORIGIN_APPLY_PATCHES guard.
</Card>
<Card title="Embedded override mode" icon="layers" href="/sdk/guides/embedded-override-mode">
Template-driven products with host-owned history.
</Card>
</CardGroup>