@devx-retailos/sdk-client
v0.0.2
Published
Frontend SDK for retailOS: typed API client and React hooks for identity, permissions, and admin resources.
Keywords
Readme
@devx-retailos/sdk-client
Frontend SDK for retailOS POS applications: a typed HTTP client for the /admin/retailos/* API, React hooks for identity and permission-gated UI, and WebUSB thermal-printer receipt printing.
Part of retailOS, a Medusa v2 SDK for offline-store POS systems. This package runs in the POS frontend and talks to a backend that has @devx-retailos/admin-extensions (and friends) installed.
Installation
npm install @devx-retailos/sdk-clientOptional peer dependencies:
react^18 || ^19— required only for the/reactand/printentry points.@point-of-sale/receipt-printer-encoder^3— enables ESC/POS receipt encoding; without it, receipts fall back to plain UTF-8 text.
Setup
import { createRetailOSClient } from "@devx-retailos/sdk-client"
const client = createRetailOSClient({
baseUrl: "https://pos-api.example.com",
// fetch?: custom fetch implementation (defaults to globalThis.fetch)
// credentials?: RequestCredentials (defaults to "include")
// defaultHeaders?: extra headers on every request
// organizationId?: sent as the x-retailos-organization-id header
// storeId?: sent as the x-retailos-store-id header
// logger?: a @devx-retailos/core Logger
})Non-2xx responses throw RetailOSClientError with status and the parsed response body.
Typed client
const me = await client.me() // { subject, scope, permissions, flags }
const { organizations } = await client.organizations.list()
const { store } = await client.stores.create({ organization_id, name: "Flagship", code: "FLG" })
const { role } = await client.roles.create({ name: "cashier", display_name: "Cashier" })
await client.roles.grantPermission(role.id, { permission_id })
await client.userRoles.assign({ subject_id, subject_type: "medusa_user", role_id: role.id, organization_id })Namespaces: me(), organizations, stores, roles (incl. grantPermission / revokePermission), permissions, userRoles (list / assign / revoke), and config (list / get / set / nextSequence / resetSequence). The config namespace requires @devx-retailos/store-config on the backend; the rest map to @devx-retailos/admin-extensions routes.
React hooks — @devx-retailos/sdk-client/react
Wrap your app in RetailOSProvider; it creates the client and loads me() once (call refresh() from useRetailOS() to reload).
import {
RetailOSProvider,
useUser,
useCan,
PermissionGate,
} from "@devx-retailos/sdk-client/react"
function App() {
return (
<RetailOSProvider config={{ baseUrl: "https://pos-api.example.com" }}>
<Pos />
</RetailOSProvider>
)
}
function Pos() {
const user = useUser() // { id, type } | null
const canRefund = useCan("order.refund") // string or string[] (all must be granted)
return (
<PermissionGate permission="product.read" fallback={<p>No access</p>}>
<Catalog />
</PermissionGate>
)
}Also exported: usePermissions() (the raw permission-key list), useFlags() / useFlag(key) and <FeatureGate flag="..."> for feature flags resolved by the backend.
Thermal printing — @devx-retailos/sdk-client/print
useThermalPrinter() manages a WebUSB receipt printer (device selection persists across reloads via navigator.usb.getDevices()):
import { useThermalPrinter, type ReceiptData } from "@devx-retailos/sdk-client/print"
function PrintButton({ receipt }: { receipt: ReceiptData }) {
const printer = useThermalPrinter()
// printer: { isConnected, deviceName, connect, disconnect, print, printReceipt }
return (
<button
onClick={async () => {
if (!printer.isConnected) await printer.connect() // WebUSB device picker
await printer.printReceipt(receipt)
}}
>
Print receipt
</button>
)
}printReceipt(data, template?) encodes ReceiptData (store header, invoice number, line items, totals, payments, footer) with DefaultReceiptTemplate — an ESC/POS template (42 columns by default, configurable via new DefaultReceiptTemplate(columns)). Pass any object implementing ReceiptTemplate (encode(data): Promise<Uint8Array>) for a custom layout, or use print(bytes) to send raw bytes. WebUSB requires a secure context (HTTPS) and a Chromium-based browser.
Related packages
@devx-retailos/admin-extensions— backend plugin serving the/admin/retailos/*routes this client calls@devx-retailos/store-config— backend plugin serving theconfigand sequence routes@devx-retailos/rbac— the RBAC module behind permissions and roles@devx-retailos/feature-flags— resolves the flags consumed byuseFlags/FeatureGate@devx-retailos/core— shared types, errors,Logger
License
MIT
