@enonic/nextjs-adapter 2.0.0 → 3.0.0-B2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/baseMappings.js +3 -2
- package/baseMappings.js.map +1 -0
- package/client.d.ts +1 -0
- package/client.js +3 -0
- package/client.js.map +1 -0
- package/common/ComponentRegistry.d.ts +34 -0
- package/{ComponentRegistry.js → common/ComponentRegistry.js} +26 -26
- package/common/ComponentRegistry.js.map +1 -0
- package/{UrlProcessor.d.ts → common/UrlProcessor.d.ts} +5 -4
- package/{UrlProcessor.js → common/UrlProcessor.js} +40 -17
- package/common/UrlProcessor.js.map +1 -0
- package/common/constants.d.ts +50 -0
- package/common/constants.js +79 -0
- package/common/constants.js.map +1 -0
- package/common/env.d.ts +11 -0
- package/common/env.js +28 -0
- package/common/env.js.map +1 -0
- package/guillotine/applyProcessors.d.ts +2 -0
- package/guillotine/applyProcessors.js +33 -0
- package/guillotine/applyProcessors.js.map +1 -0
- package/guillotine/buildComponentTree.d.ts +2 -0
- package/guillotine/buildComponentTree.js +45 -0
- package/guillotine/buildComponentTree.js.map +1 -0
- package/guillotine/buildErrorResponse.d.ts +3 -0
- package/guillotine/buildErrorResponse.js +26 -0
- package/guillotine/buildErrorResponse.js.map +1 -0
- package/guillotine/buildPage.d.ts +2 -0
- package/guillotine/buildPage.js +10 -0
- package/guillotine/buildPage.js.map +1 -0
- package/guillotine/collectComponentDescriptors.d.ts +6 -0
- package/guillotine/collectComponentDescriptors.js +43 -0
- package/guillotine/collectComponentDescriptors.js.map +1 -0
- package/guillotine/combineMultipleQueries.d.ts +2 -0
- package/guillotine/combineMultipleQueries.js +58 -0
- package/guillotine/combineMultipleQueries.js.map +1 -0
- package/guillotine/createMetaData.d.ts +17 -0
- package/guillotine/createMetaData.js +44 -0
- package/guillotine/createMetaData.js.map +1 -0
- package/guillotine/fetchContent.d.ts +1 -41
- package/guillotine/fetchContent.js +193 -800
- package/guillotine/fetchContent.js.map +1 -0
- package/guillotine/fetchContentData.d.ts +2 -0
- package/guillotine/fetchContentData.js +27 -0
- package/guillotine/fetchContentData.js.map +1 -0
- package/guillotine/fetchContentPathsForAllLocales.d.ts +2 -0
- package/guillotine/fetchContentPathsForAllLocales.js +21 -0
- package/guillotine/fetchContentPathsForAllLocales.js.map +1 -0
- package/guillotine/fetchContentPathsForLocale.d.ts +2 -0
- package/guillotine/fetchContentPathsForLocale.js +40 -0
- package/guillotine/fetchContentPathsForLocale.js.map +1 -0
- package/guillotine/fetchFromApi.d.ts +3 -0
- package/guillotine/fetchFromApi.js +65 -0
- package/guillotine/fetchFromApi.js.map +1 -0
- package/guillotine/fetchGuillotine.d.ts +3 -0
- package/guillotine/fetchGuillotine.js +55 -0
- package/guillotine/fetchGuillotine.js.map +1 -0
- package/guillotine/fetchMetaData.d.ts +2 -0
- package/guillotine/fetchMetaData.js +30 -0
- package/guillotine/fetchMetaData.js.map +1 -0
- package/guillotine/getCleanContentPathArrayOrThrow400.d.ts +2 -0
- package/guillotine/getCleanContentPathArrayOrThrow400.js +20 -0
- package/guillotine/getCleanContentPathArrayOrThrow400.js.map +1 -0
- package/guillotine/getComponentConfig.d.ts +2 -0
- package/guillotine/getComponentConfig.js +5 -0
- package/guillotine/getComponentConfig.js.map +1 -0
- package/guillotine/getContentAndComponentPaths.d.ts +1 -0
- package/guillotine/getContentAndComponentPaths.js +12 -0
- package/guillotine/getContentAndComponentPaths.js.map +1 -0
- package/guillotine/getMetaData.d.ts +0 -92
- package/guillotine/getMetaData.js +47 -109
- package/guillotine/getMetaData.js.map +1 -0
- package/guillotine/getParentRegion.d.ts +2 -0
- package/guillotine/getParentRegion.js +40 -0
- package/guillotine/getParentRegion.js.map +1 -0
- package/guillotine/getQueryAndVariables.d.ts +2 -0
- package/guillotine/getQueryAndVariables.js +32 -0
- package/guillotine/getQueryAndVariables.js.map +1 -0
- package/guillotine/metadata/configQuery.d.ts +2 -0
- package/guillotine/metadata/configQuery.js +36 -0
- package/guillotine/metadata/configQuery.js.map +1 -0
- package/guillotine/metadata/richTextQuery.d.ts +1 -0
- package/guillotine/metadata/richTextQuery.js +32 -0
- package/guillotine/metadata/richTextQuery.js.map +1 -0
- package/guillotine/parseComponentPath.d.ts +2 -0
- package/guillotine/parseComponentPath.js +22 -0
- package/guillotine/parseComponentPath.js.map +1 -0
- package/guillotine/prefixLayoutPath.d.ts +1 -0
- package/guillotine/prefixLayoutPath.js +13 -0
- package/guillotine/prefixLayoutPath.js.map +1 -0
- package/guillotine/processComponentConfig.d.ts +2 -0
- package/guillotine/processComponentConfig.js +30 -0
- package/guillotine/processComponentConfig.js.map +1 -0
- package/guillotine/restrictComponentsToPath.d.ts +2 -0
- package/guillotine/restrictComponentsToPath.js +35 -0
- package/guillotine/restrictComponentsToPath.js.map +1 -0
- package/guillotine/validateData.d.ts +2 -0
- package/guillotine/validateData.js +7 -0
- package/guillotine/validateData.js.map +1 -0
- package/guillotine/validateNotFound.d.ts +2 -0
- package/guillotine/validateNotFound.js +16 -0
- package/guillotine/validateNotFound.js.map +1 -0
- package/guillotine/validateShortcut.d.ts +2 -0
- package/guillotine/validateShortcut.js +29 -0
- package/guillotine/validateShortcut.js.map +1 -0
- package/i18n/LocaleContext.d.ts +7 -0
- package/i18n/LocaleContext.jsx +46 -0
- package/i18n/LocaleContext.jsx.map +1 -0
- package/i18n/i18n.d.ts +11 -0
- package/i18n/i18n.js +57 -0
- package/i18n/i18n.js.map +1 -0
- package/index.d.ts +18 -5
- package/index.js +18 -5
- package/index.js.map +1 -0
- package/package.json +67 -16
- package/query/Shortcut.js +1 -0
- package/query/Shortcut.js.map +1 -0
- package/types/component.d.ts +114 -0
- package/types/component.js +2 -0
- package/types/component.js.map +1 -0
- package/types/componentProps.d.ts +104 -0
- package/types/componentProps.js +2 -0
- package/types/componentProps.js.map +1 -0
- package/types/guillotine.d.ts +342 -0
- package/types/guillotine.js +2 -0
- package/types/guillotine.js.map +1 -0
- package/types/i18n.d.ts +7 -0
- package/types/i18n.js +2 -0
- package/types/i18n.js.map +1 -0
- package/types/index.d.ts +45 -0
- package/types/index.js +3 -0
- package/types/index.js.map +1 -0
- package/types/next.d.ts +6 -0
- package/types/next.js +2 -0
- package/types/next.js.map +1 -0
- package/types/util.d.ts +3 -0
- package/types/util.js +3 -0
- package/types/util.js.map +1 -0
- package/utils/addLineNumbers.d.ts +1 -0
- package/utils/addLineNumbers.js +4 -0
- package/utils/addLineNumbers.js.map +1 -0
- package/utils/buildGuillotineRequestHeaders.d.ts +7 -0
- package/utils/buildGuillotineRequestHeaders.js +16 -0
- package/utils/buildGuillotineRequestHeaders.js.map +1 -0
- package/utils/commonChars.d.ts +1 -0
- package/utils/commonChars.js +17 -0
- package/utils/commonChars.js.map +1 -0
- package/utils/fixDoubleSlashes.d.ts +1 -0
- package/utils/fixDoubleSlashes.js +4 -0
- package/utils/fixDoubleSlashes.js.map +1 -0
- package/utils/getContentApiUrl.d.ts +2 -0
- package/utils/getContentApiUrl.js +15 -0
- package/utils/getContentApiUrl.js.map +1 -0
- package/utils/getProjectLocaleConfig.d.ts +2 -0
- package/utils/getProjectLocaleConfig.js +19 -0
- package/utils/getProjectLocaleConfig.js.map +1 -0
- package/utils/getProjectLocaleConfigById.d.ts +2 -0
- package/utils/getProjectLocaleConfigById.js +16 -0
- package/utils/getProjectLocaleConfigById.js.map +1 -0
- package/utils/getProjectLocaleConfigByLocale.d.ts +2 -0
- package/utils/getProjectLocaleConfigByLocale.js +13 -0
- package/utils/getProjectLocaleConfigByLocale.js.map +1 -0
- package/utils/getProjectLocaleConfigs.d.ts +2 -0
- package/utils/getProjectLocaleConfigs.js +30 -0
- package/utils/getProjectLocaleConfigs.js.map +1 -0
- package/utils/getProjectLocales.d.ts +1 -0
- package/utils/getProjectLocales.js +5 -0
- package/utils/getProjectLocales.js.map +1 -0
- package/utils/getRenderMode.d.ts +3 -0
- package/utils/getRenderMode.js +8 -0
- package/utils/getRenderMode.js.map +1 -0
- package/utils/getRequestLocaleInfo.d.ts +6 -0
- package/utils/getRequestLocaleInfo.js +26 -0
- package/utils/getRequestLocaleInfo.js.map +1 -0
- package/utils/getXpBaseUrl.d.ts +2 -0
- package/utils/getXpBaseUrl.js +8 -0
- package/utils/getXpBaseUrl.js.map +1 -0
- package/utils/indent.d.ts +1 -0
- package/utils/indent.js +5 -0
- package/utils/indent.js.map +1 -0
- package/utils/sanitizeGraphqlName.d.ts +1 -0
- package/utils/sanitizeGraphqlName.js +12 -0
- package/utils/sanitizeGraphqlName.js.map +1 -0
- package/views/BaseComponent.d.ts +5 -10
- package/views/BaseComponent.jsx +17 -6
- package/views/BaseComponent.jsx.map +1 -0
- package/views/BaseContent.d.ts +3 -3
- package/views/BaseContent.jsx +2 -5
- package/views/BaseContent.jsx.map +1 -0
- package/views/BaseLayout.d.ts +3 -16
- package/views/BaseLayout.jsx +3 -3
- package/views/BaseLayout.jsx.map +1 -0
- package/views/BaseMacro.d.ts +3 -13
- package/views/BaseMacro.jsx +4 -3
- package/views/BaseMacro.jsx.map +1 -0
- package/views/BasePage.d.ts +3 -18
- package/views/BasePage.jsx +3 -3
- package/views/BasePage.jsx.map +1 -0
- package/views/BasePart.d.ts +3 -18
- package/views/BasePart.jsx +3 -3
- package/views/BasePart.jsx.map +1 -0
- package/views/Empty.d.ts +2 -2
- package/views/Empty.jsx +2 -1
- package/views/Empty.jsx.map +1 -0
- package/views/Fragment.d.ts +3 -9
- package/views/Fragment.jsx +2 -2
- package/views/Fragment.jsx.map +1 -0
- package/views/MainView.d.ts +3 -3
- package/views/MainView.jsx +2 -2
- package/views/MainView.jsx.map +1 -0
- package/views/PropsView.d.ts +3 -0
- package/views/PropsView.jsx +21 -0
- package/views/PropsView.jsx.map +1 -0
- package/views/Region.d.ts +4 -17
- package/views/Region.jsx +2 -2
- package/views/Region.jsx.map +1 -0
- package/views/RichTextView.d.ts +3 -13
- package/views/RichTextView.jsx +6 -3
- package/views/RichTextView.jsx.map +1 -0
- package/views/SingleComponent.d.ts +3 -3
- package/views/SingleComponent.jsx +1 -2
- package/views/SingleComponent.jsx.map +1 -0
- package/views/StaticContent.d.ts +2 -6
- package/views/StaticContent.jsx +1 -0
- package/views/StaticContent.jsx.map +1 -0
- package/views/Text.d.ts +5 -5
- package/views/Text.jsx +1 -1
- package/views/Text.jsx.map +1 -0
- package/views/getClientHydratedHtml.d.ts +2 -0
- package/views/getClientHydratedHtml.jsx +9 -0
- package/views/getClientHydratedHtml.jsx.map +1 -0
- package/views/macros/DefaultMacro.d.ts +1 -1
- package/views/macros/DefaultMacro.jsx +1 -0
- package/views/macros/DefaultMacro.jsx.map +1 -0
- package/views/macros/DisableMacro.d.ts +1 -1
- package/views/macros/DisableMacro.jsx +1 -0
- package/views/macros/DisableMacro.jsx.map +1 -0
- package/ComponentRegistry.d.ts +0 -64
- package/server/ClearableFileCache.d.ts +0 -31
- package/server/ClearableFileCache.js +0 -472
- package/server/cache.d.ts +0 -2
- package/server/cache.js +0 -129
- package/server/index.d.ts +0 -5
- package/server/index.js +0 -132
- package/utils.d.ts +0 -114
- package/utils.js +0 -241
|
@@ -7,823 +7,216 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
10
|
+
import { headers } from 'next/headers';
|
|
11
|
+
import { ComponentRegistry } from '../common/ComponentRegistry';
|
|
12
|
+
import { UrlProcessor } from '../common/UrlProcessor';
|
|
13
|
+
import { FRAGMENT_CONTENTTYPE_NAME, PAGE_TEMPLATE_CONTENTTYPE_NAME, PAGE_TEMPLATE_FOLDER, RENDER_MODE, XP_COMPONENT_TYPE, XP_REQUEST_TYPE, } from '../common/constants';
|
|
14
|
+
import { APP_NAME, APP_NAME_DASHED, IS_DEV_MODE } from '../common/env';
|
|
15
|
+
import { getContentApiUrl } from '../utils/getContentApiUrl';
|
|
16
|
+
import { getProjectLocaleConfig } from '../utils/getProjectLocaleConfig';
|
|
17
|
+
import { getRenderMode } from '../utils/getRenderMode';
|
|
18
|
+
import { getXpBaseUrl } from '../utils/getXpBaseUrl';
|
|
19
|
+
import { getRequestLocaleInfo } from '../utils/getRequestLocaleInfo';
|
|
20
|
+
import { buildGuillotineRequestHeaders } from '../utils/buildGuillotineRequestHeaders';
|
|
21
|
+
import { buildPage } from './buildPage';
|
|
22
|
+
import { fetchMetaData } from './fetchMetaData';
|
|
23
|
+
import { getCleanContentPathArrayOrThrow400 } from './getCleanContentPathArrayOrThrow400';
|
|
24
|
+
import { buildErrorResponse } from './buildErrorResponse';
|
|
25
|
+
import { getContentAndComponentPaths } from './getContentAndComponentPaths';
|
|
26
|
+
import { restrictComponentsToPath } from './restrictComponentsToPath';
|
|
27
|
+
import { processComponentConfig } from './processComponentConfig';
|
|
28
|
+
import { getQueryAndVariables } from './getQueryAndVariables';
|
|
29
|
+
import { collectComponentDescriptors } from './collectComponentDescriptors';
|
|
30
|
+
import { combineMultipleQueries } from './combineMultipleQueries';
|
|
31
|
+
import { fetchContentData } from './fetchContentData';
|
|
32
|
+
import { applyProcessors } from './applyProcessors';
|
|
33
|
+
import { createMetaData } from './createMetaData';
|
|
34
|
+
/**
|
|
35
|
+
* Default fetchContent function, built with params from imports.
|
|
36
|
+
* It runs custom content-type-specific guillotine calls against an XP guillotine endpoint, returns content data, error and some meta data
|
|
37
|
+
* 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.
|
|
38
|
+
* @param context object from Next, contains .query info
|
|
39
|
+
* @returns FetchContentResult object: {data?: T, error?: {code, message}}
|
|
40
|
+
*/
|
|
41
|
+
export const fetchContent = (context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
const { locale, locales, defaultLocale } = getRequestLocaleInfo(context);
|
|
44
|
+
// ideally we only want to set headers in draft mode,
|
|
45
|
+
// but draft mode token is not passed in non-static mode
|
|
46
|
+
// so try to add them whenever they are absent
|
|
47
|
+
if (!context.headers) {
|
|
48
|
+
// TODO does this break routing or dynamic server-side rendering?
|
|
49
|
+
// I guess hydration will fix it anyway?
|
|
50
|
+
const allHeaders = headers();
|
|
51
|
+
context.headers = new Headers();
|
|
52
|
+
allHeaders.forEach((value, key) => {
|
|
53
|
+
context.headers.set(key, value);
|
|
54
|
+
});
|
|
48
55
|
}
|
|
49
|
-
|
|
56
|
+
const outHeaders = buildGuillotineRequestHeaders({
|
|
57
|
+
context,
|
|
58
|
+
defaultLocale,
|
|
59
|
+
locale,
|
|
60
|
+
locales,
|
|
61
|
+
});
|
|
62
|
+
const xpBaseUrl = getXpBaseUrl(context);
|
|
63
|
+
const contentApiUrl = getContentApiUrl(context);
|
|
64
|
+
const projectConfig = getProjectLocaleConfig(context);
|
|
65
|
+
const renderMode = getRenderMode(context);
|
|
66
|
+
let requestType = XP_REQUEST_TYPE.TYPE;
|
|
67
|
+
const requestContentPath = getCleanContentPathArrayOrThrow400(context.contentPath);
|
|
68
|
+
const errorResponse = buildErrorResponse(requestType, renderMode, contentApiUrl, xpBaseUrl, locale, defaultLocale, requestContentPath);
|
|
69
|
+
UrlProcessor.setSiteKey(projectConfig.site);
|
|
50
70
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
71
|
+
const [siteRelativeContentPath, componentPath] = getContentAndComponentPaths(requestContentPath);
|
|
72
|
+
if (componentPath) {
|
|
73
|
+
// set component request type because url contains component path
|
|
74
|
+
requestType = XP_REQUEST_TYPE.COMPONENT;
|
|
75
|
+
}
|
|
76
|
+
// ///////////// FIRST GUILLOTINE CALL FOR METADATA /////////////////
|
|
77
|
+
const metaResult = yield fetchMetaData(contentApiUrl, '${site}/' + siteRelativeContentPath, projectConfig, outHeaders);
|
|
78
|
+
// ///////////////////////////////////////////////////////////////////////
|
|
79
|
+
const { _path, type } = metaResult.meta || {};
|
|
80
|
+
const contentPath = _path || siteRelativeContentPath;
|
|
81
|
+
if (metaResult.error) {
|
|
82
|
+
console.error(metaResult.error);
|
|
83
|
+
return errorResponse(metaResult.error.code, metaResult.error.message);
|
|
84
|
+
}
|
|
85
|
+
if (!metaResult.meta) {
|
|
86
|
+
return errorResponse('404', 'No meta data found for content, most likely content does not exist');
|
|
87
|
+
}
|
|
88
|
+
else if (!type) {
|
|
89
|
+
return errorResponse('500', "Server responded with incomplete meta data: missing content 'type' attribute.");
|
|
90
|
+
}
|
|
91
|
+
else if (renderMode === RENDER_MODE.NEXT
|
|
92
|
+
&& !IS_DEV_MODE
|
|
93
|
+
&& (type === FRAGMENT_CONTENTTYPE_NAME ||
|
|
94
|
+
type === PAGE_TEMPLATE_CONTENTTYPE_NAME ||
|
|
95
|
+
type === PAGE_TEMPLATE_FOLDER)) {
|
|
96
|
+
return errorResponse('404', `Content type [${type}] is not accessible in ${renderMode} mode`);
|
|
97
|
+
}
|
|
98
|
+
const components = restrictComponentsToPath(type, metaResult.meta.components, componentPath);
|
|
99
|
+
if (componentPath && !components.length) {
|
|
100
|
+
// component was not found
|
|
101
|
+
return errorResponse('404', `Component ${componentPath} was not found`);
|
|
102
|
+
}
|
|
103
|
+
if (requestType !== XP_REQUEST_TYPE.COMPONENT && components.length > 0) {
|
|
104
|
+
requestType = XP_REQUEST_TYPE.PAGE;
|
|
105
|
+
}
|
|
106
|
+
// ////////////////////////////////////////////////// Content type established. Proceed to data call:
|
|
107
|
+
const allDescriptors = [];
|
|
108
|
+
// Add the content type query at all cases
|
|
109
|
+
const contentTypeDef = ComponentRegistry.getContentType(type);
|
|
110
|
+
const pageCmp = (components || []).find(cmp => cmp.type === XP_COMPONENT_TYPE.PAGE);
|
|
111
|
+
if (pageCmp) {
|
|
112
|
+
processComponentConfig(APP_NAME, APP_NAME_DASHED, pageCmp);
|
|
113
|
+
}
|
|
114
|
+
const contentQueryAndVars = getQueryAndVariables(type, contentPath, context, contentTypeDef === null || contentTypeDef === void 0 ? void 0 : contentTypeDef.query, (_a = pageCmp === null || pageCmp === void 0 ? void 0 : pageCmp.page) === null || _a === void 0 ? void 0 : _a.config);
|
|
115
|
+
if (contentQueryAndVars) {
|
|
116
|
+
allDescriptors.push({
|
|
117
|
+
type: contentTypeDef,
|
|
118
|
+
queryAndVariables: contentQueryAndVars,
|
|
92
119
|
});
|
|
93
|
-
return {
|
|
94
|
-
error: {
|
|
95
|
-
code: '500',
|
|
96
|
-
message: `Server responded with ${errors.length} error(s), probably from guillotine - see log.`,
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
120
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
});
|
|
113
|
-
// /////////////////////////////////////////////////////////////////////////////// Specific fetch wrappers:
|
|
114
|
-
const fetchMetaData = (contentApiUrl, xpContentPath, projectConfig, headers) => __awaiter(void 0, void 0, void 0, function* () {
|
|
115
|
-
var _c;
|
|
116
|
-
const body = {
|
|
117
|
-
query: getMetaQuery(pageFragmentQuery()),
|
|
118
|
-
variables: {
|
|
119
|
-
path: xpContentPath,
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
const metaResult = yield fetchGuillotine(contentApiUrl, body, projectConfig, headers);
|
|
123
|
-
if (metaResult.error) {
|
|
124
|
-
return metaResult;
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
return {
|
|
128
|
-
meta: (_c = metaResult === null || metaResult === void 0 ? void 0 : metaResult.guillotine) === null || _c === void 0 ? void 0 : _c.get,
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
const fetchContentData = (contentApiUrl, xpContentPath, projectConfig, query, variables, headers) => __awaiter(void 0, void 0, void 0, function* () {
|
|
133
|
-
const body = { query };
|
|
134
|
-
if (variables && Object.keys(variables).length > 0) {
|
|
135
|
-
body.variables = variables;
|
|
136
|
-
}
|
|
137
|
-
const contentResults = yield fetchGuillotine(contentApiUrl, body, projectConfig, headers);
|
|
138
|
-
if (contentResults.error) {
|
|
139
|
-
return contentResults;
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
return {
|
|
143
|
-
// omit the aliases and return values
|
|
144
|
-
contents: Object.values(contentResults),
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
// /////////////////////////////////////////////////////////////////////////////// Error checking:
|
|
149
|
-
/** 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) => {
|
|
151
|
-
if (contentPath === undefined) {
|
|
152
|
-
return '';
|
|
153
|
-
}
|
|
154
|
-
const isArray = Array.isArray(contentPath);
|
|
155
|
-
if (!isArray) {
|
|
156
|
-
if (typeof contentPath !== 'string') {
|
|
157
|
-
throw Error(JSON.stringify({
|
|
158
|
-
code: 400,
|
|
159
|
-
message: `Unexpected target content _path: contentPath must be a string or pure string array (contentPath=${JSON.stringify(contentPath)})`,
|
|
160
|
-
}));
|
|
161
|
-
}
|
|
162
|
-
return contentPath;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
return (contentPath).join('/');
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
function parseComponentPath(contentType, path) {
|
|
169
|
-
const matches = [];
|
|
170
|
-
let match;
|
|
171
|
-
const myRegexp = /(?:(\w+)\/(\d+))+/g;
|
|
172
|
-
while ((match = myRegexp.exec(path)) !== null) {
|
|
173
|
-
matches.push({
|
|
174
|
-
region: match[1],
|
|
175
|
-
index: +match[2],
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
if (contentType === FRAGMENT_CONTENTTYPE_NAME) {
|
|
179
|
-
// there is no main region in fragment content and the root component has '/' path
|
|
180
|
-
// prepend FRAGMENT_DEFAULT_REGION_NAME to path to conform to page structure
|
|
181
|
-
matches.unshift({
|
|
182
|
-
region: FRAGMENT_DEFAULT_REGION_NAME,
|
|
183
|
-
index: 0,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
return matches;
|
|
187
|
-
}
|
|
188
|
-
function getParentRegion(source, contentType, cmpPath, components = [], createMissing) {
|
|
189
|
-
let currentTree = source;
|
|
190
|
-
let currentRegion;
|
|
191
|
-
let parentPath = '';
|
|
192
|
-
for (let i = 0; i < cmpPath.length; i++) {
|
|
193
|
-
const pathFragment = cmpPath[i];
|
|
194
|
-
const regionName = pathFragment.region;
|
|
195
|
-
parentPath += `/${pathFragment.region}/${pathFragment.index}`;
|
|
196
|
-
currentRegion = currentTree[regionName];
|
|
197
|
-
if (!currentRegion) {
|
|
198
|
-
if (createMissing) {
|
|
199
|
-
currentRegion = {
|
|
200
|
-
name: regionName,
|
|
201
|
-
components: [],
|
|
202
|
-
};
|
|
203
|
-
currentTree[regionName] = currentRegion;
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
throw `Region [${regionName}] was not found`;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if (i < cmpPath.length - 1) {
|
|
210
|
-
// look for layouts inside if this is not the last path fragment
|
|
211
|
-
const layout = components.find((cmp) => {
|
|
212
|
-
return cmp.type === XP_COMPONENT_TYPE.LAYOUT && prefixLayoutPath(contentType, cmp.path) === parentPath;
|
|
121
|
+
const commonQueryAndVars = getQueryAndVariables(type, contentPath, context, ComponentRegistry.getCommonQuery(), (_b = pageCmp === null || pageCmp === void 0 ? void 0 : pageCmp.page) === null || _b === void 0 ? void 0 : _b.config);
|
|
122
|
+
if (commonQueryAndVars) {
|
|
123
|
+
allDescriptors.push({
|
|
124
|
+
type: contentTypeDef,
|
|
125
|
+
queryAndVariables: commonQueryAndVars,
|
|
213
126
|
});
|
|
214
|
-
if (!layout) {
|
|
215
|
-
throw `Layout [${parentPath}] not found among components, but needed for component [${JSON.stringify(cmpPath, null, 2)}]`;
|
|
216
|
-
}
|
|
217
|
-
if (!layout.regions) {
|
|
218
|
-
layout.regions = {};
|
|
219
|
-
}
|
|
220
|
-
currentTree = layout.regions;
|
|
221
127
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
function prefixLayoutPath(contentType, path) {
|
|
226
|
-
if (contentType !== FRAGMENT_CONTENTTYPE_NAME) {
|
|
227
|
-
return path;
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
// prepend FRAGMENT_DEFAULT_REGION_NAME to path to conform to page structure
|
|
231
|
-
// so that component with path '/' becomes /FRAGMENT_DEFAULT_REGION_NAME/0
|
|
232
|
-
// path /left/1 becomes /FRAGMENT_DEFAULT_REGION_NAME/0/left/1
|
|
233
|
-
return `/${FRAGMENT_DEFAULT_REGION_NAME}/0${path === '/' ? '' : path}`;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
function buildPage(contentType, comps = []) {
|
|
237
|
-
const page = {
|
|
238
|
-
type: XP_COMPONENT_TYPE.PAGE,
|
|
239
|
-
path: '/',
|
|
240
|
-
};
|
|
241
|
-
return buildComponentTree(comps, page, contentType);
|
|
242
|
-
}
|
|
243
|
-
function buildComponentTree(comps, rootComp, contentType) {
|
|
244
|
-
const rootTree = {};
|
|
245
|
-
const isFragmentType = contentType === FRAGMENT_CONTENTTYPE_NAME;
|
|
246
|
-
if (isFragmentType) {
|
|
247
|
-
rootComp.regions = rootTree;
|
|
248
|
-
}
|
|
249
|
-
(comps || []).forEach(cmp => {
|
|
250
|
-
var _a, _b, _c;
|
|
251
|
-
const cmpPath = parseComponentPath(contentType, cmp.path);
|
|
252
|
-
if (cmp.path === '/') {
|
|
253
|
-
if (cmp.type === XP_COMPONENT_TYPE.PAGE && rootComp.type === XP_COMPONENT_TYPE.PAGE) {
|
|
254
|
-
// add page values to page object
|
|
255
|
-
rootComp = Object.assign(rootComp, cmp);
|
|
256
|
-
rootComp.page.regions = rootTree;
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
else if (cmp.type === XP_COMPONENT_TYPE.LAYOUT && rootComp.type === XP_COMPONENT_TYPE.FRAGMENT) {
|
|
260
|
-
// when rendering fragment as part of the page with layout at root path
|
|
261
|
-
// remove other children from list as they will be included in layout
|
|
262
|
-
rootComp.fragment.fragment.components = [cmp];
|
|
263
|
-
cmp.regions = rootTree;
|
|
128
|
+
if ((components === null || components === void 0 ? void 0 : components.length) && ComponentRegistry) {
|
|
129
|
+
for (const cmp of (components || [])) {
|
|
130
|
+
processComponentConfig(APP_NAME, APP_NAME_DASHED, cmp);
|
|
264
131
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
132
|
+
// Collect component queries if defined
|
|
133
|
+
const componentDescriptors = collectComponentDescriptors({
|
|
134
|
+
components,
|
|
135
|
+
xpContentPath: contentPath,
|
|
136
|
+
context,
|
|
137
|
+
});
|
|
138
|
+
if (componentDescriptors.length) {
|
|
139
|
+
allDescriptors.push(...componentDescriptors);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const { query, variables } = combineMultipleQueries(allDescriptors);
|
|
143
|
+
if (!query.trim()) {
|
|
144
|
+
return errorResponse('400', `Missing or empty query override for content type ${type}`);
|
|
145
|
+
}
|
|
146
|
+
// /////////////// SECOND GUILLOTINE CALL FOR DATA //////////////////////
|
|
147
|
+
const contentResults = yield fetchContentData(contentApiUrl, contentPath, projectConfig, query, variables, outHeaders);
|
|
148
|
+
// ///////////////////////////////////////////////////////////////////////////
|
|
149
|
+
if (contentResults.error) {
|
|
150
|
+
console.error(contentResults.error);
|
|
151
|
+
return errorResponse(contentResults.error.code, contentResults.error.message);
|
|
152
|
+
}
|
|
153
|
+
// Apply processors to every component
|
|
154
|
+
const datas = yield applyProcessors(allDescriptors, contentResults, context);
|
|
155
|
+
// Unwind the data back to components
|
|
156
|
+
let contentData = null, common = null;
|
|
157
|
+
let startFrom = 0;
|
|
158
|
+
if (contentQueryAndVars) {
|
|
159
|
+
const item = datas[startFrom];
|
|
160
|
+
contentData = item.status === 'fulfilled' ? item.value : item.reason;
|
|
161
|
+
startFrom++;
|
|
162
|
+
}
|
|
163
|
+
if (commonQueryAndVars) {
|
|
164
|
+
const item = datas[startFrom];
|
|
165
|
+
common = item.status === 'fulfilled' ? item.value : item.reason;
|
|
166
|
+
startFrom++;
|
|
167
|
+
}
|
|
168
|
+
for (let i = startFrom; i < datas.length; i++) {
|
|
169
|
+
// component descriptors hold references to components
|
|
170
|
+
// that will later be used for creating page regions
|
|
171
|
+
const datum = datas[i];
|
|
172
|
+
if (datum.status === 'rejected') {
|
|
173
|
+
let reason = datum.reason;
|
|
174
|
+
if (reason instanceof Error) {
|
|
175
|
+
reason = reason.message;
|
|
176
|
+
}
|
|
177
|
+
else if (typeof reason !== 'string') {
|
|
178
|
+
reason = String(reason);
|
|
179
|
+
}
|
|
180
|
+
allDescriptors[i].component.error = reason;
|
|
276
181
|
}
|
|
277
182
|
else {
|
|
278
|
-
|
|
183
|
+
allDescriptors[i].component.data = datum.value;
|
|
279
184
|
}
|
|
280
185
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
// Extract fragments first if exist
|
|
295
|
-
let q = queryAndVars.query;
|
|
296
|
-
let match = q.match(GRAPHQL_FRAGMENTS_REGEXP);
|
|
297
|
-
if ((match === null || match === void 0 ? void 0 : match.length) === 1) {
|
|
298
|
-
// extract a fragment to put it at root level
|
|
299
|
-
fragments.push(match[0]);
|
|
300
|
-
// remove it from query because queries are going to get wrapped
|
|
301
|
-
q = q.replace(match[0], '');
|
|
302
|
-
}
|
|
303
|
-
// Extract graphql query and its params and add prefixes to exclude collisions with other queries
|
|
304
|
-
match = q.match(GUILLOTINE_QUERY_REGEXP);
|
|
305
|
-
let query = '';
|
|
306
|
-
if (match && match.length === 2) {
|
|
307
|
-
// no params, just query
|
|
308
|
-
query = match[1];
|
|
309
|
-
}
|
|
310
|
-
else if (match && match.length === 3) {
|
|
311
|
-
// both query and params are present
|
|
312
|
-
query = match[2];
|
|
313
|
-
// process args
|
|
314
|
-
const args = match[1];
|
|
315
|
-
if (args) {
|
|
316
|
-
args.split(',').forEach(originalParamString => {
|
|
317
|
-
const [originalKey, originalVal] = originalParamString.trim().split(':');
|
|
318
|
-
const [prefixedKey, prefixedVal] = [`$${ALIAS_PREFIX}${index}_${originalKey.substr(1)}`, originalVal];
|
|
319
|
-
superParams.push(`${prefixedKey}:${prefixedVal}`);
|
|
320
|
-
// also update param references in query itself !
|
|
321
|
-
// query = query.replaceAll(originalKey, prefixedKey);
|
|
322
|
-
// replaceAll is not supported in older nodejs versions
|
|
323
|
-
const origKeyPattern = new RegExp(originalKey.replace(/\$/g, '\\$'), 'g');
|
|
324
|
-
query = query.replace(origKeyPattern, prefixedKey);
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
if (query.length) {
|
|
329
|
-
queries.push(`${ALIAS_PREFIX}${index}:guillotine {${query}}`);
|
|
330
|
-
}
|
|
331
|
-
// Update variables with the same prefixes
|
|
332
|
-
Object.entries(queryAndVars.variables || {}).forEach(entry => {
|
|
333
|
-
superVars[`${ALIAS_PREFIX}${index}_${entry[0]}`] = entry[1];
|
|
186
|
+
const page = buildPage(type, components);
|
|
187
|
+
const meta = createMetaData({
|
|
188
|
+
apiUrl: contentApiUrl,
|
|
189
|
+
baseUrl: xpBaseUrl,
|
|
190
|
+
components,
|
|
191
|
+
contentPath: siteRelativeContentPath,
|
|
192
|
+
contentType: type,
|
|
193
|
+
defaultLocale,
|
|
194
|
+
locale,
|
|
195
|
+
pageCmp: page,
|
|
196
|
+
renderMode,
|
|
197
|
+
requestedComponentPath: componentPath,
|
|
198
|
+
requestType,
|
|
334
199
|
});
|
|
335
|
-
});
|
|
336
|
-
// Compose the super query
|
|
337
|
-
const superQuery = `query ${superParams.length ? `(${superParams.join(', ')})` : ''} {
|
|
338
|
-
${queries.join('\n')}
|
|
339
|
-
}
|
|
340
|
-
${fragments.join('\n')}
|
|
341
|
-
`;
|
|
342
|
-
return {
|
|
343
|
-
query: superQuery,
|
|
344
|
-
variables: superVars,
|
|
345
|
-
};
|
|
346
|
-
}
|
|
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);
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
function getComponentConfig(cmp) {
|
|
369
|
-
const cmpData = cmp && cmp[cmp.type];
|
|
370
|
-
return cmpData && 'config' in cmpData ? cmpData.config : undefined;
|
|
371
|
-
}
|
|
372
|
-
function collectComponentDescriptors(components, componentRegistry, xpContentPath, context) {
|
|
373
|
-
var _a, _b;
|
|
374
|
-
const descriptors = [];
|
|
375
|
-
for (const cmp of (components || [])) {
|
|
376
|
-
processComponentConfig(APP_NAME, APP_NAME_DASHED, cmp);
|
|
377
|
-
// only look for parts
|
|
378
|
-
// look for single part if it is a single component request
|
|
379
|
-
if (XP_COMPONENT_TYPE.FRAGMENT !== cmp.type) {
|
|
380
|
-
const cmpDef = ComponentRegistry.getByComponent(cmp);
|
|
381
|
-
if (cmpDef) {
|
|
382
|
-
// const partPath = `${xpContentPath}/_component${cmp.path}`;
|
|
383
|
-
const config = getComponentConfig(cmp);
|
|
384
|
-
const queryAndVariables = getQueryAndVariables(cmp.type, xpContentPath, cmpDef.query, context, config);
|
|
385
|
-
if (queryAndVariables) {
|
|
386
|
-
descriptors.push({
|
|
387
|
-
component: cmp,
|
|
388
|
-
type: cmpDef,
|
|
389
|
-
queryAndVariables: queryAndVariables,
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
else {
|
|
395
|
-
// 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);
|
|
397
|
-
if (fragPartDescs.length) {
|
|
398
|
-
descriptors.push(...fragPartDescs);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
return descriptors;
|
|
403
|
-
}
|
|
404
|
-
function processComponentConfig(myAppName, myAppNameDashed, cmp) {
|
|
405
|
-
const cmpData = cmp[cmp.type];
|
|
406
|
-
if (cmpData && 'descriptor' in cmpData && cmpData.descriptor) {
|
|
407
|
-
const [appName, cmpName] = cmpData.descriptor.split(':');
|
|
408
|
-
if (appName !== myAppName) {
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
let config;
|
|
412
|
-
const configArray = [];
|
|
413
|
-
if ('configAsJson' in cmpData && cmpData.configAsJson && cmpData.configAsJson[myAppNameDashed]) {
|
|
414
|
-
config = cmpData.configAsJson[myAppNameDashed][cmpName];
|
|
415
|
-
if (config) {
|
|
416
|
-
configArray.push(config);
|
|
417
|
-
delete cmpData.configAsJson;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
const sanitizedAppName = sanitizeGraphqlName(appName);
|
|
421
|
-
if ('config' in cmpData && cmpData.config && cmpData.config[sanitizedAppName]) {
|
|
422
|
-
config = cmpData.config[sanitizedAppName][sanitizeGraphqlName(cmpName)];
|
|
423
|
-
if (config) {
|
|
424
|
-
configArray.push(config);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
if (configArray.length) {
|
|
428
|
-
cmpData.config = Object.assign({}, ...configArray);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
function getQueryAndVariables(type, path, selectedQuery, context, config) {
|
|
433
|
-
let query, getVariables;
|
|
434
|
-
if (typeof selectedQuery === 'string' || typeof selectedQuery === 'function') {
|
|
435
|
-
query = selectedQuery;
|
|
436
|
-
}
|
|
437
|
-
else if (Array.isArray(selectedQuery)) {
|
|
438
|
-
query = selectedQuery[0];
|
|
439
|
-
getVariables = selectedQuery[1];
|
|
440
|
-
}
|
|
441
|
-
else if (typeof selectedQuery === 'object') {
|
|
442
|
-
query = selectedQuery.query;
|
|
443
|
-
getVariables = selectedQuery.variables;
|
|
444
|
-
}
|
|
445
|
-
if (getVariables && typeof getVariables !== 'function') {
|
|
446
|
-
throw Error(`getVariables for content type ${type} should be a function, not: ${typeof getVariables}`);
|
|
447
|
-
}
|
|
448
|
-
if (query && typeof query !== 'string' && typeof query !== 'function') {
|
|
449
|
-
throw Error(`Query for content type ${type} should be a string or function, not: ${typeof query}`);
|
|
450
|
-
}
|
|
451
|
-
if (typeof query === 'function') {
|
|
452
|
-
query = query(path, context, config);
|
|
453
|
-
}
|
|
454
|
-
if (query) {
|
|
455
200
|
return {
|
|
456
|
-
|
|
457
|
-
|
|
201
|
+
data: contentData,
|
|
202
|
+
common,
|
|
203
|
+
meta,
|
|
204
|
+
page,
|
|
458
205
|
};
|
|
459
206
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
if (components && !componentPath) {
|
|
464
|
-
page = buildPage(contentType, components);
|
|
465
|
-
}
|
|
466
|
-
else {
|
|
467
|
-
// Don't build page for single component
|
|
468
|
-
page = null;
|
|
469
|
-
}
|
|
470
|
-
return page;
|
|
471
|
-
}
|
|
472
|
-
function createMetaData(contentType, contentPath, requestType, renderMode, apiUrl, baseUrl, locale, defaultLocale, requestedComponentPath, pageCmp, components = []) {
|
|
473
|
-
var _a;
|
|
474
|
-
// .meta will be visible in final rendered inline props.
|
|
475
|
-
// Only adding some .meta attributes here on certain conditions
|
|
476
|
-
// (instead of always adding them and letting them be visible as false/undefined etc)
|
|
477
|
-
const meta = {
|
|
478
|
-
type: contentType,
|
|
479
|
-
path: contentPath,
|
|
480
|
-
requestType: requestType,
|
|
481
|
-
renderMode: renderMode,
|
|
482
|
-
canRender: false,
|
|
483
|
-
catchAll: false,
|
|
484
|
-
apiUrl,
|
|
485
|
-
baseUrl,
|
|
486
|
-
locale,
|
|
487
|
-
defaultLocale,
|
|
488
|
-
};
|
|
489
|
-
if (requestedComponentPath) {
|
|
490
|
-
meta.requestedComponent = components.find(cmp => cmp.path === requestedComponentPath);
|
|
491
|
-
}
|
|
492
|
-
const pageDesc = (_a = pageCmp === null || pageCmp === void 0 ? void 0 : pageCmp.page) === null || _a === void 0 ? void 0 : _a.descriptor;
|
|
493
|
-
const typeDef = ComponentRegistry.getContentType(contentType);
|
|
494
|
-
if ((typeDef === null || typeDef === void 0 ? void 0 : typeDef.view) && !typeDef.catchAll) {
|
|
495
|
-
meta.canRender = true;
|
|
496
|
-
}
|
|
497
|
-
else if (requestType === XP_REQUEST_TYPE.COMPONENT) {
|
|
498
|
-
// always render a single component (show missing if not implemented)
|
|
499
|
-
meta.canRender = true;
|
|
500
|
-
}
|
|
501
|
-
else if (pageDesc) {
|
|
502
|
-
// always render a page if there is a descriptor (show missing if not implemented)
|
|
503
|
-
meta.canRender = true;
|
|
504
|
-
}
|
|
505
|
-
else if (typeDef === null || typeDef === void 0 ? void 0 : typeDef.view) {
|
|
506
|
-
meta.canRender = true;
|
|
507
|
-
meta.catchAll = true;
|
|
508
|
-
}
|
|
509
|
-
return meta;
|
|
510
|
-
}
|
|
511
|
-
function errorResponse(code = '500', message = 'Unknown error', requestType, renderMode, apiUrl, baseUrl, locale, defaultLocale, contentPath) {
|
|
512
|
-
return {
|
|
513
|
-
error: {
|
|
514
|
-
code,
|
|
515
|
-
message,
|
|
516
|
-
},
|
|
517
|
-
page: null,
|
|
518
|
-
common: null,
|
|
519
|
-
data: null,
|
|
520
|
-
meta: {
|
|
521
|
-
type: '',
|
|
522
|
-
requestType: requestType,
|
|
523
|
-
renderMode: renderMode,
|
|
524
|
-
path: contentPath || '',
|
|
525
|
-
canRender: false,
|
|
526
|
-
catchAll: false,
|
|
527
|
-
apiUrl,
|
|
528
|
-
baseUrl,
|
|
529
|
-
locale,
|
|
530
|
-
defaultLocale,
|
|
531
|
-
},
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
function restrictComponentsToPath(contentType, components, componentPath) {
|
|
535
|
-
if (!componentPath || !(components === null || components === void 0 ? void 0 : components.length)) {
|
|
536
|
-
return components || [];
|
|
537
|
-
}
|
|
538
|
-
// filter components to the requested one only
|
|
539
|
-
const component = components.find(cmp => {
|
|
540
|
-
return cmp.path === componentPath;
|
|
541
|
-
});
|
|
542
|
-
if (!component) {
|
|
543
|
-
return [];
|
|
544
|
-
}
|
|
545
|
-
let result = [component];
|
|
546
|
-
if (component.type !== XP_COMPONENT_TYPE.LAYOUT) {
|
|
547
|
-
// remember to include all parent layouts too !
|
|
548
|
-
const cmpPath = parseComponentPath(contentType, component.path);
|
|
549
|
-
for (let i = cmpPath.length - 2; i >= 0; i--) {
|
|
550
|
-
const parentPath = cmpPath[i];
|
|
551
|
-
const parentCmp = components.find(cmp => cmp.path === `/${parentPath.region}/${parentPath.index}`);
|
|
552
|
-
if (parentCmp) {
|
|
553
|
-
result.unshift(parentCmp);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
else {
|
|
558
|
-
// It's a layout, include child components
|
|
559
|
-
const childCmps = components.filter(cmp => cmp.path !== component.path && cmp.path.startsWith(component.path));
|
|
560
|
-
if (childCmps.length) {
|
|
561
|
-
result = result.concat(childCmps);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
return result;
|
|
565
|
-
}
|
|
566
|
-
const COMPONENT_PATH_KEY = /\/?_\/component/; // first slash is optional for root components
|
|
567
|
-
const getContentAndComponentPaths = (requestPath, context) => {
|
|
568
|
-
let contentPath, componentPath;
|
|
569
|
-
if (COMPONENT_PATH_KEY.test(requestPath)) {
|
|
570
|
-
[contentPath, componentPath] = requestPath.split(COMPONENT_PATH_KEY);
|
|
571
|
-
}
|
|
572
|
-
else {
|
|
573
|
-
contentPath = requestPath;
|
|
574
|
-
}
|
|
575
|
-
return [contentPath, componentPath];
|
|
576
|
-
};
|
|
577
|
-
// ///////////////////////////// ENTRY 1 - THE BUILDER:
|
|
578
|
-
/**
|
|
579
|
-
* Configures, builds and returns a general fetchContent function.
|
|
580
|
-
* @param config object containing ComponentRegistry as well as constants imported from enonic-connecion-config.js
|
|
581
|
-
* @returns ContentFetcher
|
|
582
|
-
*/
|
|
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;
|
|
587
|
-
if (context.preview) {
|
|
588
|
-
populateEnonicHeaders(context);
|
|
589
|
-
}
|
|
590
|
-
const headers = {};
|
|
591
|
-
addJsessionHeaders(headers, context);
|
|
592
|
-
addLocaleHeaders(headers, context);
|
|
593
|
-
const xpBaseUrl = getXpBaseUrl(context);
|
|
594
|
-
const contentApiUrl = getContentApiUrl(context);
|
|
595
|
-
const projectConfig = getLocaleProjectConfig(context);
|
|
596
|
-
const renderMode = getRenderMode(context);
|
|
597
|
-
let requestType = XP_REQUEST_TYPE.TYPE;
|
|
598
|
-
UrlProcessor.setSiteKey(projectConfig.site);
|
|
207
|
+
catch (e) {
|
|
208
|
+
console.error(e);
|
|
209
|
+
let error;
|
|
599
210
|
try {
|
|
600
|
-
|
|
601
|
-
if ('/' + requestContentPath === PURGE_CACHE_URL) {
|
|
602
|
-
// return 404 for /_/cache/enonic/purge because it should've been handled by standalone endpoint
|
|
603
|
-
return errorResponse('404', 'Not found', requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, requestContentPath);
|
|
604
|
-
}
|
|
605
|
-
const [siteRelativeContentPath, componentPath] = getContentAndComponentPaths(requestContentPath, context);
|
|
606
|
-
if (componentPath) {
|
|
607
|
-
// set component request type because url contains component path
|
|
608
|
-
requestType = XP_REQUEST_TYPE.COMPONENT;
|
|
609
|
-
}
|
|
610
|
-
// ///////////// FIRST GUILLOTINE CALL FOR METADATA /////////////////
|
|
611
|
-
const metaResult = yield fetchMetaData(contentApiUrl, '${site}/' + siteRelativeContentPath, projectConfig, headers);
|
|
612
|
-
// ///////////////////////////////////////////////////////////////////////
|
|
613
|
-
const { _path, type } = metaResult.meta || {};
|
|
614
|
-
const contentPath = _path || siteRelativeContentPath;
|
|
615
|
-
if (metaResult.error) {
|
|
616
|
-
console.error(metaResult.error);
|
|
617
|
-
return errorResponse(metaResult.error.code, metaResult.error.message, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
|
|
618
|
-
}
|
|
619
|
-
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 &&
|
|
626
|
-
(type === FRAGMENT_CONTENTTYPE_NAME ||
|
|
627
|
-
type === PAGE_TEMPLATE_CONTENTTYPE_NAME ||
|
|
628
|
-
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);
|
|
630
|
-
}
|
|
631
|
-
const components = restrictComponentsToPath(type, metaResult.meta.components, componentPath);
|
|
632
|
-
if (componentPath && !components.length) {
|
|
633
|
-
// component was not found
|
|
634
|
-
return errorResponse('404', `Component ${componentPath} was not found`, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
|
|
635
|
-
}
|
|
636
|
-
if (requestType !== XP_REQUEST_TYPE.COMPONENT && components.length > 0) {
|
|
637
|
-
requestType = XP_REQUEST_TYPE.PAGE;
|
|
638
|
-
}
|
|
639
|
-
// ////////////////////////////////////////////////// Content type established. Proceed to data call:
|
|
640
|
-
const allDescriptors = [];
|
|
641
|
-
// Add the content type query at all cases
|
|
642
|
-
const contentTypeDef = componentRegistry === null || componentRegistry === void 0 ? void 0 : componentRegistry.getContentType(type);
|
|
643
|
-
const pageCmp = (components || []).find(cmp => cmp.type === XP_COMPONENT_TYPE.PAGE);
|
|
644
|
-
if (pageCmp) {
|
|
645
|
-
processComponentConfig(APP_NAME, APP_NAME_DASHED, pageCmp);
|
|
646
|
-
}
|
|
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);
|
|
648
|
-
if (contentQueryAndVars) {
|
|
649
|
-
allDescriptors.push({
|
|
650
|
-
type: contentTypeDef,
|
|
651
|
-
queryAndVariables: contentQueryAndVars,
|
|
652
|
-
});
|
|
653
|
-
}
|
|
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);
|
|
655
|
-
if (commonQueryAndVars) {
|
|
656
|
-
allDescriptors.push({
|
|
657
|
-
type: contentTypeDef,
|
|
658
|
-
queryAndVariables: commonQueryAndVars,
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
if ((components === null || components === void 0 ? void 0 : components.length) && componentRegistry) {
|
|
662
|
-
for (const cmp of (components || [])) {
|
|
663
|
-
processComponentConfig(APP_NAME, APP_NAME_DASHED, cmp);
|
|
664
|
-
}
|
|
665
|
-
// Collect component queries if defined
|
|
666
|
-
const componentDescriptors = collectComponentDescriptors(components, componentRegistry, contentPath, context);
|
|
667
|
-
if (componentDescriptors.length) {
|
|
668
|
-
allDescriptors.push(...componentDescriptors);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
const { query, variables } = combineMultipleQueries(allDescriptors);
|
|
672
|
-
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);
|
|
674
|
-
}
|
|
675
|
-
// /////////////// SECOND GUILLOTINE CALL FOR DATA //////////////////////
|
|
676
|
-
const contentResults = yield fetchContentData(contentApiUrl, contentPath, projectConfig, query, variables, headers);
|
|
677
|
-
// ///////////////////////////////////////////////////////////////////////////
|
|
678
|
-
if (contentResults.error) {
|
|
679
|
-
console.error(contentResults.error);
|
|
680
|
-
return errorResponse(contentResults.error.code, contentResults.error.message, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPath);
|
|
681
|
-
}
|
|
682
|
-
// Apply processors to every component
|
|
683
|
-
const datas = yield applyProcessors(allDescriptors, contentResults, context);
|
|
684
|
-
// Unwind the data back to components
|
|
685
|
-
let contentData = null, common = null;
|
|
686
|
-
let startFrom = 0;
|
|
687
|
-
if (contentQueryAndVars) {
|
|
688
|
-
const item = datas[startFrom];
|
|
689
|
-
contentData = item.status === 'fulfilled' ? item.value : item.reason;
|
|
690
|
-
startFrom++;
|
|
691
|
-
}
|
|
692
|
-
if (commonQueryAndVars) {
|
|
693
|
-
const item = datas[startFrom];
|
|
694
|
-
common = item.status === 'fulfilled' ? item.value : item.reason;
|
|
695
|
-
startFrom++;
|
|
696
|
-
}
|
|
697
|
-
for (let i = startFrom; i < datas.length; i++) {
|
|
698
|
-
// component descriptors hold references to components
|
|
699
|
-
// that will later be used for creating page regions
|
|
700
|
-
const datum = datas[i];
|
|
701
|
-
if (datum.status === 'rejected') {
|
|
702
|
-
let reason = datum.reason;
|
|
703
|
-
if (reason instanceof Error) {
|
|
704
|
-
reason = reason.message;
|
|
705
|
-
}
|
|
706
|
-
else if (typeof reason !== 'string') {
|
|
707
|
-
reason = String(reason);
|
|
708
|
-
}
|
|
709
|
-
allDescriptors[i].component.error = reason;
|
|
710
|
-
}
|
|
711
|
-
else {
|
|
712
|
-
allDescriptors[i].component.data = datum.value;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
const page = createPageData(type, components);
|
|
716
|
-
const meta = createMetaData(type, siteRelativeContentPath, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, componentPath, page, components);
|
|
717
|
-
return {
|
|
718
|
-
data: contentData,
|
|
719
|
-
common,
|
|
720
|
-
meta,
|
|
721
|
-
page,
|
|
722
|
-
};
|
|
211
|
+
error = JSON.parse(e.message);
|
|
723
212
|
}
|
|
724
|
-
catch (
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
error = JSON.parse(e.message);
|
|
729
|
-
}
|
|
730
|
-
catch (e2) {
|
|
731
|
-
error = {
|
|
732
|
-
code: 'Local',
|
|
733
|
-
message: e.message,
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
return errorResponse(error.code, error.message, requestType, renderMode, contentApiUrl, xpBaseUrl, context.locale, context.defaultLocale, contentPathOrArray.toString());
|
|
737
|
-
}
|
|
738
|
-
});
|
|
739
|
-
};
|
|
740
|
-
// //////////////////////////// ENTRY 2: ready-to-use fetchContent function
|
|
741
|
-
/**
|
|
742
|
-
* Default fetchContent function, built with params from imports.
|
|
743
|
-
* It runs custom content-type-specific guillotine calls against an XP guillotine endpoint, returns content data, error and some meta data
|
|
744
|
-
* 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.
|
|
745
|
-
* @param contentPath string or string array: local (site-relative) path to a content available on the API (by XP _path - obtainable by running contentPath through getXpPath). Pre-split into string array, or already a slash-delimited string.
|
|
746
|
-
* @param context object from Next, contains .query info
|
|
747
|
-
* @returns FetchContentResult object: {data?: T, error?: {code, message}}
|
|
748
|
-
*/
|
|
749
|
-
export const fetchContent = buildContentFetcher(Object.assign(Object.assign({}, adapterConstants), { componentRegistry: ComponentRegistry }));
|
|
750
|
-
export function createResponse(props, context, isStatic = true) {
|
|
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;
|
|
754
|
-
if (meta.type === 'base:shortcut' && pageUrl) {
|
|
755
|
-
if (meta.renderMode !== RENDER_MODE.NEXT) {
|
|
756
|
-
// console.debug(`Returning 404 for shortcut in ${RENDER_MODE.NEXT} mode`);
|
|
757
|
-
// do not show shortcut targets in preview/edit mode
|
|
758
|
-
return {
|
|
759
|
-
notFound: true,
|
|
213
|
+
catch (e2) {
|
|
214
|
+
error = {
|
|
215
|
+
code: 'Local',
|
|
216
|
+
message: e.message,
|
|
760
217
|
};
|
|
761
218
|
}
|
|
762
|
-
|
|
763
|
-
// console.debug('Redirecting to', destination);
|
|
764
|
-
return {
|
|
765
|
-
redirect: {
|
|
766
|
-
statusCode: 307,
|
|
767
|
-
destination,
|
|
768
|
-
},
|
|
769
|
-
};
|
|
770
|
-
}
|
|
771
|
-
// we can not set 418 for static paths,
|
|
772
|
-
// but we can show 404 instead to be handled in CS
|
|
773
|
-
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;
|
|
776
|
-
// console.debug('Returning view ' + (notFound ? '(not found)' : ''));
|
|
777
|
-
const result = {
|
|
778
|
-
notFound,
|
|
779
|
-
props,
|
|
780
|
-
};
|
|
781
|
-
if (isStatic) {
|
|
782
|
-
result.revalidate = 3600; // In seconds, meaning every hour
|
|
219
|
+
return errorResponse(error.code, error.message);
|
|
783
220
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
function populateEnonicHeaders(context) {
|
|
787
|
-
const pd = context.previewData;
|
|
788
|
-
if (!pd) {
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
const req = context.req || {};
|
|
792
|
-
req.headers = Object.assign(req.headers || {}, pd.headers);
|
|
793
|
-
context.params = Object.assign(context.params || {}, pd.params);
|
|
794
|
-
context.req = req;
|
|
795
|
-
}
|
|
796
|
-
export function fetchContentPathsForAllLocales(path, query = GET_STATIC_PATHS_QUERY, countPerLocale = 999) {
|
|
797
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
798
|
-
const promises = Object.values(getLocaleProjectConfigs()).map(config => fetchContentPathsForLocale(path, config, query, countPerLocale));
|
|
799
|
-
return Promise.all(promises).then(results => {
|
|
800
|
-
return results.reduce((all, localePaths) => all.concat(localePaths), []);
|
|
801
|
-
});
|
|
802
|
-
});
|
|
803
|
-
}
|
|
804
|
-
export function fetchContentPathsForLocale(path, config, query = GET_STATIC_PATHS_QUERY, count = 999) {
|
|
805
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
806
|
-
const contentApiUrl = getContentApiUrl({ locale: config.locale });
|
|
807
|
-
const body = {
|
|
808
|
-
query,
|
|
809
|
-
variables: {
|
|
810
|
-
path,
|
|
811
|
-
count,
|
|
812
|
-
},
|
|
813
|
-
};
|
|
814
|
-
return fetchGuillotine(contentApiUrl, body, config).then((results) => {
|
|
815
|
-
return results.guillotine.queryDsl.reduce((prev, child) => {
|
|
816
|
-
var _a;
|
|
817
|
-
const regexp = new RegExp(`/${(_a = child.site) === null || _a === void 0 ? void 0 : _a._name}/?`);
|
|
818
|
-
const contentPath = child._path.replace(regexp, '');
|
|
819
|
-
prev.push({
|
|
820
|
-
params: {
|
|
821
|
-
contentPath: contentPath.split('/'),
|
|
822
|
-
},
|
|
823
|
-
locale: normalizeLocale(config.locale),
|
|
824
|
-
});
|
|
825
|
-
return prev;
|
|
826
|
-
}, []);
|
|
827
|
-
});
|
|
828
|
-
});
|
|
829
|
-
}
|
|
221
|
+
});
|
|
222
|
+
//# sourceMappingURL=fetchContent.js.map
|