Skip to content

Commit 5e244bc

Browse files
authored
Merge pull request #16 from AssemblyAI/E07417BDFEA3614F5967B1520F8B2F61
Release 3.0.1 👻
2 parents 387b1ac + c2c866e commit 5e244bc

File tree

22 files changed

+444
-403
lines changed

22 files changed

+444
-403
lines changed

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Changelog
2+
3+
## [3.0.1] - 2023-10-30
4+
### Changed
5+
- 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.
6+
7+
### Fixed
8+
- 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).
9+
- Added `speaker` property to the `TranscriptUtterance` type, and removed `channel` property.
10+
11+
## [3.0.0] - 2023-10-24
12+
### Changed
13+
- `AssemblyAI.files.upload` accepts streams and buffers, in addition to a string (path to file).
14+
15+
### Removed
16+
- **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'`.
17+
18+
## [2.0.2] - 2023-10-13
19+
20+
### Added
21+
- `AssemblyAI.transcripts.wordSearch` searches for keywords in the transcript.
22+
- `AssemblyAI.lemur.purgeRequestData` deletes data related to your LeMUR request.
23+
- `RealtimeService.stream` creates a writable stream that you can write audio data to instead of using `RealtimeService.sendAudio``.
24+
25+
### Fixed
26+
- The AssemblyAI class would be exported as default named export instead in certain module systems.
27+
28+
## [2.0.1] - 2023-10-10
29+
30+
Re-implement the Node SDK in TypeScript and add all AssemblyAI APIs.
31+
32+
### Added
33+
- Transcript API client
34+
- LeMUR API client
35+
- Real-time transcript client

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "assemblyai",
3-
"version": "3.0.0",
3+
"version": "3.0.1",
44
"description": "The AssemblyAI Node.js 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.",
55
"main": "dist/index.js",
66
"module": "dist/index.esm.js",
@@ -51,6 +51,7 @@
5151
"i": "^0.3.7",
5252
"jest": "^29.5.0",
5353
"jest-cli": "^29.5.0",
54+
"jest-fetch-mock": "^3.0.3",
5455
"jest-junit": "^16.0.0",
5556
"jest-mock-extended": "^3.0.4",
5657
"jest-websocket-mock": "^2.4.1",
@@ -67,7 +68,6 @@
6768
"typescript": "^5.2.2"
6869
},
6970
"dependencies": {
70-
"axios": "^1.4.0",
7171
"ws": "^8.13.0"
7272
}
7373
}

scripts/kitchensink.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,12 @@ const createTranscriptParams: CreateTranscriptParameters = {
260260
})().then(deleteTranscript);
261261

262262
(async function listTranscripts() {
263-
let nextPageUrl: string | null = null;
263+
let nextPageUrl: string | undefined | null;
264264
do {
265-
const page = await client.transcripts.list(nextPageUrl)
265+
const page = await client.transcripts.list(nextPageUrl as string | undefined)
266266
console.log(page);
267267
nextPageUrl = page.page_details.next_url;
268-
} while (nextPageUrl !== null)
268+
} while (!!nextPageUrl)
269269
})();
270270

271271
async function searchTranscript(transcript: Transcript) {
@@ -355,6 +355,6 @@ async function lemurCustomTask(transcript: Transcript) {
355355
}
356356

357357
async function purgeLemurRequestData(lemurResponse: LemurBaseResponse) {
358-
const { response } = await client.lemur.purgeRequestData(lemurResponse.request_id);
358+
const response = await client.lemur.purgeRequestData(lemurResponse.request_id);
359359
console.log(response);
360360
};

src/services/base.ts

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,53 @@
1-
import { AxiosInstance } from "axios";
1+
import { BaseServiceParams } from "..";
2+
import { Error as JsonError } from "..";
23

34
/**
45
* Base class for services that communicate with the API.
56
*/
67
export abstract class BaseService {
78
/**
89
* Create a new service.
9-
* @param params The AxiosInstance to send HTTP requests to the API.
10+
* @param params The parameters to use for the service.
1011
*/
11-
constructor(protected client: AxiosInstance) {}
12+
constructor(private params: BaseServiceParams) {}
13+
protected async fetch(
14+
input: string,
15+
init?: RequestInit | undefined
16+
): Promise<Response> {
17+
init = init ?? {};
18+
init.headers = init.headers ?? {};
19+
init.headers = {
20+
Authorization: this.params.apiKey,
21+
"Content-Type": "application/json",
22+
...init.headers,
23+
};
24+
if (!input.startsWith("http")) input = this.params.baseUrl + input;
25+
26+
const response = await fetch(input, init);
27+
28+
if (response.status >= 400) {
29+
let json: JsonError | undefined;
30+
const text = await response.text();
31+
if (text) {
32+
try {
33+
json = JSON.parse(text);
34+
} catch {
35+
/* empty */
36+
}
37+
if (json?.error) throw new Error(json.error);
38+
throw new Error(text);
39+
}
40+
throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
41+
}
42+
43+
return response;
44+
}
45+
46+
protected async fetchJson<T>(
47+
input: string,
48+
init?: RequestInit | undefined
49+
): Promise<T> {
50+
const response = await this.fetch(input, init);
51+
return response.json() as Promise<T>;
52+
}
1253
}

src/services/files/index.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// import the fs module instead if specific named exports
22
// to keep the assemblyai module more compatible. Some fs polyfills don't include `createReadStream`.
33
import fs from "fs";
4-
import { BaseService } from "@/services/base";
5-
import { UploadedFile, FileUploadParameters, FileUploadData } from "@/types";
4+
import { BaseService } from "../base";
5+
import { UploadedFile, FileUploadParameters, FileUploadData } from "../..";
66

77
export class FileService extends BaseService {
88
/**
@@ -15,16 +15,14 @@ export class FileService extends BaseService {
1515
if (typeof input === "string") fileData = fs.createReadStream(input);
1616
else fileData = input;
1717

18-
const { data } = await this.client.post<UploadedFile>(
19-
"/v2/upload",
20-
fileData,
21-
{
22-
headers: {
23-
"Content-Type": "application/octet-stream",
24-
},
25-
}
26-
);
27-
18+
const data = await this.fetchJson<UploadedFile>("/v2/upload", {
19+
method: "POST",
20+
body: fileData as BodyInit,
21+
headers: {
22+
"Content-Type": "application/octet-stream",
23+
},
24+
duplex: "half",
25+
} as RequestInit);
2826
return data.upload_url;
2927
}
3028
}

src/services/index.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { createAxiosClient } from "@/utils/axios";
2-
import { BaseServiceParams } from "@/types";
1+
import { BaseServiceParams } from "..";
32
import { LemurService } from "./lemur";
43
import { RealtimeService, RealtimeServiceFactory } from "./realtime";
54
import { TranscriptService } from "./transcripts";
65
import { FileService } from "./files";
76

7+
const defaultBaseUrl = "https://api.assemblyai.com";
8+
89
class AssemblyAI {
910
/**
1011
* The files service.
@@ -31,12 +32,13 @@ class AssemblyAI {
3132
* @param params The parameters for the service, including the API key and base URL, if any.
3233
*/
3334
constructor(params: BaseServiceParams) {
34-
params.baseUrl = params.baseUrl || "https://api.assemblyai.com";
35-
const client = createAxiosClient(params);
36-
this.files = new FileService(client);
37-
this.transcripts = new TranscriptService(client, this.files);
38-
this.lemur = new LemurService(client);
39-
this.realtime = new RealtimeServiceFactory(client, params);
35+
params.baseUrl = params.baseUrl || defaultBaseUrl;
36+
if (params.baseUrl && params.baseUrl.endsWith("/"))
37+
params.baseUrl = params.baseUrl.slice(0, -1);
38+
this.files = new FileService(params);
39+
this.transcripts = new TranscriptService(params, this.files);
40+
this.lemur = new LemurService(params);
41+
this.realtime = new RealtimeServiceFactory(params);
4042
}
4143
}
4244

src/services/lemur/index.ts

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,54 +8,55 @@ import {
88
LemurActionItemsResponse,
99
LemurTaskResponse,
1010
PurgeLemurRequestDataResponse,
11-
} from "@/types";
12-
import { BaseService } from "@/services/base";
11+
} from "../..";
12+
import { BaseService } from "../base";
1313

1414
export class LemurService extends BaseService {
15-
async summary(params: LemurSummaryParameters): Promise<LemurSummaryResponse> {
16-
const { data } = await this.client.post<LemurSummaryResponse>(
17-
"/lemur/v3/generate/summary",
18-
params
19-
);
20-
return data;
15+
summary(params: LemurSummaryParameters): Promise<LemurSummaryResponse> {
16+
return this.fetchJson<LemurSummaryResponse>("/lemur/v3/generate/summary", {
17+
method: "POST",
18+
body: JSON.stringify(params),
19+
});
2120
}
2221

23-
async questionAnswer(
22+
questionAnswer(
2423
params: LemurQuestionAnswerParameters
2524
): Promise<LemurQuestionAnswerResponse> {
26-
const { data } = await this.client.post<LemurQuestionAnswerResponse>(
25+
return this.fetchJson<LemurQuestionAnswerResponse>(
2726
"/lemur/v3/generate/question-answer",
28-
params
27+
{
28+
method: "POST",
29+
body: JSON.stringify(params),
30+
}
2931
);
30-
return data;
3132
}
3233

33-
async actionItems(
34+
actionItems(
3435
params: LemurActionItemsParameters
3536
): Promise<LemurActionItemsResponse> {
36-
const { data } = await this.client.post<LemurActionItemsResponse>(
37+
return this.fetchJson<LemurActionItemsResponse>(
3738
"/lemur/v3/generate/action-items",
38-
params
39+
{
40+
method: "POST",
41+
body: JSON.stringify(params),
42+
}
3943
);
40-
return data;
4144
}
4245

43-
async task(params: LemurTaskParameters): Promise<LemurTaskResponse> {
44-
const { data } = await this.client.post<LemurTaskResponse>(
45-
"/lemur/v3/generate/task",
46-
params
47-
);
48-
return data;
46+
task(params: LemurTaskParameters): Promise<LemurTaskResponse> {
47+
return this.fetchJson<LemurTaskResponse>("/lemur/v3/generate/task", {
48+
method: "POST",
49+
body: JSON.stringify(params),
50+
});
4951
}
5052

5153
/**
5254
* Delete the data for a previously submitted LeMUR request.
5355
* @param id ID of the LeMUR request
5456
*/
55-
async purgeRequestData(id: string): Promise<PurgeLemurRequestDataResponse> {
56-
const { data } = await this.client.delete<PurgeLemurRequestDataResponse>(
57-
`/lemur/v3/${id}`
58-
);
59-
return data;
57+
purgeRequestData(id: string): Promise<PurgeLemurRequestDataResponse> {
58+
return this.fetchJson<PurgeLemurRequestDataResponse>(`/lemur/v3/${id}`, {
59+
method: "DELETE",
60+
});
6061
}
6162
}

src/services/realtime/factory.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,35 @@ import {
33
RealtimeTokenParams,
44
CreateRealtimeServiceParams,
55
RealtimeServiceParams,
6-
} from "@/types";
7-
import { AxiosInstance } from "axios";
6+
RealtimeTemporaryTokenResponse,
7+
} from "../..";
88
import { RealtimeService } from "./service";
9+
import { BaseService } from "../base";
910

10-
export class RealtimeServiceFactory {
11-
constructor(
12-
private client: AxiosInstance,
13-
private params: BaseServiceParams
14-
) {}
11+
export class RealtimeServiceFactory extends BaseService {
12+
private rtFactoryParams: BaseServiceParams;
13+
constructor(params: BaseServiceParams) {
14+
super(params);
15+
this.rtFactoryParams = params;
16+
}
1517

1618
createService(params?: CreateRealtimeServiceParams): RealtimeService {
17-
if (!params) params = { apiKey: this.params.apiKey };
19+
if (!params) params = { apiKey: this.rtFactoryParams.apiKey };
1820
else if (!("token" in params) && !params.apiKey) {
19-
params.apiKey = this.params.apiKey;
21+
params.apiKey = this.rtFactoryParams.apiKey;
2022
}
2123

2224
return new RealtimeService(params as RealtimeServiceParams);
2325
}
2426

2527
async createTemporaryToken(params: RealtimeTokenParams) {
26-
const response = await this.client.post<{ token: string }>(
28+
const data = await this.fetchJson<RealtimeTemporaryTokenResponse>(
2729
"/v2/realtime/token",
28-
params
30+
{
31+
method: "POST",
32+
body: JSON.stringify(params),
33+
}
2934
);
30-
return response.data.token;
35+
return data.token;
3136
}
3237
}

src/services/realtime/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export * from "@/services/realtime/factory";
2-
export * from "@/services/realtime/service";
1+
export * from "./factory";
2+
export * from "./service";

src/services/realtime/service.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import {
88
PartialTranscript,
99
FinalTranscript,
1010
SessionBeginsEventData,
11-
} from "@/types";
11+
} from "../..";
1212
import {
1313
RealtimeError,
1414
RealtimeErrorMessages,
1515
RealtimeErrorType,
16-
} from "@/utils/errors";
17-
import { Writable } from "stream";
16+
} from "../../utils/errors";
17+
import Stream from "stream";
1818

1919
const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
2020

@@ -32,7 +32,6 @@ export class RealtimeService {
3232
this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
3333
this.sampleRate = params.sampleRate ?? 16_000;
3434
this.wordBoost = params.wordBoost;
35-
this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
3635
if ("apiKey" in params) this.apiKey = params.apiKey;
3736
if ("token" in params) this.token = params.token;
3837

@@ -162,8 +161,8 @@ export class RealtimeService {
162161
this.socket.send(JSON.stringify(payload));
163162
}
164163

165-
stream(): Writable {
166-
const stream = new Writable({
164+
stream(): NodeJS.WritableStream {
165+
const stream = new Stream.Writable({
167166
write: (chunk: Buffer, encoding, next) => {
168167
this.sendAudio(chunk);
169168
next();

0 commit comments

Comments
 (0)