feat: Support default mainModulePath when creating App

This commit is contained in:
Joachim Van Herwegen 2023-12-14 13:59:04 +01:00
parent 648ce1fba8
commit c6ec45c7c0
2 changed files with 48 additions and 9 deletions

View File

@ -36,13 +36,17 @@ const ENV_VAR_PREFIX = 'CSS';
export interface AppRunnerInput { export interface AppRunnerInput {
/** /**
* Properties that will be used when building the Components.js manager. * Properties that will be used when building the Components.js manager.
* Sets `typeChecking` to false by default as the server components will result in errors otherwise. * Default values:
* - `typeChecking`: `false`, as the server components would otherwise error.
* - `mainModulePath`: `@css:`, which resolves to the directory of the CSS package.
* This is useful for packages that depend on the CSS
* but do not create any new modules themselves.
*/ */
loaderProperties: IComponentsManagerBuilderOptions<App>; loaderProperties?: Partial<IComponentsManagerBuilderOptions<App>>;
/** /**
* Path to the server config file(s). * Path to the server config file(s). Defaults to `@css:config/default.json`.
*/ */
config: string | string[]; config?: string | string[];
/** /**
* Values to apply to the Components.js variables. * Values to apply to the Components.js variables.
* These are the variables CLI values will be converted to. * These are the variables CLI values will be converted to.
@ -87,14 +91,19 @@ export class AppRunner {
* *
* @param input - All values necessary to configure the server. * @param input - All values necessary to configure the server.
*/ */
public async create(input: AppRunnerInput): Promise<App> { public async create(input: AppRunnerInput = {}): Promise<App> {
const loaderProperties = { const loaderProperties = {
typeChecking: false, typeChecking: false,
mainModulePath: '@css:',
dumpErrorState: false,
...input.loaderProperties, ...input.loaderProperties,
}; };
// Expand mainModulePath as needed
loaderProperties.mainModulePath = resolveAssetPath(loaderProperties.mainModulePath);
// Potentially expand file paths as needed // Potentially expand config paths as needed
const configs = (Array.isArray(input.config) ? input.config : [ input.config ]).map(resolveAssetPath); let configs = input.config ?? [ '@css:config/default.json' ];
configs = (Array.isArray(configs) ? configs : [ configs ]).map(resolveAssetPath);
let componentsManager: ComponentsManager<any>; let componentsManager: ComponentsManager<any>;
try { try {
@ -178,8 +187,8 @@ export class AppRunner {
const params = await yargv.parse(); const params = await yargv.parse();
const loaderProperties: IComponentsManagerBuilderOptions<App> = { const loaderProperties: AppRunnerInput['loaderProperties'] = {
mainModulePath: resolveAssetPath(params.mainModulePath), mainModulePath: params.mainModulePath,
logLevel: params.loggingLevel, logLevel: params.loggingLevel,
}; };

View File

@ -206,6 +206,30 @@ describe('AppRunner', (): void => {
expect(app.clusterManager.isSingleThreaded()).toBeFalsy(); expect(app.clusterManager.isSingleThreaded()).toBeFalsy();
}); });
it('has several defaults.', async(): Promise<void> => {
const createdApp = await new AppRunner().create();
expect(createdApp).toBe(app);
expect(ComponentsManager.build).toHaveBeenCalledTimes(1);
expect(ComponentsManager.build).toHaveBeenCalledWith({
mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false,
dumpErrorState: false,
});
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register)
.toHaveBeenCalledWith(joinFilePath(__dirname, '/../../../config/default.json'));
expect(manager.instantiate).toHaveBeenCalledTimes(2);
expect(manager.instantiate).toHaveBeenNthCalledWith(1, 'urn:solid-server-app-setup:default:CliResolver', {});
expect(manager.instantiate)
.toHaveBeenNthCalledWith(2, 'urn:solid-server:default:App', { variables: {}});
expect(shorthandResolver.handleSafe).toHaveBeenCalledTimes(1);
expect(shorthandResolver.handleSafe).toHaveBeenLastCalledWith({});
expect(cliExtractor.handleSafe).toHaveBeenCalledTimes(0);
expect(app.start).toHaveBeenCalledTimes(0);
expect(app.clusterManager.isSingleThreaded()).toBeFalsy();
});
it('throws an error if threading issues are detected with 1 class.', async(): Promise<void> => { it('throws an error if threading issues are detected with 1 class.', async(): Promise<void> => {
listSingleThreadedComponentsMock.mockImplementationOnce((): string[] => [ 'ViolatingClass' ]); listSingleThreadedComponentsMock.mockImplementationOnce((): string[] => [ 'ViolatingClass' ]);
const variables = { const variables = {
@ -344,6 +368,7 @@ describe('AppRunner', (): void => {
logLevel: 'info', logLevel: 'info',
mainModulePath: joinFilePath(__dirname, '../../../'), mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false, typeChecking: false,
dumpErrorState: false,
}); });
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register) expect(manager.configRegistry.register)
@ -375,6 +400,7 @@ describe('AppRunner', (): void => {
logLevel: 'info', logLevel: 'info',
mainModulePath: joinFilePath(__dirname, '../../../'), mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false, typeChecking: false,
dumpErrorState: false,
}); });
expect(manager.configRegistry.register).toHaveBeenCalledTimes(2); expect(manager.configRegistry.register).toHaveBeenCalledTimes(2);
expect(manager.configRegistry.register).toHaveBeenNthCalledWith(1, '/var/cwd/config1.json'); expect(manager.configRegistry.register).toHaveBeenNthCalledWith(1, '/var/cwd/config1.json');
@ -419,6 +445,7 @@ describe('AppRunner', (): void => {
logLevel: 'debug', logLevel: 'debug',
mainModulePath: '/var/cwd/module/path', mainModulePath: '/var/cwd/module/path',
typeChecking: false, typeChecking: false,
dumpErrorState: false,
}); });
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register).toHaveBeenCalledWith('/var/cwd/myconfig.json'); expect(manager.configRegistry.register).toHaveBeenCalledWith('/var/cwd/myconfig.json');
@ -569,6 +596,7 @@ describe('AppRunner', (): void => {
logLevel: 'info', logLevel: 'info',
mainModulePath: joinFilePath(__dirname, '../../../'), mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false, typeChecking: false,
dumpErrorState: false,
}); });
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register) expect(manager.configRegistry.register)
@ -600,6 +628,7 @@ describe('AppRunner', (): void => {
logLevel: 'debug', logLevel: 'debug',
mainModulePath: joinFilePath(__dirname, '../../../'), mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false, typeChecking: false,
dumpErrorState: false,
}); });
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register) expect(manager.configRegistry.register)
@ -760,6 +789,7 @@ describe('AppRunner', (): void => {
logLevel: 'info', logLevel: 'info',
mainModulePath: joinFilePath(__dirname, '../../../'), mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false, typeChecking: false,
dumpErrorState: false,
}); });
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register) expect(manager.configRegistry.register)