@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.
Files changed (2) hide show
  1. package/README.md +59 -43
  2. 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
- if (!patient.name || patient.name.length === 0) {
37
- return reject("Patient must have at least one name");
38
- }
39
- return patient;
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
- export const { getMetadata, executeHook } = plugin.exports();
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 ctx.fhir.search("Patient", {
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 ctx.http.post("https://api.insurance.com/verify", {
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
- ctx.events.emit("patient.created", {
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
- ctx.logger.info("Validating patient", { id: patient.id });
198
- ctx.logger.warn("Missing phone number", { id: patient.id });
199
- ctx.logger.error("Validation failed", { id: patient.id });
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 { getMetadata, executeHook } = plugin.exports();
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 { getMetadata, executeHook } = plugin.exports();
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
- // Search for existing patients with same identifier
270
- const bundle = await ctx.fhir.search("Patient", {
271
- identifier: identifier
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
- if (bundle.total && bundle.total > 0) {
275
- return reject(`Duplicate patient found with identifier: ${identifier}`);
276
- }
280
+ if (bundle.total && bundle.total > 0) {
281
+ return reject(`Duplicate patient found with identifier: ${identifier}`);
282
+ }
277
283
 
278
- return patient;
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 { getMetadata, executeHook } = plugin.exports();
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
- // Verify with external insurance API
299
- const response = await ctx.http.post(
300
- "https://api.insurance.com/verify",
301
- { body: { memberId } }
302
- );
303
-
304
- if (!response.ok) {
305
- return reject("Insurance verification failed");
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 { getMetadata, executeHook } = plugin.exports();
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.1",
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.14.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
+ }