@sitecore-content-sdk/nextjs 0.1.0-beta.4 → 0.1.0-beta.6

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.
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MultisiteMiddleware = exports.PersonalizeMiddleware = exports.RedirectsMiddleware = exports.MiddlewareBase = exports.debug = void 0;
3
+ exports.MultisiteMiddleware = exports.PersonalizeMiddleware = exports.RedirectsMiddleware = exports.defineMiddleware = exports.Middleware = exports.MiddlewareBase = exports.debug = void 0;
4
4
  var core_1 = require("@sitecore-content-sdk/core");
5
5
  Object.defineProperty(exports, "debug", { enumerable: true, get: function () { return core_1.debug; } });
6
6
  var middleware_1 = require("./middleware");
7
7
  Object.defineProperty(exports, "MiddlewareBase", { enumerable: true, get: function () { return middleware_1.MiddlewareBase; } });
8
+ Object.defineProperty(exports, "Middleware", { enumerable: true, get: function () { return middleware_1.Middleware; } });
9
+ Object.defineProperty(exports, "defineMiddleware", { enumerable: true, get: function () { return middleware_1.defineMiddleware; } });
8
10
  var redirects_middleware_1 = require("./redirects-middleware");
9
11
  Object.defineProperty(exports, "RedirectsMiddleware", { enumerable: true, get: function () { return redirects_middleware_1.RedirectsMiddleware; } });
10
12
  var personalize_middleware_1 = require("./personalize-middleware");
@@ -1,9 +1,29 @@
1
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
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MiddlewareBase = void 0;
12
+ exports.defineMiddleware = exports.MiddlewareBase = exports.Middleware = void 0;
13
+ const core_1 = require("@sitecore-content-sdk/core");
4
14
  const server_1 = require("next/server");
5
- class MiddlewareBase {
15
+ /**
16
+ * Middleware class to be extended by all middleware implementations
17
+ */
18
+ class Middleware {
19
+ }
20
+ exports.Middleware = Middleware;
21
+ /**
22
+ * Base middleware class with common methods
23
+ */
24
+ class MiddlewareBase extends Middleware {
6
25
  constructor(config) {
26
+ super();
7
27
  this.config = config;
8
28
  this.SITE_SYMBOL = 'sc_site';
9
29
  this.REWRITE_HEADER_NAME = 'x-sc-rewrite';
@@ -29,12 +49,12 @@ class MiddlewareBase {
29
49
  req.headers.get('purpose') === 'prefetch' || req.headers.get('Next-Router-Prefetch') === '1' // Pages Router // App Router
30
50
  );
31
51
  }
32
- excludeRoute(pathname) {
33
- var _a, _b;
52
+ disabled(req, res) {
53
+ const { pathname } = req.nextUrl;
34
54
  return (pathname.startsWith('/api/') || // Ignore Next.js API calls
35
55
  pathname.startsWith('/sitecore/') || // Ignore Sitecore API calls
36
56
  pathname.startsWith('/_next') || // Ignore next service calls
37
- (((_a = this.config) === null || _a === void 0 ? void 0 : _a.excludeRoute) && ((_b = this.config) === null || _b === void 0 ? void 0 : _b.excludeRoute(pathname))));
57
+ (this.config.disabled && this.config.disabled(req, res)));
38
58
  }
39
59
  /**
40
60
  * Safely extract all headers for debug logging
@@ -95,3 +115,26 @@ class MiddlewareBase {
95
115
  }
96
116
  }
97
117
  exports.MiddlewareBase = MiddlewareBase;
118
+ /**
119
+ * Define a middleware with a list of middlewares
120
+ * @param {Middleware[]} middlewares List of middlewares to execute
121
+ */
122
+ const defineMiddleware = (...middlewares) => {
123
+ return {
124
+ /**
125
+ * Execute all middlewares
126
+ * @param {NextRequest} req request
127
+ * @param {NextFetchEvent} ev fetch event
128
+ * @param {NextResponse} [res] response
129
+ */
130
+ exec: (req, ev, res) => __awaiter(void 0, void 0, void 0, function* () {
131
+ const response = res || server_1.NextResponse.next();
132
+ core_1.debug.common('middleware start');
133
+ const start = Date.now();
134
+ const middlewareResponse = yield middlewares.reduce((p, middleware) => p.then((res) => middleware.handle(req, res, ev)), Promise.resolve(response));
135
+ core_1.debug.common('middleware end in %dms', Date.now() - start);
136
+ return middlewareResponse;
137
+ }),
138
+ };
139
+ };
140
+ exports.defineMiddleware = defineMiddleware;
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.MultisiteMiddleware = void 0;
13
- const server_1 = require("next/server");
14
13
  const site_1 = require("@sitecore-content-sdk/core/site");
15
14
  const core_1 = require("@sitecore-content-sdk/core");
16
15
  const middleware_1 = require("./middleware");
@@ -24,70 +23,63 @@ class MultisiteMiddleware extends middleware_1.MiddlewareBase {
24
23
  constructor(config) {
25
24
  super(config);
26
25
  this.config = config;
27
- this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
26
+ this.handle = (req, res) => __awaiter(this, void 0, void 0, function* () {
28
27
  var _a;
29
- const pathname = req.nextUrl.pathname;
30
- const language = this.getLanguage(req);
31
- const hostname = this.getHostHeader(req) || this.defaultHostname;
32
- const startTimestamp = Date.now();
33
- core_1.debug.multisite('multisite middleware start: %o', {
34
- pathname,
35
- language,
36
- hostname,
37
- });
38
- // Response will be provided if other middleware is run before us
39
- let response = res || server_1.NextResponse.next();
40
- if (this.isPreview(req) || this.excludeRoute(pathname)) {
41
- core_1.debug.multisite('skipped (%s)', this.isPreview(req) ? 'preview' : 'route excluded');
42
- return response;
43
- }
44
- // Site name can be forced by query string parameter or cookie
45
- const siteName = req.nextUrl.searchParams.get(this.SITE_SYMBOL) ||
46
- (this.config.useCookieResolution &&
47
- this.config.useCookieResolution(req) &&
48
- ((_a = req.cookies.get(this.SITE_SYMBOL)) === null || _a === void 0 ? void 0 : _a.value)) ||
49
- this.config.siteResolver.getByHost(hostname).name;
50
- // Rewrite to site specific path
51
- const rewritePath = (0, site_1.getSiteRewrite)(pathname, {
52
- siteName,
53
- });
54
- response = this.rewrite(rewritePath, req, response);
55
- // default site cookie attributes
56
- const defaultCookieAttributes = {
57
- secure: true,
58
- httpOnly: true,
59
- sameSite: 'none',
60
- };
61
- // Share site name with the following executed middlewares
62
- response.cookies.set(this.SITE_SYMBOL, siteName, defaultCookieAttributes);
63
- core_1.debug.multisite('multisite middleware end in %dms: %o', Date.now() - startTimestamp, {
64
- rewritePath,
65
- siteName,
66
- headers: this.extractDebugHeaders(response.headers),
67
- cookies: response.cookies,
68
- });
69
- return response;
70
- });
71
- }
72
- /**
73
- * Gets the Next.js middleware handler with error handling
74
- * @returns middleware handler
75
- */
76
- getHandler() {
77
- return (req, res) => __awaiter(this, void 0, void 0, function* () {
78
28
  try {
79
- return yield this.handler(req, res);
29
+ const pathname = req.nextUrl.pathname;
30
+ const language = this.getLanguage(req);
31
+ const hostname = this.getHostHeader(req) || this.defaultHostname;
32
+ const startTimestamp = Date.now();
33
+ core_1.debug.multisite('multisite middleware start: %o', {
34
+ pathname,
35
+ language,
36
+ hostname,
37
+ });
38
+ if (this.disabled(req, res)) {
39
+ core_1.debug.multisite('skipped (multisite middleware is disabled)');
40
+ return res;
41
+ }
42
+ if (this.isPreview(req)) {
43
+ core_1.debug.multisite('skipped (preview)');
44
+ return res;
45
+ }
46
+ // Site name can be forced by query string parameter or cookie
47
+ const siteName = req.nextUrl.searchParams.get(this.SITE_SYMBOL) ||
48
+ (this.config.useCookieResolution &&
49
+ this.config.useCookieResolution(req) &&
50
+ ((_a = req.cookies.get(this.SITE_SYMBOL)) === null || _a === void 0 ? void 0 : _a.value)) ||
51
+ this.config.siteResolver.getByHost(hostname).name;
52
+ // Rewrite to site specific path
53
+ const rewritePath = (0, site_1.getSiteRewrite)(pathname, {
54
+ siteName,
55
+ });
56
+ const response = this.rewrite(rewritePath, req, res);
57
+ // default site cookie attributes
58
+ const defaultCookieAttributes = {
59
+ secure: true,
60
+ httpOnly: true,
61
+ sameSite: 'none',
62
+ };
63
+ // Share site name with the following executed middlewares
64
+ response.cookies.set(this.SITE_SYMBOL, siteName, defaultCookieAttributes);
65
+ core_1.debug.multisite('multisite middleware end in %dms: %o', Date.now() - startTimestamp, {
66
+ rewritePath,
67
+ siteName,
68
+ headers: this.extractDebugHeaders(response.headers),
69
+ cookies: response.cookies,
70
+ });
71
+ return response;
80
72
  }
81
73
  catch (error) {
82
74
  console.log('Multisite middleware failed:');
83
75
  console.log(error);
84
- return res || server_1.NextResponse.next();
76
+ return res;
85
77
  }
86
78
  });
87
79
  }
88
- excludeRoute(pathname) {
80
+ disabled(req, res) {
89
81
  // ignore files
90
- return pathname.includes('.') || super.excludeRoute(pathname);
82
+ return req.nextUrl.pathname.includes('.') || super.disabled(req, res);
91
83
  }
92
84
  }
93
85
  exports.MultisiteMiddleware = MultisiteMiddleware;
@@ -10,12 +10,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.PersonalizeMiddleware = void 0;
13
- const server_1 = require("next/server");
14
13
  const personalize_1 = require("@sitecore-content-sdk/core/personalize");
15
14
  const core_1 = require("@sitecore-content-sdk/core");
16
15
  const middleware_1 = require("./middleware");
17
- const server_2 = require("@sitecore-cloudsdk/core/server");
18
- const server_3 = require("@sitecore-cloudsdk/personalize/server");
16
+ const server_1 = require("@sitecore-cloudsdk/core/server");
17
+ const server_2 = require("@sitecore-cloudsdk/personalize/server");
19
18
  /**
20
19
  * Middleware / handler to support Sitecore Personalize
21
20
  */
@@ -26,118 +25,107 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
26
25
  constructor(config) {
27
26
  super(config);
28
27
  this.config = config;
29
- this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
30
- const pathname = req.nextUrl.pathname;
31
- const language = this.getLanguage(req);
32
- const hostname = this.getHostHeader(req) || this.defaultHostname;
33
- const startTimestamp = Date.now();
34
- const timeout = this.config.cdpConfig.timeout;
35
- // Response will be provided if other middleware is run before us (e.g. redirects)
36
- let response = res || server_1.NextResponse.next();
37
- core_1.debug.personalize('personalize middleware start: %o', {
38
- pathname,
39
- language,
40
- hostname,
41
- headers: this.extractDebugHeaders(req.headers),
42
- });
43
- if (this.config.disabled && this.config.disabled(req, response)) {
44
- core_1.debug.personalize('skipped (personalize middleware is disabled)');
45
- return response;
46
- }
47
- if (response.redirected || // Don't attempt to personalize a redirect
48
- this.isPreview(req) || // No need to personalize for preview (layout data is already prepared for preview)
49
- this.excludeRoute(pathname)) {
50
- core_1.debug.personalize('skipped (%s)', response.redirected ? 'redirected' : this.isPreview(req) ? 'preview' : 'route excluded');
51
- return response;
52
- }
53
- const site = this.getSite(req, response);
54
- // Get personalization info from Experience Edge
55
- const personalizeInfo = yield this.personalizeService.getPersonalizeInfo(pathname, language, site.name);
56
- if (!personalizeInfo) {
57
- // Likely an invalid route / language
58
- core_1.debug.personalize('skipped (personalize info not found)');
59
- return response;
60
- }
61
- if (personalizeInfo.variantIds.length === 0) {
62
- core_1.debug.personalize('skipped (no personalization configured)');
63
- return response;
64
- }
65
- if (this.isPrefetch(req)) {
66
- core_1.debug.personalize('skipped (prefetch)');
67
- // Personalized, but this is a prefetch request.
68
- // In this case, don't execute a personalize request; otherwise, the metrics for component A/B experiments would be inaccurate.
69
- // Disable preflight caching to force revalidation on client-side navigation (personalization WILL be influenced).
70
- // Note the reason we don't move this any earlier in the middleware is that we would then be sacrificing performance for non-personalized pages.
71
- response.headers.set('x-middleware-cache', 'no-cache');
72
- return response;
73
- }
74
- yield this.initPersonalizeServer({
75
- hostname,
76
- siteName: site.name,
77
- request: req,
78
- response,
79
- });
80
- const params = this.getExperienceParams(req);
81
- const executions = this.getPersonalizeExecutions(personalizeInfo, language);
82
- const identifiedVariantIds = [];
83
- yield Promise.all(executions.map((execution) => this.personalize({
84
- friendlyId: execution.friendlyId,
85
- variantIds: execution.variantIds,
86
- params,
87
- language,
88
- timeout,
89
- }, req).then((personalization) => {
90
- const variantId = personalization.variantId;
91
- if (variantId) {
92
- if (!execution.variantIds.includes(variantId)) {
93
- core_1.debug.personalize('invalid variant %s', variantId);
94
- }
95
- else {
96
- identifiedVariantIds.push(variantId);
28
+ this.handle = (req, res) => __awaiter(this, void 0, void 0, function* () {
29
+ try {
30
+ const pathname = req.nextUrl.pathname;
31
+ const language = this.getLanguage(req);
32
+ const hostname = this.getHostHeader(req) || this.defaultHostname;
33
+ const startTimestamp = Date.now();
34
+ const timeout = this.config.cdpConfig.timeout;
35
+ core_1.debug.personalize('personalize middleware start: %o', {
36
+ pathname,
37
+ language,
38
+ hostname,
39
+ headers: this.extractDebugHeaders(req.headers),
40
+ });
41
+ if (this.disabled(req, res)) {
42
+ core_1.debug.personalize('skipped (personalize middleware is disabled)');
43
+ return res;
44
+ }
45
+ if (res.redirected || // Don't attempt to personalize a redirect
46
+ this.isPreview(req) // No need to personalize for preview (layout data is already prepared for preview)
47
+ ) {
48
+ core_1.debug.personalize('skipped (%s)', res.redirected ? 'redirected' : 'preview');
49
+ return res;
50
+ }
51
+ const site = this.getSite(req, res);
52
+ // Get personalization info from Experience Edge
53
+ const personalizeInfo = yield this.personalizeService.getPersonalizeInfo(pathname, language, site.name);
54
+ if (!personalizeInfo) {
55
+ // Likely an invalid route / language
56
+ core_1.debug.personalize('skipped (personalize info not found)');
57
+ return res;
58
+ }
59
+ if (personalizeInfo.variantIds.length === 0) {
60
+ core_1.debug.personalize('skipped (no personalization configured)');
61
+ return res;
62
+ }
63
+ if (this.isPrefetch(req)) {
64
+ core_1.debug.personalize('skipped (prefetch)');
65
+ // Personalized, but this is a prefetch request.
66
+ // In this case, don't execute a personalize request; otherwise, the metrics for component A/B experiments would be inaccurate.
67
+ // Disable preflight caching to force revalidation on client-side navigation (personalization WILL be influenced).
68
+ // Note the reason we don't move this any earlier in the middleware is that we would then be sacrificing performance for non-personalized pages.
69
+ res.headers.set('x-middleware-cache', 'no-cache');
70
+ return res;
71
+ }
72
+ yield this.initPersonalizeServer({
73
+ hostname,
74
+ siteName: site.name,
75
+ request: req,
76
+ response: res,
77
+ });
78
+ const params = this.getExperienceParams(req);
79
+ const executions = this.getPersonalizeExecutions(personalizeInfo, language);
80
+ const identifiedVariantIds = [];
81
+ yield Promise.all(executions.map((execution) => this.personalize({
82
+ friendlyId: execution.friendlyId,
83
+ variantIds: execution.variantIds,
84
+ params,
85
+ language,
86
+ timeout,
87
+ }, req).then((personalization) => {
88
+ const variantId = personalization.variantId;
89
+ if (variantId) {
90
+ if (!execution.variantIds.includes(variantId)) {
91
+ core_1.debug.personalize('invalid variant %s', variantId);
92
+ }
93
+ else {
94
+ identifiedVariantIds.push(variantId);
95
+ }
97
96
  }
97
+ })));
98
+ if (identifiedVariantIds.length === 0) {
99
+ core_1.debug.personalize('skipped (no variant(s) identified)');
100
+ return res;
98
101
  }
99
- })));
100
- if (identifiedVariantIds.length === 0) {
101
- core_1.debug.personalize('skipped (no variant(s) identified)');
102
+ // Path can be rewritten by previously executed middleware
103
+ const basePath = (res === null || res === void 0 ? void 0 : res.headers.get('x-sc-rewrite')) || pathname;
104
+ // Rewrite to persononalized path
105
+ const rewritePath = (0, personalize_1.getPersonalizedRewrite)(basePath, identifiedVariantIds);
106
+ const response = this.rewrite(rewritePath, req, res);
107
+ // Disable preflight caching to force revalidation on client-side navigation (personalization MAY be influenced).
108
+ // See https://github.com/vercel/next.js/pull/32767
109
+ response.headers.set('x-middleware-cache', 'no-cache');
110
+ core_1.debug.personalize('personalize middleware end in %dms: %o', Date.now() - startTimestamp, {
111
+ rewritePath,
112
+ headers: this.extractDebugHeaders(response.headers),
113
+ });
102
114
  return response;
103
115
  }
104
- // Path can be rewritten by previously executed middleware
105
- const basePath = (res === null || res === void 0 ? void 0 : res.headers.get('x-sc-rewrite')) || pathname;
106
- // Rewrite to persononalized path
107
- const rewritePath = (0, personalize_1.getPersonalizedRewrite)(basePath, identifiedVariantIds);
108
- response = this.rewrite(rewritePath, req, response);
109
- // Disable preflight caching to force revalidation on client-side navigation (personalization MAY be influenced).
110
- // See https://github.com/vercel/next.js/pull/32767
111
- response.headers.set('x-middleware-cache', 'no-cache');
112
- core_1.debug.personalize('personalize middleware end in %dms: %o', Date.now() - startTimestamp, {
113
- rewritePath,
114
- headers: this.extractDebugHeaders(response.headers),
115
- });
116
- return response;
117
- });
118
- // NOTE: we provide native fetch for compatibility on Next.js Edge Runtime
119
- // (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
120
- this.personalizeService = new personalize_1.GraphQLPersonalizeService(Object.assign(Object.assign({}, config.edgeConfig), { fetch: fetch }));
121
- }
122
- /**
123
- * Gets the Next.js middleware handler with error handling
124
- * @returns middleware handler
125
- */
126
- getHandler() {
127
- return (req, res) => __awaiter(this, void 0, void 0, function* () {
128
- try {
129
- return yield this.handler(req, res);
130
- }
131
116
  catch (error) {
132
117
  console.log('Personalize middleware failed:');
133
118
  console.log(error);
134
- return res || server_1.NextResponse.next();
119
+ return res;
135
120
  }
136
121
  });
122
+ // NOTE: we provide native fetch for compatibility on Next.js Edge Runtime
123
+ // (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
124
+ this.personalizeService = new personalize_1.GraphQLPersonalizeService(Object.assign(Object.assign({}, config.edgeConfig), { fetch: fetch }));
137
125
  }
138
126
  initPersonalizeServer(_a) {
139
127
  return __awaiter(this, arguments, void 0, function* ({ hostname, siteName, request, response, }) {
140
- yield (0, server_2.CloudSDK)(request, response, {
128
+ yield (0, server_1.CloudSDK)(request, response, {
141
129
  sitecoreEdgeUrl: this.config.cdpConfig.sitecoreEdgeUrl,
142
130
  sitecoreEdgeContextId: this.config.cdpConfig.sitecoreEdgeContextId,
143
131
  siteName,
@@ -152,7 +140,7 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
152
140
  return __awaiter(this, arguments, void 0, function* ({ params, friendlyId, language, timeout, variantIds, }, request) {
153
141
  var _b;
154
142
  core_1.debug.personalize('executing experience for %s %o', friendlyId, params);
155
- return (yield (0, server_3.personalize)(request, {
143
+ return (yield (0, server_2.personalize)(request, {
156
144
  channel: this.config.cdpConfig.channel || 'WEB',
157
145
  currency: (_b = this.config.cdpConfig.currency) !== null && _b !== void 0 ? _b : 'USD',
158
146
  friendlyId,
@@ -177,9 +165,9 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
177
165
  utm: utm,
178
166
  };
179
167
  }
180
- excludeRoute(pathname) {
168
+ disabled(req, res) {
181
169
  // ignore files
182
- return pathname.includes('.') || super.excludeRoute(pathname);
170
+ return req.nextUrl.pathname.includes('.') || super.disabled(req, res);
183
171
  }
184
172
  /**
185
173
  * Aggregates personalize executions based on the provided route personalize information and language