diff --git a/packages/tooling/openmrs/src/cli.ts b/packages/tooling/openmrs/src/cli.ts index 7e126c1ac..a626d87a8 100644 --- a/packages/tooling/openmrs/src/cli.ts +++ b/packages/tooling/openmrs/src/cli.ts @@ -216,6 +216,7 @@ yargs.command( describe: 'The path to a frontend configuration file. Can be used multiple times. The file is copied directly into the build directory.', type: 'array', + coerce: (arg: Array) => arg.map((p) => resolve(process.cwd(), p)), }) .option('importmap', { default: undefined, @@ -237,9 +238,9 @@ yargs.command( }), async (args) => runCommand('runBuild', { - configUrls: args['config-url'], - configPaths: args['config-path'].map((p) => resolve(process.cwd(), p)), ...args, + configUrls: args['config-url'], + configPaths: args['config-path'], }), ); @@ -263,14 +264,22 @@ yargs.command( }) .option('config', { default: ['spa-build-config.json'], - description: 'Path to a SPA build config JSON.', + description: 'Path to a SPA assemble config JSON.', + type: 'array', + coerce: (arg: Array) => arg.map((p) => resolve(process.cwd(), p)), + }) + .option('config-file', { + default: [], + describe: + 'Reference to a frontend configuration file. Can be used multiple times. Configurations are merged in the order specified into openmrs-config.json.', type: 'array', coerce: (arg: Array) => arg.map((p) => resolve(process.cwd(), p)), }) - .option('hash-importmap', { + .option('hash-files', { default: false, + alias: ['hasn', 'hash-importmap'], description: - 'Determines whether to include a content-specific hash for the generated importmap. This is useful if you want to be able to cache the importmap.', + 'Determines whether to include a content-specific hash for the generated JSON files. This is useful if you want to be able to cache those files.', type: 'boolean', }) .option('fresh', { @@ -295,7 +304,7 @@ yargs.command( 'The source of the frontend modules to assemble. `config` uses a configuration file specified via `--config`. `survey` starts an interactive command-line survey.', type: 'string', }), - (args) => runCommand('runAssemble', args), + (args) => runCommand('runAssemble', { ...args, configFiles: args['config-file'] }), ); yargs.command( @@ -326,7 +335,7 @@ yargs.command( yargs .epilog( - 'The SPA build config JSON is a JSON file, typically `frontend.json`, which defines parameters for the `build` and `assemble` ' + + 'The SPA assemble config JSON is a JSON file, typically `frontend.json`, which defines parameters for the `build` and `assemble` ' + 'commands. The keys used by `build` are:\n' + ' `apiUrl`, `spaPath`, `configPaths`, `configUrls`, `importmap`, `pageTitle`, and `supportOffline`;\n' + 'each of which is equivalent to the corresponding command line argument (see `openmrs build --help`). ' + diff --git a/packages/tooling/openmrs/src/commands/assemble.ts b/packages/tooling/openmrs/src/commands/assemble.ts index 14ddf1a7a..293ee46d9 100644 --- a/packages/tooling/openmrs/src/commands/assemble.ts +++ b/packages/tooling/openmrs/src/commands/assemble.ts @@ -8,6 +8,7 @@ import axios from 'axios'; import npmRegistryFetch from 'npm-registry-fetch'; import pacote from 'pacote'; import semver from 'semver'; +import { merge } from 'lodash-es'; import { contentHash, logInfo, logWarn, untar } from '../utils'; import { getNpmRegistryConfiguration } from '../utils/npmConfig'; @@ -18,7 +19,8 @@ export interface AssembleArgs { mode: string; config: Array; registry?: string; - hashImportmap: boolean; + configFiles: Array; + hashFiles: boolean; fresh: boolean; buildRoutes: boolean; manifest: boolean; @@ -265,7 +267,7 @@ export async function runAssemble(args: AssembleArgs) { const appRoutes = resolve(args.target, dirName, 'routes.json'); if (existsSync(appRoutes)) { try { - routes[esmName] = JSON.parse((await readFile(appRoutes)).toString()); + routes[esmName] = JSON.parse(await readFile(appRoutes, 'utf8')); routes[esmName]['version'] = version; } catch (e) { logWarn(`Error while processing routes for ${esmName} using ${appRoutes}: ${e}`); @@ -286,19 +288,38 @@ export async function runAssemble(args: AssembleArgs) { ); await writeFile( - resolve(args.target, `importmap${args.hashImportmap ? '.' + contentHash(importmap) : ''}.json`), + resolve(args.target, `importmap${args.hashFiles ? '.' + contentHash(importmap) : ''}.json`), JSON.stringify(importmap), 'utf8', ); if (args.buildRoutes) { await writeFile( - resolve(args.target, `routes.registry${args.hashImportmap ? '.' + contentHash(routes) : ''}.json`), + resolve(args.target, `routes.registry${args.hashFiles ? '.' + contentHash(routes) : ''}.json`), JSON.stringify(routes), 'utf-8', ); } + if (args.configFiles && args.configFiles.length > 0) { + const assembledConfig = args.configFiles.reduce(async (merged, file) => { + try { + const config = JSON.parse((await readFile(file), 'utf8')); + return merge(merged, config); + } catch (e) { + logWarn(`Error while processing config file ${file}: ${e}`); + } + + return merged; + }, {}); + + await writeFile( + resolve(args.target, `openmrs-config${args.hashFiles ? '.' + contentHash(assembledConfig) : ''}.json`), + JSON.stringify(assembledConfig), + 'utf8', + ); + } + if (args.manifest) { await writeFile(resolve(args.target, 'spa-assemble-config.json'), JSON.stringify(versionManifest), 'utf8'); }