@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 +6 -13
- package/dist/src/auth-providers.d.ts +10 -0
- package/dist/src/auth-providers.d.ts.map +1 -0
- package/dist/src/auth-providers.js +313 -0
- package/dist/src/client.d.ts +30 -6
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +266 -73
- package/dist/src/fhir-http.d.ts +39 -15
- package/dist/src/fhir-http.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/types.d.ts +18 -8
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +47 -46
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
|
|
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
|
-
|
|
18
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
+
}
|
package/dist/src/client.d.ts
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import type {
|
|
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
|
|
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>({
|
|
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
|
-
* - `
|
|
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>({
|
|
48
|
+
export declare function makeClient<TBundle, TOperationOutcome, TUser>({ baseUrl, authProvider, }: ClientParams): AidboxClient<TBundle, TOperationOutcome, TUser>;
|
|
25
49
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/src/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"
|
|
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"}
|