@medplum/cli 0.9.2
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.
- package/README.md +95 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Medplum Command Line Interface
|
|
2
|
+
|
|
3
|
+
The Medplum CLI (Command Line Interface) is a set of command line tools to quickly deploy Medplum web applications and Medplum bots.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add as a dependency:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @medplum/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Syntax:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
medplum <command> <args>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
At present, there is only one command called `deploy-bot`. Syntax:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
medplum deploy-bot <filename> <bot-id>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
medplum deploy-bot dist/hello-world.js e54fa800-02ab-41be-8d48-8c027dd85ccc
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
In practice, consider adding the command to the `"scripts"` section of your package.json:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"deploy:hello-world": "medplum deploy-bot dist/hello-world.js e54fa800-02ab-41be-8d48-8c0200000000"
|
|
39
|
+
},
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then, from the command line, run:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm run deploy:hello-world
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Authentication requires client credentials in the form of environment variables `MEDPLUM_CLIENT_ID` and `MEDPLUM_CLIENT_SECRET`. This supports most use cases, including secrets from CI/CD. `dotenv` is enabled, so you could store them in `.env` file.
|
|
49
|
+
|
|
50
|
+
## Example
|
|
51
|
+
|
|
52
|
+
Write your bot. This can be TypeScript. It can reference `@medplum/core` and `node-fetch`:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { MedplumClient } from '@medplum/core';
|
|
56
|
+
import { Resource } from '@medplum/fhirtypes';
|
|
57
|
+
|
|
58
|
+
export async function handler(medplum: MedplumClient, input: Resource): Promise<any> {
|
|
59
|
+
console.log('Hello world');
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Compile with vanilla `tsc` (no build tools required)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx tsc
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm run build
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
You get sensible plain old JavaScript output:
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
export async function handler(medplum, input) {
|
|
79
|
+
console.log('Hello world');
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
You can then use the Medplum CLI to deploy it.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm run deploy:hello-world
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## About Medplum
|
|
90
|
+
|
|
91
|
+
Medplum is a healthcare platform that helps you quickly develop high-quality compliant applications. Medplum includes a FHIR server, React component library, and developer app.
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
Apache 2.0. Copyright © Medplum 2022
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.main = void 0;
|
|
17
|
+
const core_1 = require("@medplum/core");
|
|
18
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
19
|
+
const fs_1 = require("fs");
|
|
20
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
21
|
+
const path_1 = require("path");
|
|
22
|
+
function main(medplum, argv) {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
dotenv_1.default.config();
|
|
25
|
+
if (argv.length < 3) {
|
|
26
|
+
console.log('Usage: medplum <command>');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const command = argv[2];
|
|
30
|
+
if (command === 'deploy-bot') {
|
|
31
|
+
yield deployBot(medplum, argv);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log(`Unknown command: ${command}`);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
exports.main = main;
|
|
39
|
+
function deployBot(medplum, argv) {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
if (argv.length < 5) {
|
|
42
|
+
console.log('Usage: medplum deploy-bot <bot-name> <bot-id>');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const botId = argv[4];
|
|
46
|
+
if (!botId) {
|
|
47
|
+
console.log('Error: Bot ID is not set');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const filePath = (0, path_1.resolve)(process.cwd(), argv[3]);
|
|
51
|
+
if (!(0, fs_1.existsSync)(filePath)) {
|
|
52
|
+
console.log('Error: Bot file does not exist: ' + filePath);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const bot = yield medplum.readResource('Bot', botId);
|
|
56
|
+
if (!bot) {
|
|
57
|
+
console.log('Error: Bot does not exist: ' + botId);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
console.log(JSON.stringify(bot, null, 2));
|
|
61
|
+
try {
|
|
62
|
+
console.log('Update bot code.....');
|
|
63
|
+
const result = yield medplum.updateResource(Object.assign(Object.assign({}, bot), { code: (0, fs_1.readFileSync)(filePath, 'utf8') }));
|
|
64
|
+
console.log(JSON.stringify(result, null, 2));
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.log('Patch error: ', err);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (process.argv[1].includes('medplum') && process.argv[1].includes('cli')) {
|
|
72
|
+
const medplum = new core_1.MedplumClient({ fetch: node_fetch_1.default });
|
|
73
|
+
medplum
|
|
74
|
+
.clientCredentials(process.env['MEDPLUM_CLIENT_ID'], process.env['MEDPLUM_CLIENT_SECRET'])
|
|
75
|
+
.then(() => {
|
|
76
|
+
main(medplum, process.argv).catch((err) => console.error('Unhandled error:', err));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { MedplumClient } from '@medplum/core';\nimport { Bot } from '@medplum/fhirtypes';\nimport dotenv from 'dotenv';\nimport { existsSync, readFileSync } from 'fs';\nimport fetch from 'node-fetch';\nimport { resolve } from 'path';\n\nexport async function main(medplum: MedplumClient, argv: string[]): Promise<void> {\n dotenv.config();\n\n if (argv.length < 3) {\n console.log('Usage: medplum <command>');\n return;\n }\n\n const command = argv[2];\n if (command === 'deploy-bot') {\n await deployBot(medplum, argv);\n } else {\n console.log(`Unknown command: ${command}`);\n }\n}\n\nasync function deployBot(medplum: MedplumClient, argv: string[]): Promise<void> {\n if (argv.length < 5) {\n console.log('Usage: medplum deploy-bot <bot-name> <bot-id>');\n return;\n }\n\n const botId = argv[4];\n if (!botId) {\n console.log('Error: Bot ID is not set');\n return;\n }\n\n const filePath = resolve(process.cwd(), argv[3]);\n if (!existsSync(filePath)) {\n console.log('Error: Bot file does not exist: ' + filePath);\n return;\n }\n\n const bot = await medplum.readResource<Bot>('Bot', botId);\n if (!bot) {\n console.log('Error: Bot does not exist: ' + botId);\n return;\n }\n console.log(JSON.stringify(bot, null, 2));\n\n try {\n console.log('Update bot code.....');\n const result = await medplum.updateResource({\n ...bot,\n code: readFileSync(filePath, 'utf8'),\n });\n console.log(JSON.stringify(result, null, 2));\n } catch (err) {\n console.log('Patch error: ', err);\n }\n}\n\nif (process.argv[1].includes('medplum') && process.argv[1].includes('cli')) {\n const medplum = new MedplumClient({ fetch });\n medplum\n .clientCredentials(process.env['MEDPLUM_CLIENT_ID'] as string, process.env['MEDPLUM_CLIENT_SECRET'] as string)\n .then(() => {\n main(medplum, process.argv).catch((err) => console.error('Unhandled error:', err));\n });\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@medplum/cli",
|
|
3
|
+
"version": "0.9.2",
|
|
4
|
+
"description": "Medplum Command Line Interface",
|
|
5
|
+
"author": "Medplum <hello@medplum.com>",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"homepage": "https://www.medplum.com/",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/medplum/medplum.git",
|
|
11
|
+
"directory": "packages/cli"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"clean": "rimraf dist",
|
|
15
|
+
"build": "npm run clean && tsc",
|
|
16
|
+
"test": "jest"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@medplum/core": "0.9.2",
|
|
20
|
+
"dotenv": "16.0.0",
|
|
21
|
+
"node-fetch": "2.6.7"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@medplum/fhirtypes": "0.9.2",
|
|
25
|
+
"@medplum/mock": "0.9.2"
|
|
26
|
+
},
|
|
27
|
+
"bin": {
|
|
28
|
+
"medplum": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"medplum",
|
|
32
|
+
"fhir",
|
|
33
|
+
"healthcare",
|
|
34
|
+
"interoperability",
|
|
35
|
+
"json",
|
|
36
|
+
"serialization",
|
|
37
|
+
"hl7",
|
|
38
|
+
"standards",
|
|
39
|
+
"clinical",
|
|
40
|
+
"dstu2",
|
|
41
|
+
"stu3",
|
|
42
|
+
"r4",
|
|
43
|
+
"normative"
|
|
44
|
+
]
|
|
45
|
+
}
|