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

@curless/shopify-adapter

v0.9.3

Published

Use a Shopify store as an agentbank catalog source, and record agent-settled sales back as paid Shopify orders. Maps Shopify Admin products → a generic CatalogItem your merchant backend prices from, writes an order back after an agent pays through agentba

Readme

@curless/shopify-adapter

Use a Shopify store as your agentbank catalog, and record agent-settled sales back as paid Shopify orders. Drop it into a merchant backend so an AI agent can buy your Shopify products through any agentbank payment protocol — the money settles through agentbank, and the sale shows up in your Shopify admin.

Zero runtime dependencies — it uses the platform fetch and the Shopify Admin GraphQL API. Pairs with @curless/agentbank-merchant-sdk, which prices and opens the checkout.

npm install @curless/shopify-adapter

The three halves

import {
  shopifyConfigFromEnv,
  fetchShopifyCatalog,
  writebackShopifyOrder,
  refundShopifyOrder,
} from '@curless/shopify-adapter';

const shopify = shopifyConfigFromEnv(); // null unless SHOPIFY_* env is set

1. Catalog — map the store's products into generic CatalogItems you price from:

const items = shopify ? await fetchShopifyCatalog(shopify) : [];
// items: { sku, name, priceMinor, currency, description, imageUrl?, variantId?, productType? }[]
// …price a merchant-quoted checkout from `items` with the merchant SDK…

2. Writeback — after the agent pays through agentbank, record the paid order:

await writebackShopifyOrder(shopify, {
  variantId,                 // CatalogItem.variantId
  quantity,
  protocol: 'acp',           // which agentbank protocol settled it
  agentbankOrderId: orderId, // idempotency tag
  unitPriceMinor: 268000,    // the amount actually collected (see below)
  currency: 'EUR',
});

No money moves in Shopify. The order is booked with a SALE transaction on the agentbank gateway (not just financialStatus: PAID, which paints the label and creates no transaction — such an order can never be refunded) and tagged agentbank + protocol:… + the agentbank order id, so it's traceable and never mistaken for a Shopify Payments sale. Pass unitPriceMinor + currency or there is no total to book the transaction with, and the order won't be reversible.

3. Refund — when agentbank refunds the sale, stop the Shopify order reading as paid:

// e.g. from your `order.refunded` webhook handler
await refundShopifyOrder(shopify, {
  agentbankOrderId: [`order_${paymentIntentId}`, paymentIntentId], // any tag you wrote back with
  reason: 'guest cancelled',
});
// → { refunded: true, id } | { refunded: false, reason }

It records the reversal rather than processing one — the sale was booked on our own gateway, so the matching REFUND transaction moves no real money. It does have to BE a transaction, though: a refund with none attached is a 0.00 refund and the order goes on reading PAID. An order written back before this adapter recorded a sale transaction has no parent to refund against and comes back {refunded:false, reason:'…no SALE transaction…'} — reverse those in the admin once.

Full-order only — agentbank refunds the whole captured amount, and inventing a partial here would let you record a reversal that doesn't match the money that actually went back.

Notes

  • Auth — pick by whose store it is.

    • A store you do NOT own (a real merchant): they create a custom app in their own admin and give you its Admin API token. Set SHOPIFY_ADMIN_TOKEN
      • SHOPIFY_SHOP_DOMAIN. This is the only option — the client-credentials grant requires the app and shop to sit in the same Shopify organization, so it cannot reach a third party's store at all.
    • Your own store: Shopify's 2026 client-credentials grant. A Dev Dashboard app no longer shows a token in the UI, so you exchange SHOPIFY_CLIENT_ID + SHOPIFY_CLIENT_SECRET for a short-lived Admin token programmatically.

    A token, when present, wins — no exchange, one fewer call and one fewer way to fail. The app needs read_products (catalog) and write_orders (writeback) — required scopes go in shopify.app.toml, then deploy + reinstall. Secrets come from the environment; never hardcode them.

  • Amounts are currency-aware. Prices convert to integer minor units using the currency's own exponent — cents for USD/EUR, none for JPY, mills for KWD — so a non-2-decimal store isn't silently mis-scaled.

  • Record the real amount. Pass unitPriceMinor + currency to the writeback so the Shopify order reflects what the agent actually paid. Omit them to fall back to the variant's current price (which drifts if the price changed after payment).

  • Idempotency. The writeback searches for an order already tagged with the agentbank order id. Shopify's tag search lags creation by the search-index refresh, so two writebacks fired within a second can both miss and duplicate — add your own in-process guard on the order id if you fire them rapidly; the tag search is the cross-restart backstop.

  • Refunds are idempotent and safe to miss. refundShopifyOrder takes one id or a list, tries them in order, and returns {refunded:false, reason} — never throws — when nothing matches or the order is already REFUNDED. Ids that could false-match a Shopify search (spaces, operators) are dropped rather than searched: refunding the wrong order is worse than refunding none.

  • Pagination. Products paginate to completion. A single product with more than 250 variants has its tail dropped with a warning (not silently).

MIT