@sitecore-jss/sitecore-jss-nextjs 21.7.0-canary.4 → 21.7.0-canary.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/context.d.ts +1 -0
  2. package/context.js +1 -0
  3. package/dist/cjs/context/context.js +68 -0
  4. package/dist/cjs/context/index.js +5 -0
  5. package/dist/cjs/editing/editing-render-middleware.js +1 -1
  6. package/dist/cjs/index.js +5 -3
  7. package/dist/cjs/middleware/middleware.js +17 -0
  8. package/dist/cjs/middleware/multisite-middleware.js +1 -6
  9. package/dist/cjs/middleware/personalize-middleware.js +34 -47
  10. package/dist/cjs/middleware/redirects-middleware.js +19 -11
  11. package/dist/cjs/revalidate/index.js +5 -0
  12. package/dist/cjs/revalidate/revalidate-middleware.js +216 -0
  13. package/dist/cjs/utils/utils.js +6 -18
  14. package/dist/esm/context/context.js +64 -0
  15. package/dist/esm/context/index.js +1 -0
  16. package/dist/esm/editing/editing-render-middleware.js +1 -1
  17. package/dist/esm/index.js +3 -2
  18. package/dist/esm/middleware/middleware.js +17 -0
  19. package/dist/esm/middleware/multisite-middleware.js +1 -6
  20. package/dist/esm/middleware/personalize-middleware.js +35 -48
  21. package/dist/esm/middleware/redirects-middleware.js +19 -11
  22. package/dist/esm/revalidate/index.js +1 -0
  23. package/dist/esm/revalidate/revalidate-middleware.js +212 -0
  24. package/dist/esm/utils/utils.js +6 -15
  25. package/package.json +11 -11
  26. package/revalidate.d.ts +1 -0
  27. package/revalidate.js +1 -0
  28. package/types/context/context.d.ts +113 -0
  29. package/types/context/index.d.ts +1 -0
  30. package/types/editing/editing-render-middleware.d.ts +1 -1
  31. package/types/index.d.ts +3 -2
  32. package/types/middleware/middleware.d.ts +8 -0
  33. package/types/middleware/personalize-middleware.d.ts +20 -15
  34. package/types/revalidate/index.d.ts +1 -0
  35. package/types/revalidate/revalidate-middleware.d.ts +115 -0
  36. package/types/utils/utils.d.ts +1 -0
package/context.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './types/context/index';
package/context.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/cjs/context/index');
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Context = void 0;
4
+ const sitecore_jss_react_1 = require("@sitecore-jss/sitecore-jss-react");
5
+ /**
6
+ * Context instance that is used to initialize the application Context and associated Software Development Kits (SDKs).
7
+ */
8
+ class Context {
9
+ constructor(props) {
10
+ this.props = props;
11
+ /**
12
+ * Indicates whether the Context and SDK(s) have been initialized
13
+ */
14
+ this.isInitialized = false;
15
+ /**
16
+ * Software Development Kits (SDKs) to be initialized
17
+ */
18
+ this.sdks = {};
19
+ /**
20
+ * Promises for the SDKs
21
+ */
22
+ this.sdkPromises = {};
23
+ /**
24
+ * Retrieves the Software Development Kit (SDK) instance, ensuring it is initialized before returning
25
+ *
26
+ * @param {string} name SDK name
27
+ * @returns initialized SDK
28
+ */
29
+ this.getSDK = (name) => {
30
+ return this.sdkPromises[name] || Promise.reject(`Unknown SDK '${String(name)}'`);
31
+ };
32
+ this.sitecoreEdgeUrl = props.sitecoreEdgeUrl;
33
+ this.sitecoreEdgeContextId = props.sitecoreEdgeContextId;
34
+ this.siteName = props.siteName;
35
+ this.pageState = sitecore_jss_react_1.LayoutServicePageState.Normal;
36
+ }
37
+ init(props = {}) {
38
+ // Context and SDKs are initialized only once
39
+ if (this.isInitialized)
40
+ return;
41
+ this.isInitialized = true;
42
+ if (props.siteName) {
43
+ this.siteName = props.siteName;
44
+ }
45
+ if (props.pageState) {
46
+ this.pageState = props.pageState;
47
+ }
48
+ // iterate over the SDKs and initialize them
49
+ for (const sdkName of Object.keys(this.props.sdks)) {
50
+ this.initSDK(sdkName);
51
+ }
52
+ }
53
+ /**
54
+ * Initializes the Software Development Kit (SDK)
55
+ *
56
+ * @param {T} name SDK name
57
+ * @returns {void}
58
+ */
59
+ initSDK(name) {
60
+ this.sdkPromises[name] = new Promise((resolve) => {
61
+ this.props.sdks[name].init(this).then(() => {
62
+ this.sdks[name] = this.props.sdks[name].sdk;
63
+ resolve(this.sdks[name]);
64
+ });
65
+ });
66
+ }
67
+ }
68
+ exports.Context = Context;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Context = void 0;
4
+ var context_1 = require("./context");
5
+ Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return context_1.Context; } });
@@ -29,7 +29,7 @@ class EditingRenderMiddleware {
29
29
  var _a, _b, _c, _d;
30
30
  /**
31
31
  * Gets query parameters that should be passed along to subsequent requests
32
- * @param query Object of query parameters from incoming URL
32
+ * @param {Object} query Object of query parameters from incoming URL
33
33
  * @returns Object of approved query parameters
34
34
  */
35
35
  this.getQueryParamsForPropagation = (query) => {
package/dist/cjs/index.js CHANGED
@@ -23,8 +23,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- 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.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.GraphQLRequestClient = exports.debug = exports.enableDebug = exports.NativeDataFetcher = exports.AxiosDataFetcher = exports.constants = void 0;
27
- exports.withDatasourceCheck = exports.withPlaceholder = exports.withEditorChromes = exports.useSitecoreContext = exports.withSitecoreContext = exports.SitecoreContextReactContext = exports.SitecoreContext = exports.VisitorIdentification = exports.File = exports.getFEAASLibraryStylesheetLinks = exports.BYOCComponent = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.EditFrame = exports.DateField = exports.Text = exports.Image = exports.ComponentBuilder = exports.BYOCWrapper = exports.FEaaSWrapper = void 0;
26
+ 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.CdpHelper = exports.normalizePersonalizedRewrite = exports.getPersonalizedRewriteData = exports.getPersonalizedRewrite = exports.personalizeLayout = exports.RestDictionaryService = exports.GraphQLDictionaryService = exports.trackingApi = exports.mediaApi = exports.getContentStylesheetLink = 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.GraphQLRequestClient = exports.debug = exports.enableDebug = exports.NativeDataFetcher = exports.AxiosDataFetcher = exports.constants = void 0;
27
+ exports.withDatasourceCheck = exports.withPlaceholder = exports.withEditorChromes = exports.useSitecoreContext = exports.withSitecoreContext = exports.SitecoreContextReactContext = exports.SitecoreContext = exports.VisitorIdentification = exports.File = exports.getFEAASLibraryStylesheetLinks = exports.BYOCComponent = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.EditFrame = exports.DateField = exports.Text = exports.Image = exports.Context = exports.ComponentBuilder = exports.BYOCWrapper = exports.FEaaSWrapper = void 0;
28
28
  var sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
29
29
  Object.defineProperty(exports, "constants", { enumerable: true, get: function () { return sitecore_jss_1.constants; } });
30
30
  Object.defineProperty(exports, "AxiosDataFetcher", { enumerable: true, get: function () { return sitecore_jss_1.AxiosDataFetcher; } });
@@ -65,6 +65,7 @@ Object.defineProperty(exports, "getFieldValue", { enumerable: true, get: functio
65
65
  Object.defineProperty(exports, "RenderingType", { enumerable: true, get: function () { return layout_1.RenderingType; } });
66
66
  Object.defineProperty(exports, "EDITING_COMPONENT_PLACEHOLDER", { enumerable: true, get: function () { return layout_1.EDITING_COMPONENT_PLACEHOLDER; } });
67
67
  Object.defineProperty(exports, "EDITING_COMPONENT_ID", { enumerable: true, get: function () { return layout_1.EDITING_COMPONENT_ID; } });
68
+ Object.defineProperty(exports, "getContentStylesheetLink", { enumerable: true, get: function () { return layout_1.getContentStylesheetLink; } });
68
69
  var media_1 = require("@sitecore-jss/sitecore-jss/media");
69
70
  Object.defineProperty(exports, "mediaApi", { enumerable: true, get: function () { return media_1.mediaApi; } });
70
71
  var tracking_1 = require("@sitecore-jss/sitecore-jss/tracking");
@@ -78,7 +79,6 @@ Object.defineProperty(exports, "getPersonalizedRewrite", { enumerable: true, get
78
79
  Object.defineProperty(exports, "getPersonalizedRewriteData", { enumerable: true, get: function () { return personalize_1.getPersonalizedRewriteData; } });
79
80
  Object.defineProperty(exports, "normalizePersonalizedRewrite", { enumerable: true, get: function () { return personalize_1.normalizePersonalizedRewrite; } });
80
81
  Object.defineProperty(exports, "CdpHelper", { enumerable: true, get: function () { return personalize_1.CdpHelper; } });
81
- Object.defineProperty(exports, "PosResolver", { enumerable: true, get: function () { return personalize_1.PosResolver; } });
82
82
  var component_props_service_1 = require("./services/component-props-service");
83
83
  Object.defineProperty(exports, "ComponentPropsService", { enumerable: true, get: function () { return component_props_service_1.ComponentPropsService; } });
84
84
  var disconnected_sitemap_service_1 = require("./services/disconnected-sitemap-service");
@@ -116,6 +116,8 @@ const BYOCWrapper = __importStar(require("./components/BYOCWrapper"));
116
116
  exports.BYOCWrapper = BYOCWrapper;
117
117
  var ComponentBuilder_1 = require("./ComponentBuilder");
118
118
  Object.defineProperty(exports, "ComponentBuilder", { enumerable: true, get: function () { return ComponentBuilder_1.ComponentBuilder; } });
119
+ var context_1 = require("./context");
120
+ Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return context_1.Context; } });
119
121
  var sitecore_jss_react_1 = require("@sitecore-jss/sitecore-jss-react");
120
122
  Object.defineProperty(exports, "Image", { enumerable: true, get: function () { return sitecore_jss_react_1.Image; } });
121
123
  Object.defineProperty(exports, "Text", { enumerable: true, get: function () { return sitecore_jss_react_1.Text; } });
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MiddlewareBase = void 0;
4
+ const server_1 = require("next/server");
4
5
  class MiddlewareBase {
5
6
  constructor(config) {
6
7
  this.config = config;
7
8
  this.SITE_SYMBOL = 'sc_site';
9
+ this.REWRITE_HEADER_NAME = 'x-sc-rewrite';
8
10
  this.defaultHostname = config.defaultHostname || 'localhost';
9
11
  }
10
12
  /**
@@ -65,5 +67,20 @@ class MiddlewareBase {
65
67
  const hostname = this.getHostHeader(req) || this.defaultHostname;
66
68
  return this.config.siteResolver.getByHost(hostname);
67
69
  }
70
+ /**
71
+ * Create a rewrite response
72
+ * @param {string} rewritePath the destionation path
73
+ * @param {NextRequest} req the current request
74
+ * @param {NextResponse} res the current response
75
+ */
76
+ rewrite(rewritePath, req, res) {
77
+ // Note an absolute URL is required: https://nextjs.org/docs/messages/middleware-relative-urls
78
+ const rewriteUrl = req.nextUrl.clone();
79
+ rewriteUrl.pathname = rewritePath;
80
+ const response = server_1.NextResponse.rewrite(rewriteUrl, res);
81
+ // Share rewrite path with following executed middlewares
82
+ response.headers.set(this.REWRITE_HEADER_NAME, rewritePath);
83
+ return response;
84
+ }
68
85
  }
69
86
  exports.MiddlewareBase = MiddlewareBase;
@@ -51,14 +51,9 @@ class MultisiteMiddleware extends middleware_1.MiddlewareBase {
51
51
  const rewritePath = (0, site_1.getSiteRewrite)(pathname, {
52
52
  siteName,
53
53
  });
54
- // Note an absolute URL is required: https://nextjs.org/docs/messages/middleware-relative-urls
55
- const rewriteUrl = req.nextUrl.clone();
56
- rewriteUrl.pathname = rewritePath;
57
- response = server_1.NextResponse.rewrite(rewriteUrl);
54
+ response = this.rewrite(rewritePath, req, response);
58
55
  // Share site name with the following executed middlewares
59
56
  response.cookies.set(this.SITE_SYMBOL, siteName);
60
- // Share rewrite path with following executed middlewares
61
- response.headers.set('x-sc-rewrite', rewritePath);
62
57
  sitecore_jss_1.debug.multisite('multisite middleware end in %dms: %o', Date.now() - startTimestamp, {
63
58
  rewritePath,
64
59
  siteName,
@@ -14,7 +14,7 @@ const server_1 = require("next/server");
14
14
  const personalize_1 = require("@sitecore-jss/sitecore-jss/personalize");
15
15
  const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
16
16
  const middleware_1 = require("./middleware");
17
- const engage_1 = require("@sitecore/engage");
17
+ const server_2 = require("@sitecore-cloudsdk/personalize/server");
18
18
  /**
19
19
  * Middleware / handler to support Sitecore Personalize
20
20
  */
@@ -26,7 +26,6 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
26
26
  super(config);
27
27
  this.config = config;
28
28
  this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
29
- var _a;
30
29
  const pathname = req.nextUrl.pathname;
31
30
  const language = this.getLanguage(req);
32
31
  const hostname = this.getHostHeader(req) || this.defaultHostname;
@@ -62,30 +61,20 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
62
61
  sitecore_jss_1.debug.personalize('skipped (no personalization configured)');
63
62
  return response;
64
63
  }
65
- const engageServer = this.initializeEngageServer(hostname, site, language);
66
- // creates the browser ID cookie on the server side
67
- // and includes the cookie in the response header
68
- try {
69
- yield engageServer.handleCookie(req, response, timeout);
70
- }
71
- catch (error) {
72
- sitecore_jss_1.debug.personalize('skipped (browser id generation failed)');
73
- throw error;
74
- }
64
+ yield this.initPersonalizeServer({
65
+ hostname,
66
+ siteName: site.name,
67
+ request: req,
68
+ response,
69
+ });
75
70
  const params = this.getExperienceParams(req);
76
- sitecore_jss_1.debug.personalize('executing experience for %s %s %o', personalizeInfo.contentId, params);
77
- const personalizationData = {
78
- channel: this.config.cdpConfig.channel || 'WEB',
79
- currency: (_a = this.config.cdpConfig.currency) !== null && _a !== void 0 ? _a : 'USA',
80
- friendlyId: personalizeInfo.contentId,
81
- params,
82
- language,
83
- };
71
+ sitecore_jss_1.debug.personalize('executing experience for %s %o', personalizeInfo.contentId, params);
84
72
  let variantId;
85
- // Execute targeted experience in CDP
73
+ // Execute targeted experience in Personalize SDK
86
74
  // eslint-disable-next-line no-useless-catch
87
75
  try {
88
- variantId = (yield engageServer.personalize(personalizationData, req, timeout)).variantId;
76
+ const personalization = yield this.personalize({ personalizeInfo, params, language, timeout }, req);
77
+ variantId = personalization.variantId;
89
78
  }
90
79
  catch (error) {
91
80
  throw error;
@@ -102,24 +91,10 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
102
91
  const basePath = (res === null || res === void 0 ? void 0 : res.headers.get('x-sc-rewrite')) || pathname;
103
92
  // Rewrite to persononalized path
104
93
  const rewritePath = (0, personalize_1.getPersonalizedRewrite)(basePath, { variantId });
105
- // Note an absolute URL is required: https://nextjs.org/docs/messages/middleware-relative-urls
106
- const rewriteUrl = req.nextUrl.clone();
107
- // Preserve cookies from previous response
108
- const cookies = response.cookies.getAll();
109
- rewriteUrl.pathname = rewritePath;
110
- response = server_1.NextResponse.rewrite(rewriteUrl, response);
94
+ response = this.rewrite(rewritePath, req, response);
111
95
  // Disable preflight caching to force revalidation on client-side navigation (personalization may be influenced)
112
96
  // See https://github.com/vercel/next.js/issues/32727
113
97
  response.headers.set('x-middleware-cache', 'no-cache');
114
- // Share rewrite path with following executed middleware
115
- response.headers.set('x-sc-rewrite', rewritePath);
116
- // Share site name with the following executed middlewares
117
- response.cookies.set(this.SITE_SYMBOL, site.name);
118
- // Restore cookies from previous response since
119
- // browserId cookie gets omitted after rewrite
120
- cookies.forEach((cookie) => {
121
- response.cookies.set(cookie);
122
- });
123
98
  sitecore_jss_1.debug.personalize('personalize middleware end in %dms: %o', Date.now() - startTimestamp, {
124
99
  rewritePath,
125
100
  headers: this.extractDebugHeaders(response.headers),
@@ -146,17 +121,29 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
146
121
  }
147
122
  });
148
123
  }
149
- initializeEngageServer(hostName, site, language) {
150
- const engageServer = (0, engage_1.initServer)({
151
- clientKey: this.config.cdpConfig.clientKey,
152
- targetURL: this.config.cdpConfig.endpoint,
153
- pointOfSale: this.config.getPointOfSale
154
- ? this.config.getPointOfSale(site, language)
155
- : personalize_1.PosResolver.resolve(site, language),
156
- cookieDomain: hostName,
157
- forceServerCookieMode: true,
124
+ initPersonalizeServer({ hostname, siteName, request, response, }) {
125
+ return __awaiter(this, void 0, void 0, function* () {
126
+ yield (0, server_2.init)({
127
+ sitecoreEdgeUrl: this.config.cdpConfig.sitecoreEdgeUrl,
128
+ sitecoreEdgeContextId: this.config.cdpConfig.sitecoreEdgeContextId,
129
+ siteName,
130
+ cookieDomain: hostname,
131
+ enableServerCookie: true,
132
+ }, request, response);
133
+ });
134
+ }
135
+ personalize({ params, personalizeInfo, language, timeout, }, request) {
136
+ var _a;
137
+ return __awaiter(this, void 0, void 0, function* () {
138
+ const personalizationData = {
139
+ channel: this.config.cdpConfig.channel || 'WEB',
140
+ currency: (_a = this.config.cdpConfig.currency) !== null && _a !== void 0 ? _a : 'USD',
141
+ friendlyId: personalizeInfo.contentId,
142
+ params,
143
+ language,
144
+ };
145
+ return (yield (0, server_2.personalize)(personalizationData, request, timeout));
158
146
  });
159
- return engageServer;
160
147
  }
161
148
  getExperienceParams(req) {
162
149
  const utm = {
@@ -42,7 +42,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
42
42
  hostname,
43
43
  });
44
44
  const createResponse = () => __awaiter(this, void 0, void 0, function* () {
45
- if (this.config.disabled && this.config.disabled(req, server_1.NextResponse.next())) {
45
+ if (this.config.disabled && this.config.disabled(req, res || server_1.NextResponse.next())) {
46
46
  sitecore_jss_1.debug.redirects('skipped (redirects middleware is disabled)');
47
47
  return res || server_1.NextResponse.next();
48
48
  }
@@ -82,19 +82,24 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
82
82
  /** return Response redirect with http code of redirect type **/
83
83
  switch (existsRedirect.redirectType) {
84
84
  case site_1.REDIRECT_TYPE_301:
85
- return server_1.NextResponse.redirect(redirectUrl, 301);
85
+ return server_1.NextResponse.redirect(redirectUrl, {
86
+ status: 301,
87
+ statusText: 'Moved Permanently',
88
+ headers: res === null || res === void 0 ? void 0 : res.headers,
89
+ });
86
90
  case site_1.REDIRECT_TYPE_302:
87
- return server_1.NextResponse.redirect(redirectUrl, 302);
91
+ return server_1.NextResponse.redirect(redirectUrl, {
92
+ status: 302,
93
+ statusText: 'Found',
94
+ headers: res === null || res === void 0 ? void 0 : res.headers,
95
+ });
88
96
  case site_1.REDIRECT_TYPE_SERVER_TRANSFER:
89
- return server_1.NextResponse.rewrite(redirectUrl);
97
+ return server_1.NextResponse.rewrite(redirectUrl, res);
90
98
  default:
91
- return server_1.NextResponse.next();
99
+ return res || server_1.NextResponse.next();
92
100
  }
93
101
  });
94
102
  const response = yield createResponse();
95
- // Share site name with the following executed middlewares
96
- // Don't need to set when middleware is disabled
97
- site && response.cookies.set(this.SITE_SYMBOL, site.name);
98
103
  sitecore_jss_1.debug.redirects('redirects middleware end in %dms: %o', Date.now() - startTimestamp, {
99
104
  redirected: response.redirected,
100
105
  status: response.status,
@@ -136,13 +141,16 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
136
141
  const redirects = yield this.redirectsService.fetchRedirects(siteName);
137
142
  const tragetURL = req.nextUrl.pathname;
138
143
  const targetQS = req.nextUrl.search || '';
139
- return redirects.length
140
- ? redirects.find((redirect) => {
144
+ const language = this.getLanguage(req);
145
+ const modifyRedirects = structuredClone(redirects);
146
+ return modifyRedirects.length
147
+ ? modifyRedirects.find((redirect) => {
148
+ redirect.pattern = redirect.pattern.replace(RegExp(`^[^]?/${language}/`, 'gi'), '');
141
149
  redirect.pattern = `/^\/${redirect.pattern
142
150
  .replace(/^\/|\/$/g, '')
143
151
  .replace(/^\^\/|\/\$$/g, '')
144
152
  .replace(/^\^|\$$/g, '')
145
- .replace(/\$\/gi$/g, '')}$/gi`;
153
+ .replace(/\$\/gi$/g, '')}[\/]?$/gi`;
146
154
  return (((0, regex_parser_1.default)(redirect.pattern).test(tragetURL) ||
147
155
  (0, regex_parser_1.default)(redirect.pattern).test(`${tragetURL}${targetQS}`) ||
148
156
  (0, regex_parser_1.default)(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}`) ||
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RevalidateMiddleware = void 0;
4
+ var revalidate_middleware_1 = require("./revalidate-middleware");
5
+ Object.defineProperty(exports, "RevalidateMiddleware", { enumerable: true, get: function () { return revalidate_middleware_1.RevalidateMiddleware; } });
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RevalidateMiddleware = void 0;
13
+ // import { I18NConfig } from 'next/dist/server/config-shared';
14
+ const personalize_1 = require("@sitecore-jss/sitecore-jss/personalize");
15
+ const site_1 = require("@sitecore-jss/sitecore-jss/site");
16
+ const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
17
+ var EntityDefinition;
18
+ (function (EntityDefinition) {
19
+ EntityDefinition["LayoutData"] = "LayoutData";
20
+ EntityDefinition["Item"] = "Item";
21
+ })(EntityDefinition || (EntityDefinition = {}));
22
+ /**
23
+ * Middleware / handler for on-demand ISR (e.g. '/api/revalidate').
24
+ */
25
+ class RevalidateMiddleware {
26
+ constructor(config) {
27
+ this.config = config;
28
+ this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
29
+ // filter out updated paths and language from request.body
30
+ const filteredUpdates = this.getFilteredUpdates(req);
31
+ if (this.isEmpty(filteredUpdates)) {
32
+ // nothing to revalidate
33
+ return res.status(204).json({ message: 'No updates to revalidate' });
34
+ }
35
+ // extract only paths from filtered updates object
36
+ const paths = this.extractPaths(filteredUpdates);
37
+ const pathsToRevalidate = [];
38
+ // when personalization is configured and when both multiSite and personalization are configured
39
+ if (this.config.personalize) {
40
+ const personalizeInfo = yield this.getPersonalizedResults(filteredUpdates);
41
+ if (this.config.multiSite) {
42
+ this.handleMultiSitePersonalization(personalizeInfo, pathsToRevalidate, this.getPathName, this.getSiteName);
43
+ }
44
+ else {
45
+ this.handleNonMultiSitePersonalization(personalizeInfo, pathsToRevalidate, this.getPathName);
46
+ }
47
+ }
48
+ // when only multiSite is configured
49
+ if (this.config.multiSite && !this.config.personalize) {
50
+ const multiSitePaths = paths.map((path) => (0, site_1.getSiteRewrite)(this.getPathName(path), { siteName: this.getSiteName(path) }));
51
+ pathsToRevalidate.push(...multiSitePaths);
52
+ }
53
+ // when both multiSite and personalization are not configured
54
+ if (!this.config.multiSite && !this.config.personalize) {
55
+ const defaultPaths = paths.map((path) => this.getPathName(path));
56
+ pathsToRevalidate.push(...defaultPaths);
57
+ }
58
+ // when other locales are configured besides defaultLocale
59
+ if (!this.isEmpty(filteredUpdates)) {
60
+ const filteredLanguage = [...new Set(filteredUpdates.map(({ language }) => language))].join(',');
61
+ if (this.config.localePrefix) {
62
+ const language = this.config.localePrefix(filteredLanguage);
63
+ if (language) {
64
+ yield Promise.all(pathsToRevalidate.map((path) => res.revalidate(`/${language}` + path)));
65
+ }
66
+ }
67
+ }
68
+ yield Promise.all(pathsToRevalidate.map((path) => res.revalidate(path)));
69
+ sitecore_jss_1.debug.revalidate(`revalidated paths: ${pathsToRevalidate.join(', ')}`);
70
+ });
71
+ this.personalizeService = new personalize_1.GraphQLPersonalizeService({
72
+ clientFactory: config.clientFactory,
73
+ });
74
+ }
75
+ /**
76
+ * Generates a Next.js API route handler that executes a revalidation process.
77
+ * @returns The route handler function for handling Next.js API requests.
78
+ */
79
+ getHandler() {
80
+ return (req, res) => __awaiter(this, void 0, void 0, function* () {
81
+ try {
82
+ yield this.handler(req, res);
83
+ return res.status(200).json({ revalidated: true });
84
+ }
85
+ catch (error) {
86
+ console.log('Error Revalidating:');
87
+ console.log(error);
88
+ return res.status(500).json({ revalidated: false });
89
+ }
90
+ });
91
+ }
92
+ /**
93
+ * Gets personalized results for the updated paths
94
+ * @param {UpdatedPaths[]} filteredUpdates Updated paths
95
+ */
96
+ getPersonalizedResults(filteredUpdates) {
97
+ return __awaiter(this, void 0, void 0, function* () {
98
+ const personalizedResults = [];
99
+ const nonPersonalizedResults = [];
100
+ yield Promise.all(filteredUpdates.map((update) => __awaiter(this, void 0, void 0, function* () {
101
+ const siteName = this.getSiteName(update.path);
102
+ const pathName = this.getPathName(update.path);
103
+ const personalizeInfo = yield this.personalizeService.getPersonalizeInfo(pathName, update.language, siteName);
104
+ if (personalizeInfo && personalizeInfo.variantIds.length > 0) {
105
+ personalizeInfo.variantIds.forEach((variantId) => {
106
+ personalizedResults.push({
107
+ path: update.path,
108
+ variantId,
109
+ });
110
+ });
111
+ }
112
+ else {
113
+ // Collect paths without personalized info
114
+ nonPersonalizedResults.push({
115
+ path: update.path,
116
+ });
117
+ }
118
+ })));
119
+ return {
120
+ personalized: personalizedResults,
121
+ nonPersonalized: nonPersonalizedResults,
122
+ };
123
+ });
124
+ }
125
+ isEmpty(data) {
126
+ return data.length === 0;
127
+ }
128
+ /**
129
+ * Extracts the paths from the updated paths
130
+ * @param {UpdatedPaths[]} filteredUpdates Updated paths
131
+ * @returns {string[]} paths
132
+ */
133
+ extractPaths(filteredUpdates) {
134
+ return filteredUpdates.map((update) => update.path);
135
+ }
136
+ /**
137
+ * Gets the site name from the path name
138
+ * @param {string} pathname Path name
139
+ * @returns {string} site name
140
+ */
141
+ getSiteName(pathname) {
142
+ let siteName = '';
143
+ const path = pathname.endsWith('/') ? pathname : pathname + '/';
144
+ const result = path.match('(.*?)\\/');
145
+ if (result && result[1] !== '') {
146
+ siteName = result[1];
147
+ }
148
+ return siteName;
149
+ }
150
+ /**
151
+ * Gets the path name from the full path
152
+ * @param {string} fullPath Full path
153
+ * @returns {string} path name
154
+ */
155
+ getPathName(fullPath) {
156
+ const pathParts = fullPath.split('/').filter((part) => part !== '');
157
+ if (pathParts.length >= 2) {
158
+ const siteName = `/${pathParts[0]}/`;
159
+ const path = `/${pathParts.slice(1).join('/')}`;
160
+ return path.startsWith(siteName) ? path.slice(siteName.length) : path;
161
+ }
162
+ return '/';
163
+ }
164
+ extractSiteName(path) {
165
+ const siteName = path.split('/')[0];
166
+ return siteName;
167
+ }
168
+ /**
169
+ * Filters out the updated paths and language from the request body
170
+ * @param {NextApiRequest} req Next.js API request
171
+ * @returns {UpdatedPaths[]} updated paths
172
+ */
173
+ getFilteredUpdates(req) {
174
+ var _a, _b;
175
+ if (!((_a = req.body) === null || _a === void 0 ? void 0 : _a.updates) || this.isEmpty(req.body.updates)) {
176
+ return [];
177
+ }
178
+ return (_b = req.body) === null || _b === void 0 ? void 0 : _b.updates.filter((update) => update.entity_definition === EntityDefinition.LayoutData && update.entity_culture).map((update) => {
179
+ if (update.identifier === 'website/') {
180
+ return null;
181
+ }
182
+ return {
183
+ path: update.identifier,
184
+ language: update.entity_culture,
185
+ };
186
+ }).filter(Boolean);
187
+ }
188
+ handleMultiSitePersonalization(personalizeInfo, pathsToRevalidate, getPathName, getSiteName) {
189
+ if (personalizeInfo.personalized.length > 0) {
190
+ const personalizedRewrite = personalizeInfo.personalized.map((info) => {
191
+ return (0, personalize_1.getPersonalizedRewrite)((0, site_1.getSiteRewrite)(getPathName(info.path), { siteName: getSiteName(info.path) }), {
192
+ variantId: info.variantId,
193
+ });
194
+ });
195
+ pathsToRevalidate.push(...personalizedRewrite);
196
+ }
197
+ if (personalizeInfo.nonPersonalized.length > 0) {
198
+ const nonPersonalizedRewrite = personalizeInfo.nonPersonalized.map((info) => {
199
+ return (0, site_1.getSiteRewrite)(getPathName(info.path), {
200
+ siteName: getSiteName(info.path),
201
+ });
202
+ });
203
+ pathsToRevalidate.push(...nonPersonalizedRewrite);
204
+ }
205
+ }
206
+ handleNonMultiSitePersonalization(personalizeInfo, pathsToRevalidate, getPathName) {
207
+ const nonMultiSitePersonalizedRewrite = personalizeInfo.personalized.map((info) => {
208
+ return (0, personalize_1.getPersonalizedRewrite)(getPathName(info.path), { variantId: info.variantId });
209
+ });
210
+ const nonMultiSiteNonPersonalizedRewrite = personalizeInfo.nonPersonalized.map((info) => {
211
+ return this.getPathName(info.path);
212
+ });
213
+ pathsToRevalidate.push(...nonMultiSitePersonalizedRewrite, ...nonMultiSiteNonPersonalizedRewrite);
214
+ }
215
+ }
216
+ exports.RevalidateMiddleware = RevalidateMiddleware;
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.getJssEditingSecret = exports.handleEditorFastRefresh = exports.getPublicUrl = void 0;
7
- const chalk_1 = __importDefault(require("chalk"));
8
4
  const utils_1 = require("@sitecore-jss/sitecore-jss/utils");
9
5
  /**
10
6
  * Get the publicUrl.
@@ -13,27 +9,19 @@ const utils_1 = require("@sitecore-jss/sitecore-jss/utils");
13
9
  * VERCEL_URL is provided by Vercel in case if we are in Preview deployment (deployment based on the custom branch),
14
10
  * preview deployment has unique url, we don't know exact url.
15
11
  * Similarly, DEPLOY_URL is provided by Netlify and would give us the deploy URL
12
+ * In production non-editing environments it is desirable to use relative urls, so in that case set PUBLIC_URL = ''
16
13
  */
17
14
  const getPublicUrl = () => {
18
- if (process.env.NETLIFY && process.env.DEPLOY_URL)
19
- return process.env.DEPLOY_URL;
20
- if (process.env.VERCEL_URL)
21
- return `https://${process.env.VERCEL_URL}`;
22
15
  let url = process.env.PUBLIC_URL;
23
16
  if (url === undefined) {
24
- console.warn(`${chalk_1.default.yellow.bold('Warning:')} An PUBLIC_URL environment variable is not defined. Falling back to http://localhost:3000.`);
17
+ if (process.env.NETLIFY && process.env.DEPLOY_URL)
18
+ return process.env.DEPLOY_URL;
19
+ if (process.env.VERCEL_URL)
20
+ return `https://${process.env.VERCEL_URL}`;
25
21
  url = 'http://localhost:3000';
26
22
  }
27
- else {
28
- try {
29
- new URL(url);
30
- }
31
- catch (error) {
32
- throw new Error(`The PUBLIC_URL environment variable '${url}' is not a valid URL.`);
33
- }
34
- }
35
23
  // Ensure no trailing slash
36
- return url.toString().replace(/\/$/, '');
24
+ return url.replace(/\/$/, '');
37
25
  };
38
26
  exports.getPublicUrl = getPublicUrl;
39
27
  /**