Skip to content

Commit cb555ff

Browse files
arbrandesclaude
andcommitted
feat: support commonAppConfig site config option
Merge commonAppConfig into the output of getAppConfig() at the lowest priority, so app-specific config values always take precedence. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 297b12c commit cb555ff

3 files changed

Lines changed: 61 additions & 1 deletion

File tree

runtime/config/index.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { CONFIG_CHANGED } from '../constants';
22
import * as subscriptions from '../subscriptions';
33
import {
4+
addAppConfigs,
5+
getAppConfig,
46
getSiteConfig,
57
mergeSiteConfig,
68
setSiteConfig,
@@ -295,4 +297,57 @@ describe('mergeSiteConfig', () => {
295297
expect(getSiteConfig().apps![0].config!.ORIGINAL).toBe('value');
296298
});
297299
});
300+
301+
describe('getAppConfig with commonAppConfig', () => {
302+
it('should return commonAppConfig values for an app with no config', () => {
303+
setSiteConfig({
304+
...defaultSiteConfig,
305+
commonAppConfig: { COMMON_KEY: 'common-value' },
306+
apps: [{ appId: 'test-app' }],
307+
});
308+
addAppConfigs();
309+
310+
const config = getAppConfig('test-app');
311+
expect(config).toEqual({ COMMON_KEY: 'common-value' });
312+
});
313+
314+
it('should let app-specific config override commonAppConfig', () => {
315+
setSiteConfig({
316+
...defaultSiteConfig,
317+
commonAppConfig: { SHARED: 'common', COMMON_ONLY: 'yes' },
318+
apps: [{ appId: 'test-app', config: { SHARED: 'app-specific', APP_ONLY: 'yes' } }],
319+
});
320+
addAppConfigs();
321+
322+
const config = getAppConfig('test-app');
323+
expect(config).toEqual({
324+
SHARED: 'app-specific',
325+
COMMON_ONLY: 'yes',
326+
APP_ONLY: 'yes',
327+
});
328+
});
329+
330+
it('should return app config as-is when commonAppConfig is not set', () => {
331+
setSiteConfig({
332+
...defaultSiteConfig,
333+
apps: [{ appId: 'test-app', config: { VALUE: 'test' } }],
334+
});
335+
addAppConfigs();
336+
337+
const config = getAppConfig('test-app');
338+
expect(config).toEqual({ VALUE: 'test' });
339+
});
340+
341+
it('should deep merge commonAppConfig with app config', () => {
342+
setSiteConfig({
343+
...defaultSiteConfig,
344+
commonAppConfig: { NESTED: { a: 1, b: 2 } },
345+
apps: [{ appId: 'test-app', config: { NESTED: { b: 3, c: 4 } } }],
346+
});
347+
addAppConfigs();
348+
349+
const config = getAppConfig('test-app');
350+
expect(config).toEqual({ NESTED: { a: 1, b: 3, c: 4 } });
351+
});
352+
});
298353
});

runtime/config/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,11 @@ export function addAppConfigs() {
272272
}
273273

274274
export function getAppConfig(id: string) {
275-
return appConfigs[id];
275+
const { commonAppConfig } = getSiteConfig();
276+
if (commonAppConfig === undefined) {
277+
return appConfigs[id];
278+
}
279+
return merge({}, commonAppConfig, appConfigs[id]);
276280
}
277281

278282
export function mergeAppConfig(id: string, newAppConfig: AppConfig) {

types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export interface OptionalSiteConfig {
5959
externalRoutes: ExternalRoute[],
6060
externalLinkUrlOverrides: string[],
6161
runtimeConfigJsonUrl: string | null,
62+
commonAppConfig: AppConfig,
6263
headerLogoImageUrl: string,
6364

6465
// Theme

0 commit comments

Comments
 (0)