@exdst-sitecore-content-sdk/astro 0.0.22 → 0.0.24
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/package.json +3 -3
- package/src/client/sitecore-astro-client.test.ts +24 -49
- package/src/client/sitecore-astro-client.ts +0 -45
- package/src/config-cli/define-cli-config.test.ts +1 -22
- package/src/context.ts +13 -15
- package/src/env.d.ts +1 -1
- package/src/middleware/multisite-middleware.test.ts +88 -19
- package/src/sharedTypes/component-props.ts +0 -10
- package/src/tests/test-components/generate-map/Button.astro +4 -0
- package/src/tests/test-components/generate-map/Link.astro +4 -0
- package/src/tools/generate-map.test.ts +201 -0
- package/src/tools/generate-map.ts +9 -21
- package/src/utils/utils.test.ts +72 -9
- package/src/services/component-props-service.ts +0 -183
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exdst-sitecore-content-sdk/astro",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"test:components": "vitest run --config ./vitest.config.ts",
|
|
16
16
|
"coverage": "nyc npm test",
|
|
17
17
|
"generate-docs": "npx typedoc --plugin typedoc-plugin-markdown --outputFileStrategy Members --parametersFormat table --readme none --out ../../ref-docs/core --entryPoints src/index.ts --entryPoints src/config/index.ts --entryPoints src/client/index.ts --entryPoints src/i18n/index.ts --entryPoints src/layout/index.ts --entryPoints src/media/index.ts --entryPoints src/personalize/index.ts --entryPoints src/site/index.ts --entryPoints src/tracking/index.ts --entryPoints src/utils/index.ts --entryPoints src/editing/index.ts --entryPoints src/tools/index.ts --githubPages false",
|
|
18
|
-
"api-extractor": "
|
|
18
|
+
"api-extractor": "api-extractor run --local --verbose",
|
|
19
19
|
"api-extractor:verify": "api-extractor run"
|
|
20
20
|
},
|
|
21
21
|
"engines": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@types/sinon-chai": "^4.0.0",
|
|
50
50
|
"@typescript-eslint/eslint-plugin": "8.39.0",
|
|
51
51
|
"@typescript-eslint/parser": "8.39.0",
|
|
52
|
-
"astro": "^6.1.
|
|
52
|
+
"astro": "^6.1.3",
|
|
53
53
|
"chai": "^4.4.1",
|
|
54
54
|
"chai-spies": "^1.1.0",
|
|
55
55
|
"chai-string": "^1.6.0",
|
|
@@ -34,9 +34,14 @@ describe('SitecoreClient', () => {
|
|
|
34
34
|
},
|
|
35
35
|
defaultSite: 'default-site',
|
|
36
36
|
defaultLanguage: 'en',
|
|
37
|
+
multisite: {
|
|
38
|
+
enabled: true,
|
|
39
|
+
useCookieResolution: () => true,
|
|
40
|
+
},
|
|
37
41
|
layout: { formatLayoutQuery: sandbox.stub() },
|
|
38
42
|
dictionary: { caching: { enabled: true, timeout: 60000 } },
|
|
39
43
|
disableCodeGeneration: false,
|
|
44
|
+
rewriteMediaUrls: false,
|
|
40
45
|
};
|
|
41
46
|
|
|
42
47
|
let sitecoreClient = new SitecoreAstroClient(defaultInitOptions);
|
|
@@ -97,12 +102,6 @@ describe('SitecoreClient', () => {
|
|
|
97
102
|
const path = `${VARIANT_PREFIX}variant1/${VARIANT_PREFIX}mountain_bike_audience/test/path`;
|
|
98
103
|
const locale = 'en-US';
|
|
99
104
|
const testLayoutData = structuredClone(layoutData);
|
|
100
|
-
|
|
101
|
-
const siteInfo = {
|
|
102
|
-
name: 'default-site',
|
|
103
|
-
hostName: 'example.com',
|
|
104
|
-
language: 'en',
|
|
105
|
-
};
|
|
106
105
|
layoutServiceStub.fetchLayoutData.returns(testLayoutData);
|
|
107
106
|
sandbox.stub(sitecoreClient, 'getHeadLinks').returns([]);
|
|
108
107
|
|
|
@@ -117,12 +116,6 @@ describe('SitecoreClient', () => {
|
|
|
117
116
|
const path = `${VARIANT_PREFIX}variant1/${VARIANT_PREFIX}sand_bike_audience/test/path`;
|
|
118
117
|
const locale = 'en-US';
|
|
119
118
|
const testLayoutData = structuredClone(layoutData);
|
|
120
|
-
|
|
121
|
-
const siteInfo = {
|
|
122
|
-
name: 'default-site',
|
|
123
|
-
hostName: 'example.com',
|
|
124
|
-
language: 'en',
|
|
125
|
-
};
|
|
126
119
|
layoutServiceStub.fetchLayoutData.returns(testLayoutData);
|
|
127
120
|
sandbox.stub(sitecoreClient, 'getHeadLinks').returns([]);
|
|
128
121
|
|
|
@@ -248,45 +241,27 @@ describe('SitecoreClient', () => {
|
|
|
248
241
|
});
|
|
249
242
|
});
|
|
250
243
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
} as
|
|
261
|
-
const layoutData = {
|
|
262
|
-
sitecore: {
|
|
263
|
-
context,
|
|
264
|
-
route: {
|
|
265
|
-
name: 'test',
|
|
266
|
-
placeholders: {
|
|
267
|
-
main: [
|
|
268
|
-
{
|
|
269
|
-
componentName: 'TestComponent',
|
|
270
|
-
uid: 'test-uid',
|
|
271
|
-
},
|
|
272
|
-
],
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
},
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
const mockComponent = {
|
|
279
|
-
getComponentServerProps: sandbox.stub().resolves({ props: { data: 'test-data' } }),
|
|
280
|
-
};
|
|
244
|
+
describe('getPreview', () => {
|
|
245
|
+
it('should call base getPreview with preview data and fetch options', async () => {
|
|
246
|
+
const previewData = {
|
|
247
|
+
variantId: 'variant-a',
|
|
248
|
+
route: '/test/path',
|
|
249
|
+
language: 'en',
|
|
250
|
+
} as any;
|
|
251
|
+
const fetchOptions = {
|
|
252
|
+
retries: 2,
|
|
253
|
+
} as any;
|
|
281
254
|
|
|
282
|
-
const
|
|
255
|
+
const basePrototype = Object.getPrototypeOf(SitecoreAstroClient.prototype);
|
|
256
|
+
const superGetPreviewStub = sandbox.stub(basePrototype, 'getPreview').resolves(null);
|
|
283
257
|
|
|
284
|
-
|
|
258
|
+
try {
|
|
259
|
+
await sitecoreClient.getPreview(previewData, fetchOptions);
|
|
285
260
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
261
|
+
expect(superGetPreviewStub).to.have.been.calledOnceWithExactly(previewData, fetchOptions);
|
|
262
|
+
} finally {
|
|
263
|
+
superGetPreviewStub.restore();
|
|
264
|
+
}
|
|
290
265
|
});
|
|
291
|
-
})
|
|
266
|
+
});
|
|
292
267
|
});
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
SitecoreClientInit,
|
|
8
8
|
} from '@sitecore-content-sdk/content/client';
|
|
9
9
|
import { PreviewData } from '../sharedTypes/component-props';
|
|
10
|
-
import { ComponentPropsService } from '../services/component-props-service';
|
|
11
10
|
import { EditingPreviewData } from '@sitecore-content-sdk/content/editing';
|
|
12
11
|
import { getSiteRewriteData, normalizeSiteRewrite } from '@sitecore-content-sdk/content/site';
|
|
13
12
|
import {
|
|
@@ -27,10 +26,8 @@ export type SitecoreAstroClientInit = SitecoreClientInit & Pick<SitecoreConfig,
|
|
|
27
26
|
* @public
|
|
28
27
|
*/
|
|
29
28
|
export class SitecoreAstroClient extends SitecoreClient {
|
|
30
|
-
protected componentPropsService: ComponentPropsService;
|
|
31
29
|
constructor(protected initOptions: SitecoreAstroClientInit) {
|
|
32
30
|
super(initOptions);
|
|
33
|
-
this.componentPropsService = this.getComponentPropsService();
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
/**
|
|
@@ -109,46 +106,4 @@ export class SitecoreAstroClient extends SitecoreClient {
|
|
|
109
106
|
|
|
110
107
|
return staticPaths;
|
|
111
108
|
}
|
|
112
|
-
|
|
113
|
-
// /**
|
|
114
|
-
// * Parses components from component map and layoutData, executes getServerProps/getStaticProps methods
|
|
115
|
-
// * and returns resulting props from components
|
|
116
|
-
// * @param {LayoutServiceData} layoutData layout data to parse compnents from
|
|
117
|
-
// * @param {ComponentMap<AstroContentSdkComponent>} components component map to get props for
|
|
118
|
-
// * @returns {ComponentPropsCollection} component props
|
|
119
|
-
// */
|
|
120
|
-
// async getComponentData(
|
|
121
|
-
// layoutData: LayoutServiceData,
|
|
122
|
-
// // context: GetServerSidePropsContext | GetStaticPropsContext,
|
|
123
|
-
// components: ComponentMap<AstroContentSdkComponent>
|
|
124
|
-
// ): Promise<ComponentPropsCollection> {
|
|
125
|
-
// let componentProps: ComponentPropsCollection = {};
|
|
126
|
-
// if (!layoutData.sitecore.route) return componentProps;
|
|
127
|
-
// // Retrieve component props using side-effects defined on components level
|
|
128
|
-
// componentProps = await this.componentPropsService.fetchComponentProps({
|
|
129
|
-
// layoutData: layoutData,
|
|
130
|
-
// // context,
|
|
131
|
-
// components,
|
|
132
|
-
// });
|
|
133
|
-
|
|
134
|
-
// const errors = Object.keys(componentProps)
|
|
135
|
-
// .map((id) => {
|
|
136
|
-
// const component = componentProps[id] as ComponentPropsError;
|
|
137
|
-
|
|
138
|
-
// return component.error
|
|
139
|
-
// ? `\nUnable to get component props for ${component.componentName} (${id}): ${component.error}`
|
|
140
|
-
// : '';
|
|
141
|
-
// })
|
|
142
|
-
// .join('');
|
|
143
|
-
|
|
144
|
-
// if (errors.length) {
|
|
145
|
-
// throw new Error(errors);
|
|
146
|
-
// }
|
|
147
|
-
|
|
148
|
-
// return componentProps;
|
|
149
|
-
// }
|
|
150
|
-
|
|
151
|
-
protected getComponentPropsService(): ComponentPropsService {
|
|
152
|
-
return new ComponentPropsService();
|
|
153
|
-
}
|
|
154
109
|
}
|
|
@@ -11,10 +11,7 @@ describe('defineCliConfig', () => {
|
|
|
11
11
|
const validateDefaultTemplates = (result: SitecoreCliConfig) => {
|
|
12
12
|
expect(result.scaffold.templates[0].name).to.equal(ComponentTemplateType.DEFAULT);
|
|
13
13
|
const defaultTemplate = result.scaffold.templates[0].generateTemplate('ComponentName');
|
|
14
|
-
|
|
15
|
-
// // eslint-disable-next-line quotes
|
|
16
|
-
// `import { ComponentParams, ComponentRendering } from '@sitecore-content-sdk/nextjs';`
|
|
17
|
-
// );
|
|
14
|
+
|
|
18
15
|
expect(defaultTemplate).to.contain('ComponentName');
|
|
19
16
|
if (result.scaffold.templates[0].getNextSteps) {
|
|
20
17
|
const componentpath = 'src/components/ComponentName.astro';
|
|
@@ -22,24 +19,6 @@ describe('defineCliConfig', () => {
|
|
|
22
19
|
`* Implement the Astro component in ${chalk.green(componentpath)}`
|
|
23
20
|
);
|
|
24
21
|
}
|
|
25
|
-
|
|
26
|
-
// expect(result.scaffold.templates[1].name).to.equal(ComponentTemplateType.BYOC);
|
|
27
|
-
// const byocTemplate = result.scaffold.templates[1].generateTemplate('ByocComponentName');
|
|
28
|
-
// expect(byocTemplate).to.contain(
|
|
29
|
-
// // eslint-disable-next-line quotes
|
|
30
|
-
// `import * as FEAAS from '@sitecore-feaas/clientside/react';`
|
|
31
|
-
// );
|
|
32
|
-
// expect(byocTemplate).to.contain('ByocComponentName');
|
|
33
|
-
|
|
34
|
-
// expect(result.scaffold.templates[1].generateTemplate('comp name')).to.contain(
|
|
35
|
-
// // eslint-disable-next-line quotes
|
|
36
|
-
// `import * as FEAAS from '@sitecore-feaas/clientside/react';`
|
|
37
|
-
// );
|
|
38
|
-
// if (result.scaffold.templates[1].getNextSteps) {
|
|
39
|
-
// expect(result.scaffold.templates[1].getNextSteps('componentpath')[0]).to.contain(
|
|
40
|
-
// '* Modify component registration through FEAAS.External.registerComponent if needed'
|
|
41
|
-
// );
|
|
42
|
-
// }
|
|
43
22
|
};
|
|
44
23
|
|
|
45
24
|
it('should add default and byoc scaffold templates', () => {
|
package/src/context.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const SitecoreContext: any = map({});
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Shape of values passed when updating {@link SitecoreContext} (page, API, and optional component map).
|
|
15
|
-
* @
|
|
15
|
+
* @public
|
|
16
16
|
*/
|
|
17
17
|
export interface SitecoreContextProps {
|
|
18
18
|
/**
|
|
@@ -31,9 +31,9 @@ export interface SitecoreContextProps {
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Shape of values passed when updating dictionary phrases on {@link SitecoreContext}.
|
|
34
|
-
* @
|
|
34
|
+
* @public
|
|
35
35
|
*/
|
|
36
|
-
export interface
|
|
36
|
+
export interface SitecoreDictionaryProps {
|
|
37
37
|
/**
|
|
38
38
|
* The dictionary data.
|
|
39
39
|
*/
|
|
@@ -42,10 +42,8 @@ export interface SitecoreDictionarytProps {
|
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Writes page data, API config, and optional component map into {@link SitecoreContext}.
|
|
45
|
-
* @param {
|
|
46
|
-
* @
|
|
47
|
-
* @param {ComponentMap} [props.componentMap] - Component map.
|
|
48
|
-
* @internal
|
|
45
|
+
* @param {SitecoreContextProps} props - Page, API, and optional component map.
|
|
46
|
+
* @public
|
|
49
47
|
*/
|
|
50
48
|
export const updateSitecoreContext = ({ page, api, componentMap }: SitecoreContextProps) => {
|
|
51
49
|
SitecoreContext.setKey('page', page);
|
|
@@ -55,11 +53,10 @@ export const updateSitecoreContext = ({ page, api, componentMap }: SitecoreConte
|
|
|
55
53
|
|
|
56
54
|
/**
|
|
57
55
|
* Writes dictionary phrases into {@link SitecoreContext} for {@link useDictionary}.
|
|
58
|
-
* @param {
|
|
59
|
-
* @
|
|
60
|
-
* @internal
|
|
56
|
+
* @param {DictionaryPhrases} dictionary - The dictionary data.
|
|
57
|
+
* @public
|
|
61
58
|
*/
|
|
62
|
-
export const updateSitecoreDictionary = ({ dictionary }:
|
|
59
|
+
export const updateSitecoreDictionary = ({ dictionary }: SitecoreDictionaryProps) => {
|
|
63
60
|
SitecoreContext.setKey('dictionary', dictionary);
|
|
64
61
|
};
|
|
65
62
|
|
|
@@ -68,9 +65,10 @@ export const updateSitecoreDictionary = ({ dictionary }: SitecoreDictionarytProp
|
|
|
68
65
|
* @public
|
|
69
66
|
*/
|
|
70
67
|
export const useSitecore = (): SitecoreContextProps => {
|
|
68
|
+
const context = SitecoreContext.get();
|
|
71
69
|
return {
|
|
72
|
-
page:
|
|
73
|
-
api:
|
|
70
|
+
page: context.page,
|
|
71
|
+
api: context.api,
|
|
74
72
|
};
|
|
75
73
|
};
|
|
76
74
|
|
|
@@ -79,7 +77,7 @@ export const useSitecore = (): SitecoreContextProps => {
|
|
|
79
77
|
* @public
|
|
80
78
|
*/
|
|
81
79
|
export const useComponentMap = (): ComponentMap => {
|
|
82
|
-
return SitecoreContext.get()
|
|
80
|
+
return SitecoreContext.get().componentMap;
|
|
83
81
|
};
|
|
84
82
|
|
|
85
83
|
/**
|
|
@@ -88,7 +86,7 @@ export const useComponentMap = (): ComponentMap => {
|
|
|
88
86
|
*/
|
|
89
87
|
export const useDictionary = () => {
|
|
90
88
|
const t = (key: string): string => {
|
|
91
|
-
const dictionary = SitecoreContext.get()
|
|
89
|
+
const dictionary = SitecoreContext.get().dictionary;
|
|
92
90
|
if (!dictionary) {
|
|
93
91
|
return key;
|
|
94
92
|
}
|
package/src/env.d.ts
CHANGED
|
@@ -202,6 +202,33 @@ describe('MultisiteMiddleware', () => {
|
|
|
202
202
|
});
|
|
203
203
|
});
|
|
204
204
|
|
|
205
|
+
describe('multisite disabled globally', () => {
|
|
206
|
+
it('should skip when enabled is false and request is not Sitecore preview', async () => {
|
|
207
|
+
const { middleware, siteResolver } = createMiddleware({
|
|
208
|
+
config: { ...defaultConfig, enabled: false },
|
|
209
|
+
});
|
|
210
|
+
const res = createResponse();
|
|
211
|
+
|
|
212
|
+
const context = createContext({
|
|
213
|
+
url: new URL(hostname),
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const mockNext = async () => res;
|
|
217
|
+
|
|
218
|
+
const finalRes = await middleware.handle(context, mockNext);
|
|
219
|
+
|
|
220
|
+
validateDebugLog('multisite middleware start: %o', {
|
|
221
|
+
pathname: '/styleguide',
|
|
222
|
+
language: 'en',
|
|
223
|
+
hostname: 'foo.net',
|
|
224
|
+
});
|
|
225
|
+
validateDebugLog('skipped (multisite middleware is disabled globally)');
|
|
226
|
+
|
|
227
|
+
expect(finalRes).to.deep.equal(res);
|
|
228
|
+
expect(siteResolver.getByHost.called).to.be.false;
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
205
232
|
describe('disabled in chain', () => {
|
|
206
233
|
it('should skip if skipMiddleware local variable is true', async () => {
|
|
207
234
|
const { middleware } = createMiddleware();
|
|
@@ -226,30 +253,33 @@ describe('MultisiteMiddleware', () => {
|
|
|
226
253
|
});
|
|
227
254
|
});
|
|
228
255
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
256
|
+
describe('Vercel/Next preview (_preview_data cookie)', () => {
|
|
257
|
+
it('should skip multisite when preview data cookie is present', async () => {
|
|
258
|
+
const { middleware, siteResolver } = createMiddleware();
|
|
259
|
+
const res = createResponse();
|
|
233
260
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
261
|
+
const context = createContext({
|
|
262
|
+
url: new URL(hostname),
|
|
263
|
+
cookieValues: {
|
|
264
|
+
_preview_data: '1',
|
|
265
|
+
},
|
|
266
|
+
});
|
|
240
267
|
|
|
241
|
-
|
|
242
|
-
// return res;
|
|
243
|
-
// };
|
|
268
|
+
const mockNext = async () => res;
|
|
244
269
|
|
|
245
|
-
|
|
270
|
+
const finalRes = await middleware.handle(context, mockNext);
|
|
246
271
|
|
|
247
|
-
|
|
272
|
+
validateDebugLog('multisite middleware start: %o', {
|
|
273
|
+
pathname: '/styleguide',
|
|
274
|
+
language: 'en',
|
|
275
|
+
hostname: 'foo.net',
|
|
276
|
+
});
|
|
277
|
+
validateDebugLog('skipped (preview)');
|
|
248
278
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
279
|
+
expect(finalRes).to.deep.equal(res);
|
|
280
|
+
expect(siteResolver.getByHost.called).to.be.false;
|
|
281
|
+
});
|
|
282
|
+
});
|
|
253
283
|
|
|
254
284
|
describe('Sitecore Preview', () => {
|
|
255
285
|
it('request is passed', async () => {
|
|
@@ -440,6 +470,45 @@ describe('MultisiteMiddleware', () => {
|
|
|
440
470
|
expect(mockNext).calledWith(sinon.match({ pathname: '/_site_foo/styleguide' }));
|
|
441
471
|
});
|
|
442
472
|
|
|
473
|
+
it('x-forwarded-host takes precedence over host for site resolution', async () => {
|
|
474
|
+
const context = createContext({
|
|
475
|
+
headerValues: {
|
|
476
|
+
'x-forwarded-host': 'forwarded.example.com',
|
|
477
|
+
host: 'foo.net',
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
const mockNext = sinon.stub().returns(
|
|
482
|
+
createResponse({
|
|
483
|
+
headers: [],
|
|
484
|
+
})
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
const { middleware, siteResolver } = createMiddleware();
|
|
488
|
+
|
|
489
|
+
const finalRes = await middleware.handle(context, mockNext);
|
|
490
|
+
|
|
491
|
+
validateDebugLog('multisite middleware start: %o', {
|
|
492
|
+
pathname: '/styleguide',
|
|
493
|
+
language: 'en',
|
|
494
|
+
hostname: 'forwarded.example.com',
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
validateEndMessageDebugLog('multisite middleware end in %dms: %o', {
|
|
498
|
+
rewritePath: '/_site_foo/styleguide',
|
|
499
|
+
siteName: 'foo',
|
|
500
|
+
headers: {
|
|
501
|
+
...(finalRes as Response).headers,
|
|
502
|
+
'x-sc-rewrite': '/_site_foo/styleguide',
|
|
503
|
+
},
|
|
504
|
+
cookies: 'sc_site=foo; HttpOnly; Secure; SameSite=None',
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
expect(siteResolver.getByHost).to.be.calledWith('forwarded.example.com');
|
|
508
|
+
|
|
509
|
+
expect(mockNext).calledWith(sinon.match({ pathname: '/_site_foo/styleguide' }));
|
|
510
|
+
});
|
|
511
|
+
|
|
443
512
|
it('custom response object is not provided', async () => {
|
|
444
513
|
const context = createContext();
|
|
445
514
|
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
export type ComponentPropsError = { error: string; componentName: string };
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shape of component props storage
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
export type ComponentPropsCollection = {
|
|
8
|
-
[componentUid: string]: unknown | ComponentPropsError;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
1
|
/**
|
|
12
2
|
* Represents an Astro component import
|
|
13
3
|
* @public
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/* eslint-disable quotes */
|
|
2
|
+
/* eslint-disable no-unused-expressions, @typescript-eslint/no-unused-expressions */
|
|
3
|
+
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import * as chai from 'chai';
|
|
6
|
+
import sinonChai from 'sinon-chai';
|
|
7
|
+
import { expect } from 'chai';
|
|
8
|
+
import sinon from 'sinon';
|
|
9
|
+
|
|
10
|
+
chai.use(sinonChai);
|
|
11
|
+
import { generateMap } from './generate-map';
|
|
12
|
+
import fs from 'fs';
|
|
13
|
+
import { ComponentImport } from '@sitecore-content-sdk/content/tools';
|
|
14
|
+
|
|
15
|
+
describe('generateMap', () => {
|
|
16
|
+
const sandbox = sinon.createSandbox();
|
|
17
|
+
|
|
18
|
+
describe('generateMap', () => {
|
|
19
|
+
const fakePackages: ComponentImport[] = [
|
|
20
|
+
{
|
|
21
|
+
importName: 'MyLib',
|
|
22
|
+
importInfo: {
|
|
23
|
+
importFrom: '@my/lib',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
importName: 'OtherLib',
|
|
28
|
+
importInfo: {
|
|
29
|
+
importFrom: '@other/lib',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
sandbox.stub(fs, 'writeFileSync');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
sandbox.restore();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should write componentMap.ts file with components from "paths" parameter', () => {
|
|
43
|
+
const paths = ['src/tests/test-components/generate-map'];
|
|
44
|
+
generateMap({ paths });
|
|
45
|
+
|
|
46
|
+
expect(fs.writeFileSync).to.have.been.calledOnce;
|
|
47
|
+
const [dest, content] = (fs.writeFileSync as sinon.SinonStub).getCall(0).args;
|
|
48
|
+
expect(dest).to.equal(path.join(process.cwd(), '.sitecore', 'component-map.ts'));
|
|
49
|
+
|
|
50
|
+
expect(content).to.include(
|
|
51
|
+
"import type { AstroContentSdkComponent } from '@exdst-sitecore-content-sdk/astro';"
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(content).to.include(
|
|
55
|
+
"import Button from 'src/tests/test-components/generate-map/Button.astro';"
|
|
56
|
+
);
|
|
57
|
+
expect(content).to.include(
|
|
58
|
+
"import Link from 'src/tests/test-components/generate-map/Link.astro';"
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(content).to.include('new Map');
|
|
62
|
+
expect(content).to.include("['Button', Button]");
|
|
63
|
+
expect(content).to.include("['Link', Link]");
|
|
64
|
+
expect(content).to.include('export default componentMap;');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should use template from custom componentMap function, when provided', () => {
|
|
68
|
+
const paths = ['src/tests/test-components/generate-map'];
|
|
69
|
+
const customTemplate = sinon.stub().returns('// custom template output');
|
|
70
|
+
const fakePackages = [
|
|
71
|
+
{
|
|
72
|
+
importName: 'CustomLib',
|
|
73
|
+
importInfo: {
|
|
74
|
+
importFrom: '@custom/lib',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
generateMap({ paths, componentImports: fakePackages, mapTemplate: customTemplate });
|
|
79
|
+
|
|
80
|
+
expect(customTemplate).to.have.been.calledOnce;
|
|
81
|
+
const [componentsArg, packagesArg] = customTemplate.getCall(0).args;
|
|
82
|
+
expect(packagesArg).to.deep.equal(fakePackages);
|
|
83
|
+
expect(componentsArg.map((c: any) => c.componentName)).to.include.members(['Button', 'Link']);
|
|
84
|
+
|
|
85
|
+
expect(fs.writeFileSync).to.have.been.calledOnce;
|
|
86
|
+
const [, content] = (fs.writeFileSync as sinon.SinonStub).getCall(0).args;
|
|
87
|
+
expect(content).to.equal('// custom template output');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should generate an empty component map if no components are found', () => {
|
|
91
|
+
const paths = ['src/tests/test-components/generate-map-empty'];
|
|
92
|
+
generateMap({ paths });
|
|
93
|
+
|
|
94
|
+
expect(fs.writeFileSync).to.have.been.calledOnce;
|
|
95
|
+
const [, content] = (fs.writeFileSync as sinon.SinonStub).getCall(0).args;
|
|
96
|
+
expect(content).to.include(
|
|
97
|
+
'export const componentMap = new Map<string, AstroContentSdkComponent>(['
|
|
98
|
+
);
|
|
99
|
+
expect(content).to.not.match(/\['Button'[\s\S]*Button/);
|
|
100
|
+
expect(content).to.not.match(/\['Link'[\s\S]*Link/);
|
|
101
|
+
expect(content).to.include('export default componentMap;');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should handle multiple paths and merge their components', () => {
|
|
105
|
+
const paths = [
|
|
106
|
+
'src/tests/test-components/generate-map',
|
|
107
|
+
'src/tests/test-components/map-components',
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
generateMap({ paths });
|
|
111
|
+
|
|
112
|
+
expect(fs.writeFileSync).to.have.been.calledOnce;
|
|
113
|
+
const [mainDest, content] = (fs.writeFileSync as sinon.SinonStub).getCall(0).args;
|
|
114
|
+
expect(mainDest).to.equal(path.join(process.cwd(), '.sitecore', 'component-map.ts'));
|
|
115
|
+
|
|
116
|
+
expect(content).to.include('new Map');
|
|
117
|
+
|
|
118
|
+
expect(content).to.include(
|
|
119
|
+
"import Button from 'src/tests/test-components/generate-map/Button.astro';"
|
|
120
|
+
);
|
|
121
|
+
expect(content).to.include(
|
|
122
|
+
"import Link from 'src/tests/test-components/generate-map/Link.astro';"
|
|
123
|
+
);
|
|
124
|
+
expect(content).to.include(
|
|
125
|
+
"import Bar from 'src/tests/test-components/map-components/Bar.astro';"
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
expect(content).to.include("['Button', Button]");
|
|
129
|
+
expect(content).to.include("['Link', Link]");
|
|
130
|
+
expect(content).to.include("['Bar', Bar]");
|
|
131
|
+
expect(content).to.include('export default componentMap;');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should not fail if packages is undefined', () => {
|
|
135
|
+
const paths = ['src/components'];
|
|
136
|
+
expect(() => generateMap({ paths, componentImports: undefined })).to.not.throw();
|
|
137
|
+
expect(fs.writeFileSync).to.have.been.calledOnce;
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should write componentMap.ts file with components from "paths" and "packages" parameters, when provided', () => {
|
|
141
|
+
const paths = ['src/components'];
|
|
142
|
+
generateMap({ paths, componentImports: fakePackages });
|
|
143
|
+
|
|
144
|
+
expect(fs.writeFileSync).to.have.been.calledOnce;
|
|
145
|
+
const [, content] = (fs.writeFileSync as sinon.SinonStub).getCall(0).args;
|
|
146
|
+
expect(content).to.include("import MyLib from '@my/lib';");
|
|
147
|
+
expect(content).to.include("import OtherLib from '@other/lib';");
|
|
148
|
+
|
|
149
|
+
expect(content).to.include(
|
|
150
|
+
'export const componentMap = new Map<string, AstroContentSdkComponent>(['
|
|
151
|
+
);
|
|
152
|
+
expect(content).to.include("['MyLib', MyLib],");
|
|
153
|
+
expect(content).to.include("['OtherLib', OtherLib],");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should use custom destination when provided', () => {
|
|
157
|
+
const paths = ['src/components'];
|
|
158
|
+
const customDir = path.join(process.cwd(), 'custom/path');
|
|
159
|
+
const mainDest = path.join(customDir, 'component-map.ts');
|
|
160
|
+
|
|
161
|
+
generateMap({ paths, destination: 'custom/path', includeVariants: false });
|
|
162
|
+
|
|
163
|
+
expect(fs.writeFileSync).to.have.been.calledOnce;
|
|
164
|
+
|
|
165
|
+
const encodingArg = sinon.match.string.or(sinon.match.has('encoding'));
|
|
166
|
+
|
|
167
|
+
expect(fs.writeFileSync).to.have.been.calledWithMatch(
|
|
168
|
+
mainDest,
|
|
169
|
+
sinon.match.string,
|
|
170
|
+
encodingArg
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should pass exclude param into component collection call', () => {
|
|
175
|
+
const paths = ['src/tests/test-components/generate-map'];
|
|
176
|
+
const exclude = ['src/tests/test-components/generate-map/Button.*'];
|
|
177
|
+
generateMap({ paths, exclude });
|
|
178
|
+
|
|
179
|
+
expect(fs.writeFileSync).to.have.been.calledOnce;
|
|
180
|
+
const [, content] = (fs.writeFileSync as sinon.SinonStub).getCall(0).args;
|
|
181
|
+
|
|
182
|
+
expect(content).to.include(
|
|
183
|
+
"import Link from 'src/tests/test-components/generate-map/Link.astro';"
|
|
184
|
+
);
|
|
185
|
+
expect(content).to.not.include('Button');
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should throw error when destination cannot be written to', async () => {
|
|
189
|
+
(fs.writeFileSync as sinon.SinonStub).throws(new Error('Disk full'));
|
|
190
|
+
const paths = ['src/components'];
|
|
191
|
+
let errorCaught = null;
|
|
192
|
+
try {
|
|
193
|
+
generateMap({ paths });
|
|
194
|
+
} catch (err) {
|
|
195
|
+
errorCaught = err;
|
|
196
|
+
}
|
|
197
|
+
expect(errorCaught).to.be.an('error');
|
|
198
|
+
expect((errorCaught as Error).message).to.equal('Disk full');
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
});
|
|
@@ -36,40 +36,28 @@ export const generateMap: GenerateMapFunction = ({
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
const buildAstroMapContent: ComponentMapTemplate = (components, componentImports): string => {
|
|
39
|
-
const
|
|
40
|
-
const namedImports: string[] = [];
|
|
41
|
-
|
|
39
|
+
const componentImportsList: string[] = [];
|
|
42
40
|
const componentMapEntries: string[] = [];
|
|
43
41
|
|
|
44
42
|
components.forEach((component) => {
|
|
45
|
-
|
|
43
|
+
componentImportsList.push(
|
|
44
|
+
`import ${component.moduleName} from '${component.importPath}.astro';`
|
|
45
|
+
);
|
|
46
46
|
componentMapEntries.push(`['${component.moduleName}', ${component.moduleName}]`);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
componentImports?.forEach((packageEntry) => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}.astro';`
|
|
55
|
-
);
|
|
56
|
-
packageEntry.importInfo.namedImports.forEach((importName) => {
|
|
57
|
-
componentMapEntries.push(`['${importName}', ${importName}]`);
|
|
58
|
-
});
|
|
59
|
-
} else {
|
|
60
|
-
wildcardImports.push(
|
|
61
|
-
`import ${packageEntry.importName} from '${packageEntry.importInfo.importFrom}';`
|
|
62
|
-
);
|
|
63
|
-
componentMapEntries.push(`['${packageEntry.importName}', ${packageEntry.importName}]`);
|
|
64
|
-
}
|
|
50
|
+
componentImportsList.push(
|
|
51
|
+
`import ${packageEntry.importName} from '${packageEntry.importInfo.importFrom}';`
|
|
52
|
+
);
|
|
53
|
+
componentMapEntries.push(`['${packageEntry.importName}', ${packageEntry.importName}]`);
|
|
65
54
|
});
|
|
66
55
|
|
|
67
56
|
return `
|
|
68
57
|
import type { AstroContentSdkComponent } from '@exdst-sitecore-content-sdk/astro';
|
|
69
58
|
|
|
70
59
|
// Components imported from the app itself
|
|
71
|
-
${
|
|
72
|
-
${namedImports.join('\n')}
|
|
60
|
+
${componentImportsList.join('\n')}
|
|
73
61
|
|
|
74
62
|
// Components must be registered within the map to match the string key with component name in Sitecore
|
|
75
63
|
export const componentMap = new Map<string, AstroContentSdkComponent>([
|
package/src/utils/utils.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-unused-expressions */
|
|
2
2
|
import { expect, use } from 'chai';
|
|
3
3
|
import spies from 'chai-spies';
|
|
4
|
-
import { addClassName, getEditingSecret } from './utils';
|
|
4
|
+
import { addClassName, extractPath, getEditingSecret, removeLanguageFromPath } from './utils';
|
|
5
5
|
|
|
6
6
|
use(spies);
|
|
7
7
|
|
|
@@ -34,15 +34,78 @@ describe('addClassName', () => {
|
|
|
34
34
|
expect(modifiableAttrs).to.deep.equal({
|
|
35
35
|
className: 'first-class second-class',
|
|
36
36
|
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should convert class attribute value to className when className is absent', () => {
|
|
40
|
+
const modifiableAttrs = {
|
|
41
|
+
class: 'second-class',
|
|
42
|
+
};
|
|
43
|
+
addClassName(modifiableAttrs);
|
|
44
|
+
expect(modifiableAttrs).to.deep.equal({
|
|
45
|
+
className: 'second-class',
|
|
46
|
+
});
|
|
47
|
+
});
|
|
37
48
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
it('should keep attributes unchanged when class is absent', () => {
|
|
50
|
+
const modifiableAttrs = {
|
|
51
|
+
className: 'first-class',
|
|
52
|
+
id: 'image',
|
|
53
|
+
};
|
|
54
|
+
addClassName(modifiableAttrs);
|
|
55
|
+
expect(modifiableAttrs).to.deep.equal({
|
|
56
|
+
className: 'first-class',
|
|
57
|
+
id: 'image',
|
|
46
58
|
});
|
|
47
59
|
});
|
|
48
60
|
});
|
|
61
|
+
|
|
62
|
+
describe('extractPath', () => {
|
|
63
|
+
it('should return root slash when params are undefined', () => {
|
|
64
|
+
const result = extractPath(undefined as unknown as Record<string, string | undefined>);
|
|
65
|
+
expect(result).to.equal('/');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should join path segments when path is an array', () => {
|
|
69
|
+
const result = extractPath({ path: ['about', 'team'] as unknown as string });
|
|
70
|
+
expect(result).to.equal('about/team');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should return path when path is a string', () => {
|
|
74
|
+
const result = extractPath({ path: 'about' });
|
|
75
|
+
expect(result).to.equal('about');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should return root slash when path is missing', () => {
|
|
79
|
+
const result = extractPath({});
|
|
80
|
+
expect(result).to.equal('/');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('removeLanguageFromPath', () => {
|
|
85
|
+
const languages = ['en', 'fr', 'de-DE'];
|
|
86
|
+
|
|
87
|
+
it('should remove a leading language segment', () => {
|
|
88
|
+
const result = removeLanguageFromPath('en/About', languages);
|
|
89
|
+
expect(result).to.equal('About');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should remove a language segment following a _site_ segment', () => {
|
|
93
|
+
const result = removeLanguageFromPath('_site_Basic/en/About', languages);
|
|
94
|
+
expect(result).to.equal('_site_Basic/About');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should match languages case-insensitively', () => {
|
|
98
|
+
const result = removeLanguageFromPath('_site_Basic/FR/About', languages);
|
|
99
|
+
expect(result).to.equal('_site_Basic/About');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should return root slash when path only contains a language segment', () => {
|
|
103
|
+
const result = removeLanguageFromPath('en', languages);
|
|
104
|
+
expect(result).to.equal('/');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should leave path unchanged when no supported language is found', () => {
|
|
108
|
+
const result = removeLanguageFromPath('es/About', languages);
|
|
109
|
+
expect(result).to.equal('es/About');
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
// import chalk from 'chalk';
|
|
2
|
-
import {
|
|
3
|
-
LayoutServiceData,
|
|
4
|
-
ComponentRendering,
|
|
5
|
-
PlaceholdersData,
|
|
6
|
-
} from '@sitecore-content-sdk/content/layout';
|
|
7
|
-
import {
|
|
8
|
-
AstroContentSdkComponent,
|
|
9
|
-
ComponentMap,
|
|
10
|
-
ComponentPropsCollection,
|
|
11
|
-
} from '../sharedTypes/component-props';
|
|
12
|
-
|
|
13
|
-
export type FetchComponentPropsArguments = {
|
|
14
|
-
layoutData: LayoutServiceData;
|
|
15
|
-
// context: NextContext;
|
|
16
|
-
components: ComponentMap<AstroContentSdkComponent>;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type ComponentPropsRequest = {
|
|
20
|
-
// fetch: ComponentPropsFetchFunction;
|
|
21
|
-
layoutData: LayoutServiceData;
|
|
22
|
-
rendering: ComponentRendering;
|
|
23
|
-
// context: NextContext;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The service for fetching component props.
|
|
28
|
-
* @public
|
|
29
|
-
*/
|
|
30
|
-
export class ComponentPropsService {
|
|
31
|
-
async fetchComponentProps(
|
|
32
|
-
params: FetchComponentPropsArguments
|
|
33
|
-
): Promise<ComponentPropsCollection> {
|
|
34
|
-
const { layoutData, components } = params;
|
|
35
|
-
const requests = await this.collectRequests({
|
|
36
|
-
placeholders: layoutData.sitecore.route?.placeholders,
|
|
37
|
-
components,
|
|
38
|
-
layoutData,
|
|
39
|
-
// context,
|
|
40
|
-
});
|
|
41
|
-
return await this.execRequests(requests);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Go through layout service data, check all renderings using displayName, which should make some side effects.
|
|
46
|
-
* Write result in requests variable
|
|
47
|
-
* @param {object} params params
|
|
48
|
-
* @param {PlaceholdersData} [params.placeholders]
|
|
49
|
-
* @param {ComponentMap} params.components
|
|
50
|
-
* @param {LayoutServiceData} params.layoutData
|
|
51
|
-
* @param {ComponentPropsRequest[]} params.requests
|
|
52
|
-
* @returns {ComponentPropsRequest[]} array of requests
|
|
53
|
-
*/
|
|
54
|
-
protected async collectRequests(params: {
|
|
55
|
-
placeholders?: PlaceholdersData;
|
|
56
|
-
components: ComponentMap<AstroContentSdkComponent>;
|
|
57
|
-
layoutData: LayoutServiceData;
|
|
58
|
-
// context: NextContext;
|
|
59
|
-
requests?: ComponentPropsRequest[];
|
|
60
|
-
}): Promise<ComponentPropsRequest[]> {
|
|
61
|
-
const { placeholders = {}, layoutData } = params;
|
|
62
|
-
|
|
63
|
-
// Will be called on first round
|
|
64
|
-
if (!params.requests) {
|
|
65
|
-
params.requests = [];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const renderings = this.flatRenderings(placeholders);
|
|
69
|
-
|
|
70
|
-
const actions = renderings.map(async (r) => {
|
|
71
|
-
// const fetchFunc = (await this.getModule(components, r.componentName))
|
|
72
|
-
// ?.getComponentServerProps;
|
|
73
|
-
|
|
74
|
-
const fetchFunc = ''; // getModule
|
|
75
|
-
|
|
76
|
-
if (fetchFunc) {
|
|
77
|
-
params.requests &&
|
|
78
|
-
params.requests.push({
|
|
79
|
-
// fetch: fetchFunc,
|
|
80
|
-
rendering: r,
|
|
81
|
-
layoutData: layoutData,
|
|
82
|
-
// context,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// If placeholders exist in current rendering
|
|
87
|
-
if (r.placeholders) {
|
|
88
|
-
await this.collectRequests({
|
|
89
|
-
...params,
|
|
90
|
-
placeholders: r.placeholders,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
await Promise.all(actions);
|
|
96
|
-
|
|
97
|
-
return params.requests;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Execute request for component props
|
|
102
|
-
* @param {ComponentPropsRequest[]} requests requests
|
|
103
|
-
* @returns {Promise<ComponentPropsCollection>} requests result
|
|
104
|
-
*/
|
|
105
|
-
protected async execRequests(
|
|
106
|
-
requests: ComponentPropsRequest[]
|
|
107
|
-
): Promise<ComponentPropsCollection> {
|
|
108
|
-
const componentProps: ComponentPropsCollection = {};
|
|
109
|
-
|
|
110
|
-
const promises = requests.map((req) => {
|
|
111
|
-
const { uid } = req.rendering;
|
|
112
|
-
|
|
113
|
-
if (!uid) {
|
|
114
|
-
console.log(
|
|
115
|
-
`Component ${req.rendering.componentName} doesn't have uid, can't store data for this component`
|
|
116
|
-
);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// return req
|
|
121
|
-
// .fetch(req.rendering, req.layoutData /*, req.context*/)
|
|
122
|
-
// .then((result) => {
|
|
123
|
-
// // Set component specific data in componentProps store
|
|
124
|
-
// componentProps[uid] = result;
|
|
125
|
-
// })
|
|
126
|
-
// .catch((error) => {
|
|
127
|
-
// const errLog = `Error during preload data for component ${
|
|
128
|
-
// req.rendering.componentName
|
|
129
|
-
// } (${uid}): ${error.message || error}`;
|
|
130
|
-
|
|
131
|
-
// console.error(chalk.red(errLog));
|
|
132
|
-
|
|
133
|
-
// componentProps[uid] = {
|
|
134
|
-
// error: error.message || errLog,
|
|
135
|
-
// componentName: req.rendering.componentName,
|
|
136
|
-
// };
|
|
137
|
-
// });
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
await Promise.all(promises);
|
|
141
|
-
|
|
142
|
-
return componentProps;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Take renderings from all placeholders and returns a flat array of renderings.
|
|
147
|
-
* @example
|
|
148
|
-
* const placeholders = {
|
|
149
|
-
* x1: [{ uid: 1 }, { uid: 2 }],
|
|
150
|
-
* x2: [{ uid: 11 }, { uid: 22 }]
|
|
151
|
-
* }
|
|
152
|
-
*
|
|
153
|
-
* flatRenderings(placeholders);
|
|
154
|
-
*
|
|
155
|
-
* RESULT: [{ uid: 1 }, { uid: 2 }, { uid: 11 }, { uid: 22 }]
|
|
156
|
-
* @param {PlaceholdersData} placeholders placeholders
|
|
157
|
-
* @returns {ComponentRendering[]} renderings
|
|
158
|
-
*/
|
|
159
|
-
protected flatRenderings(placeholders: PlaceholdersData): ComponentRendering[] {
|
|
160
|
-
const allComponentRenderings: ComponentRendering[] = [];
|
|
161
|
-
const placeholdersArr = Object.values(placeholders);
|
|
162
|
-
|
|
163
|
-
placeholdersArr.forEach((pl) => {
|
|
164
|
-
const renderings = pl as ComponentRendering[];
|
|
165
|
-
allComponentRenderings.push(...renderings);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
return allComponentRenderings;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// private async getModule(
|
|
172
|
-
// components: ComponentMap<AstroContentSdkComponent>,
|
|
173
|
-
// componentName: string
|
|
174
|
-
// ) {
|
|
175
|
-
// const component = components.get(componentName);
|
|
176
|
-
|
|
177
|
-
// if (!component) return null;
|
|
178
|
-
|
|
179
|
-
// //const module = component.dynamicModule ? await component?.dynamicModule?.() : component;
|
|
180
|
-
// const module = component;
|
|
181
|
-
// return module as AstroContentSdkComponent;
|
|
182
|
-
// }
|
|
183
|
-
}
|