@packiko/sdk
v0.2.0
Published
Typed client for the Packiko API, generated from a pinned OpenAPI contract.
Readme
@packiko/sdk
Typed client for the Packiko API, generated from a pinned OpenAPI contract.
ESM-only. Node >= 20.
Install
npm install @packiko/sdkReact bindings are exposed separately and React is an optional peer; the core entry does not import React.
Use
The client is split in two phases, because the API resolves a tenant from an X-Account-Id
header that only exists once the user has picked an account.
import { createPreAccountClient, createClient, ApiError } from '@packiko/sdk'
// Phase 1: no account yet. Only the pre-account surface is reachable.
const pre = createPreAccountClient({ token: () => accessToken })
const accounts = await pre.request('get', '/Auth/Common/Accounts')
// Phase 2: account chosen. The client sets X-Account-Id on every call.
const api = createClient({ token: () => accessToken, accountId: accounts[0].id })
const product = await api.request('get', '/Product/{id}', { path: { id: '42' } })Reaching a phase-2 path from the phase-1 client is a type error, and vice versa. X-Account-Id
is owned by the client and cannot be set by a caller.
Errors arrive as ApiError with the application/problem+json body parsed onto .problem:
try {
await api.request('get', '/Product/{id}', { path: { id: 'nope' } })
} catch (e) {
if (e instanceof ApiError) console.error(e.status, e.problem?.title, e.problem?.detail)
}token is called per request, so a rotating access token does not need a new client.
Contract pinning
spec/public.json is a byte copy of openapi/public.json from a specific commit on the api
repo's main; spec/pin.json records that commit and blob. src/types.gen.ts is generated
from the pinned copy and committed.
To move to a newer contract:
# copy the new spec into spec/public.json, update spec/pin.json, then
npm run generate
npm run typecheck && npm run gatesnpm run gates refuses a pin whose blob is not present on api's main.
CLI
The package ships packiko, a thin command line over the same client, for coding agents.
npx @packiko/sdk login # device code; approve in the browser
npx @packiko/sdk accounts # find your account id
npx @packiko/sdk login --account <id> # bind the account (approve in the browser again)
npx @packiko/sdk get /Sku --json
npx @packiko/sdk get /Sku/{id} --path id=42The account id is stored with the offline refresh token in ~/.packiko/credentials.json and is
the only source of X-Account-Id. There is no env var or flag to change it. PACKIKO_API_URL
overrides the API base URL. v1 is read-only.
Git Bash on Windows rewrites a leading / in arguments to a Windows path; run with
MSYS_NO_PATHCONV=1 or use PowerShell.
