assemblyai 4.0.0-beta.0 → 4.0.0-beta.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/CHANGELOG.md ADDED
@@ -0,0 +1,92 @@
1
+ # Changelog
2
+
3
+ ## [4.0.0]
4
+
5
+ ### Added
6
+
7
+ - Add `browser` and `workerd` (Cloudflare Workers) exports to package.json. These exports are compatible versions of the SDK, with a few limitations. You can't use the file system and you have to use a temporary auth token with the real-time transcriber.
8
+ - Add `dist/assemblyai.umd.js` and `dist/assemblyai.umd.min.js`. You can reference these script files directly in the browser and the SDK will be available at the global `assemblyai` variable.
9
+
10
+ ### Changed
11
+
12
+ - `RealtimeService.sendAudio` accepts audio via type `ArrayBufferLike`.
13
+ - **Breaking**: `RealtimeService.stream` returns a [WHATWG Streams Standard stream](https://nodejs.org/api/webstreams.html), instead of a Node stream. In the browser, the native web standard stream will be used.
14
+ - `ws` is used as the WebSocket client as before, but in the browser, the native WebSocket client is used.
15
+ - Rename Node SDK to JavaScript SDK as the SDK is compatible with more runtimes now.
16
+
17
+ ## [3.1.1] - 2023-11-21
18
+
19
+ ### Added
20
+
21
+ - Add `client.transcripts.transcribe` function to transcribe an audio file with polling until transcript status is `completed` or `error`. This function takes an `audio` option which can be an audio file URL, path, stream, or buffer.
22
+ - Add `client.transcripts.submit` function to queue a transcript. You can use `client.transcripts.waitUntilReady` to poll the transcript returned by `submit`. This function also takes an `audio` option which can be an audio file URL, path, stream, or buffer.
23
+
24
+ ### Changed
25
+
26
+ - Deprecated `client.transcripts.create` in favor of `transcribe` and `submit`, to be more consistent with other AssemblyAI SDKs.
27
+ - Renamed types
28
+ - Renamed `Parameters` type suffix with `Params` type suffix
29
+ - Renamed `CreateTranscriptParameters` to `TranscriptParams`
30
+ - Renamed `CreateTranscriptOptionalParameters` to `TranscriptOptionalParams`.
31
+ - Added deprecated aliases for the forementioned types
32
+ - Improved type docs
33
+
34
+ ## [3.1.0] - 2023-11-16
35
+
36
+ ### Added
37
+
38
+ - Add `AssemblyAI.transcripts.waitUntilReady` function to wait until a transcript is ready, meaning `status` is `completed` or `error`.
39
+ - Add `chars_per_caption` parameter to `AssemblyAI.transcripts.subtitles` function.
40
+ - Add `input_text` property to LeMUR functions. Instead of using `transcript_ids`, you can use `input_text` to provide custom formatted transcripts as input to LeMUR.
41
+
42
+ ### Changed
43
+
44
+ - Change default timeout from 3 minutes to infinite (-1). Fixes [#17](https://github.com/AssemblyAI/assemblyai-node-sdk/issues/17)
45
+
46
+ ### Fixed
47
+
48
+ - Correctly serialize the keywords for `client.transcripts.wordSearch`.
49
+ - Use more widely compatible syntax for wildcard exporting types. Fixes [#18](https://github.com/AssemblyAI/assemblyai-node-sdk/issues/18).
50
+
51
+ ## [3.0.1] - 2023-10-30
52
+
53
+ ### Changed
54
+
55
+ - The SDK uses `fetch` instead of Axios. This removes the Axios dependency. Axios relies on XMLHttpRequest which isn't supported in Cloudflare Workers, Deno, Bun, etc. By using `fetch`, the SDK is now more compatible on the forementioned runtimes.
56
+
57
+ ### Fixed
58
+
59
+ - The SDK uses relative imports instead of using path aliases, to make the library transpilable with tsc for consumers. Fixes [#14](https://github.com/AssemblyAI/assemblyai-node-sdk/issues/14).
60
+ - Added `speaker` property to the `TranscriptUtterance` type, and removed `channel` property.
61
+
62
+ ## [3.0.0] - 2023-10-24
63
+
64
+ ### Changed
65
+
66
+ - `AssemblyAI.files.upload` accepts streams and buffers, in addition to a string (path to file).
67
+
68
+ ### Removed
69
+
70
+ - **Breaking**: The module does not have a default export anymore, because of inconsistent functionality across module systems. Instead, use `AssemblyAI` as a named import like this: `import { AssemblyAI } from 'assemblyai'`.
71
+
72
+ ## [2.0.2] - 2023-10-13
73
+
74
+ ### Added
75
+
76
+ - `AssemblyAI.transcripts.wordSearch` searches for keywords in the transcript.
77
+ - `AssemblyAI.lemur.purgeRequestData` deletes data related to your LeMUR request.
78
+ - `RealtimeService.stream` creates a writable stream that you can write audio data to instead of using `RealtimeService.sendAudio``.
79
+
80
+ ### Fixed
81
+
82
+ - The AssemblyAI class would be exported as default named export instead in certain module systems.
83
+
84
+ ## [2.0.1] - 2023-10-10
85
+
86
+ Re-implement the Node SDK in TypeScript and add all AssemblyAI APIs.
87
+
88
+ ### Added
89
+
90
+ - Transcript API client
91
+ - LeMUR API client
92
+ - Real-time transcript client
@@ -146,32 +146,26 @@
146
146
  ByteLengthQueuingStrategy,
147
147
  CountQueuingStrategy,
148
148
  TextEncoderStream,
149
- TextDecoderStream,
150
- } = window;
151
-
152
- // Polyfill to make ReadableStream async-iterable with for-await
153
- // https://jakearchibald.com/2017/async-iterators-and-generators/#making-streams-iterate
154
- if (!ReadableStream.prototype[Symbol.asyncIterator]) {
155
- async function* streamAsyncIterator() {
156
- // Get a lock on the stream
157
- const reader = this.getReader();
158
-
159
- try {
160
- while (true) {
161
- // Read from the stream
162
- const { done, value } = await reader.read();
163
- // Exit if we're done
164
- if (done) return;
165
- // Else yield the chunk
166
- yield value;
149
+ TextDecoderStream
150
+ } = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : globalThis;
151
+ (function(ReadableStream2) {
152
+ if (!ReadableStream2.prototype[Symbol.asyncIterator]) {
153
+ async function* streamAsyncIterator() {
154
+ const reader = this.getReader();
155
+ try {
156
+ while (true) {
157
+ const { done, value } = await reader.read();
158
+ if (done)
159
+ return;
160
+ yield value;
161
+ }
162
+ } finally {
163
+ reader.releaseLock();
167
164
  }
168
- } finally {
169
- reader.releaseLock();
170
165
  }
166
+ ReadableStream2.prototype[Symbol.asyncIterator] = streamAsyncIterator;
171
167
  }
172
-
173
- ReadableStream.prototype[Symbol.asyncIterator] = streamAsyncIterator;
174
- }
168
+ })(ReadableStream);
175
169
 
176
170
  // https://github.com/maxogden/websocket-stream/blob/48dc3ddf943e5ada668c31ccd94e9186f02fafbd/ws-fallback.js
177
171
 
@@ -240,9 +234,9 @@
240
234
  this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
241
235
  this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
242
236
  this.wordBoost = params.wordBoost;
243
- if ("apiKey" in params)
237
+ if ("apiKey" in params && params.apiKey)
244
238
  this.apiKey = params.apiKey;
245
- if ("token" in params)
239
+ if ("token" in params && params.token)
246
240
  this.token = params.token;
247
241
  if (!(this.apiKey || this.token)) {
248
242
  throw new Error("API key or temporary token is required.");
@@ -628,7 +622,7 @@
628
622
  }
629
623
 
630
624
  function throwError() {
631
- throw new Error("Function is not supported in this environment.");
625
+ throw new Error("'fs' is not supported in this environment.");
632
626
  }
633
627
 
634
628
  const createReadStream = throwError;
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).assemblyai={})}(this,(function(e){"use strict";function t(e,t,o,s){return new(o||(o=Promise))((function(r,i){function n(e){try{l(s.next(e))}catch(e){i(e)}}function a(e){try{l(s.throw(e))}catch(e){i(e)}}function l(e){var t;e.done?r(e.value):(t=e.value,t instanceof o?t:new o((function(e){e(t)}))).then(n,a)}l((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class o{constructor(e){this.params=e}fetch(e,o){var s;return t(this,void 0,void 0,(function*(){(o=null!=o?o:{}).headers=null!==(s=o.headers)&&void 0!==s?s:{},o.headers=Object.assign({Authorization:this.params.apiKey,"Content-Type":"application/json"},o.headers),e.startsWith("http")||(e=this.params.baseUrl+e);const t=yield fetch(e,o);if(t.status>=400){let e;const o=yield t.text();if(o){try{e=JSON.parse(o)}catch(e){}if(null==e?void 0:e.error)throw new Error(e.error);throw new Error(o)}throw new Error(`HTTP Error: ${t.status} ${t.statusText}`)}return t}))}fetchJson(e,o){return t(this,void 0,void 0,(function*(){return(yield this.fetch(e,o)).json()}))}}class s extends o{summary(e){return this.fetchJson("/lemur/v3/generate/summary",{method:"POST",body:JSON.stringify(e)})}questionAnswer(e){return this.fetchJson("/lemur/v3/generate/question-answer",{method:"POST",body:JSON.stringify(e)})}actionItems(e){return this.fetchJson("/lemur/v3/generate/action-items",{method:"POST",body:JSON.stringify(e)})}task(e){return this.fetchJson("/lemur/v3/generate/task",{method:"POST",body:JSON.stringify(e)})}purgeRequestData(e){return this.fetchJson(`/lemur/v3/${e}`,{method:"DELETE"})}}const{ReadableStream:r,ReadableStreamDefaultReader:i,ReadableStreamBYOBReader:n,ReadableStreamBYOBRequest:a,ReadableByteStreamController:l,ReadableStreamDefaultController:c,TransformStream:d,TransformStreamDefaultController:u,WritableStream:h,WritableStreamDefaultWriter:f,WritableStreamDefaultController:p,ByteLengthQueuingStrategy:m,CountQueuingStrategy:y,TextEncoderStream:S,TextDecoderStream:v}=window;if(!r.prototype[Symbol.asyncIterator]){async function*P(){const e=this.getReader();try{for(;;){const{done:t,value:o}=await e.read();if(t)return;yield o}}finally{e.releaseLock()}}r.prototype[Symbol.asyncIterator]=P}var w=null;"undefined"!=typeof WebSocket?w=WebSocket:"undefined"!=typeof MozWebSocket?w=MozWebSocket:"undefined"!=typeof global?w=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window?w=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(w=self.WebSocket||self.MozWebSocket);var b,g=w;!function(e){e[e.BadSampleRate=4e3]="BadSampleRate",e[e.AuthFailed=4001]="AuthFailed",e[e.InsufficientFundsOrFreeAccount=4002]="InsufficientFundsOrFreeAccount",e[e.NonexistentSessionId=4004]="NonexistentSessionId",e[e.SessionExpired=4008]="SessionExpired",e[e.ClosedSession=4010]="ClosedSession",e[e.RateLimited=4029]="RateLimited",e[e.UniqueSessionViolation=4030]="UniqueSessionViolation",e[e.SessionTimeout=4031]="SessionTimeout",e[e.AudioTooShort=4032]="AudioTooShort",e[e.AudioTooLong=4033]="AudioTooLong",e[e.BadJson=4100]="BadJson",e[e.BadSchema=4101]="BadSchema",e[e.TooManyStreams=4102]="TooManyStreams",e[e.Reconnected=4103]="Reconnected",e[e.ReconnectAttemptsExhausted=1013]="ReconnectAttemptsExhausted"}(b||(b={}));const k={[b.BadSampleRate]:"Sample rate must be a positive integer",[b.AuthFailed]:"Not Authorized",[b.InsufficientFundsOrFreeAccount]:"Insufficient funds or you are using a free account. This feature is paid-only and requires you to add a credit card. Please visit https://assemblyai.com/dashboard/ to add a credit card to your account.",[b.NonexistentSessionId]:"Session ID does not exist",[b.SessionExpired]:"Session has expired",[b.ClosedSession]:"Session is closed",[b.RateLimited]:"Rate limited",[b.UniqueSessionViolation]:"Unique session violation",[b.SessionTimeout]:"Session Timeout",[b.AudioTooShort]:"Audio too short",[b.AudioTooLong]:"Audio too long",[b.BadJson]:"Bad JSON",[b.BadSchema]:"Bad schema",[b.TooManyStreams]:"Too many streams",[b.Reconnected]:"Reconnected",[b.ReconnectAttemptsExhausted]:"Reconnect attempts exhausted"};class T extends Error{}class R{constructor(e){var t,o;if(this.listeners={},this.realtimeUrl=null!==(t=e.realtimeUrl)&&void 0!==t?t:"wss://api.assemblyai.com/v2/realtime/ws",this.sampleRate=null!==(o=e.sampleRate)&&void 0!==o?o:16e3,this.wordBoost=e.wordBoost,"apiKey"in e&&(this.apiKey=e.apiKey),"token"in e&&(this.token=e.token),!this.apiKey&&!this.token)throw new Error("API key or temporary token is required.")}connectionUrl(){const e=new URL(this.realtimeUrl);if("wss:"!==e.protocol)throw new Error("Invalid protocol, must be wss");const t=new URLSearchParams;return this.token&&t.set("token",this.token),t.set("sample_rate",this.sampleRate.toString()),this.wordBoost&&this.wordBoost.length>0&&t.set("word_boost",JSON.stringify(this.wordBoost)),e.search=t.toString(),e}on(e,t){this.listeners[e]=t}connect(){return new Promise((e=>{if(this.socket)throw new Error("Already connected");const t=this.connectionUrl();this.token?this.socket=new g(t.toString()):this.socket=new g(t.toString(),{headers:{Authorization:this.apiKey}}),this.socket.onclose=({code:e,reason:t})=>{var o,s;t||e in b&&(t=k[e]),null===(s=(o=this.listeners).close)||void 0===s||s.call(o,e,t)},this.socket.onerror=e=>{var t,o,s,r;e.error?null===(o=(t=this.listeners).error)||void 0===o||o.call(t,e.error):null===(r=(s=this.listeners).error)||void 0===r||r.call(s,new Error(e.message))},this.socket.onmessage=({data:t})=>{var o,s,r,i,n,a,l,c,d,u,h,f,p;const m=JSON.parse(t.toString());if("error"in m)null===(s=(o=this.listeners).error)||void 0===s||s.call(o,new T(m.error));else switch(m.message_type){case"SessionBegins":{const t={sessionId:m.session_id,expiresAt:new Date(m.expires_at)};e(t),null===(i=(r=this.listeners).open)||void 0===i||i.call(r,t);break}case"PartialTranscript":m.created=new Date(m.created),null===(a=(n=this.listeners).transcript)||void 0===a||a.call(n,m),null===(c=(l=this.listeners)["transcript.partial"])||void 0===c||c.call(l,m);break;case"FinalTranscript":m.created=new Date(m.created),null===(u=(d=this.listeners).transcript)||void 0===u||u.call(d,m),null===(f=(h=this.listeners)["transcript.final"])||void 0===f||f.call(h,m);break;case"SessionTerminated":null===(p=this.sessionTerminatedResolve)||void 0===p||p.call(this)}}}))}sendAudio(e){if(!this.socket||this.socket.readyState!==g.OPEN)throw new Error("Socket is not open for communication");let t;t="undefined"!=typeof Buffer?Buffer.from(e).toString("base64"):btoa(new Uint8Array(e).reduce(((e,t)=>e+String.fromCharCode(t)),""));const o={audio_data:t};this.socket.send(JSON.stringify(o))}stream(){return new h({write:e=>{this.sendAudio(e)}})}close(e=!0){return t(this,void 0,void 0,(function*(){if(this.socket){if(this.socket.readyState===g.OPEN){const t='{"terminate_session": true}';if(e){const e=new Promise((e=>{this.sessionTerminatedResolve=e}));this.socket.send(t),yield e}else this.socket.send(t)}"removeAllListeners"in this.socket&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class O extends o{constructor(e){super(e),this.rtFactoryParams=e}createService(e){return e?"token"in e||e.apiKey||(e.apiKey=this.rtFactoryParams.apiKey):e={apiKey:this.rtFactoryParams.apiKey},new R(e)}createTemporaryToken(e){return t(this,void 0,void 0,(function*(){return(yield this.fetchJson("/v2/realtime/token",{method:"POST",body:JSON.stringify(e)})).token}))}}class x extends o{constructor(e,t){super(e),this.files=t}transcribe(e,o){return t(this,void 0,void 0,(function*(){const t=yield this.submit(e);return yield this.waitUntilReady(t.id,o)}))}submit(e){return t(this,void 0,void 0,(function*(){const{audio:t}=e,o=function(e,t){var o={};for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.indexOf(s)<0&&(o[s]=e[s]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(s=Object.getOwnPropertySymbols(e);r<s.length;r++)t.indexOf(s[r])<0&&Object.prototype.propertyIsEnumerable.call(e,s[r])&&(o[s[r]]=e[s[r]])}return o}(e,["audio"]);let s;if("string"==typeof t){const e=J(t);s=null!==e?yield this.files.upload(e):t}else s=yield this.files.upload(t);return yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(Object.assign(Object.assign({},o),{audio_url:s}))})}))}create(e,o){var s;return t(this,void 0,void 0,(function*(){const t=J(e.audio_url);if(null!==t){const o=yield this.files.upload(t);e.audio_url=o}const r=yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return null===(s=null==o?void 0:o.poll)||void 0===s||s?yield this.waitUntilReady(r.id,o):r}))}waitUntilReady(e,o){var s,r;return t(this,void 0,void 0,(function*(){const t=null!==(s=null==o?void 0:o.pollingInterval)&&void 0!==s?s:3e3,i=null!==(r=null==o?void 0:o.pollingTimeout)&&void 0!==r?r:-1,n=Date.now();for(;;){const o=yield this.get(e);if("completed"===o.status||"error"===o.status)return o;if(i>0&&Date.now()-n>i)throw new Error("Polling timeout");yield new Promise((e=>setTimeout(e,t)))}}))}get(e){return this.fetchJson(`/v2/transcript/${e}`)}list(e){return t(this,void 0,void 0,(function*(){let t="/v2/transcript";"string"==typeof e?t=e:e&&(t=`${t}?${new URLSearchParams(Object.keys(e).map((t=>{var o;return[t,(null===(o=e[t])||void 0===o?void 0:o.toString())||""]})))}`);const o=yield this.fetchJson(t);for(const e of o.transcripts)e.created=new Date(e.created),e.completed&&(e.completed=new Date(e.completed));return o}))}delete(e){return this.fetchJson(`/v2/transcript/${e}`,{method:"DELETE"})}wordSearch(e,t){const o=new URLSearchParams({words:t.join(",")});return this.fetchJson(`/v2/transcript/${e}/word-search?${o.toString()}`)}sentences(e){return this.fetchJson(`/v2/transcript/${e}/sentences`)}paragraphs(e){return this.fetchJson(`/v2/transcript/${e}/paragraphs`)}subtitles(e,o="srt",s){return t(this,void 0,void 0,(function*(){let t=`/v2/transcript/${e}/${o}`;if(s){const e=new URLSearchParams;e.set("chars_per_caption",s.toString()),t+=`?${e.toString()}`}const r=yield this.fetch(t);return yield r.text()}))}redactions(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}}function J(e){let t;try{return t=new URL(e),"file:"===t.protocol?t.pathname:null}catch(t){return e}}var A={createReadStream:function(){throw new Error("Function is not supported in this environment.")}};class E extends o{upload(e){return t(this,void 0,void 0,(function*(){let t;t="string"==typeof e?A.createReadStream(e):e;return(yield this.fetchJson("/v2/upload",{method:"POST",body:t,headers:{"Content-Type":"application/octet-stream"},duplex:"half"})).upload_url}))}}e.AssemblyAI=class{constructor(e){e.baseUrl=e.baseUrl||"https://api.assemblyai.com",e.baseUrl&&e.baseUrl.endsWith("/")&&(e.baseUrl=e.baseUrl.slice(0,-1)),this.files=new E(e),this.transcripts=new x(e,this.files),this.lemur=new s(e),this.realtime=new O(e)}},e.FileService=E,e.LemurService=s,e.RealtimeService=R,e.RealtimeServiceFactory=O,e.TranscriptService=x}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).assemblyai={})}(this,(function(e){"use strict";function t(e,t,o,s){return new(o||(o=Promise))((function(r,i){function n(e){try{l(s.next(e))}catch(e){i(e)}}function a(e){try{l(s.throw(e))}catch(e){i(e)}}function l(e){var t;e.done?r(e.value):(t=e.value,t instanceof o?t:new o((function(e){e(t)}))).then(n,a)}l((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class o{constructor(e){this.params=e}fetch(e,o){var s;return t(this,void 0,void 0,(function*(){(o=null!=o?o:{}).headers=null!==(s=o.headers)&&void 0!==s?s:{},o.headers=Object.assign({Authorization:this.params.apiKey,"Content-Type":"application/json"},o.headers),e.startsWith("http")||(e=this.params.baseUrl+e);const t=yield fetch(e,o);if(t.status>=400){let e;const o=yield t.text();if(o){try{e=JSON.parse(o)}catch(e){}if(null==e?void 0:e.error)throw new Error(e.error);throw new Error(o)}throw new Error(`HTTP Error: ${t.status} ${t.statusText}`)}return t}))}fetchJson(e,o){return t(this,void 0,void 0,(function*(){return(yield this.fetch(e,o)).json()}))}}class s extends o{summary(e){return this.fetchJson("/lemur/v3/generate/summary",{method:"POST",body:JSON.stringify(e)})}questionAnswer(e){return this.fetchJson("/lemur/v3/generate/question-answer",{method:"POST",body:JSON.stringify(e)})}actionItems(e){return this.fetchJson("/lemur/v3/generate/action-items",{method:"POST",body:JSON.stringify(e)})}task(e){return this.fetchJson("/lemur/v3/generate/task",{method:"POST",body:JSON.stringify(e)})}purgeRequestData(e){return this.fetchJson(`/lemur/v3/${e}`,{method:"DELETE"})}}const{ReadableStream:r,ReadableStreamDefaultReader:i,ReadableStreamBYOBReader:n,ReadableStreamBYOBRequest:a,ReadableByteStreamController:l,ReadableStreamDefaultController:c,TransformStream:d,TransformStreamDefaultController:u,WritableStream:h,WritableStreamDefaultWriter:f,WritableStreamDefaultController:p,ByteLengthQueuingStrategy:m,CountQueuingStrategy:y,TextEncoderStream:S,TextDecoderStream:v}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;!function(e){if(!e.prototype[Symbol.asyncIterator]){async function*t(){const e=this.getReader();try{for(;;){const{done:t,value:o}=await e.read();if(t)return;yield o}}finally{e.releaseLock()}}e.prototype[Symbol.asyncIterator]=t}}(r);var w=null;"undefined"!=typeof WebSocket?w=WebSocket:"undefined"!=typeof MozWebSocket?w=MozWebSocket:"undefined"!=typeof global?w=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window?w=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(w=self.WebSocket||self.MozWebSocket);var b,g=w;!function(e){e[e.BadSampleRate=4e3]="BadSampleRate",e[e.AuthFailed=4001]="AuthFailed",e[e.InsufficientFundsOrFreeAccount=4002]="InsufficientFundsOrFreeAccount",e[e.NonexistentSessionId=4004]="NonexistentSessionId",e[e.SessionExpired=4008]="SessionExpired",e[e.ClosedSession=4010]="ClosedSession",e[e.RateLimited=4029]="RateLimited",e[e.UniqueSessionViolation=4030]="UniqueSessionViolation",e[e.SessionTimeout=4031]="SessionTimeout",e[e.AudioTooShort=4032]="AudioTooShort",e[e.AudioTooLong=4033]="AudioTooLong",e[e.BadJson=4100]="BadJson",e[e.BadSchema=4101]="BadSchema",e[e.TooManyStreams=4102]="TooManyStreams",e[e.Reconnected=4103]="Reconnected",e[e.ReconnectAttemptsExhausted=1013]="ReconnectAttemptsExhausted"}(b||(b={}));const k={[b.BadSampleRate]:"Sample rate must be a positive integer",[b.AuthFailed]:"Not Authorized",[b.InsufficientFundsOrFreeAccount]:"Insufficient funds or you are using a free account. This feature is paid-only and requires you to add a credit card. Please visit https://assemblyai.com/dashboard/ to add a credit card to your account.",[b.NonexistentSessionId]:"Session ID does not exist",[b.SessionExpired]:"Session has expired",[b.ClosedSession]:"Session is closed",[b.RateLimited]:"Rate limited",[b.UniqueSessionViolation]:"Unique session violation",[b.SessionTimeout]:"Session Timeout",[b.AudioTooShort]:"Audio too short",[b.AudioTooLong]:"Audio too long",[b.BadJson]:"Bad JSON",[b.BadSchema]:"Bad schema",[b.TooManyStreams]:"Too many streams",[b.Reconnected]:"Reconnected",[b.ReconnectAttemptsExhausted]:"Reconnect attempts exhausted"};class T extends Error{}class R{constructor(e){var t,o;if(this.listeners={},this.realtimeUrl=null!==(t=e.realtimeUrl)&&void 0!==t?t:"wss://api.assemblyai.com/v2/realtime/ws",this.sampleRate=null!==(o=e.sampleRate)&&void 0!==o?o:16e3,this.wordBoost=e.wordBoost,"apiKey"in e&&e.apiKey&&(this.apiKey=e.apiKey),"token"in e&&e.token&&(this.token=e.token),!this.apiKey&&!this.token)throw new Error("API key or temporary token is required.")}connectionUrl(){const e=new URL(this.realtimeUrl);if("wss:"!==e.protocol)throw new Error("Invalid protocol, must be wss");const t=new URLSearchParams;return this.token&&t.set("token",this.token),t.set("sample_rate",this.sampleRate.toString()),this.wordBoost&&this.wordBoost.length>0&&t.set("word_boost",JSON.stringify(this.wordBoost)),e.search=t.toString(),e}on(e,t){this.listeners[e]=t}connect(){return new Promise((e=>{if(this.socket)throw new Error("Already connected");const t=this.connectionUrl();this.token?this.socket=new g(t.toString()):this.socket=new g(t.toString(),{headers:{Authorization:this.apiKey}}),this.socket.onclose=({code:e,reason:t})=>{var o,s;t||e in b&&(t=k[e]),null===(s=(o=this.listeners).close)||void 0===s||s.call(o,e,t)},this.socket.onerror=e=>{var t,o,s,r;e.error?null===(o=(t=this.listeners).error)||void 0===o||o.call(t,e.error):null===(r=(s=this.listeners).error)||void 0===r||r.call(s,new Error(e.message))},this.socket.onmessage=({data:t})=>{var o,s,r,i,n,a,l,c,d,u,h,f,p;const m=JSON.parse(t.toString());if("error"in m)null===(s=(o=this.listeners).error)||void 0===s||s.call(o,new T(m.error));else switch(m.message_type){case"SessionBegins":{const t={sessionId:m.session_id,expiresAt:new Date(m.expires_at)};e(t),null===(i=(r=this.listeners).open)||void 0===i||i.call(r,t);break}case"PartialTranscript":m.created=new Date(m.created),null===(a=(n=this.listeners).transcript)||void 0===a||a.call(n,m),null===(c=(l=this.listeners)["transcript.partial"])||void 0===c||c.call(l,m);break;case"FinalTranscript":m.created=new Date(m.created),null===(u=(d=this.listeners).transcript)||void 0===u||u.call(d,m),null===(f=(h=this.listeners)["transcript.final"])||void 0===f||f.call(h,m);break;case"SessionTerminated":null===(p=this.sessionTerminatedResolve)||void 0===p||p.call(this)}}}))}sendAudio(e){if(!this.socket||this.socket.readyState!==g.OPEN)throw new Error("Socket is not open for communication");let t;t="undefined"!=typeof Buffer?Buffer.from(e).toString("base64"):btoa(new Uint8Array(e).reduce(((e,t)=>e+String.fromCharCode(t)),""));const o={audio_data:t};this.socket.send(JSON.stringify(o))}stream(){return new h({write:e=>{this.sendAudio(e)}})}close(e=!0){return t(this,void 0,void 0,(function*(){if(this.socket){if(this.socket.readyState===g.OPEN){const t='{"terminate_session": true}';if(e){const e=new Promise((e=>{this.sessionTerminatedResolve=e}));this.socket.send(t),yield e}else this.socket.send(t)}"removeAllListeners"in this.socket&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class O extends o{constructor(e){super(e),this.rtFactoryParams=e}createService(e){return e?"token"in e||e.apiKey||(e.apiKey=this.rtFactoryParams.apiKey):e={apiKey:this.rtFactoryParams.apiKey},new R(e)}createTemporaryToken(e){return t(this,void 0,void 0,(function*(){return(yield this.fetchJson("/v2/realtime/token",{method:"POST",body:JSON.stringify(e)})).token}))}}class x extends o{constructor(e,t){super(e),this.files=t}transcribe(e,o){return t(this,void 0,void 0,(function*(){const t=yield this.submit(e);return yield this.waitUntilReady(t.id,o)}))}submit(e){return t(this,void 0,void 0,(function*(){const{audio:t}=e,o=function(e,t){var o={};for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.indexOf(s)<0&&(o[s]=e[s]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(s=Object.getOwnPropertySymbols(e);r<s.length;r++)t.indexOf(s[r])<0&&Object.prototype.propertyIsEnumerable.call(e,s[r])&&(o[s[r]]=e[s[r]])}return o}(e,["audio"]);let s;if("string"==typeof t){const e=J(t);s=null!==e?yield this.files.upload(e):t}else s=yield this.files.upload(t);return yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(Object.assign(Object.assign({},o),{audio_url:s}))})}))}create(e,o){var s;return t(this,void 0,void 0,(function*(){const t=J(e.audio_url);if(null!==t){const o=yield this.files.upload(t);e.audio_url=o}const r=yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return null===(s=null==o?void 0:o.poll)||void 0===s||s?yield this.waitUntilReady(r.id,o):r}))}waitUntilReady(e,o){var s,r;return t(this,void 0,void 0,(function*(){const t=null!==(s=null==o?void 0:o.pollingInterval)&&void 0!==s?s:3e3,i=null!==(r=null==o?void 0:o.pollingTimeout)&&void 0!==r?r:-1,n=Date.now();for(;;){const o=yield this.get(e);if("completed"===o.status||"error"===o.status)return o;if(i>0&&Date.now()-n>i)throw new Error("Polling timeout");yield new Promise((e=>setTimeout(e,t)))}}))}get(e){return this.fetchJson(`/v2/transcript/${e}`)}list(e){return t(this,void 0,void 0,(function*(){let t="/v2/transcript";"string"==typeof e?t=e:e&&(t=`${t}?${new URLSearchParams(Object.keys(e).map((t=>{var o;return[t,(null===(o=e[t])||void 0===o?void 0:o.toString())||""]})))}`);const o=yield this.fetchJson(t);for(const e of o.transcripts)e.created=new Date(e.created),e.completed&&(e.completed=new Date(e.completed));return o}))}delete(e){return this.fetchJson(`/v2/transcript/${e}`,{method:"DELETE"})}wordSearch(e,t){const o=new URLSearchParams({words:t.join(",")});return this.fetchJson(`/v2/transcript/${e}/word-search?${o.toString()}`)}sentences(e){return this.fetchJson(`/v2/transcript/${e}/sentences`)}paragraphs(e){return this.fetchJson(`/v2/transcript/${e}/paragraphs`)}subtitles(e,o="srt",s){return t(this,void 0,void 0,(function*(){let t=`/v2/transcript/${e}/${o}`;if(s){const e=new URLSearchParams;e.set("chars_per_caption",s.toString()),t+=`?${e.toString()}`}const r=yield this.fetch(t);return yield r.text()}))}redactions(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}}function J(e){let t;try{return t=new URL(e),"file:"===t.protocol?t.pathname:null}catch(t){return e}}var A={createReadStream:function(){throw new Error("'fs' is not supported in this environment.")}};class E extends o{upload(e){return t(this,void 0,void 0,(function*(){let t;t="string"==typeof e?A.createReadStream(e):e;return(yield this.fetchJson("/v2/upload",{method:"POST",body:t,headers:{"Content-Type":"application/octet-stream"},duplex:"half"})).upload_url}))}}e.AssemblyAI=class{constructor(e){e.baseUrl=e.baseUrl||"https://api.assemblyai.com",e.baseUrl&&e.baseUrl.endsWith("/")&&(e.baseUrl=e.baseUrl.slice(0,-1)),this.files=new E(e),this.transcripts=new x(e,this.files),this.lemur=new s(e),this.realtime=new O(e)}},e.FileService=E,e.LemurService=s,e.RealtimeService=R,e.RealtimeServiceFactory=O,e.TranscriptService=x}));
package/dist/index.cjs CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  var isomorphicStreams = require('@swimburger/isomorphic-streams');
4
4
  var WebSocket = require('isomorphic-ws');
5
- var fs = require('fs');
6
5
 
7
6
  /******************************************************************************
8
7
  Copyright (c) Microsoft Corporation.
@@ -180,9 +179,9 @@ class RealtimeService {
180
179
  this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
181
180
  this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
182
181
  this.wordBoost = params.wordBoost;
183
- if ("apiKey" in params)
182
+ if ("apiKey" in params && params.apiKey)
184
183
  this.apiKey = params.apiKey;
185
- if ("token" in params)
184
+ if ("token" in params && params.token)
186
185
  this.token = params.token;
187
186
  if (!(this.apiKey || this.token)) {
188
187
  throw new Error("API key or temporary token is required.");
@@ -567,6 +566,15 @@ function getPath(path) {
567
566
  }
568
567
  }
569
568
 
569
+ function throwError() {
570
+ throw new Error("'fs' is not supported in this environment.");
571
+ }
572
+
573
+ const createReadStream = throwError;
574
+ var fs = {
575
+ createReadStream,
576
+ };
577
+
570
578
  class FileService extends BaseService {
571
579
  /**
572
580
  * Upload a local file to AssemblyAI.
package/dist/index.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import { WritableStream } from '@swimburger/isomorphic-streams';
2
2
  import WebSocket from 'isomorphic-ws';
3
- import fs from 'fs';
4
3
 
5
4
  /******************************************************************************
6
5
  Copyright (c) Microsoft Corporation.
@@ -178,9 +177,9 @@ class RealtimeService {
178
177
  this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
179
178
  this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
180
179
  this.wordBoost = params.wordBoost;
181
- if ("apiKey" in params)
180
+ if ("apiKey" in params && params.apiKey)
182
181
  this.apiKey = params.apiKey;
183
- if ("token" in params)
182
+ if ("token" in params && params.token)
184
183
  this.token = params.token;
185
184
  if (!(this.apiKey || this.token)) {
186
185
  throw new Error("API key or temporary token is required.");
@@ -565,6 +564,15 @@ function getPath(path) {
565
564
  }
566
565
  }
567
566
 
567
+ function throwError() {
568
+ throw new Error("'fs' is not supported in this environment.");
569
+ }
570
+
571
+ const createReadStream = throwError;
572
+ var fs = {
573
+ createReadStream,
574
+ };
575
+
568
576
  class FileService extends BaseService {
569
577
  /**
570
578
  * Upload a local file to AssemblyAI.
@@ -0,0 +1,618 @@
1
+ 'use strict';
2
+
3
+ var isomorphicStreams = require('@swimburger/isomorphic-streams');
4
+ var WebSocket = require('isomorphic-ws');
5
+ var fs = require('fs');
6
+
7
+ /******************************************************************************
8
+ Copyright (c) Microsoft Corporation.
9
+
10
+ Permission to use, copy, modify, and/or distribute this software for any
11
+ purpose with or without fee is hereby granted.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
+ PERFORMANCE OF THIS SOFTWARE.
20
+ ***************************************************************************** */
21
+ /* global Reflect, Promise, SuppressedError, Symbol */
22
+
23
+
24
+ function __rest(s, e) {
25
+ var t = {};
26
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
27
+ t[p] = s[p];
28
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
29
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
30
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
31
+ t[p[i]] = s[p[i]];
32
+ }
33
+ return t;
34
+ }
35
+
36
+ function __awaiter(thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ }
45
+
46
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
47
+ var e = new Error(message);
48
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
49
+ };
50
+
51
+ /**
52
+ * Base class for services that communicate with the API.
53
+ */
54
+ class BaseService {
55
+ /**
56
+ * Create a new service.
57
+ * @param params The parameters to use for the service.
58
+ */
59
+ constructor(params) {
60
+ this.params = params;
61
+ }
62
+ fetch(input, init) {
63
+ var _a;
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ init = init !== null && init !== void 0 ? init : {};
66
+ init.headers = (_a = init.headers) !== null && _a !== void 0 ? _a : {};
67
+ init.headers = Object.assign({ Authorization: this.params.apiKey, "Content-Type": "application/json" }, init.headers);
68
+ if (!input.startsWith("http"))
69
+ input = this.params.baseUrl + input;
70
+ const response = yield fetch(input, init);
71
+ if (response.status >= 400) {
72
+ let json;
73
+ const text = yield response.text();
74
+ if (text) {
75
+ try {
76
+ json = JSON.parse(text);
77
+ }
78
+ catch (_b) {
79
+ /* empty */
80
+ }
81
+ if (json === null || json === void 0 ? void 0 : json.error)
82
+ throw new Error(json.error);
83
+ throw new Error(text);
84
+ }
85
+ throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
86
+ }
87
+ return response;
88
+ });
89
+ }
90
+ fetchJson(input, init) {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ const response = yield this.fetch(input, init);
93
+ return response.json();
94
+ });
95
+ }
96
+ }
97
+
98
+ class LemurService extends BaseService {
99
+ summary(params) {
100
+ return this.fetchJson("/lemur/v3/generate/summary", {
101
+ method: "POST",
102
+ body: JSON.stringify(params),
103
+ });
104
+ }
105
+ questionAnswer(params) {
106
+ return this.fetchJson("/lemur/v3/generate/question-answer", {
107
+ method: "POST",
108
+ body: JSON.stringify(params),
109
+ });
110
+ }
111
+ actionItems(params) {
112
+ return this.fetchJson("/lemur/v3/generate/action-items", {
113
+ method: "POST",
114
+ body: JSON.stringify(params),
115
+ });
116
+ }
117
+ task(params) {
118
+ return this.fetchJson("/lemur/v3/generate/task", {
119
+ method: "POST",
120
+ body: JSON.stringify(params),
121
+ });
122
+ }
123
+ /**
124
+ * Delete the data for a previously submitted LeMUR request.
125
+ * @param id ID of the LeMUR request
126
+ */
127
+ purgeRequestData(id) {
128
+ return this.fetchJson(`/lemur/v3/${id}`, {
129
+ method: "DELETE",
130
+ });
131
+ }
132
+ }
133
+
134
+ var RealtimeErrorType;
135
+ (function (RealtimeErrorType) {
136
+ RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
137
+ RealtimeErrorType[RealtimeErrorType["AuthFailed"] = 4001] = "AuthFailed";
138
+ // Both InsufficientFunds and FreeAccount error use 4002
139
+ RealtimeErrorType[RealtimeErrorType["InsufficientFundsOrFreeAccount"] = 4002] = "InsufficientFundsOrFreeAccount";
140
+ RealtimeErrorType[RealtimeErrorType["NonexistentSessionId"] = 4004] = "NonexistentSessionId";
141
+ RealtimeErrorType[RealtimeErrorType["SessionExpired"] = 4008] = "SessionExpired";
142
+ RealtimeErrorType[RealtimeErrorType["ClosedSession"] = 4010] = "ClosedSession";
143
+ RealtimeErrorType[RealtimeErrorType["RateLimited"] = 4029] = "RateLimited";
144
+ RealtimeErrorType[RealtimeErrorType["UniqueSessionViolation"] = 4030] = "UniqueSessionViolation";
145
+ RealtimeErrorType[RealtimeErrorType["SessionTimeout"] = 4031] = "SessionTimeout";
146
+ RealtimeErrorType[RealtimeErrorType["AudioTooShort"] = 4032] = "AudioTooShort";
147
+ RealtimeErrorType[RealtimeErrorType["AudioTooLong"] = 4033] = "AudioTooLong";
148
+ RealtimeErrorType[RealtimeErrorType["BadJson"] = 4100] = "BadJson";
149
+ RealtimeErrorType[RealtimeErrorType["BadSchema"] = 4101] = "BadSchema";
150
+ RealtimeErrorType[RealtimeErrorType["TooManyStreams"] = 4102] = "TooManyStreams";
151
+ RealtimeErrorType[RealtimeErrorType["Reconnected"] = 4103] = "Reconnected";
152
+ RealtimeErrorType[RealtimeErrorType["ReconnectAttemptsExhausted"] = 1013] = "ReconnectAttemptsExhausted";
153
+ })(RealtimeErrorType || (RealtimeErrorType = {}));
154
+ const RealtimeErrorMessages = {
155
+ [RealtimeErrorType.BadSampleRate]: "Sample rate must be a positive integer",
156
+ [RealtimeErrorType.AuthFailed]: "Not Authorized",
157
+ [RealtimeErrorType.InsufficientFundsOrFreeAccount]: "Insufficient funds or you are using a free account. This feature is paid-only and requires you to add a credit card. Please visit https://assemblyai.com/dashboard/ to add a credit card to your account.",
158
+ [RealtimeErrorType.NonexistentSessionId]: "Session ID does not exist",
159
+ [RealtimeErrorType.SessionExpired]: "Session has expired",
160
+ [RealtimeErrorType.ClosedSession]: "Session is closed",
161
+ [RealtimeErrorType.RateLimited]: "Rate limited",
162
+ [RealtimeErrorType.UniqueSessionViolation]: "Unique session violation",
163
+ [RealtimeErrorType.SessionTimeout]: "Session Timeout",
164
+ [RealtimeErrorType.AudioTooShort]: "Audio too short",
165
+ [RealtimeErrorType.AudioTooLong]: "Audio too long",
166
+ [RealtimeErrorType.BadJson]: "Bad JSON",
167
+ [RealtimeErrorType.BadSchema]: "Bad schema",
168
+ [RealtimeErrorType.TooManyStreams]: "Too many streams",
169
+ [RealtimeErrorType.Reconnected]: "Reconnected",
170
+ [RealtimeErrorType.ReconnectAttemptsExhausted]: "Reconnect attempts exhausted",
171
+ };
172
+ class RealtimeError extends Error {
173
+ }
174
+
175
+ const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
176
+ class RealtimeService {
177
+ constructor(params) {
178
+ var _a, _b;
179
+ this.listeners = {};
180
+ this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
181
+ this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
182
+ this.wordBoost = params.wordBoost;
183
+ if ("apiKey" in params && params.apiKey)
184
+ this.apiKey = params.apiKey;
185
+ if ("token" in params && params.token)
186
+ this.token = params.token;
187
+ if (!(this.apiKey || this.token)) {
188
+ throw new Error("API key or temporary token is required.");
189
+ }
190
+ }
191
+ connectionUrl() {
192
+ const url = new URL(this.realtimeUrl);
193
+ if (url.protocol !== "wss:") {
194
+ throw new Error("Invalid protocol, must be wss");
195
+ }
196
+ const searchParams = new URLSearchParams();
197
+ if (this.token) {
198
+ searchParams.set("token", this.token);
199
+ }
200
+ searchParams.set("sample_rate", this.sampleRate.toString());
201
+ if (this.wordBoost && this.wordBoost.length > 0) {
202
+ searchParams.set("word_boost", JSON.stringify(this.wordBoost));
203
+ }
204
+ url.search = searchParams.toString();
205
+ return url;
206
+ }
207
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
208
+ on(event, listener) {
209
+ this.listeners[event] = listener;
210
+ }
211
+ connect() {
212
+ return new Promise((resolve) => {
213
+ if (this.socket) {
214
+ throw new Error("Already connected");
215
+ }
216
+ const url = this.connectionUrl();
217
+ if (this.token) {
218
+ this.socket = new WebSocket(url.toString());
219
+ }
220
+ else {
221
+ this.socket = new WebSocket(url.toString(), {
222
+ headers: { Authorization: this.apiKey },
223
+ });
224
+ }
225
+ this.socket.onclose = ({ code, reason }) => {
226
+ var _a, _b;
227
+ if (!reason) {
228
+ if (code in RealtimeErrorType) {
229
+ reason = RealtimeErrorMessages[code];
230
+ }
231
+ }
232
+ (_b = (_a = this.listeners).close) === null || _b === void 0 ? void 0 : _b.call(_a, code, reason);
233
+ };
234
+ this.socket.onerror = (event) => {
235
+ var _a, _b, _c, _d;
236
+ if (event.error)
237
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, event.error);
238
+ else
239
+ (_d = (_c = this.listeners).error) === null || _d === void 0 ? void 0 : _d.call(_c, new Error(event.message));
240
+ };
241
+ this.socket.onmessage = ({ data }) => {
242
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
243
+ const message = JSON.parse(data.toString());
244
+ if ("error" in message) {
245
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, new RealtimeError(message.error));
246
+ return;
247
+ }
248
+ switch (message.message_type) {
249
+ case "SessionBegins": {
250
+ const openObject = {
251
+ sessionId: message.session_id,
252
+ expiresAt: new Date(message.expires_at),
253
+ };
254
+ resolve(openObject);
255
+ (_d = (_c = this.listeners).open) === null || _d === void 0 ? void 0 : _d.call(_c, openObject);
256
+ break;
257
+ }
258
+ case "PartialTranscript": {
259
+ // message.created is actually a string when coming from the socket
260
+ message.created = new Date(message.created);
261
+ (_f = (_e = this.listeners).transcript) === null || _f === void 0 ? void 0 : _f.call(_e, message);
262
+ (_h = (_g = this.listeners)["transcript.partial"]) === null || _h === void 0 ? void 0 : _h.call(_g, message);
263
+ break;
264
+ }
265
+ case "FinalTranscript": {
266
+ // message.created is actually a string when coming from the socket
267
+ message.created = new Date(message.created);
268
+ (_k = (_j = this.listeners).transcript) === null || _k === void 0 ? void 0 : _k.call(_j, message);
269
+ (_m = (_l = this.listeners)["transcript.final"]) === null || _m === void 0 ? void 0 : _m.call(_l, message);
270
+ break;
271
+ }
272
+ case "SessionTerminated": {
273
+ (_o = this.sessionTerminatedResolve) === null || _o === void 0 ? void 0 : _o.call(this);
274
+ break;
275
+ }
276
+ }
277
+ };
278
+ });
279
+ }
280
+ sendAudio(audio) {
281
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
282
+ throw new Error("Socket is not open for communication");
283
+ }
284
+ let audioData;
285
+ if (typeof Buffer !== "undefined") {
286
+ audioData = Buffer.from(audio).toString("base64");
287
+ }
288
+ else {
289
+ // Buffer is not available in the browser by default
290
+ // https://stackoverflow.com/a/42334410/2919731
291
+ audioData = btoa(new Uint8Array(audio).reduce((data, byte) => data + String.fromCharCode(byte), ""));
292
+ }
293
+ const payload = {
294
+ audio_data: audioData,
295
+ };
296
+ this.socket.send(JSON.stringify(payload));
297
+ }
298
+ stream() {
299
+ return new isomorphicStreams.WritableStream({
300
+ write: (chunk) => {
301
+ this.sendAudio(chunk);
302
+ },
303
+ });
304
+ }
305
+ close(waitForSessionTermination = true) {
306
+ return __awaiter(this, void 0, void 0, function* () {
307
+ if (this.socket) {
308
+ if (this.socket.readyState === WebSocket.OPEN) {
309
+ const terminateSessionMessage = `{"terminate_session": true}`;
310
+ if (waitForSessionTermination) {
311
+ const sessionTerminatedPromise = new Promise((resolve) => {
312
+ this.sessionTerminatedResolve = resolve;
313
+ });
314
+ this.socket.send(terminateSessionMessage);
315
+ yield sessionTerminatedPromise;
316
+ }
317
+ else {
318
+ this.socket.send(terminateSessionMessage);
319
+ }
320
+ }
321
+ if ("removeAllListeners" in this.socket)
322
+ this.socket.removeAllListeners();
323
+ this.socket.close();
324
+ }
325
+ this.listeners = {};
326
+ this.socket = undefined;
327
+ });
328
+ }
329
+ }
330
+
331
+ class RealtimeServiceFactory extends BaseService {
332
+ constructor(params) {
333
+ super(params);
334
+ this.rtFactoryParams = params;
335
+ }
336
+ createService(params) {
337
+ if (!params)
338
+ params = { apiKey: this.rtFactoryParams.apiKey };
339
+ else if (!("token" in params) && !params.apiKey) {
340
+ params.apiKey = this.rtFactoryParams.apiKey;
341
+ }
342
+ return new RealtimeService(params);
343
+ }
344
+ createTemporaryToken(params) {
345
+ return __awaiter(this, void 0, void 0, function* () {
346
+ const data = yield this.fetchJson("/v2/realtime/token", {
347
+ method: "POST",
348
+ body: JSON.stringify(params),
349
+ });
350
+ return data.token;
351
+ });
352
+ }
353
+ }
354
+
355
+ class TranscriptService extends BaseService {
356
+ constructor(params, files) {
357
+ super(params);
358
+ this.files = files;
359
+ }
360
+ /**
361
+ * Transcribe an audio file. This will create a transcript and wait until the transcript status is "completed" or "error".
362
+ * @param params The parameters to transcribe an audio file.
363
+ * @param options The options to transcribe an audio file.
364
+ * @returns A promise that resolves to the transcript. The transcript status is "completed" or "error".
365
+ */
366
+ transcribe(params, options) {
367
+ return __awaiter(this, void 0, void 0, function* () {
368
+ const transcript = yield this.submit(params);
369
+ return yield this.waitUntilReady(transcript.id, options);
370
+ });
371
+ }
372
+ /**
373
+ * Submits a transcription job for an audio file. This will not wait until the transcript status is "completed" or "error".
374
+ * @param params The parameters to start the transcription of an audio file.
375
+ * @returns A promise that resolves to the queued transcript.
376
+ */
377
+ submit(params) {
378
+ return __awaiter(this, void 0, void 0, function* () {
379
+ const { audio } = params, createParams = __rest(params, ["audio"]);
380
+ let audioUrl;
381
+ if (typeof audio === "string") {
382
+ const path = getPath(audio);
383
+ if (path !== null) {
384
+ // audio is local path, upload local file
385
+ audioUrl = yield this.files.upload(path);
386
+ }
387
+ else {
388
+ // audio is not a local path, assume it's a URL
389
+ audioUrl = audio;
390
+ }
391
+ }
392
+ else {
393
+ // audio is of uploadable type
394
+ audioUrl = yield this.files.upload(audio);
395
+ }
396
+ const data = yield this.fetchJson("/v2/transcript", {
397
+ method: "POST",
398
+ body: JSON.stringify(Object.assign(Object.assign({}, createParams), { audio_url: audioUrl })),
399
+ });
400
+ return data;
401
+ });
402
+ }
403
+ /**
404
+ * Create a transcript.
405
+ * @param params The parameters to create a transcript.
406
+ * @param options The options used for creating the new transcript.
407
+ * @returns A promise that resolves to the transcript.
408
+ * @deprecated Use `transcribe` instead to transcribe a audio file that includes polling, or `submit` to transcribe a audio file without polling.
409
+ */
410
+ create(params, options) {
411
+ var _a;
412
+ return __awaiter(this, void 0, void 0, function* () {
413
+ const path = getPath(params.audio_url);
414
+ if (path !== null) {
415
+ const uploadUrl = yield this.files.upload(path);
416
+ params.audio_url = uploadUrl;
417
+ }
418
+ const data = yield this.fetchJson("/v2/transcript", {
419
+ method: "POST",
420
+ body: JSON.stringify(params),
421
+ });
422
+ if ((_a = options === null || options === void 0 ? void 0 : options.poll) !== null && _a !== void 0 ? _a : true) {
423
+ return yield this.waitUntilReady(data.id, options);
424
+ }
425
+ return data;
426
+ });
427
+ }
428
+ /**
429
+ * Wait until the transcript ready, either the status is "completed" or "error".
430
+ * @param transcriptId The ID of the transcript.
431
+ * @param options The options to wait until the transcript is ready.
432
+ * @returns A promise that resolves to the transcript. The transcript status is "completed" or "error".
433
+ */
434
+ waitUntilReady(transcriptId, options) {
435
+ var _a, _b;
436
+ return __awaiter(this, void 0, void 0, function* () {
437
+ const pollingInterval = (_a = options === null || options === void 0 ? void 0 : options.pollingInterval) !== null && _a !== void 0 ? _a : 3000;
438
+ const pollingTimeout = (_b = options === null || options === void 0 ? void 0 : options.pollingTimeout) !== null && _b !== void 0 ? _b : -1;
439
+ const startTime = Date.now();
440
+ // eslint-disable-next-line no-constant-condition
441
+ while (true) {
442
+ const transcript = yield this.get(transcriptId);
443
+ if (transcript.status === "completed" || transcript.status === "error") {
444
+ return transcript;
445
+ }
446
+ else if (pollingTimeout > 0 &&
447
+ Date.now() - startTime > pollingTimeout) {
448
+ throw new Error("Polling timeout");
449
+ }
450
+ else {
451
+ yield new Promise((resolve) => setTimeout(resolve, pollingInterval));
452
+ }
453
+ }
454
+ });
455
+ }
456
+ /**
457
+ * Retrieve a transcript.
458
+ * @param id The identifier of the transcript.
459
+ * @returns A promise that resolves to the transcript.
460
+ */
461
+ get(id) {
462
+ return this.fetchJson(`/v2/transcript/${id}`);
463
+ }
464
+ /**
465
+ * Retrieves a page of transcript listings.
466
+ * @param parameters The parameters to filter the transcript list by, or the URL to retrieve the transcript list from.
467
+ */
468
+ list(parameters) {
469
+ return __awaiter(this, void 0, void 0, function* () {
470
+ let url = "/v2/transcript";
471
+ if (typeof parameters === "string") {
472
+ url = parameters;
473
+ }
474
+ else if (parameters) {
475
+ url = `${url}?${new URLSearchParams(Object.keys(parameters).map((key) => {
476
+ var _a;
477
+ return [
478
+ key,
479
+ ((_a = parameters[key]) === null || _a === void 0 ? void 0 : _a.toString()) || "",
480
+ ];
481
+ }))}`;
482
+ }
483
+ const data = yield this.fetchJson(url);
484
+ for (const transcriptListItem of data.transcripts) {
485
+ transcriptListItem.created = new Date(transcriptListItem.created);
486
+ if (transcriptListItem.completed) {
487
+ transcriptListItem.completed = new Date(transcriptListItem.completed);
488
+ }
489
+ }
490
+ return data;
491
+ });
492
+ }
493
+ /**
494
+ * Delete a transcript
495
+ * @param id The identifier of the transcript.
496
+ * @returns A promise that resolves to the transcript.
497
+ */
498
+ delete(id) {
499
+ return this.fetchJson(`/v2/transcript/${id}`, { method: "DELETE" });
500
+ }
501
+ /**
502
+ * Search through the transcript for a specific set of keywords.
503
+ * You can search for individual words, numbers, or phrases containing up to five words or numbers.
504
+ * @param id The identifier of the transcript.
505
+ * @param words Keywords to search for.
506
+ * @return A promise that resolves to the sentences.
507
+ */
508
+ wordSearch(id, words) {
509
+ const params = new URLSearchParams({ words: words.join(",") });
510
+ return this.fetchJson(`/v2/transcript/${id}/word-search?${params.toString()}`);
511
+ }
512
+ /**
513
+ * Retrieve all sentences of a transcript.
514
+ * @param id The identifier of the transcript.
515
+ * @return A promise that resolves to the sentences.
516
+ */
517
+ sentences(id) {
518
+ return this.fetchJson(`/v2/transcript/${id}/sentences`);
519
+ }
520
+ /**
521
+ * Retrieve all paragraphs of a transcript.
522
+ * @param id The identifier of the transcript.
523
+ * @return A promise that resolves to the paragraphs.
524
+ */
525
+ paragraphs(id) {
526
+ return this.fetchJson(`/v2/transcript/${id}/paragraphs`);
527
+ }
528
+ /**
529
+ * Retrieve subtitles of a transcript.
530
+ * @param id The identifier of the transcript.
531
+ * @param format The format of the subtitles.
532
+ * @param chars_per_caption The maximum number of characters per caption.
533
+ * @return A promise that resolves to the subtitles text.
534
+ */
535
+ subtitles(id, format = "srt", chars_per_caption) {
536
+ return __awaiter(this, void 0, void 0, function* () {
537
+ let url = `/v2/transcript/${id}/${format}`;
538
+ if (chars_per_caption) {
539
+ const params = new URLSearchParams();
540
+ params.set("chars_per_caption", chars_per_caption.toString());
541
+ url += `?${params.toString()}`;
542
+ }
543
+ const response = yield this.fetch(url);
544
+ return yield response.text();
545
+ });
546
+ }
547
+ /**
548
+ * Retrieve redactions of a transcript.
549
+ * @param id The identifier of the transcript.
550
+ * @return A promise that resolves to the subtitles text.
551
+ */
552
+ redactions(id) {
553
+ return this.fetchJson(`/v2/transcript/${id}/redacted-audio`);
554
+ }
555
+ }
556
+ function getPath(path) {
557
+ let url;
558
+ try {
559
+ url = new URL(path);
560
+ if (url.protocol === "file:")
561
+ return url.pathname;
562
+ else
563
+ return null;
564
+ }
565
+ catch (_a) {
566
+ return path;
567
+ }
568
+ }
569
+
570
+ class FileService extends BaseService {
571
+ /**
572
+ * Upload a local file to AssemblyAI.
573
+ * @param input The local file path to upload, or a stream or buffer of the file to upload.
574
+ * @return A promise that resolves to the uploaded file URL.
575
+ */
576
+ upload(input) {
577
+ return __awaiter(this, void 0, void 0, function* () {
578
+ let fileData;
579
+ if (typeof input === "string")
580
+ fileData = fs.createReadStream(input);
581
+ else
582
+ fileData = input;
583
+ const data = yield this.fetchJson("/v2/upload", {
584
+ method: "POST",
585
+ body: fileData,
586
+ headers: {
587
+ "Content-Type": "application/octet-stream",
588
+ },
589
+ duplex: "half",
590
+ });
591
+ return data.upload_url;
592
+ });
593
+ }
594
+ }
595
+
596
+ const defaultBaseUrl = "https://api.assemblyai.com";
597
+ class AssemblyAI {
598
+ /**
599
+ * Create a new AssemblyAI client.
600
+ * @param params The parameters for the service, including the API key and base URL, if any.
601
+ */
602
+ constructor(params) {
603
+ params.baseUrl = params.baseUrl || defaultBaseUrl;
604
+ if (params.baseUrl && params.baseUrl.endsWith("/"))
605
+ params.baseUrl = params.baseUrl.slice(0, -1);
606
+ this.files = new FileService(params);
607
+ this.transcripts = new TranscriptService(params, this.files);
608
+ this.lemur = new LemurService(params);
609
+ this.realtime = new RealtimeServiceFactory(params);
610
+ }
611
+ }
612
+
613
+ exports.AssemblyAI = AssemblyAI;
614
+ exports.FileService = FileService;
615
+ exports.LemurService = LemurService;
616
+ exports.RealtimeService = RealtimeService;
617
+ exports.RealtimeServiceFactory = RealtimeServiceFactory;
618
+ exports.TranscriptService = TranscriptService;
@@ -1,3 +1,7 @@
1
+ import { WritableStream } from '@swimburger/isomorphic-streams';
2
+ import WebSocket from 'isomorphic-ws';
3
+ import fs from 'fs';
4
+
1
5
  /******************************************************************************
2
6
  Copyright (c) Microsoft Corporation.
3
7
 
@@ -125,66 +129,6 @@ class LemurService extends BaseService {
125
129
  }
126
130
  }
127
131
 
128
- const {
129
- ReadableStream,
130
- ReadableStreamDefaultReader,
131
- ReadableStreamBYOBReader,
132
- ReadableStreamBYOBRequest,
133
- ReadableByteStreamController,
134
- ReadableStreamDefaultController,
135
- TransformStream,
136
- TransformStreamDefaultController,
137
- WritableStream,
138
- WritableStreamDefaultWriter,
139
- WritableStreamDefaultController,
140
- ByteLengthQueuingStrategy,
141
- CountQueuingStrategy,
142
- TextEncoderStream,
143
- TextDecoderStream,
144
- } = window;
145
-
146
- // Polyfill to make ReadableStream async-iterable with for-await
147
- // https://jakearchibald.com/2017/async-iterators-and-generators/#making-streams-iterate
148
- if (!ReadableStream.prototype[Symbol.asyncIterator]) {
149
- async function* streamAsyncIterator() {
150
- // Get a lock on the stream
151
- const reader = this.getReader();
152
-
153
- try {
154
- while (true) {
155
- // Read from the stream
156
- const { done, value } = await reader.read();
157
- // Exit if we're done
158
- if (done) return;
159
- // Else yield the chunk
160
- yield value;
161
- }
162
- } finally {
163
- reader.releaseLock();
164
- }
165
- }
166
-
167
- ReadableStream.prototype[Symbol.asyncIterator] = streamAsyncIterator;
168
- }
169
-
170
- // https://github.com/maxogden/websocket-stream/blob/48dc3ddf943e5ada668c31ccd94e9186f02fafbd/ws-fallback.js
171
-
172
- var ws = null;
173
-
174
- if (typeof WebSocket !== 'undefined') {
175
- ws = WebSocket;
176
- } else if (typeof MozWebSocket !== 'undefined') {
177
- ws = MozWebSocket;
178
- } else if (typeof global !== 'undefined') {
179
- ws = global.WebSocket || global.MozWebSocket;
180
- } else if (typeof window !== 'undefined') {
181
- ws = window.WebSocket || window.MozWebSocket;
182
- } else if (typeof self !== 'undefined') {
183
- ws = self.WebSocket || self.MozWebSocket;
184
- }
185
-
186
- var WebSocket$1 = ws;
187
-
188
132
  var RealtimeErrorType;
189
133
  (function (RealtimeErrorType) {
190
134
  RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
@@ -234,9 +178,9 @@ class RealtimeService {
234
178
  this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
235
179
  this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
236
180
  this.wordBoost = params.wordBoost;
237
- if ("apiKey" in params)
181
+ if ("apiKey" in params && params.apiKey)
238
182
  this.apiKey = params.apiKey;
239
- if ("token" in params)
183
+ if ("token" in params && params.token)
240
184
  this.token = params.token;
241
185
  if (!(this.apiKey || this.token)) {
242
186
  throw new Error("API key or temporary token is required.");
@@ -269,10 +213,10 @@ class RealtimeService {
269
213
  }
270
214
  const url = this.connectionUrl();
271
215
  if (this.token) {
272
- this.socket = new WebSocket$1(url.toString());
216
+ this.socket = new WebSocket(url.toString());
273
217
  }
274
218
  else {
275
- this.socket = new WebSocket$1(url.toString(), {
219
+ this.socket = new WebSocket(url.toString(), {
276
220
  headers: { Authorization: this.apiKey },
277
221
  });
278
222
  }
@@ -332,7 +276,7 @@ class RealtimeService {
332
276
  });
333
277
  }
334
278
  sendAudio(audio) {
335
- if (!this.socket || this.socket.readyState !== WebSocket$1.OPEN) {
279
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
336
280
  throw new Error("Socket is not open for communication");
337
281
  }
338
282
  let audioData;
@@ -359,7 +303,7 @@ class RealtimeService {
359
303
  close(waitForSessionTermination = true) {
360
304
  return __awaiter(this, void 0, void 0, function* () {
361
305
  if (this.socket) {
362
- if (this.socket.readyState === WebSocket$1.OPEN) {
306
+ if (this.socket.readyState === WebSocket.OPEN) {
363
307
  const terminateSessionMessage = `{"terminate_session": true}`;
364
308
  if (waitForSessionTermination) {
365
309
  const sessionTerminatedPromise = new Promise((resolve) => {
@@ -621,15 +565,6 @@ function getPath(path) {
621
565
  }
622
566
  }
623
567
 
624
- function throwError() {
625
- throw new Error("Function is not supported in this environment.");
626
- }
627
-
628
- const createReadStream = throwError;
629
- var fs = {
630
- createReadStream,
631
- };
632
-
633
568
  class FileService extends BaseService {
634
569
  /**
635
570
  * Upload a local file to AssemblyAI.
package/docs/compat.md ADDED
@@ -0,0 +1,59 @@
1
+ # SDK Compatibility
2
+
3
+ The JavaScript SDK is developed for Node.js but is also compatible with other runtimes
4
+ such as the browser, Deno, Bun, Cloudflare Workers, etc.
5
+
6
+ ## Browser compatibility
7
+
8
+ To make the SDK compatible with the browser, the SDK aims to use web standards as much as possible.
9
+ However, there are still incompatibilities between Node.js and the browser.
10
+
11
+ - `RealtimeService` doesn't support the AssemblyAI API key in the browser.
12
+ Instead, you have to generate a temporary auth token using `client.realtime.createTemporaryToken`, and pass in the resulting token to the real-time transcriber.
13
+
14
+ Generate a temporary auth token on the server.
15
+
16
+ ```js
17
+ import { AssemblyAI } from "assemblyai"
18
+ // Ideally, to avoid embedding your API key client side,
19
+ // you generate this token on the server, and pass it to the client via an API.
20
+ const client = new AssemblyAI({ apiKey: "YOUR_API_KEY" });
21
+ const token = await client.realtime.createTemporaryToken({ expires_in = 480 });
22
+ ```
23
+
24
+ > [!NOTE]
25
+ > We recommend generating the token on the server, so you don't embed your AssemblyAI API key in your client app.
26
+ > If you embed the API key on the client, everyone can see it and use it for themselves.
27
+
28
+ Then pass the token via an API to the client.
29
+ On the client, create an instance of `RealtimeService` using the token.
30
+
31
+ ```js
32
+ import { RealtimeService } from "assemblyai";
33
+ // or the following if you're using UMD
34
+ // const { RealtimeService } = assemblyai;
35
+
36
+ const token = getToken(); // getToken is a function for you to implement
37
+
38
+ const rt = new RealtimeService({
39
+ token: token,
40
+ });
41
+ ```
42
+
43
+ - You can't pass local audio file paths to `client.files.upload`, `client.transcripts.transcribe`, and `client.transcripts.submit`. If you do, you'll get the following error: "'fs' is not supported in this environment.".
44
+ If you want to transcribe audio files, you must use a public URL, a stream, or a buffer.
45
+
46
+ > [!WARNING]
47
+ > The SDK is usable from the browser, but we strongly recommend you don't embed the AssemblyAI API key into your client apps.
48
+ > If you embed the API key on the client, everyone can see it and use it for themselves.
49
+ > Instead, create use the SDK on the server and provide APIs for your client to call.
50
+
51
+ ## Deno, Bun, Cloudflare Workers, etc.
52
+
53
+ Most server-side JavaScript runtimes include a compatibility layer with Node.js.
54
+ Our SDK is developed for Node.js, which makes it compatible with other runtimes through their compatibility layer.
55
+ The bugs in these compatibility layers may introduce issues in our SDK.
56
+
57
+ ## Report issues
58
+
59
+ If you find any (undocumented) bugs when using the SDK, [submit a GitHub issue](https://github.com/AssemblyAI/assemblyai-node-sdk). We'll try to fix it or at least document the compatibility issue.
package/package.json CHANGED
@@ -1,22 +1,39 @@
1
1
  {
2
2
  "name": "assemblyai",
3
- "version": "4.0.0-beta.0",
3
+ "version": "4.0.0-beta.1",
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
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",
8
+ "node": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.node.mjs",
11
+ "require": "./dist/index.node.cjs"
12
+ },
13
+ "bun": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.node.mjs",
16
+ "require": "./dist/index.node.cjs"
17
+ },
18
+ "deno": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.node.mjs",
21
+ "require": "./dist/index.node.cjs"
22
+ },
23
+ "workerd": "./dist/index.mjs",
24
+ "browser": "./dist/index.mjs",
8
25
  "import": "./dist/index.mjs",
9
26
  "require": "./dist/index.cjs",
10
- "browser": "./dist/index.browser.js",
11
27
  "default": "./dist/index.cjs"
12
28
  },
13
29
  "./package.json": "./package.json"
14
30
  },
15
31
  "type": "commonjs",
16
- "main": "dist/index.cjs",
17
- "module": "dist/index.mjs",
18
- "types": "dist/index.d.ts",
19
- "typings": "dist/index.d.ts",
32
+ "main": "./dist/index.cjs",
33
+ "require": "./dist/index.cjs",
34
+ "module": "./dist/index.mjs",
35
+ "types": "./dist/index.d.ts",
36
+ "typings": "./dist/index.d.ts",
20
37
  "repository": {
21
38
  "type": "git",
22
39
  "url": "git+https://github.com/AssemblyAI/assemblyai-node-sdk.git"
@@ -30,8 +47,7 @@
30
47
  "build": "pnpm clean && pnpm rollup -c",
31
48
  "clean": "rimraf dist",
32
49
  "lint": "eslint -c .eslintrc.json '{src,tests}/**/*.{js,ts}' && publint",
33
- "test": "pnpm lint && pnpm test:unit",
34
- "test:unit": "jest --config jest.config.rollup.ts",
50
+ "test": "jest --config jest.config.rollup.ts",
35
51
  "format": "prettier '**/*' --write",
36
52
  "generate-types": "tsx ./scripts/generate-types.ts && pnpm format",
37
53
  "copybara:dry-run": "./copybara.sh dry_run --init-history",
@@ -49,7 +65,11 @@
49
65
  "homepage": "https://www.assemblyai.com/docs",
50
66
  "files": [
51
67
  "dist",
52
- "src"
68
+ "src",
69
+ "package.json",
70
+ "README.md",
71
+ "CHANGELOG.md",
72
+ "docs"
53
73
  ],
54
74
  "devDependencies": {
55
75
  "@rollup/plugin-alias": "^5.0.1",
@@ -83,7 +103,7 @@
83
103
  "typescript": "^5.2.2"
84
104
  },
85
105
  "dependencies": {
86
- "@swimburger/isomorphic-streams": "^1.0.5",
106
+ "@swimburger/isomorphic-streams": "^1.1.1",
87
107
  "isomorphic-ws": "^5.0.0",
88
108
  "ws": "^8.13.0"
89
109
  }
@@ -1,5 +1,5 @@
1
1
  function throwError() {
2
- throw new Error("Function is not supported in this environment.");
2
+ throw new Error("'fs' is not supported in this environment.");
3
3
  }
4
4
 
5
5
  export const createReadStream = throwError;
@@ -33,8 +33,8 @@ export class RealtimeService {
33
33
  this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
34
34
  this.sampleRate = params.sampleRate ?? 16_000;
35
35
  this.wordBoost = params.wordBoost;
36
- if ("apiKey" in params) this.apiKey = params.apiKey;
37
- if ("token" in params) this.token = params.token;
36
+ if ("apiKey" in params && params.apiKey) this.apiKey = params.apiKey;
37
+ if ("token" in params && params.token) this.token = params.token;
38
38
 
39
39
  if (!(this.apiKey || this.token)) {
40
40
  throw new Error("API key or temporary token is required.");
File without changes