@enonic/nextjs-adapter 2.0.0-B3 → 2.0.1

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 (82) hide show
  1. package/.eslint-childrc.js +17 -0
  2. package/.eslintrc.js +15 -0
  3. package/.github/dependabot.yml +20 -0
  4. package/.github/pull-merger.yml +1 -0
  5. package/.github/workflows/release.yml +39 -0
  6. package/LICENSE +201 -0
  7. package/RELEASE.md +75 -0
  8. package/package.json +8 -7
  9. package/server/.eslintrc.js +11 -0
  10. package/server/ClearableFileCache.ts +410 -0
  11. package/server/cache.ts +50 -0
  12. package/server/index.ts +74 -0
  13. package/server/tsconfig.json +23 -0
  14. package/setversion.js +8 -0
  15. package/src/.eslintrc.js +11 -0
  16. package/src/ComponentRegistry.ts +189 -0
  17. package/{UrlProcessor.js → src/UrlProcessor.ts} +54 -36
  18. package/{baseMappings.js → src/baseMappings.ts} +13 -3
  19. package/{guillotine/fetchContent.js → src/guillotine/fetchContent.ts} +496 -243
  20. package/src/guillotine/getMetaData.ts +246 -0
  21. package/{index.d.ts → src/index.ts} +1 -1
  22. package/src/tsconfig.json +20 -0
  23. package/{utils.js → src/utils.ts} +160 -70
  24. package/{views/BaseComponent.jsx → src/views/BaseComponent.tsx} +73 -39
  25. package/{views/BaseContent.jsx → src/views/BaseContent.tsx} +24 -17
  26. package/src/views/BaseLayout.tsx +45 -0
  27. package/{views/BaseMacro.jsx → src/views/BaseMacro.tsx} +45 -29
  28. package/src/views/BasePage.tsx +56 -0
  29. package/src/views/BasePart.tsx +50 -0
  30. package/{views/Empty.jsx → src/views/Empty.tsx} +2 -0
  31. package/src/views/Fragment.tsx +45 -0
  32. package/src/views/MainView.tsx +21 -0
  33. package/src/views/Region.tsx +89 -0
  34. package/{views/RichTextView.jsx → src/views/RichTextView.tsx} +31 -10
  35. package/{views/SingleComponent.jsx → src/views/SingleComponent.tsx} +8 -2
  36. package/src/views/StaticContent.tsx +40 -0
  37. package/src/views/Text.tsx +15 -0
  38. package/src/views/macros/DefaultMacro.tsx +9 -0
  39. package/src/views/macros/DisableMacro.tsx +8 -0
  40. package/ComponentRegistry.d.ts +0 -64
  41. package/ComponentRegistry.js +0 -121
  42. package/UrlProcessor.d.ts +0 -25
  43. package/baseMappings.d.ts +0 -1
  44. package/guillotine/fetchContent.d.ts +0 -48
  45. package/guillotine/getMetaData.d.ts +0 -94
  46. package/guillotine/getMetaData.js +0 -128
  47. package/index.js +0 -5
  48. package/query/Shortcut.d.ts +0 -1
  49. package/server/ClearableFileCache.d.ts +0 -31
  50. package/server/ClearableFileCache.js +0 -472
  51. package/server/cache.d.ts +0 -2
  52. package/server/cache.js +0 -129
  53. package/server/index.d.ts +0 -5
  54. package/server/index.js +0 -132
  55. package/utils.d.ts +0 -114
  56. package/views/BaseComponent.d.ts +0 -25
  57. package/views/BaseContent.d.ts +0 -4
  58. package/views/BaseLayout.d.ts +0 -17
  59. package/views/BaseLayout.jsx +0 -24
  60. package/views/BaseMacro.d.ts +0 -16
  61. package/views/BasePage.d.ts +0 -19
  62. package/views/BasePage.jsx +0 -34
  63. package/views/BasePart.d.ts +0 -19
  64. package/views/BasePart.jsx +0 -24
  65. package/views/Empty.d.ts +0 -3
  66. package/views/Fragment.d.ts +0 -10
  67. package/views/Fragment.jsx +0 -30
  68. package/views/MainView.d.ts +0 -4
  69. package/views/MainView.jsx +0 -14
  70. package/views/Region.d.ts +0 -20
  71. package/views/Region.jsx +0 -52
  72. package/views/RichTextView.d.ts +0 -16
  73. package/views/SingleComponent.d.ts +0 -5
  74. package/views/StaticContent.d.ts +0 -15
  75. package/views/StaticContent.jsx +0 -36
  76. package/views/Text.d.ts +0 -9
  77. package/views/Text.jsx +0 -4
  78. package/views/macros/DefaultMacro.d.ts +0 -4
  79. package/views/macros/DefaultMacro.jsx +0 -3
  80. package/views/macros/DisableMacro.d.ts +0 -3
  81. package/views/macros/DisableMacro.jsx +0 -2
  82. /package/{query/Shortcut.js → src/query/Shortcut.ts} +0 -0
@@ -1,22 +1,121 @@
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
- });
1
+ import {getMetaQuery, MetaData, PageComponent, PageData, pageFragmentQuery, PageRegion, RegionTree} from './getMetaData';
2
+
3
+ import adapterConstants, {
4
+ addJsessionHeaders,
5
+ addLocaleHeaders,
6
+ APP_NAME,
7
+ APP_NAME_DASHED,
8
+ ContentPathItem,
9
+ Context,
10
+ FRAGMENT_CONTENTTYPE_NAME,
11
+ FRAGMENT_DEFAULT_REGION_NAME,
12
+ GET_STATIC_PATHS_QUERY,
13
+ getContentApiUrl,
14
+ getLocaleProjectConfig,
15
+ getLocaleProjectConfigs,
16
+ getRenderMode,
17
+ getXpBaseUrl,
18
+ IS_DEV_MODE,
19
+ LocaleProjectConfig,
20
+ normalizeLocale,
21
+ PAGE_TEMPLATE_CONTENTTYPE_NAME,
22
+ PAGE_TEMPLATE_FOLDER,
23
+ PURGE_CACHE_URL,
24
+ RENDER_MODE,
25
+ sanitizeGraphqlName,
26
+ XP_COMPONENT_TYPE,
27
+ XP_REQUEST_TYPE,
28
+ } from '../utils';
29
+ import {ComponentDefinition, ComponentRegistry, SelectedQueryMaybeVariablesFunc} from '../ComponentRegistry';
30
+ import {getUrl, UrlProcessor} from '../UrlProcessor';
31
+ import {GetServerSidePropsResult, GetStaticPropsResult} from 'next';
32
+
33
+ type AdapterConstants = {
34
+ APP_NAME: string,
35
+ APP_NAME_DASHED: string,
36
+ };
37
+
38
+ type Result = {
39
+ error?: {
40
+ code: string,
41
+ message: string
42
+ } | null;
43
+ };
44
+
45
+ export type GuillotineResult = Result & {
46
+ [dataKey: string]: any;
47
+ };
48
+
49
+ type MetaResult = Result & {
50
+ meta?: {
51
+ _path: string;
52
+ type: string,
53
+ pageAsJson?: PageData,
54
+ components?: PageComponent[],
55
+ }
56
+ };
57
+
58
+ type ContentResult = Result & {
59
+ contents?: Record<string, any>[];
9
60
  };
10
- import { getMetaQuery, pageFragmentQuery } from './getMetaData';
11
- import adapterConstants, { addJsessionHeaders, addLocaleHeaders, APP_NAME, APP_NAME_DASHED, FRAGMENT_CONTENTTYPE_NAME, FRAGMENT_DEFAULT_REGION_NAME, GET_STATIC_PATHS_QUERY, getContentApiUrl, getLocaleProjectConfig, getLocaleProjectConfigs, getRenderMode, getXpBaseUrl, IS_DEV_MODE, normalizeLocale, PAGE_TEMPLATE_CONTENTTYPE_NAME, PAGE_TEMPLATE_FOLDER, PURGE_CACHE_URL, RENDER_MODE, sanitizeGraphqlName, XP_COMPONENT_TYPE, XP_REQUEST_TYPE, } from '../utils';
12
- import { ComponentRegistry } from '../ComponentRegistry';
13
- import { getUrl, UrlProcessor } from '../UrlProcessor';
14
- const NO_PROPS_PROCESSOR = (props) => __awaiter(void 0, void 0, void 0, function* () { var _a; return (_a = yield props) !== null && _a !== void 0 ? _a : {}; });
61
+
62
+ interface ComponentDescriptor {
63
+ type?: ComponentDefinition;
64
+ component?: PageComponent;
65
+ queryAndVariables?: QueryAndVariables;
66
+ }
67
+
68
+ export type FetchContentResult = Result & {
69
+ data: Record<string, any> | null,
70
+ common: Record<string, any> | null,
71
+ meta: MetaData,
72
+ page: PageComponent | null,
73
+ };
74
+
75
+
76
+ type FetcherConfig<T extends AdapterConstants> = T & {
77
+ componentRegistry: typeof ComponentRegistry
78
+ };
79
+
80
+ interface QueryAndVariables {
81
+ query: string;
82
+ variables?: Record<string, any>;
83
+ }
84
+
85
+ /**
86
+ * Sends one query to the guillotine API and asks for content type, then uses the type to select a second query and variables, which is sent to the API and fetches content data.
87
+ * @param contentPath string or string array: pre-split or slash-delimited _path to a content available on the API
88
+ * @returns FetchContentResult object: {data?: T, error?: {code, message}}
89
+ */
90
+ export type ContentFetcher = (contentPath: string | string[], context?: Context) => Promise<FetchContentResult>;
91
+
92
+ const NO_PROPS_PROCESSOR = async (props: any) => await props ?? {};
93
+
15
94
  const ALIAS_PREFIX = 'request';
95
+
16
96
  const GUILLOTINE_QUERY_REGEXP = /^\s*query\s*(?:\((.*)*\))?\s*{\s*guillotine\s*{((?:.|\s)+)}\s*}\s*$/;
97
+
17
98
  const GRAPHQL_FRAGMENTS_REGEXP = /fragment\s+.+\s+on\s+.+\s*{[\s\w{}().,:"'`]+}/;
99
+
100
+ // /////////////////////////////////////////////////////////////////////////////// Data
101
+
102
+ // Shape of content base-data API body
103
+ export type ContentApiBaseBody = {
104
+ query?: string, // Override the default base-data query
105
+ variables?: { // GraphQL variables inserted into the query
106
+ path?: string, // Full content item _path
107
+ [key: string]: string | number | undefined,
108
+ }
109
+ };
110
+
18
111
  /** Generic fetch */
19
- export const fetchFromApi = (apiUrl, body, projectConfig, headers, method = 'POST') => __awaiter(void 0, void 0, void 0, function* () {
112
+ export const fetchFromApi = async (
113
+ apiUrl: string,
114
+ body: ContentApiBaseBody,
115
+ projectConfig: LocaleProjectConfig,
116
+ headers?: {},
117
+ method = 'POST',
118
+ ) => {
20
119
  const options = {
21
120
  method,
22
121
  headers: {
@@ -26,47 +125,55 @@ export const fetchFromApi = (apiUrl, body, projectConfig, headers, method = 'POS
26
125
  },
27
126
  body: JSON.stringify(body),
28
127
  };
128
+
29
129
  if (headers) {
30
130
  Object.assign(options.headers, headers);
31
131
  }
132
+
32
133
  let res;
33
134
  try {
34
- res = yield fetch(apiUrl, options);
35
- }
36
- catch (e) {
135
+ res = await fetch(apiUrl, options);
136
+ } catch (e: any) {
37
137
  console.warn(apiUrl, e);
38
138
  throw new Error(JSON.stringify({
39
139
  code: 'API',
40
140
  message: e.message,
41
141
  }));
42
142
  }
143
+
43
144
  if (!res.ok) {
44
145
  throw new Error(JSON.stringify({
45
146
  code: res.status,
46
- message: `Data fetching failed (message: '${yield res.text()}')`,
147
+ message: `Data fetching failed (message: '${await res.text()}')`,
47
148
  }));
48
149
  }
150
+
49
151
  let json;
50
152
  try {
51
- json = yield res.json();
52
- }
53
- catch (e) {
153
+ json = await res.json();
154
+ } catch (e) {
54
155
  throw new Error(JSON.stringify({
55
156
  code: 500,
56
- message: `API call completed but with non-JSON data: ${JSON.stringify(yield res.text())}`,
157
+ message: `API call completed but with non-JSON data: ${JSON.stringify(await res.text())}`,
57
158
  }));
58
159
  }
160
+
59
161
  if (!json) {
60
162
  throw new Error(JSON.stringify({
61
163
  code: 500,
62
- message: `API call completed but with unexpectedly empty data: ${JSON.stringify(yield res.text())}`,
164
+ message: `API call completed but with unexpectedly empty data: ${JSON.stringify(await res.text())}`,
63
165
  }));
64
166
  }
167
+
65
168
  return json;
66
- });
169
+ };
170
+
67
171
  /** Guillotine-specialized fetch, using the generic fetch above */
68
- export const fetchGuillotine = (contentApiUrl, body, projectConfig, headers) => __awaiter(void 0, void 0, void 0, function* () {
69
- var _b;
172
+ export const fetchGuillotine = async (
173
+ contentApiUrl: string,
174
+ body: ContentApiBaseBody,
175
+ projectConfig: LocaleProjectConfig,
176
+ headers?: {}): Promise<GuillotineResult> => {
70
177
  if (typeof body.query !== 'string' || !body.query.trim()) {
71
178
  return {
72
179
  error: {
@@ -75,98 +182,129 @@ export const fetchGuillotine = (contentApiUrl, body, projectConfig, headers) =>
75
182
  },
76
183
  };
77
184
  }
78
- const path = (_b = body.variables) === null || _b === void 0 ? void 0 : _b.path;
185
+ const path = body.variables?.path;
79
186
  const pathMessage = path ? JSON.stringify(path) : '';
80
- const result = yield fetchFromApi(contentApiUrl, body, projectConfig, headers)
187
+ const result = await fetchFromApi(
188
+ contentApiUrl,
189
+ body,
190
+ projectConfig,
191
+ headers,
192
+ )
81
193
  .then(json => {
82
- let errors = (json || {}).errors;
83
- if (errors) {
84
- if (!Array.isArray(errors)) {
85
- errors = [errors];
86
- }
87
- console.error(`${errors.length} error(s) when fetching data from: ${contentApiUrl}`);
88
- console.error(`headers: ${JSON.stringify(headers, null, 2)}
194
+ let errors: any[] = (json || {}).errors;
195
+
196
+ if (errors) {
197
+ if (!Array.isArray(errors)) {
198
+ errors = [errors];
199
+ }
200
+ console.error(`${errors.length} error(s) when fetching data from: ${contentApiUrl}`);
201
+ console.error(`headers: ${JSON.stringify(headers, null, 2)}
89
202
  variables: ${JSON.stringify(body.variables, null, 2)}`);
90
- errors.forEach(error => {
91
- console.error(error);
92
- });
93
- return {
94
- error: {
95
- code: '500',
96
- message: `Server responded with ${errors.length} error(s), probably from guillotine - see log.`,
97
- },
98
- };
99
- }
100
- return json.data;
101
- })
203
+ errors.forEach(error => {
204
+ console.error(error);
205
+ });
206
+
207
+ return {
208
+ error: {
209
+ code: '500',
210
+ message: `Server responded with ${errors.length} error(s), probably from guillotine - see log.`,
211
+ },
212
+ };
213
+ }
214
+
215
+ return json.data;
216
+ })
102
217
  .catch((err) => {
103
- console.warn(`Client-side error when trying to fetch data ${pathMessage}`, err);
104
- try {
105
- return { error: JSON.parse(err.message) };
106
- }
107
- catch (e2) {
108
- return { error: { code: 'Client-side error', message: err.message } };
109
- }
110
- });
111
- return result;
112
- });
218
+ console.warn(`Client-side error when trying to fetch data ${pathMessage}`, err);
219
+ try {
220
+ return {error: JSON.parse(err.message)};
221
+ } catch (e2) {
222
+ return {error: {code: 'Client-side error', message: err.message}};
223
+ }
224
+ });
225
+
226
+ return result as GuillotineResult;
227
+ };
228
+
113
229
  // /////////////////////////////////////////////////////////////////////////////// Specific fetch wrappers:
114
- const fetchMetaData = (contentApiUrl, xpContentPath, projectConfig, headers) => __awaiter(void 0, void 0, void 0, function* () {
115
- var _c;
116
- const body = {
230
+
231
+ const fetchMetaData = async (contentApiUrl: string, xpContentPath: string, projectConfig: LocaleProjectConfig, headers?: {}): Promise<MetaResult> => {
232
+ const body: ContentApiBaseBody = {
117
233
  query: getMetaQuery(pageFragmentQuery()),
118
234
  variables: {
119
235
  path: xpContentPath,
120
236
  },
121
237
  };
122
- const metaResult = yield fetchGuillotine(contentApiUrl, body, projectConfig, headers);
238
+ const metaResult = await fetchGuillotine(contentApiUrl, body, projectConfig, headers);
123
239
  if (metaResult.error) {
124
240
  return metaResult;
125
- }
126
- else {
241
+ } else {
127
242
  return {
128
- meta: (_c = metaResult === null || metaResult === void 0 ? void 0 : metaResult.guillotine) === null || _c === void 0 ? void 0 : _c.get,
243
+ meta: metaResult?.guillotine?.get,
129
244
  };
130
245
  }
131
- });
132
- const fetchContentData = (contentApiUrl, xpContentPath, projectConfig, query, variables, headers) => __awaiter(void 0, void 0, void 0, function* () {
133
- const body = { query };
246
+ };
247
+
248
+
249
+ const fetchContentData = async <T>(
250
+ contentApiUrl: string,
251
+ xpContentPath: string,
252
+ projectConfig: LocaleProjectConfig,
253
+ query: string,
254
+ variables?: {},
255
+ headers?: {},
256
+ ): Promise<ContentResult> => {
257
+
258
+ const body: ContentApiBaseBody = {query};
134
259
  if (variables && Object.keys(variables).length > 0) {
135
260
  body.variables = variables;
136
261
  }
137
- const contentResults = yield fetchGuillotine(contentApiUrl, body, projectConfig, headers);
262
+ const contentResults = await fetchGuillotine(contentApiUrl, body, projectConfig, headers);
263
+
138
264
  if (contentResults.error) {
139
265
  return contentResults;
140
- }
141
- else {
266
+ } else {
142
267
  return {
143
268
  // omit the aliases and return values
144
269
  contents: Object.values(contentResults),
145
270
  };
146
271
  }
147
- });
272
+ };
273
+
274
+
148
275
  // /////////////////////////////////////////////////////////////////////////////// Error checking:
276
+
149
277
  /** Checks a site-relative contentPath as a slash-delimited string or a string array, and returns a pure site-relative path string (no double slashes, starts with a slash, does not end with one). */
150
- const getCleanContentPathArrayOrThrow400 = (contentPath) => {
278
+ const getCleanContentPathArrayOrThrow400 = (contentPath: string | string[] | undefined): string => {
151
279
  if (contentPath === undefined) {
152
280
  return '';
153
281
  }
154
282
  const isArray = Array.isArray(contentPath);
283
+
155
284
  if (!isArray) {
156
285
  if (typeof contentPath !== 'string') {
157
286
  throw Error(JSON.stringify({
158
287
  code: 400,
159
- message: `Unexpected target content _path: contentPath must be a string or pure string array (contentPath=${JSON.stringify(contentPath)})`,
288
+ message: `Unexpected target content _path: contentPath must be a string or pure string array (contentPath=${JSON.stringify(
289
+ contentPath)})`,
160
290
  }));
161
291
  }
292
+
162
293
  return contentPath;
163
- }
164
- else {
294
+
295
+ } else {
165
296
  return (contentPath).join('/');
166
297
  }
167
298
  };
168
- function parseComponentPath(contentType, path) {
169
- const matches = [];
299
+
300
+
301
+ // ------------------------------------------------------------- XP view component data handling
302
+
303
+
304
+ type PathFragment = { region: string, index: number };
305
+
306
+ function parseComponentPath(contentType: string, path: string): PathFragment[] {
307
+ const matches: PathFragment[] = [];
170
308
  let match;
171
309
  const myRegexp = /(?:(\w+)\/(\d+))+/g;
172
310
  while ((match = myRegexp.exec(path)) !== null) {
@@ -185,15 +323,20 @@ function parseComponentPath(contentType, path) {
185
323
  }
186
324
  return matches;
187
325
  }
188
- function getParentRegion(source, contentType, cmpPath, components = [], createMissing) {
189
- let currentTree = source;
190
- let currentRegion;
326
+
327
+ function getParentRegion(source: RegionTree, contentType: string, cmpPath: PathFragment[], components: PageComponent[] = [],
328
+ createMissing?: boolean): PageRegion | undefined {
329
+
330
+ let currentTree: RegionTree = source;
331
+ let currentRegion: PageRegion | undefined;
191
332
  let parentPath = '';
333
+
192
334
  for (let i = 0; i < cmpPath.length; i++) {
193
335
  const pathFragment = cmpPath[i];
194
336
  const regionName = pathFragment.region;
195
337
  parentPath += `/${pathFragment.region}/${pathFragment.index}`;
196
338
  currentRegion = currentTree[regionName];
339
+
197
340
  if (!currentRegion) {
198
341
  if (createMissing) {
199
342
  currentRegion = {
@@ -201,14 +344,15 @@ function getParentRegion(source, contentType, cmpPath, components = [], createMi
201
344
  components: [],
202
345
  };
203
346
  currentTree[regionName] = currentRegion;
204
- }
205
- else {
347
+ } else {
206
348
  throw `Region [${regionName}] was not found`;
207
349
  }
208
350
  }
351
+
209
352
  if (i < cmpPath.length - 1) {
210
353
  // look for layouts inside if this is not the last path fragment
211
- const layout = components.find((cmp) => {
354
+
355
+ const layout = components.find((cmp: PageComponent) => {
212
356
  return cmp.type === XP_COMPONENT_TYPE.LAYOUT && prefixLayoutPath(contentType, cmp.path) === parentPath;
213
357
  });
214
358
  if (!layout) {
@@ -220,94 +364,107 @@ function getParentRegion(source, contentType, cmpPath, components = [], createMi
220
364
  currentTree = layout.regions;
221
365
  }
222
366
  }
367
+
223
368
  return currentRegion;
224
369
  }
225
- function prefixLayoutPath(contentType, path) {
370
+
371
+ function prefixLayoutPath(contentType: string, path: string): string {
226
372
  if (contentType !== FRAGMENT_CONTENTTYPE_NAME) {
227
373
  return path;
228
- }
229
- else {
374
+ } else {
230
375
  // prepend FRAGMENT_DEFAULT_REGION_NAME to path to conform to page structure
231
376
  // so that component with path '/' becomes /FRAGMENT_DEFAULT_REGION_NAME/0
232
377
  // path /left/1 becomes /FRAGMENT_DEFAULT_REGION_NAME/0/left/1
233
378
  return `/${FRAGMENT_DEFAULT_REGION_NAME}/0${path === '/' ? '' : path}`;
234
379
  }
235
380
  }
236
- function buildPage(contentType, comps = []) {
237
- const page = {
381
+
382
+ function buildPage(contentType: string, comps: PageComponent[] = []): PageComponent {
383
+
384
+ const page: PageComponent = {
238
385
  type: XP_COMPONENT_TYPE.PAGE,
239
386
  path: '/',
240
387
  };
388
+
241
389
  return buildComponentTree(comps, page, contentType);
242
390
  }
243
- function buildComponentTree(comps, rootComp, contentType) {
244
- const rootTree = {};
391
+
392
+ function buildComponentTree(comps: PageComponent[], rootComp: PageComponent, contentType?: string): PageComponent {
393
+ const rootTree: RegionTree = {};
245
394
  const isFragmentType = contentType === FRAGMENT_CONTENTTYPE_NAME;
395
+
246
396
  if (isFragmentType) {
247
397
  rootComp.regions = rootTree;
248
398
  }
399
+
249
400
  (comps || []).forEach(cmp => {
250
- var _a, _b, _c;
251
401
  const cmpPath = parseComponentPath(contentType, cmp.path);
402
+
252
403
  if (cmp.path === '/') {
253
404
  if (cmp.type === XP_COMPONENT_TYPE.PAGE && rootComp.type === XP_COMPONENT_TYPE.PAGE) {
254
405
  // add page values to page object
255
406
  rootComp = Object.assign(rootComp, cmp);
256
407
  rootComp.page.regions = rootTree;
257
408
  return;
258
- }
259
- else if (cmp.type === XP_COMPONENT_TYPE.LAYOUT && rootComp.type === XP_COMPONENT_TYPE.FRAGMENT) {
409
+ } else if (cmp.type === XP_COMPONENT_TYPE.LAYOUT && rootComp.type === XP_COMPONENT_TYPE.FRAGMENT) {
260
410
  // when rendering fragment as part of the page with layout at root path
261
411
  // remove other children from list as they will be included in layout
262
412
  rootComp.fragment.fragment.components = [cmp];
263
413
  cmp.regions = rootTree;
264
414
  }
265
415
  }
416
+
266
417
  if (cmp.type === XP_COMPONENT_TYPE.FRAGMENT) {
267
418
  // build component subtree for fragment
268
- cmp = buildComponentTree((_b = (_a = cmp.fragment) === null || _a === void 0 ? void 0 : _a.fragment) === null || _b === void 0 ? void 0 : _b.components, cmp, contentType);
419
+ cmp = buildComponentTree(cmp.fragment?.fragment?.components, cmp, contentType);
269
420
  }
421
+
270
422
  const region = getParentRegion(rootTree, contentType, cmpPath, comps, true);
423
+
271
424
  if (region) {
272
425
  // getting the index of component from string like '/main/0/left/11'
273
- const cmpIndex = (_c = cmpPath[cmpPath.length - 1]) === null || _c === void 0 ? void 0 : _c.index;
426
+ const cmpIndex = cmpPath[cmpPath.length - 1]?.index;
274
427
  if (cmpIndex >= 0) {
275
428
  region.components.splice(cmpIndex, 0, cmp);
276
- }
277
- else {
429
+ } else {
278
430
  throw Error(`Could not find [${cmp.type}] component index at ${JSON.stringify(cmpPath, null, 2)}, rendering not possible.`);
279
431
  }
280
432
  }
281
433
  });
434
+
282
435
  return rootComp;
283
436
  }
284
- function combineMultipleQueries(queriesWithVars) {
285
- const queries = [];
286
- const fragments = [];
287
- const superVars = {};
288
- const superParams = [];
289
- queriesWithVars.forEach((componentDescriptor, index) => {
437
+
438
+
439
+ function combineMultipleQueries(queriesWithVars: ComponentDescriptor[]): QueryAndVariables {
440
+ const queries: string[] = [];
441
+ const fragments: string[] = [];
442
+ const superVars: { [key: string]: any } = {};
443
+ const superParams: string[] = [];
444
+
445
+ queriesWithVars.forEach((componentDescriptor: ComponentDescriptor, index: number) => {
290
446
  const queryAndVars = componentDescriptor.queryAndVariables;
291
447
  if (!queryAndVars) {
292
448
  return;
293
449
  }
450
+
294
451
  // Extract fragments first if exist
295
452
  let q = queryAndVars.query;
296
453
  let match = q.match(GRAPHQL_FRAGMENTS_REGEXP);
297
- if ((match === null || match === void 0 ? void 0 : match.length) === 1) {
454
+ if (match?.length === 1) {
298
455
  // extract a fragment to put it at root level
299
456
  fragments.push(match[0]);
300
457
  // remove it from query because queries are going to get wrapped
301
458
  q = q.replace(match[0], '');
302
459
  }
460
+
303
461
  // Extract graphql query and its params and add prefixes to exclude collisions with other queries
304
462
  match = q.match(GUILLOTINE_QUERY_REGEXP);
305
463
  let query = '';
306
464
  if (match && match.length === 2) {
307
465
  // no params, just query
308
466
  query = match[1];
309
- }
310
- else if (match && match.length === 3) {
467
+ } else if (match && match.length === 3) {
311
468
  // both query and params are present
312
469
  query = match[2];
313
470
  // process args
@@ -328,50 +485,62 @@ function combineMultipleQueries(queriesWithVars) {
328
485
  if (query.length) {
329
486
  queries.push(`${ALIAS_PREFIX}${index}:guillotine {${query}}`);
330
487
  }
488
+
331
489
  // Update variables with the same prefixes
332
490
  Object.entries(queryAndVars.variables || {}).forEach(entry => {
333
491
  superVars[`${ALIAS_PREFIX}${index}_${entry[0]}`] = entry[1];
334
492
  });
335
493
  });
494
+
336
495
  // Compose the super query
337
496
  const superQuery = `query ${superParams.length ? `(${superParams.join(', ')})` : ''} {
338
497
  ${queries.join('\n')}
339
498
  }
340
499
  ${fragments.join('\n')}
341
500
  `;
501
+
342
502
  return {
343
503
  query: superQuery,
344
504
  variables: superVars,
345
505
  };
346
506
  }
347
- function applyProcessors(componentDescriptors, contentResults, context) {
348
- return __awaiter(this, void 0, void 0, function* () {
349
- let dataCounter = 0;
350
- const processorPromises = componentDescriptors.map((desc) => __awaiter(this, void 0, void 0, function* () {
351
- var _a;
352
- // we're iterating component descriptors here
353
- // some of them might not have provided graphql requests
354
- // but we still need to run props processor for them
355
- // in case they want to fetch their data from elsewhere
356
- const propsProcessor = ((_a = desc.type) === null || _a === void 0 ? void 0 : _a.processor) || NO_PROPS_PROCESSOR;
357
- let data;
358
- if (desc.queryAndVariables) {
359
- // if there is a query then there must be a result for it
360
- data = contentResults.contents[dataCounter++];
361
- }
362
- const config = getComponentConfig(desc.component);
363
- return yield propsProcessor(data, context, config);
364
- }));
365
- return Promise.allSettled(processorPromises);
507
+
508
+ async function applyProcessors(componentDescriptors: ComponentDescriptor[], contentResults: ContentResult,
509
+ context?: Context): Promise<PromiseSettledResult<any>[]> {
510
+
511
+ let dataCounter = 0;
512
+ const processorPromises = componentDescriptors.map(async (desc: ComponentDescriptor) => {
513
+ // we're iterating component descriptors here
514
+ // some of them might not have provided graphql requests
515
+ // but we still need to run props processor for them
516
+ // in case they want to fetch their data from elsewhere
517
+ const propsProcessor = desc.type?.processor || NO_PROPS_PROCESSOR;
518
+ let data;
519
+ if (desc.queryAndVariables) {
520
+ // if there is a query then there must be a result for it
521
+ data = contentResults.contents[dataCounter++];
522
+ }
523
+
524
+ const config = getComponentConfig(desc.component);
525
+ return await propsProcessor(data, context, config);
366
526
  });
527
+
528
+ return Promise.allSettled(processorPromises);
367
529
  }
368
- function getComponentConfig(cmp) {
530
+
531
+ function getComponentConfig(cmp?: PageComponent) {
369
532
  const cmpData = cmp && cmp[cmp.type];
370
533
  return cmpData && 'config' in cmpData ? cmpData.config : undefined;
371
534
  }
372
- function collectComponentDescriptors(components, componentRegistry, xpContentPath, context) {
373
- var _a, _b;
374
- const descriptors = [];
535
+
536
+ function collectComponentDescriptors(components: PageComponent[],
537
+ componentRegistry: typeof ComponentRegistry,
538
+ xpContentPath: string,
539
+ context: Context | undefined,
540
+ ): ComponentDescriptor[] {
541
+
542
+ const descriptors: ComponentDescriptor[] = [];
543
+
375
544
  for (const cmp of (components || [])) {
376
545
  processComponentConfig(APP_NAME, APP_NAME_DASHED, cmp);
377
546
  // only look for parts
@@ -390,18 +559,19 @@ function collectComponentDescriptors(components, componentRegistry, xpContentPat
390
559
  });
391
560
  }
392
561
  }
393
- }
394
- else {
562
+ } else {
395
563
  // look for parts inside fragments
396
- const fragPartDescs = collectComponentDescriptors((_b = (_a = cmp.fragment) === null || _a === void 0 ? void 0 : _a.fragment) === null || _b === void 0 ? void 0 : _b.components, componentRegistry, xpContentPath, context);
564
+ const fragPartDescs = collectComponentDescriptors(cmp.fragment?.fragment?.components, componentRegistry, xpContentPath, context);
397
565
  if (fragPartDescs.length) {
398
566
  descriptors.push(...fragPartDescs);
399
567
  }
400
568
  }
401
569
  }
570
+
402
571
  return descriptors;
403
572
  }
404
- function processComponentConfig(myAppName, myAppNameDashed, cmp) {
573
+
574
+ function processComponentConfig(myAppName: string, myAppNameDashed: string, cmp: PageComponent) {
405
575
  const cmpData = cmp[cmp.type];
406
576
  if (cmpData && 'descriptor' in cmpData && cmpData.descriptor) {
407
577
  const [appName, cmpName] = cmpData.descriptor.split(':');
@@ -409,7 +579,7 @@ function processComponentConfig(myAppName, myAppNameDashed, cmp) {
409
579
  return;
410
580
  }
411
581
  let config;
412
- const configArray = [];
582
+ const configArray: Object[] = [];
413
583
  if ('configAsJson' in cmpData && cmpData.configAsJson && cmpData.configAsJson[myAppNameDashed]) {
414
584
  config = cmpData.configAsJson[myAppNameDashed][cmpName];
415
585
  if (config) {
@@ -429,86 +599,108 @@ function processComponentConfig(myAppName, myAppNameDashed, cmp) {
429
599
  }
430
600
  }
431
601
  }
432
- function getQueryAndVariables(type, path, selectedQuery, context, config) {
602
+
603
+ function getQueryAndVariables(type: string,
604
+ path: string,
605
+ selectedQuery?: SelectedQueryMaybeVariablesFunc,
606
+ context?: Context,
607
+ config?: any): QueryAndVariables | undefined {
608
+
433
609
  let query, getVariables;
610
+
434
611
  if (typeof selectedQuery === 'string' || typeof selectedQuery === 'function') {
435
612
  query = selectedQuery;
436
- }
437
- else if (Array.isArray(selectedQuery)) {
613
+
614
+ } else if (Array.isArray(selectedQuery)) {
438
615
  query = selectedQuery[0];
439
616
  getVariables = selectedQuery[1];
440
- }
441
- else if (typeof selectedQuery === 'object') {
617
+
618
+ } else if (typeof selectedQuery === 'object') {
442
619
  query = selectedQuery.query;
443
620
  getVariables = selectedQuery.variables;
444
621
  }
622
+
445
623
  if (getVariables && typeof getVariables !== 'function') {
446
624
  throw Error(`getVariables for content type ${type} should be a function, not: ${typeof getVariables}`);
447
625
  }
626
+
448
627
  if (query && typeof query !== 'string' && typeof query !== 'function') {
449
628
  throw Error(`Query for content type ${type} should be a string or function, not: ${typeof query}`);
450
629
  }
630
+
451
631
  if (typeof query === 'function') {
452
632
  query = query(path, context, config);
453
633
  }
634
+
454
635
  if (query) {
455
636
  return {
456
637
  query,
457
- variables: getVariables ? getVariables(path, context, config) : { path },
638
+ variables: getVariables ? getVariables(path, context, config) : {path},
458
639
  };
459
640
  }
460
641
  }
461
- function createPageData(contentType, components, componentPath) {
642
+
643
+
644
+ function createPageData(contentType: string, components: PageComponent[], componentPath?: string): PageComponent | undefined {
462
645
  let page;
463
646
  if (components && !componentPath) {
464
647
  page = buildPage(contentType, components);
465
- }
466
- else {
648
+ } else {
467
649
  // Don't build page for single component
468
650
  page = null;
469
651
  }
470
- return page;
652
+ return page as PageComponent;
471
653
  }
472
- function createMetaData(contentType, contentPath, requestType, renderMode, apiUrl, baseUrl, locale, defaultLocale, requestedComponentPath, pageCmp, components = []) {
473
- var _a;
654
+
655
+
656
+ function createMetaData(contentType: string, contentPath: string,
657
+ requestType: XP_REQUEST_TYPE, renderMode: RENDER_MODE,
658
+ apiUrl: string, baseUrl: string,
659
+ locale: string, defaultLocale: string,
660
+ requestedComponentPath: string | undefined,
661
+ pageCmp?: PageComponent, components: PageComponent[] = []): MetaData {
474
662
  // .meta will be visible in final rendered inline props.
475
663
  // Only adding some .meta attributes here on certain conditions
476
664
  // (instead of always adding them and letting them be visible as false/undefined etc)
477
- const meta = {
665
+ const meta: MetaData = {
478
666
  type: contentType,
479
667
  path: contentPath,
480
668
  requestType: requestType,
481
669
  renderMode: renderMode,
482
670
  canRender: false,
483
- catchAll: false,
671
+ catchAll: false, // catchAll only refers to content type catch-all
484
672
  apiUrl,
485
673
  baseUrl,
486
674
  locale,
487
675
  defaultLocale,
488
676
  };
677
+
489
678
  if (requestedComponentPath) {
490
679
  meta.requestedComponent = components.find(cmp => cmp.path === requestedComponentPath);
491
680
  }
492
- const pageDesc = (_a = pageCmp === null || pageCmp === void 0 ? void 0 : pageCmp.page) === null || _a === void 0 ? void 0 : _a.descriptor;
681
+
682
+ const pageDesc = pageCmp?.page?.descriptor;
493
683
  const typeDef = ComponentRegistry.getContentType(contentType);
494
- if ((typeDef === null || typeDef === void 0 ? void 0 : typeDef.view) && !typeDef.catchAll) {
684
+ if (typeDef?.view && !typeDef.catchAll) {
495
685
  meta.canRender = true;
496
- }
497
- else if (requestType === XP_REQUEST_TYPE.COMPONENT) {
686
+ } else if (requestType === XP_REQUEST_TYPE.COMPONENT) {
498
687
  // always render a single component (show missing if not implemented)
499
688
  meta.canRender = true;
500
- }
501
- else if (pageDesc) {
689
+ } else if (pageDesc) {
502
690
  // always render a page if there is a descriptor (show missing if not implemented)
503
691
  meta.canRender = true;
504
- }
505
- else if (typeDef === null || typeDef === void 0 ? void 0 : typeDef.view) {
692
+ } else if (typeDef?.view) {
506
693
  meta.canRender = true;
507
694
  meta.catchAll = true;
508
695
  }
696
+
509
697
  return meta;
510
698
  }
511
- function errorResponse(code = '500', message = 'Unknown error', requestType, renderMode, apiUrl, baseUrl, locale, defaultLocale, contentPath) {
699
+
700
+ function errorResponse(code = '500', message = 'Unknown error',
701
+ requestType: XP_REQUEST_TYPE, renderMode: RENDER_MODE,
702
+ apiUrl: string, baseUrl: string, locale: string, defaultLocale: string,
703
+ contentPath?: string): FetchContentResult {
512
704
  return {
513
705
  error: {
514
706
  code,
@@ -531,18 +723,22 @@ function errorResponse(code = '500', message = 'Unknown error', requestType, ren
531
723
  },
532
724
  };
533
725
  }
534
- function restrictComponentsToPath(contentType, components, componentPath) {
535
- if (!componentPath || !(components === null || components === void 0 ? void 0 : components.length)) {
726
+
727
+ function restrictComponentsToPath(contentType: string, components?: PageComponent[], componentPath?: string) {
728
+ if (!componentPath || !components?.length) {
536
729
  return components || [];
537
730
  }
731
+
538
732
  // filter components to the requested one only
539
733
  const component = components.find(cmp => {
540
734
  return cmp.path === componentPath;
541
735
  });
736
+
542
737
  if (!component) {
543
738
  return [];
544
739
  }
545
- let result = [component];
740
+
741
+ let result: PageComponent[] = [component];
546
742
  if (component.type !== XP_COMPONENT_TYPE.LAYOUT) {
547
743
  // remember to include all parent layouts too !
548
744
  const cmpPath = parseComponentPath(contentType, component.path);
@@ -553,8 +749,7 @@ function restrictComponentsToPath(contentType, components, componentPath) {
553
749
  result.unshift(parentCmp);
554
750
  }
555
751
  }
556
- }
557
- else {
752
+ } else {
558
753
  // It's a layout, include child components
559
754
  const childCmps = components.filter(cmp => cmp.path !== component.path && cmp.path.startsWith(component.path));
560
755
  if (childCmps.length) {
@@ -563,30 +758,40 @@ function restrictComponentsToPath(contentType, components, componentPath) {
563
758
  }
564
759
  return result;
565
760
  }
566
- const COMPONENT_PATH_KEY = /\/?_\/component/; // first slash is optional for root components
567
- const getContentAndComponentPaths = (requestPath, context) => {
761
+
762
+ const COMPONENT_PATH_KEY = /\/?_\/component/; // first slash is optional for root components
763
+
764
+ const getContentAndComponentPaths = (requestPath: string, context: Context): string[] => {
568
765
  let contentPath, componentPath;
569
766
  if (COMPONENT_PATH_KEY.test(requestPath)) {
570
767
  [contentPath, componentPath] = requestPath.split(COMPONENT_PATH_KEY);
571
- }
572
- else {
768
+ } else {
573
769
  contentPath = requestPath;
574
770
  }
575
771
  return [contentPath, componentPath];
576
772
  };
773
+
577
774
  // ///////////////////////////// ENTRY 1 - THE BUILDER:
775
+
578
776
  /**
579
777
  * Configures, builds and returns a general fetchContent function.
580
778
  * @param config object containing ComponentRegistry as well as constants imported from enonic-connecion-config.js
581
779
  * @returns ContentFetcher
582
780
  */
583
- const buildContentFetcher = (config) => {
584
- const { APP_NAME, APP_NAME_DASHED, componentRegistry, } = config;
585
- return (contentPathOrArray, context) => __awaiter(void 0, void 0, void 0, function* () {
586
- var _a, _b;
781
+ const buildContentFetcher = <T extends AdapterConstants>(config: FetcherConfig<T>): ContentFetcher => {
782
+
783
+ const {
784
+ APP_NAME,
785
+ APP_NAME_DASHED,
786
+ componentRegistry,
787
+ } = config;
788
+
789
+ return async (contentPathOrArray: string | string[], context: Context): Promise<FetchContentResult> => {
790
+
587
791
  if (context.preview) {
588
792
  populateEnonicHeaders(context);
589
793
  }
794
+
590
795
  const headers = {};
591
796
  addJsessionHeaders(headers, context);
592
797
  addLocaleHeaders(headers, context);
@@ -595,70 +800,91 @@ const buildContentFetcher = (config) => {
595
800
  const projectConfig = getLocaleProjectConfig(context);
596
801
  const renderMode = getRenderMode(context);
597
802
  let requestType = XP_REQUEST_TYPE.TYPE;
803
+
598
804
  UrlProcessor.setSiteKey(projectConfig.site);
805
+
599
806
  try {
600
807
  const requestContentPath = getCleanContentPathArrayOrThrow400(contentPathOrArray);
808
+
601
809
  if ('/' + requestContentPath === PURGE_CACHE_URL) {
602
810
  // return 404 for /_/cache/enonic/purge because it should've been handled by standalone endpoint
603
811
  return errorResponse('404', 'Not found', requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, requestContentPath);
604
812
  }
813
+
605
814
  const [siteRelativeContentPath, componentPath] = getContentAndComponentPaths(requestContentPath, context);
606
815
  if (componentPath) {
607
816
  // set component request type because url contains component path
608
817
  requestType = XP_REQUEST_TYPE.COMPONENT;
609
818
  }
819
+
610
820
  // ///////////// FIRST GUILLOTINE CALL FOR METADATA /////////////////
611
- const metaResult = yield fetchMetaData(contentApiUrl, '${site}/' + siteRelativeContentPath, projectConfig, headers);
821
+ const metaResult = await fetchMetaData(contentApiUrl, '${site}/' + siteRelativeContentPath, projectConfig, headers);
612
822
  // ///////////////////////////////////////////////////////////////////////
613
- const { _path, type } = metaResult.meta || {};
823
+
824
+ const {_path, type} = metaResult.meta || {};
614
825
  const contentPath = _path || siteRelativeContentPath;
826
+
615
827
  if (metaResult.error) {
616
828
  console.error(metaResult.error);
617
- return errorResponse(metaResult.error.code, metaResult.error.message, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
829
+ return errorResponse(metaResult.error.code, metaResult.error.message, requestType, renderMode, contentApiUrl, xpBaseUrl,
830
+ context.locale, context.defaultLocale, contentPath);
618
831
  }
832
+
619
833
  if (!metaResult.meta) {
620
- return errorResponse('404', 'No meta data found for content, most likely content does not exist', requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
621
- }
622
- else if (!type) {
623
- return errorResponse('500', "Server responded with incomplete meta data: missing content 'type' attribute.", requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
624
- }
625
- else if (renderMode === RENDER_MODE.NEXT && !IS_DEV_MODE &&
834
+ return errorResponse('404', 'No meta data found for content, most likely content does not exist', requestType, renderMode,
835
+ contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
836
+ } else if (!type) {
837
+ return errorResponse('500', "Server responded with incomplete meta data: missing content 'type' attribute.", requestType,
838
+ renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
839
+
840
+ } else if (renderMode === RENDER_MODE.NEXT && !IS_DEV_MODE &&
626
841
  (type === FRAGMENT_CONTENTTYPE_NAME ||
627
842
  type === PAGE_TEMPLATE_CONTENTTYPE_NAME ||
628
843
  type === PAGE_TEMPLATE_FOLDER)) {
629
- return errorResponse('404', `Content type [${type}] is not accessible in ${renderMode} mode`, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
844
+ return errorResponse('404', `Content type [${type}] is not accessible in ${renderMode} mode`, requestType, renderMode,
845
+ contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
630
846
  }
847
+
631
848
  const components = restrictComponentsToPath(type, metaResult.meta.components, componentPath);
632
849
  if (componentPath && !components.length) {
633
850
  // component was not found
634
- return errorResponse('404', `Component ${componentPath} was not found`, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
851
+ return errorResponse('404', `Component ${componentPath} was not found`, requestType, renderMode,
852
+ contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
635
853
  }
854
+
636
855
  if (requestType !== XP_REQUEST_TYPE.COMPONENT && components.length > 0) {
637
856
  requestType = XP_REQUEST_TYPE.PAGE;
638
857
  }
858
+
639
859
  // ////////////////////////////////////////////////// Content type established. Proceed to data call:
640
- const allDescriptors = [];
860
+
861
+ const allDescriptors: ComponentDescriptor[] = [];
862
+
641
863
  // Add the content type query at all cases
642
- const contentTypeDef = componentRegistry === null || componentRegistry === void 0 ? void 0 : componentRegistry.getContentType(type);
864
+ const contentTypeDef = componentRegistry?.getContentType(type);
643
865
  const pageCmp = (components || []).find(cmp => cmp.type === XP_COMPONENT_TYPE.PAGE);
644
866
  if (pageCmp) {
645
867
  processComponentConfig(APP_NAME, APP_NAME_DASHED, pageCmp);
646
868
  }
647
- const contentQueryAndVars = getQueryAndVariables(type, contentPath, contentTypeDef === null || contentTypeDef === void 0 ? void 0 : contentTypeDef.query, context, (_a = pageCmp === null || pageCmp === void 0 ? void 0 : pageCmp.page) === null || _a === void 0 ? void 0 : _a.config);
869
+
870
+ const contentQueryAndVars = getQueryAndVariables(type, contentPath, contentTypeDef?.query, context, pageCmp?.page?.config);
648
871
  if (contentQueryAndVars) {
649
872
  allDescriptors.push({
650
873
  type: contentTypeDef,
651
874
  queryAndVariables: contentQueryAndVars,
652
875
  });
653
876
  }
654
- const commonQueryAndVars = getQueryAndVariables(type, contentPath, componentRegistry.getCommonQuery(), context, (_b = pageCmp === null || pageCmp === void 0 ? void 0 : pageCmp.page) === null || _b === void 0 ? void 0 : _b.config);
877
+
878
+ const commonQueryAndVars = getQueryAndVariables(type, contentPath, componentRegistry.getCommonQuery(), context,
879
+ pageCmp?.page?.config);
655
880
  if (commonQueryAndVars) {
656
881
  allDescriptors.push({
657
882
  type: contentTypeDef,
658
883
  queryAndVariables: commonQueryAndVars,
659
884
  });
660
885
  }
661
- if ((components === null || components === void 0 ? void 0 : components.length) && componentRegistry) {
886
+
887
+ if (components?.length && componentRegistry) {
662
888
  for (const cmp of (components || [])) {
663
889
  processComponentConfig(APP_NAME, APP_NAME_DASHED, cmp);
664
890
  }
@@ -668,20 +894,29 @@ const buildContentFetcher = (config) => {
668
894
  allDescriptors.push(...componentDescriptors);
669
895
  }
670
896
  }
671
- const { query, variables } = combineMultipleQueries(allDescriptors);
897
+
898
+ const {query, variables} = combineMultipleQueries(allDescriptors);
899
+
672
900
  if (!query.trim()) {
673
- return errorResponse('400', `Missing or empty query override for content type ${type}`, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
901
+ return errorResponse('400', `Missing or empty query override for content type ${type}`, requestType, renderMode,
902
+ contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
674
903
  }
904
+
675
905
  // /////////////// SECOND GUILLOTINE CALL FOR DATA //////////////////////
676
- const contentResults = yield fetchContentData(contentApiUrl, contentPath, projectConfig, query, variables, headers);
906
+ const contentResults = await fetchContentData(contentApiUrl, contentPath, projectConfig, query, variables, headers);
677
907
  // ///////////////////////////////////////////////////////////////////////////
908
+
678
909
  if (contentResults.error) {
679
910
  console.error(contentResults.error);
680
- return errorResponse(contentResults.error.code, contentResults.error.message, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
911
+ return errorResponse(contentResults.error.code, contentResults.error.message, requestType, renderMode, contentApiUrl,
912
+ xpBaseUrl, context.locale, context.defaultLocale, contentPath);
681
913
  }
914
+
682
915
  // Apply processors to every component
683
- const datas = yield applyProcessors(allDescriptors, contentResults, context);
916
+ const datas = await applyProcessors(allDescriptors, contentResults, context);
917
+
684
918
  // Unwind the data back to components
919
+
685
920
  let contentData = null, common = null;
686
921
  let startFrom = 0;
687
922
  if (contentQueryAndVars) {
@@ -694,6 +929,7 @@ const buildContentFetcher = (config) => {
694
929
  common = item.status === 'fulfilled' ? item.value : item.reason;
695
930
  startFrom++;
696
931
  }
932
+
697
933
  for (let i = startFrom; i < datas.length; i++) {
698
934
  // component descriptors hold references to components
699
935
  // that will later be used for creating page regions
@@ -702,42 +938,46 @@ const buildContentFetcher = (config) => {
702
938
  let reason = datum.reason;
703
939
  if (reason instanceof Error) {
704
940
  reason = reason.message;
705
- }
706
- else if (typeof reason !== 'string') {
941
+ } else if (typeof reason !== 'string') {
707
942
  reason = String(reason);
708
943
  }
709
944
  allDescriptors[i].component.error = reason;
710
- }
711
- else {
945
+ } else {
712
946
  allDescriptors[i].component.data = datum.value;
713
947
  }
714
948
  }
949
+
715
950
  const page = createPageData(type, components);
716
951
  const meta = createMetaData(type, siteRelativeContentPath, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, componentPath, page, components);
952
+
717
953
  return {
718
954
  data: contentData,
719
955
  common,
720
956
  meta,
721
957
  page,
722
- };
723
- }
724
- catch (e) {
958
+ } as FetchContentResult;
959
+
960
+ } catch (e: any) {
725
961
  console.error(e);
962
+
726
963
  let error;
727
964
  try {
728
965
  error = JSON.parse(e.message);
729
- }
730
- catch (e2) {
966
+ } catch (e2) {
731
967
  error = {
732
968
  code: 'Local',
733
969
  message: e.message,
734
970
  };
735
971
  }
736
- return errorResponse(error.code, error.message, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPathOrArray.toString());
972
+ return errorResponse(error.code, error.message, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale,
973
+ context.defaultLocale, contentPathOrArray.toString());
737
974
  }
738
- });
975
+ };
739
976
  };
977
+
978
+
740
979
  // //////////////////////////// ENTRY 2: ready-to-use fetchContent function
980
+
741
981
  /**
742
982
  * Default fetchContent function, built with params from imports.
743
983
  * It runs custom content-type-specific guillotine calls against an XP guillotine endpoint, returns content data, error and some meta data
@@ -746,11 +986,16 @@ const buildContentFetcher = (config) => {
746
986
  * @param context object from Next, contains .query info
747
987
  * @returns FetchContentResult object: {data?: T, error?: {code, message}}
748
988
  */
749
- export const fetchContent = buildContentFetcher(Object.assign(Object.assign({}, adapterConstants), { componentRegistry: ComponentRegistry }));
750
- export function createResponse(props, context) {
751
- var _a, _b, _c, _d;
752
- const { data, meta, error } = props;
753
- const pageUrl = (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.get) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.target) === null || _c === void 0 ? void 0 : _c.pageUrl;
989
+ export const fetchContent: ContentFetcher = buildContentFetcher<AdapterConstants>({
990
+ ...adapterConstants,
991
+ componentRegistry: ComponentRegistry,
992
+ });
993
+
994
+ export function createResponse(props: FetchContentResult, context?: Context, isStatic?: true): GetStaticPropsResult<FetchContentResult>;
995
+ export function createResponse(props: FetchContentResult, context?: Context, isStatic?: false): GetServerSidePropsResult<FetchContentResult>;
996
+ export function createResponse(props: FetchContentResult, context?: Context, isStatic = true): GetStaticPropsResult<FetchContentResult> | GetServerSidePropsResult<FetchContentResult> {
997
+ const {data, meta, error} = props;
998
+ const pageUrl = data?.get?.data?.target?.pageUrl;
754
999
  if (meta.type === 'base:shortcut' && pageUrl) {
755
1000
  if (meta.renderMode !== RENDER_MODE.NEXT) {
756
1001
  // console.debug(`Returning 404 for shortcut in ${RENDER_MODE.NEXT} mode`);
@@ -759,6 +1004,7 @@ export function createResponse(props, context) {
759
1004
  notFound: true,
760
1005
  };
761
1006
  }
1007
+
762
1008
  const destination = getUrl(pageUrl, meta, true);
763
1009
  // console.debug('Redirecting to', destination);
764
1010
  return {
@@ -768,59 +1014,66 @@ export function createResponse(props, context) {
768
1014
  },
769
1015
  };
770
1016
  }
1017
+
771
1018
  // we can not set 418 for static paths,
772
1019
  // but we can show 404 instead to be handled in CS
773
1020
  const canNotRender = meta && !meta.canRender && meta.renderMode !== RENDER_MODE.EDIT;
774
- const catchAllInNextProdMode = (meta === null || meta === void 0 ? void 0 : meta.renderMode) === RENDER_MODE.NEXT && !IS_DEV_MODE && (meta === null || meta === void 0 ? void 0 : meta.catchAll);
775
- const notFound = (error && error.code === '404') || ((_d = context.res) === null || _d === void 0 ? void 0 : _d.statusCode) === 404 || canNotRender || catchAllInNextProdMode || undefined;
1021
+
1022
+ const catchAllInNextProdMode = meta?.renderMode === RENDER_MODE.NEXT && !IS_DEV_MODE && meta?.catchAll;
1023
+
1024
+ const notFound = (error && error.code === '404') || context.res?.statusCode === 404 || canNotRender || catchAllInNextProdMode || undefined;
1025
+
776
1026
  // console.debug('Returning view ' + (notFound ? '(not found)' : ''));
777
- return {
1027
+ const result: GetStaticPropsResult<FetchContentResult> | GetServerSidePropsResult<FetchContentResult> = {
778
1028
  notFound,
779
1029
  props,
780
- revalidate: 3600, // In seconds, meaning every hour
781
1030
  };
1031
+
1032
+ if (isStatic) {
1033
+ (<GetStaticPropsResult<FetchContentResult>>result).revalidate = 3600; // In seconds, meaning every hour
1034
+ }
1035
+
1036
+ return result;
782
1037
  }
783
- function populateEnonicHeaders(context) {
1038
+
1039
+ function populateEnonicHeaders(context: Context) {
784
1040
  const pd = context.previewData;
785
1041
  if (!pd) {
786
1042
  return;
787
1043
  }
788
- const req = context.req || {};
1044
+ const req = context.req || {} as any;
789
1045
  req.headers = Object.assign(req.headers || {}, pd.headers);
790
1046
  context.params = Object.assign(context.params || {}, pd.params);
791
1047
  context.req = req;
792
1048
  }
793
- export function fetchContentPathsForAllLocales(path, query = GET_STATIC_PATHS_QUERY, countPerLocale = 999) {
794
- return __awaiter(this, void 0, void 0, function* () {
795
- const promises = Object.values(getLocaleProjectConfigs()).map(config => fetchContentPathsForLocale(path, config, query, countPerLocale));
796
- return Promise.all(promises).then(results => {
797
- return results.reduce((all, localePaths) => all.concat(localePaths), []);
798
- });
1049
+
1050
+ export async function fetchContentPathsForAllLocales(path: string, query: string = GET_STATIC_PATHS_QUERY, countPerLocale = 999): Promise<ContentPathItem[]> {
1051
+ const promises = Object.values(getLocaleProjectConfigs()).map(config => fetchContentPathsForLocale(path, config, query, countPerLocale));
1052
+ return Promise.all(promises).then(results => {
1053
+ return results.reduce((all, localePaths) => all.concat(localePaths), []);
799
1054
  });
800
1055
  }
801
- export function fetchContentPathsForLocale(path, config, query = GET_STATIC_PATHS_QUERY, count = 999) {
802
- return __awaiter(this, void 0, void 0, function* () {
803
- const contentApiUrl = getContentApiUrl({ locale: config.locale });
804
- const body = {
805
- query,
806
- variables: {
807
- path,
808
- count,
809
- },
810
- };
811
- return fetchGuillotine(contentApiUrl, body, config).then((results) => {
812
- return results.guillotine.queryDsl.reduce((prev, child) => {
813
- var _a;
814
- const regexp = new RegExp(`/${(_a = child.site) === null || _a === void 0 ? void 0 : _a._name}/?`);
815
- const contentPath = child._path.replace(regexp, '');
816
- prev.push({
817
- params: {
818
- contentPath: contentPath.split('/'),
819
- },
820
- locale: normalizeLocale(config.locale),
821
- });
822
- return prev;
823
- }, []);
824
- });
1056
+
1057
+ export async function fetchContentPathsForLocale(path: string, config: LocaleProjectConfig, query: string = GET_STATIC_PATHS_QUERY, count = 999): Promise<ContentPathItem[]> {
1058
+ const contentApiUrl = getContentApiUrl({locale: config.locale});
1059
+ const body: ContentApiBaseBody = {
1060
+ query,
1061
+ variables: {
1062
+ path,
1063
+ count,
1064
+ },
1065
+ };
1066
+ return fetchGuillotine(contentApiUrl, body, config).then((results: GuillotineResult) => {
1067
+ return results.guillotine.queryDsl.reduce((prev: ContentPathItem[], child: any) => {
1068
+ const regexp = new RegExp(`/${child.site?._name}/?`);
1069
+ const contentPath = child._path.replace(regexp, '');
1070
+ prev.push({
1071
+ params: {
1072
+ contentPath: contentPath.split('/'),
1073
+ },
1074
+ locale: normalizeLocale(config.locale),
1075
+ });
1076
+ return prev;
1077
+ }, []);
825
1078
  });
826
1079
  }