dhti-cli 0.8.0 → 1.1.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.
@@ -0,0 +1,44 @@
1
+ .container {
2
+ padding: 1rem;
3
+ background-color: var(--ui-01);
4
+ border: 1px solid var(--ui-03);
5
+ margin-bottom: 1rem;
6
+ }
7
+
8
+ .header {
9
+ margin-bottom: 1rem;
10
+ h3 {
11
+ margin: 0;
12
+ }
13
+ }
14
+
15
+ .content {
16
+ display: flex;
17
+ gap: 2rem;
18
+ flex-wrap: wrap;
19
+ }
20
+
21
+ .observations, .aiInsights {
22
+ flex: 1;
23
+ min-width: 300px;
24
+ }
25
+
26
+ .observations ul {
27
+ list-style: none;
28
+ padding: 0;
29
+ li {
30
+ margin-bottom: 0.5rem;
31
+ border-bottom: 1px solid var(--ui-03);
32
+ padding-bottom: 0.25rem;
33
+ }
34
+ }
35
+
36
+ .aiContent {
37
+ background-color: var(--ui-02);
38
+ padding: 1rem;
39
+ border-radius: 4px;
40
+ }
41
+
42
+ .error {
43
+ color: var(--support-01);
44
+ }
@@ -0,0 +1,69 @@
1
+ import {useState} from 'react'
2
+ import axios from 'axios'
3
+ import {CDSHookRequest} from '../models/request'
4
+ import {CDSHookCard} from '../models/card'
5
+ import {useConfig, openmrsFetch, fhirBaseUrl} from '@openmrs/esm-framework'
6
+
7
+ interface UseDhtiReturn {
8
+ submitMessage: (newMessage: string, patientId?: string) => Promise<CDSHookCard | null>
9
+ loading: boolean
10
+ error: string | null
11
+ }
12
+
13
+ /**
14
+ * Custom hook to handle DHTI service submissions
15
+ * @returns Object with submitMessage function, loading state, and error state
16
+ */
17
+ export const useDhti = (): UseDhtiReturn => {
18
+ const [loading, setLoading] = useState<boolean>(false)
19
+ const [error, setError] = useState<string | null>(null)
20
+ const config = useConfig()
21
+
22
+ const submitMessage = async (newMessage: string, patientId?: string): Promise<CDSHookCard | null> => {
23
+ setLoading(true)
24
+ setError(null)
25
+
26
+ try {
27
+ const request = new CDSHookRequest({
28
+ context: {input: newMessage, patientId: patientId || undefined},
29
+ })
30
+
31
+ // TODO: Investigate why nested input is required
32
+ const _request = {
33
+ input: request,
34
+ }
35
+
36
+ const response = await axios.post(
37
+ config?.dhtiRoute || 'http://localhost:8001/langserve/dhti_elixir_template/cds-services/dhti-service',
38
+ {
39
+ input: _request,
40
+ config: {},
41
+ kwargs: {},
42
+ },
43
+ {
44
+ headers: {
45
+ 'Access-Control-Allow-Origin': '*',
46
+ },
47
+ },
48
+ )
49
+
50
+ // Assuming the response contains a card or cards
51
+ if (response.data && response.data.cards && response.data.cards.length > 0) {
52
+ return CDSHookCard.from(response.data.cards[0])
53
+ } else if (response.data && response.data.summary) {
54
+ // Handle case where response is directly a card (must have summary property)
55
+ return CDSHookCard.from(response.data)
56
+ }
57
+
58
+ return null
59
+ } catch (err: any) {
60
+ const errorMessage = err.response?.data?.message || err.message || 'Failed to submit message'
61
+ setError(errorMessage)
62
+ return null
63
+ } finally {
64
+ setLoading(false)
65
+ }
66
+ }
67
+
68
+ return {submitMessage, loading, error}
69
+ }
@@ -0,0 +1,61 @@
1
+ import useSWR from 'swr'
2
+ import {fhirBaseUrl, openmrsFetch} from '@openmrs/esm-framework'
3
+
4
+ /**
5
+ * This hook searches for a patient using the provided search term from the
6
+ * OpenMRS FHIR API. It leverages the useSWR hook from the SWR library
7
+ * https://swr.vercel.app/docs/data-fetching to fetch data. SWR provides a
8
+ * number of benefits over the standard React useEffect hook, including:
9
+ *
10
+ * - Fast, lightweight and reusable data fetching
11
+ * - Built-in cache and request deduplication
12
+ * - Real-time updates
13
+ * - Simplified error and loading state handling, and more.
14
+ *
15
+ * We recommend using SWR for data fetching in your OpenMRS frontend modules.
16
+ *
17
+ * See the docs for the underlying fhir.js Client object: https://github.com/FHIR/fhir.js#api
18
+ * See the OpenMRS FHIR Module docs: https://wiki.openmrs.org/display/projects/OpenMRS+FHIR+Module
19
+ * See the OpenMRS REST API docs: https://rest.openmrs.org/#openmrs-rest-api
20
+ *
21
+ * @param query A patient name or ID
22
+ * @returns The first matching patient
23
+ */
24
+
25
+ export function usePatient(query: string) {
26
+ // If query has a number anywhere in it, treat it as an identifier search
27
+ const isId = /\d/.test(query)
28
+ let url = null
29
+ if (query && query.trim()) {
30
+ if (isId) {
31
+ url = `${fhirBaseUrl}/Patient?identifier=${encodeURIComponent(query.trim())}&_summary=data`
32
+ } else {
33
+ url = `${fhirBaseUrl}/Patient?name=${encodeURIComponent(query.trim())}&_summary=data`
34
+ }
35
+ }
36
+ const {data, error, isLoading} = useSWR<any, Error>(url, openmrsFetch)
37
+
38
+ let patient = null
39
+ // * Use the code below to handle direct ID searches, if needed in future
40
+ // --- IGNORE ---
41
+ // if (isId) {
42
+ // // FHIR /Patient/{id} returns the patient directly
43
+ // if (data && data.resourceType === 'Patient') {
44
+ // patient = data;
45
+ // }
46
+ // } else {
47
+ // if (data && data.data && Array.isArray(data.data.entry) && data.data.entry.length > 0) {
48
+ // patient = data.data.entry[0].resource;
49
+ // }
50
+ // }
51
+
52
+ if (data && data.data && Array.isArray(data.data.entry) && data.data.entry.length > 0) {
53
+ patient = data.data.entry[0].resource
54
+ }
55
+
56
+ return {
57
+ patient,
58
+ error: error,
59
+ isLoading,
60
+ }
61
+ }
@@ -0,0 +1,17 @@
1
+ import {getAsyncLifecycle, defineConfigSchema} from '@openmrs/esm-framework'
2
+ import {configSchema} from './config-schema'
3
+
4
+ const moduleName = '@openmrs/esm-dhti-glycemic'
5
+
6
+ const options = {
7
+ featureName: 'dhti-glycemic',
8
+ moduleName,
9
+ }
10
+
11
+ export const importTranslation = require.context('../translations', false, /.json$/, 'lazy')
12
+
13
+ export function startupApp() {
14
+ defineConfigSchema(moduleName, configSchema)
15
+ }
16
+
17
+ export const glycemic = getAsyncLifecycle(() => import('./glycemic.component'), options)
@@ -0,0 +1,80 @@
1
+ /**
2
+ * TypeScript models for CDS Hook Card
3
+ *
4
+ * Example:
5
+ * {
6
+ * "summary": "Patient is at high risk for opioid overdose.",
7
+ * "detail": "According to CDC guidelines, the patient's opioid dosage should be tapered to less than 50 MME. [Link to CDC Guideline](https://www.cdc.gov/drugoverdose/prescribing/guidelines.html)",
8
+ * "indicator": "warning",
9
+ * "source": {
10
+ * "label": "CDC Opioid Prescribing Guidelines",
11
+ * "url": "https://www.cdc.gov/drugoverdose/prescribing/guidelines.html",
12
+ * "icon": "https://example.org/img/cdc-icon.png"
13
+ * },
14
+ * "links": [
15
+ * {
16
+ * "label": "View MME Conversion Table",
17
+ * "url": "https://www.cdc.gov/drugoverdose/prescribing/mme.html"
18
+ * }
19
+ * ]
20
+ * }
21
+ */
22
+
23
+ /**
24
+ * The allowed indicators for a CDS Hook Card.
25
+ * Mirrors: Literal["info", "warning", "hard-stop"]
26
+ */
27
+ export type CDSHookCardIndicator = 'info' | 'warning' | 'hard-stop'
28
+
29
+ /**
30
+ * Source of the CDS Hook Card
31
+ */
32
+ export class CDSHookCardSource {
33
+ label!: string
34
+ url?: string
35
+ icon?: string
36
+
37
+ constructor(init?: Partial<CDSHookCardSource>) {
38
+ Object.assign(this, init)
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Link associated with the CDS Hook Card
44
+ */
45
+ export class CDSHookCardLink {
46
+ label!: string
47
+ url!: string
48
+
49
+ constructor(init?: Partial<CDSHookCardLink>) {
50
+ Object.assign(this, init)
51
+ }
52
+ }
53
+
54
+ /**
55
+ * CDS Hook Card Model
56
+ */
57
+ export class CDSHookCard {
58
+ summary!: string
59
+ detail?: string
60
+ indicator?: CDSHookCardIndicator
61
+ source?: CDSHookCardSource
62
+ links?: CDSHookCardLink[]
63
+
64
+ constructor(init?: Partial<CDSHookCard>) {
65
+ if (init) {
66
+ // Shallow assign for primitives; nested objects handled below if present
67
+ const {source, links, ...rest} = init as CDSHookCard
68
+ Object.assign(this, rest)
69
+ if (source) this.source = new CDSHookCardSource(source)
70
+ if (links) this.links = links.map((l) => new CDSHookCardLink(l))
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Factory to build a CDSHookCard from a plain object, ensuring nested types are instantiated.
76
+ */
77
+ static from(obj: Partial<CDSHookCard>): CDSHookCard {
78
+ return new CDSHookCard(obj)
79
+ }
80
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * CDS Hook Request Model (TypeScript)
3
+ *
4
+ * Example:
5
+ * {
6
+ * "hookInstance": "d1577c69-dfbe-44ad-ba6d-3e05e953b2ea",
7
+ * "fhirServer": "https://example.com/fhir",
8
+ * "fhirAuthorization": { ... },
9
+ * "hook": "patient-view",
10
+ * "context": { ... },
11
+ * "prefetch": { ... }
12
+ * }
13
+ */
14
+
15
+ export class CDSHookRequest {
16
+ /** A unique identifier for this hook invocation */
17
+ hookInstance?: string
18
+
19
+ /** Base URL of the FHIR server associated with the hook */
20
+ fhirServer?: string
21
+
22
+ /** Authorization details (opaque to this model) */
23
+ fhirAuthorization?: Record<string, any> | null
24
+
25
+ /** Name of the hook (e.g., "patient-view", "order-select", etc.) */
26
+ hook?: string
27
+
28
+ /** Context object passed by the EHR */
29
+ context?: Record<string, any> | null
30
+
31
+ /** Prefetched FHIR resources keyed by name */
32
+ prefetch?: Record<string, any> | null
33
+
34
+ constructor(init?: Partial<CDSHookRequest>) {
35
+ Object.assign(this, init)
36
+ }
37
+
38
+ /** Factory to build a CDSHookRequest from a plain object. */
39
+ static from(obj: Partial<CDSHookRequest>): CDSHookRequest {
40
+ return new CDSHookRequest(obj)
41
+ }
42
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://json.openmrs.org/routes.schema.json",
3
+ "backendDependencies": {
4
+ "fhir2": ">=2.0.0",
5
+ "webservices.rest": ">=2.2.0"
6
+ },
7
+ "extensions": [
8
+ {
9
+ "component": "glycemic",
10
+ "name": "dhti-glycemic-widget",
11
+ "slot": "patient-chart-summary-dashboard-slot",
12
+ "meta": {
13
+ "columnSpan": 4
14
+ }
15
+ }
16
+ ]
17
+ }
@@ -19,6 +19,14 @@
19
19
  "allowNo": false,
20
20
  "type": "boolean"
21
21
  },
22
+ "env": {
23
+ "char": "e",
24
+ "description": "Environment variable name (e.g. FHIR_BASE_URL)",
25
+ "name": "env",
26
+ "hasDynamicHelp": false,
27
+ "multiple": false,
28
+ "type": "option"
29
+ },
22
30
  "file": {
23
31
  "char": "f",
24
32
  "description": "Full path to the docker compose file to read from. Creates if it does not exist",
@@ -28,6 +36,12 @@
28
36
  "multiple": false,
29
37
  "type": "option"
30
38
  },
39
+ "host": {
40
+ "description": "Use host environment variable pattern (e.g. ${VAR_NAME:-default_value})",
41
+ "name": "host",
42
+ "allowNo": false,
43
+ "type": "boolean"
44
+ },
31
45
  "module": {
32
46
  "char": "m",
33
47
  "description": "Modules to add from ( langserve, openmrs, ollama, langfuse, cqlFhir, redis, neo4j, mcpFhir, mcpx and docktor)",
@@ -35,6 +49,23 @@
35
49
  "hasDynamicHelp": false,
36
50
  "multiple": true,
37
51
  "type": "option"
52
+ },
53
+ "service": {
54
+ "char": "s",
55
+ "description": "Service name to update environment variables",
56
+ "name": "service",
57
+ "default": "langserve",
58
+ "hasDynamicHelp": false,
59
+ "multiple": false,
60
+ "type": "option"
61
+ },
62
+ "value": {
63
+ "char": "v",
64
+ "description": "Environment variable value",
65
+ "name": "value",
66
+ "hasDynamicHelp": false,
67
+ "multiple": false,
68
+ "type": "option"
38
69
  }
39
70
  },
40
71
  "hasDynamicHelp": false,
@@ -56,42 +87,27 @@
56
87
  "aliases": [],
57
88
  "args": {
58
89
  "op": {
59
- "description": "Operation to perform (install, uninstall or dev)",
90
+ "description": "Operation to perform (init, install, or start)",
60
91
  "name": "op"
61
92
  }
62
93
  },
63
- "description": "Install or uninstall conchs to create a Docker image",
94
+ "description": "Initialize, install, or start OpenMRS frontend development",
64
95
  "examples": [
65
- "<%= config.bin %> <%= command.id %>"
96
+ "<%= config.bin %> <%= command.id %> install -n my-app -w ~/projects",
97
+ "<%= config.bin %> <%= command.id %> init -n my-app -w ~/projects",
98
+ "<%= config.bin %> <%= command.id %> start -n my-app -w ~/projects",
99
+ "<%= config.bin %> <%= command.id %> start -n my-app -w ~/projects -s packages/chatbot -s packages/utils"
66
100
  ],
67
101
  "flags": {
68
102
  "branch": {
69
103
  "char": "b",
70
- "description": "Branch to install from",
104
+ "description": "Branch to install from (for install operation)",
71
105
  "name": "branch",
72
106
  "default": "develop",
73
107
  "hasDynamicHelp": false,
74
108
  "multiple": false,
75
109
  "type": "option"
76
110
  },
77
- "container": {
78
- "char": "c",
79
- "description": "Name of the container to copy the conch to while in dev mode",
80
- "name": "container",
81
- "default": "dhti-frontend-1",
82
- "hasDynamicHelp": false,
83
- "multiple": false,
84
- "type": "option"
85
- },
86
- "dev": {
87
- "char": "d",
88
- "description": "Dev folder to install",
89
- "name": "dev",
90
- "default": "none",
91
- "hasDynamicHelp": false,
92
- "multiple": false,
93
- "type": "option"
94
- },
95
111
  "dry-run": {
96
112
  "description": "Show what changes would be made without actually making them",
97
113
  "name": "dry-run",
@@ -100,60 +116,40 @@
100
116
  },
101
117
  "git": {
102
118
  "char": "g",
103
- "description": "Github repository to install",
119
+ "description": "GitHub repository to install (for install operation)",
104
120
  "name": "git",
105
- "default": "none",
106
- "hasDynamicHelp": false,
107
- "multiple": false,
108
- "type": "option"
109
- },
110
- "image": {
111
- "char": "i",
112
- "description": "Base image to use for the conch",
113
- "name": "image",
114
- "default": "openmrs/openmrs-reference-application-3-frontend:3.0.0-beta.17",
121
+ "default": "dermatologist/openmrs-esm-dhti-template",
115
122
  "hasDynamicHelp": false,
116
123
  "multiple": false,
117
124
  "type": "option"
118
125
  },
119
126
  "local": {
120
127
  "char": "l",
121
- "description": "Local directory to install from",
128
+ "description": "Local path to use instead of calculated workdir/name path (for start operation)",
122
129
  "name": "local",
123
- "default": "none",
124
130
  "hasDynamicHelp": false,
125
131
  "multiple": false,
126
132
  "type": "option"
127
133
  },
128
134
  "name": {
129
135
  "char": "n",
130
- "description": "Name of the elixir",
136
+ "description": "Name of the conch",
131
137
  "name": "name",
132
138
  "hasDynamicHelp": false,
133
139
  "multiple": false,
134
140
  "type": "option"
135
141
  },
136
- "repoVersion": {
137
- "char": "v",
138
- "description": "Version of the conch",
139
- "name": "repoVersion",
140
- "default": "1.0.0",
141
- "hasDynamicHelp": false,
142
- "multiple": false,
143
- "type": "option"
144
- },
145
- "subdirectory": {
142
+ "sources": {
146
143
  "char": "s",
147
- "description": "Subdirectory in the repository to install from (for monorepos)",
148
- "name": "subdirectory",
149
- "default": "none",
144
+ "description": "Additional sources to include when starting (e.g., packages/esm-chatbot-agent, packages/esm-another-app)",
145
+ "name": "sources",
150
146
  "hasDynamicHelp": false,
151
- "multiple": false,
147
+ "multiple": true,
152
148
  "type": "option"
153
149
  },
154
150
  "workdir": {
155
151
  "char": "w",
156
- "description": "Working directory to install the conch",
152
+ "description": "Working directory for the conch",
157
153
  "name": "workdir",
158
154
  "default": "/home/runner/dhti",
159
155
  "hasDynamicHelp": false,
@@ -360,7 +356,7 @@
360
356
  "aliases": [],
361
357
  "args": {
362
358
  "op": {
363
- "description": "Operation to perform (install, uninstall or dev)",
359
+ "description": "Operation to perform (init, install, uninstall, dev or start)",
364
360
  "name": "op"
365
361
  }
366
362
  },
@@ -402,6 +398,23 @@
402
398
  "allowNo": false,
403
399
  "type": "boolean"
404
400
  },
401
+ "elixir": {
402
+ "char": "e",
403
+ "description": "Elixir endpoint URL",
404
+ "name": "elixir",
405
+ "hasDynamicHelp": false,
406
+ "multiple": false,
407
+ "type": "option"
408
+ },
409
+ "fhir": {
410
+ "char": "f",
411
+ "description": "FHIR endpoint URL",
412
+ "name": "fhir",
413
+ "default": "http://hapi.fhir.org/baseR4",
414
+ "hasDynamicHelp": false,
415
+ "multiple": false,
416
+ "type": "option"
417
+ },
405
418
  "git": {
406
419
  "char": "g",
407
420
  "description": "Github repository to install",
@@ -792,5 +805,5 @@
792
805
  ]
793
806
  }
794
807
  },
795
- "version": "0.8.0"
808
+ "version": "1.1.0"
796
809
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dhti-cli",
3
3
  "description": "DHTI CLI",
4
- "version": "0.8.0",
4
+ "version": "1.1.0",
5
5
  "author": "Bell Eapen",
6
6
  "bin": {
7
7
  "dhti-cli": "bin/run.js"
@@ -29,6 +29,8 @@
29
29
  "@types/node": "^24",
30
30
  "@types/request": "^2.48.12",
31
31
  "@types/sinon": "^17.0.4",
32
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
33
+ "@typescript-eslint/parser": "^8.53.0",
32
34
  "chai": "^4",
33
35
  "eslint": "^8",
34
36
  "eslint-config-oclif": "^5",
@@ -1,16 +0,0 @@
1
- FROM node:20 as build
2
-
3
- ARG REACT_APP_SERVICES_HOST=/services/m
4
-
5
- WORKDIR /app
6
-
7
- COPY ./conch .
8
-
9
- RUN corepack enable
10
- RUN yarn install
11
- RUN yarn build
12
-
13
- FROM server-image as server
14
- COPY ./def /usr/share/nginx/html
15
- RUN mkdir /usr/share/nginx/html/conch-version
16
- COPY --from=build /app/dist /usr/share/nginx/html/conch-version
@@ -1,39 +0,0 @@
1
- {
2
- "imports": {
3
- "@openmrs/esm-home-app": "./openmrs-esm-home-app-5.2.2/openmrs-esm-home-app.js",
4
- "@openmrs/esm-patient-attachments-app": "./openmrs-esm-patient-attachments-app-7.0.1/openmrs-esm-patient-attachments-app.js",
5
- "@openmrs/esm-patient-flags-app": "./openmrs-esm-patient-flags-app-7.0.1/openmrs-esm-patient-flags-app.js",
6
- "@openmrs/esm-patient-appointments-app": "./openmrs-esm-patient-appointments-app-7.0.1/openmrs-esm-patient-appointments-app.js",
7
- "@openmrs/esm-patient-banner-app": "./openmrs-esm-patient-banner-app-7.0.1/openmrs-esm-patient-banner-app.js",
8
- "@openmrs/esm-patient-conditions-app": "./openmrs-esm-patient-conditions-app-7.0.1/openmrs-esm-patient-conditions-app.js",
9
- "@openmrs/esm-patient-immunizations-app": "./openmrs-esm-patient-immunizations-app-7.0.1/openmrs-esm-patient-immunizations-app.js",
10
- "@openmrs/esm-generic-patient-widgets-app": "./openmrs-esm-generic-patient-widgets-app-7.0.1/openmrs-esm-generic-patient-widgets-app.js",
11
- "@openmrs/esm-patient-chart-app": "./openmrs-esm-patient-chart-app-7.0.1/openmrs-esm-patient-chart-app.js",
12
- "@openmrs/esm-patient-forms-app": "./openmrs-esm-patient-forms-app-7.0.1/openmrs-esm-patient-forms-app.js",
13
- "@openmrs/esm-patient-labs-app": "./openmrs-esm-patient-labs-app-7.0.1/openmrs-esm-patient-labs-app.js",
14
- "@openmrs/esm-patient-programs-app": "./openmrs-esm-patient-programs-app-7.0.1/openmrs-esm-patient-programs-app.js",
15
- "@openmrs/esm-patient-orders-app": "./openmrs-esm-patient-orders-app-7.0.1/openmrs-esm-patient-orders-app.js",
16
- "@openmrs/esm-patient-list-management-app": "./openmrs-esm-patient-list-management-app-6.0.0/openmrs-esm-patient-list-management-app.js",
17
- "@openmrs/esm-patient-allergies-app": "./openmrs-esm-patient-allergies-app-7.0.1/openmrs-esm-patient-allergies-app.js",
18
- "@openmrs/esm-patient-lists-app": "./openmrs-esm-patient-lists-app-7.0.1/openmrs-esm-patient-lists-app.js",
19
- "@openmrs/esm-system-admin-app": "./openmrs-esm-system-admin-app-4.0.1/openmrs-esm-system-admin-app.js",
20
- "@openmrs/esm-form-entry-app": "./openmrs-esm-form-entry-app-7.0.1/openmrs-esm-form-entry-app.js",
21
- "@openmrs/esm-service-queues-app": "./openmrs-esm-service-queues-app-6.0.0/openmrs-esm-service-queues-app.js",
22
- "@openmrs/esm-patient-medications-app": "./openmrs-esm-patient-medications-app-7.0.1/openmrs-esm-patient-medications-app.js",
23
- "@openmrs/esm-patient-notes-app": "./openmrs-esm-patient-notes-app-7.0.1/openmrs-esm-patient-notes-app.js",
24
- "@openmrs/esm-patient-search-app": "./openmrs-esm-patient-search-app-6.0.0/openmrs-esm-patient-search-app.js",
25
- "@openmrs/esm-openconceptlab-app": "./openmrs-esm-openconceptlab-app-4.0.1/openmrs-esm-openconceptlab-app.js",
26
- "@openmrs/esm-login-app": "./openmrs-esm-login-app-5.4.0/openmrs-esm-login-app.js",
27
- "@openmrs/esm-active-visits-app": "./openmrs-esm-active-visits-app-6.0.0/openmrs-esm-active-visits-app.js",
28
- "@openmrs/esm-devtools-app": "./openmrs-esm-devtools-app-5.4.0/openmrs-esm-devtools-app.js",
29
- "@openmrs/esm-cohort-builder-app": "./openmrs-esm-cohort-builder-app-3.0.1-pre.183/openmrs-esm-cohort-builder-app.js",
30
- "@openmrs/esm-primary-navigation-app": "./openmrs-esm-primary-navigation-app-5.4.0/openmrs-esm-primary-navigation-app.js",
31
- "@openmrs/esm-patient-registration-app": "./openmrs-esm-patient-registration-app-6.0.0/openmrs-esm-patient-registration-app.js",
32
- "@openmrs/esm-implementer-tools-app": "./openmrs-esm-implementer-tools-app-5.4.0/openmrs-esm-implementer-tools-app.js",
33
- "@openmrs/esm-patient-vitals-app": "./openmrs-esm-patient-vitals-app-7.0.1/openmrs-esm-patient-vitals-app.js",
34
- "@openmrs/esm-appointments-app": "./openmrs-esm-appointments-app-6.0.0/openmrs-esm-appointments-app.js",
35
- "@openmrs/esm-dispensing-app": "./openmrs-esm-dispensing-app-1.3.0/openmrs-esm-dispensing-app.js",
36
- "@openmrs/esm-fast-data-entry-app": "./openmrs-esm-fast-data-entry-app-1.0.1-pre.128/openmrs-esm-fast-data-entry-app.js",
37
- "@openmrs/esm-form-builder-app": "./openmrs-esm-form-builder-app-2.3.1-pre.677/openmrs-esm-form-builder-app.js"
38
- }
39
- }