fix(gateway): anchor remaining config loads (#1138)
Co-Authored-By: Claude Haiku 4.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
2d5a8c81ec
commit
bd0ef2ab25
@@ -5,11 +5,13 @@ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
||||
import * as nodeUrl from 'node:url';
|
||||
import { MODULE_METADATA } from '@nestjs/common/constants.js';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import type { MosaicConfig } from '@mosaicstack/config';
|
||||
|
||||
interface ComposedModuleGraph {
|
||||
imports: readonly unknown[];
|
||||
federationModule: unknown;
|
||||
bootLogLines: readonly string[];
|
||||
mosaicConfig: MosaicConfig;
|
||||
}
|
||||
|
||||
type StorageTier = 'local' | 'standalone' | 'federated';
|
||||
@@ -95,6 +97,23 @@ async function writeFixture(path: string, contents: string, tempRoot: string): P
|
||||
await writeFile(path, contents, 'utf8');
|
||||
}
|
||||
|
||||
interface ConfigModuleProvider {
|
||||
provide: string;
|
||||
useFactory: () => MosaicConfig;
|
||||
}
|
||||
|
||||
function isConfigModuleProvider(value: unknown): value is ConfigModuleProvider {
|
||||
if (typeof value !== 'object' || value === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!('provide' in value) || typeof value.provide !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 'useFactory' in value && typeof value.useFactory === 'function';
|
||||
}
|
||||
|
||||
function singleBootLogLine(bootLogLines: readonly string[]): string {
|
||||
expect(bootLogLines).toHaveLength(1);
|
||||
const [bootLogLine] = bootLogLines;
|
||||
@@ -229,12 +248,28 @@ async function loadModuleGraphFromDotenv(
|
||||
throw new Error('AppModule imports metadata is not an array');
|
||||
}
|
||||
|
||||
const { ConfigModule, MOSAIC_CONFIG } = await import('./config/config.module.js');
|
||||
const providers: unknown = Reflect.getMetadata(MODULE_METADATA.PROVIDERS, ConfigModule);
|
||||
|
||||
if (!Array.isArray(providers)) {
|
||||
throw new Error('ConfigModule providers metadata is not an array');
|
||||
}
|
||||
|
||||
const configProvider = providers
|
||||
.filter(isConfigModuleProvider)
|
||||
.find((provider: ConfigModuleProvider): boolean => provider.provide === MOSAIC_CONFIG);
|
||||
|
||||
if (!configProvider) {
|
||||
throw new Error('MOSAIC_CONFIG provider factory not found');
|
||||
}
|
||||
|
||||
return {
|
||||
imports,
|
||||
federationModule: FederationModule,
|
||||
bootLogLines: consoleInfoSpy.mock.calls.map((args: readonly unknown[]): string =>
|
||||
args.map((value: unknown): string => String(value)).join(' '),
|
||||
),
|
||||
mosaicConfig: configProvider.useFactory(),
|
||||
};
|
||||
} finally {
|
||||
cwdSpy?.mockRestore();
|
||||
@@ -496,4 +531,57 @@ describe('AppModule federation gating', (): void => {
|
||||
},
|
||||
MODULE_IMPORT_TIMEOUT_MS,
|
||||
);
|
||||
|
||||
it(
|
||||
'MOSAIC_CONFIG provider ignores an ambient cwd/mosaic.config.json config',
|
||||
async (): Promise<void> => {
|
||||
const graph = await loadModuleGraphFromDotenv({
|
||||
rootTier: 'local',
|
||||
setup: async (fixture: ModuleGraphFixture): Promise<void> => {
|
||||
await writeFixture(
|
||||
join(fixture.cwdPath, 'mosaic.config.json'),
|
||||
JSON.stringify({
|
||||
tier: 'federated',
|
||||
storage: {
|
||||
type: 'postgres',
|
||||
url: 'postgresql://ambient-attacker.invalid/mosaic',
|
||||
enableVector: true,
|
||||
},
|
||||
queue: { type: 'bullmq' },
|
||||
memory: { type: 'pgvector' },
|
||||
}),
|
||||
fixture.tempRoot,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
expect(graph.mosaicConfig.tier).toBe('local');
|
||||
expect(graph.mosaicConfig.storage).not.toEqual(
|
||||
expect.objectContaining({ url: 'postgresql://ambient-attacker.invalid/mosaic' }),
|
||||
);
|
||||
},
|
||||
MODULE_IMPORT_TIMEOUT_MS,
|
||||
);
|
||||
|
||||
it(
|
||||
'MOSAIC_CONFIG provider resolves from the anchored monorepo-root mosaic.config.json',
|
||||
async (): Promise<void> => {
|
||||
const graph = await loadModuleGraphFromDotenv({
|
||||
rootTier: 'local',
|
||||
setup: async (fixture: ModuleGraphFixture): Promise<void> => {
|
||||
await writeFixture(
|
||||
fixture.monorepoRootConfigPath,
|
||||
configJson('federated'),
|
||||
fixture.tempRoot,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
expect(graph.mosaicConfig.tier).toBe('federated');
|
||||
expect(graph.mosaicConfig.storage).toEqual(
|
||||
expect.objectContaining({ url: 'postgresql://fixture.invalid/mosaic' }),
|
||||
);
|
||||
},
|
||||
MODULE_IMPORT_TIMEOUT_MS,
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user