@receiz/sdk 97.1.0 → 97.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js ADDED
@@ -0,0 +1,200 @@
1
+ import { createElement, useCallback, useEffect, useMemo, useState, } from "react";
2
+ import { createReceizClient, } from "./index.js";
3
+ function useReceizClient(options = {}) {
4
+ const { client, baseUrl, accessToken, fetchImpl } = options;
5
+ return useMemo(() => client ?? createReceizClient(compactClientOptions({ baseUrl, accessToken, fetchImpl })), [client, baseUrl, accessToken, fetchImpl]);
6
+ }
7
+ function compactClientOptions(options) {
8
+ const next = {};
9
+ if (options.baseUrl !== undefined)
10
+ next.baseUrl = options.baseUrl;
11
+ if (options.accessToken !== undefined)
12
+ next.accessToken = options.accessToken;
13
+ if (options.fetchImpl !== undefined)
14
+ next.fetchImpl = options.fetchImpl;
15
+ return next;
16
+ }
17
+ function compactReactClientOptions(options) {
18
+ const next = compactClientOptions(options);
19
+ if (options.client !== undefined)
20
+ next.client = options.client;
21
+ return next;
22
+ }
23
+ function compactIdentityOptions(options) {
24
+ const next = compactReactClientOptions(options);
25
+ if (options.authorize !== undefined)
26
+ next.authorize = options.authorize;
27
+ if (options.logoutUrl !== undefined)
28
+ next.logoutUrl = options.logoutUrl;
29
+ return next;
30
+ }
31
+ function errorFromUnknown(error) {
32
+ return error instanceof Error ? error : new Error(String(error));
33
+ }
34
+ export function useReceizIdentity(options = {}) {
35
+ const client = useReceizClient(options);
36
+ const authorizeUrl = options.authorize ? client.identity.authorizeUrl(options.authorize) : null;
37
+ const login = useCallback(() => {
38
+ if (!authorizeUrl || typeof window === "undefined")
39
+ return;
40
+ window.location.assign(authorizeUrl);
41
+ }, [authorizeUrl]);
42
+ const logout = useCallback(() => {
43
+ if (typeof window === "undefined")
44
+ return;
45
+ window.location.assign(options.logoutUrl ?? "/logout");
46
+ }, [options.logoutUrl]);
47
+ return { client, login, logout, authorizeUrl };
48
+ }
49
+ export function useReceizCheckout(options = {}) {
50
+ const client = useReceizClient(options);
51
+ const [state, setState] = useState({
52
+ loading: false,
53
+ error: null,
54
+ data: null,
55
+ });
56
+ const checkout = useCallback(async (request) => {
57
+ setState((current) => ({ ...current, loading: true, error: null }));
58
+ try {
59
+ const response = await client.commerce.oneClickCheckout(request);
60
+ setState({ loading: false, error: null, data: response });
61
+ return response;
62
+ }
63
+ catch (error) {
64
+ const nextError = errorFromUnknown(error);
65
+ setState({ loading: false, error: nextError, data: null });
66
+ throw nextError;
67
+ }
68
+ }, [client]);
69
+ return { ...state, checkout };
70
+ }
71
+ export function useReceizAppState(options = {}) {
72
+ const client = useReceizClient(options);
73
+ const [state, setState] = useState({
74
+ loading: false,
75
+ error: null,
76
+ data: options.initial ?? null,
77
+ });
78
+ const resolve = useCallback(async (input) => {
79
+ const target = input ?? options.resolve;
80
+ if (!target)
81
+ throw new Error("receiz_app_state_resolve_input_required");
82
+ setState((current) => ({ ...current, loading: true, error: null }));
83
+ try {
84
+ const response = await client.appState.resolve(target);
85
+ setState({ loading: false, error: null, data: response });
86
+ return response;
87
+ }
88
+ catch (error) {
89
+ const nextError = errorFromUnknown(error);
90
+ setState({ loading: false, error: nextError, data: null });
91
+ throw nextError;
92
+ }
93
+ }, [client, options.resolve]);
94
+ const publish = useCallback(async (input) => {
95
+ const response = await client.appState.publish(input);
96
+ return response;
97
+ }, [client]);
98
+ useEffect(() => {
99
+ if (options.autoResolve === false || !options.resolve || options.initial)
100
+ return;
101
+ let active = true;
102
+ const target = options.resolve;
103
+ queueMicrotask(() => {
104
+ if (!active)
105
+ return;
106
+ void resolve(target);
107
+ });
108
+ return () => {
109
+ active = false;
110
+ };
111
+ }, [options.autoResolve, options.initial, options.resolve, resolve]);
112
+ return { ...state, resolve, publish };
113
+ }
114
+ export function useReceizMedia(options = {}) {
115
+ const client = useReceizClient(options);
116
+ const [state, setState] = useState({
117
+ loading: false,
118
+ error: null,
119
+ data: null,
120
+ });
121
+ const upload = useCallback(async (file, uploadOptions = {}) => {
122
+ setState((current) => ({ ...current, loading: true, error: null }));
123
+ try {
124
+ const response = await client.media.upload(file, uploadOptions);
125
+ const data = response;
126
+ setState({ loading: false, error: null, data });
127
+ return data;
128
+ }
129
+ catch (error) {
130
+ const nextError = errorFromUnknown(error);
131
+ setState({ loading: false, error: nextError, data: null });
132
+ throw nextError;
133
+ }
134
+ }, [client]);
135
+ return { ...state, upload };
136
+ }
137
+ export function ReceizIdentityButton(props) {
138
+ const { children, client, baseUrl, accessToken, fetchImpl, authorize, logoutUrl, ...buttonProps } = props;
139
+ const identity = useReceizIdentity(compactIdentityOptions({ client, baseUrl, accessToken, fetchImpl, authorize, logoutUrl }));
140
+ return createElement("button", { ...buttonProps, type: buttonProps.type ?? "button", onClick: identity.login }, children ?? "Continue with Receiz");
141
+ }
142
+ export function ReceizCheckoutButton(props) {
143
+ const { children, client, baseUrl, accessToken, fetchImpl, request, onCheckout, ...buttonProps } = props;
144
+ const checkout = useReceizCheckout(compactReactClientOptions({ client, baseUrl, accessToken, fetchImpl }));
145
+ const onClick = useCallback(async () => {
146
+ const response = await checkout.checkout(request);
147
+ onCheckout?.(response);
148
+ }, [checkout, onCheckout, request]);
149
+ return createElement("button", { ...buttonProps, type: buttonProps.type ?? "button", disabled: buttonProps.disabled || checkout.loading, onClick }, children ?? (checkout.loading ? "Opening..." : "Checkout with Receiz"));
150
+ }
151
+ export function ReceizWalletBalance(props) {
152
+ const { client: providedClient, baseUrl, accessToken, fetchImpl, fallback = "Wallet unavailable" } = props;
153
+ const client = useReceizClient(compactReactClientOptions({ client: providedClient, baseUrl, accessToken, fetchImpl }));
154
+ const [balance, setBalance] = useState(null);
155
+ useEffect(() => {
156
+ let active = true;
157
+ void client.connect.wallet().then((wallet) => {
158
+ if (!active)
159
+ return;
160
+ setBalance(typeof wallet.balanceUsdCents === "string" ? `$${(Number(wallet.balanceUsdCents) / 100).toFixed(2)}` : null);
161
+ }).catch(() => {
162
+ if (active)
163
+ setBalance(null);
164
+ });
165
+ return () => {
166
+ active = false;
167
+ };
168
+ }, [client]);
169
+ return createElement("span", null, balance ?? fallback);
170
+ }
171
+ export function ReceizMediaUploader(props) {
172
+ const { client, baseUrl, accessToken, fetchImpl, uploadOptions, onUploaded, ...inputProps } = props;
173
+ const media = useReceizMedia(compactReactClientOptions({ client, baseUrl, accessToken, fetchImpl }));
174
+ const onChange = useCallback(async (event) => {
175
+ const file = event.currentTarget.files?.[0];
176
+ if (!file)
177
+ return;
178
+ const response = await media.upload(file, uploadOptions);
179
+ onUploaded?.(response);
180
+ }, [media, onUploaded, uploadOptions]);
181
+ return createElement("input", { ...inputProps, type: "file", onChange });
182
+ }
183
+ export function ReceizDomainConnector(props) {
184
+ const { children, client: providedClient, baseUrl, accessToken, fetchImpl, host, onStatus, ...buttonProps } = props;
185
+ const client = useReceizClient(compactReactClientOptions({ client: providedClient, baseUrl, accessToken, fetchImpl }));
186
+ const onClick = useCallback(async () => {
187
+ const response = await client.domains.status({ host });
188
+ onStatus?.(response);
189
+ }, [client, host, onStatus]);
190
+ return createElement("button", { ...buttonProps, type: buttonProps.type ?? "button", onClick }, children ?? "Check Receiz Domain");
191
+ }
192
+ export function ReceizTwinWriter(props) {
193
+ const { children, client: providedClient, baseUrl, accessToken, fetchImpl, body, onSaved, ...buttonProps } = props;
194
+ const client = useReceizClient(compactReactClientOptions({ client: providedClient, baseUrl, accessToken, fetchImpl }));
195
+ const onClick = useCallback(async () => {
196
+ const response = await client.twin.approvePromotion(body);
197
+ onSaved?.(response);
198
+ }, [body, client, onSaved]);
199
+ return createElement("button", { ...buttonProps, type: buttonProps.type ?? "button", onClick }, children ?? "Write Twin Proof");
200
+ }
@@ -1,6 +1,6 @@
1
1
  # Receiz App Runtime And Commerce Cloud Rails
2
2
 
3
- `@receiz/sdk` exposes typed rails for apps that want Receiz identity, public app-state, commerce, media, domains, events, proof search, jobs, and diagnostics without stitching a separate app backend together first.
3
+ `@receiz/sdk` exposes typed rails for apps that want Receiz identity, public app-state, commerce, media, domains, events, proof search, jobs, permissions, audit, risk, compliance, portability, notifications, release pinning, offline proof queues, and diagnostics without stitching a separate app backend together first.
4
4
 
5
5
  The SDK is convenience. It does not become proof authority. Proof objects, verified local truth, app-state projections, Connect delegated routes, wallet settlement, identity artifacts, and durable append rails remain the source of truth.
6
6
 
@@ -70,6 +70,37 @@ if (checkout.checkoutSession?.clientSecret) {
70
70
 
71
71
  Wallet-first checkout reads the delegated wallet summary, computes the card delta, and creates an embedded Connect checkout session only when a card delta remains. Settlement truth still belongs to the Connect/payment and wallet rails returned by the backend.
72
72
 
73
+ ## Enterprise Commerce
74
+
75
+ ```ts
76
+ await receiz.customers.session({
77
+ tenantHost: "bjklock.receiz.app",
78
+ customerReceizId: "customer.receiz.id",
79
+ scopes: ["orders", "rewards", "assets"],
80
+ }, { idempotencyKey: "customer-session:v1" });
81
+
82
+ await receiz.merchants.onboard({
83
+ tenantHost: "bjklock.receiz.app",
84
+ receizId: "bjklock.receiz.id",
85
+ displayName: "BJ Klock",
86
+ defaultStore: { title: "BJ Klock Store" },
87
+ }, { idempotencyKey: "merchant:bjklock:v1" });
88
+
89
+ await receiz.commerce.inventory.reserve({
90
+ tenantHost: "bjklock.receiz.app",
91
+ sku: "hat-black",
92
+ quantity: 2,
93
+ }, { idempotencyKey: "inventory:hat-black:cart-123" });
94
+
95
+ await receiz.commerce.fulfillment.update({
96
+ tenantHost: "bjklock.receiz.app",
97
+ orderId: "order_123",
98
+ status: "shipped",
99
+ }, { idempotencyKey: "fulfillment:order_123:shipped" });
100
+ ```
101
+
102
+ Additional commerce rails include refunds, subscriptions, shipping quotes, tax quotes, discounts, gift cards, access passes, inventory adjustment, and merchant payouts. Every write accepts an idempotency key so retries append once.
103
+
73
104
  ## Media, Domains, Events, Search, And Jobs
74
105
 
75
106
  ```ts
@@ -102,6 +133,84 @@ await receiz.jobs.enqueue({
102
133
  payload: { mediaId: logo.media?.id },
103
134
  idempotencyKey: "media.process:logo:v1",
104
135
  });
136
+
137
+ await receiz.media.transform({
138
+ tenantHost: "bjklock.receiz.app",
139
+ mediaId: String(logo.media?.id),
140
+ resize: { width: 1200 },
141
+ optimize: { format: "webp" },
142
+ blurPlaceholder: true,
143
+ altText: "Store logo",
144
+ }, { idempotencyKey: "media.transform:logo:v1" });
145
+
146
+ await receiz.events.replay({
147
+ tenantHost: "bjklock.receiz.app",
148
+ types: ["order.created", "payment.settled"],
149
+ since: "2026-06-01T00:00:00.000Z",
150
+ });
151
+ ```
152
+
153
+ ## Permissions, Audit, Risk, Compliance, And Portability
154
+
155
+ ```ts
156
+ await receiz.permissions.grant({
157
+ tenantHost: "bjklock.receiz.app",
158
+ actorReceizId: "staff.receiz.id",
159
+ role: "fulfillment",
160
+ }, { idempotencyKey: "grant:staff:fulfillment" });
161
+
162
+ await receiz.audit.append({
163
+ tenantHost: "bjklock.receiz.app",
164
+ action: "product.updated",
165
+ actorReceizId: "bjklock.receiz.id",
166
+ }, { idempotencyKey: "audit:product:update:123" });
167
+
168
+ const risk = await receiz.risk.scorePayment({
169
+ tenantHost: "bjklock.receiz.app",
170
+ orderId: "order_123",
171
+ amountUsd: "42.00",
172
+ });
173
+
174
+ const orders = await receiz.compliance.exportOrders({
175
+ tenantHost: "bjklock.receiz.app",
176
+ from: "2026-06-01",
177
+ to: "2026-06-30",
178
+ });
179
+
180
+ const portableStore = await receiz.portability.exportStore({
181
+ tenantHost: "bjklock.receiz.app",
182
+ });
183
+ ```
184
+
185
+ Audit, risk, compliance, and portability are projections over proof-native activity. They help applications operate; they do not outrank the proof objects, wallet settlement, or verified appends they project.
186
+
187
+ ## Offline Queue And Release Pinning
188
+
189
+ ```ts
190
+ const storage = receiz.offline.createLocalStorage("receiz:queue:bjklock");
191
+ const queue = await receiz.offline.createQueue({
192
+ ownerId: "bjklock.receiz.id",
193
+ storage,
194
+ });
195
+
196
+ queue.enqueue({
197
+ id: "store-state:offline-1",
198
+ kind: "app_state.publish",
199
+ payload: {
200
+ tenantHost: "bjklock.receiz.app",
201
+ title: "Offline storefront append",
202
+ state: { storeStateRecord },
203
+ },
204
+ idempotencyKey: "store-state:offline-1",
205
+ });
206
+ await queue.flush();
207
+
208
+ await queue.replay(receiz);
209
+
210
+ await receiz.releases.pin({
211
+ tenantHost: "bjklock.receiz.app",
212
+ rails: { appState: "v1", commerce: "v1", media: "v1" },
213
+ }, { idempotencyKey: "rails:pin:v1" });
105
214
  ```
106
215
 
107
216
  ## Deterministic Sandbox
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@receiz/sdk",
3
- "version": "97.1.0",
3
+ "version": "97.2.0",
4
4
  "description": "TypeScript SDK for Receiz proof-native artifact, public proof, wallet, sports, Twin, World, and Connect integrations.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,6 +13,10 @@
13
13
  "types": "./dist/index.d.ts",
14
14
  "import": "./dist/index.js"
15
15
  },
16
+ "./react": {
17
+ "types": "./dist/react.d.ts",
18
+ "import": "./dist/react.js"
19
+ },
16
20
  "./fixtures/*": "./fixtures/*",
17
21
  "./docs/*": "./docs/*",
18
22
  "./package.json": "./package.json"