chamelaion 0.4.0 → 0.5.0
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 +16 -0
- package/api-promise.js.map +1 -1
- package/client.d.mts +1 -1
- package/client.d.mts.map +1 -1
- package/client.d.ts +1 -1
- package/client.d.ts.map +1 -1
- package/client.js +75 -16
- package/client.js.map +1 -1
- package/client.mjs +77 -18
- package/client.mjs.map +1 -1
- package/core/api-promise.d.mts.map +1 -1
- package/core/api-promise.d.ts.map +1 -1
- package/core/api-promise.js.map +1 -1
- package/core/api-promise.mjs.map +1 -1
- package/core/error.d.mts.map +1 -1
- package/core/error.d.ts.map +1 -1
- package/core/error.js +2 -2
- package/core/error.js.map +1 -1
- package/core/error.mjs +2 -2
- package/core/error.mjs.map +1 -1
- package/error.js.map +1 -1
- package/index.d.mts +1 -1
- package/index.d.mts.map +1 -1
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js.map +1 -1
- package/index.mjs +1 -1
- package/index.mjs.map +1 -1
- package/internal/builtin-types.d.mts +5 -5
- package/internal/builtin-types.d.mts.map +1 -1
- package/internal/builtin-types.d.ts +5 -5
- package/internal/builtin-types.d.ts.map +1 -1
- package/internal/detect-platform.d.mts.map +1 -1
- package/internal/detect-platform.d.ts.map +1 -1
- package/internal/detect-platform.js.map +1 -1
- package/internal/detect-platform.mjs.map +1 -1
- package/internal/errors.js +6 -5
- package/internal/errors.js.map +1 -1
- package/internal/errors.mjs +6 -5
- package/internal/errors.mjs.map +1 -1
- package/internal/headers.js +2 -2
- package/internal/headers.js.map +1 -1
- package/internal/headers.mjs +2 -2
- package/internal/headers.mjs.map +1 -1
- package/internal/parse.d.mts.map +1 -1
- package/internal/parse.d.ts.map +1 -1
- package/internal/parse.js +7 -1
- package/internal/parse.js.map +1 -1
- package/internal/parse.mjs +7 -1
- package/internal/parse.mjs.map +1 -1
- package/internal/request-options.d.mts.map +1 -1
- package/internal/request-options.d.ts.map +1 -1
- package/internal/request-options.js.map +1 -1
- package/internal/request-options.mjs.map +1 -1
- package/internal/shim-types.d.mts.map +1 -1
- package/internal/shim-types.d.ts.map +1 -1
- package/internal/shims.d.mts.map +1 -1
- package/internal/shims.d.ts.map +1 -1
- package/internal/shims.js.map +1 -1
- package/internal/shims.mjs.map +1 -1
- package/internal/to-file.d.mts.map +1 -1
- package/internal/to-file.d.ts.map +1 -1
- package/internal/to-file.js.map +1 -1
- package/internal/to-file.mjs.map +1 -1
- package/internal/types.d.mts +17 -11
- package/internal/types.d.mts.map +1 -1
- package/internal/types.d.ts +17 -11
- package/internal/types.d.ts.map +1 -1
- package/internal/utils/log.d.mts.map +1 -1
- package/internal/utils/log.d.ts.map +1 -1
- package/internal/utils/log.js +9 -2
- package/internal/utils/log.js.map +1 -1
- package/internal/utils/log.mjs +9 -2
- package/internal/utils/log.mjs.map +1 -1
- package/internal/utils/uuid.d.mts.map +1 -1
- package/internal/utils/uuid.d.ts.map +1 -1
- package/internal/utils/uuid.js +2 -4
- package/internal/utils/uuid.js.map +1 -1
- package/internal/utils/uuid.mjs +2 -4
- package/internal/utils/uuid.mjs.map +1 -1
- package/package.json +1 -1
- package/resource.js.map +1 -1
- package/resources/health.d.mts.map +1 -1
- package/resources/health.d.ts.map +1 -1
- package/resources/health.js.map +1 -1
- package/resources/health.mjs.map +1 -1
- package/resources/index.d.mts +1 -1
- package/resources/index.d.mts.map +1 -1
- package/resources/index.d.ts +1 -1
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js +0 -3
- package/resources/index.js.map +1 -1
- package/resources/index.mjs +1 -4
- package/resources/index.mjs.map +1 -1
- package/resources/lipsync/index.d.mts +1 -1
- package/resources/lipsync/index.d.mts.map +1 -1
- package/resources/lipsync/index.d.ts +1 -1
- package/resources/lipsync/index.d.ts.map +1 -1
- package/resources/lipsync/index.js +0 -2
- package/resources/lipsync/index.js.map +1 -1
- package/resources/lipsync/index.mjs +1 -3
- package/resources/lipsync/index.mjs.map +1 -1
- package/resources/lipsync/lipsync.d.mts +5 -10
- package/resources/lipsync/lipsync.d.mts.map +1 -1
- package/resources/lipsync/lipsync.d.ts +5 -10
- package/resources/lipsync/lipsync.d.ts.map +1 -1
- package/resources/lipsync/lipsync.js +3 -4
- package/resources/lipsync/lipsync.js.map +1 -1
- package/resources/lipsync/lipsync.mjs +3 -4
- package/resources/lipsync/lipsync.mjs.map +1 -1
- package/resources/lipsync/requests.d.mts +1 -1
- package/resources/lipsync/requests.d.mts.map +1 -1
- package/resources/lipsync/requests.d.ts +1 -1
- package/resources/lipsync/requests.d.ts.map +1 -1
- package/resources/lipsync/requests.js.map +1 -1
- package/resources/lipsync/requests.mjs.map +1 -1
- package/resources/users.d.mts.map +1 -1
- package/resources/users.d.ts.map +1 -1
- package/src/api-promise.ts +1 -1
- package/src/client.ts +163 -62
- package/src/core/api-promise.ts +7 -2
- package/src/core/error.ts +22 -24
- package/src/error.ts +1 -1
- package/src/index.ts +15 -1
- package/src/internal/builtin-types.ts +14 -9
- package/src/internal/detect-platform.ts +5 -1
- package/src/internal/errors.ts +7 -7
- package/src/internal/headers.ts +2 -2
- package/src/internal/parse.ts +10 -2
- package/src/internal/request-options.ts +2 -6
- package/src/internal/shim-types.ts +2 -2
- package/src/internal/shims.ts +3 -1
- package/src/internal/to-file.ts +7 -7
- package/src/internal/types.ts +20 -16
- package/src/internal/utils/log.ts +30 -8
- package/src/internal/utils/uuid.ts +3 -5
- package/src/resource.ts +1 -1
- package/src/resources/health.ts +2 -4
- package/src/resources/index.ts +8 -3
- package/src/resources/lipsync/index.ts +7 -2
- package/src/resources/lipsync/lipsync.ts +13 -13
- package/src/resources/lipsync/requests.ts +5 -2
- package/src/resources/users.ts +1 -3
- package/src/uploads.ts +1 -1
- package/src/version.ts +1 -1
- package/uploads.js.map +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
- package/version.mjs +1 -1
- package/version.mjs.map +1 -1
package/src/client.ts
CHANGED
|
@@ -19,12 +19,23 @@ import * as API from './resources/index';
|
|
|
19
19
|
import { APIPromise } from './core/api-promise';
|
|
20
20
|
import { Health, HealthCheckResponse } from './resources/health';
|
|
21
21
|
import { UserRetrieveCurrentResponse, Users } from './resources/users';
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
Lipsync,
|
|
24
|
+
LipsyncGenerate,
|
|
25
|
+
LipsyncGenerateParams,
|
|
26
|
+
LipsyncGenerateWithMediaParams,
|
|
27
|
+
} from './resources/lipsync/lipsync';
|
|
23
28
|
import { type Fetch } from './internal/builtin-types';
|
|
24
29
|
import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers';
|
|
25
30
|
import { FinalRequestOptions, RequestOptions } from './internal/request-options';
|
|
26
31
|
import { readEnv } from './internal/utils/env';
|
|
27
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
type LogLevel,
|
|
34
|
+
type Logger,
|
|
35
|
+
formatRequestDetails,
|
|
36
|
+
loggerFor,
|
|
37
|
+
parseLogLevel,
|
|
38
|
+
} from './internal/utils/log';
|
|
28
39
|
import { isEmptyObj } from './internal/utils/values';
|
|
29
40
|
|
|
30
41
|
const environments = {
|
|
@@ -123,7 +134,7 @@ export interface ClientOptions {
|
|
|
123
134
|
}
|
|
124
135
|
|
|
125
136
|
/**
|
|
126
|
-
* API Client for interfacing with the Chamelaion API.
|
|
137
|
+
* API Client for interfacing with the Chamelaion API.
|
|
127
138
|
*/
|
|
128
139
|
export class Chamelaion {
|
|
129
140
|
bearerToken: string | null;
|
|
@@ -161,7 +172,6 @@ export class Chamelaion {
|
|
|
161
172
|
apiKey = readEnv('CHAMELAION_API_KEY') ?? null,
|
|
162
173
|
...opts
|
|
163
174
|
}: ClientOptions = {}) {
|
|
164
|
-
|
|
165
175
|
const options: ClientOptions = {
|
|
166
176
|
bearerToken,
|
|
167
177
|
apiKey,
|
|
@@ -172,8 +182,8 @@ export class Chamelaion {
|
|
|
172
182
|
|
|
173
183
|
if (baseURL && opts.environment) {
|
|
174
184
|
throw new Errors.ChamelaionError(
|
|
175
|
-
'Ambiguous URL; The `baseURL` option (or CHAMELAION_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null'
|
|
176
|
-
)
|
|
185
|
+
'Ambiguous URL; The `baseURL` option (or CHAMELAION_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null',
|
|
186
|
+
);
|
|
177
187
|
}
|
|
178
188
|
|
|
179
189
|
this.baseURL = options.baseURL || environments[options.environment || 'production'];
|
|
@@ -182,12 +192,27 @@ export class Chamelaion {
|
|
|
182
192
|
const defaultLogLevel = 'warn';
|
|
183
193
|
// Set default logLevel early so that we can log a warning in parseLogLevel.
|
|
184
194
|
this.logLevel = defaultLogLevel;
|
|
185
|
-
this.logLevel =
|
|
195
|
+
this.logLevel =
|
|
196
|
+
parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??
|
|
197
|
+
parseLogLevel(readEnv('CHAMELAION_LOG'), "process.env['CHAMELAION_LOG']", this) ??
|
|
198
|
+
defaultLogLevel;
|
|
186
199
|
this.fetchOptions = options.fetchOptions;
|
|
187
200
|
this.maxRetries = options.maxRetries ?? 2;
|
|
188
201
|
this.fetch = options.fetch ?? Shims.getDefaultFetch();
|
|
189
202
|
this.#encoder = Opts.FallbackEncoder;
|
|
190
203
|
|
|
204
|
+
const customHeadersEnv = readEnv('CHAMELAION_CUSTOM_HEADERS');
|
|
205
|
+
if (customHeadersEnv) {
|
|
206
|
+
const parsed: Record<string, string> = {};
|
|
207
|
+
for (const line of customHeadersEnv.split('\n')) {
|
|
208
|
+
const colon = line.indexOf(':');
|
|
209
|
+
if (colon >= 0) {
|
|
210
|
+
parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
options.defaultHeaders = { ...parsed, ...options.defaultHeaders };
|
|
214
|
+
}
|
|
215
|
+
|
|
191
216
|
this._options = options;
|
|
192
217
|
|
|
193
218
|
this.bearerToken = bearerToken;
|
|
@@ -210,7 +235,7 @@ export class Chamelaion {
|
|
|
210
235
|
fetchOptions: this.fetchOptions,
|
|
211
236
|
bearerToken: this.bearerToken,
|
|
212
237
|
apiKey: this.apiKey,
|
|
213
|
-
...options
|
|
238
|
+
...options,
|
|
214
239
|
});
|
|
215
240
|
return client;
|
|
216
241
|
}
|
|
@@ -223,7 +248,7 @@ export class Chamelaion {
|
|
|
223
248
|
}
|
|
224
249
|
|
|
225
250
|
protected defaultQuery(): Record<string, string | undefined> | undefined {
|
|
226
|
-
return this._options.defaultQuery
|
|
251
|
+
return this._options.defaultQuery;
|
|
227
252
|
}
|
|
228
253
|
|
|
229
254
|
protected validateHeaders({ values, nulls }: NullableHeaders) {
|
|
@@ -241,11 +266,19 @@ export class Chamelaion {
|
|
|
241
266
|
return;
|
|
242
267
|
}
|
|
243
268
|
|
|
244
|
-
throw new Error(
|
|
269
|
+
throw new Error(
|
|
270
|
+
'Could not resolve authentication method. Expected either bearerToken or apiKey to be set. Or for one of the "Authorization" or "x-api-key" headers to be explicitly omitted',
|
|
271
|
+
);
|
|
245
272
|
}
|
|
246
273
|
|
|
247
|
-
protected async authHeaders(
|
|
248
|
-
|
|
274
|
+
protected async authHeaders(
|
|
275
|
+
opts: FinalRequestOptions,
|
|
276
|
+
schemes: { bearerAuth?: boolean; apiKeyAuth?: boolean },
|
|
277
|
+
): Promise<NullableHeaders | undefined> {
|
|
278
|
+
return buildHeaders([
|
|
279
|
+
schemes.bearerAuth ? await this.bearerAuth(opts) : null,
|
|
280
|
+
schemes.apiKeyAuth ? await this.apiKeyAuth(opts) : null,
|
|
281
|
+
]);
|
|
249
282
|
}
|
|
250
283
|
|
|
251
284
|
protected async bearerAuth(opts: FinalRequestOptions): Promise<NullableHeaders | undefined> {
|
|
@@ -286,7 +319,11 @@ export class Chamelaion {
|
|
|
286
319
|
return Errors.APIError.generate(status, error, message, headers);
|
|
287
320
|
}
|
|
288
321
|
|
|
289
|
-
buildURL(
|
|
322
|
+
buildURL(
|
|
323
|
+
path: string,
|
|
324
|
+
query: Record<string, unknown> | null | undefined,
|
|
325
|
+
defaultBaseURL?: string | undefined,
|
|
326
|
+
): string {
|
|
290
327
|
const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL;
|
|
291
328
|
const url =
|
|
292
329
|
isAbsoluteURL(path) ?
|
|
@@ -374,7 +411,9 @@ export class Chamelaion {
|
|
|
374
411
|
|
|
375
412
|
await this.prepareOptions(options);
|
|
376
413
|
|
|
377
|
-
const { req, url, timeout } = await this.buildRequest(options, {
|
|
414
|
+
const { req, url, timeout } = await this.buildRequest(options, {
|
|
415
|
+
retryCount: maxRetries - retriesRemaining,
|
|
416
|
+
});
|
|
378
417
|
|
|
379
418
|
await this.prepareRequest(req, { url, options });
|
|
380
419
|
|
|
@@ -383,7 +422,16 @@ export class Chamelaion {
|
|
|
383
422
|
const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;
|
|
384
423
|
const startTime = Date.now();
|
|
385
424
|
|
|
386
|
-
loggerFor(this).debug(
|
|
425
|
+
loggerFor(this).debug(
|
|
426
|
+
`[${requestLogID}] sending request`,
|
|
427
|
+
formatRequestDetails({
|
|
428
|
+
retryOfRequestLogID,
|
|
429
|
+
method: options.method,
|
|
430
|
+
url,
|
|
431
|
+
options,
|
|
432
|
+
headers: req.headers,
|
|
433
|
+
}),
|
|
434
|
+
);
|
|
387
435
|
|
|
388
436
|
if (options.signal?.aborted) {
|
|
389
437
|
throw new Errors.APIUserAbortError();
|
|
@@ -402,21 +450,45 @@ export class Chamelaion {
|
|
|
402
450
|
// deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)"
|
|
403
451
|
// undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)"
|
|
404
452
|
// others do not provide enough information to distinguish timeouts from other connection errors
|
|
405
|
-
const isTimeout =
|
|
453
|
+
const isTimeout =
|
|
454
|
+
isAbortError(response) ||
|
|
455
|
+
/timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));
|
|
406
456
|
if (retriesRemaining) {
|
|
407
|
-
loggerFor(this).info(
|
|
408
|
-
|
|
457
|
+
loggerFor(this).info(
|
|
458
|
+
`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`,
|
|
459
|
+
);
|
|
460
|
+
loggerFor(this).debug(
|
|
461
|
+
`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`,
|
|
462
|
+
formatRequestDetails({
|
|
463
|
+
retryOfRequestLogID,
|
|
464
|
+
url,
|
|
465
|
+
durationMs: headersTime - startTime,
|
|
466
|
+
message: response.message,
|
|
467
|
+
}),
|
|
468
|
+
);
|
|
409
469
|
return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);
|
|
410
470
|
}
|
|
411
|
-
loggerFor(this).info(
|
|
412
|
-
|
|
471
|
+
loggerFor(this).info(
|
|
472
|
+
`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`,
|
|
473
|
+
);
|
|
474
|
+
loggerFor(this).debug(
|
|
475
|
+
`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`,
|
|
476
|
+
formatRequestDetails({
|
|
477
|
+
retryOfRequestLogID,
|
|
478
|
+
url,
|
|
479
|
+
durationMs: headersTime - startTime,
|
|
480
|
+
message: response.message,
|
|
481
|
+
}),
|
|
482
|
+
);
|
|
413
483
|
if (isTimeout) {
|
|
414
484
|
throw new Errors.APIConnectionTimeoutError();
|
|
415
485
|
}
|
|
416
486
|
throw new Errors.APIConnectionError({ cause: response });
|
|
417
487
|
}
|
|
418
488
|
|
|
419
|
-
const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${
|
|
489
|
+
const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${
|
|
490
|
+
response.ok ? 'succeeded' : 'failed'
|
|
491
|
+
} with status ${response.status} in ${headersTime - startTime}ms`;
|
|
420
492
|
|
|
421
493
|
if (!response.ok) {
|
|
422
494
|
const shouldRetry = await this.shouldRetry(response);
|
|
@@ -425,27 +497,60 @@ export class Chamelaion {
|
|
|
425
497
|
|
|
426
498
|
// We don't need the body of this response.
|
|
427
499
|
await Shims.CancelReadableStream(response.body);
|
|
428
|
-
loggerFor(this).info(`${responseInfo} - ${retryMessage}`)
|
|
429
|
-
loggerFor(this).debug(
|
|
430
|
-
|
|
500
|
+
loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
|
|
501
|
+
loggerFor(this).debug(
|
|
502
|
+
`[${requestLogID}] response error (${retryMessage})`,
|
|
503
|
+
formatRequestDetails({
|
|
504
|
+
retryOfRequestLogID,
|
|
505
|
+
url: response.url,
|
|
506
|
+
status: response.status,
|
|
507
|
+
headers: response.headers,
|
|
508
|
+
durationMs: headersTime - startTime,
|
|
509
|
+
}),
|
|
510
|
+
);
|
|
511
|
+
return this.retryRequest(
|
|
512
|
+
options,
|
|
513
|
+
retriesRemaining,
|
|
514
|
+
retryOfRequestLogID ?? requestLogID,
|
|
515
|
+
response.headers,
|
|
516
|
+
);
|
|
431
517
|
}
|
|
432
518
|
|
|
433
519
|
const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
|
|
434
520
|
|
|
435
|
-
loggerFor(this).info(`${responseInfo} - ${retryMessage}`)
|
|
521
|
+
loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
|
|
436
522
|
|
|
437
523
|
const errText = await response.text().catch((err: any) => castToError(err).message);
|
|
438
524
|
const errJSON = safeJSON(errText) as any;
|
|
439
525
|
const errMessage = errJSON ? undefined : errText;
|
|
440
526
|
|
|
441
|
-
loggerFor(this).debug(
|
|
527
|
+
loggerFor(this).debug(
|
|
528
|
+
`[${requestLogID}] response error (${retryMessage})`,
|
|
529
|
+
formatRequestDetails({
|
|
530
|
+
retryOfRequestLogID,
|
|
531
|
+
url: response.url,
|
|
532
|
+
status: response.status,
|
|
533
|
+
headers: response.headers,
|
|
534
|
+
message: errMessage,
|
|
535
|
+
durationMs: Date.now() - startTime,
|
|
536
|
+
}),
|
|
537
|
+
);
|
|
442
538
|
|
|
443
539
|
const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
|
|
444
540
|
throw err;
|
|
445
541
|
}
|
|
446
542
|
|
|
447
|
-
loggerFor(this).info(responseInfo)
|
|
448
|
-
loggerFor(this).debug(
|
|
543
|
+
loggerFor(this).info(responseInfo);
|
|
544
|
+
loggerFor(this).debug(
|
|
545
|
+
`[${requestLogID}] response start`,
|
|
546
|
+
formatRequestDetails({
|
|
547
|
+
retryOfRequestLogID,
|
|
548
|
+
url: response.url,
|
|
549
|
+
status: response.status,
|
|
550
|
+
headers: response.headers,
|
|
551
|
+
durationMs: headersTime - startTime,
|
|
552
|
+
}),
|
|
553
|
+
);
|
|
449
554
|
|
|
450
555
|
return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
|
|
451
556
|
}
|
|
@@ -462,7 +567,9 @@ export class Chamelaion {
|
|
|
462
567
|
|
|
463
568
|
const timeout = setTimeout(abort, ms);
|
|
464
569
|
|
|
465
|
-
const isReadableBody =
|
|
570
|
+
const isReadableBody =
|
|
571
|
+
((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||
|
|
572
|
+
(typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);
|
|
466
573
|
|
|
467
574
|
const fetchOptions: RequestInit = {
|
|
468
575
|
signal: controller.signal as any,
|
|
@@ -477,7 +584,6 @@ export class Chamelaion {
|
|
|
477
584
|
}
|
|
478
585
|
|
|
479
586
|
try {
|
|
480
|
-
|
|
481
587
|
// use undefined this binding; fetch errors if bound to something else in browser/cloudflare
|
|
482
588
|
return await this.fetch.call(undefined, url, fetchOptions);
|
|
483
589
|
} finally {
|
|
@@ -578,11 +684,12 @@ export class Chamelaion {
|
|
|
578
684
|
const req: FinalizedRequestInit = {
|
|
579
685
|
method,
|
|
580
686
|
headers: reqHeaders,
|
|
581
|
-
...(options.signal && { signal: options.signal}),
|
|
582
|
-
...((globalThis as any).ReadableStream &&
|
|
687
|
+
...(options.signal && { signal: options.signal }),
|
|
688
|
+
...((globalThis as any).ReadableStream &&
|
|
689
|
+
body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }),
|
|
583
690
|
...(body && { body }),
|
|
584
|
-
...(this.fetchOptions as any ?? {}),
|
|
585
|
-
...(options.fetchOptions as any ?? {}),
|
|
691
|
+
...((this.fetchOptions as any) ?? {}),
|
|
692
|
+
...((options.fetchOptions as any) ?? {}),
|
|
586
693
|
};
|
|
587
694
|
|
|
588
695
|
return { req, url, timeout: options.timeout };
|
|
@@ -607,15 +714,17 @@ export class Chamelaion {
|
|
|
607
714
|
|
|
608
715
|
const headers = buildHeaders([
|
|
609
716
|
idempotencyHeaders,
|
|
610
|
-
{
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
717
|
+
{
|
|
718
|
+
Accept: 'application/json',
|
|
719
|
+
'User-Agent': this.getUserAgent(),
|
|
720
|
+
'X-Stainless-Retry-Count': String(retryCount),
|
|
721
|
+
...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),
|
|
722
|
+
...getPlatformHeaders(),
|
|
723
|
+
},
|
|
724
|
+
await this.authHeaders(options, options.__security ?? { bearerAuth: true, apiKeyAuth: true }),
|
|
616
725
|
this._options.defaultHeaders,
|
|
617
726
|
bodyHeaders,
|
|
618
|
-
options.headers
|
|
727
|
+
options.headers,
|
|
619
728
|
]);
|
|
620
729
|
|
|
621
730
|
this.validateHeaders(headers);
|
|
@@ -642,11 +751,9 @@ export class Chamelaion {
|
|
|
642
751
|
ArrayBuffer.isView(body) ||
|
|
643
752
|
body instanceof ArrayBuffer ||
|
|
644
753
|
body instanceof DataView ||
|
|
645
|
-
(
|
|
646
|
-
typeof body === 'string' &&
|
|
754
|
+
(typeof body === 'string' &&
|
|
647
755
|
// Preserve legacy string encoding behavior for now
|
|
648
|
-
headers.values.has('content-type')
|
|
649
|
-
) ||
|
|
756
|
+
headers.values.has('content-type')) ||
|
|
650
757
|
// `Blob` is superset of `File`
|
|
651
758
|
((globalThis as any).Blob && body instanceof (globalThis as any).Blob) ||
|
|
652
759
|
// `FormData` -> `multipart/form-data`
|
|
@@ -677,7 +784,7 @@ export class Chamelaion {
|
|
|
677
784
|
}
|
|
678
785
|
|
|
679
786
|
static Chamelaion = this;
|
|
680
|
-
static DEFAULT_TIMEOUT = 60000 // 1 minute
|
|
787
|
+
static DEFAULT_TIMEOUT = 60000; // 1 minute
|
|
681
788
|
|
|
682
789
|
static ChamelaionError = Errors.ChamelaionError;
|
|
683
790
|
static APIError = Errors.APIError;
|
|
@@ -714,22 +821,16 @@ Chamelaion.Users = Users;
|
|
|
714
821
|
Chamelaion.Lipsync = Lipsync;
|
|
715
822
|
|
|
716
823
|
export declare namespace Chamelaion {
|
|
717
|
-
|
|
824
|
+
export type RequestOptions = Opts.RequestOptions;
|
|
718
825
|
|
|
719
|
-
|
|
720
|
-
Health as Health,
|
|
721
|
-
type HealthCheckResponse as HealthCheckResponse
|
|
722
|
-
};
|
|
826
|
+
export { Health as Health, type HealthCheckResponse as HealthCheckResponse };
|
|
723
827
|
|
|
724
|
-
export {
|
|
725
|
-
Users as Users,
|
|
726
|
-
type UserRetrieveCurrentResponse as UserRetrieveCurrentResponse
|
|
727
|
-
};
|
|
828
|
+
export { Users as Users, type UserRetrieveCurrentResponse as UserRetrieveCurrentResponse };
|
|
728
829
|
|
|
729
|
-
export {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
};
|
|
735
|
-
|
|
830
|
+
export {
|
|
831
|
+
Lipsync as Lipsync,
|
|
832
|
+
type LipsyncGenerate as LipsyncGenerate,
|
|
833
|
+
type LipsyncGenerateParams as LipsyncGenerateParams,
|
|
834
|
+
type LipsyncGenerateWithMediaParams as LipsyncGenerateWithMediaParams,
|
|
835
|
+
};
|
|
836
|
+
}
|
package/src/core/api-promise.ts
CHANGED
|
@@ -16,7 +16,10 @@ export class APIPromise<T> extends Promise<T> {
|
|
|
16
16
|
constructor(
|
|
17
17
|
client: Chamelaion,
|
|
18
18
|
private responsePromise: Promise<APIResponseProps>,
|
|
19
|
-
private parseResponse: (
|
|
19
|
+
private parseResponse: (
|
|
20
|
+
client: Chamelaion,
|
|
21
|
+
props: APIResponseProps,
|
|
22
|
+
) => PromiseOrValue<T> = defaultParseResponse,
|
|
20
23
|
) {
|
|
21
24
|
super((resolve) => {
|
|
22
25
|
// this is maybe a bit weird but this has to be a no-op to not implicitly
|
|
@@ -28,7 +31,9 @@ export class APIPromise<T> extends Promise<T> {
|
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
_thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U> {
|
|
31
|
-
return new APIPromise(this.#client, this.responsePromise, async (client, props) =>
|
|
34
|
+
return new APIPromise(this.#client, this.responsePromise, async (client, props) =>
|
|
35
|
+
transform(await this.parseResponse(client, props), props),
|
|
36
|
+
);
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
/**
|
package/src/core/error.ts
CHANGED
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import { castToError } from '../internal/errors';
|
|
4
4
|
|
|
5
|
-
export class ChamelaionError extends Error {
|
|
6
|
-
}
|
|
5
|
+
export class ChamelaionError extends Error {}
|
|
7
6
|
|
|
8
|
-
export class APIError<
|
|
7
|
+
export class APIError<
|
|
8
|
+
TStatus extends number | undefined = number | undefined,
|
|
9
|
+
THeaders extends Headers | undefined = Headers | undefined,
|
|
10
|
+
TError extends Object | undefined = Object | undefined,
|
|
11
|
+
> extends ChamelaionError {
|
|
9
12
|
/** HTTP status for the response that caused the error */
|
|
10
13
|
readonly status: TStatus;
|
|
11
14
|
/** HTTP headers for the response that caused the error */
|
|
@@ -13,9 +16,6 @@ export class APIError<TStatus extends number | undefined = number | undefined, T
|
|
|
13
16
|
/** JSON body of the response that caused the error */
|
|
14
17
|
readonly error: TError;
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
;
|
|
18
|
-
|
|
19
19
|
constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) {
|
|
20
20
|
super(`${APIError.makeMessage(status, error, message)}`);
|
|
21
21
|
this.status = status;
|
|
@@ -26,7 +26,8 @@ export class APIError<TStatus extends number | undefined = number | undefined, T
|
|
|
26
26
|
private static makeMessage(status: number | undefined, error: any, message: string | undefined) {
|
|
27
27
|
const msg =
|
|
28
28
|
error?.message ?
|
|
29
|
-
typeof error.message === 'string' ?
|
|
29
|
+
typeof error.message === 'string' ?
|
|
30
|
+
error.message
|
|
30
31
|
: JSON.stringify(error.message)
|
|
31
32
|
: error ? JSON.stringify(error)
|
|
32
33
|
: message;
|
|
@@ -43,7 +44,12 @@ export class APIError<TStatus extends number | undefined = number | undefined, T
|
|
|
43
44
|
return '(no status code or body)';
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
static generate(
|
|
47
|
+
static generate(
|
|
48
|
+
status: number | undefined,
|
|
49
|
+
errorResponse: Object | undefined,
|
|
50
|
+
message: string | undefined,
|
|
51
|
+
headers: Headers | undefined,
|
|
52
|
+
): APIError {
|
|
47
53
|
if (!status || !headers) {
|
|
48
54
|
return new APIConnectionError({ message, cause: castToError(errorResponse) });
|
|
49
55
|
}
|
|
@@ -107,26 +113,18 @@ export class APIConnectionTimeoutError extends APIConnectionError {
|
|
|
107
113
|
}
|
|
108
114
|
}
|
|
109
115
|
|
|
110
|
-
export class BadRequestError extends APIError<400, Headers> {
|
|
111
|
-
}
|
|
116
|
+
export class BadRequestError extends APIError<400, Headers> {}
|
|
112
117
|
|
|
113
|
-
export class AuthenticationError extends APIError<401, Headers> {
|
|
114
|
-
}
|
|
118
|
+
export class AuthenticationError extends APIError<401, Headers> {}
|
|
115
119
|
|
|
116
|
-
export class PermissionDeniedError extends APIError<403, Headers> {
|
|
117
|
-
}
|
|
120
|
+
export class PermissionDeniedError extends APIError<403, Headers> {}
|
|
118
121
|
|
|
119
|
-
export class NotFoundError extends APIError<404, Headers> {
|
|
120
|
-
}
|
|
122
|
+
export class NotFoundError extends APIError<404, Headers> {}
|
|
121
123
|
|
|
122
|
-
export class ConflictError extends APIError<409, Headers> {
|
|
123
|
-
}
|
|
124
|
+
export class ConflictError extends APIError<409, Headers> {}
|
|
124
125
|
|
|
125
|
-
export class UnprocessableEntityError extends APIError<422, Headers> {
|
|
126
|
-
}
|
|
126
|
+
export class UnprocessableEntityError extends APIError<422, Headers> {}
|
|
127
127
|
|
|
128
|
-
export class RateLimitError extends APIError<429, Headers> {
|
|
129
|
-
}
|
|
128
|
+
export class RateLimitError extends APIError<429, Headers> {}
|
|
130
129
|
|
|
131
|
-
export class InternalServerError extends APIError<number, Headers> {
|
|
132
|
-
}
|
|
130
|
+
export class InternalServerError extends APIError<number, Headers> {}
|
package/src/error.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** @deprecated Import from ./core/error instead */
|
|
2
|
-
export * from
|
|
2
|
+
export * from './core/error';
|
package/src/index.ts
CHANGED
|
@@ -5,4 +5,18 @@ export { Chamelaion as default } from './client';
|
|
|
5
5
|
export { type Uploadable, toFile } from './core/uploads';
|
|
6
6
|
export { APIPromise } from './core/api-promise';
|
|
7
7
|
export { Chamelaion, type ClientOptions } from './client';
|
|
8
|
-
export {
|
|
8
|
+
export {
|
|
9
|
+
ChamelaionError,
|
|
10
|
+
APIError,
|
|
11
|
+
APIConnectionError,
|
|
12
|
+
APIConnectionTimeoutError,
|
|
13
|
+
APIUserAbortError,
|
|
14
|
+
NotFoundError,
|
|
15
|
+
ConflictError,
|
|
16
|
+
RateLimitError,
|
|
17
|
+
BadRequestError,
|
|
18
|
+
AuthenticationError,
|
|
19
|
+
InternalServerError,
|
|
20
|
+
PermissionDeniedError,
|
|
21
|
+
UnprocessableEntityError,
|
|
22
|
+
} from './core/error';
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
2
|
|
|
3
|
-
export type Fetch = (
|
|
4
|
-
input: string | URL | Request,
|
|
5
|
-
init?: RequestInit,
|
|
6
|
-
) => Promise<Response>
|
|
3
|
+
export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
7
4
|
|
|
8
5
|
/**
|
|
9
6
|
* An alias to the builtin `RequestInit` type so we can
|
|
10
7
|
* easily alias it in import statements if there are name clashes.
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
*
|
|
9
|
+
* https://developer.mozilla.org/docs/Web/API/RequestInit
|
|
13
10
|
*/
|
|
14
11
|
type _RequestInit = RequestInit;
|
|
15
12
|
|
|
16
13
|
/**
|
|
17
14
|
* An alias to the builtin `Response` type so we can
|
|
18
15
|
* easily alias it in import statements if there are name clashes.
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
*
|
|
17
|
+
* https://developer.mozilla.org/docs/Web/API/Response
|
|
21
18
|
*/
|
|
22
19
|
type _Response = Response;
|
|
23
20
|
|
|
@@ -54,7 +51,15 @@ type _Array<T> = Array<T>;
|
|
|
54
51
|
*/
|
|
55
52
|
type _Record<K extends keyof any, T> = Record<K, T>;
|
|
56
53
|
|
|
57
|
-
export type {
|
|
54
|
+
export type {
|
|
55
|
+
_Array as Array,
|
|
56
|
+
_BodyInit as BodyInit,
|
|
57
|
+
_HeadersInit as HeadersInit,
|
|
58
|
+
_Record as Record,
|
|
59
|
+
_RequestInfo as RequestInfo,
|
|
60
|
+
_RequestInit as RequestInit,
|
|
61
|
+
_Response as Response,
|
|
62
|
+
};
|
|
58
63
|
|
|
59
64
|
/**
|
|
60
65
|
* A copy of the builtin `EndingType` type as it isn't fully supported in certain
|
|
@@ -25,7 +25,11 @@ function getDetectedPlatform(): DetectedPlatform {
|
|
|
25
25
|
if (typeof EdgeRuntime !== 'undefined') {
|
|
26
26
|
return 'edge';
|
|
27
27
|
}
|
|
28
|
-
if (
|
|
28
|
+
if (
|
|
29
|
+
Object.prototype.toString.call(
|
|
30
|
+
typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0,
|
|
31
|
+
) === '[object process]'
|
|
32
|
+
) {
|
|
29
33
|
return 'node';
|
|
30
34
|
}
|
|
31
35
|
return 'unknown';
|
package/src/internal/errors.ts
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
export function isAbortError(err: unknown) {
|
|
4
4
|
return (
|
|
5
|
-
typeof err === 'object' &&
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
typeof err === 'object' &&
|
|
6
|
+
err !== null &&
|
|
7
|
+
// Spec-compliant fetch implementations
|
|
8
|
+
(('name' in err && (err as any).name === 'AbortError') ||
|
|
8
9
|
// Expo fetch
|
|
9
|
-
('message' in err && String((err as any).message).includes('FetchRequestCanceledException'))
|
|
10
|
-
)
|
|
10
|
+
('message' in err && String((err as any).message).includes('FetchRequestCanceledException')))
|
|
11
11
|
);
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -24,10 +24,10 @@ export const castToError = (err: any): Error => {
|
|
|
24
24
|
if (err.name) error.name = err.name;
|
|
25
25
|
return error;
|
|
26
26
|
}
|
|
27
|
-
} catch {
|
|
27
|
+
} catch {}
|
|
28
28
|
try {
|
|
29
29
|
return new Error(JSON.stringify(err));
|
|
30
|
-
} catch {
|
|
30
|
+
} catch {}
|
|
31
31
|
}
|
|
32
32
|
return new Error(err);
|
|
33
33
|
};
|
package/src/internal/headers.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
2
|
|
|
3
|
-
import { isReadonlyArray } from
|
|
3
|
+
import { isReadonlyArray } from './utils/values';
|
|
4
4
|
|
|
5
5
|
type HeaderValue = string | undefined | null;
|
|
6
6
|
export type HeadersLike =
|
|
@@ -51,7 +51,7 @@ function* iterateHeaders(headers: HeadersLike): IterableIterator<readonly [strin
|
|
|
51
51
|
}
|
|
52
52
|
for (let row of iter) {
|
|
53
53
|
const name = row[0];
|
|
54
|
-
if (typeof name !==
|
|
54
|
+
if (typeof name !== 'string') throw new TypeError('expected header name to be a string');
|
|
55
55
|
const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
|
|
56
56
|
let didClear = false;
|
|
57
57
|
for (const value of values) {
|
package/src/internal/parse.ts
CHANGED
|
@@ -16,7 +16,6 @@ export type APIResponseProps = {
|
|
|
16
16
|
export async function defaultParseResponse<T>(client: Chamelaion, props: APIResponseProps): Promise<T> {
|
|
17
17
|
const { response, requestLogID, retryOfRequestLogID, startTime } = props;
|
|
18
18
|
const body = await (async () => {
|
|
19
|
-
|
|
20
19
|
// fetch refuses to read the body when the status code is 204.
|
|
21
20
|
if (response.status === 204) {
|
|
22
21
|
return null as T;
|
|
@@ -43,6 +42,15 @@ export async function defaultParseResponse<T>(client: Chamelaion, props: APIResp
|
|
|
43
42
|
const text = await response.text();
|
|
44
43
|
return text as unknown as T;
|
|
45
44
|
})();
|
|
46
|
-
loggerFor(client).debug(
|
|
45
|
+
loggerFor(client).debug(
|
|
46
|
+
`[${requestLogID}] response parsed`,
|
|
47
|
+
formatRequestDetails({
|
|
48
|
+
retryOfRequestLogID,
|
|
49
|
+
url: response.url,
|
|
50
|
+
status: response.status,
|
|
51
|
+
body,
|
|
52
|
+
durationMs: Date.now() - startTime,
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
47
55
|
return body;
|
|
48
56
|
}
|