@zappie/verify 0.1.2 → 0.1.5

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.
@@ -1,485 +0,0 @@
1
- // ../sdk/src/errors.ts
2
- var codes = [
3
- "network_error",
4
- "timeout",
5
- "rate_limited",
6
- "unauthorized",
7
- "forbidden_origin",
8
- "not_found",
9
- "store_not_found",
10
- "branch_not_found",
11
- "item_not_found",
12
- "cart_invalid",
13
- "invalid_request",
14
- "version_unsupported",
15
- "server_error"
16
- ];
17
- var ZappieError = class extends Error {
18
- constructor(code, message, details = {}) {
19
- super(message, { cause: details.cause });
20
- this.code = code;
21
- this.name = "ZappieError";
22
- if (details.status !== void 0) {
23
- this.status = details.status;
24
- }
25
- if (details.param !== void 0) {
26
- this.param = details.param;
27
- }
28
- if (details.requestId !== void 0) {
29
- this.requestId = details.requestId;
30
- }
31
- this.docUrl = details.docUrl ?? `https://docs.zappie.ai/errors#${code}`;
32
- this.retryable = details.retryable ?? ["network_error", "timeout", "rate_limited", "server_error"].includes(
33
- code
34
- );
35
- }
36
- };
37
- function isZappieError(error) {
38
- return error instanceof ZappieError;
39
- }
40
- function asError(error) {
41
- return isZappieError(error) ? error : new ZappieError("network_error", "The storefront request failed", {
42
- cause: error
43
- });
44
- }
45
- function wireError(value, status, requestId) {
46
- const envelope = value && typeof value === "object" ? value : {};
47
- const e = envelope.error && typeof envelope.error === "object" ? envelope.error : {};
48
- const fallback = status === 401 ? "unauthorized" : status === 403 ? "forbidden_origin" : status === 404 ? "not_found" : status === 429 ? "rate_limited" : status >= 500 ? "server_error" : "invalid_request";
49
- const known = typeof e.code === "string" && codes.includes(e.code);
50
- const code = known ? e.code : e.code ? "server_error" : fallback;
51
- const message = typeof e.message === "string" ? e.message : "The storefront request failed";
52
- return new ZappieError(
53
- code,
54
- !known && e.code ? `${String(e.code)}: ${message}` : message,
55
- {
56
- status,
57
- ...requestId ? { requestId } : {},
58
- ...typeof e.param === "string" ? { param: e.param } : {},
59
- ...typeof e.doc_url === "string" ? { docUrl: e.doc_url } : {}
60
- }
61
- );
62
- }
63
-
64
- // ../sdk/src/internal/digest.ts
65
- async function payloadKey(payload) {
66
- const digest = await globalThis.crypto.subtle.digest(
67
- "SHA-256",
68
- new TextEncoder().encode(payload)
69
- );
70
- return Array.from(
71
- new Uint8Array(digest),
72
- (byte) => byte.toString(16).padStart(2, "0")
73
- ).join("");
74
- }
75
-
76
- // ../sdk/src/money.ts
77
- var ZERO_DIGIT_CURRENCIES = " 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 ";
78
- var THREE_DIGIT_CURRENCIES = " BHD JOD KWD LYD OMR TND ";
79
- var FOUR_DIGIT_CURRENCIES = " CLF UYW ";
80
- var API_ONLY_CURRENCIES = " BOV CHE CHW CLF COU MXV USN UYI UYW VED ";
81
- var contains = (codes2, currency) => codes2.includes(` ${currency} `);
82
- var intlCurrencies;
83
- function isCurrency(code) {
84
- if (!/^[A-Z]{3}$/.test(code)) {
85
- return false;
86
- }
87
- if (typeof Intl.supportedValuesOf !== "function") {
88
- return true;
89
- }
90
- intlCurrencies ??= new Set(Intl.supportedValuesOf("currency"));
91
- return contains(API_ONLY_CURRENCIES, code) || intlCurrencies.has(code);
92
- }
93
- function currencyDigits(currency) {
94
- if (contains(ZERO_DIGIT_CURRENCIES, currency)) {
95
- return 0;
96
- }
97
- if (contains(THREE_DIGIT_CURRENCIES, currency)) {
98
- return 3;
99
- }
100
- return contains(FOUR_DIGIT_CURRENCIES, currency) ? 4 : 2;
101
- }
102
- function money(amountMinor, currency) {
103
- const normalized = typeof currency === "string" ? currency.trim().toUpperCase() : "";
104
- if (!Number.isSafeInteger(amountMinor) || !isCurrency(normalized)) {
105
- throw new ZappieError(
106
- "invalid_request",
107
- "Money requires safe integer minor units and a valid ISO 4217 currency"
108
- );
109
- }
110
- return Object.freeze({ amountMinor, currency: normalized });
111
- }
112
- var format = {
113
- money(value, opts = {}) {
114
- const normalized = money(value.amountMinor, value.currency);
115
- const locale = normalized.currency === "NGN" ? "en-NG" : "en";
116
- const digits = currencyDigits(normalized.currency);
117
- return new Intl.NumberFormat(locale, {
118
- style: "currency",
119
- currency: normalized.currency,
120
- currencyDisplay: "narrowSymbol",
121
- minimumFractionDigits: opts.showZeroDecimals || normalized.amountMinor % 10 ** digits !== 0 ? digits : 0,
122
- maximumFractionDigits: digits,
123
- notation: opts.compact ? "compact" : "standard",
124
- signDisplay: opts.sign ?? "auto"
125
- }).format(normalized.amountMinor / 10 ** digits);
126
- }
127
- };
128
-
129
- // ../sdk/src/internal/money-math.ts
130
- function sumMoney(values, zero) {
131
- let amount = zero.amountMinor;
132
- for (const value of values) {
133
- if (value.currency !== zero.currency) {
134
- throw new ZappieError(
135
- "invalid_request",
136
- "Cannot combine different currencies"
137
- );
138
- }
139
- amount = money(amount + value.amountMinor, zero.currency).amountMinor;
140
- }
141
- return money(amount, zero.currency);
142
- }
143
- function multiplyMoney(value, quantity) {
144
- if (!Number.isSafeInteger(quantity)) {
145
- throw new ZappieError(
146
- "invalid_request",
147
- "Money requires an integer quantity"
148
- );
149
- }
150
- return money(value.amountMinor * quantity, value.currency);
151
- }
152
-
153
- // ../sdk/src/transport/mappers.ts
154
- var UnsupportedValue = class extends Error {
155
- };
156
- function record(value) {
157
- if (!value || typeof value !== "object" || Array.isArray(value)) {
158
- throw new ZappieError("server_error", "Invalid storefront response object");
159
- }
160
- return value;
161
- }
162
- function text(value) {
163
- if (typeof value !== "string") {
164
- throw new ZappieError("server_error", "Invalid storefront response string");
165
- }
166
- return value;
167
- }
168
- function list(value) {
169
- if (!Array.isArray(value)) {
170
- throw new ZappieError("server_error", "Invalid storefront response list");
171
- }
172
- return value;
173
- }
174
- function number(value) {
175
- if (typeof value !== "number" || !Number.isFinite(value)) {
176
- throw new ZappieError("server_error", "Invalid storefront response number");
177
- }
178
- return value;
179
- }
180
- function nonnegative(value) {
181
- const result = number(value);
182
- if (result < 0) {
183
- throw new ZappieError(
184
- "server_error",
185
- "Negative selection or quantity bound"
186
- );
187
- }
188
- return result;
189
- }
190
- function bounds(value) {
191
- const input = record(value);
192
- const min = nonnegative(input.min);
193
- if (input.max == null) {
194
- return { min };
195
- }
196
- const max = nonnegative(input.max);
197
- if (max < min) {
198
- throw new ZappieError(
199
- "server_error",
200
- "Maximum quantity is below its minimum"
201
- );
202
- }
203
- return { min, max };
204
- }
205
- var isString = (value) => typeof value === "string";
206
- var isBoolean = (value) => typeof value === "boolean";
207
- function opt(key, value, is) {
208
- return is(value) ? { [key]: value } : {};
209
- }
210
- function mapMoney(value) {
211
- const v = record(value);
212
- return money(
213
- number(v.amount_minor ?? v.amountMinor),
214
- text(v.currency)
215
- );
216
- }
217
- function hours(value) {
218
- return list(value ?? []).map((slot) => {
219
- const v = record(slot);
220
- const day = number(v.day);
221
- if (!Number.isInteger(day) || day < 0 || day > 6) {
222
- throw new ZappieError("server_error", "Invalid opening day");
223
- }
224
- return {
225
- day,
226
- opens: text(v.opens ?? v.open ?? v.start),
227
- closes: text(v.closes ?? v.close ?? v.end),
228
- ...opt("disabled", v.disabled, isBoolean)
229
- };
230
- });
231
- }
232
- function schedule(value) {
233
- if (value === void 0) {
234
- return void 0;
235
- }
236
- const v = record(value);
237
- return {
238
- openingTimes: hours(v.opening_times ?? v.openingTimes ?? v.hours ?? []),
239
- ...opt("preorder", v.preorder, isBoolean),
240
- ...v.preorder_notice_hours !== void 0 ? { preorderNoticeHours: number(v.preorder_notice_hours) } : {},
241
- ...v.preorder_max_days !== void 0 ? { preorderMaxDays: number(v.preorder_max_days) } : {}
242
- };
243
- }
244
- function mapGroup(value) {
245
- const g = record(value);
246
- const selection = record(g.selection ?? { min: g.min ?? 0, max: g.max });
247
- const isAttribute = g.is_attribute === true;
248
- const kind = text(g.kind ?? "select");
249
- if (!["select", "text", "number", "date", "time", "toggle"].includes(kind)) {
250
- throw new UnsupportedValue(`option input kind "${kind}"`);
251
- }
252
- return {
253
- id: text(g.id),
254
- name: text(g.name),
255
- kind,
256
- required: typeof g.required === "boolean" ? g.required : number(selection.min) > 0,
257
- selection: bounds(selection),
258
- isAttribute,
259
- choices: list(g.choices ?? []).map((raw) => {
260
- const c = record(raw);
261
- const price = mapMoney(c.price);
262
- return {
263
- id: text(c.id),
264
- name: text(c.name),
265
- price: isAttribute ? money(0, price.currency) : price,
266
- ...isAttribute && c.price_hint !== void 0 ? { priceHint: mapMoney(c.price_hint) } : {},
267
- isAvailable: (c.is_available ?? c.available) === true,
268
- ...c.quantity ? { quantity: bounds(c.quantity) } : {}
269
- };
270
- }),
271
- ...opt("helpText", g.help_text, isString),
272
- ...g.input ? {
273
- input: {
274
- ...record(g.input).max_length !== void 0 ? { maxLength: number(record(g.input).max_length) } : {},
275
- ...typeof record(g.input).placeholder === "string" ? { placeholder: text(record(g.input).placeholder) } : {}
276
- }
277
- } : {},
278
- ...opt("isAvailable", g.is_available, isBoolean),
279
- ...opt("isInformational", g.is_informational, isBoolean),
280
- ...g.conditions ? {
281
- conditions: list(g.conditions).map((raw) => {
282
- const c = record(raw);
283
- const count = c.count ? record(c.count) : void 0;
284
- if (count && !["eq", "gte", "lte"].includes(text(count.op))) {
285
- throw new UnsupportedValue(
286
- `option count operator "${text(count.op)}"`
287
- );
288
- }
289
- if (c.match !== void 0 && c.match !== "any" && c.match !== "all") {
290
- throw new UnsupportedValue(
291
- `option match operator "${String(c.match)}"`
292
- );
293
- }
294
- if (c.set_required != null && typeof c.set_required !== "boolean") {
295
- throw new ZappieError(
296
- "server_error",
297
- "Invalid conditional required flag"
298
- );
299
- }
300
- return {
301
- groupId: text(c.group_id),
302
- choiceIds: list(c.choice_ids ?? []).map(text),
303
- match: c.match === "all" ? "all" : "any",
304
- ...count ? {
305
- count: {
306
- op: text(count.op),
307
- value: nonnegative(count.value)
308
- }
309
- } : {},
310
- ...c.set_required !== void 0 ? { setRequired: c.set_required } : {},
311
- ...c.set_min !== void 0 ? { setMin: c.set_min === null ? null : nonnegative(c.set_min) } : {},
312
- ...c.set_max !== void 0 ? { setMax: c.set_max === null ? null : nonnegative(c.set_max) } : {}
313
- };
314
- })
315
- } : {}
316
- };
317
- }
318
- function mapPromo(value) {
319
- const p = record(value);
320
- return { name: text(p.name) };
321
- }
322
- function mapItem(value) {
323
- const v = record(value);
324
- const id = text(v.id);
325
- const optionGroups = [];
326
- let unsupported = false;
327
- for (const raw of list(v.option_groups ?? [])) {
328
- try {
329
- optionGroups.push(mapGroup(raw));
330
- } catch (error) {
331
- if (!(error instanceof UnsupportedValue)) {
332
- throw error;
333
- }
334
- unsupported = true;
335
- console.warn(
336
- `Zappie item ${id} uses an ${error.message} this SDK can't validate; it is shown as unavailable`
337
- );
338
- }
339
- }
340
- const variants = list(v.variants).map((raw) => {
341
- const x = record(raw);
342
- return {
343
- id: text(x.id),
344
- attributeChoices: Object.fromEntries(
345
- Object.entries(record(x.attribute_choices ?? {})).map(([k, v2]) => [
346
- k,
347
- text(v2)
348
- ])
349
- ),
350
- price: mapMoney(x.price),
351
- ...opt("lowStock", x.low_stock, isBoolean),
352
- isAvailable: !unsupported && (x.is_available ?? x.available) === true
353
- };
354
- });
355
- if (!variants.length) {
356
- throw new ZappieError(
357
- "server_error",
358
- "An item must carry at least one exact variant"
359
- );
360
- }
361
- const quantity = record(
362
- v.quantity ?? { min: 1, step: 1, max: v.max_quantity }
363
- );
364
- const step = number(quantity.step);
365
- if (step <= 0 || new Set(variants.map((variant) => variant.id)).size !== variants.length) {
366
- throw new ZappieError(
367
- "server_error",
368
- "Invalid quantity step or duplicate variant identity"
369
- );
370
- }
371
- return {
372
- ...v.placements !== void 0 ? {
373
- placements: list(v.placements).map((raw) => {
374
- const placement = record(raw);
375
- return {
376
- menuId: text(placement.menu_id),
377
- categoryId: text(placement.category_id)
378
- };
379
- })
380
- } : {},
381
- id,
382
- name: text(v.name),
383
- images: list(v.images ?? []).map(text),
384
- price: mapMoney(v.price),
385
- isAvailable: !unsupported && (v.is_available ?? v.available) === true,
386
- quantity: { ...bounds(quantity), step },
387
- variants,
388
- optionGroups,
389
- tags: list(v.tags ?? []).map(text),
390
- ...opt("stockLabel", v.stock_label, isString),
391
- ...v.promo !== void 0 ? { promo: mapPromo(v.promo) } : {},
392
- ...opt("description", v.description, isString),
393
- ...v.compare_at_price ? { compareAtPrice: mapMoney(v.compare_at_price) } : {}
394
- };
395
- }
396
- function mapMenu(value, branchId) {
397
- const v = record(value);
398
- const sources = list(v.menus ?? [v]);
399
- if (v.completeness !== void 0 && v.completeness !== "partial" && v.completeness !== "complete") {
400
- throw new ZappieError("server_error", "Invalid catalogue completeness");
401
- }
402
- const categories = /* @__PURE__ */ new Map();
403
- const menus = sources.map((raw) => {
404
- const m = record(raw);
405
- if (m.placement_count !== void 0 && (!Number.isSafeInteger(m.placement_count) || Number(m.placement_count) < 0) || m.paginated !== void 0 && typeof m.paginated !== "boolean") {
406
- throw new ZappieError("server_error", "Invalid menu loading metadata");
407
- }
408
- const categoryIds = list(m.categories ?? []).map((rawCategory) => {
409
- const c = record(rawCategory);
410
- const id = text(c.id);
411
- const previous = categories.get(id);
412
- const itemIds = [
413
- .../* @__PURE__ */ new Set([
414
- ...previous?.itemIds ?? [],
415
- ...list(c.item_ids ?? []).map(text)
416
- ])
417
- ];
418
- categories.set(id, {
419
- id,
420
- name: text(c.name),
421
- itemIds,
422
- ...opt("description", c.description, isString)
423
- });
424
- return id;
425
- });
426
- const s = schedule(m.schedule);
427
- return {
428
- id: text(m.id),
429
- name: text(m.name),
430
- categoryIds,
431
- ...m.placement_count !== void 0 ? { placementCount: m.placement_count } : {},
432
- ...opt("paginated", m.paginated, isBoolean),
433
- ...s ? { schedule: s } : {},
434
- ...opt("infoBanner", m.info_banner, isString)
435
- };
436
- });
437
- const items = Object.fromEntries(
438
- Object.entries(record(v.items)).map(([id, item]) => {
439
- const mapped = mapItem(item);
440
- if (mapped.id !== id) {
441
- throw new ZappieError(
442
- "server_error",
443
- "Item map key does not match its identity"
444
- );
445
- }
446
- return [id, mapped];
447
- })
448
- );
449
- if (v.branch_id !== void 0 && v.branch_id !== branchId) {
450
- throw new ZappieError("server_error", "Menu branch mismatch");
451
- }
452
- return {
453
- id: menus.length === 1 ? menus[0].id : `branch:${branchId}`,
454
- branchId,
455
- ...v.completeness === "partial" ? { completeness: "partial" } : {},
456
- name: menus.length === 1 ? menus[0].name : "Catalogue",
457
- version: text(v.menu_version ?? v.version),
458
- categories: [...categories.values()],
459
- items,
460
- menus,
461
- ...menus.length === 1 && menus[0].schedule ? { schedule: menus[0].schedule } : {}
462
- };
463
- }
464
-
465
- export {
466
- ZappieError,
467
- asError,
468
- wireError,
469
- money,
470
- format,
471
- sumMoney,
472
- multiplyMoney,
473
- payloadKey,
474
- record,
475
- text,
476
- list,
477
- isString,
478
- isBoolean,
479
- opt,
480
- mapMoney,
481
- hours,
482
- mapItem,
483
- mapMenu
484
- };
485
- //# sourceMappingURL=chunk-WUWUDCYO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../sdk/src/errors.ts","../../sdk/src/internal/digest.ts","../../sdk/src/money.ts","../../sdk/src/internal/money-math.ts","../../sdk/src/transport/mappers.ts"],"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","/** 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\";\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","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"],"mappings":"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","names":["codes","v"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../sdk/src/cart/quote-response.ts","../../sdk/src/cart/quote-client.ts"],"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"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../sdk/src/transport/selected-menu.ts"],"sourcesContent":["import type { Zappie } from \"../client\";\nimport type { Menu } from \"../models\";\nimport type { CatalogueScope } from \"../persist/catalogue\";\nimport type { RequestCtx } from \"./types\";\n\n/** Complete for the named source, never complete for the branch. */\nexport type SelectedMenu = {\n menu: Menu & { completeness: \"partial\" };\n coverage: { menuIds: [string]; complete: true };\n};\n/**\n * A source menu with its ETag, or an unchanged response carrying the matching ETag.\n */\nexport type SelectedMenuResponse =\n (SelectedMenu & { etag: string }) | { notModified: true; etag: string };\n/**\n * A branch-scoped source-menu request with order context and an optional conditional ETag.\n */\nexport type SelectedMenuRequest = RequestCtx & {\n branchId: string;\n menuId: string;\n orderContext: CatalogueScope[\"orderContext\"];\n ifNoneMatch?: string;\n};\n/**\n * A transport that reads one complete source menu without claiming branch-wide coverage.\n */\nexport type SelectedMenuTransport = {\n getSelectedMenu(request: SelectedMenuRequest): Promise<SelectedMenuResponse>;\n};\n/** Dependencies are passed by REST to avoid splitting core shared chunks. */\nexport async function selectedMenu(\n ctx: SelectedMenuRequest,\n request: (path: string) => Promise<Response>,\n json: (response: Response) => Promise<unknown>,\n mapMenu: (value: unknown, branchId: string) => Menu,\n invalid: () => Error,\n): Promise<SelectedMenuResponse> {\n // Checked here rather than passed in: every argument REST passes costs the\n // core bytes, and the core has none to spare.\n const record = (value: unknown) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw invalid();\n }\n return value as Record<string, unknown>;\n };\n const query = new URLSearchParams({\n branch: ctx.branchId,\n order_context: ctx.orderContext,\n });\n const response = await request(\n `/menus/${encodeURIComponent(ctx.menuId)}?${query}`,\n );\n const etag = response.headers.get(\"ETag\");\n if (!etag) {\n throw invalid();\n }\n if (response.status === 304) {\n return { notModified: true, etag };\n }\n const raw = record(await json(response));\n const coverage = record(raw.coverage);\n const menu = mapMenu(raw, ctx.branchId);\n if (\n raw.next_cursor ||\n coverage.complete !== true ||\n !Array.isArray(coverage.menuIds) ||\n coverage.menuIds.length !== 1 ||\n coverage.menuIds[0] !== ctx.menuId ||\n menu.menus?.length !== 1 ||\n menu.menus[0]?.id !== ctx.menuId\n ) {\n throw invalid();\n }\n return {\n menu: { ...menu, completeness: \"partial\" },\n coverage: { menuIds: [ctx.menuId], complete: true },\n etag,\n };\n}\n/**\n * Build a versioned cache key for a source menu within a store, branch and order context.\n */\nexport function selectedMenuKey(scope: CatalogueScope) {\n return JSON.stringify([\n \"selected-menu:v1\",\n scope.store,\n scope.branchId,\n scope.orderContext,\n scope.menuId,\n ]);\n}\n/** Dedicated lazy resource: deliberately does not call menu.hydrate(). */\nexport function createSelectedMenuReader(client: Zappie) {\n const transport = client._internal.transport;\n return {\n async read(\n scope: CatalogueScope,\n options: { signal?: AbortSignal; ifNoneMatch?: string } = {},\n ) {\n if (!transport.getSelectedMenu) {\n throw new Error(\"Transport does not support selected menus\");\n }\n const response = await transport.getSelectedMenu({\n key: client.config.key,\n version: client.config.version,\n branchId: scope.branchId,\n menuId: scope.menuId,\n orderContext: scope.orderContext,\n ...options,\n });\n options.signal?.throwIfAborted();\n if (!(\"notModified\" in response)) {\n if (\n response.menu.branchId !== scope.branchId ||\n response.coverage.menuIds.length !== 1 ||\n response.coverage.menuIds[0] !== scope.menuId\n ) {\n throw new Error(\"Selected menu belongs to another scope\");\n }\n const key = selectedMenuKey(scope);\n const previous =\n client._internal.cache.snapshot<SelectedMenuResponse>(key).value;\n if (JSON.stringify(previous) !== JSON.stringify(response)) {\n client._internal.cache.set(key, response, response.etag);\n }\n }\n return response;\n },\n };\n}\n"],"mappings":";AA+BA,eAAsB,aACpB,KACA,SACA,MACA,SACA,SAC+B;AAG/B,QAAM,SAAS,CAAC,UAAmB;AACjC,QAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,YAAM,QAAQ;AAAA,IAChB;AACA,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,IAAI,gBAAgB;AAAA,IAChC,QAAQ,IAAI;AAAA,IACZ,eAAe,IAAI;AAAA,EACrB,CAAC;AACD,QAAM,WAAW,MAAM;AAAA,IACrB,UAAU,mBAAmB,IAAI,MAAM,CAAC,IAAI,KAAK;AAAA,EACnD;AACA,QAAM,OAAO,SAAS,QAAQ,IAAI,MAAM;AACxC,MAAI,CAAC,MAAM;AACT,UAAM,QAAQ;AAAA,EAChB;AACA,MAAI,SAAS,WAAW,KAAK;AAC3B,WAAO,EAAE,aAAa,MAAM,KAAK;AAAA,EACnC;AACA,QAAM,MAAM,OAAO,MAAM,KAAK,QAAQ,CAAC;AACvC,QAAM,WAAW,OAAO,IAAI,QAAQ;AACpC,QAAM,OAAO,QAAQ,KAAK,IAAI,QAAQ;AACtC,MACE,IAAI,eACJ,SAAS,aAAa,QACtB,CAAC,MAAM,QAAQ,SAAS,OAAO,KAC/B,SAAS,QAAQ,WAAW,KAC5B,SAAS,QAAQ,CAAC,MAAM,IAAI,UAC5B,KAAK,OAAO,WAAW,KACvB,KAAK,MAAM,CAAC,GAAG,OAAO,IAAI,QAC1B;AACA,UAAM,QAAQ;AAAA,EAChB;AACA,SAAO;AAAA,IACL,MAAM,EAAE,GAAG,MAAM,cAAc,UAAU;AAAA,IACzC,UAAU,EAAE,SAAS,CAAC,IAAI,MAAM,GAAG,UAAU,KAAK;AAAA,IAClD;AAAA,EACF;AACF;AAIO,SAAS,gBAAgB,OAAuB;AACrD,SAAO,KAAK,UAAU;AAAA,IACpB;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR,CAAC;AACH;AAEO,SAAS,yBAAyB,QAAgB;AACvD,QAAM,YAAY,OAAO,UAAU;AACnC,SAAO;AAAA,IACL,MAAM,KACJ,OACA,UAA0D,CAAC,GAC3D;AACA,UAAI,CAAC,UAAU,iBAAiB;AAC9B,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AACA,YAAM,WAAW,MAAM,UAAU,gBAAgB;AAAA,QAC/C,KAAK,OAAO,OAAO;AAAA,QACnB,SAAS,OAAO,OAAO;AAAA,QACvB,UAAU,MAAM;AAAA,QAChB,QAAQ,MAAM;AAAA,QACd,cAAc,MAAM;AAAA,QACpB,GAAG;AAAA,MACL,CAAC;AACD,cAAQ,QAAQ,eAAe;AAC/B,UAAI,EAAE,iBAAiB,WAAW;AAChC,YACE,SAAS,KAAK,aAAa,MAAM,YACjC,SAAS,SAAS,QAAQ,WAAW,KACrC,SAAS,SAAS,QAAQ,CAAC,MAAM,MAAM,QACvC;AACA,gBAAM,IAAI,MAAM,wCAAwC;AAAA,QAC1D;AACA,cAAM,MAAM,gBAAgB,KAAK;AACjC,cAAM,WACJ,OAAO,UAAU,MAAM,SAA+B,GAAG,EAAE;AAC7D,YAAI,KAAK,UAAU,QAAQ,MAAM,KAAK,UAAU,QAAQ,GAAG;AACzD,iBAAO,UAAU,MAAM,IAAI,KAAK,UAAU,SAAS,IAAI;AAAA,QACzD;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../sdk/src/transport/store.ts"],"sourcesContent":["import type { Branch, Fulfilment, OpeningTime, Store } from \"../models\";\nimport type { Currency, Money } from \"../money\";\n\ntype Guard<T> = (value: unknown) => value is T;\ntype Optional = <K extends string, T>(\n key: K,\n value: unknown,\n is: Guard<T>,\n) => { [P in K]?: T };\n\n/** Core parsing helpers are passed in, in this order, so this lazy entry has no runtime import. */\nexport function mapStore(\n value: unknown,\n record: (value: unknown) => Record<string, unknown>,\n text: (value: unknown) => string,\n list: (value: unknown) => unknown[],\n hours: (value: unknown) => OpeningTime[],\n mapMoney: (value: unknown) => Money,\n money: (amountMinor: number, currency: Currency) => Money,\n opt: Optional,\n isString: Guard<string>,\n isBoolean: Guard<boolean>,\n): Store {\n const coordinates = (input: unknown) => {\n const coordinates = record(input ?? {});\n return typeof coordinates.lat === \"number\" &&\n typeof coordinates.lng === \"number\"\n ? { lat: coordinates.lat, lng: coordinates.lng }\n : undefined;\n };\n const fulfilment = (input: unknown): Fulfilment => {\n const value = record(input);\n return {\n pickup: value.pickup === true,\n delivery: value.delivery === true,\n dineIn: (value.dine_in ?? value.dineIn) === true,\n scheduling: (value.scheduling ?? value.scheduled) === true,\n };\n };\n const source = record(value);\n const brand = record(source.brand ?? {});\n const branches: Branch[] = list(source.branches).map((raw) => {\n const branch = record(raw);\n const pickup = record(branch.pickup_address ?? {});\n const pickupCoordinates = coordinates(pickup.coordinates);\n const pickupAddress = {\n ...opt(\"placeId\", pickup.place_id, isString),\n ...(pickupCoordinates ? { coordinates: pickupCoordinates } : {}),\n };\n const address =\n typeof branch.address === \"string\"\n ? branch.address\n : branch.address\n ? Object.values(record(branch.address))\n .filter((entry) => typeof entry === \"string\")\n .join(\", \")\n : undefined;\n const addressFields =\n branch.address && typeof branch.address === \"object\"\n ? record(branch.address)\n : {};\n const branchCoordinates = coordinates(addressFields);\n return {\n id: text(branch.id),\n slug: text(branch.slug ?? branch.id),\n name: text(branch.name),\n openingTimes: hours(branch.opening_times ?? branch.hours),\n isOpen: branch.is_open === true,\n fulfilment: fulfilment(branch.fulfilment),\n ...(address !== undefined ? { address } : {}),\n ...(isString(branch.phone) ? { phone: branch.phone.trim() } : {}),\n ...opt(\"timezone\", branch.timezone, isString),\n ...(branchCoordinates ? { coordinates: branchCoordinates } : {}),\n ...opt(\"closedUntil\", branch.closed_until, isString),\n ...opt(\"nextChangeAt\", branch.next_change_at, isString),\n ...opt(\"isDefault\", branch.is_default, isBoolean),\n ...(Object.keys(pickupAddress).length > 0 ? { pickupAddress } : {}),\n ...(branch.social_links !== undefined\n ? {\n socialLinks: list(branch.social_links).flatMap((rawLink) => {\n const link = record(rawLink);\n // Templates render these as links; only http(s) URLs are kept.\n try {\n const url = new URL(text(link.url));\n return isString(link.type) &&\n (url.protocol === \"https:\" || url.protocol === \"http:\")\n ? [{ type: link.type, url: url.href }]\n : [];\n } catch {\n return [];\n }\n }),\n }\n : {}),\n ...(branch.minimum_order\n ? { minimumOrder: mapMoney(branch.minimum_order) }\n : {}),\n ...(branch.special_hours\n ? {\n specialHours: list(branch.special_hours).map((rawHours) => {\n const special = record(rawHours);\n return {\n date: text(special.date),\n closed: special.closed === true,\n ...opt(\"opens\", special.open, isString),\n ...opt(\"closes\", special.close, isString),\n };\n }),\n }\n : {}),\n };\n });\n const allowed = [\n \"card\",\n \"bank_transfer\",\n \"wallet\",\n \"zap\",\n \"apple_pay\",\n \"google_pay\",\n ];\n const paymentMethods = list(source.payment_methods)\n .map(text)\n .filter((method) => {\n if (allowed.includes(method)) {\n return true;\n }\n console.warn(\n `Zappie payment method \"${method}\" is newer than this SDK and was skipped`,\n );\n return false;\n });\n const aggregate = {\n pickup: false,\n delivery: false,\n dineIn: false,\n scheduling: false,\n };\n for (const branch of branches) {\n for (const key of Object.keys(aggregate) as (keyof Fulfilment)[]) {\n aggregate[key] ||= branch.fulfilment[key];\n }\n }\n const accent =\n brand.accent ?? (brand.colors ? record(brand.colors).accent : undefined);\n const templateSettings = record(source.template_settings ?? {}) as Record<\n string,\n string | number | boolean\n >;\n return {\n id: text(source.id),\n slug: text(source.slug),\n name: text(source.name),\n currency: money(0, text(source.currency) as Currency).currency,\n timezone: text(source.timezone),\n ...opt(\"description\", source.description, isString),\n ...(source.template_settings !== undefined ? { templateSettings } : {}),\n brand: {\n ...opt(\"logoUrl\", brand.logo_url, isString),\n ...opt(\"coverImageUrl\", brand.cover_image_url, isString),\n ...(isString(accent) ? { accent } : {}),\n },\n fulfilment: source.fulfilment ? fulfilment(source.fulfilment) : aggregate,\n paymentMethods: paymentMethods as Store[\"paymentMethods\"],\n branches,\n };\n}\n"],"mappings":"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","names":["coordinates","value"]}