@sitecore-jss/sitecore-jss-nextjs 21.3.0-canary.2 → 21.3.0-canary.21

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/README.md CHANGED
@@ -3,8 +3,10 @@
3
3
  This module is provided as a part of Sitecore JavaScript Rendering SDK. It contains Next.js components and integration for JSS.
4
4
 
5
5
  <!---
6
- @TODO: Update to version 20.0.0 docs before release
6
+ @TODO: Update to next version docs before release
7
7
  -->
8
- [Documentation](https://doc.sitecore.com/xp/en/developers/hd/190/sitecore-headless-development/sitecore-javascript-rendering-sdk--jss--for-next-js.html)
8
+ [Documentation (Experience Platform)](https://doc.sitecore.com/xp/en/developers/hd/21/sitecore-headless-development/sitecore-javascript-rendering-sdk--jss--for-next-js.html)
9
9
 
10
- [API reference documentation](/ref-docs/sitecore-jss-nextjs/).
10
+ [Documentation (XM Cloud)](https://doc.sitecore.com/xmc/en/developers/xm-cloud/sitecore-javascript-rendering-sdk--jss--for-next-js.html)
11
+
12
+ [API reference documentation](/ref-docs/sitecore-jss-nextjs/)
@@ -29,6 +29,7 @@ class EditingRenderMiddleware {
29
29
  this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
30
30
  var _e, _f;
31
31
  const { method, query, body, headers } = req;
32
+ const startTimestamp = Date.now();
32
33
  sitecore_jss_1.debug.editing('editing render middleware start: %o', {
33
34
  method,
34
35
  query,
@@ -104,7 +105,10 @@ class EditingRenderMiddleware {
104
105
  }
105
106
  const body = { html };
106
107
  // Return expected JSON result
107
- sitecore_jss_1.debug.editing('editing render middleware end: %o', { status: 200, body });
108
+ sitecore_jss_1.debug.editing('editing render middleware end in %dms: %o', Date.now() - startTimestamp, {
109
+ status: 200,
110
+ body,
111
+ });
108
112
  res.status(200).json(body);
109
113
  }
110
114
  catch (err) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.editingDataService = exports.ServerlessEditingDataService = exports.BasicEditingDataService = exports.EditingRenderMiddleware = exports.EditingDataMiddleware = exports.EditingDataDiskCache = void 0;
3
+ exports.VercelEditingDataCache = exports.editingDataService = exports.ServerlessEditingDataService = exports.BasicEditingDataService = exports.EditingRenderMiddleware = exports.EditingDataMiddleware = exports.EditingDataDiskCache = void 0;
4
4
  var editing_data_cache_1 = require("./editing-data-cache");
5
5
  Object.defineProperty(exports, "EditingDataDiskCache", { enumerable: true, get: function () { return editing_data_cache_1.EditingDataDiskCache; } });
6
6
  var editing_data_middleware_1 = require("./editing-data-middleware");
@@ -11,3 +11,5 @@ var editing_data_service_1 = require("./editing-data-service");
11
11
  Object.defineProperty(exports, "BasicEditingDataService", { enumerable: true, get: function () { return editing_data_service_1.BasicEditingDataService; } });
12
12
  Object.defineProperty(exports, "ServerlessEditingDataService", { enumerable: true, get: function () { return editing_data_service_1.ServerlessEditingDataService; } });
13
13
  Object.defineProperty(exports, "editingDataService", { enumerable: true, get: function () { return editing_data_service_1.editingDataService; } });
14
+ var vercel_editing_data_cache_1 = require("./vercel-editing-data-cache");
15
+ Object.defineProperty(exports, "VercelEditingDataCache", { enumerable: true, get: function () { return vercel_editing_data_cache_1.VercelEditingDataCache; } });
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VercelEditingDataCache = void 0;
4
+ const kv_1 = require("@vercel/kv");
5
+ const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
6
+ /**
7
+ * Implementation of editing cache for Vercel deployments
8
+ * Uses Vercel KV database and client to store data
9
+ * Set TTL for cache data in constructor (default: 60 seconds)
10
+ */
11
+ class VercelEditingDataCache {
12
+ /**
13
+ * @param {string} redisUrl KV endpoint URL. Usually stored in process.env.KV_REST_API_URL
14
+ * @param {string} redisToken KV endpoint tokem. Usually stored in process.env.KV_REST_API_TOKEN
15
+ */
16
+ constructor(redisUrl, redisToken) {
17
+ this.defaultTtl = 120;
18
+ if (!redisUrl || !redisToken) {
19
+ throw Error('API URL or token are missing, ensure you have set the KV or Upstash storage correctly.');
20
+ }
21
+ this.redisCache = (0, kv_1.createClient)({
22
+ url: redisUrl,
23
+ token: redisToken,
24
+ });
25
+ }
26
+ set(key, editingData) {
27
+ sitecore_jss_1.debug.editing(`Putting editing data for ${key} into redis storage...`);
28
+ return new Promise((resolve, reject) => {
29
+ this.redisCache
30
+ .set(key, JSON.stringify(editingData), { ex: this.defaultTtl })
31
+ .then(() => resolve())
32
+ .catch((err) => reject(err));
33
+ });
34
+ }
35
+ get(key) {
36
+ sitecore_jss_1.debug.editing(`Getting editing data for ${key} from redis storage...`);
37
+ return new Promise((resolve, reject) => {
38
+ this.redisCache
39
+ .get(key)
40
+ .then((entry) => {
41
+ const result = (entry || undefined);
42
+ this.redisCache.expire(key, 0).then(() => resolve(result));
43
+ })
44
+ .catch((err) => reject(err));
45
+ });
46
+ }
47
+ }
48
+ exports.VercelEditingDataCache = VercelEditingDataCache;
package/dist/cjs/index.js CHANGED
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ComponentBuilder = exports.NextImage = exports.EditingComponentPlaceholder = exports.Placeholder = exports.RichText = exports.Link = exports.useComponentProps = exports.ComponentPropsContext = exports.ComponentPropsReactContext = exports.normalizeSiteRewrite = exports.getSiteRewriteData = exports.getSiteRewrite = exports.GraphQLSiteInfoService = exports.SiteResolver = exports.GraphQLRobotsService = exports.GraphQLErrorPagesService = exports.GraphQLSitemapXmlService = exports.MultisiteGraphQLSitemapService = exports.GraphQLSitemapService = exports.DisconnectedSitemapService = exports.ComponentPropsService = exports.GraphQLRequestClient = exports.PosResolver = exports.CdpHelper = exports.normalizePersonalizedRewrite = exports.getPersonalizedRewriteData = exports.getPersonalizedRewrite = exports.personalizeLayout = exports.RestDictionaryService = exports.GraphQLDictionaryService = exports.trackingApi = exports.mediaApi = exports.EDITING_COMPONENT_ID = exports.EDITING_COMPONENT_PLACEHOLDER = exports.RenderingType = exports.getFieldValue = exports.getChildPlaceholder = exports.RestLayoutService = exports.GraphQLLayoutService = exports.LayoutServicePageState = exports.tryParseEnvValue = exports.resolveUrl = exports.resetEditorChromes = exports.isEditorActive = exports.getPublicUrl = exports.handleEditorFastRefresh = exports.enableDebug = exports.NativeDataFetcher = exports.AxiosDataFetcher = exports.constants = void 0;
4
- exports.withDatasourceCheck = exports.withPlaceholder = exports.withEditorChromes = exports.useSitecoreContext = exports.withSitecoreContext = exports.SitecoreContextReactContext = exports.SitecoreContext = exports.VisitorIdentification = exports.File = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.EditFrame = exports.DateField = exports.Text = exports.Image = void 0;
3
+ exports.NextImage = exports.EditingComponentPlaceholder = exports.Placeholder = exports.RichText = exports.Link = exports.useComponentProps = exports.ComponentPropsContext = exports.ComponentPropsReactContext = exports.normalizeSiteRewrite = exports.getSiteRewriteData = exports.getSiteRewrite = exports.GraphQLSiteInfoService = exports.SiteResolver = exports.GraphQLRobotsService = exports.GraphQLErrorPagesService = exports.GraphQLSitemapXmlService = exports.MultisiteGraphQLSitemapService = exports.GraphQLSitemapService = exports.DisconnectedSitemapService = exports.ComponentPropsService = exports.GraphQLRequestClient = exports.PosResolver = exports.CdpHelper = exports.normalizePersonalizedRewrite = exports.getPersonalizedRewriteData = exports.getPersonalizedRewrite = exports.personalizeLayout = exports.RestDictionaryService = exports.GraphQLDictionaryService = exports.trackingApi = exports.mediaApi = exports.EDITING_COMPONENT_ID = exports.EDITING_COMPONENT_PLACEHOLDER = exports.RenderingType = exports.getFieldValue = exports.getChildPlaceholder = exports.RestLayoutService = exports.GraphQLLayoutService = exports.LayoutServicePageState = exports.tryParseEnvValue = exports.resolveUrl = exports.resetEditorChromes = exports.isEditorActive = exports.getPublicUrl = exports.handleEditorFastRefresh = exports.debug = exports.enableDebug = exports.NativeDataFetcher = exports.AxiosDataFetcher = exports.constants = void 0;
4
+ exports.withDatasourceCheck = exports.withPlaceholder = exports.withEditorChromes = exports.useSitecoreContext = exports.withSitecoreContext = exports.SitecoreContextReactContext = exports.SitecoreContext = exports.VisitorIdentification = exports.File = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.EditFrame = exports.DateField = exports.Text = exports.Image = exports.ComponentBuilder = void 0;
5
5
  var sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
6
6
  Object.defineProperty(exports, "constants", { enumerable: true, get: function () { return sitecore_jss_1.constants; } });
7
7
  Object.defineProperty(exports, "AxiosDataFetcher", { enumerable: true, get: function () { return sitecore_jss_1.AxiosDataFetcher; } });
8
8
  Object.defineProperty(exports, "NativeDataFetcher", { enumerable: true, get: function () { return sitecore_jss_1.NativeDataFetcher; } });
9
9
  Object.defineProperty(exports, "enableDebug", { enumerable: true, get: function () { return sitecore_jss_1.enableDebug; } });
10
+ Object.defineProperty(exports, "debug", { enumerable: true, get: function () { return sitecore_jss_1.debug; } });
10
11
  // we will remove the root exports for these later
11
12
  // we cannot mark exports as deprected directly, so we're using this hack instead
12
13
  const utils_1 = require("@sitecore-jss/sitecore-jss/utils");
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MultisiteMiddleware = exports.PersonalizeMiddleware = exports.RedirectsMiddleware = void 0;
3
+ exports.MultisiteMiddleware = exports.PersonalizeMiddleware = exports.RedirectsMiddleware = exports.debug = void 0;
4
+ var sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
5
+ Object.defineProperty(exports, "debug", { enumerable: true, get: function () { return sitecore_jss_1.debug; } });
4
6
  var redirects_middleware_1 = require("./redirects-middleware");
5
7
  Object.defineProperty(exports, "RedirectsMiddleware", { enumerable: true, get: function () { return redirects_middleware_1.RedirectsMiddleware; } });
6
8
  var personalize_middleware_1 = require("./personalize-middleware");
@@ -29,6 +29,7 @@ class MultisiteMiddleware extends middleware_1.MiddlewareBase {
29
29
  const pathname = req.nextUrl.pathname;
30
30
  const language = this.getLanguage(req);
31
31
  const hostname = this.getHostHeader(req) || this.defaultHostname;
32
+ const startTimestamp = Date.now();
32
33
  sitecore_jss_1.debug.multisite('multisite middleware start: %o', {
33
34
  pathname,
34
35
  language,
@@ -58,7 +59,7 @@ class MultisiteMiddleware extends middleware_1.MiddlewareBase {
58
59
  response.cookies.set(this.SITE_SYMBOL, siteName);
59
60
  // Share rewrite path with following executed middlewares
60
61
  response.headers.set('x-sc-rewrite', rewritePath);
61
- sitecore_jss_1.debug.multisite('multisite middleware end: %o', {
62
+ sitecore_jss_1.debug.multisite('multisite middleware end in %dms: %o', Date.now() - startTimestamp, {
62
63
  rewritePath,
63
64
  siteName,
64
65
  headers: this.extractDebugHeaders(response.headers),
@@ -28,6 +28,7 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
28
28
  const pathname = req.nextUrl.pathname;
29
29
  const language = this.getLanguage(req);
30
30
  const hostname = this.getHostHeader(req) || this.defaultHostname;
31
+ const startTimestamp = Date.now();
31
32
  let browserId = this.getBrowserId(req);
32
33
  sitecore_jss_1.debug.personalize('personalize middleware start: %o', {
33
34
  pathname,
@@ -98,7 +99,7 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
98
99
  this.setBrowserId(response, browserId);
99
100
  // Share site name with the following executed middlewares
100
101
  response.cookies.set(this.SITE_SYMBOL, site.name);
101
- sitecore_jss_1.debug.personalize('personalize middleware end: %o', {
102
+ sitecore_jss_1.debug.personalize('personalize middleware end in %dms: %o', Date.now() - startTimestamp, {
102
103
  rewritePath,
103
104
  browserId,
104
105
  headers: this.extractDebugHeaders(response.headers),
@@ -149,7 +150,10 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
149
150
  }
150
151
  getExperienceParams(req) {
151
152
  return {
152
- referrer: req.referrer,
153
+ // It's expected that the header name "referer" is actually a misspelling of the word "referrer"
154
+ // req.referrer is used during fetching to determine the value of the Referer header of the request being made,
155
+ // used as a fallback
156
+ referrer: req.headers.get('referer') || req.referrer,
153
157
  utm: {
154
158
  campaign: req.nextUrl.searchParams.get('utm_campaign'),
155
159
  content: req.nextUrl.searchParams.get('utm_content'),
@@ -35,6 +35,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
35
35
  const language = this.getLanguage(req);
36
36
  const hostname = this.getHostHeader(req) || this.defaultHostname;
37
37
  let site;
38
+ const startTimestamp = Date.now();
38
39
  sitecore_jss_1.debug.redirects('redirects middleware start: %o', {
39
40
  pathname,
40
41
  language,
@@ -71,11 +72,12 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
71
72
  const urlFirstPart = existsRedirect.target.split('/')[1];
72
73
  if (this.locales.includes(urlFirstPart)) {
73
74
  url.locale = urlFirstPart;
74
- url.pathname = existsRedirect.target.replace(`/${urlFirstPart}`, '');
75
- }
76
- else {
77
- url.pathname = existsRedirect.target;
75
+ existsRedirect.target = existsRedirect.target.replace(`/${urlFirstPart}`, '');
78
76
  }
77
+ url.pathname = existsRedirect.target;
78
+ url.pathname = url.pathname
79
+ .replace((0, regex_parser_1.default)(existsRedirect.pattern), existsRedirect.target)
80
+ .replace(/^\/\//, '/');
79
81
  }
80
82
  const redirectUrl = decodeURIComponent(url.href);
81
83
  /** return Response redirect with http code of redirect type **/
@@ -94,7 +96,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
94
96
  // Share site name with the following executed middlewares
95
97
  // Don't need to set when middleware is disabled
96
98
  site && response.cookies.set(this.SITE_SYMBOL, site.name);
97
- sitecore_jss_1.debug.redirects('redirects middleware end: %o', {
99
+ sitecore_jss_1.debug.redirects('redirects middleware end in %dms: %o', Date.now() - startTimestamp, {
98
100
  redirected: response.redirected,
99
101
  status: response.status,
100
102
  url: response.url,
@@ -137,13 +139,14 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
137
139
  const targetQS = req.nextUrl.search || '';
138
140
  return redirects.length
139
141
  ? redirects.find((redirect) => {
140
- const pattern = `/^/${redirect.pattern
142
+ redirect.pattern = `/^\/${redirect.pattern
141
143
  .replace(/^\/|\/$/g, '')
144
+ .replace(/^\^\/|\/\$$/g, '')
142
145
  .replace(/^\^|\$$/g, '')}$/gi`;
143
- return (((0, regex_parser_1.default)(pattern).test(tragetURL) ||
144
- (0, regex_parser_1.default)(pattern).test(`${tragetURL}${targetQS}`) ||
145
- (0, regex_parser_1.default)(pattern).test(`/${req.nextUrl.locale}${tragetURL}`) ||
146
- (0, regex_parser_1.default)(pattern).test(`/${req.nextUrl.locale}${tragetURL}${targetQS}`)) &&
146
+ return (((0, regex_parser_1.default)(redirect.pattern).test(tragetURL) ||
147
+ (0, regex_parser_1.default)(redirect.pattern).test(`${tragetURL}${targetQS}`) ||
148
+ (0, regex_parser_1.default)(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}`) ||
149
+ (0, regex_parser_1.default)(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}${targetQS}`)) &&
147
150
  (redirect.locale
148
151
  ? redirect.locale.toLowerCase() === req.nextUrl.locale.toLowerCase()
149
152
  : true));
@@ -26,6 +26,7 @@ export class EditingRenderMiddleware {
26
26
  this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
27
27
  var _e, _f;
28
28
  const { method, query, body, headers } = req;
29
+ const startTimestamp = Date.now();
29
30
  debug.editing('editing render middleware start: %o', {
30
31
  method,
31
32
  query,
@@ -101,7 +102,10 @@ export class EditingRenderMiddleware {
101
102
  }
102
103
  const body = { html };
103
104
  // Return expected JSON result
104
- debug.editing('editing render middleware end: %o', { status: 200, body });
105
+ debug.editing('editing render middleware end in %dms: %o', Date.now() - startTimestamp, {
106
+ status: 200,
107
+ body,
108
+ });
105
109
  res.status(200).json(body);
106
110
  }
107
111
  catch (err) {
@@ -2,3 +2,4 @@ export { EditingDataDiskCache } from './editing-data-cache';
2
2
  export { EditingDataMiddleware } from './editing-data-middleware';
3
3
  export { EditingRenderMiddleware, } from './editing-render-middleware';
4
4
  export { BasicEditingDataService, ServerlessEditingDataService, editingDataService, } from './editing-data-service';
5
+ export { VercelEditingDataCache } from './vercel-editing-data-cache';
@@ -0,0 +1,44 @@
1
+ import { createClient } from '@vercel/kv';
2
+ import { debug } from '@sitecore-jss/sitecore-jss';
3
+ /**
4
+ * Implementation of editing cache for Vercel deployments
5
+ * Uses Vercel KV database and client to store data
6
+ * Set TTL for cache data in constructor (default: 60 seconds)
7
+ */
8
+ export class VercelEditingDataCache {
9
+ /**
10
+ * @param {string} redisUrl KV endpoint URL. Usually stored in process.env.KV_REST_API_URL
11
+ * @param {string} redisToken KV endpoint tokem. Usually stored in process.env.KV_REST_API_TOKEN
12
+ */
13
+ constructor(redisUrl, redisToken) {
14
+ this.defaultTtl = 120;
15
+ if (!redisUrl || !redisToken) {
16
+ throw Error('API URL or token are missing, ensure you have set the KV or Upstash storage correctly.');
17
+ }
18
+ this.redisCache = createClient({
19
+ url: redisUrl,
20
+ token: redisToken,
21
+ });
22
+ }
23
+ set(key, editingData) {
24
+ debug.editing(`Putting editing data for ${key} into redis storage...`);
25
+ return new Promise((resolve, reject) => {
26
+ this.redisCache
27
+ .set(key, JSON.stringify(editingData), { ex: this.defaultTtl })
28
+ .then(() => resolve())
29
+ .catch((err) => reject(err));
30
+ });
31
+ }
32
+ get(key) {
33
+ debug.editing(`Getting editing data for ${key} from redis storage...`);
34
+ return new Promise((resolve, reject) => {
35
+ this.redisCache
36
+ .get(key)
37
+ .then((entry) => {
38
+ const result = (entry || undefined);
39
+ this.redisCache.expire(key, 0).then(() => resolve(result));
40
+ })
41
+ .catch((err) => reject(err));
42
+ });
43
+ }
44
+ }
package/dist/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { constants, AxiosDataFetcher, NativeDataFetcher, enableDebug, } from '@sitecore-jss/sitecore-jss';
1
+ export { constants, AxiosDataFetcher, NativeDataFetcher, enableDebug, debug, } from '@sitecore-jss/sitecore-jss';
2
2
  // we will remove the root exports for these later
3
3
  // we cannot mark exports as deprected directly, so we're using this hack instead
4
4
  import { isEditorActive as isEditorActiveDep, resetEditorChromes as resetEditorChromesDep, resolveUrl as resolveUrlDep, tryParseEnvValue as tryParseEnvValueDep, } from '@sitecore-jss/sitecore-jss/utils';
@@ -1,3 +1,4 @@
1
+ export { debug } from '@sitecore-jss/sitecore-jss';
1
2
  export { RedirectsMiddleware } from './redirects-middleware';
2
3
  export { PersonalizeMiddleware } from './personalize-middleware';
3
4
  export { MultisiteMiddleware } from './multisite-middleware';
@@ -26,6 +26,7 @@ export class MultisiteMiddleware extends MiddlewareBase {
26
26
  const pathname = req.nextUrl.pathname;
27
27
  const language = this.getLanguage(req);
28
28
  const hostname = this.getHostHeader(req) || this.defaultHostname;
29
+ const startTimestamp = Date.now();
29
30
  debug.multisite('multisite middleware start: %o', {
30
31
  pathname,
31
32
  language,
@@ -55,7 +56,7 @@ export class MultisiteMiddleware extends MiddlewareBase {
55
56
  response.cookies.set(this.SITE_SYMBOL, siteName);
56
57
  // Share rewrite path with following executed middlewares
57
58
  response.headers.set('x-sc-rewrite', rewritePath);
58
- debug.multisite('multisite middleware end: %o', {
59
+ debug.multisite('multisite middleware end in %dms: %o', Date.now() - startTimestamp, {
59
60
  rewritePath,
60
61
  siteName,
61
62
  headers: this.extractDebugHeaders(response.headers),
@@ -25,6 +25,7 @@ export class PersonalizeMiddleware extends MiddlewareBase {
25
25
  const pathname = req.nextUrl.pathname;
26
26
  const language = this.getLanguage(req);
27
27
  const hostname = this.getHostHeader(req) || this.defaultHostname;
28
+ const startTimestamp = Date.now();
28
29
  let browserId = this.getBrowserId(req);
29
30
  debug.personalize('personalize middleware start: %o', {
30
31
  pathname,
@@ -95,7 +96,7 @@ export class PersonalizeMiddleware extends MiddlewareBase {
95
96
  this.setBrowserId(response, browserId);
96
97
  // Share site name with the following executed middlewares
97
98
  response.cookies.set(this.SITE_SYMBOL, site.name);
98
- debug.personalize('personalize middleware end: %o', {
99
+ debug.personalize('personalize middleware end in %dms: %o', Date.now() - startTimestamp, {
99
100
  rewritePath,
100
101
  browserId,
101
102
  headers: this.extractDebugHeaders(response.headers),
@@ -146,7 +147,10 @@ export class PersonalizeMiddleware extends MiddlewareBase {
146
147
  }
147
148
  getExperienceParams(req) {
148
149
  return {
149
- referrer: req.referrer,
150
+ // It's expected that the header name "referer" is actually a misspelling of the word "referrer"
151
+ // req.referrer is used during fetching to determine the value of the Referer header of the request being made,
152
+ // used as a fallback
153
+ referrer: req.headers.get('referer') || req.referrer,
150
154
  utm: {
151
155
  campaign: req.nextUrl.searchParams.get('utm_campaign'),
152
156
  content: req.nextUrl.searchParams.get('utm_content'),
@@ -29,6 +29,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
29
29
  const language = this.getLanguage(req);
30
30
  const hostname = this.getHostHeader(req) || this.defaultHostname;
31
31
  let site;
32
+ const startTimestamp = Date.now();
32
33
  debug.redirects('redirects middleware start: %o', {
33
34
  pathname,
34
35
  language,
@@ -65,11 +66,12 @@ export class RedirectsMiddleware extends MiddlewareBase {
65
66
  const urlFirstPart = existsRedirect.target.split('/')[1];
66
67
  if (this.locales.includes(urlFirstPart)) {
67
68
  url.locale = urlFirstPart;
68
- url.pathname = existsRedirect.target.replace(`/${urlFirstPart}`, '');
69
- }
70
- else {
71
- url.pathname = existsRedirect.target;
69
+ existsRedirect.target = existsRedirect.target.replace(`/${urlFirstPart}`, '');
72
70
  }
71
+ url.pathname = existsRedirect.target;
72
+ url.pathname = url.pathname
73
+ .replace(regexParser(existsRedirect.pattern), existsRedirect.target)
74
+ .replace(/^\/\//, '/');
73
75
  }
74
76
  const redirectUrl = decodeURIComponent(url.href);
75
77
  /** return Response redirect with http code of redirect type **/
@@ -88,7 +90,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
88
90
  // Share site name with the following executed middlewares
89
91
  // Don't need to set when middleware is disabled
90
92
  site && response.cookies.set(this.SITE_SYMBOL, site.name);
91
- debug.redirects('redirects middleware end: %o', {
93
+ debug.redirects('redirects middleware end in %dms: %o', Date.now() - startTimestamp, {
92
94
  redirected: response.redirected,
93
95
  status: response.status,
94
96
  url: response.url,
@@ -131,13 +133,14 @@ export class RedirectsMiddleware extends MiddlewareBase {
131
133
  const targetQS = req.nextUrl.search || '';
132
134
  return redirects.length
133
135
  ? redirects.find((redirect) => {
134
- const pattern = `/^/${redirect.pattern
136
+ redirect.pattern = `/^\/${redirect.pattern
135
137
  .replace(/^\/|\/$/g, '')
138
+ .replace(/^\^\/|\/\$$/g, '')
136
139
  .replace(/^\^|\$$/g, '')}$/gi`;
137
- return ((regexParser(pattern).test(tragetURL) ||
138
- regexParser(pattern).test(`${tragetURL}${targetQS}`) ||
139
- regexParser(pattern).test(`/${req.nextUrl.locale}${tragetURL}`) ||
140
- regexParser(pattern).test(`/${req.nextUrl.locale}${tragetURL}${targetQS}`)) &&
140
+ return ((regexParser(redirect.pattern).test(tragetURL) ||
141
+ regexParser(redirect.pattern).test(`${tragetURL}${targetQS}`) ||
142
+ regexParser(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}`) ||
143
+ regexParser(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}${targetQS}`)) &&
141
144
  (redirect.locale
142
145
  ? redirect.locale.toLowerCase() === req.nextUrl.locale.toLowerCase()
143
146
  : true));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sitecore-jss/sitecore-jss-nextjs",
3
- "version": "21.3.0-canary.2",
3
+ "version": "21.3.0-canary.21",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "sideEffects": false,
@@ -70,9 +70,10 @@
70
70
  "react-dom": "^18.2.0"
71
71
  },
72
72
  "dependencies": {
73
- "@sitecore-jss/sitecore-jss": "^21.3.0-canary.2",
74
- "@sitecore-jss/sitecore-jss-dev-tools": "^21.3.0-canary.2",
75
- "@sitecore-jss/sitecore-jss-react": "^21.3.0-canary.2",
73
+ "@sitecore-jss/sitecore-jss": "^21.3.0-canary.21",
74
+ "@sitecore-jss/sitecore-jss-dev-tools": "^21.3.0-canary.21",
75
+ "@sitecore-jss/sitecore-jss-react": "^21.3.0-canary.21",
76
+ "@vercel/kv": "^0.2.1",
76
77
  "node-html-parser": "^6.1.4",
77
78
  "prop-types": "^15.8.1",
78
79
  "regex-parser": "^2.2.11",
@@ -80,7 +81,7 @@
80
81
  },
81
82
  "description": "",
82
83
  "types": "types/index.d.ts",
83
- "gitHead": "a498d1b8b6bab066a58907a2a01a554b9d20bd42",
84
+ "gitHead": "5c3f12c1712a188fa9f91a549dd688f71a74c4e8",
84
85
  "files": [
85
86
  "dist",
86
87
  "types",
@@ -3,3 +3,4 @@ export { EditingDataCache, EditingDataDiskCache } from './editing-data-cache';
3
3
  export { EditingDataMiddleware, EditingDataMiddlewareConfig } from './editing-data-middleware';
4
4
  export { EditingRenderMiddleware, EditingRenderMiddlewareConfig, } from './editing-render-middleware';
5
5
  export { EditingPreviewData, EditingDataService, BasicEditingDataService, BasicEditingDataServiceConfig, ServerlessEditingDataService, ServerlessEditingDataServiceConfig, editingDataService, } from './editing-data-service';
6
+ export { VercelEditingDataCache } from './vercel-editing-data-cache';
@@ -0,0 +1,19 @@
1
+ import { VercelKV } from '@vercel/kv';
2
+ import { EditingDataCache } from './editing-data-cache';
3
+ import { EditingData } from './editing-data';
4
+ /**
5
+ * Implementation of editing cache for Vercel deployments
6
+ * Uses Vercel KV database and client to store data
7
+ * Set TTL for cache data in constructor (default: 60 seconds)
8
+ */
9
+ export declare class VercelEditingDataCache implements EditingDataCache {
10
+ protected redisCache: VercelKV;
11
+ private defaultTtl;
12
+ /**
13
+ * @param {string} redisUrl KV endpoint URL. Usually stored in process.env.KV_REST_API_URL
14
+ * @param {string} redisToken KV endpoint tokem. Usually stored in process.env.KV_REST_API_TOKEN
15
+ */
16
+ constructor(redisUrl: string | undefined, redisToken: string | undefined);
17
+ set(key: string, editingData: EditingData): Promise<void>;
18
+ get(key: string): Promise<EditingData | undefined>;
19
+ }
package/types/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { constants, HttpDataFetcher, HttpResponse, AxiosResponse, AxiosDataFetcher, AxiosDataFetcherConfig, NativeDataFetcher, NativeDataFetcherConfig, HTMLLink, enableDebug, } from '@sitecore-jss/sitecore-jss';
1
+ export { constants, HttpDataFetcher, HttpResponse, AxiosResponse, AxiosDataFetcher, AxiosDataFetcherConfig, NativeDataFetcher, NativeDataFetcherConfig, HTMLLink, enableDebug, debug, } from '@sitecore-jss/sitecore-jss';
2
2
  import { resolveUrl as resolveUrlDep } from '@sitecore-jss/sitecore-jss/utils';
3
3
  /** @deprecated use import from '@sitecore-jss/sitecore-jss-nextjs/utils' instead */
4
4
  declare const isEditorActive: () => boolean, resetEditorChromes: () => void, resolveUrl: typeof resolveUrlDep, tryParseEnvValue: <T>(envValue: string | undefined, defaultValue: T) => T, handleEditorFastRefresh: (forceReload?: boolean) => void, getPublicUrl: () => string;
@@ -1,3 +1,4 @@
1
+ export { debug } from '@sitecore-jss/sitecore-jss';
1
2
  export { RedirectsMiddleware, RedirectsMiddlewareConfig } from './redirects-middleware';
2
3
  export { PersonalizeMiddleware, PersonalizeMiddlewareConfig } from './personalize-middleware';
3
4
  export { MultisiteMiddleware, MultisiteMiddlewareConfig } from './multisite-middleware';