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