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

@weavix/sdk-core

v0.0.40

Published

Framework-agnostic plugin SDK runtime — host API, event system, UI helpers, and shared storage.

Readme

@weavix/sdk-core

Framework-agnostic plugin SDK runtime — host API, event system, UI helpers, and shared storage.

This package is a base layer. Domain-specific SDK packages (e.g. @weavix/tracker-plugin-sdk) build typed wrappers on top of it. If you are building a Tracker plugin, you likely want that package instead.

Installation

npm install @weavix/sdk-core

Quick start

import { hostApi, uiApi, on } from '@weavix/sdk-core';

// Initialize the bridge (must be called first)
hostApi.init({ autoResize: true });

// Subscribe to host events
on('theme.changed', (theme) => {
  document.body.dataset.theme = theme;
});

// Notify the host that the plugin is ready
await hostApi.notifyReady();

hostApi

Singleton for communicating with the host. Call hostApi.init() before using any other method.

hostApi.init(options)

Initializes the plugin: reads parameters from the URL and sets up the postMessage bridge.

hostApi.init({ autoResize: true });

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | autoResize | boolean | true | Automatically resize the iframe height when content changes |

Call once at plugin startup.

Reading context

const theme    = await hostApi.getTheme();      // 'light' | 'light-hc' | 'dark' | 'dark-hc' | 'system' | undefined
const lang     = await hostApi.getLanguage();    // 'ru' | 'en' | ...
const userId   = await hostApi.getUserId();      // string | undefined
const orgId    = await hostApi.getOrgId();       // string | undefined
const isYateam = await hostApi.getIsYateam();    // boolean
const isOrbita = await hostApi.getIsOrbita();    // boolean
const ctx      = await hostApi.getContext();     // depends on the slot

Synchronous getters (available after init())

const slot        = hostApi.getSlot();         // string — current slot name
const service     = hostApi.getService();      // string — service identifier
const queryParams = hostApi.getQueryParams();  // Record<string, string>
const entityId    = hostApi.getEntityId();     // string | null
const entityMeta  = hostApi.getEntityMeta();   // Record<string, string> | undefined
const ctxLevel    = hostApi.getContextLevel(); // 'basic' | 'full'

Plugin lifecycle

// Notify the host that the plugin is ready to display
await hostApi.notifyReady();

// Explicitly set the container height
await hostApi.updateContentSize({ height: 500 });

// Disable auto-resize
hostApi.disableAutoResize();

// Ask the host to close the plugin
await hostApi.close({ reason: 'done' });

// Block / unblock host-initiated close
await hostApi.preventClose({ prevent: true });

External APIs

Proxy for calling third-party HTTP APIs through the host. Domains are declared in the plugin manifest (permissions.external).

import { hostApi } from '@weavix/sdk-core';

// Check and request credentials via dialog if needed
const { success } = await hostApi.externalApiAuthCheckAndRequest({
  domains: ['api.example.com'],
});
if (!success) return;

// Proxy HTTP request through the host
const { status, body } = await hostApi.externalApiCall({
  url: 'https://api.example.com/v1/items',
  method: 'GET',
});

hostApi.externalApiAuthGetStatus(payload)

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | domains | string[] \| undefined | all plugin domains | Domains to check | | contextType | 'user' \| 'organization' \| undefined | — | Credential context type |

Returns Promise<{ domains: ExternalApiAuthGetStatusDomain[] }>.

hostApi.externalApiAuthRequest(payload)

| Parameter | Type | Description | |-----------|------|-------------| | domains | ExternalApiDomainInfo[] | Domains with optional dialog hints |

ExternalApiDomainInfo:

| Field | Type | Description | |-------|------|-------------| | domain | string | Domain from the manifest | | instructions | string \| { en?: string; ru?: string } | Optional dialog hint |

Returns Promise<{ success: boolean }>. success: false means the user dismissed the dialog or the timeout (~5 minutes) elapsed.

hostApi.externalApiAuthRevoke(payload)

| Parameter | Type | Description | |-----------|------|-------------| | domains | string[] | Domains to revoke (at least one) | | contextType | 'user' \| 'organization' \| undefined | Credential context type |

Returns Promise<{ success: boolean }>.

hostApi.externalApiAuthCheckAndRequest(payload)

Combines getStatus + request for unauthenticated domains only. Parameters are identical to externalApiAuthGetStatus.

Returns Promise<{ success: boolean }>. Returns { success: true } immediately if all domains are already authenticated.

hostApi.externalApiCall(payload)

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | url | string | — | Full request URL (required) | | method | 'GET' \| 'POST' \| 'PUT' \| 'PATCH' \| 'DELETE' | — | HTTP method (required) | | headers | Record<string, string> | — | Additional headers | | body | Record<string, unknown> | — | Request body | | timeoutMs | number | — | Timeout in milliseconds | | contextType | 'user' \| 'organization' \| undefined | — | Credential context |

Returns Promise<{ status: number; headers?: Record<string, string>; body?: Record<string, unknown> }>.

On proxy error, throws PluginActionError with code EXTERNAL_API_CALL_ERROR (1013).


uiApi

Host UI methods: navigation, toast notifications, confirmation dialog.

uiApi.navigate(request)

Opens a path in the host application or an external URL.

import { uiApi } from '@weavix/sdk-core';

await uiApi.navigate({
  path: '/queues/MYQUEUE',
  params: { tab: 'settings' },
  options: { newTab: true },
});

| Field | Type | Description | |-------|------|-------------| | path | string | Path or URL (required) | | params | QueryParams | Query parameters | | options.newTab | boolean | Open in a new tab |

uiApi.toaster.add(options)

Shows a toast notification in the host application.

Permission: Requires "toaster" in permissions.ui of the plugin manifest.

import { uiApi } from '@weavix/sdk-core';

// Simple toast
uiApi.toaster.add({ title: 'Saved', theme: 'success' });

// Toast with action
uiApi.toaster.add({
  title: 'Item deleted',
  theme: 'info',
  content: 'QUEUE-123',
  actions: [
    { label: 'Undo', onClick: () => { /* handle */ } },
  ],
});

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | title | string | — | Toast title (required, max 200 chars) | | name | string | auto | Unique key for deduplication | | theme | 'success' \| 'danger' \| 'warning' \| 'info' | 'info' | Theme | | content | string | — | Body text (max 500 chars) | | autoHiding | number | 5000 | Display time in ms (1000–30000) | | isClosable | boolean | true | Show close button | | actions | ToastAction[] | — | Action buttons (max 2) |

ToastAction:

| Field | Type | Description | |-------|------|-------------| | label | string | Button label (max 50 chars) | | onClick | () => void | Click callback |

Returns Promise<{ name: string }>.

uiApi.confirm.show(options)

Shows a confirmation dialog.

Permission: Requires "confirm" in permissions.ui of the plugin manifest.

import { uiApi } from '@weavix/sdk-core';

const { confirmed } = await uiApi.confirm.show({
  title: 'Delete issue?',
  message: 'This action cannot be undone.',
  textButtonApply: 'Delete',
  textButtonCancel: 'Cancel',
  theme: 'danger',
});

if (confirmed) {
  // perform deletion
}

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | message | string | — | Dialog body text (required) | | title | string | — | Dialog title | | textButtonApply | string | — | Confirm button label | | textButtonCancel | string | — | Cancel button label | | theme | 'normal' \| 'danger' | 'normal' | Confirm button theme |

Returns Promise<{ confirmed: boolean }>. Timeout: 5 minutes.


storageApi

Organisation-level JSON storage. Data is shared across all plugin users in the organisation; write permission is determined by the host via the canWrite field in the response.

Currently the only available context is storageApi.orgShared.

storageApi.orgShared.get(bucket?)

import { storageApi } from '@weavix/sdk-core';

const record = await storageApi.orgShared.get('settings');
// record: StorageRecord | null
// { key, version, data, canWrite, createdAt, updatedAt }

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | bucket | string \| undefined | 'default' (set by host) | Record key |

Returns Promise<StorageRecord | null>.

storageApi.orgShared.patch(options)

Merge-patch: fields from data are merged onto the current record. A null value deletes the key. Returns the full merged StorageRecord with the new version.

// Create a record
await storageApi.orgShared.patch({
  bucket: 'settings',
  data: { theme: 'dark', notifications: true },
  version: 0,
});

// Update without explicit version — SDK resolves conflicts automatically
await storageApi.orgShared.patch({
  bucket: 'settings',
  data: { count: 42 },
});

// Delete a field — pass null
await storageApi.orgShared.patch({
  bucket: 'settings',
  data: { theme: null },
});

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | bucket | string | 'default' (set by host) | Record key | | data | Record<string, unknown> | — | Merge-doc; null deletes a field | | version | number \| undefined | auto-resolve | Expected current version |

Versioning modes:

  • With explicit version — single request; VERSION_CONFLICT is thrown to the caller. Pass version: 0 to create a new record.
  • Without version — SDK reads the current version via get, then patches. Retries up to 2 times on VERSION_CONFLICT. Worst case: 6 round-trips.

Storage types

import type {
  StorageContextType, // 'orgShared'
  StorageRecord,      // { key, version, data, canWrite, createdAt, updatedAt }
} from '@weavix/sdk-core';

Events

The host can push events to the plugin. Subscribe via on() or eventBus.on().

Last-value cache: if an event was already dispatched before a subscription, the callback is invoked synchronously with the cached value at subscription time.

on(method, callback)

import { on } from '@weavix/sdk-core';

const unsubscribe = on('theme.changed', (theme) => {
  console.log('Theme:', theme);
});

// Unsubscribe
unsubscribe();

eventBus.on(method, callback)

import { eventBus } from '@weavix/sdk-core';

const unsubscribe = eventBus.on('language.changed', (lang) => {
  console.log('Language:', lang);
});

Supported events

| Method | Payload type | Description | |--------|-------------|-------------| | theme.changed | Theme | Host theme changed | | language.changed | string | Host language changed | | userId.changed | string | User ID changed | | orgId.changed | string | Organisation ID changed | | isYateam.changed | boolean | Yandex-Team flag changed | | isOrbita.changed | boolean | Orbita flag changed | | context.changed | Record<string, unknown> | Slot context changed | | toast.action.clicked | { name: string; actionId: string } | Toast action button clicked |


Utilities

getLocalizedString(value, language?)

Resolves a LocalizedString (a plain string or { ru, en, ... } object) for the given language.

import { getLocalizedString } from '@weavix/sdk-core';

const label = getLocalizedString({ ru: 'Задача', en: 'Issue' }, 'en'); // 'Issue'
const plain = getLocalizedString('plain string', 'en');                // 'plain string'

getField(obj, path)

Safely reads a nested field of an object by dot-separated path.

import { getField } from '@weavix/sdk-core';

const value = getField({ a: { b: 42 } }, 'a.b'); // 42

Error handling

All SDK method errors are instances of PluginActionError with a numeric error code.

import { PluginActionError, VERSION_CONFLICT } from '@weavix/sdk-core';

try {
  await storageApi.orgShared.patch({ bucket: 'cfg', data: { x: 1 }, version: 0 });
} catch (e) {
  if (e instanceof PluginActionError) {
    console.log(e.code, e.message, e.errorData);
  }
}

Error codes

| Code | Constant | When | |------|----------|------| | 1002 | VALIDATION_ERROR | Request data failed validation | | 1003 | METHOD_NOT_SUPPORTED | Method not supported in this configuration | | 1004 | MISSING_REQUIRED_SCOPE | Plugin lacks the required permission scope | | 1005 | CONTEXT_ERROR | Failed to fetch or parse slot context | | 1007 | RATE_LIMIT_EXCEEDED | Request rate limit exceeded | | 1008 | CONFIRM_ALREADY_OPEN | A confirmation dialog is already open | | 1010 | VERSION_CONFLICT | Storage record version mismatch | | 1011 | DATA_TOO_LARGE | Data exceeds 256 KiB | | 1012 | BAD_KEY | Bucket key failed validation | | 1013 | EXTERNAL_API_CALL_ERROR | External API proxy call failed |


Related packages

| Package | Purpose | |---------|---------| | @weavix/sdk-react | React wrapper: PluginProvider, hooks | | @weavix/tracker-plugin-sdk | Typed wrapper for Tracker plugins (recommended) | | @weavix/tracker-plugin-sdk-react | React integration for Tracker plugins | | @weavix/tracker-api-types | Tracker Public API v3 types |

License

SEE LICENSE IN LICENSE