@sitecore-content-sdk/core 0.2.0-beta.2 → 0.2.0-beta.21

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 (88) hide show
  1. package/content.d.ts +1 -0
  2. package/content.js +1 -0
  3. package/dist/cjs/client/graphql-edge-proxy.js +3 -3
  4. package/dist/cjs/client/sitecore-client.js +34 -17
  5. package/dist/cjs/config/define-config.js +6 -5
  6. package/dist/cjs/constants.js +12 -1
  7. package/dist/cjs/content/content-client.js +148 -0
  8. package/dist/cjs/content/index.js +13 -0
  9. package/dist/cjs/content/locales.js +32 -0
  10. package/dist/cjs/content/taxonomies.js +78 -0
  11. package/dist/cjs/content/utils.js +16 -0
  12. package/dist/cjs/debug.js +1 -0
  13. package/dist/cjs/editing/design-library.js +2 -1
  14. package/dist/cjs/editing/rest-component-layout-service.js +26 -45
  15. package/dist/cjs/index.js +3 -1
  16. package/dist/cjs/layout/content-styles.js +2 -1
  17. package/dist/cjs/layout/themes.js +2 -1
  18. package/dist/cjs/site/graphql-robots-service.js +3 -2
  19. package/dist/cjs/tools/auth/encryption.js +141 -0
  20. package/dist/cjs/tools/auth/fetcher.js +34 -0
  21. package/dist/cjs/tools/auth/flow.js +123 -0
  22. package/dist/cjs/tools/auth/index.js +27 -0
  23. package/dist/cjs/tools/auth/models.js +2 -0
  24. package/dist/cjs/tools/auth/renewal.js +130 -0
  25. package/dist/cjs/tools/auth/tenant-state.js +110 -0
  26. package/dist/cjs/tools/auth/tenant-store.js +250 -0
  27. package/dist/cjs/tools/index.js +26 -1
  28. package/dist/cjs/utils/normalize-url.js +5 -0
  29. package/dist/cjs/utils/utils.js +5 -3
  30. package/dist/esm/client/graphql-edge-proxy.js +1 -1
  31. package/dist/esm/client/sitecore-client.js +34 -17
  32. package/dist/esm/config/define-config.js +6 -5
  33. package/dist/esm/constants.js +11 -0
  34. package/dist/esm/content/content-client.js +141 -0
  35. package/dist/esm/content/index.js +4 -0
  36. package/dist/esm/content/locales.js +29 -0
  37. package/dist/esm/content/taxonomies.js +75 -0
  38. package/dist/esm/content/utils.js +13 -0
  39. package/dist/esm/debug.js +1 -0
  40. package/dist/esm/editing/design-library.js +2 -1
  41. package/dist/esm/editing/rest-component-layout-service.js +23 -45
  42. package/dist/esm/index.js +2 -0
  43. package/dist/esm/layout/content-styles.js +2 -1
  44. package/dist/esm/layout/themes.js +2 -1
  45. package/dist/esm/site/graphql-robots-service.js +3 -2
  46. package/dist/esm/tools/auth/encryption.js +101 -0
  47. package/dist/esm/tools/auth/fetcher.js +31 -0
  48. package/dist/esm/tools/auth/flow.js +118 -0
  49. package/dist/esm/tools/auth/index.js +5 -0
  50. package/dist/esm/tools/auth/models.js +1 -0
  51. package/dist/esm/tools/auth/renewal.js +124 -0
  52. package/dist/esm/tools/auth/tenant-state.js +73 -0
  53. package/dist/esm/tools/auth/tenant-store.js +213 -0
  54. package/dist/esm/tools/index.js +3 -0
  55. package/dist/esm/utils/normalize-url.js +1 -0
  56. package/dist/esm/utils/utils.js +5 -3
  57. package/package.json +19 -18
  58. package/types/client/index.d.ts +1 -1
  59. package/types/client/models.d.ts +17 -1
  60. package/types/client/sitecore-client.d.ts +50 -22
  61. package/types/config/index.d.ts +1 -1
  62. package/types/config/models.d.ts +12 -2
  63. package/types/constants.d.ts +10 -0
  64. package/types/content/content-client.d.ts +92 -0
  65. package/types/content/index.d.ts +4 -0
  66. package/types/content/locales.d.ts +38 -0
  67. package/types/content/taxonomies.d.ts +125 -0
  68. package/types/content/utils.d.ts +15 -0
  69. package/types/debug.d.ts +1 -0
  70. package/types/editing/rest-component-layout-service.d.ts +23 -58
  71. package/types/index.d.ts +2 -0
  72. package/types/native-fetcher.d.ts +0 -7
  73. package/types/site/graphql-robots-service.d.ts +3 -2
  74. package/types/tools/auth/encryption.d.ts +34 -0
  75. package/types/tools/auth/fetcher.d.ts +13 -0
  76. package/types/tools/auth/flow.d.ts +40 -0
  77. package/types/tools/auth/index.d.ts +5 -0
  78. package/types/tools/auth/models.d.ts +233 -0
  79. package/types/tools/auth/renewal.d.ts +36 -0
  80. package/types/tools/auth/tenant-state.d.ts +21 -0
  81. package/types/tools/auth/tenant-store.d.ts +63 -0
  82. package/types/tools/index.d.ts +3 -0
  83. package/types/utils/normalize-url.d.ts +1 -0
  84. package/dist/cjs/data-fetcher.js +0 -22
  85. package/dist/esm/data-fetcher.js +0 -17
  86. package/form.d.ts +0 -1
  87. package/form.js +0 -1
  88. package/types/data-fetcher.d.ts +0 -34
@@ -0,0 +1,250 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.unitMocks = exports.getAllTenantsInfo = exports.deleteTenantAuthInfo = exports.readTenantInfo = exports.writeTenantInfo = exports.readTenantAuthInfo = exports.writeTenantAuthInfo = exports.decodeJwtPayload = void 0;
37
+ exports.getTenantPath = getTenantPath;
38
+ /* eslint-disable jsdoc/require-jsdoc */
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const os = __importStar(require("os"));
42
+ const encryption_1 = require("./encryption");
43
+ const constants_1 = require("./../../constants");
44
+ const rootDir = path.join(os.homedir(), '.sitecore', 'sitecore-tools');
45
+ /**
46
+ * Decodes a JWT without verifying its signature.
47
+ * @param {string} token - The access token string.
48
+ * @returns Decoded payload object or null if invalid.
49
+ */
50
+ exports.decodeJwtPayload = _decodeJwtPayload;
51
+ /**
52
+ * Write the authentication configuration for a tenant.
53
+ * @param {string} tenantId - The tenant ID.
54
+ * @param {TenantAuth} authInfo - The tenant's auth data.
55
+ */
56
+ exports.writeTenantAuthInfo = _writeTenantAuthInfo;
57
+ /**
58
+ * Read the authentication configuration for a tenant.
59
+ * @param {string} tenantId - The tenant ID.
60
+ * @returns Parsed auth config or null if not found or failed to read.
61
+ */
62
+ exports.readTenantAuthInfo = _readTenantAuthInfo;
63
+ /**
64
+ * Write the public metadata information for a tenant.
65
+ * @param {TenantInfo} info - The tenant info object.
66
+ */
67
+ exports.writeTenantInfo = _writeTenantInfo;
68
+ /**
69
+ * Read the public metadata information for a tenant.
70
+ * @param {string} tenantId - The tenant ID.
71
+ * @returns Parsed tenant info or null if not found or failed to read.
72
+ */
73
+ exports.readTenantInfo = _readTenantInfo;
74
+ /**
75
+ * Deletes the stored auth.json file for the given tenant.
76
+ * @param {string} tenantId - The tenant ID.
77
+ */
78
+ exports.deleteTenantAuthInfo = _deleteTenantAuthInfo;
79
+ /**
80
+ * Scans the CLI root directory and returns all valid tenant infos.
81
+ * @returns A list of TenantInfo objects found in {tenant-id}/info.json files.
82
+ */
83
+ exports.getAllTenantsInfo = _getAllTenantsInfo;
84
+ // mock setup for unit tests to make sinon happy and mock-able with esbuild/tsx
85
+ // https://sinonjs.org/how-to/typescript-swc/
86
+ // This, plus the `_` names make the exports writable for sinon
87
+ exports.unitMocks = {
88
+ set decodeJwtPayload(mockImplementation) {
89
+ exports.decodeJwtPayload = mockImplementation;
90
+ },
91
+ get decodeJwtPayload() {
92
+ return _decodeJwtPayload;
93
+ },
94
+ set writeTenantAuthInfo(mockImplementation) {
95
+ exports.writeTenantAuthInfo = mockImplementation;
96
+ },
97
+ get writeTenantAuthInfo() {
98
+ return _writeTenantAuthInfo;
99
+ },
100
+ set readTenantAuthInfo(mockImplementation) {
101
+ exports.readTenantAuthInfo = mockImplementation;
102
+ },
103
+ get readTenantAuthInfo() {
104
+ return _readTenantAuthInfo;
105
+ },
106
+ set writeTenantInfo(mockImplementation) {
107
+ exports.writeTenantInfo = mockImplementation;
108
+ },
109
+ get writeTenantInfo() {
110
+ return _writeTenantInfo;
111
+ },
112
+ set readTenantInfo(mockImplementation) {
113
+ exports.readTenantInfo = mockImplementation;
114
+ },
115
+ get readTenantInfo() {
116
+ return _readTenantInfo;
117
+ },
118
+ set deleteTenantAuthInfo(mockImplementation) {
119
+ exports.deleteTenantAuthInfo = mockImplementation;
120
+ },
121
+ get deleteTenantAuthInfo() {
122
+ return _deleteTenantAuthInfo;
123
+ },
124
+ set getAllTenantsInfo(mockImplementation) {
125
+ exports.getAllTenantsInfo = mockImplementation;
126
+ },
127
+ get getAllTenantsInfo() {
128
+ return _getAllTenantsInfo;
129
+ },
130
+ };
131
+ /**
132
+ * Get the full path to the tenant-specific folder.
133
+ * @param {string} tenantId - The tenant ID.
134
+ * @returns The absolute path to the tenant directory.
135
+ */
136
+ function getTenantPath(tenantId) {
137
+ return path.join(rootDir, tenantId);
138
+ }
139
+ async function _writeTenantAuthInfo(tenantId, authInfo) {
140
+ try {
141
+ const dir = getTenantPath(tenantId);
142
+ fs.mkdirSync(dir, { recursive: true });
143
+ const encrypted = await (0, encryption_1.encryptData)(JSON.stringify(authInfo), tenantId);
144
+ fs.writeFileSync(path.join(dir, 'auth.json'), JSON.stringify(encrypted));
145
+ }
146
+ catch (error) {
147
+ console.error(`\n Failed to write auth.json for tenant '${tenantId}': ${error.message}`);
148
+ }
149
+ }
150
+ async function _readTenantAuthInfo(tenantId) {
151
+ const filePath = path.join(getTenantPath(tenantId), 'auth.json');
152
+ if (!fs.existsSync(filePath))
153
+ return null;
154
+ try {
155
+ const encryptedPayloadRaw = fs.readFileSync(filePath, 'utf8');
156
+ const encryptedPayload = JSON.parse(encryptedPayloadRaw);
157
+ const decryptedData = await (0, encryption_1.decryptData)(encryptedPayload, tenantId, true);
158
+ if (decryptedData === null) {
159
+ return null;
160
+ }
161
+ return JSON.parse(decryptedData);
162
+ }
163
+ catch (error) {
164
+ console.error(`\n Failed to read auth.json for tenant '${tenantId}': ${error.message}`);
165
+ return null;
166
+ }
167
+ }
168
+ async function _writeTenantInfo(info) {
169
+ try {
170
+ const dir = getTenantPath(info.tenantId);
171
+ fs.mkdirSync(dir, { recursive: true });
172
+ fs.writeFileSync(path.join(dir, 'info.json'), JSON.stringify(info, null, 2));
173
+ }
174
+ catch (error) {
175
+ console.error(`\n Failed to write info.json for tenant '${info.tenantId}': ${error.message}`);
176
+ }
177
+ }
178
+ async function _readTenantInfo(tenantId) {
179
+ const infoFilePath = path.join(getTenantPath(tenantId), 'info.json');
180
+ if (!fs.existsSync(infoFilePath)) {
181
+ return null;
182
+ }
183
+ try {
184
+ const content = fs.readFileSync(infoFilePath, 'utf-8');
185
+ return JSON.parse(content);
186
+ }
187
+ catch (error) {
188
+ console.error(`\n Failed to read info.json for tenant '${tenantId}': ${error.message}`);
189
+ return null;
190
+ }
191
+ }
192
+ async function _deleteTenantAuthInfo(tenantId) {
193
+ const filePath = path.join(getTenantPath(tenantId), 'auth.json');
194
+ try {
195
+ if (fs.existsSync(filePath)) {
196
+ fs.unlinkSync(filePath);
197
+ }
198
+ }
199
+ catch (error) {
200
+ console.error(`\n Failed to delete auth.json for tenant '${tenantId}': ${error.message}`);
201
+ }
202
+ }
203
+ function _getAllTenantsInfo() {
204
+ if (!fs.existsSync(rootDir))
205
+ return [];
206
+ const subDirs = fs
207
+ .readdirSync(rootDir)
208
+ .filter((entry) => fs.statSync(path.join(rootDir, entry)).isDirectory());
209
+ const tenants = [];
210
+ for (const dir of subDirs) {
211
+ const infoPath = path.join(rootDir, dir, 'info.json');
212
+ if (fs.existsSync(infoPath)) {
213
+ try {
214
+ const content = fs.readFileSync(infoPath, 'utf-8');
215
+ const data = JSON.parse(content);
216
+ if (data.tenantId && data.tenantName && data.organizationId) {
217
+ tenants.push({
218
+ tenantId: data.tenantId,
219
+ tenantName: data.tenantName,
220
+ organizationId: data.organizationId,
221
+ clientId: data.clientId,
222
+ authority: data.authority,
223
+ audience: data.audience,
224
+ baseUrl: data.baseUrl,
225
+ });
226
+ }
227
+ }
228
+ catch (error) {
229
+ console.error('\n Failed to read tenant info file', error.message);
230
+ }
231
+ }
232
+ }
233
+ return tenants;
234
+ }
235
+ function _decodeJwtPayload(token) {
236
+ try {
237
+ const base64Payload = token.split('.')[1];
238
+ const payload = Buffer.from(base64Payload, 'base64').toString('utf-8');
239
+ const decoded = JSON.parse(payload);
240
+ return {
241
+ tokenTenantId: decoded === null || decoded === void 0 ? void 0 : decoded[`${constants_1.CLAIMS}/tenant_id`],
242
+ tokenOrgId: decoded === null || decoded === void 0 ? void 0 : decoded[`${constants_1.CLAIMS}/org_id`],
243
+ tokenTenantName: decoded === null || decoded === void 0 ? void 0 : decoded[`${constants_1.CLAIMS}/tenant_name`],
244
+ };
245
+ }
246
+ catch (error) {
247
+ console.error('\n Failed to decode access token:', error.message);
248
+ return null;
249
+ }
250
+ }
@@ -10,11 +10,33 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
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
+ });
13
18
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
20
  };
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
16
38
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.scaffoldComponent = exports.generateMetadata = exports.generateSites = void 0;
39
+ exports.auth = exports.scaffoldComponent = exports.generateMetadata = exports.generateSites = void 0;
18
40
  var generateSites_1 = require("./generateSites");
19
41
  Object.defineProperty(exports, "generateSites", { enumerable: true, get: function () { return generateSites_1.generateSites; } });
20
42
  var generateMetadata_1 = require("./generateMetadata");
@@ -22,3 +44,6 @@ Object.defineProperty(exports, "generateMetadata", { enumerable: true, get: func
22
44
  var scaffold_1 = require("./scaffold");
23
45
  Object.defineProperty(exports, "scaffoldComponent", { enumerable: true, get: function () { return scaffold_1.scaffoldComponent; } });
24
46
  __exportStar(require("./templating"), exports);
47
+ __exportStar(require("./auth/models"), exports);
48
+ const auth = __importStar(require("./auth"));
49
+ exports.auth = auth;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeUrl = void 0;
4
+ const normalizeUrl = (url) => (url.endsWith('/') ? url.slice(0, -1) : url);
5
+ exports.normalizeUrl = normalizeUrl;
@@ -173,7 +173,7 @@ exports.areURLSearchParamsEqual = areURLSearchParamsEqual;
173
173
  * @returns {string} - The modified string or regex with non-special "?" characters escaped.
174
174
  */
175
175
  const escapeNonSpecialQuestionMarks = (input) => {
176
- const regexPattern = /(?<!\\)\?/g; // Match unescaped "?" characters
176
+ const regexPattern = /(\\)?\?/g; // Match "?" that may or may not be preceded by a backslash
177
177
  const negativeLookaheadPattern = /\(\?!$/; // Detect the start of a Negative Lookahead pattern
178
178
  const specialRegexSymbols = /[.*+)\[\]|\(]$/; // Check for special regex symbols before "?"
179
179
  let result = '';
@@ -182,12 +182,14 @@ const escapeNonSpecialQuestionMarks = (input) => {
182
182
  while ((match = regexPattern.exec(input)) !== null) {
183
183
  const index = match.index; // Position of the "?" in the string
184
184
  const before = input.slice(lastIndex, index); // Context before the "?"
185
+ // Check if "?" is preceded by a backslash (escaped)
186
+ const isEscaped = match[1] !== undefined; // match[1] is the backslash group
185
187
  // Check if "?" is part of a Negative Lookahead
186
188
  const isNegativeLookahead = negativeLookaheadPattern.test(before.slice(-3));
187
189
  // Check if "?" follows a special regex symbol
188
190
  const isSpecialRegexSymbol = specialRegexSymbols.test(before.slice(-1));
189
- if (isNegativeLookahead || isSpecialRegexSymbol) {
190
- // If it's a special case, keep the "?" as is
191
+ if (isEscaped || isNegativeLookahead || isSpecialRegexSymbol) {
192
+ // If it's escaped, part of a Negative Lookahead, or follows a special regex symbol, keep the "?" as is
191
193
  result += input.slice(lastIndex, index + 1);
192
194
  }
193
195
  else {
@@ -1,5 +1,5 @@
1
1
  import { SITECORE_EDGE_URL_DEFAULT } from '../constants';
2
- const normalizeUrl = (url) => (url.endsWith('/') ? url.slice(0, -1) : url);
2
+ import { normalizeUrl } from '../utils/normalize-url';
3
3
  /**
4
4
  * Generates a URL for accessing Sitecore Edge Platform Content using the provided endpoint and context ID.
5
5
  * @param {string} sitecoreEdgeContextId - The unique context id.
@@ -6,6 +6,7 @@ import { personalizeLayout } from '../personalize/layout-personalizer';
6
6
  import { SiteResolver, GraphQLErrorPagesService, GraphQLSitePathService, GraphQLSitemapXmlService, } from '../site';
7
7
  import { createGraphQLClientFactory } from './utils';
8
8
  import { NativeDataFetcher } from '../native-fetcher';
9
+ import { GraphQLRobotsService } from '../site/graphql-robots-service';
9
10
  /**
10
11
  * This is a generic content client that can be used by any framework.
11
12
  * Use it to retrieve pages, preview data, dictionary and other data
@@ -16,16 +17,19 @@ export class SitecoreClient {
16
17
  * @param {SitecoreClientInit} initOptions initOptions for the client, containing site and Sitecore connection details
17
18
  */
18
19
  constructor(initOptions) {
20
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
19
21
  this.initOptions = initOptions;
20
22
  this.clientFactory = this.getClientFactory();
21
- this.siteResolver = this.getSiteResolver();
23
+ this.siteResolver = (_b = (_a = initOptions.custom) === null || _a === void 0 ? void 0 : _a.siteResolver) !== null && _b !== void 0 ? _b : this.getSiteResolver();
22
24
  const baseServiceOptions = this.getBaseServiceOptions();
23
- this.layoutService = this.getLayoutService(baseServiceOptions);
24
- this.dictionaryService = this.getDictionaryService(baseServiceOptions);
25
- this.editingService = this.getEditingService();
26
- this.errorPagesService = this.getErrorPagesService();
25
+ this.layoutService =
26
+ (_d = (_c = initOptions.custom) === null || _c === void 0 ? void 0 : _c.layoutService) !== null && _d !== void 0 ? _d : this.getLayoutService(baseServiceOptions);
27
+ this.dictionaryService =
28
+ (_f = (_e = initOptions.custom) === null || _e === void 0 ? void 0 : _e.dictionaryService) !== null && _f !== void 0 ? _f : this.getDictionaryService(baseServiceOptions);
29
+ this.editingService = (_h = (_g = initOptions.custom) === null || _g === void 0 ? void 0 : _g.editingService) !== null && _h !== void 0 ? _h : this.getEditingService();
30
+ this.errorPagesService = (_k = (_j = initOptions.custom) === null || _j === void 0 ? void 0 : _j.errorPagesService) !== null && _k !== void 0 ? _k : this.getErrorPagesService();
31
+ this.sitePathService = (_m = (_l = initOptions.custom) === null || _l === void 0 ? void 0 : _l.sitePathService) !== null && _m !== void 0 ? _m : this.getSitePathService();
27
32
  this.componentService = this.getComponentService();
28
- this.sitePathService = this.getSitePathService();
29
33
  }
30
34
  /**
31
35
  * Resolve site by hostname
@@ -56,7 +60,7 @@ export class SitecoreClient {
56
60
  * Get page details for a route, with layout and other details
57
61
  * @param {string} path route path
58
62
  * @param {PageOptions} [pageOptions] site, language and personalization variant details for route
59
- * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests (like retries and fetch)
63
+ * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests
60
64
  * @returns {Page | null} page details
61
65
  */
62
66
  async getPage(path, pageOptions, fetchOptions) {
@@ -112,7 +116,7 @@ export class SitecoreClient {
112
116
  /**
113
117
  * Retrieves dictionary phrases for a given site and locale.
114
118
  * @param {RouteOptions} routeOptions - Route options containing language and site name to load dictionary for
115
- * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests (like retries and fetch)
119
+ * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests
116
120
  * @returns {DictionaryPhrases} A promise that resolves to the dictionary phrases.
117
121
  */
118
122
  async getDictionary(routeOptions, fetchOptions) {
@@ -123,7 +127,7 @@ export class SitecoreClient {
123
127
  /**
124
128
  * Retrieves error pages for a given site and locale.
125
129
  * @param {RouteOptions} routeOptions - Route options containing language and site name to load error pages
126
- * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests (like retries and fetch)
130
+ * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests
127
131
  * @returns {ErrorPages | null} A promise that resolves to the error pages or null if not found.
128
132
  */
129
133
  async getErrorPages(routeOptions, fetchOptions) {
@@ -134,7 +138,7 @@ export class SitecoreClient {
134
138
  /**
135
139
  * Retrieves preview page and layout details
136
140
  * @param {EditingPreviewData | undefined} previewData - The editing preview data for metadata mode.
137
- * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests (like retries and fetch)
141
+ * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests
138
142
  * @returns {Page} preview page details
139
143
  */
140
144
  async getPreview(previewData, fetchOptions) {
@@ -168,7 +172,7 @@ export class SitecoreClient {
168
172
  /**
169
173
  * Get design library page details for Design Library mode of your app
170
174
  * @param {DesignLibraryRenderPreviewData} designLibData preview data set in 'library' mode of the app
171
- * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests (like retries and fetch)
175
+ * @param {FetchOptions} [fetchOptions] Additional fetch fetch options to override GraphQL requests
172
176
  * @returns {Page} preview page for Design Library
173
177
  */
174
178
  async getDesignLibraryData(designLibData, fetchOptions) {
@@ -253,6 +257,18 @@ export class SitecoreClient {
253
257
  .join('')}
254
258
  </sitemapindex>`;
255
259
  }
260
+ /**
261
+ * Retrieves the robots.txt content for a given site name.
262
+ * @param {string} siteName - The name of the site to retrieve the robots.txt for.
263
+ * @param {FetchOptions} [fetchOptions] - Optional fetch options.
264
+ * @returns {Promise<string | null>} A promise that resolves to the robots.txt content,
265
+ * or null if no content is found.
266
+ */
267
+ async getRobots(siteName, fetchOptions) {
268
+ const robotsService = this.getRobotsService(siteName || this.initOptions.defaultSite);
269
+ const content = await robotsService.fetchRobots(fetchOptions);
270
+ return content || null;
271
+ }
256
272
  /**
257
273
  * Factory methods for creating dependencies
258
274
  * Subclasses can override these to provide custom implementations.
@@ -263,6 +279,12 @@ export class SitecoreClient {
263
279
  siteName,
264
280
  });
265
281
  }
282
+ getRobotsService(siteName) {
283
+ return new GraphQLRobotsService({
284
+ clientFactory: this.clientFactory,
285
+ siteName,
286
+ });
287
+ }
266
288
  getBaseServiceOptions() {
267
289
  return {
268
290
  defaultSite: this.initOptions.defaultSite,
@@ -294,12 +316,7 @@ export class SitecoreClient {
294
316
  return new GraphQLErrorPagesService(Object.assign(Object.assign({}, this.initOptions), { language: this.initOptions.defaultLanguage, clientFactory: this.clientFactory }));
295
317
  }
296
318
  getComponentService() {
297
- var _a, _b;
298
- return new RestComponentLayoutService({
299
- apiHost: (_a = this.initOptions.api.local) === null || _a === void 0 ? void 0 : _a.apiHost,
300
- apiKey: (_b = this.initOptions.api.local) === null || _b === void 0 ? void 0 : _b.apiKey,
301
- siteName: this.initOptions.defaultSite,
302
- });
319
+ return new RestComponentLayoutService(this.initOptions.api.edge);
303
320
  }
304
321
  getSitePathService() {
305
322
  return new GraphQLSitePathService({
@@ -7,9 +7,9 @@ import { DefaultRetryStrategy } from '../retries';
7
7
  export const getFallbackConfig = () => ({
8
8
  api: {
9
9
  edge: {
10
- contextId: '',
10
+ contextId: process.env.SITECORE_EDGE_CONTEXT_ID || '',
11
11
  clientContextId: '',
12
- edgeUrl: SITECORE_EDGE_URL_DEFAULT,
12
+ edgeUrl: process.env.SITECORE_EDGE_URL || SITECORE_EDGE_URL_DEFAULT,
13
13
  },
14
14
  local: {
15
15
  apiKey: '',
@@ -17,7 +17,7 @@ export const getFallbackConfig = () => ({
17
17
  path: '/sitecore/api/graph/edge',
18
18
  },
19
19
  },
20
- editingSecret: 'editing-secret-missing',
20
+ editingSecret: process.env.JSS_EDITING_SECRET || 'editing-secret-missing',
21
21
  retries: {
22
22
  count: 3,
23
23
  retryStrategy: new DefaultRetryStrategy({
@@ -34,8 +34,8 @@ export const getFallbackConfig = () => ({
34
34
  },
35
35
  personalize: {
36
36
  enabled: process.env.NODE_ENV !== 'development',
37
- edgeTimeout: 400,
38
- cdpTimeout: 400,
37
+ edgeTimeout: parseInt(process.env.PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT, 10) || 400,
38
+ cdpTimeout: parseInt(process.env.PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT, 10) || 400,
39
39
  scope: '',
40
40
  channel: 'WEB',
41
41
  currency: 'USD',
@@ -51,6 +51,7 @@ export const getFallbackConfig = () => ({
51
51
  timeout: 60,
52
52
  },
53
53
  },
54
+ disableCodeGeneration: false,
54
55
  });
55
56
  /**
56
57
  * Merges two SitecoreConfig objects
@@ -8,3 +8,14 @@ export var SitecoreTemplateId;
8
8
  export const siteNameError = 'The siteName cannot be empty';
9
9
  export const SITECORE_EDGE_URL_DEFAULT = 'https://edge-platform.sitecorecloud.io';
10
10
  export const HIDDEN_RENDERING_NAME = 'Hidden Rendering';
11
+ // Sitecore Auth constants
12
+ export const DEFAULT_SITECORE_AUTH_DOMAIN = 'https://auth.sitecorecloud.io';
13
+ export const DEFAULT_SITECORE_AUTH_AUDIENCE = 'https://api.sitecorecloud.io';
14
+ export const DEFAULT_SITECORE_AUTH_BASE_URL = 'https://edge-platform.sitecorecloud.io/cs/api';
15
+ export const CLAIMS = 'https://auth.sitecorecloud.io/claims';
16
+ export const CLIENT_GRANT_TYPE = 'client_credentials';
17
+ export const DEVICE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';
18
+ export const REFRESH_GRANT_TYPE = 'refresh_token';
19
+ export const SCOPE = 'openid profile email offline_access';
20
+ export const TIMEOUT = 600;
21
+ export const DEFAULT_INTERVAL = 10;
@@ -0,0 +1,141 @@
1
+ import { GraphQLRequestClient } from '../graphql-request-client';
2
+ import { getContentUrl } from './utils';
3
+ import debug from '../debug';
4
+ import { GET_LOCALE_QUERY, GET_LOCALES_QUERY, } from './locales';
5
+ import { GET_TAXONOMY_QUERY, GET_TAXONOMIES_QUERY, } from './taxonomies';
6
+ /**
7
+ * Class representing a client for interacting with the Content API.
8
+ */
9
+ export class ContentClient {
10
+ constructor({ url, tenant, environment, preview = false, token }) {
11
+ this.endpoint = getContentUrl({
12
+ environment,
13
+ preview,
14
+ tenant,
15
+ url,
16
+ });
17
+ this.graphqlClient = new GraphQLRequestClient(this.endpoint, {
18
+ headers: {
19
+ Authorization: `Bearer ${token}`,
20
+ },
21
+ debugger: debug.content,
22
+ });
23
+ }
24
+ /**
25
+ * Factory method for creating a ContentClient instance. This method allows you to create a client with the values populated from environment variables or provided as arguments.
26
+ * @param {Partial<ContentClientOptions>} [options] - client configuration options
27
+ * @param {string} [options.url] - Content base graphql endpoint url. If not provided, it will be read from the SITECORE_CS_URL environment variable. Otherwise, it defaults to https://cs-graphqlapi-staging.sitecore-staging.cloud.
28
+ * @param {string} [options.tenant] - Tenant name. If not provided, it will be read from the SITECORE_CS_TENANT environment variable
29
+ * @param {string} [options.environment] - Environment name. If not provided, it will be read from the SITECORE_CS_ENVIRONMENT environment variable. Otherwise, it defaults to 'main'
30
+ * @param {boolean} [options.preview] - Indicates if preview mode is enabled. If not provided, it will be read from the SITECORE_CS_PREVIEW environment variable. Otherwise, it defaults to false
31
+ * @param {string} [options.token] - Token for authentication. If not provided, it will be read from the SITECORE_CS_TOKEN environment variable.
32
+ * @returns {ContentClient} ContentClient instance
33
+ * @throws {Error} If tenant or token is not provided
34
+ */
35
+ static createClient({ url, tenant, environment, preview, token, } = {}) {
36
+ const options = {
37
+ url: url || process.env.SITECORE_CS_URL,
38
+ tenant: tenant || process.env.SITECORE_CS_TENANT || '',
39
+ environment: environment || process.env.SITECORE_CS_ENVIRONMENT || 'main',
40
+ preview: preview || process.env.SITECORE_CS_PREVIEW === 'true',
41
+ token: token || process.env.SITECORE_CS_TOKEN || '',
42
+ };
43
+ if (!options.tenant) {
44
+ throw new Error('Tenant is required to be provided as an argument or as a SITECORE_CS_TENANT environment variable');
45
+ }
46
+ if (!options.token) {
47
+ throw new Error('Token is required to be provided as an argument or as a SITECORE_CS_TOKEN environment variable');
48
+ }
49
+ return new ContentClient(options);
50
+ }
51
+ /**
52
+ * Execute graphql request
53
+ * @param {string | DocumentNode} query graphql query
54
+ * @param {object} variables variables for the query
55
+ * @param {FetchOptions} options options for configuring the request
56
+ * @returns {T} response data
57
+ */
58
+ async get(query, variables = {}, options = {}) {
59
+ debug.content('fetching content data');
60
+ return this.graphqlClient.request(query, variables, options);
61
+ }
62
+ /**
63
+ * Retrieves the locale information for a given locale ID.
64
+ * @param {string} id - The unique identifier of the locale item.
65
+ * @returns A promise that resolves to the locale information associated with the specified locale ID.
66
+ */
67
+ async getLocale(id) {
68
+ var _a;
69
+ debug.content('Getting locale for id: %s', id);
70
+ const response = await this.get(GET_LOCALE_QUERY, { id });
71
+ return ((_a = response.locale) === null || _a === void 0 ? void 0 : _a.system) || null;
72
+ }
73
+ /**
74
+ * Retrieves all available locales from the content service.
75
+ * @returns A promise that resolves to an array of locales.
76
+ */
77
+ async getLocales() {
78
+ var _a, _b;
79
+ debug.content('Getting all locales');
80
+ const response = await this.get(GET_LOCALES_QUERY);
81
+ return (_b = (_a = response === null || response === void 0 ? void 0 : response.manyLocale) === null || _a === void 0 ? void 0 : _a.map((entry) => entry.system)) !== null && _b !== void 0 ? _b : [];
82
+ }
83
+ /**
84
+ * Retrieves all available taxonomies with optional pagination support.
85
+ * @param {object} [options] - Optional pagination options.
86
+ * @param {number} [options.pageSize] - Limits the number of taxonomies returned per page. Defaults to the API's default
87
+ * @param {string} [options.after] - Cursor for pagination; use the `cursor` returned from the previous call to fetch the next page.
88
+ * @returns A promise that resolves to an object containing taxonomies, their terms, and pagination info.
89
+ */
90
+ async getTaxonomies(options) {
91
+ var _a, _b, _c, _d, _e;
92
+ debug.content('Getting taxonomies (pageSize: %s, after: %s)', (_a = options === null || options === void 0 ? void 0 : options.pageSize) !== null && _a !== void 0 ? _a : 'API Default', (_b = options === null || options === void 0 ? void 0 : options.after) !== null && _b !== void 0 ? _b : '');
93
+ const variables = {
94
+ pageSize: options === null || options === void 0 ? void 0 : options.pageSize,
95
+ after: (_c = options === null || options === void 0 ? void 0 : options.after) !== null && _c !== void 0 ? _c : '',
96
+ };
97
+ const response = await this.get(GET_TAXONOMIES_QUERY, variables);
98
+ const data = response === null || response === void 0 ? void 0 : response.manyTaxonomy;
99
+ return {
100
+ results: ((_d = data === null || data === void 0 ? void 0 : data.results) !== null && _d !== void 0 ? _d : []).map((taxonomy) => {
101
+ var _a, _b;
102
+ return ({
103
+ system: taxonomy.system,
104
+ terms: (_b = (_a = taxonomy.terms) === null || _a === void 0 ? void 0 : _a.results) !== null && _b !== void 0 ? _b : [],
105
+ });
106
+ }),
107
+ cursor: data === null || data === void 0 ? void 0 : data.cursor,
108
+ hasMore: (_e = data === null || data === void 0 ? void 0 : data.hasMore) !== null && _e !== void 0 ? _e : false,
109
+ };
110
+ }
111
+ /**
112
+ * Retrieves a taxonomy by its ID, with optional pagination support for its terms.
113
+ * @param {object} options - Options for fetching the taxonomy.
114
+ * @param {string} options.id - The unique identifier of the taxonomy.
115
+ * @param {object} [options.terms] - Optional pagination options for terms.
116
+ * @param {number} [options.terms.pageSize] - Optional. Limits the number of terms returned per page.
117
+ * @param {string} [options.terms.after] - Optional. Cursor for pagination. Used to fetch the next page of terms.
118
+ * @returns A promise that resolves to the taxonomy object, including pagination metadata (`hasMore`, `cursor`) for its terms. Returns `null` if the taxonomy is not found.
119
+ */
120
+ async getTaxonomy({ id, terms, }) {
121
+ var _a, _b, _c, _d, _e, _f, _g;
122
+ debug.content('Getting taxonomy for id: %s (termsPageSize: %s, termsAfter: %s)', id, (_a = terms === null || terms === void 0 ? void 0 : terms.pageSize) !== null && _a !== void 0 ? _a : 'API Default', (_b = terms === null || terms === void 0 ? void 0 : terms.after) !== null && _b !== void 0 ? _b : '');
123
+ const variables = {
124
+ id,
125
+ termsPageSize: terms === null || terms === void 0 ? void 0 : terms.pageSize,
126
+ termsAfter: terms === null || terms === void 0 ? void 0 : terms.after,
127
+ };
128
+ const response = await this.get(GET_TAXONOMY_QUERY, variables);
129
+ const taxonomy = response === null || response === void 0 ? void 0 : response.taxonomy;
130
+ if (!taxonomy)
131
+ return null;
132
+ return {
133
+ system: taxonomy.system,
134
+ terms: {
135
+ results: (_d = (_c = taxonomy.terms) === null || _c === void 0 ? void 0 : _c.results) !== null && _d !== void 0 ? _d : [],
136
+ cursor: (_e = taxonomy.terms) === null || _e === void 0 ? void 0 : _e.cursor,
137
+ hasMore: (_g = (_f = taxonomy.terms) === null || _f === void 0 ? void 0 : _f.hasMore) !== null && _g !== void 0 ? _g : false,
138
+ },
139
+ };
140
+ }
141
+ }
@@ -0,0 +1,4 @@
1
+ export { ContentClient } from './content-client';
2
+ export { GET_LOCALE_QUERY, GET_LOCALES_QUERY, } from './locales';
3
+ export { GET_TAXONOMY_QUERY, GET_TAXONOMIES_QUERY, } from './taxonomies';
4
+ export { getContentUrl } from './utils';