assemblyai 4.4.0 → 4.4.2-beta.0

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/node.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var web = require('stream/web');
4
- var WebSocket = require('#ws');
4
+ var ws = require('ws');
5
5
  var fs = require('fs');
6
6
  var stream = require('stream');
7
7
 
@@ -24,6 +24,7 @@ class BaseService {
24
24
  "Content-Type": "application/json",
25
25
  ...init.headers,
26
26
  };
27
+ init.cache = "no-store";
27
28
  if (!input.startsWith("http"))
28
29
  input = this.params.baseUrl + input;
29
30
  const response = await fetch(input, init);
@@ -87,6 +88,8 @@ class LemurService extends BaseService {
87
88
  }
88
89
  }
89
90
 
91
+ const factory = (url, params) => new ws(url, params);
92
+
90
93
  var RealtimeErrorType;
91
94
  (function (RealtimeErrorType) {
92
95
  RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
@@ -139,7 +142,6 @@ class RealtimeTranscriber {
139
142
  this.wordBoost = params.wordBoost;
140
143
  this.encoding = params.encoding;
141
144
  this.endUtteranceSilenceThreshold = params.endUtteranceSilenceThreshold;
142
- this.enableExtraSessionInformation = params.enableExtraSessionInformation;
143
145
  this.disablePartialTranscripts = params.disablePartialTranscripts;
144
146
  if ("token" in params && params.token)
145
147
  this.token = params.token;
@@ -165,9 +167,7 @@ class RealtimeTranscriber {
165
167
  if (this.encoding) {
166
168
  searchParams.set("encoding", this.encoding);
167
169
  }
168
- if (this.enableExtraSessionInformation) {
169
- searchParams.set("enable_extra_session_information", this.enableExtraSessionInformation.toString());
170
- }
170
+ searchParams.set("enable_extra_session_information", "true");
171
171
  if (this.disablePartialTranscripts) {
172
172
  searchParams.set("disable_partial_transcripts", this.disablePartialTranscripts.toString());
173
173
  }
@@ -185,10 +185,10 @@ class RealtimeTranscriber {
185
185
  }
186
186
  const url = this.connectionUrl();
187
187
  if (this.token) {
188
- this.socket = new WebSocket(url.toString());
188
+ this.socket = factory(url.toString());
189
189
  }
190
190
  else {
191
- this.socket = new WebSocket(url.toString(), {
191
+ this.socket = factory(url.toString(), {
192
192
  headers: { Authorization: this.apiKey },
193
193
  });
194
194
  }
@@ -281,14 +281,14 @@ class RealtimeTranscriber {
281
281
  this.send(`{"end_utterance_silence_threshold":${threshold}}`);
282
282
  }
283
283
  send(data) {
284
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
284
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
285
285
  throw new Error("Socket is not open for communication");
286
286
  }
287
287
  this.socket.send(data);
288
288
  }
289
289
  async close(waitForSessionTermination = true) {
290
290
  if (this.socket) {
291
- if (this.socket.readyState === WebSocket.OPEN) {
291
+ if (this.socket.readyState === this.socket.OPEN) {
292
292
  if (waitForSessionTermination) {
293
293
  const sessionTerminatedPromise = new Promise((resolve) => {
294
294
  this.sessionTerminatedResolve = resolve;
@@ -300,7 +300,7 @@ class RealtimeTranscriber {
300
300
  this.socket.send(terminateSessionMessage);
301
301
  }
302
302
  }
303
- if ("removeAllListeners" in this.socket)
303
+ if (this.socket?.removeAllListeners)
304
304
  this.socket.removeAllListeners();
305
305
  this.socket.close();
306
306
  }
@@ -351,6 +351,8 @@ function getPath(path) {
351
351
  return null;
352
352
  if (path.startsWith("https"))
353
353
  return null;
354
+ if (path.startsWith("data:"))
355
+ return null;
354
356
  if (path.startsWith("file://"))
355
357
  return path.substring(7);
356
358
  if (path.startsWith("file:"))
@@ -392,8 +394,13 @@ class TranscriptService extends BaseService {
392
394
  audioUrl = await this.files.upload(path);
393
395
  }
394
396
  else {
395
- // audio is not a local path, assume it's a URL
396
- audioUrl = audio;
397
+ if (audio.startsWith("data:")) {
398
+ audioUrl = await this.files.upload(audio);
399
+ }
400
+ else {
401
+ // audio is not a local path, and not a data-URI, assume it's a normal URL
402
+ audioUrl = audio;
403
+ }
397
404
  }
398
405
  }
399
406
  else {
@@ -570,8 +577,14 @@ class FileService extends BaseService {
570
577
  */
571
578
  async upload(input) {
572
579
  let fileData;
573
- if (typeof input === "string")
574
- fileData = await readFile(input);
580
+ if (typeof input === "string") {
581
+ if (input.startsWith("data:")) {
582
+ fileData = dataUrlToBlob(input);
583
+ }
584
+ else {
585
+ fileData = await readFile(input);
586
+ }
587
+ }
575
588
  else
576
589
  fileData = input;
577
590
  const data = await this.fetchJson("/v2/upload", {
@@ -585,6 +598,17 @@ class FileService extends BaseService {
585
598
  return data.upload_url;
586
599
  }
587
600
  }
601
+ function dataUrlToBlob(dataUrl) {
602
+ const arr = dataUrl.split(",");
603
+ const mime = arr[0].match(/:(.*?);/)[1];
604
+ const bstr = atob(arr[1]);
605
+ let n = bstr.length;
606
+ const u8arr = new Uint8Array(n);
607
+ while (n--) {
608
+ u8arr[n] = bstr.charCodeAt(n);
609
+ }
610
+ return new Blob([u8arr], { type: mime });
611
+ }
588
612
 
589
613
  const defaultBaseUrl = "https://api.assemblyai.com";
590
614
  class AssemblyAI {
package/dist/node.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { WritableStream } from 'stream/web';
2
- import WebSocket from '#ws';
2
+ import ws from 'ws';
3
3
  import { createReadStream } from 'fs';
4
4
  import { Readable } from 'stream';
5
5
 
@@ -22,6 +22,7 @@ class BaseService {
22
22
  "Content-Type": "application/json",
23
23
  ...init.headers,
24
24
  };
25
+ init.cache = "no-store";
25
26
  if (!input.startsWith("http"))
26
27
  input = this.params.baseUrl + input;
27
28
  const response = await fetch(input, init);
@@ -85,6 +86,8 @@ class LemurService extends BaseService {
85
86
  }
86
87
  }
87
88
 
89
+ const factory = (url, params) => new ws(url, params);
90
+
88
91
  var RealtimeErrorType;
89
92
  (function (RealtimeErrorType) {
90
93
  RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
@@ -137,7 +140,6 @@ class RealtimeTranscriber {
137
140
  this.wordBoost = params.wordBoost;
138
141
  this.encoding = params.encoding;
139
142
  this.endUtteranceSilenceThreshold = params.endUtteranceSilenceThreshold;
140
- this.enableExtraSessionInformation = params.enableExtraSessionInformation;
141
143
  this.disablePartialTranscripts = params.disablePartialTranscripts;
142
144
  if ("token" in params && params.token)
143
145
  this.token = params.token;
@@ -163,9 +165,7 @@ class RealtimeTranscriber {
163
165
  if (this.encoding) {
164
166
  searchParams.set("encoding", this.encoding);
165
167
  }
166
- if (this.enableExtraSessionInformation) {
167
- searchParams.set("enable_extra_session_information", this.enableExtraSessionInformation.toString());
168
- }
168
+ searchParams.set("enable_extra_session_information", "true");
169
169
  if (this.disablePartialTranscripts) {
170
170
  searchParams.set("disable_partial_transcripts", this.disablePartialTranscripts.toString());
171
171
  }
@@ -183,10 +183,10 @@ class RealtimeTranscriber {
183
183
  }
184
184
  const url = this.connectionUrl();
185
185
  if (this.token) {
186
- this.socket = new WebSocket(url.toString());
186
+ this.socket = factory(url.toString());
187
187
  }
188
188
  else {
189
- this.socket = new WebSocket(url.toString(), {
189
+ this.socket = factory(url.toString(), {
190
190
  headers: { Authorization: this.apiKey },
191
191
  });
192
192
  }
@@ -279,14 +279,14 @@ class RealtimeTranscriber {
279
279
  this.send(`{"end_utterance_silence_threshold":${threshold}}`);
280
280
  }
281
281
  send(data) {
282
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
282
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
283
283
  throw new Error("Socket is not open for communication");
284
284
  }
285
285
  this.socket.send(data);
286
286
  }
287
287
  async close(waitForSessionTermination = true) {
288
288
  if (this.socket) {
289
- if (this.socket.readyState === WebSocket.OPEN) {
289
+ if (this.socket.readyState === this.socket.OPEN) {
290
290
  if (waitForSessionTermination) {
291
291
  const sessionTerminatedPromise = new Promise((resolve) => {
292
292
  this.sessionTerminatedResolve = resolve;
@@ -298,7 +298,7 @@ class RealtimeTranscriber {
298
298
  this.socket.send(terminateSessionMessage);
299
299
  }
300
300
  }
301
- if ("removeAllListeners" in this.socket)
301
+ if (this.socket?.removeAllListeners)
302
302
  this.socket.removeAllListeners();
303
303
  this.socket.close();
304
304
  }
@@ -349,6 +349,8 @@ function getPath(path) {
349
349
  return null;
350
350
  if (path.startsWith("https"))
351
351
  return null;
352
+ if (path.startsWith("data:"))
353
+ return null;
352
354
  if (path.startsWith("file://"))
353
355
  return path.substring(7);
354
356
  if (path.startsWith("file:"))
@@ -390,8 +392,13 @@ class TranscriptService extends BaseService {
390
392
  audioUrl = await this.files.upload(path);
391
393
  }
392
394
  else {
393
- // audio is not a local path, assume it's a URL
394
- audioUrl = audio;
395
+ if (audio.startsWith("data:")) {
396
+ audioUrl = await this.files.upload(audio);
397
+ }
398
+ else {
399
+ // audio is not a local path, and not a data-URI, assume it's a normal URL
400
+ audioUrl = audio;
401
+ }
395
402
  }
396
403
  }
397
404
  else {
@@ -568,8 +575,14 @@ class FileService extends BaseService {
568
575
  */
569
576
  async upload(input) {
570
577
  let fileData;
571
- if (typeof input === "string")
572
- fileData = await readFile(input);
578
+ if (typeof input === "string") {
579
+ if (input.startsWith("data:")) {
580
+ fileData = dataUrlToBlob(input);
581
+ }
582
+ else {
583
+ fileData = await readFile(input);
584
+ }
585
+ }
573
586
  else
574
587
  fileData = input;
575
588
  const data = await this.fetchJson("/v2/upload", {
@@ -583,6 +596,17 @@ class FileService extends BaseService {
583
596
  return data.upload_url;
584
597
  }
585
598
  }
599
+ function dataUrlToBlob(dataUrl) {
600
+ const arr = dataUrl.split(",");
601
+ const mime = arr[0].match(/:(.*?);/)[1];
602
+ const bstr = atob(arr[1]);
603
+ let n = bstr.length;
604
+ const u8arr = new Uint8Array(n);
605
+ while (n--) {
606
+ u8arr[n] = bstr.charCodeAt(n);
607
+ }
608
+ return new Blob([u8arr], { type: mime });
609
+ }
586
610
 
587
611
  const defaultBaseUrl = "https://api.assemblyai.com";
588
612
  class AssemblyAI {
@@ -0,0 +1,3 @@
1
+ import { PolyfillWebSocketFactory } from ".";
2
+ export { PolyfillWebSocket } from ".";
3
+ export declare const factory: PolyfillWebSocketFactory;
@@ -0,0 +1,3 @@
1
+ import { PolyfillWebSocketFactory } from ".";
2
+ export { PolyfillWebSocket } from ".";
3
+ export declare const factory: PolyfillWebSocketFactory;
@@ -0,0 +1,27 @@
1
+ /// <reference types="node" />
2
+ import ws, { Event, ErrorEvent, CloseEvent, MessageEvent } from "ws";
3
+ export type PolyfillWebSocket = {
4
+ OPEN: typeof ws.OPEN;
5
+ binaryType: string;
6
+ onopen: ((event: Event) => void) | null;
7
+ onerror: ((event: ErrorEvent) => void) | null;
8
+ onclose: ((event: CloseEvent) => void) | null;
9
+ onmessage: ((event: MessageEvent) => void) | null;
10
+ readonly readyState: typeof ws.CONNECTING | typeof ws.OPEN | typeof ws.CLOSING | typeof ws.CLOSED;
11
+ removeAllListeners?: () => void;
12
+ send(data: string | number | Buffer | DataView | ArrayBufferView | Uint8Array | ArrayBuffer | SharedArrayBuffer | readonly unknown[] | readonly number[] | {
13
+ valueOf(): ArrayBuffer;
14
+ } | {
15
+ valueOf(): SharedArrayBuffer;
16
+ } | {
17
+ valueOf(): Uint8Array;
18
+ } | {
19
+ valueOf(): readonly number[];
20
+ } | {
21
+ valueOf(): string;
22
+ } | {
23
+ [Symbol.toPrimitive](hint: string): string;
24
+ }): unknown;
25
+ close(): unknown;
26
+ };
27
+ export type PolyfillWebSocketFactory = (url: string, params?: unknown) => PolyfillWebSocket;
@@ -7,7 +7,6 @@ export declare class RealtimeTranscriber {
7
7
  private apiKey?;
8
8
  private token?;
9
9
  private endUtteranceSilenceThreshold?;
10
- private enableExtraSessionInformation?;
11
10
  private disablePartialTranscripts?;
12
11
  private socket?;
13
12
  private listeners;
@@ -721,7 +721,7 @@ export type LemurQuestionAnswerResponse = LemurBaseResponse & {
721
721
  * ```js
722
722
  * {
723
723
  * "transcript_ids": [
724
- * "64nygnr62k-405c-4ae8-8a6b-d90b40ff3cce"
724
+ * "47b95ba5-8889-44d8-bc80-5de38306e582"
725
725
  * ],
726
726
  * "context": "This is an interview about wildfires.",
727
727
  * "final_model": "default",
@@ -828,7 +828,6 @@ export type ListTranscriptParams = {
828
828
  throttled_only?: boolean;
829
829
  };
830
830
  /**
831
- * Details of the transcript page.
832
831
  * Details of the transcript page. Transcripts are sorted from newest to oldest. The previous URL always points to a page with older transcripts.
833
832
  * @example
834
833
  * ```js
@@ -851,12 +850,10 @@ export type PageDetails = {
851
850
  */
852
851
  limit: number;
853
852
  /**
854
- * The URL to the next page of transcripts
855
853
  * The URL to the next page of transcripts. The next URL always points to a page with newer transcripts.
856
854
  */
857
855
  next_url: string | null;
858
856
  /**
859
- * The URL to the previous page of transcripts
860
857
  * The URL to the next page of transcripts. The previous URL always points to a page with older transcripts.
861
858
  */
862
859
  prev_url: string | null;
@@ -1124,7 +1121,7 @@ export type SentencesResponse = {
1124
1121
  };
1125
1122
  export type Sentiment = "POSITIVE" | "NEUTRAL" | "NEGATIVE";
1126
1123
  /**
1127
- * The result of the sentiment analysis model
1124
+ * The result of the Sentiment Analysis model
1128
1125
  * @example
1129
1126
  * ```js
1130
1127
  * {
@@ -2114,7 +2111,7 @@ export type Transcript = {
2114
2111
  auto_highlights: boolean;
2115
2112
  /**
2116
2113
  * An array of results for the Key Phrases model, if it is enabled.
2117
- * See {@link https://www.assemblyai.com/docs/models/key-phrases | Key phrases } for more information.
2114
+ * See {@link https://www.assemblyai.com/docs/models/key-phrases | Key Phrases } for more information.
2118
2115
  */
2119
2116
  auto_highlights_result?: AutoHighlightsResult | null;
2120
2117
  /**
@@ -2236,7 +2233,7 @@ export type Transcript = {
2236
2233
  sentiment_analysis?: boolean | null;
2237
2234
  /**
2238
2235
  * An array of results for the Sentiment Analysis model, if it is enabled.
2239
- * See {@link https://www.assemblyai.com/docs/models/sentiment-analysis | Sentiment analysis } for more information.
2236
+ * See {@link https://www.assemblyai.com/docs/models/sentiment-analysis | Sentiment Analysis } for more information.
2240
2237
  */
2241
2238
  sentiment_analysis_results?: SentimentAnalysisResult[] | null;
2242
2239
  /**
@@ -2313,7 +2310,7 @@ export type Transcript = {
2313
2310
  */
2314
2311
  webhook_status_code?: number | null;
2315
2312
  /**
2316
- * The URL to which we send webhooks upon trancription completion
2313
+ * The URL to which we send webhooks upon transcription completion
2317
2314
  */
2318
2315
  webhook_url?: string | null;
2319
2316
  /**
@@ -2358,9 +2355,8 @@ export type TranscriptCustomSpelling = {
2358
2355
  *
2359
2356
  * @defaultValue "en_us
2360
2357
  */
2361
- export type TranscriptLanguageCode = "en" | "en_au" | "en_uk" | "en_us" | "es" | "fr" | "de" | "it" | "pt" | "nl" | "hi" | "ja" | "zh" | "fi" | "ko" | "pl" | "ru" | "tr" | "uk" | "vi";
2358
+ export type TranscriptLanguageCode = "en" | "en_au" | "en_uk" | "en_us" | "es" | "fr" | "de" | "it" | "pt" | "nl" | "af" | "sq" | "am" | "ar" | "hy" | "as" | "az" | "ba" | "eu" | "be" | "bn" | "bs" | "br" | "bg" | "my" | "ca" | "zh" | "hr" | "cs" | "da" | "et" | "fo" | "fi" | "gl" | "ka" | "el" | "gu" | "ht" | "ha" | "haw" | "he" | "hi" | "hu" | "is" | "id" | "ja" | "jw" | "kn" | "kk" | "km" | "ko" | "lo" | "la" | "lv" | "ln" | "lt" | "lb" | "mk" | "mg" | "ms" | "ml" | "mt" | "mi" | "mr" | "mn" | "ne" | "no" | "nn" | "oc" | "pa" | "ps" | "fa" | "pl" | "ro" | "ru" | "sa" | "sr" | "sn" | "sd" | "si" | "sk" | "sl" | "so" | "su" | "sw" | "sv" | "tl" | "tg" | "ta" | "tt" | "te" | "th" | "bo" | "tr" | "tk" | "uk" | "ur" | "uz" | "vi" | "cy" | "yi" | "yo";
2362
2359
  /**
2363
- * A list of transcripts
2364
2360
  * A list of transcripts. Transcripts are sorted from newest to oldest. The previous URL always points to a page with older transcripts.
2365
2361
  * @example
2366
2362
  * ```js
@@ -2498,7 +2494,7 @@ export type TranscriptOptionalParams = {
2498
2494
  */
2499
2495
  auto_chapters?: boolean;
2500
2496
  /**
2501
- * Whether Key Phrases is enabled, either true or false
2497
+ * Enable Key Phrases, either true or false
2502
2498
  */
2503
2499
  auto_highlights?: boolean;
2504
2500
  /**
@@ -2510,7 +2506,7 @@ export type TranscriptOptionalParams = {
2510
2506
  */
2511
2507
  content_safety?: boolean;
2512
2508
  /**
2513
- * The confidence threshold for content moderation. Values must be between 25 and 100.
2509
+ * The confidence threshold for the Content Moderation model. Values must be between 25 and 100.
2514
2510
  */
2515
2511
  content_safety_confidence?: number;
2516
2512
  /**
@@ -2518,7 +2514,7 @@ export type TranscriptOptionalParams = {
2518
2514
  */
2519
2515
  custom_spelling?: TranscriptCustomSpelling[];
2520
2516
  /**
2521
- * Whether custom topics is enabled, either true or false
2517
+ * Enable custom topics, either true or false
2522
2518
  */
2523
2519
  custom_topics?: boolean;
2524
2520
  /**
@@ -2551,7 +2547,7 @@ export type TranscriptOptionalParams = {
2551
2547
  */
2552
2548
  language_code?: LiteralUnion<TranscriptLanguageCode, string> | null;
2553
2549
  /**
2554
- * Whether {@link https://www.assemblyai.com/docs/models/speech-recognition#automatic-language-detection | Automatic language detection } was enabled in the transcription request, either true or false.
2550
+ * Enable {@link https://www.assemblyai.com/docs/models/speech-recognition#automatic-language-detection | Automatic language detection }, either true or false.
2555
2551
  */
2556
2552
  language_detection?: boolean;
2557
2553
  /**
@@ -2619,7 +2615,7 @@ export type TranscriptOptionalParams = {
2619
2615
  */
2620
2616
  summary_type?: SummaryType;
2621
2617
  /**
2622
- * The list of custom topics provided, if custom topics is enabled
2618
+ * The list of custom topics
2623
2619
  */
2624
2620
  topics?: string[];
2625
2621
  /**
@@ -2633,7 +2629,7 @@ export type TranscriptOptionalParams = {
2633
2629
  */
2634
2630
  webhook_auth_header_value?: string | null;
2635
2631
  /**
2636
- * The URL to which AssemblyAI send webhooks upon trancription completion
2632
+ * The URL to which AssemblyAI send webhooks upon transcription completion
2637
2633
  */
2638
2634
  webhook_url?: string;
2639
2635
  /**
@@ -29,7 +29,8 @@ type CreateRealtimeTranscriberParams = {
29
29
  /**
30
30
  * Enable extra session information.
31
31
  * Set to `true` to receive the `session_information` message before the session ends. Defaults to `false`.
32
- * @defaultValue false
32
+ * @defaultValue true
33
+ * @deprecated This parameter is now ignored and will be removed. Session information will always be sent.
33
34
  */
34
35
  enableExtraSessionInformation?: boolean;
35
36
  } & ({
@@ -78,7 +79,8 @@ type RealtimeTranscriberParams = {
78
79
  /**
79
80
  * Enable extra session information.
80
81
  * Set to `true` to receive the `session_information` message before the session ends. Defaults to `false`.
81
- * @defaultValue false
82
+ * @defaultValue true
83
+ * @deprecated This parameter is now ignored and will be removed. Session information will always be sent.
82
84
  */
83
85
  enableExtraSessionInformation?: boolean;
84
86
  } & ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assemblyai",
3
- "version": "4.4.0",
3
+ "version": "4.4.2-beta.0",
4
4
  "description": "The AssemblyAI JavaScript SDK provides an easy-to-use interface for interacting with the AssemblyAI API, which supports async and real-time transcription, as well as the latest LeMUR models.",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -17,7 +17,8 @@
17
17
  "default": "./dist/deno.mjs"
18
18
  },
19
19
  "workerd": "./dist/index.mjs",
20
- "browser": "./dist/index.mjs",
20
+ "browser": "./dist/browser.mjs",
21
+ "react-native": "./dist/browser.mjs",
21
22
  "node": {
22
23
  "types": "./dist/index.d.ts",
23
24
  "import": "./dist/node.mjs",
@@ -40,14 +41,10 @@
40
41
  "node": "./src/polyfills/streams/node.ts",
41
42
  "default": "./src/polyfills/streams/index.ts"
42
43
  },
43
- "#ws": {
44
- "types": "./src/polyfills/ws/index.d.ts",
45
- "browser": "./src/polyfills/ws/browser.mjs",
46
- "default": {
47
- "types": "./src/polyfills/ws/index.d.ts",
48
- "import": "./src/polyfills/ws/index.mjs",
49
- "require": "./src/polyfills/ws/index.cjs"
50
- }
44
+ "#websocket": {
45
+ "browser": "./src/polyfills/websocket/browser.ts",
46
+ "node": "./src/polyfills/websocket/default.ts",
47
+ "default": "./src/polyfills/websocket/default.ts"
51
48
  }
52
49
  },
53
50
  "type": "commonjs",
@@ -61,7 +58,7 @@
61
58
  "url": "git+https://github.com/AssemblyAI/assemblyai-node-sdk.git"
62
59
  },
63
60
  "publishConfig": {
64
- "tag": "latest",
61
+ "tag": "beta",
65
62
  "access": "public",
66
63
  "registry": "https://registry.npmjs.org/"
67
64
  },
@@ -70,7 +67,7 @@
70
67
  "clean": "rimraf dist/* && rimraf temp/* && rimraf temp-docs/*",
71
68
  "lint": "eslint -c .eslintrc.json '{src,tests}/**/*.{js,ts}' && publint && tsc --noEmit -p tsconfig.json",
72
69
  "test": "pnpm run test:unit && pnpm run test:integration",
73
- "test:unit": "jest --config jest.unit.config.js",
70
+ "test:unit": "jest --config jest.unit.config.js --testTimeout 1000",
74
71
  "test:integration": "jest --config jest.integration.config.js --testTimeout 360000",
75
72
  "format": "prettier '**/*' --write",
76
73
  "generate:types": "tsx ./scripts/generate-types.ts && prettier 'src/types/*.generated.ts' --write",
@@ -0,0 +1,18 @@
1
+ import { PolyfillWebSocketFactory, PolyfillWebSocket } from ".";
2
+ export { PolyfillWebSocket } from ".";
3
+
4
+ const PolyfillWebSocket =
5
+ WebSocket ?? global?.WebSocket ?? window?.WebSocket ?? self?.WebSocket;
6
+
7
+ export const factory: PolyfillWebSocketFactory = (
8
+ url: string,
9
+ params?: unknown,
10
+ ) => {
11
+ if (params) {
12
+ return new PolyfillWebSocket(
13
+ url,
14
+ params as string | string[],
15
+ ) as unknown as PolyfillWebSocket;
16
+ }
17
+ return new PolyfillWebSocket(url) as unknown as PolyfillWebSocket;
18
+ };
@@ -0,0 +1,8 @@
1
+ import ws from "ws";
2
+ import { PolyfillWebSocket, PolyfillWebSocketFactory } from ".";
3
+ export { PolyfillWebSocket } from ".";
4
+
5
+ export const factory: PolyfillWebSocketFactory = (
6
+ url: string,
7
+ params?: unknown,
8
+ ) => new ws(url, params as ws.ClientOptions) as unknown as PolyfillWebSocket;
@@ -0,0 +1,41 @@
1
+ import ws, { Event, ErrorEvent, CloseEvent, MessageEvent } from "ws";
2
+
3
+ export type PolyfillWebSocket = {
4
+ OPEN: typeof ws.OPEN;
5
+ binaryType: string;
6
+ onopen: ((event: Event) => void) | null;
7
+ onerror: ((event: ErrorEvent) => void) | null;
8
+ onclose: ((event: CloseEvent) => void) | null;
9
+ onmessage: ((event: MessageEvent) => void) | null;
10
+ readonly readyState:
11
+ | typeof ws.CONNECTING
12
+ | typeof ws.OPEN
13
+ | typeof ws.CLOSING
14
+ | typeof ws.CLOSED;
15
+ removeAllListeners?: () => void;
16
+ send(
17
+ data:
18
+ | string
19
+ | number
20
+ | Buffer
21
+ | DataView
22
+ | ArrayBufferView
23
+ | Uint8Array
24
+ | ArrayBuffer
25
+ | SharedArrayBuffer
26
+ | readonly unknown[]
27
+ | readonly number[]
28
+ | { valueOf(): ArrayBuffer }
29
+ | { valueOf(): SharedArrayBuffer }
30
+ | { valueOf(): Uint8Array }
31
+ | { valueOf(): readonly number[] }
32
+ | { valueOf(): string }
33
+ | { [Symbol.toPrimitive](hint: string): string },
34
+ ): unknown;
35
+ close(): unknown;
36
+ };
37
+
38
+ export type PolyfillWebSocketFactory = (
39
+ url: string,
40
+ params?: unknown,
41
+ ) => PolyfillWebSocket;
@@ -21,6 +21,7 @@ export abstract class BaseService {
21
21
  "Content-Type": "application/json",
22
22
  ...init.headers,
23
23
  };
24
+ init.cache = "no-store";
24
25
  if (!input.startsWith("http")) input = this.params.baseUrl + input;
25
26
 
26
27
  const response = await fetch(input, init);
@@ -10,8 +10,13 @@ export class FileService extends BaseService {
10
10
  */
11
11
  async upload(input: FileUploadParams): Promise<string> {
12
12
  let fileData: FileUploadData;
13
- if (typeof input === "string") fileData = await readFile(input);
14
- else fileData = input;
13
+ if (typeof input === "string") {
14
+ if (input.startsWith("data:")) {
15
+ fileData = dataUrlToBlob(input);
16
+ } else {
17
+ fileData = await readFile(input);
18
+ }
19
+ } else fileData = input;
15
20
 
16
21
  const data = await this.fetchJson<UploadedFile>("/v2/upload", {
17
22
  method: "POST",
@@ -24,3 +29,15 @@ export class FileService extends BaseService {
24
29
  return data.upload_url;
25
30
  }
26
31
  }
32
+
33
+ function dataUrlToBlob(dataUrl: string) {
34
+ const arr = dataUrl.split(",");
35
+ const mime = arr[0].match(/:(.*?);/)![1];
36
+ const bstr = atob(arr[1]);
37
+ let n = bstr.length;
38
+ const u8arr = new Uint8Array(n);
39
+ while (n--) {
40
+ u8arr[n] = bstr.charCodeAt(n);
41
+ }
42
+ return new Blob([u8arr], { type: mime });
43
+ }