@sitecore-content-sdk/nextjs 2.2.0 → 2.2.1-canary.20260701073911

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.
@@ -127,11 +127,14 @@ class RedirectsProxy extends proxy_1.ProxyBase {
127
127
  // Apply regex replacements to the target URL if the pattern is a regex
128
128
  const sourcePath = existsRedirect.matchedPath || reqUrl.pathname;
129
129
  const pathForCaptureMatch = sourcePath.replace(/\/*$/gi, '') || '/';
130
- const matched = pathForCaptureMatch.match(this.getRedirectPatternRegex(existsRedirect.pattern));
131
- if (matched) {
132
- existsRedirect.target = existsRedirect.target.replace(/\$(\d+)/g, (_, index) => {
133
- return matched[parseInt(index, 10)] || '';
134
- });
130
+ if ((0, tools_1.isRegexOrUrl)(existsRedirect.pattern) === 'regex') {
131
+ const redirectRegex = this.safeCompileRedirectPattern(existsRedirect.pattern);
132
+ const matched = redirectRegex ? pathForCaptureMatch.match(redirectRegex) : null;
133
+ if (matched) {
134
+ existsRedirect.target = existsRedirect.target.replace(/\$(\d+)/g, (_, index) => {
135
+ return matched[parseInt(index, 10)] || '';
136
+ });
137
+ }
135
138
  }
136
139
  const isAbsoluteUrl = REGEXP_ABSOLUTE_URL.test(existsRedirect.target);
137
140
  const redirectedResponse = isAbsoluteUrl
@@ -266,7 +269,7 @@ class RedirectsProxy extends proxy_1.ProxyBase {
266
269
  const patternParts = patternPath.split('/');
267
270
  const maybeLocale = patternParts[1].toLowerCase();
268
271
  // case insensitive lookup of locales
269
- if (new RegExp(this.locales.join('|'), 'i').test(maybeLocale)) {
272
+ if (new RegExp(this.locales.map(tools_1.escapeRegExp).join('|'), 'i').test(maybeLocale)) {
270
273
  patternPath = patternPath.replace(`/${patternParts[1]}`, `/${maybeLocale}`);
271
274
  }
272
275
  return ((patternPath === localePath || patternPath === normalizedPath) &&
@@ -274,7 +277,10 @@ class RedirectsProxy extends proxy_1.ProxyBase {
274
277
  (0, tools_1.areURLSearchParamsEqual)(new URLSearchParams(patternQS), new URLSearchParams(incomingQS))));
275
278
  }
276
279
  // process regex rules
277
- const regex = this.getRedirectPatternRegex(redirect.pattern);
280
+ const regex = this.safeCompileRedirectPattern(redirect.pattern);
281
+ if (!regex) {
282
+ return false;
283
+ }
278
284
  const testRegex = (value) => {
279
285
  regex.lastIndex = 0;
280
286
  return regex.test(value);
@@ -309,7 +315,7 @@ class RedirectsProxy extends proxy_1.ProxyBase {
309
315
  * @private
310
316
  */
311
317
  matchRedirectItemRedirect(redirects, locale, currentPath) {
312
- const nonLocalePath = currentPath.replace(new RegExp(`^\/?${locale}\/`, 'i'), '/');
318
+ const nonLocalePath = currentPath.replace(new RegExp(`^/?${(0, tools_1.escapeRegExp)(locale)}/`, 'i'), '/');
313
319
  return redirects.length
314
320
  ? redirects.find((redirect) => {
315
321
  const patternPath = redirect.pattern.replace(/\/*$/g, '').toLowerCase();
@@ -441,6 +447,23 @@ class RedirectsProxy extends proxy_1.ProxyBase {
441
447
  }
442
448
  return redirect;
443
449
  }
450
+ /**
451
+ * Compiles a redirect pattern to RegExp; returns null if Sitecore produced a malformed rule
452
+ * so one bad entry does not fail the entire redirect chain.
453
+ * @param {string} pattern redirect pattern from redirect map
454
+ * @returns {RegExp | null} normalized regex instance, or null when invalid
455
+ * @private
456
+ */
457
+ safeCompileRedirectPattern(pattern) {
458
+ try {
459
+ return this.getRedirectPatternRegex(pattern);
460
+ }
461
+ catch (error) {
462
+ const message = error instanceof Error ? error.message : String(error);
463
+ console.warn(`[RedirectsProxy] Invalid redirect regex; skipping rule. pattern=${pattern} (${message})`);
464
+ return null;
465
+ }
466
+ }
444
467
  /**
445
468
  * Converts a redirect pattern string into a RegExp.
446
469
  * Supports both JS literal form (`/pattern/i`) and plain regex source (`^/path$`).
@@ -469,7 +492,7 @@ class RedirectsProxy extends proxy_1.ProxyBase {
469
492
  if (!urlLocale) {
470
493
  return path;
471
494
  }
472
- const localePrefixRegex = new RegExp(`^/${urlLocale}(?=/|$)`, 'i');
495
+ const localePrefixRegex = new RegExp(`^/${(0, tools_1.escapeRegExp)(urlLocale)}(?=/|$)`, 'i');
473
496
  const strippedPath = path.replace(localePrefixRegex, '') || '/';
474
497
  return strippedPath.startsWith('/') ? strippedPath : `/${strippedPath}`;
475
498
  }
@@ -1,5 +1,5 @@
1
1
  import { RedirectsService, REDIRECT_TYPE_301, REDIRECT_TYPE_302, REDIRECT_TYPE_SERVER_TRANSFER, } from '@sitecore-content-sdk/content/site';
2
- import { areURLSearchParamsEqual, escapeNonSpecialQuestionMarks, isRegexOrUrl, mergeURLSearchParams, } from '@sitecore-content-sdk/core/tools';
2
+ import { areURLSearchParamsEqual, escapeNonSpecialQuestionMarks, escapeRegExp, isRegexOrUrl, mergeURLSearchParams, } from '@sitecore-content-sdk/core/tools';
3
3
  import { NextResponse } from 'next/server';
4
4
  import { ProxyBase, REWRITE_HEADER_NAME } from './proxy';
5
5
  import debug from '../debug';
@@ -121,11 +121,14 @@ export class RedirectsProxy extends ProxyBase {
121
121
  // Apply regex replacements to the target URL if the pattern is a regex
122
122
  const sourcePath = existsRedirect.matchedPath || reqUrl.pathname;
123
123
  const pathForCaptureMatch = sourcePath.replace(/\/*$/gi, '') || '/';
124
- const matched = pathForCaptureMatch.match(this.getRedirectPatternRegex(existsRedirect.pattern));
125
- if (matched) {
126
- existsRedirect.target = existsRedirect.target.replace(/\$(\d+)/g, (_, index) => {
127
- return matched[parseInt(index, 10)] || '';
128
- });
124
+ if (isRegexOrUrl(existsRedirect.pattern) === 'regex') {
125
+ const redirectRegex = this.safeCompileRedirectPattern(existsRedirect.pattern);
126
+ const matched = redirectRegex ? pathForCaptureMatch.match(redirectRegex) : null;
127
+ if (matched) {
128
+ existsRedirect.target = existsRedirect.target.replace(/\$(\d+)/g, (_, index) => {
129
+ return matched[parseInt(index, 10)] || '';
130
+ });
131
+ }
129
132
  }
130
133
  const isAbsoluteUrl = REGEXP_ABSOLUTE_URL.test(existsRedirect.target);
131
134
  const redirectedResponse = isAbsoluteUrl
@@ -260,7 +263,7 @@ export class RedirectsProxy extends ProxyBase {
260
263
  const patternParts = patternPath.split('/');
261
264
  const maybeLocale = patternParts[1].toLowerCase();
262
265
  // case insensitive lookup of locales
263
- if (new RegExp(this.locales.join('|'), 'i').test(maybeLocale)) {
266
+ if (new RegExp(this.locales.map(escapeRegExp).join('|'), 'i').test(maybeLocale)) {
264
267
  patternPath = patternPath.replace(`/${patternParts[1]}`, `/${maybeLocale}`);
265
268
  }
266
269
  return ((patternPath === localePath || patternPath === normalizedPath) &&
@@ -268,7 +271,10 @@ export class RedirectsProxy extends ProxyBase {
268
271
  areURLSearchParamsEqual(new URLSearchParams(patternQS), new URLSearchParams(incomingQS))));
269
272
  }
270
273
  // process regex rules
271
- const regex = this.getRedirectPatternRegex(redirect.pattern);
274
+ const regex = this.safeCompileRedirectPattern(redirect.pattern);
275
+ if (!regex) {
276
+ return false;
277
+ }
272
278
  const testRegex = (value) => {
273
279
  regex.lastIndex = 0;
274
280
  return regex.test(value);
@@ -303,7 +309,7 @@ export class RedirectsProxy extends ProxyBase {
303
309
  * @private
304
310
  */
305
311
  matchRedirectItemRedirect(redirects, locale, currentPath) {
306
- const nonLocalePath = currentPath.replace(new RegExp(`^\/?${locale}\/`, 'i'), '/');
312
+ const nonLocalePath = currentPath.replace(new RegExp(`^/?${escapeRegExp(locale)}/`, 'i'), '/');
307
313
  return redirects.length
308
314
  ? redirects.find((redirect) => {
309
315
  const patternPath = redirect.pattern.replace(/\/*$/g, '').toLowerCase();
@@ -435,6 +441,23 @@ export class RedirectsProxy extends ProxyBase {
435
441
  }
436
442
  return redirect;
437
443
  }
444
+ /**
445
+ * Compiles a redirect pattern to RegExp; returns null if Sitecore produced a malformed rule
446
+ * so one bad entry does not fail the entire redirect chain.
447
+ * @param {string} pattern redirect pattern from redirect map
448
+ * @returns {RegExp | null} normalized regex instance, or null when invalid
449
+ * @private
450
+ */
451
+ safeCompileRedirectPattern(pattern) {
452
+ try {
453
+ return this.getRedirectPatternRegex(pattern);
454
+ }
455
+ catch (error) {
456
+ const message = error instanceof Error ? error.message : String(error);
457
+ console.warn(`[RedirectsProxy] Invalid redirect regex; skipping rule. pattern=${pattern} (${message})`);
458
+ return null;
459
+ }
460
+ }
438
461
  /**
439
462
  * Converts a redirect pattern string into a RegExp.
440
463
  * Supports both JS literal form (`/pattern/i`) and plain regex source (`^/path$`).
@@ -463,7 +486,7 @@ export class RedirectsProxy extends ProxyBase {
463
486
  if (!urlLocale) {
464
487
  return path;
465
488
  }
466
- const localePrefixRegex = new RegExp(`^/${urlLocale}(?=/|$)`, 'i');
489
+ const localePrefixRegex = new RegExp(`^/${escapeRegExp(urlLocale)}(?=/|$)`, 'i');
467
490
  const strippedPath = path.replace(localePrefixRegex, '') || '/';
468
491
  return strippedPath.startsWith('/') ? strippedPath : `/${strippedPath}`;
469
492
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sitecore-content-sdk/nextjs",
3
- "version": "2.2.0",
3
+ "version": "2.2.1-canary.20260701073911",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "sideEffects": false,
@@ -101,6 +101,14 @@ export declare class RedirectsProxy extends ProxyBase {
101
101
  * @returns {NextResponse<unknown>} The redirect response.
102
102
  */
103
103
  protected createRedirectResponse(url: NextURL | string, res: Response | undefined, status: number, statusText: string): NextResponse;
104
+ /**
105
+ * Compiles a redirect pattern to RegExp; returns null if Sitecore produced a malformed rule
106
+ * so one bad entry does not fail the entire redirect chain.
107
+ * @param {string} pattern redirect pattern from redirect map
108
+ * @returns {RegExp | null} normalized regex instance, or null when invalid
109
+ * @private
110
+ */
111
+ private safeCompileRedirectPattern;
104
112
  /**
105
113
  * Converts a redirect pattern string into a RegExp.
106
114
  * Supports both JS literal form (`/pattern/i`) and plain regex source (`^/path$`).
@@ -1 +1 @@
1
- {"version":3,"file":"redirects-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/redirects-proxy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"redirects-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/redirects-proxy.ts"],"names":[],"mappings":"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"}