@sitecore-jss/sitecore-jss-nextjs 22.1.0-canary.9 → 22.2.0-canary.2

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 (50) hide show
  1. package/dist/cjs/components/Link.js +7 -3
  2. package/dist/cjs/components/NextImage.js +10 -5
  3. package/dist/cjs/components/RichText.js +2 -2
  4. package/dist/cjs/editing/constants.js +12 -3
  5. package/dist/cjs/editing/editing-config-middleware.js +8 -0
  6. package/dist/cjs/editing/editing-data-middleware.js +6 -0
  7. package/dist/cjs/editing/editing-render-middleware.js +229 -103
  8. package/dist/cjs/editing/feaas-render-middleware.js +8 -0
  9. package/dist/cjs/editing/index.js +4 -1
  10. package/dist/cjs/editing/render-middleware.js +18 -4
  11. package/dist/cjs/index.js +9 -7
  12. package/dist/cjs/middleware/middleware.js +12 -0
  13. package/dist/cjs/middleware/personalize-middleware.js +85 -25
  14. package/dist/cjs/services/base-graphql-sitemap-service.js +5 -4
  15. package/dist/cjs/utils/index.js +4 -3
  16. package/dist/cjs/utils/utils.js +3 -3
  17. package/dist/esm/components/Link.js +7 -3
  18. package/dist/esm/components/NextImage.js +11 -5
  19. package/dist/esm/components/RichText.js +2 -2
  20. package/dist/esm/editing/constants.js +11 -2
  21. package/dist/esm/editing/editing-config-middleware.js +9 -1
  22. package/dist/esm/editing/editing-data-middleware.js +7 -1
  23. package/dist/esm/editing/editing-render-middleware.js +227 -103
  24. package/dist/esm/editing/feaas-render-middleware.js +9 -1
  25. package/dist/esm/editing/index.js +2 -1
  26. package/dist/esm/editing/render-middleware.js +19 -5
  27. package/dist/esm/index.js +3 -4
  28. package/dist/esm/middleware/middleware.js +12 -0
  29. package/dist/esm/middleware/personalize-middleware.js +86 -26
  30. package/dist/esm/services/base-graphql-sitemap-service.js +5 -4
  31. package/dist/esm/utils/index.js +2 -1
  32. package/dist/esm/utils/utils.js +1 -1
  33. package/package.json +10 -11
  34. package/types/ComponentBuilder.d.ts +3 -5
  35. package/types/components/Placeholder.d.ts +7 -2
  36. package/types/components/RichText.d.ts +6 -0
  37. package/types/editing/constants.d.ts +11 -2
  38. package/types/editing/editing-config-middleware.d.ts +7 -0
  39. package/types/editing/editing-data-service.d.ts +1 -0
  40. package/types/editing/editing-render-middleware.d.ts +111 -23
  41. package/types/editing/index.d.ts +2 -1
  42. package/types/editing/render-middleware.d.ts +9 -0
  43. package/types/index.d.ts +3 -4
  44. package/types/middleware/middleware.d.ts +6 -0
  45. package/types/middleware/personalize-middleware.d.ts +22 -2
  46. package/types/services/base-graphql-sitemap-service.d.ts +3 -2
  47. package/types/utils/index.d.ts +2 -1
  48. package/dist/cjs/components/EditingComponentPlaceholder.js +0 -12
  49. package/dist/esm/components/EditingComponentPlaceholder.js +0 -5
  50. package/types/components/EditingComponentPlaceholder.d.ts +0 -4
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { NextResponse } from 'next/server';
11
- import { GraphQLPersonalizeService, getPersonalizedRewrite, } from '@sitecore-jss/sitecore-jss/personalize';
11
+ import { GraphQLPersonalizeService, getPersonalizedRewrite, CdpHelper, DEFAULT_VARIANT, } from '@sitecore-jss/sitecore-jss/personalize';
12
12
  import { debug } from '@sitecore-jss/sitecore-jss';
13
13
  import { MiddlewareBase } from './middleware';
14
14
  import { init, personalize } from '@sitecore-cloudsdk/personalize/server';
@@ -58,6 +58,15 @@ export class PersonalizeMiddleware extends MiddlewareBase {
58
58
  debug.personalize('skipped (no personalization configured)');
59
59
  return response;
60
60
  }
61
+ if (this.isPrefetch(req)) {
62
+ debug.personalize('skipped (prefetch)');
63
+ // Personalized, but this is a prefetch request.
64
+ // In this case, don't execute a personalize request; otherwise, the metrics for component A/B experiments would be inaccurate.
65
+ // Disable preflight caching to force revalidation on client-side navigation (personalization WILL be influenced).
66
+ // 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.
67
+ response.headers.set('x-middleware-cache', 'no-cache');
68
+ return response;
69
+ }
61
70
  yield this.initPersonalizeServer({
62
71
  hostname,
63
72
  siteName: site.name,
@@ -65,32 +74,36 @@ export class PersonalizeMiddleware extends MiddlewareBase {
65
74
  response,
66
75
  });
67
76
  const params = this.getExperienceParams(req);
68
- debug.personalize('executing experience for %s %o', personalizeInfo.contentId, params);
69
- let variantId;
70
- // Execute targeted experience in Personalize SDK
71
- // eslint-disable-next-line no-useless-catch
72
- try {
73
- const personalization = yield this.personalize({ personalizeInfo, params, language, timeout }, req);
74
- variantId = personalization.variantId;
75
- }
76
- catch (error) {
77
- throw error;
78
- }
79
- if (!variantId) {
80
- debug.personalize('skipped (no variant identified)');
81
- return response;
82
- }
83
- if (!personalizeInfo.variantIds.includes(variantId)) {
84
- debug.personalize('skipped (invalid variant)');
77
+ const executions = this.getPersonalizeExecutions(personalizeInfo, language);
78
+ const identifiedVariantIds = [];
79
+ yield Promise.all(executions.map((execution) => this.personalize({
80
+ friendlyId: execution.friendlyId,
81
+ variantIds: execution.variantIds,
82
+ params,
83
+ language,
84
+ timeout,
85
+ }, req).then((personalization) => {
86
+ const variantId = personalization.variantId;
87
+ if (variantId) {
88
+ if (!execution.variantIds.includes(variantId)) {
89
+ debug.personalize('invalid variant %s', variantId);
90
+ }
91
+ else {
92
+ identifiedVariantIds.push(variantId);
93
+ }
94
+ }
95
+ })));
96
+ if (identifiedVariantIds.length === 0) {
97
+ debug.personalize('skipped (no variant(s) identified)');
85
98
  return response;
86
99
  }
87
100
  // Path can be rewritten by previously executed middleware
88
101
  const basePath = (res === null || res === void 0 ? void 0 : res.headers.get('x-sc-rewrite')) || pathname;
89
102
  // Rewrite to persononalized path
90
- const rewritePath = getPersonalizedRewrite(basePath, { variantId });
103
+ const rewritePath = getPersonalizedRewrite(basePath, identifiedVariantIds);
91
104
  response = this.rewrite(rewritePath, req, response);
92
- // Disable preflight caching to force revalidation on client-side navigation (personalization may be influenced)
93
- // See https://github.com/vercel/next.js/issues/32727
105
+ // Disable preflight caching to force revalidation on client-side navigation (personalization MAY be influenced).
106
+ // See https://github.com/vercel/next.js/pull/32767
94
107
  response.headers.set('x-middleware-cache', 'no-cache');
95
108
  debug.personalize('personalize middleware end in %dms: %o', Date.now() - startTimestamp, {
96
109
  rewritePath,
@@ -129,17 +142,18 @@ export class PersonalizeMiddleware extends MiddlewareBase {
129
142
  });
130
143
  });
131
144
  }
132
- personalize({ params, personalizeInfo, language, timeout, }, request) {
145
+ personalize({ params, friendlyId, language, timeout, variantIds, }, request) {
133
146
  var _a;
134
147
  return __awaiter(this, void 0, void 0, function* () {
135
- const personalizationData = {
148
+ debug.personalize('executing experience for %s %o', friendlyId, params);
149
+ return (yield personalize(request, {
136
150
  channel: this.config.cdpConfig.channel || 'WEB',
137
151
  currency: (_a = this.config.cdpConfig.currency) !== null && _a !== void 0 ? _a : 'USD',
138
- friendlyId: personalizeInfo.contentId,
152
+ friendlyId,
139
153
  params,
140
154
  language,
141
- };
142
- return (yield personalize(request, personalizationData, { timeout }));
155
+ pageVariantIds: variantIds,
156
+ }, { timeout }));
143
157
  });
144
158
  }
145
159
  getExperienceParams(req) {
@@ -161,4 +175,50 @@ export class PersonalizeMiddleware extends MiddlewareBase {
161
175
  // ignore files
162
176
  return pathname.includes('.') || super.excludeRoute(pathname);
163
177
  }
178
+ /**
179
+ * Aggregates personalize executions based on the provided route personalize information and language
180
+ * @param {PersonalizeInfo} personalizeInfo the route personalize information
181
+ * @param {string} language the language
182
+ * @returns An array of personalize executions
183
+ */
184
+ getPersonalizeExecutions(personalizeInfo, language) {
185
+ if (personalizeInfo.variantIds.length === 0) {
186
+ return [];
187
+ }
188
+ const results = [];
189
+ return personalizeInfo.variantIds.reduce((results, variantId) => {
190
+ if (variantId.includes('_')) {
191
+ // Component-level personalization in format "<ComponentID>_<VariantID>"
192
+ const componentId = variantId.split('_')[0];
193
+ const friendlyId = CdpHelper.getComponentFriendlyId(personalizeInfo.pageId, componentId, language, this.config.scope || this.config.edgeConfig.scope);
194
+ const execution = results.find((x) => x.friendlyId === friendlyId);
195
+ if (execution) {
196
+ execution.variantIds.push(variantId);
197
+ }
198
+ else {
199
+ // The default/control variant (format "<ComponentID>_default") is also a valid value returned by the execution
200
+ const defaultVariant = `${componentId}${DEFAULT_VARIANT}`;
201
+ results.push({
202
+ friendlyId,
203
+ variantIds: [defaultVariant, variantId],
204
+ });
205
+ }
206
+ }
207
+ else {
208
+ // Embedded (page-level) personalization in format "<VariantID>"
209
+ const friendlyId = CdpHelper.getPageFriendlyId(personalizeInfo.pageId, language, this.config.scope || this.config.edgeConfig.scope);
210
+ const execution = results.find((x) => x.friendlyId === friendlyId);
211
+ if (execution) {
212
+ execution.variantIds.push(variantId);
213
+ }
214
+ else {
215
+ results.push({
216
+ friendlyId,
217
+ variantIds: [variantId],
218
+ });
219
+ }
220
+ }
221
+ return results;
222
+ }, results);
223
+ }
164
224
  }
@@ -144,13 +144,14 @@ export class BaseGraphQLSitemapService {
144
144
  const formatPath = (path) => formatStaticPath(path.replace(/^\/|\/$/g, '').split('/'), language);
145
145
  const aggregatedPaths = [];
146
146
  sitePaths.forEach((item) => {
147
- var _a, _b, _c, _d;
147
+ var _a, _b, _c;
148
148
  if (!item)
149
149
  return;
150
150
  aggregatedPaths.push(formatPath(item.path));
151
- // check for type safety's sake - personalize may be empty depending on query type
152
- if ((_b = (_a = item.route) === null || _a === void 0 ? void 0 : _a.personalization) === null || _b === void 0 ? void 0 : _b.variantIds.length) {
153
- aggregatedPaths.push(...(((_d = (_c = item.route) === null || _c === void 0 ? void 0 : _c.personalization) === null || _d === void 0 ? void 0 : _d.variantIds.map((varId) => formatPath(getPersonalizedRewrite(item.path, { variantId: varId })))) || {}));
151
+ const variantIds = (_c = (_b = (_a = item.route) === null || _a === void 0 ? void 0 : _a.personalization) === null || _b === void 0 ? void 0 : _b.variantIds) === null || _c === void 0 ? void 0 : _c.filter((variantId) => !variantId.includes('_') // exclude component A/B test variants
152
+ );
153
+ if (variantIds === null || variantIds === void 0 ? void 0 : variantIds.length) {
154
+ aggregatedPaths.push(...variantIds.map((varId) => formatPath(getPersonalizedRewrite(item.path, [varId]))));
154
155
  }
155
156
  });
156
157
  return aggregatedPaths;
@@ -1,2 +1,3 @@
1
1
  export { getPublicUrl, handleEditorFastRefresh } from './utils';
2
- export { tryParseEnvValue, isEditorActive, resetEditorChromes, resolveUrl, } from '@sitecore-jss/sitecore-jss/utils';
2
+ export { tryParseEnvValue, resolveUrl } from '@sitecore-jss/sitecore-jss/utils';
3
+ export { isEditorActive, resetEditorChromes } from '@sitecore-jss/sitecore-jss/editing';
@@ -1,4 +1,4 @@
1
- import { isEditorActive, resetEditorChromes } from '@sitecore-jss/sitecore-jss/utils';
1
+ import { isEditorActive, resetEditorChromes } from '@sitecore-jss/sitecore-jss/editing';
2
2
  /**
3
3
  * Get the publicUrl.
4
4
  * This is used primarily to enable compatibility with Sitecore editors.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sitecore-jss/sitecore-jss-nextjs",
3
- "version": "22.1.0-canary.9",
3
+ "version": "22.2.0-canary.2",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "sideEffects": false,
@@ -14,7 +14,7 @@
14
14
  "generate-docs": "npx typedoc --plugin typedoc-plugin-markdown --readme none --out ../../ref-docs/sitecore-jss-nextjs --entryPoints src/index.ts --entryPoints src/monitoring/index.ts --entryPoints src/editing/index.ts --entryPoints src/middleware/index.ts --entryPoints src/context/index.ts --entryPoints src/utils/index.ts --entryPoints src/site/index.ts --entryPoints src/graphql/index.ts --githubPages false"
15
15
  },
16
16
  "engines": {
17
- "node": ">=18"
17
+ "node": ">=20"
18
18
  },
19
19
  "author": {
20
20
  "name": "Sitecore Corporation",
@@ -29,13 +29,13 @@
29
29
  "url": "https://github.com/sitecore/jss/issues"
30
30
  },
31
31
  "devDependencies": {
32
- "@sitecore-cloudsdk/personalize": "^0.3.0",
32
+ "@sitecore-cloudsdk/personalize": "^0.3.1",
33
33
  "@types/chai": "^4.3.4",
34
34
  "@types/chai-as-promised": "^7.1.5",
35
35
  "@types/chai-string": "^1.4.2",
36
36
  "@types/enzyme": "^3.10.12",
37
37
  "@types/mocha": "^10.0.1",
38
- "@types/node": "~18.11.18",
38
+ "@types/node": "~20.14.2",
39
39
  "@types/prop-types": "^15.7.5",
40
40
  "@types/react": "^18.2.22",
41
41
  "@types/react-dom": "^18.0.10",
@@ -65,25 +65,24 @@
65
65
  "typescript": "~4.9.4"
66
66
  },
67
67
  "peerDependencies": {
68
- "@sitecore-cloudsdk/events": "^0.3.0",
69
- "@sitecore-cloudsdk/personalize": "^0.3.0",
68
+ "@sitecore-cloudsdk/events": "^0.3.1",
69
+ "@sitecore-cloudsdk/personalize": "^0.3.1",
70
70
  "next": "^14.1.0",
71
71
  "react": "^18.2.0",
72
72
  "react-dom": "^18.2.0"
73
73
  },
74
74
  "dependencies": {
75
- "@sitecore-jss/sitecore-jss": "^22.1.0-canary.9",
76
- "@sitecore-jss/sitecore-jss-dev-tools": "^22.1.0-canary.9",
77
- "@sitecore-jss/sitecore-jss-react": "^22.1.0-canary.9",
75
+ "@sitecore-jss/sitecore-jss": "^22.2.0-canary.2",
76
+ "@sitecore-jss/sitecore-jss-dev-tools": "^22.2.0-canary.2",
77
+ "@sitecore-jss/sitecore-jss-react": "^22.2.0-canary.2",
78
78
  "@vercel/kv": "^0.2.1",
79
- "node-html-parser": "^6.1.4",
80
79
  "prop-types": "^15.8.1",
81
80
  "regex-parser": "^2.2.11",
82
81
  "sync-disk-cache": "^2.1.0"
83
82
  },
84
83
  "description": "",
85
84
  "types": "types/index.d.ts",
86
- "gitHead": "9b249f8d03fb9d74e74f74f3040fc2668137bdcc",
85
+ "gitHead": "ba1b71ef1209c0e3bdd3557d315a0e2a46ba4580",
87
86
  "files": [
88
87
  "dist",
89
88
  "types",
@@ -1,18 +1,16 @@
1
- /// <reference types="@types/react" />
2
- import { ComponentFactory } from '@sitecore-jss/sitecore-jss-react';
1
+ import { ComponentFactory, JssComponentType } from '@sitecore-jss/sitecore-jss-react';
3
2
  import { Module, ModuleFactory } from './sharedTypes/module-factory';
4
- import { ComponentType } from 'react';
5
3
  /**
6
4
  * Represents a component that can be imported dynamically
7
5
  */
8
6
  export type LazyModule = {
9
7
  module: () => Promise<Module>;
10
- element: (isEditing?: boolean) => ComponentType;
8
+ element: (isEditing?: boolean) => JssComponentType;
11
9
  };
12
10
  /**
13
11
  * Component is a module or a lazy module
14
12
  */
15
- type Component = Module | LazyModule | ComponentType;
13
+ type Component = Module | LazyModule | JssComponentType;
16
14
  /**
17
15
  * Configuration for ComponentBuilder
18
16
  */
@@ -1,4 +1,9 @@
1
1
  /// <reference types="@types/react" />
2
2
  import React from 'react';
3
- import { PlaceholderComponentProps } from '@sitecore-jss/sitecore-jss-react';
4
- export declare const Placeholder: (props: PlaceholderComponentProps) => React.JSX.Element;
3
+ import { PlaceholderComponentProps, WithSitecoreContextProps, EnhancedOmit } from '@sitecore-jss/sitecore-jss-react';
4
+ /**
5
+ * React Placeholder component wrapped by withSitecoreContext, so these properties shouldn't be passed to the Next.js Placeholder.
6
+ */
7
+ type PlaceholderProps = EnhancedOmit<PlaceholderComponentProps, keyof WithSitecoreContextProps>;
8
+ export declare const Placeholder: (props: PlaceholderProps) => React.JSX.Element;
9
+ export {};
@@ -1,3 +1,5 @@
1
+ /// <reference types="@types/react" />
2
+ import React from 'react';
1
3
  import PropTypes from 'prop-types';
2
4
  import { RichTextProps as ReactRichTextProps } from '@sitecore-jss/sitecore-jss-react';
3
5
  export type RichTextProps = ReactRichTextProps & {
@@ -19,9 +21,13 @@ export declare const RichText: {
19
21
  field: PropTypes.Requireable<PropTypes.InferProps<{
20
22
  value: PropTypes.Requireable<string>;
21
23
  editable: PropTypes.Requireable<string>;
24
+ metadata: PropTypes.Requireable<{
25
+ [x: string]: any;
26
+ }>;
22
27
  }>>;
23
28
  tag: PropTypes.Requireable<string>;
24
29
  editable: PropTypes.Requireable<boolean>;
30
+ emptyFieldEditingComponent: PropTypes.Requireable<NonNullable<React.ComponentClass<unknown, any> | React.FC<unknown>>>;
25
31
  internalLinksSelector: PropTypes.Requireable<string>;
26
32
  };
27
33
  displayName: string;
@@ -1,3 +1,12 @@
1
1
  export declare const QUERY_PARAM_EDITING_SECRET = "secret";
2
- export declare const QUERY_PARAM_PROTECTION_BYPASS_SITECORE = "x-sitecore-protection-bypass";
3
- export declare const QUERY_PARAM_PROTECTION_BYPASS_VERCEL = "x-vercel-protection-bypass";
2
+ export declare const QUERY_PARAM_VERCEL_PROTECTION_BYPASS = "x-vercel-protection-bypass";
3
+ export declare const QUERY_PARAM_VERCEL_SET_BYPASS_COOKIE = "x-vercel-set-bypass-cookie";
4
+ /**
5
+ * Headers that should be passed along to (Editing Chromes handler) SSR request.
6
+ * Note these are in lowercase format to match expected `IncomingHttpHeaders`.
7
+ */
8
+ 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,4 +1,5 @@
1
1
  import { NextApiRequest, NextApiResponse } from 'next';
2
+ import { EditMode } from '@sitecore-jss/sitecore-jss/layout';
2
3
  import { Metadata } from '@sitecore-jss/sitecore-jss-dev-tools';
3
4
  export type EditingConfigMiddlewareConfig = {
4
5
  /**
@@ -9,6 +10,12 @@ export type EditingConfigMiddlewareConfig = {
9
10
  * Application metadata
10
11
  */
11
12
  metadata: Metadata;
13
+ /**
14
+ * Determines which editing mode should be used by Pages.
15
+ * Can be either 'chromes' or 'metadata'.
16
+ * By default its 'metadata'
17
+ */
18
+ pagesEditMode?: EditMode;
12
19
  };
13
20
  /**
14
21
  * Middleware / handler used in the editing config API route in xmcloud add on (e.g. '/api/editing/config')
@@ -4,6 +4,7 @@ import { EditingDataCache } from './editing-data-cache';
4
4
  import { PreviewData } from 'next';
5
5
  /**
6
6
  * Data for Next.js Preview (Editing) mode
7
+ * Used in Chromes Edit Mode only
7
8
  */
8
9
  export interface EditingPreviewData {
9
10
  key: string;
@@ -1,16 +1,23 @@
1
1
  import { NextApiRequest, NextApiResponse } from 'next';
2
2
  import { AxiosDataFetcher } from '@sitecore-jss/sitecore-jss';
3
- import { EditingData } from './editing-data';
3
+ import { EditMode, LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
4
4
  import { EditingDataService } from './editing-data-service';
5
5
  import { RenderMiddlewareBase } from './render-middleware';
6
- export interface EditingRenderMiddlewareConfig {
6
+ /**
7
+ * Configuration for the Editing Render Middleware.
8
+ */
9
+ export type EditingRenderMiddlewareConfig = {
7
10
  /**
11
+ * -- Edit Mode Chromes --
12
+ *
8
13
  * The `AxiosDataFetcher` instance to use for API requests.
9
14
  * @default new AxiosDataFetcher()
10
15
  * @see AxiosDataFetcher
11
16
  */
12
17
  dataFetcher?: AxiosDataFetcher;
13
18
  /**
19
+ * -- Edit Mode Chromes --
20
+ *
14
21
  * The `EditingDataService` instance to use.
15
22
  * This would typically only be necessary if you've got a custom `EditingDataService` instance (e.g. using a custom API route).
16
23
  * By default, this is `editingDataService` (the `EditingDataService` default instance).
@@ -20,16 +27,25 @@ export interface EditingRenderMiddlewareConfig {
20
27
  */
21
28
  editingDataService?: EditingDataService;
22
29
  /**
30
+ * -- Edit Mode Chromes / Metadata --
31
+ *
23
32
  * Function used to determine route/page URL to render.
24
33
  * This may be necessary for certain custom Next.js routing configurations.
25
- * @param {string} serverUrl The root server URL e.g. 'http://localhost:3000'
34
+ * @param {Object} args Arguments for resolving the page URL
35
+ * @param {string} args.serverUrl The root server URL e.g. 'http://localhost:3000'. Available in Chromes Edit Mode only.
26
36
  * @param {string} itemPath The Sitecore relative item path e.g. '/styleguide'
27
37
  * @returns {string} The URL to render
28
- * @default `${serverUrl}${itemPath}`
38
+ * @default `${serverUrl}${itemPath}` In Edit Mode Chromes
39
+ * @default `${itemPath}` In XMCloud Pages for Edit Mode Metadata
29
40
  * @see resolveServerUrl
30
41
  */
31
- resolvePageUrl?: (serverUrl: string, itemPath: string) => string;
42
+ resolvePageUrl?: (args: {
43
+ serverUrl?: string;
44
+ itemPath: string;
45
+ }) => string;
32
46
  /**
47
+ * -- Edit Mode Chromes --
48
+ *
33
49
  * Function used to determine the root server URL. This is used for the route/page and subsequent data API requests.
34
50
  * By default, the host header is used, with https protocol on Vercel (due to serverless function architecture) and http protocol elsewhere.
35
51
  * @param {NextApiRequest} req The current request.
@@ -37,30 +53,29 @@ export interface EditingRenderMiddlewareConfig {
37
53
  * @see resolvePageUrl
38
54
  */
39
55
  resolveServerUrl?: (req: NextApiRequest) => string;
40
- }
56
+ };
41
57
  /**
42
- * Middleware / handler for use in the editing render Next.js API route (e.g. '/api/editing/render')
43
- * which is required for Sitecore editing support.
58
+ * Configuration for the Editing Chromes Handler.
44
59
  */
45
- export declare class EditingRenderMiddleware extends RenderMiddlewareBase {
60
+ export type EditingRenderMiddlewareChromesConfig = EditingRenderMiddlewareConfig;
61
+ /**
62
+ * Handler for the Editing Chromes POST requests.
63
+ * This handler is responsible for rendering the page and returning the HTML content that is provided via request.
64
+ */
65
+ export declare class ChromesHandler extends RenderMiddlewareBase {
66
+ config?: EditingRenderMiddlewareConfig | undefined;
46
67
  private editingDataService;
47
68
  private dataFetcher;
48
69
  private resolvePageUrl;
49
70
  private resolveServerUrl;
50
- /**
51
- * @param {EditingRenderMiddlewareConfig} [config] Editing render middleware config
52
- */
53
- constructor(config?: EditingRenderMiddlewareConfig);
54
- /**
55
- * Gets the Next.js API route handler
56
- * @returns route handler
57
- */
58
- getHandler(): (req: NextApiRequest, res: NextApiResponse) => Promise<void>;
59
- private handler;
71
+ constructor(config?: EditingRenderMiddlewareConfig | undefined);
72
+ render(req: NextApiRequest, res: NextApiResponse): Promise<void>;
60
73
  /**
61
74
  * Default page URL resolution.
62
- * @param {string} serverUrl
63
- * @param {string} itemPath
75
+ * @param {Object} args Arguments for resolving the page URL
76
+ * @param {string} args.serverUrl The root server URL e.g. 'http://localhost:3000'
77
+ * @param {string} args.itemPath The Sitecore relative item path e.g. '/styleguide'
78
+ * @returns {string} The URL to render
64
79
  */
65
80
  private defaultResolvePageUrl;
66
81
  /**
@@ -74,8 +89,81 @@ export declare class EditingRenderMiddleware extends RenderMiddlewareBase {
74
89
  * @param {NextApiRequest} req
75
90
  */
76
91
  private defaultResolveServerUrl;
92
+ private extractEditingData;
93
+ }
94
+ /**
95
+ * Configuration for the Editing Metadata Handler.
96
+ */
97
+ 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
+ /**
113
+ * Next.js API request with Metadata query parameters.
114
+ */
115
+ type MetadataNextApiRequest = NextApiRequest & {
116
+ query: MetadataQueryParams;
117
+ };
118
+ /**
119
+ * Data for Next.js Preview (Editing) Metadata Edit Mode.
120
+ */
121
+ export type EditingMetadataPreviewData = {
122
+ site: string;
123
+ itemId: string;
124
+ language: string;
125
+ editMode: EditMode.Metadata;
126
+ pageState: Exclude<LayoutServicePageState, 'Normal'>;
127
+ variantIds: string[];
128
+ version?: string;
129
+ };
130
+ /**
131
+ * Type guard for EditingMetadataPreviewData
132
+ * @param {Object} data preview data to check
133
+ * @returns true if the data is EditingMetadataPreviewData
134
+ * @see EditingMetadataPreviewData
135
+ */
136
+ export declare const isEditingMetadataPreviewData: (data: unknown) => data is EditingMetadataPreviewData;
137
+ /**
138
+ * Handler for the Editing Metadata GET requests.
139
+ * This handler is responsible for redirecting the request to the page route.
140
+ * The page fetches the layout, dictionary and renders the page.
141
+ */
142
+ export declare class MetadataHandler {
143
+ config: EditingRenderMiddlewareMetadataConfig;
144
+ constructor(config: EditingRenderMiddlewareMetadataConfig);
145
+ render(req: MetadataNextApiRequest, res: NextApiResponse): void;
146
+ /**
147
+ * Gets the Content-Security-Policy header value
148
+ * @returns Content-Security-Policy header value
149
+ */
150
+ getSCPHeader(): string;
77
151
  }
78
152
  /**
79
- * @param {NextApiRequest} req
153
+ * Middleware / handler for use in the editing render Next.js API route (e.g. '/api/editing/render')
154
+ * which is required for Sitecore editing support.
80
155
  */
81
- export declare function extractEditingData(req: NextApiRequest): EditingData;
156
+ export declare class EditingRenderMiddleware extends RenderMiddlewareBase {
157
+ config?: EditingRenderMiddlewareConfig | undefined;
158
+ /**
159
+ * @param {EditingRenderMiddlewareConfig} [config] Editing render middleware config
160
+ */
161
+ constructor(config?: EditingRenderMiddlewareConfig | undefined);
162
+ /**
163
+ * Gets the Next.js API route handler
164
+ * @returns route handler
165
+ */
166
+ getHandler(): (req: NextApiRequest, res: NextApiResponse) => Promise<void>;
167
+ private handler;
168
+ }
169
+ export {};
@@ -1,7 +1,8 @@
1
+ export { GraphQLEditingService } from '@sitecore-jss/sitecore-jss/editing';
1
2
  export { EditingData } from './editing-data';
2
3
  export { EditingDataCache, EditingDataDiskCache } from './editing-data-cache';
3
4
  export { EditingDataMiddleware, EditingDataMiddlewareConfig } from './editing-data-middleware';
4
- export { EditingRenderMiddleware, EditingRenderMiddlewareConfig, } from './editing-render-middleware';
5
+ export { EditingRenderMiddleware, EditingRenderMiddlewareConfig, EditingMetadataPreviewData, isEditingMetadataPreviewData, } from './editing-render-middleware';
5
6
  export { EditingPreviewData, EditingDataService, BasicEditingDataService, BasicEditingDataServiceConfig, ServerlessEditingDataService, ServerlessEditingDataServiceConfig, editingDataService, } from './editing-data-service';
6
7
  export { VercelEditingDataCache } from './vercel-editing-data-cache';
7
8
  export { FEAASRenderMiddleware, FEAASRenderMiddlewareConfig } from './feaas-render-middleware';
@@ -1,3 +1,4 @@
1
+ import { IncomingHttpHeaders } from 'http';
1
2
  /**
2
3
  * Base class for middleware that handles pages and components rendering in Sitecore Editors.
3
4
  */
@@ -12,4 +13,12 @@ export declare abstract class RenderMiddlewareBase {
12
13
  }>) => {
13
14
  [key: string]: string;
14
15
  };
16
+ /**
17
+ * Get headers that should be passed along to subsequent requests
18
+ * @param {IncomingHttpHeaders} headers Incoming HTTP Headers
19
+ * @returns Object of approved headers
20
+ */
21
+ protected getHeadersForPropagation: (headers: IncomingHttpHeaders) => {
22
+ [key: string]: string | string[];
23
+ };
15
24
  }
package/types/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export { constants, HttpDataFetcher, HttpResponse, AxiosResponse, AxiosDataFetcher, AxiosDataFetcherConfig, NativeDataFetcher, NativeDataFetcherConfig, HTMLLink, enableDebug, debug, } from '@sitecore-jss/sitecore-jss';
2
- export { LayoutService, LayoutServiceData, LayoutServicePageState, LayoutServiceContext, LayoutServiceContextData, GraphQLLayoutService, GraphQLLayoutServiceConfig, RestLayoutService, RestLayoutServiceConfig, PlaceholderData, PlaceholdersData, RouteData, Field, Item, HtmlElementRendering, getChildPlaceholder, getFieldValue, ComponentRendering, ComponentFields, ComponentParams, RenderingType, EDITING_COMPONENT_PLACEHOLDER, EDITING_COMPONENT_ID, getContentStylesheetLink, } from '@sitecore-jss/sitecore-jss/layout';
2
+ export { LayoutService, LayoutServiceData, LayoutServicePageState, LayoutServiceContext, LayoutServiceContextData, GraphQLLayoutService, GraphQLLayoutServiceConfig, RestLayoutService, RestLayoutServiceConfig, PlaceholderData, PlaceholdersData, RouteData, Field, Item, HtmlElementRendering, getChildPlaceholder, getFieldValue, ComponentRendering, ComponentFields, ComponentParams, getContentStylesheetLink, EditMode, } from '@sitecore-jss/sitecore-jss/layout';
3
3
  export { mediaApi } from '@sitecore-jss/sitecore-jss/media';
4
4
  export { trackingApi, TrackingRequestOptions, CampaignInstance, GoalInstance, OutcomeInstance, EventInstance, PageViewInstance, } from '@sitecore-jss/sitecore-jss/tracking';
5
5
  export { DictionaryPhrases, DictionaryService, GraphQLDictionaryService, GraphQLDictionaryServiceConfig, RestDictionaryService, RestDictionaryServiceConfig, } from '@sitecore-jss/sitecore-jss/i18n';
6
- export { personalizeLayout, getPersonalizedRewrite, getPersonalizedRewriteData, normalizePersonalizedRewrite, CdpHelper, } from '@sitecore-jss/sitecore-jss/personalize';
6
+ export { personalizeLayout, getPersonalizedRewrite, getPersonalizedRewriteData, getGroomedVariantIds, normalizePersonalizedRewrite, CdpHelper, } from '@sitecore-jss/sitecore-jss/personalize';
7
7
  export { ComponentPropsCollection, ComponentPropsError, GetStaticComponentProps, GetServerSideComponentProps, } from './sharedTypes/component-props';
8
8
  export { ModuleFactory, Module } from './sharedTypes/module-factory';
9
9
  export { ComponentPropsService } from './services/component-props-service';
@@ -16,7 +16,6 @@ export { ComponentPropsReactContext, ComponentPropsContextProps, ComponentPropsC
16
16
  export { Link, LinkProps } from './components/Link';
17
17
  export { RichText, RichTextProps } from './components/RichText';
18
18
  export { Placeholder } from './components/Placeholder';
19
- export { EditingComponentPlaceholder } from './components/EditingComponentPlaceholder';
20
19
  export { NextImage } from './components/NextImage';
21
20
  import * as FEaaSWrapper from './components/FEaaSWrapper';
22
21
  import * as BYOCWrapper from './components/BYOCWrapper';
@@ -24,4 +23,4 @@ export { FEaaSWrapper };
24
23
  export { BYOCWrapper };
25
24
  export { ComponentBuilder, ComponentBuilderConfig } from './ComponentBuilder';
26
25
  export { Context, ContextConfig, SDK } from './context';
27
- export { ComponentFactory, Image, ImageField, ImageFieldValue, ImageProps, LinkField, LinkFieldValue, Text, TextField, DateField, EditFrame, FEaaSComponent, FEaaSComponentProps, FEaaSComponentParams, fetchFEaaSComponentServerProps, BYOCComponentParams, BYOCComponent, BYOCComponentProps, getComponentLibraryStylesheetLinks, File, FileField, RichTextField, VisitorIdentification, PlaceholderComponentProps, SitecoreContext, SitecoreContextState, SitecoreContextValue, SitecoreContextReactContext, withSitecoreContext, useSitecoreContext, withEditorChromes, withPlaceholder, withDatasourceCheck, ImageSizeParameters, ComponentConsumerProps, WithSitecoreContextOptions, WithSitecoreContextProps, } from '@sitecore-jss/sitecore-jss-react';
26
+ export { ComponentFactory, Image, ImageField, ImageFieldValue, ImageProps, LinkField, LinkFieldValue, Text, TextField, DateField, EditFrame, FEaaSComponent, FEaaSComponentProps, FEaaSComponentParams, fetchFEaaSComponentServerProps, BYOCComponentParams, BYOCComponent, BYOCComponentProps, getComponentLibraryStylesheetLinks, File, FileField, RichTextField, DefaultEmptyFieldEditingComponentImage, DefaultEmptyFieldEditingComponentText, VisitorIdentification, PlaceholderComponentProps, SitecoreContext, SitecoreContextState, SitecoreContextValue, SitecoreContextReactContext, withSitecoreContext, useSitecoreContext, withEditorChromes, withPlaceholder, withDatasourceCheck, ImageSizeParameters, WithSitecoreContextOptions, WithSitecoreContextProps, WithSitecoreContextHocProps, withFieldMetadata, withEmptyFieldEditingComponent, EditingScripts, } from '@sitecore-jss/sitecore-jss-react';
@@ -37,6 +37,12 @@ export declare abstract class MiddlewareBase {
37
37
  * @returns {boolean} is preview
38
38
  */
39
39
  protected isPreview(req: NextRequest): boolean;
40
+ /**
41
+ * Determines if the request is a Next.js (next/link) prefetch request
42
+ * @param {NextRequest} req request
43
+ * @returns {boolean} is prefetch
44
+ */
45
+ protected isPrefetch(req: NextRequest): boolean;
40
46
  protected excludeRoute(pathname: string): boolean | undefined;
41
47
  /**
42
48
  * Safely extract all headers for debug logging