@health-samurai/aidbox-client 0.0.0-alpha.1 → 0.0.0-alpha.2

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 CHANGED
@@ -7,17 +7,10 @@ A typescript client for interacting with a FHIR server.
7
7
  The client is created with the `makeClient` function:
8
8
 
9
9
  ```typescript
10
- const client = makeClient({ baseurl: "https://fhir-server.address" });
11
- ```
12
-
13
- This constructor accepts an additional `onResponse` option, which is a side-effect-only function, that recieves a copy of the Response from the server as is:
14
-
15
- ```typescript
10
+ const baseUrl = "https://fhir-server.address";
16
11
  const client = makeClient({
17
- baseurl: "https://fhir-server.address"
18
- onResponse: (response: Response) => {
19
- /* analyze Response, use throw to interrupt request early */
20
- }
12
+ baseUrl,
13
+ authProvider: new BrowserAuthProvider(baseUrl);
21
14
  });
22
15
  ```
23
16
 
@@ -65,7 +58,7 @@ if (result.isOk()) {
65
58
  }
66
59
 
67
60
  if (result.isErr()) {
68
- const outcome: OperationOutcome = result.error.resource;
61
+ const outcome: OperationOutcome = result.value.resource;
69
62
  // process OperationOutcome
70
63
  }
71
64
  ```
@@ -114,14 +107,14 @@ Most client methods return a `Result<T, E>` object, with methods to check if the
114
107
  ```typescript
115
108
  const result = await client.read<Patient>({type: 'Patient', id: 'patient-id'});
116
109
  if (result.isErr())
117
- throw new Error("error reading Patient", { cause: result.error })
110
+ throw new Error("error reading Patient", { cause: result.value })
118
111
 
119
112
  const { resource: patient } = result.value;
120
113
 
121
114
  // work with patient.
122
115
  ```
123
116
 
124
- Unwrapping is not required to modify the data in the result:
117
+ Unwrapping is not required to modify the data in the `Result`:
125
118
 
126
119
  ```typescript
127
120
  const result = await client.read<Patient>({type: 'Patient', id: 'patient-id'});
@@ -0,0 +1,10 @@
1
+ import type { AuthProvider } from "./types";
2
+ export declare class BrowserAuthProvider implements AuthProvider {
3
+ #private;
4
+ baseUrl: string;
5
+ constructor(baseUrl: string);
6
+ establishSession(): Promise<void>;
7
+ revokeSession(): Promise<void>;
8
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
9
+ }
10
+ //# sourceMappingURL=auth-providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-providers.d.ts","sourceRoot":"","sources":["../../src/auth-providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,qBAAa,mBAAoB,YAAW,YAAY;;IAChD,OAAO,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM;IAgBd,gBAAgB;IAQhB,aAAa;IAWb,KAAK,CACjB,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GAChB,OAAO,CAAC,QAAQ,CAAC;CAsBpB"}
@@ -0,0 +1,313 @@
1
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
+ try {
3
+ var info = gen[key](arg);
4
+ var value = info.value;
5
+ } catch (error) {
6
+ reject(error);
7
+ return;
8
+ }
9
+ if (info.done) {
10
+ resolve(value);
11
+ } else {
12
+ Promise.resolve(value).then(_next, _throw);
13
+ }
14
+ }
15
+ function _async_to_generator(fn) {
16
+ return function() {
17
+ var self = this, args = arguments;
18
+ return new Promise(function(resolve, reject) {
19
+ var gen = fn.apply(self, args);
20
+ function _next(value) {
21
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
+ }
23
+ function _throw(err) {
24
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
+ }
26
+ _next(undefined);
27
+ });
28
+ };
29
+ }
30
+ function _check_private_redeclaration(obj, privateCollection) {
31
+ if (privateCollection.has(obj)) {
32
+ throw new TypeError("Cannot initialize the same private elements twice on an object");
33
+ }
34
+ }
35
+ function _class_call_check(instance, Constructor) {
36
+ if (!(instance instanceof Constructor)) {
37
+ throw new TypeError("Cannot call a class as a function");
38
+ }
39
+ }
40
+ function _class_private_method_get(receiver, privateSet, fn) {
41
+ if (!privateSet.has(receiver)) {
42
+ throw new TypeError("attempted to get private field on non-instance");
43
+ }
44
+ return fn;
45
+ }
46
+ function _class_private_method_init(obj, privateSet) {
47
+ _check_private_redeclaration(obj, privateSet);
48
+ privateSet.add(obj);
49
+ }
50
+ function _defineProperties(target, props) {
51
+ for(var i = 0; i < props.length; i++){
52
+ var descriptor = props[i];
53
+ descriptor.enumerable = descriptor.enumerable || false;
54
+ descriptor.configurable = true;
55
+ if ("value" in descriptor) descriptor.writable = true;
56
+ Object.defineProperty(target, descriptor.key, descriptor);
57
+ }
58
+ }
59
+ function _create_class(Constructor, protoProps, staticProps) {
60
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
61
+ if (staticProps) _defineProperties(Constructor, staticProps);
62
+ return Constructor;
63
+ }
64
+ function _define_property(obj, key, value) {
65
+ if (key in obj) {
66
+ Object.defineProperty(obj, key, {
67
+ value: value,
68
+ enumerable: true,
69
+ configurable: true,
70
+ writable: true
71
+ });
72
+ } else {
73
+ obj[key] = value;
74
+ }
75
+ return obj;
76
+ }
77
+ function _instanceof(left, right) {
78
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
79
+ return !!right[Symbol.hasInstance](left);
80
+ } else {
81
+ return left instanceof right;
82
+ }
83
+ }
84
+ function _ts_generator(thisArg, body) {
85
+ var f, y, t, _ = {
86
+ label: 0,
87
+ sent: function() {
88
+ if (t[0] & 1) throw t[1];
89
+ return t[1];
90
+ },
91
+ trys: [],
92
+ ops: []
93
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
94
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
95
+ return this;
96
+ }), g;
97
+ function verb(n) {
98
+ return function(v) {
99
+ return step([
100
+ n,
101
+ v
102
+ ]);
103
+ };
104
+ }
105
+ function step(op) {
106
+ if (f) throw new TypeError("Generator is already executing.");
107
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
108
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
109
+ if (y = 0, t) op = [
110
+ op[0] & 2,
111
+ t.value
112
+ ];
113
+ switch(op[0]){
114
+ case 0:
115
+ case 1:
116
+ t = op;
117
+ break;
118
+ case 4:
119
+ _.label++;
120
+ return {
121
+ value: op[1],
122
+ done: false
123
+ };
124
+ case 5:
125
+ _.label++;
126
+ y = op[1];
127
+ op = [
128
+ 0
129
+ ];
130
+ continue;
131
+ case 7:
132
+ op = _.ops.pop();
133
+ _.trys.pop();
134
+ continue;
135
+ default:
136
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
137
+ _ = 0;
138
+ continue;
139
+ }
140
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
141
+ _.label = op[1];
142
+ break;
143
+ }
144
+ if (op[0] === 6 && _.label < t[1]) {
145
+ _.label = t[1];
146
+ t = op;
147
+ break;
148
+ }
149
+ if (t && _.label < t[2]) {
150
+ _.label = t[2];
151
+ _.ops.push(op);
152
+ break;
153
+ }
154
+ if (t[2]) _.ops.pop();
155
+ _.trys.pop();
156
+ continue;
157
+ }
158
+ op = body.call(thisArg, _);
159
+ } catch (e) {
160
+ op = [
161
+ 6,
162
+ e
163
+ ];
164
+ y = 0;
165
+ } finally{
166
+ f = t = 0;
167
+ }
168
+ if (op[0] & 5) throw op[1];
169
+ return {
170
+ value: op[0] ? op[1] : void 0,
171
+ done: true
172
+ };
173
+ }
174
+ }
175
+ var _checkSession = /*#__PURE__*/ new WeakSet();
176
+ export var BrowserAuthProvider = /*#__PURE__*/ function() {
177
+ "use strict";
178
+ function BrowserAuthProvider(baseUrl) {
179
+ _class_call_check(this, BrowserAuthProvider);
180
+ _class_private_method_init(this, _checkSession);
181
+ _define_property(this, "baseUrl", void 0);
182
+ this.baseUrl = baseUrl;
183
+ }
184
+ _create_class(BrowserAuthProvider, [
185
+ {
186
+ key: "establishSession",
187
+ value: function establishSession() {
188
+ return _async_to_generator(function() {
189
+ var encodedLocation, redirectTo;
190
+ return _ts_generator(this, function(_state) {
191
+ switch(_state.label){
192
+ case 0:
193
+ return [
194
+ 4,
195
+ _class_private_method_get(this, _checkSession, checkSession).call(this)
196
+ ];
197
+ case 1:
198
+ if (!_state.sent()) {
199
+ encodedLocation = encodeURIComponent(btoa(window.location.href));
200
+ redirectTo = "".concat(this.baseUrl, "/auth/login?redirect_to=").concat(encodedLocation);
201
+ window.location.href = redirectTo;
202
+ }
203
+ return [
204
+ 2
205
+ ];
206
+ }
207
+ });
208
+ }).call(this);
209
+ }
210
+ },
211
+ {
212
+ key: "revokeSession",
213
+ value: function revokeSession() {
214
+ return _async_to_generator(function() {
215
+ return _ts_generator(this, function(_state) {
216
+ switch(_state.label){
217
+ case 0:
218
+ return [
219
+ 4,
220
+ fetch(new URL("/auth/logout", this.baseUrl), {
221
+ method: "POST",
222
+ headers: {
223
+ "content-type": "application/json",
224
+ accept: "application/json"
225
+ },
226
+ credentials: "include"
227
+ })
228
+ ];
229
+ case 1:
230
+ _state.sent();
231
+ return [
232
+ 2
233
+ ];
234
+ }
235
+ });
236
+ }).call(this);
237
+ }
238
+ },
239
+ {
240
+ key: "fetch",
241
+ value: function fetch1(input, init) {
242
+ return _async_to_generator(function() {
243
+ var url, i, response;
244
+ return _ts_generator(this, function(_state) {
245
+ switch(_state.label){
246
+ case 0:
247
+ if (_instanceof(input, Request)) url = input.url;
248
+ else url = input.toString();
249
+ if (!url.startsWith(this.baseUrl)) throw Error("url of the request must start with baseUrl");
250
+ i = init !== null && init !== void 0 ? init : {};
251
+ i.credentials = "include";
252
+ return [
253
+ 4,
254
+ fetch(input, i)
255
+ ];
256
+ case 1:
257
+ response = _state.sent();
258
+ if (!(response.status === 401)) return [
259
+ 3,
260
+ 3
261
+ ];
262
+ return [
263
+ 4,
264
+ this.establishSession()
265
+ ];
266
+ case 2:
267
+ _state.sent();
268
+ throw new Error("unauthorized");
269
+ case 3:
270
+ return [
271
+ 2,
272
+ response
273
+ ];
274
+ case 4:
275
+ return [
276
+ 2
277
+ ];
278
+ }
279
+ });
280
+ }).call(this);
281
+ }
282
+ }
283
+ ]);
284
+ return BrowserAuthProvider;
285
+ } // TODO: backend auth provider
286
+ ();
287
+ function checkSession() {
288
+ return _async_to_generator(function() {
289
+ var response;
290
+ return _ts_generator(this, function(_state) {
291
+ switch(_state.label){
292
+ case 0:
293
+ return [
294
+ 4,
295
+ fetch(new URL("/auth/userinfo", this.baseUrl), {
296
+ method: "GET",
297
+ headers: {
298
+ "content-type": "application/json",
299
+ accept: "application/json"
300
+ },
301
+ credentials: "include"
302
+ })
303
+ ];
304
+ case 1:
305
+ response = _state.sent();
306
+ return [
307
+ 2,
308
+ response.status !== 401
309
+ ];
310
+ }
311
+ });
312
+ }).call(this);
313
+ }
@@ -1,13 +1,20 @@
1
- import type { ClientParams, FhirServerClient } from "./types";
1
+ import type { AidboxClient, ClientParams } from "./types";
2
2
  /**
3
3
  * Create a client to the FHIR server.
4
4
  *
5
5
  * ```typescript
6
- * const client = makeClient({ baseurl: "https://fhir-server.address" })
6
+ * const baseUrl = "https://fhir-server.address";
7
+ * const client = makeClient({
8
+ * baseUrl,
9
+ * authProvider: new BrowserAuthProvider(baseUrl);
10
+ * });
7
11
  *
8
12
  * // alternatively, specify different FHIR types:
9
13
  * import type { Bundle, OperationOutcome } from "hl7-fhir-r5-core";
10
- * const client = makeClient<Bundle, OperationOutcome>({ baseurl: "https://fhir-server.address" })
14
+ * const client = makeClient<Bundle, OperationOutcome, User>({
15
+ * baseUrl,
16
+ * authProvider: new BrowserAuthProvider(baseUrl);
17
+ * });
11
18
  * ```
12
19
  *
13
20
  * Main client functions are `request` for typed interactions, and `rawRequest` for manual response processing.
@@ -15,11 +22,28 @@ import type { ClientParams, FhirServerClient } from "./types";
15
22
  * This client also provides a set of convenience methods for accessing FHIR operations:
16
23
  *
17
24
  * - `read`
18
- * - `search`
25
+ * - `vread`
26
+ * - `searchType`
27
+ * - `searchSystem`
28
+ * - `searchCompartment`
19
29
  * - `create`
30
+ * - `conditionalCreate`
31
+ * - `update`
32
+ * - `conditionalUpdate`
33
+ * - `patch`
34
+ * - `conditionalPatch`
35
+ * - `delete: deleteOp`
36
+ * - `deleteHistory`
37
+ * - `deleteHistoryVersion`
38
+ * - `conditionalDelete`
39
+ * - `historyInstance`
40
+ * - `historyType`
41
+ * - `historySystem`
42
+ * - `capabilities`
43
+ * - `batch`
44
+ * - `transaction`
20
45
  * - `operation`
21
46
  * - `validate`
22
- *
23
47
  */
24
- export declare function makeClient<TBundle, TOperationOutcome, TUser>({ baseurl, onResponse, }: ClientParams): FhirServerClient<TBundle, TOperationOutcome, TUser>;
48
+ export declare function makeClient<TBundle, TOperationOutcome, TUser>({ baseUrl, authProvider, }: ClientParams): AidboxClient<TBundle, TOperationOutcome, TUser>;
25
49
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EACX,YAAY,EACZ,gBAAgB,EAIhB,MAAM,SAAS,CAAC;AAgBjB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,EAC7D,OAAO,EACP,UAAsB,GACtB,EAAE,YAAY,GAAG,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,CAAC,CA+dpE"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACX,YAAY,EACZ,YAAY,EAIZ,MAAM,SAAS,CAAC;AAsBjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,EAC7D,OAAO,EACP,YAAY,GACZ,EAAE,YAAY,GAAG,YAAY,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,CAAC,CAihBhE"}