@pylonsync/sdk is the foundation every other JS package depends on. It’s two things in one package:
- A schema DSL for declaring entities, queries, actions, policies in TypeScript instead of editing
pylon.manifest.jsonby hand. - The codegen runtime that compiles your TS schema into the manifest the Pylon server reads.
@pylonsync/react (browser) or @pylonsync/sync (any JS host).
Install
Defining your schema
Createapp.ts:
field helper (field.string(), field.int(), field.id("User"), …) and refined with chained modifiers (.unique(), .optional(), .default(v), .defaultNow(), .owner(), .serverOnly(), .crdt(...)). query / action register a name plus a typed input list; the handler itself lives in a functions/*.ts file (see Actions).
Then run codegen to materialize the manifest:
pylon dev does this automatically on file change.
Field types
Modifiers are chained methods, not option objects:
.crdt(annotation):
"text" and "counter" are wired end-to-end; the "list", "movable-list", and "tree" annotations are reserved (wire format locked in, server-side projection still landing). CRDT-backed fields don’t go through normal LWW merge; they sync via the binary CRDT broadcast channel. See Loro for the full picture.
Indexes
Search config
search plugin. Once enabled, the entity is queryable via POST /api/search/Post.
Relations
include joins on queries. On the client, request them through the query’s include map (an object keyed by relation name):
Queries
Named, typed query inputs. Eachinput entry is { name, type, optional? }, where type is a field-type string ("string", "int", `id(User)`, …). Resolve to /api/query/<name>:
query / action register the name + input contract; the handler lives in a functions/<name>.ts file. Use a query() handler for reads and a mutation() / action() handler for writes and computed results.
Actions
Server-side functions with typed args. Resolve to/api/fn/<name>:
functions/completeTodo.ts) and the function runtime wires it up:
Policies
allowRead, allowInsert, allowUpdate, allowDelete. allowWrite is a shared fallback for the three write ops, and allow is the fallback for all four. Expression syntax in RBAC.
Plugins
definePlugin({ name, hooks }) returns a PluginDefinition — a named set of server-side entity lifecycle hooks:
beforeInsert, afterInsert, beforeUpdate, afterUpdate, beforeDelete, afterDelete.
Many capabilities don’t need a plugin at all — they’re declarative: full-text search is an entity’s search: option (above), and auth / scheduled jobs are configured with the auth() / cron() helpers passed to buildManifest.
Manifest output
buildManifest({...}) returns a Manifest object. The codegen step writes it to JSON:
Where to next
- Browser clients →
@pylonsync/react - Mobile →
@pylonsync/react-nativeor Swift - Server-rendered →
@pylonsync/next - Sync engine on its own →
@pylonsync/sync