@zappie/sdk 0.1.6 → 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.
Files changed (62) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +21 -1
  3. package/dist/cart/branch.d.ts +2 -2
  4. package/dist/cart/item.d.ts +3 -3
  5. package/dist/cart/quote.d.ts +3 -3
  6. package/dist/{client-Bm2cCYea.d.ts → client-iVMHfAFn.d.ts} +2 -2
  7. package/dist/debug.d.ts +3 -3
  8. package/dist/debug.js +1 -1
  9. package/dist/index.d.ts +6 -6
  10. package/dist/index.js +1 -1
  11. package/dist/integrations/index.d.ts +9 -6
  12. package/dist/integrations/index.js +1 -0
  13. package/dist/integrations/index.js.map +2 -2
  14. package/dist/internal.d.ts +3 -3
  15. package/dist/{models-Rg5kQUkv.d.ts → models-D__QbqEd.d.ts} +14 -1
  16. package/dist/persist/catalogue.d.ts +3 -3
  17. package/dist/react/index.d.ts +3 -3
  18. package/dist/server/index.d.ts +7 -4
  19. package/dist/server/storefront-url/build-v1.js +8 -17
  20. package/dist/server/storefront-url/build-v1.js.map +2 -2
  21. package/dist/server/storefront-url/build-v2.js +13 -41
  22. package/dist/server/storefront-url/build-v2.js.map +2 -2
  23. package/dist/server/storefront-url/canonical.js +36 -0
  24. package/dist/server/storefront-url/canonical.js.map +7 -0
  25. package/dist/server/storefront-url/contract.js +2 -2
  26. package/dist/server/storefront-url/contract.js.map +2 -2
  27. package/dist/server/storefront-url/params.js +35 -18
  28. package/dist/server/storefront-url/params.js.map +2 -2
  29. package/dist/server/storefront-url/parse-v1.js +15 -12
  30. package/dist/server/storefront-url/parse-v1.js.map +2 -2
  31. package/dist/server/storefront-url/parse-v2.js +17 -79
  32. package/dist/server/storefront-url/parse-v2.js.map +2 -2
  33. package/dist/server/storefront-url/public-id.js +8 -0
  34. package/dist/server/storefront-url/public-id.js.map +7 -0
  35. package/dist/server/storefront-url/redirect.js +20 -6
  36. package/dist/server/storefront-url/redirect.js.map +2 -2
  37. package/dist/server/storefront-url/sign-in.js +2 -1
  38. package/dist/server/storefront-url/sign-in.js.map +2 -2
  39. package/dist/server/storefront-url/types.js +1 -0
  40. package/dist/server/storefront-url/types.js.map +2 -2
  41. package/dist/server/storefront-url/url.js +34 -23
  42. package/dist/server/storefront-url/url.js.map +2 -2
  43. package/dist/testing/index.d.ts +3 -3
  44. package/dist/transport/category-page.d.ts +2 -2
  45. package/dist/transport/category-page.js +6 -2
  46. package/dist/transport/category-page.js.map +2 -2
  47. package/dist/transport/presentation.d.ts +7 -0
  48. package/dist/transport/presentation.js +68 -0
  49. package/dist/transport/presentation.js.map +7 -0
  50. package/dist/transport/rest.js +15 -3
  51. package/dist/transport/rest.js.map +2 -2
  52. package/dist/transport/search.d.ts +3 -3
  53. package/dist/transport/search.js +6 -1
  54. package/dist/transport/search.js.map +2 -2
  55. package/dist/transport/selected-menu.d.ts +3 -3
  56. package/dist/transport/selected-menu.js +7 -2
  57. package/dist/transport/selected-menu.js.map +2 -2
  58. package/dist/transport/store.d.ts +1 -2
  59. package/dist/transport/store.js.map +1 -1
  60. package/dist/{types-CuDvfW9g.d.ts → types-B-iTMrVV.d.ts} +1 -1
  61. package/dist/url/index.d.ts +4 -1
  62. package/package.json +1 -1
@@ -1,25 +1,19 @@
1
1
  // src/server/storefront-url/params.ts
2
2
  import { CART_MODAL, CHECKOUT_MODAL, SIGN_IN_MODAL } from "./contract.js";
3
+ import { publicId } from "./public-id.js";
4
+ import { STATE_FIELDS } from "./url.js";
3
5
  var stateParams = (route) => {
4
6
  const params = new URLSearchParams(route.state.query);
5
7
  const state = route.state;
6
- const values = [
7
- ["menu_id", state.menuId],
8
- ["category_id", state.categoryId],
9
- ["menu_layout", state.menuLayout],
10
- ["pickup", state.mode ? String(state.mode === "pickup") : void 0],
11
- ["modal_id", state.modalId],
12
- ["auth_modal_id", state.authModalId],
13
- ["payment_id", state.paymentId],
14
- ["lightbox", state.lightbox],
15
- ["catalogue_search", state.catalogueSearch],
16
- ["catalogue_categories", state.catalogueCategories]
17
- ];
18
- values.forEach(([key, value]) => {
8
+ for (const [key, field] of Object.entries(STATE_FIELDS)) {
9
+ const value = state[field];
19
10
  if (value !== void 0) {
20
11
  params.set(key, value);
21
12
  }
22
- });
13
+ }
14
+ if (state.mode) {
15
+ params.set("pickup", String(state.mode === "pickup"));
16
+ }
23
17
  return params;
24
18
  };
25
19
  var v1Params = (route) => {
@@ -43,16 +37,39 @@ var v1Params = (route) => {
43
37
  };
44
38
  var v2Params = (route, installation) => {
45
39
  const params = stateParams(route);
46
- if (route.type === "order-menu" || route.type === "item" || route.type === "cart" || route.type === "checkout" || route.type === "checkout-return" || route.type === "sign-in" || route.type === "content-page") {
40
+ const menu = params.get("menu_id");
41
+ if (menu) {
42
+ params.set("menu", publicId(menu, "menu"));
43
+ }
44
+ for (const key of [
45
+ "menu_id",
46
+ "category_id",
47
+ "pickup",
48
+ "menu_layout",
49
+ "catalogue_search",
50
+ "catalogue_categories",
51
+ "template",
52
+ "catalog_rendering",
53
+ "prefetch",
54
+ "ws",
55
+ "env",
56
+ "business",
57
+ "business_tag",
58
+ "switched_branch",
59
+ "success",
60
+ "auto_scroll",
61
+ "preview",
62
+ "modal_id"
63
+ ]) {
64
+ params.delete(key);
65
+ }
66
+ if ("business" in route) {
47
67
  if (route.branch && route.branch !== installation.defaultBranch) {
48
68
  params.set("branch", route.branch);
49
69
  } else {
50
70
  params.delete("branch");
51
71
  }
52
72
  }
53
- if (route.type === "item" || route.type === "cart" || route.type === "checkout" || route.type === "checkout-return") {
54
- params.delete("modal_id");
55
- }
56
73
  if (route.type === "sign-in") {
57
74
  params.delete("auth_modal_id");
58
75
  if (route.returnTo !== void 0) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/storefront-url/params.ts"],
4
- "sourcesContent": ["import { CART_MODAL, CHECKOUT_MODAL, SIGN_IN_MODAL } from \"./contract\";\nimport type { StorefrontInstallation, StorefrontRoute } from \"./types\";\n\nconst stateParams = (route: StorefrontRoute) => {\n const params = new URLSearchParams(route.state.query);\n const state = route.state;\n const values: ReadonlyArray<[string, string | undefined]> = [\n [\"menu_id\", state.menuId],\n [\"category_id\", state.categoryId],\n [\"menu_layout\", state.menuLayout],\n [\"pickup\", state.mode ? String(state.mode === \"pickup\") : undefined],\n [\"modal_id\", state.modalId],\n [\"auth_modal_id\", state.authModalId],\n [\"payment_id\", state.paymentId],\n [\"lightbox\", state.lightbox],\n [\"catalogue_search\", state.catalogueSearch],\n [\"catalogue_categories\", state.catalogueCategories],\n ];\n values.forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, value);\n }\n });\n return params;\n};\n\nexport const v1Params = (route: StorefrontRoute) => {\n const params = stateParams(route);\n if (route.type === \"item\") {\n params.delete(\"modal_id\");\n } else if (route.type === \"cart\") {\n params.set(\"modal_id\", CART_MODAL);\n } else if (route.type === \"checkout\") {\n params.set(\"modal_id\", CHECKOUT_MODAL);\n } else if (route.type === \"sign-in\") {\n params.set(\"auth_modal_id\", SIGN_IN_MODAL);\n if (route.returnTo !== undefined) {\n params.set(\"return\", route.returnTo);\n }\n } else if (route.type === \"checkout-return\" && route.session !== undefined) {\n params.set(\"session\", route.session);\n }\n params.sort();\n return params;\n};\n\nexport const v2Params = (\n route: StorefrontRoute,\n installation: StorefrontInstallation,\n) => {\n const params = stateParams(route);\n if (\n route.type === \"order-menu\" ||\n route.type === \"item\" ||\n route.type === \"cart\" ||\n route.type === \"checkout\" ||\n route.type === \"checkout-return\" ||\n route.type === \"sign-in\" ||\n route.type === \"content-page\"\n ) {\n if (route.branch && route.branch !== installation.defaultBranch) {\n params.set(\"branch\", route.branch);\n } else {\n params.delete(\"branch\");\n }\n }\n if (\n route.type === \"item\" ||\n route.type === \"cart\" ||\n route.type === \"checkout\" ||\n route.type === \"checkout-return\"\n ) {\n params.delete(\"modal_id\");\n }\n if (route.type === \"sign-in\") {\n params.delete(\"auth_modal_id\");\n if (route.returnTo !== undefined) {\n params.set(\"return\", route.returnTo);\n }\n }\n if (route.type === \"checkout-return\" && route.session !== undefined) {\n params.set(\"session\", route.session);\n }\n params.sort();\n return params;\n};\n"],
5
- "mappings": ";AAAA,SAAS,YAAY,gBAAgB,qBAAqB;AAG1D,IAAM,cAAc,CAAC,UAA2B;AAC9C,QAAM,SAAS,IAAI,gBAAgB,MAAM,MAAM,KAAK;AACpD,QAAM,QAAQ,MAAM;AACpB,QAAM,SAAsD;AAAA,IAC1D,CAAC,WAAW,MAAM,MAAM;AAAA,IACxB,CAAC,eAAe,MAAM,UAAU;AAAA,IAChC,CAAC,eAAe,MAAM,UAAU;AAAA,IAChC,CAAC,UAAU,MAAM,OAAO,OAAO,MAAM,SAAS,QAAQ,IAAI,MAAS;AAAA,IACnE,CAAC,YAAY,MAAM,OAAO;AAAA,IAC1B,CAAC,iBAAiB,MAAM,WAAW;AAAA,IACnC,CAAC,cAAc,MAAM,SAAS;AAAA,IAC9B,CAAC,YAAY,MAAM,QAAQ;AAAA,IAC3B,CAAC,oBAAoB,MAAM,eAAe;AAAA,IAC1C,CAAC,wBAAwB,MAAM,mBAAmB;AAAA,EACpD;AACA,SAAO,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/B,QAAI,UAAU,QAAW;AACvB,aAAO,IAAI,KAAK,KAAK;AAAA,IACvB;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAEO,IAAM,WAAW,CAAC,UAA2B;AAClD,QAAM,SAAS,YAAY,KAAK;AAChC,MAAI,MAAM,SAAS,QAAQ;AACzB,WAAO,OAAO,UAAU;AAAA,EAC1B,WAAW,MAAM,SAAS,QAAQ;AAChC,WAAO,IAAI,YAAY,UAAU;AAAA,EACnC,WAAW,MAAM,SAAS,YAAY;AACpC,WAAO,IAAI,YAAY,cAAc;AAAA,EACvC,WAAW,MAAM,SAAS,WAAW;AACnC,WAAO,IAAI,iBAAiB,aAAa;AACzC,QAAI,MAAM,aAAa,QAAW;AAChC,aAAO,IAAI,UAAU,MAAM,QAAQ;AAAA,IACrC;AAAA,EACF,WAAW,MAAM,SAAS,qBAAqB,MAAM,YAAY,QAAW;AAC1E,WAAO,IAAI,WAAW,MAAM,OAAO;AAAA,EACrC;AACA,SAAO,KAAK;AACZ,SAAO;AACT;AAEO,IAAM,WAAW,CACtB,OACA,iBACG;AACH,QAAM,SAAS,YAAY,KAAK;AAChC,MACE,MAAM,SAAS,gBACf,MAAM,SAAS,UACf,MAAM,SAAS,UACf,MAAM,SAAS,cACf,MAAM,SAAS,qBACf,MAAM,SAAS,aACf,MAAM,SAAS,gBACf;AACA,QAAI,MAAM,UAAU,MAAM,WAAW,aAAa,eAAe;AAC/D,aAAO,IAAI,UAAU,MAAM,MAAM;AAAA,IACnC,OAAO;AACL,aAAO,OAAO,QAAQ;AAAA,IACxB;AAAA,EACF;AACA,MACE,MAAM,SAAS,UACf,MAAM,SAAS,UACf,MAAM,SAAS,cACf,MAAM,SAAS,mBACf;AACA,WAAO,OAAO,UAAU;AAAA,EAC1B;AACA,MAAI,MAAM,SAAS,WAAW;AAC5B,WAAO,OAAO,eAAe;AAC7B,QAAI,MAAM,aAAa,QAAW;AAChC,aAAO,IAAI,UAAU,MAAM,QAAQ;AAAA,IACrC;AAAA,EACF;AACA,MAAI,MAAM,SAAS,qBAAqB,MAAM,YAAY,QAAW;AACnE,WAAO,IAAI,WAAW,MAAM,OAAO;AAAA,EACrC;AACA,SAAO,KAAK;AACZ,SAAO;AACT;",
4
+ "sourcesContent": ["import { CART_MODAL, CHECKOUT_MODAL, SIGN_IN_MODAL } from \"./contract\";\nimport { publicId } from \"./public-id\";\nimport type { StorefrontInstallation, StorefrontRoute } from \"./types\";\nimport { STATE_FIELDS } from \"./url\";\n\nconst stateParams = (route: StorefrontRoute) => {\n const params = new URLSearchParams(route.state.query);\n const state = route.state;\n for (const [key, field] of Object.entries(STATE_FIELDS)) {\n const value = state[field];\n if (value !== undefined) {\n params.set(key, value);\n }\n }\n if (state.mode) {\n params.set(\"pickup\", String(state.mode === \"pickup\"));\n }\n return params;\n};\n\nexport const v1Params = (route: StorefrontRoute) => {\n const params = stateParams(route);\n if (route.type === \"item\") {\n params.delete(\"modal_id\");\n } else if (route.type === \"cart\") {\n params.set(\"modal_id\", CART_MODAL);\n } else if (route.type === \"checkout\") {\n params.set(\"modal_id\", CHECKOUT_MODAL);\n } else if (route.type === \"sign-in\") {\n params.set(\"auth_modal_id\", SIGN_IN_MODAL);\n if (route.returnTo !== undefined) {\n params.set(\"return\", route.returnTo);\n }\n } else if (route.type === \"checkout-return\" && route.session !== undefined) {\n params.set(\"session\", route.session);\n }\n params.sort();\n return params;\n};\n\nexport const v2Params = (\n route: StorefrontRoute,\n installation: StorefrontInstallation,\n) => {\n const params = stateParams(route);\n const menu = params.get(\"menu_id\");\n if (menu) {\n params.set(\"menu\", publicId(menu, \"menu\"));\n }\n for (const key of [\n \"menu_id\",\n \"category_id\",\n \"pickup\",\n \"menu_layout\",\n \"catalogue_search\",\n \"catalogue_categories\",\n \"template\",\n \"catalog_rendering\",\n \"prefetch\",\n \"ws\",\n \"env\",\n \"business\",\n \"business_tag\",\n \"switched_branch\",\n \"success\",\n \"auto_scroll\",\n \"preview\",\n \"modal_id\",\n ]) {\n params.delete(key);\n }\n\n if (\"business\" in route) {\n if (route.branch && route.branch !== installation.defaultBranch) {\n params.set(\"branch\", route.branch);\n } else {\n params.delete(\"branch\");\n }\n }\n if (route.type === \"sign-in\") {\n params.delete(\"auth_modal_id\");\n if (route.returnTo !== undefined) {\n params.set(\"return\", route.returnTo);\n }\n }\n if (route.type === \"checkout-return\" && route.session !== undefined) {\n params.set(\"session\", route.session);\n }\n params.sort();\n return params;\n};\n"],
5
+ "mappings": ";AAAA,SAAS,YAAY,gBAAgB,qBAAqB;AAC1D,SAAS,gBAAgB;AAEzB,SAAS,oBAAoB;AAE7B,IAAM,cAAc,CAAC,UAA2B;AAC9C,QAAM,SAAS,IAAI,gBAAgB,MAAM,MAAM,KAAK;AACpD,QAAM,QAAQ,MAAM;AACpB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACvD,UAAM,QAAQ,MAAM,KAAK;AACzB,QAAI,UAAU,QAAW;AACvB,aAAO,IAAI,KAAK,KAAK;AAAA,IACvB;AAAA,EACF;AACA,MAAI,MAAM,MAAM;AACd,WAAO,IAAI,UAAU,OAAO,MAAM,SAAS,QAAQ,CAAC;AAAA,EACtD;AACA,SAAO;AACT;AAEO,IAAM,WAAW,CAAC,UAA2B;AAClD,QAAM,SAAS,YAAY,KAAK;AAChC,MAAI,MAAM,SAAS,QAAQ;AACzB,WAAO,OAAO,UAAU;AAAA,EAC1B,WAAW,MAAM,SAAS,QAAQ;AAChC,WAAO,IAAI,YAAY,UAAU;AAAA,EACnC,WAAW,MAAM,SAAS,YAAY;AACpC,WAAO,IAAI,YAAY,cAAc;AAAA,EACvC,WAAW,MAAM,SAAS,WAAW;AACnC,WAAO,IAAI,iBAAiB,aAAa;AACzC,QAAI,MAAM,aAAa,QAAW;AAChC,aAAO,IAAI,UAAU,MAAM,QAAQ;AAAA,IACrC;AAAA,EACF,WAAW,MAAM,SAAS,qBAAqB,MAAM,YAAY,QAAW;AAC1E,WAAO,IAAI,WAAW,MAAM,OAAO;AAAA,EACrC;AACA,SAAO,KAAK;AACZ,SAAO;AACT;AAEO,IAAM,WAAW,CACtB,OACA,iBACG;AACH,QAAM,SAAS,YAAY,KAAK;AAChC,QAAM,OAAO,OAAO,IAAI,SAAS;AACjC,MAAI,MAAM;AACR,WAAO,IAAI,QAAQ,SAAS,MAAM,MAAM,CAAC;AAAA,EAC3C;AACA,aAAW,OAAO;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG;AACD,WAAO,OAAO,GAAG;AAAA,EACnB;AAEA,MAAI,cAAc,OAAO;AACvB,QAAI,MAAM,UAAU,MAAM,WAAW,aAAa,eAAe;AAC/D,aAAO,IAAI,UAAU,MAAM,MAAM;AAAA,IACnC,OAAO;AACL,aAAO,OAAO,QAAQ;AAAA,IACxB;AAAA,EACF;AACA,MAAI,MAAM,SAAS,WAAW;AAC5B,WAAO,OAAO,eAAe;AAC7B,QAAI,MAAM,aAAa,QAAW;AAChC,aAAO,IAAI,UAAU,MAAM,QAAQ;AAAA,IACrC;AAAA,EACF;AACA,MAAI,MAAM,SAAS,qBAAqB,MAAM,YAAY,QAAW;AACnE,WAAO,IAAI,WAAW,MAAM,OAAO;AAAA,EACrC;AACA,SAAO,KAAK;AACZ,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -9,13 +9,12 @@ var FIXED_ROUTES = {
9
9
  "/reservation": "reservation"
10
10
  };
11
11
  var ID_ROUTES = {
12
- "dine-in": (order, state) => ({ type: "dine-in", order, state }),
13
- "pay-point": (payPoint, state) => ({ type: "pay-point", payPoint, state }),
14
- beacons: (beacon, state) => ({ type: "beacon", beacon, state }),
15
- links: (link, state) => ({ type: "link", link, state }),
16
- pay: (session, state) => ({ type: "pay-session", session, state })
12
+ "dine-in": ["dine-in", "order"],
13
+ "pay-point": ["pay-point", "payPoint"],
14
+ beacons: ["beacon", "beacon"],
15
+ links: ["link", "link"],
16
+ pay: ["pay-session", "session"]
17
17
  };
18
- var isKeyOf = (table, key) => Object.hasOwn(table, key);
19
18
  var parseV1 = (input, options = {}) => {
20
19
  try {
21
20
  const url = inputUrl(input);
@@ -74,23 +73,27 @@ var parseV1 = (input, options = {}) => {
74
73
  };
75
74
  }
76
75
  }
77
- if (isKeyOf(FIXED_ROUTES, pathname)) {
78
- return { type: FIXED_ROUTES[pathname], state };
76
+ if (Object.hasOwn(FIXED_ROUTES, pathname)) {
77
+ return {
78
+ type: FIXED_ROUTES[pathname],
79
+ state
80
+ };
79
81
  }
80
82
  const [prefix = "", id] = parts;
81
- if (parts.length === 2 && id && isKeyOf(ID_ROUTES, prefix)) {
82
- return ID_ROUTES[prefix](segment(parts, 1), state);
83
+ if (parts.length === 2 && id && Object.hasOwn(ID_ROUTES, prefix)) {
84
+ const [type, field] = ID_ROUTES[prefix];
85
+ return { type, [field]: segment(parts, 1), state };
83
86
  }
84
87
  if (parts[0] === "payment" && parts[1] === "card" && parts[2] && parts.length === 3) {
85
88
  return { type: "payment-card", transaction: segment(parts, 2), state };
86
89
  }
87
90
  if (parts[0] === "payment" && parts[1] && parts.length <= 3) {
88
91
  const step = parts[2];
89
- if (!step || step === "successful" || step === "failed" || step === "refunded") {
92
+ if (!step || ["successful", "failed", "refunded"].includes(step)) {
90
93
  return {
91
94
  type: "payment-step",
92
95
  payment: segment(parts, 1),
93
- step: step === "successful" || step === "failed" || step === "refunded" ? step : "payment",
96
+ step: step || "payment",
94
97
  state
95
98
  };
96
99
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/storefront-url/parse-v1.ts"],
4
- "sourcesContent": ["import { installationPath, normalizedPath, segment } from \"./installation\";\nimport {\n type StorefrontPageState,\n type StorefrontRoute,\n type StorefrontUrlInput,\n type StorefrontUrlOptions,\n} from \"./types\";\nimport { ITEM_MODAL_PREFIX, inputUrl, pageState } from \"./url\";\n\n/** Paths with no variable segment. Checked before ID_ROUTES: `/dine-in/menus` is not a dine-in order. */\nconst FIXED_ROUTES = {\n \"/dine-in/menus\": \"dine-in-menus\",\n \"/self-service/menus\": \"self-service-menus\",\n \"/collect-payment\": \"collect-payment\",\n \"/reservation\": \"reservation\",\n} as const;\n\n/** `/<prefix>/<id>` routes, where the one segment after the prefix names the resource. */\nconst ID_ROUTES = {\n \"dine-in\": (order, state) => ({ type: \"dine-in\", order, state }),\n \"pay-point\": (payPoint, state) => ({ type: \"pay-point\", payPoint, state }),\n beacons: (beacon, state) => ({ type: \"beacon\", beacon, state }),\n links: (link, state) => ({ type: \"link\", link, state }),\n pay: (session, state) => ({ type: \"pay-session\", session, state }),\n} satisfies Record<\n string,\n (id: string, state: StorefrontPageState) => StorefrontRoute\n>;\n\nconst isKeyOf = <T extends object>(\n table: T,\n key: string,\n): key is Extract<keyof T, string> => Object.hasOwn(table, key);\n\nexport const parseV1 = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions = {},\n): StorefrontRoute => {\n try {\n const url = inputUrl(input);\n const state = pageState(url, \"v1\");\n const pathname = installationPath(\n normalizedPath(url.pathname),\n options.installation,\n );\n const parts = pathname.split(\"/\").filter(Boolean);\n\n if (parts[0] === \"order\" && parts[1]) {\n const business = segment(parts, 1);\n if (parts[2] === \"pages\" && parts.length === 4) {\n return {\n type: \"content-page\",\n business,\n slug: segment(parts, 3),\n state,\n };\n }\n const branch = parts[2] ? segment(parts, 2) : undefined;\n if (branch && parts[3] === \"pages\" && parts.length === 5) {\n return {\n type: \"content-page\",\n business,\n branch,\n slug: segment(parts, 4),\n state,\n };\n }\n if (branch && parts[3] === \"products\" && parts[4] && parts.length === 5) {\n return {\n type: \"item\",\n business,\n branch,\n item: segment(parts, 4),\n state,\n };\n }\n if (\n parts.length <= 3 ||\n (parts.length === 4 && parts[3] === \"products\")\n ) {\n const modalItem = state.modalId?.startsWith(ITEM_MODAL_PREFIX)\n ? state.modalId.slice(ITEM_MODAL_PREFIX.length)\n : \"\";\n if (branch && modalItem) {\n return {\n type: \"item\",\n business,\n branch,\n item: modalItem,\n state,\n };\n }\n return {\n type: \"order-menu\",\n business,\n ...(branch ? { branch } : {}),\n ...(parts[3] === \"products\" ? { cataloguePath: true } : {}),\n state,\n };\n }\n }\n\n if (isKeyOf(FIXED_ROUTES, pathname)) {\n return { type: FIXED_ROUTES[pathname], state };\n }\n const [prefix = \"\", id] = parts;\n if (parts.length === 2 && id && isKeyOf(ID_ROUTES, prefix)) {\n return ID_ROUTES[prefix](segment(parts, 1), state);\n }\n if (\n parts[0] === \"payment\" &&\n parts[1] === \"card\" &&\n parts[2] &&\n parts.length === 3\n ) {\n return { type: \"payment-card\", transaction: segment(parts, 2), state };\n }\n if (parts[0] === \"payment\" && parts[1] && parts.length <= 3) {\n const step = parts[2];\n if (\n !step ||\n step === \"successful\" ||\n step === \"failed\" ||\n step === \"refunded\"\n ) {\n return {\n type: \"payment-step\",\n payment: segment(parts, 1),\n step:\n step === \"successful\" || step === \"failed\" || step === \"refunded\"\n ? step\n : \"payment\",\n state,\n };\n }\n }\n if (parts[0] === \"orders\" && parts.length <= 2) {\n return {\n type: \"profile\",\n page: \"orders\",\n ...(parts[1] ? { order: segment(parts, 1) } : {}),\n state,\n };\n }\n if (parts[0] === \"profile\" && parts[1] && parts.length <= 3) {\n const page = parts[1];\n if (\n page === \"add-store-credit\" ||\n page === \"edit\" ||\n page === \"payment-methods\" ||\n page === \"transactions\"\n ) {\n return { type: \"profile\", page, state };\n }\n if (page === \"orders\") {\n return {\n type: \"profile\",\n page,\n ...(parts[2] ? { order: segment(parts, 2) } : {}),\n state,\n };\n }\n }\n if (pathname === \"/\" || pathname === \"/explore\") {\n return {\n type: \"explore\",\n ...(pathname === \"/\" ? { home: true } : {}),\n state,\n };\n }\n return { type: \"unknown\", pathname, state };\n } catch {\n return { type: \"unknown\", pathname: \"\", state: { query: {} } };\n }\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { installationPath, normalizedPath, segment } from \"./installation\";\nimport {\n type StorefrontRoute,\n type StorefrontUrlInput,\n type StorefrontUrlOptions,\n} from \"./types\";\nimport { ITEM_MODAL_PREFIX, inputUrl, pageState } from \"./url\";\n\n/** Paths with no variable segment. Checked before ID_ROUTES: `/dine-in/menus` is not a dine-in order. */\nconst FIXED_ROUTES = {\n \"/dine-in/menus\": \"dine-in-menus\",\n \"/self-service/menus\": \"self-service-menus\",\n \"/collect-payment\": \"collect-payment\",\n \"/reservation\": \"reservation\",\n} as const;\n\n/** `/<prefix>/<id>` routes, where the one segment after the prefix names the resource. */\nconst ID_ROUTES = {\n \"dine-in\": [\"dine-in\", \"order\"],\n \"pay-point\": [\"pay-point\", \"payPoint\"],\n beacons: [\"beacon\", \"beacon\"],\n links: [\"link\", \"link\"],\n pay: [\"pay-session\", \"session\"],\n} as const;\n\nexport const parseV1 = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions = {},\n): StorefrontRoute => {\n try {\n const url = inputUrl(input);\n const state = pageState(url, \"v1\");\n const pathname = installationPath(\n normalizedPath(url.pathname),\n options.installation,\n );\n const parts = pathname.split(\"/\").filter(Boolean);\n\n if (parts[0] === \"order\" && parts[1]) {\n const business = segment(parts, 1);\n if (parts[2] === \"pages\" && parts.length === 4) {\n return {\n type: \"content-page\",\n business,\n slug: segment(parts, 3),\n state,\n };\n }\n const branch = parts[2] ? segment(parts, 2) : undefined;\n if (branch && parts[3] === \"pages\" && parts.length === 5) {\n return {\n type: \"content-page\",\n business,\n branch,\n slug: segment(parts, 4),\n state,\n };\n }\n if (branch && parts[3] === \"products\" && parts[4] && parts.length === 5) {\n return {\n type: \"item\",\n business,\n branch,\n item: segment(parts, 4),\n state,\n };\n }\n if (\n parts.length <= 3 ||\n (parts.length === 4 && parts[3] === \"products\")\n ) {\n const modalItem = state.modalId?.startsWith(ITEM_MODAL_PREFIX)\n ? state.modalId.slice(ITEM_MODAL_PREFIX.length)\n : \"\";\n if (branch && modalItem) {\n return {\n type: \"item\",\n business,\n branch,\n item: modalItem,\n state,\n };\n }\n return {\n type: \"order-menu\",\n business,\n ...(branch ? { branch } : {}),\n ...(parts[3] === \"products\" ? { cataloguePath: true } : {}),\n state,\n };\n }\n }\n\n if (Object.hasOwn(FIXED_ROUTES, pathname)) {\n return {\n type: FIXED_ROUTES[pathname as keyof typeof FIXED_ROUTES],\n state,\n };\n }\n const [prefix = \"\", id] = parts;\n if (parts.length === 2 && id && Object.hasOwn(ID_ROUTES, prefix)) {\n const [type, field] = ID_ROUTES[prefix as keyof typeof ID_ROUTES];\n return { type, [field]: segment(parts, 1), state } as StorefrontRoute;\n }\n if (\n parts[0] === \"payment\" &&\n parts[1] === \"card\" &&\n parts[2] &&\n parts.length === 3\n ) {\n return { type: \"payment-card\", transaction: segment(parts, 2), state };\n }\n if (parts[0] === \"payment\" && parts[1] && parts.length <= 3) {\n const step = parts[2];\n if (!step || [\"successful\", \"failed\", \"refunded\"].includes(step)) {\n return {\n type: \"payment-step\",\n payment: segment(parts, 1),\n step: (step || \"payment\") as Extract<\n StorefrontRoute,\n { type: \"payment-step\" }\n >[\"step\"],\n state,\n };\n }\n }\n if (parts[0] === \"orders\" && parts.length <= 2) {\n return {\n type: \"profile\",\n page: \"orders\",\n ...(parts[1] ? { order: segment(parts, 1) } : {}),\n state,\n };\n }\n if (parts[0] === \"profile\" && parts[1] && parts.length <= 3) {\n const page = parts[1];\n if (\n page === \"add-store-credit\" ||\n page === \"edit\" ||\n page === \"payment-methods\" ||\n page === \"transactions\"\n ) {\n return { type: \"profile\", page, state };\n }\n if (page === \"orders\") {\n return {\n type: \"profile\",\n page,\n ...(parts[2] ? { order: segment(parts, 2) } : {}),\n state,\n };\n }\n }\n if (pathname === \"/\" || pathname === \"/explore\") {\n return {\n type: \"explore\",\n ...(pathname === \"/\" ? { home: true } : {}),\n state,\n };\n }\n return { type: \"unknown\", pathname, state };\n } catch {\n return { type: \"unknown\", pathname: \"\", state: { query: {} } };\n }\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,69 +1,43 @@
1
1
  // src/server/storefront-url/parse-v2.ts
2
- import { CART_MODAL, CHECKOUT_MODAL, SIGN_IN_MODALS } from "./contract.js";
2
+ import { canonicalRoute } from "./canonical.js";
3
3
  import { normalizedPath, segment } from "./installation.js";
4
4
  import { parseV1 } from "./parse-v1.js";
5
- import { signInFromOverlay } from "./sign-in.js";
6
- import { ITEM_MODAL_PREFIX, inputUrl, pageState } from "./url.js";
7
- var branch = (url) => url.searchParams.has("branch") ? { branch: url.searchParams.get("branch") ?? "" } : {};
5
+ import { inputUrl, pageState } from "./url.js";
8
6
  var canonical = (url, state, business) => {
9
7
  const pathname = normalizedPath(url.pathname);
10
8
  const parts = pathname.split("/").filter(Boolean);
11
- const scoped = branch(url);
9
+ const branch = url.searchParams.get("branch");
10
+ const common = { business, ...branch !== null ? { branch } : {}, state };
12
11
  if (pathname === "/") {
13
- return { type: "order-menu", business, ...scoped, state };
12
+ return { type: "order-menu", ...common };
14
13
  }
15
14
  if (parts[0] === "item" && parts[1] && parts.length === 2) {
16
15
  return {
17
16
  type: "item",
18
- business,
19
- ...scoped,
20
- item: segment(parts, 1),
21
- state
17
+ ...common,
18
+ item: segment(parts, 1)
22
19
  };
23
20
  }
24
21
  if (pathname === "/cart" || pathname === "/checkout") {
25
22
  return {
26
23
  type: pathname === "/cart" ? "cart" : "checkout",
27
- business,
28
- ...scoped,
29
- state
24
+ ...common
30
25
  };
31
26
  }
32
- if (pathname === "/checkout/return") {
33
- const session = url.searchParams.get("session");
27
+ if (pathname === "/checkout/return" || pathname === "/sign-in") {
28
+ const signIn = pathname === "/sign-in";
29
+ const value = url.searchParams.get(signIn ? "return" : "session");
34
30
  return {
35
- type: "checkout-return",
36
- business,
37
- ...scoped,
38
- ...session !== null ? { session } : {},
39
- state
40
- };
41
- }
42
- if (pathname === "/sign-in") {
43
- const returnTo = url.searchParams.get("return");
44
- return {
45
- type: "sign-in",
46
- business,
47
- ...scoped,
48
- ...returnTo !== null ? { returnTo } : {},
49
- state
31
+ type: signIn ? "sign-in" : "checkout-return",
32
+ ...common,
33
+ ...value !== null ? { [signIn ? "returnTo" : "session"]: value } : {}
50
34
  };
51
35
  }
52
36
  if (parts[0] === "pages" && parts[1] && parts.length === 2) {
53
37
  return {
54
38
  type: "content-page",
55
- business,
56
- ...scoped,
57
- slug: segment(parts, 1),
58
- state
59
- };
60
- }
61
- if (parts[0] === "orders" && parts.length <= 2) {
62
- return {
63
- type: "profile",
64
- page: "orders",
65
- ...parts[1] ? { order: segment(parts, 1) } : {},
66
- state
39
+ ...common,
40
+ slug: segment(parts, 1)
67
41
  };
68
42
  }
69
43
  if (parts[0] === "account" && parts.length <= 2) {
@@ -86,49 +60,13 @@ var canonical = (url, state, business) => {
86
60
  }
87
61
  return null;
88
62
  };
89
- var overlay = (route, installation) => {
90
- if (route.type !== "order-menu") {
91
- return route;
92
- }
93
- const { authModalId, modalId } = route.state;
94
- if (authModalId && SIGN_IN_MODALS.has(authModalId)) {
95
- return signInFromOverlay(route, installation);
96
- }
97
- if (modalId?.startsWith(ITEM_MODAL_PREFIX)) {
98
- return {
99
- type: "item",
100
- business: route.business,
101
- ...route.branch !== void 0 ? { branch: route.branch } : {},
102
- item: modalId.slice(ITEM_MODAL_PREFIX.length),
103
- state: route.state
104
- };
105
- }
106
- if (modalId === CART_MODAL || modalId === CHECKOUT_MODAL) {
107
- return {
108
- type: modalId === CART_MODAL ? "cart" : "checkout",
109
- business: route.business,
110
- ...route.branch !== void 0 ? { branch: route.branch } : {},
111
- state: route.state
112
- };
113
- }
114
- return route;
115
- };
116
63
  var parseV2 = (input, options) => {
117
64
  try {
118
65
  const url = inputUrl(input);
119
66
  const state = pageState(url);
120
67
  const installation = options.installation;
121
- if (!installation) {
122
- return parseV1(input, options);
123
- }
124
68
  const route = canonical(url, state, installation.business);
125
- if (route) {
126
- return route.type === "order-menu" ? overlay(route, installation) : route;
127
- }
128
- return overlay(
129
- parseV1(input, { ...options, contract: "v1" }),
130
- installation
131
- );
69
+ return canonicalRoute(route ?? parseV1(input, options), installation);
132
70
  } catch {
133
71
  return { type: "unknown", pathname: "", state: { query: {} } };
134
72
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/storefront-url/parse-v2.ts"],
4
- "sourcesContent": ["import { CART_MODAL, CHECKOUT_MODAL, SIGN_IN_MODALS } from \"./contract\";\nimport { normalizedPath, segment } from \"./installation\";\nimport { parseV1 } from \"./parse-v1\";\nimport { signInFromOverlay } from \"./sign-in\";\nimport type {\n StorefrontPageState,\n StorefrontRoute,\n StorefrontUrlInput,\n StorefrontUrlOptions,\n} from \"./types\";\nimport { ITEM_MODAL_PREFIX, inputUrl, pageState } from \"./url\";\n\nconst branch = (url: URL) =>\n url.searchParams.has(\"branch\")\n ? { branch: url.searchParams.get(\"branch\") ?? \"\" }\n : {};\n\nconst canonical = (\n url: URL,\n state: StorefrontPageState,\n business: string,\n): StorefrontRoute | null => {\n const pathname = normalizedPath(url.pathname);\n const parts = pathname.split(\"/\").filter(Boolean);\n const scoped = branch(url);\n if (pathname === \"/\") {\n return { type: \"order-menu\", business, ...scoped, state };\n }\n if (parts[0] === \"item\" && parts[1] && parts.length === 2) {\n return {\n type: \"item\",\n business,\n ...scoped,\n item: segment(parts, 1),\n state,\n };\n }\n if (pathname === \"/cart\" || pathname === \"/checkout\") {\n return {\n type: pathname === \"/cart\" ? \"cart\" : \"checkout\",\n business,\n ...scoped,\n state,\n };\n }\n if (pathname === \"/checkout/return\") {\n const session = url.searchParams.get(\"session\");\n return {\n type: \"checkout-return\",\n business,\n ...scoped,\n ...(session !== null ? { session } : {}),\n state,\n };\n }\n if (pathname === \"/sign-in\") {\n const returnTo = url.searchParams.get(\"return\");\n return {\n type: \"sign-in\",\n business,\n ...scoped,\n ...(returnTo !== null ? { returnTo } : {}),\n state,\n };\n }\n if (parts[0] === \"pages\" && parts[1] && parts.length === 2) {\n return {\n type: \"content-page\",\n business,\n ...scoped,\n slug: segment(parts, 1),\n state,\n };\n }\n if (parts[0] === \"orders\" && parts.length <= 2) {\n return {\n type: \"profile\",\n page: \"orders\",\n ...(parts[1] ? { order: segment(parts, 1) } : {}),\n state,\n };\n }\n if (parts[0] === \"account\" && parts.length <= 2) {\n const pages = {\n \"payment-methods\": \"payment-methods\",\n transactions: \"transactions\",\n \"store-credit\": \"add-store-credit\",\n } as const;\n if (parts.length === 1) {\n return { type: \"profile\", page: \"edit\", state };\n }\n const page = parts[1];\n if (page && Object.hasOwn(pages, page)) {\n return {\n type: \"profile\",\n page: pages[page as keyof typeof pages],\n state,\n };\n }\n }\n return null;\n};\n\nconst overlay = (\n route: StorefrontRoute,\n installation: NonNullable<StorefrontUrlOptions[\"installation\"]>,\n): StorefrontRoute => {\n if (route.type !== \"order-menu\") {\n return route;\n }\n const { authModalId, modalId } = route.state;\n if (authModalId && SIGN_IN_MODALS.has(authModalId)) {\n return signInFromOverlay(route, installation);\n }\n if (modalId?.startsWith(ITEM_MODAL_PREFIX)) {\n return {\n type: \"item\",\n business: route.business,\n ...(route.branch !== undefined ? { branch: route.branch } : {}),\n item: modalId.slice(ITEM_MODAL_PREFIX.length),\n state: route.state,\n };\n }\n if (modalId === CART_MODAL || modalId === CHECKOUT_MODAL) {\n return {\n type: modalId === CART_MODAL ? \"cart\" : \"checkout\",\n business: route.business,\n ...(route.branch !== undefined ? { branch: route.branch } : {}),\n state: route.state,\n };\n }\n return route;\n};\n\nexport const parseV2 = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions,\n): StorefrontRoute => {\n try {\n const url = inputUrl(input);\n const state = pageState(url);\n const installation = options.installation;\n if (!installation) {\n return parseV1(input, options);\n }\n const route = canonical(url, state, installation.business);\n if (route) {\n return route.type === \"order-menu\" ? overlay(route, installation) : route;\n }\n return overlay(\n parseV1(input, { ...options, contract: \"v1\" }),\n installation,\n );\n } catch {\n return { type: \"unknown\", pathname: \"\", state: { query: {} } };\n }\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { canonicalRoute } from \"./canonical\";\nimport { normalizedPath, segment } from \"./installation\";\nimport { parseV1 } from \"./parse-v1\";\nimport type {\n StorefrontInstallation,\n StorefrontPageState,\n StorefrontRoute,\n StorefrontUrlInput,\n StorefrontUrlOptions,\n} from \"./types\";\nimport { inputUrl, pageState } from \"./url\";\n\nconst canonical = (\n url: URL,\n state: StorefrontPageState,\n business: string,\n): StorefrontRoute | null => {\n const pathname = normalizedPath(url.pathname);\n const parts = pathname.split(\"/\").filter(Boolean);\n const branch = url.searchParams.get(\"branch\");\n const common = { business, ...(branch !== null ? { branch } : {}), state };\n if (pathname === \"/\") {\n return { type: \"order-menu\", ...common };\n }\n if (parts[0] === \"item\" && parts[1] && parts.length === 2) {\n return {\n type: \"item\",\n ...common,\n item: segment(parts, 1),\n };\n }\n if (pathname === \"/cart\" || pathname === \"/checkout\") {\n return {\n type: pathname === \"/cart\" ? \"cart\" : \"checkout\",\n ...common,\n };\n }\n if (pathname === \"/checkout/return\" || pathname === \"/sign-in\") {\n const signIn = pathname === \"/sign-in\";\n const value = url.searchParams.get(signIn ? \"return\" : \"session\");\n return {\n type: signIn ? \"sign-in\" : \"checkout-return\",\n ...common,\n ...(value !== null ? { [signIn ? \"returnTo\" : \"session\"]: value } : {}),\n };\n }\n if (parts[0] === \"pages\" && parts[1] && parts.length === 2) {\n return {\n type: \"content-page\",\n ...common,\n slug: segment(parts, 1),\n };\n }\n if (parts[0] === \"account\" && parts.length <= 2) {\n const pages = {\n \"payment-methods\": \"payment-methods\",\n transactions: \"transactions\",\n \"store-credit\": \"add-store-credit\",\n } as const;\n if (parts.length === 1) {\n return { type: \"profile\", page: \"edit\", state };\n }\n const page = parts[1];\n if (page && Object.hasOwn(pages, page)) {\n return {\n type: \"profile\",\n page: pages[page as keyof typeof pages],\n state,\n };\n }\n }\n return null;\n};\n\nexport const parseV2 = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions & { installation: StorefrontInstallation },\n): StorefrontRoute => {\n try {\n const url = inputUrl(input);\n const state = pageState(url);\n const installation = options.installation;\n const route = canonical(url, state, installation.business);\n return canonicalRoute(route ?? parseV1(input, options), installation);\n } catch {\n return { type: \"unknown\", pathname: \"\", state: { query: {} } };\n }\n};\n"],
5
+ "mappings": ";AAAA,SAAS,sBAAsB;AAC/B,SAAS,gBAAgB,eAAe;AACxC,SAAS,eAAe;AAQxB,SAAS,UAAU,iBAAiB;AAEpC,IAAM,YAAY,CAChB,KACA,OACA,aAC2B;AAC3B,QAAM,WAAW,eAAe,IAAI,QAAQ;AAC5C,QAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAChD,QAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,QAAM,SAAS,EAAE,UAAU,GAAI,WAAW,OAAO,EAAE,OAAO,IAAI,CAAC,GAAI,MAAM;AACzE,MAAI,aAAa,KAAK;AACpB,WAAO,EAAE,MAAM,cAAc,GAAG,OAAO;AAAA,EACzC;AACA,MAAI,MAAM,CAAC,MAAM,UAAU,MAAM,CAAC,KAAK,MAAM,WAAW,GAAG;AACzD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,GAAG;AAAA,MACH,MAAM,QAAQ,OAAO,CAAC;AAAA,IACxB;AAAA,EACF;AACA,MAAI,aAAa,WAAW,aAAa,aAAa;AACpD,WAAO;AAAA,MACL,MAAM,aAAa,UAAU,SAAS;AAAA,MACtC,GAAG;AAAA,IACL;AAAA,EACF;AACA,MAAI,aAAa,sBAAsB,aAAa,YAAY;AAC9D,UAAM,SAAS,aAAa;AAC5B,UAAM,QAAQ,IAAI,aAAa,IAAI,SAAS,WAAW,SAAS;AAChE,WAAO;AAAA,MACL,MAAM,SAAS,YAAY;AAAA,MAC3B,GAAG;AAAA,MACH,GAAI,UAAU,OAAO,EAAE,CAAC,SAAS,aAAa,SAAS,GAAG,MAAM,IAAI,CAAC;AAAA,IACvE;AAAA,EACF;AACA,MAAI,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,KAAK,MAAM,WAAW,GAAG;AAC1D,WAAO;AAAA,MACL,MAAM;AAAA,MACN,GAAG;AAAA,MACH,MAAM,QAAQ,OAAO,CAAC;AAAA,IACxB;AAAA,EACF;AACA,MAAI,MAAM,CAAC,MAAM,aAAa,MAAM,UAAU,GAAG;AAC/C,UAAM,QAAQ;AAAA,MACZ,mBAAmB;AAAA,MACnB,cAAc;AAAA,MACd,gBAAgB;AAAA,IAClB;AACA,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO,EAAE,MAAM,WAAW,MAAM,QAAQ,MAAM;AAAA,IAChD;AACA,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,QAAQ,OAAO,OAAO,OAAO,IAAI,GAAG;AACtC,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM,MAAM,IAA0B;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,UAAU,CACrB,OACA,YACoB;AACpB,MAAI;AACF,UAAM,MAAM,SAAS,KAAK;AAC1B,UAAM,QAAQ,UAAU,GAAG;AAC3B,UAAM,eAAe,QAAQ;AAC7B,UAAM,QAAQ,UAAU,KAAK,OAAO,aAAa,QAAQ;AACzD,WAAO,eAAe,SAAS,QAAQ,OAAO,OAAO,GAAG,YAAY;AAAA,EACtE,QAAQ;AACN,WAAO,EAAE,MAAM,WAAW,UAAU,IAAI,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EAC/D;AACF;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,8 @@
1
+ // src/server/storefront-url/public-id.ts
2
+ var publicId = (value, prefix) => value.startsWith(`${prefix}_`) ? value : `${prefix}_${value}`;
3
+ var categoryHash = (category) => category ? `#c-${encodeURIComponent(publicId(category, "cat"))}` : "";
4
+ export {
5
+ categoryHash,
6
+ publicId
7
+ };
8
+ //# sourceMappingURL=public-id.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/server/storefront-url/public-id.ts"],
4
+ "sourcesContent": ["export const publicId = (value: string, prefix: string) =>\n value.startsWith(`${prefix}_`) ? value : `${prefix}_${value}`;\n\nexport const categoryHash = (category?: string) =>\n category ? `#c-${encodeURIComponent(publicId(category, \"cat\"))}` : \"\";\n"],
5
+ "mappings": ";AAAO,IAAM,WAAW,CAAC,OAAe,WACtC,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,QAAQ,GAAG,MAAM,IAAI,KAAK;AAEtD,IAAM,eAAe,CAAC,aAC3B,WAAW,MAAM,mBAAmB,SAAS,UAAU,KAAK,CAAC,CAAC,KAAK;",
6
+ "names": []
7
+ }
@@ -3,11 +3,10 @@ import { buildStorefrontUrl } from "./build.js";
3
3
  import { usesV2 } from "./contract.js";
4
4
  import { normalizedPath } from "./installation.js";
5
5
  import { parseStorefrontUrl } from "./parse.js";
6
- import { inputUrl } from "./url.js";
7
- var comparable = (value) => {
8
- const url = inputUrl(value);
6
+ import { inputUrl, isAttributionKey } from "./url.js";
7
+ var comparable = (url) => {
9
8
  url.searchParams.sort();
10
- return `${normalizedPath(url.pathname)}${url.search}`;
9
+ return `${normalizedPath(url.pathname)}${url.search}${url.hash}`;
11
10
  };
12
11
  var storefrontRedirect = (input, options = {}) => {
13
12
  if (!usesV2(options)) {
@@ -18,8 +17,23 @@ var storefrontRedirect = (input, options = {}) => {
18
17
  if (route.type === "unknown") {
19
18
  return null;
20
19
  }
21
- const target = buildStorefrontUrl(route, options);
22
- return comparable(inputUrl(input)) === comparable(target) ? null : target;
20
+ const targetUrl = inputUrl(buildStorefrontUrl(route, options));
21
+ const original = inputUrl(input);
22
+ for (const key of [...targetUrl.searchParams.keys()]) {
23
+ if (isAttributionKey(key)) {
24
+ targetUrl.searchParams.delete(key);
25
+ }
26
+ }
27
+ original.searchParams.forEach((value, key) => {
28
+ if (isAttributionKey(key)) {
29
+ targetUrl.searchParams.append(key, value);
30
+ }
31
+ });
32
+ const path = comparable(targetUrl);
33
+ if (comparable(original) === path) {
34
+ return null;
35
+ }
36
+ return options.origin ? targetUrl.href : path;
23
37
  } catch {
24
38
  return null;
25
39
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/storefront-url/redirect.ts"],
4
- "sourcesContent": ["import { buildStorefrontUrl } from \"./build\";\nimport { usesV2 } from \"./contract\";\nimport { normalizedPath } from \"./installation\";\nimport { parseStorefrontUrl } from \"./parse\";\nimport type { StorefrontUrlInput, StorefrontUrlOptions } from \"./types\";\nimport { inputUrl } from \"./url\";\n\nconst comparable = (value: string | URL) => {\n const url = inputUrl(value);\n url.searchParams.sort();\n return `${normalizedPath(url.pathname)}${url.search}`;\n};\n\n/**\n * Find the canonical v2 URL for a recognized storefront route.\n * Compares normalized paths and sorted query parameters to avoid unnecessary redirects.\n *\n * @returns A redirect target, or null for v1, an unknown route, a parse/build failure or an equivalent URL.\n */\nexport const storefrontRedirect = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions = {},\n): string | null => {\n if (!usesV2(options)) {\n return null;\n }\n try {\n const route = parseStorefrontUrl(input, options);\n if (route.type === \"unknown\") {\n return null;\n }\n const target = buildStorefrontUrl(route, options);\n return comparable(inputUrl(input)) === comparable(target) ? null : target;\n } catch {\n return null;\n }\n};\n"],
5
- "mappings": ";AAAA,SAAS,0BAA0B;AACnC,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AAEnC,SAAS,gBAAgB;AAEzB,IAAM,aAAa,CAAC,UAAwB;AAC1C,QAAM,MAAM,SAAS,KAAK;AAC1B,MAAI,aAAa,KAAK;AACtB,SAAO,GAAG,eAAe,IAAI,QAAQ,CAAC,GAAG,IAAI,MAAM;AACrD;AAQO,IAAM,qBAAqB,CAChC,OACA,UAAgC,CAAC,MACf;AAClB,MAAI,CAAC,OAAO,OAAO,GAAG;AACpB,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,QAAQ,mBAAmB,OAAO,OAAO;AAC/C,QAAI,MAAM,SAAS,WAAW;AAC5B,aAAO;AAAA,IACT;AACA,UAAM,SAAS,mBAAmB,OAAO,OAAO;AAChD,WAAO,WAAW,SAAS,KAAK,CAAC,MAAM,WAAW,MAAM,IAAI,OAAO;AAAA,EACrE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;",
4
+ "sourcesContent": ["import { buildStorefrontUrl } from \"./build\";\nimport { usesV2 } from \"./contract\";\nimport { normalizedPath } from \"./installation\";\nimport { parseStorefrontUrl } from \"./parse\";\nimport type { StorefrontUrlInput, StorefrontUrlOptions } from \"./types\";\nimport { inputUrl, isAttributionKey } from \"./url\";\n\nconst comparable = (url: URL) => {\n url.searchParams.sort();\n return `${normalizedPath(url.pathname)}${url.search}${url.hash}`;\n};\n\n/**\n * Find the canonical v2 URL for a recognized storefront route.\n * Compares normalized paths and sorted query parameters to avoid unnecessary redirects.\n *\n * Callers choose the HTTP status when serving the redirect.\n * Zappie templates use temporary redirects (302) for now.\n *\n * @returns A redirect target, or null for v1, an unknown route, a parse/build failure or an equivalent URL.\n */\nexport const storefrontRedirect = (\n input: StorefrontUrlInput,\n options: StorefrontUrlOptions = {},\n): string | null => {\n if (!usesV2(options)) {\n return null;\n }\n try {\n const route = parseStorefrontUrl(input, options);\n if (route.type === \"unknown\") {\n return null;\n }\n const targetUrl = inputUrl(buildStorefrontUrl(route, options));\n const original = inputUrl(input);\n for (const key of [...targetUrl.searchParams.keys()]) {\n if (isAttributionKey(key)) {\n targetUrl.searchParams.delete(key);\n }\n }\n original.searchParams.forEach((value, key) => {\n if (isAttributionKey(key)) {\n targetUrl.searchParams.append(key, value);\n }\n });\n const path = comparable(targetUrl);\n if (comparable(original) === path) {\n return null;\n }\n return options.origin ? targetUrl.href : path;\n } catch {\n return null;\n }\n};\n"],
5
+ "mappings": ";AAAA,SAAS,0BAA0B;AACnC,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AAEnC,SAAS,UAAU,wBAAwB;AAE3C,IAAM,aAAa,CAAC,QAAa;AAC/B,MAAI,aAAa,KAAK;AACtB,SAAO,GAAG,eAAe,IAAI,QAAQ,CAAC,GAAG,IAAI,MAAM,GAAG,IAAI,IAAI;AAChE;AAWO,IAAM,qBAAqB,CAChC,OACA,UAAgC,CAAC,MACf;AAClB,MAAI,CAAC,OAAO,OAAO,GAAG;AACpB,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,QAAQ,mBAAmB,OAAO,OAAO;AAC/C,QAAI,MAAM,SAAS,WAAW;AAC5B,aAAO;AAAA,IACT;AACA,UAAM,YAAY,SAAS,mBAAmB,OAAO,OAAO,CAAC;AAC7D,UAAM,WAAW,SAAS,KAAK;AAC/B,eAAW,OAAO,CAAC,GAAG,UAAU,aAAa,KAAK,CAAC,GAAG;AACpD,UAAI,iBAAiB,GAAG,GAAG;AACzB,kBAAU,aAAa,OAAO,GAAG;AAAA,MACnC;AAAA,IACF;AACA,aAAS,aAAa,QAAQ,CAAC,OAAO,QAAQ;AAC5C,UAAI,iBAAiB,GAAG,GAAG;AACzB,kBAAU,aAAa,OAAO,KAAK,KAAK;AAAA,MAC1C;AAAA,IACF,CAAC;AACD,UAAM,OAAO,WAAW,SAAS;AACjC,QAAI,WAAW,QAAQ,MAAM,MAAM;AACjC,aAAO;AAAA,IACT;AACA,WAAO,QAAQ,SAAS,UAAU,OAAO;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
1
  // src/server/storefront-url/sign-in.ts
2
2
  import { v2Params } from "./params.js";
3
+ import { categoryHash } from "./public-id.js";
3
4
  var signInFromOverlay = (route, installation) => {
4
5
  const params = v2Params(route, installation);
5
6
  params.delete("auth_modal_id");
@@ -8,7 +9,7 @@ var signInFromOverlay = (route, installation) => {
8
9
  type: "sign-in",
9
10
  business: route.business,
10
11
  state: { query: {} },
11
- returnTo: `/${search ? `?${search}` : ""}`
12
+ returnTo: `/${search ? `?${search}` : ""}${categoryHash(route.state.categoryId)}`
12
13
  };
13
14
  };
14
15
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/storefront-url/sign-in.ts"],
4
- "sourcesContent": ["import { v2Params } from \"./params\";\nimport type { StorefrontInstallation, StorefrontRoute } from \"./types\";\n\nexport const signInFromOverlay = (\n route: Extract<StorefrontRoute, { type: \"order-menu\" }>,\n installation: StorefrontInstallation,\n): Extract<StorefrontRoute, { type: \"sign-in\" }> => {\n const params = v2Params(route, installation);\n params.delete(\"auth_modal_id\");\n const search = params.toString();\n return {\n type: \"sign-in\",\n business: route.business,\n state: { query: {} },\n returnTo: `/${search ? `?${search}` : \"\"}`,\n };\n};\n"],
5
- "mappings": ";AAAA,SAAS,gBAAgB;AAGlB,IAAM,oBAAoB,CAC/B,OACA,iBACkD;AAClD,QAAM,SAAS,SAAS,OAAO,YAAY;AAC3C,SAAO,OAAO,eAAe;AAC7B,QAAM,SAAS,OAAO,SAAS;AAC/B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,OAAO,EAAE,OAAO,CAAC,EAAE;AAAA,IACnB,UAAU,IAAI,SAAS,IAAI,MAAM,KAAK,EAAE;AAAA,EAC1C;AACF;",
4
+ "sourcesContent": ["import { v2Params } from \"./params\";\nimport { categoryHash } from \"./public-id\";\nimport type { StorefrontInstallation, StorefrontRoute } from \"./types\";\n\nexport const signInFromOverlay = (\n route: Extract<StorefrontRoute, { type: \"order-menu\" }>,\n installation: StorefrontInstallation,\n): Extract<StorefrontRoute, { type: \"sign-in\" }> => {\n const params = v2Params(route, installation);\n params.delete(\"auth_modal_id\");\n const search = params.toString();\n return {\n type: \"sign-in\",\n business: route.business,\n state: { query: {} },\n returnTo: `/${search ? `?${search}` : \"\"}${categoryHash(route.state.categoryId)}`,\n };\n};\n"],
5
+ "mappings": ";AAAA,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAGtB,IAAM,oBAAoB,CAC/B,OACA,iBACkD;AAClD,QAAM,SAAS,SAAS,OAAO,YAAY;AAC3C,SAAO,OAAO,eAAe;AAC7B,QAAM,SAAS,OAAO,SAAS;AAC/B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,OAAO,EAAE,OAAO,CAAC,EAAE;AAAA,IACnB,UAAU,IAAI,SAAS,IAAI,MAAM,KAAK,EAAE,GAAG,aAAa,MAAM,MAAM,UAAU,CAAC;AAAA,EACjF;AACF;",
6
6
  "names": []
7
7
  }
@@ -45,6 +45,7 @@ var STOREFRONT_V1_QUERY_PARAMETERS = [
45
45
  ];
46
46
  var STOREFRONT_QUERY_PARAMETERS = [
47
47
  ...STOREFRONT_V1_QUERY_PARAMETERS,
48
+ "menu",
48
49
  "return",
49
50
  "session"
50
51
  ];
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/storefront-url/types.ts"],
4
- "sourcesContent": ["/**\n * A URL string, URL object or Request you can parse as a storefront route.\n */\nexport type StorefrontUrlInput = string | URL | Request;\n\n/**\n * The business and optional default branch bound to an installed storefront.\n */\nexport type StorefrontInstallation = {\n business: string;\n defaultBranch?: string;\n};\n\n/**\n * URL contract, installation and origin settings for parsing and building storefront routes.\n * An installation selects v2 unless you explicitly request v1.\n */\nexport type StorefrontUrlOptions = {\n contract?: \"v1\" | \"v2\";\n installation?: StorefrontInstallation;\n origin?: string;\n};\n\n/** Query keys that URL contract v1 keeps. */\nexport const STOREFRONT_V1_QUERY_PARAMETERS = [\n \"ref\",\n \"utm_source\",\n \"payment_id\",\n \"context\",\n \"prefetch\",\n \"business_tag\",\n \"pay_point_id\",\n \"dine_in_order_id\",\n \"no_context\",\n \"payment_context_id\",\n \"ws\",\n \"preview\",\n \"device\",\n \"auto_scroll\",\n \"pickup\",\n \"branch_closed\",\n \"order_id\",\n \"modal_id\",\n \"lightbox\",\n \"menu_id\",\n \"payment_method\",\n \"beacon_id\",\n \"menu_group_id\",\n \"category_id\",\n \"menu_layout\",\n \"can_schedule\",\n \"refresh\",\n \"success\",\n \"grant\",\n \"portal\",\n \"can_download_receipt\",\n \"auth_modal_id\",\n \"experimental_otp\",\n \"branch\",\n \"business\",\n \"env\",\n \"switched_branch\",\n \"from\",\n \"template\",\n \"catalog_rendering\",\n \"catalogue_search\",\n \"catalogue_categories\",\n] as const;\n\n/**\n * Recognized storefront query keys, including the v1 keys and checkout return and session keys.\n */\nexport const STOREFRONT_QUERY_PARAMETERS = [\n ...STOREFRONT_V1_QUERY_PARAMETERS,\n \"return\",\n \"session\",\n] as const;\n\n/**\n * Readonly query parameter names and string values carried by storefront page state.\n */\nexport type StorefrontQuery = Readonly<Record<string, string>>;\n\n/**\n * Query parameters and named UI selections carried alongside a storefront route.\n */\nexport type StorefrontPageState = {\n query: StorefrontQuery;\n menuId?: string;\n categoryId?: string;\n menuLayout?: string;\n mode?: \"delivery\" | \"pickup\";\n modalId?: string;\n authModalId?: string;\n paymentId?: string;\n lightbox?: string;\n catalogueSearch?: string;\n catalogueCategories?: string;\n};\n\nexport type WithState = { state: StorefrontPageState };\n\n/**\n * A parsed storefront destination with its route identifiers and page state.\n * Unrecognized paths use the unknown variant.\n */\nexport type StorefrontRoute =\n | ({\n type: \"order-menu\";\n business: string;\n branch?: string;\n cataloguePath?: boolean;\n } & WithState)\n | ({\n type: \"item\";\n business: string;\n branch?: string;\n item: string;\n } & WithState)\n | ({ type: \"cart\"; business: string; branch?: string } & WithState)\n | ({ type: \"checkout\"; business: string; branch?: string } & WithState)\n | ({\n type: \"checkout-return\";\n business: string;\n branch?: string;\n session?: string;\n } & WithState)\n | ({\n type: \"sign-in\";\n business: string;\n branch?: string;\n returnTo?: string;\n } & WithState)\n | ({\n type: \"content-page\";\n business: string;\n slug: string;\n branch?: string;\n } & WithState)\n | ({ type: \"dine-in\"; order: string } & WithState)\n | ({ type: \"dine-in-menus\" } & WithState)\n | ({ type: \"self-service-menus\" } & WithState)\n | ({ type: \"pay-point\"; payPoint: string } & WithState)\n | ({ type: \"beacon\"; beacon: string } & WithState)\n | ({ type: \"link\"; link: string } & WithState)\n | ({ type: \"collect-payment\" } & WithState)\n | ({ type: \"reservation\" } & WithState)\n | ({ type: \"pay-session\"; session: string } & WithState)\n | ({\n type: \"payment-step\";\n payment: string;\n step: \"payment\" | \"successful\" | \"failed\" | \"refunded\";\n } & WithState)\n | ({\n type: \"payment-card\";\n transaction: string;\n } & WithState)\n | ({\n type: \"profile\";\n page:\n | \"add-store-credit\"\n | \"edit\"\n | \"orders\"\n | \"payment-methods\"\n | \"transactions\";\n order?: string;\n } & WithState)\n | ({ type: \"explore\"; home?: boolean } & WithState)\n | ({ type: \"unknown\"; pathname: string } & WithState);\n"],
5
- "mappings": ";AAwBO,IAAM,iCAAiC;AAAA,EAC5C;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;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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,8BAA8B;AAAA,EACzC,GAAG;AAAA,EACH;AAAA,EACA;AACF;",
4
+ "sourcesContent": ["/**\n * A URL string, URL object or Request you can parse as a storefront route.\n */\nexport type StorefrontUrlInput = string | URL | Request;\n\n/**\n * The business and optional default branch bound to an installed storefront.\n */\nexport type StorefrontInstallation = {\n business: string;\n defaultBranch?: string;\n};\n\n/**\n * URL contract, installation and origin settings for parsing and building storefront routes.\n * An installation selects v2 unless you explicitly request v1.\n */\nexport type StorefrontUrlOptions = {\n contract?: \"v1\" | \"v2\";\n installation?: StorefrontInstallation;\n origin?: string;\n};\n\n/** Query keys that URL contract v1 keeps. */\nexport const STOREFRONT_V1_QUERY_PARAMETERS = [\n \"ref\",\n \"utm_source\",\n \"payment_id\",\n \"context\",\n \"prefetch\",\n \"business_tag\",\n \"pay_point_id\",\n \"dine_in_order_id\",\n \"no_context\",\n \"payment_context_id\",\n \"ws\",\n \"preview\",\n \"device\",\n \"auto_scroll\",\n \"pickup\",\n \"branch_closed\",\n \"order_id\",\n \"modal_id\",\n \"lightbox\",\n \"menu_id\",\n \"payment_method\",\n \"beacon_id\",\n \"menu_group_id\",\n \"category_id\",\n \"menu_layout\",\n \"can_schedule\",\n \"refresh\",\n \"success\",\n \"grant\",\n \"portal\",\n \"can_download_receipt\",\n \"auth_modal_id\",\n \"experimental_otp\",\n \"branch\",\n \"business\",\n \"env\",\n \"switched_branch\",\n \"from\",\n \"template\",\n \"catalog_rendering\",\n \"catalogue_search\",\n \"catalogue_categories\",\n] as const;\n\n/**\n * Recognized storefront query keys, including the v1 keys and checkout return and session keys.\n */\nexport const STOREFRONT_QUERY_PARAMETERS = [\n ...STOREFRONT_V1_QUERY_PARAMETERS,\n \"menu\",\n \"return\",\n \"session\",\n] as const;\n\n/**\n * Readonly query parameter names and string values carried by storefront page state.\n */\nexport type StorefrontQuery = Readonly<Record<string, string>>;\n\n/**\n * Query parameters and named UI selections carried alongside a storefront route.\n */\nexport type StorefrontPageState = {\n query: StorefrontQuery;\n menuId?: string;\n categoryId?: string;\n menuLayout?: string;\n mode?: \"delivery\" | \"pickup\";\n modalId?: string;\n authModalId?: string;\n paymentId?: string;\n lightbox?: string;\n catalogueSearch?: string;\n catalogueCategories?: string;\n};\n\nexport type WithState = { state: StorefrontPageState };\n\n/**\n * A parsed storefront destination with its route identifiers and page state.\n * Unrecognized paths use the unknown variant.\n */\nexport type StorefrontRoute =\n | ({\n type: \"order-menu\";\n business: string;\n branch?: string;\n cataloguePath?: boolean;\n } & WithState)\n | ({\n type: \"item\";\n business: string;\n branch?: string;\n item: string;\n } & WithState)\n | ({ type: \"cart\"; business: string; branch?: string } & WithState)\n | ({ type: \"checkout\"; business: string; branch?: string } & WithState)\n | ({\n type: \"checkout-return\";\n business: string;\n branch?: string;\n session?: string;\n } & WithState)\n | ({\n type: \"sign-in\";\n business: string;\n branch?: string;\n returnTo?: string;\n } & WithState)\n | ({\n type: \"content-page\";\n business: string;\n slug: string;\n branch?: string;\n } & WithState)\n | ({ type: \"dine-in\"; order: string } & WithState)\n | ({ type: \"dine-in-menus\" } & WithState)\n | ({ type: \"self-service-menus\" } & WithState)\n | ({ type: \"pay-point\"; payPoint: string } & WithState)\n | ({ type: \"beacon\"; beacon: string } & WithState)\n | ({ type: \"link\"; link: string } & WithState)\n | ({ type: \"collect-payment\" } & WithState)\n | ({ type: \"reservation\" } & WithState)\n | ({ type: \"pay-session\"; session: string } & WithState)\n | ({\n type: \"payment-step\";\n payment: string;\n step: \"payment\" | \"successful\" | \"failed\" | \"refunded\";\n } & WithState)\n | ({\n type: \"payment-card\";\n transaction: string;\n } & WithState)\n | ({\n type: \"profile\";\n page:\n | \"add-store-credit\"\n | \"edit\"\n | \"orders\"\n | \"payment-methods\"\n | \"transactions\";\n order?: string;\n } & WithState)\n | ({ type: \"explore\"; home?: boolean } & WithState)\n | ({ type: \"unknown\"; pathname: string } & WithState);\n"],
5
+ "mappings": ";AAwBO,IAAM,iCAAiC;AAAA,EAC5C;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;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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,8BAA8B;AAAA,EACzC,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": []
7
7
  }