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

@yespos/client

v0.1.1

Published

SDK resmi untuk YesPOS Client API: outlet, produk, metode pembayaran, dan order (QRIS, Virtual Account, EDC).

Readme

@yespos/client

SDK TypeScript untuk YesPOS Client API (/api/client/*): outlet, produk, metode pembayaran, dan order dengan QRIS, Virtual Account, atau EDC.

  • Tanpa dependency. Memakai fetch dan Web Crypto bawaan runtime.
  • Jalan di mana saja. Node 20+, Bun, Deno, dan runtime edge (Vercel, Cloudflare Workers).
  • ESM + CJS + types.

⚠️ Hanya untuk server. Setiap request ditandatangani dengan client secret. Jangan pernah memakai SDK ini di browser — secret akan ikut terkirim. Panggil dari backend, API route, atau server function.

Instalasi

npm install @yespos/client

Mulai cepat

import { Shop } from '@yespos/client';

const shop = new Shop(
  { baseUrl: process.env.YESPOS_API_BASE_URL!, key: process.env.YESPOS_CLIENT_KEY!, secret: process.env.YESPOS_CLIENT_SECRET! },
  { outletUuid: process.env.YESPOS_OUTLET_UUID }
);

const categories = await shop.products();
const methods = await shop.paymentMethods();

const order = await shop.placeOrder(
  [{ productUuid: 'abc-123', quantity: 2 }],          // tanpa harga
  { name: 'Budi', email: '[email protected]', phone: '08123456789' },
  'va:bca'                                             // "<method>:<channel>"
);

order.payment_no;  // nomor VA yang dibayar pembeli
order.expired_at;  // batas waktu bayar

Atau langsung dari environment variable:

import { shopFromEnv } from '@yespos/client';
const shop = shopFromEnv(); // membaca YESPOS_* dari process.env

Dua lapisan

| Lapisan | Untuk apa | |---|---| | YesposClient | Akses mentah ke endpoint. Tidak ada aturan tambahan. | | Shop | Logika toko: pilih outlet, sembunyikan EDC bila tak dikonfigurasi, dan hitung harga dari API. |

Shop — dipakai storefront

const shop = new Shop(clientAtauOptions, {
  outletUuid: 'uuid-outlet',        // kosong = outlet pertama milik pemilik client
  notifyUrl: 'https://…/callback',  // callback status order
  edc: { app_code: 'YESPOS', terminal_code: 'T1', merchant_code: 'M1' }, // null = EDC disembunyikan
  messages: { methodUnavailable: 'Metode pembayaran tidak tersedia.' }    // untuk terjemahan
});

await shop.outlet();                       // Outlet
await shop.products();                     // ProductCategory[]
await shop.product('uuid-produk');         // ProductDetail
await shop.paymentMethods();               // PaymentMethod[]
await shop.priceCart(lines);               // OrderItem[] dengan harga dari API
await shop.placeOrder(lines, buyer, 'qris:qris');
await shop.order(uuid);
await shop.changePayment(uuid, 'va:bca');  // order pending → metode lain
shop.mediaUrl(token);                      // URL gambar publik

Harga selalu diambil dari API. placeOrder hanya menerima productUuid, variantUuid, dan quantity; totalnya dihitung ulang di server. Harga yang dikirim dari browser tidak dipercaya.

YesposClient — akses langsung

import { YesposClient } from '@yespos/client';
const yespos = new YesposClient({ baseUrl, key, secret, timeout: 15000, language: 'id' });

await yespos.outlets.list();
await yespos.products.list(outletUuid);
await yespos.products.get(outletUuid, productUuid);
await yespos.products.map(outletUuid);                 // Map<uuid, Product>
await yespos.paymentMethods.list();
await yespos.orders.create(input);
await yespos.orders.get(uuid);
await yespos.orders.list({ page: 1, limit: 10 });
await yespos.orders.changePaymentMethod(uuid, input);
yespos.mediaUrl(token);

Endpoint yang belum dibungkus bisa dipanggil lewat transport-nya:

await yespos.http.get<Something>('/endpoint-baru');
await yespos.http.post<Something>('/endpoint-baru', body);

Metode pembayaran

GET /api/client/payment-method hanya mengembalikan metode yang diaktifkan oleh pemilik client di dashboard YesPOS. Metode di luar daftar itu akan ditolak saat membuat order.

Satu pilihan ditulis "<method>:<channel>":

| Nilai | Arti | Field di response order | |---|---|---| | qris:qris | QRIS | qr_string → render jadi QR | | va:bca, va:bri, … | Virtual account per bank | payment_no, payment_name, expired_at | | edc:linkpayment | Kartu lewat EDC | app_link → buka di perangkat EDC |

import { paymentValue } from '@yespos/client';
const options = (await shop.paymentMethods()).map((m) => ({ value: paymentValue(m), label: m.name }));

Status order

import { orderState, isPending, isPaid } from '@yespos/client';

orderState('pending');            // 'pending'
orderState('berhasil_settled');   // 'paid'
orderState('expired');            // 'failed'

Status akhir dikirim YesPOS ke notifyUrl. Untuk menampilkannya di halaman, panggil shop.order(uuid) saat pembeli menekan tombol cek status — hindari polling berkala.

Error

Semua kegagalan dilempar sebagai YesposError.

import { isYesposError } from '@yespos/client';

try {
  await shop.placeOrder(lines, buyer, 'va:bca');
} catch (error) {
  if (isYesposError(error)) {
    error.status;          // status HTTP; 0 bila server tak terjangkau
    error.message;         // pesan dari API, sudah digabung bila berupa daftar
    error.details;         // field `details` dari API, bila ada
    error.isNetworkError;  // true bila tidak terhubung / timeout
    error.isAuthError;     // true untuk 401/403
  }
}

Beberapa yang sering muncul:

| Status | Arti | |---|---| | 400 | Metode pembayaran tidak tersedia, atau payment_channel wajib diisi | | 404 | Outlet, produk, atau order tidak ditemukan | | 409 | Produk di keranjang sudah tidak dijual, atau order sudah tidak pending | | 401 | Signature ditolak — periksa key dan secret |

Konfigurasi

new YesposClient({
  baseUrl: 'https://api.yespos.id', // tanpa / di akhir (tetap aman bila ada)
  key: '…',                          // header `va`
  secret: '…',                       // penandatangan request, simpan di server
  timeout: 15000,                    // ms, default 15000
  language: 'id',                    // bahasa pesan API, default 'id'
  fetch: customFetch                 // opsional: fetch sendiri (proxy, retry, dll.)
});

Variabel environment yang dibaca shopFromEnv() / clientFromEnv():

YESPOS_API_BASE_URL, YESPOS_CLIENT_KEY, YESPOS_CLIENT_SECRET,
YESPOS_OUTLET_UUID, YESPOS_NOTIFY_URL,
YESPOS_EDC_APP_CODE, YESPOS_EDC_TERMINAL_CODE, YESPOS_EDC_MERCHANT_CODE

Cara kerja signature

SDK menandatangani setiap request seperti yang dicek ClientAuthMiddleware di YesPOS:

signature = HMAC-SHA256(secret, `${METHOD}:${key}:${sha256(body || "{}")}:${secret}`)

Lalu dikirim sebagai header va, signature, dan timestamp. Fungsinya diekspor sebagai signRequest() bila diperlukan di luar SDK.

Contoh pemakaian

Tiga storefront contoh memakai SDK ini:

  • yespos-example-landingpage (SvelteKit)
  • yespos-example-landingpage-vue (Nuxt)
  • yespos-example-landingpage-react (Next.js)

Pola yang dipakai ketiganya: SDK hanya di server, lalu browser memanggil endpoint JSON milik aplikasi sendiri (/api/*).

Pengembangan

npm install
npm test          # vitest, termasuk mock yang memverifikasi signature
npm run typecheck
npm run build

Rilis

Publish ke npm berjalan otomatis dari GitHub Actions saat tag versi di-push.

npm version patch        # atau minor / major — mengubah package.json + membuat tag
git push --follow-tags   # tag v* memicu workflow Release

Workflow release.yml memastikan tag cocok dengan package.json, menjalankan typecheck + test + build, lalu npm publish dan membuat GitHub Release.

Autentikasi ke npm memakai Trusted Publishing (OIDC): npm memverifikasi workflow lewat GitHub, jadi tidak ada token npm yang disimpan di repo. Provenance ikut dibuat otomatis.

Setup sekali di npmjs.com → paket → Settings → Trusted publishing → GitHub Actions:

| Isian | Nilai | |---|---| | Organization or user | Yes-Pos | | Repository | yespos-client-sdk | | Workflow filename | release.yml | | Allowed actions | cukup npm stage publish (biarkan npm publish tidak dicentang) |

Workflow memakai staged publishing: CI hanya boleh menaruh versi di ruang tunggu, lalu kamu menyetujuinya dengan 2FA:

npm stage list @yespos/client     # ambil stage-id
npm stage approve <stage-id>      # minta 2FA, lalu versi terbit

Atau lewat npmjs.com → paket → tab Staged Packages → Approve. Perintahnya juga muncul di ringkasan job Actions setelah rilis.

Alasannya: tanpa langkah ini, siapa pun yang bisa mendorong tag — atau dependency build yang disusupi — dapat menerbitkan versi ke semua pengguna tanpa sepengetahuan manusia.

Syarat: repository.url di package.json harus sama persis dengan repo GitHub-nya, dan konfigurasi trusted publisher harus dipakai untuk publish pertama dalam 2 hari atau kedaluwarsa.

Publish pertama tetap manual (npm publish), karena trusted publisher baru bisa didaftarkan setelah paketnya ada di npm.

Lisensi

MIT