Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 3.0.1 👻 #15

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "assemblyai",
"version": "3.0.0",
"version": "3.0.1",
"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.",
"main": "dist/index.js",
"module": "dist/index.esm.js",
Expand Down Expand Up @@ -51,6 +51,7 @@
"i": "^0.3.7",
"jest": "^29.5.0",
"jest-cli": "^29.5.0",
"jest-fetch-mock": "^3.0.3",
"jest-junit": "^16.0.0",
"jest-mock-extended": "^3.0.4",
"jest-websocket-mock": "^2.4.1",
Expand All @@ -67,7 +68,6 @@
"typescript": "^5.2.2"
},
"dependencies": {
"axios": "^1.4.0",
"ws": "^8.13.0"
}
}
8 changes: 4 additions & 4 deletions scripts/kitchensink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,12 @@ const createTranscriptParams: CreateTranscriptParameters = {
})().then(deleteTranscript);

(async function listTranscripts() {
let nextPageUrl: string | null = null;
let nextPageUrl: string | undefined | null;
do {
const page = await client.transcripts.list(nextPageUrl)
const page = await client.transcripts.list(nextPageUrl as string | undefined)
console.log(page);
nextPageUrl = page.page_details.next_url;
} while (nextPageUrl !== null)
} while (!!nextPageUrl)
})();

async function searchTranscript(transcript: Transcript) {
Expand Down Expand Up @@ -355,6 +355,6 @@ async function lemurCustomTask(transcript: Transcript) {
}

async function purgeLemurRequestData(lemurResponse: LemurBaseResponse) {
const { response } = await client.lemur.purgeRequestData(lemurResponse.request_id);
const response = await client.lemur.purgeRequestData(lemurResponse.request_id);
console.log(response);
};
47 changes: 44 additions & 3 deletions src/services/base.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,53 @@
import { AxiosInstance } from "axios";
import { BaseServiceParams } from "..";
import { Error as JsonError } from "..";

/**
* Base class for services that communicate with the API.
*/
export abstract class BaseService {
/**
* Create a new service.
* @param params The AxiosInstance to send HTTP requests to the API.
* @param params The parameters to use for the service.
*/
constructor(protected client: AxiosInstance) {}
constructor(private params: BaseServiceParams) {}
protected async fetch(
input: string,
init?: RequestInit | undefined
): Promise<Response> {
init = init ?? {};
init.headers = init.headers ?? {};
init.headers = {
Authorization: this.params.apiKey,
"Content-Type": "application/json",
...init.headers,
};
if (!input.startsWith("http")) input = this.params.baseUrl + input;

const response = await fetch(input, init);

if (response.status >= 400) {
let json: JsonError | undefined;
const text = await response.text();
if (text) {
try {
json = JSON.parse(text);
} catch {
/* empty */
}
if (json?.error) throw new Error(json.error);
throw new Error(text);
}
throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
}

return response;
}

protected async fetchJson<T>(
input: string,
init?: RequestInit | undefined
): Promise<T> {
const response = await this.fetch(input, init);
return response.json() as Promise<T>;
}
}
22 changes: 10 additions & 12 deletions src/services/files/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// import the fs module instead if specific named exports
// to keep the assemblyai module more compatible. Some fs polyfills don't include `createReadStream`.
import fs from "fs";
import { BaseService } from "@/services/base";
import { UploadedFile, FileUploadParameters, FileUploadData } from "@/types";
import { BaseService } from "../base";
import { UploadedFile, FileUploadParameters, FileUploadData } from "../..";

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

const { data } = await this.client.post<UploadedFile>(
"/v2/upload",
fileData,
{
headers: {
"Content-Type": "application/octet-stream",
},
}
);

const data = await this.fetchJson<UploadedFile>("/v2/upload", {
method: "POST",
body: fileData as BodyInit,
headers: {
"Content-Type": "application/octet-stream",
},
duplex: "half",
} as RequestInit);
return data.upload_url;
}
}
18 changes: 10 additions & 8 deletions src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createAxiosClient } from "@/utils/axios";
import { BaseServiceParams } from "@/types";
import { BaseServiceParams } from "..";
import { LemurService } from "./lemur";
import { RealtimeService, RealtimeServiceFactory } from "./realtime";
import { TranscriptService } from "./transcripts";
import { FileService } from "./files";

const defaultBaseUrl = "https://api.assemblyai.com";

class AssemblyAI {
/**
* The files service.
Expand All @@ -31,12 +32,13 @@ class AssemblyAI {
* @param params The parameters for the service, including the API key and base URL, if any.
*/
constructor(params: BaseServiceParams) {
params.baseUrl = params.baseUrl || "https://api.assemblyai.com";
const client = createAxiosClient(params);
this.files = new FileService(client);
this.transcripts = new TranscriptService(client, this.files);
this.lemur = new LemurService(client);
this.realtime = new RealtimeServiceFactory(client, params);
params.baseUrl = params.baseUrl || defaultBaseUrl;
if (params.baseUrl && params.baseUrl.endsWith("/"))
params.baseUrl = params.baseUrl.slice(0, -1);
this.files = new FileService(params);
this.transcripts = new TranscriptService(params, this.files);
this.lemur = new LemurService(params);
this.realtime = new RealtimeServiceFactory(params);
}
}

Expand Down
55 changes: 28 additions & 27 deletions src/services/lemur/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,55 @@ import {
LemurActionItemsResponse,
LemurTaskResponse,
PurgeLemurRequestDataResponse,
} from "@/types";
import { BaseService } from "@/services/base";
} from "../..";
import { BaseService } from "../base";

export class LemurService extends BaseService {
async summary(params: LemurSummaryParameters): Promise<LemurSummaryResponse> {
const { data } = await this.client.post<LemurSummaryResponse>(
"/lemur/v3/generate/summary",
params
);
return data;
summary(params: LemurSummaryParameters): Promise<LemurSummaryResponse> {
return this.fetchJson<LemurSummaryResponse>("/lemur/v3/generate/summary", {
method: "POST",
body: JSON.stringify(params),
});
}

async questionAnswer(
questionAnswer(
params: LemurQuestionAnswerParameters
): Promise<LemurQuestionAnswerResponse> {
const { data } = await this.client.post<LemurQuestionAnswerResponse>(
return this.fetchJson<LemurQuestionAnswerResponse>(
"/lemur/v3/generate/question-answer",
params
{
method: "POST",
body: JSON.stringify(params),
}
);
return data;
}

async actionItems(
actionItems(
params: LemurActionItemsParameters
): Promise<LemurActionItemsResponse> {
const { data } = await this.client.post<LemurActionItemsResponse>(
return this.fetchJson<LemurActionItemsResponse>(
"/lemur/v3/generate/action-items",
params
{
method: "POST",
body: JSON.stringify(params),
}
);
return data;
}

async task(params: LemurTaskParameters): Promise<LemurTaskResponse> {
const { data } = await this.client.post<LemurTaskResponse>(
"/lemur/v3/generate/task",
params
);
return data;
task(params: LemurTaskParameters): Promise<LemurTaskResponse> {
return this.fetchJson<LemurTaskResponse>("/lemur/v3/generate/task", {
method: "POST",
body: JSON.stringify(params),
});
}

/**
* Delete the data for a previously submitted LeMUR request.
* @param id ID of the LeMUR request
*/
async purgeRequestData(id: string): Promise<PurgeLemurRequestDataResponse> {
const { data } = await this.client.delete<PurgeLemurRequestDataResponse>(
`/lemur/v3/${id}`
);
return data;
purgeRequestData(id: string): Promise<PurgeLemurRequestDataResponse> {
return this.fetchJson<PurgeLemurRequestDataResponse>(`/lemur/v3/${id}`, {
method: "DELETE",
});
}
}
29 changes: 17 additions & 12 deletions src/services/realtime/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,35 @@ import {
RealtimeTokenParams,
CreateRealtimeServiceParams,
RealtimeServiceParams,
} from "@/types";
import { AxiosInstance } from "axios";
RealtimeTemporaryTokenResponse,
} from "../..";
import { RealtimeService } from "./service";
import { BaseService } from "../base";

export class RealtimeServiceFactory {
constructor(
private client: AxiosInstance,
private params: BaseServiceParams
) {}
export class RealtimeServiceFactory extends BaseService {
private rtFactoryParams: BaseServiceParams;
constructor(params: BaseServiceParams) {
super(params);
this.rtFactoryParams = params;
}

createService(params?: CreateRealtimeServiceParams): RealtimeService {
if (!params) params = { apiKey: this.params.apiKey };
if (!params) params = { apiKey: this.rtFactoryParams.apiKey };
else if (!("token" in params) && !params.apiKey) {
params.apiKey = this.params.apiKey;
params.apiKey = this.rtFactoryParams.apiKey;
}

return new RealtimeService(params as RealtimeServiceParams);
}

async createTemporaryToken(params: RealtimeTokenParams) {
const response = await this.client.post<{ token: string }>(
const data = await this.fetchJson<RealtimeTemporaryTokenResponse>(
"/v2/realtime/token",
params
{
method: "POST",
body: JSON.stringify(params),
}
);
return response.data.token;
return data.token;
}
}
4 changes: 2 additions & 2 deletions src/services/realtime/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from "@/services/realtime/factory";
export * from "@/services/realtime/service";
export * from "./factory";
export * from "./service";
11 changes: 5 additions & 6 deletions src/services/realtime/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import {
PartialTranscript,
FinalTranscript,
SessionBeginsEventData,
} from "@/types";
} from "../..";
import {
RealtimeError,
RealtimeErrorMessages,
RealtimeErrorType,
} from "@/utils/errors";
import { Writable } from "stream";
} from "../../utils/errors";
import Stream from "stream";

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

Expand All @@ -32,7 +32,6 @@ export class RealtimeService {
this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
this.sampleRate = params.sampleRate ?? 16_000;
this.wordBoost = params.wordBoost;
this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
if ("apiKey" in params) this.apiKey = params.apiKey;
if ("token" in params) this.token = params.token;

Expand Down Expand Up @@ -162,8 +161,8 @@ export class RealtimeService {
this.socket.send(JSON.stringify(payload));
}

stream(): Writable {
const stream = new Writable({
stream(): NodeJS.WritableStream {
const stream = new Stream.Writable({
write: (chunk: Buffer, encoding, next) => {
this.sendAudio(chunk);
next();
Expand Down
Loading