@medplum/cli 2.0.15 → 2.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
+ var commander = require('commander');
4
5
  var core = require('@medplum/core');
5
- var child_process = require('child_process');
6
- var dotenv = require('dotenv');
7
6
  var fs = require('fs');
8
- var http = require('http');
9
- var fetch = require('node-fetch');
10
7
  var os = require('os');
11
8
  var path = require('path');
9
+ var dotenv = require('dotenv');
10
+ var child_process = require('child_process');
11
+ var http = require('http');
12
12
 
13
13
  class FileSystemStorage extends core.ClientStorage {
14
14
  constructor() {
@@ -46,69 +46,178 @@ class FileSystemStorage extends core.ClientStorage {
46
46
  }
47
47
  }
48
48
 
49
- const clientId = 'medplum-cli';
50
- const redirectUri = 'http://localhost:9615';
51
- async function main(medplum, argv) {
52
- if (argv.length < 3) {
53
- console.log('Usage: medplum <command>');
49
+ function prettyPrint(input) {
50
+ console.log(JSON.stringify(input, null, 2));
51
+ }
52
+ async function saveBot(medplum, botConfig, bot) {
53
+ const code = readFileContents(botConfig.source);
54
+ if (!code) {
54
55
  return;
55
56
  }
56
- // Legacy support for MEDPLUM_CLIENT_ID and MEDPLUM_CLIENT_SECRET environment variables
57
- const clientId = process.env['MEDPLUM_CLIENT_ID'];
58
- const clientSecret = process.env['MEDPLUM_CLIENT_SECRET'];
59
- if (clientId && clientSecret) {
60
- await medplum.startClientLogin(clientId, clientSecret);
61
- }
62
57
  try {
63
- const command = argv[2].toLowerCase();
64
- switch (command) {
65
- //
66
- // Auth commands
67
- //
68
- case 'login':
69
- await startLogin(medplum);
70
- break;
71
- case 'whoami':
72
- printMe(medplum);
73
- break;
74
- //
75
- // REST commands
76
- //
77
- case 'delete':
78
- prettyPrint(await medplum.delete(cleanUrl(argv[3])));
79
- break;
80
- case 'get':
81
- prettyPrint(await medplum.get(cleanUrl(argv[3])));
82
- break;
83
- case 'patch':
84
- prettyPrint(await medplum.patch(cleanUrl(argv[3]), parseBody(argv[4])));
85
- break;
86
- case 'post':
87
- prettyPrint(await medplum.post(cleanUrl(argv[3]), parseBody(argv[4])));
88
- break;
89
- case 'put':
90
- prettyPrint(await medplum.put(cleanUrl(argv[3]), parseBody(argv[4])));
91
- break;
92
- //
93
- // Bot commands
94
- //
95
- case 'save-bot':
96
- await runBotCommands(medplum, argv, ['save']);
97
- break;
98
- case 'deploy-bot':
99
- await runBotCommands(medplum, argv, ['save', 'deploy']);
100
- break;
101
- case 'create-bot':
102
- await createBot(medplum, argv);
103
- break;
104
- default:
105
- console.log(`Unknown command: ${command}`);
58
+ console.log('Update bot code.....');
59
+ const updateResult = await medplum.updateResource({
60
+ ...bot,
61
+ code,
62
+ });
63
+ if (!updateResult) {
64
+ console.log('Bot not modified');
65
+ }
66
+ else {
67
+ console.log('Success! New bot version: ' + updateResult.meta?.versionId);
106
68
  }
107
69
  }
108
70
  catch (err) {
109
- console.error('Error: ' + core.normalizeErrorString(err));
71
+ console.log('Update error: ', err);
110
72
  }
111
73
  }
74
+ async function deployBot(medplum, botConfig, bot) {
75
+ const code = readFileContents(botConfig.dist ?? botConfig.source);
76
+ if (!code) {
77
+ return;
78
+ }
79
+ try {
80
+ console.log('Deploying bot...');
81
+ const deployResult = (await medplum.post(medplum.fhirUrl('Bot', bot.id, '$deploy'), {
82
+ code,
83
+ }));
84
+ console.log('Deploy result: ' + deployResult.issue?.[0]?.details?.text);
85
+ }
86
+ catch (err) {
87
+ console.log('Deploy error: ', err);
88
+ }
89
+ }
90
+ async function createBot(medplum, argv) {
91
+ if (argv.length < 4) {
92
+ console.log(`Error: command needs to be npx medplum <new-bot-name> <project-id> <source-file> <dist-file>`);
93
+ return;
94
+ }
95
+ const botName = argv[0];
96
+ const projectId = argv[1];
97
+ const sourceFile = argv[2];
98
+ const distFile = argv[3];
99
+ try {
100
+ const body = {
101
+ name: botName,
102
+ description: '',
103
+ };
104
+ const newBot = await medplum.post('admin/projects/' + projectId + '/bot', body);
105
+ const bot = await medplum.readResource('Bot', newBot.id);
106
+ const botConfig = {
107
+ name: botName,
108
+ id: newBot.id,
109
+ source: sourceFile,
110
+ dist: distFile,
111
+ };
112
+ await saveBot(medplum, botConfig, bot);
113
+ console.log(`Success! Bot created: ${bot.id}`);
114
+ addBotToConfig(botConfig);
115
+ }
116
+ catch (err) {
117
+ console.log('Error while creating new bot: ' + err);
118
+ }
119
+ }
120
+ function readBotConfigs(botName) {
121
+ const regExBotName = new RegExp('^' + escapeRegex(botName).replace(/\\\*/g, '.*') + '$');
122
+ const botConfigs = readConfig()?.bots?.filter((b) => regExBotName.test(b.name));
123
+ if (!botConfigs) {
124
+ return [];
125
+ }
126
+ return botConfigs;
127
+ }
128
+ function readConfig() {
129
+ const content = readFileContents('medplum.config.json');
130
+ if (!content) {
131
+ return undefined;
132
+ }
133
+ return JSON.parse(content);
134
+ }
135
+ function readFileContents(fileName) {
136
+ const path$1 = path.resolve(process.cwd(), fileName);
137
+ if (!fs.existsSync(path$1)) {
138
+ console.log('Error: File does not exist: ' + path$1);
139
+ return '';
140
+ }
141
+ return fs.readFileSync(path$1, 'utf8');
142
+ }
143
+ function addBotToConfig(botConfig) {
144
+ const config = readConfig();
145
+ config?.bots?.push(botConfig);
146
+ fs.writeFile('medplum.config.json', JSON.stringify(config), () => {
147
+ console.log(`Bot added to config: ${botConfig.id}`);
148
+ });
149
+ }
150
+ function escapeRegex(str) {
151
+ return str.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
152
+ }
153
+
154
+ const bot = new commander.Command('bot');
155
+ // Commands to deprecate
156
+ const saveBotDeprecate = new commander.Command('save-bot');
157
+ const deployBotDeprecate = new commander.Command('deploy-bot');
158
+ const createBotDeprecate = new commander.Command('create-bot');
159
+ bot
160
+ .command('save')
161
+ .description('Saving the bot')
162
+ .argument('<botName>')
163
+ .action(async (botName) => {
164
+ await botWrapper(exports.medplum, botName);
165
+ });
166
+ bot
167
+ .command('deploy')
168
+ .description('Deploy the app to AWS')
169
+ .argument('<botName>')
170
+ .action(async (botName) => {
171
+ await botWrapper(exports.medplum, botName, true);
172
+ });
173
+ bot
174
+ .command('create')
175
+ .arguments('<botName> <projectId> <sourceFile> <distFile>')
176
+ .description('Creating a bot')
177
+ .action(async (botName, projectId, sourceFile, distFile) => {
178
+ await createBot(exports.medplum, [botName, projectId, sourceFile, distFile]);
179
+ });
180
+ async function botWrapper(medplum, botName, deploy = false) {
181
+ const botConfigs = readBotConfigs(botName);
182
+ for (const botConfig of botConfigs) {
183
+ const bot = await medplum.readResource('Bot', botConfig.id);
184
+ await saveBot(medplum, botConfig, bot);
185
+ if (deploy) {
186
+ await deployBot(medplum, botConfig, bot);
187
+ }
188
+ }
189
+ console.log(`Number of bots deployed: ${botConfigs.length}`);
190
+ }
191
+ // Deprecate bot commands
192
+ saveBotDeprecate
193
+ .description('Saves the bot')
194
+ .argument('<botName>')
195
+ .action(async (botName) => {
196
+ await botWrapper(exports.medplum, botName);
197
+ });
198
+ deployBotDeprecate
199
+ .description('Deploy the bot to AWS')
200
+ .argument('<botName>')
201
+ .action(async (botName) => {
202
+ await botWrapper(exports.medplum, botName, true);
203
+ });
204
+ createBotDeprecate
205
+ .arguments('<botName> <projectId> <sourceFile> <distFile>')
206
+ .description('Creates and saves the bot')
207
+ .action(async (botName, projectId, sourceFile, distFile) => {
208
+ await createBot(exports.medplum, [botName, projectId, sourceFile, distFile]);
209
+ });
210
+
211
+ const clientId = 'medplum-cli';
212
+ const redirectUri = 'http://localhost:9615';
213
+ const login = new commander.Command('login');
214
+ const whoami = new commander.Command('whoami');
215
+ login.action(async () => {
216
+ await startLogin(exports.medplum);
217
+ });
218
+ whoami.action(() => {
219
+ printMe(exports.medplum);
220
+ });
112
221
  async function startLogin(medplum) {
113
222
  await startWebServer(medplum);
114
223
  const loginUrl = new URL('/oauth2/authorize', medplum.getBaseUrl());
@@ -181,15 +290,41 @@ function printMe(medplum) {
181
290
  console.log('Not logged in');
182
291
  }
183
292
  }
184
- function cleanUrl(input) {
185
- const knownPrefixes = ['admin/', 'auth/', 'fhir/R4'];
186
- if (knownPrefixes.some((p) => input.startsWith(p))) {
187
- // If the URL starts with a known prefix, return it as-is
188
- return input;
293
+
294
+ const deleteObject = new commander.Command('delete');
295
+ const get = new commander.Command('get');
296
+ const patch = new commander.Command('patch');
297
+ const post = new commander.Command('post');
298
+ const put = new commander.Command('put');
299
+ deleteObject.argument('<url>', 'Resource/$id').action(async (url) => {
300
+ prettyPrint(await exports.medplum.delete(cleanUrl(url)));
301
+ });
302
+ get
303
+ .argument('<url>', 'Resource/$id')
304
+ .option('--as-transaction', 'Print out the bundle as a transaction type')
305
+ .action(async (url, options) => {
306
+ try {
307
+ const response = await exports.medplum.get(cleanUrl(url));
308
+ if (options.asTransaction) {
309
+ prettyPrint(core.convertToTransactionBundle(response));
310
+ }
311
+ else {
312
+ prettyPrint(response);
313
+ }
189
314
  }
190
- // Otherwise, default to FHIR
191
- return 'fhir/R4/' + input;
192
- }
315
+ catch (err) {
316
+ console.log(err);
317
+ }
318
+ });
319
+ patch.arguments('<url> <body>').action(async (url, body) => {
320
+ prettyPrint(await exports.medplum.patch(cleanUrl(url), parseBody(body)));
321
+ });
322
+ post.arguments('<url> <body>').action(async (url, body) => {
323
+ prettyPrint(await exports.medplum.post(cleanUrl(url), parseBody(body)));
324
+ });
325
+ put.arguments('<url> <body>').action(async (url, body) => {
326
+ prettyPrint(await exports.medplum.put(cleanUrl(url), parseBody(body)));
327
+ });
193
328
  function parseBody(input) {
194
329
  if (!input) {
195
330
  return undefined;
@@ -201,148 +336,99 @@ function parseBody(input) {
201
336
  return input;
202
337
  }
203
338
  }
204
- function prettyPrint(input) {
205
- console.log(JSON.stringify(input, null, 2));
206
- }
207
- async function runBotCommands(medplum, argv, commands) {
208
- if (argv.length < 4) {
209
- console.log(`Usage: medplum ${argv[2]} <bot-name>`);
210
- return;
211
- }
212
- const botName = argv[3];
213
- const botConfigs = readBotConfigs(botName);
214
- if (botConfigs.length === 0) {
215
- console.log(`Error: ${botName} not found`);
216
- return;
217
- }
218
- for (const botConfig of botConfigs) {
219
- await runBotConfig(botConfig, medplum, argv, commands);
220
- }
221
- console.log(`Number of bots deployed: ${botConfigs.length}`);
222
- }
223
- async function runBotConfig(botConfig, medplum, argv, commands) {
224
- let bot;
225
- try {
226
- bot = await medplum.readResource('Bot', botConfig.id);
227
- console.log(`Initialized Bot -> ${bot.name}...`);
228
- }
229
- catch (err) {
230
- console.log('Error: ' + core.normalizeErrorString(err));
231
- return;
232
- }
233
- if (commands.includes('save')) {
234
- await saveBot(medplum, botConfig, bot);
235
- }
236
- if (commands.includes('deploy')) {
237
- await deployBot(medplum, botConfig, bot);
339
+ function cleanUrl(input) {
340
+ const knownPrefixes = ['admin/', 'auth/', 'fhir/R4'];
341
+ if (knownPrefixes.some((p) => input.startsWith(p))) {
342
+ // If the URL starts with a known prefix, return it as-is
343
+ return input;
238
344
  }
345
+ // Otherwise, default to FHIR
346
+ return 'fhir/R4/' + input;
239
347
  }
240
- async function createBot(medplum, argv) {
241
- if (argv.length < 7) {
242
- console.log(`Error: command needs to be npx medplum <new-bot-name> <project-id> <source-file> <dist-file>`);
243
- return;
244
- }
245
- const botName = argv[3];
246
- const projectId = argv[4];
247
- const sourceFile = argv[5];
248
- const distFile = argv[6];
249
- try {
250
- const body = {
251
- name: botName,
252
- description: '',
253
- };
254
- const newBot = await medplum.post('admin/projects/' + projectId + '/bot', body);
255
- const bot = await medplum.readResource('Bot', newBot.id);
256
- const botConfig = {
257
- name: botName,
258
- id: newBot.id,
259
- source: sourceFile,
260
- dist: distFile,
261
- };
262
- await saveBot(medplum, botConfig, bot);
263
- console.log(`Success! Bot created: ${bot.id}`);
264
- addBotToConfig(botConfig);
265
- }
266
- catch (err) {
267
- console.log('Error while creating new bot ', err);
268
- }
348
+
349
+ const project = new commander.Command('project');
350
+ project
351
+ .command('list')
352
+ .description('List of current projects')
353
+ .action(async () => {
354
+ projectList(exports.medplum);
355
+ });
356
+ function projectList(medplum) {
357
+ const logins = medplum.getLogins();
358
+ const projects = logins
359
+ .map((login) => `${login.project.display} (${login.project.reference})`)
360
+ .join('\n\n');
361
+ console.log(projects);
269
362
  }
270
- async function saveBot(medplum, botConfig, bot) {
271
- const code = readFileContents(botConfig.source);
272
- if (!code) {
273
- return;
363
+ project
364
+ .command('current')
365
+ .description('Project you are currently on')
366
+ .action(() => {
367
+ const login = exports.medplum.getActiveLogin();
368
+ if (!login) {
369
+ throw new Error('Unauthenticated: run `npx medplum login` to login');
370
+ }
371
+ console.log(`${login.project.display} (${login.project.reference})`);
372
+ });
373
+ project
374
+ .command('switch')
375
+ .description('Switching to another project from the current one')
376
+ .argument('<projectId>')
377
+ .action(async (projectId) => {
378
+ await switchProject(exports.medplum, projectId);
379
+ });
380
+ async function switchProject(medplum, projectId) {
381
+ const logins = medplum.getLogins();
382
+ const login = logins.find((login) => login.project?.reference?.includes(projectId));
383
+ if (!login) {
384
+ console.log(`Error: project ${projectId} not found. Make sure you are added as a user to this project`);
274
385
  }
275
- try {
276
- console.log('Update bot code.....');
277
- const updateResult = await medplum.updateResource({
278
- ...bot,
279
- code,
280
- });
281
- if (!updateResult) {
282
- console.log('Bot not modified');
283
- }
284
- else {
285
- console.log('Success! New bot version: ' + updateResult.meta?.versionId);
286
- }
287
- }
288
- catch (err) {
289
- console.log('Update error: ', err);
386
+ else {
387
+ await medplum.setActiveLogin(login);
388
+ console.log(`Switched to project ${projectId}\n`);
290
389
  }
291
390
  }
292
- async function deployBot(medplum, botConfig, bot) {
293
- const code = readFileContents(botConfig.dist ?? botConfig.source);
294
- if (!code) {
295
- return;
391
+
392
+ exports.medplum = void 0;
393
+ async function main(medplumClient, argv) {
394
+ exports.medplum = medplumClient;
395
+ // Legacy support for MEDPLUM_CLIENT_ID and MEDPLUM_CLIENT_SECRET environment variables
396
+ const clientId = process.env['MEDPLUM_CLIENT_ID'];
397
+ const clientSecret = process.env['MEDPLUM_CLIENT_SECRET'];
398
+ if (clientId && clientSecret) {
399
+ await exports.medplum.startClientLogin(clientId, clientSecret);
296
400
  }
297
401
  try {
298
- console.log('Deploying bot...');
299
- const deployResult = (await medplum.post(medplum.fhirUrl('Bot', bot.id, '$deploy'), {
300
- code,
301
- }));
302
- console.log('Deploy result: ' + deployResult.issue?.[0]?.details?.text);
402
+ const index = new commander.Command('medplum').description('Command to access Medplum CLI');
403
+ index.version('0.1.0');
404
+ // Auth commands
405
+ index.addCommand(login);
406
+ index.addCommand(whoami);
407
+ // REST commands
408
+ index.addCommand(get);
409
+ index.addCommand(post);
410
+ index.addCommand(patch);
411
+ index.addCommand(put);
412
+ index.addCommand(deleteObject);
413
+ // Project
414
+ index.addCommand(project);
415
+ // Bot Commands
416
+ index.addCommand(bot);
417
+ // Deprecated Bot Commands
418
+ index.addCommand(saveBotDeprecate);
419
+ index.addCommand(deployBotDeprecate);
420
+ index.addCommand(createBotDeprecate);
421
+ await index.parseAsync(argv);
303
422
  }
304
423
  catch (err) {
305
- console.log('Deploy error: ', err);
306
- }
307
- }
308
- function escapeRegex(str) {
309
- return str.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
310
- }
311
- function readBotConfigs(botName) {
312
- const regExBotName = new RegExp('^' + escapeRegex(botName).replace(/\\\*/g, '.*') + '$');
313
- const botConfigs = readConfig()?.bots?.filter((b) => regExBotName.test(b.name));
314
- if (!botConfigs) {
315
- return [];
316
- }
317
- return botConfigs;
318
- }
319
- function readConfig() {
320
- const content = readFileContents('medplum.config.json');
321
- if (!content) {
322
- return undefined;
323
- }
324
- return JSON.parse(content);
325
- }
326
- function readFileContents(fileName) {
327
- const path$1 = path.resolve(process.cwd(), fileName);
328
- if (!fs.existsSync(path$1)) {
329
- console.log('Error: File does not exist: ' + path$1);
330
- return '';
424
+ console.error('Error: ' + core.normalizeErrorString(err));
331
425
  }
332
- return fs.readFileSync(path$1, 'utf8');
333
- }
334
- function addBotToConfig(botConfig) {
335
- const config = readConfig();
336
- config?.bots?.push(botConfig);
337
- fs.writeFile('medplum.config.json', JSON.stringify(config), () => {
338
- console.log(`Bot added to config: ${botConfig.id}`);
339
- });
340
426
  }
341
427
  if (require.main === module) {
342
428
  dotenv.config();
343
429
  const baseUrl = process.env['MEDPLUM_BASE_URL'] || 'https://api.medplum.com/';
344
- const medplum = new core.MedplumClient({ fetch, baseUrl, storage: new FileSystemStorage() });
345
- main(medplum, process.argv).catch((err) => console.error('Unhandled error:', err));
430
+ const medplumClient = new core.MedplumClient({ fetch, baseUrl, storage: new FileSystemStorage() });
431
+ main(medplumClient, process.argv).catch((err) => console.error('Unhandled error:', err));
346
432
  }
347
433
 
348
434
  exports.main = main;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../src/storage.ts","../../../src/index.ts"],"sourcesContent":["import { ClientStorage } from '@medplum/core';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { homedir } from 'os';\nimport { resolve } from 'path';\n\nexport class FileSystemStorage extends ClientStorage {\n private readonly dirName: string;\n private readonly fileName: string;\n\n constructor() {\n super();\n this.dirName = resolve(homedir(), '.medplum');\n this.fileName = resolve(this.dirName, 'credentials');\n }\n\n clear(): void {\n this.writeFile({});\n }\n\n getString(key: string): string | undefined {\n return this.readFile()?.[key];\n }\n\n setString(key: string, value: string | undefined): void {\n const data = this.readFile() || {};\n if (value) {\n data[key] = value;\n } else {\n delete data[key];\n }\n this.writeFile(data);\n }\n\n private readFile(): Record<string, string> | undefined {\n if (existsSync(this.fileName)) {\n return JSON.parse(readFileSync(this.fileName, 'utf8'));\n }\n return undefined;\n }\n\n private writeFile(data: Record<string, string>): void {\n if (!existsSync(this.dirName)) {\n mkdirSync(this.dirName);\n }\n writeFileSync(this.fileName, JSON.stringify(data, null, 2), 'utf8');\n }\n}\n","import { getDisplayString, MedplumClient, normalizeErrorString } from '@medplum/core';\nimport { Bot, OperationOutcome } from '@medplum/fhirtypes';\nimport { exec } from 'child_process';\nimport dotenv from 'dotenv';\nimport { existsSync, readFileSync, writeFile } from 'fs';\nimport { createServer } from 'http';\nimport fetch from 'node-fetch';\nimport { platform } from 'os';\nimport { resolve } from 'path';\nimport { FileSystemStorage } from './storage';\n\ninterface MedplumConfig {\n readonly bots?: MedplumBotConfig[];\n}\n\ninterface MedplumBotConfig {\n readonly name: string;\n readonly id: string;\n readonly source: string;\n readonly dist?: string;\n}\n\nconst clientId = 'medplum-cli';\nconst redirectUri = 'http://localhost:9615';\n\nexport async function main(medplum: MedplumClient, argv: string[]): Promise<void> {\n if (argv.length < 3) {\n console.log('Usage: medplum <command>');\n return;\n }\n\n // Legacy support for MEDPLUM_CLIENT_ID and MEDPLUM_CLIENT_SECRET environment variables\n const clientId = process.env['MEDPLUM_CLIENT_ID'];\n const clientSecret = process.env['MEDPLUM_CLIENT_SECRET'];\n if (clientId && clientSecret) {\n await medplum.startClientLogin(clientId, clientSecret);\n }\n\n try {\n const command = argv[2].toLowerCase();\n switch (command) {\n //\n // Auth commands\n //\n case 'login':\n await startLogin(medplum);\n break;\n case 'whoami':\n printMe(medplum);\n break;\n //\n // REST commands\n //\n case 'delete':\n prettyPrint(await medplum.delete(cleanUrl(argv[3])));\n break;\n case 'get':\n prettyPrint(await medplum.get(cleanUrl(argv[3])));\n break;\n case 'patch':\n prettyPrint(await medplum.patch(cleanUrl(argv[3]), parseBody(argv[4])));\n break;\n case 'post':\n prettyPrint(await medplum.post(cleanUrl(argv[3]), parseBody(argv[4])));\n break;\n case 'put':\n prettyPrint(await medplum.put(cleanUrl(argv[3]), parseBody(argv[4])));\n break;\n //\n // Bot commands\n //\n case 'save-bot':\n await runBotCommands(medplum, argv, ['save']);\n break;\n case 'deploy-bot':\n await runBotCommands(medplum, argv, ['save', 'deploy']);\n break;\n case 'create-bot':\n await createBot(medplum, argv);\n break;\n default:\n console.log(`Unknown command: ${command}`);\n }\n } catch (err) {\n console.error('Error: ' + normalizeErrorString(err));\n }\n}\n\nasync function startLogin(medplum: MedplumClient): Promise<void> {\n await startWebServer(medplum);\n\n const loginUrl = new URL('/oauth2/authorize', medplum.getBaseUrl());\n loginUrl.searchParams.set('client_id', clientId);\n loginUrl.searchParams.set('redirect_uri', redirectUri);\n loginUrl.searchParams.set('scope', 'openid');\n loginUrl.searchParams.set('response_type', 'code');\n await openBrowser(loginUrl.toString());\n}\n\nasync function startWebServer(medplum: MedplumClient): Promise<void> {\n const server = createServer(async (req, res) => {\n const url = new URL(req.url as string, 'http://localhost:9615');\n const code = url.searchParams.get('code');\n if (url.pathname === '/' && code) {\n try {\n const profile = await medplum.processCode(code, { clientId, redirectUri });\n res.writeHead(200, { 'Content-Type': 'text/plain' });\n res.end(`Signed in as ${getDisplayString(profile)}. You may close this window.`);\n } catch (err) {\n res.writeHead(400, { 'Content-Type': 'text/plain' });\n res.end(`Error: ${normalizeErrorString(err)}`);\n } finally {\n server.close();\n }\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not found');\n }\n }).listen(9615);\n}\n\n/**\n * Opens a web browser to the specified URL.\n * See: https://hasinthaindrajee.medium.com/browser-sso-for-cli-applications-b0be743fa656\n * @param url The URL to open.\n */\nasync function openBrowser(url: string): Promise<void> {\n const os = platform();\n let cmd = undefined;\n switch (os) {\n case 'openbsd':\n case 'linux':\n cmd = `xdg-open '${url}'`;\n break;\n case 'darwin':\n cmd = `open '${url}'`;\n break;\n case 'win32':\n cmd = `cmd /c start \"\" \"${url}\"`;\n break;\n default:\n throw new Error('Unsupported platform: ' + os);\n }\n exec(cmd);\n}\n\n/**\n * Prints the current user and project.\n * @param medplum The Medplum client.\n */\nfunction printMe(medplum: MedplumClient): void {\n const loginState = medplum.getActiveLogin();\n if (loginState) {\n console.log(`Server: ${medplum.getBaseUrl()}`);\n console.log(`Profile: ${loginState.profile?.display} (${loginState.profile?.reference})`);\n console.log(`Project: ${loginState.project?.display} (${loginState.project?.reference})`);\n } else {\n console.log('Not logged in');\n }\n}\n\nfunction cleanUrl(input: string): string {\n const knownPrefixes = ['admin/', 'auth/', 'fhir/R4'];\n if (knownPrefixes.some((p) => input.startsWith(p))) {\n // If the URL starts with a known prefix, return it as-is\n return input;\n }\n // Otherwise, default to FHIR\n return 'fhir/R4/' + input;\n}\n\nfunction parseBody(input: string | undefined): any {\n if (!input) {\n return undefined;\n }\n try {\n return JSON.parse(input);\n } catch (err) {\n return input;\n }\n}\n\nfunction prettyPrint(input: unknown): void {\n console.log(JSON.stringify(input, null, 2));\n}\n\nasync function runBotCommands(medplum: MedplumClient, argv: string[], commands: string[]): Promise<void> {\n if (argv.length < 4) {\n console.log(`Usage: medplum ${argv[2]} <bot-name>`);\n return;\n }\n\n const botName = argv[3];\n\n const botConfigs = readBotConfigs(botName);\n if (botConfigs.length === 0) {\n console.log(`Error: ${botName} not found`);\n return;\n }\n\n for (const botConfig of botConfigs) {\n await runBotConfig(botConfig, medplum, argv, commands);\n }\n\n console.log(`Number of bots deployed: ${botConfigs.length}`);\n}\n\nasync function runBotConfig(\n botConfig: MedplumBotConfig,\n medplum: MedplumClient,\n argv: string[],\n commands: string[]\n): Promise<void> {\n let bot;\n try {\n bot = await medplum.readResource('Bot', botConfig.id);\n console.log(`Initialized Bot -> ${bot.name}...`);\n } catch (err) {\n console.log('Error: ' + normalizeErrorString(err));\n return;\n }\n\n if (commands.includes('save')) {\n await saveBot(medplum, botConfig, bot);\n }\n\n if (commands.includes('deploy')) {\n await deployBot(medplum, botConfig, bot);\n }\n}\n\nasync function createBot(medplum: MedplumClient, argv: string[]): Promise<void> {\n if (argv.length < 7) {\n console.log(`Error: command needs to be npx medplum <new-bot-name> <project-id> <source-file> <dist-file>`);\n return;\n }\n const botName = argv[3];\n const projectId = argv[4];\n const sourceFile = argv[5];\n const distFile = argv[6];\n\n try {\n const body = {\n name: botName,\n description: '',\n };\n const newBot = await medplum.post('admin/projects/' + projectId + '/bot', body);\n const bot = await medplum.readResource('Bot', newBot.id);\n\n const botConfig = {\n name: botName,\n id: newBot.id,\n source: sourceFile,\n dist: distFile,\n };\n await saveBot(medplum, botConfig as MedplumBotConfig, bot);\n console.log(`Success! Bot created: ${bot.id}`);\n\n addBotToConfig(botConfig);\n } catch (err) {\n console.log('Error while creating new bot ', err);\n }\n}\n\nasync function saveBot(medplum: MedplumClient, botConfig: MedplumBotConfig, bot: Bot): Promise<void> {\n const code = readFileContents(botConfig.source);\n if (!code) {\n return;\n }\n\n try {\n console.log('Update bot code.....');\n const updateResult = await medplum.updateResource({\n ...bot,\n code,\n });\n if (!updateResult) {\n console.log('Bot not modified');\n } else {\n console.log('Success! New bot version: ' + updateResult.meta?.versionId);\n }\n } catch (err) {\n console.log('Update error: ', err);\n }\n}\n\nasync function deployBot(medplum: MedplumClient, botConfig: MedplumBotConfig, bot: Bot): Promise<void> {\n const code = readFileContents(botConfig.dist ?? botConfig.source);\n if (!code) {\n return;\n }\n\n try {\n console.log('Deploying bot...');\n const deployResult = (await medplum.post(medplum.fhirUrl('Bot', bot.id as string, '$deploy'), {\n code,\n })) as OperationOutcome;\n console.log('Deploy result: ' + deployResult.issue?.[0]?.details?.text);\n } catch (err) {\n console.log('Deploy error: ', err);\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[/\\-\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n}\n\nfunction readBotConfigs(botName: string): MedplumBotConfig[] {\n const regExBotName = new RegExp('^' + escapeRegex(botName).replace(/\\\\\\*/g, '.*') + '$');\n const botConfigs = readConfig()?.bots?.filter((b) => regExBotName.test(b.name));\n if (!botConfigs) {\n return [];\n }\n return botConfigs;\n}\n\nfunction readConfig(): MedplumConfig | undefined {\n const content = readFileContents('medplum.config.json');\n if (!content) {\n return undefined;\n }\n return JSON.parse(content);\n}\n\nfunction readFileContents(fileName: string): string | undefined {\n const path = resolve(process.cwd(), fileName);\n if (!existsSync(path)) {\n console.log('Error: File does not exist: ' + path);\n return '';\n }\n return readFileSync(path, 'utf8');\n}\n\nfunction addBotToConfig(botConfig: MedplumBotConfig): void {\n const config = readConfig();\n config?.bots?.push(botConfig);\n writeFile('medplum.config.json', JSON.stringify(config), () => {\n console.log(`Bot added to config: ${botConfig.id}`);\n });\n}\n\nif (require.main === module) {\n dotenv.config();\n const baseUrl = process.env['MEDPLUM_BASE_URL'] || 'https://api.medplum.com/';\n const medplum = new MedplumClient({ fetch, baseUrl, storage: new FileSystemStorage() });\n main(medplum, process.argv).catch((err) => console.error('Unhandled error:', err));\n}\n"],"names":["ClientStorage","resolve","homedir","existsSync","readFileSync","mkdirSync","writeFileSync","normalizeErrorString","createServer","getDisplayString","os","platform","exec","path","writeFile","MedplumClient"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../src/storage.ts","../../../src/utils.ts","../../../src/bots.ts","../../../src/auth.ts","../../../src/rest.ts","../../../src/projects.ts","../../../src/index.ts"],"sourcesContent":["import { ClientStorage } from '@medplum/core';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { homedir } from 'os';\nimport { resolve } from 'path';\n\nexport class FileSystemStorage extends ClientStorage {\n private readonly dirName: string;\n private readonly fileName: string;\n\n constructor() {\n super();\n this.dirName = resolve(homedir(), '.medplum');\n this.fileName = resolve(this.dirName, 'credentials');\n }\n\n clear(): void {\n this.writeFile({});\n }\n\n getString(key: string): string | undefined {\n return this.readFile()?.[key];\n }\n\n setString(key: string, value: string | undefined): void {\n const data = this.readFile() || {};\n if (value) {\n data[key] = value;\n } else {\n delete data[key];\n }\n this.writeFile(data);\n }\n\n private readFile(): Record<string, string> | undefined {\n if (existsSync(this.fileName)) {\n return JSON.parse(readFileSync(this.fileName, 'utf8'));\n }\n return undefined;\n }\n\n private writeFile(data: Record<string, string>): void {\n if (!existsSync(this.dirName)) {\n mkdirSync(this.dirName);\n }\n writeFileSync(this.fileName, JSON.stringify(data, null, 2), 'utf8');\n }\n}\n","import { MedplumClient } from '@medplum/core';\nimport { resolve } from 'path';\nimport { existsSync, readFileSync, writeFile } from 'fs';\nimport { Bot, OperationOutcome } from '@medplum/fhirtypes';\n\ninterface MedplumConfig {\n readonly bots?: MedplumBotConfig[];\n}\n\ninterface MedplumBotConfig {\n readonly name: string;\n readonly id: string;\n readonly source: string;\n readonly dist?: string;\n}\n\nexport function prettyPrint(input: unknown): void {\n console.log(JSON.stringify(input, null, 2));\n}\n\nexport async function saveBot(medplum: MedplumClient, botConfig: MedplumBotConfig, bot: Bot): Promise<void> {\n const code = readFileContents(botConfig.source);\n if (!code) {\n return;\n }\n\n try {\n console.log('Update bot code.....');\n const updateResult = await medplum.updateResource({\n ...bot,\n code,\n });\n if (!updateResult) {\n console.log('Bot not modified');\n } else {\n console.log('Success! New bot version: ' + updateResult.meta?.versionId);\n }\n } catch (err) {\n console.log('Update error: ', err);\n }\n}\n\nexport async function deployBot(medplum: MedplumClient, botConfig: MedplumBotConfig, bot: Bot): Promise<void> {\n const code = readFileContents(botConfig.dist ?? botConfig.source);\n if (!code) {\n return;\n }\n\n try {\n console.log('Deploying bot...');\n const deployResult = (await medplum.post(medplum.fhirUrl('Bot', bot.id as string, '$deploy'), {\n code,\n })) as OperationOutcome;\n console.log('Deploy result: ' + deployResult.issue?.[0]?.details?.text);\n } catch (err) {\n console.log('Deploy error: ', err);\n }\n}\n\nexport async function createBot(medplum: MedplumClient, argv: string[]): Promise<void> {\n if (argv.length < 4) {\n console.log(`Error: command needs to be npx medplum <new-bot-name> <project-id> <source-file> <dist-file>`);\n return;\n }\n const botName = argv[0];\n const projectId = argv[1];\n const sourceFile = argv[2];\n const distFile = argv[3];\n\n try {\n const body = {\n name: botName,\n description: '',\n };\n const newBot = await medplum.post('admin/projects/' + projectId + '/bot', body);\n const bot = await medplum.readResource('Bot', newBot.id);\n\n const botConfig = {\n name: botName,\n id: newBot.id,\n source: sourceFile,\n dist: distFile,\n };\n await saveBot(medplum, botConfig as MedplumBotConfig, bot);\n console.log(`Success! Bot created: ${bot.id}`);\n\n addBotToConfig(botConfig);\n } catch (err) {\n console.log('Error while creating new bot: ' + err);\n }\n}\n\nexport function readBotConfigs(botName: string): MedplumBotConfig[] {\n const regExBotName = new RegExp('^' + escapeRegex(botName).replace(/\\\\\\*/g, '.*') + '$');\n const botConfigs = readConfig()?.bots?.filter((b) => regExBotName.test(b.name));\n if (!botConfigs) {\n return [];\n }\n return botConfigs;\n}\n\nfunction readConfig(): MedplumConfig | undefined {\n const content = readFileContents('medplum.config.json');\n if (!content) {\n return undefined;\n }\n return JSON.parse(content);\n}\n\nfunction readFileContents(fileName: string): string | undefined {\n const path = resolve(process.cwd(), fileName);\n if (!existsSync(path)) {\n console.log('Error: File does not exist: ' + path);\n return '';\n }\n return readFileSync(path, 'utf8');\n}\n\nfunction addBotToConfig(botConfig: MedplumBotConfig): void {\n const config = readConfig();\n config?.bots?.push(botConfig);\n writeFile('medplum.config.json', JSON.stringify(config), () => {\n console.log(`Bot added to config: ${botConfig.id}`);\n });\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[/\\-\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n}\n","import { Command } from 'commander';\nimport { medplum } from '.';\nimport { createBot, deployBot, readBotConfigs, saveBot } from './utils';\nimport { MedplumClient } from '@medplum/core';\n\nexport const bot = new Command('bot');\n\n// Commands to deprecate\nexport const saveBotDeprecate = new Command('save-bot');\nexport const deployBotDeprecate = new Command('deploy-bot');\nexport const createBotDeprecate = new Command('create-bot');\n\nbot\n .command('save')\n .description('Saving the bot')\n .argument('<botName>')\n .action(async (botName) => {\n await botWrapper(medplum, botName);\n });\n\nbot\n .command('deploy')\n .description('Deploy the app to AWS')\n .argument('<botName>')\n .action(async (botName) => {\n await botWrapper(medplum, botName, true);\n });\n\nbot\n .command('create')\n .arguments('<botName> <projectId> <sourceFile> <distFile>')\n .description('Creating a bot')\n .action(async (botName, projectId, sourceFile, distFile) => {\n await createBot(medplum, [botName, projectId, sourceFile, distFile]);\n });\n\nexport async function botWrapper(medplum: MedplumClient, botName: string, deploy = false): Promise<void> {\n const botConfigs = readBotConfigs(botName);\n for (const botConfig of botConfigs) {\n const bot = await medplum.readResource('Bot', botConfig.id);\n await saveBot(medplum, botConfig, bot);\n if (deploy) {\n await deployBot(medplum, botConfig, bot);\n }\n }\n console.log(`Number of bots deployed: ${botConfigs.length}`);\n}\n\n// Deprecate bot commands\nsaveBotDeprecate\n .description('Saves the bot')\n .argument('<botName>')\n .action(async (botName) => {\n await botWrapper(medplum, botName);\n });\n\ndeployBotDeprecate\n .description('Deploy the bot to AWS')\n .argument('<botName>')\n .action(async (botName) => {\n await botWrapper(medplum, botName, true);\n });\n\ncreateBotDeprecate\n .arguments('<botName> <projectId> <sourceFile> <distFile>')\n .description('Creates and saves the bot')\n .action(async (botName, projectId, sourceFile, distFile) => {\n await createBot(medplum, [botName, projectId, sourceFile, distFile]);\n });\n","import { Command } from 'commander';\nimport { medplum } from '.';\nimport { MedplumClient, getDisplayString, normalizeErrorString } from '@medplum/core';\nimport { platform } from 'os';\nimport { exec } from 'child_process';\nimport { createServer } from 'http';\n\nconst clientId = 'medplum-cli';\nconst redirectUri = 'http://localhost:9615';\n\nexport const login = new Command('login');\nexport const whoami = new Command('whoami');\n\nlogin.action(async () => {\n await startLogin(medplum);\n});\n\nwhoami.action(() => {\n printMe(medplum);\n});\n\nasync function startLogin(medplum: MedplumClient): Promise<void> {\n await startWebServer(medplum);\n\n const loginUrl = new URL('/oauth2/authorize', medplum.getBaseUrl());\n loginUrl.searchParams.set('client_id', clientId);\n loginUrl.searchParams.set('redirect_uri', redirectUri);\n loginUrl.searchParams.set('scope', 'openid');\n loginUrl.searchParams.set('response_type', 'code');\n await openBrowser(loginUrl.toString());\n}\n\nasync function startWebServer(medplum: MedplumClient): Promise<void> {\n const server = createServer(async (req, res) => {\n const url = new URL(req.url as string, 'http://localhost:9615');\n const code = url.searchParams.get('code');\n if (url.pathname === '/' && code) {\n try {\n const profile = await medplum.processCode(code, { clientId, redirectUri });\n res.writeHead(200, { 'Content-Type': 'text/plain' });\n res.end(`Signed in as ${getDisplayString(profile)}. You may close this window.`);\n } catch (err) {\n res.writeHead(400, { 'Content-Type': 'text/plain' });\n res.end(`Error: ${normalizeErrorString(err)}`);\n } finally {\n server.close();\n }\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not found');\n }\n }).listen(9615);\n}\n\n/**\n * Opens a web browser to the specified URL.\n * See: https://hasinthaindrajee.medium.com/browser-sso-for-cli-applications-b0be743fa656\n * @param url The URL to open.\n */\nasync function openBrowser(url: string): Promise<void> {\n const os = platform();\n let cmd = undefined;\n switch (os) {\n case 'openbsd':\n case 'linux':\n cmd = `xdg-open '${url}'`;\n break;\n case 'darwin':\n cmd = `open '${url}'`;\n break;\n case 'win32':\n cmd = `cmd /c start \"\" \"${url}\"`;\n break;\n default:\n throw new Error('Unsupported platform: ' + os);\n }\n exec(cmd);\n}\n\n/**\n * Prints the current user and project.\n * @param medplum The Medplum client.\n */\nfunction printMe(medplum: MedplumClient): void {\n const loginState = medplum.getActiveLogin();\n if (loginState) {\n console.log(`Server: ${medplum.getBaseUrl()}`);\n console.log(`Profile: ${loginState.profile?.display} (${loginState.profile?.reference})`);\n console.log(`Project: ${loginState.project?.display} (${loginState.project?.reference})`);\n } else {\n console.log('Not logged in');\n }\n}\n","import { convertToTransactionBundle } from '@medplum/core';\nimport { Command } from 'commander';\nimport { medplum } from '.';\nimport { prettyPrint } from './utils';\n\nexport const deleteObject = new Command('delete');\nexport const get = new Command('get');\nexport const patch = new Command('patch');\nexport const post = new Command('post');\nexport const put = new Command('put');\n\ndeleteObject.argument('<url>', 'Resource/$id').action(async (url) => {\n prettyPrint(await medplum.delete(cleanUrl(url)));\n});\n\nget\n .argument('<url>', 'Resource/$id')\n .option('--as-transaction', 'Print out the bundle as a transaction type')\n .action(async (url, options) => {\n try {\n const response = await medplum.get(cleanUrl(url));\n if (options.asTransaction) {\n prettyPrint(convertToTransactionBundle(response));\n } else {\n prettyPrint(response);\n }\n } catch (err) {\n console.log(err);\n }\n });\n\npatch.arguments('<url> <body>').action(async (url, body) => {\n prettyPrint(await medplum.patch(cleanUrl(url), parseBody(body)));\n});\n\npost.arguments('<url> <body>').action(async (url, body) => {\n prettyPrint(await medplum.post(cleanUrl(url), parseBody(body)));\n});\n\nput.arguments('<url> <body>').action(async (url, body) => {\n prettyPrint(await medplum.put(cleanUrl(url), parseBody(body)));\n});\n\nfunction parseBody(input: string | undefined): any {\n if (!input) {\n return undefined;\n }\n try {\n return JSON.parse(input);\n } catch (err) {\n return input;\n }\n}\n\nexport function cleanUrl(input: string): string {\n const knownPrefixes = ['admin/', 'auth/', 'fhir/R4'];\n if (knownPrefixes.some((p) => input.startsWith(p))) {\n // If the URL starts with a known prefix, return it as-is\n return input;\n }\n // Otherwise, default to FHIR\n return 'fhir/R4/' + input;\n}\n","import { Command } from 'commander';\nimport { medplum } from '.';\nimport { MedplumClient, LoginState } from '@medplum/core';\n\nexport const project = new Command('project');\n\nproject\n .command('list')\n .description('List of current projects')\n .action(async () => {\n projectList(medplum);\n });\n\nfunction projectList(medplum: MedplumClient): void {\n const logins = medplum.getLogins();\n\n const projects = logins\n .map((login: LoginState) => `${login.project.display} (${login.project.reference})`)\n .join('\\n\\n');\n\n console.log(projects);\n}\n\nproject\n .command('current')\n .description('Project you are currently on')\n .action(() => {\n const login = medplum.getActiveLogin();\n if (!login) {\n throw new Error('Unauthenticated: run `npx medplum login` to login');\n }\n console.log(`${login.project.display} (${login.project.reference})`);\n });\n\nproject\n .command('switch')\n .description('Switching to another project from the current one')\n .argument('<projectId>')\n .action(async (projectId) => {\n await switchProject(medplum, projectId);\n });\n\nasync function switchProject(medplum: MedplumClient, projectId: string): Promise<void> {\n const logins = medplum.getLogins();\n const login = logins.find((login: LoginState) => login.project?.reference?.includes(projectId));\n if (!login) {\n console.log(`Error: project ${projectId} not found. Make sure you are added as a user to this project`);\n } else {\n await medplum.setActiveLogin(login);\n console.log(`Switched to project ${projectId}\\n`);\n }\n}\n","import { Command } from 'commander';\nimport { FileSystemStorage } from './storage';\nimport { MedplumClient, normalizeErrorString } from '@medplum/core';\nimport dotenv from 'dotenv';\nimport { bot, createBotDeprecate, deployBotDeprecate, saveBotDeprecate } from './bots';\nimport { login, whoami } from './auth';\nimport { deleteObject, get, patch, post, put } from './rest';\nimport { project } from './projects';\n\nexport let medplum: MedplumClient;\n\nexport async function main(medplumClient: MedplumClient, argv: string[]): Promise<void> {\n medplum = medplumClient;\n\n // Legacy support for MEDPLUM_CLIENT_ID and MEDPLUM_CLIENT_SECRET environment variables\n const clientId = process.env['MEDPLUM_CLIENT_ID'];\n const clientSecret = process.env['MEDPLUM_CLIENT_SECRET'];\n if (clientId && clientSecret) {\n await medplum.startClientLogin(clientId, clientSecret);\n }\n try {\n const index = new Command('medplum').description('Command to access Medplum CLI');\n index.version('0.1.0');\n\n // Auth commands\n index.addCommand(login);\n index.addCommand(whoami);\n\n // REST commands\n index.addCommand(get);\n index.addCommand(post);\n index.addCommand(patch);\n index.addCommand(put);\n index.addCommand(deleteObject);\n\n // Project\n index.addCommand(project);\n\n // Bot Commands\n index.addCommand(bot);\n\n // Deprecated Bot Commands\n index.addCommand(saveBotDeprecate);\n index.addCommand(deployBotDeprecate);\n index.addCommand(createBotDeprecate);\n\n await index.parseAsync(argv);\n } catch (err) {\n console.error('Error: ' + normalizeErrorString(err));\n }\n}\n\nif (require.main === module) {\n dotenv.config();\n const baseUrl = process.env['MEDPLUM_BASE_URL'] || 'https://api.medplum.com/';\n const medplumClient = new MedplumClient({ fetch, baseUrl, storage: new FileSystemStorage() });\n main(medplumClient, process.argv).catch((err) => console.error('Unhandled error:', err));\n}\n"],"names":["ClientStorage","resolve","homedir","existsSync","readFileSync","mkdirSync","writeFileSync","path","writeFile","Command","medplum","createServer","getDisplayString","normalizeErrorString","os","platform","exec","convertToTransactionBundle","MedplumClient"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medplum/cli",
3
- "version": "2.0.15",
3
+ "version": "2.0.16",
4
4
  "description": "Medplum Command Line Interface",
5
5
  "author": "Medplum <hello@medplum.com>",
6
6
  "license": "Apache-2.0",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@medplum/core": "*",
21
+ "commander": "10.0.1",
21
22
  "dotenv": "16.0.3",
22
23
  "node-fetch": "2.6.9"
23
24
  },