@zappie/sdk 0.0.0-stage → 0.1.1
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 +19 -0
- package/LICENSE +21 -0
- package/README.md +79 -2
- package/dist/cart/item.d.ts +10 -0
- package/dist/cart/item.js +1 -0
- package/dist/cart/item.js.map +1 -0
- package/dist/cart/quote.d.ts +15 -0
- package/dist/cart/quote.js +1 -0
- package/dist/cart/quote.js.map +1 -0
- package/dist/checkout/index.d.ts +141 -0
- package/dist/checkout/index.js +1 -0
- package/dist/checkout/index.js.map +1 -0
- package/dist/chunk-I55A5QXJ.js +2 -0
- package/dist/chunk-I55A5QXJ.js.map +1 -0
- package/dist/chunk-LFBQICYU.js +2 -0
- package/dist/chunk-LFBQICYU.js.map +1 -0
- package/dist/client-BctSrEhO.d.ts +725 -0
- package/dist/config/index.d.ts +83 -0
- package/dist/config/index.js +1 -0
- package/dist/customer/index.d.ts +175 -0
- package/dist/customer/index.js +3 -0
- package/dist/customer/index.js.map +1 -0
- package/dist/customer/react.d.ts +31 -0
- package/dist/customer/react.js +3 -0
- package/dist/customer/react.js.map +1 -0
- package/dist/debug.d.ts +45 -0
- package/dist/debug.js +1 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +14 -0
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -0
- package/dist/models-Dj-VkdU1.d.ts +230 -0
- package/dist/persist/catalogue.d.ts +2 -0
- package/dist/persist/catalogue.js +2 -0
- package/dist/persist/catalogue.js.map +1 -0
- package/dist/places/index.d.ts +121 -0
- package/dist/places/index.js +1 -0
- package/dist/places/index.js.map +1 -0
- package/dist/react/index.d.ts +79 -0
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -0
- package/dist/server/index.d.ts +235 -0
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -0
- package/dist/template/index.d.ts +16 -0
- package/dist/template/index.js +3 -0
- package/dist/template/index.js.map +1 -0
- package/dist/template/react.d.ts +13 -0
- package/dist/template/react.js +3 -0
- package/dist/template/react.js.map +1 -0
- package/dist/testing/index.d.ts +64 -0
- package/dist/testing/index.js +2 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/transport/category-page.d.ts +17 -0
- package/dist/transport/category-page.js +2 -0
- package/dist/transport/category-page.js.map +1 -0
- package/dist/transport/search.d.ts +7 -0
- package/dist/transport/search.js +2 -0
- package/dist/transport/search.js.map +1 -0
- package/dist/transport/selected-menu.d.ts +2 -0
- package/dist/transport/selected-menu.js +2 -0
- package/dist/transport/selected-menu.js.map +1 -0
- package/dist/transport/store.d.ts +10 -0
- package/dist/transport/store.js +2 -0
- package/dist/transport/store.js.map +1 -0
- package/dist/url/index.d.ts +157 -0
- package/dist/url/index.js +2 -0
- package/dist/url/index.js.map +1 -0
- package/dist/visits/index.d.ts +89 -0
- package/dist/visits/index.js +1 -0
- package/dist/visits/index.js.map +1 -0
- package/package.json +105 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @zappie/sdk
|
|
2
|
+
|
|
3
|
+
## 0.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 38f23ac: `VERSION` (`@zappie/sdk`) and `FOUNDATIONS_VERSION` (`@zappie/foundations`) report the installed version. In 0.1.0 they said `"0.0.0"`. Verify reports now carry the real `verifyVersion`, and the test-mode debug channel the real SDK version.
|
|
8
|
+
- 1e6f420: Each package now has a README written for people installing it from npm: what it does, how to install and use it, its entry points, and links to docs.zappie.ai. `@zappie/kit` gains its first README.
|
|
9
|
+
|
|
10
|
+
## 0.1.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- - `@zappie/tokens`: Publish the semantic storefront token contract, CSS aliases, validation and compilation tools.
|
|
15
|
+
- `@zappie/sdk`: Publish the framework-agnostic storefront client and its React, server, checkout, customer, places, visits and URL entries. Money accepts every ISO 4217 currency the Zappie API accepts, with the API's minor-unit digits.
|
|
16
|
+
- `@zappie/foundations`: Publish accessible, unstyled React primitives for storefront catalogue, item, fulfilment and cart experiences.
|
|
17
|
+
- `@zappie/theme-base`: Publish the reusable base storefront theme and its catalogue, item and cart surfaces.
|
|
18
|
+
- `@zappie/kit`: Publish the built component registry consumed by the Zappie CLI.
|
|
19
|
+
- `zappie`: Publish the component CLI with `add`, `list` and `diff`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zappie
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,80 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @zappie/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The typed client for Zappie storefronts. Read a store and its menus, keep a cart on the shopper's device, get quoted totals from Zappie and hand payment to Zappie's hosted checkout. It runs in browsers, Node and Cloudflare Workers.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install @zappie/sdk
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Use it
|
|
10
|
+
|
|
11
|
+
Create a client with your publishable key and the store's slug, then share it with React through `ZappieProvider`:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { createZappie } from "@zappie/sdk";
|
|
15
|
+
import { ZappieProvider } from "@zappie/sdk/react";
|
|
16
|
+
import { type ReactNode, useMemo } from "react";
|
|
17
|
+
|
|
18
|
+
type StorefrontEnv = { ZAPPIE_KEY: string; ZAPPIE_STORE: string };
|
|
19
|
+
|
|
20
|
+
export function Storefront({
|
|
21
|
+
env,
|
|
22
|
+
children,
|
|
23
|
+
}: {
|
|
24
|
+
env: StorefrontEnv;
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
}) {
|
|
27
|
+
const client = useMemo(
|
|
28
|
+
() => createZappie({ key: env.ZAPPIE_KEY, store: env.ZAPPIE_STORE }),
|
|
29
|
+
[env.ZAPPIE_KEY, env.ZAPPIE_STORE],
|
|
30
|
+
);
|
|
31
|
+
return <ZappieProvider client={client}>{children}</ZappieProvider>;
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Any component inside can read the cart. Show Zappie's quoted total once it arrives, and the local subtotal until then:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { format } from "@zappie/sdk";
|
|
39
|
+
import { useCart } from "@zappie/sdk/react";
|
|
40
|
+
|
|
41
|
+
export function CartTotal() {
|
|
42
|
+
const cart = useCart();
|
|
43
|
+
const total =
|
|
44
|
+
cart.state.status === "quoted" ? cart.state.quote.total : cart.subtotal;
|
|
45
|
+
return <span>{total ? format.money(total) : "Add an item"}</span>;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Prices always come from Zappie. The cart shows a local estimate while it waits, and Zappie quotes the real total before checkout.
|
|
50
|
+
|
|
51
|
+
## Entry points
|
|
52
|
+
|
|
53
|
+
| Import | For |
|
|
54
|
+
| -------------------------------------------- | ---------------------------------------------------------------------- |
|
|
55
|
+
| `@zappie/sdk` | The client, the cart, money formatting and errors |
|
|
56
|
+
| `@zappie/sdk/react` | `ZappieProvider` and hooks such as `useStore`, `useMenu` and `useCart` |
|
|
57
|
+
| `@zappie/sdk/checkout` | Opening Zappie's hosted checkout and checking it completed |
|
|
58
|
+
| `@zappie/sdk/customer` and `/customer/react` | Signed-in customers, their orders and saved addresses |
|
|
59
|
+
| `@zappie/sdk/places` | Address search and delivery-zone checks |
|
|
60
|
+
| `@zappie/sdk/server` | Server-side reads, storefront URLs and `verifyWebhook()` |
|
|
61
|
+
| `@zappie/sdk/template` and `/template/react` | Template settings and responsive images for template authors |
|
|
62
|
+
| `@zappie/sdk/testing` | A mock client for your tests |
|
|
63
|
+
|
|
64
|
+
Customer sign-in runs through Zappie's site host, so `@zappie/sdk/customer` works on sites Zappie hosts. Sign-in for a site you host yourself isn't available yet.
|
|
65
|
+
|
|
66
|
+
Use a publishable key (`pk_test_…` or `pk_live_…`) in browsers. Secret keys work only in `@zappie/sdk/server`. `@zappie/sdk/internal` is for Zappie's own packages and can change in any release.
|
|
67
|
+
|
|
68
|
+
## Docs
|
|
69
|
+
|
|
70
|
+
- [SDK reference](https://docs.zappie.ai/sdk/core)
|
|
71
|
+
- [Build a storefront](https://docs.zappie.ai/guides/build-a-storefront)
|
|
72
|
+
- [Keys](https://docs.zappie.ai/keys)
|
|
73
|
+
|
|
74
|
+
## Status
|
|
75
|
+
|
|
76
|
+
The SDK is at `0.x`. Its API can change in a minor release while it settles. Each change is listed in `CHANGELOG.md`.
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
MIT
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Z as Zappie } from '../client-BctSrEhO.js';
|
|
2
|
+
import { I as Item } from '../models-Dj-VkdU1.js';
|
|
3
|
+
|
|
4
|
+
/** Register an item already read by a partial/selected catalogue, without fetching it again. */
|
|
5
|
+
declare function prepareItem(client: Zappie, item: Item, options: {
|
|
6
|
+
branch: string;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
}): Promise<Item>;
|
|
9
|
+
|
|
10
|
+
export { prepareItem };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
async function a(r,t,e){return e.signal?.throwIfAborted(),await r.menu.get({...e,metadataOnly:true}),e.signal?.throwIfAborted(),r._internal.cache.set(`item:${e.branch}:${t.id}`,t),r.menu.item(t.id,e)}export{a as prepareItem};//# sourceMappingURL=item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cart/item.ts"],"names":["prepareItem","client","item","options"],"mappings":"AAIA,eAAsBA,CAAAA,CACpBC,EACAC,CAAAA,CACAC,CAAAA,CACe,CACf,OAAAA,CAAAA,CAAQ,QAAQ,cAAA,EAAe,CAC/B,MAAMF,CAAAA,CAAO,IAAA,CAAK,IAAI,CAAE,GAAGE,EAAS,YAAA,CAAc,IAAK,CAAC,CAAA,CACxDA,CAAAA,CAAQ,QAAQ,cAAA,EAAe,CAC/BF,EAAO,SAAA,CAAU,KAAA,CAAM,IAAI,CAAA,KAAA,EAAQE,CAAAA,CAAQ,MAAM,CAAA,CAAA,EAAID,CAAAA,CAAK,EAAE,CAAA,CAAA,CAAIA,CAAI,EAG7DD,CAAAA,CAAO,IAAA,CAAK,KAAKC,CAAAA,CAAK,EAAA,CAAIC,CAAO,CAC1C","file":"item.js","sourcesContent":["import type { Zappie } from \"../client\";\nimport type { Item } from \"../models\";\n\n/** Register an item already read by a partial/selected catalogue, without fetching it again. */\nexport async function prepareItem(\n client: Zappie,\n item: Item,\n options: { branch: string; signal?: AbortSignal },\n): Promise<Item> {\n options.signal?.throwIfAborted();\n await client.menu.get({ ...options, metadataOnly: true });\n options.signal?.throwIfAborted();\n client._internal.cache.set(`item:${options.branch}:${item.id}`, item);\n // menu.item owns the working-set item registry. Its fresh cache entry means\n // this registration does no item read and never promotes a partial menu.\n return client.menu.item(item.id, options);\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { T as Transport, R as RequestCtx, Q as QuoteRequest, a as Quote } from '../client-BctSrEhO.js';
|
|
2
|
+
import '../models-Dj-VkdU1.js';
|
|
3
|
+
|
|
4
|
+
declare function createQuoteClient(transport: Transport, context: () => RequestCtx): {
|
|
5
|
+
cancel: () => void;
|
|
6
|
+
get(body: QuoteRequest, force: boolean, apply: (quote: Quote) => void): Promise<Quote>;
|
|
7
|
+
accept(issue: CartIssueForAcceptance): void;
|
|
8
|
+
};
|
|
9
|
+
type CartIssueForAcceptance = {
|
|
10
|
+
code: string;
|
|
11
|
+
lineId?: string;
|
|
12
|
+
};
|
|
13
|
+
type QuoteClient = ReturnType<typeof createQuoteClient>;
|
|
14
|
+
|
|
15
|
+
export { type QuoteClient, createQuoteClient };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {i as i$1,a,j,p,g,e}from'../chunk-I55A5QXJ.js';function d(){throw new a("server_error","Invalid quote response")}function i(c){return typeof c!="string"?d():c}function y(c){return Array.isArray(c)?c:d()}function M(c){let r=j(c);switch(r.action){case "remove_line":case "accept_price":case "remove_promo":case "change_address":return {action:r.action};case "choose_option":case "choose_other_option":return {action:r.action,groupId:i(r.group_id)};case "set_quantity":return !Number.isInteger(r.quantity)||Number(r.quantity)<1||Number(r.quantity)>99?d():{action:r.action,quantity:r.quantity};case "schedule":return {action:r.action,...r.next_open_at?{nextOpenAt:i(r.next_open_at)}:{},...r.slots?{slots:y(r.slots).map(i)}:{}};case "switch_fulfilment":{let t=y(r.types).map(i).filter(s=>["pickup","delivery","dine_in"].includes(s));return t.length?{action:r.action,types:t}:void 0}default:return}}var N=["item_unavailable","item_not_found","option_unavailable","option_required","option_limit","quantity_limit","price_changed","branch_closed","fulfilment_unavailable","outside_delivery_zone","delivery_region_required","schedule_invalid","promo_invalid","promo_min_spend","min_order","menu_version_stale"];function A(c,r){let t=j(c);if(t.branch_id!==r||!Number.isFinite(Date.parse(i(t.expires_at))))return d();let s=p(t.subtotal),o=j(t.checkout);if(typeof t.can_checkout!="boolean"||typeof o.ready!="boolean"||o.reason!==void 0&&o.reason!=="issues"&&o.reason!=="customer_required")return d();let l=n=>{let e=p(n);return e.currency!==s.currency?d():e},q=n=>{let e=j(n);return {code:i(e.code),label:i(e.label),amount:l(e.amount)}},a=y(t.charges).map(q),p$1=y(t.discounts).map(q),w=l(t.total);if(g([...a,...p$1].map(n=>n.amount),s).amountMinor!==w.amountMinor)return d();let m=a.filter(n=>n.code==="delivery"),v=y(t.lines).map(n=>{let e=j(n);return (e.unit_price==null||e.line_total==null)&&t.lines_unpriced!==true?d():{lineId:i(e.line_id),unitPrice:e.unit_price==null?null:l(e.unit_price),total:e.line_total==null?null:l(e.line_total)}});return t.lines_unpriced!==true&&g(v.map(n=>n.total),e(0,s.currency)).amountMinor!==s.amountMinor?d():{lines:v,...t.lines_unpriced===true?{linesUnpriced:true}:{},subtotal:s,total:w,fees:a.filter(n=>n.code!=="delivery"),discounts:p$1,...m.length?{delivery:g(m.map(n=>n.amount),e(0,s.currency))}:{},menuVersion:i(t.menu_version),expiresAt:i(t.expires_at),issues:y(t.issues).flatMap(n=>{let e=j(n),h=i(e.code),g=i(e.severity),u=N.includes(h)&&["blocking","warning","info"].includes(g),k=y(e.fixes).map(M).filter(F=>F!==void 0),_=e.line_id?i(e.line_id):void 0;return !u&&(g==="warning"||g==="info")?(console.warn(`Zappie quote issue "${h}" is newer than this SDK and was skipped`),[]):[{code:u?h:"item_unavailable",severity:u?g:"blocking",message:i(e.message),source:"quote",..._?{lineId:_}:{},...e.group_id?{groupId:i(e.group_id)}:{},...e.data||!u?{data:{...e.data?j(e.data):{},...u?{}:{code:h}}}:{},fixes:!u&&!k.length&&_?[{action:"remove_line"}]:k}]}),canCheckout:t.can_checkout,checkout:{ready:o.ready,...o.reason!==void 0?{reason:o.reason}:{}}}}function E(c,r){let t,s=0,o,l,q=()=>{s++,t?.abort(),l=void 0;};return {cancel:q,async get(a$1,p,w){let m=JSON.stringify(a$1);if(!p&&o?.key===m&&Date.parse(o.quote.expiresAt)>Date.now())return w(o.quote),o.quote;if(!p&&l?.key===m)return l.promise;q();let v=s;t=new AbortController;let n=t.signal,e=(async()=>{let h=await i$1(m);n.throwIfAborted();let g=await c.quote({...r(),signal:n,idempotencyKey:h},a$1);n.throwIfAborted();let u=A(g,a$1.branch_id),k=new Set(u.lines.map(_=>_.lineId));if(k.size!==u.lines.length||u.lines.length!==a$1.lines.length||a$1.lines.some(_=>!k.has(_.line_id)))throw new a("server_error","Quote line identities do not match the cart");return v===s&&(o={key:m,quote:u},w(u)),u})();l={key:m,promise:e};try{return await e}finally{v===s&&(l=void 0);}},accept(a){o&&(o.quote={...o.quote,issues:o.quote.issues.filter(p=>!(p.code===a.code&&p.lineId===a.lineId))});}}}export{E as createQuoteClient};//# sourceMappingURL=quote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cart/quote-response.ts","../../src/cart/quote-client.ts"],"names":["fail","ZappieError","text","value","list","fix","v","record","types","t","codes","mapQuote","branchId","subtotal","mapMoney","checkout","amount","raw","result","charge","c","charges","discounts","total","sumMoney","deliveryCharges","lines","l","line","money","i","code","severity","known","fixes","f","lineId","createQuoteClient","transport","context","controller","sequence","cached","flight","cancel","body","force","apply","key","seq","signal","promise","idempotencyKey","payloadKey","quote","ids","issue"],"mappings":"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","file":"quote.js","sourcesContent":["// Quote responses load lazily with the quote client, outside the synchronous core.\nimport { ZappieError } from \"../errors\";\nimport { sumMoney } from \"../internal/money-math\";\nimport { money } from \"../money\";\nimport { mapMoney, record } from \"../transport/mappers\";\nimport type { CartFix, CartFulfilment, CartIssue, Quote } from \"./types\";\nfunction fail(): never {\n throw new ZappieError(\"server_error\", \"Invalid quote response\");\n}\nfunction text(value: unknown): string {\n if (typeof value !== \"string\") {\n return fail();\n }\n return value;\n}\nfunction list(value: unknown): unknown[] {\n if (!Array.isArray(value)) {\n return fail();\n }\n return value;\n}\n/** A fix newer than this SDK is dropped (undefined); a malformed known fix still fails. */\nfunction fix(value: unknown): CartFix | undefined {\n const v = record(value);\n switch (v.action) {\n case \"remove_line\":\n case \"accept_price\":\n case \"remove_promo\":\n case \"change_address\":\n return { action: v.action };\n case \"choose_option\":\n case \"choose_other_option\":\n return { action: v.action, groupId: text(v.group_id) };\n case \"set_quantity\": {\n if (\n !Number.isInteger(v.quantity) ||\n Number(v.quantity) < 1 ||\n Number(v.quantity) > 99\n ) {\n return fail();\n }\n return { action: v.action, quantity: v.quantity as number };\n }\n case \"schedule\":\n return {\n action: v.action,\n ...(v.next_open_at ? { nextOpenAt: text(v.next_open_at) } : {}),\n ...(v.slots ? { slots: list(v.slots).map(text) } : {}),\n };\n case \"switch_fulfilment\": {\n const types = list(v.types)\n .map(text)\n .filter((t) => [\"pickup\", \"delivery\", \"dine_in\"].includes(t));\n return types.length\n ? { action: v.action, types: types as CartFulfilment[\"type\"][] }\n : undefined;\n }\n default:\n return undefined;\n }\n}\nconst codes = [\n \"item_unavailable\",\n \"item_not_found\",\n \"option_unavailable\",\n \"option_required\",\n \"option_limit\",\n \"quantity_limit\",\n \"price_changed\",\n \"branch_closed\",\n \"fulfilment_unavailable\",\n \"outside_delivery_zone\",\n \"delivery_region_required\",\n \"schedule_invalid\",\n \"promo_invalid\",\n \"promo_min_spend\",\n \"min_order\",\n \"menu_version_stale\",\n];\nexport function mapQuote(value: unknown, branchId: string): Quote {\n const v = record(value);\n if (\n v.branch_id !== branchId ||\n !Number.isFinite(Date.parse(text(v.expires_at)))\n ) {\n return fail();\n }\n const subtotal = mapMoney(v.subtotal);\n const checkout = record(v.checkout);\n if (\n typeof v.can_checkout !== \"boolean\" ||\n typeof checkout.ready !== \"boolean\" ||\n (checkout.reason !== undefined &&\n checkout.reason !== \"issues\" &&\n checkout.reason !== \"customer_required\")\n ) {\n return fail();\n }\n const amount = (raw: unknown) => {\n const result = mapMoney(raw);\n if (result.currency !== subtotal.currency) {\n return fail();\n }\n return result;\n };\n const charge = (raw: unknown) => {\n const c = record(raw);\n return {\n code: text(c.code),\n label: text(c.label),\n amount: amount(c.amount),\n };\n };\n const charges = list(v.charges).map(charge);\n const discounts = list(v.discounts).map(charge);\n const total = amount(v.total);\n if (\n sumMoney(\n [...charges, ...discounts].map((c) => c.amount),\n subtotal,\n ).amountMinor !== total.amountMinor\n ) {\n return fail();\n }\n const deliveryCharges = charges.filter((c) => c.code === \"delivery\");\n const lines = list(v.lines).map((raw) => {\n const l = record(raw);\n if (\n (l.unit_price == null || l.line_total == null) &&\n v.lines_unpriced !== true\n ) {\n return fail();\n }\n return {\n lineId: text(l.line_id),\n unitPrice: l.unit_price == null ? null : amount(l.unit_price),\n total: l.line_total == null ? null : amount(l.line_total),\n };\n });\n if (\n v.lines_unpriced !== true &&\n sumMoney(\n lines.map((line) => line.total!),\n money(0, subtotal.currency),\n ).amountMinor !== subtotal.amountMinor\n ) {\n return fail();\n }\n return {\n lines,\n ...(v.lines_unpriced === true ? { linesUnpriced: true } : {}),\n subtotal,\n total,\n fees: charges.filter((c) => c.code !== \"delivery\"),\n discounts,\n ...(deliveryCharges.length\n ? {\n delivery: sumMoney(\n deliveryCharges.map((c) => c.amount),\n money(0, subtotal.currency),\n ),\n }\n : {}),\n menuVersion: text(v.menu_version),\n expiresAt: text(v.expires_at),\n issues: list(v.issues).flatMap((raw): CartIssue[] => {\n const i = record(raw);\n const code = text(i.code);\n const severity = text(i.severity);\n const known =\n codes.includes(code) &&\n [\"blocking\", \"warning\", \"info\"].includes(severity);\n const fixes = list(i.fixes)\n .map(fix)\n .filter((f): f is CartFix => f !== undefined);\n const lineId = i.line_id ? text(i.line_id) : undefined;\n if (!known && (severity === \"warning\" || severity === \"info\")) {\n console.warn(\n `Zappie quote issue \"${code}\" is newer than this SDK and was skipped`,\n );\n return [];\n }\n // A blocking (or unknown-severity) issue newer than the SDK keeps checkout blocked.\n return [\n {\n code: known ? (code as CartIssue[\"code\"]) : \"item_unavailable\",\n severity: known ? (severity as CartIssue[\"severity\"]) : \"blocking\",\n message: text(i.message),\n source: \"quote\",\n ...(lineId ? { lineId } : {}),\n ...(i.group_id ? { groupId: text(i.group_id) } : {}),\n ...(i.data || !known\n ? {\n data: {\n ...(i.data ? record(i.data) : {}),\n ...(known ? {} : { code }),\n },\n }\n : {}),\n fixes:\n !known && !fixes.length && lineId\n ? [{ action: \"remove_line\" }]\n : fixes,\n },\n ];\n }),\n canCheckout: v.can_checkout,\n checkout: {\n ready: checkout.ready,\n ...(checkout.reason !== undefined ? { reason: checkout.reason } : {}),\n },\n };\n}\n","import { ZappieError } from \"../errors\";\nimport { payloadKey } from \"../internal/digest\";\nimport type { RequestCtx, Transport } from \"../transport/types\";\nimport { mapQuote } from \"./quote-response\";\nimport type { Quote, QuoteRequest } from \"./types\";\nexport function createQuoteClient(\n transport: Transport,\n context: () => RequestCtx,\n) {\n let controller: AbortController | undefined;\n let sequence = 0;\n let cached: { key: string; quote: Quote } | undefined;\n let flight: { key: string; promise: Promise<Quote> } | undefined;\n const cancel = () => {\n sequence++;\n controller?.abort();\n flight = undefined;\n };\n return {\n cancel,\n async get(\n body: QuoteRequest,\n force: boolean,\n apply: (quote: Quote) => void,\n ): Promise<Quote> {\n const key = JSON.stringify(body);\n if (\n !force &&\n cached?.key === key &&\n Date.parse(cached.quote.expiresAt) > Date.now()\n ) {\n apply(cached.quote);\n return cached.quote;\n }\n if (!force && flight?.key === key) {\n return flight.promise;\n }\n cancel();\n const seq = sequence;\n controller = new AbortController();\n const signal = controller.signal;\n const promise = (async () => {\n const idempotencyKey = await payloadKey(key);\n signal.throwIfAborted();\n const raw = await transport.quote(\n { ...context(), signal, idempotencyKey },\n body,\n );\n signal.throwIfAborted();\n const quote = mapQuote(raw, body.branch_id);\n const ids = new Set(quote.lines.map((line) => line.lineId));\n if (\n ids.size !== quote.lines.length ||\n quote.lines.length !== body.lines.length ||\n body.lines.some((line) => !ids.has(line.line_id))\n ) {\n throw new ZappieError(\n \"server_error\",\n \"Quote line identities do not match the cart\",\n );\n }\n if (seq === sequence) {\n cached = { key, quote };\n apply(quote);\n }\n return quote;\n })();\n flight = { key, promise };\n try {\n return await promise;\n } finally {\n if (seq === sequence) {\n flight = undefined;\n }\n }\n },\n accept(issue: CartIssueForAcceptance) {\n if (cached) {\n cached.quote = {\n ...cached.quote,\n issues: cached.quote.issues.filter(\n (i) => !(i.code === issue.code && i.lineId === issue.lineId),\n ),\n };\n }\n },\n };\n}\ntype CartIssueForAcceptance = { code: string; lineId?: string };\n\nexport type QuoteClient = ReturnType<typeof createQuoteClient>;\n"]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { WireLine, WireMoney, ZappieError, Quote } from '@zappie/sdk';
|
|
2
|
+
export { wireFulfilment as checkoutFulfilment } from '@zappie/sdk/internal';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Address fields you can send with a delivery checkout request.
|
|
6
|
+
*/
|
|
7
|
+
type CheckoutAddress = {
|
|
8
|
+
line1?: string;
|
|
9
|
+
city?: string;
|
|
10
|
+
place_id?: string;
|
|
11
|
+
lat?: number;
|
|
12
|
+
lng?: number;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Pickup or delivery details for a checkout session, including an optional schedule.
|
|
16
|
+
*/
|
|
17
|
+
type CheckoutFulfilment = {
|
|
18
|
+
/** Dine-in orders are not checked out through a session. */
|
|
19
|
+
type: "pickup" | "delivery";
|
|
20
|
+
address?: CheckoutAddress;
|
|
21
|
+
scheduled_for?: string | null;
|
|
22
|
+
delivery_region_id?: string;
|
|
23
|
+
instructions?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Cart lines, branch, fulfilment and return URLs you send to open checkout.
|
|
27
|
+
*/
|
|
28
|
+
type CheckoutRequest = {
|
|
29
|
+
branch_id: string;
|
|
30
|
+
menu_version: string;
|
|
31
|
+
lines: WireLine[];
|
|
32
|
+
fulfilment: CheckoutFulfilment;
|
|
33
|
+
contact_phone?: string;
|
|
34
|
+
promo_code?: string;
|
|
35
|
+
return_url: string;
|
|
36
|
+
cancel_url?: string;
|
|
37
|
+
source?: string;
|
|
38
|
+
campaign?: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* A checkout session returned by the service, with its amount, expiry and order status.
|
|
42
|
+
*/
|
|
43
|
+
type CheckoutSession = {
|
|
44
|
+
id: string;
|
|
45
|
+
status: "open" | "completed" | "expired" | "cancelled";
|
|
46
|
+
url?: string;
|
|
47
|
+
amount: WireMoney;
|
|
48
|
+
order_id: string | null;
|
|
49
|
+
return_url: string;
|
|
50
|
+
cancel_url?: string;
|
|
51
|
+
expires_at: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A checkout session with a payment URL you can use to send the shopper to checkout.
|
|
55
|
+
*/
|
|
56
|
+
type OpenCheckoutSession = CheckoutSession & {
|
|
57
|
+
url: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* A terminal checkout result: a completed order, an expired session or a cancelled session.
|
|
61
|
+
*/
|
|
62
|
+
type CheckoutCompletion = (CheckoutSession & {
|
|
63
|
+
status: "completed";
|
|
64
|
+
order_id: string;
|
|
65
|
+
}) | (CheckoutSession & {
|
|
66
|
+
status: "expired" | "cancelled";
|
|
67
|
+
});
|
|
68
|
+
/**
|
|
69
|
+
* Optional customer API base URL and fetch implementation for the checkout client.
|
|
70
|
+
*/
|
|
71
|
+
type CheckoutClientOptions = {
|
|
72
|
+
customerBase?: string;
|
|
73
|
+
fetch?: typeof fetch;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Cancellation signal and polling interval in milliseconds for awaiting checkout completion.
|
|
77
|
+
*/
|
|
78
|
+
type AwaitCompletionOptions = {
|
|
79
|
+
signal?: AbortSignal;
|
|
80
|
+
intervalMs?: number;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Create a client that opens checkout sessions, reads them and polls for completion.
|
|
85
|
+
*
|
|
86
|
+
* @param options - Override the default `/_zappie/api` base or fetch implementation.
|
|
87
|
+
* @returns A checkout client. Retain each idempotency key when retrying the same cart.
|
|
88
|
+
*/
|
|
89
|
+
declare function createCheckout(options?: CheckoutClientOptions): {
|
|
90
|
+
/** The caller retains this key and reuses it when retrying the same cart. */
|
|
91
|
+
open(body: CheckoutRequest, idempotencyKey: string): Promise<OpenCheckoutSession>;
|
|
92
|
+
session(id: string): Promise<CheckoutSession>;
|
|
93
|
+
awaitCompletion(id: string, options?: AwaitCompletionOptions): Promise<CheckoutCompletion>;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* The session creation, lookup and completion methods returned by createCheckout.
|
|
97
|
+
*/
|
|
98
|
+
type CheckoutClient = ReturnType<typeof createCheckout>;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A checkout API failure with its HTTP status, API code and optional validation issues.
|
|
102
|
+
* Statuses 409, 429 and 5xx are marked retryable.
|
|
103
|
+
*/
|
|
104
|
+
declare class CheckoutError extends ZappieError {
|
|
105
|
+
readonly apiCode: string;
|
|
106
|
+
readonly issues?: unknown;
|
|
107
|
+
constructor(status: number, apiCode: string, message: string, param?: string, issues?: unknown);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The next action your payment UI should present, from fixing an address to paying.
|
|
112
|
+
*/
|
|
113
|
+
type PayReadiness = "address" | "quoting" | "retry" | "choose_area" | "fix_issues" | "sign_in" | "phone" | "pay";
|
|
114
|
+
/**
|
|
115
|
+
* The quote loading state and, when ready, the quote used to decide payment readiness.
|
|
116
|
+
*/
|
|
117
|
+
type PayReadinessQuoteState = {
|
|
118
|
+
status: "idle" | "loading";
|
|
119
|
+
} | {
|
|
120
|
+
status: "error";
|
|
121
|
+
} | {
|
|
122
|
+
status: "ready";
|
|
123
|
+
quote: Quote;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Check whether a phone is blank or contains 7 to 15 digits with an optional leading plus.
|
|
127
|
+
* Whitespace within a nonblank phone is ignored. This does not verify that the number exists.
|
|
128
|
+
*
|
|
129
|
+
* @param phone - The contact phone entered by the shopper.
|
|
130
|
+
* @returns Whether the phone passes this optional-field format check.
|
|
131
|
+
*/
|
|
132
|
+
declare function isContactPhoneValid(phone: string): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Choose the next payment action from address validity, quote state and contact phone validity.
|
|
135
|
+
* Address and quote issues take priority over sign-in and phone prompts.
|
|
136
|
+
*
|
|
137
|
+
* @returns The action you should display in your payment UI.
|
|
138
|
+
*/
|
|
139
|
+
declare function payReadiness(state: PayReadinessQuoteState, contactPhoneValid: boolean, addressValid?: boolean): PayReadiness;
|
|
140
|
+
|
|
141
|
+
export { type AwaitCompletionOptions, type CheckoutAddress, type CheckoutClient, type CheckoutClientOptions, type CheckoutCompletion, CheckoutError, type CheckoutFulfilment, type CheckoutRequest, type CheckoutSession, type OpenCheckoutSession, type PayReadiness, type PayReadinessQuoteState, createCheckout, isContactPhoneValid, payReadiness };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {ZappieError,money}from'@zappie/sdk';export{wireFulfilment as checkoutFulfilment}from'@zappie/sdk/internal';function l(e){return e===400||e===422?"invalid_request":e===401?"unauthorized":e===404?"not_found":e===429?"rate_limited":"server_error"}async function h(e,r){let t=await e.json().catch(()=>({})),s=t&&typeof t=="object"?t:{},o="error"in s&&s.error&&typeof s.error=="object"?s.error:{};return {apiCode:"code"in o&&typeof o.code=="string"?o.code:"server_error",message:"message"in o&&typeof o.message=="string"?o.message:r,..."param"in o&&typeof o.param=="string"?{param:o.param}:{},..."issues"in o?{issues:o.issues}:{}}}function m(e,r){return r?.throwIfAborted(),new Promise((t,s)=>{let i=setTimeout(()=>{r?.removeEventListener("abort",n),t();},e),n=()=>{clearTimeout(i),r?.removeEventListener("abort",n),s(r?.reason??new DOMException("Aborted","AbortError"));};r?.addEventListener("abort",n,{once:true});})}async function y(e,r,t,s){for(let o=0;o<2;o++)try{return await e(r,{...t,credentials:"same-origin",headers:{Accept:"application/json",...t.headers}})}catch(i){if(t.signal?.aborted)throw t.signal.reason??i;if(o===1)throw new ZappieError("network_error",s,{cause:i,retryable:true});await m(400,t.signal??void 0);}throw new ZappieError("network_error",s,{retryable:true})}var p=class extends ZappieError{constructor(t,s,o,i,n){super(l(t),o,{status:t,retryable:t===409||t===429||t>=500,...i!==void 0?{param:i}:{}});this.apiCode=s;n!==void 0&&(this.issues=n);}};function k(e){if(!e||typeof e!="object"||Array.isArray(e))throw new ZappieError("server_error","Invalid checkout session response");return e}function d(e){if(typeof e!="string")throw new ZappieError("server_error","Invalid checkout session response");return e}function C(e){try{return money(0,d(e)).currency}catch{throw new ZappieError("server_error","Invalid checkout session response")}}function g(e){let r=k(e),t=k(r.amount),s=d(r.status);if(!["open","completed","expired","cancelled"].includes(s))throw new ZappieError("server_error","Invalid checkout session response");let o=d(r.expires_at);if(!Number.isFinite(Date.parse(o)))throw new ZappieError("server_error","Invalid checkout session response");if(!Number.isSafeInteger(t.amount_minor))throw new ZappieError("server_error","Invalid checkout session response");if(r.order_id!==null&&typeof r.order_id!="string")throw new ZappieError("server_error","Invalid checkout session response");return {id:d(r.id),status:s,...typeof r.url=="string"?{url:r.url}:{},amount:{amount_minor:t.amount_minor,currency:C(t.currency)},order_id:r.order_id,return_url:d(r.return_url),...typeof r.cancel_url=="string"?{cancel_url:r.cancel_url}:{},expires_at:o}}var b="/_zappie/api";async function x(e){let r=await h(e,`The checkout service answered ${e.status}`);return new p(e.status,r.apiCode,r.message,r.param,r.issues)}function v(e={}){let r=(e.customerBase??b).replace(/\/+$/,""),t=e.fetch??globalThis.fetch,s=async(i,n)=>{let c=await y(t,r+i,n,"Could not reach checkout");if(!c.ok)throw await x(c);return g(await c.json())},o=(i,n)=>s(`/checkout/sessions/${encodeURIComponent(i)}`,{method:"GET",...n?{signal:n}:{}});return {async open(i,n){let c=await s("/checkout/sessions",{method:"POST",headers:{"Content-Type":"application/json","Idempotency-Key":n},body:JSON.stringify(i)});if(!c.url)throw new ZappieError("server_error","Checkout session has no payment URL");return globalThis.__zappieEmit?.("checkout:open",c),{...c,url:c.url}},session(i){return o(i)},async awaitCompletion(i,n={}){let c=n.intervalMs??3e3;if(!Number.isFinite(c)||c<0)throw new ZappieError("invalid_request","intervalMs cannot be negative");for(;;){n.signal?.throwIfAborted();try{let a=await o(i,n.signal);if(a.status==="completed"&&a.order_id)return globalThis.__zappieEmit?.("checkout:completed",a),{...a,status:"completed",order_id:a.order_id};if(a.status==="expired"||a.status==="cancelled")return {...a,status:a.status}}catch(a){if(n.signal?.throwIfAborted(),a instanceof ZappieError&&a.status!==void 0&&a.status>=400&&a.status<500)throw a}await m(c,n.signal);}}}}function E(e){return e.trim()===""||/^\+?[0-9]{7,15}$/.test(e.replace(/\s+/g,""))}function R(e,r,t=true){if(!t)return "address";switch(e.status){case "idle":case "loading":return "quoting";case "error":return "retry"}return e.quote.issues.some(s=>s.code==="delivery_region_required")?"choose_area":!e.quote.canCheckout||e.quote.checkout.reason==="issues"?"fix_issues":e.quote.checkout.reason==="customer_required"?"sign_in":r?"pay":"phone"}export{p as CheckoutError,v as createCheckout,E as isContactPhoneValid,R as payReadiness};//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/internal/customer-http.ts","../../src/checkout/error.ts","../../src/checkout/session.ts","../../src/checkout/client.ts","../../src/checkout/readiness.ts"],"names":["stableErrorCode","status","apiError","response","fallback","body","envelope","value","wait","ms","signal","resolve","reject","timer","aborted","requestWithRetry","fetcher","input","init","message","attempt","cause","ZappieError","CheckoutError","apiCode","param","issues","object","string","currency","money","mapCheckoutSession","session","amount","expiresAt","DEFAULT_CUSTOMER_BASE","error","createCheckout","options","base","request","path","read","id","idempotencyKey","interval","failure","isContactPhoneValid","phone","payReadiness","state","contactPhoneValid","addressValid","issue"],"mappings":"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","file":"index.js","sourcesContent":["// Isolated customer-facing bundles import the installed core so error identity is shared.\n// eslint-disable-next-line no-restricted-imports\nimport { ZappieError } from \"@zappie/sdk\";\n\nexport type ApiErrorDetails = {\n apiCode: string;\n message: string;\n param?: string;\n issues?: unknown;\n};\n\nexport function stableErrorCode(status: number) {\n if (status === 400 || status === 422) {\n return \"invalid_request\" as const;\n }\n if (status === 401) {\n return \"unauthorized\" as const;\n }\n if (status === 404) {\n return \"not_found\" as const;\n }\n if (status === 429) {\n return \"rate_limited\" as const;\n }\n return \"server_error\" as const;\n}\n\nexport async function apiError(\n response: Response,\n fallback: string,\n): Promise<ApiErrorDetails> {\n const body = await response.json().catch(() => ({}));\n const envelope = body && typeof body === \"object\" ? body : {};\n const value =\n \"error\" in envelope && envelope.error && typeof envelope.error === \"object\"\n ? envelope.error\n : {};\n return {\n apiCode:\n \"code\" in value && typeof value.code === \"string\"\n ? value.code\n : \"server_error\",\n message:\n \"message\" in value && typeof value.message === \"string\"\n ? value.message\n : fallback,\n ...(\"param\" in value && typeof value.param === \"string\"\n ? { param: value.param }\n : {}),\n ...(\"issues\" in value ? { issues: value.issues } : {}),\n };\n}\n\nexport function wait(ms: number, signal?: AbortSignal): Promise<void> {\n signal?.throwIfAborted();\n return new Promise((resolve, reject) => {\n const done = () => {\n signal?.removeEventListener(\"abort\", aborted);\n resolve();\n };\n const timer = setTimeout(done, ms);\n const aborted = () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", aborted);\n reject(signal?.reason ?? new DOMException(\"Aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", aborted, { once: true });\n });\n}\n\nexport async function requestWithRetry(\n fetcher: typeof fetch,\n input: string,\n init: RequestInit,\n message: string,\n): Promise<Response> {\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n return await fetcher(input, {\n ...init,\n credentials: \"same-origin\",\n headers: { Accept: \"application/json\", ...init.headers },\n });\n } catch (cause) {\n if (init.signal?.aborted) {\n throw init.signal.reason ?? cause;\n }\n if (attempt === 1) {\n throw new ZappieError(\"network_error\", message, {\n cause,\n retryable: true,\n });\n }\n await wait(400, init.signal ?? undefined);\n }\n }\n throw new ZappieError(\"network_error\", message, { retryable: true });\n}\n","import { stableErrorCode } from \"../internal/customer-http\";\nimport { ZappieError } from \"./sdk\";\n\n/**\n * A checkout API failure with its HTTP status, API code and optional validation issues.\n * Statuses 409, 429 and 5xx are marked retryable.\n */\nexport class CheckoutError extends ZappieError {\n readonly issues?: unknown;\n\n constructor(\n status: number,\n readonly apiCode: string,\n message: string,\n param?: string,\n issues?: unknown,\n ) {\n super(stableErrorCode(status), message, {\n status,\n // 409 means the same idempotency key is still being processed; retrying with it is safe.\n retryable: status === 409 || status === 429 || status >= 500,\n ...(param !== undefined ? { param } : {}),\n });\n if (issues !== undefined) {\n this.issues = issues;\n }\n }\n}\n","import { type Currency, money, ZappieError } from \"./sdk\";\nimport type { CheckoutSession } from \"./types\";\n\nfunction object(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new ZappieError(\"server_error\", \"Invalid checkout session response\");\n }\n return value as Record<string, unknown>;\n}\n\nfunction string(value: unknown): string {\n if (typeof value !== \"string\") {\n throw new ZappieError(\"server_error\", \"Invalid checkout session response\");\n }\n return value;\n}\n\nfunction currency(value: unknown): Currency {\n try {\n return money(0, string(value)).currency;\n } catch {\n throw new ZappieError(\"server_error\", \"Invalid checkout session response\");\n }\n}\n\nexport function mapCheckoutSession(value: unknown): CheckoutSession {\n const session = object(value);\n const amount = object(session.amount);\n const status = string(session.status);\n if (\n !([\"open\", \"completed\", \"expired\", \"cancelled\"] as string[]).includes(\n status,\n )\n ) {\n throw new ZappieError(\"server_error\", \"Invalid checkout session response\");\n }\n const expiresAt = string(session.expires_at);\n if (!Number.isFinite(Date.parse(expiresAt))) {\n throw new ZappieError(\"server_error\", \"Invalid checkout session response\");\n }\n if (!Number.isSafeInteger(amount.amount_minor)) {\n throw new ZappieError(\"server_error\", \"Invalid checkout session response\");\n }\n if (session.order_id !== null && typeof session.order_id !== \"string\") {\n throw new ZappieError(\"server_error\", \"Invalid checkout session response\");\n }\n return {\n id: string(session.id),\n status: status as CheckoutSession[\"status\"],\n ...(typeof session.url === \"string\" ? { url: session.url } : {}),\n amount: {\n amount_minor: amount.amount_minor as number,\n currency: currency(amount.currency),\n },\n order_id: session.order_id,\n return_url: string(session.return_url),\n ...(typeof session.cancel_url === \"string\"\n ? { cancel_url: session.cancel_url }\n : {}),\n expires_at: expiresAt,\n };\n}\n","import { apiError, requestWithRetry, wait } from \"../internal/customer-http\";\nimport { CheckoutError } from \"./error\";\nimport { ZappieError } from \"./sdk\";\nimport { mapCheckoutSession } from \"./session\";\nimport type {\n AwaitCompletionOptions,\n CheckoutClientOptions,\n CheckoutCompletion,\n CheckoutRequest,\n CheckoutSession,\n OpenCheckoutSession,\n} from \"./types\";\n\nconst DEFAULT_CUSTOMER_BASE = \"/_zappie/api\";\n\nasync function error(response: Response): Promise<CheckoutError> {\n const value = await apiError(\n response,\n `The checkout service answered ${response.status}`,\n );\n return new CheckoutError(\n response.status,\n value.apiCode,\n value.message,\n value.param,\n value.issues,\n );\n}\n\n/**\n * Create a client that opens checkout sessions, reads them and polls for completion.\n *\n * @param options - Override the default `/_zappie/api` base or fetch implementation.\n * @returns A checkout client. Retain each idempotency key when retrying the same cart.\n */\nexport function createCheckout(options: CheckoutClientOptions = {}) {\n const base = (options.customerBase ?? DEFAULT_CUSTOMER_BASE).replace(\n /\\/+$/,\n \"\",\n );\n const fetcher = options.fetch ?? globalThis.fetch;\n const request = async (\n path: string,\n init: RequestInit,\n ): Promise<CheckoutSession> => {\n const response = await requestWithRetry(\n fetcher,\n base + path,\n init,\n \"Could not reach checkout\",\n );\n if (!response.ok) {\n throw await error(response);\n }\n return mapCheckoutSession(await response.json());\n };\n const read = (id: string, signal?: AbortSignal) =>\n request(`/checkout/sessions/${encodeURIComponent(id)}`, {\n method: \"GET\",\n ...(signal ? { signal } : {}),\n });\n return {\n /** The caller retains this key and reuses it when retrying the same cart. */\n async open(\n body: CheckoutRequest,\n idempotencyKey: string,\n ): Promise<OpenCheckoutSession> {\n const session = await request(\"/checkout/sessions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Idempotency-Key\": idempotencyKey,\n },\n body: JSON.stringify(body),\n });\n if (!session.url) {\n throw new ZappieError(\n \"server_error\",\n \"Checkout session has no payment URL\",\n );\n }\n globalThis.__zappieEmit?.(\"checkout:open\", session);\n return { ...session, url: session.url };\n },\n session(id: string): Promise<CheckoutSession> {\n return read(id);\n },\n async awaitCompletion(\n id: string,\n options: AwaitCompletionOptions = {},\n ): Promise<CheckoutCompletion> {\n const interval = options.intervalMs ?? 3_000;\n if (!Number.isFinite(interval) || interval < 0) {\n throw new ZappieError(\n \"invalid_request\",\n \"intervalMs cannot be negative\",\n );\n }\n for (;;) {\n options.signal?.throwIfAborted();\n try {\n const session = await read(id, options.signal);\n if (session.status === \"completed\" && session.order_id) {\n globalThis.__zappieEmit?.(\"checkout:completed\", session);\n return {\n ...session,\n status: \"completed\",\n order_id: session.order_id,\n };\n }\n if (session.status === \"expired\" || session.status === \"cancelled\") {\n return { ...session, status: session.status };\n }\n } catch (failure) {\n options.signal?.throwIfAborted();\n if (\n failure instanceof ZappieError &&\n failure.status !== undefined &&\n failure.status >= 400 &&\n failure.status < 500\n ) {\n throw failure;\n }\n }\n await wait(interval, options.signal);\n }\n },\n };\n}\n\n/**\n * The session creation, lookup and completion methods returned by createCheckout.\n */\nexport type CheckoutClient = ReturnType<typeof createCheckout>;\n","import type { Quote } from \"./sdk\";\n\n/**\n * The next action your payment UI should present, from fixing an address to paying.\n */\nexport type PayReadiness =\n | \"address\"\n | \"quoting\"\n | \"retry\"\n | \"choose_area\"\n | \"fix_issues\"\n | \"sign_in\"\n | \"phone\"\n | \"pay\";\n\n/**\n * The quote loading state and, when ready, the quote used to decide payment readiness.\n */\nexport type PayReadinessQuoteState =\n | { status: \"idle\" | \"loading\" }\n | { status: \"error\" }\n | { status: \"ready\"; quote: Quote };\n\n/**\n * Check whether a phone is blank or contains 7 to 15 digits with an optional leading plus.\n * Whitespace within a nonblank phone is ignored. This does not verify that the number exists.\n *\n * @param phone - The contact phone entered by the shopper.\n * @returns Whether the phone passes this optional-field format check.\n */\nexport function isContactPhoneValid(phone: string): boolean {\n return (\n phone.trim() === \"\" || /^\\+?[0-9]{7,15}$/.test(phone.replace(/\\s+/g, \"\"))\n );\n}\n\n/**\n * Choose the next payment action from address validity, quote state and contact phone validity.\n * Address and quote issues take priority over sign-in and phone prompts.\n *\n * @returns The action you should display in your payment UI.\n */\nexport function payReadiness(\n state: PayReadinessQuoteState,\n contactPhoneValid: boolean,\n addressValid = true,\n): PayReadiness {\n if (!addressValid) {\n return \"address\";\n }\n switch (state.status) {\n case \"idle\":\n case \"loading\":\n return \"quoting\";\n case \"error\":\n return \"retry\";\n }\n if (\n state.quote.issues.some(\n (issue) => issue.code === \"delivery_region_required\",\n )\n ) {\n return \"choose_area\";\n }\n if (!state.quote.canCheckout || state.quote.checkout.reason === \"issues\") {\n return \"fix_issues\";\n }\n if (state.quote.checkout.reason === \"customer_required\") {\n return \"sign_in\";\n }\n if (!contactPhoneValid) {\n return \"phone\";\n }\n return \"pay\";\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var D=["network_error","timeout","rate_limited","unauthorized","forbidden_origin","not_found","store_not_found","branch_not_found","item_not_found","cart_invalid","invalid_request","version_unsupported","server_error"],u=class extends Error{constructor(r,s,t={}){super(s,{cause:t.cause});this.code=r;this.name="ZappieError",t.status!==void 0&&(this.status=t.status),t.param!==void 0&&(this.param=t.param),t.requestId!==void 0&&(this.requestId=t.requestId),this.docUrl=t.docUrl??`https://docs.zappie.ai/errors#${r}`,this.retryable=t.retryable??["network_error","timeout","rate_limited","server_error"].includes(r);}};function N(n){return n instanceof u}function j(n){return N(n)?n:new u("network_error","The storefront request failed",{cause:n})}function V(n,e,r){let s=n&&typeof n=="object"?n:{},t=s.error&&typeof s.error=="object"?s.error:{},p=e===401?"unauthorized":e===403?"forbidden_origin":e===404?"not_found":e===429?"rate_limited":e>=500?"server_error":"invalid_request",o=typeof t.code=="string"&&D.includes(t.code),m=o?t.code:t.code?"server_error":p,a=typeof t.message=="string"?t.message:"The storefront request failed";return new u(m,!o&&t.code?`${String(t.code)}: ${a}`:a,{status:e,...r?{requestId:r}:{},...typeof t.param=="string"?{param:t.param}:{},...typeof t.doc_url=="string"?{docUrl:t.doc_url}:{}})}var R=" AFN ALL BIF CLP DJF GNF IQD IRR ISK JPY KMF KPW KRW LAK LBP MGA MMK PYG RSD RWF SLL SOS SYP UGX UYI VND VUV XAF XOF XPF YER ",A=" BHD JOD KWD LYD OMR TND ",F=" CLF UYW ",T=" BOV CHE CHW CLF COU MXV USN UYI UYW VED ",k=(n,e)=>n.includes(` ${e} `),C;function U(n){return /^[A-Z]{3}$/.test(n)?typeof Intl.supportedValuesOf!="function"?true:(C??(C=new Set(Intl.supportedValuesOf("currency"))),k(T,n)||C.has(n)):false}function G(n){return k(R,n)?0:k(A,n)?3:k(F,n)?4:2}function y(n,e){let r=typeof e=="string"?e.trim().toUpperCase():"";if(!Number.isSafeInteger(n)||!U(r))throw new u("invalid_request","Money requires safe integer minor units and a valid ISO 4217 currency");return Object.freeze({amountMinor:n,currency:r})}var H={money(n,e={}){let r=y(n.amountMinor,n.currency),s=r.currency==="NGN"?"en-NG":"en",t=G(r.currency);return new Intl.NumberFormat(s,{style:"currency",currency:r.currency,currencyDisplay:"narrowSymbol",minimumFractionDigits:e.showZeroDecimals||r.amountMinor%10**t!==0?t:0,maximumFractionDigits:t,notation:e.compact?"compact":"standard",signDisplay:e.sign??"auto"}).format(r.amountMinor/10**t)}};function J(n,e){let r=e.amountMinor;for(let s of n){if(s.currency!==e.currency)throw new u("invalid_request","Cannot combine different currencies");r=y(r+s.amountMinor,e.currency).amountMinor;}return y(r,e.currency)}function Q(n,e){if(!Number.isSafeInteger(e))throw new u("invalid_request","Money requires an integer quantity");return y(n.amountMinor*e,n.currency)}async function ne(n){let e=await globalThis.crypto.subtle.digest("SHA-256",new TextEncoder().encode(n));return Array.from(new Uint8Array(e),r=>r.toString(16).padStart(2,"0")).join("")}var g=class extends Error{};function c(n){if(!n||typeof n!="object"||Array.isArray(n))throw new u("server_error","Invalid storefront response object");return n}function i(n){if(typeof n!="string")throw new u("server_error","Invalid storefront response string");return n}function l(n){if(!Array.isArray(n))throw new u("server_error","Invalid storefront response list");return n}function _(n){if(typeof n!="number"||!Number.isFinite(n))throw new u("server_error","Invalid storefront response number");return n}function h(n){let e=_(n);if(e<0)throw new u("server_error","Negative selection or quantity bound");return e}function E(n){let e=c(n),r=h(e.min);if(e.max==null)return {min:r};let s=h(e.max);if(s<r)throw new u("server_error","Maximum quantity is below its minimum");return {min:r,max:s}}var v=n=>typeof n=="string",w=n=>typeof n=="boolean";function f(n,e,r){return r(e)?{[n]:e}:{}}function b(n){let e=c(n);return y(_(e.amount_minor??e.amountMinor),i(e.currency))}function Z(n){return l(n??[]).map(e=>{let r=c(e),s=_(r.day);if(!Number.isInteger(s)||s<0||s>6)throw new u("server_error","Invalid opening day");return {day:s,opens:i(r.opens??r.open??r.start),closes:i(r.closes??r.close??r.end),...f("disabled",r.disabled,w)}})}function K(n){if(n===void 0)return;let e=c(n);return {openingTimes:Z(e.opening_times??e.openingTimes??e.hours??[]),...f("preorder",e.preorder,w),...e.preorder_notice_hours!==void 0?{preorderNoticeHours:_(e.preorder_notice_hours)}:{},...e.preorder_max_days!==void 0?{preorderMaxDays:_(e.preorder_max_days)}:{}}}function L(n){let e=c(n),r=c(e.selection??{min:e.min??0,max:e.max}),s=e.is_attribute===true,t=i(e.kind??"select");if(!["select","text","number","date","time","toggle"].includes(t))throw new g(`option input kind "${t}"`);return {id:i(e.id),name:i(e.name),kind:t,required:typeof e.required=="boolean"?e.required:_(r.min)>0,selection:E(r),isAttribute:s,choices:l(e.choices??[]).map(p=>{let o=c(p),m=b(o.price);return {id:i(o.id),name:i(o.name),price:s?y(0,m.currency):m,...s&&o.price_hint!==void 0?{priceHint:b(o.price_hint)}:{},isAvailable:(o.is_available??o.available)===true,...o.quantity?{quantity:E(o.quantity)}:{}}}),...f("helpText",e.help_text,v),...e.input?{input:{...c(e.input).max_length!==void 0?{maxLength:_(c(e.input).max_length)}:{},...typeof c(e.input).placeholder=="string"?{placeholder:i(c(e.input).placeholder)}:{}}}:{},...f("isAvailable",e.is_available,w),...f("isInformational",e.is_informational,w),...e.conditions?{conditions:l(e.conditions).map(p=>{let o=c(p),m=o.count?c(o.count):void 0;if(m&&!["eq","gte","lte"].includes(i(m.op)))throw new g(`option count operator "${i(m.op)}"`);if(o.match!==void 0&&o.match!=="any"&&o.match!=="all")throw new g(`option match operator "${String(o.match)}"`);if(o.set_required!=null&&typeof o.set_required!="boolean")throw new u("server_error","Invalid conditional required flag");return {groupId:i(o.group_id),choiceIds:l(o.choice_ids??[]).map(i),match:o.match==="all"?"all":"any",...m?{count:{op:i(m.op),value:h(m.value)}}:{},...o.set_required!==void 0?{setRequired:o.set_required}:{},...o.set_min!==void 0?{setMin:o.set_min===null?null:h(o.set_min)}:{},...o.set_max!==void 0?{setMax:o.set_max===null?null:h(o.set_max)}:{}}})}:{}}}function P(n){let e=c(n);return {name:i(e.name)}}function $(n){let e=c(n),r=i(e.id),s=[],t=false;for(let a of l(e.option_groups??[]))try{s.push(L(a));}catch(d){if(!(d instanceof g))throw d;t=true,console.warn(`Zappie item ${r} uses an ${d.message} this SDK can't validate; it is shown as unavailable`);}let p=l(e.variants).map(a=>{let d=c(a);return {id:i(d.id),attributeChoices:Object.fromEntries(Object.entries(c(d.attribute_choices??{})).map(([x,q])=>[x,i(q)])),price:b(d.price),...f("lowStock",d.low_stock,w),isAvailable:!t&&(d.is_available??d.available)===true}});if(!p.length)throw new u("server_error","An item must carry at least one exact variant");let o=c(e.quantity??{min:1,step:1,max:e.max_quantity}),m=_(o.step);if(m<=0||new Set(p.map(a=>a.id)).size!==p.length)throw new u("server_error","Invalid quantity step or duplicate variant identity");return {...e.placements!==void 0?{placements:l(e.placements).map(a=>{let d=c(a);return {menuId:i(d.menu_id),categoryId:i(d.category_id)}})}:{},id:r,name:i(e.name),images:l(e.images??[]).map(i),price:b(e.price),isAvailable:!t&&(e.is_available??e.available)===true,quantity:{...E(o),step:m},variants:p,optionGroups:s,tags:l(e.tags??[]).map(i),...f("stockLabel",e.stock_label,v),...e.promo!==void 0?{promo:P(e.promo)}:{},...f("description",e.description,v),...e.compare_at_price?{compareAtPrice:b(e.compare_at_price)}:{}}}function ie(n,e){let r=c(n),s=l(r.menus??[r]);if(r.completeness!==void 0&&r.completeness!=="partial"&&r.completeness!=="complete")throw new u("server_error","Invalid catalogue completeness");let t=new Map,p=s.map(m=>{let a=c(m);if(a.placement_count!==void 0&&(!Number.isSafeInteger(a.placement_count)||Number(a.placement_count)<0)||a.paginated!==void 0&&typeof a.paginated!="boolean")throw new u("server_error","Invalid menu loading metadata");let d=l(a.categories??[]).map(q=>{let I=c(q),M=i(I.id),S=t.get(M),O=[...new Set([...S?.itemIds??[],...l(I.item_ids??[]).map(i)])];return t.set(M,{id:M,name:i(I.name),itemIds:O,...f("description",I.description,v)}),M}),x=K(a.schedule);return {id:i(a.id),name:i(a.name),categoryIds:d,...a.placement_count!==void 0?{placementCount:a.placement_count}:{},...f("paginated",a.paginated,w),...x?{schedule:x}:{},...f("infoBanner",a.info_banner,v)}}),o=Object.fromEntries(Object.entries(c(r.items)).map(([m,a])=>{let d=$(a);if(d.id!==m)throw new u("server_error","Item map key does not match its identity");return [m,d]}));if(r.branch_id!==void 0&&r.branch_id!==e)throw new u("server_error","Menu branch mismatch");return {id:p.length===1?p[0].id:`branch:${e}`,branchId:e,...r.completeness==="partial"?{completeness:"partial"}:{},name:p.length===1?p[0].name:"Catalogue",version:i(r.menu_version??r.version),categories:[...t.values()],items:o,menus:p,...p.length===1&&p[0].schedule?{schedule:p[0].schedule}:{}}}
|
|
2
|
+
export{u as a,N as b,j as c,V as d,y as e,H as f,J as g,Q as h,ne as i,c as j,i as k,l,v as m,w as n,f as o,b as p,Z as q,$ as r,ie as s};//# sourceMappingURL=chunk-I55A5QXJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/money.ts","../src/internal/money-math.ts","../src/internal/digest.ts","../src/transport/mappers.ts"],"names":["codes","ZappieError","code","message","details","isZappieError","error","asError","wireError","value","status","requestId","envelope","e","fallback","known","ZERO_DIGIT_CURRENCIES","THREE_DIGIT_CURRENCIES","FOUR_DIGIT_CURRENCIES","API_ONLY_CURRENCIES","contains","currency","intlCurrencies","isCurrency","currencyDigits","money","amountMinor","normalized","format","opts","locale","digits","sumMoney","values","zero","amount","multiplyMoney","quantity","payloadKey","payload","digest","byte","UnsupportedValue","record","text","list","number","nonnegative","result","bounds","input","min","max","isString","isBoolean","opt","key","is","mapMoney","v","hours","slot","day","schedule","mapGroup","g","selection","isAttribute","kind","raw","c","price","count","mapPromo","p","mapItem","id","optionGroups","unsupported","variants","x","k","step","variant","placement","mapMenu","branchId","sources","categories","menus","m","categoryIds","rawCategory","previous","itemIds","s","items","item","mapped"],"mappings":"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","file":"chunk-I55A5QXJ.js","sourcesContent":["/** Stable public error codes. */\nexport type ZappieErrorCode =\n | \"network_error\"\n | \"timeout\"\n | \"rate_limited\"\n | \"unauthorized\"\n | \"forbidden_origin\"\n | \"not_found\"\n | \"store_not_found\"\n | \"branch_not_found\"\n | \"item_not_found\"\n | \"cart_invalid\"\n | \"invalid_request\"\n | \"version_unsupported\"\n | \"server_error\";\nconst codes: readonly string[] = [\n \"network_error\",\n \"timeout\",\n \"rate_limited\",\n \"unauthorized\",\n \"forbidden_origin\",\n \"not_found\",\n \"store_not_found\",\n \"branch_not_found\",\n \"item_not_found\",\n \"cart_invalid\",\n \"invalid_request\",\n \"version_unsupported\",\n \"server_error\",\n];\n/** Context attached to an SDK failure. */\nexport type ErrorDetails = {\n status?: number;\n param?: string;\n docUrl?: string;\n requestId?: string;\n retryable?: boolean;\n cause?: unknown;\n};\n/** An SDK error you can handle by its stable code. */\nexport class ZappieError extends Error {\n readonly status?: number;\n readonly param?: string;\n readonly docUrl: string;\n readonly requestId?: string;\n readonly retryable: boolean;\n constructor(\n readonly code: ZappieErrorCode,\n message: string,\n details: ErrorDetails = {},\n ) {\n super(message, { cause: details.cause });\n this.name = \"ZappieError\";\n if (details.status !== undefined) {\n this.status = details.status;\n }\n if (details.param !== undefined) {\n this.param = details.param;\n }\n if (details.requestId !== undefined) {\n this.requestId = details.requestId;\n }\n this.docUrl = details.docUrl ?? `https://docs.zappie.ai/errors#${code}`;\n this.retryable =\n details.retryable ??\n [\"network_error\", \"timeout\", \"rate_limited\", \"server_error\"].includes(\n code,\n );\n }\n}\n/** Check whether a thrown value is a ZappieError. */\nexport function isZappieError(error: unknown): error is ZappieError {\n return error instanceof ZappieError;\n}\nexport function asError(error: unknown): ZappieError {\n return isZappieError(error)\n ? error\n : new ZappieError(\"network_error\", \"The storefront request failed\", {\n cause: error,\n });\n}\nexport function wireError(\n value: unknown,\n status: number,\n requestId?: string,\n): ZappieError {\n const envelope =\n value && typeof value === \"object\"\n ? (value as Record<string, unknown>)\n : {};\n const e =\n envelope.error && typeof envelope.error === \"object\"\n ? (envelope.error as Record<string, unknown>)\n : {};\n const fallback =\n status === 401\n ? \"unauthorized\"\n : status === 403\n ? \"forbidden_origin\"\n : status === 404\n ? \"not_found\"\n : status === 429\n ? \"rate_limited\"\n : status >= 500\n ? \"server_error\"\n : \"invalid_request\";\n const known = typeof e.code === \"string\" && codes.includes(e.code);\n const code = known\n ? (e.code as ZappieErrorCode)\n : e.code\n ? \"server_error\"\n : fallback;\n const message =\n typeof e.message === \"string\" ? e.message : \"The storefront request failed\";\n return new ZappieError(\n code,\n !known && e.code ? `${String(e.code)}: ${message}` : message,\n {\n status,\n ...(requestId ? { requestId } : {}),\n ...(typeof e.param === \"string\" ? { param: e.param } : {}),\n ...(typeof e.doc_url === \"string\" ? { docUrl: e.doc_url } : {}),\n },\n );\n}\n","import { ZappieError } from \"./errors\";\ndeclare const MoneyBrand: unique symbol;\n/** A normalized ISO 4217 currency code. */\nexport type Currency = string;\n// Minor-unit digits match the API, which scales amount_minor with\n// github.com/bojanz/currency v1.2.0 (pkg/currency.Digits). Intl differs for COP,\n// HUF, IDR, PKR and RSD, so it only presents the amount. Unlisted codes use 2.\nconst ZERO_DIGIT_CURRENCIES =\n \" AFN ALL BIF CLP DJF GNF IQD IRR ISK JPY KMF KPW KRW LAK LBP MGA MMK PYG RSD RWF SLL SOS SYP UGX UYI VND VUV XAF XOF XPF YER \";\nconst THREE_DIGIT_CURRENCIES = \" BHD JOD KWD LYD OMR TND \";\nconst FOUR_DIGIT_CURRENCIES = \" CLF UYW \";\n// API codes that Intl.supportedValuesOf(\"currency\") doesn't list.\nconst API_ONLY_CURRENCIES = \" BOV CHE CHW CLF COU MXV USN UYI UYW VED \";\nconst contains = (codes: string, currency: string) =>\n codes.includes(` ${currency} `);\nlet intlCurrencies: Set<string> | undefined;\nfunction isCurrency(code: string): boolean {\n if (!/^[A-Z]{3}$/.test(code)) {\n return false;\n }\n if (typeof Intl.supportedValuesOf !== \"function\") {\n return true;\n }\n intlCurrencies ??= new Set(Intl.supportedValuesOf(\"currency\"));\n return contains(API_ONLY_CURRENCIES, code) || intlCurrencies.has(code);\n}\nfunction currencyDigits(currency: Currency): number {\n if (contains(ZERO_DIGIT_CURRENCIES, currency)) {\n return 0;\n }\n if (contains(THREE_DIGIT_CURRENCIES, currency)) {\n return 3;\n }\n return contains(FOUR_DIGIT_CURRENCIES, currency) ? 4 : 2;\n}\n/** A frozen amount in safe integer minor units. Create it with money(). */\nexport type Money = {\n readonly amountMinor: number;\n readonly currency: Currency;\n readonly [MoneyBrand]: true;\n};\n/** Validate an amount in minor units and freeze it without rounding. */\nexport function money(amountMinor: number, currency: Currency): Money {\n const normalized =\n typeof currency === \"string\" ? currency.trim().toUpperCase() : \"\";\n if (!Number.isSafeInteger(amountMinor) || !isCurrency(normalized)) {\n throw new ZappieError(\n \"invalid_request\",\n \"Money requires safe integer minor units and a valid ISO 4217 currency\",\n );\n }\n return Object.freeze({ amountMinor, currency: normalized }) as Money;\n}\n/** Currency presentation options. */\nexport type MoneyFormatOptions = {\n showZeroDecimals?: boolean;\n compact?: boolean;\n sign?: \"auto\" | \"always\";\n};\n/** Format amounts for display. Use server quotes for final prices. */\nexport interface Formatters {\n money(value: Money, opts?: MoneyFormatOptions): string;\n}\n/** Format money with currency-specific minor units and locale defaults. */\nexport const format: Formatters = {\n money(value, opts = {}) {\n const normalized = money(value.amountMinor, value.currency);\n const locale = normalized.currency === \"NGN\" ? \"en-NG\" : \"en\";\n const digits = currencyDigits(normalized.currency);\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency: normalized.currency,\n currencyDisplay: \"narrowSymbol\",\n minimumFractionDigits:\n opts.showZeroDecimals || normalized.amountMinor % 10 ** digits !== 0\n ? digits\n : 0,\n maximumFractionDigits: digits,\n notation: opts.compact ? \"compact\" : \"standard\",\n signDisplay: opts.sign ?? \"auto\",\n }).format(normalized.amountMinor / 10 ** digits);\n },\n};\n","import { ZappieError } from \"../errors\";\nimport type { Money } from \"../money\";\nimport { money } from \"../money\";\nexport function sumMoney(values: readonly Money[], zero: Money): Money {\n let amount = zero.amountMinor;\n for (const value of values) {\n if (value.currency !== zero.currency) {\n throw new ZappieError(\n \"invalid_request\",\n \"Cannot combine different currencies\",\n );\n }\n amount = money(amount + value.amountMinor, zero.currency).amountMinor;\n }\n return money(amount, zero.currency);\n}\nexport function multiplyMoney(value: Money, quantity: number): Money {\n if (!Number.isSafeInteger(quantity)) {\n throw new ZappieError(\n \"invalid_request\",\n \"Money requires an integer quantity\",\n );\n }\n return money(value.amountMinor * quantity, value.currency);\n}\n","/** Payload digests avoid putting notes, addresses or credentials in request headers. */\nexport async function payloadKey(payload: string): Promise<string> {\n const digest = await globalThis.crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(payload),\n );\n return Array.from(new Uint8Array(digest), (byte) =>\n byte.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n}\n","import { ZappieError } from \"../errors\";\nimport type {\n Item,\n Menu,\n MenuSchedule,\n OpeningTime,\n OptionGroup,\n Variant,\n} from \"../models\";\nimport type { Currency, Money } from \"../money\";\nimport { money } from \"../money\";\n/** A value newer than this SDK; the item that carries it is shown as unavailable. */\nclass UnsupportedValue extends Error {}\nexport function record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new ZappieError(\"server_error\", \"Invalid storefront response object\");\n }\n return value as Record<string, unknown>;\n}\nexport function text(value: unknown): string {\n if (typeof value !== \"string\") {\n throw new ZappieError(\"server_error\", \"Invalid storefront response string\");\n }\n return value;\n}\nexport function list(value: unknown): unknown[] {\n if (!Array.isArray(value)) {\n throw new ZappieError(\"server_error\", \"Invalid storefront response list\");\n }\n return value;\n}\nfunction number(value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new ZappieError(\"server_error\", \"Invalid storefront response number\");\n }\n return value;\n}\nfunction nonnegative(value: unknown): number {\n const result = number(value);\n if (result < 0) {\n throw new ZappieError(\n \"server_error\",\n \"Negative selection or quantity bound\",\n );\n }\n return result;\n}\nfunction bounds(value: unknown): { min: number; max?: number } {\n const input = record(value);\n const min = nonnegative(input.min);\n if (input.max == null) {\n return { min };\n }\n const max = nonnegative(input.max);\n if (max < min) {\n throw new ZappieError(\n \"server_error\",\n \"Maximum quantity is below its minimum\",\n );\n }\n return { min, max };\n}\nexport const isString = (value: unknown): value is string =>\n typeof value === \"string\";\nexport const isBoolean = (value: unknown): value is boolean =>\n typeof value === \"boolean\";\n/** `{ [key]: value }` when the value passes the guard, otherwise `{}`, for optional wire fields. */\nexport function opt<K extends string, T>(\n key: K,\n value: unknown,\n is: (value: unknown) => value is T,\n): { [P in K]?: T } {\n return is(value) ? ({ [key]: value } as { [P in K]?: T }) : {};\n}\nexport function mapMoney(value: unknown): Money {\n const v = record(value);\n return money(\n number(v.amount_minor ?? v.amountMinor),\n text(v.currency) as Currency,\n );\n}\nexport function hours(value: unknown): OpeningTime[] {\n return list(value ?? []).map((slot) => {\n const v = record(slot);\n const day = number(v.day);\n if (!Number.isInteger(day) || day < 0 || day > 6) {\n throw new ZappieError(\"server_error\", \"Invalid opening day\");\n }\n return {\n day: day as OpeningTime[\"day\"],\n opens: text(v.opens ?? v.open ?? v.start),\n closes: text(v.closes ?? v.close ?? v.end),\n ...opt(\"disabled\", v.disabled, isBoolean),\n };\n });\n}\nfunction schedule(value: unknown): MenuSchedule | undefined {\n if (value === undefined) {\n return undefined;\n }\n const v = record(value);\n return {\n openingTimes: hours(v.opening_times ?? v.openingTimes ?? v.hours ?? []),\n ...opt(\"preorder\", v.preorder, isBoolean),\n ...(v.preorder_notice_hours !== undefined\n ? { preorderNoticeHours: number(v.preorder_notice_hours) }\n : {}),\n ...(v.preorder_max_days !== undefined\n ? { preorderMaxDays: number(v.preorder_max_days) }\n : {}),\n };\n}\nfunction mapGroup(value: unknown): OptionGroup {\n const g = record(value);\n const selection = record(g.selection ?? { min: g.min ?? 0, max: g.max });\n const isAttribute = g.is_attribute === true;\n const kind = text(g.kind ?? \"select\");\n if (![\"select\", \"text\", \"number\", \"date\", \"time\", \"toggle\"].includes(kind)) {\n throw new UnsupportedValue(`option input kind \"${kind}\"`);\n }\n return {\n id: text(g.id),\n name: text(g.name),\n kind: kind as OptionGroup[\"kind\"],\n required:\n typeof g.required === \"boolean\" ? g.required : number(selection.min) > 0,\n selection: bounds(selection),\n isAttribute,\n choices: list(g.choices ?? []).map((raw) => {\n const c = record(raw);\n const price = mapMoney(c.price);\n return {\n id: text(c.id),\n name: text(c.name),\n price: isAttribute ? money(0, price.currency) : price,\n ...(isAttribute && c.price_hint !== undefined\n ? { priceHint: mapMoney(c.price_hint) }\n : {}),\n isAvailable: (c.is_available ?? c.available) === true,\n ...(c.quantity ? { quantity: bounds(c.quantity) } : {}),\n };\n }),\n ...opt(\"helpText\", g.help_text, isString),\n ...(g.input\n ? {\n input: {\n ...(record(g.input).max_length !== undefined\n ? { maxLength: number(record(g.input).max_length) }\n : {}),\n ...(typeof record(g.input).placeholder === \"string\"\n ? { placeholder: text(record(g.input).placeholder) }\n : {}),\n },\n }\n : {}),\n ...opt(\"isAvailable\", g.is_available, isBoolean),\n ...opt(\"isInformational\", g.is_informational, isBoolean),\n ...(g.conditions\n ? {\n conditions: list(g.conditions).map((raw) => {\n const c = record(raw);\n const count = c.count ? record(c.count) : undefined;\n if (count && ![\"eq\", \"gte\", \"lte\"].includes(text(count.op))) {\n throw new UnsupportedValue(\n `option count operator \"${text(count.op)}\"`,\n );\n }\n if (\n c.match !== undefined &&\n c.match !== \"any\" &&\n c.match !== \"all\"\n ) {\n throw new UnsupportedValue(\n `option match operator \"${String(c.match)}\"`,\n );\n }\n if (c.set_required != null && typeof c.set_required !== \"boolean\") {\n throw new ZappieError(\n \"server_error\",\n \"Invalid conditional required flag\",\n );\n }\n return {\n groupId: text(c.group_id),\n choiceIds: list(c.choice_ids ?? []).map(text),\n match: c.match === \"all\" ? (\"all\" as const) : (\"any\" as const),\n ...(count\n ? {\n count: {\n op: text(count.op) as \"eq\" | \"gte\" | \"lte\",\n value: nonnegative(count.value),\n },\n }\n : {}),\n ...(c.set_required !== undefined\n ? { setRequired: c.set_required as boolean | null }\n : {}),\n ...(c.set_min !== undefined\n ? { setMin: c.set_min === null ? null : nonnegative(c.set_min) }\n : {}),\n ...(c.set_max !== undefined\n ? { setMax: c.set_max === null ? null : nonnegative(c.set_max) }\n : {}),\n };\n }),\n }\n : {}),\n };\n}\nfunction mapPromo(value: unknown): NonNullable<Item[\"promo\"]> {\n const p = record(value);\n return { name: text(p.name) };\n}\nexport function mapItem(value: unknown): Item {\n const v = record(value);\n const id = text(v.id);\n const optionGroups: OptionGroup[] = [];\n let unsupported = false;\n for (const raw of list(v.option_groups ?? [])) {\n try {\n optionGroups.push(mapGroup(raw));\n } catch (error) {\n if (!(error instanceof UnsupportedValue)) {\n throw error;\n }\n unsupported = true;\n console.warn(\n `Zappie item ${id} uses an ${error.message} this SDK can't validate; it is shown as unavailable`,\n );\n }\n }\n const variants = list(v.variants).map((raw) => {\n const x = record(raw);\n return {\n id: text(x.id),\n attributeChoices: Object.fromEntries(\n Object.entries(record(x.attribute_choices ?? {})).map(([k, v]) => [\n k,\n text(v),\n ]),\n ),\n price: mapMoney(x.price),\n ...opt(\"lowStock\", x.low_stock, isBoolean),\n isAvailable: !unsupported && (x.is_available ?? x.available) === true,\n };\n });\n if (!variants.length) {\n throw new ZappieError(\n \"server_error\",\n \"An item must carry at least one exact variant\",\n );\n }\n const quantity = record(\n v.quantity ?? { min: 1, step: 1, max: v.max_quantity },\n );\n const step = number(quantity.step);\n if (\n step <= 0 ||\n new Set(variants.map((variant) => variant.id)).size !== variants.length\n ) {\n throw new ZappieError(\n \"server_error\",\n \"Invalid quantity step or duplicate variant identity\",\n );\n }\n return {\n ...(v.placements !== undefined\n ? {\n placements: list(v.placements).map((raw) => {\n const placement = record(raw);\n return {\n menuId: text(placement.menu_id),\n categoryId: text(placement.category_id),\n };\n }),\n }\n : {}),\n id,\n name: text(v.name),\n images: list(v.images ?? []).map(text),\n price: mapMoney(v.price),\n isAvailable: !unsupported && (v.is_available ?? v.available) === true,\n quantity: { ...bounds(quantity), step },\n variants: variants as [Variant, ...Variant[]],\n optionGroups,\n tags: list(v.tags ?? []).map(text),\n ...opt(\"stockLabel\", v.stock_label, isString),\n ...(v.promo !== undefined ? { promo: mapPromo(v.promo) } : {}),\n ...opt(\"description\", v.description, isString),\n ...(v.compare_at_price\n ? { compareAtPrice: mapMoney(v.compare_at_price) }\n : {}),\n };\n}\nexport function mapMenu(value: unknown, branchId: string): Menu {\n const v = record(value);\n const sources = list(v.menus ?? [v]);\n if (\n v.completeness !== undefined &&\n v.completeness !== \"partial\" &&\n v.completeness !== \"complete\"\n ) {\n throw new ZappieError(\"server_error\", \"Invalid catalogue completeness\");\n }\n const categories = new Map<string, Menu[\"categories\"][number]>();\n const menus = sources.map((raw) => {\n const m = record(raw);\n if (\n (m.placement_count !== undefined &&\n (!Number.isSafeInteger(m.placement_count) ||\n Number(m.placement_count) < 0)) ||\n (m.paginated !== undefined && typeof m.paginated !== \"boolean\")\n ) {\n throw new ZappieError(\"server_error\", \"Invalid menu loading metadata\");\n }\n const categoryIds = list(m.categories ?? []).map((rawCategory) => {\n const c = record(rawCategory);\n const id = text(c.id);\n const previous = categories.get(id);\n const itemIds = [\n ...new Set([\n ...(previous?.itemIds ?? []),\n ...list(c.item_ids ?? []).map(text),\n ]),\n ];\n categories.set(id, {\n id,\n name: text(c.name),\n itemIds,\n ...opt(\"description\", c.description, isString),\n });\n return id;\n });\n const s = schedule(m.schedule);\n return {\n id: text(m.id),\n name: text(m.name),\n categoryIds,\n ...(m.placement_count !== undefined\n ? { placementCount: m.placement_count as number }\n : {}),\n ...opt(\"paginated\", m.paginated, isBoolean),\n ...(s ? { schedule: s } : {}),\n ...opt(\"infoBanner\", m.info_banner, isString),\n };\n });\n const items = Object.fromEntries(\n Object.entries(record(v.items)).map(([id, item]) => {\n const mapped = mapItem(item);\n if (mapped.id !== id) {\n throw new ZappieError(\n \"server_error\",\n \"Item map key does not match its identity\",\n );\n }\n return [id, mapped];\n }),\n );\n if (v.branch_id !== undefined && v.branch_id !== branchId) {\n throw new ZappieError(\"server_error\", \"Menu branch mismatch\");\n }\n return {\n id: menus.length === 1 ? menus[0]!.id : `branch:${branchId}`,\n branchId,\n ...(v.completeness === \"partial\"\n ? { completeness: \"partial\" as const }\n : {}),\n name: menus.length === 1 ? menus[0]!.name : \"Catalogue\",\n version: text(v.menu_version ?? v.version),\n categories: [...categories.values()],\n items,\n menus,\n ...(menus.length === 1 && menus[0]!.schedule\n ? { schedule: menus[0]!.schedule }\n : {}),\n };\n}\n"]}
|