5 KiB
5 KiB
@open-pencil/fig package plan
@open-pencil/fig is the next package-split stage after @open-pencil/kiwi. It should own .fig document policy while @open-pencil/kiwi remains a pure low-level Kiwi/schema/container package and @open-pencil/core remains the editable SceneGraph/editor package.
Package boundary
| Package | Owns | Must not own |
|---|---|---|
@open-pencil/kiwi |
Kiwi schema runtime, Figma Kiwi protocol/schema data, low-level codec, FIG Kiwi containers, GUID helpers, raw parse helpers | SceneGraph conversion, Figma compatibility policy, raw metadata invalidation |
@open-pencil/fig |
.fig read/write orchestration, raw metadata preservation/invalidation policy, SceneGraph ⇄ NodeChange conversion, component/instance interpretation, fixture/oracle helpers |
Editor actions, Vue/app UI, CLI formatting, MCP transport |
@open-pencil/core |
SceneGraph data model, renderer, layout, editor actions, tools | Low-level Kiwi codec internals once @open-pencil/fig owns .fig policy |
Initial public API sketch
import { readFig, writeFig } from '@open-pencil/fig'
const document = await readFig(bytes, { preserveRawMetadata: true })
const nextBytes = await writeFig(document.graph, { source: document.source })
Potential subpaths:
@open-pencil/fig— high-level.figread/write API@open-pencil/fig/node-change— SceneGraph ⇄ NodeChange conversion helpers@open-pencil/fig/metadata— raw metadata protection/invalidation helpers@open-pencil/fig/instances— component/instance interpretation helpers@open-pencil/fig/oracles— test-only oracle fixture helpers if they prove reusable outside core tests
Do not expose low-level Kiwi codec names from @open-pencil/fig; consumers that need raw codec access should use @open-pencil/kiwi/fig/* directly.
Migration inventory
Candidate code currently in @open-pencil/core:
packages/core/src/io/formats/fig/**packages/core/src/kiwi/fig/import.tspackages/core/src/kiwi/fig/lazy-import.tspackages/core/src/kiwi/fig/node-change/**packages/core/src/kiwi/fig/instance-overrides/**packages/core/src/kiwi/fig/parse/worker.tspackages/core/src/kiwi/fig/parse/transfer.ts
Keep these in core until the new package has package-local tests and published-style smoke coverage. Do not move editor-specific operations, renderer code, or app document stores.
Milestones
1. Define package shell
- Add
packages/fig/package.json,tsconfig.json,tsdown.config.ts, package-local tests, andREADME.md. - Depend on
@open-pencil/corefor SceneGraph types and@open-pencil/kiwifor low-level FIG/Kiwi helpers. - Add package metadata checks and tarball smoke imports before moving behavior.
2. Move pure .fig orchestration helpers
- Move read/write orchestration wrappers that do not depend on app/editor state.
- Preserve current core public exports with thin compatibility barrels only where public API stability requires them.
- Avoid deep compatibility shims for private paths.
3. Move NodeChange conversion policy
- Move SceneGraph ⇄ NodeChange conversion modules with tests covering:
- text styles and glyph metadata
- boolean operation
EXCLUDE⇄ KiwiXOR - fills/strokes/effects raw field preservation
- masks and component metadata
- variable bindings and style refs
4. Move raw metadata invalidation/protection
- Centralize source metadata invalidation rules in
@open-pencil/fig. - Keep tests that mutate SceneGraph fields and verify stale raw fields are invalidated.
- Preserve real Figma/oracle evidence in fixtures rather than guessing schema fields.
5. Move instance/component interpretation
- Move component props, derived symbol data, instance override resolution, and sync helpers once NodeChange conversion is stable.
- Keep package-local fixtures for component sets, variants, nested instances, and override propagation.
6. Rewire core consumers
- Make core import
.figpolicy through public@open-pencil/figexports. - Keep app, CLI, and MCP consuming core-level document APIs unless a direct
@open-pencil/figimport is clearly better. - Run architecture checks to ensure package boundaries stay acyclic.
Tests and smoke coverage
Each milestone should keep these passing:
bun run check
bun scripts/smoke-packages.ts
bun test packages/fig/tests
bun test tests/engine/io/fig
bun test tests/engine/kiwi
The smoke script should eventually cover:
await import('@open-pencil/fig')await import('@open-pencil/fig/node-change')- a minimal
.figread/write round trip through packed packages
Non-goals
- Do not move browser/app file picker logic into
@open-pencil/fig. - Do not move renderer behavior or visual comparison scripts into
@open-pencil/figunless they become package-local test utilities. - Do not guess unsupported Figma schema fields. Use Figma/oracle payloads first.
- Do not merge
@open-pencil/figand@open-pencil/kiwi; the low-level codec package must remain SceneGraph-agnostic.