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

@viu/emporix-sdk

v2.18.0

Published

TypeScript SDK for the Emporix Commerce Engine

Readme

@viu/emporix-sdk

CI npm bundle size

Framework-agnostic TypeScript SDK for the Emporix Commerce Engine. Native fetch only (Node 20.19+), zero runtime dependencies.

Install

pnpm add @viu/emporix-sdk

Quick start

import { EmporixClient, auth } from "@viu/emporix-sdk";

const sdk = new EmporixClient({
  tenant: "mytenant",
  credentials: {
    backend: { clientId: "...", secret: "..." },
    storefront: { clientId: "..." },
    custom: { partner: { clientId: "...", secret: "..." } },
  },
});

// Anonymous browse
const products = await sdk.products.list();

// Authenticated shopper
const { customerToken } = await sdk.customers.login({ email, password });
const ctx = auth.customer(customerToken);
const me = await sdk.customers.me(ctx);
const cart = await sdk.carts.create({ currency: "EUR" }, ctx);
await sdk.carts.addItem(cart.id, { productId: "p_1", quantity: 2 }, ctx);

// Service account with a custom credential set
await sdk.products.list(undefined, auth.service("partner"));

// Externally-issued token (SSO/token-exchange done upstream)
await sdk.customers.me(auth.raw(externalJwt));

Services

The client exposes the full Emporix surface as namespaced services. Each is a property on the EmporixClient instance:

| Area | Services | | --- | --- | | Catalog | products, categories, prices, brands, labels, catalogs | | Cart & checkout | carts, checkout, payments, coupons, taxes, shipping, fees | | Orders & fulfilment | orders, salesOrders, returns, pickPack, availability, indexing | | Customers & B2B | customers, customerAdmin, companies, contacts, locations, customerGroups, approvals, rewardPoints, segments | | Platform & config | sites, sessionContext, tenantConfig, clientConfig, media, schemas, webhooks, sequentialIds, units, countries, currencies, vendors, shoppingLists, sepaExport, ai, ragIndexer |

The sections below highlight the most-used services; per-service guides live in ../../docs/.

Searching by mixin (custom) fields

products.search, categories.search, orders.listMine({ q }), customerAdmin.searchCustomers({ q }) and vendor.searchVendors({ q }) accept a raw Emporix q string or a type-safe filter built with mixinQuery from @viu/emporix-mixins. The filter is entity-gated (a filter built for one entity is a compile error on another) and an or() filter is rejected on services that don't support compoundLogicalQuery.

import { mixinQuery } from "@viu/emporix-mixins";
import { mixins } from "./mixins/generated/registry";

const q = mixinQuery(mixins.attrs, { color: "Blue", qty: { gte: 10 } });
const page = await sdk.products.search(q);

See ../../docs/mixin-search.md for the capability matrix.

Configuration

| Option | Default | Notes | | --- | --- | --- | | tenant (required) | — | lowercase, 3–16 chars, ^[a-z][a-z0-9]+$ | | credentials.backend (required) | — | { clientId, secret, scope? } — service token | | credentials.storefront | — | { clientId } — anonymous token (no secret) | | credentials.custom | — | Record<name, { clientId, secret, scope? }> | | host | https://api.emporix.io | | | timeouts | { connectMs: 10000, readMs: 60000 } | | | retry | { maxAttempts: 3 } | 5xx/429 backoff + jitter for idempotent methods (GET/PUT/DELETE; POST/PATCH opt in via idempotent: true); numeric Retry-After honoured, capped at 8s | | cache | { expirationBufferSeconds: 60, maxLifetimeSeconds: 3600 } | token cache | | logger | console @ warn | false, a Logger, or { level, services, pretty, redact } | | tokenProvider | built-in | inject for SSO/token-exchange |

AuthContext per method

auth.service(name?), auth.anonymous(), auth.customer(token), auth.raw(token). The last argument of every service method is the AuthContext; defaults below apply when omitted.

| Method | Default | Required kind | | --- | --- | --- | | customers.signup / .login / .requestPasswordReset / .confirmPasswordReset | anonymous | — | | customers.me / .update / .changePassword / .addresses.* | — | customer or raw | | customers.anonymous() | — | obtains anonymous session (token ignored) | | products.* / categories.* (reads) | anonymous | — (pass customer for personalized pricing) | | carts.* | — | explicit customer or anonymous | | carts.merge | — | customer | | companies.* / contacts.* / locations.* / customerGroups.* (B2B) | — | customer (reads need *_read_own; mutations need *_manage) | | media.* (Asset CRUD + download) | service | service — server-only (media.asset_read / media.asset_manage); never call from the browser |

AuthContext is per call, never stored — one client safely serves many concurrent shoppers (SSR/edge/multi-tenant). SDK-managed (service/anonymous) 401s refresh-and-retry once; caller-managed (customer/raw) 401s propagate as EmporixAuthError. Full details in ../../docs/auth.md.

Logging

Structured, level-aware, per-service controllable, secret-redacting, zero dependency. See ../../docs/logging.md.

Checkout & payment

sdk.checkout.placeOrder(...) / .placeOrderFromQuote(...) and sdk.payments.listPaymentModes(...) / .authorize(...). The saas-token header, guest checkout and deferred payment are covered in ../../docs/checkout.md.

B2B

sdk.companies (legal entities), sdk.contacts (contact assignments), sdk.locations (HQ/warehouse/office), sdk.customerGroups (IAM groups, read-only for now). Switching company scope is a customer-token rescope via sdk.customers.refresh({ refreshToken, legalEntityId }). Mutations that the customer's role lacks scope for surface as EmporixInsufficientScopeError (extends EmporixForbiddenError, carries requiredScope). See ../../docs/b2b.md.

Media

sdk.media covers the full /media/{tenant}/assets/* surface: create (uploadFile / link / create), list (paginated, PaginatedItems<Asset>), get, update (JSON metadata or BLOB multipart file-replacement via the replaceFile sugar), remove, and download (resolves to either a redirect URL for PUBLIC assets or an ArrayBuffer for PRIVATE). All endpoints require a server-only scope — every call defaults to a service AuthContext. Storefronts read media via product.productMedia (denormalised on the product) or the useProductMedia(productId) hook, not by calling the Media service directly. See ../../docs/media.md.

Availability

sdk.availability reads site-aware product availability: get(productId, siteCode) for one product and getMany(productIds, siteCode) for a batch (single POST .../search request, result in input order). The opt-in defaultAvailableOnNotFound returns { available: true } for products without a stock record. There is no restock-date field. See ../../docs/availability.md.

Subpath exports

@viu/emporix-sdk (the package root) re-exports everything — every service, type, and helper. Tree-shakeable subpaths are published for the high-traffic services: ./customer, ./product, ./category, ./cart, ./checkout, ./payment, ./price, ./media, ./segment, ./companies, ./contacts, ./locations, ./customer-groups, ./orders, ./availability. All other services (Tax, Coupon, RewardPoints, Shipping, Returns, Catalog, Vendor, PickPack, CustomerAdmin, Approval, …) are reached from the package root.

Authors

  • Dominic FritschiMaintainerVIU
  • Andreas NebikerContributorVIU
  • The Team at VIUContributorsVIU

License

This project is licensed under the MIT License — see the LICENSE file for details.