@enonic/nextjs-adapter 2.0.1 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ComponentRegistry.d.ts +64 -0
- package/ComponentRegistry.js +121 -0
- package/UrlProcessor.d.ts +25 -0
- package/{src/UrlProcessor.ts → UrlProcessor.js} +35 -53
- package/baseMappings.d.ts +1 -0
- package/{src/baseMappings.ts → baseMappings.js} +3 -13
- package/guillotine/fetchContent.d.ts +49 -0
- package/{src/guillotine/fetchContent.ts → guillotine/fetchContent.js} +243 -493
- package/guillotine/getMetaData.d.ts +94 -0
- package/guillotine/getMetaData.js +128 -0
- package/{src/index.ts → index.d.ts} +1 -1
- package/index.js +5 -0
- package/package.json +2 -2
- package/query/Shortcut.d.ts +1 -0
- package/server/ClearableFileCache.d.ts +31 -0
- package/server/ClearableFileCache.js +472 -0
- package/server/cache.d.ts +2 -0
- package/server/cache.js +129 -0
- package/server/index.d.ts +5 -0
- package/server/index.js +132 -0
- package/utils.d.ts +114 -0
- package/{src/utils.ts → utils.js} +69 -148
- package/views/BaseComponent.d.ts +25 -0
- package/{src/views/BaseComponent.tsx → views/BaseComponent.jsx} +39 -73
- package/views/BaseContent.d.ts +4 -0
- package/{src/views/BaseContent.tsx → views/BaseContent.jsx} +17 -24
- package/views/BaseLayout.d.ts +17 -0
- package/views/BaseLayout.jsx +24 -0
- package/views/BaseMacro.d.ts +16 -0
- package/{src/views/BaseMacro.tsx → views/BaseMacro.jsx} +29 -45
- package/views/BasePage.d.ts +19 -0
- package/views/BasePage.jsx +34 -0
- package/views/BasePart.d.ts +19 -0
- package/views/BasePart.jsx +24 -0
- package/views/Empty.d.ts +3 -0
- package/{src/views/Empty.tsx → views/Empty.jsx} +0 -2
- package/views/Fragment.d.ts +10 -0
- package/views/Fragment.jsx +30 -0
- package/views/MainView.d.ts +4 -0
- package/views/MainView.jsx +14 -0
- package/views/Region.d.ts +20 -0
- package/views/Region.jsx +52 -0
- package/views/RichTextView.d.ts +16 -0
- package/{src/views/RichTextView.tsx → views/RichTextView.jsx} +10 -31
- package/views/SingleComponent.d.ts +5 -0
- package/{src/views/SingleComponent.tsx → views/SingleComponent.jsx} +2 -8
- package/views/StaticContent.d.ts +15 -0
- package/views/StaticContent.jsx +36 -0
- package/views/Text.d.ts +9 -0
- package/views/Text.jsx +4 -0
- package/views/macros/DefaultMacro.d.ts +4 -0
- package/views/macros/DefaultMacro.jsx +3 -0
- package/views/macros/DisableMacro.d.ts +3 -0
- package/views/macros/DisableMacro.jsx +2 -0
- package/.eslint-childrc.js +0 -17
- package/.eslintrc.js +0 -15
- package/.github/dependabot.yml +0 -20
- package/.github/pull-merger.yml +0 -1
- package/.github/workflows/release.yml +0 -39
- package/LICENSE +0 -201
- package/RELEASE.md +0 -75
- package/server/.eslintrc.js +0 -11
- package/server/ClearableFileCache.ts +0 -410
- package/server/cache.ts +0 -50
- package/server/index.ts +0 -74
- package/server/tsconfig.json +0 -23
- package/src/.eslintrc.js +0 -11
- package/src/ComponentRegistry.ts +0 -189
- package/src/guillotine/getMetaData.ts +0 -246
- package/src/tsconfig.json +0 -20
- package/src/views/BaseLayout.tsx +0 -45
- package/src/views/BasePage.tsx +0 -56
- package/src/views/BasePart.tsx +0 -50
- package/src/views/Fragment.tsx +0 -45
- package/src/views/MainView.tsx +0 -21
- package/src/views/Region.tsx +0 -89
- package/src/views/StaticContent.tsx +0 -40
- package/src/views/Text.tsx +0 -15
- package/src/views/macros/DefaultMacro.tsx +0 -9
- package/src/views/macros/DisableMacro.tsx +0 -8
- /package/{src/query/Shortcut.ts → query/Shortcut.js} +0 -0
package/src/ComponentRegistry.ts
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import {PageComponent} from './guillotine/getMetaData';
|
|
2
|
-
import {Context, XP_COMPONENT_TYPE} from './utils';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Object that configures the handling of a particular content type. All attributes are optional (see examples below), and missing values will fall back to default behavior:
|
|
7
|
-
* - 'query' (used in fetchContent.ts) Guillotine query for fetching content data, may also have a function that supplies guillotine variables. So, 'query' can EITHER be only a query string, OR also add a get-guillotine-variables function. In the latter case, 'query' can be an object with 'query' and 'variables' attributes, or an array where the query string is first and the get-variables function is second. Either way, the get-variables function takes two arguments: path (content path, mandatory) and context (next.js-supplied Context from getServerSideProps etc. Optional, and requires that fetchContent is called with the context, of course).
|
|
8
|
-
* - 'props' (used in fetchContent.ts) is a function for processing props after fetching them
|
|
9
|
-
* - 'view' (used in BasePage.tsx) is a React component: top-level content-type-specific rendering with the props first fetched from guillotine (and then optionally preprocessed with the function in 'props').
|
|
10
|
-
*/
|
|
11
|
-
export interface ComponentDefinition {
|
|
12
|
-
catchAll?: boolean; // will be set automatically depending on the binding
|
|
13
|
-
query?: SelectedQueryMaybeVariablesFunc,
|
|
14
|
-
configQuery?: string,
|
|
15
|
-
processor?: DataProcessor,
|
|
16
|
-
view?: React.FunctionComponent<any>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
type SelectorName = 'contentType' | 'page' | 'component' | 'part' | 'layout' | 'macro';
|
|
20
|
-
|
|
21
|
-
function toSelectorName(type: XP_COMPONENT_TYPE): SelectorName | undefined {
|
|
22
|
-
switch (type) {
|
|
23
|
-
case XP_COMPONENT_TYPE.PAGE:
|
|
24
|
-
return 'page';
|
|
25
|
-
case XP_COMPONENT_TYPE.LAYOUT:
|
|
26
|
-
return 'layout';
|
|
27
|
-
case XP_COMPONENT_TYPE.PART:
|
|
28
|
-
return 'part';
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface ComponentDictionary {
|
|
33
|
-
[type: string]: ComponentDefinition;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// NB! Always return null or empty object from processor for next is unable to serialize undefined
|
|
37
|
-
export type DataProcessor = (data: any, context?: Context, config?: any) => Promise<Record<string, any>>;
|
|
38
|
-
|
|
39
|
-
// TODO: also access as arguments: dataAsJson, pageAsJson, configAsJson from the first (meta) call here?
|
|
40
|
-
// Another option could be to let the component or page controller pass those values to NextJS by a header
|
|
41
|
-
export type VariablesGetter = (path: string, context?: Context, config?: any) => VariablesGetterResult;
|
|
42
|
-
|
|
43
|
-
export type QueryGetter = (path: string, context?: Context, config?: any) => string;
|
|
44
|
-
|
|
45
|
-
export type VariablesGetterResult = {
|
|
46
|
-
[variables: string]: any,
|
|
47
|
-
path: string,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export type SelectedQueryMaybeVariablesFunc = string | QueryGetter |
|
|
51
|
-
{ query: string | QueryGetter, variables: VariablesGetter } |
|
|
52
|
-
[string | QueryGetter, VariablesGetter];
|
|
53
|
-
|
|
54
|
-
export const CATCH_ALL = '*';
|
|
55
|
-
|
|
56
|
-
export class ComponentRegistry {
|
|
57
|
-
|
|
58
|
-
private static contentTypes: ComponentDictionary = {};
|
|
59
|
-
private static pages: ComponentDictionary = {};
|
|
60
|
-
private static components: ComponentDictionary = {};
|
|
61
|
-
private static parts: ComponentDictionary = {};
|
|
62
|
-
private static layouts: ComponentDictionary = {};
|
|
63
|
-
private static macros: ComponentDictionary = {};
|
|
64
|
-
private static commonQuery: SelectedQueryMaybeVariablesFunc;
|
|
65
|
-
|
|
66
|
-
private static getSelector(name: SelectorName): ComponentDictionary {
|
|
67
|
-
switch (name) {
|
|
68
|
-
case 'contentType':
|
|
69
|
-
return this.contentTypes;
|
|
70
|
-
case 'page':
|
|
71
|
-
return this.pages;
|
|
72
|
-
case 'component':
|
|
73
|
-
return this.components;
|
|
74
|
-
case 'layout':
|
|
75
|
-
return this.layouts;
|
|
76
|
-
case 'part':
|
|
77
|
-
return this.parts;
|
|
78
|
-
case 'macro':
|
|
79
|
-
return this.macros;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private static getType(selectorName: SelectorName, typeName: string, useCatchAll = true): ComponentDefinition | undefined {
|
|
84
|
-
const selector = ComponentRegistry.getSelector(selectorName);
|
|
85
|
-
let type = selector[typeName];
|
|
86
|
-
if (type) {
|
|
87
|
-
type.catchAll = false;
|
|
88
|
-
} else if (!type && useCatchAll) {
|
|
89
|
-
type = selector[CATCH_ALL];
|
|
90
|
-
if (type) {
|
|
91
|
-
type.catchAll = true;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return type;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private static addType(selectorName: SelectorName, name: string, obj: ComponentDefinition): void {
|
|
98
|
-
const selector = ComponentRegistry.getSelector(selectorName);
|
|
99
|
-
const curr = selector[name];
|
|
100
|
-
selector[name] = curr ? Object.assign(curr, obj) : obj;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
public static getByComponent(component: PageComponent): ComponentDefinition | undefined {
|
|
104
|
-
const selName = toSelectorName(component.type);
|
|
105
|
-
const cmpData = component[component.type];
|
|
106
|
-
const desc = cmpData && 'descriptor' in cmpData ? cmpData.descriptor : component.path;
|
|
107
|
-
return selName && desc ? this.getType(selName, desc) : undefined;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
public static setCommonQuery(query: SelectedQueryMaybeVariablesFunc): void {
|
|
111
|
-
this.commonQuery = query;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
public static getCommonQuery(): SelectedQueryMaybeVariablesFunc {
|
|
115
|
-
return this.commonQuery;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
public static addMacro(name: string, obj: ComponentDefinition): void {
|
|
119
|
-
return ComponentRegistry.addType('macro', name, obj);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
public static getMacro(name: string): ComponentDefinition | undefined {
|
|
123
|
-
return ComponentRegistry.getType('macro', name);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
public static getMacros(): [string, ComponentDefinition][] {
|
|
127
|
-
return Object.entries(this.macros);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public static getParts(): [string, ComponentDefinition][] {
|
|
131
|
-
return Object.entries(this.parts);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
public static getLayouts(): [string, ComponentDefinition][] {
|
|
135
|
-
return Object.entries(this.layouts);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
public static getPages(): [string, ComponentDefinition][] {
|
|
139
|
-
return Object.entries(this.pages);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
public static getContentTypes(): [string, ComponentDefinition][] {
|
|
143
|
-
return Object.entries(this.contentTypes);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
public static getComponents(): [string, ComponentDefinition][] {
|
|
147
|
-
return Object.entries(this.components);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
public static addContentType(name: string, obj: ComponentDefinition): void {
|
|
151
|
-
return ComponentRegistry.addType('contentType', name, obj);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
public static getContentType(name: string): ComponentDefinition | undefined {
|
|
155
|
-
return ComponentRegistry.getType('contentType', name);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
public static addPage(name: string, obj: ComponentDefinition): void {
|
|
159
|
-
return ComponentRegistry.addType('page', name, obj);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public static getPage(name: string): ComponentDefinition | undefined {
|
|
163
|
-
return ComponentRegistry.getType('page', name);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
public static addPart(name: string, obj: ComponentDefinition): void {
|
|
167
|
-
return ComponentRegistry.addType('part', name, obj);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
public static getPart(name: string): ComponentDefinition | undefined {
|
|
171
|
-
return ComponentRegistry.getType('part', name);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
public static addLayout(name: string, obj: ComponentDefinition): void {
|
|
175
|
-
return ComponentRegistry.addType('layout', name, obj);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
public static getLayout(name: string): ComponentDefinition | undefined {
|
|
179
|
-
return ComponentRegistry.getType('layout', name);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
public static addComponent(name: string, obj: ComponentDefinition): void {
|
|
183
|
-
return ComponentRegistry.addType('component', name, obj);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
public static getComponent(name: string): ComponentDefinition | undefined {
|
|
187
|
-
return ComponentRegistry.getType('component', name);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import {RENDER_MODE, sanitizeGraphqlName, XP_COMPONENT_TYPE, XP_REQUEST_TYPE} from '../utils';
|
|
2
|
-
import {ComponentDefinition, ComponentRegistry} from '../ComponentRegistry';
|
|
3
|
-
|
|
4
|
-
const macroConfigQuery = (): string => {
|
|
5
|
-
return configQuery(ComponentRegistry.getMacros(), false, false);
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
const partConfigQuery = (): string => {
|
|
9
|
-
return configQuery(ComponentRegistry.getParts());
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const layoutConfigQuery = (): string => {
|
|
13
|
-
return configQuery(ComponentRegistry.getLayouts());
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const pageConfigQuery = (): string => {
|
|
17
|
-
return configQuery(ComponentRegistry.getPages());
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const configQuery = (list: [string, ComponentDefinition][], includeAppName = true, canUseConfigAsJson = true): string => {
|
|
21
|
-
const hasQueryList = list?.filter(([key, def]) => def.configQuery) || [];
|
|
22
|
-
if (hasQueryList.length === 0) {
|
|
23
|
-
return canUseConfigAsJson ? 'configAsJson' : '';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const configsByApp: { [app: string]: string[] } = {};
|
|
27
|
-
hasQueryList
|
|
28
|
-
.forEach((entry) => {
|
|
29
|
-
const nameParts = entry[0].split(':');
|
|
30
|
-
if (nameParts.length === 2) {
|
|
31
|
-
const sanitizedAppName = sanitizeGraphqlName(nameParts[0]);
|
|
32
|
-
let existingConfigs = configsByApp[sanitizedAppName];
|
|
33
|
-
if (!existingConfigs) {
|
|
34
|
-
existingConfigs = [];
|
|
35
|
-
configsByApp[sanitizedAppName] = existingConfigs;
|
|
36
|
-
}
|
|
37
|
-
existingConfigs.push(`${sanitizeGraphqlName(nameParts[1])}${entry[1].configQuery}`);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Still query for configAsJson if at least one item has no configQuery defined
|
|
42
|
-
const configAsJsonQuery = canUseConfigAsJson && hasQueryList.length < list.length ? 'configAsJson' : '';
|
|
43
|
-
|
|
44
|
-
if (!includeAppName) {
|
|
45
|
-
return `${configAsJsonQuery}
|
|
46
|
-
config {
|
|
47
|
-
${Object.values(configsByApp).reduce((arr, curr) => arr.concat(curr), []).join('\n')}
|
|
48
|
-
}`;
|
|
49
|
-
} else {
|
|
50
|
-
return `${configAsJsonQuery}
|
|
51
|
-
config {
|
|
52
|
-
${Object.entries(configsByApp).map(entry => entry[0] + '{\n' + entry[1].join('\n') + '\n}')}
|
|
53
|
-
}`;
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
/*
|
|
58
|
-
IMPORTANT: make sure to transform your queries into functions too when using this function inside them !!!
|
|
59
|
-
*/
|
|
60
|
-
export const richTextQuery = (fieldName: string) => {
|
|
61
|
-
return `${fieldName}(processHtml:{type:absolute, imageWidths:[400, 800, 1200], imageSizes:"(max-width: 400px) 400px, (max-width: 800px) 800px, 1200px"}) {
|
|
62
|
-
processedHtml
|
|
63
|
-
macros {
|
|
64
|
-
ref
|
|
65
|
-
name
|
|
66
|
-
descriptor
|
|
67
|
-
${macroConfigQuery()}
|
|
68
|
-
}
|
|
69
|
-
links {
|
|
70
|
-
ref
|
|
71
|
-
media {
|
|
72
|
-
content {
|
|
73
|
-
_id
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
images {
|
|
78
|
-
ref
|
|
79
|
-
image {
|
|
80
|
-
_id
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}`;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const componentsQuery = () => `
|
|
87
|
-
type
|
|
88
|
-
path
|
|
89
|
-
page {
|
|
90
|
-
descriptor
|
|
91
|
-
${pageConfigQuery()}
|
|
92
|
-
template {
|
|
93
|
-
_path
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
layout {
|
|
97
|
-
descriptor
|
|
98
|
-
${layoutConfigQuery()}
|
|
99
|
-
}
|
|
100
|
-
text {
|
|
101
|
-
${richTextQuery('value')}
|
|
102
|
-
}
|
|
103
|
-
part {
|
|
104
|
-
descriptor
|
|
105
|
-
${partConfigQuery()}
|
|
106
|
-
}
|
|
107
|
-
image {
|
|
108
|
-
caption
|
|
109
|
-
image {
|
|
110
|
-
imageUrl (type:absolute, scale: "width-768")
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
`;
|
|
114
|
-
|
|
115
|
-
// THIS QUERY DOES NOT SUPPORT NESTED FRAGMENTS
|
|
116
|
-
export const pageFragmentQuery = () => `
|
|
117
|
-
components(resolveFragment: false, resolveTemplate: true) {
|
|
118
|
-
fragment {
|
|
119
|
-
id
|
|
120
|
-
fragment {
|
|
121
|
-
components {
|
|
122
|
-
${componentsQuery()}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
${componentsQuery()}
|
|
127
|
-
}`;
|
|
128
|
-
|
|
129
|
-
export function getMetaQuery(pageFragment?: string): string {
|
|
130
|
-
return `query($path:ID!){
|
|
131
|
-
guillotine {
|
|
132
|
-
get(key:$path) {
|
|
133
|
-
_path
|
|
134
|
-
type
|
|
135
|
-
${pageFragment || ''}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}`;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export interface PageComponent {
|
|
142
|
-
[key: string]: any; // keeps ts happy when accessing component data field by XP_COMPONENT_TYPE type
|
|
143
|
-
type: XP_COMPONENT_TYPE;
|
|
144
|
-
path: string;
|
|
145
|
-
page?: PageData;
|
|
146
|
-
part?: PartData;
|
|
147
|
-
layout?: LayoutData;
|
|
148
|
-
fragment?: FragmentData;
|
|
149
|
-
text?: TextData;
|
|
150
|
-
image?: any;
|
|
151
|
-
regions?: RegionTree;
|
|
152
|
-
data?: any;
|
|
153
|
-
error?: any;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export interface TextData {
|
|
157
|
-
value: RichTextData;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export interface RichTextData {
|
|
161
|
-
processedHtml: string,
|
|
162
|
-
links: LinkData[],
|
|
163
|
-
macros: MacroData[],
|
|
164
|
-
images: ImageData[],
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export interface LinkData {
|
|
168
|
-
ref: string,
|
|
169
|
-
media: {
|
|
170
|
-
content: {
|
|
171
|
-
id: string,
|
|
172
|
-
}
|
|
173
|
-
} | null,
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export interface MacroData {
|
|
177
|
-
ref: string;
|
|
178
|
-
name: string;
|
|
179
|
-
descriptor: string;
|
|
180
|
-
config: {
|
|
181
|
-
[name: string]: MacroConfig;
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export interface ImageData {
|
|
186
|
-
ref: string;
|
|
187
|
-
image: {
|
|
188
|
-
id: string,
|
|
189
|
-
} | null,
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export interface MacroConfig {
|
|
193
|
-
[key: string]: any;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
export interface RegionTree {
|
|
198
|
-
[key: string]: PageRegion;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export interface PageRegion {
|
|
202
|
-
name: string;
|
|
203
|
-
components: PageComponent[];
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export interface PartData {
|
|
207
|
-
descriptor: string;
|
|
208
|
-
config: any;
|
|
209
|
-
|
|
210
|
-
[customKeysFromQuery: string]: any;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export interface LayoutData {
|
|
214
|
-
descriptor: string;
|
|
215
|
-
config?: any;
|
|
216
|
-
|
|
217
|
-
[customKeysFromQuery: string]: any;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export interface PageData {
|
|
221
|
-
descriptor: string;
|
|
222
|
-
config?: any;
|
|
223
|
-
template?: string | null;
|
|
224
|
-
regions?: RegionTree;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export interface FragmentData {
|
|
228
|
-
id: string;
|
|
229
|
-
fragment: {
|
|
230
|
-
components: PageComponent[];
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
export interface MetaData {
|
|
235
|
-
type: string,
|
|
236
|
-
path: string,
|
|
237
|
-
requestType: XP_REQUEST_TYPE,
|
|
238
|
-
renderMode: RENDER_MODE,
|
|
239
|
-
requestedComponent?: PageComponent,
|
|
240
|
-
canRender: boolean,
|
|
241
|
-
catchAll: boolean,
|
|
242
|
-
apiUrl: string,
|
|
243
|
-
baseUrl: string,
|
|
244
|
-
locale: string,
|
|
245
|
-
defaultLocale: string,
|
|
246
|
-
}
|
package/src/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES6",
|
|
4
|
-
"esModuleInterop": true,
|
|
5
|
-
"forceConsistentCasingInFileNames": true,
|
|
6
|
-
"allowSyntheticDefaultImports": true,
|
|
7
|
-
"module": "ESNext",
|
|
8
|
-
"moduleResolution": "node",
|
|
9
|
-
"resolveJsonModule": true,
|
|
10
|
-
"isolatedModules": true,
|
|
11
|
-
"jsx": "preserve",
|
|
12
|
-
"outDir": "../dist",
|
|
13
|
-
"declaration": true
|
|
14
|
-
},
|
|
15
|
-
"include": [
|
|
16
|
-
"**/*.ts",
|
|
17
|
-
"**/*.tsx"
|
|
18
|
-
],
|
|
19
|
-
"exclude": []
|
|
20
|
-
}
|
package/src/views/BaseLayout.tsx
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {LayoutData, MetaData, RegionTree} from '../guillotine/getMetaData';
|
|
3
|
-
import {ComponentRegistry} from '../ComponentRegistry';
|
|
4
|
-
import {XP_COMPONENT_TYPE} from '../utils';
|
|
5
|
-
import {MissingComponent, shouldShowMissingView} from './BaseComponent';
|
|
6
|
-
|
|
7
|
-
export interface LayoutProps {
|
|
8
|
-
layout: LayoutData;
|
|
9
|
-
path: string;
|
|
10
|
-
common: any;
|
|
11
|
-
meta: MetaData;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface BaseLayoutProps {
|
|
15
|
-
component?: LayoutData;
|
|
16
|
-
path: string;
|
|
17
|
-
regions?: RegionTree;
|
|
18
|
-
common?: any;
|
|
19
|
-
meta: MetaData;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const BaseLayout = (props: BaseLayoutProps) => {
|
|
23
|
-
|
|
24
|
-
const {component, common, regions, meta, path} = props;
|
|
25
|
-
let layoutSelection;
|
|
26
|
-
if (component) {
|
|
27
|
-
layoutSelection = ComponentRegistry.getLayout(component.descriptor);
|
|
28
|
-
}
|
|
29
|
-
const SelectedLayoutView = layoutSelection?.view;
|
|
30
|
-
if (SelectedLayoutView) {
|
|
31
|
-
return <SelectedLayoutView layout={{descriptor: component?.descriptor, regions: regions || {}, config: component?.config}}
|
|
32
|
-
path={path}
|
|
33
|
-
common={common}
|
|
34
|
-
meta={meta}/>;
|
|
35
|
-
} else if (component?.descriptor) {
|
|
36
|
-
// empty descriptor usually means uninitialized layout
|
|
37
|
-
console.warn(`BaseLayout: can not render layout '${component?.descriptor}': no next view or catch-all defined`);
|
|
38
|
-
if (shouldShowMissingView(meta)) {
|
|
39
|
-
return <MissingComponent type={XP_COMPONENT_TYPE.LAYOUT} descriptor={component.descriptor}/>;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return null;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export default BaseLayout;
|
package/src/views/BasePage.tsx
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {ComponentRegistry} from '../ComponentRegistry';
|
|
3
|
-
import {MetaData, PageData} from '../guillotine/getMetaData';
|
|
4
|
-
import {XP_COMPONENT_TYPE} from '../utils';
|
|
5
|
-
import {ErrorComponent, MissingComponent, shouldShowErrorView, shouldShowMissingView} from './BaseComponent';
|
|
6
|
-
|
|
7
|
-
export interface PageProps {
|
|
8
|
-
page: PageData;
|
|
9
|
-
path: string;
|
|
10
|
-
data?: any;
|
|
11
|
-
common?: any; // Content is passed down to componentviews. TODO: Use a react contextprovider instead?
|
|
12
|
-
meta: MetaData;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface BasePageProps {
|
|
16
|
-
component?: PageData;
|
|
17
|
-
path?: string;
|
|
18
|
-
common?: any;
|
|
19
|
-
data?: any;
|
|
20
|
-
error?: string;
|
|
21
|
-
meta: MetaData;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const BasePage = (props: BasePageProps) => {
|
|
25
|
-
const {component, data, common, error, meta, path} = props;
|
|
26
|
-
const desc = component?.descriptor;
|
|
27
|
-
if (error) {
|
|
28
|
-
console.warn(`BasePage: '${desc}' error: ${error}`);
|
|
29
|
-
if (shouldShowErrorView(meta)) {
|
|
30
|
-
return <ErrorComponent reason={error} descriptor={desc} type={XP_COMPONENT_TYPE.PAGE}/>;
|
|
31
|
-
} else {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
let pageDef;
|
|
36
|
-
if (desc) {
|
|
37
|
-
pageDef = ComponentRegistry.getPage(desc);
|
|
38
|
-
}
|
|
39
|
-
const PageView = pageDef?.view;
|
|
40
|
-
if (PageView) {
|
|
41
|
-
return <PageView page={component}
|
|
42
|
-
path={path}
|
|
43
|
-
data={data}
|
|
44
|
-
common={common}
|
|
45
|
-
meta={meta}/>;
|
|
46
|
-
} else if (component?.descriptor) {
|
|
47
|
-
// empty descriptor usually means uninitialized page
|
|
48
|
-
console.warn(`BasePage: can not render page '${desc}': no next view or catch-all defined`);
|
|
49
|
-
if (shouldShowMissingView(meta)) {
|
|
50
|
-
return <MissingComponent type={XP_COMPONENT_TYPE.PAGE} descriptor={component.descriptor}/>;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return null;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export default BasePage;
|
package/src/views/BasePart.tsx
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {MetaData, PartData} from '../guillotine/getMetaData';
|
|
3
|
-
import {ComponentRegistry} from '../ComponentRegistry';
|
|
4
|
-
import {XP_COMPONENT_TYPE} from '../utils';
|
|
5
|
-
import {MissingComponent, shouldShowMissingView} from './BaseComponent';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export interface PartProps {
|
|
9
|
-
part: PartData;
|
|
10
|
-
path: string;
|
|
11
|
-
data?: any;
|
|
12
|
-
common?: any; // Content is passed down to componentviews. TODO: Use a react contextprovider instead?
|
|
13
|
-
meta: MetaData;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface BasePartProps {
|
|
17
|
-
component?: PartData;
|
|
18
|
-
path: string;
|
|
19
|
-
common?: any;
|
|
20
|
-
data?: any;
|
|
21
|
-
error?: string;
|
|
22
|
-
meta: MetaData;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const BasePart = (props: BasePartProps) => {
|
|
26
|
-
const {component, data, common, meta, path} = props;
|
|
27
|
-
|
|
28
|
-
let partSelection;
|
|
29
|
-
if (component) {
|
|
30
|
-
partSelection = ComponentRegistry.getPart(component.descriptor);
|
|
31
|
-
}
|
|
32
|
-
const SelectedPartView = partSelection?.view;
|
|
33
|
-
if (SelectedPartView) {
|
|
34
|
-
return <SelectedPartView part={component}
|
|
35
|
-
path={path}
|
|
36
|
-
data={data}
|
|
37
|
-
common={common}
|
|
38
|
-
meta={meta}/>;
|
|
39
|
-
} else if (component?.descriptor) {
|
|
40
|
-
// empty descriptor usually means uninitialized part
|
|
41
|
-
console.warn(`BasePart: can not render part '${component.descriptor}': no next view or catch-all defined`);
|
|
42
|
-
if (shouldShowMissingView(meta)) {
|
|
43
|
-
return <MissingComponent type={XP_COMPONENT_TYPE.PART} descriptor={component.descriptor}/>;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return null;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export default BasePart;
|
|
50
|
-
|
package/src/views/Fragment.tsx
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import BaseComponent, {MissingComponent, shouldShowMissingView} from './BaseComponent';
|
|
3
|
-
import {FragmentData, MetaData, PageComponent, PageData} from '../guillotine/getMetaData';
|
|
4
|
-
import {FRAGMENT_DEFAULT_REGION_NAME, XP_COMPONENT_TYPE} from '../utils';
|
|
5
|
-
|
|
6
|
-
interface FragmentProps {
|
|
7
|
-
page?: PageData;
|
|
8
|
-
component?: FragmentData;
|
|
9
|
-
common?: any;
|
|
10
|
-
meta: MetaData;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const FragmentView = (props: FragmentProps) => {
|
|
14
|
-
const {component, page} = props;
|
|
15
|
-
const comps: PageComponent[] = [];
|
|
16
|
-
if (page) {
|
|
17
|
-
// rendering whole page
|
|
18
|
-
const regions = page.regions || {};
|
|
19
|
-
const regionComps = regions[FRAGMENT_DEFAULT_REGION_NAME]?.components;
|
|
20
|
-
if (regionComps) {
|
|
21
|
-
comps.push(...regionComps);
|
|
22
|
-
}
|
|
23
|
-
} else if (component?.fragment) {
|
|
24
|
-
// rendering a part of a page
|
|
25
|
-
comps.push(...component.fragment.components);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!comps.length && shouldShowMissingView(props.meta)) {
|
|
29
|
-
return <MissingComponent type={XP_COMPONENT_TYPE.FRAGMENT} descriptor={page?.descriptor || component?.id}/>;
|
|
30
|
-
} else {
|
|
31
|
-
const {common, meta} = props;
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<>
|
|
35
|
-
{
|
|
36
|
-
comps.map((comp: PageComponent, i: number) => (
|
|
37
|
-
<BaseComponent key={i} component={comp} common={common} meta={meta}/>
|
|
38
|
-
))
|
|
39
|
-
}
|
|
40
|
-
</>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export default FragmentView;
|
package/src/views/MainView.tsx
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import {FetchContentResult} from '../guillotine/fetchContent';
|
|
4
|
-
import SingleComponent from './SingleComponent';
|
|
5
|
-
import BaseContent from './BaseContent';
|
|
6
|
-
import {XP_REQUEST_TYPE} from '../utils';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const _MainView = (props: FetchContentResult) => {
|
|
10
|
-
const {meta} = props;
|
|
11
|
-
|
|
12
|
-
// Single-component render:
|
|
13
|
-
if (meta?.requestType === XP_REQUEST_TYPE.COMPONENT) {
|
|
14
|
-
return <SingleComponent {...props} />;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// meta.requestType="type", and hence content-type based, is standard view for now.
|
|
18
|
-
return <BaseContent {...props} />;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export default _MainView;
|