@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.
- package/README.md +93 -5
- package/dist/index.d.ts +391 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +633 -2
- package/dist/react.d.ts +80 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +200 -0
- package/docs/app-runtime-commerce-cloud.md +178 -13
- package/package.json +20 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,46 @@
|
|
|
1
1
|
import { buildReceizIdContinueRequest, createReceizIdIdentity, projectReceizIdentityAccount, readReceizIdentityArtifact, signReceizIdentityLoginProof, verifyReceizIdentityLoginProof, } from "./identity.js";
|
|
2
2
|
export * from "./identity.js";
|
|
3
|
-
export const RECEIZ_SDK_VERSION = "97.
|
|
3
|
+
export const RECEIZ_SDK_VERSION = "97.3.0";
|
|
4
4
|
export const RECEIZ_DEFAULT_BASE_URL = "https://receiz.com";
|
|
5
5
|
export const RECEIZ_WEBHOOK_SIGNATURE_HEADER = "x-receiz-signature";
|
|
6
6
|
export const RECEIZ_WEBHOOK_TIMESTAMP_HEADER = "x-receiz-timestamp";
|
|
7
7
|
export const RECEIZ_APP_STATE_FEED_SCHEMA = "receiz.app.public_state_registry_feed.v1";
|
|
8
8
|
export const RECEIZ_PUBLIC_STORE_STATE_FEED_SCHEMA = "receiz.app.public_store_state_registry_feed.v1";
|
|
9
9
|
export const RECEIZ_PUBLIC_STORE_STATE_PROJECTION_SCHEMA = "receiz.app.public_store_state_projection.v1";
|
|
10
|
+
export const RECEIZ_OIDC_SCOPES_BY_RAIL = {
|
|
11
|
+
identity: ["openid", "profile", "email"],
|
|
12
|
+
wallet: ["receiz:wallet.read", "receiz:wallet.transfer"],
|
|
13
|
+
payments: ["receiz:payments.read", "receiz:payments.create"],
|
|
14
|
+
proofStore: ["receiz:record", "receiz:seal", "receiz:verify"],
|
|
15
|
+
media: ["receiz:record"],
|
|
16
|
+
domains: ["receiz:record"],
|
|
17
|
+
twin: ["receiz:twin.read", "receiz:twin.write"],
|
|
18
|
+
commerce: ["receiz:payments.read", "receiz:payments.create", "receiz:wallet.read", "receiz:record"],
|
|
19
|
+
rewards: ["receiz:record", "receiz:wallet.read"],
|
|
20
|
+
customers: ["openid", "profile", "email", "offline_access", "receiz:wallet.read", "receiz:payments.read"],
|
|
21
|
+
merchants: ["openid", "profile", "email", "offline_access", "receiz:record", "receiz:wallet.read", "receiz:payments.read", "receiz:payments.create"],
|
|
22
|
+
events: ["receiz:record"],
|
|
23
|
+
search: ["receiz:record"],
|
|
24
|
+
permissions: ["receiz:record"],
|
|
25
|
+
jobs: ["receiz:record"],
|
|
26
|
+
audit: ["receiz:record"],
|
|
27
|
+
risk: ["receiz:record"],
|
|
28
|
+
compliance: ["receiz:record"],
|
|
29
|
+
portability: ["receiz:record"],
|
|
30
|
+
notifications: ["receiz:record"],
|
|
31
|
+
offline: ["receiz:record"],
|
|
32
|
+
releases: ["receiz:record"],
|
|
33
|
+
appState: ["receiz:record"],
|
|
34
|
+
publicStore: ["receiz:record"],
|
|
35
|
+
};
|
|
36
|
+
export function receizOidcScopesForRails(...rails) {
|
|
37
|
+
const scopes = new Set();
|
|
38
|
+
for (const rail of rails) {
|
|
39
|
+
for (const scope of RECEIZ_OIDC_SCOPES_BY_RAIL[rail] ?? [])
|
|
40
|
+
scopes.add(scope);
|
|
41
|
+
}
|
|
42
|
+
return [...scopes];
|
|
43
|
+
}
|
|
10
44
|
export const RECEIZ_ASSET_MANIFEST_SCHEMA = {
|
|
11
45
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
12
46
|
$id: "https://receiz.com/standards/receiz.asset-manifest.schema.v1.json",
|
|
@@ -268,6 +302,19 @@ function headersWithIdempotency(headers, idempotencyKey) {
|
|
|
268
302
|
next.set("idempotency-key", idempotencyKey);
|
|
269
303
|
return next;
|
|
270
304
|
}
|
|
305
|
+
function queryParams(input) {
|
|
306
|
+
const params = {};
|
|
307
|
+
for (const [key, value] of Object.entries(input)) {
|
|
308
|
+
if (value === null ||
|
|
309
|
+
value === undefined ||
|
|
310
|
+
typeof value === "string" ||
|
|
311
|
+
typeof value === "number" ||
|
|
312
|
+
typeof value === "boolean") {
|
|
313
|
+
params[key] = value;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return params;
|
|
317
|
+
}
|
|
271
318
|
function usdToCents(value) {
|
|
272
319
|
const trimmed = value.trim();
|
|
273
320
|
if (!/^\d+(\.\d{1,2})?$/.test(trimmed))
|
|
@@ -577,6 +624,12 @@ export class ReceizClient {
|
|
|
577
624
|
extractData: extractReceizAppStateData,
|
|
578
625
|
restoreProjection: restoreReceizAppStateProjection,
|
|
579
626
|
};
|
|
627
|
+
publicStore = {
|
|
628
|
+
publish: (input, options = {}) => this.publishPublicStore(input, options),
|
|
629
|
+
resolve: (input) => this.resolvePublicStore(input),
|
|
630
|
+
createRecord: createReceizPublicStoreStateRecord,
|
|
631
|
+
scopes: RECEIZ_OIDC_SCOPES_BY_RAIL.publicStore,
|
|
632
|
+
};
|
|
580
633
|
sports = {
|
|
581
634
|
conformance: () => this.sportsConformance(),
|
|
582
635
|
conformanceHistory: () => this.request("/api/game/sports/conformance/history"),
|
|
@@ -584,10 +637,16 @@ export class ReceizClient {
|
|
|
584
637
|
badge: () => this.request("/api/game/sports/conformance/badge"),
|
|
585
638
|
eventProofUrl: (eventProofId) => `${this.baseUrl}/game/sports/event/${encodePathSegment(eventProofId)}`,
|
|
586
639
|
assertCardManifest: assertReceizSportsCardManifest,
|
|
640
|
+
resolveCardMemory: (input) => this.resolveLocalFirstSurface("sports.card_memory", input),
|
|
641
|
+
resolvePitchDayProof: (input) => this.resolveLocalFirstSurface("sports.pitch_day_proof", input),
|
|
587
642
|
};
|
|
588
643
|
wallet = {
|
|
589
644
|
publicLedger: (query = {}) => this.publicWalletLedger(query),
|
|
590
645
|
actionLedger: (query = {}) => this.request(appendQuery("/api/ledger/actions/public", query)),
|
|
646
|
+
resolveLedger: (input) => this.resolveLocalFirstSurface("wallet.ledger", input),
|
|
647
|
+
};
|
|
648
|
+
profile = {
|
|
649
|
+
resolveLocalFirst: (input) => this.resolveLocalFirstSurface("profile", input),
|
|
591
650
|
};
|
|
592
651
|
world = {
|
|
593
652
|
publicSnapshot: () => this.request("/api/world/public"),
|
|
@@ -676,9 +735,61 @@ export class ReceizClient {
|
|
|
676
735
|
}),
|
|
677
736
|
bootstrap: (username) => this.request(`/api/connect/login/bootstrap/${encodePathSegment(username)}`),
|
|
678
737
|
authorizeUrl: (options) => this.authorizeUrl(options),
|
|
738
|
+
ensureTenantSession: (input) => this.ensureTenantSession(input),
|
|
739
|
+
};
|
|
740
|
+
customers = {
|
|
741
|
+
bootstrapSession: (body, options = {}) => this.bootstrapCustomerSession(body, options),
|
|
742
|
+
bootstrap: (body, options = {}) => this.bootstrapCustomerSession(body, options),
|
|
743
|
+
session: (body, options = {}) => this.delegatedWrite("/api/connect/customers/session", body, options),
|
|
744
|
+
portal: (body) => this.delegatedWrite("/api/connect/customers/portal", body),
|
|
745
|
+
orders: (query = {}) => this.delegated(appendQuery("/api/connect/customers/orders", queryParams(query))),
|
|
746
|
+
rewards: (query = {}) => this.delegated(appendQuery("/api/connect/customers/rewards", queryParams(query))),
|
|
747
|
+
assets: (query = {}) => this.delegated(appendQuery("/api/connect/customers/assets", queryParams(query))),
|
|
748
|
+
};
|
|
749
|
+
merchants = {
|
|
750
|
+
onboard: (body, options = {}) => this.delegatedWrite("/api/connect/merchants/onboard", body, options),
|
|
751
|
+
profile: (query = {}) => this.delegated(appendQuery("/api/connect/merchants/profile", query)),
|
|
752
|
+
capabilities: (query = {}) => this.delegated(appendQuery("/api/connect/merchants/capabilities", query)),
|
|
679
753
|
};
|
|
680
754
|
commerce = {
|
|
681
755
|
oneClickCheckout: (body) => this.oneClickCheckout(body),
|
|
756
|
+
refunds: {
|
|
757
|
+
create: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/refunds", body, options),
|
|
758
|
+
},
|
|
759
|
+
subscriptions: {
|
|
760
|
+
create: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/subscriptions", body, options),
|
|
761
|
+
cancel: (subscriptionId, body, options = {}) => this.delegatedWrite(`/api/connect/commerce/subscriptions/${encodePathSegment(subscriptionId)}/cancel`, body, options),
|
|
762
|
+
},
|
|
763
|
+
shipping: {
|
|
764
|
+
quote: (body) => this.delegatedWrite("/api/connect/commerce/shipping/quote", body),
|
|
765
|
+
update: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/shipping/update", body, options),
|
|
766
|
+
},
|
|
767
|
+
tax: {
|
|
768
|
+
quote: (body) => this.delegatedWrite("/api/connect/commerce/tax/quote", body),
|
|
769
|
+
},
|
|
770
|
+
discounts: {
|
|
771
|
+
create: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/discounts", body, options),
|
|
772
|
+
redeem: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/discounts/redeem", body, options),
|
|
773
|
+
},
|
|
774
|
+
giftCards: {
|
|
775
|
+
issue: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/gift-cards", body, options),
|
|
776
|
+
redeem: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/gift-cards/redeem", body, options),
|
|
777
|
+
},
|
|
778
|
+
accessPasses: {
|
|
779
|
+
issue: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/access-passes", body, options),
|
|
780
|
+
verify: (body) => this.delegatedWrite("/api/connect/commerce/access-passes/verify", body),
|
|
781
|
+
},
|
|
782
|
+
inventory: {
|
|
783
|
+
reserve: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/inventory/reserve", body, options),
|
|
784
|
+
adjust: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/inventory/adjust", body, options),
|
|
785
|
+
},
|
|
786
|
+
fulfillment: {
|
|
787
|
+
update: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/fulfillment", body, options),
|
|
788
|
+
},
|
|
789
|
+
payouts: {
|
|
790
|
+
create: (body, options = {}) => this.delegatedWrite("/api/connect/commerce/payouts", body, options),
|
|
791
|
+
status: (query = {}) => this.delegated(appendQuery("/api/connect/commerce/payouts/status", query)),
|
|
792
|
+
},
|
|
682
793
|
};
|
|
683
794
|
payments = {
|
|
684
795
|
embeddedCheckout: (body) => this.request("/api/payments/embed/checkout", { method: "POST", body }),
|
|
@@ -686,6 +797,7 @@ export class ReceizClient {
|
|
|
686
797
|
};
|
|
687
798
|
media = {
|
|
688
799
|
upload: (file, options = {}) => this.uploadMedia(file, options),
|
|
800
|
+
transform: (body, options = {}) => this.delegatedWrite("/api/connect/media/transform", body, options),
|
|
689
801
|
objectUrl: (query) => appendQuery(`${this.baseUrl}/api/storage/object`, query),
|
|
690
802
|
};
|
|
691
803
|
domains = {
|
|
@@ -708,6 +820,9 @@ export class ReceizClient {
|
|
|
708
820
|
};
|
|
709
821
|
events = {
|
|
710
822
|
subscribe: (body) => this.eventSubscribe(body),
|
|
823
|
+
replay: (body) => this.delegatedWrite("/api/connect/events/replay", body),
|
|
824
|
+
list: (query = {}) => this.delegated(appendQuery("/api/connect/events", queryParams(query))),
|
|
825
|
+
ack: (eventId, body = {}) => this.delegatedWrite(`/api/connect/events/${encodePathSegment(eventId)}/ack`, body),
|
|
711
826
|
};
|
|
712
827
|
proof = {
|
|
713
828
|
query: (query) => this.delegated("/api/connect/proof/query", { method: "POST", body: query }),
|
|
@@ -718,6 +833,56 @@ export class ReceizClient {
|
|
|
718
833
|
body: bodyWithIdempotency(body, body.idempotencyKey),
|
|
719
834
|
headers: headersWithIdempotency(undefined, body.idempotencyKey),
|
|
720
835
|
}),
|
|
836
|
+
status: (jobId) => this.delegated(`/api/connect/jobs/${encodePathSegment(jobId)}`),
|
|
837
|
+
cancel: (jobId, body = {}) => this.delegatedWrite(`/api/connect/jobs/${encodePathSegment(jobId)}/cancel`, body),
|
|
838
|
+
list: (query = {}) => this.delegated(appendQuery("/api/connect/jobs", queryParams(query))),
|
|
839
|
+
};
|
|
840
|
+
permissions = {
|
|
841
|
+
grant: (body, options = {}) => this.delegatedWrite("/api/connect/permissions/grants", body, options),
|
|
842
|
+
revoke: (body, options = {}) => this.delegatedWrite("/api/connect/permissions/revoke", body, options),
|
|
843
|
+
check: (body) => this.delegatedWrite("/api/connect/permissions/check", body),
|
|
844
|
+
roles: (query = {}) => this.delegated(appendQuery("/api/connect/permissions/roles", query)),
|
|
845
|
+
};
|
|
846
|
+
audit = {
|
|
847
|
+
append: (body, options = {}) => this.delegatedWrite("/api/connect/audit/events", body, options),
|
|
848
|
+
query: (query = {}) => this.delegated(appendQuery("/api/connect/audit/events", queryParams(query))),
|
|
849
|
+
export: (query = {}) => this.delegated(appendQuery("/api/connect/audit/export", queryParams(query))),
|
|
850
|
+
};
|
|
851
|
+
risk = {
|
|
852
|
+
scorePayment: (body) => this.delegatedWrite("/api/connect/risk/payment", body),
|
|
853
|
+
scoreAccountRecovery: (body) => this.delegatedWrite("/api/connect/risk/account-recovery", body),
|
|
854
|
+
velocity: (body) => this.delegatedWrite("/api/connect/risk/velocity", body),
|
|
855
|
+
proofActivity: (body) => this.delegatedWrite("/api/connect/risk/proof-activity", body),
|
|
856
|
+
};
|
|
857
|
+
compliance = {
|
|
858
|
+
exportOrders: (query) => this.delegated(appendQuery("/api/connect/compliance/orders", queryParams(query))),
|
|
859
|
+
exportTaxes: (query) => this.delegated(appendQuery("/api/connect/compliance/taxes", queryParams(query))),
|
|
860
|
+
exportPayouts: (query) => this.delegated(appendQuery("/api/connect/compliance/payouts", queryParams(query))),
|
|
861
|
+
exportCustomers: (query) => this.delegated(appendQuery("/api/connect/compliance/customers", queryParams(query))),
|
|
862
|
+
exportAudit: (query) => this.delegated(appendQuery("/api/connect/compliance/audit", queryParams(query))),
|
|
863
|
+
};
|
|
864
|
+
portability = {
|
|
865
|
+
exportStore: (query) => this.delegated(appendQuery("/api/connect/portability/store/export", query)),
|
|
866
|
+
importStore: (body, options = {}) => this.delegatedWrite("/api/connect/portability/store/import", body, options),
|
|
867
|
+
};
|
|
868
|
+
search = {
|
|
869
|
+
query: (body) => this.delegatedWrite("/api/connect/search/query", body),
|
|
870
|
+
products: (body) => this.delegatedWrite("/api/connect/search/products", body),
|
|
871
|
+
pages: (body) => this.delegatedWrite("/api/connect/search/pages", body),
|
|
872
|
+
blog: (body) => this.delegatedWrite("/api/connect/search/blog", body),
|
|
873
|
+
orders: (body) => this.delegatedWrite("/api/connect/search/orders", body),
|
|
874
|
+
customers: (body) => this.delegatedWrite("/api/connect/search/customers", body),
|
|
875
|
+
proofObjects: (body) => this.delegatedWrite("/api/connect/search/proof-objects", body),
|
|
876
|
+
};
|
|
877
|
+
notifications = {
|
|
878
|
+
send: (body, options = {}) => this.delegatedWrite("/api/connect/notifications/send", body, options),
|
|
879
|
+
subscribe: (body, options = {}) => this.delegatedWrite("/api/connect/notifications/subscribe", body, options),
|
|
880
|
+
templates: (query = {}) => this.delegated(appendQuery("/api/connect/notifications/templates", query)),
|
|
881
|
+
};
|
|
882
|
+
releases = {
|
|
883
|
+
pin: (body, options = {}) => this.delegatedWrite("/api/connect/releases/pin", body, options),
|
|
884
|
+
check: (query = {}) => this.delegated(appendQuery("/api/connect/releases/check", query)),
|
|
885
|
+
supported: () => this.request("/api/releases/rails/supported"),
|
|
721
886
|
};
|
|
722
887
|
webhooks = {
|
|
723
888
|
sign: createReceizWebhookSignature,
|
|
@@ -775,6 +940,16 @@ export class ReceizClient {
|
|
|
775
940
|
createLocalStorage: createReceizLocalStorageProofMemoryStorage,
|
|
776
941
|
assertSnapshot: assertReceizProofRegisterSnapshot,
|
|
777
942
|
additionsQuery: receizProofMemoryAdditionsQuery,
|
|
943
|
+
syncAdditions: (input) => this.syncProofMemoryAdditions(input),
|
|
944
|
+
};
|
|
945
|
+
runtime = {
|
|
946
|
+
localFirst: (input = {}) => this.runtimeLocalFirst(input),
|
|
947
|
+
};
|
|
948
|
+
offline = {
|
|
949
|
+
createQueue: createReceizOfflineProofQueue,
|
|
950
|
+
createInMemoryStorage: createReceizInMemoryOfflineProofQueueStorage,
|
|
951
|
+
createLocalStorage: createReceizLocalStorageOfflineProofQueueStorage,
|
|
952
|
+
assertSnapshot: assertReceizOfflineProofQueueSnapshot,
|
|
778
953
|
};
|
|
779
954
|
constructor(options = {}) {
|
|
780
955
|
this.baseUrl = trimTrailingSlash(options.baseUrl ?? RECEIZ_DEFAULT_BASE_URL);
|
|
@@ -831,12 +1006,14 @@ export class ReceizClient {
|
|
|
831
1006
|
const tenantHost = options.tenantHost ? normalizeReceizHost(options.tenantHost) : undefined;
|
|
832
1007
|
const scopes = options.scopes ?? [];
|
|
833
1008
|
const delegatedAvailable = Boolean(this.accessToken);
|
|
834
|
-
const configured = (available, reason) => ({
|
|
1009
|
+
const configured = (available, reason, requirements) => ({
|
|
835
1010
|
available,
|
|
836
1011
|
status: available ? "available" : "missing",
|
|
837
1012
|
...(reason ? { reason } : {}),
|
|
838
1013
|
...(!available ? { fixUrl: `${this.baseUrl}/developers` } : {}),
|
|
1014
|
+
...(requirements ? { requirements } : {}),
|
|
839
1015
|
});
|
|
1016
|
+
const tenantAndBearer = { tenantHost: true, accessToken: true };
|
|
840
1017
|
return {
|
|
841
1018
|
ok: true,
|
|
842
1019
|
schema: "receiz.sdk.capabilities.v1",
|
|
@@ -853,10 +1030,19 @@ export class ReceizClient {
|
|
|
853
1030
|
twin: configured(delegatedAvailable, "Connect bearer token required for Twin routes."),
|
|
854
1031
|
commerce: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for commerce helpers."),
|
|
855
1032
|
rewards: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for reward routes."),
|
|
1033
|
+
customers: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for customer sessions.", tenantAndBearer),
|
|
1034
|
+
merchants: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for merchant rails.", tenantAndBearer),
|
|
856
1035
|
events: configured(delegatedAvailable, "Connect bearer token required for event subscriptions."),
|
|
857
1036
|
search: configured(delegatedAvailable, "Connect bearer token required for private proof search."),
|
|
858
1037
|
permissions: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for tenant permissions."),
|
|
859
1038
|
jobs: configured(delegatedAvailable, "Connect bearer token required for durable jobs."),
|
|
1039
|
+
audit: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for sealed tenant audit events."),
|
|
1040
|
+
risk: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for risk signals."),
|
|
1041
|
+
compliance: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for compliance exports."),
|
|
1042
|
+
portability: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for store portability."),
|
|
1043
|
+
notifications: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for notifications."),
|
|
1044
|
+
offline: configured(true),
|
|
1045
|
+
releases: configured(delegatedAvailable && Boolean(tenantHost), "Connect bearer token and tenantHost are required for release rail pinning."),
|
|
860
1046
|
},
|
|
861
1047
|
};
|
|
862
1048
|
}
|
|
@@ -1011,6 +1197,167 @@ export class ReceizClient {
|
|
|
1011
1197
|
}
|
|
1012
1198
|
throw new ReceizValidationError("receiz.appState.resolve", ["id, url, host, tenantHost, namespace, creatorReceizId, or receizId is required"]);
|
|
1013
1199
|
}
|
|
1200
|
+
async publishPublicStore(input, options = {}) {
|
|
1201
|
+
const tenantHost = normalizeReceizHost(input.tenantHost);
|
|
1202
|
+
const sourceUrl = input.sourceUrl ?? receizAppStateUrlFromHost(tenantHost);
|
|
1203
|
+
const publicStoreRecordInput = {
|
|
1204
|
+
sourceUrl,
|
|
1205
|
+
externalCreatorId: input.merchantReceizId,
|
|
1206
|
+
title: input.title ?? `${tenantHost} storefront`,
|
|
1207
|
+
namespace: input.namespace ?? tenantHost,
|
|
1208
|
+
state: input.projectionState ?? "published",
|
|
1209
|
+
schema: input.schema ?? RECEIZ_PUBLIC_STORE_STATE_PROJECTION_SCHEMA,
|
|
1210
|
+
platform: input.platform ?? "Receiz.app Commerce Cloud",
|
|
1211
|
+
record: input.record ?? input.state,
|
|
1212
|
+
data: input.data ?? {
|
|
1213
|
+
storeStateRecord: input.state,
|
|
1214
|
+
tenantHost,
|
|
1215
|
+
merchantReceizId: input.merchantReceizId,
|
|
1216
|
+
},
|
|
1217
|
+
};
|
|
1218
|
+
if (input.id)
|
|
1219
|
+
publicStoreRecordInput.id = input.id;
|
|
1220
|
+
const record = createReceizPublicStoreStateRecord(publicStoreRecordInput);
|
|
1221
|
+
const feedOptions = {
|
|
1222
|
+
schema: RECEIZ_PUBLIC_STORE_STATE_FEED_SCHEMA,
|
|
1223
|
+
externalCreatorId: input.merchantReceizId,
|
|
1224
|
+
};
|
|
1225
|
+
if (record.namespace)
|
|
1226
|
+
feedOptions.namespace = record.namespace;
|
|
1227
|
+
const publishOptions = {};
|
|
1228
|
+
const idempotencyKey = options.idempotencyKey ?? input.idempotencyKey;
|
|
1229
|
+
if (idempotencyKey)
|
|
1230
|
+
publishOptions.idempotencyKey = idempotencyKey;
|
|
1231
|
+
return this.publishAppState(createReceizAppStateFeed([record], feedOptions), publishOptions);
|
|
1232
|
+
}
|
|
1233
|
+
async resolvePublicStore(input) {
|
|
1234
|
+
const options = {
|
|
1235
|
+
schema: RECEIZ_PUBLIC_STORE_STATE_PROJECTION_SCHEMA,
|
|
1236
|
+
state: "published",
|
|
1237
|
+
requiredDataKey: "storeStateRecord",
|
|
1238
|
+
};
|
|
1239
|
+
let restored;
|
|
1240
|
+
if (input.id) {
|
|
1241
|
+
restored = await this.restoreAppStateById(input.id, options);
|
|
1242
|
+
}
|
|
1243
|
+
else if (input.url) {
|
|
1244
|
+
restored = await this.restoreAppStateByUrl(input.url, options);
|
|
1245
|
+
}
|
|
1246
|
+
else {
|
|
1247
|
+
const host = input.host ?? input.tenantHost;
|
|
1248
|
+
if (!host)
|
|
1249
|
+
throw new ReceizValidationError("receiz.publicStore.resolve", ["host, tenantHost, url, or id is required"]);
|
|
1250
|
+
restored = await this.restoreAppStateByHost(host, options);
|
|
1251
|
+
}
|
|
1252
|
+
const storeStateRecord = restored.data?.storeStateRecord ?? null;
|
|
1253
|
+
return {
|
|
1254
|
+
...restored,
|
|
1255
|
+
state: storeStateRecord,
|
|
1256
|
+
storeStateRecord,
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
async syncProofMemoryAdditions(input) {
|
|
1260
|
+
const knownHead = input.memory.knownHead(input.limit);
|
|
1261
|
+
const batch = await input.fetchAdditions(knownHead);
|
|
1262
|
+
let admitted = 0;
|
|
1263
|
+
for (const addition of proofMemoryAdditionValues(batch)) {
|
|
1264
|
+
admitProofMemoryAddition(input.memory, addition);
|
|
1265
|
+
admitted += 1;
|
|
1266
|
+
}
|
|
1267
|
+
await input.memory.flush();
|
|
1268
|
+
return {
|
|
1269
|
+
ok: true,
|
|
1270
|
+
schema: "receiz.sdk.proof_memory.sync.v1",
|
|
1271
|
+
knownHead,
|
|
1272
|
+
admitted,
|
|
1273
|
+
snapshot: input.memory.snapshot(),
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
async resolveLocalFirstSurface(surface, input) {
|
|
1277
|
+
const local = input.local ?? null;
|
|
1278
|
+
const snapshot = input.memory?.snapshot() ?? null;
|
|
1279
|
+
const knownHead = input.memory ? input.memory.knownHead(input.limit) : null;
|
|
1280
|
+
const sync = input.memory && input.sync
|
|
1281
|
+
? this.syncProofMemoryAdditions({
|
|
1282
|
+
memory: input.memory,
|
|
1283
|
+
fetchAdditions: input.sync,
|
|
1284
|
+
...(input.limit === undefined ? {} : { limit: input.limit }),
|
|
1285
|
+
})
|
|
1286
|
+
: null;
|
|
1287
|
+
if (local !== null) {
|
|
1288
|
+
return {
|
|
1289
|
+
ok: true,
|
|
1290
|
+
schema: "receiz.sdk.local_first.v1",
|
|
1291
|
+
surface,
|
|
1292
|
+
source: "local",
|
|
1293
|
+
value: local,
|
|
1294
|
+
local,
|
|
1295
|
+
knownHead,
|
|
1296
|
+
snapshot,
|
|
1297
|
+
sync,
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
const remote = input.remote ? await input.remote() : null;
|
|
1301
|
+
return {
|
|
1302
|
+
ok: true,
|
|
1303
|
+
schema: "receiz.sdk.local_first.v1",
|
|
1304
|
+
surface,
|
|
1305
|
+
source: remote !== null ? "remote" : "empty",
|
|
1306
|
+
value: remote,
|
|
1307
|
+
local,
|
|
1308
|
+
knownHead,
|
|
1309
|
+
snapshot,
|
|
1310
|
+
sync,
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
async runtimeLocalFirst(input = {}) {
|
|
1314
|
+
const memoryOptions = {
|
|
1315
|
+
...(input.ownerId === undefined ? {} : { ownerId: input.ownerId }),
|
|
1316
|
+
...(input.storage === undefined ? {} : { storage: input.storage }),
|
|
1317
|
+
};
|
|
1318
|
+
const memory = await createReceizProofMemory(memoryOptions);
|
|
1319
|
+
for (const proofObject of input.seed ?? [])
|
|
1320
|
+
memory.admit(proofObject);
|
|
1321
|
+
await memory.flush();
|
|
1322
|
+
const knownHead = memory.knownHead(input.limit);
|
|
1323
|
+
const sync = input.sync
|
|
1324
|
+
? this.syncProofMemoryAdditions({
|
|
1325
|
+
memory,
|
|
1326
|
+
fetchAdditions: input.sync,
|
|
1327
|
+
...(input.limit === undefined ? {} : { limit: input.limit }),
|
|
1328
|
+
})
|
|
1329
|
+
: null;
|
|
1330
|
+
return {
|
|
1331
|
+
ok: true,
|
|
1332
|
+
schema: "receiz.sdk.runtime.local_first.v1",
|
|
1333
|
+
memory,
|
|
1334
|
+
snapshot: memory.snapshot(),
|
|
1335
|
+
knownHead,
|
|
1336
|
+
sync,
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
async bootstrapCustomerSession(body, options = {}) {
|
|
1340
|
+
const tenantHost = normalizeReceizHost(body.tenantHost);
|
|
1341
|
+
const requestBody = {
|
|
1342
|
+
...body,
|
|
1343
|
+
tenantHost,
|
|
1344
|
+
};
|
|
1345
|
+
const session = await this.delegatedWrite("/api/connect/customers/session", requestBody, options);
|
|
1346
|
+
const wallet = body.includeWallet === false ? null : await this.delegated("/api/connect/wallet/me");
|
|
1347
|
+
const customer = body.includeCustomer === false ? null : await this.delegatedWrite("/api/connect/customers/portal", requestBody);
|
|
1348
|
+
const permissions = body.includePermissions === false
|
|
1349
|
+
? null
|
|
1350
|
+
: await this.delegated(appendQuery("/api/connect/permissions/roles", { tenantHost }));
|
|
1351
|
+
return {
|
|
1352
|
+
ok: true,
|
|
1353
|
+
schema: "receiz.sdk.customer_session.bootstrap.v1",
|
|
1354
|
+
tenantHost,
|
|
1355
|
+
session,
|
|
1356
|
+
wallet,
|
|
1357
|
+
customer,
|
|
1358
|
+
permissions,
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1014
1361
|
async oneClickCheckout(body) {
|
|
1015
1362
|
const tenantHost = normalizeReceizHost(body.tenantHost);
|
|
1016
1363
|
const totalUsdCents = usdToCents(body.amountUsd);
|
|
@@ -1123,6 +1470,14 @@ export class ReceizClient {
|
|
|
1123
1470
|
throw new Error("receiz_access_token_required");
|
|
1124
1471
|
return this.request(path, { ...options, bearerToken: this.accessToken });
|
|
1125
1472
|
}
|
|
1473
|
+
async delegatedWrite(path, body = {}, options = {}) {
|
|
1474
|
+
const idempotencyKey = options.idempotencyKey ?? (typeof body.idempotencyKey === "string" ? body.idempotencyKey : undefined);
|
|
1475
|
+
return this.delegated(path, {
|
|
1476
|
+
method: "POST",
|
|
1477
|
+
body: bodyWithIdempotency(body, idempotencyKey),
|
|
1478
|
+
headers: headersWithIdempotency(undefined, idempotencyKey),
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1126
1481
|
async delegatedBlob(path, options = {}) {
|
|
1127
1482
|
if (!this.accessToken)
|
|
1128
1483
|
throw new Error("receiz_access_token_required");
|
|
@@ -1224,6 +1579,48 @@ export class ReceizClient {
|
|
|
1224
1579
|
url.searchParams.set("login_hint", options.usernameHint);
|
|
1225
1580
|
return url.toString();
|
|
1226
1581
|
}
|
|
1582
|
+
ensureTenantSession(input) {
|
|
1583
|
+
const tenantHost = normalizeReceizHost(input.tenantHost);
|
|
1584
|
+
const fallback = input.fallback ?? "artifact_upload";
|
|
1585
|
+
const scope = Array.isArray(input.scope)
|
|
1586
|
+
? input.scope
|
|
1587
|
+
: typeof input.scope === "string" && input.scope.trim()
|
|
1588
|
+
? input.scope.trim().split(/\s+/)
|
|
1589
|
+
: receizOidcScopesForRails("identity", "customers", "publicStore");
|
|
1590
|
+
let url;
|
|
1591
|
+
if (input.clientId && input.codeChallenge) {
|
|
1592
|
+
const authorizeOptions = {
|
|
1593
|
+
clientId: input.clientId,
|
|
1594
|
+
redirectUri: input.redirectUri ?? input.returnTo ?? `${this.baseUrl}/developers/connect`,
|
|
1595
|
+
codeChallenge: input.codeChallenge,
|
|
1596
|
+
scope,
|
|
1597
|
+
};
|
|
1598
|
+
if (input.codeChallengeMethod)
|
|
1599
|
+
authorizeOptions.codeChallengeMethod = input.codeChallengeMethod;
|
|
1600
|
+
if (input.state)
|
|
1601
|
+
authorizeOptions.state = input.state;
|
|
1602
|
+
if (input.usernameHint)
|
|
1603
|
+
authorizeOptions.usernameHint = input.usernameHint;
|
|
1604
|
+
url = new URL(this.authorizeUrl(authorizeOptions));
|
|
1605
|
+
}
|
|
1606
|
+
else {
|
|
1607
|
+
url = new URL(`${this.baseUrl}/signin`);
|
|
1608
|
+
url.searchParams.set("lane", "connect");
|
|
1609
|
+
}
|
|
1610
|
+
url.searchParams.set("tenantHost", tenantHost);
|
|
1611
|
+
if (input.returnTo)
|
|
1612
|
+
url.searchParams.set("returnTo", input.returnTo);
|
|
1613
|
+
url.searchParams.set("fallback", fallback);
|
|
1614
|
+
return {
|
|
1615
|
+
ok: true,
|
|
1616
|
+
schema: "receiz.sdk.identity.tenant_session.ensure.v1",
|
|
1617
|
+
tenantHost,
|
|
1618
|
+
fallback,
|
|
1619
|
+
url: url.toString(),
|
|
1620
|
+
scope,
|
|
1621
|
+
...(input.returnTo ? { returnTo: input.returnTo } : {}),
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1227
1624
|
async delegatedVerifyArtifact(file) {
|
|
1228
1625
|
const form = new FormData();
|
|
1229
1626
|
form.set("file", file);
|
|
@@ -1705,6 +2102,33 @@ function errorDetail(error) {
|
|
|
1705
2102
|
return { name: error.name, message: error.message };
|
|
1706
2103
|
return { message: String(error) };
|
|
1707
2104
|
}
|
|
2105
|
+
function isProofRegisterEntry(value) {
|
|
2106
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.kind === "string" && isRecord(value.payload);
|
|
2107
|
+
}
|
|
2108
|
+
function proofMemoryAdditionValues(batch) {
|
|
2109
|
+
if (Array.isArray(batch))
|
|
2110
|
+
return batch;
|
|
2111
|
+
if (isProofRegisterEntry(batch))
|
|
2112
|
+
return [batch];
|
|
2113
|
+
const out = [];
|
|
2114
|
+
for (const key of ["entries", "additions", "proofs", "records"]) {
|
|
2115
|
+
const value = batch[key];
|
|
2116
|
+
if (Array.isArray(value))
|
|
2117
|
+
out.push(...value);
|
|
2118
|
+
}
|
|
2119
|
+
return out;
|
|
2120
|
+
}
|
|
2121
|
+
function admitProofMemoryAddition(memory, addition) {
|
|
2122
|
+
if (isProofRegisterEntry(addition)) {
|
|
2123
|
+
memory.append(addition);
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2126
|
+
if (isRecord(addition) && isProofRegisterEntry(addition.entry)) {
|
|
2127
|
+
memory.append(addition.entry);
|
|
2128
|
+
return;
|
|
2129
|
+
}
|
|
2130
|
+
memory.admit(addition);
|
|
2131
|
+
}
|
|
1708
2132
|
export class ReceizProofRegister {
|
|
1709
2133
|
ownerId;
|
|
1710
2134
|
createdAt;
|
|
@@ -1957,6 +2381,213 @@ export function receizProofMemoryAdditionsQuery(value, limit) {
|
|
|
1957
2381
|
...(limit === undefined ? {} : { limit }),
|
|
1958
2382
|
};
|
|
1959
2383
|
}
|
|
2384
|
+
function normalizeOfflineQueueItem(value) {
|
|
2385
|
+
const record = ensureRecord(value, "ReceizOfflineProofQueueItem");
|
|
2386
|
+
const issues = [];
|
|
2387
|
+
const id = ensureString(record, "id", issues);
|
|
2388
|
+
const kind = ensureString(record, "kind", issues);
|
|
2389
|
+
if (!isRecord(record.payload))
|
|
2390
|
+
issues.push("payload must be an object");
|
|
2391
|
+
const attempts = record.attempts;
|
|
2392
|
+
if (attempts !== undefined && (typeof attempts !== "number" || !Number.isInteger(attempts) || attempts < 0)) {
|
|
2393
|
+
issues.push("attempts must be a non-negative integer when present");
|
|
2394
|
+
}
|
|
2395
|
+
const item = {
|
|
2396
|
+
id: id ?? "",
|
|
2397
|
+
kind: (kind ?? ""),
|
|
2398
|
+
payload: isRecord(record.payload) ? record.payload : {},
|
|
2399
|
+
createdAt: typeof record.createdAt === "string" && record.createdAt.trim() ? record.createdAt : new Date().toISOString(),
|
|
2400
|
+
attempts: typeof attempts === "number" ? attempts : 0,
|
|
2401
|
+
};
|
|
2402
|
+
if (typeof record.idempotencyKey === "string" && record.idempotencyKey.trim())
|
|
2403
|
+
item.idempotencyKey = record.idempotencyKey;
|
|
2404
|
+
if (record.lastError === null || isRecord(record.lastError))
|
|
2405
|
+
item.lastError = record.lastError;
|
|
2406
|
+
failIfIssues("ReceizOfflineProofQueueItem", issues);
|
|
2407
|
+
return item;
|
|
2408
|
+
}
|
|
2409
|
+
export function assertReceizOfflineProofQueueSnapshot(value) {
|
|
2410
|
+
const record = ensureRecord(value, "ReceizOfflineProofQueueSnapshot");
|
|
2411
|
+
const issues = [];
|
|
2412
|
+
if (record.schema !== "receiz.sdk.offline_proof_queue.v1")
|
|
2413
|
+
issues.push("schema must be receiz.sdk.offline_proof_queue.v1");
|
|
2414
|
+
const ownerId = record.ownerId;
|
|
2415
|
+
if (ownerId !== null && ownerId !== undefined && typeof ownerId !== "string") {
|
|
2416
|
+
issues.push("ownerId must be a string or null when present");
|
|
2417
|
+
}
|
|
2418
|
+
const createdAt = ensureString(record, "createdAt", issues);
|
|
2419
|
+
const updatedAt = ensureString(record, "updatedAt", issues);
|
|
2420
|
+
if (!Array.isArray(record.pending))
|
|
2421
|
+
issues.push("pending must be an array");
|
|
2422
|
+
if (!Array.isArray(record.settled))
|
|
2423
|
+
issues.push("settled must be an array");
|
|
2424
|
+
if (!Array.isArray(record.failed))
|
|
2425
|
+
issues.push("failed must be an array");
|
|
2426
|
+
failIfIssues("ReceizOfflineProofQueueSnapshot", issues);
|
|
2427
|
+
return {
|
|
2428
|
+
schema: "receiz.sdk.offline_proof_queue.v1",
|
|
2429
|
+
ownerId: typeof ownerId === "string" || ownerId === null ? ownerId : null,
|
|
2430
|
+
createdAt: createdAt ?? "",
|
|
2431
|
+
updatedAt: updatedAt ?? "",
|
|
2432
|
+
pending: Array.isArray(record.pending) ? record.pending.map(normalizeOfflineQueueItem) : [],
|
|
2433
|
+
settled: Array.isArray(record.settled) ? record.settled.map(normalizeOfflineQueueItem) : [],
|
|
2434
|
+
failed: Array.isArray(record.failed) ? record.failed.map(normalizeOfflineQueueItem) : [],
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
function parseOfflineProofQueueStorageValue(value) {
|
|
2438
|
+
if (value === null || value === undefined)
|
|
2439
|
+
return null;
|
|
2440
|
+
if (typeof value === "string") {
|
|
2441
|
+
const trimmed = value.trim();
|
|
2442
|
+
if (!trimmed)
|
|
2443
|
+
return null;
|
|
2444
|
+
return assertReceizOfflineProofQueueSnapshot(JSON.parse(trimmed));
|
|
2445
|
+
}
|
|
2446
|
+
return assertReceizOfflineProofQueueSnapshot(value);
|
|
2447
|
+
}
|
|
2448
|
+
export class ReceizOfflineProofQueue {
|
|
2449
|
+
ownerId;
|
|
2450
|
+
createdAt;
|
|
2451
|
+
pendingItems;
|
|
2452
|
+
settledItems;
|
|
2453
|
+
failedItems;
|
|
2454
|
+
storage;
|
|
2455
|
+
constructor(options = {}) {
|
|
2456
|
+
const snapshot = options.snapshot ? assertReceizOfflineProofQueueSnapshot(options.snapshot) : null;
|
|
2457
|
+
this.ownerId = options.ownerId ?? snapshot?.ownerId ?? null;
|
|
2458
|
+
this.createdAt = snapshot?.createdAt ?? new Date().toISOString();
|
|
2459
|
+
this.pendingItems = snapshot?.pending ? [...snapshot.pending] : [];
|
|
2460
|
+
this.settledItems = snapshot?.settled ? [...snapshot.settled] : [];
|
|
2461
|
+
this.failedItems = snapshot?.failed ? [...snapshot.failed] : [];
|
|
2462
|
+
this.storage = options.storage ?? null;
|
|
2463
|
+
}
|
|
2464
|
+
enqueue(item) {
|
|
2465
|
+
const normalized = normalizeOfflineQueueItem(item);
|
|
2466
|
+
if (this.pendingItems.some((pending) => pending.id === normalized.id))
|
|
2467
|
+
return this;
|
|
2468
|
+
if (this.settledItems.some((settled) => settled.id === normalized.id))
|
|
2469
|
+
return this;
|
|
2470
|
+
this.pendingItems.push(normalized);
|
|
2471
|
+
return this;
|
|
2472
|
+
}
|
|
2473
|
+
snapshot() {
|
|
2474
|
+
return {
|
|
2475
|
+
schema: "receiz.sdk.offline_proof_queue.v1",
|
|
2476
|
+
ownerId: this.ownerId,
|
|
2477
|
+
createdAt: this.createdAt,
|
|
2478
|
+
updatedAt: new Date().toISOString(),
|
|
2479
|
+
pending: [...this.pendingItems],
|
|
2480
|
+
settled: [...this.settledItems],
|
|
2481
|
+
failed: [...this.failedItems],
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
async flush() {
|
|
2485
|
+
const snapshot = this.snapshot();
|
|
2486
|
+
if (this.storage)
|
|
2487
|
+
await this.storage.write(snapshot);
|
|
2488
|
+
return snapshot;
|
|
2489
|
+
}
|
|
2490
|
+
async clear() {
|
|
2491
|
+
this.pendingItems = [];
|
|
2492
|
+
this.settledItems = [];
|
|
2493
|
+
this.failedItems = [];
|
|
2494
|
+
if (this.storage?.remove)
|
|
2495
|
+
await this.storage.remove();
|
|
2496
|
+
}
|
|
2497
|
+
async replay(client) {
|
|
2498
|
+
const originalPending = [...this.pendingItems];
|
|
2499
|
+
let settled = 0;
|
|
2500
|
+
let failed = 0;
|
|
2501
|
+
this.pendingItems = [];
|
|
2502
|
+
for (const item of originalPending) {
|
|
2503
|
+
try {
|
|
2504
|
+
await replayOfflineProofQueueItem(client, item);
|
|
2505
|
+
this.settledItems.push({ ...item, attempts: (item.attempts ?? 0) + 1, lastError: null });
|
|
2506
|
+
settled += 1;
|
|
2507
|
+
}
|
|
2508
|
+
catch (error) {
|
|
2509
|
+
const failedItem = {
|
|
2510
|
+
...item,
|
|
2511
|
+
attempts: (item.attempts ?? 0) + 1,
|
|
2512
|
+
lastError: errorDetail(error),
|
|
2513
|
+
};
|
|
2514
|
+
this.failedItems.push(failedItem);
|
|
2515
|
+
failed += 1;
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
await this.flush();
|
|
2519
|
+
return { ok: failed === 0, settled, failed };
|
|
2520
|
+
}
|
|
2521
|
+
toJSON() {
|
|
2522
|
+
return this.snapshot();
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
async function replayOfflineProofQueueItem(client, item) {
|
|
2526
|
+
if (item.kind === "app_state.publish") {
|
|
2527
|
+
return client.appState.publish(item.payload, item.idempotencyKey ? { idempotencyKey: item.idempotencyKey } : {});
|
|
2528
|
+
}
|
|
2529
|
+
if (item.kind === "connect.record") {
|
|
2530
|
+
return client.request("/api/connect/record", {
|
|
2531
|
+
method: "POST",
|
|
2532
|
+
body: bodyWithIdempotency(item.payload, item.idempotencyKey),
|
|
2533
|
+
headers: headersWithIdempotency(undefined, item.idempotencyKey),
|
|
2534
|
+
});
|
|
2535
|
+
}
|
|
2536
|
+
if (item.kind === "webhook.event") {
|
|
2537
|
+
return client.request("/api/connect/webhooks/replay", {
|
|
2538
|
+
method: "POST",
|
|
2539
|
+
body: bodyWithIdempotency(item.payload, item.idempotencyKey),
|
|
2540
|
+
headers: headersWithIdempotency(undefined, item.idempotencyKey),
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2543
|
+
return client.request("/api/connect/offline/replay", {
|
|
2544
|
+
method: "POST",
|
|
2545
|
+
body: bodyWithIdempotency({ kind: item.kind, payload: item.payload }, item.idempotencyKey),
|
|
2546
|
+
headers: headersWithIdempotency(undefined, item.idempotencyKey),
|
|
2547
|
+
});
|
|
2548
|
+
}
|
|
2549
|
+
export async function createReceizOfflineProofQueue(options = {}) {
|
|
2550
|
+
const storedSnapshot = options.storage ? parseOfflineProofQueueStorageValue(await options.storage.read()) : null;
|
|
2551
|
+
const queueOptions = {
|
|
2552
|
+
ownerId: options.ownerId ?? storedSnapshot?.ownerId ?? null,
|
|
2553
|
+
};
|
|
2554
|
+
if (options.storage)
|
|
2555
|
+
queueOptions.storage = options.storage;
|
|
2556
|
+
const snapshot = options.snapshot ?? storedSnapshot;
|
|
2557
|
+
if (snapshot)
|
|
2558
|
+
queueOptions.snapshot = snapshot;
|
|
2559
|
+
return new ReceizOfflineProofQueue(queueOptions);
|
|
2560
|
+
}
|
|
2561
|
+
export function createReceizInMemoryOfflineProofQueueStorage(initialValue = null) {
|
|
2562
|
+
let storedText = typeof initialValue === "string"
|
|
2563
|
+
? initialValue
|
|
2564
|
+
: initialValue
|
|
2565
|
+
? JSON.stringify(assertReceizOfflineProofQueueSnapshot(initialValue))
|
|
2566
|
+
: null;
|
|
2567
|
+
return {
|
|
2568
|
+
read: () => storedText,
|
|
2569
|
+
write: (snapshot) => {
|
|
2570
|
+
storedText = JSON.stringify(assertReceizOfflineProofQueueSnapshot(snapshot));
|
|
2571
|
+
},
|
|
2572
|
+
remove: () => {
|
|
2573
|
+
storedText = null;
|
|
2574
|
+
},
|
|
2575
|
+
readText: () => storedText,
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
export function createReceizLocalStorageOfflineProofQueueStorage(key = "receiz:offline-proof-queue:v1", storage = globalThis.localStorage) {
|
|
2579
|
+
if (!storage)
|
|
2580
|
+
throw new Error("receiz_local_storage_unavailable");
|
|
2581
|
+
return {
|
|
2582
|
+
read: () => storage.getItem(key),
|
|
2583
|
+
write: (snapshot) => {
|
|
2584
|
+
storage.setItem(key, JSON.stringify(assertReceizOfflineProofQueueSnapshot(snapshot)));
|
|
2585
|
+
},
|
|
2586
|
+
remove: () => {
|
|
2587
|
+
storage.removeItem(key);
|
|
2588
|
+
},
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
1960
2591
|
function bodyToString(body) {
|
|
1961
2592
|
if (typeof body === "string")
|
|
1962
2593
|
return body;
|