@zappie/sdk 0.1.0 → 0.1.2
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/CHANGELOG.md +25 -0
- package/README.md +55 -313
- package/dist/cart/errors.js +13 -0
- package/dist/cart/errors.js.map +7 -0
- package/dist/cart/index.js +768 -0
- package/dist/cart/index.js.map +7 -0
- package/dist/cart/item.js +12 -1
- package/dist/cart/item.js.map +7 -1
- package/dist/cart/preview.js +32 -0
- package/dist/cart/preview.js.map +7 -0
- package/dist/cart/price.js +25 -0
- package/dist/cart/price.js.map +7 -0
- package/dist/cart/quote-client.js +76 -0
- package/dist/cart/quote-client.js.map +7 -0
- package/dist/cart/quote-response.js +178 -0
- package/dist/cart/quote-response.js.map +7 -0
- package/dist/cart/reconcile.js +108 -0
- package/dist/cart/reconcile.js.map +7 -0
- package/dist/cart/source-menu.js +21 -0
- package/dist/cart/source-menu.js.map +7 -0
- package/dist/cart/storage.js +174 -0
- package/dist/cart/storage.js.map +7 -0
- package/dist/cart/types.js +1 -0
- package/dist/cart/types.js.map +7 -0
- package/dist/cart/validate.js +265 -0
- package/dist/cart/validate.js.map +7 -0
- package/dist/cart/wire.js +42 -0
- package/dist/cart/wire.js.map +7 -0
- package/dist/cart/working-set.js +80 -0
- package/dist/cart/working-set.js.map +7 -0
- package/dist/checkout/client.js +102 -0
- package/dist/checkout/client.js.map +7 -0
- package/dist/checkout/error.js +21 -0
- package/dist/checkout/error.js.map +7 -0
- package/dist/checkout/index.js +13 -1
- package/dist/checkout/index.js.map +7 -1
- package/dist/checkout/readiness.js +36 -0
- package/dist/checkout/readiness.js.map +7 -0
- package/dist/checkout/sdk.js +9 -0
- package/dist/checkout/sdk.js.map +7 -0
- package/dist/checkout/session.js +58 -0
- package/dist/checkout/session.js.map +7 -0
- package/dist/checkout/types.js +1 -0
- package/dist/checkout/types.js.map +7 -0
- package/dist/client.js +253 -0
- package/dist/client.js.map +7 -0
- package/dist/config/index.js +13 -1
- package/dist/config/index.js.map +7 -0
- package/dist/config.js +28 -0
- package/dist/config.js.map +7 -0
- package/dist/customer/client.js +149 -0
- package/dist/customer/client.js.map +7 -0
- package/dist/customer/error.js +20 -0
- package/dist/customer/error.js.map +7 -0
- package/dist/customer/index.js +8 -3
- package/dist/customer/index.js.map +7 -1
- package/dist/customer/navigation.js +45 -0
- package/dist/customer/navigation.js.map +7 -0
- package/dist/customer/react.js +67 -2
- package/dist/customer/react.js.map +7 -1
- package/dist/customer/request.js +37 -0
- package/dist/customer/request.js.map +7 -0
- package/dist/customer/sdk.js +6 -0
- package/dist/customer/sdk.js.map +7 -0
- package/dist/customer/types.js +1 -0
- package/dist/customer/types.js.map +7 -0
- package/dist/customer/watch-order.js +80 -0
- package/dist/customer/watch-order.js.map +7 -0
- package/dist/debug.js +78 -1
- package/dist/debug.js.map +7 -1
- package/dist/errors.js +69 -0
- package/dist/errors.js.map +7 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +29 -1
- package/dist/index.js.map +7 -1
- package/dist/internal/abort.js +29 -0
- package/dist/internal/abort.js.map +7 -0
- package/dist/internal/cache.js +142 -0
- package/dist/internal/cache.js.map +7 -0
- package/dist/internal/customer-http.js +74 -0
- package/dist/internal/customer-http.js.map +7 -0
- package/dist/internal/digest.js +15 -0
- package/dist/internal/digest.js.map +7 -0
- package/dist/internal/emitter.js +27 -0
- package/dist/internal/emitter.js.map +7 -0
- package/dist/internal/money-math.js +30 -0
- package/dist/internal/money-math.js.map +7 -0
- package/dist/internal.js +9 -1
- package/dist/internal.js.map +7 -1
- package/dist/models.js +1 -0
- package/dist/models.js.map +7 -0
- package/dist/money.js +58 -0
- package/dist/money.js.map +7 -0
- package/dist/persist/catalogue.js +206 -2
- package/dist/persist/catalogue.js.map +7 -1
- package/dist/places/client.js +97 -0
- package/dist/places/client.js.map +7 -0
- package/dist/places/error.js +20 -0
- package/dist/places/error.js.map +7 -0
- package/dist/places/index.js +8 -1
- package/dist/places/index.js.map +7 -1
- package/dist/places/request.js +40 -0
- package/dist/places/request.js.map +7 -0
- package/dist/places/sdk.js +10 -0
- package/dist/places/sdk.js.map +7 -0
- package/dist/places/search.js +80 -0
- package/dist/places/search.js.map +7 -0
- package/dist/places/types.js +1 -0
- package/dist/places/types.js.map +7 -0
- package/dist/react/cart.js +30 -0
- package/dist/react/cart.js.map +7 -0
- package/dist/react/hooks.js +91 -0
- package/dist/react/hooks.js.map +7 -0
- package/dist/react/index.js +18 -1
- package/dist/react/index.js.map +7 -1
- package/dist/react/provider.js +34 -0
- package/dist/react/provider.js.map +7 -0
- package/dist/server/index.js +32 -2
- package/dist/server/index.js.map +7 -1
- package/dist/server/storefront-url/build-v1.js +75 -0
- package/dist/server/storefront-url/build-v1.js.map +7 -0
- package/dist/server/storefront-url/build-v2.js +79 -0
- package/dist/server/storefront-url/build-v2.js.map +7 -0
- package/dist/server/storefront-url/build.js +19 -0
- package/dist/server/storefront-url/build.js.map +7 -0
- package/dist/server/storefront-url/contract.js +25 -0
- package/dist/server/storefront-url/contract.js.map +7 -0
- package/dist/server/storefront-url/index.js +16 -0
- package/dist/server/storefront-url/index.js.map +7 -0
- package/dist/server/storefront-url/installation.js +58 -0
- package/dist/server/storefront-url/installation.js.map +7 -0
- package/dist/server/storefront-url/params.js +72 -0
- package/dist/server/storefront-url/params.js.map +7 -0
- package/dist/server/storefront-url/parse-v1.js +135 -0
- package/dist/server/storefront-url/parse-v1.js.map +7 -0
- package/dist/server/storefront-url/parse-v2.js +139 -0
- package/dist/server/storefront-url/parse-v2.js.map +7 -0
- package/dist/server/storefront-url/parse.js +9 -0
- package/dist/server/storefront-url/parse.js.map +7 -0
- package/dist/server/storefront-url/redirect.js +30 -0
- package/dist/server/storefront-url/redirect.js.map +7 -0
- package/dist/server/storefront-url/sign-in.js +17 -0
- package/dist/server/storefront-url/sign-in.js.map +7 -0
- package/dist/server/storefront-url/types.js +55 -0
- package/dist/server/storefront-url/types.js.map +7 -0
- package/dist/server/storefront-url/url.js +61 -0
- package/dist/server/storefront-url/url.js.map +7 -0
- package/dist/server/webhook.js +96 -0
- package/dist/server/webhook.js.map +7 -0
- package/dist/site-config/helpers.js +59 -0
- package/dist/site-config/helpers.js.map +7 -0
- package/dist/site-config/sections.js +105 -0
- package/dist/site-config/sections.js.map +7 -0
- package/dist/site-config/types.js +31 -0
- package/dist/site-config/types.js.map +7 -0
- package/dist/site-config/validate.js +165 -0
- package/dist/site-config/validate.js.map +7 -0
- package/dist/template/index.js +46 -3
- package/dist/template/index.js.map +7 -1
- package/dist/template/react.js +81 -2
- package/dist/template/react.js.map +7 -1
- package/dist/testing/index.js +451 -2
- package/dist/testing/index.js.map +7 -1
- package/dist/transport/category-page.js +21 -2
- package/dist/transport/category-page.js.map +7 -1
- package/dist/transport/mappers.js +326 -0
- package/dist/transport/mappers.js.map +7 -0
- package/dist/transport/rest.js +313 -0
- package/dist/transport/rest.js.map +7 -0
- package/dist/transport/search.js +32 -2
- package/dist/transport/search.js.map +7 -1
- package/dist/transport/selected-menu.js +79 -2
- package/dist/transport/selected-menu.js.map +7 -1
- package/dist/transport/store.js +120 -2
- package/dist/transport/store.js.map +7 -1
- package/dist/transport/types.js +1 -0
- package/dist/transport/types.js.map +7 -0
- package/dist/url/index.js +16 -2
- package/dist/url/index.js.map +7 -1
- package/dist/visits/index.js +62 -1
- package/dist/visits/index.js.map +7 -1
- package/dist/visits/page-views.js +103 -0
- package/dist/visits/page-views.js.map +7 -0
- package/package.json +5 -4
- package/dist/cart/quote.js +0 -1
- package/dist/cart/quote.js.map +0 -1
- package/dist/chunk-I55A5QXJ.js +0 -2
- package/dist/chunk-I55A5QXJ.js.map +0 -1
- package/dist/chunk-VG7NKIKR.js +0 -2
- package/dist/chunk-VG7NKIKR.js.map +0 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/places/search.ts
|
|
2
|
+
var aborted = () => new DOMException("Superseded", "AbortError");
|
|
3
|
+
function createAddressSearch(client, options = {}) {
|
|
4
|
+
const debounceMs = options.debounceMs ?? 250;
|
|
5
|
+
let token = crypto.randomUUID();
|
|
6
|
+
let controller;
|
|
7
|
+
let timer;
|
|
8
|
+
let rejectPending;
|
|
9
|
+
let revision = 0;
|
|
10
|
+
const cancel = () => {
|
|
11
|
+
revision++;
|
|
12
|
+
if (timer !== void 0) {
|
|
13
|
+
clearTimeout(timer);
|
|
14
|
+
timer = void 0;
|
|
15
|
+
}
|
|
16
|
+
controller?.abort(aborted());
|
|
17
|
+
controller = void 0;
|
|
18
|
+
rejectPending?.(aborted());
|
|
19
|
+
rejectPending = void 0;
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
suggest(query) {
|
|
23
|
+
cancel();
|
|
24
|
+
const current = revision;
|
|
25
|
+
if (!query.trim()) {
|
|
26
|
+
return Promise.resolve([]);
|
|
27
|
+
}
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
rejectPending = reject;
|
|
30
|
+
timer = setTimeout(async () => {
|
|
31
|
+
timer = void 0;
|
|
32
|
+
controller = new AbortController();
|
|
33
|
+
try {
|
|
34
|
+
const value = await client.autocomplete(query.trim(), token, {
|
|
35
|
+
signal: controller.signal
|
|
36
|
+
});
|
|
37
|
+
if (current === revision) {
|
|
38
|
+
resolve(value);
|
|
39
|
+
}
|
|
40
|
+
} catch (failure) {
|
|
41
|
+
if (current === revision) {
|
|
42
|
+
reject(failure);
|
|
43
|
+
}
|
|
44
|
+
} finally {
|
|
45
|
+
if (current === revision) {
|
|
46
|
+
rejectPending = void 0;
|
|
47
|
+
controller = void 0;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}, debounceMs);
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
async select(placeId) {
|
|
54
|
+
cancel();
|
|
55
|
+
const current = revision;
|
|
56
|
+
controller = new AbortController();
|
|
57
|
+
try {
|
|
58
|
+
const value = await client.place(placeId, {
|
|
59
|
+
...options.branchId !== void 0 ? { branchId: options.branchId } : {},
|
|
60
|
+
sessionToken: token,
|
|
61
|
+
signal: controller.signal
|
|
62
|
+
});
|
|
63
|
+
if (current !== revision) {
|
|
64
|
+
throw aborted();
|
|
65
|
+
}
|
|
66
|
+
token = crypto.randomUUID();
|
|
67
|
+
return value;
|
|
68
|
+
} finally {
|
|
69
|
+
if (current === revision) {
|
|
70
|
+
controller = void 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
dispose: cancel
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
createAddressSearch
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/places/search.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AddressSearchOptions, Place, PlaceSuggestion } from \"./types\";\n\ntype SearchClient = {\n autocomplete(\n query: string,\n token: string,\n options: { signal?: AbortSignal },\n ): Promise<PlaceSuggestion[]>;\n place(\n id: string,\n options: {\n branchId?: string;\n sessionToken?: string;\n signal?: AbortSignal;\n },\n ): Promise<Place>;\n};\n\nconst aborted = () => new DOMException(\"Superseded\", \"AbortError\");\n\nexport function createAddressSearch(\n client: SearchClient,\n options: AddressSearchOptions = {},\n) {\n const debounceMs = options.debounceMs ?? 250;\n let token = crypto.randomUUID();\n let controller: AbortController | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let rejectPending: ((reason: unknown) => void) | undefined;\n let revision = 0;\n const cancel = () => {\n revision++;\n if (timer !== undefined) {\n clearTimeout(timer);\n timer = undefined;\n }\n controller?.abort(aborted());\n controller = undefined;\n rejectPending?.(aborted());\n rejectPending = undefined;\n };\n return {\n suggest(query: string): Promise<PlaceSuggestion[]> {\n cancel();\n const current = revision;\n if (!query.trim()) {\n return Promise.resolve([]);\n }\n return new Promise((resolve, reject) => {\n rejectPending = reject;\n timer = setTimeout(async () => {\n timer = undefined;\n controller = new AbortController();\n try {\n const value = await client.autocomplete(query.trim(), token, {\n signal: controller.signal,\n });\n if (current === revision) {\n resolve(value);\n }\n } catch (failure) {\n if (current === revision) {\n reject(failure);\n }\n } finally {\n if (current === revision) {\n rejectPending = undefined;\n controller = undefined;\n }\n }\n }, debounceMs);\n });\n },\n async select(placeId: string): Promise<Place> {\n cancel();\n const current = revision;\n controller = new AbortController();\n try {\n const value = await client.place(placeId, {\n ...(options.branchId !== undefined\n ? { branchId: options.branchId }\n : {}),\n sessionToken: token,\n signal: controller.signal,\n });\n if (current !== revision) {\n throw aborted();\n }\n token = crypto.randomUUID();\n return value;\n } finally {\n if (current === revision) {\n controller = undefined;\n }\n }\n },\n dispose: cancel,\n };\n}\n"],
|
|
5
|
+
"mappings": ";AAkBA,IAAM,UAAU,MAAM,IAAI,aAAa,cAAc,YAAY;AAE1D,SAAS,oBACd,QACA,UAAgC,CAAC,GACjC;AACA,QAAM,aAAa,QAAQ,cAAc;AACzC,MAAI,QAAQ,OAAO,WAAW;AAC9B,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,WAAW;AACf,QAAM,SAAS,MAAM;AACnB;AACA,QAAI,UAAU,QAAW;AACvB,mBAAa,KAAK;AAClB,cAAQ;AAAA,IACV;AACA,gBAAY,MAAM,QAAQ,CAAC;AAC3B,iBAAa;AACb,oBAAgB,QAAQ,CAAC;AACzB,oBAAgB;AAAA,EAClB;AACA,SAAO;AAAA,IACL,QAAQ,OAA2C;AACjD,aAAO;AACP,YAAM,UAAU;AAChB,UAAI,CAAC,MAAM,KAAK,GAAG;AACjB,eAAO,QAAQ,QAAQ,CAAC,CAAC;AAAA,MAC3B;AACA,aAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,wBAAgB;AAChB,gBAAQ,WAAW,YAAY;AAC7B,kBAAQ;AACR,uBAAa,IAAI,gBAAgB;AACjC,cAAI;AACF,kBAAM,QAAQ,MAAM,OAAO,aAAa,MAAM,KAAK,GAAG,OAAO;AAAA,cAC3D,QAAQ,WAAW;AAAA,YACrB,CAAC;AACD,gBAAI,YAAY,UAAU;AACxB,sBAAQ,KAAK;AAAA,YACf;AAAA,UACF,SAAS,SAAS;AAChB,gBAAI,YAAY,UAAU;AACxB,qBAAO,OAAO;AAAA,YAChB;AAAA,UACF,UAAE;AACA,gBAAI,YAAY,UAAU;AACxB,8BAAgB;AAChB,2BAAa;AAAA,YACf;AAAA,UACF;AAAA,QACF,GAAG,UAAU;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,MAAM,OAAO,SAAiC;AAC5C,aAAO;AACP,YAAM,UAAU;AAChB,mBAAa,IAAI,gBAAgB;AACjC,UAAI;AACF,cAAM,QAAQ,MAAM,OAAO,MAAM,SAAS;AAAA,UACxC,GAAI,QAAQ,aAAa,SACrB,EAAE,UAAU,QAAQ,SAAS,IAC7B,CAAC;AAAA,UACL,cAAc;AAAA,UACd,QAAQ,WAAW;AAAA,QACrB,CAAC;AACD,YAAI,YAAY,UAAU;AACxB,gBAAM,QAAQ;AAAA,QAChB;AACA,gBAAQ,OAAO,WAAW;AAC1B,eAAO;AAAA,MACT,UAAE;AACA,YAAI,YAAY,UAAU;AACxB,uBAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,EACX;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/react/cart.ts
|
|
4
|
+
import { useEffect, useSyncExternalStore } from "react";
|
|
5
|
+
import { EMPTY_CART } from "../cart/index.js";
|
|
6
|
+
import { useZappie } from "./provider.js";
|
|
7
|
+
function useCart() {
|
|
8
|
+
const { cart } = useZappie();
|
|
9
|
+
const snapshot = useSyncExternalStore(
|
|
10
|
+
cart.subscribe,
|
|
11
|
+
cart.getSnapshot,
|
|
12
|
+
() => EMPTY_CART
|
|
13
|
+
);
|
|
14
|
+
useEffect(() => cart.mount(), [cart]);
|
|
15
|
+
return { ...snapshot, actions: cart };
|
|
16
|
+
}
|
|
17
|
+
function useCartLine(lineId) {
|
|
18
|
+
return useCart().lines.find((line) => line.id === lineId);
|
|
19
|
+
}
|
|
20
|
+
function useCartCatalogue() {
|
|
21
|
+
const client = useZappie();
|
|
22
|
+
useCart();
|
|
23
|
+
return client._internal.cartCatalogue();
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
useCart,
|
|
27
|
+
useCartCatalogue,
|
|
28
|
+
useCartLine
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=cart.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/react/cart.ts"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport { useEffect, useSyncExternalStore } from \"react\";\nimport { EMPTY_CART } from \"../cart\";\nimport { useZappie } from \"./provider\";\n/** Load saved cart state after mount. Server and initial hydration snapshots are empty. */\nexport function useCart() {\n const { cart } = useZappie();\n const snapshot = useSyncExternalStore(\n cart.subscribe,\n cart.getSnapshot,\n () => EMPTY_CART,\n );\n useEffect(() => cart.mount(), [cart]);\n return { ...snapshot, actions: cart };\n}\n/**\n * Subscribe to the cart and return the line with the given ID, or undefined if it is absent.\n * Use within a ZappieProvider. Server and initial hydration snapshots contain no lines.\n */\nexport function useCartLine(lineId: string) {\n return useCart().lines.find((line) => line.id === lineId);\n}\n/** Read the cart validation catalogue, including held items, without fetching it. */\nexport function useCartCatalogue() {\n const client = useZappie();\n useCart();\n return client._internal.cartCatalogue();\n}\n"],
|
|
5
|
+
"mappings": ";;;AACA,SAAS,WAAW,4BAA4B;AAChD,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAEnB,SAAS,UAAU;AACxB,QAAM,EAAE,KAAK,IAAI,UAAU;AAC3B,QAAM,WAAW;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACA,YAAU,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,CAAC;AACpC,SAAO,EAAE,GAAG,UAAU,SAAS,KAAK;AACtC;AAKO,SAAS,YAAY,QAAgB;AAC1C,SAAO,QAAQ,EAAE,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,MAAM;AAC1D;AAEO,SAAS,mBAAmB;AACjC,QAAM,SAAS,UAAU;AACzB,UAAQ;AACR,SAAO,OAAO,UAAU,cAAc;AACxC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/react/hooks.ts
|
|
4
|
+
import { useEffect, useMemo, useSyncExternalStore } from "react";
|
|
5
|
+
import { ZappieError } from "../errors.js";
|
|
6
|
+
import { useZappie } from "./provider.js";
|
|
7
|
+
function useStore() {
|
|
8
|
+
const client = useZappie();
|
|
9
|
+
const cache = client._internal.cache;
|
|
10
|
+
const snapshot = useSyncExternalStore(
|
|
11
|
+
cache.subscribe,
|
|
12
|
+
() => cache.snapshot("store"),
|
|
13
|
+
() => cache.snapshot("store")
|
|
14
|
+
);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const abort = new AbortController();
|
|
17
|
+
void client.store.get({ signal: abort.signal }).catch(() => {
|
|
18
|
+
});
|
|
19
|
+
return () => abort.abort();
|
|
20
|
+
}, [client]);
|
|
21
|
+
return {
|
|
22
|
+
data: snapshot.value,
|
|
23
|
+
error: snapshot.error,
|
|
24
|
+
isLoading: !snapshot.value && !snapshot.error
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function useMenu(branch, options = {}) {
|
|
28
|
+
const metadataOnly = options.metadataOnly === true;
|
|
29
|
+
const client = useZappie();
|
|
30
|
+
const store = useStore();
|
|
31
|
+
const cache = client._internal.cache;
|
|
32
|
+
let key;
|
|
33
|
+
let branchError;
|
|
34
|
+
try {
|
|
35
|
+
key = client._internal.menuKey(branch);
|
|
36
|
+
if (metadataOnly && !cache.snapshot(key).value) {
|
|
37
|
+
key += ":partial";
|
|
38
|
+
}
|
|
39
|
+
} catch (error2) {
|
|
40
|
+
key = "menu:invalid";
|
|
41
|
+
branchError = error2;
|
|
42
|
+
}
|
|
43
|
+
const snapshot = useSyncExternalStore(
|
|
44
|
+
cache.subscribe,
|
|
45
|
+
() => cache.snapshot(key),
|
|
46
|
+
() => cache.snapshot(key)
|
|
47
|
+
);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!store.data || branchError) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (metadataOnly && cache.snapshot(client._internal.menuKey(branch)).value) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const abort = new AbortController();
|
|
56
|
+
void client.menu.get({
|
|
57
|
+
...branch ? { branch } : {},
|
|
58
|
+
...metadataOnly ? { metadataOnly: true } : {},
|
|
59
|
+
signal: abort.signal
|
|
60
|
+
}).catch(() => {
|
|
61
|
+
});
|
|
62
|
+
return () => abort.abort();
|
|
63
|
+
}, [client, branch, store.data, branchError?.code, metadataOnly, cache]);
|
|
64
|
+
const error = branchError ?? snapshot.error ?? store.error;
|
|
65
|
+
return {
|
|
66
|
+
data: snapshot.value,
|
|
67
|
+
error,
|
|
68
|
+
isLoading: !snapshot.value && !error,
|
|
69
|
+
isStale: cache.stale(key)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function useItem(id, branch) {
|
|
73
|
+
const menu = useMenu(branch);
|
|
74
|
+
const data = menu.data && Object.prototype.hasOwnProperty.call(menu.data.items, id) ? menu.data.items[id] : void 0;
|
|
75
|
+
const missing = Boolean(menu.data) && !data;
|
|
76
|
+
const notFound = useMemo(
|
|
77
|
+
() => missing ? new ZappieError("item_not_found", "Item not found") : void 0,
|
|
78
|
+
[missing, id]
|
|
79
|
+
);
|
|
80
|
+
return {
|
|
81
|
+
data,
|
|
82
|
+
error: menu.error ?? notFound,
|
|
83
|
+
isLoading: menu.isLoading
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
useItem,
|
|
88
|
+
useMenu,
|
|
89
|
+
useStore
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/react/hooks.ts"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport { useEffect, useMemo, useSyncExternalStore } from \"react\";\nimport { ZappieError } from \"../errors\";\nimport type { Menu, Store } from \"../models\";\nimport { useZappie } from \"./provider\";\n/** Subscribe to storefront identity and branch-directory data. */\nexport function useStore() {\n const client = useZappie();\n const cache = client._internal.cache;\n const snapshot = useSyncExternalStore(\n cache.subscribe,\n () => cache.snapshot<Store>(\"store\"),\n () => cache.snapshot<Store>(\"store\"),\n );\n useEffect(() => {\n const abort = new AbortController();\n void client.store.get({ signal: abort.signal }).catch(() => {});\n return () => abort.abort();\n }, [client]);\n return {\n data: snapshot.value,\n error: snapshot.error,\n isLoading: !snapshot.value && !snapshot.error,\n };\n}\n/** Subscribe to a branch catalogue and refresh stale data in the background. */\nexport function useMenu(\n branch?: string,\n options: { metadataOnly?: boolean } = {},\n) {\n const metadataOnly = options.metadataOnly === true;\n const client = useZappie();\n const store = useStore();\n const cache = client._internal.cache;\n let key: string;\n let branchError: ZappieError | undefined;\n try {\n key = client._internal.menuKey(branch);\n if (metadataOnly && !cache.snapshot<Menu>(key).value) {\n key += \":partial\";\n }\n } catch (error) {\n key = \"menu:invalid\";\n branchError = error as ZappieError;\n }\n const snapshot = useSyncExternalStore(\n cache.subscribe,\n () => cache.snapshot<Menu>(key),\n () => cache.snapshot<Menu>(key),\n );\n useEffect(() => {\n if (!store.data || branchError) {\n return;\n }\n if (\n metadataOnly &&\n cache.snapshot<Menu>(client._internal.menuKey(branch)).value\n ) {\n return;\n }\n const abort = new AbortController();\n void client.menu\n .get({\n ...(branch ? { branch } : {}),\n ...(metadataOnly ? { metadataOnly: true } : {}),\n signal: abort.signal,\n })\n .catch(() => {});\n return () => abort.abort();\n }, [client, branch, store.data, branchError?.code, metadataOnly, cache]);\n const error = branchError ?? snapshot.error ?? store.error;\n return {\n data: snapshot.value,\n error,\n isLoading: !snapshot.value && !error,\n isStale: cache.stale(key),\n };\n}\n/** Select one item from the branch catalogue without duplicating a request. */\nexport function useItem(id: string, branch?: string) {\n const menu = useMenu(branch);\n const data =\n menu.data && Object.prototype.hasOwnProperty.call(menu.data.items, id)\n ? menu.data.items[id]\n : undefined;\n const missing = Boolean(menu.data) && !data;\n const notFound = useMemo(\n () =>\n missing ? new ZappieError(\"item_not_found\", \"Item not found\") : undefined,\n [missing, id],\n );\n return {\n data,\n error: menu.error ?? notFound,\n isLoading: menu.isLoading,\n };\n}\n"],
|
|
5
|
+
"mappings": ";;;AACA,SAAS,WAAW,SAAS,4BAA4B;AACzD,SAAS,mBAAmB;AAE5B,SAAS,iBAAiB;AAEnB,SAAS,WAAW;AACzB,QAAM,SAAS,UAAU;AACzB,QAAM,QAAQ,OAAO,UAAU;AAC/B,QAAM,WAAW;AAAA,IACf,MAAM;AAAA,IACN,MAAM,MAAM,SAAgB,OAAO;AAAA,IACnC,MAAM,MAAM,SAAgB,OAAO;AAAA,EACrC;AACA,YAAU,MAAM;AACd,UAAM,QAAQ,IAAI,gBAAgB;AAClC,SAAK,OAAO,MAAM,IAAI,EAAE,QAAQ,MAAM,OAAO,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9D,WAAO,MAAM,MAAM,MAAM;AAAA,EAC3B,GAAG,CAAC,MAAM,CAAC;AACX,SAAO;AAAA,IACL,MAAM,SAAS;AAAA,IACf,OAAO,SAAS;AAAA,IAChB,WAAW,CAAC,SAAS,SAAS,CAAC,SAAS;AAAA,EAC1C;AACF;AAEO,SAAS,QACd,QACA,UAAsC,CAAC,GACvC;AACA,QAAM,eAAe,QAAQ,iBAAiB;AAC9C,QAAM,SAAS,UAAU;AACzB,QAAM,QAAQ,SAAS;AACvB,QAAM,QAAQ,OAAO,UAAU;AAC/B,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,UAAM,OAAO,UAAU,QAAQ,MAAM;AACrC,QAAI,gBAAgB,CAAC,MAAM,SAAe,GAAG,EAAE,OAAO;AACpD,aAAO;AAAA,IACT;AAAA,EACF,SAASA,QAAO;AACd,UAAM;AACN,kBAAcA;AAAA,EAChB;AACA,QAAM,WAAW;AAAA,IACf,MAAM;AAAA,IACN,MAAM,MAAM,SAAe,GAAG;AAAA,IAC9B,MAAM,MAAM,SAAe,GAAG;AAAA,EAChC;AACA,YAAU,MAAM;AACd,QAAI,CAAC,MAAM,QAAQ,aAAa;AAC9B;AAAA,IACF;AACA,QACE,gBACA,MAAM,SAAe,OAAO,UAAU,QAAQ,MAAM,CAAC,EAAE,OACvD;AACA;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,gBAAgB;AAClC,SAAK,OAAO,KACT,IAAI;AAAA,MACH,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,eAAe,EAAE,cAAc,KAAK,IAAI,CAAC;AAAA,MAC7C,QAAQ,MAAM;AAAA,IAChB,CAAC,EACA,MAAM,MAAM;AAAA,IAAC,CAAC;AACjB,WAAO,MAAM,MAAM,MAAM;AAAA,EAC3B,GAAG,CAAC,QAAQ,QAAQ,MAAM,MAAM,aAAa,MAAM,cAAc,KAAK,CAAC;AACvE,QAAM,QAAQ,eAAe,SAAS,SAAS,MAAM;AACrD,SAAO;AAAA,IACL,MAAM,SAAS;AAAA,IACf;AAAA,IACA,WAAW,CAAC,SAAS,SAAS,CAAC;AAAA,IAC/B,SAAS,MAAM,MAAM,GAAG;AAAA,EAC1B;AACF;AAEO,SAAS,QAAQ,IAAY,QAAiB;AACnD,QAAM,OAAO,QAAQ,MAAM;AAC3B,QAAM,OACJ,KAAK,QAAQ,OAAO,UAAU,eAAe,KAAK,KAAK,KAAK,OAAO,EAAE,IACjE,KAAK,KAAK,MAAM,EAAE,IAClB;AACN,QAAM,UAAU,QAAQ,KAAK,IAAI,KAAK,CAAC;AACvC,QAAM,WAAW;AAAA,IACf,MACE,UAAU,IAAI,YAAY,kBAAkB,gBAAgB,IAAI;AAAA,IAClE,CAAC,SAAS,EAAE;AAAA,EACd;AACA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,KAAK,SAAS;AAAA,IACrB,WAAW,KAAK;AAAA,EAClB;AACF;",
|
|
6
|
+
"names": ["error"]
|
|
7
|
+
}
|
package/dist/react/index.js
CHANGED
|
@@ -1,2 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
// src/react/index.ts
|
|
4
|
+
import { VERSION } from "../index.js";
|
|
5
|
+
import { useItem, useMenu, useStore } from "./hooks.js";
|
|
6
|
+
import { ZappieProvider, useZappie } from "./provider.js";
|
|
7
|
+
import { useCart, useCartCatalogue, useCartLine } from "./cart.js";
|
|
8
|
+
export {
|
|
9
|
+
VERSION,
|
|
10
|
+
ZappieProvider,
|
|
11
|
+
useCart,
|
|
12
|
+
useCartCatalogue,
|
|
13
|
+
useCartLine,
|
|
14
|
+
useItem,
|
|
15
|
+
useMenu,
|
|
16
|
+
useStore,
|
|
17
|
+
useZappie
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/react/index.ts"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nexport { VERSION } from \"../index\";\nexport { useItem, useMenu, useStore } from \"./hooks\";\nexport { ZappieProvider, useZappie } from \"./provider\";\n\nexport { useCart, useCartCatalogue, useCartLine } from \"./cart\";\n"],
|
|
5
|
+
"mappings": ";;;AACA,SAAS,eAAe;AACxB,SAAS,SAAS,SAAS,gBAAgB;AAC3C,SAAS,gBAAgB,iBAAiB;AAE1C,SAAS,SAAS,kBAAkB,mBAAmB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/react/provider.tsx
|
|
4
|
+
import { createContext, useContext, useMemo } from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
var Context = createContext(null);
|
|
7
|
+
function ZappieProvider({
|
|
8
|
+
client,
|
|
9
|
+
initialData,
|
|
10
|
+
children
|
|
11
|
+
}) {
|
|
12
|
+
const value = useMemo(() => {
|
|
13
|
+
if (initialData?.store && !client.store.peek()) {
|
|
14
|
+
client._internal.hydrateStore(initialData.store);
|
|
15
|
+
}
|
|
16
|
+
if (initialData?.menu && !client._internal.cache.snapshot(`menu:${initialData.menu.branchId}`).value) {
|
|
17
|
+
client.menu.hydrate(initialData.menu);
|
|
18
|
+
}
|
|
19
|
+
return client;
|
|
20
|
+
}, [client, initialData]);
|
|
21
|
+
return /* @__PURE__ */ jsx(Context.Provider, { value, children });
|
|
22
|
+
}
|
|
23
|
+
function useZappie() {
|
|
24
|
+
const client = useContext(Context);
|
|
25
|
+
if (!client) {
|
|
26
|
+
throw new Error("useZappie requires ZappieProvider");
|
|
27
|
+
}
|
|
28
|
+
return client;
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
ZappieProvider,
|
|
32
|
+
useZappie
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/react/provider.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport type { ReactNode } from \"react\";\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { Zappie } from \"../client\";\nimport type { Menu, Store } from \"../models\";\nconst Context = createContext<Zappie | null>(null);\n/** Supply initial storefront data before children subscribe. Use one client per server request. */\nexport function ZappieProvider({\n client,\n initialData,\n children,\n}: {\n client: Zappie;\n initialData?: { store?: Store; menu?: Menu };\n children: ReactNode;\n}) {\n const value = useMemo(() => {\n if (initialData?.store && !client.store.peek()) {\n client._internal.hydrateStore(initialData.store);\n }\n if (\n initialData?.menu &&\n !client._internal.cache.snapshot(`menu:${initialData.menu.branchId}`)\n .value\n ) {\n client.menu.hydrate(initialData.menu);\n }\n return client;\n }, [client, initialData]);\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n/** Read your storefront client from the nearest ZappieProvider. */\nexport function useZappie(): Zappie {\n const client = useContext(Context);\n if (!client) {\n throw new Error(\"useZappie requires ZappieProvider\");\n }\n return client;\n}\n"],
|
|
5
|
+
"mappings": ";;;AAEA,SAAS,eAAe,YAAY,eAAe;AA2B1C;AAxBT,IAAM,UAAU,cAA6B,IAAI;AAE1C,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,QAAQ,QAAQ,MAAM;AAC1B,QAAI,aAAa,SAAS,CAAC,OAAO,MAAM,KAAK,GAAG;AAC9C,aAAO,UAAU,aAAa,YAAY,KAAK;AAAA,IACjD;AACA,QACE,aAAa,QACb,CAAC,OAAO,UAAU,MAAM,SAAS,QAAQ,YAAY,KAAK,QAAQ,EAAE,EACjE,OACH;AACA,aAAO,KAAK,QAAQ,YAAY,IAAI;AAAA,IACtC;AACA,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,WAAW,CAAC;AACxB,SAAO,oBAAC,QAAQ,UAAR,EAAiB,OAAe,UAAS;AACnD;AAEO,SAAS,YAAoB;AAClC,QAAM,SAAS,WAAW,OAAO;AACjC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/server/index.js
CHANGED
|
@@ -1,2 +1,32 @@
|
|
|
1
|
-
import {l}from'../chunk-VG7NKIKR.js';export{o as VERSION}from'../chunk-VG7NKIKR.js';import {a as a$1}from'../chunk-I55A5QXJ.js';var f="review-menu",y="payment",w="send-otp",E=new Set([w,"verify-otp","update-profile"]),h=t=>t.contract!=="v1"&&t.installation!==void 0,C=t=>({type:"order-menu",business:t.business,...t.branch!==void 0?{branch:t.branch}:{},state:t.state});var g=["ref","utm_source","payment_id","context","prefetch","business_tag","pay_point_id","dine_in_order_id","no_context","payment_context_id","ws","preview","device","auto_scroll","pickup","branch_closed","order_id","modal_id","lightbox","menu_id","payment_method","beacon_id","menu_group_id","category_id","menu_layout","can_schedule","refresh","success","grant","portal","can_download_receipt","auth_modal_id","experimental_otp","branch","business","env","switched_branch","from","template","catalog_rendering","catalogue_search","catalogue_categories"],_=[...g,"return","session"];var et="https://storefront.invalid",d="product_",V=t=>{try{return decodeURIComponent(t)}catch{return t}},a=t=>encodeURIComponent(t),m=t=>{if(t instanceof URL)return new URL(t.toString());let e=typeof t=="string"?t:t.url;return new URL(e,et)},rt=(t,e)=>{let r={};return t.forEach((o,s)=>{(e==="v2"?_:g).includes(s)&&(r[s]=o);}),r},k=(t,e="v2")=>{let r=rt(t.searchParams,e),o=t.searchParams.get("pickup");return {query:r,...t.searchParams.has("menu_id")?{menuId:t.searchParams.get("menu_id")??""}:{},...t.searchParams.has("category_id")?{categoryId:t.searchParams.get("category_id")??""}:{},...t.searchParams.has("menu_layout")?{menuLayout:t.searchParams.get("menu_layout")??""}:{},...o==="true"?{mode:"pickup"}:o==="false"?{mode:"delivery"}:{},...t.searchParams.has("modal_id")?{modalId:t.searchParams.get("modal_id")??""}:{},...t.searchParams.has("auth_modal_id")?{authModalId:t.searchParams.get("auth_modal_id")??""}:{},...t.searchParams.has("payment_id")?{paymentId:t.searchParams.get("payment_id")??""}:{},...t.searchParams.has("lightbox")?{lightbox:t.searchParams.get("lightbox")??""}:{},...t.searchParams.has("catalogue_search")?{catalogueSearch:t.searchParams.get("catalogue_search")??""}:{},...t.searchParams.has("catalogue_categories")?{catalogueCategories:t.searchParams.get("catalogue_categories")??""}:{}}};var S=t=>t.replace(/\/+$/,"")||"/",D=(t,e)=>{if(!e)return t;let r=`/order/${a(e.business)}`;if(t==="/")return r;if(t==="/order")return e.defaultBranch?`${r}/${a(e.defaultBranch)}`:r;if(t.startsWith("/pages/"))return `${r}${t}`;if(!t.startsWith("/order/")||t===r||t.startsWith(`${r}/`))return t;let o=t.slice(6);return e.defaultBranch&&(o==="/products"||o.startsWith("/products/")||o.startsWith("/pages/"))?`${r}/${a(e.defaultBranch)}${o}`:`${r}${o}`},F=(t,e,r)=>{if(!r||!("business"in e)||e.business!==r.business)return t;if(e.type==="content-page"&&!e.branch)return `/pages/${a(e.slug)}`;if(e.type==="order-menu"&&!e.branch)return "/";let o=`/order/${a(e.business)}/${a(e.branch??"")}`,s=t.slice(o.length);return e.branch===r.defaultBranch?`/order${s}`:`/order/${a(e.branch??"")}${s}`},p=(t,e)=>V(t[e]??"");var q=t=>{let e=new URLSearchParams(t.state.query),r=t.state;return [["menu_id",r.menuId],["category_id",r.categoryId],["menu_layout",r.menuLayout],["pickup",r.mode?String(r.mode==="pickup"):void 0],["modal_id",r.modalId],["auth_modal_id",r.authModalId],["payment_id",r.paymentId],["lightbox",r.lightbox],["catalogue_search",r.catalogueSearch],["catalogue_categories",r.catalogueCategories]].forEach(([s,n])=>{n!==void 0&&e.set(s,n);}),e},Q=t=>{let e=q(t);return t.type==="item"?e.delete("modal_id"):t.type==="cart"?e.set("modal_id",f):t.type==="checkout"?e.set("modal_id",y):t.type==="sign-in"?(e.set("auth_modal_id",w),t.returnTo!==void 0&&e.set("return",t.returnTo)):t.type==="checkout-return"&&t.session!==void 0&&e.set("session",t.session),e.sort(),e},v=(t,e)=>{let r=q(t);return (t.type==="order-menu"||t.type==="item"||t.type==="cart"||t.type==="checkout"||t.type==="checkout-return"||t.type==="sign-in"||t.type==="content-page")&&(t.branch&&t.branch!==e.defaultBranch?r.set("branch",t.branch):r.delete("branch")),(t.type==="item"||t.type==="cart"||t.type==="checkout"||t.type==="checkout-return")&&r.delete("modal_id"),t.type==="sign-in"&&(r.delete("auth_modal_id"),t.returnTo!==void 0&&r.set("return",t.returnTo)),t.type==="checkout-return"&&t.session!==void 0&&r.set("session",t.session),r.sort(),r};var T=(t,e={})=>{switch(t.type){case "order-menu":return `/order/${a(t.business)}${t.branch?`/${a(t.branch)}`:""}${t.cataloguePath?"/products":""}`;case "item":{let r=t.branch??e.installation?.defaultBranch;return r?`/order/${a(t.business)}/${a(r)}/products/${a(t.item)}`:`/order/${a(t.business)}`}case "cart":case "checkout":case "checkout-return":case "sign-in":return T(C(t),e);case "content-page":return `/order/${a(t.business)}${t.branch?`/${a(t.branch)}`:""}/pages/${a(t.slug)}`;case "dine-in":return `/dine-in/${a(t.order)}`;case "dine-in-menus":return "/dine-in/menus";case "self-service-menus":return "/self-service/menus";case "pay-point":return `/pay-point/${a(t.payPoint)}`;case "beacon":return `/beacons/${a(t.beacon)}`;case "link":return `/links/${a(t.link)}`;case "collect-payment":return "/collect-payment";case "reservation":return "/reservation";case "pay-session":return `/pay/${a(t.session)}`;case "payment-step":return `/payment/${a(t.payment)}${t.step==="payment"?"":`/${t.step}`}`;case "payment-card":return `/payment/card/${a(t.transaction)}`;case "profile":return `/profile/${t.page}${t.order?`/${a(t.order)}`:""}`;case "explore":return t.home?"/":"/explore";case "unknown":return t.pathname||"/"}},B=(t,e={})=>{let r=T(t,e),o=t.type==="item"&&t.branch===void 0&&e.installation?.defaultBranch?{...t,branch:e.installation.defaultBranch}:t,s=F(r,o,e.installation),n=Q(t).toString(),c=`${s}${n?`?${n}`:""}`;if(!e.origin)return c;try{return new URL(c,e.origin).toString()}catch{return c}};var $=(t,e)=>{let r=v(t,e);r.delete("auth_modal_id");let o=r.toString();return {type:"sign-in",business:t.business,state:{query:{}},returnTo:`/${o?`?${o}`:""}`}};var nt=(t,e)=>{if(t.type!=="order-menu")return t;let r={business:t.business,...t.branch!==void 0?{branch:t.branch}:{},state:t.state};return t.state.authModalId&&E.has(t.state.authModalId)?$(t,e):t.state.modalId?.startsWith(d)?{type:"item",...r,item:t.state.modalId.slice(d.length)}:t.state.modalId===f?{type:"cart",...r}:t.state.modalId===y?{type:"checkout",...r}:t},ot=t=>t.page==="orders"?`/orders${t.order?`/${a(t.order)}`:""}`:t.page==="edit"?"/account":`/account/${t.page==="add-store-credit"?"store-credit":t.page}`,st=(t,e)=>{switch(t.type){case "order-menu":return "/";case "item":return `/item/${a(t.item)}`;case "cart":return "/cart";case "checkout":return "/checkout";case "checkout-return":return "/checkout/return";case "sign-in":return "/sign-in";case "content-page":return `/pages/${a(t.slug)}`;case "profile":return ot(t);default:return T(t,e)}},Y=(t,e)=>{let r=e.installation;if(!r)return "";let o=nt(t,r),s=st(o,e),n=v(o,r).toString();return `${s}${n?`?${n}`:""}`};var R=(t,e={})=>{let r=h(e)?Y(t,e):B(t,e);if(!e.origin)return r;try{return new URL(r,e.origin).toString()}catch{return r}};var H={"/dine-in/menus":"dine-in-menus","/self-service/menus":"self-service-menus","/collect-payment":"collect-payment","/reservation":"reservation"},K={"dine-in":(t,e)=>({type:"dine-in",order:t,state:e}),"pay-point":(t,e)=>({type:"pay-point",payPoint:t,state:e}),beacons:(t,e)=>({type:"beacon",beacon:t,state:e}),links:(t,e)=>({type:"link",link:t,state:e}),pay:(t,e)=>({type:"pay-session",session:t,state:e})},Z=(t,e)=>Object.hasOwn(t,e),x=(t,e={})=>{try{let r=m(t),o=k(r,"v1"),s=D(S(r.pathname),e.installation),n=s.split("/").filter(Boolean);if(n[0]==="order"&&n[1]){let i=p(n,1);if(n[2]==="pages"&&n.length===4)return {type:"content-page",business:i,slug:p(n,3),state:o};let l=n[2]?p(n,2):void 0;if(l&&n[3]==="pages"&&n.length===5)return {type:"content-page",business:i,branch:l,slug:p(n,4),state:o};if(l&&n[3]==="products"&&n[4]&&n.length===5)return {type:"item",business:i,branch:l,item:p(n,4),state:o};if(n.length<=3||n.length===4&&n[3]==="products"){let A=o.modalId?.startsWith(d)?o.modalId.slice(d.length):"";return l&&A?{type:"item",business:i,branch:l,item:A,state:o}:{type:"order-menu",business:i,...l?{branch:l}:{},...n[3]==="products"?{cataloguePath:!0}:{},state:o}}}if(Z(H,s))return {type:H[s],state:o};let[c="",u]=n;if(n.length===2&&u&&Z(K,c))return K[c](p(n,1),o);if(n[0]==="payment"&&n[1]==="card"&&n[2]&&n.length===3)return {type:"payment-card",transaction:p(n,2),state:o};if(n[0]==="payment"&&n[1]&&n.length<=3){let i=n[2];if(!i||i==="successful"||i==="failed"||i==="refunded")return {type:"payment-step",payment:p(n,1),step:i==="successful"||i==="failed"||i==="refunded"?i:"payment",state:o}}if(n[0]==="orders"&&n.length<=2)return {type:"profile",page:"orders",...n[1]?{order:p(n,1)}:{},state:o};if(n[0]==="profile"&&n[1]&&n.length<=3){let i=n[1];if(i==="add-store-credit"||i==="edit"||i==="payment-methods"||i==="transactions")return {type:"profile",page:i,state:o};if(i==="orders")return {type:"profile",page:i,...n[2]?{order:p(n,2)}:{},state:o}}return s==="/"||s==="/explore"?{type:"explore",...s==="/"?{home:!0}:{},state:o}:{type:"unknown",pathname:s,state:o}}catch{return {type:"unknown",pathname:"",state:{query:{}}}}};var at=t=>t.searchParams.has("branch")?{branch:t.searchParams.get("branch")??""}:{},it=(t,e,r)=>{let o=S(t.pathname),s=o.split("/").filter(Boolean),n=at(t);if(o==="/")return {type:"order-menu",business:r,...n,state:e};if(s[0]==="item"&&s[1]&&s.length===2)return {type:"item",business:r,...n,item:p(s,1),state:e};if(o==="/cart"||o==="/checkout")return {type:o==="/cart"?"cart":"checkout",business:r,...n,state:e};if(o==="/checkout/return"){let c=t.searchParams.get("session");return {type:"checkout-return",business:r,...n,...c!==null?{session:c}:{},state:e}}if(o==="/sign-in"){let c=t.searchParams.get("return");return {type:"sign-in",business:r,...n,...c!==null?{returnTo:c}:{},state:e}}if(s[0]==="pages"&&s[1]&&s.length===2)return {type:"content-page",business:r,...n,slug:p(s,1),state:e};if(s[0]==="orders"&&s.length<=2)return {type:"profile",page:"orders",...s[1]?{order:p(s,1)}:{},state:e};if(s[0]==="account"&&s.length<=2){let c={"payment-methods":"payment-methods",transactions:"transactions","store-credit":"add-store-credit"};if(s.length===1)return {type:"profile",page:"edit",state:e};let u=s[1];if(u&&Object.hasOwn(c,u))return {type:"profile",page:c[u],state:e}}return null},j=(t,e)=>{if(t.type!=="order-menu")return t;let{authModalId:r,modalId:o}=t.state;return r&&E.has(r)?$(t,e):o?.startsWith(d)?{type:"item",business:t.business,...t.branch!==void 0?{branch:t.branch}:{},item:o.slice(d.length),state:t.state}:o===f||o===y?{type:o===f?"cart":"checkout",business:t.business,...t.branch!==void 0?{branch:t.branch}:{},state:t.state}:t},G=(t,e)=>{try{let r=m(t),o=k(r),s=e.installation;if(!s)return x(t,e);let n=it(r,o,s.business);return n?n.type==="order-menu"?j(n,s):n:j(x(t,{...e,contract:"v1"}),s)}catch{return {type:"unknown",pathname:"",state:{query:{}}}}};var I=(t,e={})=>h(e)?G(t,e):x(t,e);var X=t=>{let e=m(t);return e.searchParams.sort(),`${S(e.pathname)}${e.search}`},M=(t,e={})=>{if(!h(e))return null;try{let r=I(t,e);if(r.type==="unknown")return null;let o=R(r,e);return X(m(t))===X(o)?null:o}catch{return null}};var U=class extends a$1{constructor(){super("invalid_request","Zappie could not verify this webhook signature."),this.name="ZappieWebhookSignatureError";}},W=new TextEncoder;async function ct({payload:t,header:e,secret:r,toleranceSec:o=300,now:s=new Date}){let n=pt(e);if(r.length===0||!n||!Number.isFinite(o)||o<0||Math.abs(s.getTime()/1e3-n.seconds)>o)throw new U;let c=typeof t=="string"?W.encode(t):t,u=W.encode(`${n.timestamp}.`),i=new Uint8Array(u.length+c.length);i.set(u),i.set(c,u.length);let l=await crypto.subtle.importKey("raw",W.encode(r),{name:"HMAC",hash:"SHA-256"},false,["verify"]);if(!(await Promise.all(n.signatures.map(async O=>{let L=/^[0-9a-f]{64}$/.test(O),z=L?ut(O):new Uint8Array(32),J=await crypto.subtle.verify("HMAC",l,z,i);return L&&J}))).some(Boolean))throw new U;let b;try{b=JSON.parse(new TextDecoder().decode(c));}catch(O){throw new a$1("invalid_request","The verified webhook payload is not valid JSON.",{cause:O})}if(!b||typeof b!="object"||Array.isArray(b))throw new a$1("invalid_request","The verified webhook payload is not a JSON object.");return b}function pt(t){let e="",r=[];for(let s of t?.split(",")??[]){let n=s.trim(),c=n.indexOf("=");if(c<0)continue;let u=n.slice(0,c),i=n.slice(c+1);u==="t"?e=i:u==="v1"&&r.push(i);}if(!/^[+-]?\d+$/.test(e)||r.length===0)return null;let o=Number(e);return Number.isSafeInteger(o)?{timestamp:e,seconds:o,signatures:r}:null}function ut(t){let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r+=1)e[r]=Number.parseInt(t.slice(r*2,r*2+2),16);return e}function le({secretKey:t,...e}){return l({...e,key:t},true)}
|
|
2
|
-
|
|
1
|
+
// src/server/index.ts
|
|
2
|
+
import { buildClient } from "../client.js";
|
|
3
|
+
import { VERSION } from "../index.js";
|
|
4
|
+
import {
|
|
5
|
+
buildStorefrontUrl,
|
|
6
|
+
parseStorefrontUrl,
|
|
7
|
+
STOREFRONT_QUERY_PARAMETERS,
|
|
8
|
+
STOREFRONT_V1_QUERY_PARAMETERS,
|
|
9
|
+
storefrontRedirect
|
|
10
|
+
} from "../url/index.js";
|
|
11
|
+
import {
|
|
12
|
+
verifyWebhook,
|
|
13
|
+
ZappieWebhookSignatureError
|
|
14
|
+
} from "./webhook.js";
|
|
15
|
+
function createZappieServer({
|
|
16
|
+
secretKey,
|
|
17
|
+
...config
|
|
18
|
+
}) {
|
|
19
|
+
return buildClient({ ...config, key: secretKey }, true);
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
STOREFRONT_QUERY_PARAMETERS,
|
|
23
|
+
STOREFRONT_V1_QUERY_PARAMETERS,
|
|
24
|
+
VERSION,
|
|
25
|
+
ZappieWebhookSignatureError,
|
|
26
|
+
buildStorefrontUrl,
|
|
27
|
+
createZappieServer,
|
|
28
|
+
parseStorefrontUrl,
|
|
29
|
+
storefrontRedirect,
|
|
30
|
+
verifyWebhook
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/storefront-url/contract.ts","../../src/server/storefront-url/types.ts","../../src/server/storefront-url/url.ts","../../src/server/storefront-url/installation.ts","../../src/server/storefront-url/params.ts","../../src/server/storefront-url/build-v1.ts","../../src/server/storefront-url/sign-in.ts","../../src/server/storefront-url/build-v2.ts","../../src/server/storefront-url/build.ts","../../src/server/storefront-url/parse-v1.ts","../../src/server/storefront-url/parse-v2.ts","../../src/server/storefront-url/parse.ts","../../src/server/storefront-url/redirect.ts","../../src/server/webhook.ts","../../src/server/index.ts"],"names":["CART_MODAL","CHECKOUT_MODAL","SIGN_IN_MODAL","SIGN_IN_MODALS","usesV2","options","menuRoute","route","STOREFRONT_V1_QUERY_PARAMETERS","STOREFRONT_QUERY_PARAMETERS","FALLBACK_ORIGIN","ITEM_MODAL_PREFIX","decode","value","encode","inputUrl","input","queryRecord","params","contract","query","key","pageState","url","pickup","normalizedPath","pathname","installationPath","installation","business","suffix","publicInstallationPath","branchPrefix","segment","parts","index","stateParams","state","v1Params","v2Params","routePathV1","branch","buildV1","internal","publicRoute","signInFromOverlay","search","canonicalRoute","common","profilePath","routePathV2","buildV2","canonical","buildStorefrontUrl","FIXED_ROUTES","ID_ROUTES","order","payPoint","beacon","link","session","isKeyOf","table","parseV1","modalItem","prefix","id","step","page","scoped","returnTo","pages","overlay","authModalId","modalId","parseV2","parseStorefrontUrl","comparable","storefrontRedirect","target","ZappieWebhookSignatureError","ZappieError","encoder","verifyWebhook","payload","header","secret","toleranceSec","now","parsed","signatureHeader","body","signed","candidate","valid","bytes","hex","match","event","cause","timestamp","signatures","part","separator","item","seconds","createZappieServer","secretKey","config","buildClient"],"mappings":"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","file":"index.js","sourcesContent":["import type { StorefrontRoute, StorefrontUrlOptions } from \"./types\";\n\nexport const CART_MODAL = \"review-menu\";\nexport const CHECKOUT_MODAL = \"payment\";\nexport const SIGN_IN_MODAL = \"send-otp\";\nexport const SIGN_IN_MODALS = new Set([\n SIGN_IN_MODAL,\n \"verify-otp\",\n \"update-profile\",\n]);\n\nexport const usesV2 = (options: StorefrontUrlOptions) =>\n options.contract !== \"v1\" && options.installation !== undefined;\n\nexport const menuRoute = (\n route: Extract<\n StorefrontRoute,\n { type: \"cart\" | \"checkout\" | \"checkout-return\" | \"sign-in\" }\n >,\n): Extract<StorefrontRoute, { type: \"order-menu\" }> => ({\n type: \"order-menu\",\n business: route.business,\n ...(route.branch !== undefined ? { branch: route.branch } : {}),\n state: route.state,\n});\n","/**\n * A URL string, URL object or Request you can parse as a storefront route.\n */\nexport type StorefrontUrlInput = string | URL | Request;\n\n/**\n * The business and optional default branch bound to an installed storefront.\n */\nexport type StorefrontInstallation = {\n business: string;\n defaultBranch?: string;\n};\n\n/**\n * URL contract, installation and origin settings for parsing and building storefront routes.\n * An installation selects v2 unless you explicitly request v1.\n */\nexport type StorefrontUrlOptions = {\n contract?: \"v1\" | \"v2\";\n installation?: StorefrontInstallation;\n origin?: string;\n};\n\n/** Query keys that URL contract v1 keeps. */\nexport const STOREFRONT_V1_QUERY_PARAMETERS = [\n \"ref\",\n \"utm_source\",\n \"payment_id\",\n \"context\",\n \"prefetch\",\n \"business_tag\",\n \"pay_point_id\",\n \"dine_in_order_id\",\n \"no_context\",\n \"payment_context_id\",\n \"ws\",\n \"preview\",\n \"device\",\n \"auto_scroll\",\n \"pickup\",\n \"branch_closed\",\n \"order_id\",\n \"modal_id\",\n \"lightbox\",\n \"menu_id\",\n \"payment_method\",\n \"beacon_id\",\n \"menu_group_id\",\n \"category_id\",\n \"menu_layout\",\n \"can_schedule\",\n \"refresh\",\n \"success\",\n \"grant\",\n \"portal\",\n \"can_download_receipt\",\n \"auth_modal_id\",\n \"experimental_otp\",\n \"branch\",\n \"business\",\n \"env\",\n \"switched_branch\",\n \"from\",\n \"template\",\n \"catalog_rendering\",\n \"catalogue_search\",\n \"catalogue_categories\",\n] as const;\n\n/**\n * Recognized storefront query keys, including the v1 keys and checkout return and session keys.\n */\nexport const STOREFRONT_QUERY_PARAMETERS = [\n ...STOREFRONT_V1_QUERY_PARAMETERS,\n \"return\",\n \"session\",\n] as const;\n\n/**\n * Readonly query parameter names and string values carried by storefront page state.\n */\nexport type StorefrontQuery = Readonly<Record<string, string>>;\n\n/**\n * Query parameters and named UI selections carried alongside a storefront route.\n */\nexport type StorefrontPageState = {\n query: StorefrontQuery;\n menuId?: string;\n categoryId?: string;\n menuLayout?: string;\n mode?: \"delivery\" | \"pickup\";\n modalId?: string;\n authModalId?: string;\n paymentId?: string;\n lightbox?: string;\n catalogueSearch?: string;\n catalogueCategories?: string;\n};\n\nexport type WithState = { state: StorefrontPageState };\n\n/**\n * A parsed storefront destination with its route identifiers and page state.\n * Unrecognized paths use the unknown variant.\n */\nexport type StorefrontRoute =\n | ({\n type: \"order-menu\";\n business: string;\n branch?: string;\n cataloguePath?: boolean;\n } & WithState)\n | ({\n type: \"item\";\n business: string;\n branch?: string;\n item: string;\n } & WithState)\n | ({ type: \"cart\"; business: string; branch?: string } & WithState)\n | ({ type: \"checkout\"; business: string; branch?: string } & WithState)\n | ({\n type: \"checkout-return\";\n business: string;\n branch?: string;\n session?: string;\n } & WithState)\n | ({\n type: \"sign-in\";\n business: string;\n branch?: string;\n returnTo?: string;\n } & WithState)\n | ({\n type: \"content-page\";\n business: string;\n slug: string;\n branch?: string;\n } & WithState)\n | ({ type: \"dine-in\"; order: string } & WithState)\n | ({ type: \"dine-in-menus\" } & WithState)\n | ({ type: \"self-service-menus\" } & WithState)\n | ({ type: \"pay-point\"; payPoint: string } & WithState)\n | ({ type: \"beacon\"; beacon: string } & WithState)\n | ({ type: \"link\"; link: string } & WithState)\n | ({ type: \"collect-payment\" } & WithState)\n | ({ type: \"reservation\" } & WithState)\n | ({ type: \"pay-session\"; session: string } & WithState)\n | ({\n type: \"payment-step\";\n payment: string;\n step: \"payment\" | \"successful\" | \"failed\" | \"refunded\";\n } & WithState)\n | ({\n type: \"payment-card\";\n transaction: string;\n } & WithState)\n | ({\n type: \"profile\";\n page:\n | \"add-store-credit\"\n | \"edit\"\n | \"orders\"\n | \"payment-methods\"\n | \"transactions\";\n order?: string;\n } & WithState)\n | ({ type: \"explore\"; home?: boolean } & WithState)\n | ({ type: \"unknown\"; pathname: string } & WithState);\n","import {\n STOREFRONT_QUERY_PARAMETERS,\n STOREFRONT_V1_QUERY_PARAMETERS,\n type StorefrontPageState,\n type StorefrontUrlInput,\n} from \"./types\";\n\nexport const FALLBACK_ORIGIN = \"https://storefront.invalid\";\nexport const ITEM_MODAL_PREFIX = \"product_\";\n\nexport const decode = (value: string) => {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n};\n\nexport const encode = (value: string) => encodeURIComponent(value);\n\nexport const inputUrl = (input: StorefrontUrlInput) => {\n if (input instanceof URL) {\n return new URL(input.toString());\n }\n const value = typeof input === \"string\" ? input : input.url;\n return new URL(value, FALLBACK_ORIGIN);\n};\n\nexport const queryRecord = (params: URLSearchParams, contract: \"v1\" | \"v2\") => {\n const query: Record<string, string> = {};\n params.forEach((value, key) => {\n const allowed: readonly string[] =\n contract === \"v2\"\n ? STOREFRONT_QUERY_PARAMETERS\n : STOREFRONT_V1_QUERY_PARAMETERS;\n if (allowed.includes(key)) {\n query[key] = value;\n }\n });\n return query;\n};\n\nexport const pageState = (\n url: URL,\n contract: \"v1\" | \"v2\" = \"v2\",\n): StorefrontPageState => {\n const query = queryRecord(url.searchParams, contract);\n const pickup = url.searchParams.get(\"pickup\");\n return {\n query,\n ...(url.searchParams.has(\"menu_id\")\n ? { menuId: url.searchParams.get(\"menu_id\") ?? \"\" }\n : {}),\n ...(url.searchParams.has(\"category_id\")\n ? { categoryId: url.searchParams.get(\"category_id\") ?? \"\" }\n : {}),\n ...(url.searchParams.has(\"menu_layout\")\n ? { menuLayout: url.searchParams.get(\"menu_layout\") ?? \"\" }\n : {}),\n ...(pickup === \"true\"\n ? { mode: \"pickup\" as const }\n : pickup === \"false\"\n ? { mode: \"delivery\" as const }\n : {}),\n ...(url.searchParams.has(\"modal_id\")\n ? { modalId: url.searchParams.get(\"modal_id\") ?? \"\" }\n : {}),\n ...(url.searchParams.has(\"auth_modal_id\")\n ? { authModalId: url.searchParams.get(\"auth_modal_id\") ?? \"\" }\n : {}),\n ...(url.searchParams.has(\"payment_id\")\n ? { paymentId: url.searchParams.get(\"payment_id\") ?? \"\" }\n : {}),\n ...(url.searchParams.has(\"lightbox\")\n ? { lightbox: url.searchParams.get(\"lightbox\") ?? \"\" }\n : {}),\n ...(url.searchParams.has(\"catalogue_search\")\n ? { catalogueSearch: url.searchParams.get(\"catalogue_search\") ?? \"\" }\n : {}),\n ...(url.searchParams.has(\"catalogue_categories\")\n ? {\n catalogueCategories:\n url.searchParams.get(\"catalogue_categories\") ?? \"\",\n }\n : {}),\n };\n};\n","import { type StorefrontInstallation, type StorefrontRoute } from \"./types\";\nimport { decode, encode } from \"./url\";\n\nexport const normalizedPath = (pathname: string) => {\n const trimmed = pathname.replace(/\\/+$/, \"\");\n return trimmed || \"/\";\n};\n\nexport const installationPath = (\n pathname: string,\n installation?: StorefrontInstallation,\n) => {\n if (!installation) {\n return pathname;\n }\n const business = `/order/${encode(installation.business)}`;\n if (pathname === \"/\") {\n return business;\n }\n if (pathname === \"/order\") {\n return installation.defaultBranch\n ? `${business}/${encode(installation.defaultBranch)}`\n : business;\n }\n if (pathname.startsWith(\"/pages/\")) {\n return `${business}${pathname}`;\n }\n if (\n !pathname.startsWith(\"/order/\") ||\n pathname === business ||\n pathname.startsWith(`${business}/`)\n ) {\n return pathname;\n }\n const suffix = pathname.slice(\"/order\".length);\n if (\n installation.defaultBranch &&\n (suffix === \"/products\" ||\n suffix.startsWith(\"/products/\") ||\n suffix.startsWith(\"/pages/\"))\n ) {\n return `${business}/${encode(installation.defaultBranch)}${suffix}`;\n }\n return `${business}${suffix}`;\n};\n\nexport const publicInstallationPath = (\n pathname: string,\n route: StorefrontRoute,\n installation?: StorefrontInstallation,\n) => {\n if (!installation || !(\"business\" in route)) {\n return pathname;\n }\n if (route.business !== installation.business) {\n return pathname;\n }\n if (route.type === \"content-page\" && !route.branch) {\n return `/pages/${encode(route.slug)}`;\n }\n if (route.type === \"order-menu\" && !route.branch) {\n return \"/\";\n }\n const branchPrefix = `/order/${encode(route.business)}/${encode(route.branch ?? \"\")}`;\n const suffix = pathname.slice(branchPrefix.length);\n if (route.branch === installation.defaultBranch) {\n return `/order${suffix}`;\n }\n return `/order/${encode(route.branch ?? \"\")}${suffix}`;\n};\n\nexport const segment = (parts: string[], index: number) =>\n decode(parts[index] ?? \"\");\n","import { CART_MODAL, CHECKOUT_MODAL, SIGN_IN_MODAL } from \"./contract\";\nimport type { StorefrontInstallation, StorefrontRoute } from \"./types\";\n\nconst stateParams = (route: StorefrontRoute) => {\n const params = new URLSearchParams(route.state.query);\n const state = route.state;\n const values: ReadonlyArray<[string, string | undefined]> = [\n [\"menu_id\", state.menuId],\n [\"category_id\", state.categoryId],\n [\"menu_layout\", state.menuLayout],\n [\"pickup\", state.mode ? String(state.mode === \"pickup\") : undefined],\n [\"modal_id\", state.modalId],\n [\"auth_modal_id\", state.authModalId],\n [\"payment_id\", state.paymentId],\n [\"lightbox\", state.lightbox],\n [\"catalogue_search\", state.catalogueSearch],\n [\"catalogue_categories\", state.catalogueCategories],\n ];\n values.forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, value);\n }\n });\n return params;\n};\n\nexport const v1Params = (route: StorefrontRoute) => {\n const params = stateParams(route);\n if (route.type === \"item\") {\n params.delete(\"modal_id\");\n } else if (route.type === \"cart\") {\n params.set(\"modal_id\", CART_MODAL);\n } else if (route.type === \"checkout\") {\n params.set(\"modal_id\", CHECKOUT_MODAL);\n } else if (route.type === \"sign-in\") {\n params.set(\"auth_modal_id\", SIGN_IN_MODAL);\n if (route.returnTo !== undefined) {\n params.set(\"return\", route.returnTo);\n }\n } else if (route.type === \"checkout-return\" && route.session !== undefined) {\n params.set(\"session\", route.session);\n }\n params.sort();\n return params;\n};\n\nexport const v2Params = (\n route: StorefrontRoute,\n installation: StorefrontInstallation,\n) => {\n const params = stateParams(route);\n if (\n route.type === \"order-menu\" ||\n route.type === \"item\" ||\n route.type === \"cart\" ||\n route.type === \"checkout\" ||\n route.type === \"checkout-return\" ||\n route.type === \"sign-in\" ||\n route.type === \"content-page\"\n ) {\n if (route.branch && route.branch !== installation.defaultBranch) {\n params.set(\"branch\", route.branch);\n } else {\n params.delete(\"branch\");\n }\n }\n if (\n route.type === \"item\" ||\n route.type === \"cart\" ||\n route.type === \"checkout\" ||\n route.type === \"checkout-return\"\n ) {\n params.delete(\"modal_id\");\n }\n if (route.type === \"sign-in\") {\n params.delete(\"auth_modal_id\");\n if (route.returnTo !== undefined) {\n params.set(\"return\", route.returnTo);\n }\n }\n if (route.type === \"checkout-return\" && route.session !== undefined) {\n params.set(\"session\", route.session);\n }\n params.sort();\n return params;\n};\n","import { menuRoute } from \"./contract\";\nimport { publicInstallationPath } from \"./installation\";\nimport { v1Params } from \"./params\";\nimport { type StorefrontRoute, type StorefrontUrlOptions } from \"./types\";\nimport { encode } from \"./url\";\n\nexport const routePathV1 = (\n route: StorefrontRoute,\n options: StorefrontUrlOptions = {},\n): string => {\n switch (route.type) {\n case \"order-menu\":\n return `/order/${encode(route.business)}${route.branch ? `/${encode(route.branch)}` : \"\"}${route.cataloguePath ? \"/products\" : \"\"}`;\n case \"item\": {\n const branch = route.branch ?? options.installation?.defaultBranch;\n return branch\n ? `/order/${encode(route.business)}/${encode(branch)}/products/${encode(route.item)}`\n : `/order/${encode(route.business)}`;\n }\n case \"cart\":\n case \"checkout\":\n case \"checkout-return\":\n case \"sign-in\":\n return routePathV1(menuRoute(route), options);\n case \"content-page\":\n return `/order/${encode(route.business)}${route.branch ? `/${encode(route.branch)}` : \"\"}/pages/${encode(route.slug)}`;\n case \"dine-in\":\n return `/dine-in/${encode(route.order)}`;\n case \"dine-in-menus\":\n return \"/dine-in/menus\";\n case \"self-service-menus\":\n return \"/self-service/menus\";\n case \"pay-point\":\n return `/pay-point/${encode(route.payPoint)}`;\n case \"beacon\":\n return `/beacons/${encode(route.beacon)}`;\n case \"link\":\n return `/links/${encode(route.link)}`;\n case \"collect-payment\":\n return \"/collect-payment\";\n case \"reservation\":\n return \"/reservation\";\n case \"pay-session\":\n return `/pay/${encode(route.session)}`;\n case \"payment-step\":\n return `/payment/${encode(route.payment)}${route.step === \"payment\" ? \"\" : `/${route.step}`}`;\n case \"payment-card\":\n return `/payment/card/${encode(route.transaction)}`;\n case \"profile\":\n return `/profile/${route.page}${route.order ? `/${encode(route.order)}` : \"\"}`;\n case \"explore\":\n return route.home ? \"/\" : \"/explore\";\n case \"unknown\":\n return route.pathname || \"/\";\n }\n};\n\nexport const buildV1 = (\n route: StorefrontRoute,\n options: StorefrontUrlOptions = {},\n) => {\n const internal = routePathV1(route, options);\n const publicRoute =\n route.type === \"item\" &&\n route.branch === undefined &&\n options.installation?.defaultBranch\n ? { ...route, branch: options.installation.defaultBranch }\n : route;\n const pathname = publicInstallationPath(\n internal,\n publicRoute,\n options.installation,\n );\n const query = v1Params(route).toString();\n const value = `${pathname}${query ? `?${query}` : \"\"}`;\n if (!options.origin) {\n return value;\n }\n try {\n return new URL(value, options.origin).toString();\n } catch {\n return value;\n }\n};\n","import { v2Params } from \"./params\";\nimport type { StorefrontInstallation, StorefrontRoute } from \"./types\";\n\nexport const signInFromOverlay = (\n route: Extract<StorefrontRoute, { type: \"order-menu\" }>,\n installation: StorefrontInstallation,\n): Extract<StorefrontRoute, { type: \"sign-in\" }> => {\n const params = v2Params(route, installation);\n params.delete(\"auth_modal_id\");\n const search = params.toString();\n return {\n type: \"sign-in\",\n business: route.business,\n state: { query: {} },\n returnTo: `/${search ? `?${search}` : \"\"}`,\n };\n};\n","import { routePathV1 } from \"./build-v1\";\nimport { CART_MODAL, CHECKOUT_MODAL, SIGN_IN_MODALS } from \"./contract\";\nimport { v2Params } from \"./params\";\nimport { signInFromOverlay } from \"./sign-in\";\nimport type {\n StorefrontInstallation,\n StorefrontRoute,\n StorefrontUrlOptions,\n} from \"./types\";\nimport { encode, ITEM_MODAL_PREFIX } from \"./url\";\n\nconst canonicalRoute = (\n route: StorefrontRoute,\n installation: StorefrontInstallation,\n): StorefrontRoute => {\n if (route.type !== \"order-menu\") {\n return route;\n }\n const common = {\n business: route.business,\n ...(route.branch !== undefined ? { branch: route.branch } : {}),\n state: route.state,\n };\n if (route.state.authModalId && SIGN_IN_MODALS.has(route.state.authModalId)) {\n return signInFromOverlay(route, installation);\n }\n if (route.state.modalId?.startsWith(ITEM_MODAL_PREFIX)) {\n return {\n type: \"item\",\n ...common,\n item: route.state.modalId.slice(ITEM_MODAL_PREFIX.length),\n };\n }\n if (route.state.modalId === CART_MODAL) {\n return { type: \"cart\", ...common };\n }\n if (route.state.modalId === CHECKOUT_MODAL) {\n return { type: \"checkout\", ...common };\n }\n return route;\n};\n\nconst profilePath = (route: Extract<StorefrontRoute, { type: \"profile\" }>) => {\n if (route.page === \"orders\") {\n return `/orders${route.order ? `/${encode(route.order)}` : \"\"}`;\n }\n if (route.page === \"edit\") {\n return \"/account\";\n }\n const page = route.page === \"add-store-credit\" ? \"store-credit\" : route.page;\n return `/account/${page}`;\n};\n\nconst routePathV2 = (route: StorefrontRoute, options: StorefrontUrlOptions) => {\n switch (route.type) {\n case \"order-menu\":\n return \"/\";\n case \"item\":\n return `/item/${encode(route.item)}`;\n case \"cart\":\n return \"/cart\";\n case \"checkout\":\n return \"/checkout\";\n case \"checkout-return\":\n return \"/checkout/return\";\n case \"sign-in\":\n return \"/sign-in\";\n case \"content-page\":\n return `/pages/${encode(route.slug)}`;\n case \"profile\":\n return profilePath(route);\n default:\n return routePathV1(route, options);\n }\n};\n\nexport const buildV2 = (\n route: StorefrontRoute,\n options: StorefrontUrlOptions,\n) => {\n const installation = options.installation;\n if (!installation) {\n return \"\";\n }\n const canonical = canonicalRoute(route, installation);\n const pathname = routePathV2(canonical, options);\n const query = v2Params(canonical, installation).toString();\n return `${pathname}${query ? `?${query}` : \"\"}`;\n};\n","import { buildV1 } from \"./build-v1\";\nimport { buildV2 } from \"./build-v2\";\nimport { usesV2 } from \"./contract\";\nimport type { StorefrontRoute, StorefrontUrlOptions } from \"./types\";\n\n/**\n * Build a storefront URL from a route and its page state.\n * Uses v2 when installation metadata is present unless you select v1 explicitly.\n *\n * @param route - The destination and UI state to encode.\n * @param options - Contract, installation and optional origin for an absolute URL.\n * @returns The built path, or an absolute URL when the origin resolves successfully.\n */\nexport const buildStorefrontUrl = (\n route: StorefrontRoute,\n options: StorefrontUrlOptions = {},\n) => {\n const value = usesV2(options)\n ? buildV2(route, options)\n : buildV1(route, options);\n if (!options.origin) {\n return value;\n }\n try {\n return new URL(value, options.origin).toString();\n } catch {\n return value;\n }\n};\n","import { installationPath, normalizedPath, segment } from \"./installation\";\nimport {\n type StorefrontPageState,\n type StorefrontRoute,\n type StorefrontUrlInput,\n type StorefrontUrlOptions,\n} from \"./types\";\nimport { ITEM_MODAL_PREFIX, inputUrl, pageState } from \"./url\";\n\n/** Paths with no variable segment. Checked before ID_ROUTES: `/dine-in/menus` is not a dine-in order. */\nconst FIXED_ROUTES = {\n \"/dine-in/menus\": \"dine-in-menus\",\n \"/self-service/menus\": \"self-service-menus\",\n \"/collect-payment\": \"collect-payment\",\n \"/reservation\": \"reservation\",\n} as const;\n\n/** `/<prefix>/<id>` routes, where the one segment after the prefix names the resource. */\nconst ID_ROUTES = {\n \"dine-in\": (order, state) => ({ type: \"dine-in\", order, state }),\n \"pay-point\": (payPoint, state) => ({ type: \"pay-point\", payPoint, state }),\n beacons: (beacon, state) => ({ type: \"beacon\", beacon, state }),\n links: (link, state) => ({ type: \"link\", link, state }),\n pay: (session, state) => ({ type: \"pay-session\", session, state }),\n} satisfies Record<\n string,\n (id: string, state: StorefrontPageState) => StorefrontRoute\n>;\n\nconst isKeyOf = <T extends object>(\n table: T,\n key: string,\n): key is Extract<keyof T, string> => Object.hasOwn(table, key);\n\nexport const parseV1 = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions = {},\n): StorefrontRoute => {\n try {\n const url = inputUrl(input);\n const state = pageState(url, \"v1\");\n const pathname = installationPath(\n normalizedPath(url.pathname),\n options.installation,\n );\n const parts = pathname.split(\"/\").filter(Boolean);\n\n if (parts[0] === \"order\" && parts[1]) {\n const business = segment(parts, 1);\n if (parts[2] === \"pages\" && parts.length === 4) {\n return {\n type: \"content-page\",\n business,\n slug: segment(parts, 3),\n state,\n };\n }\n const branch = parts[2] ? segment(parts, 2) : undefined;\n if (branch && parts[3] === \"pages\" && parts.length === 5) {\n return {\n type: \"content-page\",\n business,\n branch,\n slug: segment(parts, 4),\n state,\n };\n }\n if (branch && parts[3] === \"products\" && parts[4] && parts.length === 5) {\n return {\n type: \"item\",\n business,\n branch,\n item: segment(parts, 4),\n state,\n };\n }\n if (\n parts.length <= 3 ||\n (parts.length === 4 && parts[3] === \"products\")\n ) {\n const modalItem = state.modalId?.startsWith(ITEM_MODAL_PREFIX)\n ? state.modalId.slice(ITEM_MODAL_PREFIX.length)\n : \"\";\n if (branch && modalItem) {\n return {\n type: \"item\",\n business,\n branch,\n item: modalItem,\n state,\n };\n }\n return {\n type: \"order-menu\",\n business,\n ...(branch ? { branch } : {}),\n ...(parts[3] === \"products\" ? { cataloguePath: true } : {}),\n state,\n };\n }\n }\n\n if (isKeyOf(FIXED_ROUTES, pathname)) {\n return { type: FIXED_ROUTES[pathname], state };\n }\n const [prefix = \"\", id] = parts;\n if (parts.length === 2 && id && isKeyOf(ID_ROUTES, prefix)) {\n return ID_ROUTES[prefix](segment(parts, 1), state);\n }\n if (\n parts[0] === \"payment\" &&\n parts[1] === \"card\" &&\n parts[2] &&\n parts.length === 3\n ) {\n return { type: \"payment-card\", transaction: segment(parts, 2), state };\n }\n if (parts[0] === \"payment\" && parts[1] && parts.length <= 3) {\n const step = parts[2];\n if (\n !step ||\n step === \"successful\" ||\n step === \"failed\" ||\n step === \"refunded\"\n ) {\n return {\n type: \"payment-step\",\n payment: segment(parts, 1),\n step:\n step === \"successful\" || step === \"failed\" || step === \"refunded\"\n ? step\n : \"payment\",\n state,\n };\n }\n }\n if (parts[0] === \"orders\" && parts.length <= 2) {\n return {\n type: \"profile\",\n page: \"orders\",\n ...(parts[1] ? { order: segment(parts, 1) } : {}),\n state,\n };\n }\n if (parts[0] === \"profile\" && parts[1] && parts.length <= 3) {\n const page = parts[1];\n if (\n page === \"add-store-credit\" ||\n page === \"edit\" ||\n page === \"payment-methods\" ||\n page === \"transactions\"\n ) {\n return { type: \"profile\", page, state };\n }\n if (page === \"orders\") {\n return {\n type: \"profile\",\n page,\n ...(parts[2] ? { order: segment(parts, 2) } : {}),\n state,\n };\n }\n }\n if (pathname === \"/\" || pathname === \"/explore\") {\n return {\n type: \"explore\",\n ...(pathname === \"/\" ? { home: true } : {}),\n state,\n };\n }\n return { type: \"unknown\", pathname, state };\n } catch {\n return { type: \"unknown\", pathname: \"\", state: { query: {} } };\n }\n};\n","import { CART_MODAL, CHECKOUT_MODAL, SIGN_IN_MODALS } from \"./contract\";\nimport { normalizedPath, segment } from \"./installation\";\nimport { parseV1 } from \"./parse-v1\";\nimport { signInFromOverlay } from \"./sign-in\";\nimport type {\n StorefrontPageState,\n StorefrontRoute,\n StorefrontUrlInput,\n StorefrontUrlOptions,\n} from \"./types\";\nimport { ITEM_MODAL_PREFIX, inputUrl, pageState } from \"./url\";\n\nconst branch = (url: URL) =>\n url.searchParams.has(\"branch\")\n ? { branch: url.searchParams.get(\"branch\") ?? \"\" }\n : {};\n\nconst canonical = (\n url: URL,\n state: StorefrontPageState,\n business: string,\n): StorefrontRoute | null => {\n const pathname = normalizedPath(url.pathname);\n const parts = pathname.split(\"/\").filter(Boolean);\n const scoped = branch(url);\n if (pathname === \"/\") {\n return { type: \"order-menu\", business, ...scoped, state };\n }\n if (parts[0] === \"item\" && parts[1] && parts.length === 2) {\n return {\n type: \"item\",\n business,\n ...scoped,\n item: segment(parts, 1),\n state,\n };\n }\n if (pathname === \"/cart\" || pathname === \"/checkout\") {\n return {\n type: pathname === \"/cart\" ? \"cart\" : \"checkout\",\n business,\n ...scoped,\n state,\n };\n }\n if (pathname === \"/checkout/return\") {\n const session = url.searchParams.get(\"session\");\n return {\n type: \"checkout-return\",\n business,\n ...scoped,\n ...(session !== null ? { session } : {}),\n state,\n };\n }\n if (pathname === \"/sign-in\") {\n const returnTo = url.searchParams.get(\"return\");\n return {\n type: \"sign-in\",\n business,\n ...scoped,\n ...(returnTo !== null ? { returnTo } : {}),\n state,\n };\n }\n if (parts[0] === \"pages\" && parts[1] && parts.length === 2) {\n return {\n type: \"content-page\",\n business,\n ...scoped,\n slug: segment(parts, 1),\n state,\n };\n }\n if (parts[0] === \"orders\" && parts.length <= 2) {\n return {\n type: \"profile\",\n page: \"orders\",\n ...(parts[1] ? { order: segment(parts, 1) } : {}),\n state,\n };\n }\n if (parts[0] === \"account\" && parts.length <= 2) {\n const pages = {\n \"payment-methods\": \"payment-methods\",\n transactions: \"transactions\",\n \"store-credit\": \"add-store-credit\",\n } as const;\n if (parts.length === 1) {\n return { type: \"profile\", page: \"edit\", state };\n }\n const page = parts[1];\n if (page && Object.hasOwn(pages, page)) {\n return {\n type: \"profile\",\n page: pages[page as keyof typeof pages],\n state,\n };\n }\n }\n return null;\n};\n\nconst overlay = (\n route: StorefrontRoute,\n installation: NonNullable<StorefrontUrlOptions[\"installation\"]>,\n): StorefrontRoute => {\n if (route.type !== \"order-menu\") {\n return route;\n }\n const { authModalId, modalId } = route.state;\n if (authModalId && SIGN_IN_MODALS.has(authModalId)) {\n return signInFromOverlay(route, installation);\n }\n if (modalId?.startsWith(ITEM_MODAL_PREFIX)) {\n return {\n type: \"item\",\n business: route.business,\n ...(route.branch !== undefined ? { branch: route.branch } : {}),\n item: modalId.slice(ITEM_MODAL_PREFIX.length),\n state: route.state,\n };\n }\n if (modalId === CART_MODAL || modalId === CHECKOUT_MODAL) {\n return {\n type: modalId === CART_MODAL ? \"cart\" : \"checkout\",\n business: route.business,\n ...(route.branch !== undefined ? { branch: route.branch } : {}),\n state: route.state,\n };\n }\n return route;\n};\n\nexport const parseV2 = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions,\n): StorefrontRoute => {\n try {\n const url = inputUrl(input);\n const state = pageState(url);\n const installation = options.installation;\n if (!installation) {\n return parseV1(input, options);\n }\n const route = canonical(url, state, installation.business);\n if (route) {\n return route.type === \"order-menu\" ? overlay(route, installation) : route;\n }\n return overlay(\n parseV1(input, { ...options, contract: \"v1\" }),\n installation,\n );\n } catch {\n return { type: \"unknown\", pathname: \"\", state: { query: {} } };\n }\n};\n","import { usesV2 } from \"./contract\";\nimport { parseV1 } from \"./parse-v1\";\nimport { parseV2 } from \"./parse-v2\";\nimport type {\n StorefrontRoute,\n StorefrontUrlInput,\n StorefrontUrlOptions,\n} from \"./types\";\n\n/**\n * Parse a storefront URL into a route and its page state.\n * Uses v2 when installation metadata is present unless you select v1 explicitly.\n *\n * @param input - A URL string, URL object or Request.\n * @param options - Contract, installation and origin settings.\n * @returns A recognized route or an unknown route retaining the pathname.\n */\nexport const parseStorefrontUrl = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions = {},\n): StorefrontRoute =>\n usesV2(options) ? parseV2(input, options) : parseV1(input, options);\n","import { buildStorefrontUrl } from \"./build\";\nimport { usesV2 } from \"./contract\";\nimport { normalizedPath } from \"./installation\";\nimport { parseStorefrontUrl } from \"./parse\";\nimport type { StorefrontUrlInput, StorefrontUrlOptions } from \"./types\";\nimport { inputUrl } from \"./url\";\n\nconst comparable = (value: string | URL) => {\n const url = inputUrl(value);\n url.searchParams.sort();\n return `${normalizedPath(url.pathname)}${url.search}`;\n};\n\n/**\n * Find the canonical v2 URL for a recognized storefront route.\n * Compares normalized paths and sorted query parameters to avoid unnecessary redirects.\n *\n * @returns A redirect target, or null for v1, an unknown route, a parse/build failure or an equivalent URL.\n */\nexport const storefrontRedirect = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions = {},\n): string | null => {\n if (!usesV2(options)) {\n return null;\n }\n try {\n const route = parseStorefrontUrl(input, options);\n if (route.type === \"unknown\") {\n return null;\n }\n const target = buildStorefrontUrl(route, options);\n return comparable(inputUrl(input)) === comparable(target) ? null : target;\n } catch {\n return null;\n }\n};\n","import { ZappieError } from \"../errors\";\n\n/** Event names sent by the Zappie webhook API. */\nexport type WebhookEventType =\n | \"menu.updated\"\n | \"branch.hours_changed\"\n | \"store.updated\"\n | \"checkout.session.completed\"\n | \"checkout.session.expired\"\n | \"order.created\"\n | \"order.paid\"\n | \"order.status_changed\"\n | \"customer.signed_in\"\n | \"payout.initiated\"\n | \"payout.paid\"\n | \"payout.failed\"\n | \"payout_request.created\"\n | \"payout_request.approved\"\n | \"payout_request.rejected\"\n | \"payment.received\";\n\n/** The event envelope sent in a Zappie webhook request. */\nexport type WebhookEvent = {\n id: string;\n type: WebhookEventType;\n version: string;\n created_at: string;\n livemode: boolean;\n business_id: string;\n branch_id?: string;\n idempotency_key: string;\n data: { object: Record<string, unknown> };\n previous_attributes: Record<string, unknown> | null;\n};\n\n/** Input for webhook signature verification. */\nexport type VerifyWebhookOptions = {\n payload: string | Uint8Array;\n header: string | null | undefined;\n secret: string;\n toleranceSec?: number;\n now?: Date;\n};\n\n/** A webhook signature that cannot be trusted. */\nexport class ZappieWebhookSignatureError extends ZappieError {\n constructor() {\n super(\"invalid_request\", \"Zappie could not verify this webhook signature.\");\n this.name = \"ZappieWebhookSignatureError\";\n }\n}\n\nconst encoder = new TextEncoder();\n\n/** Verify a webhook signature against its raw body and return the event. */\nexport async function verifyWebhook({\n payload,\n header,\n secret,\n toleranceSec = 300,\n now = new Date(),\n}: VerifyWebhookOptions): Promise<WebhookEvent> {\n const parsed = signatureHeader(header);\n if (\n secret.length === 0 ||\n !parsed ||\n !Number.isFinite(toleranceSec) ||\n toleranceSec < 0 ||\n Math.abs(now.getTime() / 1000 - parsed.seconds) > toleranceSec\n ) {\n throw new ZappieWebhookSignatureError();\n }\n const body = typeof payload === \"string\" ? encoder.encode(payload) : payload;\n const prefix = encoder.encode(`${parsed.timestamp}.`);\n const signed = new Uint8Array(prefix.length + body.length);\n signed.set(prefix);\n signed.set(body, prefix.length);\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"verify\"],\n );\n const matches = await Promise.all(\n parsed.signatures.map(async (candidate) => {\n const valid = /^[0-9a-f]{64}$/.test(candidate);\n const bytes = valid ? hex(candidate) : new Uint8Array(32);\n const match = await crypto.subtle.verify(\"HMAC\", key, bytes, signed);\n return valid && match;\n }),\n );\n if (!matches.some(Boolean)) {\n throw new ZappieWebhookSignatureError();\n }\n let event: unknown;\n try {\n event = JSON.parse(new TextDecoder().decode(body));\n } catch (cause) {\n throw new ZappieError(\n \"invalid_request\",\n \"The verified webhook payload is not valid JSON.\",\n { cause },\n );\n }\n if (!event || typeof event !== \"object\" || Array.isArray(event)) {\n throw new ZappieError(\n \"invalid_request\",\n \"The verified webhook payload is not a JSON object.\",\n );\n }\n return event as WebhookEvent;\n}\n\nfunction signatureHeader(header: string | null | undefined) {\n let timestamp = \"\";\n const signatures: string[] = [];\n for (const part of header?.split(\",\") ?? []) {\n const value = part.trim();\n const separator = value.indexOf(\"=\");\n if (separator < 0) {\n continue;\n }\n const key = value.slice(0, separator);\n const item = value.slice(separator + 1);\n if (key === \"t\") {\n timestamp = item;\n } else if (key === \"v1\") {\n signatures.push(item);\n }\n }\n if (!/^[+-]?\\d+$/.test(timestamp) || signatures.length === 0) {\n return null;\n }\n const seconds = Number(timestamp);\n return Number.isSafeInteger(seconds)\n ? { timestamp, seconds, signatures }\n : null;\n}\n\nfunction hex(value: string) {\n const bytes = new Uint8Array(value.length / 2);\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = Number.parseInt(value.slice(index * 2, index * 2 + 2), 16);\n }\n return bytes;\n}\n","import { buildClient } from \"../client\";\nimport type { ZappieConfig } from \"../config\";\nimport type { Menu } from \"../models\";\nexport { VERSION } from \"../index\";\nexport {\n buildStorefrontUrl,\n parseStorefrontUrl,\n STOREFRONT_QUERY_PARAMETERS,\n STOREFRONT_V1_QUERY_PARAMETERS,\n storefrontRedirect,\n type StorefrontInstallation,\n type StorefrontPageState,\n type StorefrontQuery,\n type StorefrontRoute,\n type StorefrontUrlInput,\n type StorefrontUrlOptions,\n} from \"../url/index\";\nexport {\n verifyWebhook,\n ZappieWebhookSignatureError,\n type VerifyWebhookOptions,\n type WebhookEvent,\n type WebhookEventType,\n} from \"./webhook\";\n/** An edge reader that returns a Menu snapshot or null. */\nexport interface EdgeSnapshotReader {\n getMenu(storeId: string, branchId: string): Promise<Menu | null>;\n}\n/** Settings for your server client. Keep secret keys out of browser bundles. */\nexport type ZappieServerConfig = Omit<ZappieConfig, \"key\"> & {\n secretKey: string;\n};\n/** Create a server client with your secret key and configured transport. */\nexport function createZappieServer({\n secretKey,\n ...config\n}: ZappieServerConfig) {\n return buildClient({ ...config, key: secretKey }, true);\n}\n"]}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/server/index.ts"],
|
|
4
|
+
"sourcesContent": ["import { buildClient } from \"../client\";\nimport type { ZappieConfig } from \"../config\";\nimport type { Menu } from \"../models\";\nexport { VERSION } from \"../index\";\nexport {\n buildStorefrontUrl,\n parseStorefrontUrl,\n STOREFRONT_QUERY_PARAMETERS,\n STOREFRONT_V1_QUERY_PARAMETERS,\n storefrontRedirect,\n type StorefrontInstallation,\n type StorefrontPageState,\n type StorefrontQuery,\n type StorefrontRoute,\n type StorefrontUrlInput,\n type StorefrontUrlOptions,\n} from \"../url/index\";\nexport {\n verifyWebhook,\n ZappieWebhookSignatureError,\n type VerifyWebhookOptions,\n type WebhookEvent,\n type WebhookEventType,\n} from \"./webhook\";\n/** An edge reader that returns a Menu snapshot or null. */\nexport interface EdgeSnapshotReader {\n getMenu(storeId: string, branchId: string): Promise<Menu | null>;\n}\n/** Settings for your server client. Keep secret keys out of browser bundles. */\nexport type ZappieServerConfig = Omit<ZappieConfig, \"key\"> & {\n secretKey: string;\n};\n/** Create a server client with your secret key and configured transport. */\nexport function createZappieServer({\n secretKey,\n ...config\n}: ZappieServerConfig) {\n return buildClient({ ...config, key: secretKey }, true);\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,mBAAmB;AAG5B,SAAS,eAAe;AACxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAOK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAUA,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,GAAG;AACL,GAAuB;AACrB,SAAO,YAAY,EAAE,GAAG,QAAQ,KAAK,UAAU,GAAG,IAAI;AACxD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|