@sitecore-jss/sitecore-jss-nextjs 22.2.0-canary.6 → 22.2.0-canary.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/NextImage.js +6 -1
- package/dist/cjs/editing/constants.js +1 -6
- package/dist/cjs/editing/editing-config-middleware.js +3 -3
- package/dist/cjs/editing/editing-data-middleware.js +3 -3
- package/dist/cjs/editing/editing-data-service.js +2 -2
- package/dist/cjs/editing/editing-render-middleware.js +5 -5
- package/dist/cjs/editing/feaas-render-middleware.js +3 -3
- package/dist/cjs/middleware/redirects-middleware.js +90 -30
- package/dist/esm/components/NextImage.js +8 -3
- package/dist/esm/editing/constants.js +0 -5
- package/dist/esm/editing/editing-config-middleware.js +1 -1
- package/dist/esm/editing/editing-data-middleware.js +1 -1
- package/dist/esm/editing/editing-data-service.js +1 -1
- package/dist/esm/editing/editing-render-middleware.js +2 -2
- package/dist/esm/editing/feaas-render-middleware.js +1 -1
- package/dist/esm/middleware/redirects-middleware.js +90 -30
- package/package.json +7 -7
- package/types/editing/constants.d.ts +0 -5
- package/types/editing/editing-render-middleware.d.ts +3 -15
- package/types/middleware/redirects-middleware.d.ts +18 -1
|
@@ -24,7 +24,9 @@ const sitecore_jss_react_2 = require("@sitecore-jss/sitecore-jss-react");
|
|
|
24
24
|
const sitecore_jss_react_3 = require("@sitecore-jss/sitecore-jss-react");
|
|
25
25
|
const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
|
|
26
26
|
exports.NextImage = (0, sitecore_jss_react_1.withFieldMetadata)((0, sitecore_jss_react_2.withEmptyFieldEditingComponent)((_a) => {
|
|
27
|
+
var _b;
|
|
27
28
|
var { editable = true, imageParams, field, mediaUrlPrefix, fill, priority } = _a, otherProps = __rest(_a, ["editable", "imageParams", "field", "mediaUrlPrefix", "fill", "priority"]);
|
|
29
|
+
const sitecoreContext = react_1.default.useContext(sitecore_jss_react_1.SitecoreContextReactContext);
|
|
28
30
|
// next handles src and we use a custom loader,
|
|
29
31
|
// throw error if these are present
|
|
30
32
|
if (otherProps.src) {
|
|
@@ -46,8 +48,11 @@ exports.NextImage = (0, sitecore_jss_react_1.withFieldMetadata)((0, sitecore_jss
|
|
|
46
48
|
if (!img) {
|
|
47
49
|
return null;
|
|
48
50
|
}
|
|
51
|
+
// disable image optimization for Edit and Preview, but preserve original value if true
|
|
52
|
+
const unoptimized = otherProps.unoptimized ||
|
|
53
|
+
((_b = sitecoreContext.context) === null || _b === void 0 ? void 0 : _b.pageState) !== layout_1.LayoutServicePageState.Normal;
|
|
49
54
|
const attrs = Object.assign(Object.assign(Object.assign({}, img), otherProps), { fill,
|
|
50
|
-
priority, src: media_1.mediaApi.updateImageUrl(img.src, imageParams, mediaUrlPrefix) });
|
|
55
|
+
priority, src: media_1.mediaApi.updateImageUrl(img.src, imageParams, mediaUrlPrefix), unoptimized });
|
|
51
56
|
const imageProps = Object.assign(Object.assign({}, attrs), {
|
|
52
57
|
// force replace /media with /jssmedia in src since we _know_ we will be adding a 'mw' query string parameter
|
|
53
58
|
// this is required for Sitecore media API resizing to work properly
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.QUERY_PARAM_EDITING_SECRET = 'secret';
|
|
3
|
+
exports.EDITING_PASS_THROUGH_HEADERS = exports.QUERY_PARAM_VERCEL_SET_BYPASS_COOKIE = exports.QUERY_PARAM_VERCEL_PROTECTION_BYPASS = void 0;
|
|
5
4
|
exports.QUERY_PARAM_VERCEL_PROTECTION_BYPASS = 'x-vercel-protection-bypass';
|
|
6
5
|
exports.QUERY_PARAM_VERCEL_SET_BYPASS_COOKIE = 'x-vercel-set-bypass-cookie';
|
|
7
6
|
/**
|
|
@@ -9,7 +8,3 @@ exports.QUERY_PARAM_VERCEL_SET_BYPASS_COOKIE = 'x-vercel-set-bypass-cookie';
|
|
|
9
8
|
* Note these are in lowercase format to match expected `IncomingHttpHeaders`.
|
|
10
9
|
*/
|
|
11
10
|
exports.EDITING_PASS_THROUGH_HEADERS = ['authorization', 'cookie'];
|
|
12
|
-
/**
|
|
13
|
-
* Default allowed origins for editing requests. This is used to enforce CORS, CSP headers.
|
|
14
|
-
*/
|
|
15
|
-
exports.EDITING_ALLOWED_ORIGINS = ['https://pages*.cloud', 'https://pages.sitecorecloud.io'];
|
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.EditingConfigMiddleware = void 0;
|
|
13
|
-
const
|
|
13
|
+
const editing_1 = require("@sitecore-jss/sitecore-jss/editing");
|
|
14
14
|
const utils_1 = require("../utils/utils");
|
|
15
15
|
const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
|
|
16
16
|
const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
|
|
@@ -26,8 +26,8 @@ class EditingConfigMiddleware {
|
|
|
26
26
|
constructor(config) {
|
|
27
27
|
this.config = config;
|
|
28
28
|
this.handler = (_req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
29
|
-
const secret = _req.query[
|
|
30
|
-
if (!(0, utils_2.enforceCors)(_req, res,
|
|
29
|
+
const secret = _req.query[editing_1.QUERY_PARAM_EDITING_SECRET];
|
|
30
|
+
if (!(0, utils_2.enforceCors)(_req, res, editing_1.EDITING_ALLOWED_ORIGINS)) {
|
|
31
31
|
sitecore_jss_1.debug.editing('invalid origin host - set allowed origins in JSS_ALLOWED_ORIGINS environment variable');
|
|
32
32
|
return res.status(401).json({ message: 'Invalid origin' });
|
|
33
33
|
}
|
|
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.EditingDataMiddleware = void 0;
|
|
13
13
|
const editing_data_cache_1 = require("./editing-data-cache");
|
|
14
14
|
const editing_data_1 = require("./editing-data");
|
|
15
|
-
const
|
|
15
|
+
const editing_1 = require("@sitecore-jss/sitecore-jss/editing");
|
|
16
16
|
const utils_1 = require("../utils/utils");
|
|
17
17
|
const utils_2 = require("@sitecore-jss/sitecore-jss/utils");
|
|
18
18
|
const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
|
|
@@ -28,9 +28,9 @@ class EditingDataMiddleware {
|
|
|
28
28
|
var _a, _b;
|
|
29
29
|
this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
30
30
|
const { method, query, body } = req;
|
|
31
|
-
const secret = query[
|
|
31
|
+
const secret = query[editing_1.QUERY_PARAM_EDITING_SECRET];
|
|
32
32
|
const key = query[this.queryParamKey];
|
|
33
|
-
if (!(0, utils_2.enforceCors)(req, res,
|
|
33
|
+
if (!(0, utils_2.enforceCors)(req, res, editing_1.EDITING_ALLOWED_ORIGINS)) {
|
|
34
34
|
sitecore_jss_1.debug.editing('invalid origin host - set allowed origins in JSS_ALLOWED_ORIGINS environment variable');
|
|
35
35
|
return res.status(401).json({ message: 'Invalid origin' });
|
|
36
36
|
}
|
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.editingDataService = exports.ServerlessEditingDataService = exports.BasicEditingDataService = exports.generateKey = void 0;
|
|
13
|
-
const
|
|
13
|
+
const editing_1 = require("@sitecore-jss/sitecore-jss/editing");
|
|
14
14
|
const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
|
|
15
15
|
const editing_data_cache_1 = require("./editing-data-cache");
|
|
16
16
|
const utils_1 = require("../utils/utils");
|
|
@@ -137,7 +137,7 @@ class ServerlessEditingDataService {
|
|
|
137
137
|
// http://localhost:3000/api/editing/data/52961eea-bafd-5287-a532-a72e36bd8a36-qkb4e3fv5x?secret=1234secret
|
|
138
138
|
const apiRoute = (_a = this.apiRoute) === null || _a === void 0 ? void 0 : _a.replace('[key]', key);
|
|
139
139
|
const url = new URL(apiRoute, serverUrl);
|
|
140
|
-
url.searchParams.append(
|
|
140
|
+
url.searchParams.append(editing_1.QUERY_PARAM_EDITING_SECRET, (0, utils_1.getJssEditingSecret)());
|
|
141
141
|
if (params) {
|
|
142
142
|
for (const key in params) {
|
|
143
143
|
if ({}.hasOwnProperty.call(params, key)) {
|
|
@@ -13,8 +13,8 @@ exports.EditingRenderMiddleware = exports.MetadataHandler = exports.isEditingMet
|
|
|
13
13
|
const constants_1 = require("next/constants");
|
|
14
14
|
const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
|
|
15
15
|
const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
|
|
16
|
+
const editing_1 = require("@sitecore-jss/sitecore-jss/editing");
|
|
16
17
|
const editing_data_service_1 = require("./editing-data-service");
|
|
17
|
-
const constants_2 = require("./constants");
|
|
18
18
|
const utils_1 = require("../utils/utils");
|
|
19
19
|
const render_middleware_1 = require("./render-middleware");
|
|
20
20
|
const utils_2 = require("@sitecore-jss/sitecore-jss/utils");
|
|
@@ -221,10 +221,10 @@ class MetadataHandler {
|
|
|
221
221
|
version: query.sc_version,
|
|
222
222
|
editMode: layout_1.EditMode.Metadata,
|
|
223
223
|
pageState: query.mode,
|
|
224
|
+
layoutKind: query.sc_layoutKind,
|
|
224
225
|
},
|
|
225
226
|
// Cache the preview data for 3 seconds to ensure the page is rendered with the correct preview data not the cached one
|
|
226
227
|
{
|
|
227
|
-
path: query.route,
|
|
228
228
|
maxAge: 3,
|
|
229
229
|
});
|
|
230
230
|
// Cookies with the SameSite=Lax policy set by Next.js setPreviewData function causes CORS issue
|
|
@@ -265,7 +265,7 @@ class MetadataHandler {
|
|
|
265
265
|
* @returns Content-Security-Policy header value
|
|
266
266
|
*/
|
|
267
267
|
getSCPHeader() {
|
|
268
|
-
return `frame-ancestors 'self' ${[(0, utils_2.getAllowedOriginsFromEnv)(), ...
|
|
268
|
+
return `frame-ancestors 'self' ${[(0, utils_2.getAllowedOriginsFromEnv)(), ...editing_1.EDITING_ALLOWED_ORIGINS].join(' ')}`;
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
exports.MetadataHandler = MetadataHandler;
|
|
@@ -289,14 +289,14 @@ class EditingRenderMiddleware extends render_middleware_1.RenderMiddlewareBase {
|
|
|
289
289
|
headers,
|
|
290
290
|
body,
|
|
291
291
|
});
|
|
292
|
-
if (!(0, utils_2.enforceCors)(req, res,
|
|
292
|
+
if (!(0, utils_2.enforceCors)(req, res, editing_1.EDITING_ALLOWED_ORIGINS)) {
|
|
293
293
|
sitecore_jss_1.debug.editing('invalid origin host - set allowed origins in JSS_ALLOWED_ORIGINS environment variable');
|
|
294
294
|
return res.status(401).json({
|
|
295
295
|
html: `<html><body>Requests from origin ${(_a = req.headers) === null || _a === void 0 ? void 0 : _a.origin} not allowed</body></html>`,
|
|
296
296
|
});
|
|
297
297
|
}
|
|
298
298
|
// Validate secret
|
|
299
|
-
const secret = (_b = query[
|
|
299
|
+
const secret = (_b = query[editing_1.QUERY_PARAM_EDITING_SECRET]) !== null && _b !== void 0 ? _b : body === null || body === void 0 ? void 0 : body.jssEditingSecret;
|
|
300
300
|
if (secret !== (0, utils_1.getJssEditingSecret)()) {
|
|
301
301
|
sitecore_jss_1.debug.editing('invalid editing secret - sent "%s" expected "%s"', secret, (0, utils_1.getJssEditingSecret)());
|
|
302
302
|
return res.status(401).json({
|
|
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.FEAASRenderMiddleware = void 0;
|
|
13
13
|
const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
|
|
14
|
-
const
|
|
14
|
+
const editing_1 = require("@sitecore-jss/sitecore-jss/editing");
|
|
15
15
|
const utils_1 = require("../utils/utils");
|
|
16
16
|
const render_middleware_1 = require("./render-middleware");
|
|
17
17
|
const utils_2 = require("@sitecore-jss/sitecore-jss/utils");
|
|
@@ -37,7 +37,7 @@ class FEAASRenderMiddleware extends render_middleware_1.RenderMiddlewareBase {
|
|
|
37
37
|
query,
|
|
38
38
|
headers,
|
|
39
39
|
});
|
|
40
|
-
if (!(0, utils_2.enforceCors)(req, res,
|
|
40
|
+
if (!(0, utils_2.enforceCors)(req, res, editing_1.EDITING_ALLOWED_ORIGINS)) {
|
|
41
41
|
sitecore_jss_1.debug.editing('invalid origin host - set allowed origins in JSS_ALLOWED_ORIGINS environment variable');
|
|
42
42
|
return res
|
|
43
43
|
.status(401)
|
|
@@ -49,7 +49,7 @@ class FEAASRenderMiddleware extends render_middleware_1.RenderMiddlewareBase {
|
|
|
49
49
|
return res.status(405).send(`<html><body>Invalid request method '${method}'</body></html>`);
|
|
50
50
|
}
|
|
51
51
|
// Validate secret
|
|
52
|
-
const secret = query[
|
|
52
|
+
const secret = query[editing_1.QUERY_PARAM_EDITING_SECRET];
|
|
53
53
|
if (secret !== (0, utils_1.getJssEditingSecret)()) {
|
|
54
54
|
sitecore_jss_1.debug.editing('invalid editing secret - sent "%s" expected "%s"', secret, (0, utils_1.getJssEditingSecret)());
|
|
55
55
|
return res.status(401).send('<html><body>Missing or invalid secret</body></html>');
|
|
@@ -13,10 +13,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.RedirectsMiddleware = void 0;
|
|
16
|
-
const regex_parser_1 = __importDefault(require("regex-parser"));
|
|
17
|
-
const server_1 = require("next/server");
|
|
18
|
-
const site_1 = require("@sitecore-jss/sitecore-jss/site");
|
|
19
16
|
const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
|
|
17
|
+
const site_1 = require("@sitecore-jss/sitecore-jss/site");
|
|
18
|
+
const server_1 = require("next/server");
|
|
19
|
+
const regex_parser_1 = __importDefault(require("regex-parser"));
|
|
20
20
|
const middleware_1 = require("./middleware");
|
|
21
21
|
const REGEXP_CONTEXT_SITE_LANG = new RegExp(/\$siteLang/, 'i');
|
|
22
22
|
const REGEXP_ABSOLUTE_URL = new RegExp('^(?:[a-z]+:)?//', 'i');
|
|
@@ -43,6 +43,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
43
43
|
hostname,
|
|
44
44
|
});
|
|
45
45
|
const createResponse = () => __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
var _a;
|
|
46
47
|
if (this.config.disabled && this.config.disabled(req, res || server_1.NextResponse.next())) {
|
|
47
48
|
sitecore_jss_1.debug.redirects('skipped (redirects middleware is disabled)');
|
|
48
49
|
return res || server_1.NextResponse.next();
|
|
@@ -64,47 +65,46 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
64
65
|
existsRedirect.target.includes(hostname))) {
|
|
65
66
|
existsRedirect.target = existsRedirect.target.replace(REGEXP_CONTEXT_SITE_LANG, site.language);
|
|
66
67
|
}
|
|
67
|
-
const url = req.nextUrl.clone();
|
|
68
|
+
const url = this.normalizeUrl(req.nextUrl.clone());
|
|
68
69
|
if (REGEXP_ABSOLUTE_URL.test(existsRedirect.target)) {
|
|
69
70
|
url.href = existsRedirect.target;
|
|
70
71
|
}
|
|
71
72
|
else {
|
|
72
|
-
const source = `${url.pathname}${url.search}`;
|
|
73
|
-
url.search = existsRedirect.isQueryStringPreserved ? url.search : '';
|
|
73
|
+
const source = `${url.pathname.replace(/\/*$/gi, '')}${url.search}`;
|
|
74
74
|
const urlFirstPart = existsRedirect.target.split('/')[1];
|
|
75
75
|
if (this.locales.includes(urlFirstPart)) {
|
|
76
|
-
|
|
76
|
+
req.nextUrl.locale = urlFirstPart;
|
|
77
77
|
existsRedirect.target = existsRedirect.target.replace(`/${urlFirstPart}`, '');
|
|
78
78
|
}
|
|
79
79
|
const target = source
|
|
80
80
|
.replace((0, regex_parser_1.default)(existsRedirect.pattern), existsRedirect.target)
|
|
81
81
|
.replace(/^\/\//, '/')
|
|
82
82
|
.split('?');
|
|
83
|
-
url.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
if (url.search && existsRedirect.isQueryStringPreserved) {
|
|
84
|
+
const targetQueryString = (_a = target[1]) !== null && _a !== void 0 ? _a : '';
|
|
85
|
+
url.search = '?' + new URLSearchParams(`${url.search}&${targetQueryString}`).toString();
|
|
86
|
+
}
|
|
87
|
+
else if (target[1]) {
|
|
88
|
+
url.search = '?' + target[1];
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
url.search = '';
|
|
89
92
|
}
|
|
93
|
+
const prepareNewURL = new URL(`${target[0]}${url.search}`, url.origin);
|
|
94
|
+
url.href = prepareNewURL.href;
|
|
90
95
|
}
|
|
91
96
|
const redirectUrl = decodeURIComponent(url.href);
|
|
92
97
|
/** return Response redirect with http code of redirect type **/
|
|
93
98
|
switch (existsRedirect.redirectType) {
|
|
94
|
-
case site_1.REDIRECT_TYPE_301:
|
|
95
|
-
return
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
case site_1.
|
|
101
|
-
return server_1.NextResponse.
|
|
102
|
-
|
|
103
|
-
statusText: 'Found',
|
|
104
|
-
headers: res === null || res === void 0 ? void 0 : res.headers,
|
|
105
|
-
});
|
|
106
|
-
case site_1.REDIRECT_TYPE_SERVER_TRANSFER:
|
|
107
|
-
return server_1.NextResponse.rewrite(redirectUrl, res);
|
|
99
|
+
case site_1.REDIRECT_TYPE_301: {
|
|
100
|
+
return this.createRedirectResponse(redirectUrl, res, 301, 'Moved Permanently');
|
|
101
|
+
}
|
|
102
|
+
case site_1.REDIRECT_TYPE_302: {
|
|
103
|
+
return this.createRedirectResponse(redirectUrl, res, 302, 'Found');
|
|
104
|
+
}
|
|
105
|
+
case site_1.REDIRECT_TYPE_SERVER_TRANSFER: {
|
|
106
|
+
return this.rewrite(redirectUrl, req, res || server_1.NextResponse.next());
|
|
107
|
+
}
|
|
108
108
|
default:
|
|
109
109
|
return res || server_1.NextResponse.next();
|
|
110
110
|
}
|
|
@@ -149,8 +149,9 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
149
149
|
getExistsRedirect(req, siteName) {
|
|
150
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
151
151
|
const redirects = yield this.redirectsService.fetchRedirects(siteName);
|
|
152
|
-
const
|
|
153
|
-
const
|
|
152
|
+
const normalizedUrl = this.normalizeUrl(req.nextUrl.clone());
|
|
153
|
+
const tragetURL = normalizedUrl.pathname;
|
|
154
|
+
const targetQS = normalizedUrl.search || '';
|
|
154
155
|
const language = this.getLanguage(req);
|
|
155
156
|
const modifyRedirects = structuredClone(redirects);
|
|
156
157
|
return modifyRedirects.length
|
|
@@ -163,7 +164,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
163
164
|
.replace(/(?<!\\)\?/g, '\\?')
|
|
164
165
|
.replace(/\$\/gi$/g, '')}[\/]?$/gi`;
|
|
165
166
|
return (((0, regex_parser_1.default)(redirect.pattern).test(tragetURL) ||
|
|
166
|
-
(0, regex_parser_1.default)(redirect.pattern).test(`${tragetURL}${targetQS}`) ||
|
|
167
|
+
(0, regex_parser_1.default)(redirect.pattern).test(`${tragetURL.replace(/\/*$/gi, '')}${targetQS}`) ||
|
|
167
168
|
(0, regex_parser_1.default)(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}`) ||
|
|
168
169
|
(0, regex_parser_1.default)(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}${targetQS}`)) &&
|
|
169
170
|
(redirect.locale
|
|
@@ -173,5 +174,64 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
173
174
|
: undefined;
|
|
174
175
|
});
|
|
175
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* When a user clicks on a link generated by the Link component from next/link,
|
|
179
|
+
* Next.js adds special parameters in the route called path.
|
|
180
|
+
* This method removes these special parameters.
|
|
181
|
+
* @param {URL} url
|
|
182
|
+
* @returns {string} normalize url
|
|
183
|
+
*/
|
|
184
|
+
normalizeUrl(url) {
|
|
185
|
+
if (!url.search) {
|
|
186
|
+
return url;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Prepare special parameters for exclusion.
|
|
190
|
+
*/
|
|
191
|
+
const splittedPathname = url.pathname
|
|
192
|
+
.split('/')
|
|
193
|
+
.filter((route) => route)
|
|
194
|
+
.map((route) => `path=${route}`);
|
|
195
|
+
/**
|
|
196
|
+
* Remove special parameters(Next.JS)
|
|
197
|
+
* Example: /about/contact/us
|
|
198
|
+
* When a user clicks on this link, Next.js should generate a link for the middleware, formatted like this:
|
|
199
|
+
* http://host/about/contact/us?path=about&path=contact&path=us
|
|
200
|
+
*/
|
|
201
|
+
const newQueryString = url.search
|
|
202
|
+
.replace(/^\?/, '')
|
|
203
|
+
.split('&')
|
|
204
|
+
.filter((param) => {
|
|
205
|
+
if (!splittedPathname.includes(param)) {
|
|
206
|
+
return param;
|
|
207
|
+
}
|
|
208
|
+
return false;
|
|
209
|
+
})
|
|
210
|
+
.join('&');
|
|
211
|
+
if (newQueryString) {
|
|
212
|
+
return new URL(`${url.pathname}?${newQueryString}`, url.origin);
|
|
213
|
+
}
|
|
214
|
+
return new URL(`${url.pathname}`, url.origin);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Helper function to create a redirect response and remove the x-middleware-next header.
|
|
218
|
+
* @param {string} url The URL to redirect to.
|
|
219
|
+
* @param {Response} res The response object.
|
|
220
|
+
* @param {number} status The HTTP status code of the redirect.
|
|
221
|
+
* @param {string} statusText The status text of the redirect.
|
|
222
|
+
* @returns {NextResponse<unknown>} The redirect response.
|
|
223
|
+
*/
|
|
224
|
+
createRedirectResponse(url, res, status, statusText) {
|
|
225
|
+
const redirect = server_1.NextResponse.redirect(url, {
|
|
226
|
+
status,
|
|
227
|
+
statusText,
|
|
228
|
+
headers: res === null || res === void 0 ? void 0 : res.headers,
|
|
229
|
+
});
|
|
230
|
+
if (res === null || res === void 0 ? void 0 : res.headers) {
|
|
231
|
+
redirect.headers.delete('x-middleware-next');
|
|
232
|
+
redirect.headers.delete('x-middleware-rewrite');
|
|
233
|
+
}
|
|
234
|
+
return redirect;
|
|
235
|
+
}
|
|
176
236
|
}
|
|
177
237
|
exports.RedirectsMiddleware = RedirectsMiddleware;
|
|
@@ -12,13 +12,15 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { mediaApi } from '@sitecore-jss/sitecore-jss/media';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
14
|
import React from 'react';
|
|
15
|
-
import { getEEMarkup, withFieldMetadata, } from '@sitecore-jss/sitecore-jss-react';
|
|
15
|
+
import { getEEMarkup, withFieldMetadata, SitecoreContextReactContext, } from '@sitecore-jss/sitecore-jss-react';
|
|
16
16
|
import Image from 'next/image';
|
|
17
17
|
import { withEmptyFieldEditingComponent } from '@sitecore-jss/sitecore-jss-react';
|
|
18
18
|
import { DefaultEmptyFieldEditingComponentImage } from '@sitecore-jss/sitecore-jss-react';
|
|
19
|
-
import { isFieldValueEmpty } from '@sitecore-jss/sitecore-jss/layout';
|
|
19
|
+
import { isFieldValueEmpty, LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
|
|
20
20
|
export const NextImage = withFieldMetadata(withEmptyFieldEditingComponent((_a) => {
|
|
21
|
+
var _b;
|
|
21
22
|
var { editable = true, imageParams, field, mediaUrlPrefix, fill, priority } = _a, otherProps = __rest(_a, ["editable", "imageParams", "field", "mediaUrlPrefix", "fill", "priority"]);
|
|
23
|
+
const sitecoreContext = React.useContext(SitecoreContextReactContext);
|
|
22
24
|
// next handles src and we use a custom loader,
|
|
23
25
|
// throw error if these are present
|
|
24
26
|
if (otherProps.src) {
|
|
@@ -40,8 +42,11 @@ export const NextImage = withFieldMetadata(withEmptyFieldEditingComponent((_a) =
|
|
|
40
42
|
if (!img) {
|
|
41
43
|
return null;
|
|
42
44
|
}
|
|
45
|
+
// disable image optimization for Edit and Preview, but preserve original value if true
|
|
46
|
+
const unoptimized = otherProps.unoptimized ||
|
|
47
|
+
((_b = sitecoreContext.context) === null || _b === void 0 ? void 0 : _b.pageState) !== LayoutServicePageState.Normal;
|
|
43
48
|
const attrs = Object.assign(Object.assign(Object.assign({}, img), otherProps), { fill,
|
|
44
|
-
priority, src: mediaApi.updateImageUrl(img.src, imageParams, mediaUrlPrefix) });
|
|
49
|
+
priority, src: mediaApi.updateImageUrl(img.src, imageParams, mediaUrlPrefix), unoptimized });
|
|
45
50
|
const imageProps = Object.assign(Object.assign({}, attrs), {
|
|
46
51
|
// force replace /media with /jssmedia in src since we _know_ we will be adding a 'mw' query string parameter
|
|
47
52
|
// this is required for Sitecore media API resizing to work properly
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export const QUERY_PARAM_EDITING_SECRET = 'secret';
|
|
2
1
|
export const QUERY_PARAM_VERCEL_PROTECTION_BYPASS = 'x-vercel-protection-bypass';
|
|
3
2
|
export const QUERY_PARAM_VERCEL_SET_BYPASS_COOKIE = 'x-vercel-set-bypass-cookie';
|
|
4
3
|
/**
|
|
@@ -6,7 +5,3 @@ export const QUERY_PARAM_VERCEL_SET_BYPASS_COOKIE = 'x-vercel-set-bypass-cookie'
|
|
|
6
5
|
* Note these are in lowercase format to match expected `IncomingHttpHeaders`.
|
|
7
6
|
*/
|
|
8
7
|
export const EDITING_PASS_THROUGH_HEADERS = ['authorization', 'cookie'];
|
|
9
|
-
/**
|
|
10
|
-
* Default allowed origins for editing requests. This is used to enforce CORS, CSP headers.
|
|
11
|
-
*/
|
|
12
|
-
export const EDITING_ALLOWED_ORIGINS = ['https://pages*.cloud', 'https://pages.sitecorecloud.io'];
|
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET } from '
|
|
10
|
+
import { EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET, } from '@sitecore-jss/sitecore-jss/editing';
|
|
11
11
|
import { getJssEditingSecret } from '../utils/utils';
|
|
12
12
|
import { debug } from '@sitecore-jss/sitecore-jss';
|
|
13
13
|
import { EditMode } from '@sitecore-jss/sitecore-jss/layout';
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { editingDataDiskCache } from './editing-data-cache';
|
|
11
11
|
import { isEditingData } from './editing-data';
|
|
12
|
-
import { EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET } from '
|
|
12
|
+
import { EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET, } from '@sitecore-jss/sitecore-jss/editing';
|
|
13
13
|
import { getJssEditingSecret } from '../utils/utils';
|
|
14
14
|
import { enforceCors } from '@sitecore-jss/sitecore-jss/utils';
|
|
15
15
|
import { debug } from '@sitecore-jss/sitecore-jss';
|
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { QUERY_PARAM_EDITING_SECRET } from '
|
|
10
|
+
import { QUERY_PARAM_EDITING_SECRET } from '@sitecore-jss/sitecore-jss/editing';
|
|
11
11
|
import { AxiosDataFetcher, debug } from '@sitecore-jss/sitecore-jss';
|
|
12
12
|
import { editingDataDiskCache } from './editing-data-cache';
|
|
13
13
|
import { getJssEditingSecret } from '../utils/utils';
|
|
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { STATIC_PROPS_ID, SERVER_PROPS_ID } from 'next/constants';
|
|
11
11
|
import { AxiosDataFetcher, debug } from '@sitecore-jss/sitecore-jss';
|
|
12
12
|
import { EditMode } from '@sitecore-jss/sitecore-jss/layout';
|
|
13
|
+
import { QUERY_PARAM_EDITING_SECRET, EDITING_ALLOWED_ORIGINS, } from '@sitecore-jss/sitecore-jss/editing';
|
|
13
14
|
import { editingDataService } from './editing-data-service';
|
|
14
|
-
import { EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET } from './constants';
|
|
15
15
|
import { getJssEditingSecret } from '../utils/utils';
|
|
16
16
|
import { RenderMiddlewareBase } from './render-middleware';
|
|
17
17
|
import { enforceCors, getAllowedOriginsFromEnv } from '@sitecore-jss/sitecore-jss/utils';
|
|
@@ -216,10 +216,10 @@ export class MetadataHandler {
|
|
|
216
216
|
version: query.sc_version,
|
|
217
217
|
editMode: EditMode.Metadata,
|
|
218
218
|
pageState: query.mode,
|
|
219
|
+
layoutKind: query.sc_layoutKind,
|
|
219
220
|
},
|
|
220
221
|
// Cache the preview data for 3 seconds to ensure the page is rendered with the correct preview data not the cached one
|
|
221
222
|
{
|
|
222
|
-
path: query.route,
|
|
223
223
|
maxAge: 3,
|
|
224
224
|
});
|
|
225
225
|
// Cookies with the SameSite=Lax policy set by Next.js setPreviewData function causes CORS issue
|
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { debug } from '@sitecore-jss/sitecore-jss';
|
|
11
|
-
import { EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET } from '
|
|
11
|
+
import { EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET, } from '@sitecore-jss/sitecore-jss/editing';
|
|
12
12
|
import { getJssEditingSecret } from '../utils/utils';
|
|
13
13
|
import { RenderMiddlewareBase } from './render-middleware';
|
|
14
14
|
import { enforceCors } from '@sitecore-jss/sitecore-jss/utils';
|
|
@@ -7,10 +7,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import regexParser from 'regex-parser';
|
|
11
|
-
import { NextResponse } from 'next/server';
|
|
12
|
-
import { GraphQLRedirectsService, REDIRECT_TYPE_301, REDIRECT_TYPE_302, REDIRECT_TYPE_SERVER_TRANSFER, } from '@sitecore-jss/sitecore-jss/site';
|
|
13
10
|
import { debug } from '@sitecore-jss/sitecore-jss';
|
|
11
|
+
import { GraphQLRedirectsService, REDIRECT_TYPE_301, REDIRECT_TYPE_302, REDIRECT_TYPE_SERVER_TRANSFER, } from '@sitecore-jss/sitecore-jss/site';
|
|
12
|
+
import { NextResponse } from 'next/server';
|
|
13
|
+
import regexParser from 'regex-parser';
|
|
14
14
|
import { MiddlewareBase } from './middleware';
|
|
15
15
|
const REGEXP_CONTEXT_SITE_LANG = new RegExp(/\$siteLang/, 'i');
|
|
16
16
|
const REGEXP_ABSOLUTE_URL = new RegExp('^(?:[a-z]+:)?//', 'i');
|
|
@@ -37,6 +37,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
37
37
|
hostname,
|
|
38
38
|
});
|
|
39
39
|
const createResponse = () => __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
var _a;
|
|
40
41
|
if (this.config.disabled && this.config.disabled(req, res || NextResponse.next())) {
|
|
41
42
|
debug.redirects('skipped (redirects middleware is disabled)');
|
|
42
43
|
return res || NextResponse.next();
|
|
@@ -58,47 +59,46 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
58
59
|
existsRedirect.target.includes(hostname))) {
|
|
59
60
|
existsRedirect.target = existsRedirect.target.replace(REGEXP_CONTEXT_SITE_LANG, site.language);
|
|
60
61
|
}
|
|
61
|
-
const url = req.nextUrl.clone();
|
|
62
|
+
const url = this.normalizeUrl(req.nextUrl.clone());
|
|
62
63
|
if (REGEXP_ABSOLUTE_URL.test(existsRedirect.target)) {
|
|
63
64
|
url.href = existsRedirect.target;
|
|
64
65
|
}
|
|
65
66
|
else {
|
|
66
|
-
const source = `${url.pathname}${url.search}`;
|
|
67
|
-
url.search = existsRedirect.isQueryStringPreserved ? url.search : '';
|
|
67
|
+
const source = `${url.pathname.replace(/\/*$/gi, '')}${url.search}`;
|
|
68
68
|
const urlFirstPart = existsRedirect.target.split('/')[1];
|
|
69
69
|
if (this.locales.includes(urlFirstPart)) {
|
|
70
|
-
|
|
70
|
+
req.nextUrl.locale = urlFirstPart;
|
|
71
71
|
existsRedirect.target = existsRedirect.target.replace(`/${urlFirstPart}`, '');
|
|
72
72
|
}
|
|
73
73
|
const target = source
|
|
74
74
|
.replace(regexParser(existsRedirect.pattern), existsRedirect.target)
|
|
75
75
|
.replace(/^\/\//, '/')
|
|
76
76
|
.split('?');
|
|
77
|
-
url.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
if (url.search && existsRedirect.isQueryStringPreserved) {
|
|
78
|
+
const targetQueryString = (_a = target[1]) !== null && _a !== void 0 ? _a : '';
|
|
79
|
+
url.search = '?' + new URLSearchParams(`${url.search}&${targetQueryString}`).toString();
|
|
80
|
+
}
|
|
81
|
+
else if (target[1]) {
|
|
82
|
+
url.search = '?' + target[1];
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
url.search = '';
|
|
83
86
|
}
|
|
87
|
+
const prepareNewURL = new URL(`${target[0]}${url.search}`, url.origin);
|
|
88
|
+
url.href = prepareNewURL.href;
|
|
84
89
|
}
|
|
85
90
|
const redirectUrl = decodeURIComponent(url.href);
|
|
86
91
|
/** return Response redirect with http code of redirect type **/
|
|
87
92
|
switch (existsRedirect.redirectType) {
|
|
88
|
-
case REDIRECT_TYPE_301:
|
|
89
|
-
return
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
case
|
|
95
|
-
return
|
|
96
|
-
|
|
97
|
-
statusText: 'Found',
|
|
98
|
-
headers: res === null || res === void 0 ? void 0 : res.headers,
|
|
99
|
-
});
|
|
100
|
-
case REDIRECT_TYPE_SERVER_TRANSFER:
|
|
101
|
-
return NextResponse.rewrite(redirectUrl, res);
|
|
93
|
+
case REDIRECT_TYPE_301: {
|
|
94
|
+
return this.createRedirectResponse(redirectUrl, res, 301, 'Moved Permanently');
|
|
95
|
+
}
|
|
96
|
+
case REDIRECT_TYPE_302: {
|
|
97
|
+
return this.createRedirectResponse(redirectUrl, res, 302, 'Found');
|
|
98
|
+
}
|
|
99
|
+
case REDIRECT_TYPE_SERVER_TRANSFER: {
|
|
100
|
+
return this.rewrite(redirectUrl, req, res || NextResponse.next());
|
|
101
|
+
}
|
|
102
102
|
default:
|
|
103
103
|
return res || NextResponse.next();
|
|
104
104
|
}
|
|
@@ -143,8 +143,9 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
143
143
|
getExistsRedirect(req, siteName) {
|
|
144
144
|
return __awaiter(this, void 0, void 0, function* () {
|
|
145
145
|
const redirects = yield this.redirectsService.fetchRedirects(siteName);
|
|
146
|
-
const
|
|
147
|
-
const
|
|
146
|
+
const normalizedUrl = this.normalizeUrl(req.nextUrl.clone());
|
|
147
|
+
const tragetURL = normalizedUrl.pathname;
|
|
148
|
+
const targetQS = normalizedUrl.search || '';
|
|
148
149
|
const language = this.getLanguage(req);
|
|
149
150
|
const modifyRedirects = structuredClone(redirects);
|
|
150
151
|
return modifyRedirects.length
|
|
@@ -157,7 +158,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
157
158
|
.replace(/(?<!\\)\?/g, '\\?')
|
|
158
159
|
.replace(/\$\/gi$/g, '')}[\/]?$/gi`;
|
|
159
160
|
return ((regexParser(redirect.pattern).test(tragetURL) ||
|
|
160
|
-
regexParser(redirect.pattern).test(`${tragetURL}${targetQS}`) ||
|
|
161
|
+
regexParser(redirect.pattern).test(`${tragetURL.replace(/\/*$/gi, '')}${targetQS}`) ||
|
|
161
162
|
regexParser(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}`) ||
|
|
162
163
|
regexParser(redirect.pattern).test(`/${req.nextUrl.locale}${tragetURL}${targetQS}`)) &&
|
|
163
164
|
(redirect.locale
|
|
@@ -167,4 +168,63 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
167
168
|
: undefined;
|
|
168
169
|
});
|
|
169
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* When a user clicks on a link generated by the Link component from next/link,
|
|
173
|
+
* Next.js adds special parameters in the route called path.
|
|
174
|
+
* This method removes these special parameters.
|
|
175
|
+
* @param {URL} url
|
|
176
|
+
* @returns {string} normalize url
|
|
177
|
+
*/
|
|
178
|
+
normalizeUrl(url) {
|
|
179
|
+
if (!url.search) {
|
|
180
|
+
return url;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Prepare special parameters for exclusion.
|
|
184
|
+
*/
|
|
185
|
+
const splittedPathname = url.pathname
|
|
186
|
+
.split('/')
|
|
187
|
+
.filter((route) => route)
|
|
188
|
+
.map((route) => `path=${route}`);
|
|
189
|
+
/**
|
|
190
|
+
* Remove special parameters(Next.JS)
|
|
191
|
+
* Example: /about/contact/us
|
|
192
|
+
* When a user clicks on this link, Next.js should generate a link for the middleware, formatted like this:
|
|
193
|
+
* http://host/about/contact/us?path=about&path=contact&path=us
|
|
194
|
+
*/
|
|
195
|
+
const newQueryString = url.search
|
|
196
|
+
.replace(/^\?/, '')
|
|
197
|
+
.split('&')
|
|
198
|
+
.filter((param) => {
|
|
199
|
+
if (!splittedPathname.includes(param)) {
|
|
200
|
+
return param;
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
})
|
|
204
|
+
.join('&');
|
|
205
|
+
if (newQueryString) {
|
|
206
|
+
return new URL(`${url.pathname}?${newQueryString}`, url.origin);
|
|
207
|
+
}
|
|
208
|
+
return new URL(`${url.pathname}`, url.origin);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Helper function to create a redirect response and remove the x-middleware-next header.
|
|
212
|
+
* @param {string} url The URL to redirect to.
|
|
213
|
+
* @param {Response} res The response object.
|
|
214
|
+
* @param {number} status The HTTP status code of the redirect.
|
|
215
|
+
* @param {string} statusText The status text of the redirect.
|
|
216
|
+
* @returns {NextResponse<unknown>} The redirect response.
|
|
217
|
+
*/
|
|
218
|
+
createRedirectResponse(url, res, status, statusText) {
|
|
219
|
+
const redirect = NextResponse.redirect(url, {
|
|
220
|
+
status,
|
|
221
|
+
statusText,
|
|
222
|
+
headers: res === null || res === void 0 ? void 0 : res.headers,
|
|
223
|
+
});
|
|
224
|
+
if (res === null || res === void 0 ? void 0 : res.headers) {
|
|
225
|
+
redirect.headers.delete('x-middleware-next');
|
|
226
|
+
redirect.headers.delete('x-middleware-rewrite');
|
|
227
|
+
}
|
|
228
|
+
return redirect;
|
|
229
|
+
}
|
|
170
230
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sitecore-jss/sitecore-jss-nextjs",
|
|
3
|
-
"version": "22.2.0-canary.
|
|
3
|
+
"version": "22.2.0-canary.61",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"eslint-plugin-react": "^7.32.1",
|
|
55
55
|
"jsdom": "^21.1.0",
|
|
56
56
|
"mocha": "^10.2.0",
|
|
57
|
-
"next": "^14.
|
|
57
|
+
"next": "^14.2.7",
|
|
58
58
|
"nock": "^13.3.0",
|
|
59
59
|
"nyc": "^15.1.0",
|
|
60
60
|
"react": "^18.2.0",
|
|
@@ -67,14 +67,14 @@
|
|
|
67
67
|
"peerDependencies": {
|
|
68
68
|
"@sitecore-cloudsdk/events": "^0.3.1",
|
|
69
69
|
"@sitecore-cloudsdk/personalize": "^0.3.1",
|
|
70
|
-
"next": "^14.
|
|
70
|
+
"next": "^14.2.7",
|
|
71
71
|
"react": "^18.2.0",
|
|
72
72
|
"react-dom": "^18.2.0"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@sitecore-jss/sitecore-jss": "^22.2.0-canary.
|
|
76
|
-
"@sitecore-jss/sitecore-jss-dev-tools": "^22.2.0-canary.
|
|
77
|
-
"@sitecore-jss/sitecore-jss-react": "^22.2.0-canary.
|
|
75
|
+
"@sitecore-jss/sitecore-jss": "^22.2.0-canary.61",
|
|
76
|
+
"@sitecore-jss/sitecore-jss-dev-tools": "^22.2.0-canary.61",
|
|
77
|
+
"@sitecore-jss/sitecore-jss-react": "^22.2.0-canary.61",
|
|
78
78
|
"@vercel/kv": "^0.2.1",
|
|
79
79
|
"prop-types": "^15.8.1",
|
|
80
80
|
"regex-parser": "^2.2.11",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
},
|
|
83
83
|
"description": "",
|
|
84
84
|
"types": "types/index.d.ts",
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "50eb0f665c2936d8c6262020bb57a8eea359f7b7",
|
|
86
86
|
"files": [
|
|
87
87
|
"dist",
|
|
88
88
|
"types",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export declare const QUERY_PARAM_EDITING_SECRET = "secret";
|
|
2
1
|
export declare const QUERY_PARAM_VERCEL_PROTECTION_BYPASS = "x-vercel-protection-bypass";
|
|
3
2
|
export declare const QUERY_PARAM_VERCEL_SET_BYPASS_COOKIE = "x-vercel-set-bypass-cookie";
|
|
4
3
|
/**
|
|
@@ -6,7 +5,3 @@ export declare const QUERY_PARAM_VERCEL_SET_BYPASS_COOKIE = "x-vercel-set-bypass
|
|
|
6
5
|
* Note these are in lowercase format to match expected `IncomingHttpHeaders`.
|
|
7
6
|
*/
|
|
8
7
|
export declare const EDITING_PASS_THROUGH_HEADERS: string[];
|
|
9
|
-
/**
|
|
10
|
-
* Default allowed origins for editing requests. This is used to enforce CORS, CSP headers.
|
|
11
|
-
*/
|
|
12
|
-
export declare const EDITING_ALLOWED_ORIGINS: string[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextApiRequest, NextApiResponse } from 'next';
|
|
2
2
|
import { AxiosDataFetcher } from '@sitecore-jss/sitecore-jss';
|
|
3
3
|
import { EditMode, LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
|
|
4
|
+
import { RenderMetadataQueryParams, LayoutKind } from '@sitecore-jss/sitecore-jss/editing';
|
|
4
5
|
import { EditingDataService } from './editing-data-service';
|
|
5
6
|
import { RenderMiddlewareBase } from './render-middleware';
|
|
6
7
|
/**
|
|
@@ -95,25 +96,11 @@ export declare class ChromesHandler extends RenderMiddlewareBase {
|
|
|
95
96
|
* Configuration for the Editing Metadata Handler.
|
|
96
97
|
*/
|
|
97
98
|
export type EditingRenderMiddlewareMetadataConfig = Pick<EditingRenderMiddlewareConfig, 'resolvePageUrl'>;
|
|
98
|
-
/**
|
|
99
|
-
* Query parameters appended to the page route URL
|
|
100
|
-
* Appended when XMCloud Pages preview (editing) Metadata Edit Mode is used
|
|
101
|
-
*/
|
|
102
|
-
export type MetadataQueryParams = {
|
|
103
|
-
secret: string;
|
|
104
|
-
sc_lang: string;
|
|
105
|
-
sc_itemid: string;
|
|
106
|
-
sc_site: string;
|
|
107
|
-
route: string;
|
|
108
|
-
mode: Exclude<LayoutServicePageState, 'normal'>;
|
|
109
|
-
sc_variant?: string;
|
|
110
|
-
sc_version?: string;
|
|
111
|
-
};
|
|
112
99
|
/**
|
|
113
100
|
* Next.js API request with Metadata query parameters.
|
|
114
101
|
*/
|
|
115
102
|
type MetadataNextApiRequest = NextApiRequest & {
|
|
116
|
-
query:
|
|
103
|
+
query: RenderMetadataQueryParams;
|
|
117
104
|
};
|
|
118
105
|
/**
|
|
119
106
|
* Data for Next.js Preview (Editing) Metadata Edit Mode.
|
|
@@ -126,6 +113,7 @@ export type EditingMetadataPreviewData = {
|
|
|
126
113
|
pageState: Exclude<LayoutServicePageState, 'Normal'>;
|
|
127
114
|
variantIds: string[];
|
|
128
115
|
version?: string;
|
|
116
|
+
layoutKind?: LayoutKind;
|
|
129
117
|
};
|
|
130
118
|
/**
|
|
131
119
|
* Type guard for EditingMetadataPreviewData
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { NextResponse, NextRequest } from 'next/server';
|
|
2
1
|
import { GraphQLRedirectsServiceConfig } from '@sitecore-jss/sitecore-jss/site';
|
|
2
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
3
3
|
import { MiddlewareBase, MiddlewareBaseConfig } from './middleware';
|
|
4
4
|
/**
|
|
5
5
|
* extended RedirectsMiddlewareConfig config type for RedirectsMiddleware
|
|
@@ -37,4 +37,21 @@ export declare class RedirectsMiddleware extends MiddlewareBase {
|
|
|
37
37
|
* @private
|
|
38
38
|
*/
|
|
39
39
|
private getExistsRedirect;
|
|
40
|
+
/**
|
|
41
|
+
* When a user clicks on a link generated by the Link component from next/link,
|
|
42
|
+
* Next.js adds special parameters in the route called path.
|
|
43
|
+
* This method removes these special parameters.
|
|
44
|
+
* @param {URL} url
|
|
45
|
+
* @returns {string} normalize url
|
|
46
|
+
*/
|
|
47
|
+
private normalizeUrl;
|
|
48
|
+
/**
|
|
49
|
+
* Helper function to create a redirect response and remove the x-middleware-next header.
|
|
50
|
+
* @param {string} url The URL to redirect to.
|
|
51
|
+
* @param {Response} res The response object.
|
|
52
|
+
* @param {number} status The HTTP status code of the redirect.
|
|
53
|
+
* @param {string} statusText The status text of the redirect.
|
|
54
|
+
* @returns {NextResponse<unknown>} The redirect response.
|
|
55
|
+
*/
|
|
56
|
+
private createRedirectResponse;
|
|
40
57
|
}
|