npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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 plugin

store — 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                     │
└─────────────────────────────────────────────┘