@obieg-zero/sdk
v0.5.1
Published
Plugin SDK for Obieg Zero — types, UI components, store/plugin contracts
Downloads
988
Readme
@obieg-zero/sdk
Plugin SDK for Obieg Zero — browser-native document flow engine.
Plugin contract
A plugin is a function that receives { React, store, sdk, ui, icons } and returns { id, label, icon }.
Plugins run in a sandbox — no fetch, no import(), no direct DOM. All data goes through store, all UI through ui.
import type { PluginFactory } from '@obieg-zero/sdk'
const plugin: PluginFactory = ({ store, sdk, ui, icons }) => {
store.registerType('task', [
{ key: 'title', label: 'Tytuł', required: true },
{ key: 'done', label: 'Gotowe' },
], 'Zadania')
function Center() {
const tasks = store.usePosts('task')
return <ui.Page><ui.Stack>
{tasks.map(t => <ui.ListItem key={t.id} label={t.data.title}
action={<ui.RemoveButton onClick={() => store.remove(t.id)} />} />)}
<ui.Button onClick={() => store.add('task', { title: 'Nowe', done: false })}>+ Dodaj</ui.Button>
</ui.Stack></ui.Page>
}
sdk.registerView('tasks.center', { slot: 'center', component: Center })
return { id: 'tasks', label: 'Zadania', icon: icons.CheckSquare }
}
export default pluginstore — data (Zustand + IndexedDB)
| Method | Description |
|--------|-------------|
| add(type, data, opts?) | Create record. Returns PostRecord. opts: { id?, parentId? } |
| get(id) | Get record by ID (sync) |
| update(id, data) | Merge data into record |
| remove(id) | Delete record + children (cascade) |
| usePost(id) | React hook — single record by ID |
| usePosts(type) | React hook — all records of type, sorted by createdAt |
| useChildren(parentId, type?) | React hook — children of a record |
| getPosts(type) | Sync query (for factory/callbacks, not components) |
| registerType(type, schema, label?, opts?) | Register type with schema. opts: { strict?: boolean } |
| setOption(key, value) | Persistent key-value config |
| useOption(key) | React hook — read option |
| importJSON(nodes) | Bulk import [{ type, data, children? }] |
| writeFile(postId, name, data) | Attach file (OPFS) |
| readFile(postId, name) | Read attached file |
Store przechowuje dane aplikacji. Stan pluginów (specs, labels, licencja) jest w OPFS — patrz SDK plugin management.
PostRecord
{ id: string, type: string, parentId: string | null, data: Record<string, any>, createdAt: number, updatedAt: number }Parent-child: set parentId via opts.parentId in add(). Query children with useChildren(parentId). remove() cascades to children.
sdk — host services
| Method | Description |
|--------|-------------|
| registerView(id, { slot, component }) | Register UI in slot: left, center, right, footer |
| registerParser(id, { accept, targetType, parse }) | Register file parser (e.g. CSV → records) |
| registerAction(id, { node }) | Register toolbar action |
| uploadFile(parentId) | Open file dialog, create event, store in OPFS |
| downloadFile(postId, filename) | Download attached file |
| shared | Zustand store shared between plugins. shared(s => s.x), shared.setState({x}) |
| create(initializer) | Create plugin-scoped Zustand store |
| useForm(defaults, opts?) | Form state helper with validation |
| log(text, level?) | Write to host log panel |
| installPlugin(spec, label?) | Install plugin + persist to OPFS |
| uninstallPlugin(spec) | Uninstall plugin + remove from OPFS |
| getInstalledPlugins() | List installed plugins [{ spec, label }] |
| setStoreAuth(auth) | Set store license (persisted to OPFS) |
| getStoreAuth() | Get current store license |
ui — components (props only, no className)
Layout: Stack Row Page Box Stage StageLayout
Nav: Tabs Cell
Form: Button Input Select Field
Data: Text Value Badge Heading StepHeading Card Stats Stat Table ListItem CheckItem
Actions: Placeholder Spinner FileAction RemoveButton Divider
Security
Sandbox: Plugins run as ES modules evaluated via blob URL. They have no access to fetch, import(), localStorage, or raw DOM (className). All I/O goes through store (data) and ui (rendering).
Integrity (SRI): config.json supports integrity field per plugin — deployer pins SHA-256 hash, loader verifies on every fetch. Use tagged versions (@vX.Y.Z) in production — they are immutable on GitHub and cached in OPFS.
Store plugins (store://): Served via authenticated Cloudflare Worker from private GitHub repos. License key required for paid plugins.
Plugin persistence (OPFS): Installed plugins, labels, and license are stored in OPFS meta.json — survives IndexedDB/localStorage clearing. Plugin code is cached in OPFS for offline use.
icons
All react-feather icons: icons.Briefcase, icons.DollarSign, icons.Upload, etc.
Slots
A plugin with a center view appears in the navigation. All slots of the active plugin are rendered.
┌──────────┬──────────────────────┬──────────┐
│ left │ center │ right │
│ │ │ │
├──────────┴──────────────────────┴──────────┤
│ footer │
└─────────────────────────────────────────────┘