@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.
- package/CHANGELOG.md +17 -7
- package/dist/_virtual/{_rolldown/runtime.js → rolldown_runtime.js} +7 -4
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +17 -6
- package/dist/client/client.js.map +1 -1
- package/dist/client/extra.d.ts +3 -3
- package/dist/client/extra.d.ts.map +1 -1
- package/dist/client/extra.js +10 -5
- package/dist/client/extra.js.map +1 -1
- package/dist/client/label.d.ts.map +1 -1
- package/dist/client/label.js +10 -5
- package/dist/client/label.js.map +1 -1
- package/dist/client/layout.d.ts +3 -3
- package/dist/client/layout.d.ts.map +1 -1
- package/dist/client/layout.js +10 -5
- package/dist/client/layout.js.map +1 -1
- package/dist/client/local.collection.d.ts.map +1 -1
- package/dist/client/local.collection.js +4 -2
- package/dist/client/local.collection.js.map +1 -1
- package/dist/client/metadata.d.ts +3 -3
- package/dist/client/metadata.d.ts.map +1 -1
- package/dist/client/metadata.js +48 -40
- package/dist/client/metadata.js.map +1 -1
- package/dist/client/page.d.ts +3 -3
- package/dist/client/page.d.ts.map +1 -1
- package/dist/client/page.js +10 -5
- package/dist/client/page.js.map +1 -1
- package/dist/client/useApi.d.ts +7 -7
- package/dist/client/useApi.d.ts.map +1 -1
- package/dist/client/useApi.js +2 -1
- package/dist/client/useApi.js.map +1 -1
- package/dist/client/useCollectionApi.d.ts +6 -6
- package/dist/client/useCollectionApi.d.ts.map +1 -1
- package/dist/client/useCollectionApi.js +4 -2
- package/dist/client/useCollectionApi.js.map +1 -1
- package/dist/client/useExtra.d.ts.map +1 -1
- package/dist/client/useExtra.js +5 -2
- package/dist/client/useExtra.js.map +1 -1
- package/dist/client/useHttp.d.ts.map +1 -1
- package/dist/client/useHttp.js +9 -6
- package/dist/client/useHttp.js.map +1 -1
- package/dist/client/useLabel.d.ts.map +1 -1
- package/dist/client/useLabel.js +5 -2
- package/dist/client/useLabel.js.map +1 -1
- package/dist/client/useLayout.d.ts.map +1 -1
- package/dist/client/useLayout.js +5 -2
- package/dist/client/useLayout.js.map +1 -1
- package/dist/client/useLink.d.ts.map +1 -1
- package/dist/client/useLink.js +7 -3
- package/dist/client/useLink.js.map +1 -1
- package/dist/client/useMetaData.d.ts.map +1 -1
- package/dist/client/useMetaData.js +5 -2
- package/dist/client/useMetaData.js.map +1 -1
- package/dist/client/usePage.d.ts.map +1 -1
- package/dist/client/usePage.js +5 -2
- package/dist/client/usePage.js.map +1 -1
- package/dist/client/useUser.d.ts.map +1 -1
- package/dist/client/useUser.js +5 -2
- package/dist/client/useUser.js.map +1 -1
- package/dist/client/user.d.ts.map +1 -1
- package/dist/client/user.js +17 -11
- package/dist/client/user.js.map +1 -1
- package/dist/exports/client.js +2 -1
- package/dist/exports/instrumentation.js +2 -1
- package/dist/exports/proxy.js +2 -1
- package/dist/exports/server.js +2 -1
- package/dist/index.js +2 -1
- package/dist/instrumentation/client.d.ts.map +1 -1
- package/dist/instrumentation/client.js +2 -1
- package/dist/instrumentation/client.js.map +1 -1
- package/dist/instrumentation/sentry/capture.requestError.js +4 -1
- package/dist/instrumentation/sentry/capture.requestError.js.map +1 -1
- package/dist/instrumentation/sentry/capture.routerTransitionStart.js +2 -1
- package/dist/instrumentation/sentry/capture.routerTransitionStart.js.map +1 -1
- package/dist/instrumentation/sentry/config.client.js +10 -2
- package/dist/instrumentation/sentry/config.client.js.map +1 -0
- package/dist/instrumentation/sentry/config.edge.js +10 -2
- package/dist/instrumentation/sentry/config.edge.js.map +1 -0
- package/dist/instrumentation/sentry/config.server.js +10 -2
- package/dist/instrumentation/sentry/config.server.js.map +1 -0
- package/dist/instrumentation/server.d.ts.map +1 -1
- package/dist/instrumentation/server.js +8 -5
- package/dist/instrumentation/server.js.map +1 -1
- package/dist/instrumentation/types.d.ts.map +1 -1
- package/dist/lib/breadcrumb.d.ts.map +1 -1
- package/dist/lib/breadcrumb.js +6 -1
- package/dist/lib/breadcrumb.js.map +1 -1
- package/dist/lib/const.d.ts.map +1 -1
- package/dist/lib/const.js +1 -1
- package/dist/lib/const.js.map +1 -1
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js +6 -3
- package/dist/lib/http.js.map +1 -1
- package/dist/lib/label.d.ts.map +1 -1
- package/dist/lib/label.js +4 -3
- package/dist/lib/label.js.map +1 -1
- package/dist/lib/layout.defaults.d.ts.map +1 -1
- package/dist/lib/layout.defaults.js +1 -1
- package/dist/lib/layout.defaults.js.map +1 -1
- package/dist/lib/link.d.ts.map +1 -1
- package/dist/lib/link.js +2 -1
- package/dist/lib/link.js.map +1 -1
- package/dist/lib/meta-data.d.ts.map +1 -1
- package/dist/lib/open-graph.d.ts.map +1 -1
- package/dist/lib/pagination.d.ts.map +1 -1
- package/dist/lib/pagination.js +4 -2
- package/dist/lib/pagination.js.map +1 -1
- package/dist/lib/route.d.ts.map +1 -1
- package/dist/lib/route.js +9 -3
- package/dist/lib/route.js.map +1 -1
- package/dist/lib/store.d.ts.map +1 -1
- package/dist/lib/store.js +31 -31
- package/dist/lib/store.js.map +1 -1
- package/dist/lib/structured-data.d.ts.map +1 -1
- package/dist/lib/twitter-card.d.ts.map +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +3 -2
- package/dist/lib/utils.js.map +1 -1
- package/dist/mock.d.ts.map +1 -1
- package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js +3 -2
- package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js.map +1 -1
- package/dist/node_modules/deepmerge/dist/cjs.js +17 -9
- package/dist/node_modules/deepmerge/dist/cjs.js.map +1 -1
- package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js +2 -2
- package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js.map +1 -1
- package/dist/node_modules/dom-serializer/lib/esm/index.js +10 -15
- package/dist/node_modules/dom-serializer/lib/esm/index.js.map +1 -1
- package/dist/node_modules/domelementtype/lib/esm/index.js +12 -12
- package/dist/node_modules/domelementtype/lib/esm/index.js.map +1 -1
- package/dist/node_modules/domhandler/lib/esm/index.js +4 -3
- package/dist/node_modules/domhandler/lib/esm/index.js.map +1 -1
- package/dist/node_modules/domhandler/lib/esm/node.js +8 -7
- package/dist/node_modules/domhandler/lib/esm/node.js.map +1 -1
- package/dist/node_modules/entities/lib/esm/decode.js +33 -32
- package/dist/node_modules/entities/lib/esm/decode.js.map +1 -1
- package/dist/node_modules/entities/lib/esm/decode_codepoint.js +5 -5
- package/dist/node_modules/entities/lib/esm/decode_codepoint.js.map +1 -1
- package/dist/node_modules/entities/lib/esm/escape.js +14 -6
- package/dist/node_modules/entities/lib/esm/escape.js.map +1 -1
- package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js +2 -2
- package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js.map +1 -1
- package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js +2 -2
- package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js.map +1 -1
- package/dist/node_modules/html-to-text/lib/html-to-text.js +45 -33
- package/dist/node_modules/html-to-text/lib/html-to-text.js.map +1 -1
- package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js +25 -25
- package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js.map +1 -1
- package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js +76 -73
- package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js.map +1 -1
- package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js +4 -3
- package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js.map +1 -1
- package/dist/node_modules/leac/lib/leac.js +72 -72
- package/dist/node_modules/leac/lib/leac.js.map +1 -1
- package/dist/node_modules/parseley/lib/parseley.js +37 -33
- package/dist/node_modules/parseley/lib/parseley.js.map +1 -1
- package/dist/node_modules/peberminta/lib/core.js +4 -4
- package/dist/node_modules/peberminta/lib/core.js.map +1 -1
- package/dist/node_modules/selderee/lib/selderee.js +16 -10
- package/dist/node_modules/selderee/lib/selderee.js.map +1 -1
- package/dist/proxy/protected-route.d.ts.map +1 -1
- package/dist/proxy/protected-route.js +11 -6
- package/dist/proxy/protected-route.js.map +1 -1
- package/dist/proxy/proxy.d.ts.map +1 -1
- package/dist/proxy/proxy.js +17 -2
- package/dist/proxy/proxy.js.map +1 -1
- package/dist/proxy/route-auto-detection.d.ts.map +1 -1
- package/dist/proxy/route-auto-detection.js +26 -14
- package/dist/proxy/route-auto-detection.js.map +1 -1
- package/dist/proxy/route-proxy.d.ts.map +1 -1
- package/dist/proxy/route-proxy.js +22 -5
- package/dist/proxy/route-proxy.js.map +1 -1
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +20 -2
- package/dist/server/context.js.map +1 -1
- package/dist/server/handlers/auth.handler.d.ts.map +1 -1
- package/dist/server/handlers/auth.handler.js +4 -2
- package/dist/server/handlers/auth.handler.js.map +1 -1
- package/dist/server/handlers/captions.handler.d.ts.map +1 -1
- package/dist/server/handlers/captions.handler.js +4 -2
- package/dist/server/handlers/captions.handler.js.map +1 -1
- package/dist/server/handlers/collection.handler.d.ts.map +1 -1
- package/dist/server/handlers/collection.handler.js +2 -1
- package/dist/server/handlers/collection.handler.js.map +1 -1
- package/dist/server/handlers/error-response.js +6 -2
- package/dist/server/handlers/error-response.js.map +1 -1
- package/dist/server/handlers/index.handler.d.ts.map +1 -1
- package/dist/server/handlers/index.handler.js +2 -1
- package/dist/server/handlers/index.handler.js.map +1 -1
- package/dist/server/handlers/preview.handler.d.ts.map +1 -1
- package/dist/server/handlers/preview.handler.js +6 -3
- package/dist/server/handlers/preview.handler.js.map +1 -1
- package/dist/server/handlers/registry.handler.d.ts.map +1 -1
- package/dist/server/handlers/registry.handler.js +14 -9
- package/dist/server/handlers/registry.handler.js.map +1 -1
- package/dist/server/handlers/route.handler.d.ts.map +1 -1
- package/dist/server/handlers/route.handler.js +12 -3
- package/dist/server/handlers/route.handler.js.map +1 -1
- package/dist/server/handlers/sitemap.handler.d.ts.map +1 -1
- package/dist/server/handlers/sitemap.handler.js +12 -9
- package/dist/server/handlers/sitemap.handler.js.map +1 -1
- package/dist/server/handlers/static-params.handler.d.ts.map +1 -1
- package/dist/server/handlers/static-params.handler.js +13 -8
- package/dist/server/handlers/static-params.handler.js.map +1 -1
- package/dist/server/handlers/vars.handler.d.ts.map +1 -1
- package/dist/server/handlers/vars.handler.js +5 -4
- package/dist/server/handlers/vars.handler.js.map +1 -1
- package/dist/server/layout.js +34 -12
- package/dist/server/layout.js.map +1 -1
- package/dist/server/lazy.d.ts.map +1 -1
- package/dist/server/lazy.js +5 -2
- package/dist/server/lazy.js.map +1 -1
- package/dist/server/local-api.d.ts.map +1 -1
- package/dist/server/local-api.js +12 -6
- package/dist/server/local-api.js.map +1 -1
- package/dist/server/metadata.d.ts.map +1 -1
- package/dist/server/metadata.js +5 -1
- package/dist/server/metadata.js.map +1 -1
- package/dist/server/mixer-payload.d.ts +1 -1
- package/dist/server/mixer-payload.d.ts.map +1 -1
- package/dist/server/mixer.d.ts.map +1 -1
- package/dist/server/mixer.js +183 -57
- package/dist/server/mixer.js.map +1 -1
- package/dist/server/page.d.ts.map +1 -1
- package/dist/server/page.js +15 -4
- package/dist/server/page.js.map +1 -1
- package/dist/server/utils.d.ts.map +1 -1
- package/dist/server/utils.js +4 -2
- package/dist/server/utils.js.map +1 -1
- package/dist/server/utmz.d.ts.map +1 -1
- package/dist/server/utmz.js +1 -1
- package/dist/server/utmz.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -11
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { compareSpecificity, normalize, parse1, serialize } from "../../parseley/lib/parseley.js";
|
|
2
|
-
|
|
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:
|
|
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)
|
|
106
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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":"
|
|
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;
|
|
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"}
|
package/dist/proxy/proxy.js
CHANGED
|
@@ -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
|
-
|
|
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
|
package/dist/proxy/proxy.js.map
CHANGED
|
@@ -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":"
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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() +
|
|
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":"
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|