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

@enforly/sdk

v0.3.0

Published

Server-side JavaScript and TypeScript client for the Enforly guardrails API

Readme

@enforly/sdk

Server-side JavaScript and TypeScript client for the Enforly guardrails API. Use it before executing an action that a policy may restrict.

Install

Requires Node.js 20 or newer and an Enforly API key. Create a key in the Enforly console, then set it as ENFORLY_API_KEY in your server environment. Keep the key on your server; do not put it in browser code or a public environment variable.

npm install @enforly/sdk
import { Enforly } from '@enforly/sdk'

const guard = new Enforly({ apiKey: process.env.ENFORLY_API_KEY })

The default API origin is https://api.enforly.com. Set baseUrl in the constructor if your API runs at another origin.

Check an action

Pass exactly one of policy, policyId, or policyIds. Put the action and any evidence needed to judge it in the single JSON data field.

const result = await guard.check({
  policy: 'Never run destructive database operations without explicit confirmation.',
  data: {
    action: { tool: 'database.execute_sql', query: 'DROP TABLE customers' },
    userConfirmed: false,
  },
})

if (result.allowed) {
  // Execute the checked action here.
} else {
  // Stop the action. A review decision needs a human or more evidence.
}

Use a saved policy ID to evaluate its active version (set in the dashboard or with policies.activate):

const result = await guard.check({
  policyId: '70fa6222-b16b-48b8-a137-c6f278503a91',
  data: { tool: 'database.execute_sql', query: 'SELECT count(*) FROM customers' },
})

Evaluate distinct saved policies in one request. The maximum depends on the tenant's plan (Free: 10, Basic: 25, Pro: 50 by default):

const result = await guard.check({
  policyIds: [
    '70fa6222-b16b-48b8-a137-c6f278503a91',
    '00000000-0000-4000-8000-000000000001',
  ],
  data: { tool: 'database.execute_sql', query: 'DROP TABLE customers' },
})

console.log(result.decision, result.allowed, result.results)

Pin an exact version so a later edit or preset update cannot change the check. A version that does not exist fails with POLICY_VERSION_NOT_FOUND:

await guard.check({ policyId: '70fa6222-b16b-48b8-a137-c6f278503a91', policyVersion: 3, data })
await guard.check({
  policyIds: [{ id: '70fa6222-b16b-48b8-a137-c6f278503a91', version: 3 }, '00000000-0000-4000-8000-000000000001'],
  data,
})

Single-policy results include decision, allowed, violationProbability, reviewProbability, policyId, policyVersion, and requestId. Multi-policy results include the overall decision, allowed, results (one decision and both probabilities per policy), and requestId. decision is allow, deny, or review. review means a person should decide: either the policy hands this case to a person (for example "refunds above 200 USD need manager approval") and that approval is missing from data, or the evidence is not clear enough to allow or deny. allowed is true only for allow; a model probability is an estimate, not proof. If any policy denies, the overall decision denies; otherwise any review makes the overall decision review.

Manage saved policies

const { policies } = await guard.policies.list()
const { id } = await guard.policies.create({
  slug: 'database-safety',
  title: 'Database safety',
  body: 'Never run destructive database operations without explicit confirmation.',
})
const { policy } = await guard.policies.get(id)
const { version } = await guard.policies.update(id, {
  body: 'Never run destructive database operations without explicit confirmation from the user.',
})
await guard.policies.activate(id, 1) // Roll back: unpinned checks use version 1 again.
await guard.policies.delete(id) // Deactivates the policy: { id, deactivated: true, requestId }.

Updates create a new immutable version and make it active. In the dashboard you can also save a rule change as a draft and activate it later, or rename a policy without creating a version (checks never read the title). After delete, checks that use the ID fail with POLICY_NOT_FOUND; the dashboard keeps the policy listed read-only with its versions. version in listing and detail results is the active version and latest_version the newest; a preset stays on the version current when your workspace was created until you activate a newer one. The API returns policy listing and detail fields in snake_case, such as tenant_id and created_at. A key can read platform policies and policies owned by its tenant; only its own policies can be changed.

Handle errors safely

HTTP errors, network failures, timeouts, and invalid responses reject the call. Do not execute the checked action when a call throws.

import { EnforlyError } from '@enforly/sdk'

try {
  const action = { tool: 'database.execute_sql', query: 'SELECT 1' }
  const result = await guard.check({ policy: 'Do not delete data.', data: action })
  if (result.allowed) {
    // Execute the action here.
  } else {
    console.log('Action stopped:', result.decision)
  }
} catch (error) {
  if (error instanceof EnforlyError) {
    console.error(error.code, error.status, error.requestId)
  }
  // Stop the action and surface the failure to your application.
}

EnforlyError has code, status (HTTP status or null), and requestId (when available). Authentication, validation, missing-policy, rate-limit, context-limit, and service errors retain the API's error code. A request that exceeds 32,768 characters in the complete Jev payload returns 413 CONTEXT_LIMIT_EXCEEDED without consuming a monthly check. The client uses a 30-second timeout by default; change it with new Enforly({ apiKey, timeoutMs: 45000 }).