@zappie/sdk 0.1.6 → 0.1.8

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +47 -1
  3. package/dist/cart/branch.d.ts +2 -2
  4. package/dist/cart/item.d.ts +3 -3
  5. package/dist/cart/quote-response.js +6 -1
  6. package/dist/cart/quote-response.js.map +2 -2
  7. package/dist/cart/quote.d.ts +3 -3
  8. package/dist/{client-Bm2cCYea.d.ts → client-DzUauU-b.d.ts} +2 -2
  9. package/dist/debug.d.ts +3 -3
  10. package/dist/debug.js +1 -1
  11. package/dist/index.d.ts +6 -6
  12. package/dist/index.js +1 -1
  13. package/dist/integrations/index.d.ts +9 -6
  14. package/dist/integrations/index.js +1 -0
  15. package/dist/integrations/index.js.map +2 -2
  16. package/dist/internal.d.ts +3 -3
  17. package/dist/{models-Rg5kQUkv.d.ts → models-D__QbqEd.d.ts} +14 -1
  18. package/dist/persist/catalogue.d.ts +3 -3
  19. package/dist/places/index.d.ts +6 -2
  20. package/dist/pricing/index.d.ts +116 -0
  21. package/dist/pricing/index.js +30 -0
  22. package/dist/pricing/index.js.map +7 -0
  23. package/dist/react/index.d.ts +3 -3
  24. package/dist/server/index.d.ts +7 -4
  25. package/dist/server/storefront-url/build-v1.js +8 -17
  26. package/dist/server/storefront-url/build-v1.js.map +2 -2
  27. package/dist/server/storefront-url/build-v2.js +13 -41
  28. package/dist/server/storefront-url/build-v2.js.map +2 -2
  29. package/dist/server/storefront-url/canonical.js +36 -0
  30. package/dist/server/storefront-url/canonical.js.map +7 -0
  31. package/dist/server/storefront-url/contract.js +2 -2
  32. package/dist/server/storefront-url/contract.js.map +2 -2
  33. package/dist/server/storefront-url/params.js +35 -18
  34. package/dist/server/storefront-url/params.js.map +2 -2
  35. package/dist/server/storefront-url/parse-v1.js +15 -12
  36. package/dist/server/storefront-url/parse-v1.js.map +2 -2
  37. package/dist/server/storefront-url/parse-v2.js +17 -79
  38. package/dist/server/storefront-url/parse-v2.js.map +2 -2
  39. package/dist/server/storefront-url/public-id.js +8 -0
  40. package/dist/server/storefront-url/public-id.js.map +7 -0
  41. package/dist/server/storefront-url/redirect.js +20 -6
  42. package/dist/server/storefront-url/redirect.js.map +2 -2
  43. package/dist/server/storefront-url/sign-in.js +2 -1
  44. package/dist/server/storefront-url/sign-in.js.map +2 -2
  45. package/dist/server/storefront-url/types.js +1 -0
  46. package/dist/server/storefront-url/types.js.map +2 -2
  47. package/dist/server/storefront-url/url.js +34 -23
  48. package/dist/server/storefront-url/url.js.map +2 -2
  49. package/dist/testing/index.d.ts +3 -3
  50. package/dist/transport/category-page.d.ts +2 -2
  51. package/dist/transport/category-page.js +6 -2
  52. package/dist/transport/category-page.js.map +2 -2
  53. package/dist/transport/presentation.d.ts +7 -0
  54. package/dist/transport/presentation.js +68 -0
  55. package/dist/transport/presentation.js.map +7 -0
  56. package/dist/transport/rest.js +15 -3
  57. package/dist/transport/rest.js.map +2 -2
  58. package/dist/transport/search.d.ts +3 -3
  59. package/dist/transport/search.js +6 -1
  60. package/dist/transport/search.js.map +2 -2
  61. package/dist/transport/selected-menu.d.ts +3 -3
  62. package/dist/transport/selected-menu.js +7 -2
  63. package/dist/transport/selected-menu.js.map +2 -2
  64. package/dist/transport/store.d.ts +1 -2
  65. package/dist/transport/store.js.map +1 -1
  66. package/dist/{types-CuDvfW9g.d.ts → types-gQXU2gEA.d.ts} +3 -1
  67. package/dist/url/index.d.ts +4 -1
  68. package/package.json +6 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @zappie/sdk
2
2
 
3
+ ## 0.1.8
4
+
5
+ ### Patch Changes
6
+
7
+ - 4f3cdc3: Add `quote.feesTotal`, and `startingPrice(item)` and `showsFromPrice(item)` in the new `@zappie/sdk/pricing` entry point. Type the place route's `distance_meters` and new `duration_seconds` as optional, and pass both through.
8
+
9
+ ## 0.1.7
10
+
11
+ ### Patch Changes
12
+
13
+ - 4bfb1b2: Read the optional Maps browser key from storefront integrations. Map legacy URLs to public item, menu, category and order IDs, preserve attribution parameters.
14
+ - 666ba1c: Read selected-menu coverage from `menu_ids`. Expose menu layout and availability, separate plain-text and HTML banners, branch promotions, and order-ahead days. Preserve omitted descriptions and phone numbers as absent fields.
15
+
3
16
  ## 0.1.6
4
17
 
5
18
  ### Patch Changes
package/README.md CHANGED
@@ -56,8 +56,9 @@ Prices always come from Zappie. The cart shows a local estimate while it waits,
56
56
  | `@zappie/sdk/react` | `ZappieProvider` and hooks such as `useStore`, `useMenu` and `useCart` |
57
57
  | `@zappie/sdk/checkout` | Opening Zappie's hosted checkout and checking it completed |
58
58
  | `@zappie/sdk/customer` and `/customer/react` | Signed-in customers, their orders and saved addresses |
59
- | `@zappie/sdk/integrations` | Public tracking IDs for your app’s consent flow |
59
+ | `@zappie/sdk/integrations` | Public integration IDs and browser keys |
60
60
  | `@zappie/sdk/places` | Address search and delivery-zone checks |
61
+ | `@zappie/sdk/pricing` | An item's starting price and whether to show it as "From" |
61
62
  | `@zappie/sdk/server` | Server-side reads, storefront URLs and `verifyWebhook()` |
62
63
  | `@zappie/sdk/template` and `/template/react` | Template settings and responsive images for template authors |
63
64
  | `@zappie/sdk/testing` | A mock client for your tests |
@@ -79,3 +80,48 @@ The SDK is at `0.x`. Its API can change in a minor release while it settles. Eac
79
80
  ## License
80
81
 
81
82
  MIT
83
+
84
+ ### Quote fees
85
+
86
+ `quote.feesTotal` is the sum of `quote.fees`, so a template can print one
87
+ "Fees" line without adding money itself. It leaves delivery out (that is
88
+ `quote.delivery`) and is zero when there are no fees. Each quote line has
89
+ `optionsTotal` when the API prices its options.
90
+
91
+ ### Starting price
92
+
93
+ `startingPrice(item)` from `@zappie/sdk/pricing` returns the price an item starts from: the cheapest
94
+ available variant plus the cheapest choice of each required add-on group. It is
95
+ the rule Zappie uses for a product's starting price. When no variant is
96
+ available, it uses the cheapest variant. `showsFromPrice(item)` says whether to
97
+ show that price as "From": available variants differ in price, or a required
98
+ add-on raises it. `item.price` is the branch price, not the starting price.
99
+
100
+ The API sends one `available` flag per item and variant, and a free-text
101
+ `stockLabel`. It doesn't say whether an item is sold out or unavailable for
102
+ another reason, so `isAvailable` covers both.
103
+
104
+ ### Place routes
105
+
106
+ `places.place(placeId, { branchId })` returns `route` with optional
107
+ `distance_meters` and `duration_seconds`, as the API sends them.
108
+
109
+ ### Maps browser key
110
+
111
+ `createIntegrations().get()` from `@zappie/sdk/integrations` returns optional
112
+ `googleMaps: { browserKey: string }`. The REST field is
113
+ `google_maps: { browser_key: string } | null`. An absent or null field returns
114
+ `googleMaps: undefined`, so apps can use this before the API field is deployed.
115
+ The SDK does not load Maps scripts.
116
+
117
+ ### Legacy redirects
118
+
119
+ `storefrontRedirect(input, { installation })` from `@zappie/sdk/url` returns
120
+ `string | null`. Callers choose the HTTP status when they serve the redirect.
121
+ Zappie's templates use temporary redirects (302) for now.
122
+
123
+ V2 URLs use `item_` and `ord_` public IDs, `menu=menu_<id>`, and category
124
+ anchors `#c-cat_<id>`. Already-prefixed IDs stay unchanged. Legacy cart,
125
+ checkout and sign-in overlays become routes. Unsupported legacy UI parameters
126
+ are dropped. Ad click IDs, `ref`, and every `utm_*` parameter retain their values.
127
+ Payment-return and printed QR routes retain their existing parameters.
@@ -1,5 +1,5 @@
1
- import { M as Money, I as Item, a as Menu } from '../models-Rg5kQUkv.js';
2
- import { C as CartLine } from '../types-CuDvfW9g.js';
1
+ import { M as Money, I as Item, a as Menu } from '../models-D__QbqEd.js';
2
+ import { C as CartLine } from '../types-gQXU2gEA.js';
3
3
 
4
4
  /** A line that can move to the destination branch, with its old and new estimates. */
5
5
  type BranchSwitchKeptLine = {
@@ -1,6 +1,6 @@
1
- import { Z as Zappie } from '../client-Bm2cCYea.js';
2
- import { I as Item } from '../models-Rg5kQUkv.js';
3
- import '../types-CuDvfW9g.js';
1
+ import { Z as Zappie } from '../client-DzUauU-b.js';
2
+ import { I as Item } from '../models-D__QbqEd.js';
3
+ import '../types-gQXU2gEA.js';
4
4
 
5
5
  /** Register an item already read by a partial/selected catalogue, without fetching it again. */
6
6
  declare function prepareItem(client: Zappie, item: Item, options: {
@@ -103,6 +103,7 @@ function mapQuote(value, branchId) {
103
103
  return fail();
104
104
  }
105
105
  const deliveryCharges = charges.filter((c) => c.code === "delivery");
106
+ const fees = charges.filter((c) => c.code !== "delivery");
106
107
  const integer = (value2) => {
107
108
  if (!Number.isSafeInteger(value2) || Number(value2) < 0) {
108
109
  return fail();
@@ -151,7 +152,11 @@ function mapQuote(value, branchId) {
151
152
  ...v.lines_unpriced === true ? { linesUnpriced: true } : {},
152
153
  subtotal,
153
154
  total,
154
- fees: charges.filter((c) => c.code !== "delivery"),
155
+ fees,
156
+ feesTotal: sumMoney(
157
+ fees.map((c) => c.amount),
158
+ money(0, subtotal.currency)
159
+ ),
155
160
  discounts,
156
161
  ...deliveryCharges.length ? {
157
162
  delivery: sumMoney(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cart/quote-response.ts"],
4
- "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 case \"choose_region\":\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 integer = (value: unknown) => {\n if (!Number.isSafeInteger(value) || Number(value) < 0) {\n return fail();\n }\n return value as number;\n };\n const fulfilment =\n v.fulfilment === undefined ? undefined : record(v.fulfilment);\n if (\n v.menu_version_stale !== undefined &&\n typeof v.menu_version_stale !== \"boolean\"\n ) {\n return fail();\n }\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 ...(l.item_id !== undefined ? { itemId: text(l.item_id) } : {}),\n ...(l.name !== undefined ? { name: text(l.name) } : {}),\n ...(l.quantity !== undefined ? { quantity: integer(l.quantity) } : {}),\n ...(l.status !== undefined ? { status: text(l.status) } : {}),\n ...(l.options_total !== undefined\n ? {\n optionsTotal:\n l.options_total === null ? null : amount(l.options_total),\n }\n : {}),\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 ...(v.menu_version_stale !== undefined\n ? { menuVersionStale: v.menu_version_stale as boolean }\n : {}),\n ...(fulfilment\n ? {\n fulfilment: {\n type: text(fulfilment.type),\n scheduledFor:\n fulfilment.scheduled_for === null\n ? null\n : text(fulfilment.scheduled_for),\n ...(fulfilment.eta_minutes !== undefined\n ? { etaMinutes: list(fulfilment.eta_minutes).map(integer) }\n : {}),\n ...(fulfilment.delivery_region_id !== undefined\n ? { deliveryRegionId: text(fulfilment.delivery_region_id) }\n : {}),\n },\n }\n : {}),\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"],
5
- "mappings": "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",
4
+ "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 case \"choose_region\":\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 fees = charges.filter((c) => c.code !== \"delivery\");\n const integer = (value: unknown) => {\n if (!Number.isSafeInteger(value) || Number(value) < 0) {\n return fail();\n }\n return value as number;\n };\n const fulfilment =\n v.fulfilment === undefined ? undefined : record(v.fulfilment);\n if (\n v.menu_version_stale !== undefined &&\n typeof v.menu_version_stale !== \"boolean\"\n ) {\n return fail();\n }\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 ...(l.item_id !== undefined ? { itemId: text(l.item_id) } : {}),\n ...(l.name !== undefined ? { name: text(l.name) } : {}),\n ...(l.quantity !== undefined ? { quantity: integer(l.quantity) } : {}),\n ...(l.status !== undefined ? { status: text(l.status) } : {}),\n ...(l.options_total !== undefined\n ? {\n optionsTotal:\n l.options_total === null ? null : amount(l.options_total),\n }\n : {}),\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 ...(v.menu_version_stale !== undefined\n ? { menuVersionStale: v.menu_version_stale as boolean }\n : {}),\n ...(fulfilment\n ? {\n fulfilment: {\n type: text(fulfilment.type),\n scheduledFor:\n fulfilment.scheduled_for === null\n ? null\n : text(fulfilment.scheduled_for),\n ...(fulfilment.eta_minutes !== undefined\n ? { etaMinutes: list(fulfilment.eta_minutes).map(integer) }\n : {}),\n ...(fulfilment.delivery_region_id !== undefined\n ? { deliveryRegionId: text(fulfilment.delivery_region_id) }\n : {}),\n },\n }\n : {}),\n lines,\n ...(v.lines_unpriced === true ? { linesUnpriced: true } : {}),\n subtotal,\n total,\n fees,\n feesTotal: sumMoney(\n fees.map((c) => c.amount),\n money(0, subtotal.currency),\n ),\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"],
5
+ "mappings": "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",
6
6
  "names": ["value"]
7
7
  }
@@ -1,6 +1,6 @@
1
- import { T as Transport, R as RequestCtx } from '../client-Bm2cCYea.js';
2
- import { Q as QuoteRequest, a as Quote } from '../types-CuDvfW9g.js';
3
- import '../models-Rg5kQUkv.js';
1
+ import { T as Transport, R as RequestCtx } from '../client-DzUauU-b.js';
2
+ import { Q as QuoteRequest, a as Quote } from '../types-gQXU2gEA.js';
3
+ import '../models-D__QbqEd.js';
4
4
 
5
5
  type QuoteClientOptions = {
6
6
  customerBase?: string | undefined;
@@ -1,5 +1,5 @@
1
- import { a as Menu, C as CategoryPage, S as Store, I as Item, M as Money, F as Formatters } from './models-Rg5kQUkv.js';
2
- import { Q as QuoteRequest, g as WireQuote, i as CartIssueCode, d as CartModule, b as CartLineInput } from './types-CuDvfW9g.js';
1
+ import { a as Menu, C as CategoryPage, S as Store, I as Item, M as Money, F as Formatters } from './models-D__QbqEd.js';
2
+ import { Q as QuoteRequest, g as WireQuote, i as CartIssueCode, d as CartModule, b as CartLineInput } from './types-gQXU2gEA.js';
3
3
 
4
4
  /**
5
5
  * The store, branch, order context and source menu that identify a saved catalogue.
package/dist/debug.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { b as CartLineInput, a as Quote } from './types-CuDvfW9g.js';
2
- import { M as Money, a as Menu, B as Branch } from './models-Rg5kQUkv.js';
3
- import { Z as Zappie } from './client-Bm2cCYea.js';
1
+ import { b as CartLineInput, a as Quote } from './types-gQXU2gEA.js';
2
+ import { M as Money, a as Menu, B as Branch } from './models-D__QbqEd.js';
3
+ import { Z as Zappie } from './client-DzUauU-b.js';
4
4
 
5
5
  type StoredLine = CartLineInput & {
6
6
  id: string;
package/dist/debug.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/debug.ts
2
- var VERSION = true ? "0.1.6" : "0.0.0-development";
2
+ var VERSION = true ? "0.1.8" : "0.0.0-development";
3
3
  function installDebug(client) {
4
4
  if (typeof window === "undefined" || client.mode !== "test") {
5
5
  return;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { T as Transport, R as RequestCtx, f as MenuFulfilment, g as MenuResponse, h as SelectedMenuRequest, i as SelectedMenuResponse, j as SearchRequest, k as SearchPage, l as MenuVersion, a as ZappieError } from './client-Bm2cCYea.js';
2
- export { A as API_VERSION, E as ErrorDetails, m as MenuReadOptions, M as MenuResource, n as ReadOptions, S as StorageLike, c as StoreResource, Z as Zappie, b as ZappieClientOptions, b as ZappieConfig, e as ZappieErrorCode, d as ZappieEvents, o as createZappie, p as isZappieError } from './client-Bm2cCYea.js';
3
- import { S as Store, C as CategoryPage, I as Item, O as OptionGroup, M as Money, a as Menu, B as Branch } from './models-Rg5kQUkv.js';
4
- export { b as Category, c as Choice, d as Currency, F as Formatters, e as Fulfilment, f as MenuSchedule, g as MenuSection, h as MoneyFormatOptions, i as OpeningTime, j as OptionCondition, P as PaymentMethodKind, k as SpecialHours, V as Variant, l as format, m as money } from './models-Rg5kQUkv.js';
5
- import { Q as QuoteRequest, g as WireQuote, f as CartIssue, b as CartLineInput, C as CartLine } from './types-CuDvfW9g.js';
6
- export { h as CartFix, c as CartFulfilment, i as CartIssueCode, d as CartModule, j as CartSnapshot, e as CartState, k as CartSyncAdapter, l as CartSyncDocument, D as DeliveryAddress, a as Quote, m as WireFix, W as WireFulfilment, n as WireIssue, o as WireLine, p as WireMoney } from './types-CuDvfW9g.js';
1
+ import { T as Transport, R as RequestCtx, f as MenuFulfilment, g as MenuResponse, h as SelectedMenuRequest, i as SelectedMenuResponse, j as SearchRequest, k as SearchPage, l as MenuVersion, a as ZappieError } from './client-DzUauU-b.js';
2
+ export { A as API_VERSION, E as ErrorDetails, m as MenuReadOptions, M as MenuResource, n as ReadOptions, S as StorageLike, c as StoreResource, Z as Zappie, b as ZappieClientOptions, b as ZappieConfig, e as ZappieErrorCode, d as ZappieEvents, o as createZappie, p as isZappieError } from './client-DzUauU-b.js';
3
+ import { S as Store, C as CategoryPage, I as Item, O as OptionGroup, M as Money, a as Menu, B as Branch } from './models-D__QbqEd.js';
4
+ export { b as Category, c as Choice, d as Currency, F as Formatters, e as Fulfilment, f as MenuSchedule, g as MenuSection, h as MoneyFormatOptions, i as OpeningTime, j as OptionCondition, P as PaymentMethodKind, k as SpecialHours, V as Variant, l as format, m as money } from './models-D__QbqEd.js';
5
+ import { Q as QuoteRequest, g as WireQuote, f as CartIssue, b as CartLineInput, C as CartLine } from './types-gQXU2gEA.js';
6
+ export { h as CartFix, c as CartFulfilment, i as CartIssueCode, d as CartModule, j as CartSnapshot, e as CartState, k as CartSyncAdapter, l as CartSyncDocument, D as DeliveryAddress, a as Quote, m as WireFix, W as WireFulfilment, n as WireIssue, o as WireLine, p as WireMoney } from './types-gQXU2gEA.js';
7
7
 
8
8
  /** REST connection options. A custom fetch can provide tracing or mock responses. */
9
9
  type RestTransportOptions = {
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import { previewItem } from "./cart/preview.js";
10
10
  import { estimateUnitPrice } from "./cart/price.js";
11
11
  import { resolveSourceMenu } from "./cart/source-menu.js";
12
12
  import { validateLine } from "./cart/validate.js";
13
- var VERSION = true ? "0.1.6" : "0.0.0-development";
13
+ var VERSION = true ? "0.1.8" : "0.0.0-development";
14
14
  export {
15
15
  API_VERSION,
16
16
  RestTransport,
@@ -1,9 +1,12 @@
1
- import { R as RequestCtx } from '../client-Bm2cCYea.js';
2
- import '../models-Rg5kQUkv.js';
3
- import '../types-CuDvfW9g.js';
1
+ import { R as RequestCtx } from '../client-DzUauU-b.js';
2
+ import '../models-D__QbqEd.js';
3
+ import '../types-gQXU2gEA.js';
4
4
 
5
- /** Public tracking IDs. Your app decides when consent allows it to load scripts. */
5
+ /** Public integration IDs and browser keys. Your app decides when to load scripts. */
6
6
  type Integrations = {
7
+ googleMaps?: {
8
+ browserKey: string;
9
+ };
7
10
  googleAnalytics?: {
8
11
  measurementId: string;
9
12
  };
@@ -11,7 +14,7 @@ type Integrations = {
11
14
  pixelId: string;
12
15
  };
13
16
  };
14
- /** A backend that supplies public tracking IDs without loading scripts. */
17
+ /** A backend that supplies public integration IDs and browser keys without loading scripts. */
15
18
  type IntegrationsTransport = {
16
19
  getIntegrations(ctx: RequestCtx): Promise<Integrations>;
17
20
  };
@@ -24,7 +27,7 @@ type IntegrationsOptions = {
24
27
  transport?: IntegrationsTransport;
25
28
  };
26
29
  /**
27
- * Create a client that reads public tracking IDs. It never loads tracking scripts.
30
+ * Create a client that reads public integration IDs and browser keys. It never loads tracking scripts.
28
31
  * Import this entry when your app needs the IDs, then apply your consent policy.
29
32
  */
30
33
  declare function createIntegrations(options: IntegrationsOptions): {
@@ -62,6 +62,7 @@ function createIntegrations(options) {
62
62
  return result;
63
63
  };
64
64
  return {
65
+ ...raw.google_maps != null ? { googleMaps: { browserKey: id(raw.google_maps, "browser_key") } } : {},
65
66
  ...raw.google_analytics != null ? {
66
67
  googleAnalytics: {
67
68
  measurementId: id(raw.google_analytics, "measurement_id")
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/integrations/index.ts"],
4
- "sourcesContent": ["import { requestWithRetry } from \"../internal/customer-http\";\nimport {\n API_VERSION,\n RestTransport,\n validateConfig,\n ZappieError,\n} from \"../places/sdk\";\nimport type { RequestCtx } from \"../transport/types\";\n\n/** Public tracking IDs. Your app decides when consent allows it to load scripts. */\nexport type Integrations = {\n googleAnalytics?: { measurementId: string };\n metaPixel?: { pixelId: string };\n};\n\n/** A backend that supplies public tracking IDs without loading scripts. */\nexport type IntegrationsTransport = {\n getIntegrations(ctx: RequestCtx): Promise<Integrations>;\n};\n\n/** Credentials and optional connection settings for the integrations read. */\nexport type IntegrationsOptions = {\n key: string;\n baseUrl?: string;\n version?: string;\n fetch?: typeof fetch;\n transport?: IntegrationsTransport;\n};\n\n/**\n * Create a client that reads public tracking IDs. It never loads tracking scripts.\n * Import this entry when your app needs the IDs, then apply your consent policy.\n */\nexport function createIntegrations(options: IntegrationsOptions) {\n validateConfig({ store: \"integrations\", key: options.key });\n const base = new RestTransport(options).baseUrl;\n return {\n /** Read enabled integrations. An absent integration has no public ID to use. */\n async get(read: { signal?: AbortSignal } = {}): Promise<Integrations> {\n const ctx = {\n key: options.key,\n version: options.version ?? API_VERSION,\n ...read,\n };\n if (options.transport) {\n return options.transport.getIntegrations(ctx);\n }\n const response = await requestWithRetry(\n options.fetch ?? ((input, init) => globalThis.fetch(input, init)),\n `${base}/store/integrations`,\n {\n redirect: \"manual\",\n headers: {\n Authorization: `Bearer ${ctx.key}`,\n \"Zappie-Version\": ctx.version,\n },\n ...read,\n },\n \"Could not read storefront integrations\",\n );\n if (!response.ok) {\n throw new ZappieError(\n \"server_error\",\n \"Could not read storefront integrations\",\n { status: response.status },\n );\n }\n const value: unknown = await response.json();\n const record = (value: unknown): Record<string, unknown> => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new ZappieError(\n \"server_error\",\n \"Invalid storefront integrations\",\n );\n }\n return value as Record<string, unknown>;\n };\n const raw = record(value);\n const id = (value: unknown, key: string): string => {\n const result = record(value)[key];\n if (typeof result !== \"string\" || !result) {\n throw new ZappieError(\n \"server_error\",\n \"Invalid storefront integration ID\",\n );\n }\n return result;\n };\n return {\n ...(raw.google_analytics != null\n ? {\n googleAnalytics: {\n measurementId: id(raw.google_analytics, \"measurement_id\"),\n },\n }\n : {}),\n ...(raw.meta_pixel != null\n ? { metaPixel: { pixelId: id(raw.meta_pixel, \"pixel_id\") } }\n : {}),\n };\n },\n };\n}\n\n/** The integrations read returned by createIntegrations. */\nexport type IntegrationsClient = ReturnType<typeof createIntegrations>;\n"],
5
- "mappings": ";AAAA,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA2BA,SAAS,mBAAmB,SAA8B;AAC/D,iBAAe,EAAE,OAAO,gBAAgB,KAAK,QAAQ,IAAI,CAAC;AAC1D,QAAM,OAAO,IAAI,cAAc,OAAO,EAAE;AACxC,SAAO;AAAA;AAAA,IAEL,MAAM,IAAI,OAAiC,CAAC,GAA0B;AACpE,YAAM,MAAM;AAAA,QACV,KAAK,QAAQ;AAAA,QACb,SAAS,QAAQ,WAAW;AAAA,QAC5B,GAAG;AAAA,MACL;AACA,UAAI,QAAQ,WAAW;AACrB,eAAO,QAAQ,UAAU,gBAAgB,GAAG;AAAA,MAC9C;AACA,YAAM,WAAW,MAAM;AAAA,QACrB,QAAQ,UAAU,CAAC,OAAO,SAAS,WAAW,MAAM,OAAO,IAAI;AAAA,QAC/D,GAAG,IAAI;AAAA,QACP;AAAA,UACE,UAAU;AAAA,UACV,SAAS;AAAA,YACP,eAAe,UAAU,IAAI,GAAG;AAAA,YAChC,kBAAkB,IAAI;AAAA,UACxB;AAAA,UACA,GAAG;AAAA,QACL;AAAA,QACA;AAAA,MACF;AACA,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA,EAAE,QAAQ,SAAS,OAAO;AAAA,QAC5B;AAAA,MACF;AACA,YAAM,QAAiB,MAAM,SAAS,KAAK;AAC3C,YAAM,SAAS,CAACA,WAA4C;AAC1D,YAAI,CAACA,UAAS,OAAOA,WAAU,YAAY,MAAM,QAAQA,MAAK,GAAG;AAC/D,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAOA;AAAA,MACT;AACA,YAAM,MAAM,OAAO,KAAK;AACxB,YAAM,KAAK,CAACA,QAAgB,QAAwB;AAClD,cAAM,SAAS,OAAOA,MAAK,EAAE,GAAG;AAChC,YAAI,OAAO,WAAW,YAAY,CAAC,QAAQ;AACzC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL,GAAI,IAAI,oBAAoB,OACxB;AAAA,UACE,iBAAiB;AAAA,YACf,eAAe,GAAG,IAAI,kBAAkB,gBAAgB;AAAA,UAC1D;AAAA,QACF,IACA,CAAC;AAAA,QACL,GAAI,IAAI,cAAc,OAClB,EAAE,WAAW,EAAE,SAAS,GAAG,IAAI,YAAY,UAAU,EAAE,EAAE,IACzD,CAAC;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { requestWithRetry } from \"../internal/customer-http\";\nimport {\n API_VERSION,\n RestTransport,\n validateConfig,\n ZappieError,\n} from \"../places/sdk\";\nimport type { RequestCtx } from \"../transport/types\";\n\n/** Public integration IDs and browser keys. Your app decides when to load scripts. */\nexport type Integrations = {\n googleMaps?: { browserKey: string };\n googleAnalytics?: { measurementId: string };\n metaPixel?: { pixelId: string };\n};\n\n/** A backend that supplies public integration IDs and browser keys without loading scripts. */\nexport type IntegrationsTransport = {\n getIntegrations(ctx: RequestCtx): Promise<Integrations>;\n};\n\n/** Credentials and optional connection settings for the integrations read. */\nexport type IntegrationsOptions = {\n key: string;\n baseUrl?: string;\n version?: string;\n fetch?: typeof fetch;\n transport?: IntegrationsTransport;\n};\n\n/**\n * Create a client that reads public integration IDs and browser keys. It never loads tracking scripts.\n * Import this entry when your app needs the IDs, then apply your consent policy.\n */\nexport function createIntegrations(options: IntegrationsOptions) {\n validateConfig({ store: \"integrations\", key: options.key });\n const base = new RestTransport(options).baseUrl;\n return {\n /** Read enabled integrations. An absent integration has no public ID to use. */\n async get(read: { signal?: AbortSignal } = {}): Promise<Integrations> {\n const ctx = {\n key: options.key,\n version: options.version ?? API_VERSION,\n ...read,\n };\n if (options.transport) {\n return options.transport.getIntegrations(ctx);\n }\n const response = await requestWithRetry(\n options.fetch ?? ((input, init) => globalThis.fetch(input, init)),\n `${base}/store/integrations`,\n {\n redirect: \"manual\",\n headers: {\n Authorization: `Bearer ${ctx.key}`,\n \"Zappie-Version\": ctx.version,\n },\n ...read,\n },\n \"Could not read storefront integrations\",\n );\n if (!response.ok) {\n throw new ZappieError(\n \"server_error\",\n \"Could not read storefront integrations\",\n { status: response.status },\n );\n }\n const value: unknown = await response.json();\n const record = (value: unknown): Record<string, unknown> => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new ZappieError(\n \"server_error\",\n \"Invalid storefront integrations\",\n );\n }\n return value as Record<string, unknown>;\n };\n const raw = record(value);\n const id = (value: unknown, key: string): string => {\n const result = record(value)[key];\n if (typeof result !== \"string\" || !result) {\n throw new ZappieError(\n \"server_error\",\n \"Invalid storefront integration ID\",\n );\n }\n return result;\n };\n return {\n ...(raw.google_maps != null\n ? { googleMaps: { browserKey: id(raw.google_maps, \"browser_key\") } }\n : {}),\n ...(raw.google_analytics != null\n ? {\n googleAnalytics: {\n measurementId: id(raw.google_analytics, \"measurement_id\"),\n },\n }\n : {}),\n ...(raw.meta_pixel != null\n ? { metaPixel: { pixelId: id(raw.meta_pixel, \"pixel_id\") } }\n : {}),\n };\n },\n };\n}\n\n/** The integrations read returned by createIntegrations. */\nexport type IntegrationsClient = ReturnType<typeof createIntegrations>;\n"],
5
+ "mappings": ";AAAA,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA4BA,SAAS,mBAAmB,SAA8B;AAC/D,iBAAe,EAAE,OAAO,gBAAgB,KAAK,QAAQ,IAAI,CAAC;AAC1D,QAAM,OAAO,IAAI,cAAc,OAAO,EAAE;AACxC,SAAO;AAAA;AAAA,IAEL,MAAM,IAAI,OAAiC,CAAC,GAA0B;AACpE,YAAM,MAAM;AAAA,QACV,KAAK,QAAQ;AAAA,QACb,SAAS,QAAQ,WAAW;AAAA,QAC5B,GAAG;AAAA,MACL;AACA,UAAI,QAAQ,WAAW;AACrB,eAAO,QAAQ,UAAU,gBAAgB,GAAG;AAAA,MAC9C;AACA,YAAM,WAAW,MAAM;AAAA,QACrB,QAAQ,UAAU,CAAC,OAAO,SAAS,WAAW,MAAM,OAAO,IAAI;AAAA,QAC/D,GAAG,IAAI;AAAA,QACP;AAAA,UACE,UAAU;AAAA,UACV,SAAS;AAAA,YACP,eAAe,UAAU,IAAI,GAAG;AAAA,YAChC,kBAAkB,IAAI;AAAA,UACxB;AAAA,UACA,GAAG;AAAA,QACL;AAAA,QACA;AAAA,MACF;AACA,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA,EAAE,QAAQ,SAAS,OAAO;AAAA,QAC5B;AAAA,MACF;AACA,YAAM,QAAiB,MAAM,SAAS,KAAK;AAC3C,YAAM,SAAS,CAACA,WAA4C;AAC1D,YAAI,CAACA,UAAS,OAAOA,WAAU,YAAY,MAAM,QAAQA,MAAK,GAAG;AAC/D,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAOA;AAAA,MACT;AACA,YAAM,MAAM,OAAO,KAAK;AACxB,YAAM,KAAK,CAACA,QAAgB,QAAwB;AAClD,cAAM,SAAS,OAAOA,MAAK,EAAE,GAAG;AAChC,YAAI,OAAO,WAAW,YAAY,CAAC,QAAQ;AACzC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL,GAAI,IAAI,eAAe,OACnB,EAAE,YAAY,EAAE,YAAY,GAAG,IAAI,aAAa,aAAa,EAAE,EAAE,IACjE,CAAC;AAAA,QACL,GAAI,IAAI,oBAAoB,OACxB;AAAA,UACE,iBAAiB;AAAA,YACf,eAAe,GAAG,IAAI,kBAAkB,gBAAgB;AAAA,UAC1D;AAAA,QACF,IACA,CAAC;AAAA,QACL,GAAI,IAAI,cAAc,OAClB,EAAE,WAAW,EAAE,SAAS,GAAG,IAAI,YAAY,UAAU,EAAE,EAAE,IACzD,CAAC;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": ["value"]
7
7
  }
@@ -1,6 +1,6 @@
1
- import { c as CartFulfilment, W as WireFulfilment } from './types-CuDvfW9g.js';
2
- export { v as validateConfig } from './client-Bm2cCYea.js';
3
- import './models-Rg5kQUkv.js';
1
+ import { c as CartFulfilment, W as WireFulfilment } from './types-gQXU2gEA.js';
2
+ export { v as validateConfig } from './client-DzUauU-b.js';
3
+ import './models-D__QbqEd.js';
4
4
 
5
5
  /**
6
6
  * Convert a cart fulfilment selection to the API field names used by quotes and checkout.
@@ -74,6 +74,14 @@ type Branch = {
74
74
  lng: number;
75
75
  };
76
76
  };
77
+ /** Automatic promotions to display. The quote decides whether an order qualifies. */
78
+ promos?: {
79
+ id: string;
80
+ name: string;
81
+ description: string;
82
+ }[];
83
+ /** How many days ahead this branch accepts scheduled orders. */
84
+ orderAheadDays?: number;
77
85
  socialLinks?: {
78
86
  type: string;
79
87
  url: string;
@@ -135,8 +143,13 @@ type MenuSection = {
135
143
  id: string;
136
144
  name: string;
137
145
  categoryIds: string[];
138
- /** Merchant rich text. Sanitize it before you render it. */
146
+ layout?: "LIST" | "GRID" | "CARD";
147
+ /** Whether this menu is available now at the selected branch. */
148
+ isActive?: boolean;
149
+ /** Plain-text merchant banner. */
139
150
  infoBanner?: string;
151
+ /** Sanitized rich-text banner supplied by the service. */
152
+ infoBannerHtml?: string;
140
153
  schedule?: MenuSchedule;
141
154
  };
142
155
  /** A branch catalogue that stores each item once across categories. */
@@ -1,3 +1,3 @@
1
- export { q as CATALOGUE_MAX_AGE_MS, r as CATALOGUE_MAX_BYTES, s as CatalogueScope, t as SavedCatalogue, u as catalogueDigest, w as catalogueKey, x as createCatalogueStorage, y as createSavedCatalogue } from '../client-Bm2cCYea.js';
2
- import '../models-Rg5kQUkv.js';
3
- import '../types-CuDvfW9g.js';
1
+ export { q as CATALOGUE_MAX_AGE_MS, r as CATALOGUE_MAX_BYTES, s as CatalogueScope, t as SavedCatalogue, u as catalogueDigest, w as catalogueKey, x as createCatalogueStorage, y as createSavedCatalogue } from '../client-DzUauU-b.js';
2
+ import '../models-D__QbqEd.js';
3
+ import '../types-gQXU2gEA.js';
@@ -9,7 +9,7 @@ type PlaceSuggestion = {
9
9
  secondary?: string;
10
10
  };
11
11
  /**
12
- * A resolved place with address text, coordinates and an optional route distance in metres.
12
+ * A resolved place with address text, coordinates and, when you pass a branch, the route from that branch.
13
13
  */
14
14
  type Place = {
15
15
  place_id: string;
@@ -18,8 +18,12 @@ type Place = {
18
18
  country?: string;
19
19
  lat: number;
20
20
  lng: number;
21
+ /** The route from the branch. Each field is absent when the API doesn't send it. */
21
22
  route?: {
22
- distance_meters: number;
23
+ /** Road distance in metres. */
24
+ distance_meters?: number;
25
+ /** Travel time in seconds. */
26
+ duration_seconds?: number;
23
27
  };
24
28
  };
25
29
  /**
@@ -0,0 +1,116 @@
1
+ declare const MoneyBrand: unique symbol;
2
+ /** A normalized ISO 4217 currency code. */
3
+ type Currency = string;
4
+ /** A frozen amount in safe integer minor units. Create it with money(). */
5
+ type Money = {
6
+ readonly amountMinor: number;
7
+ readonly currency: Currency;
8
+ readonly [MoneyBrand]: true;
9
+ };
10
+
11
+ /** An exact variant with its selected attributes, price and availability. */
12
+ type Variant = {
13
+ /** A low-stock hint for shoppers. This does not give a stock balance. */
14
+ lowStock?: boolean;
15
+ id: string;
16
+ attributeChoices: Record<string, string>;
17
+ price: Money;
18
+ isAvailable: boolean;
19
+ };
20
+ /** Item details and choices, with at least one exact variant. */
21
+ type Item = {
22
+ /** Fulfilment modes returned for this item. */
23
+ fulfilment?: string[];
24
+ /** Exact source placements returned by targeted item reads. */
25
+ placements?: {
26
+ menuId: string;
27
+ categoryId: string;
28
+ }[];
29
+ /** Stock text for display. Use isAvailable and the server quote to check eligibility. */
30
+ stockLabel?: string;
31
+ promo?: {
32
+ name: string;
33
+ };
34
+ id: string;
35
+ name: string;
36
+ description?: string;
37
+ images: string[];
38
+ price: Money;
39
+ compareAtPrice?: Money;
40
+ isAvailable: boolean;
41
+ quantity: {
42
+ min: number;
43
+ max?: number;
44
+ step: number;
45
+ };
46
+ variants: [Variant, ...Variant[]];
47
+ optionGroups: OptionGroup[];
48
+ tags: string[];
49
+ };
50
+ /** Conditions that change option rules when selected choices match. */
51
+ type OptionCondition = {
52
+ groupId: string;
53
+ choiceIds: string[];
54
+ match: "any" | "all";
55
+ count?: {
56
+ op: "eq" | "gte" | "lte";
57
+ value: number;
58
+ };
59
+ setRequired?: boolean | null;
60
+ setMin?: number | null;
61
+ setMax?: number | null;
62
+ };
63
+ /** Addon or exact-variant attribute selection rules. */
64
+ type OptionGroup = {
65
+ id: string;
66
+ name: string;
67
+ helpText?: string;
68
+ kind: "select" | "text" | "number" | "date" | "time" | "toggle";
69
+ required: boolean;
70
+ isAvailable?: boolean;
71
+ isInformational?: boolean;
72
+ selection: {
73
+ min: number;
74
+ max?: number;
75
+ };
76
+ isAttribute: boolean;
77
+ choices: Choice[];
78
+ input?: {
79
+ maxLength?: number;
80
+ placeholder?: string;
81
+ };
82
+ conditions?: OptionCondition[];
83
+ };
84
+ /** A selectable option. Attribute prices are zero to avoid charging twice. */
85
+ type Choice = {
86
+ /** An attribute price adjustment for display. Cart calculations exclude it. */
87
+ priceHint?: Money;
88
+ id: string;
89
+ name: string;
90
+ price: Money;
91
+ isAvailable: boolean;
92
+ quantity?: {
93
+ min: number;
94
+ max?: number;
95
+ };
96
+ };
97
+
98
+ /**
99
+ * The lowest price a shopper can pay for one of this item, by the same rule
100
+ * Zappie uses for a product's starting price: the cheapest available variant
101
+ * plus the cheapest choice of each required add-on group. When no variant is
102
+ * available, the cheapest variant is used.
103
+ *
104
+ * @param item - The catalogue item.
105
+ * @returns A display price. Use a server quote for checkout totals.
106
+ */
107
+ declare function startingPrice(item: Item): Money;
108
+ /**
109
+ * Whether to show the starting price as "From": true when available variants
110
+ * have different prices, or a required add-on raises the starting price.
111
+ *
112
+ * @param item - The catalogue item.
113
+ */
114
+ declare function showsFromPrice(item: Item): boolean;
115
+
116
+ export { showsFromPrice, startingPrice };
@@ -0,0 +1,30 @@
1
+ // src/pricing/index.ts
2
+ import { sumMoney } from "../internal/money-math.js";
3
+ var cheapest = (prices) => prices.filter((price) => price.amountMinor >= 0).sort((a, b) => a.amountMinor - b.amountMinor)[0];
4
+ function startingPrice(item) {
5
+ const available = item.variants.filter((variant) => variant.isAvailable);
6
+ const base = cheapest(
7
+ (available.length ? available : item.variants).map(
8
+ (variant) => variant.price
9
+ )
10
+ ) ?? item.price;
11
+ return sumMoney(
12
+ item.optionGroups.flatMap(
13
+ (group) => !group.isAttribute && group.required && group.kind === "select" ? cheapest(group.choices.map((choice) => choice.price)) ?? [] : []
14
+ ),
15
+ base
16
+ );
17
+ }
18
+ function showsFromPrice(item) {
19
+ const prices = [
20
+ ...new Set(
21
+ item.variants.filter((variant) => variant.isAvailable).map((variant) => variant.price.amountMinor)
22
+ )
23
+ ];
24
+ return prices.length > 1 || prices.length === 1 && startingPrice(item).amountMinor > prices[0];
25
+ }
26
+ export {
27
+ showsFromPrice,
28
+ startingPrice
29
+ };
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/pricing/index.ts"],
4
+ "sourcesContent": ["import { sumMoney } from \"../internal/money-math\";\nimport type { Item } from \"../models\";\nimport type { Money } from \"../money\";\n\nconst cheapest = (prices: Money[]): Money | undefined =>\n prices\n .filter((price) => price.amountMinor >= 0)\n .sort((a, b) => a.amountMinor - b.amountMinor)[0];\n\n/**\n * The lowest price a shopper can pay for one of this item, by the same rule\n * Zappie uses for a product's starting price: the cheapest available variant\n * plus the cheapest choice of each required add-on group. When no variant is\n * available, the cheapest variant is used.\n *\n * @param item - The catalogue item.\n * @returns A display price. Use a server quote for checkout totals.\n */\nexport function startingPrice(item: Item): Money {\n const available = item.variants.filter((variant) => variant.isAvailable);\n const base =\n cheapest(\n (available.length ? available : item.variants).map(\n (variant) => variant.price,\n ),\n ) ?? item.price;\n return sumMoney(\n item.optionGroups.flatMap((group) =>\n !group.isAttribute && group.required && group.kind === \"select\"\n ? (cheapest(group.choices.map((choice) => choice.price)) ?? [])\n : [],\n ),\n base,\n );\n}\n\n/**\n * Whether to show the starting price as \"From\": true when available variants\n * have different prices, or a required add-on raises the starting price.\n *\n * @param item - The catalogue item.\n */\nexport function showsFromPrice(item: Item): boolean {\n const prices = [\n ...new Set(\n item.variants\n .filter((variant) => variant.isAvailable)\n .map((variant) => variant.price.amountMinor),\n ),\n ];\n return (\n prices.length > 1 ||\n (prices.length === 1 && startingPrice(item).amountMinor > prices[0]!)\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,gBAAgB;AAIzB,IAAM,WAAW,CAAC,WAChB,OACG,OAAO,CAAC,UAAU,MAAM,eAAe,CAAC,EACxC,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC;AAW7C,SAAS,cAAc,MAAmB;AAC/C,QAAM,YAAY,KAAK,SAAS,OAAO,CAAC,YAAY,QAAQ,WAAW;AACvE,QAAM,OACJ;AAAA,KACG,UAAU,SAAS,YAAY,KAAK,UAAU;AAAA,MAC7C,CAAC,YAAY,QAAQ;AAAA,IACvB;AAAA,EACF,KAAK,KAAK;AACZ,SAAO;AAAA,IACL,KAAK,aAAa;AAAA,MAAQ,CAAC,UACzB,CAAC,MAAM,eAAe,MAAM,YAAY,MAAM,SAAS,WAClD,SAAS,MAAM,QAAQ,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,KAAK,CAAC,IAC3D,CAAC;AAAA,IACP;AAAA,IACA;AAAA,EACF;AACF;AAQO,SAAS,eAAe,MAAqB;AAClD,QAAM,SAAS;AAAA,IACb,GAAG,IAAI;AAAA,MACL,KAAK,SACF,OAAO,CAAC,YAAY,QAAQ,WAAW,EACvC,IAAI,CAAC,YAAY,QAAQ,MAAM,WAAW;AAAA,IAC/C;AAAA,EACF;AACA,SACE,OAAO,SAAS,KACf,OAAO,WAAW,KAAK,cAAc,IAAI,EAAE,cAAc,OAAO,CAAC;AAEtE;",
6
+ "names": []
7
+ }
@@ -1,9 +1,9 @@
1
1
  export { VERSION } from '../index.js';
2
- import { I as Item, a as Menu, S as Store, M as Money } from '../models-Rg5kQUkv.js';
3
- import { a as ZappieError, Z as Zappie } from '../client-Bm2cCYea.js';
2
+ import { I as Item, a as Menu, S as Store, M as Money } from '../models-D__QbqEd.js';
3
+ import { a as ZappieError, Z as Zappie } from '../client-DzUauU-b.js';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import { ReactNode } from 'react';
6
- import { d as CartModule, C as CartLine, c as CartFulfilment, e as CartState, f as CartIssue } from '../types-CuDvfW9g.js';
6
+ import { d as CartModule, C as CartLine, c as CartFulfilment, e as CartState, f as CartIssue } from '../types-gQXU2gEA.js';
7
7
 
8
8
  /** Subscribe to storefront identity and branch-directory data. */
9
9
  declare function useStore(): {
@@ -1,7 +1,7 @@
1
- import { a as Menu, F as Formatters, S as Store } from '../models-Rg5kQUkv.js';
2
- import { a as ZappieError, b as ZappieConfig, T as Transport, S as StorageLike, c as StoreResource, M as MenuResource, d as ZappieEvents, C as Cache } from '../client-Bm2cCYea.js';
1
+ import { a as Menu, F as Formatters, S as Store } from '../models-D__QbqEd.js';
2
+ import { a as ZappieError, b as ZappieConfig, T as Transport, S as StorageLike, c as StoreResource, M as MenuResource, d as ZappieEvents, C as Cache } from '../client-DzUauU-b.js';
3
3
  export { VERSION } from '../index.js';
4
- import { d as CartModule, b as CartLineInput } from '../types-CuDvfW9g.js';
4
+ import { d as CartModule, b as CartLineInput } from '../types-gQXU2gEA.js';
5
5
 
6
6
  /**
7
7
  * A URL string, URL object or Request you can parse as a storefront route.
@@ -28,7 +28,7 @@ declare const STOREFRONT_V1_QUERY_PARAMETERS: readonly ["ref", "utm_source", "pa
28
28
  /**
29
29
  * Recognized storefront query keys, including the v1 keys and checkout return and session keys.
30
30
  */
31
- declare const STOREFRONT_QUERY_PARAMETERS: readonly ["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", "return", "session"];
31
+ declare const STOREFRONT_QUERY_PARAMETERS: readonly ["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", "menu", "return", "session"];
32
32
  /**
33
33
  * Readonly query parameter names and string values carried by storefront page state.
34
34
  */
@@ -155,6 +155,9 @@ declare const parseStorefrontUrl: (input: StorefrontUrlInput, options?: Storefro
155
155
  * Find the canonical v2 URL for a recognized storefront route.
156
156
  * Compares normalized paths and sorted query parameters to avoid unnecessary redirects.
157
157
  *
158
+ * Callers choose the HTTP status when serving the redirect.
159
+ * Zappie templates use temporary redirects (302) for now.
160
+ *
158
161
  * @returns A redirect target, or null for v1, an unknown route, a parse/build failure or an equivalent URL.
159
162
  */
160
163
  declare const storefrontRedirect: (input: StorefrontUrlInput, options?: StorefrontUrlOptions) => string | null;