@sitecore-content-sdk/nextjs 2.1.0-canary.1 → 2.1.0-canary.10
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/dist/cjs/initialization/proxy/analytics-adapter.js +6 -3
- package/dist/cjs/proxy/bot-tracking-proxy.js +14 -3
- package/dist/cjs/proxy/personalize-proxy.js +1 -1
- package/dist/cjs/proxy/redirects-proxy.js +49 -11
- package/dist/esm/initialization/proxy/analytics-adapter.js +5 -2
- package/dist/esm/proxy/bot-tracking-proxy.js +15 -4
- package/dist/esm/proxy/personalize-proxy.js +1 -1
- package/dist/esm/proxy/redirects-proxy.js +49 -11
- package/package.json +11 -11
- package/types/initialization/proxy/analytics-adapter.d.ts.map +1 -1
- package/types/proxy/bot-tracking-proxy.d.ts.map +1 -1
- package/types/proxy/redirects-proxy.d.ts +20 -1
- package/types/proxy/redirects-proxy.d.ts.map +1 -1
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getClientId = void 0;
|
|
4
4
|
exports.analyticsProxyAdapter = analyticsProxyAdapter;
|
|
5
5
|
const internal_1 = require("@sitecore-content-sdk/analytics-core/internal");
|
|
6
|
-
const internal_2 = require("@sitecore-content-sdk/analytics-core/internal");
|
|
7
6
|
const core_1 = require("@sitecore-content-sdk/core");
|
|
8
7
|
/**
|
|
9
8
|
* Creates a proxy-based analytics adapter that reads and writes the visitor ID
|
|
@@ -17,13 +16,17 @@ const core_1 = require("@sitecore-content-sdk/core");
|
|
|
17
16
|
function analyticsProxyAdapter(request, response) {
|
|
18
17
|
return {
|
|
19
18
|
type: 'proxy',
|
|
19
|
+
isBot: () => {
|
|
20
|
+
const botCookie = (0, internal_1.getBotCookieServerSide)(request.cookies.toString());
|
|
21
|
+
return !!botCookie || (0, internal_1.isBot)(request.headers.get('user-agent'));
|
|
22
|
+
},
|
|
20
23
|
getClientId: () => {
|
|
21
24
|
return (0, exports.getClientId)(request);
|
|
22
25
|
},
|
|
23
26
|
setClientId: async () => {
|
|
24
27
|
var _a;
|
|
25
28
|
const coreConfig = (0, core_1.getCoreContext)().config;
|
|
26
|
-
const analyticsOptions = (0,
|
|
29
|
+
const analyticsOptions = (0, internal_1.getAnalyticsPlugin)().options;
|
|
27
30
|
const cookieOptions = analyticsOptions.cookies;
|
|
28
31
|
const clientIdCookieName = cookieOptions.name;
|
|
29
32
|
const legacyClientIdCookieName = `${internal_1.COOKIE_NAME_PREFIX}${coreConfig.contextId}`;
|
|
@@ -65,7 +68,7 @@ function analyticsProxyAdapter(request, response) {
|
|
|
65
68
|
*/
|
|
66
69
|
const getClientId = (request) => {
|
|
67
70
|
var _a;
|
|
68
|
-
const clientIdCookieName = (0,
|
|
71
|
+
const clientIdCookieName = (0, internal_1.getAnalyticsPlugin)().options.cookies.name;
|
|
69
72
|
return ((_a = request.cookies.get(clientIdCookieName)) === null || _a === void 0 ? void 0 : _a.value) || null;
|
|
70
73
|
};
|
|
71
74
|
exports.getClientId = getClientId;
|
|
@@ -7,7 +7,7 @@ exports.BotTrackingProxy = void 0;
|
|
|
7
7
|
const core_1 = require("@sitecore-content-sdk/core");
|
|
8
8
|
const analytics_core_1 = require("@sitecore-content-sdk/analytics-core");
|
|
9
9
|
const events_1 = require("@sitecore-content-sdk/events");
|
|
10
|
-
const internal_1 = require("@sitecore-content-sdk/
|
|
10
|
+
const internal_1 = require("@sitecore-content-sdk/analytics-core/internal");
|
|
11
11
|
const proxy_1 = require("./proxy");
|
|
12
12
|
const debug_1 = __importDefault(require("../debug"));
|
|
13
13
|
const analytics_adapter_1 = require("../initialization/proxy/analytics-adapter");
|
|
@@ -39,7 +39,12 @@ class BotTrackingProxy extends proxy_1.ProxyBase {
|
|
|
39
39
|
debug_1.default.common('bot tracking proxy skipped (local environment)');
|
|
40
40
|
return res;
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
const userAgent = req.headers.get('user-agent');
|
|
43
|
+
if (!userAgent) {
|
|
44
|
+
debug_1.default.common('bot tracking proxy skipped (no user-agent)');
|
|
45
|
+
return res;
|
|
46
|
+
}
|
|
47
|
+
if (!(0, internal_1.isBot)(userAgent)) {
|
|
43
48
|
debug_1.default.common('bot tracking proxy skipped (not a bot)');
|
|
44
49
|
return res;
|
|
45
50
|
}
|
|
@@ -48,6 +53,7 @@ class BotTrackingProxy extends proxy_1.ProxyBase {
|
|
|
48
53
|
return res;
|
|
49
54
|
}
|
|
50
55
|
const site = this.getSite(req, res);
|
|
56
|
+
const language = this.getLanguage(req, res);
|
|
51
57
|
const botTracking = async () => {
|
|
52
58
|
await (0, core_1.initContentSdk)({
|
|
53
59
|
config: {
|
|
@@ -65,13 +71,18 @@ class BotTrackingProxy extends proxy_1.ProxyBase {
|
|
|
65
71
|
(0, events_1.eventsPlugin)(),
|
|
66
72
|
],
|
|
67
73
|
});
|
|
68
|
-
await (0, events_1.botPageView)(
|
|
74
|
+
await (0, events_1.botPageView)({
|
|
75
|
+
page: req.nextUrl.pathname,
|
|
76
|
+
language: language,
|
|
77
|
+
userAgent,
|
|
78
|
+
});
|
|
69
79
|
};
|
|
70
80
|
res.cookies.set(internal_1.BOT_DETECTION_COOKIE, '1', {
|
|
71
81
|
secure: true,
|
|
72
82
|
sameSite: 'lax',
|
|
73
83
|
path: '/',
|
|
74
84
|
});
|
|
85
|
+
debug_1.default.common('bot tracking proxy (visitor is a bot)');
|
|
75
86
|
if (this.config.fetchEvent) {
|
|
76
87
|
this.config.fetchEvent.waitUntil(botTracking());
|
|
77
88
|
}
|
|
@@ -5,9 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.PersonalizeProxy = void 0;
|
|
7
7
|
const personalize_1 = require("@sitecore-content-sdk/content/personalize");
|
|
8
|
+
const internal_1 = require("@sitecore-content-sdk/analytics-core/internal");
|
|
8
9
|
const core_1 = require("@sitecore-content-sdk/core");
|
|
9
10
|
const personalize_2 = require("@sitecore-content-sdk/personalize");
|
|
10
|
-
const internal_1 = require("@sitecore-content-sdk/events/internal");
|
|
11
11
|
const analytics_core_1 = require("@sitecore-content-sdk/analytics-core");
|
|
12
12
|
const personalize_3 = require("@sitecore-content-sdk/personalize");
|
|
13
13
|
const analytics_adapter_1 = require("../initialization/proxy/analytics-adapter");
|
|
@@ -65,7 +65,7 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
65
65
|
}
|
|
66
66
|
site = this.getSite(req, res);
|
|
67
67
|
// Find the redirect from result of RedirectService
|
|
68
|
-
const existsRedirect = await this.getExistsRedirect(req, site.name);
|
|
68
|
+
const existsRedirect = await this.getExistsRedirect(req, site.name, language);
|
|
69
69
|
if (!existsRedirect) {
|
|
70
70
|
debug_1.default.redirects('skipped (redirect does not exist)');
|
|
71
71
|
return res;
|
|
@@ -202,19 +202,38 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
202
202
|
* @returns Promise<RedirectInfo | undefined>
|
|
203
203
|
* @private
|
|
204
204
|
*/
|
|
205
|
-
async getExistsRedirect(req, siteName) {
|
|
205
|
+
async getExistsRedirect(req, siteName, requestLocale) {
|
|
206
206
|
if (!this.redirectsService) {
|
|
207
207
|
return undefined;
|
|
208
208
|
}
|
|
209
209
|
const { pathname: incomingURL, search: incomingQS = '' } = this.normalizeUrl(req.nextUrl.clone());
|
|
210
|
-
const locale = this.getLanguage(req);
|
|
211
210
|
const normalizedPath = incomingURL.replace(/\/*$/gi, '').toLowerCase();
|
|
212
211
|
const redirects = await this.redirectsService.fetchRedirects(siteName);
|
|
213
|
-
|
|
212
|
+
// using locale of current request (from URL, headers or otherwise), used to match versioned redirect rules
|
|
213
|
+
const matchedLocaleRedirect = this.matchRedirectItemRedirect(redirects, requestLocale, normalizedPath);
|
|
214
|
+
if (matchedLocaleRedirect) {
|
|
215
|
+
return matchedLocaleRedirect;
|
|
216
|
+
}
|
|
217
|
+
// locale of the url - if present in the url, used for redirect map matching
|
|
218
|
+
const urlLocale = req.nextUrl.locale;
|
|
219
|
+
return this.matchFromRedirectMapRedirect(redirects, urlLocale, incomingURL, incomingQS);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Matches redirect-map rules without a `locale` field against the incoming URL (static or regex patterns).
|
|
223
|
+
* @param {RedirectResult[]} redirects All redirects from the service (non-locale entries are filtered inside).
|
|
224
|
+
* @param {string} urlLocale Locale segment from the request URL (`nextUrl.locale`).
|
|
225
|
+
* @param {string} incomingURL Original pathname used for regex tests.
|
|
226
|
+
* @param {string} incomingQS Query string including leading `?` if present.
|
|
227
|
+
* @returns {RedirectResult | undefined} First matching redirect or undefined.
|
|
228
|
+
* @private
|
|
229
|
+
*/
|
|
230
|
+
matchFromRedirectMapRedirect(redirects, urlLocale, incomingURL, incomingQS) {
|
|
231
|
+
const nonLocaleRedirects = redirects.filter((redirect) => !redirect.locale);
|
|
214
232
|
let matchedQueryString;
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
233
|
+
const normalizedPath = incomingURL.replace(/\/*$/gi, '').toLowerCase();
|
|
234
|
+
const localePath = `/${urlLocale.toLowerCase()}${normalizedPath}`;
|
|
235
|
+
return nonLocaleRedirects.length
|
|
236
|
+
? nonLocaleRedirects.find((redirect) => {
|
|
218
237
|
// process static URL (non-regex) rules
|
|
219
238
|
if ((0, tools_1.isRegexOrUrl)(redirect.pattern) === 'url') {
|
|
220
239
|
const urlArray = redirect.pattern.endsWith('/')
|
|
@@ -236,14 +255,14 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
236
255
|
// process regex rules
|
|
237
256
|
// Modify the redirect pattern to ignore the language prefix in the path
|
|
238
257
|
// And escapes non-special "?" characters in a string or regex.
|
|
239
|
-
redirect.pattern = (0, tools_1.escapeNonSpecialQuestionMarks)('^' + redirect.pattern.replace(new RegExp(`^[^]?/${
|
|
258
|
+
redirect.pattern = (0, tools_1.escapeNonSpecialQuestionMarks)('^' + redirect.pattern.replace(new RegExp(`^[^]?/${urlLocale}/`, 'gi'), '') // ensure function thinks input is regex
|
|
240
259
|
);
|
|
241
260
|
// Prepare the redirect pattern as a regular expression, making it more flexible for matching URLs
|
|
242
261
|
redirect.pattern = `/^\/${redirect.pattern
|
|
243
262
|
.replace(/^\/|\/$/g, '') // Removes leading and trailing slashes
|
|
244
263
|
.replace(/^\^\/|\/\$$/g, '') // Removes unnecessary start (^) and end ($) anchors
|
|
245
264
|
.replace(/^\^|\$$/g, '') // Further cleans up anchors
|
|
246
|
-
.replace(/\$\/
|
|
265
|
+
.replace(/\$\/g$/g, '')}[\/]?$/i`; // Ensures the pattern allows an optional trailing slash
|
|
247
266
|
// Redirect pattern matches the full incoming URL with query string present
|
|
248
267
|
matchedQueryString = [
|
|
249
268
|
(0, regex_parser_1.default)(redirect.pattern).test(`/${localePath}${incomingQS}`),
|
|
@@ -253,9 +272,28 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
253
272
|
: undefined;
|
|
254
273
|
// Save the matched query string (if found) into the redirect object
|
|
255
274
|
redirect.matchedQueryString = matchedQueryString || '';
|
|
256
|
-
return (!!((0, regex_parser_1.default)(redirect.pattern).test(`/${
|
|
275
|
+
return (!!((0, regex_parser_1.default)(redirect.pattern).test(`/${urlLocale}${incomingURL}`) ||
|
|
257
276
|
(0, regex_parser_1.default)(redirect.pattern).test(incomingURL) ||
|
|
258
|
-
matchedQueryString) &&
|
|
277
|
+
matchedQueryString) &&
|
|
278
|
+
(redirect.locale ? redirect.locale.toLowerCase() === urlLocale.toLowerCase() : true));
|
|
279
|
+
})
|
|
280
|
+
: undefined;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Processes redirect rules from redirect items (language-versioned)
|
|
284
|
+
* @param {RedirectResult[]} redirects redirect entries from Edge
|
|
285
|
+
* @param {string} locale current request locale
|
|
286
|
+
* @param {string} currentPath current request path
|
|
287
|
+
* @returns {RedirectResult | undefined} matched redirect item redirect result or undefined
|
|
288
|
+
* @private
|
|
289
|
+
*/
|
|
290
|
+
matchRedirectItemRedirect(redirects, locale, currentPath) {
|
|
291
|
+
const nonLocalePath = currentPath.replace(new RegExp(`^\/?${locale}\/`, 'i'), '/');
|
|
292
|
+
return redirects.length
|
|
293
|
+
? redirects.find((redirect) => {
|
|
294
|
+
const patternPath = redirect.pattern.replace(/\/*$/g, '').toLowerCase();
|
|
295
|
+
// locale rules are easy and nice
|
|
296
|
+
return redirect.locale === locale && patternPath === nonLocalePath;
|
|
259
297
|
})
|
|
260
298
|
: undefined;
|
|
261
299
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { COOKIE_NAME_PREFIX, fetchClientIdFromEdgeProxy, getDefaultCookieAttributes, } from '@sitecore-content-sdk/analytics-core/internal';
|
|
2
|
-
import { getAnalyticsPlugin, } from '@sitecore-content-sdk/analytics-core/internal';
|
|
1
|
+
import { COOKIE_NAME_PREFIX, fetchClientIdFromEdgeProxy, getBotCookieServerSide, getDefaultCookieAttributes, getAnalyticsPlugin, isBot, } from '@sitecore-content-sdk/analytics-core/internal';
|
|
3
2
|
import { getCoreContext } from '@sitecore-content-sdk/core';
|
|
4
3
|
/**
|
|
5
4
|
* Creates a proxy-based analytics adapter that reads and writes the visitor ID
|
|
@@ -13,6 +12,10 @@ import { getCoreContext } from '@sitecore-content-sdk/core';
|
|
|
13
12
|
export function analyticsProxyAdapter(request, response) {
|
|
14
13
|
return {
|
|
15
14
|
type: 'proxy',
|
|
15
|
+
isBot: () => {
|
|
16
|
+
const botCookie = getBotCookieServerSide(request.cookies.toString());
|
|
17
|
+
return !!botCookie || isBot(request.headers.get('user-agent'));
|
|
18
|
+
},
|
|
16
19
|
getClientId: () => {
|
|
17
20
|
return getClientId(request);
|
|
18
21
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { initContentSdk } from '@sitecore-content-sdk/core';
|
|
2
2
|
import { analyticsPlugin } from '@sitecore-content-sdk/analytics-core';
|
|
3
|
-
import { eventsPlugin, botPageView
|
|
4
|
-
import { isBot, BOT_DETECTION_COOKIE } from '@sitecore-content-sdk/
|
|
3
|
+
import { eventsPlugin, botPageView } from '@sitecore-content-sdk/events';
|
|
4
|
+
import { isBot, BOT_DETECTION_COOKIE } from '@sitecore-content-sdk/analytics-core/internal';
|
|
5
5
|
import { ProxyBase } from './proxy';
|
|
6
6
|
import debug from '../debug';
|
|
7
7
|
import { analyticsProxyAdapter } from '../initialization/proxy/analytics-adapter';
|
|
@@ -33,7 +33,12 @@ export class BotTrackingProxy extends ProxyBase {
|
|
|
33
33
|
debug.common('bot tracking proxy skipped (local environment)');
|
|
34
34
|
return res;
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
const userAgent = req.headers.get('user-agent');
|
|
37
|
+
if (!userAgent) {
|
|
38
|
+
debug.common('bot tracking proxy skipped (no user-agent)');
|
|
39
|
+
return res;
|
|
40
|
+
}
|
|
41
|
+
if (!isBot(userAgent)) {
|
|
37
42
|
debug.common('bot tracking proxy skipped (not a bot)');
|
|
38
43
|
return res;
|
|
39
44
|
}
|
|
@@ -42,6 +47,7 @@ export class BotTrackingProxy extends ProxyBase {
|
|
|
42
47
|
return res;
|
|
43
48
|
}
|
|
44
49
|
const site = this.getSite(req, res);
|
|
50
|
+
const language = this.getLanguage(req, res);
|
|
45
51
|
const botTracking = async () => {
|
|
46
52
|
await initContentSdk({
|
|
47
53
|
config: {
|
|
@@ -59,13 +65,18 @@ export class BotTrackingProxy extends ProxyBase {
|
|
|
59
65
|
eventsPlugin(),
|
|
60
66
|
],
|
|
61
67
|
});
|
|
62
|
-
await botPageView(
|
|
68
|
+
await botPageView({
|
|
69
|
+
page: req.nextUrl.pathname,
|
|
70
|
+
language: language,
|
|
71
|
+
userAgent,
|
|
72
|
+
});
|
|
63
73
|
};
|
|
64
74
|
res.cookies.set(BOT_DETECTION_COOKIE, '1', {
|
|
65
75
|
secure: true,
|
|
66
76
|
sameSite: 'lax',
|
|
67
77
|
path: '/',
|
|
68
78
|
});
|
|
79
|
+
debug.common('bot tracking proxy (visitor is a bot)');
|
|
69
80
|
if (this.config.fetchEvent) {
|
|
70
81
|
this.config.fetchEvent.waitUntil(botTracking());
|
|
71
82
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PersonalizeService, getPersonalizedRewrite, CdpHelper, DEFAULT_VARIANT, } from '@sitecore-content-sdk/content/personalize';
|
|
2
|
+
import { BOT_DETECTION_COOKIE } from '@sitecore-content-sdk/analytics-core/internal';
|
|
2
3
|
import { initContentSdk } from '@sitecore-content-sdk/core';
|
|
3
4
|
import { personalize } from '@sitecore-content-sdk/personalize';
|
|
4
|
-
import { BOT_DETECTION_COOKIE } from '@sitecore-content-sdk/events/internal';
|
|
5
5
|
import { analyticsPlugin } from '@sitecore-content-sdk/analytics-core';
|
|
6
6
|
import { personalizeServerPlugin } from '@sitecore-content-sdk/personalize';
|
|
7
7
|
import { analyticsProxyAdapter } from '../initialization/proxy/analytics-adapter';
|
|
@@ -59,7 +59,7 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
59
59
|
}
|
|
60
60
|
site = this.getSite(req, res);
|
|
61
61
|
// Find the redirect from result of RedirectService
|
|
62
|
-
const existsRedirect = await this.getExistsRedirect(req, site.name);
|
|
62
|
+
const existsRedirect = await this.getExistsRedirect(req, site.name, language);
|
|
63
63
|
if (!existsRedirect) {
|
|
64
64
|
debug.redirects('skipped (redirect does not exist)');
|
|
65
65
|
return res;
|
|
@@ -196,19 +196,38 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
196
196
|
* @returns Promise<RedirectInfo | undefined>
|
|
197
197
|
* @private
|
|
198
198
|
*/
|
|
199
|
-
async getExistsRedirect(req, siteName) {
|
|
199
|
+
async getExistsRedirect(req, siteName, requestLocale) {
|
|
200
200
|
if (!this.redirectsService) {
|
|
201
201
|
return undefined;
|
|
202
202
|
}
|
|
203
203
|
const { pathname: incomingURL, search: incomingQS = '' } = this.normalizeUrl(req.nextUrl.clone());
|
|
204
|
-
const locale = this.getLanguage(req);
|
|
205
204
|
const normalizedPath = incomingURL.replace(/\/*$/gi, '').toLowerCase();
|
|
206
205
|
const redirects = await this.redirectsService.fetchRedirects(siteName);
|
|
207
|
-
|
|
206
|
+
// using locale of current request (from URL, headers or otherwise), used to match versioned redirect rules
|
|
207
|
+
const matchedLocaleRedirect = this.matchRedirectItemRedirect(redirects, requestLocale, normalizedPath);
|
|
208
|
+
if (matchedLocaleRedirect) {
|
|
209
|
+
return matchedLocaleRedirect;
|
|
210
|
+
}
|
|
211
|
+
// locale of the url - if present in the url, used for redirect map matching
|
|
212
|
+
const urlLocale = req.nextUrl.locale;
|
|
213
|
+
return this.matchFromRedirectMapRedirect(redirects, urlLocale, incomingURL, incomingQS);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Matches redirect-map rules without a `locale` field against the incoming URL (static or regex patterns).
|
|
217
|
+
* @param {RedirectResult[]} redirects All redirects from the service (non-locale entries are filtered inside).
|
|
218
|
+
* @param {string} urlLocale Locale segment from the request URL (`nextUrl.locale`).
|
|
219
|
+
* @param {string} incomingURL Original pathname used for regex tests.
|
|
220
|
+
* @param {string} incomingQS Query string including leading `?` if present.
|
|
221
|
+
* @returns {RedirectResult | undefined} First matching redirect or undefined.
|
|
222
|
+
* @private
|
|
223
|
+
*/
|
|
224
|
+
matchFromRedirectMapRedirect(redirects, urlLocale, incomingURL, incomingQS) {
|
|
225
|
+
const nonLocaleRedirects = redirects.filter((redirect) => !redirect.locale);
|
|
208
226
|
let matchedQueryString;
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
227
|
+
const normalizedPath = incomingURL.replace(/\/*$/gi, '').toLowerCase();
|
|
228
|
+
const localePath = `/${urlLocale.toLowerCase()}${normalizedPath}`;
|
|
229
|
+
return nonLocaleRedirects.length
|
|
230
|
+
? nonLocaleRedirects.find((redirect) => {
|
|
212
231
|
// process static URL (non-regex) rules
|
|
213
232
|
if (isRegexOrUrl(redirect.pattern) === 'url') {
|
|
214
233
|
const urlArray = redirect.pattern.endsWith('/')
|
|
@@ -230,14 +249,14 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
230
249
|
// process regex rules
|
|
231
250
|
// Modify the redirect pattern to ignore the language prefix in the path
|
|
232
251
|
// And escapes non-special "?" characters in a string or regex.
|
|
233
|
-
redirect.pattern = escapeNonSpecialQuestionMarks('^' + redirect.pattern.replace(new RegExp(`^[^]?/${
|
|
252
|
+
redirect.pattern = escapeNonSpecialQuestionMarks('^' + redirect.pattern.replace(new RegExp(`^[^]?/${urlLocale}/`, 'gi'), '') // ensure function thinks input is regex
|
|
234
253
|
);
|
|
235
254
|
// Prepare the redirect pattern as a regular expression, making it more flexible for matching URLs
|
|
236
255
|
redirect.pattern = `/^\/${redirect.pattern
|
|
237
256
|
.replace(/^\/|\/$/g, '') // Removes leading and trailing slashes
|
|
238
257
|
.replace(/^\^\/|\/\$$/g, '') // Removes unnecessary start (^) and end ($) anchors
|
|
239
258
|
.replace(/^\^|\$$/g, '') // Further cleans up anchors
|
|
240
|
-
.replace(/\$\/
|
|
259
|
+
.replace(/\$\/g$/g, '')}[\/]?$/i`; // Ensures the pattern allows an optional trailing slash
|
|
241
260
|
// Redirect pattern matches the full incoming URL with query string present
|
|
242
261
|
matchedQueryString = [
|
|
243
262
|
regexParser(redirect.pattern).test(`/${localePath}${incomingQS}`),
|
|
@@ -247,9 +266,28 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
247
266
|
: undefined;
|
|
248
267
|
// Save the matched query string (if found) into the redirect object
|
|
249
268
|
redirect.matchedQueryString = matchedQueryString || '';
|
|
250
|
-
return (!!(regexParser(redirect.pattern).test(`/${
|
|
269
|
+
return (!!(regexParser(redirect.pattern).test(`/${urlLocale}${incomingURL}`) ||
|
|
251
270
|
regexParser(redirect.pattern).test(incomingURL) ||
|
|
252
|
-
matchedQueryString) &&
|
|
271
|
+
matchedQueryString) &&
|
|
272
|
+
(redirect.locale ? redirect.locale.toLowerCase() === urlLocale.toLowerCase() : true));
|
|
273
|
+
})
|
|
274
|
+
: undefined;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Processes redirect rules from redirect items (language-versioned)
|
|
278
|
+
* @param {RedirectResult[]} redirects redirect entries from Edge
|
|
279
|
+
* @param {string} locale current request locale
|
|
280
|
+
* @param {string} currentPath current request path
|
|
281
|
+
* @returns {RedirectResult | undefined} matched redirect item redirect result or undefined
|
|
282
|
+
* @private
|
|
283
|
+
*/
|
|
284
|
+
matchRedirectItemRedirect(redirects, locale, currentPath) {
|
|
285
|
+
const nonLocalePath = currentPath.replace(new RegExp(`^\/?${locale}\/`, 'i'), '/');
|
|
286
|
+
return redirects.length
|
|
287
|
+
? redirects.find((redirect) => {
|
|
288
|
+
const patternPath = redirect.pattern.replace(/\/*$/g, '').toLowerCase();
|
|
289
|
+
// locale rules are easy and nice
|
|
290
|
+
return redirect.locale === locale && patternPath === nonLocalePath;
|
|
253
291
|
})
|
|
254
292
|
: undefined;
|
|
255
293
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sitecore-content-sdk/nextjs",
|
|
3
|
-
"version": "2.1.0-canary.
|
|
3
|
+
"version": "2.1.0-canary.10",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"url": "https://github.com/sitecore/content-sdk/issues"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@sitecore-content-sdk/analytics-core": "2.1.0-canary.
|
|
36
|
-
"@sitecore-content-sdk/personalize": "2.1.0-canary.
|
|
35
|
+
"@sitecore-content-sdk/analytics-core": "2.1.0-canary.10",
|
|
36
|
+
"@sitecore-content-sdk/personalize": "2.1.0-canary.10",
|
|
37
37
|
"@stylistic/eslint-plugin": "^5.2.2",
|
|
38
38
|
"@testing-library/dom": "^10.4.0",
|
|
39
39
|
"@testing-library/react": "^16.3.0",
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
"typescript": "~5.8.3"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
|
-
"@sitecore-content-sdk/analytics-core": "^2.0
|
|
80
|
-
"@sitecore-content-sdk/events": "^2.0
|
|
81
|
-
"@sitecore-content-sdk/personalize": "^2.0
|
|
79
|
+
"@sitecore-content-sdk/analytics-core": "^2.1.0-canary.3",
|
|
80
|
+
"@sitecore-content-sdk/events": "^2.1.0-canary.3",
|
|
81
|
+
"@sitecore-content-sdk/personalize": "^2.1.0-canary.3",
|
|
82
82
|
"next": "^16.2.0",
|
|
83
83
|
"react": "^19.2.1",
|
|
84
84
|
"react-dom": "^19.2.1",
|
|
@@ -91,10 +91,10 @@
|
|
|
91
91
|
},
|
|
92
92
|
"dependencies": {
|
|
93
93
|
"@babel/parser": "^7.27.2",
|
|
94
|
-
"@sitecore-content-sdk/content": "2.1.0-canary.
|
|
95
|
-
"@sitecore-content-sdk/core": "2.1.0-canary.
|
|
96
|
-
"@sitecore-content-sdk/events": "2.1.0-canary.
|
|
97
|
-
"@sitecore-content-sdk/react": "2.1.0-canary.
|
|
94
|
+
"@sitecore-content-sdk/content": "2.1.0-canary.10",
|
|
95
|
+
"@sitecore-content-sdk/core": "2.1.0-canary.10",
|
|
96
|
+
"@sitecore-content-sdk/events": "2.1.0-canary.10",
|
|
97
|
+
"@sitecore-content-sdk/react": "2.1.0-canary.10",
|
|
98
98
|
"recast": "^0.23.11",
|
|
99
99
|
"regex-parser": "^2.3.1",
|
|
100
100
|
"sync-disk-cache": "^2.1.0"
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
},
|
|
179
179
|
"description": "",
|
|
180
180
|
"types": "types/index.d.ts",
|
|
181
|
-
"gitHead": "
|
|
181
|
+
"gitHead": "f4f6bb8a4ac09e5d721e8a4a361c8ad980997e6c",
|
|
182
182
|
"files": [
|
|
183
183
|
"dist",
|
|
184
184
|
"types",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics-adapter.d.ts","sourceRoot":"","sources":["../../../src/initialization/proxy/analytics-adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analytics-adapter.d.ts","sourceRoot":"","sources":["../../../src/initialization/proxy/analytics-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,gBAAgB,EAEjB,MAAM,+CAA+C,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,GACrB,qBAAqB,CA+DvB;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,WAAW,KAAG,MAAM,GAAG,IAI3D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot-tracking-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/bot-tracking-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"bot-tracking-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/bot-tracking-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAItE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAIrD;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAChE,IAAI,CAAC,eAAe,EAAE,iBAAiB,CAAC,GAAG;IACzC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B,CAAC;AAEJ;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,SAAS;IACjC,SAAS,CAAC,MAAM,EAAE,sBAAsB;gBAA9B,MAAM,EAAE,sBAAsB;IAIpD,MAAM,GAAU,KAAK,WAAW,EAAE,KAAK,YAAY,KAAG,OAAO,CAAC,YAAY,CAAC,CA4FzE;IAEF;;;;OAIG;IACH,SAAS,CAAC,6BAA6B,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;CAwBnE"}
|
|
@@ -35,7 +35,26 @@ export declare class RedirectsProxy extends ProxyBase {
|
|
|
35
35
|
* @returns Promise<RedirectInfo | undefined>
|
|
36
36
|
* @private
|
|
37
37
|
*/
|
|
38
|
-
protected getExistsRedirect(req: NextRequest, siteName: string): Promise<RedirectResult | undefined>;
|
|
38
|
+
protected getExistsRedirect(req: NextRequest, siteName: string, requestLocale: string): Promise<RedirectResult | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* Matches redirect-map rules without a `locale` field against the incoming URL (static or regex patterns).
|
|
41
|
+
* @param {RedirectResult[]} redirects All redirects from the service (non-locale entries are filtered inside).
|
|
42
|
+
* @param {string} urlLocale Locale segment from the request URL (`nextUrl.locale`).
|
|
43
|
+
* @param {string} incomingURL Original pathname used for regex tests.
|
|
44
|
+
* @param {string} incomingQS Query string including leading `?` if present.
|
|
45
|
+
* @returns {RedirectResult | undefined} First matching redirect or undefined.
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
protected matchFromRedirectMapRedirect(redirects: RedirectResult[], urlLocale: string, incomingURL: string, incomingQS: string): RedirectResult | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Processes redirect rules from redirect items (language-versioned)
|
|
51
|
+
* @param {RedirectResult[]} redirects redirect entries from Edge
|
|
52
|
+
* @param {string} locale current request locale
|
|
53
|
+
* @param {string} currentPath current request path
|
|
54
|
+
* @returns {RedirectResult | undefined} matched redirect item redirect result or undefined
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
protected matchRedirectItemRedirect(redirects: RedirectResult[], locale: string, currentPath: string): RedirectResult | undefined;
|
|
39
58
|
/**
|
|
40
59
|
* When a user clicks on a link generated by the Link component from next/link,
|
|
41
60
|
* Next.js adds special parameters in the route called path.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirects-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/redirects-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EAItB,YAAY,EAEb,MAAM,oCAAoC,CAAC;AAO5C,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAuB,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAM3C,KAAK,cAAc,GAAG,YAAY,GAAG;IAAE,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,eAAe,CAAC,GACxF,cAAc,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GACpD,eAAe,GACf,cAAc,CAAC,WAAW,CAAC,GAAG;IAC5B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AACJ;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,SAAS;IAO/B,SAAS,CAAC,MAAM,EAAE,oBAAoB;IANlD,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpD,OAAO,CAAC,OAAO,CAAW;IAE1B;;OAEG;gBACmB,MAAM,EAAE,oBAAoB;IAmDlD,MAAM,GAAU,KAAK,WAAW,EAAE,KAAK,YAAY,KAAG,OAAO,CAAC,YAAY,CAAC,CA4KzE;IAEF,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,GAAG,SAAS;IAU5E;;;;;;OAMG;cACa,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"redirects-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/redirects-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EAItB,YAAY,EAEb,MAAM,oCAAoC,CAAC;AAO5C,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAuB,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAM3C,KAAK,cAAc,GAAG,YAAY,GAAG;IAAE,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,eAAe,CAAC,GACxF,cAAc,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GACpD,eAAe,GACf,cAAc,CAAC,WAAW,CAAC,GAAG;IAC5B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AACJ;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,SAAS;IAO/B,SAAS,CAAC,MAAM,EAAE,oBAAoB;IANlD,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpD,OAAO,CAAC,OAAO,CAAW;IAE1B;;OAEG;gBACmB,MAAM,EAAE,oBAAoB;IAmDlD,MAAM,GAAU,KAAK,WAAW,EAAE,KAAK,YAAY,KAAG,OAAO,CAAC,YAAY,CAAC,CA4KzE;IAEF,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,GAAG,SAAS;IAU5E;;;;;;OAMG;cACa,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IA0BtC;;;;;;;;OAQG;IACH,SAAS,CAAC,4BAA4B,CACpC,SAAS,EAAE,cAAc,EAAE,EAC3B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,cAAc,GAAG,SAAS;IAsE7B;;;;;;;OAOG;IACH,SAAS,CAAC,yBAAyB,CACjC,SAAS,EAAE,cAAc,EAAE,EAC3B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,cAAc,GAAG,SAAS;IAW7B;;;;;;OAMG;IACH,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IA6C7C;;;;;;;;;OASG;IACH,SAAS,CAAC,gBAAgB,CACxB,MAAM,EAAE,OAAO,GAAG,MAAM,EACxB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,YAAY,EACjB,UAAU,UAAQ,GACjB,YAAY;IAkDf;;;;;;;OAOG;IACH,SAAS,CAAC,sBAAsB,CAC9B,GAAG,EAAE,OAAO,GAAG,MAAM,EACrB,GAAG,EAAE,QAAQ,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,YAAY;CAehB"}
|