Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Define a schema from TypeScript

Prerequisites

@panproto/core installed (Install the TypeScript SDK).

The task

import { Panproto } from '@panproto/core';

const p = await Panproto.init();
const proto = p.protocol('atproto');

const schema = proto.schema()
  .vertex('post', 'record', { nsid: 'app.bsky.feed.post' })
  .vertex('post:body', 'object')
  .vertex('post:body.text', 'string')
  .edge('post', 'post:body', 'record-schema')
  .edge('post:body', 'post:body.text', 'prop', { name: 'text' })
  .build();

p.protocol(name) loads the named protocol. proto.schema() returns an immutable SchemaBuilder: each operation returns a new builder containing the added structure. .build() sends those operations to WebAssembly, where vertex and edge rules are checked, and returns a BuiltSchema handle. Run the separate validation pass below to check constraint sorts and other finished-schema conditions.

Verification

const result = schema.validate(proto);
if (!result.isValid) throw new Error(JSON.stringify(result.issues));

validate(protocol) returns a ValidationResult containing any issues. An empty issue list confirms the schema satisfies the protocol’s edge rules and obj-kinds.

Common mistakes

  • Ignoring the builder returned by .vertex() or .edge(). Builders are immutable, so the original value does not acquire the operation.
  • Treating .build() as equation verification. It constructs a schema and enforces builder-level checks; schema.validate(proto) is the finished-schema structural validation pass.
  • Treating the returned Schema handle as a plain object. It is an opaque handle into the WASM heap; pass it to subsequent SDK calls, do not introspect it directly.

See also