Skip to content

Commit 430760f

Browse files
committed
docs: streamline README and drop examples/
Trim the README to a quick-start pointer to docs.lmnt.com/api/sdks/typescript where the full SDK guide now lives. Remove the examples/ directory; the docs site carries equivalent (and freshly maintained) snippets.
1 parent ac364d1 commit 430760f

8 files changed

Lines changed: 7 additions & 537 deletions

File tree

README.md

Lines changed: 7 additions & 340 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
1-
# Lmnt Node API Library
1+
# LMNT Node SDK
22

33
[![NPM version](https://img.shields.io/npm/v/lmnt-node.svg)](https://npmjs.org/package/lmnt-node) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/lmnt-node)
44

5-
This library provides convenient access to the Lmnt REST API from server-side TypeScript or JavaScript.
5+
The LMNT Node SDK provides convenient access to the LMNT API from server-side TypeScript applications.
66

7-
The REST API documentation can be found on [docs.lmnt.com](https://docs.lmnt.com). The full API of this library can be found in [api.md](api.md).
7+
## Documentation
88

9-
It is generated with [Stainless](https://www.stainless.com/).
9+
Full documentation is available at [docs.lmnt.com/api/sdks/typescript](https://docs.lmnt.com/api/sdks/typescript).
1010

1111
## Installation
1212

1313
```sh
1414
npm install lmnt-node
1515
```
1616

17-
## Usage
17+
## Getting started
1818

19-
The full API of this library can be found in [api.md](api.md).
20-
21-
<!-- prettier-ignore -->
22-
```js
19+
```ts
2320
import Lmnt from 'lmnt-node';
2421

2522
const client = new Lmnt({
@@ -32,339 +29,9 @@ const content = await response.blob();
3229
console.log(content);
3330
```
3431

35-
#### Session:
36-
37-
```ts
38-
import { createWriteStream } from 'fs';
39-
import Lmnt from 'lmnt-node';
40-
41-
const client = new Lmnt();
42-
43-
async function main() {
44-
// Prepare an output file to which we write streamed audio. This
45-
// could alternatively be piped to a media player or another remote client.
46-
const audioFile = createWriteStream('stream-output.mp3');
47-
48-
// Construct the streaming connection with our desired voice
49-
const speechSession = client.speech.sessions.create({
50-
voice: 'morgan',
51-
});
52-
53-
const writeTask = async () => {
54-
// Simulate a message stream w/ a 1 second delay between messages.
55-
for (let i = 0; i < 5; i++) {
56-
speechSession.appendText(`Hello, world!`);
57-
console.log(` ** Sent to LMNT -- Message ${i} ** `);
58-
await new Promise((resolve) => setTimeout(resolve, 1000));
59-
}
60-
61-
// After `finish` is called, the server will close the connection
62-
// when it has finished synthesizing.
63-
speechSession.finish();
64-
};
65-
66-
const readTask = async () => {
67-
for await (const message of speechSession) {
68-
if (message.type === 'audio') {
69-
const audioBytes = Buffer.byteLength(message.audio);
70-
console.log(` ** Received from LMNT -- ${audioBytes} bytes ** `);
71-
audioFile.write(message.audio);
72-
}
73-
}
74-
75-
speechSession.close();
76-
};
77-
await Promise.all([writeTask(), readTask()]);
78-
audioFile.close();
79-
}
80-
81-
main();
82-
```
83-
84-
### Request & Response types
85-
86-
This library includes TypeScript definitions for all request params and response fields. You may import and use them like so:
87-
88-
<!-- prettier-ignore -->
89-
```ts
90-
import Lmnt from 'lmnt-node';
91-
92-
const client = new Lmnt({
93-
apiKey: process.env['LMNT_API_KEY'], // This is the default and can be omitted
94-
});
95-
96-
const params: Lmnt.SpeechGenerateParams = { text: 'hello world.', voice: 'leah' };
97-
const response: Response = await client.speech.generate(params);
98-
```
99-
100-
Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.
101-
102-
## File uploads
103-
104-
Request parameters that correspond to file uploads can be passed in many different forms:
105-
106-
- `File` (or an object with the same structure)
107-
- a `fetch` `Response` (or an object with the same structure)
108-
- an `fs.ReadStream`
109-
- the return value of our `toFile` helper
110-
111-
```ts
112-
import fs from 'fs';
113-
import fetch from 'node-fetch';
114-
import Lmnt, { toFile } from 'lmnt-node';
115-
116-
const client = new Lmnt();
117-
118-
// If you have access to Node `fs` we recommend using `fs.createReadStream()`:
119-
await client.voices.create({ name: 'new-voice', files: [fs.createReadStream('/path/to/file')] });
120-
121-
// Or if you have the web `File` API you can pass a `File` instance:
122-
await client.voices.create({ name: 'new-voice', files: [new File(['my bytes'], 'file')] });
123-
124-
// You can also pass a `fetch` `Response`:
125-
await client.voices.create({ name: 'new-voice', files: [await fetch('https://somesite/file')] });
126-
127-
// Finally, if none of the above are convenient, you can use our `toFile` helper:
128-
await client.voices.create({ name: 'new-voice', files: [await toFile(Buffer.from('my bytes'), 'file')] });
129-
await client.voices.create({ name: 'new-voice', files: [await toFile(new Uint8Array([0, 1, 2]), 'file')] });
130-
```
131-
132-
## Handling errors
133-
134-
When the library is unable to connect to the API,
135-
or if the API returns a non-success status code (i.e., 4xx or 5xx response),
136-
a subclass of `APIError` will be thrown:
137-
138-
<!-- prettier-ignore -->
139-
```ts
140-
const response = await client.speech.generate({ text: 'hello world.', voice: 'leah' }).catch(async (err) => {
141-
if (err instanceof Lmnt.APIError) {
142-
console.log(err.status); // 400
143-
console.log(err.name); // BadRequestError
144-
console.log(err.headers); // {server: 'nginx', ...}
145-
} else {
146-
throw err;
147-
}
148-
});
149-
```
150-
151-
Error codes are as follows:
152-
153-
| Status Code | Error Type |
154-
| ----------- | -------------------------- |
155-
| 400 | `BadRequestError` |
156-
| 401 | `AuthenticationError` |
157-
| 403 | `PermissionDeniedError` |
158-
| 404 | `NotFoundError` |
159-
| 422 | `UnprocessableEntityError` |
160-
| 429 | `RateLimitError` |
161-
| >=500 | `InternalServerError` |
162-
| N/A | `APIConnectionError` |
163-
164-
### Retries
165-
166-
Certain errors will be automatically retried 2 times by default, with a short exponential backoff.
167-
Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,
168-
429 Rate Limit, and >=500 Internal errors will all be retried by default.
169-
170-
You can use the `maxRetries` option to configure or disable this:
171-
172-
<!-- prettier-ignore -->
173-
```js
174-
// Configure the default for all requests:
175-
const client = new Lmnt({
176-
maxRetries: 0, // default is 2
177-
});
178-
179-
// Or, configure per-request:
180-
await client.speech.generate({ text: 'hello world.', voice: 'leah' }, {
181-
maxRetries: 5,
182-
});
183-
```
184-
185-
### Timeouts
186-
187-
Requests time out after 1 minute by default. You can configure this with a `timeout` option:
188-
189-
<!-- prettier-ignore -->
190-
```ts
191-
// Configure the default for all requests:
192-
const client = new Lmnt({
193-
timeout: 20 * 1000, // 20 seconds (default is 1 minute)
194-
});
195-
196-
// Override per-request:
197-
await client.speech.generate({ text: 'hello world.', voice: 'leah' }, {
198-
timeout: 5 * 1000,
199-
});
200-
```
201-
202-
On timeout, an `APIConnectionTimeoutError` is thrown.
203-
204-
Note that requests which time out will be [retried twice by default](#retries).
205-
206-
## Advanced Usage
207-
208-
### Accessing raw Response data (e.g., headers)
209-
210-
The "raw" `Response` returned by `fetch()` can be accessed through the `.asResponse()` method on the `APIPromise` type that all methods return.
211-
212-
You can also use the `.withResponse()` method to get the raw `Response` along with the parsed data.
213-
214-
<!-- prettier-ignore -->
215-
```ts
216-
const client = new Lmnt();
217-
218-
const response = await client.speech.generate({ text: 'hello world.', voice: 'leah' }).asResponse();
219-
console.log(response.headers.get('X-My-Header'));
220-
console.log(response.statusText); // access the underlying Response object
221-
222-
const { data: response, response: raw } = await client.speech
223-
.generate({ text: 'hello world.', voice: 'leah' })
224-
.withResponse();
225-
console.log(raw.headers.get('X-My-Header'));
226-
console.log(response);
227-
```
228-
229-
### Making custom/undocumented requests
230-
231-
This library is typed for convenient access to the documented API. If you need to access undocumented
232-
endpoints, params, or response properties, the library can still be used.
233-
234-
#### Undocumented endpoints
235-
236-
To make requests to undocumented endpoints, you can use `client.get`, `client.post`, and other HTTP verbs.
237-
Options on the client, such as retries, will be respected when making these requests.
238-
239-
```ts
240-
await client.post('/some/path', {
241-
body: { some_prop: 'foo' },
242-
query: { some_query_arg: 'bar' },
243-
});
244-
```
245-
246-
#### Undocumented request params
247-
248-
To make requests using undocumented parameters, you may use `// @ts-expect-error` on the undocumented
249-
parameter. This library doesn't validate at runtime that the request matches the type, so any extra values you
250-
send will be sent as-is.
251-
252-
```ts
253-
client.foo.create({
254-
foo: 'my_param',
255-
bar: 12,
256-
// @ts-expect-error baz is not yet public
257-
baz: 'undocumented option',
258-
});
259-
```
260-
261-
For requests with the `GET` verb, any extra params will be in the query, all other requests will send the
262-
extra param in the body.
263-
264-
If you want to explicitly send an extra argument, you can do so with the `query`, `body`, and `headers` request
265-
options.
266-
267-
#### Undocumented response properties
268-
269-
To access undocumented response properties, you may access the response object with `// @ts-expect-error` on
270-
the response object, or cast the response object to the requisite type. Like the request params, we do not
271-
validate or strip extra properties from the response from the API.
272-
273-
### Customizing the fetch client
274-
275-
By default, this library uses `node-fetch` in Node, and expects a global `fetch` function in other environments.
276-
277-
If you would prefer to use a global, web-standards-compliant `fetch` function even in a Node environment,
278-
(for example, if you are running Node with `--experimental-fetch` or using NextJS which polyfills with `undici`),
279-
add the following import before your first import `from "Lmnt"`:
280-
281-
```ts
282-
// Tell TypeScript and the package to use the global web fetch instead of node-fetch.
283-
// Note, despite the name, this does not add any polyfills, but expects them to be provided if needed.
284-
import 'lmnt-node/shims/web';
285-
import Lmnt from 'lmnt-node';
286-
```
287-
288-
To do the inverse, add `import "lmnt-node/shims/node"` (which does import polyfills).
289-
This can also be useful if you are getting the wrong TypeScript types for `Response` ([more details](https://github.com/lmnt-com/lmnt-node/tree/master/src/_shims#readme)).
290-
291-
### Logging and middleware
292-
293-
You may also provide a custom `fetch` function when instantiating the client,
294-
which can be used to inspect or alter the `Request` or `Response` before/after each request:
295-
296-
```ts
297-
import { fetch } from 'undici'; // as one example
298-
import Lmnt from 'lmnt-node';
299-
300-
const client = new Lmnt({
301-
fetch: async (url: RequestInfo, init?: RequestInit): Promise<Response> => {
302-
console.log('About to make a request', url, init);
303-
const response = await fetch(url, init);
304-
console.log('Got response', response);
305-
return response;
306-
},
307-
});
308-
```
309-
310-
Note that if given a `DEBUG=true` environment variable, this library will log all requests and responses automatically.
311-
This is intended for debugging purposes only and may change in the future without notice.
312-
313-
### Configuring an HTTP(S) Agent (e.g., for proxies)
314-
315-
By default, this library uses a stable agent for all http/https requests to reuse TCP connections, eliminating many TCP & TLS handshakes and shaving around 100ms off most requests.
316-
317-
If you would like to disable or customize this behavior, for example to use the API behind a proxy, you can pass an `httpAgent` which is used for all requests (be they http or https), for example:
318-
319-
<!-- prettier-ignore -->
320-
```ts
321-
import http from 'http';
322-
import { HttpsProxyAgent } from 'https-proxy-agent';
323-
324-
// Configure the default for all requests:
325-
const client = new Lmnt({
326-
httpAgent: new HttpsProxyAgent(process.env.PROXY_URL),
327-
});
328-
329-
// Override per-request:
330-
await client.speech.generate(
331-
{ text: 'hello world.', voice: 'leah' },
332-
{
333-
httpAgent: new http.Agent({ keepAlive: false }),
334-
},
335-
);
336-
```
337-
338-
## Semantic versioning
339-
340-
This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
341-
342-
1. Changes that only affect static types, without breaking runtime behavior.
343-
2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
344-
3. Changes that we do not expect to impact the vast majority of users in practice.
345-
346-
We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
347-
348-
We are keen for your feedback; please open an [issue](https://www.github.com/lmnt-com/lmnt-node/issues) with questions, bugs, or suggestions.
349-
35032
## Requirements
35133

352-
TypeScript >= 4.5 is supported.
353-
354-
The following runtimes are supported:
355-
356-
- Web browsers (Up-to-date Chrome, Firefox, Safari, Edge, and more)
357-
- Node.js 20 LTS or later ([non-EOL](https://endoflife.date/nodejs)) versions.
358-
- Deno v1.28.0 or higher.
359-
- Bun 1.0 or later.
360-
- Cloudflare Workers.
361-
- Vercel Edge Runtime.
362-
- Jest 28 or greater with the `"node"` environment (`"jsdom"` is not supported at this time).
363-
- Nitro v2.6 or greater.
364-
365-
Note that React Native is not supported at this time.
366-
367-
If you are interested in other runtime environments, please open or upvote an issue on GitHub.
34+
TypeScript >= 4.5 and Node.js 20 LTS or later are supported.
36835

36936
## Contributing
37037

examples/.keep

Lines changed: 0 additions & 4 deletions
This file was deleted.

examples/create_voice.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)