diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92975a2..3d404ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,15 @@
# Changelog
-## [4.4.2]
+## [4.4.3] - 2024-05-09
+
+- Add react-native exports that resolve to the browser version of the library.
+
+## [4.4.2] - 2024-05-03
### Changed
- Caching is disabled for all HTTP request made by the SDK
+- Accept data-URIs in `client.files.upload(dataUri)`, `client.transcripts.submit(audio: dataUri)`, `client.transcripts.transcribe(audio: dataUri)`.
- Change how the WebSocket libraries are imported for better compatibility across frameworks and runtimes.
The library no longer relies on a internal `#ws` import, and instead compiles the imports into the dist bundles.
Browser builds will use the native `WebSocket`, other builds will use the `ws` package.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..19dff87
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,96 @@
+# Contribute
+
+We welcome contributions from the community.
+
+## Create issues
+
+Before you create an issue, check the [existing issues](https://github.com/AssemblyAI/assemblyai-node-sdk/issues) to see if someone's already created a similar one.
+
+- If you find an existing issue, add any relevant information and upvote the issue using a thumb-up emoji (👍).
+- If you don't find an issue, [create an issue](https://github.com/AssemblyAI/assemblyai-node-sdk/issues/new) so we can help you, and discuss solutions and next steps.
+
+## Submit a PR
+
+Before submitting a PR, to avoid wasting your valuable time, make sure you are aligned with the maintainers of the repository by discussing the desired changes in a GitHub issue.
+
+To make changes, follow these steps:
+
+1. Fork the repository and clone your own fork.
+2. [Set up pnpm](https://pnpm.io/installation).
+3. Run `pnpm install`.
+4. Make your changes.
+
+- Make the changes themselves.
+- Add tests that verify your changes.
+- Describe your changes in [CHANGELOG.md](./CHANGELOG.md).
+
+1. Before committing your changes, run the following scripts:
+ - `pnpm format`
+ - `pnpm lint`
+ - `pnpm test` (see [run integration tests](#run-integration-tests))
+ - `pnpm build`
+2. If linting and testing passes, commit your changes.
+3. Submit your PR.
+
+## Run integration tests
+
+The integration tests require an upgraded AssemblyAI account.
+The integration tests will use the AssemblyAI API and you'll be charged for your usage.
+Reach out to us if you want some credits for running integration tests.
+
+The integration tests require the following environment variables:
+
+- `ASSEMBLYAI_API_KEY`: Your AssemblyAI API key
+- `TEST_TRANSCRIPT_ID`: The transcript ID of a completed transcript your created
+- `TEST_TRANSCRIPT_IDS`: One or more completed transcript IDs, separated by a comma `,`
+
+You can set these environment variables in your shell, or by creating a _.env_ file with the following format:
+
+```plaintext
+ASSEMBLYAI_API_KEY=...
+TEST_TRANSCRIPT_ID=...
+TEST_TRANSCRIPT_IDS=...
+```
+
+## Generate types from OpenAPI and AsyncAPI spec
+
+1. Configure the location of the OpenAPI and AsyncAPI spec as environment variables:
+ - `OPENAPI_SPEC`: Path or URL to the AssemblyAI OpenAPI spec
+ - `ASYNCAPI_SPEC`: Path or URL to the AssemblyAI AsyncAPI spec
+
+2. Generate the types using `pnpm generate:types`.
+
+
+## Notes about the JavaScript SDK
+
+### Rollup
+
+We use Rollup to build the JavaScript SDK.
+Our Rollup configuration generates the following versions:
+- node.{cjs,mjs}: The Node runtime version using CommonJS and ESModule syntax.
+- bun.mjs: The Bun runtime version.
+- deno.mjs: The Deno runtime version.
+- browser: The browser runtime version that uses the native WebSocket instead of `ws`.
+ - browser.mjs: Using ESModule syntax, to be used by users using a bundler.
+ - assemblyai.umd?(.min).js: Using UMD syntax which creates, to be used directly from a script tag.
+ This script adds the SDK to the global `assemblyai` variable.
+- index.cjs: The default version using CommonJS syntax.
+- index.mjs: The default version using ESModule syntax.
+- index.d.ts: The TypeScript types for the SDK.
+
+### Package.json exports
+
+When a user uses the SDK, the users' runtime will automatically choose the runtime-specific version
+if defined in the package.json `exports` object, or fall back to the default version.
+
+For example, Bun will use *bun.mjs* and Cloudflare Workers (workerd) will use *index.mjs*.
+
+### Package.json imports
+
+To make the SDK compatible with a variety of runtimes, we have to polyfill certain features.
+We're doing this using package.json `imports`, which lets you define runtime-specific imports.
+When these imports are TypeScript files, Rollup automatically includes the code in the output for the specified runtime.
+
+When they are ordinary JavaScript files, Rollup leaves the private import in the output as is.
+This works fine in most runtimes, but some runtimes like React Native/Expo do not support this.
+Therefore, we should restrict ourselves to using only TypeScript code with package.json imports.
diff --git a/README.md b/README.md
index 4a7cd05..161379e 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,30 @@ const client = new AssemblyAI({
You can now use the `client` object to interact with the AssemblyAI API.
+### Using a CDN
+
+You can use automatic CDNs like [UNPKG](https://unpkg.com/) to load the library from a script tag.
+
+- Replace `:version` with the desired version or `latest`.
+- Remove `.min` to load the non-minified version.
+
+```html
+
+```
+
+The script creates a global `assemblyai` variable containing all the services.
+Here's how you create a `RealtimeTranscriber` object.
+
+```js
+const { RealtimeTranscriber } = assemblyai;
+const transcriber = new RealtimeTranscriber({
+ token: "[GENERATE TEMPORARY AUTH TOKEN IN YOUR API]",
+ ...
+});
+```
+
+For type support in your IDE, see [Reference types from JavaScript](./docs/reference-types-from-js.md).
+
## Speech-To-Text
### Transcribe audio and video files
@@ -229,24 +253,25 @@ const rt = client.realtime.transcriber({
> [!WARNING]
> Storing your API key in client-facing applications exposes your API key.
-> Generate a temporary auth token on the server and pass it to your client.
-> _Server code_:
+> Generate a temporary auth token on the server and pass it to your client.
+> _Server code_:
+>
> ```typescript
> const token = await client.realtime.createTemporaryToken({ expires_in = 60 });
> // TODO: return token to client
> ```
>
> _Client code_:
+>
> ```typescript
> import { RealtimeTranscriber } from "assemblyai";
> // TODO: implement getToken to retrieve token from server
> const token = await getToken();
> const rt = new RealtimeTranscriber({
-> token
+> token,
> });
> ```
-
You can configure the following events.
@@ -351,3 +376,7 @@ const response = await client.lemur.purgeRequestData(lemurResponse.request_id);
```
+
+## Contributing
+
+If you want to contribute to the JavaScript SDK, follow the guidelines in [CONTRIBUTING.md](./CONTRIBUTING.md).
diff --git a/docs/reference-types-from-js.md b/docs/reference-types-from-js.md
new file mode 100644
index 0000000..b760ced
--- /dev/null
+++ b/docs/reference-types-from-js.md
@@ -0,0 +1,27 @@
+# Reference types from JavaScript
+
+Types are automatically configured in most IDEs when you import the `assemblyai` module using `require` or `import`.
+However, if you're using the _assemblyai.umd.js_ or _assemblyai.umd.min.js_ script,
+you need to manually reference the types.
+
+1. Install the `assemblyai` module locally.
+2. Create an _assemblyai.d.ts_ file with the following content.
+ ```typescript
+ import AssemblyAIModule from "assemblyai";
+ declare global {
+ const assemblyai: typeof AssemblyAIModule;
+ }
+ ```
+ This will import the TypeScript types from the `assemblyai` module,
+ and configure them as the global `assemblyai` variable.
+3. Reference the _assemblyai.d.ts_ file at the top of your script file.
+
+ ```js
+ ///
+ const { RealtimeTranscriber } = assemblyai;
+ ...
+ ```
+
+ Your IDE will load the types specified in the `` tag.
+
+ > [!INFO] > `/// ` tags only work in script files, not script-blocks, and should be at the top of the file.
diff --git a/package.json b/package.json
index 18b5bc2..f81ca2a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "assemblyai",
- "version": "4.4.2",
+ "version": "4.4.3",
"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.",
"engines": {
"node": ">=18"
@@ -18,6 +18,7 @@
},
"workerd": "./dist/index.mjs",
"browser": "./dist/browser.mjs",
+ "react-native": "./dist/browser.mjs",
"node": {
"types": "./dist/index.d.ts",
"import": "./dist/node.mjs",
@@ -47,6 +48,8 @@
}
},
"type": "commonjs",
+ "react-native": "./dist/browser.mjs",
+ "browser": "./dist/browser.mjs",
"main": "./dist/index.cjs",
"require": "./dist/index.cjs",
"module": "./dist/index.mjs",
@@ -68,7 +71,7 @@
"test": "pnpm run test:unit && pnpm run test:integration",
"test:unit": "jest --config jest.unit.config.js --testTimeout 1000",
"test:integration": "jest --config jest.integration.config.js --testTimeout 360000",
- "format": "prettier '**/*' --write",
+ "format": "prettier {*,**/*} --write --no-error-on-unmatched-pattern",
"generate:types": "tsx ./scripts/generate-types.ts && prettier 'src/types/*.generated.ts' --write",
"generate:reference": "typedoc",
"copybara:dry-run": "./copybara.sh dry_run --init-history",
@@ -97,16 +100,16 @@
"docs"
],
"devDependencies": {
- "@babel/preset-env": "^7.24.0",
- "@babel/preset-typescript": "^7.23.3",
+ "@babel/preset-env": "^7.24.5",
+ "@babel/preset-typescript": "^7.24.1",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"@types/jest": "^29.5.12",
- "@types/node": "^18.11.9",
+ "@types/node": "^18.19.32",
"@types/websocket": "^1.0.10",
"@types/ws": "^8.5.10",
- "@typescript-eslint/eslint-plugin": "^7.2.0",
+ "@typescript-eslint/eslint-plugin": "^7.8.0",
"dotenv": "^16.4.5",
"eslint": "^8.57.0",
"eslint-plugin-tsdoc": "^0.2.17",
@@ -120,14 +123,14 @@
"prettier": "^3.2.5",
"publint": "^0.2.7",
"rimraf": "^5.0.5",
- "rollup": "^4.13.0",
+ "rollup": "^4.17.2",
"ts-jest": "^29.1.2",
"tslib": "^2.5.3",
- "typescript": "^5.4.2",
- "typedoc": "^0.25.12",
- "typedoc-plugin-extras": "^3.0.0"
+ "typedoc": "^0.25.13",
+ "typedoc-plugin-extras": "^3.0.0",
+ "typescript": "^5.4.5"
},
"dependencies": {
- "ws": "^8.16.0"
+ "ws": "^8.17.0"
}
}
diff --git a/scripts/generate-types.ts b/scripts/generate-types.ts
index 96f7f19..9c489a7 100644
--- a/scripts/generate-types.ts
+++ b/scripts/generate-types.ts
@@ -1,7 +1,15 @@
import openapiTS from "openapi-typescript";
import fs from "fs";
+import "dotenv/config";
+
+async function generateTypes(
+ apiSpecPath: string | undefined,
+ outputPath: string,
+) {
+ if (!apiSpecPath) {
+ throw new Error("API spec path not provided.");
+ }
-async function generateTypes(apiSpecPath: string, outputPath: string) {
const localPath = new URL(apiSpecPath, import.meta.url);
let output = await openapiTS(localPath, {
alphabetize: true,
@@ -90,5 +98,5 @@ type OneOf = T extends [infer Only] ? Only : T extends [infer A
fs.writeFileSync(outputPath, output);
}
-generateTypes("../../spec/openapi.yml", "./src/types/openapi.generated.ts");
-generateTypes("../../spec/asyncapi.yml", "./src/types/asyncapi.generated.ts");
+generateTypes(process.env.OPENAPI_SPEC, "./src/types/openapi.generated.ts");
+generateTypes(process.env.ASYNCAPI_SPEC, "./src/types/asyncapi.generated.ts");