dhti-cli 0.5.0 → 0.7.0
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 +12 -4
- package/dist/commands/compose.js +3 -1
- package/dist/commands/docktor.d.ts +1 -1
- package/dist/commands/docktor.js +88 -78
- package/dist/commands/mimic.d.ts +1 -0
- package/dist/commands/mimic.js +24 -6
- package/dist/commands/synthea.d.ts +73 -0
- package/dist/commands/synthea.js +579 -0
- package/dist/resources/docker-compose-master.yml +135 -23
- package/oclif.manifest.json +176 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
- 🚀 *Dhanvantari rose out of the water with his four hands, holding a pot full of elixirs!*
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
### TL; DR: 🏥 DHTI enables rapid prototyping, sharing, and testing of GenAI healthcare applications within an EHR, facilitating the seamless transition of your experiments to practice!
|
|
17
17
|
👉 [Try it out today!](#try-it-out) and give us a star ⭐️ if you like it!
|
|
18
18
|
|
|
19
19
|
### About
|
|
@@ -62,8 +62,6 @@ The essence of DHTI is *modularity* with an emphasis on *configuration!* It is n
|
|
|
62
62
|
<img src="https://github.com/dermatologist/dhti/blob/develop/notes/arch-1.drawio.svg" />
|
|
63
63
|
</p>
|
|
64
64
|
|
|
65
|
-
🔥 **Coming soon!:** We are currently working on expanding the DHTI architecture to support traditional machine learning models, such as *EEG sleep stage classification* and *trichogram analysis*, exposing inference pipelines as agentic tools!
|
|
66
|
-
|
|
67
65
|
## ✨ Features
|
|
68
66
|
* **Modular**: Supports installable Gen AI routines and UI elements.
|
|
69
67
|
* **Quick prototyping**: CLI helps in quick prototyping and testing of Gen AI routines and UI elements.
|
|
@@ -71,7 +69,7 @@ The essence of DHTI is *modularity* with an emphasis on *configuration!* It is n
|
|
|
71
69
|
* **Developer friendly**: Copy working files to running containers for testing.
|
|
72
70
|
* **Dry-run mode**: Preview changes before execution with the `--dry-run` flag.
|
|
73
71
|
* **Dependency Injection**: Dependency injection for models and hyperparameters for configuring elixirs.
|
|
74
|
-
* **Generate synthetic data**: DHTI supports generating synthetic data for testing.
|
|
72
|
+
* **Generate synthetic data**: [DHTI supports generating synthetic data for testing, using synthea.](/notes/SYNTHEA.md)
|
|
75
73
|
* **CQL support**: [CQL for clinical decision support](https://nuchange.ca/2025/06/v-llm-in-the-loop-cql-execution-with-unstructured-data-and-fhir-terminology-support.html).
|
|
76
74
|
* **FHIR**: Data exchange with FHIR schema.
|
|
77
75
|
* **MCP**: Built in MCP server for pluggable tools.
|
|
@@ -81,6 +79,15 @@ The essence of DHTI is *modularity* with an emphasis on *configuration!* It is n
|
|
|
81
79
|
* **Graph utilities**: Neo4j for graph utilities.
|
|
82
80
|
* **LLM**: Ollama for self-hosting LLM models.
|
|
83
81
|
|
|
82
|
+
## ✨ New
|
|
83
|
+
* **MCPX integration**: DHTI now includes an [MCP integrator](https://docs.lunar.dev/mcpx/) that allows other MCP servers to be "installed" and exposed seamlessly to DHTI through the MCPX gateway.
|
|
84
|
+
* **DOCKTOR module**: A new module, [DOCKTOR](/notes/DOCKTOR.md), support traditional machine learning model packaged as Docker containers, to be used as MCP tools, enabling the deployment of inference pipelines as agent-invokable tools. (in beta)
|
|
85
|
+
* **MCP aware agent**: [dhti-elixir-template](https://github.com/dermatologist/dhti-elixir-template) used in the examples now includes an [MCP aware agent](https://github.com/dermatologist/dhti-elixir-template/blob/feature/agent-2/src/dhti_elixir_template/chain.py) that can autodiscover and invoke tools from the MCPX gateway. Install it using `npx dhti-cli elixir install -g https://github.com/dermatologist/dhti-elixir-template.git -n dhti-elixir-template -b feature/agent2`.
|
|
86
|
+
* **Medplum integration**: [Medplum](https://www.medplum.com/) is now supported as an alternative FHIR server. Read more [here](/notes/medplum.md). This allows you to add FHIR subscriptions for real-time updates and much more.
|
|
87
|
+
* **Synthea integration**: You can now generate synthetic FHIR data using [Synthea](https://synthetichealth.github.io/synthea/). Read more [here](/notes/SYNTHEA.md).
|
|
88
|
+
* **MIMIC support**: You can now load [MIMIC Demo](https://physionet.org/content/mimic-iv-demo/2.2/) data using DHTI in [one command](https://nuchange.ca/2024/11/loading-mimic-dataset-onto-a-fhir-server-in-two-easy-steps.html).
|
|
89
|
+
|
|
90
|
+
|
|
84
91
|
## 🔧 For Gen AI Developers
|
|
85
92
|
|
|
86
93
|
*Developers can build elixirs and conchs for DHTI.*
|
|
@@ -124,6 +131,7 @@ Tools to fine-tune language models for the stack are on our roadmap. We encourag
|
|
|
124
131
|
## :sparkles: Resources (in Alpha)
|
|
125
132
|
* [cookiecutter for scaffolding elixirs](https://github.com/dermatologist/cookiecutter-uv)
|
|
126
133
|
* [cds-hooks-sandbox for testing](https://github.com/dermatologist/cds-hooks-sandbox/tree/dhti-1)
|
|
134
|
+
* [Medplum integration](/notes/medplum.md)
|
|
127
135
|
|
|
128
136
|
## :sunglasses: Coming soon
|
|
129
137
|
|
package/dist/commands/compose.js
CHANGED
|
@@ -59,15 +59,17 @@ export default class Compose extends Command {
|
|
|
59
59
|
const mcpFhir = ['mcp-fhir', 'fhir', 'postgres-db'];
|
|
60
60
|
const mcpx = ['mcpx'];
|
|
61
61
|
const docktor = ['mcpx'];
|
|
62
|
+
const medplum = ['medplum-server', 'medplum-app', 'postgres-db', 'redis', 'mpclient'];
|
|
62
63
|
const _modules = {
|
|
63
64
|
cqlFhir,
|
|
65
|
+
docktor,
|
|
64
66
|
fhir,
|
|
65
67
|
gateway,
|
|
66
68
|
langfuse,
|
|
67
69
|
langserve,
|
|
68
70
|
mcpFhir,
|
|
69
71
|
mcpx,
|
|
70
|
-
|
|
72
|
+
medplum,
|
|
71
73
|
neo4j,
|
|
72
74
|
ollama,
|
|
73
75
|
openmrs,
|
|
@@ -13,6 +13,6 @@ export default class Docktor extends Command {
|
|
|
13
13
|
'model-path': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
14
|
workdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
15
|
};
|
|
16
|
-
private restartMcpxContainer;
|
|
17
16
|
run(): Promise<void>;
|
|
17
|
+
private restartMcpxContainer;
|
|
18
18
|
}
|
package/dist/commands/docktor.js
CHANGED
|
@@ -22,8 +22,8 @@ export default class Docktor extends Command {
|
|
|
22
22
|
}),
|
|
23
23
|
environment: Flags.string({
|
|
24
24
|
char: 'e',
|
|
25
|
-
multiple: true,
|
|
26
25
|
description: 'Environment variables to pass to docker (format: VAR=value)',
|
|
26
|
+
multiple: true,
|
|
27
27
|
}),
|
|
28
28
|
image: Flags.string({ char: 'i', description: 'Docker image for the inference pipeline (required for install)' }),
|
|
29
29
|
'model-path': Flags.string({
|
|
@@ -37,18 +37,6 @@ export default class Docktor extends Command {
|
|
|
37
37
|
description: 'Working directory for MCPX config',
|
|
38
38
|
}),
|
|
39
39
|
};
|
|
40
|
-
async restartMcpxContainer(mcpxConfigPath, containerName) {
|
|
41
|
-
try {
|
|
42
|
-
const { execSync } = await import('node:child_process');
|
|
43
|
-
execSync(`docker cp ${mcpxConfigPath} ${containerName}:/lunar/packages/mcpx-server/`);
|
|
44
|
-
this.log(chalk.green('Copied mcp.json to container: /lunar/packages/mcpx-server/config/mcp.json'));
|
|
45
|
-
execSync(`docker restart ${containerName}`);
|
|
46
|
-
this.log(chalk.green(`Restarted ${containerName} container.`));
|
|
47
|
-
}
|
|
48
|
-
catch (err) {
|
|
49
|
-
this.log(chalk.red(`Failed to copy config or restart container '${containerName}'. Please check Docker status and container name.`));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
40
|
async run() {
|
|
53
41
|
const { args, flags } = await this.parse(Docktor);
|
|
54
42
|
const mcpxConfigPath = path.join(flags.workdir, 'config');
|
|
@@ -61,83 +49,105 @@ export default class Docktor extends Command {
|
|
|
61
49
|
if (!fs.existsSync(mcpJsonPath)) {
|
|
62
50
|
fs.writeFileSync(mcpJsonPath, JSON.stringify({ mcpServers: {} }, null, 2));
|
|
63
51
|
}
|
|
64
|
-
|
|
52
|
+
const mcpConfig = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf8'));
|
|
65
53
|
// Ensure mcpServers exists
|
|
66
54
|
if (!mcpConfig.mcpServers) {
|
|
67
55
|
mcpConfig.mcpServers = {};
|
|
68
56
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
57
|
+
switch (args.op) {
|
|
58
|
+
case 'install': {
|
|
59
|
+
if (!args.name) {
|
|
60
|
+
this.error('Name is required for install operation');
|
|
61
|
+
}
|
|
62
|
+
if (!flags.image) {
|
|
63
|
+
this.error('Image is required for install operation');
|
|
64
|
+
}
|
|
65
|
+
const binds = [];
|
|
66
|
+
const envVars = [];
|
|
67
|
+
if (flags['model-path']) {
|
|
68
|
+
const absModelPath = path.resolve(flags['model-path']);
|
|
69
|
+
binds.push(`${absModelPath}:/model`);
|
|
70
|
+
}
|
|
71
|
+
if (flags.environment && flags.environment.length > 0) {
|
|
72
|
+
const invalidEnvVars = flags.environment.filter((e) => {
|
|
73
|
+
const idx = e.indexOf('=');
|
|
74
|
+
return idx <= 0 || idx === e.length - 1;
|
|
75
|
+
});
|
|
76
|
+
if (invalidEnvVars.length > 0) {
|
|
77
|
+
this.error(`Invalid environment variable format. Expected 'NAME=value'. Invalid entries: ${invalidEnvVars.join(', ')}`);
|
|
78
|
+
}
|
|
79
|
+
envVars.push(...flags.environment);
|
|
80
|
+
}
|
|
81
|
+
// Add socket mounting for docker tools if needed, but primarily we want the container to run as a server
|
|
82
|
+
// MCPX handles the running of the docker container.
|
|
83
|
+
// We need to configure it in mcp.json so MCPX picks it up.
|
|
84
|
+
// Based on MCP std, docker servers are defined with `docker` command.
|
|
85
|
+
// Add (merge) new server into existing mcpServers
|
|
86
|
+
mcpConfig.mcpServers[args.name] = {
|
|
87
|
+
args: [
|
|
88
|
+
'run',
|
|
89
|
+
'-i',
|
|
90
|
+
'--rm',
|
|
91
|
+
...binds.flatMap((b) => ['-v', b]),
|
|
92
|
+
...envVars.flatMap((e) => ['-e', e]),
|
|
93
|
+
flags.image,
|
|
94
|
+
],
|
|
95
|
+
command: 'docker',
|
|
96
|
+
};
|
|
97
|
+
// Write back the updated config (preserving all other properties and existing servers)
|
|
98
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
99
|
+
this.log(chalk.green(`Inference pipeline '${args.name}' added`));
|
|
100
|
+
// Copy only mcp.json to container and restart (non-fatal if it fails)
|
|
101
|
+
try {
|
|
102
|
+
await this.restartMcpxContainer(mcpxConfigPath, flags.container);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
this.log(chalk.yellow('Note: Could not restart container. Please restart manually if needed.'));
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
81
108
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
109
|
+
case 'remove': {
|
|
110
|
+
if (!args.name) {
|
|
111
|
+
this.error('Name is required for remove operation');
|
|
112
|
+
}
|
|
113
|
+
if (mcpConfig.mcpServers && mcpConfig.mcpServers[args.name]) {
|
|
114
|
+
delete mcpConfig.mcpServers[args.name];
|
|
115
|
+
// Write back the updated config (preserving all other properties and remaining servers)
|
|
116
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
117
|
+
this.log(chalk.green(`Inference pipeline '${args.name}' removed`));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.log(chalk.yellow(`Inference pipeline '${args.name}' not found.`));
|
|
89
121
|
}
|
|
90
|
-
|
|
122
|
+
break;
|
|
91
123
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// Based on MCP std, docker servers are defined with `docker` command.
|
|
96
|
-
// Add (merge) new server into existing mcpServers
|
|
97
|
-
mcpConfig.mcpServers[args.name] = {
|
|
98
|
-
command: 'docker',
|
|
99
|
-
args: [
|
|
100
|
-
'run',
|
|
101
|
-
'-i',
|
|
102
|
-
'--rm',
|
|
103
|
-
...binds.flatMap((b) => ['-v', b]),
|
|
104
|
-
...envVars.flatMap((e) => ['-e', e]),
|
|
105
|
-
flags.image,
|
|
106
|
-
],
|
|
107
|
-
};
|
|
108
|
-
// Write back the updated config (preserving all other properties and existing servers)
|
|
109
|
-
fs.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
110
|
-
this.log(chalk.green(`Inference pipeline '${args.name}' added to MCPX config.`));
|
|
111
|
-
// Copy only mcp.json to container and restart
|
|
112
|
-
await this.restartMcpxContainer(mcpxConfigPath, flags.container);
|
|
113
|
-
}
|
|
114
|
-
else if (args.op === 'remove') {
|
|
115
|
-
if (!args.name) {
|
|
116
|
-
this.error('Name is required for remove operation');
|
|
124
|
+
case 'restart': {
|
|
125
|
+
await this.restartMcpxContainer(mcpxConfigPath, flags.container);
|
|
126
|
+
break;
|
|
117
127
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
128
|
+
case 'list': {
|
|
129
|
+
this.log(chalk.blue('Installed Inference Pipelines:'));
|
|
130
|
+
for (const [name, config] of Object.entries(mcpConfig.mcpServers)) {
|
|
131
|
+
const argsList = Array.isArray(config.args) ? config.args.join(' ') : '';
|
|
132
|
+
this.log(`- ${name}: ${argsList}`);
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
124
135
|
}
|
|
125
|
-
|
|
126
|
-
this.
|
|
136
|
+
default: {
|
|
137
|
+
this.error(`Unknown operation: ${args.op}`);
|
|
127
138
|
}
|
|
128
139
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
140
|
+
}
|
|
141
|
+
async restartMcpxContainer(mcpxConfigPath, containerName) {
|
|
142
|
+
try {
|
|
143
|
+
const { execSync } = await import('node:child_process');
|
|
144
|
+
execSync(`docker cp ${mcpxConfigPath} ${containerName}:/lunar/packages/mcpx-server/`);
|
|
145
|
+
this.log(chalk.green('Copied mcp.json to container: /lunar/packages/mcpx-server/config/mcp.json'));
|
|
146
|
+
execSync(`docker restart ${containerName}`);
|
|
147
|
+
this.log(chalk.green(`Restarted ${containerName} container.`));
|
|
138
148
|
}
|
|
139
|
-
|
|
140
|
-
this.
|
|
149
|
+
catch {
|
|
150
|
+
this.log(chalk.red(`Failed to copy config or restart container '${containerName}'. Please check Docker status and container name.`));
|
|
141
151
|
}
|
|
142
152
|
}
|
|
143
153
|
}
|
package/dist/commands/mimic.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export default class Mimic extends Command {
|
|
|
7
7
|
static examples: string[];
|
|
8
8
|
static flags: {
|
|
9
9
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
11
|
};
|
|
11
12
|
run(): Promise<void>;
|
|
12
13
|
}
|
package/dist/commands/mimic.js
CHANGED
|
@@ -11,9 +11,18 @@ export default class Mimic extends Command {
|
|
|
11
11
|
default: false,
|
|
12
12
|
description: 'Show what changes would be made without actually making them',
|
|
13
13
|
}),
|
|
14
|
+
token: Flags.string({
|
|
15
|
+
char: 't',
|
|
16
|
+
description: 'Bearer token for authentication (optional)',
|
|
17
|
+
}),
|
|
14
18
|
};
|
|
15
19
|
async run() {
|
|
16
20
|
const { args, flags } = await this.parse(Mimic);
|
|
21
|
+
// Ensure server URL ends with /$import
|
|
22
|
+
let serverUrl = args.server;
|
|
23
|
+
if (!serverUrl.endsWith('/$import')) {
|
|
24
|
+
serverUrl = serverUrl.replace(/\/$/, '') + '/$import';
|
|
25
|
+
}
|
|
17
26
|
const mimic_request = `{
|
|
18
27
|
|
|
19
28
|
"resourceType": "Parameters",
|
|
@@ -148,25 +157,34 @@ export default class Mimic extends Command {
|
|
|
148
157
|
|
|
149
158
|
}`;
|
|
150
159
|
if (flags['dry-run']) {
|
|
151
|
-
console.log(chalk.yellow(`[DRY RUN] Would send POST request to: ${
|
|
160
|
+
console.log(chalk.yellow(`[DRY RUN] Would send POST request to: ${serverUrl}`));
|
|
152
161
|
console.log(chalk.cyan('[DRY RUN] Request headers:'));
|
|
153
162
|
console.log(chalk.green(' Content-Type: application/fhir+json'));
|
|
154
163
|
console.log(chalk.green(' Prefer: respond-async'));
|
|
164
|
+
if (flags.token) {
|
|
165
|
+
console.log(chalk.green(' Authorization: Bearer <token>'));
|
|
166
|
+
}
|
|
155
167
|
console.log(chalk.cyan('[DRY RUN] Request body:'));
|
|
156
168
|
console.log(mimic_request);
|
|
157
169
|
return;
|
|
158
170
|
}
|
|
171
|
+
// Build request headers
|
|
172
|
+
const headers = {
|
|
173
|
+
'Content-Type': 'application/fhir+json',
|
|
174
|
+
Prefer: 'respond-async',
|
|
175
|
+
};
|
|
176
|
+
if (flags.token) {
|
|
177
|
+
headers.Authorization = `Bearer ${flags.token}`;
|
|
178
|
+
}
|
|
159
179
|
// send a POST request to the server with the mimic_request body
|
|
160
|
-
const response = await fetch(
|
|
180
|
+
const response = await fetch(serverUrl, {
|
|
161
181
|
body: mimic_request,
|
|
162
|
-
headers
|
|
163
|
-
'Content-Type': 'application/fhir+json',
|
|
164
|
-
Prefer: 'respond-async',
|
|
165
|
-
},
|
|
182
|
+
headers,
|
|
166
183
|
method: 'POST',
|
|
167
184
|
});
|
|
168
185
|
if (!response.ok) {
|
|
169
186
|
console.error(`Error: ${response.status} ${response.statusText}`);
|
|
187
|
+
this.exit(1);
|
|
170
188
|
}
|
|
171
189
|
}
|
|
172
190
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
/**
|
|
3
|
+
* Synthea command for managing synthetic FHIR data generation
|
|
4
|
+
*
|
|
5
|
+
* This command provides subcommands to:
|
|
6
|
+
* - install: Download and install Synthea JAR file
|
|
7
|
+
* - generate: Generate synthetic FHIR data using Synthea
|
|
8
|
+
* - upload: Upload generated FHIR resources to a FHIR server
|
|
9
|
+
* - delete: Clean up generated synthetic data
|
|
10
|
+
* - download: Download pre-generated Synthea datasets
|
|
11
|
+
*/
|
|
12
|
+
export default class Synthea extends Command {
|
|
13
|
+
static args: {
|
|
14
|
+
subcommand: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
15
|
+
};
|
|
16
|
+
static description: string;
|
|
17
|
+
static examples: string[];
|
|
18
|
+
static flags: {
|
|
19
|
+
age: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
city: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
+
covid19: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
|
+
covid19_10k: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
23
|
+
covid19_csv: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
24
|
+
covid19_csv_10k: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
25
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
endpoint: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
|
+
gender: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
|
+
population: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
29
|
+
seed: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
30
|
+
state: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
31
|
+
synthea_sample_data_csv_latest: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
32
|
+
synthea_sample_data_fhir_latest: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
33
|
+
synthea_sample_data_fhir_stu3_latest: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
34
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
|
+
workdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Main command execution
|
|
39
|
+
* Dispatches to appropriate subcommand handler
|
|
40
|
+
* @returns Promise that resolves when subcommand completes
|
|
41
|
+
*/
|
|
42
|
+
run(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Delete synthetic data
|
|
45
|
+
* @param flags Command flags including workdir and dry-run
|
|
46
|
+
* @returns Promise that resolves when deletion completes
|
|
47
|
+
*/
|
|
48
|
+
private delete;
|
|
49
|
+
/**
|
|
50
|
+
* Download pre-generated Synthea datasets
|
|
51
|
+
* @param flags Command flags including workdir, dataset selections, and dry-run
|
|
52
|
+
* @returns Promise that resolves when download completes
|
|
53
|
+
*/
|
|
54
|
+
private download;
|
|
55
|
+
/**
|
|
56
|
+
* Generate synthetic FHIR data
|
|
57
|
+
* @param flags Command flags including population, state, city, gender, age, seed, workdir, and dry-run
|
|
58
|
+
* @returns Promise that resolves when generation completes
|
|
59
|
+
*/
|
|
60
|
+
private generate;
|
|
61
|
+
/**
|
|
62
|
+
* Install Synthea JAR file
|
|
63
|
+
* @param flags Command flags including workdir and dry-run
|
|
64
|
+
* @returns Promise that resolves when installation completes
|
|
65
|
+
*/
|
|
66
|
+
private install;
|
|
67
|
+
/**
|
|
68
|
+
* Upload FHIR resources to server
|
|
69
|
+
* @param flags Command flags including endpoint, token, workdir, and dry-run
|
|
70
|
+
* @returns Promise that resolves when upload completes
|
|
71
|
+
*/
|
|
72
|
+
private upload;
|
|
73
|
+
}
|