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

@customyai/openfeature-provider

v0.1.10

Published

OpenFeature provider for Customy Experiments: server and web, with local evaluation over the Access flags snapshot or remote evaluation (POST /v1/flags/evaluate), change events, track() to conversions and exposure reporting.

Readme

@customyai/openfeature-provider

Proveedor de OpenFeature para Customy Experiments, para servidor (@openfeature/server-sdk) y navegador (@openfeature/web-sdk). Sobre @customyai/access.

npm install @customyai/openfeature-provider @openfeature/server-sdk

Servidor

import { OpenFeature } from "@openfeature/server-sdk";
import { CustomyServerProvider } from "@customyai/openfeature-provider";

await OpenFeature.setProviderAndWait(new CustomyServerProvider({
  clientOptions: { accessToken: process.env.CUSTOMY_TOKEN! }, // token de máquina con flags:read
  realtimeUrl: "https://realtime.customy.ai",                 // cambios y kill switch en vivo
}));

const flags = OpenFeature.getClient();
const on = await flags.getBooleanValue("checkout.v2", false, { targetingKey: user.id, plan: "pro" });
flags.track("purchase", { targetingKey: user.id }, { value: 49.9, eventId: order.id });

Navegador

import { OpenFeature } from "@openfeature/web-sdk";
import { CustomyWebProvider } from "@customyai/openfeature-provider/web";

await OpenFeature.setContext({ targetingKey: visitorId });
await OpenFeature.setProviderAndWait(new CustomyWebProvider({ clientOptions: { publishableKey }, pollIntervalMs: 30_000 }));

Dos modos

| Modo | Cómo evalúa | Para quién | |---|---|---| | local (por defecto) | La instantánea publicada se evalúa en el proceso con el cliente de @customyai/access/flags (ETag/304, firma, realtime). Sin red por evaluación. | Node, navegador. | | remote ({ mode: "remote", baseUrl, publishableKey \| accessToken }) | POST /v1/flags/evaluate en Customy Experiments, con el mismo motor. Exposiciones y conversiones por /v1/flags/impressions y /conversions. | Quien no puede evaluar localmente. En web precarga todos los flags del contexto y sirve de esa copia. |

Se puede inyectar un cliente propio (client) para compartir la instantánea con el resto de la app.

Contrato de razones

El proveedor traduce el reasonCode del evaluador (el mismo en todos los SDK) al spec de OpenFeature; el original queda en flagMetadata.reasonCode.

| reasonCode | reason OpenFeature | |---|---| | default, prerequisite_failed | DEFAULT | | rule:<id>, segment:<key> | TARGETING_MATCH (flagMetadata.ruleId) | | rollout | SPLIT (flagMetadata.bucketBp, 0..9999) | | off, killed | DISABLED | | error | ERROR + errorCode (FLAG_NOT_FOUND, PROVIDER_NOT_READY, TARGETING_KEY_MISSING, GENERAL) |

variant es la clave del tratamiento. Un valor que no es del tipo pedido da TYPE_MISMATCH y el valor por defecto del código. Nunca lanza ni bloquea: ante cualquier fallo devuelve el valor por defecto con reason: ERROR.

Eventos

  • PROVIDER_CONFIGURATION_CHANGED con flagsChanged cuando llega una versión nueva (realtime o sondeo).
  • PROVIDER_STALE si falla refrescar con una instantánea en mano (se sigue sirviendo la última); PROVIDER_READY al volver.
  • PROVIDER_ERROR si la evaluación remota falla (una vez por racha); PROVIDER_READY al recuperarse.

track() y exposición

La exposición se registra con un hook after cuando el valor se entregó de verdad (una por flag, unidad y hora). track(nombre, contexto, { value, eventId, flagKey? }) registra una conversión de métrica nombre en los flags que esa unidad ha visto (o en flagKey/flagKeys); eventId hace idempotente un reintento.

Contexto

targetingKey es la clave de la unidad (obligatoria: sin ella el evaluador responde missing_context_key ⇒ TARGETING_KEY_MISSING). El resto son atributos para segmentar; los objetos se aplanan con punto (account.tier) y las fechas van en ISO 8601.

Otros lenguajes

Go, Python, Java, .NET y Ruby usan el proveedor OpenFeature de su lenguaje contra POST /v1/flags/evaluate (cuerpo { context: { key, attributes }, flagKey? | flags? }, cabecera x-publishable-key o Authorization: Bearer).