@receiz/sdk 97.1.0 → 97.3.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.
@@ -0,0 +1,80 @@
1
+ import { type ComponentPropsWithoutRef, type ReactElement, type ReactNode } from "react";
2
+ import { type JsonObject, type ReceizAppStatePublishInput, type ReceizAppStateResolveInput, type ReceizAppStateResolveResult, type ReceizClient, type ReceizClientOptions, type ReceizMediaUploadOptions, type ReceizOneClickCheckoutRequest, type ReceizOneClickCheckoutResponse, type TwinPromotionApprovalInput } from "./index.js";
3
+ export type ReceizReactClientOptions = ReceizClientOptions & {
4
+ client?: ReceizClient;
5
+ };
6
+ export type ReceizAsyncState<T> = {
7
+ loading: boolean;
8
+ error: Error | null;
9
+ data: T | null;
10
+ };
11
+ export type ReceizIdentityHook = {
12
+ client: ReceizClient;
13
+ login: () => void;
14
+ logout: () => void;
15
+ authorizeUrl: string | null;
16
+ };
17
+ export type ReceizIdentityHookOptions = ReceizReactClientOptions & {
18
+ authorize?: {
19
+ clientId: string;
20
+ redirectUri: string;
21
+ codeChallenge: string;
22
+ codeChallengeMethod?: "S256" | "plain";
23
+ state?: string;
24
+ scope?: string | string[];
25
+ usernameHint?: string;
26
+ };
27
+ logoutUrl?: string;
28
+ };
29
+ export type ReceizCheckoutHook = ReceizAsyncState<ReceizOneClickCheckoutResponse> & {
30
+ checkout: (request: ReceizOneClickCheckoutRequest) => Promise<ReceizOneClickCheckoutResponse>;
31
+ };
32
+ export type ReceizAppStateHook<TData extends JsonObject = JsonObject> = ReceizAsyncState<ReceizAppStateResolveResult<TData>> & {
33
+ resolve: (input?: ReceizAppStateResolveInput) => Promise<ReceizAppStateResolveResult<TData>>;
34
+ publish: (input: ReceizAppStatePublishInput) => Promise<JsonObject>;
35
+ };
36
+ export type ReceizAppStateHookOptions<TData extends JsonObject = JsonObject> = ReceizReactClientOptions & {
37
+ resolve?: ReceizAppStateResolveInput;
38
+ initial?: ReceizAppStateResolveResult<TData> | null;
39
+ autoResolve?: boolean;
40
+ };
41
+ export type ReceizMediaHook = ReceizAsyncState<JsonObject> & {
42
+ upload: (file: Blob, options?: ReceizMediaUploadOptions) => Promise<JsonObject>;
43
+ };
44
+ type ReceizButtonProps = Omit<ComponentPropsWithoutRef<"button">, "onClick"> & {
45
+ children?: ReactNode;
46
+ };
47
+ type ReceizIdentityButtonProps = ReceizButtonProps & ReceizIdentityHookOptions;
48
+ type ReceizCheckoutButtonProps = ReceizButtonProps & ReceizReactClientOptions & {
49
+ request: ReceizOneClickCheckoutRequest;
50
+ onCheckout?: (response: ReceizOneClickCheckoutResponse) => void;
51
+ };
52
+ type ReceizWalletBalanceProps = ReceizReactClientOptions & {
53
+ tenantHost?: string;
54
+ fallback?: ReactNode;
55
+ };
56
+ type ReceizMediaUploaderProps = Omit<ComponentPropsWithoutRef<"input">, "type" | "onChange"> & ReceizReactClientOptions & {
57
+ uploadOptions?: ReceizMediaUploadOptions;
58
+ onUploaded?: (response: JsonObject) => void;
59
+ };
60
+ type ReceizDomainConnectorProps = ReceizButtonProps & ReceizReactClientOptions & {
61
+ host: string;
62
+ onStatus?: (response: JsonObject) => void;
63
+ };
64
+ type ReceizTwinWriterProps = Omit<ComponentPropsWithoutRef<"button">, "onClick"> & ReceizReactClientOptions & {
65
+ body: TwinPromotionApprovalInput;
66
+ onSaved?: (response: JsonObject) => void;
67
+ children?: ReactNode;
68
+ };
69
+ export declare function useReceizIdentity(options?: ReceizIdentityHookOptions): ReceizIdentityHook;
70
+ export declare function useReceizCheckout(options?: ReceizReactClientOptions): ReceizCheckoutHook;
71
+ export declare function useReceizAppState<TData extends JsonObject = JsonObject>(options?: ReceizAppStateHookOptions<TData>): ReceizAppStateHook<TData>;
72
+ export declare function useReceizMedia(options?: ReceizReactClientOptions): ReceizMediaHook;
73
+ export declare function ReceizIdentityButton(props: ReceizIdentityButtonProps): ReactElement;
74
+ export declare function ReceizCheckoutButton(props: ReceizCheckoutButtonProps): ReactElement;
75
+ export declare function ReceizWalletBalance(props: ReceizWalletBalanceProps): ReactElement;
76
+ export declare function ReceizMediaUploader(props: ReceizMediaUploaderProps): ReactElement;
77
+ export declare function ReceizDomainConnector(props: ReceizDomainConnectorProps): ReactElement;
78
+ export declare function ReceizTwinWriter(props: ReceizTwinWriterProps): ReactElement;
79
+ export {};
80
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"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"}
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,20 +1,20 @@
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
 
7
7
  ## Self-Debug First
8
8
 
9
9
  ```ts
10
- import { createReceizClient } from "@receiz/sdk";
10
+ import { RECEIZ_OIDC_SCOPES_BY_RAIL, createReceizClient, receizOidcScopesForRails } from "@receiz/sdk";
11
11
 
12
12
  const receiz = createReceizClient({ accessToken });
13
13
 
14
14
  const doctor = await receiz.doctor({
15
15
  tenantHost: "bjklock.receiz.app",
16
16
  callbackUrl: "https://bjklock.receiz.app/api/auth/receiz/callback",
17
- scopes: ["openid", "profile", "receiz:record", "receiz:wallet.read"],
17
+ scopes: receizOidcScopesForRails("identity", "customers", "merchants", "publicStore", "commerce"),
18
18
  });
19
19
 
20
20
  if (!doctor.ok) {
@@ -22,34 +22,71 @@ if (!doctor.ok) {
22
22
  }
23
23
 
24
24
  const caps = await receiz.capabilities({ tenantHost: "bjklock.receiz.app" });
25
- if (!caps.capabilities.commerce.available) {
25
+ if (!caps.capabilities.customers.available || !caps.capabilities.merchants.available || !caps.capabilities.commerce.available) {
26
26
  // Hide checkout setup or show the exact Connect fix.
27
27
  }
28
+
29
+ console.log(RECEIZ_OIDC_SCOPES_BY_RAIL.publicStore);
28
30
  ```
29
31
 
30
32
  ## Publish And Resolve Tenant State
31
33
 
32
34
  ```ts
33
- await receiz.appState.publish({
35
+ await receiz.publicStore.publish({
34
36
  tenantHost: "bjklock.receiz.app",
35
- creatorReceizId: "bjklock.receiz.id",
37
+ merchantReceizId: "bjklock.receiz.id",
36
38
  title: "BJ Klock storefront",
37
- state: { storeStateRecord },
39
+ state: storeStateRecord,
38
40
  idempotencyKey: `storefront:${storeStateRecord.updatedKaiUpulse}`,
39
41
  });
40
42
 
41
- const restored = await createReceizClient().appState.resolve<{
42
- storeStateRecord: StoreStateRecord;
43
- }>({
43
+ const restored = await createReceizClient().publicStore.resolve<StoreStateRecord>({
44
44
  host: "bjklock.receiz.app",
45
- requiredDataKey: "storeStateRecord",
46
45
  });
47
46
 
48
- if (restored.ok && restored.data) {
49
- renderStorefront(restored.data.storeStateRecord);
47
+ if (restored.ok && restored.storeStateRecord) {
48
+ renderStorefront(restored.storeStateRecord);
50
49
  }
51
50
  ```
52
51
 
52
+ `receiz.appState.publish()` and `receiz.appState.resolve()` remain available for custom app projections. `receiz.publicStore.*` is the first-party commerce-store namespace so every storefront uses the same public projection envelope.
53
+
54
+ ## Local-First Dogfood Recipes
55
+
56
+ ```ts
57
+ const runtime = await receiz.runtime.localFirst({
58
+ ownerId: "bjklock.receiz.id",
59
+ storage: receiz.proofMemory.createLocalStorage("receiz:profile:bjklock"),
60
+ seed: [identityRecord, currentProfileManifest],
61
+ sync: (knownHead) => fetchVerifiedAdditionsAfter(knownHead),
62
+ limit: 100,
63
+ });
64
+
65
+ const profile = await receiz.profile.resolveLocalFirst({
66
+ memory: runtime.memory,
67
+ local: admittedProfileTruth,
68
+ sync: (knownHead) => fetchVerifiedProfileAdditions(knownHead),
69
+ });
70
+
71
+ const wallet = await receiz.wallet.resolveLedger({
72
+ memory: runtime.memory,
73
+ local: admittedWalletLedger,
74
+ sync: (knownHead) => fetchVerifiedLedgerAdditions(knownHead),
75
+ });
76
+
77
+ const cardMemory = await receiz.sports.resolveCardMemory({
78
+ memory: runtime.memory,
79
+ local: admittedSportsCardMemory,
80
+ sync: (knownHead) => fetchVerifiedSportsAdditions(knownHead),
81
+ });
82
+
83
+ const pitchDay = await receiz.sports.resolvePitchDayProof({
84
+ local: admittedPitchDayProof,
85
+ });
86
+ ```
87
+
88
+ These recipes are for dogfooding `@receiz/sdk` inside Receiz later without making the SDK a truth authority. If `local` exists, the recipe returns it immediately and starts append sync after the known head. `remote` is only used when local truth is absent.
89
+
53
90
  ## One-Click Checkout
54
91
 
55
92
  ```ts
@@ -70,6 +107,56 @@ if (checkout.checkoutSession?.clientSecret) {
70
107
 
71
108
  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
109
 
110
+ ## Enterprise Commerce
111
+
112
+ ```ts
113
+ await receiz.customers.session({
114
+ tenantHost: "bjklock.receiz.app",
115
+ customerReceizId: "customer.receiz.id",
116
+ scopes: ["orders", "rewards", "assets"],
117
+ }, { idempotencyKey: "customer-session:v1" });
118
+
119
+ const tenantSession = await receiz.customers.bootstrapSession({
120
+ tenantHost: "bjklock.receiz.app",
121
+ customerReceizId: "customer.receiz.id",
122
+ scopes: ["orders", "rewards", "assets"],
123
+ }, { idempotencyKey: "customer-session:v1" });
124
+
125
+ renderCustomerAccount({
126
+ session: tenantSession.session,
127
+ wallet: tenantSession.wallet,
128
+ customer: tenantSession.customer,
129
+ permissions: tenantSession.permissions,
130
+ });
131
+
132
+ const hostedIdentity = receiz.identity.ensureTenantSession({
133
+ tenantHost: "bjklock.receiz.app",
134
+ returnTo: "https://bjklock.receiz.app/account",
135
+ fallback: "artifact_upload",
136
+ });
137
+
138
+ await receiz.merchants.onboard({
139
+ tenantHost: "bjklock.receiz.app",
140
+ receizId: "bjklock.receiz.id",
141
+ displayName: "BJ Klock",
142
+ defaultStore: { title: "BJ Klock Store" },
143
+ }, { idempotencyKey: "merchant:bjklock:v1" });
144
+
145
+ await receiz.commerce.inventory.reserve({
146
+ tenantHost: "bjklock.receiz.app",
147
+ sku: "hat-black",
148
+ quantity: 2,
149
+ }, { idempotencyKey: "inventory:hat-black:cart-123" });
150
+
151
+ await receiz.commerce.fulfillment.update({
152
+ tenantHost: "bjklock.receiz.app",
153
+ orderId: "order_123",
154
+ status: "shipped",
155
+ }, { idempotencyKey: "fulfillment:order_123:shipped" });
156
+ ```
157
+
158
+ 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.
159
+
73
160
  ## Media, Domains, Events, Search, And Jobs
74
161
 
75
162
  ```ts
@@ -102,6 +189,84 @@ await receiz.jobs.enqueue({
102
189
  payload: { mediaId: logo.media?.id },
103
190
  idempotencyKey: "media.process:logo:v1",
104
191
  });
192
+
193
+ await receiz.media.transform({
194
+ tenantHost: "bjklock.receiz.app",
195
+ mediaId: String(logo.media?.id),
196
+ resize: { width: 1200 },
197
+ optimize: { format: "webp" },
198
+ blurPlaceholder: true,
199
+ altText: "Store logo",
200
+ }, { idempotencyKey: "media.transform:logo:v1" });
201
+
202
+ await receiz.events.replay({
203
+ tenantHost: "bjklock.receiz.app",
204
+ types: ["order.created", "payment.settled"],
205
+ since: "2026-06-01T00:00:00.000Z",
206
+ });
207
+ ```
208
+
209
+ ## Permissions, Audit, Risk, Compliance, And Portability
210
+
211
+ ```ts
212
+ await receiz.permissions.grant({
213
+ tenantHost: "bjklock.receiz.app",
214
+ actorReceizId: "staff.receiz.id",
215
+ role: "fulfillment",
216
+ }, { idempotencyKey: "grant:staff:fulfillment" });
217
+
218
+ await receiz.audit.append({
219
+ tenantHost: "bjklock.receiz.app",
220
+ action: "product.updated",
221
+ actorReceizId: "bjklock.receiz.id",
222
+ }, { idempotencyKey: "audit:product:update:123" });
223
+
224
+ const risk = await receiz.risk.scorePayment({
225
+ tenantHost: "bjklock.receiz.app",
226
+ orderId: "order_123",
227
+ amountUsd: "42.00",
228
+ });
229
+
230
+ const orders = await receiz.compliance.exportOrders({
231
+ tenantHost: "bjklock.receiz.app",
232
+ from: "2026-06-01",
233
+ to: "2026-06-30",
234
+ });
235
+
236
+ const portableStore = await receiz.portability.exportStore({
237
+ tenantHost: "bjklock.receiz.app",
238
+ });
239
+ ```
240
+
241
+ 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.
242
+
243
+ ## Offline Queue And Release Pinning
244
+
245
+ ```ts
246
+ const storage = receiz.offline.createLocalStorage("receiz:queue:bjklock");
247
+ const queue = await receiz.offline.createQueue({
248
+ ownerId: "bjklock.receiz.id",
249
+ storage,
250
+ });
251
+
252
+ queue.enqueue({
253
+ id: "store-state:offline-1",
254
+ kind: "app_state.publish",
255
+ payload: {
256
+ tenantHost: "bjklock.receiz.app",
257
+ title: "Offline storefront append",
258
+ state: { storeStateRecord },
259
+ },
260
+ idempotencyKey: "store-state:offline-1",
261
+ });
262
+ await queue.flush();
263
+
264
+ await queue.replay(receiz);
265
+
266
+ await receiz.releases.pin({
267
+ tenantHost: "bjklock.receiz.app",
268
+ rails: { appState: "v1", commerce: "v1", media: "v1" },
269
+ }, { idempotencyKey: "rails:pin:v1" });
105
270
  ```
106
271
 
107
272
  ## 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.3.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"
@@ -40,6 +44,21 @@
40
44
  "sdk"
41
45
  ],
42
46
  "license": "MIT",
47
+ "peerDependencies": {
48
+ "react": ">=18.0.0 <20.0.0"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "react": {
52
+ "optional": true
53
+ }
54
+ },
55
+ "devDependencies": {
56
+ "@types/node": "^20",
57
+ "@types/react": "^19",
58
+ "react": "19.2.3",
59
+ "tsx": "^4.20.4",
60
+ "typescript": "^5.9.3"
61
+ },
43
62
  "publishConfig": {
44
63
  "access": "public"
45
64
  }