@sitecore-content-sdk/nextjs 0.1.0 → 0.2.0-beta.10

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 (44) hide show
  1. package/dist/cjs/components/Link.js +0 -2
  2. package/dist/cjs/components/NextImage.js +6 -25
  3. package/dist/cjs/components/RichText.js +0 -5
  4. package/dist/cjs/config/define-config.js +25 -0
  5. package/dist/cjs/config/index.js +3 -3
  6. package/dist/cjs/editing/editing-render-middleware.js +1 -1
  7. package/dist/cjs/index.js +9 -4
  8. package/dist/cjs/middleware/index.js +10 -1
  9. package/dist/cjs/middleware/middleware.js +4 -0
  10. package/dist/cjs/middleware/personalize-middleware.js +32 -25
  11. package/dist/cjs/middleware/redirects-middleware.js +14 -3
  12. package/dist/cjs/middleware/robots-middleware.js +42 -0
  13. package/dist/cjs/tools/codegen/extract-components.js +64 -0
  14. package/dist/cjs/tools/codegen/utils.js +255 -0
  15. package/dist/cjs/tools/index.js +3 -1
  16. package/dist/esm/components/Link.js +1 -3
  17. package/dist/esm/components/NextImage.js +6 -25
  18. package/dist/esm/components/RichText.js +1 -3
  19. package/dist/esm/config/define-config.js +20 -0
  20. package/dist/esm/config/index.js +1 -1
  21. package/dist/esm/editing/editing-render-middleware.js +1 -1
  22. package/dist/esm/index.js +3 -3
  23. package/dist/esm/middleware/index.js +3 -0
  24. package/dist/esm/middleware/middleware.js +4 -0
  25. package/dist/esm/middleware/personalize-middleware.js +32 -25
  26. package/dist/esm/middleware/redirects-middleware.js +14 -3
  27. package/dist/esm/middleware/robots-middleware.js +38 -0
  28. package/dist/esm/tools/codegen/extract-components.js +57 -0
  29. package/dist/esm/tools/codegen/utils.js +212 -0
  30. package/dist/esm/tools/index.js +1 -0
  31. package/package.json +40 -38
  32. package/types/components/ComponentPropsContext.d.ts +1 -1
  33. package/types/components/RichText.d.ts +1 -14
  34. package/types/config/define-config.d.ts +33 -0
  35. package/types/config/index.d.ts +1 -1
  36. package/types/index.d.ts +4 -4
  37. package/types/middleware/index.d.ts +3 -0
  38. package/types/middleware/middleware.d.ts +3 -0
  39. package/types/middleware/personalize-middleware.d.ts +6 -29
  40. package/types/middleware/redirects-middleware.d.ts +13 -6
  41. package/types/middleware/robots-middleware.d.ts +11 -0
  42. package/types/tools/codegen/extract-components.d.ts +10 -0
  43. package/types/tools/codegen/utils.d.ts +40 -0
  44. package/types/tools/index.d.ts +1 -0
@@ -0,0 +1,255 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.sendCode = exports.resolveComponentImportFiles = exports.validateDeployContext = exports.validateConsent = exports.ExtractedFileType = void 0;
49
+ const chalk_1 = __importDefault(require("chalk"));
50
+ const path_1 = __importDefault(require("path"));
51
+ const fs_1 = __importDefault(require("fs"));
52
+ const ts = __importStar(require("typescript"));
53
+ const core_1 = require("@sitecore-content-sdk/core");
54
+ /**
55
+ * Type of file to be sent to the mesh endpoint
56
+ */
57
+ var ExtractedFileType;
58
+ (function (ExtractedFileType) {
59
+ ExtractedFileType["Component"] = "component";
60
+ ExtractedFileType["Json"] = "json";
61
+ ExtractedFileType["Package"] = "package.json";
62
+ })(ExtractedFileType || (exports.ExtractedFileType = ExtractedFileType = {}));
63
+ /**
64
+ * Validates consent for code extraction procedures
65
+ * @returns {boolean} - true if consent is given, false otherwise
66
+ */
67
+ const validateConsent = () => {
68
+ if (!process.env.EXTRACT_CONSENT) {
69
+ console.log(chalk_1.default.yellow('EXTRACT_CONSENT is not set'));
70
+ return false;
71
+ }
72
+ return true;
73
+ };
74
+ exports.validateConsent = validateConsent;
75
+ /**
76
+ * Validates if the current operation is done in Vercel, Netlify or XMCloud
77
+ * deploy context
78
+ * @returns {boolean} - true if in deploy context, false otherwise
79
+ */
80
+ const validateDeployContext = () => {
81
+ if (process.env.NETLIFY && process.env.BUILD_ID) {
82
+ return true;
83
+ }
84
+ // workaround, Vercel does not have variables that are only accessible at build time
85
+ if (process.env.VERCEL && !process.env.VERCEL_REGION) {
86
+ return true;
87
+ }
88
+ if (process.env.SITECORE && process.env.BuildMetadata_BuildId) {
89
+ return true;
90
+ }
91
+ return false;
92
+ };
93
+ exports.validateDeployContext = validateDeployContext;
94
+ /**
95
+ * Parses the componentBuilder.ts file and returns a map of component names
96
+ * and their respective import strings
97
+ * @param {string} appPath path to the JSS app root
98
+ * @param {string} [componentMapPath] path to the app's component map file. Default: 'src/lib/componentMap.ts'
99
+ * @returns map of component names and their respective import strings
100
+ */
101
+ const resolveComponentImportFiles = (appPath, componentMapPath = './src/lib/componentMap.ts') => {
102
+ appPath = path_1.default.isAbsolute(appPath) ? appPath : path_1.default.resolve(process.cwd(), appPath);
103
+ const tsConfig = ts.readConfigFile(path_1.default.resolve(appPath, 'tsconfig.json'), ts.sys.readFile);
104
+ if (tsConfig.error) {
105
+ throw new Error(`Error reading tsconfig.json from JSS app root: ${tsConfig.error.messageText}`);
106
+ }
107
+ const componentMapFullPath = path_1.default.isAbsolute(componentMapPath)
108
+ ? componentMapPath
109
+ : path_1.default.resolve(appPath, componentMapPath);
110
+ const cliCompilerOptions = Object.assign(Object.assign({}, tsConfig.config.compilerOptions), { baseUrl: appPath });
111
+ const tsHost = ts.createCompilerHost(cliCompilerOptions, true);
112
+ const componentMapSourceFile = tsHost.getSourceFile(componentMapFullPath, ts.ScriptTarget.Latest, (msg) => {
113
+ throw new Error(`Failed to parse ${componentMapFullPath}: ${msg}`);
114
+ });
115
+ if (!componentMapSourceFile)
116
+ throw ReferenceError(`Failed to find file ${componentMapFullPath}`);
117
+ // this map matches all raw import strings (i.e. * as component) to import strings
118
+ const importStringsMap = {};
119
+ // this map will match component names only to full resolved source file paths
120
+ const componentImportsMap = new Map();
121
+ let mapExportName = '';
122
+ // all new xyz() statements in file
123
+ const newAssignments = [];
124
+ // all map.set() assignments in file
125
+ const mapAssignments = [];
126
+ // this function will traverse the map = new Map([/values/]) statement
127
+ // and get the component names registered in map from it
128
+ const traverseNewStatement = (node) => {
129
+ // going through map invocation, we're looking for outer array value
130
+ if (ts.isArrayLiteralExpression(node)) {
131
+ ts.forEachChild(node, (childNode) => {
132
+ // and then parse each individual array pair (i.e. ['MyComp', MyComp])
133
+ if (!ts.isArrayLiteralExpression(childNode)) {
134
+ return;
135
+ }
136
+ const componentKey = childNode.elements[1].getText();
137
+ const componentImport = Object.keys(importStringsMap).find((importStatement) => {
138
+ const matcher = new RegExp(`\\b(${componentKey})\\b`);
139
+ return importStatement.match(matcher) !== null;
140
+ });
141
+ if (componentImport) {
142
+ const componentValue = importStringsMap[componentImport];
143
+ componentImportsMap.set(componentKey, componentValue);
144
+ }
145
+ });
146
+ }
147
+ else if (node.getChildCount() > 0) {
148
+ ts.forEachChild(node, (childNode) => {
149
+ traverseNewStatement(childNode);
150
+ });
151
+ }
152
+ };
153
+ // step 1: get all import statements, map assignments (map.set) and map inits (map = new Map()) from componentMap file
154
+ ts.forEachChild(componentMapSourceFile, (childNode) => {
155
+ var _a;
156
+ // first, all import statements are parsed
157
+ if (ts.isImportDeclaration(childNode) && childNode.importClause) {
158
+ // import path is extracted
159
+ const moduleName = childNode.moduleSpecifier.getText().replace(/['"]/g, '');
160
+ // unless the import is a nodeJS one, or points to dependency package, resolve full path to the imported source file
161
+ if (moduleName.startsWith('node:') || moduleName.indexOf('/node_modules') > -1) {
162
+ return;
163
+ }
164
+ const resolvedModule = ts.nodeModuleNameResolver(moduleName, componentMapFullPath, cliCompilerOptions, tsHost);
165
+ const resolvedFile = (_a = resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.resolvedModule) === null || _a === void 0 ? void 0 : _a.resolvedFileName;
166
+ // module imports will be resolved to /node_modules location - we don't support that yet
167
+ if (resolvedFile && resolvedFile.indexOf('node_modules') === -1) {
168
+ importStringsMap[childNode.importClause.getText()] = path_1.default.resolve(resolvedFile);
169
+ }
170
+ else {
171
+ console.warn('Could not resolve a file for import %s', moduleName);
172
+ }
173
+ }
174
+ else if (ts.isExpressionStatement(childNode)) {
175
+ // parse map assignments (map.set(..)) to get registered components
176
+ ts.forEachChild(childNode, (expressionNode) => {
177
+ if (ts.isCallExpression(expressionNode) &&
178
+ expressionNode.expression.getText().indexOf('set') !== -1) {
179
+ // get map.set assignments
180
+ mapAssignments.push(expressionNode);
181
+ }
182
+ });
183
+ }
184
+ else if (ts.isExportAssignment(childNode)) {
185
+ // get component map export variable
186
+ mapExportName = childNode.expression.getText();
187
+ }
188
+ else if (childNode.kind === ts.SyntaxKind.FirstStatement) {
189
+ // get potential map = new Map() assignments to extract initial component values from
190
+ newAssignments.push(childNode);
191
+ }
192
+ });
193
+ // step 2: parse map assignments (from map.set and the new Map()) and retrieve import paths
194
+ // only for components registered into component map
195
+ for (const mapAssignment of newAssignments) {
196
+ // parse new Map() statement first
197
+ // only consider variable name for map that is exported
198
+ if (
199
+ // get the (maybe) exported new Map() statement
200
+ // matches i.e. export const map.. / export default const map.. / let map = .. / etc
201
+ mapAssignment
202
+ .getText()
203
+ .match(`^((export )|(export default ))?\\b(var|let|const)\\b\\s{1}\\b(${mapExportName})\\b`)) {
204
+ traverseNewStatement(mapAssignment);
205
+ break;
206
+ }
207
+ }
208
+ for (const mapAssignment of mapAssignments) {
209
+ // only consider the map variable that is exported
210
+ if (mapAssignment.getText().startsWith(mapExportName)) {
211
+ const componentKey = mapAssignment.arguments[1].getText();
212
+ const componentImport = Object.keys(importStringsMap).find((importStatement) => {
213
+ const matcher = new RegExp(`\\b(${componentKey})\\b`);
214
+ return importStatement.match(matcher) !== null;
215
+ });
216
+ if (componentImport) {
217
+ const componentValue = importStringsMap[componentImport];
218
+ componentImportsMap.set(componentKey, componentValue);
219
+ }
220
+ }
221
+ }
222
+ return componentImportsMap;
223
+ };
224
+ exports.resolveComponentImportFiles = resolveComponentImportFiles;
225
+ const sendCode = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file, token, edgeUrl, }) {
226
+ const meshEndpoint = `${edgeUrl || core_1.constants.SITECORE_EDGE_URL_DEFAULT}/api/v1/mesh`;
227
+ if (!fs_1.default.existsSync(file.path)) {
228
+ console.error(chalk_1.default.red(`Component file not found: ${file.path}`));
229
+ return;
230
+ }
231
+ const code = fs_1.default.readFileSync(file.path);
232
+ const response = yield fetch(meshEndpoint, {
233
+ method: 'POST',
234
+ headers: {
235
+ Authorization: `Bearer ${token}`,
236
+ 'Content-Type': 'application/json',
237
+ },
238
+ body: JSON.stringify({
239
+ name: file.name,
240
+ content: code.toString(),
241
+ labels: {
242
+ properties: {
243
+ type: file.type,
244
+ },
245
+ },
246
+ }),
247
+ });
248
+ if (!response.ok) {
249
+ console.error(chalk_1.default.red(`Failed to send extracted code from ${file.path}: ${response.statusText}`));
250
+ }
251
+ else {
252
+ console.log(chalk_1.default.green(`Code from ${file.path} extracted and sent to mesh endpoint`));
253
+ }
254
+ });
255
+ exports.sendCode = sendCode;
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ModuleType = exports.generatePlugins = exports.getComponentList = exports.generateMetadata = exports.generateSites = void 0;
3
+ exports.extractComponents = exports.ModuleType = exports.generatePlugins = exports.getComponentList = exports.generateMetadata = exports.generateSites = void 0;
4
4
  var tools_1 = require("@sitecore-content-sdk/core/tools");
5
5
  Object.defineProperty(exports, "generateSites", { enumerable: true, get: function () { return tools_1.generateSites; } });
6
6
  Object.defineProperty(exports, "generateMetadata", { enumerable: true, get: function () { return tools_1.generateMetadata; } });
7
7
  Object.defineProperty(exports, "getComponentList", { enumerable: true, get: function () { return tools_1.getComponentList; } });
8
8
  Object.defineProperty(exports, "generatePlugins", { enumerable: true, get: function () { return tools_1.generatePlugins; } });
9
9
  Object.defineProperty(exports, "ModuleType", { enumerable: true, get: function () { return tools_1.ModuleType; } });
10
+ var extract_components_1 = require("./codegen/extract-components");
11
+ Object.defineProperty(exports, "extractComponents", { enumerable: true, get: function () { return extract_components_1.extractComponents; } });
@@ -10,9 +10,8 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import React, { forwardRef } from 'react';
13
- import PropTypes from 'prop-types';
14
13
  import NextLink from 'next/link';
15
- import { Link as ReactLink, LinkPropTypes, } from '@sitecore-content-sdk/react';
14
+ import { Link as ReactLink, } from '@sitecore-content-sdk/react';
16
15
  /**
17
16
  * Matches relative URLs that end with a file extension.
18
17
  */
@@ -51,4 +50,3 @@ export const Link = forwardRef((props, ref) => {
51
50
  return (React.createElement(ReactLink, Object.assign({}, reactLinkProps, { ref: ref }, (process.env.TEST ? { 'data-react-link': true } : {}))));
52
51
  });
53
52
  Link.displayName = 'NextLink';
54
- Link.propTypes = Object.assign({ internalLinkMatcher: PropTypes.instanceOf(RegExp) }, LinkPropTypes);
@@ -10,15 +10,12 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { mediaApi } from '@sitecore-content-sdk/core/media';
13
- import PropTypes from 'prop-types';
14
13
  import React from 'react';
15
- import { withFieldMetadata, SitecoreContextReactContext, } from '@sitecore-content-sdk/react';
14
+ import { withFieldMetadata, SitecoreContextReactContext, DefaultEmptyFieldEditingComponentImage, withEmptyFieldEditingComponent, } from '@sitecore-content-sdk/react';
16
15
  import Image from 'next/image';
17
- import { withEmptyFieldEditingComponent } from '@sitecore-content-sdk/react';
18
- import { DefaultEmptyFieldEditingComponentImage } from '@sitecore-content-sdk/react';
19
- import { isFieldValueEmpty, LayoutServicePageState } from '@sitecore-content-sdk/core/layout';
16
+ import { isFieldValueEmpty, LayoutServicePageState, RenderingType, } from '@sitecore-content-sdk/core/layout';
20
17
  export const NextImage = withFieldMetadata(withEmptyFieldEditingComponent((_a) => {
21
- var _b;
18
+ var _b, _c;
22
19
  var { editable = true, imageParams, field, mediaUrlPrefix, fill, priority } = _a, otherProps = __rest(_a, ["editable", "imageParams", "field", "mediaUrlPrefix", "fill", "priority"]);
23
20
  const sitecoreContext = React.useContext(SitecoreContextReactContext);
24
21
  // next handles src and we use a custom loader,
@@ -37,9 +34,10 @@ export const NextImage = withFieldMetadata(withEmptyFieldEditingComponent((_a) =
37
34
  if (!img) {
38
35
  return null;
39
36
  }
40
- // disable image optimization for Edit and Preview, but preserve original value if true
37
+ // disable image optimization for Edit / Preview / Component rendering, but preserve original value if true
41
38
  const unoptimized = otherProps.unoptimized ||
42
- ((_b = sitecoreContext.context) === null || _b === void 0 ? void 0 : _b.pageState) !== LayoutServicePageState.Normal;
39
+ ((_b = sitecoreContext.context) === null || _b === void 0 ? void 0 : _b.renderingType) === RenderingType.Component ||
40
+ ((_c = sitecoreContext.context) === null || _c === void 0 ? void 0 : _c.pageState) !== LayoutServicePageState.Normal;
43
41
  const attrs = Object.assign(Object.assign(Object.assign({}, img), otherProps), { fill,
44
42
  priority, src: mediaApi.updateImageUrl(img.src, imageParams, mediaUrlPrefix), unoptimized });
45
43
  const imageProps = Object.assign(Object.assign({}, attrs), {
@@ -56,21 +54,4 @@ export const NextImage = withFieldMetadata(withEmptyFieldEditingComponent((_a) =
56
54
  }
57
55
  return null; // we can't handle the truth
58
56
  }, { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentImage }));
59
- NextImage.propTypes = {
60
- field: PropTypes.oneOfType([
61
- PropTypes.shape({
62
- src: PropTypes.string.isRequired,
63
- }),
64
- PropTypes.shape({
65
- value: PropTypes.object,
66
- }),
67
- ]),
68
- editable: PropTypes.bool,
69
- mediaUrlPrefix: PropTypes.instanceOf(RegExp),
70
- imageParams: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]).isRequired),
71
- emptyFieldEditingComponent: PropTypes.oneOfType([
72
- PropTypes.object,
73
- PropTypes.func,
74
- ]),
75
- };
76
57
  NextImage.displayName = 'NextImage';
@@ -10,9 +10,8 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import React, { useEffect, useRef } from 'react';
13
- import PropTypes from 'prop-types';
14
13
  import { useRouter } from 'next/router';
15
- import { RichText as ReactRichText, RichTextPropTypes, } from '@sitecore-content-sdk/react';
14
+ import { RichText as ReactRichText, } from '@sitecore-content-sdk/react';
16
15
  export const prefetched = {};
17
16
  export const RichText = (props) => {
18
17
  const { internalLinksSelector = 'a[href^="/"]', prefetchLinks = true, editable = true } = props, rest = __rest(props, ["internalLinksSelector", "prefetchLinks", "editable"]);
@@ -63,5 +62,4 @@ export const RichText = (props) => {
63
62
  };
64
63
  return React.createElement(ReactRichText, Object.assign({ ref: richTextRef, editable: editable }, rest));
65
64
  };
66
- RichText.propTypes = Object.assign({ internalLinksSelector: PropTypes.string }, RichTextPropTypes);
67
65
  RichText.displayName = 'NextRichText';
@@ -0,0 +1,20 @@
1
+ import { defineConfig as defineConfigCore, } from '@sitecore-content-sdk/core/config';
2
+ /**
3
+ * Provides default NextJs initial values from env variables for SitecoreConfig
4
+ * @param {SitecoreConfigInput} config optional override values to be written over default config settings
5
+ * @returns default nextjs input config
6
+ */
7
+ export const getNextFallbackConfig = (config) => {
8
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
9
+ return Object.assign(Object.assign({}, config), { api: Object.assign(Object.assign({}, config === null || config === void 0 ? void 0 : config.api), { edge: Object.assign(Object.assign({}, (_a = config === null || config === void 0 ? void 0 : config.api) === null || _a === void 0 ? void 0 : _a.edge), { contextId: ((_c = (_b = config === null || config === void 0 ? void 0 : config.api) === null || _b === void 0 ? void 0 : _b.edge) === null || _c === void 0 ? void 0 : _c.contextId) || process.env.NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID || '', clientContextId: ((_e = (_d = config === null || config === void 0 ? void 0 : config.api) === null || _d === void 0 ? void 0 : _d.edge) === null || _e === void 0 ? void 0 : _e.clientContextId) || process.env.NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID, edgeUrl: ((_g = (_f = config === null || config === void 0 ? void 0 : config.api) === null || _f === void 0 ? void 0 : _f.edge) === null || _g === void 0 ? void 0 : _g.edgeUrl) || process.env.NEXT_PUBLIC_SITECORE_EDGE_URL }), local: Object.assign(Object.assign({}, (_h = config === null || config === void 0 ? void 0 : config.api) === null || _h === void 0 ? void 0 : _h.local), { apiKey: ((_k = (_j = config === null || config === void 0 ? void 0 : config.api) === null || _j === void 0 ? void 0 : _j.local) === null || _k === void 0 ? void 0 : _k.apiKey) || process.env.NEXT_PUBLIC_SITECORE_API_KEY || '', apiHost: ((_m = (_l = config === null || config === void 0 ? void 0 : config.api) === null || _l === void 0 ? void 0 : _l.local) === null || _m === void 0 ? void 0 : _m.apiHost) || process.env.NEXT_PUBLIC_SITECORE_API_HOST || '' }) }), defaultSite: (config === null || config === void 0 ? void 0 : config.defaultSite) || process.env.NEXT_PUBLIC_SITECORE_SITE_NAME || '', defaultLanguage: (config === null || config === void 0 ? void 0 : config.defaultLanguage) || process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE || 'en', multisite: Object.assign(Object.assign({}, config === null || config === void 0 ? void 0 : config.multisite), { useCookieResolution: (_p = (_o = config === null || config === void 0 ? void 0 : config.multisite) === null || _o === void 0 ? void 0 : _o.useCookieResolution) !== null && _p !== void 0 ? _p : (() => process.env.VERCEL_ENV === 'preview') }), personalize: Object.assign(Object.assign({}, config === null || config === void 0 ? void 0 : config.personalize), { scope: ((_q = config === null || config === void 0 ? void 0 : config.personalize) === null || _q === void 0 ? void 0 : _q.scope) || process.env.NEXT_PUBLIC_PERSONALIZE_SCOPE }), disableStaticPaths: process.env.DISABLE_SSG_FETCH !== undefined
10
+ ? process.env.DISABLE_SSG_FETCH.toLowerCase() === 'true'
11
+ : (_r = config === null || config === void 0 ? void 0 : config.disableStaticPaths) !== null && _r !== void 0 ? _r : false });
12
+ };
13
+ /**
14
+ * Accepts a SitecoreConfigInput object and returns full sitecore configuration
15
+ * @param {SitecoreConfigInput} config override values to be written over default config settings
16
+ * @returns {SitecoreConfig} full sitecore configuration to use in application
17
+ */
18
+ export const defineConfig = (config) => {
19
+ return defineConfigCore(getNextFallbackConfig(config));
20
+ };
@@ -1,2 +1,2 @@
1
- export { defineConfig, } from '@sitecore-content-sdk/core/config';
2
1
  export { defineCliConfig } from './define-cli-config';
2
+ export { defineConfig } from './define-config';
@@ -101,7 +101,7 @@ export class EditingRenderMiddleware extends RenderMiddlewareBase {
101
101
  language: query.sc_lang,
102
102
  site: query.sc_site,
103
103
  mode: 'library',
104
- dataSourceId: query.sc_datasourceId,
104
+ dataSourceId: query.dataSourceId,
105
105
  version: query.sc_version,
106
106
  }, {
107
107
  maxAge: 3,
package/dist/esm/index.js CHANGED
@@ -5,10 +5,10 @@ export { LayoutServicePageState, GraphQLLayoutService, getChildPlaceholder, getF
5
5
  export { RestComponentLayoutService } from '@sitecore-content-sdk/core/editing';
6
6
  export { mediaApi } from '@sitecore-content-sdk/core/media';
7
7
  export { GraphQLDictionaryService, } from '@sitecore-content-sdk/core/i18n';
8
- export { personalizeLayout, getPersonalizedRewrite, getPersonalizedRewriteData, getGroomedVariantIds, normalizePersonalizedRewrite, CdpHelper, } from '@sitecore-content-sdk/core/personalize';
9
- export { ComponentPropsService } from './services/component-props-service';
10
- export { GraphQLSitePathService, } from '@sitecore-content-sdk/core/site';
8
+ export { personalizeLayout, getPersonalizedRewrite, getPersonalizedRewriteData, getGroomedVariantIds, normalizePersonalizedRewrite, CdpHelper, GraphQLPersonalizeService, } from '@sitecore-content-sdk/core/personalize';
9
+ export { GraphQLSitePathService, GraphQLRedirectsService, REDIRECT_TYPE_301, REDIRECT_TYPE_302, REDIRECT_TYPE_SERVER_TRANSFER, } from '@sitecore-content-sdk/core/site';
11
10
  export { GraphQLSitemapXmlService, GraphQLErrorPagesService, GraphQLRobotsService, SiteResolver, GraphQLSiteInfoService, getSiteRewrite, getSiteRewriteData, normalizeSiteRewrite, } from '@sitecore-content-sdk/core/site';
11
+ export { ComponentPropsService } from './services/component-props-service';
12
12
  export { ComponentPropsReactContext, ComponentPropsContext, useComponentProps, } from './components/ComponentPropsContext';
13
13
  export { Link } from './components/Link';
14
14
  export { RichText } from './components/RichText';
@@ -4,3 +4,6 @@ export { RedirectsMiddleware } from './redirects-middleware';
4
4
  export { PersonalizeMiddleware } from './personalize-middleware';
5
5
  export { MultisiteMiddleware } from './multisite-middleware';
6
6
  export { SitemapMiddleware } from './sitemap-middleware';
7
+ export { RobotsMiddleware } from './robots-middleware';
8
+ export { GraphQLPersonalizeService, } from '@sitecore-content-sdk/core/personalize';
9
+ export { GraphQLRedirectsService, REDIRECT_TYPE_301, REDIRECT_TYPE_302, REDIRECT_TYPE_SERVER_TRANSFER, } from '@sitecore-content-sdk/core/site';
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { SITE_KEY, SiteResolver } from '@sitecore-content-sdk/core/site';
11
11
  import { debug } from '@sitecore-content-sdk/core';
12
12
  import { NextResponse } from 'next/server';
13
+ import { createGraphQLClientFactory, } from '@sitecore-content-sdk/core/client';
13
14
  export const REWRITE_HEADER_NAME = 'x-sc-rewrite';
14
15
  /**
15
16
  * Middleware class to be extended by all middleware implementations
@@ -104,6 +105,9 @@ export class MiddlewareBase extends Middleware {
104
105
  }
105
106
  return this.siteResolver.getByHost(hostname);
106
107
  }
108
+ getClientFactory(graphQLOptions) {
109
+ return createGraphQLClientFactory(graphQLOptions);
110
+ }
107
111
  /**
108
112
  * Create a rewrite response
109
113
  * @param {string} rewritePath the destionation path
@@ -20,6 +20,7 @@ export class PersonalizeMiddleware extends MiddlewareBase {
20
20
  * @param {PersonalizeMiddlewareConfig} [config] Personalize middleware config
21
21
  */
22
22
  constructor(config) {
23
+ var _a;
23
24
  super(config);
24
25
  this.config = config;
25
26
  this.handle = (req, res) => __awaiter(this, void 0, void 0, function* () {
@@ -120,14 +121,39 @@ export class PersonalizeMiddleware extends MiddlewareBase {
120
121
  return res;
121
122
  }
122
123
  });
124
+ const graphQLOptions = {
125
+ api: {
126
+ edge: {
127
+ contextId: this.config.contextId,
128
+ clientContextId: this.config.clientContextId,
129
+ edgeUrl: this.config.edgeUrl,
130
+ },
131
+ },
132
+ };
123
133
  // NOTE: we provide native fetch for compatibility on Next.js Edge Runtime
124
134
  // (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
125
- this.personalizeService = new GraphQLPersonalizeService({
126
- clientFactory: this.config.clientFactory,
127
- timeout: this.config.edgeTimeout,
128
- scope: this.config.scope,
129
- fetch: fetch,
130
- });
135
+ this.personalizeService =
136
+ (_a = this.config.personalizeService) !== null && _a !== void 0 ? _a : new GraphQLPersonalizeService({
137
+ clientFactory: this.getClientFactory(graphQLOptions),
138
+ timeout: this.config.edgeTimeout,
139
+ scope: this.config.scope,
140
+ fetch: fetch,
141
+ });
142
+ }
143
+ getExperienceParams(req) {
144
+ const extraParams = this.config.getExtraUtmParams ? this.config.getExtraUtmParams(req) : {};
145
+ const utm = Object.assign({ campaign: req.nextUrl.searchParams.get('utm_campaign') || undefined, content: req.nextUrl.searchParams.get('utm_content') || undefined, medium: req.nextUrl.searchParams.get('utm_medium') || undefined, source: req.nextUrl.searchParams.get('utm_source') || undefined }, extraParams);
146
+ return {
147
+ // It's expected that the header name "referer" is actually a misspelling of the word "referrer"
148
+ // req.referrer is used during fetching to determine the value of the Referer header of the request being made,
149
+ // used as a fallback
150
+ referrer: req.headers.get('referer') || req.referrer,
151
+ utm,
152
+ };
153
+ }
154
+ disabled(req, res) {
155
+ // ignore files
156
+ return req.nextUrl.pathname.includes('.') || super.disabled(req, res);
131
157
  }
132
158
  initPersonalizeServer(_a) {
133
159
  return __awaiter(this, arguments, void 0, function* ({ hostname, siteName, request, response, }) {
@@ -156,25 +182,6 @@ export class PersonalizeMiddleware extends MiddlewareBase {
156
182
  }, { timeout }));
157
183
  });
158
184
  }
159
- getExperienceParams(req) {
160
- const utm = {
161
- campaign: req.nextUrl.searchParams.get('utm_campaign') || undefined,
162
- content: req.nextUrl.searchParams.get('utm_content') || undefined,
163
- medium: req.nextUrl.searchParams.get('utm_medium') || undefined,
164
- source: req.nextUrl.searchParams.get('utm_source') || undefined,
165
- };
166
- return {
167
- // It's expected that the header name "referer" is actually a misspelling of the word "referrer"
168
- // req.referrer is used during fetching to determine the value of the Referer header of the request being made,
169
- // used as a fallback
170
- referrer: req.headers.get('referer') || req.referrer,
171
- utm: utm,
172
- };
173
- }
174
- disabled(req, res) {
175
- // ignore files
176
- return req.nextUrl.pathname.includes('.') || super.disabled(req, res);
177
- }
178
185
  /**
179
186
  * Aggregates personalize executions based on the provided route personalize information and language
180
187
  * @param {PersonalizeInfo} personalizeInfo the route personalize information
@@ -24,6 +24,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
24
24
  * @param {RedirectsMiddlewareConfig} [config] redirects middleware config
25
25
  */
26
26
  constructor(config) {
27
+ var _a;
27
28
  super(config);
28
29
  this.config = config;
29
30
  this.handle = (req, res) => __awaiter(this, void 0, void 0, function* () {
@@ -134,9 +135,19 @@ export class RedirectsMiddleware extends MiddlewareBase {
134
135
  return res;
135
136
  }
136
137
  });
138
+ const graphQLOptions = {
139
+ api: {
140
+ edge: {
141
+ contextId: this.config.contextId,
142
+ clientContextId: this.config.clientContextId,
143
+ edgeUrl: this.config.edgeUrl,
144
+ },
145
+ },
146
+ };
137
147
  // NOTE: we provide native fetch for compatibility on Next.js Edge Runtime
138
148
  // (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
139
- this.redirectsService = new GraphQLRedirectsService(Object.assign(Object.assign({}, config), { fetch: fetch }));
149
+ this.redirectsService =
150
+ (_a = this.config.redirectsService) !== null && _a !== void 0 ? _a : new GraphQLRedirectsService(Object.assign(Object.assign({}, config), { clientFactory: this.getClientFactory(graphQLOptions), fetch: fetch }));
140
151
  this.locales = config.locales;
141
152
  }
142
153
  /**
@@ -236,9 +247,9 @@ export class RedirectsMiddleware extends MiddlewareBase {
236
247
  return false;
237
248
  })
238
249
  .join('&');
239
- const newUrl = new URL(`${url.pathname}?${newQueryString}`, url.origin);
250
+ const newUrl = new URL(`${url.pathname.toLowerCase()}?${newQueryString}`, url.origin);
240
251
  url.search = newUrl.search;
241
- url.pathname = newUrl.pathname;
252
+ url.pathname = newUrl.pathname.toLocaleLowerCase();
242
253
  url.href = newUrl.href;
243
254
  return url;
244
255
  }
@@ -0,0 +1,38 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ /**
11
+ * Middleware for handling robots.txt requests in a Next.js application.
12
+ */
13
+ export class RobotsMiddleware {
14
+ constructor(client) {
15
+ this.client = client;
16
+ }
17
+ getHandler() {
18
+ return this.handler.bind(this);
19
+ }
20
+ handler(req, res) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ var _a;
23
+ res.setHeader('Content-Type', 'text/plain');
24
+ const hostName = ((_a = req.headers.host) === null || _a === void 0 ? void 0 : _a.split(':')[0]) || 'localhost';
25
+ const site = this.client.resolveSite(hostName);
26
+ try {
27
+ const robotsContent = yield this.client.getRobots(site.name);
28
+ if (!robotsContent) {
29
+ return res.status(404).send('User-agent: *\nDisallow: /');
30
+ }
31
+ res.status(200).send(robotsContent);
32
+ }
33
+ catch (_b) {
34
+ res.status(500).send('Internal Server Error');
35
+ }
36
+ });
37
+ }
38
+ }