@websolutespa/bom-next 3.0.2 → 4.0.0-next.0

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 (234) hide show
  1. package/CHANGELOG.md +17 -7
  2. package/dist/_virtual/{_rolldown/runtime.js → rolldown_runtime.js} +7 -4
  3. package/dist/client/client.d.ts.map +1 -1
  4. package/dist/client/client.js +17 -6
  5. package/dist/client/client.js.map +1 -1
  6. package/dist/client/extra.d.ts +3 -3
  7. package/dist/client/extra.d.ts.map +1 -1
  8. package/dist/client/extra.js +10 -5
  9. package/dist/client/extra.js.map +1 -1
  10. package/dist/client/label.d.ts.map +1 -1
  11. package/dist/client/label.js +10 -5
  12. package/dist/client/label.js.map +1 -1
  13. package/dist/client/layout.d.ts +3 -3
  14. package/dist/client/layout.d.ts.map +1 -1
  15. package/dist/client/layout.js +10 -5
  16. package/dist/client/layout.js.map +1 -1
  17. package/dist/client/local.collection.d.ts.map +1 -1
  18. package/dist/client/local.collection.js +4 -2
  19. package/dist/client/local.collection.js.map +1 -1
  20. package/dist/client/metadata.d.ts +3 -3
  21. package/dist/client/metadata.d.ts.map +1 -1
  22. package/dist/client/metadata.js +48 -40
  23. package/dist/client/metadata.js.map +1 -1
  24. package/dist/client/page.d.ts +3 -3
  25. package/dist/client/page.d.ts.map +1 -1
  26. package/dist/client/page.js +10 -5
  27. package/dist/client/page.js.map +1 -1
  28. package/dist/client/useApi.d.ts +7 -7
  29. package/dist/client/useApi.d.ts.map +1 -1
  30. package/dist/client/useApi.js +2 -1
  31. package/dist/client/useApi.js.map +1 -1
  32. package/dist/client/useCollectionApi.d.ts +6 -6
  33. package/dist/client/useCollectionApi.d.ts.map +1 -1
  34. package/dist/client/useCollectionApi.js +4 -2
  35. package/dist/client/useCollectionApi.js.map +1 -1
  36. package/dist/client/useExtra.d.ts.map +1 -1
  37. package/dist/client/useExtra.js +5 -2
  38. package/dist/client/useExtra.js.map +1 -1
  39. package/dist/client/useHttp.d.ts.map +1 -1
  40. package/dist/client/useHttp.js +9 -6
  41. package/dist/client/useHttp.js.map +1 -1
  42. package/dist/client/useLabel.d.ts.map +1 -1
  43. package/dist/client/useLabel.js +5 -2
  44. package/dist/client/useLabel.js.map +1 -1
  45. package/dist/client/useLayout.d.ts.map +1 -1
  46. package/dist/client/useLayout.js +5 -2
  47. package/dist/client/useLayout.js.map +1 -1
  48. package/dist/client/useLink.d.ts.map +1 -1
  49. package/dist/client/useLink.js +7 -3
  50. package/dist/client/useLink.js.map +1 -1
  51. package/dist/client/useMetaData.d.ts.map +1 -1
  52. package/dist/client/useMetaData.js +5 -2
  53. package/dist/client/useMetaData.js.map +1 -1
  54. package/dist/client/usePage.d.ts.map +1 -1
  55. package/dist/client/usePage.js +5 -2
  56. package/dist/client/usePage.js.map +1 -1
  57. package/dist/client/useUser.d.ts.map +1 -1
  58. package/dist/client/useUser.js +5 -2
  59. package/dist/client/useUser.js.map +1 -1
  60. package/dist/client/user.d.ts.map +1 -1
  61. package/dist/client/user.js +17 -11
  62. package/dist/client/user.js.map +1 -1
  63. package/dist/exports/client.js +2 -1
  64. package/dist/exports/instrumentation.js +2 -1
  65. package/dist/exports/proxy.js +2 -1
  66. package/dist/exports/server.js +2 -1
  67. package/dist/index.js +2 -1
  68. package/dist/instrumentation/client.d.ts.map +1 -1
  69. package/dist/instrumentation/client.js +2 -1
  70. package/dist/instrumentation/client.js.map +1 -1
  71. package/dist/instrumentation/sentry/capture.requestError.js +4 -1
  72. package/dist/instrumentation/sentry/capture.requestError.js.map +1 -1
  73. package/dist/instrumentation/sentry/capture.routerTransitionStart.js +2 -1
  74. package/dist/instrumentation/sentry/capture.routerTransitionStart.js.map +1 -1
  75. package/dist/instrumentation/sentry/config.client.js +10 -2
  76. package/dist/instrumentation/sentry/config.client.js.map +1 -0
  77. package/dist/instrumentation/sentry/config.edge.js +10 -2
  78. package/dist/instrumentation/sentry/config.edge.js.map +1 -0
  79. package/dist/instrumentation/sentry/config.server.js +10 -2
  80. package/dist/instrumentation/sentry/config.server.js.map +1 -0
  81. package/dist/instrumentation/server.d.ts.map +1 -1
  82. package/dist/instrumentation/server.js +8 -5
  83. package/dist/instrumentation/server.js.map +1 -1
  84. package/dist/instrumentation/types.d.ts.map +1 -1
  85. package/dist/lib/breadcrumb.d.ts.map +1 -1
  86. package/dist/lib/breadcrumb.js +6 -1
  87. package/dist/lib/breadcrumb.js.map +1 -1
  88. package/dist/lib/const.d.ts.map +1 -1
  89. package/dist/lib/const.js +1 -1
  90. package/dist/lib/const.js.map +1 -1
  91. package/dist/lib/http.d.ts.map +1 -1
  92. package/dist/lib/http.js +6 -3
  93. package/dist/lib/http.js.map +1 -1
  94. package/dist/lib/label.d.ts.map +1 -1
  95. package/dist/lib/label.js +4 -3
  96. package/dist/lib/label.js.map +1 -1
  97. package/dist/lib/layout.defaults.d.ts.map +1 -1
  98. package/dist/lib/layout.defaults.js +1 -1
  99. package/dist/lib/layout.defaults.js.map +1 -1
  100. package/dist/lib/link.d.ts.map +1 -1
  101. package/dist/lib/link.js +2 -1
  102. package/dist/lib/link.js.map +1 -1
  103. package/dist/lib/meta-data.d.ts.map +1 -1
  104. package/dist/lib/open-graph.d.ts.map +1 -1
  105. package/dist/lib/pagination.d.ts.map +1 -1
  106. package/dist/lib/pagination.js +4 -2
  107. package/dist/lib/pagination.js.map +1 -1
  108. package/dist/lib/route.d.ts.map +1 -1
  109. package/dist/lib/route.js +9 -3
  110. package/dist/lib/route.js.map +1 -1
  111. package/dist/lib/store.d.ts.map +1 -1
  112. package/dist/lib/store.js +31 -31
  113. package/dist/lib/store.js.map +1 -1
  114. package/dist/lib/structured-data.d.ts.map +1 -1
  115. package/dist/lib/twitter-card.d.ts.map +1 -1
  116. package/dist/lib/utils.d.ts.map +1 -1
  117. package/dist/lib/utils.js +3 -2
  118. package/dist/lib/utils.js.map +1 -1
  119. package/dist/mock.d.ts.map +1 -1
  120. package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js +3 -2
  121. package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js.map +1 -1
  122. package/dist/node_modules/deepmerge/dist/cjs.js +17 -9
  123. package/dist/node_modules/deepmerge/dist/cjs.js.map +1 -1
  124. package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js +2 -2
  125. package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js.map +1 -1
  126. package/dist/node_modules/dom-serializer/lib/esm/index.js +10 -15
  127. package/dist/node_modules/dom-serializer/lib/esm/index.js.map +1 -1
  128. package/dist/node_modules/domelementtype/lib/esm/index.js +12 -12
  129. package/dist/node_modules/domelementtype/lib/esm/index.js.map +1 -1
  130. package/dist/node_modules/domhandler/lib/esm/index.js +4 -3
  131. package/dist/node_modules/domhandler/lib/esm/index.js.map +1 -1
  132. package/dist/node_modules/domhandler/lib/esm/node.js +8 -7
  133. package/dist/node_modules/domhandler/lib/esm/node.js.map +1 -1
  134. package/dist/node_modules/entities/lib/esm/decode.js +33 -32
  135. package/dist/node_modules/entities/lib/esm/decode.js.map +1 -1
  136. package/dist/node_modules/entities/lib/esm/decode_codepoint.js +5 -5
  137. package/dist/node_modules/entities/lib/esm/decode_codepoint.js.map +1 -1
  138. package/dist/node_modules/entities/lib/esm/escape.js +14 -6
  139. package/dist/node_modules/entities/lib/esm/escape.js.map +1 -1
  140. package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js +2 -2
  141. package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js.map +1 -1
  142. package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js +2 -2
  143. package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js.map +1 -1
  144. package/dist/node_modules/html-to-text/lib/html-to-text.js +45 -33
  145. package/dist/node_modules/html-to-text/lib/html-to-text.js.map +1 -1
  146. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js +25 -25
  147. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js.map +1 -1
  148. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js +76 -73
  149. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js.map +1 -1
  150. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js +4 -3
  151. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js.map +1 -1
  152. package/dist/node_modules/leac/lib/leac.js +72 -72
  153. package/dist/node_modules/leac/lib/leac.js.map +1 -1
  154. package/dist/node_modules/parseley/lib/parseley.js +37 -33
  155. package/dist/node_modules/parseley/lib/parseley.js.map +1 -1
  156. package/dist/node_modules/peberminta/lib/core.js +4 -4
  157. package/dist/node_modules/peberminta/lib/core.js.map +1 -1
  158. package/dist/node_modules/selderee/lib/selderee.js +16 -10
  159. package/dist/node_modules/selderee/lib/selderee.js.map +1 -1
  160. package/dist/proxy/protected-route.d.ts.map +1 -1
  161. package/dist/proxy/protected-route.js +11 -6
  162. package/dist/proxy/protected-route.js.map +1 -1
  163. package/dist/proxy/proxy.d.ts.map +1 -1
  164. package/dist/proxy/proxy.js +17 -2
  165. package/dist/proxy/proxy.js.map +1 -1
  166. package/dist/proxy/route-auto-detection.d.ts.map +1 -1
  167. package/dist/proxy/route-auto-detection.js +26 -14
  168. package/dist/proxy/route-auto-detection.js.map +1 -1
  169. package/dist/proxy/route-proxy.d.ts.map +1 -1
  170. package/dist/proxy/route-proxy.js +22 -5
  171. package/dist/proxy/route-proxy.js.map +1 -1
  172. package/dist/server/context.d.ts.map +1 -1
  173. package/dist/server/context.js +20 -2
  174. package/dist/server/context.js.map +1 -1
  175. package/dist/server/handlers/auth.handler.d.ts.map +1 -1
  176. package/dist/server/handlers/auth.handler.js +4 -2
  177. package/dist/server/handlers/auth.handler.js.map +1 -1
  178. package/dist/server/handlers/captions.handler.d.ts.map +1 -1
  179. package/dist/server/handlers/captions.handler.js +4 -2
  180. package/dist/server/handlers/captions.handler.js.map +1 -1
  181. package/dist/server/handlers/collection.handler.d.ts.map +1 -1
  182. package/dist/server/handlers/collection.handler.js +2 -1
  183. package/dist/server/handlers/collection.handler.js.map +1 -1
  184. package/dist/server/handlers/error-response.js +6 -2
  185. package/dist/server/handlers/error-response.js.map +1 -1
  186. package/dist/server/handlers/index.handler.d.ts.map +1 -1
  187. package/dist/server/handlers/index.handler.js +2 -1
  188. package/dist/server/handlers/index.handler.js.map +1 -1
  189. package/dist/server/handlers/preview.handler.d.ts.map +1 -1
  190. package/dist/server/handlers/preview.handler.js +6 -3
  191. package/dist/server/handlers/preview.handler.js.map +1 -1
  192. package/dist/server/handlers/registry.handler.d.ts.map +1 -1
  193. package/dist/server/handlers/registry.handler.js +14 -9
  194. package/dist/server/handlers/registry.handler.js.map +1 -1
  195. package/dist/server/handlers/route.handler.d.ts.map +1 -1
  196. package/dist/server/handlers/route.handler.js +12 -3
  197. package/dist/server/handlers/route.handler.js.map +1 -1
  198. package/dist/server/handlers/sitemap.handler.d.ts.map +1 -1
  199. package/dist/server/handlers/sitemap.handler.js +12 -9
  200. package/dist/server/handlers/sitemap.handler.js.map +1 -1
  201. package/dist/server/handlers/static-params.handler.d.ts.map +1 -1
  202. package/dist/server/handlers/static-params.handler.js +13 -8
  203. package/dist/server/handlers/static-params.handler.js.map +1 -1
  204. package/dist/server/handlers/vars.handler.d.ts.map +1 -1
  205. package/dist/server/handlers/vars.handler.js +5 -4
  206. package/dist/server/handlers/vars.handler.js.map +1 -1
  207. package/dist/server/layout.js +34 -12
  208. package/dist/server/layout.js.map +1 -1
  209. package/dist/server/lazy.d.ts.map +1 -1
  210. package/dist/server/lazy.js +5 -2
  211. package/dist/server/lazy.js.map +1 -1
  212. package/dist/server/local-api.d.ts.map +1 -1
  213. package/dist/server/local-api.js +12 -6
  214. package/dist/server/local-api.js.map +1 -1
  215. package/dist/server/metadata.d.ts.map +1 -1
  216. package/dist/server/metadata.js +5 -1
  217. package/dist/server/metadata.js.map +1 -1
  218. package/dist/server/mixer-payload.d.ts +1 -1
  219. package/dist/server/mixer-payload.d.ts.map +1 -1
  220. package/dist/server/mixer.d.ts.map +1 -1
  221. package/dist/server/mixer.js +183 -57
  222. package/dist/server/mixer.js.map +1 -1
  223. package/dist/server/page.d.ts.map +1 -1
  224. package/dist/server/page.js +15 -4
  225. package/dist/server/page.js.map +1 -1
  226. package/dist/server/utils.d.ts.map +1 -1
  227. package/dist/server/utils.js +4 -2
  228. package/dist/server/utils.js.map +1 -1
  229. package/dist/server/utmz.d.ts.map +1 -1
  230. package/dist/server/utmz.js +1 -1
  231. package/dist/server/utmz.js.map +1 -1
  232. package/dist/types.d.ts +1 -1
  233. package/dist/types.d.ts.map +1 -1
  234. package/package.json +11 -11
@@ -1,5 +1,6 @@
1
1
  import { compareSpecificity, normalize, parse1, serialize } from "../../parseley/lib/parseley.js";
2
- //#region ../../node_modules/selderee/lib/selderee.mjs
2
+
3
+ //#region ../../../node_modules/selderee/lib/selderee.mjs
3
4
  var DecisionTree = class {
4
5
  constructor(input) {
5
6
  this.branches = weave(toAstTerminalPairs(input));
@@ -64,7 +65,9 @@ function reduceSelectorVariants(ast) {
64
65
  newList.push(sel);
65
66
  break;
66
67
  case "universal": break;
67
- default: newList.push(sel);
68
+ default:
69
+ newList.push(sel);
70
+ break;
68
71
  }
69
72
  });
70
73
  ast.list = newList;
@@ -102,8 +105,10 @@ function breakByKind(items, selectedKind) {
102
105
  const empty = [];
103
106
  for (const item of items) {
104
107
  const simpsels = item.ast.list;
105
- if (simpsels.length) (simpsels.some((node) => getSelectorKind(node) === selectedKind) ? matches : nonmatches).push(item);
106
- else empty.push(item);
108
+ if (simpsels.length) {
109
+ const isMatch = simpsels.some((node) => getSelectorKind(node) === selectedKind);
110
+ (isMatch ? matches : nonmatches).push(item);
111
+ } else empty.push(item);
107
112
  }
108
113
  return {
109
114
  matches,
@@ -129,13 +134,14 @@ function branchOfKind(kind, items) {
129
134
  }
130
135
  function tagNameBranch(items) {
131
136
  const groups = spliceAndGroup(items, (x) => x.type === "tag", (x) => x.name);
137
+ const variants = Object.entries(groups).map(([name, group]) => ({
138
+ type: "variant",
139
+ value: name,
140
+ cont: weave(group.items)
141
+ }));
132
142
  return {
133
143
  type: "tagName",
134
- variants: Object.entries(groups).map(([name, group]) => ({
135
- type: "variant",
136
- value: name,
137
- cont: weave(group.items)
138
- }))
144
+ variants
139
145
  };
140
146
  }
141
147
  function attrPresenceBranch(name, items) {
@@ -313,7 +319,7 @@ function comparatorPreferLast(acc, next) {
313
319
  const diff = compareSpecificity(next.specificity, acc.specificity);
314
320
  return diff > 0 || diff === 0 && next.index > acc.index;
315
321
  }
322
+
316
323
  //#endregion
317
324
  export { DecisionTree, Picker };
318
-
319
325
  //# sourceMappingURL=selderee.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"selderee.js","names":["parseley.parse1","parseley.serialize"],"sources":["../../../../../../node_modules/selderee/lib/selderee.mjs"],"sourcesContent":["import * as parseley from 'parseley';\nimport { compareSpecificity } from 'parseley';\n\nvar Ast = /*#__PURE__*/Object.freeze({\n __proto__: null\n});\n\nvar Types = /*#__PURE__*/Object.freeze({\n __proto__: null\n});\n\nconst treeify = (nodes) => '▽\\n' + treeifyArray(nodes, thinLines);\nconst thinLines = [['├─', '│ '], ['└─', ' ']];\nconst heavyLines = [['┠─', '┃ '], ['┖─', ' ']];\nconst doubleLines = [['╟─', '║ '], ['╙─', ' ']];\nfunction treeifyArray(nodes, tpl = heavyLines) {\n return prefixItems(tpl, nodes.map(n => treeifyNode(n)));\n}\nfunction treeifyNode(node) {\n switch (node.type) {\n case 'terminal': {\n const vctr = node.valueContainer;\n return `◁ #${vctr.index} ${JSON.stringify(vctr.specificity)} ${vctr.value}`;\n }\n case 'tagName':\n return `◻ Tag name\\n${treeifyArray(node.variants, doubleLines)}`;\n case 'attrValue':\n return `▣ Attr value: ${node.name}\\n${treeifyArray(node.matchers, doubleLines)}`;\n case 'attrPresence':\n return `◨ Attr presence: ${node.name}\\n${treeifyArray(node.cont)}`;\n case 'pushElement':\n return `◉ Push element: ${node.combinator}\\n${treeifyArray(node.cont, thinLines)}`;\n case 'popElement':\n return `◌ Pop element\\n${treeifyArray(node.cont, thinLines)}`;\n case 'variant':\n return `◇ = ${node.value}\\n${treeifyArray(node.cont)}`;\n case 'matcher':\n return `◈ ${node.matcher} \"${node.value}\"${node.modifier || ''}\\n${treeifyArray(node.cont)}`;\n }\n}\nfunction prefixItems(tpl, items) {\n return items\n .map((item, i, { length }) => prefixItem(tpl, item, i === length - 1))\n .join('\\n');\n}\nfunction prefixItem(tpl, item, tail = true) {\n const tpl1 = tpl[tail ? 1 : 0];\n return tpl1[0] + item.split('\\n').join('\\n' + tpl1[1]);\n}\n\nvar TreeifyBuilder = /*#__PURE__*/Object.freeze({\n __proto__: null,\n treeify: treeify\n});\n\nclass DecisionTree {\n constructor(input) {\n this.branches = weave(toAstTerminalPairs(input));\n }\n build(builder) {\n return builder(this.branches);\n }\n}\nfunction toAstTerminalPairs(array) {\n const len = array.length;\n const results = new Array(len);\n for (let i = 0; i < len; i++) {\n const [selectorString, val] = array[i];\n const ast = preprocess(parseley.parse1(selectorString));\n results[i] = {\n ast: ast,\n terminal: {\n type: 'terminal',\n valueContainer: { index: i, value: val, specificity: ast.specificity }\n }\n };\n }\n return results;\n}\nfunction preprocess(ast) {\n reduceSelectorVariants(ast);\n parseley.normalize(ast);\n return ast;\n}\nfunction reduceSelectorVariants(ast) {\n const newList = [];\n ast.list.forEach(sel => {\n switch (sel.type) {\n case 'class':\n newList.push({\n matcher: '~=',\n modifier: null,\n name: 'class',\n namespace: null,\n specificity: sel.specificity,\n type: 'attrValue',\n value: sel.name,\n });\n break;\n case 'id':\n newList.push({\n matcher: '=',\n modifier: null,\n name: 'id',\n namespace: null,\n specificity: sel.specificity,\n type: 'attrValue',\n value: sel.name,\n });\n break;\n case 'combinator':\n reduceSelectorVariants(sel.left);\n newList.push(sel);\n break;\n case 'universal':\n break;\n default:\n newList.push(sel);\n break;\n }\n });\n ast.list = newList;\n}\nfunction weave(items) {\n const branches = [];\n while (items.length) {\n const topKind = findTopKey(items, (sel) => true, getSelectorKind);\n const { matches, nonmatches, empty } = breakByKind(items, topKind);\n items = nonmatches;\n if (matches.length) {\n branches.push(branchOfKind(topKind, matches));\n }\n if (empty.length) {\n branches.push(...terminate(empty));\n }\n }\n return branches;\n}\nfunction terminate(items) {\n const results = [];\n for (const item of items) {\n const terminal = item.terminal;\n if (terminal.type === 'terminal') {\n results.push(terminal);\n }\n else {\n const { matches, rest } = partition(terminal.cont, (node) => node.type === 'terminal');\n matches.forEach((node) => results.push(node));\n if (rest.length) {\n terminal.cont = rest;\n results.push(terminal);\n }\n }\n }\n return results;\n}\nfunction breakByKind(items, selectedKind) {\n const matches = [];\n const nonmatches = [];\n const empty = [];\n for (const item of items) {\n const simpsels = item.ast.list;\n if (simpsels.length) {\n const isMatch = simpsels.some(node => getSelectorKind(node) === selectedKind);\n (isMatch ? matches : nonmatches).push(item);\n }\n else {\n empty.push(item);\n }\n }\n return { matches, nonmatches, empty };\n}\nfunction getSelectorKind(sel) {\n switch (sel.type) {\n case 'attrPresence':\n return `attrPresence ${sel.name}`;\n case 'attrValue':\n return `attrValue ${sel.name}`;\n case 'combinator':\n return `combinator ${sel.combinator}`;\n default:\n return sel.type;\n }\n}\nfunction branchOfKind(kind, items) {\n if (kind === 'tag') {\n return tagNameBranch(items);\n }\n if (kind.startsWith('attrValue ')) {\n return attrValueBranch(kind.substring(10), items);\n }\n if (kind.startsWith('attrPresence ')) {\n return attrPresenceBranch(kind.substring(13), items);\n }\n if (kind === 'combinator >') {\n return combinatorBranch('>', items);\n }\n if (kind === 'combinator +') {\n return combinatorBranch('+', items);\n }\n throw new Error(`Unsupported selector kind: ${kind}`);\n}\nfunction tagNameBranch(items) {\n const groups = spliceAndGroup(items, (x) => x.type === 'tag', (x) => x.name);\n const variants = Object.entries(groups).map(([name, group]) => ({\n type: 'variant',\n value: name,\n cont: weave(group.items)\n }));\n return {\n type: 'tagName',\n variants: variants\n };\n}\nfunction attrPresenceBranch(name, items) {\n for (const item of items) {\n spliceSimpleSelector(item, (x) => (x.type === 'attrPresence') && (x.name === name));\n }\n return {\n type: 'attrPresence',\n name: name,\n cont: weave(items)\n };\n}\nfunction attrValueBranch(name, items) {\n const groups = spliceAndGroup(items, (x) => (x.type === 'attrValue') && (x.name === name), (x) => `${x.matcher} ${x.modifier || ''} ${x.value}`);\n const matchers = [];\n for (const group of Object.values(groups)) {\n const sel = group.oneSimpleSelector;\n const predicate = getAttrPredicate(sel);\n const continuation = weave(group.items);\n matchers.push({\n type: 'matcher',\n matcher: sel.matcher,\n modifier: sel.modifier,\n value: sel.value,\n predicate: predicate,\n cont: continuation\n });\n }\n return {\n type: 'attrValue',\n name: name,\n matchers: matchers\n };\n}\nfunction getAttrPredicate(sel) {\n if (sel.modifier === 'i') {\n const expected = sel.value.toLowerCase();\n switch (sel.matcher) {\n case '=':\n return (actual) => expected === actual.toLowerCase();\n case '~=':\n return (actual) => actual.toLowerCase().split(/[ \\t]+/).includes(expected);\n case '^=':\n return (actual) => actual.toLowerCase().startsWith(expected);\n case '$=':\n return (actual) => actual.toLowerCase().endsWith(expected);\n case '*=':\n return (actual) => actual.toLowerCase().includes(expected);\n case '|=':\n return (actual) => {\n const lower = actual.toLowerCase();\n return (expected === lower) || (lower.startsWith(expected) && lower[expected.length] === '-');\n };\n }\n }\n else {\n const expected = sel.value;\n switch (sel.matcher) {\n case '=':\n return (actual) => expected === actual;\n case '~=':\n return (actual) => actual.split(/[ \\t]+/).includes(expected);\n case '^=':\n return (actual) => actual.startsWith(expected);\n case '$=':\n return (actual) => actual.endsWith(expected);\n case '*=':\n return (actual) => actual.includes(expected);\n case '|=':\n return (actual) => (expected === actual) || (actual.startsWith(expected) && actual[expected.length] === '-');\n }\n }\n}\nfunction combinatorBranch(combinator, items) {\n const groups = spliceAndGroup(items, (x) => (x.type === 'combinator') && (x.combinator === combinator), (x) => parseley.serialize(x.left));\n const leftItems = [];\n for (const group of Object.values(groups)) {\n const rightCont = weave(group.items);\n const leftAst = group.oneSimpleSelector.left;\n leftItems.push({\n ast: leftAst,\n terminal: { type: 'popElement', cont: rightCont }\n });\n }\n return {\n type: 'pushElement',\n combinator: combinator,\n cont: weave(leftItems)\n };\n}\nfunction spliceAndGroup(items, predicate, keyCallback) {\n const groups = {};\n while (items.length) {\n const bestKey = findTopKey(items, predicate, keyCallback);\n const bestKeyPredicate = (sel) => predicate(sel) && keyCallback(sel) === bestKey;\n const hasBestKeyPredicate = (item) => item.ast.list.some(bestKeyPredicate);\n const { matches, rest } = partition1(items, hasBestKeyPredicate);\n let oneSimpleSelector = null;\n for (const item of matches) {\n const splicedNode = spliceSimpleSelector(item, bestKeyPredicate);\n if (!oneSimpleSelector) {\n oneSimpleSelector = splicedNode;\n }\n }\n if (oneSimpleSelector == null) {\n throw new Error('No simple selector is found.');\n }\n groups[bestKey] = { oneSimpleSelector: oneSimpleSelector, items: matches };\n items = rest;\n }\n return groups;\n}\nfunction spliceSimpleSelector(item, predicate) {\n const simpsels = item.ast.list;\n const matches = new Array(simpsels.length);\n let firstIndex = -1;\n for (let i = simpsels.length; i-- > 0;) {\n if (predicate(simpsels[i])) {\n matches[i] = true;\n firstIndex = i;\n }\n }\n if (firstIndex == -1) {\n throw new Error(`Couldn't find the required simple selector.`);\n }\n const result = simpsels[firstIndex];\n item.ast.list = simpsels.filter((sel, i) => !matches[i]);\n return result;\n}\nfunction findTopKey(items, predicate, keyCallback) {\n const candidates = {};\n for (const item of items) {\n const candidates1 = {};\n for (const node of item.ast.list.filter(predicate)) {\n candidates1[keyCallback(node)] = true;\n }\n for (const key of Object.keys(candidates1)) {\n if (candidates[key]) {\n candidates[key]++;\n }\n else {\n candidates[key] = 1;\n }\n }\n }\n let topKind = '';\n let topCounter = 0;\n for (const entry of Object.entries(candidates)) {\n if (entry[1] > topCounter) {\n topKind = entry[0];\n topCounter = entry[1];\n }\n }\n return topKind;\n}\nfunction partition(src, predicate) {\n const matches = [];\n const rest = [];\n for (const x of src) {\n if (predicate(x)) {\n matches.push(x);\n }\n else {\n rest.push(x);\n }\n }\n return { matches, rest };\n}\nfunction partition1(src, predicate) {\n const matches = [];\n const rest = [];\n for (const x of src) {\n if (predicate(x)) {\n matches.push(x);\n }\n else {\n rest.push(x);\n }\n }\n return { matches, rest };\n}\n\nclass Picker {\n constructor(f) {\n this.f = f;\n }\n pickAll(el) {\n return this.f(el);\n }\n pick1(el, preferFirst = false) {\n const results = this.f(el);\n const len = results.length;\n if (len === 0) {\n return null;\n }\n if (len === 1) {\n return results[0].value;\n }\n const comparator = (preferFirst)\n ? comparatorPreferFirst\n : comparatorPreferLast;\n let result = results[0];\n for (let i = 1; i < len; i++) {\n const next = results[i];\n if (comparator(result, next)) {\n result = next;\n }\n }\n return result.value;\n }\n}\nfunction comparatorPreferFirst(acc, next) {\n const diff = compareSpecificity(next.specificity, acc.specificity);\n return diff > 0 || (diff === 0 && next.index < acc.index);\n}\nfunction comparatorPreferLast(acc, next) {\n const diff = compareSpecificity(next.specificity, acc.specificity);\n return diff > 0 || (diff === 0 && next.index > acc.index);\n}\n\nexport { Ast, DecisionTree, Picker, TreeifyBuilder as Treeify, Types };\n"],"x_google_ignoreList":[0],"mappings":"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"}
1
+ {"version":3,"file":"selderee.js","names":[],"sources":["../../../../../../../node_modules/selderee/lib/selderee.mjs"],"sourcesContent":["import * as parseley from 'parseley';\nimport { compareSpecificity } from 'parseley';\n\nvar Ast = /*#__PURE__*/Object.freeze({\n __proto__: null\n});\n\nvar Types = /*#__PURE__*/Object.freeze({\n __proto__: null\n});\n\nconst treeify = (nodes) => '▽\\n' + treeifyArray(nodes, thinLines);\nconst thinLines = [['├─', '│ '], ['└─', ' ']];\nconst heavyLines = [['┠─', '┃ '], ['┖─', ' ']];\nconst doubleLines = [['╟─', '║ '], ['╙─', ' ']];\nfunction treeifyArray(nodes, tpl = heavyLines) {\n return prefixItems(tpl, nodes.map(n => treeifyNode(n)));\n}\nfunction treeifyNode(node) {\n switch (node.type) {\n case 'terminal': {\n const vctr = node.valueContainer;\n return `◁ #${vctr.index} ${JSON.stringify(vctr.specificity)} ${vctr.value}`;\n }\n case 'tagName':\n return `◻ Tag name\\n${treeifyArray(node.variants, doubleLines)}`;\n case 'attrValue':\n return `▣ Attr value: ${node.name}\\n${treeifyArray(node.matchers, doubleLines)}`;\n case 'attrPresence':\n return `◨ Attr presence: ${node.name}\\n${treeifyArray(node.cont)}`;\n case 'pushElement':\n return `◉ Push element: ${node.combinator}\\n${treeifyArray(node.cont, thinLines)}`;\n case 'popElement':\n return `◌ Pop element\\n${treeifyArray(node.cont, thinLines)}`;\n case 'variant':\n return `◇ = ${node.value}\\n${treeifyArray(node.cont)}`;\n case 'matcher':\n return `◈ ${node.matcher} \"${node.value}\"${node.modifier || ''}\\n${treeifyArray(node.cont)}`;\n }\n}\nfunction prefixItems(tpl, items) {\n return items\n .map((item, i, { length }) => prefixItem(tpl, item, i === length - 1))\n .join('\\n');\n}\nfunction prefixItem(tpl, item, tail = true) {\n const tpl1 = tpl[tail ? 1 : 0];\n return tpl1[0] + item.split('\\n').join('\\n' + tpl1[1]);\n}\n\nvar TreeifyBuilder = /*#__PURE__*/Object.freeze({\n __proto__: null,\n treeify: treeify\n});\n\nclass DecisionTree {\n constructor(input) {\n this.branches = weave(toAstTerminalPairs(input));\n }\n build(builder) {\n return builder(this.branches);\n }\n}\nfunction toAstTerminalPairs(array) {\n const len = array.length;\n const results = new Array(len);\n for (let i = 0; i < len; i++) {\n const [selectorString, val] = array[i];\n const ast = preprocess(parseley.parse1(selectorString));\n results[i] = {\n ast: ast,\n terminal: {\n type: 'terminal',\n valueContainer: { index: i, value: val, specificity: ast.specificity }\n }\n };\n }\n return results;\n}\nfunction preprocess(ast) {\n reduceSelectorVariants(ast);\n parseley.normalize(ast);\n return ast;\n}\nfunction reduceSelectorVariants(ast) {\n const newList = [];\n ast.list.forEach(sel => {\n switch (sel.type) {\n case 'class':\n newList.push({\n matcher: '~=',\n modifier: null,\n name: 'class',\n namespace: null,\n specificity: sel.specificity,\n type: 'attrValue',\n value: sel.name,\n });\n break;\n case 'id':\n newList.push({\n matcher: '=',\n modifier: null,\n name: 'id',\n namespace: null,\n specificity: sel.specificity,\n type: 'attrValue',\n value: sel.name,\n });\n break;\n case 'combinator':\n reduceSelectorVariants(sel.left);\n newList.push(sel);\n break;\n case 'universal':\n break;\n default:\n newList.push(sel);\n break;\n }\n });\n ast.list = newList;\n}\nfunction weave(items) {\n const branches = [];\n while (items.length) {\n const topKind = findTopKey(items, (sel) => true, getSelectorKind);\n const { matches, nonmatches, empty } = breakByKind(items, topKind);\n items = nonmatches;\n if (matches.length) {\n branches.push(branchOfKind(topKind, matches));\n }\n if (empty.length) {\n branches.push(...terminate(empty));\n }\n }\n return branches;\n}\nfunction terminate(items) {\n const results = [];\n for (const item of items) {\n const terminal = item.terminal;\n if (terminal.type === 'terminal') {\n results.push(terminal);\n }\n else {\n const { matches, rest } = partition(terminal.cont, (node) => node.type === 'terminal');\n matches.forEach((node) => results.push(node));\n if (rest.length) {\n terminal.cont = rest;\n results.push(terminal);\n }\n }\n }\n return results;\n}\nfunction breakByKind(items, selectedKind) {\n const matches = [];\n const nonmatches = [];\n const empty = [];\n for (const item of items) {\n const simpsels = item.ast.list;\n if (simpsels.length) {\n const isMatch = simpsels.some(node => getSelectorKind(node) === selectedKind);\n (isMatch ? matches : nonmatches).push(item);\n }\n else {\n empty.push(item);\n }\n }\n return { matches, nonmatches, empty };\n}\nfunction getSelectorKind(sel) {\n switch (sel.type) {\n case 'attrPresence':\n return `attrPresence ${sel.name}`;\n case 'attrValue':\n return `attrValue ${sel.name}`;\n case 'combinator':\n return `combinator ${sel.combinator}`;\n default:\n return sel.type;\n }\n}\nfunction branchOfKind(kind, items) {\n if (kind === 'tag') {\n return tagNameBranch(items);\n }\n if (kind.startsWith('attrValue ')) {\n return attrValueBranch(kind.substring(10), items);\n }\n if (kind.startsWith('attrPresence ')) {\n return attrPresenceBranch(kind.substring(13), items);\n }\n if (kind === 'combinator >') {\n return combinatorBranch('>', items);\n }\n if (kind === 'combinator +') {\n return combinatorBranch('+', items);\n }\n throw new Error(`Unsupported selector kind: ${kind}`);\n}\nfunction tagNameBranch(items) {\n const groups = spliceAndGroup(items, (x) => x.type === 'tag', (x) => x.name);\n const variants = Object.entries(groups).map(([name, group]) => ({\n type: 'variant',\n value: name,\n cont: weave(group.items)\n }));\n return {\n type: 'tagName',\n variants: variants\n };\n}\nfunction attrPresenceBranch(name, items) {\n for (const item of items) {\n spliceSimpleSelector(item, (x) => (x.type === 'attrPresence') && (x.name === name));\n }\n return {\n type: 'attrPresence',\n name: name,\n cont: weave(items)\n };\n}\nfunction attrValueBranch(name, items) {\n const groups = spliceAndGroup(items, (x) => (x.type === 'attrValue') && (x.name === name), (x) => `${x.matcher} ${x.modifier || ''} ${x.value}`);\n const matchers = [];\n for (const group of Object.values(groups)) {\n const sel = group.oneSimpleSelector;\n const predicate = getAttrPredicate(sel);\n const continuation = weave(group.items);\n matchers.push({\n type: 'matcher',\n matcher: sel.matcher,\n modifier: sel.modifier,\n value: sel.value,\n predicate: predicate,\n cont: continuation\n });\n }\n return {\n type: 'attrValue',\n name: name,\n matchers: matchers\n };\n}\nfunction getAttrPredicate(sel) {\n if (sel.modifier === 'i') {\n const expected = sel.value.toLowerCase();\n switch (sel.matcher) {\n case '=':\n return (actual) => expected === actual.toLowerCase();\n case '~=':\n return (actual) => actual.toLowerCase().split(/[ \\t]+/).includes(expected);\n case '^=':\n return (actual) => actual.toLowerCase().startsWith(expected);\n case '$=':\n return (actual) => actual.toLowerCase().endsWith(expected);\n case '*=':\n return (actual) => actual.toLowerCase().includes(expected);\n case '|=':\n return (actual) => {\n const lower = actual.toLowerCase();\n return (expected === lower) || (lower.startsWith(expected) && lower[expected.length] === '-');\n };\n }\n }\n else {\n const expected = sel.value;\n switch (sel.matcher) {\n case '=':\n return (actual) => expected === actual;\n case '~=':\n return (actual) => actual.split(/[ \\t]+/).includes(expected);\n case '^=':\n return (actual) => actual.startsWith(expected);\n case '$=':\n return (actual) => actual.endsWith(expected);\n case '*=':\n return (actual) => actual.includes(expected);\n case '|=':\n return (actual) => (expected === actual) || (actual.startsWith(expected) && actual[expected.length] === '-');\n }\n }\n}\nfunction combinatorBranch(combinator, items) {\n const groups = spliceAndGroup(items, (x) => (x.type === 'combinator') && (x.combinator === combinator), (x) => parseley.serialize(x.left));\n const leftItems = [];\n for (const group of Object.values(groups)) {\n const rightCont = weave(group.items);\n const leftAst = group.oneSimpleSelector.left;\n leftItems.push({\n ast: leftAst,\n terminal: { type: 'popElement', cont: rightCont }\n });\n }\n return {\n type: 'pushElement',\n combinator: combinator,\n cont: weave(leftItems)\n };\n}\nfunction spliceAndGroup(items, predicate, keyCallback) {\n const groups = {};\n while (items.length) {\n const bestKey = findTopKey(items, predicate, keyCallback);\n const bestKeyPredicate = (sel) => predicate(sel) && keyCallback(sel) === bestKey;\n const hasBestKeyPredicate = (item) => item.ast.list.some(bestKeyPredicate);\n const { matches, rest } = partition1(items, hasBestKeyPredicate);\n let oneSimpleSelector = null;\n for (const item of matches) {\n const splicedNode = spliceSimpleSelector(item, bestKeyPredicate);\n if (!oneSimpleSelector) {\n oneSimpleSelector = splicedNode;\n }\n }\n if (oneSimpleSelector == null) {\n throw new Error('No simple selector is found.');\n }\n groups[bestKey] = { oneSimpleSelector: oneSimpleSelector, items: matches };\n items = rest;\n }\n return groups;\n}\nfunction spliceSimpleSelector(item, predicate) {\n const simpsels = item.ast.list;\n const matches = new Array(simpsels.length);\n let firstIndex = -1;\n for (let i = simpsels.length; i-- > 0;) {\n if (predicate(simpsels[i])) {\n matches[i] = true;\n firstIndex = i;\n }\n }\n if (firstIndex == -1) {\n throw new Error(`Couldn't find the required simple selector.`);\n }\n const result = simpsels[firstIndex];\n item.ast.list = simpsels.filter((sel, i) => !matches[i]);\n return result;\n}\nfunction findTopKey(items, predicate, keyCallback) {\n const candidates = {};\n for (const item of items) {\n const candidates1 = {};\n for (const node of item.ast.list.filter(predicate)) {\n candidates1[keyCallback(node)] = true;\n }\n for (const key of Object.keys(candidates1)) {\n if (candidates[key]) {\n candidates[key]++;\n }\n else {\n candidates[key] = 1;\n }\n }\n }\n let topKind = '';\n let topCounter = 0;\n for (const entry of Object.entries(candidates)) {\n if (entry[1] > topCounter) {\n topKind = entry[0];\n topCounter = entry[1];\n }\n }\n return topKind;\n}\nfunction partition(src, predicate) {\n const matches = [];\n const rest = [];\n for (const x of src) {\n if (predicate(x)) {\n matches.push(x);\n }\n else {\n rest.push(x);\n }\n }\n return { matches, rest };\n}\nfunction partition1(src, predicate) {\n const matches = [];\n const rest = [];\n for (const x of src) {\n if (predicate(x)) {\n matches.push(x);\n }\n else {\n rest.push(x);\n }\n }\n return { matches, rest };\n}\n\nclass Picker {\n constructor(f) {\n this.f = f;\n }\n pickAll(el) {\n return this.f(el);\n }\n pick1(el, preferFirst = false) {\n const results = this.f(el);\n const len = results.length;\n if (len === 0) {\n return null;\n }\n if (len === 1) {\n return results[0].value;\n }\n const comparator = (preferFirst)\n ? comparatorPreferFirst\n : comparatorPreferLast;\n let result = results[0];\n for (let i = 1; i < len; i++) {\n const next = results[i];\n if (comparator(result, next)) {\n result = next;\n }\n }\n return result.value;\n }\n}\nfunction comparatorPreferFirst(acc, next) {\n const diff = compareSpecificity(next.specificity, acc.specificity);\n return diff > 0 || (diff === 0 && next.index < acc.index);\n}\nfunction comparatorPreferLast(acc, next) {\n const diff = compareSpecificity(next.specificity, acc.specificity);\n return diff > 0 || (diff === 0 && next.index > acc.index);\n}\n\nexport { Ast, DecisionTree, Picker, TreeifyBuilder as Treeify, Types };\n"],"x_google_ignoreList":[0],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"protected-route.d.ts","names":[],"sources":["../../src/proxy/protected-route.ts"],"mappings":";;;cAca,qBAAqB"}
1
+ {"version":3,"file":"protected-route.d.ts","names":[],"sources":["../../src/proxy/protected-route.ts"],"sourcesContent":[],"mappings":";;;cAca,qBAAqB"}
@@ -2,25 +2,29 @@ import { localApiGet } from "../lib/http.js";
2
2
  import { getNextUrl } from "../server/utils.js";
3
3
  import { getRequestOrigin } from "./proxy.js";
4
4
  import { NextResponse } from "next/server";
5
+
5
6
  //#region src/proxy/protected-route.ts
6
7
  function getPublicRedirectUrl(request, href) {
7
- if (!href.startsWith("/") || href.startsWith("//")) return;
8
+ if (!href.startsWith("/") || href.startsWith("//")) return void 0;
8
9
  const url = new URL(href, getRequestOrigin(request));
9
10
  return url.pathname === request.nextUrl.pathname ? void 0 : url;
10
11
  }
11
12
  const protectedRouteProxy = async ({ request, route }) => {
12
13
  if (route.isProtected) {
13
- const isAuthenticated = request.cookies.get("payload-token");
14
+ const token = request.cookies.get("payload-token");
15
+ const isAuthenticated = token;
14
16
  console.log("protectedRouteProxy.isAuthenticated", isAuthenticated);
15
17
  if (!isAuthenticated) {
16
18
  if (route.publicRedirect) {
17
19
  const redirectUrl = getPublicRedirectUrl(request, route.publicRedirect);
18
20
  if (redirectUrl) return NextResponse.redirect(redirectUrl);
19
21
  }
20
- const { pathname } = request.nextUrl;
22
+ const url = request.nextUrl;
23
+ const { pathname } = url;
21
24
  const reqHeaders = new Headers(request.headers);
22
25
  reqHeaders.set("x-pathname", pathname);
23
- const nextRoute = (await localApiGet(`/-route?schema=login&market=${encodeURIComponent(route.market)}&locale=${encodeURIComponent(route.locale)}`, {}, void 0, getRequestOrigin(request)))?.route;
26
+ const resolution = await localApiGet(`/-route?schema=login&market=${encodeURIComponent(route.market)}&locale=${encodeURIComponent(route.locale)}`, {}, void 0, getRequestOrigin(request));
27
+ const nextRoute = resolution?.route;
24
28
  if (nextRoute) {
25
29
  const nextUrl = getNextUrl(request, nextRoute);
26
30
  reqHeaders.set("x-market", nextRoute.market);
@@ -29,12 +33,13 @@ const protectedRouteProxy = async ({ request, route }) => {
29
33
  reqHeaders.set("x-id", String(nextRoute.page));
30
34
  reqHeaders.set("x-forwarded-pathname", nextUrl.pathname);
31
35
  console.log("protectedRouteProxy.Protected", pathname, ">", nextUrl.pathname);
32
- return NextResponse.rewrite(nextUrl, { request: { headers: reqHeaders } });
36
+ const response = NextResponse.rewrite(nextUrl, { request: { headers: reqHeaders } });
37
+ return response;
33
38
  }
34
39
  }
35
40
  }
36
41
  };
42
+
37
43
  //#endregion
38
44
  export { protectedRouteProxy };
39
-
40
45
  //# sourceMappingURL=protected-route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"protected-route.js","names":[],"sources":["../../src/proxy/protected-route.ts"],"sourcesContent":["import { NextResponse } from 'next/server';\r\nimport { localApiGet } from '../lib/http';\r\nimport { getNextUrl } from '../server/utils';\r\nimport { getRequestOrigin } from './proxy';\r\nimport type { RouteMiddleware, RouteMiddlewareOptions, RouteResolverResponse } from './route-proxy';\r\n\r\nfunction getPublicRedirectUrl(request: RouteMiddlewareOptions['request'], href: string): URL | undefined {\r\n if (!href.startsWith('/') || href.startsWith('//')) {\r\n return undefined;\r\n }\r\n const url = new URL(href, getRequestOrigin(request));\r\n return url.pathname === request.nextUrl.pathname ? undefined : url;\r\n}\r\n\r\nexport const protectedRouteProxy: RouteMiddleware = async ({ request, route }: RouteMiddlewareOptions) => {\r\n // console.log('protectedRouteProxy', 'token', token);\r\n if (route.isProtected) {\r\n const token = request.cookies.get('payload-token');\r\n const isAuthenticated = token; // await hasValidSession();\r\n console.log('protectedRouteProxy.isAuthenticated', isAuthenticated);\r\n if (!isAuthenticated) {\r\n if (route.publicRedirect) {\r\n const redirectUrl = getPublicRedirectUrl(request, route.publicRedirect);\r\n if (redirectUrl) {\r\n return NextResponse.redirect(redirectUrl);\r\n }\r\n }\r\n const url = request.nextUrl;\r\n const { pathname } = url;\r\n const reqHeaders = new Headers(request.headers);\r\n reqHeaders.set('x-pathname', pathname);\r\n const resolution = await localApiGet<RouteResolverResponse>(\r\n `/-route?schema=login&market=${encodeURIComponent(route.market)}&locale=${encodeURIComponent(route.locale)}`,\r\n {},\r\n undefined,\r\n getRequestOrigin(request)\r\n );\r\n const nextRoute = resolution?.route;\r\n if (nextRoute) {\r\n const nextUrl = getNextUrl(request, nextRoute);\r\n reqHeaders.set('x-market', nextRoute.market);\r\n reqHeaders.set('x-locale', nextRoute.locale);\r\n reqHeaders.set('x-schema', nextRoute.schema);\r\n reqHeaders.set('x-id', String(nextRoute.page));\r\n reqHeaders.set('x-forwarded-pathname', nextUrl.pathname);\r\n console.log('protectedRouteProxy.Protected', pathname, '>', nextUrl.pathname);\r\n const response = NextResponse\r\n .rewrite(nextUrl, {\r\n request: {\r\n headers: reqHeaders,\r\n },\r\n });\r\n return response;\r\n }\r\n }\r\n }\r\n};\r\n"],"mappings":";;;;;AAMA,SAAS,qBAAqB,SAA4C,MAA+B;CACvG,IAAI,CAAC,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,IAAI,GAC/C;CAEF,MAAM,MAAM,IAAI,IAAI,MAAM,iBAAiB,OAAO,CAAC;CACnD,OAAO,IAAI,aAAa,QAAQ,QAAQ,WAAW,KAAA,IAAY;AACjE;AAEA,MAAa,sBAAuC,OAAO,EAAE,SAAS,YAAoC;CAExG,IAAI,MAAM,aAAa;EAErB,MAAM,kBADQ,QAAQ,QAAQ,IAAI,eACN;EAC5B,QAAQ,IAAI,uCAAuC,eAAe;EAClE,IAAI,CAAC,iBAAiB;GACpB,IAAI,MAAM,gBAAgB;IACxB,MAAM,cAAc,qBAAqB,SAAS,MAAM,cAAc;IACtE,IAAI,aACF,OAAO,aAAa,SAAS,WAAW;GAE5C;GAEA,MAAM,EAAE,aADI,QAAQ;GAEpB,MAAM,aAAa,IAAI,QAAQ,QAAQ,OAAO;GAC9C,WAAW,IAAI,cAAc,QAAQ;GAOrC,MAAM,aAAY,MANO,YACvB,+BAA+B,mBAAmB,MAAM,MAAM,EAAE,UAAU,mBAAmB,MAAM,MAAM,KACzG,CAAC,GACD,KAAA,GACA,iBAAiB,OAAO,CAC1B,EAAA,EAC8B;GAC9B,IAAI,WAAW;IACb,MAAM,UAAU,WAAW,SAAS,SAAS;IAC7C,WAAW,IAAI,YAAY,UAAU,MAAM;IAC3C,WAAW,IAAI,YAAY,UAAU,MAAM;IAC3C,WAAW,IAAI,YAAY,UAAU,MAAM;IAC3C,WAAW,IAAI,QAAQ,OAAO,UAAU,IAAI,CAAC;IAC7C,WAAW,IAAI,wBAAwB,QAAQ,QAAQ;IACvD,QAAQ,IAAI,iCAAiC,UAAU,KAAK,QAAQ,QAAQ;IAO5E,OANiB,aACd,QAAQ,SAAS,EAChB,SAAS,EACP,SAAS,WACX,EACF,CACY;GAChB;EACF;CACF;AACF"}
1
+ {"version":3,"file":"protected-route.js","names":["request: RouteMiddlewareOptions['request']","href: string","protectedRouteProxy: RouteMiddleware"],"sources":["../../src/proxy/protected-route.ts"],"sourcesContent":["import { NextResponse } from 'next/server';\r\nimport { localApiGet } from '../lib/http';\r\nimport { getNextUrl } from '../server/utils';\r\nimport { getRequestOrigin } from './proxy';\r\nimport type { RouteMiddleware, RouteMiddlewareOptions, RouteResolverResponse } from './route-proxy';\r\n\r\nfunction getPublicRedirectUrl(request: RouteMiddlewareOptions['request'], href: string): URL | undefined {\r\n if (!href.startsWith('/') || href.startsWith('//')) {\r\n return undefined;\r\n }\r\n const url = new URL(href, getRequestOrigin(request));\r\n return url.pathname === request.nextUrl.pathname ? undefined : url;\r\n}\r\n\r\nexport const protectedRouteProxy: RouteMiddleware = async ({ request, route }: RouteMiddlewareOptions) => {\r\n // console.log('protectedRouteProxy', 'token', token);\r\n if (route.isProtected) {\r\n const token = request.cookies.get('payload-token');\r\n const isAuthenticated = token; // await hasValidSession();\r\n console.log('protectedRouteProxy.isAuthenticated', isAuthenticated);\r\n if (!isAuthenticated) {\r\n if (route.publicRedirect) {\r\n const redirectUrl = getPublicRedirectUrl(request, route.publicRedirect);\r\n if (redirectUrl) {\r\n return NextResponse.redirect(redirectUrl);\r\n }\r\n }\r\n const url = request.nextUrl;\r\n const { pathname } = url;\r\n const reqHeaders = new Headers(request.headers);\r\n reqHeaders.set('x-pathname', pathname);\r\n const resolution = await localApiGet<RouteResolverResponse>(\r\n `/-route?schema=login&market=${encodeURIComponent(route.market)}&locale=${encodeURIComponent(route.locale)}`,\r\n {},\r\n undefined,\r\n getRequestOrigin(request)\r\n );\r\n const nextRoute = resolution?.route;\r\n if (nextRoute) {\r\n const nextUrl = getNextUrl(request, nextRoute);\r\n reqHeaders.set('x-market', nextRoute.market);\r\n reqHeaders.set('x-locale', nextRoute.locale);\r\n reqHeaders.set('x-schema', nextRoute.schema);\r\n reqHeaders.set('x-id', String(nextRoute.page));\r\n reqHeaders.set('x-forwarded-pathname', nextUrl.pathname);\r\n console.log('protectedRouteProxy.Protected', pathname, '>', nextUrl.pathname);\r\n const response = NextResponse\r\n .rewrite(nextUrl, {\r\n request: {\r\n headers: reqHeaders,\r\n },\r\n });\r\n return response;\r\n }\r\n }\r\n }\r\n};\r\n"],"mappings":";;;;;;AAMA,SAAS,qBAAqBA,SAA4CC,MAA+B;AACvG,KAAI,CAAC,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,KAAK,CAChD,QAAO;CAET,MAAM,MAAM,IAAI,IAAI,MAAM,iBAAiB,QAAQ;AACnD,QAAO,IAAI,aAAa,QAAQ,QAAQ,WAAW,SAAY;AAChE;AAED,MAAaC,sBAAuC,OAAO,EAAE,SAAS,OAA+B,KAAK;AAExG,KAAI,MAAM,aAAa;EACrB,MAAM,QAAQ,QAAQ,QAAQ,IAAI,gBAAgB;EAClD,MAAM,kBAAkB;EACxB,QAAQ,IAAI,uCAAuC,gBAAgB;AACnE,MAAI,CAAC,iBAAiB;AACpB,OAAI,MAAM,gBAAgB;IACxB,MAAM,cAAc,qBAAqB,SAAS,MAAM,eAAe;AACvE,QAAI,YACF,QAAO,aAAa,SAAS,YAAY;GAE5C;GACD,MAAM,MAAM,QAAQ;GACpB,MAAM,EAAE,UAAU,GAAG;GACrB,MAAM,aAAa,IAAI,QAAQ,QAAQ;GACvC,WAAW,IAAI,cAAc,SAAS;GACtC,MAAM,aAAa,MAAM,YACvB,CAAC,4BAA4B,EAAE,mBAAmB,MAAM,OAAO,CAAC,QAAQ,EAAE,mBAAmB,MAAM,OAAO,EAAE,EAC5G,CAAE,GACF,QACA,iBAAiB,QAAQ,CAC1B;GACD,MAAM,YAAY,YAAY;AAC9B,OAAI,WAAW;IACb,MAAM,UAAU,WAAW,SAAS,UAAU;IAC9C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,WAAW,IAAI,QAAQ,OAAO,UAAU,KAAK,CAAC;IAC9C,WAAW,IAAI,wBAAwB,QAAQ,SAAS;IACxD,QAAQ,IAAI,iCAAiC,UAAU,KAAK,QAAQ,SAAS;IAC7E,MAAM,WAAW,aACd,QAAQ,SAAS,EAChB,SAAS,EACP,SAAS,WACV,EACF,EAAC;AACJ,WAAO;GACR;EACF;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","names":[],"sources":["../../src/proxy/proxy.ts"],"mappings":";;;;KAKY,iBAAA;WACD;EADC,IAAA,EAEJ,cAFqB;EAAA,QAAA,CAAA,EAAA,OAAA;AAClB,CAAA;AACH,KAGI,UAAA,GAHJ,CAAA,KAAA,EAGyB,iBAHzB,EAAA,GAG+C,oBAH/C,GAGsE,OAHtE,CAG8E,oBAH9E,CAAA;AAAc;AAGtB;AAAsB;AAAW;AAAsB;AAA+B;AAAR;AAAO;AAUrE,iBAAA,gBAAA,CAA0B,OAAW,EAAX,WAAW,CAAA,EAAA,MAAA;AAwBrD;AAA2B;AAAa;AAAe;AAAU;;;iBAAjD,WAAA,aAAwB,eAAe"}
1
+ {"version":3,"file":"proxy.d.ts","names":[],"sources":["../../src/proxy/proxy.ts"],"sourcesContent":[],"mappings":";;;;KAKY,iBAAA;WACD;EADC,IAAA,EAEJ,cAFqB;EAAA,QAAA,CAAA,EAAA,OAAA;CAAA;AAErB,KAGI,UAAA,GAHJ,CAAA,KAAA,EAGyB,iBAHzB,EAAA,GAG+C,oBAH/C,GAGsE,OAHtE,CAG8E,oBAH9E,CAAA;AAAc;AAGtB;;;;;;AAAqF;AAUrE,iBAAA,gBAAA,CAA0B,OAAW,EAAX,WAAW,CAAA,EAAA,MAAA;AAwBrD;;;;AAAiE;;;iBAAjD,WAAA,aAAwB,eAAe"}
@@ -1,12 +1,20 @@
1
1
  import { NextResponse } from "next/server";
2
+
2
3
  //#region src/proxy/proxy.ts
3
4
  /**
5
+
4
6
  * Returns the externally visible origin for an internal middleware request.
7
+
5
8
  *
9
+
6
10
  * Deployments commonly terminate TLS or change ports before forwarding to
11
+
7
12
  * Next.js. Honoring valid forwarded headers keeps resolver requests on the
13
+
8
14
  * public host and prevents an avoidable proxy redirect; direct-origin fallback
15
+
9
16
  * keeps local development and untrusted/invalid header values deterministic.
17
+
10
18
  */
11
19
  function getRequestOrigin(request) {
12
20
  const forwardedHost = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();
@@ -16,14 +24,21 @@ function getRequestOrigin(request) {
16
24
  const protocol = forwardedProtocol;
17
25
  const defaultPort = protocol === "https" ? "443" : "80";
18
26
  const includesPort = forwardedHost.startsWith("[") ? forwardedHost.includes("]:") : forwardedHost.includes(":");
19
- return `${protocol}://${forwardedPort && forwardedPort !== defaultPort && !includesPort ? `${forwardedHost}:${forwardedPort}` : forwardedHost}`;
27
+ const authority = forwardedPort && forwardedPort !== defaultPort && !includesPort ? `${forwardedHost}:${forwardedPort}` : forwardedHost;
28
+ return `${protocol}://${authority}`;
20
29
  }
21
30
  /**
31
+
22
32
  * Composes middleware into an ordered, short-circuiting proxy pipeline.
33
+
23
34
  *
35
+
24
36
  * A disabled proxy returns immediately, avoiding all downstream request work.
37
+
25
38
  * Otherwise each middleware can claim the response; stopping at its first
39
+
26
40
  * result prevents duplicate rewrites, redirects, and expensive policy checks.
41
+
27
42
  */
28
43
  function createProxy(...proxies) {
29
44
  return async function({ request, next, disabled }) {
@@ -43,7 +58,7 @@ function createProxy(...proxies) {
43
58
  return NextResponse.next();
44
59
  };
45
60
  }
61
+
46
62
  //#endregion
47
63
  export { createProxy, getRequestOrigin };
48
-
49
64
  //# sourceMappingURL=proxy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","names":[],"sources":["../../src/proxy/proxy.ts"],"sourcesContent":["import { NextMiddlewareResult } from 'next/dist/server/web/types';\r\nimport { NextFetchEvent, NextRequest, NextResponse } from 'next/server';\r\n\r\n// export type Middleware = (request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;\r\n\r\nexport type MiddlewareOptions = {\r\n request: NextRequest,\r\n next: NextFetchEvent,\r\n disabled?: boolean,\r\n};\r\nexport type Middleware = (props: MiddlewareOptions) => NextMiddlewareResult | Promise<NextMiddlewareResult>;\r\n\r\n/**\r\n * Returns the externally visible origin for an internal middleware request.\r\n *\r\n * Deployments commonly terminate TLS or change ports before forwarding to\r\n * Next.js. Honoring valid forwarded headers keeps resolver requests on the\r\n * public host and prevents an avoidable proxy redirect; direct-origin fallback\r\n * keeps local development and untrusted/invalid header values deterministic.\r\n */\r\nexport function getRequestOrigin(request: NextRequest): string {\r\n const forwardedHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim();\r\n const forwardedProtocol = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim();\r\n const forwardedPort = request.headers.get('x-forwarded-port')?.split(',')[0]?.trim();\r\n\r\n if (!forwardedHost || !['http', 'https'].includes(forwardedProtocol || '')) {\r\n return request.nextUrl.origin;\r\n }\r\n\r\n const protocol = forwardedProtocol!;\r\n const defaultPort = protocol === 'https' ? '443' : '80';\r\n const includesPort = forwardedHost.startsWith('[') ? forwardedHost.includes(']:') : forwardedHost.includes(':');\r\n const authority = forwardedPort && forwardedPort !== defaultPort && !includesPort ? `${forwardedHost}:${forwardedPort}` : forwardedHost;\r\n\r\n return `${protocol}://${authority}`;\r\n}\r\n\r\n/**\r\n * Composes middleware into an ordered, short-circuiting proxy pipeline.\r\n *\r\n * A disabled proxy returns immediately, avoiding all downstream request work.\r\n * Otherwise each middleware can claim the response; stopping at its first\r\n * result prevents duplicate rewrites, redirects, and expensive policy checks.\r\n */\r\nexport function createProxy(...proxies: Middleware[]): Middleware {\r\n return async function ({ request, next, disabled }: MiddlewareOptions) {\r\n if (disabled) {\r\n return NextResponse.next();\r\n }\r\n let proxyResponse, i = 0;\r\n while (i < proxies.length && !proxyResponse) {\r\n const proxy = proxies[i] as Middleware;\r\n // console.log('createProxy.proxies', proxies.length, typeof proxy === 'function');\r\n if (typeof proxy === 'function') {\r\n proxyResponse = await proxy({ request, next });\r\n if (proxyResponse) {\r\n return proxyResponse;\r\n }\r\n }\r\n i++;\r\n }\r\n return NextResponse.next();\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;AAoBA,SAAgB,iBAAiB,SAA8B;CAC7D,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,kBAAkB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK;CACnF,MAAM,oBAAoB,QAAQ,QAAQ,IAAI,mBAAmB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK;CACxF,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,kBAAkB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK;CAEnF,IAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,SAAS,qBAAqB,EAAE,GACvE,OAAO,QAAQ,QAAQ;CAGzB,MAAM,WAAW;CACjB,MAAM,cAAc,aAAa,UAAU,QAAQ;CACnD,MAAM,eAAe,cAAc,WAAW,GAAG,IAAI,cAAc,SAAS,IAAI,IAAI,cAAc,SAAS,GAAG;CAG9G,OAAO,GAAG,SAAS,KAFD,iBAAiB,kBAAkB,eAAe,CAAC,eAAe,GAAG,cAAc,GAAG,kBAAkB;AAG5H;;;;;;;;AASA,SAAgB,YAAY,GAAG,SAAmC;CAChE,OAAO,eAAgB,EAAE,SAAS,MAAM,YAA+B;EACrE,IAAI,UACF,OAAO,aAAa,KAAK;EAE3B,IAAI,eAAe,IAAI;EACvB,OAAO,IAAI,QAAQ,UAAU,CAAC,eAAe;GAC3C,MAAM,QAAQ,QAAQ;GAEtB,IAAI,OAAO,UAAU,YAAY;IAC/B,gBAAgB,MAAM,MAAM;KAAE;KAAS;IAAK,CAAC;IAC7C,IAAI,eACF,OAAO;GAEX;GACA;EACF;EACA,OAAO,aAAa,KAAK;CAC3B;AACF"}
1
+ {"version":3,"file":"proxy.js","names":["request: NextRequest"],"sources":["../../src/proxy/proxy.ts"],"sourcesContent":["import { NextMiddlewareResult } from 'next/dist/server/web/types';\r\nimport { NextFetchEvent, NextRequest, NextResponse } from 'next/server';\r\n\r\n// export type Middleware = (request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;\r\n\r\nexport type MiddlewareOptions = {\r\n request: NextRequest,\r\n next: NextFetchEvent,\r\n disabled?: boolean,\r\n};\r\nexport type Middleware = (props: MiddlewareOptions) => NextMiddlewareResult | Promise<NextMiddlewareResult>;\r\n\r\n/**\r\n * Returns the externally visible origin for an internal middleware request.\r\n *\r\n * Deployments commonly terminate TLS or change ports before forwarding to\r\n * Next.js. Honoring valid forwarded headers keeps resolver requests on the\r\n * public host and prevents an avoidable proxy redirect; direct-origin fallback\r\n * keeps local development and untrusted/invalid header values deterministic.\r\n */\r\nexport function getRequestOrigin(request: NextRequest): string {\r\n const forwardedHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim();\r\n const forwardedProtocol = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim();\r\n const forwardedPort = request.headers.get('x-forwarded-port')?.split(',')[0]?.trim();\r\n\r\n if (!forwardedHost || !['http', 'https'].includes(forwardedProtocol || '')) {\r\n return request.nextUrl.origin;\r\n }\r\n\r\n const protocol = forwardedProtocol!;\r\n const defaultPort = protocol === 'https' ? '443' : '80';\r\n const includesPort = forwardedHost.startsWith('[') ? forwardedHost.includes(']:') : forwardedHost.includes(':');\r\n const authority = forwardedPort && forwardedPort !== defaultPort && !includesPort ? `${forwardedHost}:${forwardedPort}` : forwardedHost;\r\n\r\n return `${protocol}://${authority}`;\r\n}\r\n\r\n/**\r\n * Composes middleware into an ordered, short-circuiting proxy pipeline.\r\n *\r\n * A disabled proxy returns immediately, avoiding all downstream request work.\r\n * Otherwise each middleware can claim the response; stopping at its first\r\n * result prevents duplicate rewrites, redirects, and expensive policy checks.\r\n */\r\nexport function createProxy(...proxies: Middleware[]): Middleware {\r\n return async function ({ request, next, disabled }: MiddlewareOptions) {\r\n if (disabled) {\r\n return NextResponse.next();\r\n }\r\n let proxyResponse, i = 0;\r\n while (i < proxies.length && !proxyResponse) {\r\n const proxy = proxies[i] as Middleware;\r\n // console.log('createProxy.proxies', proxies.length, typeof proxy === 'function');\r\n if (typeof proxy === 'function') {\r\n proxyResponse = await proxy({ request, next });\r\n if (proxyResponse) {\r\n return proxyResponse;\r\n }\r\n }\r\n i++;\r\n }\r\n return NextResponse.next();\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,SAAgB,iBAAiBA,SAA8B;CAC7D,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;CACpF,MAAM,oBAAoB,QAAQ,QAAQ,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;CACzF,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;AAEpF,KAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,OAAQ,EAAC,SAAS,qBAAqB,GAAG,CACxE,QAAO,QAAQ,QAAQ;CAGzB,MAAM,WAAW;CACjB,MAAM,cAAc,aAAa,UAAU,QAAQ;CACnD,MAAM,eAAe,cAAc,WAAW,IAAI,GAAG,cAAc,SAAS,KAAK,GAAG,cAAc,SAAS,IAAI;CAC/G,MAAM,YAAY,iBAAiB,kBAAkB,eAAe,CAAC,eAAe,GAAG,cAAc,CAAC,EAAE,eAAe,GAAG;AAE1H,QAAO,GAAG,SAAS,GAAG,EAAE,WAAW;AACpC;;;;;;;;;;;;;;AASD,SAAgB,YAAY,GAAG,SAAmC;AAChE,QAAO,eAAgB,EAAE,SAAS,MAAM,UAA6B,EAAE;AACrE,MAAI,SACF,QAAO,aAAa,MAAM;EAE5B,IAAI,eAAe,IAAI;AACvB,SAAO,IAAI,QAAQ,UAAU,CAAC,eAAe;GAC3C,MAAM,QAAQ,QAAQ;AAEtB,OAAI,OAAO,UAAU,YAAY;IAC/B,gBAAgB,MAAM,MAAM;KAAE;KAAS;IAAM,EAAC;AAC9C,QAAI,cACF,QAAO;GAEV;GACD;EACD;AACD,SAAO,aAAa,MAAM;CAC3B;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"route-auto-detection.d.ts","names":[],"sources":["../../src/proxy/route-auto-detection.ts"],"mappings":";;;;iBAOsB,YAAA,UAAsB,sCAAmC;iBAMzD,aAAA,UAAuB,sCAAmC;AAN1D,cA2CT,kBA3CqB,EA2CD,UA3CC;AAAA"}
1
+ {"version":3,"file":"route-auto-detection.d.ts","names":[],"sources":["../../src/proxy/route-auto-detection.ts"],"sourcesContent":[],"mappings":";;;;iBAOsB,YAAA,UAAsB,sCAAmC;iBAMzD,aAAA,UAAuB,sCAAmC;AAN1D,cA2CT,kBA3CqB,EA2CD,UA3CC"}
@@ -1,14 +1,18 @@
1
- "use server";
1
+ 'use server';
2
+
3
+
2
4
  import { localApiGet } from "../lib/http.js";
3
5
  import { getRequestOrigin } from "./proxy.js";
4
6
  import { asEquatable, defaultLocale, defaultMarket } from "@websolutespa/bom-core";
5
7
  import { NextResponse } from "next/server";
8
+
6
9
  //#region src/proxy/route-auto-detection.ts
7
- async function detectLocale(request, defaultLocale) {
10
+ async function detectLocale(request, defaultLocale$1) {
8
11
  const acceptLanguage = request.headers.get("accept-language")?.split(",")[0];
9
- return request.cookies.get("NEXT_LOCALE")?.value || acceptLanguage || defaultLocale || process.env.DEFAULT_LOCALE;
12
+ const detectedLocale = request.cookies.get("NEXT_LOCALE")?.value || acceptLanguage || defaultLocale$1 || process.env.DEFAULT_LOCALE;
13
+ return detectedLocale;
10
14
  }
11
- async function detectCountry(request, defaultMarket) {
15
+ async function detectCountry(request, defaultMarket$1) {
12
16
  let ip = request.headers.get("x-forwarded-for") || request.headers.get("x-real-ip");
13
17
  if (ip) ip = ip.split(",")[0];
14
18
  const isValidIp = ip?.match(/^(\d+?)\.(\d+?)\.(\d+?)\.(\d+?)$/);
@@ -18,17 +22,23 @@ async function detectCountry(request, defaultMarket) {
18
22
  if (token) {
19
23
  const url = isValidIp ? `https://api.ipinfo.io/lite/${ip}/country_code?token=${token}` : `https://api.ipinfo.io/lite/me/country_code?token=${token}`;
20
24
  const response = await fetch(url);
21
- if (response.ok) detectedCountry = (await response.text()).toLowerCase();
25
+ if (response.ok) {
26
+ const data = await response.text();
27
+ detectedCountry = data.toLowerCase();
28
+ }
22
29
  } else {
23
30
  const url = `https://geoip.websolute.it/Ip2Location/get_info.aspx?ipaddress=${isValidIp ? ip : ""}`;
24
31
  const response = await fetch(url);
25
- if (response.ok) detectedCountry = (((await response.text()).split("<CountryCode><![CDATA[")[1] || "").split("]]></CountryCode>")[0] || "").replace("-", "").toLowerCase();
32
+ if (response.ok) {
33
+ const xml = await response.text();
34
+ detectedCountry = ((xml.split("<CountryCode><![CDATA[")[1] || "").split("]]></CountryCode>")[0] || "").replace("-", "").toLowerCase();
35
+ }
26
36
  }
27
- return detectedCountry || defaultMarket || process.env.DEFAULT_MARKET;
37
+ return detectedCountry || defaultMarket$1 || process.env.DEFAULT_MARKET;
28
38
  } catch (error) {
29
39
  console.log("routeInterceptor.detectCountry.error", error);
30
40
  }
31
- return defaultMarket || process.env.DEFAULT_MARKET;
41
+ return defaultMarket$1 || process.env.DEFAULT_MARKET;
32
42
  }
33
43
  const routeAutoDetection = async ({ request }) => {
34
44
  let redirectUrl = void 0;
@@ -38,12 +48,14 @@ const routeAutoDetection = async ({ request }) => {
38
48
  const cookie = request.cookies.get("detectedRoute");
39
49
  if (cookie?.value) redirectUrl = cookie.value;
40
50
  const rootRoutes = await localApiGet("/-route?where[isRoot][equals]=true", {}, void 0, origin);
41
- if (rootRoutes.find((x) => x.id === "/")) return;
51
+ const defaultRoute = rootRoutes.find((x) => x.id === "/");
52
+ if (defaultRoute) return;
42
53
  const markets = await localApiGet("/market?pagination=false", {}, void 0, origin);
43
54
  const market = markets.find((x) => x.isDefault) || markets.find((x) => x.id === defaultMarket) || markets[0];
44
55
  const detectedCountry = await detectCountry(request, market.id);
45
56
  const detectedMarket = detectedCountry ? markets.filter((x) => Array.isArray(x.countries)).find((x) => {
46
- return (x.countries || []).map((x) => typeof x === "string" ? x : x.id).includes(detectedCountry);
57
+ const countries = (x.countries || []).map((x$1) => typeof x$1 === "string" ? x$1 : x$1.id);
58
+ return countries.includes(detectedCountry);
47
59
  }) || markets.find((x) => !Array.isArray(x.countries)) : void 0;
48
60
  let detectedMarketRoutes = rootRoutes.filter((x) => x.market === detectedMarket?.id);
49
61
  if (detectedMarketRoutes.length === 0) detectedMarketRoutes = rootRoutes.filter((x) => x.market === market.id);
@@ -51,8 +63,8 @@ const routeAutoDetection = async ({ request }) => {
51
63
  const detectedLocale = await detectLocale(request, defaultMarketLocale);
52
64
  const detectedLocaleRoutes = detectedMarketRoutes.filter((x) => x.locale === detectedLocale);
53
65
  const detectedRoute = detectedLocaleRoutes.length > 0 ? detectedLocaleRoutes[0] : detectedMarketRoutes.find((x) => {
54
- const market = markets.find((m) => m.id === x.market);
55
- const marketLocale = market.defaultLanguage ? asEquatable(market.defaultLanguage) : defaultMarketLocale;
66
+ const market$1 = markets.find((m) => m.id === x.market);
67
+ const marketLocale = market$1.defaultLanguage ? asEquatable(market$1.defaultLanguage) : defaultMarketLocale;
56
68
  return x.locale === marketLocale;
57
69
  });
58
70
  if (detectedRoute && detectedRoute.id !== url.pathname) {
@@ -65,7 +77,7 @@ const routeAutoDetection = async ({ request }) => {
65
77
  const search = request.nextUrl.search;
66
78
  const response = NextResponse.redirect(resolvedUrl + search, { status: 307 });
67
79
  response.cookies.set({
68
- expires: new Date(Date.now() + 864e5),
80
+ expires: new Date(Date.now() + 1440 * 60 * 1e3),
69
81
  httpOnly: true,
70
82
  name: "detectedRoute",
71
83
  path: "/",
@@ -76,7 +88,7 @@ const routeAutoDetection = async ({ request }) => {
76
88
  return response;
77
89
  }
78
90
  };
91
+
79
92
  //#endregion
80
93
  export { detectCountry, detectLocale, routeAutoDetection };
81
-
82
94
  //# sourceMappingURL=route-auto-detection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"route-auto-detection.js","names":[],"sources":["../../src/proxy/route-auto-detection.ts"],"sourcesContent":["'use server';\r\n\r\nimport { asEquatable, defaultLocale, defaultMarket, IMarket, IRoute } from '@websolutespa/bom-core';\r\nimport { NextRequest, NextResponse } from 'next/server';\r\nimport { localApiGet } from '../lib/http';\r\nimport { getRequestOrigin, Middleware, MiddlewareOptions } from './proxy';\r\n\r\nexport async function detectLocale(request: NextRequest, defaultLocale?: string) {\r\n const acceptLanguage = request.headers.get('accept-language')?.split(',')[0];\r\n const detectedLocale = request.cookies.get('NEXT_LOCALE')?.value || acceptLanguage || defaultLocale || process.env.DEFAULT_LOCALE;\r\n return detectedLocale as string;\r\n}\r\n\r\nexport async function detectCountry(request: NextRequest, defaultMarket?: string) {\r\n let ip = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip');\r\n if (ip) {\r\n ip = ip.split(',')[0];\r\n }\r\n const isValidIp = ip?.match(/^(\\d+?)\\.(\\d+?)\\.(\\d+?)\\.(\\d+?)$/);\r\n let detectedCountry = '';\r\n try {\r\n const token = process.env.IPINFO_TOKEN;\r\n if (token) {\r\n const url = isValidIp ?\r\n `https://api.ipinfo.io/lite/${ip}/country_code?token=${token}` :\r\n `https://api.ipinfo.io/lite/me/country_code?token=${token}`;\r\n const response = await fetch(url);\r\n if (response.ok) {\r\n const data = await response.text();\r\n detectedCountry = data.toLowerCase();\r\n }\r\n } else {\r\n const url = `https://geoip.websolute.it/Ip2Location/get_info.aspx?ipaddress=${isValidIp ? ip : ''}`;\r\n const response = await fetch(url);\r\n if (response.ok) {\r\n const xml = await response.text();\r\n detectedCountry = (\r\n ((xml.split('<CountryCode><![CDATA[')[1] || '').split(']]></CountryCode>')[0] || '')\r\n ).replace('-', '').toLowerCase();\r\n // console.log('detectedCountry', detectedCountry);\r\n }\r\n }\r\n // console.log('routeInterceptor.detectCountry', detectedCountry);\r\n return detectedCountry || defaultMarket || process.env.DEFAULT_MARKET;\r\n } catch (error) {\r\n console.log('routeInterceptor.detectCountry.error', error);\r\n }\r\n return (defaultMarket || process.env.DEFAULT_MARKET) as string;\r\n}\r\n\r\nexport const routeAutoDetection: Middleware = async ({ request }: MiddlewareOptions) => {\r\n let redirectUrl: string | undefined = undefined;\r\n const url = request.nextUrl;\r\n const origin = getRequestOrigin(request);\r\n if (url.pathname === '/') {\r\n const cookie = request.cookies.get('detectedRoute');\r\n if (cookie?.value) {\r\n redirectUrl = cookie.value;\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection', url.pathname);\r\n const rootRoutes: IRoute[] = await localApiGet('/-route?where[isRoot][equals]=true', {}, undefined, origin);\r\n // console.log('routeInterceptor.routeAutoDetection.rootRoutes', rootRoutes);\r\n const defaultRoute = rootRoutes.find(x => x.id === '/');\r\n // console.log('routeInterceptor.routeAutoDetection.defaultRoute', defaultRoute);\r\n if (defaultRoute) {\r\n return;\r\n }\r\n const markets: IMarket[] = await localApiGet('/market?pagination=false', {}, undefined, origin);\r\n // console.log('routeInterceptor.routeAutoDetection.markets', markets);\r\n const market = markets.find(x => x.isDefault) || markets.find(x => x.id === defaultMarket) || markets[0];\r\n // console.log('routeInterceptor.routeAutoDetection.market', market);\r\n const detectedCountry = await detectCountry(request, market.id);\r\n // console.log('routeInterceptor.routeAutoDetection.detectedCountry', detectedCountry);\r\n const detectedMarket = detectedCountry ? (\r\n markets.filter(x => Array.isArray(x.countries)).find(x => {\r\n const countries: string[] = (x.countries || []).map(x => typeof x === 'string' ? x : x.id as string);\r\n return countries.includes(detectedCountry);\r\n }) ||\r\n markets.find(x => !Array.isArray(x.countries))\r\n ) : undefined;\r\n // console.log('routeInterceptor.routeAutoDetection.detectedMarket', detectedMarket);\r\n let detectedMarketRoutes = rootRoutes.filter(x => x.market === detectedMarket?.id);\r\n if (detectedMarketRoutes.length === 0) {\r\n detectedMarketRoutes = rootRoutes.filter(x => x.market === market.id);\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection.detectedMarketRoutes', detectedMarketRoutes);\r\n const defaultMarketLocale = market.defaultLanguage ? (\r\n typeof market.defaultLanguage === 'string' ? market.defaultLanguage : market.defaultLanguage.id\r\n ) as string : defaultLocale;\r\n // console.log('routeInterceptor.routeAutoDetection.defaultMarketLocale', defaultMarketLocale);\r\n const detectedLocale = await detectLocale(request, defaultMarketLocale);\r\n // console.log('routeInterceptor.routeAutoDetection.detectedLocale', detectedLocale);\r\n const detectedLocaleRoutes = detectedMarketRoutes.filter(x => x.locale === detectedLocale);\r\n const detectedRoute =\r\n detectedLocaleRoutes.length > 0 ?\r\n detectedLocaleRoutes[0]! :\r\n detectedMarketRoutes.find(x => {\r\n const market = markets.find(m => m.id === x.market)!;\r\n const marketLocale = (market.defaultLanguage ? asEquatable(market.defaultLanguage as string) : defaultMarketLocale);\r\n return x.locale === marketLocale;\r\n })!;\r\n // console.log('routeInterceptor.routeAutoDetection.detectedRoute', detectedRoute);\r\n if (detectedRoute && detectedRoute.id !== url.pathname) {\r\n console.log('routeInterceptor.routeAutoDetection', detectedLocale, detectedCountry, detectedRoute.id);\r\n redirectUrl = detectedRoute.id;\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection', locale, detectedCountry, rootRoutes);\r\n }\r\n if (redirectUrl) {\r\n // console.log('routeInterceptor', 'redirectUrl', redirectUrl);\r\n const resolvedUrl = new URL(redirectUrl, origin).href;\r\n // console.log('routeInterceptor', 'resolvedUrl', resolvedUrl);\r\n const search = request.nextUrl.search;\r\n const response = NextResponse.redirect(resolvedUrl + search, { status: 307 });\r\n response.cookies.set({\r\n expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000),\r\n httpOnly: true,\r\n name: 'detectedRoute',\r\n path: '/',\r\n sameSite: 'lax',\r\n secure: true,\r\n value: redirectUrl,\r\n });\r\n return response;\r\n }\r\n};\r\n"],"mappings":";;;;;;AAOA,eAAsB,aAAa,SAAsB,eAAwB;CAC/E,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,iBAAiB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;CAE1E,OADuB,QAAQ,QAAQ,IAAI,aAAa,CAAC,EAAE,SAAS,kBAAkB,iBAAiB,QAAQ,IAAI;AAErH;AAEA,eAAsB,cAAc,SAAsB,eAAwB;CAChF,IAAI,KAAK,QAAQ,QAAQ,IAAI,iBAAiB,KAAK,QAAQ,QAAQ,IAAI,WAAW;CAClF,IAAI,IACF,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;CAErB,MAAM,YAAY,IAAI,MAAM,kCAAkC;CAC9D,IAAI,kBAAkB;CACtB,IAAI;EACF,MAAM,QAAQ,QAAQ,IAAI;EAC1B,IAAI,OAAO;GACT,MAAM,MAAM,YACV,8BAA8B,GAAG,sBAAsB,UACvD,oDAAoD;GACtD,MAAM,WAAW,MAAM,MAAM,GAAG;GAChC,IAAI,SAAS,IAEX,mBAAkB,MADC,SAAS,KAAK,EAAA,CACV,YAAY;EAEvC,OAAO;GACL,MAAM,MAAM,kEAAkE,YAAY,KAAK;GAC/F,MAAM,WAAW,MAAM,MAAM,GAAG;GAChC,IAAI,SAAS,IAEX,qBACI,MAFc,SAAS,KAAK,EAAA,CAExB,MAAM,wBAAwB,CAAC,CAAC,MAAM,GAAA,CAAI,MAAM,mBAAmB,CAAC,CAAC,MAAM,GAAA,CACjF,QAAQ,KAAK,EAAE,CAAC,CAAC,YAAY;EAGnC;EAEA,OAAO,mBAAmB,iBAAiB,QAAQ,IAAI;CACzD,SAAS,OAAO;EACd,QAAQ,IAAI,wCAAwC,KAAK;CAC3D;CACA,OAAQ,iBAAiB,QAAQ,IAAI;AACvC;AAEA,MAAa,qBAAiC,OAAO,EAAE,cAAiC;CACtF,IAAI,cAAkC,KAAA;CACtC,MAAM,MAAM,QAAQ;CACpB,MAAM,SAAS,iBAAiB,OAAO;CACvC,IAAI,IAAI,aAAa,KAAK;EACxB,MAAM,SAAS,QAAQ,QAAQ,IAAI,eAAe;EAClD,IAAI,QAAQ,OACV,cAAc,OAAO;EAGvB,MAAM,aAAuB,MAAM,YAAY,sCAAsC,CAAC,GAAG,KAAA,GAAW,MAAM;EAI1G,IAFqB,WAAW,MAAK,MAAK,EAAE,OAAO,GAEpC,GACb;EAEF,MAAM,UAAqB,MAAM,YAAY,4BAA4B,CAAC,GAAG,KAAA,GAAW,MAAM;EAE9F,MAAM,SAAS,QAAQ,MAAK,MAAK,EAAE,SAAS,KAAK,QAAQ,MAAK,MAAK,EAAE,OAAO,aAAa,KAAK,QAAQ;EAEtG,MAAM,kBAAkB,MAAM,cAAc,SAAS,OAAO,EAAE;EAE9D,MAAM,iBAAiB,kBACrB,QAAQ,QAAO,MAAK,MAAM,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,MAAK,MAAK;GAExD,QAD6B,EAAE,aAAa,CAAC,EAAA,CAAG,KAAI,MAAK,OAAO,MAAM,WAAW,IAAI,EAAE,EACxE,CAAC,CAAC,SAAS,eAAe;EAC3C,CAAC,KACD,QAAQ,MAAK,MAAK,CAAC,MAAM,QAAQ,EAAE,SAAS,CAAC,IAC3C,KAAA;EAEJ,IAAI,uBAAuB,WAAW,QAAO,MAAK,EAAE,WAAW,gBAAgB,EAAE;EACjF,IAAI,qBAAqB,WAAW,GAClC,uBAAuB,WAAW,QAAO,MAAK,EAAE,WAAW,OAAO,EAAE;EAGtE,MAAM,sBAAsB,OAAO,kBACjC,OAAO,OAAO,oBAAoB,WAAW,OAAO,kBAAkB,OAAO,gBAAgB,KACjF;EAEd,MAAM,iBAAiB,MAAM,aAAa,SAAS,mBAAmB;EAEtE,MAAM,uBAAuB,qBAAqB,QAAO,MAAK,EAAE,WAAW,cAAc;EACzF,MAAM,gBACJ,qBAAqB,SAAS,IAC5B,qBAAqB,KACrB,qBAAqB,MAAK,MAAK;GAC7B,MAAM,SAAS,QAAQ,MAAK,MAAK,EAAE,OAAO,EAAE,MAAM;GAClD,MAAM,eAAgB,OAAO,kBAAkB,YAAY,OAAO,eAAyB,IAAI;GAC/F,OAAO,EAAE,WAAW;EACtB,CAAC;EAEL,IAAI,iBAAiB,cAAc,OAAO,IAAI,UAAU;GACtD,QAAQ,IAAI,uCAAuC,gBAAgB,iBAAiB,cAAc,EAAE;GACpG,cAAc,cAAc;EAC9B;CAEF;CACA,IAAI,aAAa;EAEf,MAAM,cAAc,IAAI,IAAI,aAAa,MAAM,CAAC,CAAC;EAEjD,MAAM,SAAS,QAAQ,QAAQ;EAC/B,MAAM,WAAW,aAAa,SAAS,cAAc,QAAQ,EAAE,QAAQ,IAAI,CAAC;EAC5E,SAAS,QAAQ,IAAI;GACnB,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAuB;GACtD,UAAU;GACV,MAAM;GACN,MAAM;GACN,UAAU;GACV,QAAQ;GACR,OAAO;EACT,CAAC;EACD,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"route-auto-detection.js","names":["request: NextRequest","defaultLocale?: string","defaultLocale","defaultMarket?: string","defaultMarket","routeAutoDetection: Middleware","redirectUrl: string | undefined","rootRoutes: IRoute[]","markets: IMarket[]","countries: string[]","x","market"],"sources":["../../src/proxy/route-auto-detection.ts"],"sourcesContent":["'use server';\r\n\r\nimport { asEquatable, defaultLocale, defaultMarket, IMarket, IRoute } from '@websolutespa/bom-core';\r\nimport { NextRequest, NextResponse } from 'next/server';\r\nimport { localApiGet } from '../lib/http';\r\nimport { getRequestOrigin, Middleware, MiddlewareOptions } from './proxy';\r\n\r\nexport async function detectLocale(request: NextRequest, defaultLocale?: string) {\r\n const acceptLanguage = request.headers.get('accept-language')?.split(',')[0];\r\n const detectedLocale = request.cookies.get('NEXT_LOCALE')?.value || acceptLanguage || defaultLocale || process.env.DEFAULT_LOCALE;\r\n return detectedLocale as string;\r\n}\r\n\r\nexport async function detectCountry(request: NextRequest, defaultMarket?: string) {\r\n let ip = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip');\r\n if (ip) {\r\n ip = ip.split(',')[0];\r\n }\r\n const isValidIp = ip?.match(/^(\\d+?)\\.(\\d+?)\\.(\\d+?)\\.(\\d+?)$/);\r\n let detectedCountry = '';\r\n try {\r\n const token = process.env.IPINFO_TOKEN;\r\n if (token) {\r\n const url = isValidIp ?\r\n `https://api.ipinfo.io/lite/${ip}/country_code?token=${token}` :\r\n `https://api.ipinfo.io/lite/me/country_code?token=${token}`;\r\n const response = await fetch(url);\r\n if (response.ok) {\r\n const data = await response.text();\r\n detectedCountry = data.toLowerCase();\r\n }\r\n } else {\r\n const url = `https://geoip.websolute.it/Ip2Location/get_info.aspx?ipaddress=${isValidIp ? ip : ''}`;\r\n const response = await fetch(url);\r\n if (response.ok) {\r\n const xml = await response.text();\r\n detectedCountry = (\r\n ((xml.split('<CountryCode><![CDATA[')[1] || '').split(']]></CountryCode>')[0] || '')\r\n ).replace('-', '').toLowerCase();\r\n // console.log('detectedCountry', detectedCountry);\r\n }\r\n }\r\n // console.log('routeInterceptor.detectCountry', detectedCountry);\r\n return detectedCountry || defaultMarket || process.env.DEFAULT_MARKET;\r\n } catch (error) {\r\n console.log('routeInterceptor.detectCountry.error', error);\r\n }\r\n return (defaultMarket || process.env.DEFAULT_MARKET) as string;\r\n}\r\n\r\nexport const routeAutoDetection: Middleware = async ({ request }: MiddlewareOptions) => {\r\n let redirectUrl: string | undefined = undefined;\r\n const url = request.nextUrl;\r\n const origin = getRequestOrigin(request);\r\n if (url.pathname === '/') {\r\n const cookie = request.cookies.get('detectedRoute');\r\n if (cookie?.value) {\r\n redirectUrl = cookie.value;\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection', url.pathname);\r\n const rootRoutes: IRoute[] = await localApiGet('/-route?where[isRoot][equals]=true', {}, undefined, origin);\r\n // console.log('routeInterceptor.routeAutoDetection.rootRoutes', rootRoutes);\r\n const defaultRoute = rootRoutes.find(x => x.id === '/');\r\n // console.log('routeInterceptor.routeAutoDetection.defaultRoute', defaultRoute);\r\n if (defaultRoute) {\r\n return;\r\n }\r\n const markets: IMarket[] = await localApiGet('/market?pagination=false', {}, undefined, origin);\r\n // console.log('routeInterceptor.routeAutoDetection.markets', markets);\r\n const market = markets.find(x => x.isDefault) || markets.find(x => x.id === defaultMarket) || markets[0];\r\n // console.log('routeInterceptor.routeAutoDetection.market', market);\r\n const detectedCountry = await detectCountry(request, market.id);\r\n // console.log('routeInterceptor.routeAutoDetection.detectedCountry', detectedCountry);\r\n const detectedMarket = detectedCountry ? (\r\n markets.filter(x => Array.isArray(x.countries)).find(x => {\r\n const countries: string[] = (x.countries || []).map(x => typeof x === 'string' ? x : x.id as string);\r\n return countries.includes(detectedCountry);\r\n }) ||\r\n markets.find(x => !Array.isArray(x.countries))\r\n ) : undefined;\r\n // console.log('routeInterceptor.routeAutoDetection.detectedMarket', detectedMarket);\r\n let detectedMarketRoutes = rootRoutes.filter(x => x.market === detectedMarket?.id);\r\n if (detectedMarketRoutes.length === 0) {\r\n detectedMarketRoutes = rootRoutes.filter(x => x.market === market.id);\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection.detectedMarketRoutes', detectedMarketRoutes);\r\n const defaultMarketLocale = market.defaultLanguage ? (\r\n typeof market.defaultLanguage === 'string' ? market.defaultLanguage : market.defaultLanguage.id\r\n ) as string : defaultLocale;\r\n // console.log('routeInterceptor.routeAutoDetection.defaultMarketLocale', defaultMarketLocale);\r\n const detectedLocale = await detectLocale(request, defaultMarketLocale);\r\n // console.log('routeInterceptor.routeAutoDetection.detectedLocale', detectedLocale);\r\n const detectedLocaleRoutes = detectedMarketRoutes.filter(x => x.locale === detectedLocale);\r\n const detectedRoute =\r\n detectedLocaleRoutes.length > 0 ?\r\n detectedLocaleRoutes[0]! :\r\n detectedMarketRoutes.find(x => {\r\n const market = markets.find(m => m.id === x.market)!;\r\n const marketLocale = (market.defaultLanguage ? asEquatable(market.defaultLanguage as string) : defaultMarketLocale);\r\n return x.locale === marketLocale;\r\n })!;\r\n // console.log('routeInterceptor.routeAutoDetection.detectedRoute', detectedRoute);\r\n if (detectedRoute && detectedRoute.id !== url.pathname) {\r\n console.log('routeInterceptor.routeAutoDetection', detectedLocale, detectedCountry, detectedRoute.id);\r\n redirectUrl = detectedRoute.id;\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection', locale, detectedCountry, rootRoutes);\r\n }\r\n if (redirectUrl) {\r\n // console.log('routeInterceptor', 'redirectUrl', redirectUrl);\r\n const resolvedUrl = new URL(redirectUrl, origin).href;\r\n // console.log('routeInterceptor', 'resolvedUrl', resolvedUrl);\r\n const search = request.nextUrl.search;\r\n const response = NextResponse.redirect(resolvedUrl + search, { status: 307 });\r\n response.cookies.set({\r\n expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000),\r\n httpOnly: true,\r\n name: 'detectedRoute',\r\n path: '/',\r\n sameSite: 'lax',\r\n secure: true,\r\n value: redirectUrl,\r\n });\r\n return response;\r\n }\r\n};\r\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"route-proxy.d.ts","names":[],"sources":["../../src/proxy/route-proxy.ts"],"mappings":";;;;;;KAOY,KAAA,aAAkB,mBAAmB,mBAAmB,QAAQ;KAEhE,sBAAA;EAFA,OAAA,EAGD,WAHM;EAAA,IAAA,EAIT,cAJS;EAAa,KAAA,EAKrB,MALqB;EAAmB,QAAA,CAAA,EAAA,OAAA;AAA2B,CAAA;AAAR,KAQxD,eAAA,GARwD,CAAA,KAAA,EAQ9B,sBAR8B,EAAA,GAQH,oBARG,GAQoB,OARpB,CAQ4B,oBAR5B,CAAA;AAAO,KAU/D,qBAAA,GAV+D,CAAA,KAAA,EAU/B,MAV+B,EAAA,OAAA,EAUd,WAVc,EAAA,IAAA,EAUK,cAVL,EAAA,GAUwB,OAVxB,CAUgC,oBAVhC,CAAA;AAE/D,KAUA,aAAA,GAAgB,MAVM,GAAA;EAAA,KAAA,CAAA,EAAA,MAAA;AACvB,CAAA;AACH,KASI,qBAAA,GATJ;EACC,MAAA,CAAA,EASE,MATF;EAAM,KAAA,CAAA,EAUL,aAVK;AAGf,CAAA;AAA2B;AAAW;AAA2B;AAA+B;AAAR;AAAO;AAE/F;AAAiC;AAAW,iBAgB5B,gBAAA,CAhB4B,GAAA,WAAA,EAgBK,eAhBL,EAAA,CAAA,EAgByB,UAhBzB;AAAiB"}
1
+ {"version":3,"file":"route-proxy.d.ts","names":[],"sources":["../../src/proxy/route-proxy.ts"],"sourcesContent":[],"mappings":";;;;;;KAOY,KAAA,aAAkB,mBAAmB,mBAAmB,QAAQ;KAEhE,sBAAA;EAFA,OAAA,EAGD,WAHM;EAAA,IAAA,EAIT,cAJS;EAAA,KAAa,EAKrB,MALqB;EAAW,QAAQ,CAAA,EAAA,OAAA;CAAc;AAAK,KAQxD,eAAA,GARwD,CAAA,KAAA,EAQ9B,sBAR8B,EAAA,GAQH,oBARG,GAQoB,OARpB,CAQ4B,oBAR5B,CAAA;AAAO,KAU/D,qBAAA,GAV+D,CAAA,KAAA,EAU/B,MAV+B,EAAA,OAAA,EAUd,WAVc,EAAA,IAAA,EAUK,cAVL,EAAA,GAUwB,OAVxB,CAUgC,oBAVhC,CAAA;AAE/D,KAUA,aAAA,GAAgB,MAVM,GAAA;EAAA,KAAA,CAAA,EAAA,MAAA;CAAA;AAE1B,KASI,qBAAA,GATJ;EAAc,MACb,CAAA,EASE,MATF;EAAM,KAAA,CAAA,EAUL,aAVK;AAGf,CAAA;;;;;;AAA+F;AAE/F;;AAA4C,iBAgB5B,gBAAA,CAhB4B,GAAA,WAAA,EAgBK,eAhBL,EAAA,CAAA,EAgByB,UAhBzB"}
@@ -3,14 +3,22 @@ import { getHrefBeforeRedirect, getNextUrl } from "../server/utils.js";
3
3
  import { getRequestOrigin } from "./proxy.js";
4
4
  import { defaultLocale, defaultMarket } from "@websolutespa/bom-core";
5
5
  import { NextResponse } from "next/server";
6
+
6
7
  //#region src/proxy/route-proxy.ts
7
8
  /**
9
+
8
10
  * Resolves a public request to a CMS route, then rewrites it to the internal
11
+
9
12
  * Next.js page while preserving the original browser URL.
13
+
10
14
  *
15
+
11
16
  * The resolver call is deliberately made to this request's public origin so it
17
+
12
18
  * works behind reverse proxies and deployment hosts. A rewrite keeps routing
19
+
13
20
  * server-side, avoiding an extra browser round trip that a redirect would add.
21
+
14
22
  */
15
23
  function createRouteProxy(...middlewares) {
16
24
  return async function({ request, next }) {
@@ -47,7 +55,8 @@ function createRouteProxy(...middlewares) {
47
55
  headers.set("x-schema", route.schema);
48
56
  headers.set("x-id", String(route.page));
49
57
  headers.set("x-forwarded-pathname", nextUrl.pathname);
50
- return NextResponse.rewrite(nextUrl, { request: { headers } });
58
+ const response = NextResponse.rewrite(nextUrl, { request: { headers } });
59
+ return response;
51
60
  } else {
52
61
  const parentRoute = resolution?.parent;
53
62
  const market = parentRoute?.market || defaultMarket;
@@ -60,7 +69,8 @@ function createRouteProxy(...middlewares) {
60
69
  headers.set("x-id", "404");
61
70
  headers.set("x-forwarded-pathname", nextUrl.pathname);
62
71
  console.log("createRouteProxy.NotFound", pathname);
63
- return NextResponse.rewrite(nextUrl, { request: { headers } });
72
+ const response = NextResponse.rewrite(nextUrl, { request: { headers } });
73
+ return response;
64
74
  }
65
75
  } catch (error) {
66
76
  const routeError = error && typeof error === "object" ? error : {};
@@ -69,14 +79,20 @@ function createRouteProxy(...middlewares) {
69
79
  const nextUrl = request.nextUrl.clone();
70
80
  nextUrl.pathname = "/";
71
81
  headers.set("x-forwarded-pathname", nextUrl.pathname);
72
- return NextResponse.redirect(nextUrl, 307);
82
+ const response = NextResponse.redirect(nextUrl, 307);
83
+ return response;
73
84
  } else if (routeError.status && routeError.status >= 400 && routeError.status < 500) {
74
85
  if (routeError.status === 404)
75
86
  /**
87
+
76
88
  * A resolver miss is not necessarily a CMS 404: it may be a Next.js
89
+
77
90
  * file-system route such as an API endpoint or static asset. Letting
91
+
78
92
  * Next continue avoids routing those requests through a fallback
93
+
79
94
  * render and keeps their fast native handling intact.
95
+
80
96
  */
81
97
  return;
82
98
  console.log("createRouteProxy.4xx", url.pathname, routeError.status, routeError.statusText);
@@ -90,14 +106,15 @@ function createRouteProxy(...middlewares) {
90
106
  headers.set("x-id", "404");
91
107
  headers.set("x-forwarded-pathname", nextUrl.pathname);
92
108
  console.log("createRouteProxy.NotFound", pathname);
93
- return NextResponse.rewrite(nextUrl, { request: { headers } });
109
+ const response = NextResponse.rewrite(nextUrl, { request: { headers } });
110
+ return response;
94
111
  }
95
112
  console.log("createRouteProxy.error.5xx", url.pathname, routeError.url, routeError.status, routeError.statusText || error);
96
113
  return;
97
114
  }
98
115
  };
99
116
  }
117
+
100
118
  //#endregion
101
119
  export { createRouteProxy };
102
-
103
120
  //# sourceMappingURL=route-proxy.js.map