@fhirust/sdk 0.3.1 → 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 +59 -43
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ npm install @fhirust/sdk @bytecodealliance/componentize-js
|
|
|
18
18
|
**Requirements:**
|
|
19
19
|
- Node.js 18+ or Bun
|
|
20
20
|
- TypeScript 5.0+
|
|
21
|
+
- `@bytecodealliance/componentize-js` >= 0.14.0 (0.19+ recommended for security fixes)
|
|
21
22
|
|
|
22
23
|
---
|
|
23
24
|
|
|
@@ -33,14 +34,16 @@ const plugin = new FhirPlugin("my-validator", "1.0.0");
|
|
|
33
34
|
|
|
34
35
|
// Validate Patient before creation
|
|
35
36
|
plugin.beforeCreate<Patient>("Patient", (patient, ctx) => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
if (!patient.name || patient.name.length === 0) {
|
|
38
|
+
return reject("Patient must have at least one name");
|
|
39
|
+
}
|
|
40
|
+
return patient;
|
|
40
41
|
});
|
|
41
42
|
|
|
42
43
|
// Export plugin hooks
|
|
43
|
-
|
|
44
|
+
const pluginExports = plugin.exports();
|
|
45
|
+
export const lifecycle = pluginExports.lifecycle;
|
|
46
|
+
export const hooks = pluginExports.hooks;
|
|
44
47
|
```
|
|
45
48
|
|
|
46
49
|
### 2. Build the plugin
|
|
@@ -130,16 +133,16 @@ return outcome([
|
|
|
130
133
|
|
|
131
134
|
### FHIR Client
|
|
132
135
|
|
|
133
|
-
Access the FHIR server from within your plugin.
|
|
136
|
+
Access the FHIR server from within your plugin using `plugin.fhir`.
|
|
134
137
|
|
|
135
138
|
```typescript
|
|
136
139
|
plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
137
140
|
// Search for duplicates
|
|
138
|
-
const bundle = await
|
|
141
|
+
const bundle = await plugin.fhir.search("Patient", {
|
|
139
142
|
identifier: patient.identifier?.[0]?.value
|
|
140
143
|
});
|
|
141
144
|
|
|
142
|
-
if (bundle.total > 0) {
|
|
145
|
+
if (bundle.total && bundle.total > 0) {
|
|
143
146
|
return reject("Duplicate patient identifier");
|
|
144
147
|
}
|
|
145
148
|
|
|
@@ -148,20 +151,20 @@ plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
|
148
151
|
```
|
|
149
152
|
|
|
150
153
|
**Methods:**
|
|
151
|
-
- `fhir.search(resourceType, params)` — Search for resources
|
|
152
|
-
- `fhir.read(resourceType, id)` — Read a resource by ID
|
|
153
|
-
- `fhir.create(resourceType, resource)` — Create a new resource
|
|
154
|
-
- `fhir.update(resourceType, id, resource)` — Update a resource
|
|
155
|
-
- `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
|
|
156
159
|
|
|
157
160
|
### HTTP Client
|
|
158
161
|
|
|
159
|
-
Make HTTP requests to external APIs (requires `http.fetch` permission).
|
|
162
|
+
Make HTTP requests to external APIs using `plugin.http` (requires `http.fetch` permission).
|
|
160
163
|
|
|
161
164
|
```typescript
|
|
162
165
|
plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
163
166
|
// Verify insurance eligibility via external API
|
|
164
|
-
const response = await
|
|
167
|
+
const response = await plugin.http.post("https://api.insurance.com/verify", {
|
|
165
168
|
body: { memberId: patient.identifier?.[0]?.value }
|
|
166
169
|
});
|
|
167
170
|
|
|
@@ -175,11 +178,11 @@ plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
|
175
178
|
|
|
176
179
|
### Event Emitter
|
|
177
180
|
|
|
178
|
-
Emit events for async processing.
|
|
181
|
+
Emit events for async processing using `plugin.events`.
|
|
179
182
|
|
|
180
183
|
```typescript
|
|
181
184
|
plugin.afterCreate<Patient>("Patient", (patient, ctx) => {
|
|
182
|
-
|
|
185
|
+
plugin.events.emit("patient.created", {
|
|
183
186
|
id: patient.id,
|
|
184
187
|
name: patient.name?.[0]?.family
|
|
185
188
|
});
|
|
@@ -190,18 +193,20 @@ plugin.afterCreate<Patient>("Patient", (patient, ctx) => {
|
|
|
190
193
|
|
|
191
194
|
### Logger
|
|
192
195
|
|
|
193
|
-
Structured logging with severity levels.
|
|
196
|
+
Structured logging with severity levels using `plugin.log`.
|
|
194
197
|
|
|
195
198
|
```typescript
|
|
196
199
|
plugin.beforeCreate<Patient>("Patient", (patient, ctx) => {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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}`);
|
|
200
203
|
|
|
201
204
|
return patient;
|
|
202
205
|
});
|
|
203
206
|
```
|
|
204
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
|
+
|
|
205
210
|
---
|
|
206
211
|
|
|
207
212
|
## 💡 Examples
|
|
@@ -227,7 +232,7 @@ plugin.beforeCreate<Patient>("Patient", (patient) => {
|
|
|
227
232
|
return patient;
|
|
228
233
|
});
|
|
229
234
|
|
|
230
|
-
export const {
|
|
235
|
+
export const { lifecycle, hooks } = plugin.exports();
|
|
231
236
|
```
|
|
232
237
|
|
|
233
238
|
### Example 2: Auto-Tag Resources
|
|
@@ -251,7 +256,7 @@ plugin.beforeCreate<Patient>("Patient", (patient) => {
|
|
|
251
256
|
return patient;
|
|
252
257
|
});
|
|
253
258
|
|
|
254
|
-
export const {
|
|
259
|
+
export const { lifecycle, hooks } = plugin.exports();
|
|
255
260
|
```
|
|
256
261
|
|
|
257
262
|
### Example 3: Duplicate Detection
|
|
@@ -266,19 +271,25 @@ plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
|
266
271
|
const identifier = patient.identifier?.[0]?.value;
|
|
267
272
|
if (!identifier) return patient;
|
|
268
273
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
274
|
+
try {
|
|
275
|
+
// Search for existing patients with same identifier
|
|
276
|
+
const bundle = await plugin.fhir.search("Patient", {
|
|
277
|
+
identifier: identifier
|
|
278
|
+
});
|
|
273
279
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
280
|
+
if (bundle.total && bundle.total > 0) {
|
|
281
|
+
return reject(`Duplicate patient found with identifier: ${identifier}`);
|
|
282
|
+
}
|
|
277
283
|
|
|
278
|
-
|
|
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
|
+
}
|
|
279
290
|
});
|
|
280
291
|
|
|
281
|
-
export const {
|
|
292
|
+
export const { lifecycle, hooks } = plugin.exports();
|
|
282
293
|
```
|
|
283
294
|
|
|
284
295
|
### Example 4: External API Integration
|
|
@@ -295,23 +306,28 @@ plugin.beforeCreate<Patient>("Patient", async (patient, ctx) => {
|
|
|
295
306
|
)?.value;
|
|
296
307
|
|
|
297
308
|
if (memberId) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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");
|
|
306
324
|
}
|
|
307
|
-
|
|
308
|
-
ctx.logger.info("Insurance verified", { memberId });
|
|
309
325
|
}
|
|
310
326
|
|
|
311
327
|
return patient;
|
|
312
328
|
});
|
|
313
329
|
|
|
314
|
-
export const {
|
|
330
|
+
export const { lifecycle, hooks } = plugin.exports();
|
|
315
331
|
```
|
|
316
332
|
|
|
317
333
|
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fhirust/sdk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "TypeScript SDK for building FHIRust WASM plugins",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
],
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"@bytecodealliance/componentize-js": ">=0.14.0"
|
|
46
|
+
"@bytecodealliance/componentize-js": ">=0.14.0 <1.0.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependenciesMeta": {
|
|
49
49
|
"@bytecodealliance/componentize-js": {
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
}
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@bytecodealliance/componentize-js": "^0.
|
|
54
|
+
"@bytecodealliance/componentize-js": "^0.19.3",
|
|
55
55
|
"@types/node": "^25.2.2",
|
|
56
56
|
"tsx": "^4.21.0",
|
|
57
57
|
"typescript": "^5.5.0"
|
|
58
58
|
}
|
|
59
|
-
}
|
|
59
|
+
}
|