npm.io
0.49.0 • Published 6d ago

commerce-kit

Licence
AGPL-3.0-only
Version
0.49.0
Deps
0
Size
456 kB
Vulns
0
Weekly
0

commerce-kit

TypeScript SDK for the Your Next Store API.

Installation

bun add commerce-kit
# or
npm install commerce-kit

Quick Start

import { Commerce } from 'commerce-kit';

const commerce = Commerce();

That's it! The SDK reads YNS_API_KEY from environment and auto-detects the correct store and API base URL: https://yns.store

Products

// List products
const { data, meta } = await commerce.productBrowse({
  limit: 10,
  offset: 0,
  category: 'shoes',
  query: 'running',
  active: true,
  orderBy: 'createdAt',
  orderDirection: 'desc',
});

// Get single product by ID or slug
const product = await commerce.productGet({ idOrSlug: 'running-shoes' });

Cart

// Create or update cart
const cart = await commerce.cartUpsert({
  cartId: 'cart_123', // optional, creates new if omitted
  variantId: 'variant_456',
  quantity: 2,
});

// Get cart
const cart = await commerce.cartGet({ cartId: 'cart_123' });

// Remove item from cart
await commerce.cartRemoveItem({
  cartId: 'cart_123',
  variantId: 'variant_456',
});

Orders

// List orders
const { data, meta } = await commerce.orderBrowse({
  limit: 10,
  offset: 0,
});

// Get single order
const order = await commerce.orderGet({ id: 'order_789' });
// Orders with event-ticket lines carry a buyer access code: order.ticketCode (string | null)

Events

An event is a product flagged as an event (with a date, location, and capacity) plus a single non-shippable ticket variant. Requires the store's Events tool to be enabled.

// List events (with live ticketsSold counts)
const { data, total } = await commerce.eventBrowse({ limit: 10, offset: 0 });

// Get one event by id or slug
const { event } = await commerce.eventGet({ idOrSlug: 'summer-fest' });

// Create an event (ticket price is a decimal string)
const { event } = await commerce.eventCreate({
  name: 'Summer Fest',
  price: '29.99',
  startsAt: '2026-07-01T18:00:00Z',
  location: 'Berlin',
  capacity: 500,
});

// Update event metadata (partial; send null to clear a field).
// Does not change the ticket price/variants — use the products API for those.
await commerce.eventUpdate({ idOrSlug: 'summer-fest' }, { capacity: 600, status: 'published' });

// Attendee rollup (buyers and ticket quantities, from paid orders)
const { attendees, totalTickets } = await commerce.eventAttendeesBrowse({ idOrSlug: 'summer-fest' });

Tickets

No-login access to purchased event tickets. The buyer gets a 6-character access code on the order (order.ticketCode, also in the confirmation email) and manages all attendee details with it plus the purchase email. Each seat carries its own shareable token — a view-only link for the attendee; attendee details can only be edited by the buyer.

// Buyer lookup: access code + purchase email.
// Returns null on any mismatch (the API answers a uniform 404).
const bundle = await commerce.ticketsGet({ code: 'K7M3PA', email: 'buyer@example.com' });
// bundle.lines[].event — startsAt, location, guestLabel, guest
// bundle.lines[].seats[] — { token, name, email } per ticket

// Buyer bulk-edit of attendee names/emails.
// Throws on mismatch (404) or when the order is cancelled/refunded (409).
const updated = await commerce.ticketsUpdate(
  { code: 'K7M3PA' },
  {
    email: 'buyer@example.com',
    seats: [{ token: bundle.lines[0].seats[0].token, name: 'Ada Lovelace', email: null }],
  },
);

// View-only attendee ticket by seat token (null for unknown tokens)
const ticket = await commerce.ticketAttendeeGet({ token: 'a1b2c3...' });

Collections & Categories

Full CRUD for product collections, product categories, and blog categories. Mutations are partial (send only the fields you want to change; pass null to clear an optional field).

// Collections — create, partially update, delete
const collection = await commerce.collectionCreate({ name: 'Summer', filter: { type: 'manual' }, active: true });
await commerce.collectionUpdate({ idOrSlug: 'summer' }, { name: 'Summer 2026', active: false });
await commerce.collectionDelete({ idOrSlug: 'summer' }); // { ok: true, deleted: 1 }

// Group related collections under a free-form key and fetch them together
await commerce.collectionUpdate({ idOrSlug: 'floral' }, { group: 'fragrances' });
const fragrances = await commerce.collectionBrowse({ group: 'fragrances' });
await commerce.collectionUpdate({ idOrSlug: 'floral' }, { group: null }); // clear

// Categories — delete (create/update already supported)
await commerce.categoryUpdate({ idOrSlug: 'shoes' }, { name: 'Footwear' });
await commerce.categoryDelete({ idOrSlug: 'footwear' }); // 409 if still referenced by products

// Blog categories — full CRUD
const blogCategory = await commerce.blogCategoryCreate({ name: 'Guides' });
await commerce.blogCategoryUpdate({ idOrSlug: 'guides' }, { description: null });
await commerce.blogCategoryDelete({ idOrSlug: 'guides' });

Raw API Requests

For endpoints not yet implemented in the SDK, use the request() method:

// GET request
const webhooks = await commerce.request<Webhook[]>('/webhooks');

// POST with body
const webhook = await commerce.request<Webhook, CreateWebhookBody>('/webhooks', {
  method: 'POST',
  body: { url: 'https://example.com/hook', events: ['order.created'] },
});

// GET with query parameters
const results = await commerce.request<SearchResult>('/search', {
  query: { q: 'shoes', limit: 5 },
});

// Path parameters via template literals
const variant = await commerce.request<Variant>(`/products/${productId}/variants/${variantId}`);

TypeScript

All API types are exported:

import type {
  APIProductsBrowseResult,
  APIProductGetByIdResult,
  APICartCreateBody,
  APIOrderGetByIdResult,
  CommerceConfig,
} from 'commerce-kit';

License

AGPL-3.0-only

Keywords