Skip to content

Commit 75ea7e4

Browse files
committed
fix(lde): domain props were not applied in lde mode
1 parent ee5d73e commit 75ea7e4

File tree

7 files changed

+161
-6
lines changed

7 files changed

+161
-6
lines changed

ilc/server/tailor/merge-configs.spec.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,4 +961,82 @@ describe('merge configs', () => {
961961
expect(mergeConfigs(registryConfigWithWildcardRoutes, overrideConfig)).to.be.eql(mergedConfig);
962962
});
963963
});
964+
965+
describe('should apply domain props to LDE-only apps', () => {
966+
const domainProps = { appProps: { brandId: 'namecheap' }, cdnUrl: 'https://cdn.namecheap.com' };
967+
const domainSsrProps = { secretKey: 'server-secret' };
968+
969+
const registryConfigWithDomainProps: TransformedRegistryConfig = {
970+
...registryConfig,
971+
domainProps,
972+
domainSsrProps,
973+
};
974+
975+
it('should merge domain props into a new LDE-only app', () => {
976+
const overrideConfig = {
977+
apps: {
978+
'@portal/new-lde-app': {
979+
spaBundle: 'https://localhost:3000/app.js',
980+
ssr: { src: 'https://localhost:3000/ssr' },
981+
props: { appConfig: { lde: true } },
982+
},
983+
},
984+
};
985+
986+
const result = mergeConfigs(registryConfigWithDomainProps, overrideConfig);
987+
988+
expect(result.apps['@portal/new-lde-app'].props).to.deep.equal({
989+
...domainProps,
990+
appConfig: { lde: true },
991+
});
992+
expect(result.apps['@portal/new-lde-app'].ssrProps).to.deep.equal(domainSsrProps);
993+
});
994+
995+
it('should let LDE app props override domain props for the same key', () => {
996+
const overrideConfig = {
997+
apps: {
998+
'@portal/new-lde-app': {
999+
spaBundle: 'https://localhost:3000/app.js',
1000+
props: { appProps: { brandId: 'override-brand' } },
1001+
},
1002+
},
1003+
};
1004+
1005+
const result = mergeConfigs(registryConfigWithDomainProps, overrideConfig);
1006+
1007+
expect(result.apps['@portal/new-lde-app'].props).to.deep.equal({
1008+
...domainProps,
1009+
appProps: { brandId: 'override-brand' },
1010+
});
1011+
});
1012+
1013+
it('should not apply domain props to apps already in the registry', () => {
1014+
const overrideConfig = {
1015+
apps: {
1016+
'@portal/will-change': {
1017+
spaBundle: 'https://localhost:3000/will-change.js',
1018+
},
1019+
},
1020+
};
1021+
1022+
const result = mergeConfigs(registryConfigWithDomainProps, overrideConfig);
1023+
1024+
expect(result.apps['@portal/will-change'].props).to.deep.equal(apps['@portal/will-change'].props);
1025+
});
1026+
1027+
it('should not apply domain props when registry config has no domainProps', () => {
1028+
const overrideConfig = {
1029+
apps: {
1030+
'@portal/new-lde-app': {
1031+
spaBundle: 'https://localhost:3000/app.js',
1032+
props: { foo: 'bar' },
1033+
},
1034+
},
1035+
};
1036+
1037+
const result = mergeConfigs(registryConfig, overrideConfig);
1038+
1039+
expect(result.apps['@portal/new-lde-app'].props).to.deep.equal({ foo: 'bar' });
1040+
});
1041+
});
9641042
});

ilc/server/tailor/merge-configs.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,31 @@ export function mergeConfigs(
6969
)
7070
: original.sharedLibs;
7171

72-
return {
73-
...original,
74-
apps,
75-
routes,
76-
sharedLibs,
77-
};
72+
return applyDomainPropsToLdeApps({ ...original, apps, routes, sharedLibs }, override, original);
73+
}
74+
75+
function applyDomainPropsToLdeApps(
76+
result: TransformedRegistryConfig,
77+
override: OverrideConfig,
78+
original: TransformedRegistryConfig,
79+
): TransformedRegistryConfig {
80+
if (!override.apps || (!result.domainProps && !result.domainSsrProps)) {
81+
return result;
82+
}
83+
84+
const apps = { ...result.apps };
85+
for (const appName of Object.keys(override.apps)) {
86+
if (!original.apps[appName] && apps[appName]) {
87+
const app = { ...apps[appName] };
88+
if (result.domainProps) {
89+
app.props = deepmerge(result.domainProps, app.props ?? {});
90+
}
91+
if (result.domainSsrProps) {
92+
app.ssrProps = deepmerge(result.domainSsrProps, app.ssrProps ?? {});
93+
}
94+
apps[appName] = app;
95+
}
96+
}
97+
98+
return { ...result, apps };
7899
}

ilc/server/tailor/request-fragment.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ module.exports = (filterHeaders, processFragmentResponse, logger) =>
169169
},
170170
});
171171

172+
console.trace(
173+
'[DEBUG domain props] request-fragment attributes.appProps',
174+
attributes.id,
175+
JSON.stringify(attributes.appProps),
176+
);
172177
const reqUrl = makeFragmentUrl({
173178
domain: request.host,
174179
route: currRoute,
@@ -177,6 +182,7 @@ module.exports = (filterHeaders, processFragmentResponse, logger) =>
177182
props: attributes.appProps,
178183
sdkOptions: sdkOptions.toJSON(),
179184
});
185+
console.trace('[DEBUG domain props] request-fragment final URL', reqUrl);
180186

181187
logger.debug(
182188
{

ilc/server/tailor/server-router.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ module.exports = class ServerRouter {
8585
}
8686

8787
ssrOpts.appProps = deepmerge.all([appInfo.props || {}, appInfo.ssrProps || {}, row.props || {}]);
88+
console.trace(
89+
'[DEBUG domain props] server-router getFragmentsContext',
90+
appId,
91+
JSON.stringify({ appProps: ssrOpts.appProps }),
92+
);
8893
ssrOpts.wrapperConf = row.wrapperConf;
8994
ssrOpts.spaBundleUrl = appInfo.spaBundle;
9095

ilc/server/types/RegistryConfig.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,6 @@ export interface RegistryConfig {
7171
sharedLibs: Record<string, string>;
7272
dynamicLibs: Record<string, DynamicLib>;
7373
canonicalDomain?: string;
74+
domainProps?: Record<string, any>;
75+
domainSsrProps?: Record<string, any>;
7476
}

registry/server/config/getConfig.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Tables } from '../db/structure';
66
import settingsService from '../settings/services/SettingsService';
77
import { appendDigest } from '../util/hmac';
88
import { EntityTypes } from '../versioning/interfaces';
9+
import { parseJSON } from '../common/services/json';
910
import { AppRouteDto, transformApps, transformRoutes, transformSharedLibs } from './transformConfig';
1011

1112
export const getConfig: RequestHandler = async (req, res) => {
@@ -38,6 +39,8 @@ export const getConfig: RequestHandler = async (req, res) => {
3839
sharedLibs: {},
3940
dynamicLibs: {},
4041
canonicalDomain: undefined as string | undefined,
42+
domainProps: undefined as Record<string, unknown> | undefined,
43+
domainSsrProps: undefined as Record<string, unknown> | undefined,
4144
};
4245

4346
data.apps = transformApps(apps, routerDomains, sharedProps, domainName);
@@ -62,6 +65,12 @@ export const getConfig: RequestHandler = async (req, res) => {
6265
if (currentDomain?.canonicalDomain) {
6366
data.canonicalDomain = currentDomain.canonicalDomain;
6467
}
68+
if (currentDomain?.props) {
69+
data.domainProps = parseJSON(currentDomain.props) as Record<string, unknown>;
70+
}
71+
if (currentDomain?.ssrProps) {
72+
data.domainSsrProps = parseJSON(currentDomain.ssrProps) as Record<string, unknown>;
73+
}
6574
}
6675

6776
return res.send(data);

registry/tests/config.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ describe('Tests /api/v1/config', () => {
254254
});
255255

256256
expect(response.body.canonicalDomain).to.equal(example.routerDomains.canonicalDomain);
257+
258+
expect(response.body.domainProps).to.deep.equal(example.routerDomains.props);
259+
expect(response.body.domainSsrProps).to.deep.equal(example.routerDomains.ssrProps);
257260
} finally {
258261
routeId && (await req.delete('/api/v1/route/' + routeId));
259262
routeIdWithDomain && (await req.delete('/api/v1/route/' + routeIdWithDomain));
@@ -266,6 +269,37 @@ describe('Tests /api/v1/config', () => {
266269
await req.delete('/api/v1/template/' + example.templates.name).expect(204);
267270
}
268271
});
272+
273+
it('should expose domainProps and domainSsrProps in config response for matching domain', async () => {
274+
let routerDomainsId: number | undefined;
275+
try {
276+
await req.post('/api/v1/template/').send(example.templates).expect(200);
277+
278+
const domain = {
279+
domainName: 'domainprops-test.example.com',
280+
template500: example.templates.name,
281+
props: { appProps: { brandId: 'namecheap' } },
282+
ssrProps: { secretKey: 'server-secret' },
283+
};
284+
285+
const res = await req.post('/api/v1/router_domains/').send(domain).expect(200);
286+
routerDomainsId = res.body.id;
287+
288+
const response = await req.get('/api/v1/config').query({ domainName: domain.domainName }).expect(200);
289+
290+
expect(response.body.domainProps).to.deep.equal(domain.props);
291+
expect(response.body.domainSsrProps).to.deep.equal(domain.ssrProps);
292+
} finally {
293+
routerDomainsId && (await req.delete('/api/v1/router_domains/' + routerDomainsId));
294+
await req.delete('/api/v1/template/' + example.templates.name);
295+
}
296+
});
297+
298+
it('should not expose domainProps and domainSsrProps when no domainName is provided', async () => {
299+
const response = await req.get('/api/v1/config').expect(200);
300+
expect(response.body.domainProps).to.be.undefined;
301+
expect(response.body.domainSsrProps).to.be.undefined;
302+
});
269303
});
270304

271305
describe('Authentication / Authorization', () => {

0 commit comments

Comments
 (0)