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

@sailpoint/ui-plugin-sdk

v0.0.2

Published

Browser runtime library for SailPoint ISC UI plugins

Readme

@sailpoint/ui-plugin-sdk

Browser runtime library for SailPoint ISC UI plugins — COIP/iframe handshake and plugin integration.

Getting Started

Prerequisites

Setup

pnpm install

Usage

When the plugin is mounted inside ISC, the SDK resolves the App Shell origin from the iframe context:

import { createSDK } from '@sailpoint/ui-plugin-sdk';

const sdk = createSDK();
const context = await sdk.getContext();

The SDK reconciles the App Shell-provided parentOrigin query parameter with the browser ancestor origin when available, then falls back to the document referrer. It throws if no trusted origin can be resolved or if the query and browser ancestor origins disagree.

This resolution is defense-in-depth for consistent postMessage targeting and inbound origin validation. A plugin's frame-ancestors CSP remains the primary control that prevents untrusted pages from embedding it.

Pass targetOrigin explicitly for tests, mocks, or non-standard embeddings:

const sdk = createSDK({ targetOrigin: 'https://app-shell.example.com' });

Handling API Errors

Non-OK responses from api.get and api.post throw ApiError, which exposes the HTTP status, status text, request path, and response body. JSON bodies are parsed; non-JSON bodies remain strings, and empty or unreadable bodies are null.

import { ApiError, createSDK } from '@sailpoint/ui-plugin-sdk';

const sdk = createSDK();

try {
	await sdk.api.get('/v3/accounts/missing');
} catch (error) {
	if (error instanceof ApiError) {
		handleRequestFailure(error.status, error.body);
	} else {
		throw error;
	}
}

Treat body as untrusted API data and avoid logging it without reviewing it for sensitive content.

Commands

| Command | Description | |---------|-------------| | pnpm run build | Compile TypeScript to dist/ | | pnpm run lint | Run ESLint | | pnpm run lint:fix | Run ESLint with auto-fix | | pnpm run format | Format code with Prettier | | pnpm run format:check | Check formatting without writing | | pnpm run test | Run Jest tests | | pnpm run typecheck | TypeScript type checking (no emit) |

Testing Plugins Offline

The @sailpoint/ui-plugin-sdk/testing subpath provides a framework-agnostic mock App Shell for browser-like unit-test environments. Install the mock before calling an SDK method that starts the handshake, then restore it after the test.

context is optional — the default models a valid least-privileged user, so pass it only when the test depends on specific tenant or capability values.

import { createSDK } from '@sailpoint/ui-plugin-sdk';
import type { UserCapabilities } from '@sailpoint/ui-plugin-sdk';
import { mockSdkContext } from '@sailpoint/ui-plugin-sdk/testing';

/**
 * Capability flags are exhaustive: App Shell always sends every key, so a mock
 * context must too. Start from all-false and enable what the test needs.
 */
const capabilities: UserCapabilities = {
	isOrgAdmin: true,
	isHelpdesk: false,
	isDashboard: false,
	isCertAdmin: false,
	isReportAdmin: false,
	isSourceAdmin: false,
	isSourceSubadmin: false,
	isRoleAdmin: false,
	isRoleSubadmin: false,
	isCloudGovAdmin: false,
	isCloudGovUser: false,
	isSaasManagementAdmin: false,
	isSaasManagementReader: false
};

const appShell = mockSdkContext({
	context: {
		tenant: {
			id: 'tenant-1',
			scriptName: 'acme',
			org: 'acme',
			name: 'Acme',
			pod: 'useast1',
			region: 'us-east-1',
			apiUrl: { idn: 'https://acme.api.identitynow.com' },
			products: []
		},
		user: { id: 'user-1', displayName: 'Test User', email: '[email protected]', capabilities },
		page: { route: 'https://acme.identitynow.com/plugins/example' },
		slot: { id: 'slot-1' },
		pluginConfiguration: { pluginId: 'plugin-1' }
	}
});
const sdk = createSDK({ targetOrigin: appShell.targetOrigin });

expect(await sdk.getContext()).toEqual(appShell.context);

const onViewportChange = jest.fn();
sdk.events.onViewportChange(onViewportChange);
appShell.emitViewportChange({ width: 1280, height: 720 });

expect(onViewportChange).toHaveBeenCalledWith({ width: 1280, height: 720 });
appShell.restore();

The mock also supports emitTokenUpdate(), responds to forced token refreshes, and exposes recorded outbound messages for protocol assertions. It has no dependency on Jest, Vitest, or another test framework.

Contributing

Contributions are welcome. See CONTRIBUTING.md for how to report issues, propose changes, and run the project locally.

License

MIT

Code of Conduct

This project follows the Contributor Covenant. Please read it before participating in issues, pull requests, or discussions.