diff --git a/src/init/AppRunner.ts b/src/init/AppRunner.ts index a91d08c81..0f2f701c1 100644 --- a/src/init/AppRunner.ts +++ b/src/init/AppRunner.ts @@ -36,13 +36,17 @@ const ENV_VAR_PREFIX = 'CSS'; export interface AppRunnerInput { /** * 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; + loaderProperties?: Partial>; /** - * 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. * 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. */ - public async create(input: AppRunnerInput): Promise { + public async create(input: AppRunnerInput = {}): Promise { const loaderProperties = { typeChecking: false, + mainModulePath: '@css:', + dumpErrorState: false, ...input.loaderProperties, }; + // Expand mainModulePath as needed + loaderProperties.mainModulePath = resolveAssetPath(loaderProperties.mainModulePath); - // Potentially expand file paths as needed - const configs = (Array.isArray(input.config) ? input.config : [ input.config ]).map(resolveAssetPath); + // Potentially expand config paths as needed + let configs = input.config ?? [ '@css:config/default.json' ]; + configs = (Array.isArray(configs) ? configs : [ configs ]).map(resolveAssetPath); let componentsManager: ComponentsManager; try { @@ -178,8 +187,8 @@ export class AppRunner { const params = await yargv.parse(); - const loaderProperties: IComponentsManagerBuilderOptions = { - mainModulePath: resolveAssetPath(params.mainModulePath), + const loaderProperties: AppRunnerInput['loaderProperties'] = { + mainModulePath: params.mainModulePath, logLevel: params.loggingLevel, }; diff --git a/test/unit/init/AppRunner.test.ts b/test/unit/init/AppRunner.test.ts index c99b0eea0..2013cd7d9 100644 --- a/test/unit/init/AppRunner.test.ts +++ b/test/unit/init/AppRunner.test.ts @@ -206,6 +206,30 @@ describe('AppRunner', (): void => { expect(app.clusterManager.isSingleThreaded()).toBeFalsy(); }); + it('has several defaults.', async(): Promise => { + 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 => { listSingleThreadedComponentsMock.mockImplementationOnce((): string[] => [ 'ViolatingClass' ]); const variables = { @@ -344,6 +368,7 @@ describe('AppRunner', (): void => { logLevel: 'info', mainModulePath: joinFilePath(__dirname, '../../../'), typeChecking: false, + dumpErrorState: false, }); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register) @@ -375,6 +400,7 @@ describe('AppRunner', (): void => { logLevel: 'info', mainModulePath: joinFilePath(__dirname, '../../../'), typeChecking: false, + dumpErrorState: false, }); expect(manager.configRegistry.register).toHaveBeenCalledTimes(2); expect(manager.configRegistry.register).toHaveBeenNthCalledWith(1, '/var/cwd/config1.json'); @@ -419,6 +445,7 @@ describe('AppRunner', (): void => { logLevel: 'debug', mainModulePath: '/var/cwd/module/path', typeChecking: false, + dumpErrorState: false, }); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register).toHaveBeenCalledWith('/var/cwd/myconfig.json'); @@ -569,6 +596,7 @@ describe('AppRunner', (): void => { logLevel: 'info', mainModulePath: joinFilePath(__dirname, '../../../'), typeChecking: false, + dumpErrorState: false, }); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register) @@ -600,6 +628,7 @@ describe('AppRunner', (): void => { logLevel: 'debug', mainModulePath: joinFilePath(__dirname, '../../../'), typeChecking: false, + dumpErrorState: false, }); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register) @@ -760,6 +789,7 @@ describe('AppRunner', (): void => { logLevel: 'info', mainModulePath: joinFilePath(__dirname, '../../../'), typeChecking: false, + dumpErrorState: false, }); expect(manager.configRegistry.register).toHaveBeenCalledTimes(1); expect(manager.configRegistry.register)