@fhirust/sdk 0.3.2 → 0.3.3
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 +58 -43
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,14 +34,16 @@ const plugin = new FhirPlugin("my-validator", "1.0.0");
|
|
|
34
34
|
|
|
35
35
|
// Validate Patient before creation
|
|
36
36
|
plugin.beforeCreate<Patient>("Patient", (patient, ctx) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
if (!patient.name || patient.name.length === 0) {
|
|
38
|
+
return reject("Patient must have at least one name");
|
|
39
|
+
}
|
|
40
|
+
return patient;
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
// Export plugin hooks
|
|
44
|
-
|
|
44
|
+
const pluginExports = plugin.exports();
|
|
45
|
+
export const lifecycle = pluginExports.lifecycle;
|
|
46
|
+
export const hooks = pluginExports.hooks;
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
### 2. Build the plugin
|
|
@@ -131,16 +133,16 @@ return outcome([
|
|
|
131
133
|
|
|
132
134
|
### FHIR Client
|
|
133
135
|
|
|
134
|
-
Access the FHIR server from within your plugin.
|
|
136
|
+
Access the FHIR server from within your plugin using `plugin.fhir`.
|
|
135
137
|
|
|
136
138
|
```typescript
|
|
137
139
|
plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
138
140
|
// Search for duplicates
|
|
139
|
-
const bundle = await
|
|
141
|
+
const bundle = await plugin.fhir.search("Patient", {
|
|
140
142
|
identifier: patient.identifier?.[0]?.value
|
|
141
143
|
});
|
|
142
144
|
|
|
143
|
-
if (bundle.total > 0) {
|
|
145
|
+
if (bundle.total && bundle.total > 0) {
|
|
144
146
|
return reject("Duplicate patient identifier");
|
|
145
147
|
}
|
|
146
148
|
|
|
@@ -149,20 +151,20 @@ plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
|
149
151
|
```
|
|
150
152
|
|
|
151
153
|
**Methods:**
|
|
152
|
-
- `fhir.search(resourceType, params)` — Search for resources
|
|
153
|
-
- `fhir.read(resourceType, id)` — Read a resource by ID
|
|
154
|
-
- `fhir.create(resourceType, resource)` — Create a new resource
|
|
155
|
-
- `fhir.update(resourceType, id, resource)` — Update a resource
|
|
156
|
-
- `fhir.delete(resourceType, id)` — Delete a resource
|
|
154
|
+
- `plugin.fhir.search(resourceType, params)` — Search for resources
|
|
155
|
+
- `plugin.fhir.read(resourceType, id)` — Read a resource by ID
|
|
156
|
+
- `plugin.fhir.create(resourceType, resource)` — Create a new resource
|
|
157
|
+
- `plugin.fhir.update(resourceType, id, resource)` — Update a resource
|
|
158
|
+
- `plugin.fhir.delete(resourceType, id)` — Delete a resource
|
|
157
159
|
|
|
158
160
|
### HTTP Client
|
|
159
161
|
|
|
160
|
-
Make HTTP requests to external APIs (requires `http.fetch` permission).
|
|
162
|
+
Make HTTP requests to external APIs using `plugin.http` (requires `http.fetch` permission).
|
|
161
163
|
|
|
162
164
|
```typescript
|
|
163
165
|
plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
164
166
|
// Verify insurance eligibility via external API
|
|
165
|
-
const response = await
|
|
167
|
+
const response = await plugin.http.post("https://api.insurance.com/verify", {
|
|
166
168
|
body: { memberId: patient.identifier?.[0]?.value }
|
|
167
169
|
});
|
|
168
170
|
|
|
@@ -176,11 +178,11 @@ plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
|
176
178
|
|
|
177
179
|
### Event Emitter
|
|
178
180
|
|
|
179
|
-
Emit events for async processing.
|
|
181
|
+
Emit events for async processing using `plugin.events`.
|
|
180
182
|
|
|
181
183
|
```typescript
|
|
182
184
|
plugin.afterCreate<Patient>("Patient", (patient, ctx) => {
|
|
183
|
-
|
|
185
|
+
plugin.events.emit("patient.created", {
|
|
184
186
|
id: patient.id,
|
|
185
187
|
name: patient.name?.[0]?.family
|
|
186
188
|
});
|
|
@@ -191,18 +193,20 @@ plugin.afterCreate<Patient>("Patient", (patient, ctx) => {
|
|
|
191
193
|
|
|
192
194
|
### Logger
|
|
193
195
|
|
|
194
|
-
Structured logging with severity levels.
|
|
196
|
+
Structured logging with severity levels using `plugin.log`.
|
|
195
197
|
|
|
196
198
|
```typescript
|
|
197
199
|
plugin.beforeCreate<Patient>("Patient", (patient, ctx) => {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
plugin.log.info(`Validating patient: ${patient.id}`);
|
|
201
|
+
plugin.log.warn(`Missing phone number for patient: ${patient.id}`);
|
|
202
|
+
plugin.log.error(`Validation failed for patient: ${patient.id}`);
|
|
201
203
|
|
|
202
204
|
return patient;
|
|
203
205
|
});
|
|
204
206
|
```
|
|
205
207
|
|
|
208
|
+
**Note:** Logger methods accept only string messages. To include structured data, serialize it in the message string using template literals or `JSON.stringify()`.
|
|
209
|
+
|
|
206
210
|
---
|
|
207
211
|
|
|
208
212
|
## 💡 Examples
|
|
@@ -228,7 +232,7 @@ plugin.beforeCreate<Patient>("Patient", (patient) => {
|
|
|
228
232
|
return patient;
|
|
229
233
|
});
|
|
230
234
|
|
|
231
|
-
export const {
|
|
235
|
+
export const { lifecycle, hooks } = plugin.exports();
|
|
232
236
|
```
|
|
233
237
|
|
|
234
238
|
### Example 2: Auto-Tag Resources
|
|
@@ -252,7 +256,7 @@ plugin.beforeCreate<Patient>("Patient", (patient) => {
|
|
|
252
256
|
return patient;
|
|
253
257
|
});
|
|
254
258
|
|
|
255
|
-
export const {
|
|
259
|
+
export const { lifecycle, hooks } = plugin.exports();
|
|
256
260
|
```
|
|
257
261
|
|
|
258
262
|
### Example 3: Duplicate Detection
|
|
@@ -267,19 +271,25 @@ plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
|
267
271
|
const identifier = patient.identifier?.[0]?.value;
|
|
268
272
|
if (!identifier) return patient;
|
|
269
273
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
+
try {
|
|
275
|
+
// Search for existing patients with same identifier
|
|
276
|
+
const bundle = await plugin.fhir.search("Patient", {
|
|
277
|
+
identifier: identifier
|
|
278
|
+
});
|
|
274
279
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
280
|
+
if (bundle.total && bundle.total > 0) {
|
|
281
|
+
return reject(`Duplicate patient found with identifier: ${identifier}`);
|
|
282
|
+
}
|
|
278
283
|
|
|
279
|
-
|
|
284
|
+
return patient;
|
|
285
|
+
} catch (error) {
|
|
286
|
+
plugin.log.error(`Duplicate check failed: ${error}`);
|
|
287
|
+
// Fail open: allow creation if duplicate check fails
|
|
288
|
+
return patient;
|
|
289
|
+
}
|
|
280
290
|
});
|
|
281
291
|
|
|
282
|
-
export const {
|
|
292
|
+
export const { lifecycle, hooks } = plugin.exports();
|
|
283
293
|
```
|
|
284
294
|
|
|
285
295
|
### Example 4: External API Integration
|
|
@@ -296,23 +306,28 @@ plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
|
296
306
|
)?.value;
|
|
297
307
|
|
|
298
308
|
if (memberId) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
309
|
+
try {
|
|
310
|
+
// Verify with external insurance API
|
|
311
|
+
const response = await plugin.http.post(
|
|
312
|
+
"https://api.insurance.com/verify",
|
|
313
|
+
{ body: { memberId } }
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
if (!response.ok) {
|
|
317
|
+
return reject("Insurance verification failed");
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
plugin.log.info(`Insurance verified for member: ${memberId}`);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
plugin.log.error(`Insurance verification error: ${error}`);
|
|
323
|
+
return reject("Insurance verification service unavailable");
|
|
307
324
|
}
|
|
308
|
-
|
|
309
|
-
ctx.logger.info("Insurance verified", { memberId });
|
|
310
325
|
}
|
|
311
326
|
|
|
312
327
|
return patient;
|
|
313
328
|
});
|
|
314
329
|
|
|
315
|
-
export const {
|
|
330
|
+
export const { lifecycle, hooks } = plugin.exports();
|
|
316
331
|
```
|
|
317
332
|
|
|
318
333
|
---
|