@medplum/cli 2.0.16 → 2.0.17

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,49 +1,219 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var commander = require('commander');
5
4
  var core = require('@medplum/core');
5
+ var commander = require('commander');
6
+ var dotenv = require('dotenv');
7
+ var clientCloudformation = require('@aws-sdk/client-cloudformation');
8
+ var clientEcs = require('@aws-sdk/client-ecs');
9
+ var path = require('path');
6
10
  var fs = require('fs');
7
11
  var os = require('os');
8
- var path = require('path');
9
- var dotenv = require('dotenv');
10
12
  var child_process = require('child_process');
11
13
  var http = require('http');
12
14
 
13
- class FileSystemStorage extends core.ClientStorage {
14
- constructor() {
15
- super();
16
- this.dirName = path.resolve(os.homedir(), '.medplum');
17
- this.fileName = path.resolve(this.dirName, 'credentials');
15
+ const clientId = 'medplum-cli';
16
+ const redirectUri = 'http://localhost:9615';
17
+ const login = new commander.Command('login');
18
+ const whoami = new commander.Command('whoami');
19
+ login.action(async () => {
20
+ await startLogin(exports.medplum);
21
+ });
22
+ whoami.action(() => {
23
+ printMe(exports.medplum);
24
+ });
25
+ async function startLogin(medplum) {
26
+ await startWebServer(medplum);
27
+ const loginUrl = new URL('/oauth2/authorize', medplum.getBaseUrl());
28
+ loginUrl.searchParams.set('client_id', clientId);
29
+ loginUrl.searchParams.set('redirect_uri', redirectUri);
30
+ loginUrl.searchParams.set('scope', 'openid');
31
+ loginUrl.searchParams.set('response_type', 'code');
32
+ await openBrowser(loginUrl.toString());
33
+ }
34
+ async function startWebServer(medplum) {
35
+ const server = http.createServer(async (req, res) => {
36
+ const url = new URL(req.url, 'http://localhost:9615');
37
+ const code = url.searchParams.get('code');
38
+ if (url.pathname === '/' && code) {
39
+ try {
40
+ const profile = await medplum.processCode(code, { clientId, redirectUri });
41
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
42
+ res.end(`Signed in as ${core.getDisplayString(profile)}. You may close this window.`);
43
+ }
44
+ catch (err) {
45
+ res.writeHead(400, { 'Content-Type': 'text/plain' });
46
+ res.end(`Error: ${core.normalizeErrorString(err)}`);
47
+ }
48
+ finally {
49
+ server.close();
50
+ }
51
+ }
52
+ else {
53
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
54
+ res.end('Not found');
55
+ }
56
+ }).listen(9615);
57
+ }
58
+ /**
59
+ * Opens a web browser to the specified URL.
60
+ * See: https://hasinthaindrajee.medium.com/browser-sso-for-cli-applications-b0be743fa656
61
+ * @param url The URL to open.
62
+ */
63
+ async function openBrowser(url) {
64
+ const os$1 = os.platform();
65
+ let cmd = undefined;
66
+ switch (os$1) {
67
+ case 'openbsd':
68
+ case 'linux':
69
+ cmd = `xdg-open '${url}'`;
70
+ break;
71
+ case 'darwin':
72
+ cmd = `open '${url}'`;
73
+ break;
74
+ case 'win32':
75
+ cmd = `cmd /c start "" "${url}"`;
76
+ break;
77
+ default:
78
+ throw new Error('Unsupported platform: ' + os$1);
18
79
  }
19
- clear() {
20
- this.writeFile({});
80
+ child_process.exec(cmd);
81
+ }
82
+ /**
83
+ * Prints the current user and project.
84
+ * @param medplum The Medplum client.
85
+ */
86
+ function printMe(medplum) {
87
+ const loginState = medplum.getActiveLogin();
88
+ if (loginState) {
89
+ console.log(`Server: ${medplum.getBaseUrl()}`);
90
+ console.log(`Profile: ${loginState.profile?.display} (${loginState.profile?.reference})`);
91
+ console.log(`Project: ${loginState.project?.display} (${loginState.project?.reference})`);
21
92
  }
22
- getString(key) {
23
- return this.readFile()?.[key];
93
+ else {
94
+ console.log('Not logged in');
24
95
  }
25
- setString(key, value) {
26
- const data = this.readFile() || {};
27
- if (value) {
28
- data[key] = value;
29
- }
30
- else {
31
- delete data[key];
96
+ }
97
+
98
+ const aws = new commander.Command('aws').description('Commands to manage AWS resources');
99
+ const client = new clientCloudformation.CloudFormationClient({});
100
+ const tagKey = 'medplum:environment';
101
+ aws
102
+ .command('list')
103
+ .description('List Medplum AWS CloudFormation stacks')
104
+ .action(async () => {
105
+ const stackSummaries = await listStacks();
106
+ for (const stackSummary of stackSummaries) {
107
+ const stackName = stackSummary.StackName;
108
+ const details = await getStackDetails(stackName);
109
+ if (!details) {
110
+ continue;
32
111
  }
33
- this.writeFile(data);
112
+ printStackDetails(details);
113
+ console.log('');
34
114
  }
35
- readFile() {
36
- if (fs.existsSync(this.fileName)) {
37
- return JSON.parse(fs.readFileSync(this.fileName, 'utf8'));
115
+ });
116
+ aws
117
+ .command('describe')
118
+ .description('Describe a Medplum AWS CloudFormation stack by tag')
119
+ .argument('<tag>')
120
+ .action(async (tag) => {
121
+ const details = await getStackByTag(tag);
122
+ if (!details) {
123
+ console.log('Stack not found');
124
+ return;
125
+ }
126
+ printStackDetails(details);
127
+ });
128
+ aws
129
+ .command('update-server')
130
+ .description('Update the server image')
131
+ .argument('<tag>')
132
+ .action(async (tag) => {
133
+ const details = await getStackByTag(tag);
134
+ if (!details) {
135
+ console.log('Stack not found');
136
+ return;
137
+ }
138
+ const ecsCluster = details.ecsCluster?.PhysicalResourceId;
139
+ if (!ecsCluster) {
140
+ console.log('ECS Cluster not found');
141
+ return;
142
+ }
143
+ const ecsService = getEcsServiceName(details.ecsService);
144
+ if (!ecsService) {
145
+ console.log('ECS Service not found');
146
+ return;
147
+ }
148
+ const client = new clientEcs.ECSClient({});
149
+ await client.send(new clientEcs.UpdateServiceCommand({
150
+ cluster: ecsCluster,
151
+ service: ecsService,
152
+ forceNewDeployment: true,
153
+ }));
154
+ console.log(`Service "${ecsService}" updated successfully.`);
155
+ });
156
+ async function listStacks() {
157
+ const listResult = await client.send(new clientCloudformation.ListStacksCommand({}));
158
+ return (listResult.StackSummaries?.filter((s) => s.StackName && s.StackStatus !== 'DELETE_COMPLETE') || []);
159
+ }
160
+ async function getStackByTag(tag) {
161
+ const stackSummaries = await listStacks();
162
+ for (const stackSummary of stackSummaries) {
163
+ const stackName = stackSummary.StackName;
164
+ const details = await getStackDetails(stackName);
165
+ if (details?.tag === tag) {
166
+ return details;
38
167
  }
168
+ }
169
+ return undefined;
170
+ }
171
+ async function getStackDetails(stackName) {
172
+ const describeStacksCommand = new clientCloudformation.DescribeStacksCommand({ StackName: stackName });
173
+ const stackDetails = await client.send(describeStacksCommand);
174
+ const stack = stackDetails.Stacks && stackDetails.Stacks[0];
175
+ const medplumTag = stack?.Tags?.find((tag) => tag.Key === tagKey);
176
+ if (!medplumTag) {
39
177
  return undefined;
40
178
  }
41
- writeFile(data) {
42
- if (!fs.existsSync(this.dirName)) {
43
- fs.mkdirSync(this.dirName);
179
+ const stackResources = await client.send(new clientCloudformation.DescribeStackResourcesCommand({ StackName: stackName }));
180
+ if (!stackResources.StackResources) {
181
+ return undefined;
182
+ }
183
+ const result = {
184
+ stack: stack,
185
+ tag: medplumTag.Value,
186
+ };
187
+ for (const resource of stackResources.StackResources) {
188
+ if (resource.ResourceType === 'AWS::ECS::Cluster') {
189
+ result.ecsCluster = resource;
190
+ }
191
+ else if (resource.ResourceType === 'AWS::ECS::Service') {
192
+ result.ecsService = resource;
193
+ }
194
+ else if (resource.ResourceType === 'AWS::S3::Bucket' &&
195
+ resource.LogicalResourceId?.startsWith('FrontEndAppBucket')) {
196
+ result.appBucket = resource;
197
+ }
198
+ else if (resource.ResourceType === 'AWS::S3::Bucket' &&
199
+ resource.LogicalResourceId?.startsWith('StorageStorageBucket')) {
200
+ result.storageBucket = resource;
44
201
  }
45
- fs.writeFileSync(this.fileName, JSON.stringify(data, null, 2), 'utf8');
46
202
  }
203
+ return result;
204
+ }
205
+ function printStackDetails(details) {
206
+ console.log(`Medplum Tag: ${details.tag}`);
207
+ console.log(`Stack Name: ${details.stack.StackName}`);
208
+ console.log(`Stack ID: ${details.stack.StackId}`);
209
+ console.log(`Status: ${details.stack.StackStatus}`);
210
+ console.log(`ECS Cluster: ${details.ecsCluster?.PhysicalResourceId}`);
211
+ console.log(`ECS Service: ${getEcsServiceName(details.ecsService)}`);
212
+ console.log(`App Bucket: ${details.appBucket?.PhysicalResourceId}`);
213
+ console.log(`Storage Bucket: ${details.storageBucket?.PhysicalResourceId}`);
214
+ }
215
+ function getEcsServiceName(resource) {
216
+ return resource?.PhysicalResourceId?.split('/')?.pop() || '';
47
217
  }
48
218
 
49
219
  function prettyPrint(input) {
@@ -208,86 +378,46 @@ createBotDeprecate
208
378
  await createBot(exports.medplum, [botName, projectId, sourceFile, distFile]);
209
379
  });
210
380
 
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);
381
+ const project = new commander.Command('project');
382
+ project
383
+ .command('list')
384
+ .description('List of current projects')
385
+ .action(async () => {
386
+ projectList(exports.medplum);
220
387
  });
221
- async function startLogin(medplum) {
222
- await startWebServer(medplum);
223
- const loginUrl = new URL('/oauth2/authorize', medplum.getBaseUrl());
224
- loginUrl.searchParams.set('client_id', clientId);
225
- loginUrl.searchParams.set('redirect_uri', redirectUri);
226
- loginUrl.searchParams.set('scope', 'openid');
227
- loginUrl.searchParams.set('response_type', 'code');
228
- await openBrowser(loginUrl.toString());
229
- }
230
- async function startWebServer(medplum) {
231
- const server = http.createServer(async (req, res) => {
232
- const url = new URL(req.url, 'http://localhost:9615');
233
- const code = url.searchParams.get('code');
234
- if (url.pathname === '/' && code) {
235
- try {
236
- const profile = await medplum.processCode(code, { clientId, redirectUri });
237
- res.writeHead(200, { 'Content-Type': 'text/plain' });
238
- res.end(`Signed in as ${core.getDisplayString(profile)}. You may close this window.`);
239
- }
240
- catch (err) {
241
- res.writeHead(400, { 'Content-Type': 'text/plain' });
242
- res.end(`Error: ${core.normalizeErrorString(err)}`);
243
- }
244
- finally {
245
- server.close();
246
- }
247
- }
248
- else {
249
- res.writeHead(404, { 'Content-Type': 'text/plain' });
250
- res.end('Not found');
251
- }
252
- }).listen(9615);
388
+ function projectList(medplum) {
389
+ const logins = medplum.getLogins();
390
+ const projects = logins
391
+ .map((login) => `${login.project.display} (${login.project.reference})`)
392
+ .join('\n\n');
393
+ console.log(projects);
253
394
  }
254
- /**
255
- * Opens a web browser to the specified URL.
256
- * See: https://hasinthaindrajee.medium.com/browser-sso-for-cli-applications-b0be743fa656
257
- * @param url The URL to open.
258
- */
259
- async function openBrowser(url) {
260
- const os$1 = os.platform();
261
- let cmd = undefined;
262
- switch (os$1) {
263
- case 'openbsd':
264
- case 'linux':
265
- cmd = `xdg-open '${url}'`;
266
- break;
267
- case 'darwin':
268
- cmd = `open '${url}'`;
269
- break;
270
- case 'win32':
271
- cmd = `cmd /c start "" "${url}"`;
272
- break;
273
- default:
274
- throw new Error('Unsupported platform: ' + os$1);
395
+ project
396
+ .command('current')
397
+ .description('Project you are currently on')
398
+ .action(() => {
399
+ const login = exports.medplum.getActiveLogin();
400
+ if (!login) {
401
+ throw new Error('Unauthenticated: run `npx medplum login` to login');
275
402
  }
276
- child_process.exec(cmd);
277
- }
278
- /**
279
- * Prints the current user and project.
280
- * @param medplum The Medplum client.
281
- */
282
- function printMe(medplum) {
283
- const loginState = medplum.getActiveLogin();
284
- if (loginState) {
285
- console.log(`Server: ${medplum.getBaseUrl()}`);
286
- console.log(`Profile: ${loginState.profile?.display} (${loginState.profile?.reference})`);
287
- console.log(`Project: ${loginState.project?.display} (${loginState.project?.reference})`);
403
+ console.log(`${login.project.display} (${login.project.reference})`);
404
+ });
405
+ project
406
+ .command('switch')
407
+ .description('Switching to another project from the current one')
408
+ .argument('<projectId>')
409
+ .action(async (projectId) => {
410
+ await switchProject(exports.medplum, projectId);
411
+ });
412
+ async function switchProject(medplum, projectId) {
413
+ const logins = medplum.getLogins();
414
+ const login = logins.find((login) => login.project?.reference?.includes(projectId));
415
+ if (!login) {
416
+ console.log(`Error: project ${projectId} not found. Make sure you are added as a user to this project`);
288
417
  }
289
418
  else {
290
- console.log('Not logged in');
419
+ await medplum.setActiveLogin(login);
420
+ console.log(`Switched to project ${projectId}\n`);
291
421
  }
292
422
  }
293
423
 
@@ -303,17 +433,12 @@ get
303
433
  .argument('<url>', 'Resource/$id')
304
434
  .option('--as-transaction', 'Print out the bundle as a transaction type')
305
435
  .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
- }
436
+ const response = await exports.medplum.get(cleanUrl(url));
437
+ if (options.asTransaction) {
438
+ prettyPrint(core.convertToTransactionBundle(response));
314
439
  }
315
- catch (err) {
316
- console.log(err);
440
+ else {
441
+ prettyPrint(response);
317
442
  }
318
443
  });
319
444
  patch.arguments('<url> <body>').action(async (url, body) => {
@@ -346,46 +471,39 @@ function cleanUrl(input) {
346
471
  return 'fhir/R4/' + input;
347
472
  }
348
473
 
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);
362
- }
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');
474
+ class FileSystemStorage extends core.ClientStorage {
475
+ constructor() {
476
+ super();
477
+ this.dirName = path.resolve(os.homedir(), '.medplum');
478
+ this.fileName = path.resolve(this.dirName, 'credentials');
370
479
  }
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`);
480
+ clear() {
481
+ this.writeFile({});
385
482
  }
386
- else {
387
- await medplum.setActiveLogin(login);
388
- console.log(`Switched to project ${projectId}\n`);
483
+ getString(key) {
484
+ return this.readFile()?.[key];
485
+ }
486
+ setString(key, value) {
487
+ const data = this.readFile() || {};
488
+ if (value) {
489
+ data[key] = value;
490
+ }
491
+ else {
492
+ delete data[key];
493
+ }
494
+ this.writeFile(data);
495
+ }
496
+ readFile() {
497
+ if (fs.existsSync(this.fileName)) {
498
+ return JSON.parse(fs.readFileSync(this.fileName, 'utf8'));
499
+ }
500
+ return undefined;
501
+ }
502
+ writeFile(data) {
503
+ if (!fs.existsSync(this.dirName)) {
504
+ fs.mkdirSync(this.dirName);
505
+ }
506
+ fs.writeFileSync(this.fileName, JSON.stringify(data, null, 2), 'utf8');
389
507
  }
390
508
  }
391
509
 
@@ -418,6 +536,8 @@ async function main(medplumClient, argv) {
418
536
  index.addCommand(saveBotDeprecate);
419
537
  index.addCommand(deployBotDeprecate);
420
538
  index.addCommand(createBotDeprecate);
539
+ // AWS commands
540
+ index.addCommand(aws);
421
541
  await index.parseAsync(argv);
422
542
  }
423
543
  catch (err) {
@@ -427,9 +547,17 @@ async function main(medplumClient, argv) {
427
547
  if (require.main === module) {
428
548
  dotenv.config();
429
549
  const baseUrl = process.env['MEDPLUM_BASE_URL'] || 'https://api.medplum.com/';
430
- const medplumClient = new core.MedplumClient({ fetch, baseUrl, storage: new FileSystemStorage() });
550
+ const medplumClient = new core.MedplumClient({
551
+ fetch,
552
+ baseUrl,
553
+ storage: new FileSystemStorage(),
554
+ onUnauthenticated: onUnauthenticated,
555
+ });
431
556
  main(medplumClient, process.argv).catch((err) => console.error('Unhandled error:', err));
432
557
  }
558
+ function onUnauthenticated() {
559
+ console.log('Unauthenticated: run `npx medplum login` to sign in');
560
+ }
433
561
 
434
562
  exports.main = main;
435
563
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
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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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../src/auth.ts","../../../src/aws.ts","../../../src/utils.ts","../../../src/bots.ts","../../../src/projects.ts","../../../src/rest.ts","../../../src/storage.ts","../../../src/index.ts"],"sourcesContent":["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 {\n CloudFormationClient,\n DescribeStackResourcesCommand,\n DescribeStacksCommand,\n ListStacksCommand,\n Stack,\n StackResource,\n StackSummary,\n} from '@aws-sdk/client-cloudformation';\nimport { ECSClient, UpdateServiceCommand } from '@aws-sdk/client-ecs';\nimport { Command } from 'commander';\n\ninterface MedplumStackDetails {\n stack: Stack;\n tag: string;\n ecsCluster?: StackResource;\n ecsService?: StackResource;\n appBucket?: StackResource;\n storageBucket?: StackResource;\n}\n\nexport const aws = new Command('aws').description('Commands to manage AWS resources');\nconst client = new CloudFormationClient({});\nconst tagKey = 'medplum:environment';\n\naws\n .command('list')\n .description('List Medplum AWS CloudFormation stacks')\n .action(async () => {\n const stackSummaries = await listStacks();\n for (const stackSummary of stackSummaries) {\n const stackName = stackSummary.StackName;\n const details = await getStackDetails(stackName);\n if (!details) {\n continue;\n }\n printStackDetails(details);\n console.log('');\n }\n });\n\naws\n .command('describe')\n .description('Describe a Medplum AWS CloudFormation stack by tag')\n .argument('<tag>')\n .action(async (tag) => {\n const details = await getStackByTag(tag);\n if (!details) {\n console.log('Stack not found');\n return;\n }\n printStackDetails(details);\n });\n\naws\n .command('update-server')\n .description('Update the server image')\n .argument('<tag>')\n .action(async (tag) => {\n const details = await getStackByTag(tag);\n if (!details) {\n console.log('Stack not found');\n return;\n }\n const ecsCluster = details.ecsCluster?.PhysicalResourceId;\n if (!ecsCluster) {\n console.log('ECS Cluster not found');\n return;\n }\n const ecsService = getEcsServiceName(details.ecsService);\n if (!ecsService) {\n console.log('ECS Service not found');\n return;\n }\n const client = new ECSClient({});\n await client.send(\n new UpdateServiceCommand({\n cluster: ecsCluster,\n service: ecsService,\n forceNewDeployment: true,\n })\n );\n console.log(`Service \"${ecsService}\" updated successfully.`);\n });\n\nasync function listStacks(): Promise<(StackSummary & { StackName: string })[]> {\n const listResult = await client.send(new ListStacksCommand({}));\n return (\n (listResult.StackSummaries?.filter((s) => s.StackName && s.StackStatus !== 'DELETE_COMPLETE') as (StackSummary & {\n StackName: string;\n })[]) || []\n );\n}\n\nasync function getStackByTag(tag: string): Promise<MedplumStackDetails | undefined> {\n const stackSummaries = await listStacks();\n for (const stackSummary of stackSummaries) {\n const stackName = stackSummary.StackName;\n const details = await getStackDetails(stackName);\n if (details?.tag === tag) {\n return details;\n }\n }\n return undefined;\n}\n\nasync function getStackDetails(stackName: string): Promise<MedplumStackDetails | undefined> {\n const describeStacksCommand = new DescribeStacksCommand({ StackName: stackName });\n const stackDetails = await client.send(describeStacksCommand);\n const stack = stackDetails.Stacks && stackDetails.Stacks[0];\n const medplumTag = stack?.Tags?.find((tag) => tag.Key === tagKey);\n if (!medplumTag) {\n return undefined;\n }\n\n const stackResources = await client.send(new DescribeStackResourcesCommand({ StackName: stackName }));\n if (!stackResources.StackResources) {\n return undefined;\n }\n\n const result: MedplumStackDetails = {\n stack: stack as Stack,\n tag: medplumTag.Value as string,\n };\n\n for (const resource of stackResources.StackResources) {\n if (resource.ResourceType === 'AWS::ECS::Cluster') {\n result.ecsCluster = resource;\n } else if (resource.ResourceType === 'AWS::ECS::Service') {\n result.ecsService = resource;\n } else if (\n resource.ResourceType === 'AWS::S3::Bucket' &&\n resource.LogicalResourceId?.startsWith('FrontEndAppBucket')\n ) {\n result.appBucket = resource;\n } else if (\n resource.ResourceType === 'AWS::S3::Bucket' &&\n resource.LogicalResourceId?.startsWith('StorageStorageBucket')\n ) {\n result.storageBucket = resource;\n }\n }\n\n return result;\n}\n\nfunction printStackDetails(details: MedplumStackDetails): void {\n console.log(`Medplum Tag: ${details.tag}`);\n console.log(`Stack Name: ${details.stack.StackName}`);\n console.log(`Stack ID: ${details.stack.StackId}`);\n console.log(`Status: ${details.stack.StackStatus}`);\n console.log(`ECS Cluster: ${details.ecsCluster?.PhysicalResourceId}`);\n console.log(`ECS Service: ${getEcsServiceName(details.ecsService)}`);\n console.log(`App Bucket: ${details.appBucket?.PhysicalResourceId}`);\n console.log(`Storage Bucket: ${details.storageBucket?.PhysicalResourceId}`);\n}\n\nfunction getEcsServiceName(resource: StackResource | undefined): string | undefined {\n return resource?.PhysicalResourceId?.split('/')?.pop() || '';\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, 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 { 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 const response = await medplum.get(cleanUrl(url));\n if (options.asTransaction) {\n prettyPrint(convertToTransactionBundle(response));\n } else {\n prettyPrint(response);\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 { 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, normalizeErrorString } from '@medplum/core';\nimport { Command } from 'commander';\nimport dotenv from 'dotenv';\nimport { login, whoami } from './auth';\nimport { aws } from './aws';\nimport { bot, createBotDeprecate, deployBotDeprecate, saveBotDeprecate } from './bots';\nimport { project } from './projects';\nimport { deleteObject, get, patch, post, put } from './rest';\nimport { FileSystemStorage } from './storage';\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 // AWS commands\n index.addCommand(aws);\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({\n fetch,\n baseUrl,\n storage: new FileSystemStorage(),\n onUnauthenticated: onUnauthenticated,\n });\n main(medplumClient, process.argv).catch((err) => console.error('Unhandled error:', err));\n}\n\nfunction onUnauthenticated(): void {\n console.log('Unauthenticated: run `npx medplum login` to sign in');\n}\n"],"names":["Command","medplum","createServer","getDisplayString","normalizeErrorString","os","platform","exec","CloudFormationClient","ECSClient","UpdateServiceCommand","ListStacksCommand","DescribeStacksCommand","DescribeStackResourcesCommand","path","resolve","existsSync","readFileSync","writeFile","convertToTransactionBundle","ClientStorage","homedir","mkdirSync","writeFileSync","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.16",
3
+ "version": "2.0.17",
4
4
  "description": "Medplum Command Line Interface",
5
5
  "author": "Medplum <hello@medplum.com>",
6
6
  "license": "Apache-2.0",
@@ -17,7 +17,11 @@
17
17
  "test": "jest"
18
18
  },
19
19
  "dependencies": {
20
+ "@aws-sdk/client-cloudformation": "3.319.0",
21
+ "@aws-sdk/client-ecs": "3.319.0",
22
+ "@aws-sdk/client-s3": "3.319.0",
20
23
  "@medplum/core": "*",
24
+ "aws-sdk-client-mock": "2.1.1",
21
25
  "commander": "10.0.1",
22
26
  "dotenv": "16.0.3",
23
27
  "node-fetch": "2.6.9"