@zappie/sdk 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +21 -1
- package/dist/cart/branch.d.ts +2 -2
- package/dist/cart/item.d.ts +3 -3
- package/dist/cart/quote.d.ts +3 -3
- package/dist/{client-Bm2cCYea.d.ts → client-iVMHfAFn.d.ts} +2 -2
- package/dist/config/index.d.ts +11 -0
- package/dist/debug.d.ts +3 -3
- package/dist/debug.js +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +1 -1
- package/dist/integrations/index.d.ts +9 -6
- package/dist/integrations/index.js +1 -0
- package/dist/integrations/index.js.map +2 -2
- package/dist/internal.d.ts +3 -3
- package/dist/{models-Rg5kQUkv.d.ts → models-D__QbqEd.d.ts} +14 -1
- package/dist/persist/catalogue.d.ts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/server/index.d.ts +7 -4
- package/dist/server/storefront-url/build-v1.js +8 -17
- package/dist/server/storefront-url/build-v1.js.map +2 -2
- package/dist/server/storefront-url/build-v2.js +13 -41
- package/dist/server/storefront-url/build-v2.js.map +2 -2
- package/dist/server/storefront-url/canonical.js +36 -0
- package/dist/server/storefront-url/canonical.js.map +7 -0
- package/dist/server/storefront-url/contract.js +2 -2
- package/dist/server/storefront-url/contract.js.map +2 -2
- package/dist/server/storefront-url/params.js +35 -18
- package/dist/server/storefront-url/params.js.map +2 -2
- package/dist/server/storefront-url/parse-v1.js +15 -12
- package/dist/server/storefront-url/parse-v1.js.map +2 -2
- package/dist/server/storefront-url/parse-v2.js +17 -79
- package/dist/server/storefront-url/parse-v2.js.map +2 -2
- package/dist/server/storefront-url/public-id.js +8 -0
- package/dist/server/storefront-url/public-id.js.map +7 -0
- package/dist/server/storefront-url/redirect.js +20 -6
- package/dist/server/storefront-url/redirect.js.map +2 -2
- package/dist/server/storefront-url/sign-in.js +2 -1
- package/dist/server/storefront-url/sign-in.js.map +2 -2
- package/dist/server/storefront-url/types.js +1 -0
- package/dist/server/storefront-url/types.js.map +2 -2
- package/dist/server/storefront-url/url.js +34 -23
- package/dist/server/storefront-url/url.js.map +2 -2
- package/dist/site-config/types.js.map +1 -1
- package/dist/site-config/validate.js +32 -0
- package/dist/site-config/validate.js.map +2 -2
- package/dist/testing/index.d.ts +3 -3
- package/dist/transport/category-page.d.ts +2 -2
- package/dist/transport/category-page.js +6 -2
- package/dist/transport/category-page.js.map +2 -2
- package/dist/transport/presentation.d.ts +7 -0
- package/dist/transport/presentation.js +68 -0
- package/dist/transport/presentation.js.map +7 -0
- package/dist/transport/rest.js +15 -3
- package/dist/transport/rest.js.map +2 -2
- package/dist/transport/search.d.ts +3 -3
- package/dist/transport/search.js +6 -1
- package/dist/transport/search.js.map +2 -2
- package/dist/transport/selected-menu.d.ts +3 -3
- package/dist/transport/selected-menu.js +7 -2
- package/dist/transport/selected-menu.js.map +2 -2
- package/dist/transport/store.d.ts +1 -2
- package/dist/transport/store.js.map +1 -1
- package/dist/{types-CuDvfW9g.d.ts → types-B-iTMrVV.d.ts} +1 -1
- package/dist/url/index.d.ts +4 -1
- package/package.json +1 -1
|
@@ -20,41 +20,52 @@ var inputUrl = (input) => {
|
|
|
20
20
|
const value = typeof input === "string" ? input : input.url;
|
|
21
21
|
return new URL(value, FALLBACK_ORIGIN);
|
|
22
22
|
};
|
|
23
|
+
var isAttributionKey = (key) => /^utm_|^(ref|\w*c..?id|.?braid|li_fat_id)$/.test(key);
|
|
23
24
|
var queryRecord = (params, contract) => {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
const allowed = contract === "v2" ? STOREFRONT_QUERY_PARAMETERS : STOREFRONT_V1_QUERY_PARAMETERS;
|
|
26
|
+
return Object.fromEntries(
|
|
27
|
+
[...params].filter(
|
|
28
|
+
([key]) => allowed.includes(key) || isAttributionKey(key)
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
var STATE_FIELDS = {
|
|
33
|
+
menu_id: "menuId",
|
|
34
|
+
category_id: "categoryId",
|
|
35
|
+
menu_layout: "menuLayout",
|
|
36
|
+
modal_id: "modalId",
|
|
37
|
+
auth_modal_id: "authModalId",
|
|
38
|
+
payment_id: "paymentId",
|
|
39
|
+
lightbox: "lightbox",
|
|
40
|
+
catalogue_search: "catalogueSearch",
|
|
41
|
+
catalogue_categories: "catalogueCategories"
|
|
32
42
|
};
|
|
33
43
|
var pageState = (url, contract = "v2") => {
|
|
34
44
|
const query = queryRecord(url.searchParams, contract);
|
|
45
|
+
const state = { query };
|
|
46
|
+
for (const [key, field] of Object.entries(STATE_FIELDS)) {
|
|
47
|
+
const value = url.searchParams.get(key);
|
|
48
|
+
if (value !== null) {
|
|
49
|
+
state[field] = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
35
52
|
const pickup = url.searchParams.get("pickup");
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
...url.searchParams.has("auth_modal_id") ? { authModalId: url.searchParams.get("auth_modal_id") ?? "" } : {},
|
|
44
|
-
...url.searchParams.has("payment_id") ? { paymentId: url.searchParams.get("payment_id") ?? "" } : {},
|
|
45
|
-
...url.searchParams.has("lightbox") ? { lightbox: url.searchParams.get("lightbox") ?? "" } : {},
|
|
46
|
-
...url.searchParams.has("catalogue_search") ? { catalogueSearch: url.searchParams.get("catalogue_search") ?? "" } : {},
|
|
47
|
-
...url.searchParams.has("catalogue_categories") ? {
|
|
48
|
-
catalogueCategories: url.searchParams.get("catalogue_categories") ?? ""
|
|
49
|
-
} : {}
|
|
50
|
-
};
|
|
53
|
+
if (pickup === "true" || pickup === "false") {
|
|
54
|
+
state.mode = pickup === "true" ? "pickup" : "delivery";
|
|
55
|
+
}
|
|
56
|
+
if (state.categoryId === void 0 && contract === "v2" && url.hash.startsWith("#c-")) {
|
|
57
|
+
state.categoryId = decode(url.hash.slice(3));
|
|
58
|
+
}
|
|
59
|
+
return state;
|
|
51
60
|
};
|
|
52
61
|
export {
|
|
53
62
|
FALLBACK_ORIGIN,
|
|
54
63
|
ITEM_MODAL_PREFIX,
|
|
64
|
+
STATE_FIELDS,
|
|
55
65
|
decode,
|
|
56
66
|
encode,
|
|
57
67
|
inputUrl,
|
|
68
|
+
isAttributionKey,
|
|
58
69
|
pageState,
|
|
59
70
|
queryRecord
|
|
60
71
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/server/storefront-url/url.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n STOREFRONT_QUERY_PARAMETERS,\n STOREFRONT_V1_QUERY_PARAMETERS,\n type StorefrontPageState,\n type StorefrontUrlInput,\n} from \"./types\";\n\nexport const FALLBACK_ORIGIN = \"https://storefront.invalid\";\nexport const ITEM_MODAL_PREFIX = \"product_\";\n\nexport const decode = (value: string) => {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n};\n\nexport const encode = (value: string) => encodeURIComponent(value);\n\nexport const inputUrl = (input: StorefrontUrlInput) => {\n if (input instanceof URL) {\n return new URL(input.toString());\n }\n const value = typeof input === \"string\" ? input : input.url;\n return new URL(value, FALLBACK_ORIGIN);\n};\n\nexport const queryRecord = (params: URLSearchParams, contract: \"v1\" | \"v2\") => {\n const
|
|
5
|
-
"mappings": ";AAAA;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAEA,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAE1B,IAAM,SAAS,CAAC,UAAkB;AACvC,MAAI;AACF,WAAO,mBAAmB,KAAK;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,SAAS,CAAC,UAAkB,mBAAmB,KAAK;AAE1D,IAAM,WAAW,CAAC,UAA8B;AACrD,MAAI,iBAAiB,KAAK;AACxB,WAAO,IAAI,IAAI,MAAM,SAAS,CAAC;AAAA,EACjC;AACA,QAAM,QAAQ,OAAO,UAAU,WAAW,QAAQ,MAAM;AACxD,SAAO,IAAI,IAAI,OAAO,eAAe;AACvC;AAEO,IAAM,
|
|
4
|
+
"sourcesContent": ["import {\n STOREFRONT_QUERY_PARAMETERS,\n STOREFRONT_V1_QUERY_PARAMETERS,\n type StorefrontPageState,\n type StorefrontUrlInput,\n} from \"./types\";\n\nexport const FALLBACK_ORIGIN = \"https://storefront.invalid\";\nexport const ITEM_MODAL_PREFIX = \"product_\";\n\nexport const decode = (value: string) => {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n};\n\nexport const encode = (value: string) => encodeURIComponent(value);\n\nexport const inputUrl = (input: StorefrontUrlInput) => {\n if (input instanceof URL) {\n return new URL(input.toString());\n }\n const value = typeof input === \"string\" ? input : input.url;\n return new URL(value, FALLBACK_ORIGIN);\n};\n\nexport const isAttributionKey = (key: string) =>\n /^utm_|^(ref|\\w*c..?id|.?braid|li_fat_id)$/.test(key);\n\nexport const queryRecord = (params: URLSearchParams, contract: \"v1\" | \"v2\") => {\n const allowed: readonly string[] =\n contract === \"v2\"\n ? STOREFRONT_QUERY_PARAMETERS\n : STOREFRONT_V1_QUERY_PARAMETERS;\n return Object.fromEntries(\n [...params].filter(\n ([key]) => allowed.includes(key) || isAttributionKey(key),\n ),\n );\n};\n\nexport const STATE_FIELDS = {\n menu_id: \"menuId\",\n category_id: \"categoryId\",\n menu_layout: \"menuLayout\",\n modal_id: \"modalId\",\n auth_modal_id: \"authModalId\",\n payment_id: \"paymentId\",\n lightbox: \"lightbox\",\n catalogue_search: \"catalogueSearch\",\n catalogue_categories: \"catalogueCategories\",\n} as const;\n\nexport const pageState = (\n url: URL,\n contract: \"v1\" | \"v2\" = \"v2\",\n): StorefrontPageState => {\n const query = queryRecord(url.searchParams, contract);\n const state: StorefrontPageState = { query };\n for (const [key, field] of Object.entries(STATE_FIELDS)) {\n const value = url.searchParams.get(key);\n if (value !== null) {\n state[field] = value;\n }\n }\n const pickup = url.searchParams.get(\"pickup\");\n if (pickup === \"true\" || pickup === \"false\") {\n state.mode = pickup === \"true\" ? \"pickup\" : \"delivery\";\n }\n if (\n state.categoryId === undefined &&\n contract === \"v2\" &&\n url.hash.startsWith(\"#c-\")\n ) {\n state.categoryId = decode(url.hash.slice(3));\n }\n return state;\n};\n"],
|
|
5
|
+
"mappings": ";AAAA;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAEA,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAE1B,IAAM,SAAS,CAAC,UAAkB;AACvC,MAAI;AACF,WAAO,mBAAmB,KAAK;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,SAAS,CAAC,UAAkB,mBAAmB,KAAK;AAE1D,IAAM,WAAW,CAAC,UAA8B;AACrD,MAAI,iBAAiB,KAAK;AACxB,WAAO,IAAI,IAAI,MAAM,SAAS,CAAC;AAAA,EACjC;AACA,QAAM,QAAQ,OAAO,UAAU,WAAW,QAAQ,MAAM;AACxD,SAAO,IAAI,IAAI,OAAO,eAAe;AACvC;AAEO,IAAM,mBAAmB,CAAC,QAC/B,4CAA4C,KAAK,GAAG;AAE/C,IAAM,cAAc,CAAC,QAAyB,aAA0B;AAC7E,QAAM,UACJ,aAAa,OACT,8BACA;AACN,SAAO,OAAO;AAAA,IACZ,CAAC,GAAG,MAAM,EAAE;AAAA,MACV,CAAC,CAAC,GAAG,MAAM,QAAQ,SAAS,GAAG,KAAK,iBAAiB,GAAG;AAAA,IAC1D;AAAA,EACF;AACF;AAEO,IAAM,eAAe;AAAA,EAC1B,SAAS;AAAA,EACT,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,sBAAsB;AACxB;AAEO,IAAM,YAAY,CACvB,KACA,WAAwB,SACA;AACxB,QAAM,QAAQ,YAAY,IAAI,cAAc,QAAQ;AACpD,QAAM,QAA6B,EAAE,MAAM;AAC3C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACvD,UAAM,QAAQ,IAAI,aAAa,IAAI,GAAG;AACtC,QAAI,UAAU,MAAM;AAClB,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AACA,QAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,MAAI,WAAW,UAAU,WAAW,SAAS;AAC3C,UAAM,OAAO,WAAW,SAAS,WAAW;AAAA,EAC9C;AACA,MACE,MAAM,eAAe,UACrB,aAAa,QACb,IAAI,KAAK,WAAW,KAAK,GACzB;AACA,UAAM,aAAa,OAAO,IAAI,KAAK,MAAM,CAAC,CAAC;AAAA,EAC7C;AACA,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/site-config/types.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Default site budgets: 200 KB gzipped JavaScript, 50 KB gzipped CSS and 2500 ms LCP.\n */\nexport const DEFAULT_BUDGETS = {\n jsKbGz: 200,\n cssKbGz: 50,\n lcpMs: 2500,\n} as const;\n\n/**\n * Package names and patterns allowed globally without a site-specific allowlist entry.\n */\nexport const GLOBAL_PACKAGE_ALLOWLIST = [\n \"react\",\n \"react-dom\",\n \"react-router\",\n \"@react-router/*\",\n \"@zappie/*\",\n \"tailwindcss\",\n \"@tailwindcss/*\",\n \"clsx\",\n \"tailwind-merge\",\n \"class-variance-authority\",\n \"lucide-react\",\n \"date-fns\",\n \"embla-carousel-react\",\n \"framer-motion/motion\",\n \"zod\",\n \"@radix-ui/*\",\n \"sonner\",\n \"vaul\",\n] as const;\n\n/**\n * The store, theme and optional build policies you export from zappie.config.ts.\n */\nexport type ZappieSiteConfig = {\n store: string;\n branches?: string[];\n theme: string;\n prerender?: string[];\n menu?: { hiddenCategories?: string[] };\n packages?: { allow?: string[] };\n outbound?: { allow?: string[] };\n /** Each budget left out uses DEFAULT_BUDGETS. */\n budgets?: {\n jsKbGz?: number;\n cssKbGz?: number;\n lcpMs?: number;\n override?: { reason: string };\n };\n analytics?: { forward?: { ga4?: string; metaPixel?: string } };\n};\n\n/**\n * A configuration diagnostic with its field path, stable code, message and severity.\n */\nexport type ConfigIssue = {\n path: string;\n code:\n | \"invalid_type\"\n | \"missing_required\"\n | \"unknown_key\"\n | \"invalid_format\"\n | \"duplicate\"\n | \"redundant_allowlist\"\n | \"budget_override\";\n message: string;\n severity: \"error\" | \"warning\";\n};\n\n/**\n * Configuration validation results. Warnings alone do not make valid false.\n */\nexport type ConfigValidation = { valid: boolean; issues: ConfigIssue[] };\n"],
|
|
4
|
+
"sourcesContent": ["/**\n * Default site budgets: 200 KB gzipped JavaScript, 50 KB gzipped CSS and 2500 ms LCP.\n */\nexport const DEFAULT_BUDGETS = {\n jsKbGz: 200,\n cssKbGz: 50,\n lcpMs: 2500,\n} as const;\n\n/**\n * Package names and patterns allowed globally without a site-specific allowlist entry.\n */\nexport const GLOBAL_PACKAGE_ALLOWLIST = [\n \"react\",\n \"react-dom\",\n \"react-router\",\n \"@react-router/*\",\n \"@zappie/*\",\n \"tailwindcss\",\n \"@tailwindcss/*\",\n \"clsx\",\n \"tailwind-merge\",\n \"class-variance-authority\",\n \"lucide-react\",\n \"date-fns\",\n \"embla-carousel-react\",\n \"framer-motion/motion\",\n \"zod\",\n \"@radix-ui/*\",\n \"sonner\",\n \"vaul\",\n] as const;\n\n/**\n * The store, theme and optional build policies you export from zappie.config.ts.\n */\nexport type ZappieSiteConfig = {\n store: string;\n branches?: string[];\n theme: string;\n prerender?: string[];\n menu?: { hiddenCategories?: string[] };\n packages?: { allow?: string[] };\n outbound?: { allow?: string[] };\n /** Each budget left out uses DEFAULT_BUDGETS. */\n budgets?: {\n jsKbGz?: number;\n cssKbGz?: number;\n lcpMs?: number;\n override?: { reason: string };\n };\n /** Records explained exceptions to storefront readiness checks. */\n readiness?: {\n /** Lets this site skip the initial route discovery requirement. */\n routeDiscovery?: {\n /** Explains why this site does not use initial route discovery. */\n optOut: {\n /** States the constraint that prevents initial route discovery. */\n reason: string;\n };\n };\n };\n analytics?: { forward?: { ga4?: string; metaPixel?: string } };\n};\n\n/**\n * A configuration diagnostic with its field path, stable code, message and severity.\n */\nexport type ConfigIssue = {\n path: string;\n code:\n | \"invalid_type\"\n | \"missing_required\"\n | \"unknown_key\"\n | \"invalid_format\"\n | \"duplicate\"\n | \"redundant_allowlist\"\n | \"budget_override\";\n message: string;\n severity: \"error\" | \"warning\";\n};\n\n/**\n * Configuration validation results. Warnings alone do not make valid false.\n */\nexport type ConfigValidation = { valid: boolean; issues: ConfigIssue[] };\n"],
|
|
5
5
|
"mappings": ";AAGO,IAAM,kBAAkB;AAAA,EAC7B,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,OAAO;AACT;AAKO,IAAM,2BAA2B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -17,6 +17,7 @@ var rootKeys = [
|
|
|
17
17
|
"packages",
|
|
18
18
|
"outbound",
|
|
19
19
|
"budgets",
|
|
20
|
+
"readiness",
|
|
20
21
|
"analytics"
|
|
21
22
|
];
|
|
22
23
|
function validateConfig(input) {
|
|
@@ -80,6 +81,37 @@ function validateConfig(input) {
|
|
|
80
81
|
});
|
|
81
82
|
});
|
|
82
83
|
budgets(input.budgets, issue, error);
|
|
84
|
+
nested(
|
|
85
|
+
input.readiness,
|
|
86
|
+
"readiness",
|
|
87
|
+
["routeDiscovery"],
|
|
88
|
+
issue,
|
|
89
|
+
(readiness) => {
|
|
90
|
+
nested(
|
|
91
|
+
readiness.routeDiscovery,
|
|
92
|
+
"readiness.routeDiscovery",
|
|
93
|
+
["optOut"],
|
|
94
|
+
issue,
|
|
95
|
+
(routeDiscovery) => {
|
|
96
|
+
nested(
|
|
97
|
+
routeDiscovery.optOut,
|
|
98
|
+
"readiness.routeDiscovery.optOut",
|
|
99
|
+
["reason"],
|
|
100
|
+
issue,
|
|
101
|
+
(optOut) => {
|
|
102
|
+
if (typeof optOut.reason !== "string" || !optOut.reason.trim()) {
|
|
103
|
+
error(
|
|
104
|
+
"readiness.routeDiscovery.optOut.reason",
|
|
105
|
+
"invalid_format",
|
|
106
|
+
"Expected a non-blank reason. Explain why the site disables initial route discovery."
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
);
|
|
83
115
|
analytics(input.analytics, issue, error);
|
|
84
116
|
return {
|
|
85
117
|
valid: !issues.some((entry) => entry.severity === "error"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/site-config/validate.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n globallyAllowed,\n hostname,\n nonblank,\n packageName,\n record,\n unknownKeys,\n} from \"./helpers\";\nimport { analytics, budgets, nested } from \"./sections\";\nimport type { ConfigIssue, ConfigValidation } from \"./types\";\n\nconst rootKeys = [\n \"store\",\n \"branches\",\n \"theme\",\n \"prerender\",\n \"menu\",\n \"packages\",\n \"outbound\",\n \"budgets\",\n \"analytics\",\n] as const;\n\n/**\n * Validate a site configuration and collect errors and warnings without changing it.\n * Checks required fields, unknown keys, allowlists, budgets and analytics settings.\n *\n * @param input - The configuration value to inspect.\n * @returns Diagnostics and a valid flag that is true when there are no errors.\n */\nexport function validateConfig(input: unknown): ConfigValidation {\n const issues: ConfigIssue[] = [];\n const issue = (value: ConfigIssue) => issues.push(value);\n const error = (path: string, code: ConfigIssue[\"code\"], message: string) =>\n issue({ path, code, message, severity: \"error\" });\n if (!record(input)) {\n return {\n valid: false,\n issues: [\n {\n path: \"$\",\n code: \"invalid_type\",\n message:\n \"Expected a configuration object. Export an object from zappie.config.ts.\",\n severity: \"error\",\n },\n ],\n };\n }\n unknownKeys(input, rootKeys, \"\", issue);\n requiredSlug(input.store, \"store\", error);\n theme(input.theme, error);\n stringList(input.branches, \"branches\", error, {\n nonempty: true,\n unique: true,\n slug: true,\n });\n paths(input.prerender, error);\n nested(input.menu, \"menu\", [\"hiddenCategories\"], issue, (value) => {\n stringList(value.hiddenCategories, \"menu.hiddenCategories\", error);\n });\n nested(input.packages, \"packages\", [\"allow\"], issue, (value) => {\n const allow = stringList(value.allow, \"packages.allow\", error);\n allow?.forEach((name, index) => {\n if (globallyAllowed(name)) {\n issue({\n path: `packages.allow[${index}]`,\n code: \"redundant_allowlist\",\n message: `${name} is already globally allowed. Remove it from packages.allow.`,\n severity: \"warning\",\n });\n } else if (!packageName(name)) {\n error(\n `packages.allow[${index}]`,\n \"invalid_format\",\n \"Expected a lowercase npm package name. Use a package name such as lucide-react or @scope/name.\",\n );\n }\n });\n });\n nested(input.outbound, \"outbound\", [\"allow\"], issue, (value) => {\n const allow = stringList(value.allow, \"outbound.allow\", error);\n allow?.forEach((host, index) => {\n if (!hostname(host)) {\n error(\n `outbound.allow[${index}]`,\n \"invalid_format\",\n \"Expected a hostname or leading *. subdomain pattern without a scheme, path, port or IP. Use a value such as api.example.com.\",\n );\n }\n });\n });\n budgets(input.budgets, issue, error);\n analytics(input.analytics, issue, error);\n return {\n valid: !issues.some((entry) => entry.severity === \"error\"),\n issues,\n };\n}\n\ntype AddError = (\n path: string,\n code: ConfigIssue[\"code\"],\n message: string,\n) => void;\n\nfunction requiredSlug(value: unknown, path: string, error: AddError) {\n if (!nonblank(value)) {\n error(\n path,\n value === undefined ? \"missing_required\" : \"invalid_type\",\n `Expected a non-empty storefront slug. Set ${path} to the slug used by createZappie().`,\n );\n }\n}\n\nfunction theme(value: unknown, error: AddError) {\n if (typeof value !== \"string\") {\n error(\n \"theme\",\n value === undefined ? \"missing_required\" : \"invalid_type\",\n \"Expected a relative .json path. Set theme to a value such as ./theme.json.\",\n );\n } else if (\n !/\\.json$/.test(value) ||\n /^(?:[a-z][a-z\\d+.-]*:|\\/|\\\\)/i.test(value) ||\n value.includes(\"\\\\\")\n ) {\n error(\n \"theme\",\n \"invalid_format\",\n \"Expected a relative .json path. Use a value such as ./theme.json.\",\n );\n }\n}\n\nfunction stringList(\n value: unknown,\n path: string,\n error: AddError,\n options: { nonempty?: boolean; unique?: boolean; slug?: boolean } = {},\n) {\n if (value === undefined) {\n return undefined;\n }\n if (\n !Array.isArray(value) ||\n value.some((entry) => typeof entry !== \"string\")\n ) {\n error(\n path,\n \"invalid_type\",\n `Expected an array of strings. Set ${path} to string values.`,\n );\n return undefined;\n }\n if (options.nonempty && value.length === 0) {\n error(\n path,\n \"invalid_format\",\n `Expected at least one value. Add a value to ${path} or remove the field.`,\n );\n }\n value.forEach((entry, index) => {\n if (options.slug && !nonblank(entry)) {\n error(\n `${path}[${index}]`,\n \"invalid_format\",\n \"Expected a non-empty branch slug. Remove the empty value or use a branch slug.\",\n );\n }\n });\n if (options.unique && new Set(value).size !== value.length) {\n error(\n path,\n \"duplicate\",\n `Expected unique values. Remove duplicates from ${path}.`,\n );\n }\n return value;\n}\n\nfunction paths(value: unknown, error: AddError) {\n const values = stringList(value, \"prerender\", error, { unique: true });\n values?.forEach((path, index) => {\n if (!path.startsWith(\"/\")) {\n error(\n `prerender[${index}]`,\n \"invalid_format\",\n \"Expected a route starting with /. Prefix the route with /.\",\n );\n }\n });\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n globallyAllowed,\n hostname,\n nonblank,\n packageName,\n record,\n unknownKeys,\n} from \"./helpers\";\nimport { analytics, budgets, nested } from \"./sections\";\nimport type { ConfigIssue, ConfigValidation } from \"./types\";\n\nconst rootKeys = [\n \"store\",\n \"branches\",\n \"theme\",\n \"prerender\",\n \"menu\",\n \"packages\",\n \"outbound\",\n \"budgets\",\n \"readiness\",\n \"analytics\",\n] as const;\n\n/**\n * Validate a site configuration and collect errors and warnings without changing it.\n * Checks required fields, unknown keys, allowlists, budgets and analytics settings.\n *\n * @param input - The configuration value to inspect.\n * @returns Diagnostics and a valid flag that is true when there are no errors.\n */\nexport function validateConfig(input: unknown): ConfigValidation {\n const issues: ConfigIssue[] = [];\n const issue = (value: ConfigIssue) => issues.push(value);\n const error = (path: string, code: ConfigIssue[\"code\"], message: string) =>\n issue({ path, code, message, severity: \"error\" });\n if (!record(input)) {\n return {\n valid: false,\n issues: [\n {\n path: \"$\",\n code: \"invalid_type\",\n message:\n \"Expected a configuration object. Export an object from zappie.config.ts.\",\n severity: \"error\",\n },\n ],\n };\n }\n unknownKeys(input, rootKeys, \"\", issue);\n requiredSlug(input.store, \"store\", error);\n theme(input.theme, error);\n stringList(input.branches, \"branches\", error, {\n nonempty: true,\n unique: true,\n slug: true,\n });\n paths(input.prerender, error);\n nested(input.menu, \"menu\", [\"hiddenCategories\"], issue, (value) => {\n stringList(value.hiddenCategories, \"menu.hiddenCategories\", error);\n });\n nested(input.packages, \"packages\", [\"allow\"], issue, (value) => {\n const allow = stringList(value.allow, \"packages.allow\", error);\n allow?.forEach((name, index) => {\n if (globallyAllowed(name)) {\n issue({\n path: `packages.allow[${index}]`,\n code: \"redundant_allowlist\",\n message: `${name} is already globally allowed. Remove it from packages.allow.`,\n severity: \"warning\",\n });\n } else if (!packageName(name)) {\n error(\n `packages.allow[${index}]`,\n \"invalid_format\",\n \"Expected a lowercase npm package name. Use a package name such as lucide-react or @scope/name.\",\n );\n }\n });\n });\n nested(input.outbound, \"outbound\", [\"allow\"], issue, (value) => {\n const allow = stringList(value.allow, \"outbound.allow\", error);\n allow?.forEach((host, index) => {\n if (!hostname(host)) {\n error(\n `outbound.allow[${index}]`,\n \"invalid_format\",\n \"Expected a hostname or leading *. subdomain pattern without a scheme, path, port or IP. Use a value such as api.example.com.\",\n );\n }\n });\n });\n budgets(input.budgets, issue, error);\n nested(\n input.readiness,\n \"readiness\",\n [\"routeDiscovery\"],\n issue,\n (readiness) => {\n nested(\n readiness.routeDiscovery,\n \"readiness.routeDiscovery\",\n [\"optOut\"],\n issue,\n (routeDiscovery) => {\n nested(\n routeDiscovery.optOut,\n \"readiness.routeDiscovery.optOut\",\n [\"reason\"],\n issue,\n (optOut) => {\n if (typeof optOut.reason !== \"string\" || !optOut.reason.trim()) {\n error(\n \"readiness.routeDiscovery.optOut.reason\",\n \"invalid_format\",\n \"Expected a non-blank reason. Explain why the site disables initial route discovery.\",\n );\n }\n },\n );\n },\n );\n },\n );\n analytics(input.analytics, issue, error);\n return {\n valid: !issues.some((entry) => entry.severity === \"error\"),\n issues,\n };\n}\n\ntype AddError = (\n path: string,\n code: ConfigIssue[\"code\"],\n message: string,\n) => void;\n\nfunction requiredSlug(value: unknown, path: string, error: AddError) {\n if (!nonblank(value)) {\n error(\n path,\n value === undefined ? \"missing_required\" : \"invalid_type\",\n `Expected a non-empty storefront slug. Set ${path} to the slug used by createZappie().`,\n );\n }\n}\n\nfunction theme(value: unknown, error: AddError) {\n if (typeof value !== \"string\") {\n error(\n \"theme\",\n value === undefined ? \"missing_required\" : \"invalid_type\",\n \"Expected a relative .json path. Set theme to a value such as ./theme.json.\",\n );\n } else if (\n !/\\.json$/.test(value) ||\n /^(?:[a-z][a-z\\d+.-]*:|\\/|\\\\)/i.test(value) ||\n value.includes(\"\\\\\")\n ) {\n error(\n \"theme\",\n \"invalid_format\",\n \"Expected a relative .json path. Use a value such as ./theme.json.\",\n );\n }\n}\n\nfunction stringList(\n value: unknown,\n path: string,\n error: AddError,\n options: { nonempty?: boolean; unique?: boolean; slug?: boolean } = {},\n) {\n if (value === undefined) {\n return undefined;\n }\n if (\n !Array.isArray(value) ||\n value.some((entry) => typeof entry !== \"string\")\n ) {\n error(\n path,\n \"invalid_type\",\n `Expected an array of strings. Set ${path} to string values.`,\n );\n return undefined;\n }\n if (options.nonempty && value.length === 0) {\n error(\n path,\n \"invalid_format\",\n `Expected at least one value. Add a value to ${path} or remove the field.`,\n );\n }\n value.forEach((entry, index) => {\n if (options.slug && !nonblank(entry)) {\n error(\n `${path}[${index}]`,\n \"invalid_format\",\n \"Expected a non-empty branch slug. Remove the empty value or use a branch slug.\",\n );\n }\n });\n if (options.unique && new Set(value).size !== value.length) {\n error(\n path,\n \"duplicate\",\n `Expected unique values. Remove duplicates from ${path}.`,\n );\n }\n return value;\n}\n\nfunction paths(value: unknown, error: AddError) {\n const values = stringList(value, \"prerender\", error, { unique: true });\n values?.forEach((path, index) => {\n if (!path.startsWith(\"/\")) {\n error(\n `prerender[${index}]`,\n \"invalid_format\",\n \"Expected a route starting with /. Prefix the route with /.\",\n );\n }\n });\n}\n"],
|
|
5
|
+
"mappings": ";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW,SAAS,cAAc;AAG3C,IAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,SAAS,eAAe,OAAkC;AAC/D,QAAM,SAAwB,CAAC;AAC/B,QAAM,QAAQ,CAAC,UAAuB,OAAO,KAAK,KAAK;AACvD,QAAM,QAAQ,CAAC,MAAc,MAA2B,YACtD,MAAM,EAAE,MAAM,MAAM,SAAS,UAAU,QAAQ,CAAC;AAClD,MAAI,CAAC,OAAO,KAAK,GAAG;AAClB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SACE;AAAA,UACF,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,cAAY,OAAO,UAAU,IAAI,KAAK;AACtC,eAAa,MAAM,OAAO,SAAS,KAAK;AACxC,QAAM,MAAM,OAAO,KAAK;AACxB,aAAW,MAAM,UAAU,YAAY,OAAO;AAAA,IAC5C,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM;AAAA,EACR,CAAC;AACD,QAAM,MAAM,WAAW,KAAK;AAC5B,SAAO,MAAM,MAAM,QAAQ,CAAC,kBAAkB,GAAG,OAAO,CAAC,UAAU;AACjE,eAAW,MAAM,kBAAkB,yBAAyB,KAAK;AAAA,EACnE,CAAC;AACD,SAAO,MAAM,UAAU,YAAY,CAAC,OAAO,GAAG,OAAO,CAAC,UAAU;AAC9D,UAAM,QAAQ,WAAW,MAAM,OAAO,kBAAkB,KAAK;AAC7D,WAAO,QAAQ,CAAC,MAAM,UAAU;AAC9B,UAAI,gBAAgB,IAAI,GAAG;AACzB,cAAM;AAAA,UACJ,MAAM,kBAAkB,KAAK;AAAA,UAC7B,MAAM;AAAA,UACN,SAAS,GAAG,IAAI;AAAA,UAChB,UAAU;AAAA,QACZ,CAAC;AAAA,MACH,WAAW,CAAC,YAAY,IAAI,GAAG;AAC7B;AAAA,UACE,kBAAkB,KAAK;AAAA,UACvB;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACD,SAAO,MAAM,UAAU,YAAY,CAAC,OAAO,GAAG,OAAO,CAAC,UAAU;AAC9D,UAAM,QAAQ,WAAW,MAAM,OAAO,kBAAkB,KAAK;AAC7D,WAAO,QAAQ,CAAC,MAAM,UAAU;AAC9B,UAAI,CAAC,SAAS,IAAI,GAAG;AACnB;AAAA,UACE,kBAAkB,KAAK;AAAA,UACvB;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACD,UAAQ,MAAM,SAAS,OAAO,KAAK;AACnC;AAAA,IACE,MAAM;AAAA,IACN;AAAA,IACA,CAAC,gBAAgB;AAAA,IACjB;AAAA,IACA,CAAC,cAAc;AACb;AAAA,QACE,UAAU;AAAA,QACV;AAAA,QACA,CAAC,QAAQ;AAAA,QACT;AAAA,QACA,CAAC,mBAAmB;AAClB;AAAA,YACE,eAAe;AAAA,YACf;AAAA,YACA,CAAC,QAAQ;AAAA,YACT;AAAA,YACA,CAAC,WAAW;AACV,kBAAI,OAAO,OAAO,WAAW,YAAY,CAAC,OAAO,OAAO,KAAK,GAAG;AAC9D;AAAA,kBACE;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,YAAU,MAAM,WAAW,OAAO,KAAK;AACvC,SAAO;AAAA,IACL,OAAO,CAAC,OAAO,KAAK,CAAC,UAAU,MAAM,aAAa,OAAO;AAAA,IACzD;AAAA,EACF;AACF;AAQA,SAAS,aAAa,OAAgB,MAAc,OAAiB;AACnE,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB;AAAA,MACE;AAAA,MACA,UAAU,SAAY,qBAAqB;AAAA,MAC3C,6CAA6C,IAAI;AAAA,IACnD;AAAA,EACF;AACF;AAEA,SAAS,MAAM,OAAgB,OAAiB;AAC9C,MAAI,OAAO,UAAU,UAAU;AAC7B;AAAA,MACE;AAAA,MACA,UAAU,SAAY,qBAAqB;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,WACE,CAAC,UAAU,KAAK,KAAK,KACrB,gCAAgC,KAAK,KAAK,KAC1C,MAAM,SAAS,IAAI,GACnB;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,WACP,OACA,MACA,OACA,UAAoE,CAAC,GACrE;AACA,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,MACE,CAAC,MAAM,QAAQ,KAAK,KACpB,MAAM,KAAK,CAAC,UAAU,OAAO,UAAU,QAAQ,GAC/C;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA,qCAAqC,IAAI;AAAA,IAC3C;AACA,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,YAAY,MAAM,WAAW,GAAG;AAC1C;AAAA,MACE;AAAA,MACA;AAAA,MACA,+CAA+C,IAAI;AAAA,IACrD;AAAA,EACF;AACA,QAAM,QAAQ,CAAC,OAAO,UAAU;AAC9B,QAAI,QAAQ,QAAQ,CAAC,SAAS,KAAK,GAAG;AACpC;AAAA,QACE,GAAG,IAAI,IAAI,KAAK;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,MAAI,QAAQ,UAAU,IAAI,IAAI,KAAK,EAAE,SAAS,MAAM,QAAQ;AAC1D;AAAA,MACE;AAAA,MACA;AAAA,MACA,kDAAkD,IAAI;AAAA,IACxD;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,MAAM,OAAgB,OAAiB;AAC9C,QAAM,SAAS,WAAW,OAAO,aAAa,OAAO,EAAE,QAAQ,KAAK,CAAC;AACrE,UAAQ,QAAQ,CAAC,MAAM,UAAU;AAC/B,QAAI,CAAC,KAAK,WAAW,GAAG,GAAG;AACzB;AAAA,QACE,aAAa,KAAK;AAAA,QAClB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { T as Transport, e as ZappieErrorCode, S as StorageLike, c as StoreResource, M as MenuResource, d as ZappieEvents, C as Cache } from '../client-
|
|
2
|
-
import { S as Store, a as Menu, F as Formatters } from '../models-
|
|
1
|
+
import { T as Transport, e as ZappieErrorCode, S as StorageLike, c as StoreResource, M as MenuResource, d as ZappieEvents, C as Cache } from '../client-iVMHfAFn.js';
|
|
2
|
+
import { S as Store, a as Menu, F as Formatters } from '../models-D__QbqEd.js';
|
|
3
3
|
export { VERSION } from '../index.js';
|
|
4
|
-
import { d as CartModule, b as CartLineInput } from '../types-
|
|
4
|
+
import { d as CartModule, b as CartLineInput } from '../types-B-iTMrVV.js';
|
|
5
5
|
|
|
6
6
|
/** Store and branch menus supplied to the deterministic mock transport. */
|
|
7
7
|
type MockFixtures = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as Menu, C as CategoryPage } from '../models-
|
|
1
|
+
import { a as Menu, C as CategoryPage } from '../models-D__QbqEd.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Validates and maps one category page. Only progressive catalogues read
|
|
@@ -12,6 +12,6 @@ declare function categoryPage(raw: Record<string, unknown>, ctx: {
|
|
|
12
12
|
menuId: string;
|
|
13
13
|
categoryId: string;
|
|
14
14
|
cursor?: string;
|
|
15
|
-
}, mapMenu: (value: unknown, branchId: string) => Menu, invalid: () => Error): CategoryPage
|
|
15
|
+
}, mapMenu: (value: unknown, branchId: string) => Menu, invalid: () => Error): Promise<CategoryPage>;
|
|
16
16
|
|
|
17
17
|
export { categoryPage };
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// src/transport/category-page.ts
|
|
2
|
-
function categoryPage(raw, ctx, mapMenu, invalid) {
|
|
3
|
-
const menu =
|
|
2
|
+
async function categoryPage(raw, ctx, mapMenu, invalid) {
|
|
3
|
+
const menu = (await import("./presentation.js")).presentMenu(
|
|
4
|
+
mapMenu(raw, ctx.branchId),
|
|
5
|
+
raw,
|
|
6
|
+
invalid
|
|
7
|
+
);
|
|
4
8
|
if (raw.next_cursor != null && (typeof raw.next_cursor !== "string" || !raw.next_cursor || raw.next_cursor === ctx.cursor) || menu.categories.some((c) => c.id !== ctx.categoryId) || Object.keys(menu.items).some(
|
|
5
9
|
(id) => !menu.categories.some((c) => c.itemIds.includes(id))
|
|
6
10
|
) || !menu.menus?.some(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/transport/category-page.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CategoryPage, Menu } from \"../models\";\n\n/**\n * Validates and maps one category page. Only progressive catalogues read\n * pages, so this loads on the first `menu.page()` call and stays out of the\n * core bundle, like the quote client (PRD 03 \u00A74). The mapper and error come\n * in as arguments: importing them would split the core's shared code into a\n * separate chunk, which costs the core more than this module saves.\n */\nexport function categoryPage(\n raw: Record<string, unknown>,\n ctx: {\n branchId: string;\n menuId: string;\n categoryId: string;\n cursor?: string;\n },\n mapMenu: (value: unknown, branchId: string) => Menu,\n invalid: () => Error,\n): CategoryPage {\n const menu = mapMenu(raw, ctx.branchId);\n if (\n (raw.next_cursor != null &&\n (typeof raw.next_cursor !== \"string\" ||\n !raw.next_cursor ||\n raw.next_cursor === ctx.cursor)) ||\n menu.categories.some((c) => c.id !== ctx.categoryId) ||\n Object.keys(menu.items).some(\n (id) => !menu.categories.some((c) => c.itemIds.includes(id)),\n ) ||\n !menu.menus?.some(\n (m) => m.id === ctx.menuId && m.categoryIds.includes(ctx.categoryId),\n )\n ) {\n throw invalid();\n }\n return {\n menu: { ...menu, completeness: \"partial\" },\n menuId: ctx.menuId,\n categoryId: ctx.categoryId,\n ...(typeof raw.next_cursor === \"string\" && raw.next_cursor\n ? { nextCursor: raw.next_cursor }\n : {}),\n };\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import type { CategoryPage, Menu } from \"../models\";\n\n/**\n * Validates and maps one category page. Only progressive catalogues read\n * pages, so this loads on the first `menu.page()` call and stays out of the\n * core bundle, like the quote client (PRD 03 \u00A74). The mapper and error come\n * in as arguments: importing them would split the core's shared code into a\n * separate chunk, which costs the core more than this module saves.\n */\nexport async function categoryPage(\n raw: Record<string, unknown>,\n ctx: {\n branchId: string;\n menuId: string;\n categoryId: string;\n cursor?: string;\n },\n mapMenu: (value: unknown, branchId: string) => Menu,\n invalid: () => Error,\n): Promise<CategoryPage> {\n const menu = (await import(\"./presentation\")).presentMenu(\n mapMenu(raw, ctx.branchId),\n raw,\n invalid,\n );\n if (\n (raw.next_cursor != null &&\n (typeof raw.next_cursor !== \"string\" ||\n !raw.next_cursor ||\n raw.next_cursor === ctx.cursor)) ||\n menu.categories.some((c) => c.id !== ctx.categoryId) ||\n Object.keys(menu.items).some(\n (id) => !menu.categories.some((c) => c.itemIds.includes(id)),\n ) ||\n !menu.menus?.some(\n (m) => m.id === ctx.menuId && m.categoryIds.includes(ctx.categoryId),\n )\n ) {\n throw invalid();\n }\n return {\n menu: { ...menu, completeness: \"partial\" },\n menuId: ctx.menuId,\n categoryId: ctx.categoryId,\n ...(typeof raw.next_cursor === \"string\" && raw.next_cursor\n ? { nextCursor: raw.next_cursor }\n : {}),\n };\n}\n"],
|
|
5
|
+
"mappings": ";AASA,eAAsB,aACpB,KACA,KAMA,SACA,SACuB;AACvB,QAAM,QAAQ,MAAM,OAAO,mBAAgB,GAAG;AAAA,IAC5C,QAAQ,KAAK,IAAI,QAAQ;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AACA,MACG,IAAI,eAAe,SACjB,OAAO,IAAI,gBAAgB,YAC1B,CAAC,IAAI,eACL,IAAI,gBAAgB,IAAI,WAC5B,KAAK,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,UAAU,KACnD,OAAO,KAAK,KAAK,KAAK,EAAE;AAAA,IACtB,CAAC,OAAO,CAAC,KAAK,WAAW,KAAK,CAAC,MAAM,EAAE,QAAQ,SAAS,EAAE,CAAC;AAAA,EAC7D,KACA,CAAC,KAAK,OAAO;AAAA,IACX,CAAC,MAAM,EAAE,OAAO,IAAI,UAAU,EAAE,YAAY,SAAS,IAAI,UAAU;AAAA,EACrE,GACA;AACA,UAAM,QAAQ;AAAA,EAChB;AACA,SAAO;AAAA,IACL,MAAM,EAAE,GAAG,MAAM,cAAc,UAAU;AAAA,IACzC,QAAQ,IAAI;AAAA,IACZ,YAAY,IAAI;AAAA,IAChB,GAAI,OAAO,IAAI,gBAAgB,YAAY,IAAI,cAC3C,EAAE,YAAY,IAAI,YAAY,IAC9B,CAAC;AAAA,EACP;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { a as Menu, S as Store } from '../models-D__QbqEd.js';
|
|
2
|
+
|
|
3
|
+
type Invalid = () => Error;
|
|
4
|
+
declare function presentStore(store: Store, value: unknown, invalid: Invalid): Store;
|
|
5
|
+
declare function presentMenu(menu: Menu, value: unknown, invalid: Invalid): Menu;
|
|
6
|
+
|
|
7
|
+
export { presentMenu, presentStore };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/transport/presentation.ts
|
|
2
|
+
var object = (value, invalid) => {
|
|
3
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
4
|
+
throw invalid();
|
|
5
|
+
}
|
|
6
|
+
return value;
|
|
7
|
+
};
|
|
8
|
+
var array = (value, invalid) => {
|
|
9
|
+
if (!Array.isArray(value)) {
|
|
10
|
+
throw invalid();
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
};
|
|
14
|
+
var string = (value, invalid) => {
|
|
15
|
+
if (typeof value !== "string") {
|
|
16
|
+
throw invalid();
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
};
|
|
20
|
+
function presentStore(store, value, invalid) {
|
|
21
|
+
const source = value;
|
|
22
|
+
source.branches.forEach((raw, index) => {
|
|
23
|
+
const branch = store.branches[index];
|
|
24
|
+
if (raw.order_ahead_days !== void 0) {
|
|
25
|
+
if (!Number.isSafeInteger(raw.order_ahead_days) || Number(raw.order_ahead_days) < 0) {
|
|
26
|
+
throw invalid();
|
|
27
|
+
}
|
|
28
|
+
branch.orderAheadDays = raw.order_ahead_days;
|
|
29
|
+
}
|
|
30
|
+
if (raw.promos !== void 0) {
|
|
31
|
+
branch.promos = array(raw.promos, invalid).map((value2) => {
|
|
32
|
+
const promo = object(value2, invalid);
|
|
33
|
+
return {
|
|
34
|
+
id: string(promo.id, invalid),
|
|
35
|
+
name: string(promo.name, invalid),
|
|
36
|
+
description: string(promo.description, invalid)
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return store;
|
|
42
|
+
}
|
|
43
|
+
function presentMenu(menu, value, invalid) {
|
|
44
|
+
value.menus.forEach((raw, index) => {
|
|
45
|
+
const section = menu.menus[index];
|
|
46
|
+
if (raw.layout !== void 0) {
|
|
47
|
+
if (!["LIST", "GRID", "CARD"].includes(raw.layout)) {
|
|
48
|
+
throw invalid();
|
|
49
|
+
}
|
|
50
|
+
section.layout = raw.layout;
|
|
51
|
+
}
|
|
52
|
+
if (raw.is_active !== void 0) {
|
|
53
|
+
if (typeof raw.is_active !== "boolean") {
|
|
54
|
+
throw invalid();
|
|
55
|
+
}
|
|
56
|
+
section.isActive = raw.is_active;
|
|
57
|
+
}
|
|
58
|
+
if (raw.info_banner_html !== void 0) {
|
|
59
|
+
section.infoBannerHtml = string(raw.info_banner_html, invalid);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return menu;
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
presentMenu,
|
|
66
|
+
presentStore
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=presentation.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/transport/presentation.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Menu, Store } from \"../models\";\n\ntype Invalid = () => Error;\ntype Wire = Record<string, unknown>;\n\nconst object = (value: unknown, invalid: Invalid) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw invalid();\n }\n return value as Wire;\n};\nconst array = (value: unknown, invalid: Invalid) => {\n if (!Array.isArray(value)) {\n throw invalid();\n }\n return value;\n};\nconst string = (value: unknown, invalid: Invalid) => {\n if (typeof value !== \"string\") {\n throw invalid();\n }\n return value;\n};\n\nexport function presentStore(store: Store, value: unknown, invalid: Invalid) {\n const source = value as Wire;\n (source.branches as Wire[]).forEach((raw, index) => {\n const branch = store.branches[index]!;\n if (raw.order_ahead_days !== undefined) {\n if (\n !Number.isSafeInteger(raw.order_ahead_days) ||\n Number(raw.order_ahead_days) < 0\n ) {\n throw invalid();\n }\n branch.orderAheadDays = raw.order_ahead_days as number;\n }\n if (raw.promos !== undefined) {\n branch.promos = array(raw.promos, invalid).map((value) => {\n const promo = object(value, invalid);\n return {\n id: string(promo.id, invalid),\n name: string(promo.name, invalid),\n description: string(promo.description, invalid),\n };\n });\n }\n });\n return store;\n}\n\nexport function presentMenu(menu: Menu, value: unknown, invalid: Invalid) {\n ((value as Wire).menus as Wire[]).forEach((raw, index) => {\n const section = menu.menus![index]!;\n if (raw.layout !== undefined) {\n if (![\"LIST\", \"GRID\", \"CARD\"].includes(raw.layout as string)) {\n throw invalid();\n }\n section.layout = raw.layout as NonNullable<typeof section.layout>;\n }\n if (raw.is_active !== undefined) {\n if (typeof raw.is_active !== \"boolean\") {\n throw invalid();\n }\n section.isActive = raw.is_active;\n }\n if (raw.info_banner_html !== undefined) {\n section.infoBannerHtml = string(raw.info_banner_html, invalid);\n }\n });\n return menu;\n}\n"],
|
|
5
|
+
"mappings": ";AAKA,IAAM,SAAS,CAAC,OAAgB,YAAqB;AACnD,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,UAAM,QAAQ;AAAA,EAChB;AACA,SAAO;AACT;AACA,IAAM,QAAQ,CAAC,OAAgB,YAAqB;AAClD,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,UAAM,QAAQ;AAAA,EAChB;AACA,SAAO;AACT;AACA,IAAM,SAAS,CAAC,OAAgB,YAAqB;AACnD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,QAAQ;AAAA,EAChB;AACA,SAAO;AACT;AAEO,SAAS,aAAa,OAAc,OAAgB,SAAkB;AAC3E,QAAM,SAAS;AACf,EAAC,OAAO,SAAoB,QAAQ,CAAC,KAAK,UAAU;AAClD,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,QAAI,IAAI,qBAAqB,QAAW;AACtC,UACE,CAAC,OAAO,cAAc,IAAI,gBAAgB,KAC1C,OAAO,IAAI,gBAAgB,IAAI,GAC/B;AACA,cAAM,QAAQ;AAAA,MAChB;AACA,aAAO,iBAAiB,IAAI;AAAA,IAC9B;AACA,QAAI,IAAI,WAAW,QAAW;AAC5B,aAAO,SAAS,MAAM,IAAI,QAAQ,OAAO,EAAE,IAAI,CAACA,WAAU;AACxD,cAAM,QAAQ,OAAOA,QAAO,OAAO;AACnC,eAAO;AAAA,UACL,IAAI,OAAO,MAAM,IAAI,OAAO;AAAA,UAC5B,MAAM,OAAO,MAAM,MAAM,OAAO;AAAA,UAChC,aAAa,OAAO,MAAM,aAAa,OAAO;AAAA,QAChD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAEO,SAAS,YAAY,MAAY,OAAgB,SAAkB;AACxE,EAAE,MAAe,MAAiB,QAAQ,CAAC,KAAK,UAAU;AACxD,UAAM,UAAU,KAAK,MAAO,KAAK;AACjC,QAAI,IAAI,WAAW,QAAW;AAC5B,UAAI,CAAC,CAAC,QAAQ,QAAQ,MAAM,EAAE,SAAS,IAAI,MAAgB,GAAG;AAC5D,cAAM,QAAQ;AAAA,MAChB;AACA,cAAQ,SAAS,IAAI;AAAA,IACvB;AACA,QAAI,IAAI,cAAc,QAAW;AAC/B,UAAI,OAAO,IAAI,cAAc,WAAW;AACtC,cAAM,QAAQ;AAAA,MAChB;AACA,cAAQ,WAAW,IAAI;AAAA,IACzB;AACA,QAAI,IAAI,qBAAqB,QAAW;AACtC,cAAQ,iBAAiB,OAAO,IAAI,kBAAkB,OAAO;AAAA,IAC/D;AAAA,EACF,CAAC;AACD,SAAO;AACT;",
|
|
6
|
+
"names": ["value"]
|
|
7
|
+
}
|
package/dist/transport/rest.js
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from "./mappers.js";
|
|
19
19
|
var MAX_RETRY_WAIT_MS = 5e3;
|
|
20
20
|
var wireFulfilment = (value) => value === "dineIn" ? "dine_in" : value;
|
|
21
|
+
var presentationError = () => new ZappieError("server_error", "Invalid storefront presentation");
|
|
21
22
|
var RestTransport = class {
|
|
22
23
|
constructor(opts = {}) {
|
|
23
24
|
const url = new URL(opts.baseUrl ?? "https://api.zappie.ai/storefront/v1");
|
|
@@ -124,11 +125,16 @@ var RestTransport = class {
|
|
|
124
125
|
{ cause }
|
|
125
126
|
);
|
|
126
127
|
});
|
|
128
|
+
const presentation = import("./presentation.js");
|
|
127
129
|
const response = this.request("/store", ctx).then(
|
|
128
130
|
(value) => this.json(value)
|
|
129
131
|
);
|
|
130
|
-
const [{ mapStore }, raw] = await Promise.all([
|
|
131
|
-
|
|
132
|
+
const [{ mapStore }, { presentStore }, raw] = await Promise.all([
|
|
133
|
+
mapper,
|
|
134
|
+
presentation,
|
|
135
|
+
response
|
|
136
|
+
]);
|
|
137
|
+
const store = mapStore(
|
|
132
138
|
raw,
|
|
133
139
|
record,
|
|
134
140
|
text,
|
|
@@ -141,8 +147,10 @@ var RestTransport = class {
|
|
|
141
147
|
isBoolean,
|
|
142
148
|
mapSeo
|
|
143
149
|
);
|
|
150
|
+
return presentStore(store, raw, presentationError);
|
|
144
151
|
}
|
|
145
152
|
async getMenu(ctx) {
|
|
153
|
+
const presentation = import("./presentation.js");
|
|
146
154
|
let cursor;
|
|
147
155
|
const seen = /* @__PURE__ */ new Set();
|
|
148
156
|
let output;
|
|
@@ -172,7 +180,11 @@ var RestTransport = class {
|
|
|
172
180
|
};
|
|
173
181
|
}
|
|
174
182
|
const raw = record(await this.json(response));
|
|
175
|
-
const page =
|
|
183
|
+
const page = (await presentation).presentMenu(
|
|
184
|
+
mapMenu(raw, ctx.branchId),
|
|
185
|
+
raw,
|
|
186
|
+
presentationError
|
|
187
|
+
);
|
|
176
188
|
if (ctx.metadataOnly) {
|
|
177
189
|
if (Object.keys(page.items).length || raw.next_cursor) {
|
|
178
190
|
throw new ZappieError("server_error", "Invalid metadata response");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/transport/rest.ts"],
|
|
4
|
-
"sourcesContent": ["import type { QuoteRequest, WireQuote } from \"../cart/types\";\nimport type { MenuFulfilment } from \"../client\";\nimport { ZappieError, wireError } from \"../errors\";\nimport { delay, throwIfAborted } from \"../internal/abort\";\nimport { payloadKey } from \"../internal/digest\";\nimport { money } from \"../money\";\nimport {\n hours,\n isBoolean,\n isString,\n list,\n mapItem,\n mapMenu,\n mapMoney,\n mapSeo,\n opt,\n record,\n text,\n} from \"./mappers\";\nimport type { SelectedMenuRequest } from \"./selected-menu\";\nimport type {\n MenuResponse,\n MenuVersion,\n RequestCtx,\n SearchRequest,\n Transport,\n} from \"./types\";\n/** The longest Retry-After the SDK waits out before surfacing the error instead. */\nconst MAX_RETRY_WAIT_MS = 5_000;\nconst wireFulfilment = (value: MenuFulfilment) =>\n value === \"dineIn\" ? \"dine_in\" : value;\n/** REST connection options. A custom fetch can provide tracing or mock responses. */\nexport type RestTransportOptions = { baseUrl?: string; fetch?: typeof fetch };\n/** REST read adapter for the versioned storefront API. */\nexport class RestTransport implements Transport {\n readonly baseUrl: string;\n private fetcher: typeof fetch;\n constructor(opts: RestTransportOptions = {}) {\n const url = new URL(opts.baseUrl ?? \"https://api.zappie.ai/storefront/v1\");\n if (\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n (url.protocol !== \"https:\" &&\n !(\n url.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname)\n ))\n ) {\n throw new ZappieError(\n \"invalid_request\",\n \"REST baseUrl requires HTTPS, or HTTP on localhost\",\n );\n }\n this.baseUrl = url.href.replace(/\\/$/, \"\");\n // Called as this.fetcher(), a stored global fetch would run with the\n // transport as `this`, which Workers refuses (\"Illegal invocation\").\n this.fetcher =\n opts.fetch ?? ((input, init) => globalThis.fetch(input, init));\n }\n private async request(\n path: string,\n ctx: RequestCtx,\n etag?: string,\n body?: QuoteRequest,\n ): Promise<Response> {\n if (typeof window !== \"undefined\" && ctx.key.startsWith(\"sk_\")) {\n throw new ZappieError(\n \"invalid_request\",\n \"Secret keys cannot be sent from a browser\",\n );\n }\n for (let attempt = 0; ; attempt++) {\n throwIfAborted(ctx.signal);\n let response: Response;\n try {\n response = await this.fetcher(this.baseUrl + path, {\n method: body ? \"POST\" : \"GET\",\n ...(body ? { body: JSON.stringify(body) } : {}),\n // Workers reject redirect: \"error\"; a redirect is still refused below\n // as a non-OK response (a 3xx, or opaqueredirect in browsers).\n redirect: \"manual\",\n headers: {\n ...(body ? { \"Content-Type\": \"application/json\" } : {}),\n ...(ctx.idempotencyKey\n ? { \"Idempotency-Key\": ctx.idempotencyKey }\n : {}),\n Authorization: `Bearer ${ctx.key}`,\n \"Zappie-Version\": ctx.version,\n ...(etag ? { \"If-None-Match\": etag } : {}),\n },\n ...(ctx.signal ? { signal: ctx.signal } : {}),\n });\n } catch (error) {\n throwIfAborted(ctx.signal);\n if (attempt >= 2) {\n throw new ZappieError(\n \"network_error\",\n \"Could not reach the storefront service\",\n { cause: error },\n );\n }\n await delay(100 * 2 ** attempt + Math.random() * 100, ctx.signal);\n continue;\n }\n if (response.ok || response.status === 304) {\n return response;\n }\n const retry = response.headers.get(\"Retry-After\");\n const seconds = retry !== null ? Number(retry) : NaN;\n const wait =\n retry !== null\n ? Number.isFinite(seconds)\n ? Math.max(0, seconds * 1000)\n : Math.max(0, Date.parse(retry) - Date.now())\n : NaN;\n // A longer wait than this is the caller's decision, not a silently stalled read.\n const tooLong = Number.isFinite(wait) && wait > MAX_RETRY_WAIT_MS;\n if (\n attempt < 2 &&\n !tooLong &&\n (response.status === 429 || response.status >= 500)\n ) {\n await response.body?.cancel();\n await delay(\n Number.isFinite(wait)\n ? wait\n : 100 * 2 ** attempt + Math.random() * 100,\n ctx.signal,\n );\n continue;\n }\n const errorBody = await response.json().catch(() => ({}));\n throw wireError(\n errorBody,\n response.status,\n response.headers.get(\"Zappie-Request-Id\") ?? undefined,\n );\n }\n }\n private async json(response: Response): Promise<unknown> {\n try {\n return await response.json();\n } catch (cause) {\n if (cause instanceof Error && cause.name === \"AbortError\") {\n throw cause;\n }\n throw new ZappieError(\n \"server_error\",\n \"The storefront service returned invalid JSON\",\n { status: response.status, cause },\n );\n }\n }\n async quote(ctx: RequestCtx, body: QuoteRequest): Promise<WireQuote> {\n body = (await import(\"./quote-body\")).quoteBody(body);\n const request = {\n ...ctx,\n idempotencyKey:\n ctx.idempotencyKey ?? (await payloadKey(JSON.stringify(body))),\n };\n const raw = await this.json(\n await this.request(\"/quote\", request, undefined, body),\n );\n // The cart's quote client validates and maps the response.\n return raw as WireQuote;\n }\n async getStore(ctx: RequestCtx) {\n const mapper = import(\"./store\").catch((cause) => {\n throw new ZappieError(\n \"server_error\",\n \"Could not load the storefront store mapper\",\n { cause },\n );\n });\n const response = this.request(\"/store\", ctx).then((value) =>\n this.json(value),\n );\n const [{ mapStore }, raw] = await Promise.all([mapper, response]);\n return mapStore(\n raw,\n record,\n text,\n list,\n hours,\n mapMoney,\n money,\n opt,\n isString,\n isBoolean,\n mapSeo,\n );\n }\n async getMenu(\n ctx: RequestCtx & {\n branchId: string;\n ifNoneMatch?: string;\n metadataOnly?: boolean;\n fulfilment?: MenuFulfilment;\n },\n ): Promise<MenuResponse> {\n let cursor: string | undefined;\n const seen = new Set<string>();\n let output: ReturnType<typeof mapMenu> | undefined;\n let etag: string | undefined;\n do {\n const query = new URLSearchParams({\n branch: ctx.branchId,\n ...(ctx.fulfilment\n ? { fulfilment: wireFulfilment(ctx.fulfilment) }\n : {}),\n ...(ctx.metadataOnly ? { metadata_only: \"true\" } : {}),\n ...(cursor ? { cursor } : {}),\n });\n const response = await this.request(\n `/menus?${query}`,\n ctx,\n cursor ? undefined : ctx.ifNoneMatch,\n );\n if (response.status === 304) {\n if (cursor) {\n throw new ZappieError(\n \"server_error\",\n \"Unexpected 304 on a continuation page\",\n );\n }\n return {\n notModified: true,\n ...(response.headers.get(\"ETag\")\n ? { etag: response.headers.get(\"ETag\")! }\n : {}),\n };\n }\n const raw = record(await this.json(response));\n const page = mapMenu(raw, ctx.branchId);\n if (ctx.metadataOnly) {\n if (Object.keys(page.items).length || raw.next_cursor) {\n throw new ZappieError(\"server_error\", \"Invalid metadata response\");\n }\n return { menu: { ...page, completeness: \"partial\" } };\n }\n if (!output) {\n output = page;\n etag = response.headers.get(\"ETag\") ?? undefined;\n } else {\n if (page.version !== output.version) {\n throw new ZappieError(\n \"server_error\",\n \"Menu changed while fetching pages; retry the read\",\n );\n }\n Object.assign(output.items, page.items);\n for (const category of page.categories) {\n const existing = output.categories.find((c) => c.id === category.id);\n if (existing) {\n existing.itemIds = [\n ...new Set([...existing.itemIds, ...category.itemIds]),\n ];\n } else {\n output.categories.push(category);\n }\n }\n for (const section of page.menus ?? []) {\n const existing = output.menus?.find((m) => m.id === section.id);\n if (existing) {\n existing.categoryIds = [\n ...new Set([...existing.categoryIds, ...section.categoryIds]),\n ];\n } else {\n output.menus?.push(section);\n }\n }\n }\n cursor =\n typeof raw.next_cursor === \"string\" && raw.next_cursor\n ? raw.next_cursor\n : undefined;\n if (cursor) {\n if (seen.has(cursor)) {\n throw new ZappieError(\n \"server_error\",\n \"Repeated menu pagination cursor\",\n );\n }\n seen.add(cursor);\n }\n } while (cursor);\n if (output.menus && output.menus.length > 1) {\n output.id = `branch:${ctx.branchId}`;\n output.name = \"Catalogue\";\n delete output.schedule;\n }\n for (const category of output.categories) {\n for (const id of category.itemIds) {\n if (!Object.prototype.hasOwnProperty.call(output.items, id)) {\n throw new ZappieError(\n \"server_error\",\n \"Category refers to a missing item\",\n );\n }\n }\n }\n if (Object.keys(output.items).length > 2000) {\n console.warn(\"Zappie menu contains more than 2,000 items\");\n }\n return { menu: output, ...(etag ? { etag } : {}) };\n }\n async getSelectedMenu(ctx: SelectedMenuRequest) {\n return (await import(\"./selected-menu\")).selectedMenu(\n ctx,\n (path) => this.request(path, ctx, ctx.ifNoneMatch),\n (response) => this.json(response),\n mapMenu,\n () => new ZappieError(\"server_error\", \"Invalid selected menu\"),\n );\n }\n async search(ctx: SearchRequest) {\n return (await import(\"./search\")).searchPage(\n ctx,\n async (path) => this.json(await this.request(path, ctx)),\n mapMenu,\n () => new ZappieError(\"server_error\", \"Invalid search page\"),\n );\n }\n async getCategoryPage(\n ctx: RequestCtx & {\n branchId: string;\n menuId: string;\n categoryId: string;\n cursor?: string;\n },\n ) {\n const query = new URLSearchParams({\n branch: ctx.branchId,\n ...(ctx.cursor ? { cursor: ctx.cursor } : {}),\n });\n const raw = await this.json(\n await this.request(\n `/menus/${encodeURIComponent(ctx.menuId)}/categories/${encodeURIComponent(ctx.categoryId)}/items?${query}`,\n ctx,\n ),\n );\n // Loaded on first use: only progressive catalogues read pages.\n return (await import(\"./category-page\")).categoryPage(\n record(raw),\n ctx,\n mapMenu,\n () => new ZappieError(\"server_error\", \"Invalid category page\"),\n );\n }\n async getMenuVersion(\n ctx: RequestCtx & { branchId: string; fulfilment?: MenuFulfilment },\n ): Promise<MenuVersion> {\n const value = record(\n await this.json(\n await this.request(\n `/menus/version?${new URLSearchParams({\n branch: ctx.branchId,\n ...(ctx.fulfilment\n ? { fulfilment: wireFulfilment(ctx.fulfilment) }\n : {}),\n })}`,\n ctx,\n ),\n ),\n );\n if (\n typeof value.menu_version !== \"string\" ||\n typeof value.availability_hash !== \"string\"\n ) {\n throw new ZappieError(\"server_error\", \"Invalid menu version response\");\n }\n return {\n version: value.menu_version,\n availabilityHash: value.availability_hash,\n };\n }\n async getItem(ctx: RequestCtx & { branchId: string; itemId: string }) {\n const item = mapItem(\n await this.json(\n await this.request(\n `/items/${encodeURIComponent(ctx.itemId)}?${new URLSearchParams({ branch: ctx.branchId })}`,\n ctx,\n ),\n ),\n );\n if (item.id !== ctx.itemId) {\n throw new ZappieError(\n \"server_error\",\n \"Item response identity does not match the request\",\n );\n }\n return item;\n }\n}\n"],
|
|
5
|
-
"mappings": ";AAEA,SAAS,aAAa,iBAAiB;AACvC,SAAS,OAAO,sBAAsB;AACtC,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AACtB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAUP,IAAM,oBAAoB;AAC1B,IAAM,iBAAiB,CAAC,UACtB,UAAU,WAAW,YAAY;
|
|
4
|
+
"sourcesContent": ["import type { QuoteRequest, WireQuote } from \"../cart/types\";\nimport type { MenuFulfilment } from \"../client\";\nimport { ZappieError, wireError } from \"../errors\";\nimport { delay, throwIfAborted } from \"../internal/abort\";\nimport { payloadKey } from \"../internal/digest\";\nimport { money } from \"../money\";\nimport {\n hours,\n isBoolean,\n isString,\n list,\n mapItem,\n mapMenu,\n mapMoney,\n mapSeo,\n opt,\n record,\n text,\n} from \"./mappers\";\nimport type { SelectedMenuRequest } from \"./selected-menu\";\nimport type {\n MenuResponse,\n MenuVersion,\n RequestCtx,\n SearchRequest,\n Transport,\n} from \"./types\";\n/** The longest Retry-After the SDK waits out before surfacing the error instead. */\nconst MAX_RETRY_WAIT_MS = 5_000;\nconst wireFulfilment = (value: MenuFulfilment) =>\n value === \"dineIn\" ? \"dine_in\" : value;\nconst presentationError = () =>\n new ZappieError(\"server_error\", \"Invalid storefront presentation\");\n/** REST connection options. A custom fetch can provide tracing or mock responses. */\nexport type RestTransportOptions = { baseUrl?: string; fetch?: typeof fetch };\n/** REST read adapter for the versioned storefront API. */\nexport class RestTransport implements Transport {\n readonly baseUrl: string;\n private fetcher: typeof fetch;\n constructor(opts: RestTransportOptions = {}) {\n const url = new URL(opts.baseUrl ?? \"https://api.zappie.ai/storefront/v1\");\n if (\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n (url.protocol !== \"https:\" &&\n !(\n url.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname)\n ))\n ) {\n throw new ZappieError(\n \"invalid_request\",\n \"REST baseUrl requires HTTPS, or HTTP on localhost\",\n );\n }\n this.baseUrl = url.href.replace(/\\/$/, \"\");\n // Called as this.fetcher(), a stored global fetch would run with the\n // transport as `this`, which Workers refuses (\"Illegal invocation\").\n this.fetcher =\n opts.fetch ?? ((input, init) => globalThis.fetch(input, init));\n }\n private async request(\n path: string,\n ctx: RequestCtx,\n etag?: string,\n body?: QuoteRequest,\n ): Promise<Response> {\n if (typeof window !== \"undefined\" && ctx.key.startsWith(\"sk_\")) {\n throw new ZappieError(\n \"invalid_request\",\n \"Secret keys cannot be sent from a browser\",\n );\n }\n for (let attempt = 0; ; attempt++) {\n throwIfAborted(ctx.signal);\n let response: Response;\n try {\n response = await this.fetcher(this.baseUrl + path, {\n method: body ? \"POST\" : \"GET\",\n ...(body ? { body: JSON.stringify(body) } : {}),\n // Workers reject redirect: \"error\"; a redirect is still refused below\n // as a non-OK response (a 3xx, or opaqueredirect in browsers).\n redirect: \"manual\",\n headers: {\n ...(body ? { \"Content-Type\": \"application/json\" } : {}),\n ...(ctx.idempotencyKey\n ? { \"Idempotency-Key\": ctx.idempotencyKey }\n : {}),\n Authorization: `Bearer ${ctx.key}`,\n \"Zappie-Version\": ctx.version,\n ...(etag ? { \"If-None-Match\": etag } : {}),\n },\n ...(ctx.signal ? { signal: ctx.signal } : {}),\n });\n } catch (error) {\n throwIfAborted(ctx.signal);\n if (attempt >= 2) {\n throw new ZappieError(\n \"network_error\",\n \"Could not reach the storefront service\",\n { cause: error },\n );\n }\n await delay(100 * 2 ** attempt + Math.random() * 100, ctx.signal);\n continue;\n }\n if (response.ok || response.status === 304) {\n return response;\n }\n const retry = response.headers.get(\"Retry-After\");\n const seconds = retry !== null ? Number(retry) : NaN;\n const wait =\n retry !== null\n ? Number.isFinite(seconds)\n ? Math.max(0, seconds * 1000)\n : Math.max(0, Date.parse(retry) - Date.now())\n : NaN;\n // A longer wait than this is the caller's decision, not a silently stalled read.\n const tooLong = Number.isFinite(wait) && wait > MAX_RETRY_WAIT_MS;\n if (\n attempt < 2 &&\n !tooLong &&\n (response.status === 429 || response.status >= 500)\n ) {\n await response.body?.cancel();\n await delay(\n Number.isFinite(wait)\n ? wait\n : 100 * 2 ** attempt + Math.random() * 100,\n ctx.signal,\n );\n continue;\n }\n const errorBody = await response.json().catch(() => ({}));\n throw wireError(\n errorBody,\n response.status,\n response.headers.get(\"Zappie-Request-Id\") ?? undefined,\n );\n }\n }\n private async json(response: Response): Promise<unknown> {\n try {\n return await response.json();\n } catch (cause) {\n if (cause instanceof Error && cause.name === \"AbortError\") {\n throw cause;\n }\n throw new ZappieError(\n \"server_error\",\n \"The storefront service returned invalid JSON\",\n { status: response.status, cause },\n );\n }\n }\n async quote(ctx: RequestCtx, body: QuoteRequest): Promise<WireQuote> {\n body = (await import(\"./quote-body\")).quoteBody(body);\n const request = {\n ...ctx,\n idempotencyKey:\n ctx.idempotencyKey ?? (await payloadKey(JSON.stringify(body))),\n };\n const raw = await this.json(\n await this.request(\"/quote\", request, undefined, body),\n );\n // The cart's quote client validates and maps the response.\n return raw as WireQuote;\n }\n async getStore(ctx: RequestCtx) {\n const mapper = import(\"./store\").catch((cause) => {\n throw new ZappieError(\n \"server_error\",\n \"Could not load the storefront store mapper\",\n { cause },\n );\n });\n const presentation = import(\"./presentation\");\n const response = this.request(\"/store\", ctx).then((value) =>\n this.json(value),\n );\n const [{ mapStore }, { presentStore }, raw] = await Promise.all([\n mapper,\n presentation,\n response,\n ]);\n const store = mapStore(\n raw,\n record,\n text,\n list,\n hours,\n mapMoney,\n money,\n opt,\n isString,\n isBoolean,\n mapSeo,\n );\n return presentStore(store, raw, presentationError);\n }\n async getMenu(\n ctx: RequestCtx & {\n branchId: string;\n ifNoneMatch?: string;\n metadataOnly?: boolean;\n fulfilment?: MenuFulfilment;\n },\n ): Promise<MenuResponse> {\n const presentation = import(\"./presentation\");\n let cursor: string | undefined;\n const seen = new Set<string>();\n let output: ReturnType<typeof mapMenu> | undefined;\n let etag: string | undefined;\n do {\n const query = new URLSearchParams({\n branch: ctx.branchId,\n ...(ctx.fulfilment\n ? { fulfilment: wireFulfilment(ctx.fulfilment) }\n : {}),\n ...(ctx.metadataOnly ? { metadata_only: \"true\" } : {}),\n ...(cursor ? { cursor } : {}),\n });\n const response = await this.request(\n `/menus?${query}`,\n ctx,\n cursor ? undefined : ctx.ifNoneMatch,\n );\n if (response.status === 304) {\n if (cursor) {\n throw new ZappieError(\n \"server_error\",\n \"Unexpected 304 on a continuation page\",\n );\n }\n return {\n notModified: true,\n ...(response.headers.get(\"ETag\")\n ? { etag: response.headers.get(\"ETag\")! }\n : {}),\n };\n }\n const raw = record(await this.json(response));\n const page = (await presentation).presentMenu(\n mapMenu(raw, ctx.branchId),\n raw,\n presentationError,\n );\n if (ctx.metadataOnly) {\n if (Object.keys(page.items).length || raw.next_cursor) {\n throw new ZappieError(\"server_error\", \"Invalid metadata response\");\n }\n return { menu: { ...page, completeness: \"partial\" } };\n }\n if (!output) {\n output = page;\n etag = response.headers.get(\"ETag\") ?? undefined;\n } else {\n if (page.version !== output.version) {\n throw new ZappieError(\n \"server_error\",\n \"Menu changed while fetching pages; retry the read\",\n );\n }\n Object.assign(output.items, page.items);\n for (const category of page.categories) {\n const existing = output.categories.find((c) => c.id === category.id);\n if (existing) {\n existing.itemIds = [\n ...new Set([...existing.itemIds, ...category.itemIds]),\n ];\n } else {\n output.categories.push(category);\n }\n }\n for (const section of page.menus ?? []) {\n const existing = output.menus?.find((m) => m.id === section.id);\n if (existing) {\n existing.categoryIds = [\n ...new Set([...existing.categoryIds, ...section.categoryIds]),\n ];\n } else {\n output.menus?.push(section);\n }\n }\n }\n cursor =\n typeof raw.next_cursor === \"string\" && raw.next_cursor\n ? raw.next_cursor\n : undefined;\n if (cursor) {\n if (seen.has(cursor)) {\n throw new ZappieError(\n \"server_error\",\n \"Repeated menu pagination cursor\",\n );\n }\n seen.add(cursor);\n }\n } while (cursor);\n if (output.menus && output.menus.length > 1) {\n output.id = `branch:${ctx.branchId}`;\n output.name = \"Catalogue\";\n delete output.schedule;\n }\n for (const category of output.categories) {\n for (const id of category.itemIds) {\n if (!Object.prototype.hasOwnProperty.call(output.items, id)) {\n throw new ZappieError(\n \"server_error\",\n \"Category refers to a missing item\",\n );\n }\n }\n }\n if (Object.keys(output.items).length > 2000) {\n console.warn(\"Zappie menu contains more than 2,000 items\");\n }\n return { menu: output, ...(etag ? { etag } : {}) };\n }\n async getSelectedMenu(ctx: SelectedMenuRequest) {\n return (await import(\"./selected-menu\")).selectedMenu(\n ctx,\n (path) => this.request(path, ctx, ctx.ifNoneMatch),\n (response) => this.json(response),\n mapMenu,\n () => new ZappieError(\"server_error\", \"Invalid selected menu\"),\n );\n }\n async search(ctx: SearchRequest) {\n return (await import(\"./search\")).searchPage(\n ctx,\n async (path) => this.json(await this.request(path, ctx)),\n mapMenu,\n () => new ZappieError(\"server_error\", \"Invalid search page\"),\n );\n }\n async getCategoryPage(\n ctx: RequestCtx & {\n branchId: string;\n menuId: string;\n categoryId: string;\n cursor?: string;\n },\n ) {\n const query = new URLSearchParams({\n branch: ctx.branchId,\n ...(ctx.cursor ? { cursor: ctx.cursor } : {}),\n });\n const raw = await this.json(\n await this.request(\n `/menus/${encodeURIComponent(ctx.menuId)}/categories/${encodeURIComponent(ctx.categoryId)}/items?${query}`,\n ctx,\n ),\n );\n // Loaded on first use: only progressive catalogues read pages.\n return (await import(\"./category-page\")).categoryPage(\n record(raw),\n ctx,\n mapMenu,\n () => new ZappieError(\"server_error\", \"Invalid category page\"),\n );\n }\n async getMenuVersion(\n ctx: RequestCtx & { branchId: string; fulfilment?: MenuFulfilment },\n ): Promise<MenuVersion> {\n const value = record(\n await this.json(\n await this.request(\n `/menus/version?${new URLSearchParams({\n branch: ctx.branchId,\n ...(ctx.fulfilment\n ? { fulfilment: wireFulfilment(ctx.fulfilment) }\n : {}),\n })}`,\n ctx,\n ),\n ),\n );\n if (\n typeof value.menu_version !== \"string\" ||\n typeof value.availability_hash !== \"string\"\n ) {\n throw new ZappieError(\"server_error\", \"Invalid menu version response\");\n }\n return {\n version: value.menu_version,\n availabilityHash: value.availability_hash,\n };\n }\n async getItem(ctx: RequestCtx & { branchId: string; itemId: string }) {\n const item = mapItem(\n await this.json(\n await this.request(\n `/items/${encodeURIComponent(ctx.itemId)}?${new URLSearchParams({ branch: ctx.branchId })}`,\n ctx,\n ),\n ),\n );\n if (item.id !== ctx.itemId) {\n throw new ZappieError(\n \"server_error\",\n \"Item response identity does not match the request\",\n );\n }\n return item;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as Menu } from '../models-
|
|
2
|
-
import { j as SearchRequest, k as SearchPage } from '../client-
|
|
3
|
-
import '../types-
|
|
1
|
+
import { a as Menu } from '../models-D__QbqEd.js';
|
|
2
|
+
import { j as SearchRequest, k as SearchPage } from '../client-iVMHfAFn.js';
|
|
3
|
+
import '../types-B-iTMrVV.js';
|
|
4
4
|
|
|
5
5
|
/** Loaded only when search is used; request authentication/retries stay in REST. */
|
|
6
6
|
declare function searchPage(ctx: SearchRequest, read: (path: string) => Promise<unknown>, mapMenu: (value: unknown, branchId: string) => Menu, invalid: () => Error): Promise<SearchPage>;
|
package/dist/transport/search.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/transport/search.ts
|
|
2
2
|
async function searchPage(ctx, read, mapMenu, invalid) {
|
|
3
|
+
const presentation = import("./presentation.js");
|
|
3
4
|
ctx.signal?.throwIfAborted();
|
|
4
5
|
const query = new URLSearchParams({
|
|
5
6
|
branch: ctx.branchId,
|
|
@@ -13,7 +14,11 @@ async function searchPage(ctx, read, mapMenu, invalid) {
|
|
|
13
14
|
throw invalid();
|
|
14
15
|
}
|
|
15
16
|
const cursor = raw.next_cursor;
|
|
16
|
-
const menu =
|
|
17
|
+
const menu = (await presentation).presentMenu(
|
|
18
|
+
mapMenu(raw, ctx.branchId),
|
|
19
|
+
raw,
|
|
20
|
+
invalid
|
|
21
|
+
);
|
|
17
22
|
if (Object.keys(menu.items).length > 25 || cursor != null && (typeof cursor !== "string" || !cursor || cursor === ctx.cursor) || Object.keys(menu.items).some(
|
|
18
23
|
(id) => !menu.categories.some((category) => category.itemIds.includes(id))
|
|
19
24
|
) || menu.categories.some(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/transport/search.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Menu } from \"../models\";\nimport type { SearchPage, SearchRequest } from \"./types\";\n\n/** Loaded only when search is used; request authentication/retries stay in REST. */\nexport async function searchPage(\n ctx: SearchRequest,\n read: (path: string) => Promise<unknown>,\n mapMenu: (value: unknown, branchId: string) => Menu,\n invalid: () => Error,\n): Promise<SearchPage> {\n ctx.signal?.throwIfAborted();\n const query = new URLSearchParams({\n branch: ctx.branchId,\n query: ctx.query.trim(),\n limit: \"25\",\n ...(ctx.cursor ? { cursor: ctx.cursor } : {}),\n });\n const raw = await read(`/items/search?${query}`);\n ctx.signal?.throwIfAborted();\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw invalid();\n }\n const cursor = (raw as Record<string, unknown>).next_cursor;\n const menu = mapMenu(raw, ctx.branchId);\n if (\n Object.keys(menu.items).length > 25 ||\n (cursor != null &&\n (typeof cursor !== \"string\" || !cursor || cursor === ctx.cursor)) ||\n Object.keys(menu.items).some(\n (id) =>\n !menu.categories.some((category) => category.itemIds.includes(id)),\n ) ||\n menu.categories.some(\n (category) =>\n !menu.menus?.some((source) => source.categoryIds.includes(category.id)),\n )\n ) {\n throw invalid();\n }\n return {\n menu: { ...menu, completeness: \"partial\" },\n ...(typeof cursor === \"string\" ? { nextCursor: cursor } : {}),\n };\n}\n"],
|
|
5
|
-
"mappings": ";AAIA,eAAsB,WACpB,KACA,MACA,SACA,SACqB;AACrB,MAAI,QAAQ,eAAe;AAC3B,QAAM,QAAQ,IAAI,gBAAgB;AAAA,IAChC,QAAQ,IAAI;AAAA,IACZ,OAAO,IAAI,MAAM,KAAK;AAAA,IACtB,OAAO;AAAA,IACP,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;AAAA,EAC7C,CAAC;AACD,QAAM,MAAM,MAAM,KAAK,iBAAiB,KAAK,EAAE;AAC/C,MAAI,QAAQ,eAAe;AAC3B,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,GAAG;AACzD,UAAM,QAAQ;AAAA,EAChB;AACA,QAAM,SAAU,IAAgC;AAChD,QAAM,
|
|
4
|
+
"sourcesContent": ["import type { Menu } from \"../models\";\nimport type { SearchPage, SearchRequest } from \"./types\";\n\n/** Loaded only when search is used; request authentication/retries stay in REST. */\nexport async function searchPage(\n ctx: SearchRequest,\n read: (path: string) => Promise<unknown>,\n mapMenu: (value: unknown, branchId: string) => Menu,\n invalid: () => Error,\n): Promise<SearchPage> {\n const presentation = import(\"./presentation\");\n ctx.signal?.throwIfAborted();\n const query = new URLSearchParams({\n branch: ctx.branchId,\n query: ctx.query.trim(),\n limit: \"25\",\n ...(ctx.cursor ? { cursor: ctx.cursor } : {}),\n });\n const raw = await read(`/items/search?${query}`);\n ctx.signal?.throwIfAborted();\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw invalid();\n }\n const cursor = (raw as Record<string, unknown>).next_cursor;\n const menu = (await presentation).presentMenu(\n mapMenu(raw, ctx.branchId),\n raw,\n invalid,\n );\n if (\n Object.keys(menu.items).length > 25 ||\n (cursor != null &&\n (typeof cursor !== \"string\" || !cursor || cursor === ctx.cursor)) ||\n Object.keys(menu.items).some(\n (id) =>\n !menu.categories.some((category) => category.itemIds.includes(id)),\n ) ||\n menu.categories.some(\n (category) =>\n !menu.menus?.some((source) => source.categoryIds.includes(category.id)),\n )\n ) {\n throw invalid();\n }\n return {\n menu: { ...menu, completeness: \"partial\" },\n ...(typeof cursor === \"string\" ? { nextCursor: cursor } : {}),\n };\n}\n"],
|
|
5
|
+
"mappings": ";AAIA,eAAsB,WACpB,KACA,MACA,SACA,SACqB;AACrB,QAAM,eAAe,OAAO,mBAAgB;AAC5C,MAAI,QAAQ,eAAe;AAC3B,QAAM,QAAQ,IAAI,gBAAgB;AAAA,IAChC,QAAQ,IAAI;AAAA,IACZ,OAAO,IAAI,MAAM,KAAK;AAAA,IACtB,OAAO;AAAA,IACP,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;AAAA,EAC7C,CAAC;AACD,QAAM,MAAM,MAAM,KAAK,iBAAiB,KAAK,EAAE;AAC/C,MAAI,QAAQ,eAAe;AAC3B,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,GAAG;AACzD,UAAM,QAAQ;AAAA,EAChB;AACA,QAAM,SAAU,IAAgC;AAChD,QAAM,QAAQ,MAAM,cAAc;AAAA,IAChC,QAAQ,KAAK,IAAI,QAAQ;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AACA,MACE,OAAO,KAAK,KAAK,KAAK,EAAE,SAAS,MAChC,UAAU,SACR,OAAO,WAAW,YAAY,CAAC,UAAU,WAAW,IAAI,WAC3D,OAAO,KAAK,KAAK,KAAK,EAAE;AAAA,IACtB,CAAC,OACC,CAAC,KAAK,WAAW,KAAK,CAAC,aAAa,SAAS,QAAQ,SAAS,EAAE,CAAC;AAAA,EACrE,KACA,KAAK,WAAW;AAAA,IACd,CAAC,aACC,CAAC,KAAK,OAAO,KAAK,CAAC,WAAW,OAAO,YAAY,SAAS,SAAS,EAAE,CAAC;AAAA,EAC1E,GACA;AACA,UAAM,QAAQ;AAAA,EAChB;AACA,SAAO;AAAA,IACL,MAAM,EAAE,GAAG,MAAM,cAAc,UAAU;AAAA,IACzC,GAAI,OAAO,WAAW,WAAW,EAAE,YAAY,OAAO,IAAI,CAAC;AAAA,EAC7D;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { z as SelectedMenu, h as SelectedMenuRequest, i as SelectedMenuResponse, B as SelectedMenuTransport, D as createSelectedMenuReader, F as selectedMenu, G as selectedMenuKey } from '../client-
|
|
2
|
-
import '../models-
|
|
3
|
-
import '../types-
|
|
1
|
+
export { z as SelectedMenu, h as SelectedMenuRequest, i as SelectedMenuResponse, B as SelectedMenuTransport, D as createSelectedMenuReader, F as selectedMenu, G as selectedMenuKey } from '../client-iVMHfAFn.js';
|
|
2
|
+
import '../models-D__QbqEd.js';
|
|
3
|
+
import '../types-B-iTMrVV.js';
|