- name
- api
- description
- Authoritative TypeScript signatures for `engine.design`, the only API edit
code uses. Use this skill whenever you need the exact signature, prop path,
or return type — especially before calling a member you haven't used yet.
Generated from the `.d.ts` of the same `@cesdk/node` package the engine
runs, it is THE source of truth; prose docs can drift.
This skill's entry document carries the WHOLE edit-code API surface inline
— the engine.design facade, the props trees, the attachment unions and the
capability matrix: all edit code needs, in one read.
The sub-file "signatures.d.ts" adds the upstream CE.SDK core as reference
only (edit code never calls it), every vocabulary type flattened to its
literal union.
## Start here: `engine.design` (inside `edit` code)
Edit code uses `engine.design` only — the edit gate refuses every other
engine namespace (block, scene, variable, editor, asset, event) and names the
equivalent. One nested-props dialect, one call per block:
```js
const [scene] = await engine.design.findByType('scene');
const page = await engine.design.create(
{ type: 'page', props: { width: 1080, height: 1920 } },
{ parent: scene } // a page goes into the scene's stack
);
const chip = await engine.design.create(
{
type: 'text',
name: 'chip',
props: {
backgroundColor: {
enabled: true,
color: ACCENT,
paddingLeft: 24,
cornerRadius: 999
}
}
},
{ parent: page }
);
await engine.design.setProps(title, {
opacity: 0.9,
stroke: { enabled: true, width: 2 }
});
const { width } = await engine.design.getProps(page, ['width']);
```
- `create(spec, { parent?, index? })` (await it!) is THE constructor — one
block or a whole subtree, the same spec shape at every level. It folds
create, appendChild and property writes into one call and rolls back on
failure. Returns the root block id.
- A spec node carries exactly `type`, `name`, `props` and `children` (nested,
same shape). Everything else IS props — including the font: naming a
family (`text: { font: { family, weight } }`) makes `create` — and
`setProps` — look the family up in this deployment's typeface sources and
pick that weight's file. Every `engine.design` member returns a Promise:
always `await` it (the edit gate rejects un-awaited calls).
`text: { string, ranges }` (style ranges replayed reshape-safe), inline
`fill: { type, ... }` / `shape` / `blur` / `effects: [...]` / `animations`
specs all sit under `props`. `create` awaits the subtree's font/image loads,
so measuring right after it is safe.
- `name` on any node is written onto the block itself:
`const [chip] = await engine.design.findByName('chip')` resolves it in this edit
and in every later one. Name every block you may touch again.
- No `describe`: identity IS props — `getProps(id)` for everything valued,
`getProps(id, ['type'])` for what a block is, `getCapabilities(idOrType)`
for what it supports. Attachments (fill/shape/blur/effects/animations/
transition) round-trip as `{ type, ...props }` specs through
setProps/getProps — attachment ids never circulate.
- Text is all props too: `setProps(id, { text: { string, font, weight,
case, ranges, path, decoration } })` (a range also takes
`scriptStyle: 'Superscript' | 'Subscript'`) — leaves apply in a safe order and
a string-only write auto-preserves style ranges. Read back via
`getProps(id, ['text.ranges'])` / `['text.paragraphs']`.
- Length props take unit strings: `width: '210mm'`, `fontSize: '32pt'`,
`'50%'` (sets Percent mode too) — converted against the scene's units at
write time. Plain numbers stay engine-native, EXCEPT font sizes
(`text.fontSize`, a range's `size`): a bare number would render ~4.2× too
large, so a unit is required.
- `setProps` validates **every** leaf before touching the scene: a bad leaf
throws listing all bad paths with suggestions, and nothing is applied.
- `getProps(id, ['opacity', 'stroke'])` reads leaves or whole subtrees; an
unknown selector throws — it never answers a typo with `undefined`.
- Attachment state is a discriminated union: assign `{ type, ...props }` to
`fill`/`shape`/`blur`/`effects`/`animations`/`transition`. The type picks
the arm and the arm names every prop it carries. A type MATCHING what is
attached edits it in place; a different type replaces it; `null` detaches
(except `effects`, replaced wholesale — `[]` clears). Reads answer in the
same shape, so `getProps` output feeds straight back in. Tree/layout verbs
live on `engine.design` (group, appendChild, align); saving and exporting
are the `export` tool.
- Document state is on the scene block (`variables`, `spotColors`,
`scene.*`); a new document is `create({ type: 'scene', children })`.
- Video, animation, audio: `playback`, `animations`, `audio` and `track`
props; recipe and traps in `../handbook/video.md`.
- Scalar wrappers (`setOpacity`, …), `is*`/`supports*` predicates and
editor-UI methods are in `signatures-extended.d.ts`, for reference only.
## Reference: `signatures.d.ts`
`signatures.d.ts`: the upstream CE.SDK surface `engine.design`
wraps (~2000 lines) — read it to understand a prop or enum, never to call
it. Types are flattened to their values. Class start lines:
| Class | Start line |
| ------------ | ---------- |
| AssetAPI | 1210 |
| **BlockAPI** | **1515** |
| EditorAPI | 1735 |
| EventAPI | 1872 |
| **SceneAPI** | **1972** |
| VariableAPI | 2189 |
## What is NOT in this file
- **Parameter semantics** — units, value ranges, defaults for optional
parameters. Where a signature says only `r: number`, color components are
in the range 0–1, never 0–255. For anything else a bare `number`/`string`
leaves open, check the handbook's topic page before guessing.
- Recipes by topic → the handbook: `../handbook/print.md` (CMYK,
spot colours, bleed, PDF/X), `../handbook/templates.md` (text
variables, placeholders, locking), `../handbook/video.md` and
`../handbook/animation.md` (timeline, captions, animations).
---
# The edit-code API surface (docs/api/signatures.d.ts)
Everything edit code uses, inline below. The upstream CE.SDK core it wraps is the rest of that file — `signatures.d.ts` — reference only.
```typescript
// ============================================================================
// codesign extension: engine.design — the ONLY API `edit` code uses.
// engine.block/scene/variable/editor/asset/event are refused by the edit
// gate, which names the engine.design equivalent; the upstream classes after
// this section are reference only. One nested-props dialect replaces the
// typed accessors (setFloat/getBool/…), the per-property wrappers
// (setOpacity, setStrokeWidth, setPositionX, …) and the is*-state reads.
// Scene-wide state (variables, spotColors, scene.*) lives on the scene block.
//
// Attachment state (fill/shape/blur/effects/animations/transition) is the
// typed unions below — assign { type, ...props } specs via setProps.
//
// Units (lengths, paddings, stroke.width, shadows, margins): see the api
// skill; '50%' also sets '<leaf>Mode' to 'Percent'. letterSpacing is a FACTOR, never a length. lineHeight: write { visual: n }
// (CSS-style x fontSize — the facade converts per font); a bare number is the
// ENGINE scale (x the font's contentArea) and renders looser than it reads.
// Text glyph color is per-character: fill.solid.color on a text block is
// REJECTED — write setProps(id, { text: { color } }) instead.
// ============================================================================
// Branded attachment ids — nominal guidance (runtime dispatch enforces the
// category): a FillId/EffectId/... is where the matching attachment props
// tree applies, never BlockProps.
// Durable identity: every id parameter also accepts the block's UUID string
// (read it via getProps(id, ['uuid']) or a tree read) — the identity that
// persists in the scene file and crosses edits/revisions. An unknown uuid
// throws "not in this revision"; a stale numeric handle can't be caught.
type BlockRef = DesignBlockId | string /* uuid */;
// One node of the document read as a tree; feed a (subset of a) node tree
// back to setProps to patch every node by uuid.
interface PropsNode { uuid: string; name?: string; type: string; props: BlockProps; children: PropsNode[] }
type FillId = DesignBlockId & { readonly __kind?: 'fill' };
type EffectId = DesignBlockId & { readonly __kind?: 'effect' };
type BlurId = DesignBlockId & { readonly __kind?: 'blur' };
type ShapeId = DesignBlockId & { readonly __kind?: 'shape' };
type AnimationId = DesignBlockId & { readonly __kind?: 'animation' };
interface DesignApi {
/** EVERY member returns a Promise — always: await engine.design.x(...)
* (a floating rejection fails the edit at commit). */
/** THE constructor: one block or a whole subtree, same spec shape at
* every level. Looks up any font: { family, weight }, applies props,
* attaches to the parent, and awaits the subtree's font/image loads
* before returning, so measure() is truthful immediately. Rolls the
* WHOLE subtree back on failure. Name the nodes you will touch again:
* the name lands on the block and findByName resolves it later.
* A NEW document: create({ type: 'scene', props: { scene: { mode?:
* 'Video', layout?, designUnit? }, variables?, spotColors? }, children:
* [pages] }) replaces the current scene; a page whose parent is the
* scene goes into its stack. */
create(spec: BuildSpec, opts?: { parent?: BlockRef; index?: number }): Promise<DesignBlockId>;
/** Partial deep-merge write. Brand-dispatched: pass a FILL/EFFECT/BLUR/
* SHAPE/ANIMATION block id and the matching attachment props tree
* (effect/*, fill/*, … paths as nested keys) applies instead.
* Given a PropsNode TREE (a node with uuid+props or children) it
* patches every node by uuid — read the tree, transform it in JS,
* write it back. Patch-only: an absent block/prop is untouched, never
* deleted; uuids resolve for the whole tree before anything applies. */
setProps(id: BlockRef, props: BlockProps | PropsNode): Promise<void>;
/** Read leaves or whole subtrees — getProps(id, ['opacity', 'stroke']) —
* or omit select for EVERY applicable prop of this block, valued.
* { children: true, props?: [...] } reads the whole SUBTREE as one
* uuid-keyed PropsNode tree — filter it with plain JS (a selector a
* block kind lacks is skipped for that block). The snapshot never
* enters your reply unless you print it. */
getProps(id: BlockRef, select?: string[] | { children: true; props?: string[] }): Promise<BlockProps>;
/** Editor settings, same dialect. */
setSettings(props: SettingsProps): Promise<void>;
getSettings(select?: string[]): Promise<SettingsProps>;
// text.path is raw-or-spec like every attachment: a raw SVG string, or
// { shape: 'circle', diameter, align?: 'top' | 'bottom' | 0..1 } — the
// spec authors the circle, measures the flat glyph run, centers the
// offset and sets the D×D frame (align: 'bottom' = upright underside).
// No describe: identity IS props. getProps(id, ['type']) names the block,
// getCapabilities answers what it supports, and fill/shape/blur/effects/
// animations round-trip as { type, ...props } specs through
// setProps/getProps — attachment ids never circulate.
/** Editing scopes (what the browser-editor user may change). */
getScopes(id: BlockRef): Promise<Record<Scope, boolean>>;
setScopes(id: BlockRef, scopes: Partial<Record<Scope, boolean>>): Promise<void>;
getCapabilities(idOrType: BlockRef | DesignBlockType): Promise<readonly string[]>;
// Attachment values are the discriminated unions below — the type picks
// the arm, the arm names every prop that type carries. A type MATCHING
// what is attached edits it in place; a different type replaces it
// (replaced attachment blocks are destroyed, no leaks); null detaches:
// await setProps(id, { fill: { type: 'color', color: { value } } })
// await setProps(id, { fill: { enabled: false } }) // no type ⇒ host leaves
// Gradient fills round-trip stops; image fills round-trip sourceSet —
// getProps(id, ['fill']) → tweak → setProps is lossless.
// await setProps(id, { shape: { type: 'rect' } }) · { blur: { type: 'uniform' } }
// await setProps(id, { effects: [{ type: 'duotone_filter', duotone_filter: {…} }] })
// await setProps(id, { animations: { in: { type: 'slide', … } } }) // null detaches
// TEXT is all props too, applied in canonical order (font → string →
// styles → ranges) whatever the key order:
// await setProps(id, { text: { string, font: { typeface }, weight, case,
// listStyle, path, pathOffset, pathFlipped,
// ranges: [{ from, to, color?, weight?, style?, size?, case?, scriptStyle?,
// decoration?, kerning? }] } })
// A string write WITHOUT other text styling auto-preserves existing
// ranges; with styling, ranges reset (pass ranges to keep or ranges: []
// to wipe); font/size/lineHeight writes auto-reshape. Read the per-run
// truth via getProps(id, ['text.ranges']); paragraphs (read-only) carry
// listStyle + listLevel.
// CAPTIONS: page→captionTrack→caption, caption.* as text.*; style+layout TRACK-WIDE
adjustCropToFillFrame(id: BlockRef, minScaleRatio: number): Promise<number>;
// Multi-block layout verbs:
/** Axis-keyed ('Center' is never ambiguous); one call may do both axes. */
align(ids: BlockRef[], alignment: { horizontal?: 'Left' | 'Center' | 'Right'; vertical?: 'Top' | 'Center' | 'Bottom' }): Promise<void>;
GitHub에서 보기