@yannelli/nextvisit-sdk 1.0.1
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 +399 -0
- package/dist/index.d.mts +1416 -0
- package/dist/index.d.ts +1416 -0
- package/dist/index.js +953 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +937 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,953 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/errors.ts
|
|
4
|
+
var NextvisitError = class _NextvisitError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "NextvisitError";
|
|
8
|
+
Object.setPrototypeOf(this, _NextvisitError.prototype);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var NextvisitApiError = class _NextvisitApiError extends NextvisitError {
|
|
12
|
+
constructor(status, error) {
|
|
13
|
+
super(error.message);
|
|
14
|
+
this.name = "NextvisitApiError";
|
|
15
|
+
this.status = status;
|
|
16
|
+
this.errors = error.errors;
|
|
17
|
+
Object.setPrototypeOf(this, _NextvisitApiError.prototype);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var UnauthorizedError = class _UnauthorizedError extends NextvisitApiError {
|
|
21
|
+
constructor(error) {
|
|
22
|
+
super(401, error);
|
|
23
|
+
this.name = "UnauthorizedError";
|
|
24
|
+
Object.setPrototypeOf(this, _UnauthorizedError.prototype);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var ForbiddenError = class _ForbiddenError extends NextvisitApiError {
|
|
28
|
+
constructor(error) {
|
|
29
|
+
super(403, error);
|
|
30
|
+
this.name = "ForbiddenError";
|
|
31
|
+
Object.setPrototypeOf(this, _ForbiddenError.prototype);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var NotFoundError = class _NotFoundError extends NextvisitApiError {
|
|
35
|
+
constructor(error) {
|
|
36
|
+
super(404, error);
|
|
37
|
+
this.name = "NotFoundError";
|
|
38
|
+
Object.setPrototypeOf(this, _NotFoundError.prototype);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var ValidationError = class _ValidationError extends NextvisitApiError {
|
|
42
|
+
constructor(error) {
|
|
43
|
+
super(422, error);
|
|
44
|
+
this.name = "ValidationError";
|
|
45
|
+
Object.setPrototypeOf(this, _ValidationError.prototype);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var NetworkError = class _NetworkError extends NextvisitError {
|
|
49
|
+
constructor(message, cause) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.name = "NetworkError";
|
|
52
|
+
this.cause = cause;
|
|
53
|
+
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// src/http.ts
|
|
58
|
+
var HttpClient = class {
|
|
59
|
+
constructor(config) {
|
|
60
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
61
|
+
this.token = config.token;
|
|
62
|
+
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
63
|
+
this.timeout = config.timeout ?? 3e4;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Set the authentication token
|
|
67
|
+
*/
|
|
68
|
+
setToken(token) {
|
|
69
|
+
this.token = token;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get the current authentication token
|
|
73
|
+
*/
|
|
74
|
+
getToken() {
|
|
75
|
+
return this.token;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Build URL with query parameters
|
|
79
|
+
*/
|
|
80
|
+
buildUrl(path, params) {
|
|
81
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
82
|
+
if (params) {
|
|
83
|
+
for (const [key, value] of Object.entries(params)) {
|
|
84
|
+
if (value !== void 0) {
|
|
85
|
+
url.searchParams.set(key, String(value));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return url.toString();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build request headers
|
|
93
|
+
*/
|
|
94
|
+
buildHeaders(options, contentType) {
|
|
95
|
+
const headers = {
|
|
96
|
+
Accept: "application/json",
|
|
97
|
+
...options?.headers
|
|
98
|
+
};
|
|
99
|
+
if (contentType) {
|
|
100
|
+
headers["Content-Type"] = contentType;
|
|
101
|
+
}
|
|
102
|
+
if (this.token) {
|
|
103
|
+
headers["Authorization"] = `Bearer ${this.token}`;
|
|
104
|
+
}
|
|
105
|
+
return headers;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Handle API error responses
|
|
109
|
+
*/
|
|
110
|
+
async handleError(response) {
|
|
111
|
+
let error;
|
|
112
|
+
try {
|
|
113
|
+
error = await response.json();
|
|
114
|
+
} catch {
|
|
115
|
+
error = { message: response.statusText || "Unknown error" };
|
|
116
|
+
}
|
|
117
|
+
switch (response.status) {
|
|
118
|
+
case 401:
|
|
119
|
+
throw new UnauthorizedError(error);
|
|
120
|
+
case 403:
|
|
121
|
+
throw new ForbiddenError(error);
|
|
122
|
+
case 404:
|
|
123
|
+
throw new NotFoundError(error);
|
|
124
|
+
case 422:
|
|
125
|
+
throw new ValidationError(error);
|
|
126
|
+
default:
|
|
127
|
+
throw new NextvisitApiError(response.status, error);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Execute a fetch request with timeout
|
|
132
|
+
*/
|
|
133
|
+
async executeFetch(url, init, signal) {
|
|
134
|
+
const controller = new AbortController();
|
|
135
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
136
|
+
const combinedSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
|
|
137
|
+
try {
|
|
138
|
+
const response = await this.fetchFn(url, {
|
|
139
|
+
...init,
|
|
140
|
+
signal: combinedSignal
|
|
141
|
+
});
|
|
142
|
+
clearTimeout(timeoutId);
|
|
143
|
+
return response;
|
|
144
|
+
} catch (err) {
|
|
145
|
+
clearTimeout(timeoutId);
|
|
146
|
+
if (err instanceof Error) {
|
|
147
|
+
if (err.name === "AbortError") {
|
|
148
|
+
throw new NetworkError("Request was aborted or timed out", err);
|
|
149
|
+
}
|
|
150
|
+
throw new NetworkError(`Network request failed: ${err.message}`, err);
|
|
151
|
+
}
|
|
152
|
+
throw new NetworkError("Network request failed");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Make a GET request
|
|
157
|
+
*/
|
|
158
|
+
async get(path, options) {
|
|
159
|
+
const url = this.buildUrl(path, options?.params);
|
|
160
|
+
const headers = this.buildHeaders(options);
|
|
161
|
+
const response = await this.executeFetch(
|
|
162
|
+
url,
|
|
163
|
+
{ method: "GET", headers },
|
|
164
|
+
options?.signal
|
|
165
|
+
);
|
|
166
|
+
if (!response.ok) {
|
|
167
|
+
await this.handleError(response);
|
|
168
|
+
}
|
|
169
|
+
return await response.json();
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Make a POST request with JSON body
|
|
173
|
+
*/
|
|
174
|
+
async post(path, body, options) {
|
|
175
|
+
const url = this.buildUrl(path, options?.params);
|
|
176
|
+
const headers = this.buildHeaders(options, "application/json");
|
|
177
|
+
const response = await this.executeFetch(
|
|
178
|
+
url,
|
|
179
|
+
{
|
|
180
|
+
method: "POST",
|
|
181
|
+
headers,
|
|
182
|
+
body: body ? JSON.stringify(body) : void 0
|
|
183
|
+
},
|
|
184
|
+
options?.signal
|
|
185
|
+
);
|
|
186
|
+
if (!response.ok) {
|
|
187
|
+
await this.handleError(response);
|
|
188
|
+
}
|
|
189
|
+
return await response.json();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Make a POST request with FormData body (for file uploads)
|
|
193
|
+
*/
|
|
194
|
+
async postForm(path, formData, options) {
|
|
195
|
+
const url = this.buildUrl(path, options?.params);
|
|
196
|
+
const headers = this.buildHeaders(options);
|
|
197
|
+
const response = await this.executeFetch(
|
|
198
|
+
url,
|
|
199
|
+
{
|
|
200
|
+
method: "POST",
|
|
201
|
+
headers,
|
|
202
|
+
body: formData
|
|
203
|
+
},
|
|
204
|
+
options?.signal
|
|
205
|
+
);
|
|
206
|
+
if (!response.ok) {
|
|
207
|
+
await this.handleError(response);
|
|
208
|
+
}
|
|
209
|
+
return await response.json();
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Make a PUT request with JSON body
|
|
213
|
+
*/
|
|
214
|
+
async put(path, body, options) {
|
|
215
|
+
const url = this.buildUrl(path, options?.params);
|
|
216
|
+
const headers = this.buildHeaders(options, "application/json");
|
|
217
|
+
const response = await this.executeFetch(
|
|
218
|
+
url,
|
|
219
|
+
{
|
|
220
|
+
method: "PUT",
|
|
221
|
+
headers,
|
|
222
|
+
body: body ? JSON.stringify(body) : void 0
|
|
223
|
+
},
|
|
224
|
+
options?.signal
|
|
225
|
+
);
|
|
226
|
+
if (!response.ok) {
|
|
227
|
+
await this.handleError(response);
|
|
228
|
+
}
|
|
229
|
+
return await response.json();
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Make a DELETE request
|
|
233
|
+
*/
|
|
234
|
+
async delete(path, options) {
|
|
235
|
+
const url = this.buildUrl(path, options?.params);
|
|
236
|
+
const headers = this.buildHeaders(options);
|
|
237
|
+
const response = await this.executeFetch(
|
|
238
|
+
url,
|
|
239
|
+
{ method: "DELETE", headers },
|
|
240
|
+
options?.signal
|
|
241
|
+
);
|
|
242
|
+
if (!response.ok) {
|
|
243
|
+
await this.handleError(response);
|
|
244
|
+
}
|
|
245
|
+
return await response.json();
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// src/resources/base.ts
|
|
250
|
+
var BaseResource = class {
|
|
251
|
+
constructor(http) {
|
|
252
|
+
this.http = http;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// src/resources/auth.ts
|
|
257
|
+
var AuthResource = class extends BaseResource {
|
|
258
|
+
/**
|
|
259
|
+
* Create a new access token (login)
|
|
260
|
+
*
|
|
261
|
+
* Authenticates a user with email and password, returning an access token
|
|
262
|
+
* that can be used for subsequent API requests.
|
|
263
|
+
*
|
|
264
|
+
* @param credentials - Login credentials
|
|
265
|
+
* @returns Token response with access token and user info
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```typescript
|
|
269
|
+
* const response = await client.auth.createToken({
|
|
270
|
+
* email: "user@example.com",
|
|
271
|
+
* password: "password123",
|
|
272
|
+
* device_name: "My App"
|
|
273
|
+
* });
|
|
274
|
+
*
|
|
275
|
+
* console.log(response.token); // Use this token for authentication
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
async createToken(credentials) {
|
|
279
|
+
return this.http.post("/v1/auth/tokens", credentials);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Authenticate with Google Sign-In
|
|
283
|
+
*
|
|
284
|
+
* Authenticates a user using a Google ID token obtained from Google Sign-In SDK.
|
|
285
|
+
* Supports tokens from web applications, Chrome extensions, iOS apps, and Android apps.
|
|
286
|
+
* If the user doesn't exist, a new account is automatically created.
|
|
287
|
+
*
|
|
288
|
+
* @param params - Google authentication parameters
|
|
289
|
+
* @returns Authentication response with access token and user info
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```typescript
|
|
293
|
+
* // Web application
|
|
294
|
+
* const response = await client.auth.googleAuth({
|
|
295
|
+
* id_token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
296
|
+
* device_name: "Web Browser"
|
|
297
|
+
* });
|
|
298
|
+
*
|
|
299
|
+
* if (response.is_new_user) {
|
|
300
|
+
* console.log("Welcome! Your account has been created.");
|
|
301
|
+
* }
|
|
302
|
+
*
|
|
303
|
+
* // Use response.token for subsequent requests
|
|
304
|
+
* client.setToken(response.token);
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
async googleAuth(params) {
|
|
308
|
+
return this.http.post("/v1/auth/google", params);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Revoke the current access token (logout)
|
|
312
|
+
*
|
|
313
|
+
* Invalidates the current authentication token. After calling this method,
|
|
314
|
+
* the token can no longer be used for API requests.
|
|
315
|
+
*
|
|
316
|
+
* @returns Confirmation message
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```typescript
|
|
320
|
+
* await client.auth.revokeCurrentToken();
|
|
321
|
+
* // Token is now invalid
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
async revokeCurrentToken() {
|
|
325
|
+
return this.http.delete("/v1/auth/tokens/current");
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* List all tokens for the authenticated user
|
|
329
|
+
*
|
|
330
|
+
* Returns a list of all active tokens associated with the current user,
|
|
331
|
+
* including information about when each token was created and last used.
|
|
332
|
+
*
|
|
333
|
+
* @returns List of tokens
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```typescript
|
|
337
|
+
* const response = await client.auth.listTokens();
|
|
338
|
+
*
|
|
339
|
+
* for (const token of response.tokens) {
|
|
340
|
+
* console.log(`${token.name} - Created: ${token.created_at}`);
|
|
341
|
+
* }
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
async listTokens() {
|
|
345
|
+
return this.http.get("/v1/auth/tokens");
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Revoke a specific token by ID
|
|
349
|
+
*
|
|
350
|
+
* Invalidates a specific token by its ID. This can be used to revoke
|
|
351
|
+
* tokens on other devices or applications.
|
|
352
|
+
*
|
|
353
|
+
* @param id - The unique identifier of the token to revoke
|
|
354
|
+
* @returns Confirmation message
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```typescript
|
|
358
|
+
* // List tokens and revoke a specific one
|
|
359
|
+
* const { tokens } = await client.auth.listTokens();
|
|
360
|
+
* const oldToken = tokens.find(t => t.name === "Old Device");
|
|
361
|
+
*
|
|
362
|
+
* if (oldToken) {
|
|
363
|
+
* await client.auth.revokeToken(oldToken.id);
|
|
364
|
+
* console.log("Token revoked");
|
|
365
|
+
* }
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
async revokeToken(id) {
|
|
369
|
+
return this.http.delete(`/v1/auth/tokens/${id}`);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
// src/resources/users.ts
|
|
374
|
+
var UsersResource = class extends BaseResource {
|
|
375
|
+
/**
|
|
376
|
+
* Get the currently authenticated user
|
|
377
|
+
*
|
|
378
|
+
* Retrieves the full profile of the user associated with the current
|
|
379
|
+
* authentication token.
|
|
380
|
+
*
|
|
381
|
+
* @returns The authenticated user's details
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```typescript
|
|
385
|
+
* const user = await client.users.getCurrentUser();
|
|
386
|
+
* console.log(`Logged in as ${user.name} (${user.email})`);
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
async getCurrentUser() {
|
|
390
|
+
return this.http.get("/user");
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
// src/resources/patients.ts
|
|
395
|
+
var PatientsResource = class extends BaseResource {
|
|
396
|
+
/**
|
|
397
|
+
* List patients
|
|
398
|
+
*
|
|
399
|
+
* Returns a paginated list of patients with optional filtering
|
|
400
|
+
* and customizable pagination/sorting.
|
|
401
|
+
*
|
|
402
|
+
* @param params - Optional filtering and pagination parameters
|
|
403
|
+
* @returns Paginated list of patients
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```typescript
|
|
407
|
+
* // Get all patients
|
|
408
|
+
* const patients = await client.patients.list();
|
|
409
|
+
*
|
|
410
|
+
* // Filter and sort patients
|
|
411
|
+
* const filtered = await client.patients.list({
|
|
412
|
+
* "filter[last_name]": "Smith",
|
|
413
|
+
* sort: "-created_at",
|
|
414
|
+
* per_page: 25
|
|
415
|
+
* });
|
|
416
|
+
*
|
|
417
|
+
* // Include soft-deleted patients
|
|
418
|
+
* const withTrashed = await client.patients.list({
|
|
419
|
+
* "filter[trashed]": "with"
|
|
420
|
+
* });
|
|
421
|
+
* ```
|
|
422
|
+
*/
|
|
423
|
+
async list(params) {
|
|
424
|
+
return this.http.get("/v1/patients", {
|
|
425
|
+
params
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Get a specific patient
|
|
430
|
+
*
|
|
431
|
+
* Retrieves detailed information about a single patient by their ID.
|
|
432
|
+
*
|
|
433
|
+
* @param id - The patient ID
|
|
434
|
+
* @returns The patient details wrapped in a response object
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```typescript
|
|
438
|
+
* const response = await client.patients.get(123);
|
|
439
|
+
* console.log(response.data.first_name);
|
|
440
|
+
* console.log(response.data.date_of_birth);
|
|
441
|
+
* ```
|
|
442
|
+
*/
|
|
443
|
+
async get(id) {
|
|
444
|
+
return this.http.get(`/v1/patients/${id}`);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Create a new patient
|
|
448
|
+
*
|
|
449
|
+
* Creates a new patient record with the provided information.
|
|
450
|
+
*
|
|
451
|
+
* @param params - The patient data
|
|
452
|
+
* @returns The created patient wrapped in a response object
|
|
453
|
+
*
|
|
454
|
+
* @example
|
|
455
|
+
* ```typescript
|
|
456
|
+
* const response = await client.patients.create({
|
|
457
|
+
* first_name: "John",
|
|
458
|
+
* last_name: "Doe",
|
|
459
|
+
* date_of_birth: "1990-05-15",
|
|
460
|
+
* notes: "New patient referral",
|
|
461
|
+
* allergies: "Penicillin"
|
|
462
|
+
* });
|
|
463
|
+
*
|
|
464
|
+
* console.log(response.data.id);
|
|
465
|
+
* ```
|
|
466
|
+
*/
|
|
467
|
+
async create(params) {
|
|
468
|
+
return this.http.post("/v1/patients", params);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Update a patient
|
|
472
|
+
*
|
|
473
|
+
* Updates an existing patient's information.
|
|
474
|
+
*
|
|
475
|
+
* @param id - The patient ID
|
|
476
|
+
* @param params - The fields to update
|
|
477
|
+
* @returns The updated patient wrapped in a response object
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* ```typescript
|
|
481
|
+
* const response = await client.patients.update(123, {
|
|
482
|
+
* first_name: "Jonathan",
|
|
483
|
+
* notes: "Updated contact information"
|
|
484
|
+
* });
|
|
485
|
+
*
|
|
486
|
+
* console.log(response.data.first_name); // "Jonathan"
|
|
487
|
+
* ```
|
|
488
|
+
*/
|
|
489
|
+
async update(id, params) {
|
|
490
|
+
return this.http.put(`/v1/patients/${id}`, params);
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Delete a patient (soft delete)
|
|
494
|
+
*
|
|
495
|
+
* Soft deletes a patient record. The patient can be restored or
|
|
496
|
+
* permanently deleted later. Use the trashed filter to view deleted patients.
|
|
497
|
+
*
|
|
498
|
+
* @param id - The patient ID
|
|
499
|
+
* @returns Confirmation message
|
|
500
|
+
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```typescript
|
|
503
|
+
* await client.patients.delete(123);
|
|
504
|
+
* console.log("Patient soft deleted successfully");
|
|
505
|
+
*
|
|
506
|
+
* // View deleted patients
|
|
507
|
+
* const deleted = await client.patients.list({
|
|
508
|
+
* "filter[trashed]": "only"
|
|
509
|
+
* });
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
async delete(id) {
|
|
513
|
+
return this.http.delete(`/v1/patients/${id}`);
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Search patients
|
|
517
|
+
*
|
|
518
|
+
* Searches for patients matching the query string within the authenticated
|
|
519
|
+
* user's current team.
|
|
520
|
+
*
|
|
521
|
+
* @param params - Search parameters including query string
|
|
522
|
+
* @returns Paginated list of matching patients
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```typescript
|
|
526
|
+
* // Search for patients by name
|
|
527
|
+
* const results = await client.patients.search({
|
|
528
|
+
* query: "John",
|
|
529
|
+
* per_page: 10,
|
|
530
|
+
* sort_by: "desc"
|
|
531
|
+
* });
|
|
532
|
+
*
|
|
533
|
+
* console.log(`Found ${results.meta.total} patients`);
|
|
534
|
+
* results.data.forEach(patient => {
|
|
535
|
+
* console.log(`${patient.first_name} ${patient.last_name}`);
|
|
536
|
+
* });
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
async search(params) {
|
|
540
|
+
return this.http.get(
|
|
541
|
+
`/v1/patients/search`,
|
|
542
|
+
{
|
|
543
|
+
params
|
|
544
|
+
}
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
// src/resources/progress-notes.ts
|
|
550
|
+
var ProgressNotesResource = class extends BaseResource {
|
|
551
|
+
/**
|
|
552
|
+
* List progress notes
|
|
553
|
+
*
|
|
554
|
+
* Returns a paginated list of progress notes with optional filtering
|
|
555
|
+
* by patient and customizable pagination/sorting.
|
|
556
|
+
*
|
|
557
|
+
* @param params - Optional filtering and pagination parameters
|
|
558
|
+
* @returns Paginated list of progress notes
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
* ```typescript
|
|
562
|
+
* // Get latest notes
|
|
563
|
+
* const notes = await client.progressNotes.list();
|
|
564
|
+
*
|
|
565
|
+
* // Filter by patient
|
|
566
|
+
* const patientNotes = await client.progressNotes.list({
|
|
567
|
+
* patient_id: 123,
|
|
568
|
+
* per_page: 25,
|
|
569
|
+
* sort_by: "oldest"
|
|
570
|
+
* });
|
|
571
|
+
* ```
|
|
572
|
+
*/
|
|
573
|
+
async list(params) {
|
|
574
|
+
return this.http.get("/v1/progress-notes", {
|
|
575
|
+
params
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Get a specific progress note
|
|
580
|
+
*
|
|
581
|
+
* Retrieves detailed information about a single progress note by its ID.
|
|
582
|
+
*
|
|
583
|
+
* @param id - The progress note ID
|
|
584
|
+
* @returns The progress note details
|
|
585
|
+
*
|
|
586
|
+
* @example
|
|
587
|
+
* ```typescript
|
|
588
|
+
* const note = await client.progressNotes.get(123);
|
|
589
|
+
* console.log(note.name);
|
|
590
|
+
* console.log(note.transcription);
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
async get(id) {
|
|
594
|
+
return this.http.get(`/v1/progress-notes/${id}`);
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Get audio URL for a progress note
|
|
598
|
+
*
|
|
599
|
+
* Retrieves a temporary URL to access the audio file associated with
|
|
600
|
+
* a progress note. The URL is time-limited and will expire.
|
|
601
|
+
*
|
|
602
|
+
* @param id - The progress note ID
|
|
603
|
+
* @returns Object containing the temporary audio URL
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* ```typescript
|
|
607
|
+
* const response = await client.progressNotes.getAudioUrl(123);
|
|
608
|
+
* console.log(response.url); // Temporary URL to audio file
|
|
609
|
+
* ```
|
|
610
|
+
*/
|
|
611
|
+
async getAudioUrl(id) {
|
|
612
|
+
return this.http.get(`/v1/progress-notes/${id}/audio-url`);
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Create a new progress note
|
|
616
|
+
*
|
|
617
|
+
* Creates a new progress note with either an audio file or text content.
|
|
618
|
+
* For audio files, the audio will be transcribed and analyzed asynchronously.
|
|
619
|
+
* For text-only notes, provide the note content directly.
|
|
620
|
+
*
|
|
621
|
+
* @param params - The progress note data (audio file or text-only)
|
|
622
|
+
* @returns The created progress note
|
|
623
|
+
*
|
|
624
|
+
* @example
|
|
625
|
+
* ```typescript
|
|
626
|
+
* // With audio file
|
|
627
|
+
* const audioFile = new File([audioBlob], "recording.mp3", {
|
|
628
|
+
* type: "audio/mpeg"
|
|
629
|
+
* });
|
|
630
|
+
*
|
|
631
|
+
* const note = await client.progressNotes.create({
|
|
632
|
+
* name: "Follow-up Visit - John Doe",
|
|
633
|
+
* patient_id: 456,
|
|
634
|
+
* file: audioFile,
|
|
635
|
+
* model_id: 1 // Optional template
|
|
636
|
+
* });
|
|
637
|
+
*
|
|
638
|
+
* // Text-only note
|
|
639
|
+
* const textNote = await client.progressNotes.create({
|
|
640
|
+
* name: "Patient Consultation",
|
|
641
|
+
* note: "Patient presented with symptoms of...",
|
|
642
|
+
* model_id: 1,
|
|
643
|
+
* patient_id: 456
|
|
644
|
+
* });
|
|
645
|
+
* ```
|
|
646
|
+
*/
|
|
647
|
+
async create(params) {
|
|
648
|
+
const formData = new FormData();
|
|
649
|
+
formData.append("name", params.name);
|
|
650
|
+
if (params.patient_id !== void 0) {
|
|
651
|
+
formData.append("patient_id", String(params.patient_id));
|
|
652
|
+
}
|
|
653
|
+
if (params.context !== void 0) {
|
|
654
|
+
formData.append("context", params.context);
|
|
655
|
+
}
|
|
656
|
+
if ("file" in params) {
|
|
657
|
+
const fileParams = params;
|
|
658
|
+
formData.append("file", fileParams.file);
|
|
659
|
+
if (fileParams.model_id !== void 0) {
|
|
660
|
+
formData.append("model_id", String(fileParams.model_id));
|
|
661
|
+
}
|
|
662
|
+
} else {
|
|
663
|
+
const textParams = params;
|
|
664
|
+
formData.append("note", textParams.note);
|
|
665
|
+
formData.append("model_id", String(textParams.model_id));
|
|
666
|
+
if (textParams.documents !== void 0 && textParams.documents.length > 0) {
|
|
667
|
+
for (const docId of textParams.documents) {
|
|
668
|
+
formData.append("documents[]", String(docId));
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return this.http.postForm("/v1/progress-notes", formData);
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Update a progress note
|
|
676
|
+
*
|
|
677
|
+
* Updates an existing progress note's metadata, transcription, or analysis.
|
|
678
|
+
*
|
|
679
|
+
* @param id - The progress note ID
|
|
680
|
+
* @param params - The fields to update
|
|
681
|
+
* @returns The updated progress note
|
|
682
|
+
*
|
|
683
|
+
* @example
|
|
684
|
+
* ```typescript
|
|
685
|
+
* const updated = await client.progressNotes.update(123, {
|
|
686
|
+
* name: "Updated Visit Name",
|
|
687
|
+
* transcription: "Corrected transcription text..."
|
|
688
|
+
* });
|
|
689
|
+
* ```
|
|
690
|
+
*/
|
|
691
|
+
async update(id, params) {
|
|
692
|
+
return this.http.put(`/v1/progress-notes/${id}`, params);
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Delete a progress note
|
|
696
|
+
*
|
|
697
|
+
* Permanently deletes a progress note and its associated audio files.
|
|
698
|
+
* This action cannot be undone.
|
|
699
|
+
*
|
|
700
|
+
* @param id - The progress note ID
|
|
701
|
+
* @returns Confirmation message
|
|
702
|
+
*
|
|
703
|
+
* @example
|
|
704
|
+
* ```typescript
|
|
705
|
+
* await client.progressNotes.delete(123);
|
|
706
|
+
* console.log("Note deleted successfully");
|
|
707
|
+
* ```
|
|
708
|
+
*/
|
|
709
|
+
async delete(id) {
|
|
710
|
+
return this.http.delete(`/v1/progress-notes/${id}`);
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Sign a progress note
|
|
714
|
+
*
|
|
715
|
+
* Marks a progress note as reviewed and signed. A note can only be signed
|
|
716
|
+
* after transcription and analysis have been completed.
|
|
717
|
+
*
|
|
718
|
+
* @param id - The progress note ID
|
|
719
|
+
* @returns The signed progress note
|
|
720
|
+
*
|
|
721
|
+
* @example
|
|
722
|
+
* ```typescript
|
|
723
|
+
* const signedNote = await client.progressNotes.sign(123);
|
|
724
|
+
* console.log(signedNote.has?.signed); // true
|
|
725
|
+
* ```
|
|
726
|
+
*/
|
|
727
|
+
async sign(id) {
|
|
728
|
+
return this.http.put(`/v1/progress-notes/${id}/sign`);
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
// src/resources/billing.ts
|
|
733
|
+
var BillingResource = class extends BaseResource {
|
|
734
|
+
/**
|
|
735
|
+
* List available billing plans
|
|
736
|
+
*
|
|
737
|
+
* Retrieves all available billing plans that can be subscribed to,
|
|
738
|
+
* including pricing information and features.
|
|
739
|
+
*
|
|
740
|
+
* @returns List of available billing plans
|
|
741
|
+
*
|
|
742
|
+
* @example
|
|
743
|
+
* ```typescript
|
|
744
|
+
* const response = await client.billing.listPlans();
|
|
745
|
+
*
|
|
746
|
+
* for (const plan of response.plans) {
|
|
747
|
+
* console.log(`${plan.name}: ${plan.price_prefix}${plan.price}${plan.price_suffix}`);
|
|
748
|
+
* if (plan.features) {
|
|
749
|
+
* plan.features.forEach(feature => console.log(` - ${feature}`));
|
|
750
|
+
* }
|
|
751
|
+
* }
|
|
752
|
+
* ```
|
|
753
|
+
*/
|
|
754
|
+
async listPlans() {
|
|
755
|
+
return this.http.get("/v1/billing/plans");
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Get billing cost estimate
|
|
759
|
+
*
|
|
760
|
+
* Calculates the estimated billing cost based on the current number
|
|
761
|
+
* of users in the team and any child teams.
|
|
762
|
+
*
|
|
763
|
+
* @returns Billing cost estimate with user count and formatted total
|
|
764
|
+
*
|
|
765
|
+
* @example
|
|
766
|
+
* ```typescript
|
|
767
|
+
* const estimate = await client.billing.getEstimate();
|
|
768
|
+
*
|
|
769
|
+
* console.log(`Users: ${estimate.users}`);
|
|
770
|
+
* console.log(`Estimated cost: ${estimate.total_formatted}`);
|
|
771
|
+
* console.log(`Next renewal: ${estimate.renewal_date}`);
|
|
772
|
+
* ```
|
|
773
|
+
*/
|
|
774
|
+
async getEstimate() {
|
|
775
|
+
return this.http.get("/v1/billing/estimate");
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Get billing usage statistics
|
|
779
|
+
*
|
|
780
|
+
* Retrieves usage statistics for a specific billing module, including
|
|
781
|
+
* the current subscription plan status and detailed usage metrics.
|
|
782
|
+
*
|
|
783
|
+
* @param module - The billing module to get usage for (e.g., 'notes')
|
|
784
|
+
* @returns Billing usage with plan status and usage statistics
|
|
785
|
+
*
|
|
786
|
+
* @example
|
|
787
|
+
* ```typescript
|
|
788
|
+
* const usage = await client.billing.getUsage("notes");
|
|
789
|
+
*
|
|
790
|
+
* console.log(`Plan: ${usage.plan.name} (${usage.plan.status})`);
|
|
791
|
+
* console.log(`Usage: ${usage.usage.used} / ${usage.usage.limit}`);
|
|
792
|
+
* console.log(`Period: ${usage.usage.period_start} to ${usage.usage.period_end}`);
|
|
793
|
+
*
|
|
794
|
+
* if (usage.plan.trial.on_trial) {
|
|
795
|
+
* console.log(`Trial ends: ${usage.plan.trial.trial_ends_at}`);
|
|
796
|
+
* }
|
|
797
|
+
* ```
|
|
798
|
+
*/
|
|
799
|
+
async getUsage(module) {
|
|
800
|
+
return this.http.get(`/v1/billing/usage/${module}`);
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
// src/resources/transcription.ts
|
|
805
|
+
var TranscriptionResource = class extends BaseResource {
|
|
806
|
+
/**
|
|
807
|
+
* Transcribe an audio file
|
|
808
|
+
*
|
|
809
|
+
* Uploads an audio file and returns the transcribed text using AI-powered speech recognition.
|
|
810
|
+
* Supported formats: mp3, mp4, m4a, wav, ogg, webm, flac, aac, pcm, opus
|
|
811
|
+
* Maximum file size: 200MB
|
|
812
|
+
*
|
|
813
|
+
* @param params - The transcription parameters including the audio file
|
|
814
|
+
* @returns Transcription response with the transcribed text
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* ```typescript
|
|
818
|
+
* // Transcribe an audio file from a file input
|
|
819
|
+
* const fileInput = document.querySelector('input[type="file"]');
|
|
820
|
+
* const file = fileInput.files[0];
|
|
821
|
+
*
|
|
822
|
+
* const response = await client.transcription.transcribeFile({ file });
|
|
823
|
+
*
|
|
824
|
+
* if (response.success) {
|
|
825
|
+
* console.log(response.text); // The transcribed text
|
|
826
|
+
* }
|
|
827
|
+
* ```
|
|
828
|
+
*
|
|
829
|
+
* @example
|
|
830
|
+
* ```typescript
|
|
831
|
+
* // Transcribe a Blob from recorded audio
|
|
832
|
+
* const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
|
|
833
|
+
*
|
|
834
|
+
* const response = await client.transcription.transcribeFile({
|
|
835
|
+
* file: audioBlob
|
|
836
|
+
* });
|
|
837
|
+
*
|
|
838
|
+
* console.log(response.message); // Status message
|
|
839
|
+
* ```
|
|
840
|
+
*/
|
|
841
|
+
async transcribeFile(params) {
|
|
842
|
+
const formData = new FormData();
|
|
843
|
+
formData.append("file", params.file);
|
|
844
|
+
return this.http.postForm(
|
|
845
|
+
"/v1/transcribe/file",
|
|
846
|
+
formData
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Get a temporary transcription token
|
|
851
|
+
*
|
|
852
|
+
* Returns a temporary Deepgram API token for client-side audio transcription.
|
|
853
|
+
* The token is short-lived and should be used immediately.
|
|
854
|
+
*
|
|
855
|
+
* @returns Token response with the temporary API token
|
|
856
|
+
*
|
|
857
|
+
* @example
|
|
858
|
+
* ```typescript
|
|
859
|
+
* const response = await client.transcription.getToken();
|
|
860
|
+
*
|
|
861
|
+
* if (response.success && response.token) {
|
|
862
|
+
* // Use the token for client-side Deepgram SDK
|
|
863
|
+
* const deepgram = createClient(response.token);
|
|
864
|
+
* }
|
|
865
|
+
* ```
|
|
866
|
+
*/
|
|
867
|
+
async getToken() {
|
|
868
|
+
return this.http.get("/v1/transcribe/token");
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
|
|
872
|
+
// src/client.ts
|
|
873
|
+
var DEFAULT_BASE_URL = "https://nextvisit.app/api";
|
|
874
|
+
var NextvisitClient = class {
|
|
875
|
+
/**
|
|
876
|
+
* Create a new Nextvisit API client
|
|
877
|
+
*
|
|
878
|
+
* @param config - Client configuration options
|
|
879
|
+
*/
|
|
880
|
+
constructor(config = {}) {
|
|
881
|
+
const httpConfig = {
|
|
882
|
+
baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
|
|
883
|
+
token: config.token,
|
|
884
|
+
fetch: config.fetch,
|
|
885
|
+
timeout: config.timeout
|
|
886
|
+
};
|
|
887
|
+
this.http = new HttpClient(httpConfig);
|
|
888
|
+
this.auth = new AuthResource(this.http);
|
|
889
|
+
this.users = new UsersResource(this.http);
|
|
890
|
+
this.progressNotes = new ProgressNotesResource(this.http);
|
|
891
|
+
this.billing = new BillingResource(this.http);
|
|
892
|
+
this.transcription = new TranscriptionResource(this.http);
|
|
893
|
+
this.patients = new PatientsResource(this.http);
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Set the authentication token
|
|
897
|
+
*
|
|
898
|
+
* Updates the token used for API requests. Call this after
|
|
899
|
+
* authenticating with `auth.createToken()`.
|
|
900
|
+
*
|
|
901
|
+
* @param token - The authentication token
|
|
902
|
+
*
|
|
903
|
+
* @example
|
|
904
|
+
* ```typescript
|
|
905
|
+
* const { token } = await client.auth.createToken(credentials);
|
|
906
|
+
* client.setToken(token);
|
|
907
|
+
* ```
|
|
908
|
+
*/
|
|
909
|
+
setToken(token) {
|
|
910
|
+
this.http.setToken(token);
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Clear the authentication token
|
|
914
|
+
*
|
|
915
|
+
* Removes the current token. Subsequent requests will be
|
|
916
|
+
* unauthenticated.
|
|
917
|
+
*
|
|
918
|
+
* @example
|
|
919
|
+
* ```typescript
|
|
920
|
+
* await client.auth.revokeCurrentToken();
|
|
921
|
+
* client.clearToken();
|
|
922
|
+
* ```
|
|
923
|
+
*/
|
|
924
|
+
clearToken() {
|
|
925
|
+
this.http.setToken(void 0);
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Check if the client has an authentication token set
|
|
929
|
+
*
|
|
930
|
+
* @returns `true` if a token is set, `false` otherwise
|
|
931
|
+
*/
|
|
932
|
+
hasToken() {
|
|
933
|
+
return this.http.getToken() !== void 0;
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
exports.AuthResource = AuthResource;
|
|
938
|
+
exports.BillingResource = BillingResource;
|
|
939
|
+
exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
940
|
+
exports.ForbiddenError = ForbiddenError;
|
|
941
|
+
exports.NetworkError = NetworkError;
|
|
942
|
+
exports.NextvisitApiError = NextvisitApiError;
|
|
943
|
+
exports.NextvisitClient = NextvisitClient;
|
|
944
|
+
exports.NextvisitError = NextvisitError;
|
|
945
|
+
exports.NotFoundError = NotFoundError;
|
|
946
|
+
exports.PatientsResource = PatientsResource;
|
|
947
|
+
exports.ProgressNotesResource = ProgressNotesResource;
|
|
948
|
+
exports.TranscriptionResource = TranscriptionResource;
|
|
949
|
+
exports.UnauthorizedError = UnauthorizedError;
|
|
950
|
+
exports.UsersResource = UsersResource;
|
|
951
|
+
exports.ValidationError = ValidationError;
|
|
952
|
+
//# sourceMappingURL=index.js.map
|
|
953
|
+
//# sourceMappingURL=index.js.map
|