@discomedia/utils 1.0.65 → 1.0.66
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/dist/index-frontend.cjs +188 -11
- package/dist/index-frontend.cjs.map +1 -1
- package/dist/index-frontend.mjs +188 -11
- package/dist/index-frontend.mjs.map +1 -1
- package/dist/index.cjs +234 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +234 -63
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +6 -6
- package/dist/test.js +236 -65
- package/dist/test.js.map +1 -1
- package/dist/types/alpaca-market-data-api.d.ts +10 -0
- package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types-frontend/alpaca-market-data-api.d.ts +10 -0
- package/dist/types-frontend/alpaca-market-data-api.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/index-frontend.mjs
CHANGED
|
@@ -209,6 +209,37 @@ class InvalidWebhookSignatureError extends Error {
|
|
|
209
209
|
super(message);
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Error thrown by the API server during OAuth token exchange.
|
|
214
|
+
* Can have status codes 400, 401, or 403.
|
|
215
|
+
* Other status codes from OAuth endpoints are raised as normal APIError types.
|
|
216
|
+
*/
|
|
217
|
+
class OAuthError extends APIError {
|
|
218
|
+
constructor(status, error, headers) {
|
|
219
|
+
let finalMessage = 'OAuth2 authentication error';
|
|
220
|
+
let error_code = undefined;
|
|
221
|
+
if (error && typeof error === 'object') {
|
|
222
|
+
const errorData = error;
|
|
223
|
+
error_code = errorData['error'];
|
|
224
|
+
const description = errorData['error_description'];
|
|
225
|
+
if (description && typeof description === 'string') {
|
|
226
|
+
finalMessage = description;
|
|
227
|
+
}
|
|
228
|
+
else if (error_code) {
|
|
229
|
+
finalMessage = error_code;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
super(status, error, finalMessage, headers);
|
|
233
|
+
this.error_code = error_code;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
class SubjectTokenProviderError extends OpenAIError {
|
|
237
|
+
constructor(message, provider, cause) {
|
|
238
|
+
super(message);
|
|
239
|
+
this.provider = provider;
|
|
240
|
+
this.cause = cause;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
212
243
|
|
|
213
244
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
214
245
|
// https://url.spec.whatwg.org/#url-scheme-string
|
|
@@ -261,7 +292,7 @@ const safeJSON = (text) => {
|
|
|
261
292
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
262
293
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
263
294
|
|
|
264
|
-
const VERSION = '6.
|
|
295
|
+
const VERSION = '6.34.0'; // x-release-please-version
|
|
265
296
|
|
|
266
297
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
267
298
|
const isRunningInBrowser = () => {
|
|
@@ -1642,6 +1673,91 @@ class ConversationCursorPage extends AbstractPage {
|
|
|
1642
1673
|
}
|
|
1643
1674
|
}
|
|
1644
1675
|
|
|
1676
|
+
const SUBJECT_TOKEN_TYPES = {
|
|
1677
|
+
jwt: 'urn:ietf:params:oauth:token-type:jwt',
|
|
1678
|
+
id: 'urn:ietf:params:oauth:token-type:id_token',
|
|
1679
|
+
};
|
|
1680
|
+
const TOKEN_EXCHANGE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:token-exchange';
|
|
1681
|
+
class WorkloadIdentityAuth {
|
|
1682
|
+
constructor(config, fetch) {
|
|
1683
|
+
this.cachedToken = null;
|
|
1684
|
+
this.refreshPromise = null;
|
|
1685
|
+
this.tokenExchangeUrl = 'https://auth.openai.com/oauth/token';
|
|
1686
|
+
this.config = config;
|
|
1687
|
+
this.fetch = fetch ?? getDefaultFetch();
|
|
1688
|
+
}
|
|
1689
|
+
async getToken() {
|
|
1690
|
+
if (!this.cachedToken || this.isTokenExpired(this.cachedToken)) {
|
|
1691
|
+
if (this.refreshPromise) {
|
|
1692
|
+
return await this.refreshPromise;
|
|
1693
|
+
}
|
|
1694
|
+
this.refreshPromise = this.refreshToken();
|
|
1695
|
+
try {
|
|
1696
|
+
const token = await this.refreshPromise;
|
|
1697
|
+
return token;
|
|
1698
|
+
}
|
|
1699
|
+
finally {
|
|
1700
|
+
this.refreshPromise = null;
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
if (this.needsRefresh(this.cachedToken) && !this.refreshPromise) {
|
|
1704
|
+
this.refreshPromise = this.refreshToken().finally(() => {
|
|
1705
|
+
this.refreshPromise = null;
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
return this.cachedToken.token;
|
|
1709
|
+
}
|
|
1710
|
+
async refreshToken() {
|
|
1711
|
+
const subjectToken = await this.config.provider.getToken();
|
|
1712
|
+
const response = await this.fetch(this.tokenExchangeUrl, {
|
|
1713
|
+
method: 'POST',
|
|
1714
|
+
headers: {
|
|
1715
|
+
'Content-Type': 'application/json',
|
|
1716
|
+
},
|
|
1717
|
+
body: JSON.stringify({
|
|
1718
|
+
grant_type: TOKEN_EXCHANGE_GRANT_TYPE,
|
|
1719
|
+
client_id: this.config.clientId,
|
|
1720
|
+
subject_token: subjectToken,
|
|
1721
|
+
subject_token_type: SUBJECT_TOKEN_TYPES[this.config.provider.tokenType],
|
|
1722
|
+
identity_provider_id: this.config.identityProviderId,
|
|
1723
|
+
service_account_id: this.config.serviceAccountId,
|
|
1724
|
+
}),
|
|
1725
|
+
});
|
|
1726
|
+
if (!response.ok) {
|
|
1727
|
+
const errorText = await response.text();
|
|
1728
|
+
let body = undefined;
|
|
1729
|
+
try {
|
|
1730
|
+
body = JSON.parse(errorText);
|
|
1731
|
+
}
|
|
1732
|
+
catch { }
|
|
1733
|
+
if (response.status === 400 || response.status === 401 || response.status === 403) {
|
|
1734
|
+
throw new OAuthError(response.status, body, response.headers);
|
|
1735
|
+
}
|
|
1736
|
+
throw APIError.generate(response.status, body, `Token exchange failed with status ${response.status}`, response.headers);
|
|
1737
|
+
}
|
|
1738
|
+
const tokenResponse = (await response.json());
|
|
1739
|
+
const expiresIn = tokenResponse.expires_in || 3600;
|
|
1740
|
+
const expiresAt = Date.now() + expiresIn * 1000;
|
|
1741
|
+
this.cachedToken = {
|
|
1742
|
+
token: tokenResponse.access_token,
|
|
1743
|
+
expiresAt,
|
|
1744
|
+
};
|
|
1745
|
+
return tokenResponse.access_token;
|
|
1746
|
+
}
|
|
1747
|
+
isTokenExpired(cachedToken) {
|
|
1748
|
+
return Date.now() >= cachedToken.expiresAt;
|
|
1749
|
+
}
|
|
1750
|
+
needsRefresh(cachedToken) {
|
|
1751
|
+
const bufferSeconds = this.config.refreshBufferSeconds ?? 1200;
|
|
1752
|
+
const bufferMs = bufferSeconds * 1000;
|
|
1753
|
+
return Date.now() >= cachedToken.expiresAt - bufferMs;
|
|
1754
|
+
}
|
|
1755
|
+
invalidateToken() {
|
|
1756
|
+
this.cachedToken = null;
|
|
1757
|
+
this.refreshPromise = null;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1645
1761
|
const checkFileSupport = () => {
|
|
1646
1762
|
if (typeof File === 'undefined') {
|
|
1647
1763
|
const { process } = globalThis;
|
|
@@ -6947,6 +7063,7 @@ _Webhooks_instances = new WeakSet(), _Webhooks_validateSecret = function _Webhoo
|
|
|
6947
7063
|
|
|
6948
7064
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
6949
7065
|
var _OpenAI_instances, _a$1, _OpenAI_encoder, _OpenAI_baseURLOverridden;
|
|
7066
|
+
const WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER = 'workload-identity-auth';
|
|
6950
7067
|
/**
|
|
6951
7068
|
* API Client for interfacing with the OpenAI API.
|
|
6952
7069
|
*/
|
|
@@ -6967,7 +7084,7 @@ class OpenAI {
|
|
|
6967
7084
|
* @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
|
|
6968
7085
|
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
|
6969
7086
|
*/
|
|
6970
|
-
constructor({ baseURL = readEnv('OPENAI_BASE_URL'), apiKey = readEnv('OPENAI_API_KEY'), organization = readEnv('OPENAI_ORG_ID') ?? null, project = readEnv('OPENAI_PROJECT_ID') ?? null, webhookSecret = readEnv('OPENAI_WEBHOOK_SECRET') ?? null, ...opts } = {}) {
|
|
7087
|
+
constructor({ baseURL = readEnv('OPENAI_BASE_URL'), apiKey = readEnv('OPENAI_API_KEY'), organization = readEnv('OPENAI_ORG_ID') ?? null, project = readEnv('OPENAI_PROJECT_ID') ?? null, webhookSecret = readEnv('OPENAI_WEBHOOK_SECRET') ?? null, workloadIdentity, ...opts } = {}) {
|
|
6971
7088
|
_OpenAI_instances.add(this);
|
|
6972
7089
|
_OpenAI_encoder.set(this, void 0);
|
|
6973
7090
|
/**
|
|
@@ -7022,14 +7139,21 @@ class OpenAI {
|
|
|
7022
7139
|
this.containers = new Containers(this);
|
|
7023
7140
|
this.skills = new Skills(this);
|
|
7024
7141
|
this.videos = new Videos(this);
|
|
7025
|
-
if (
|
|
7026
|
-
|
|
7142
|
+
if (workloadIdentity) {
|
|
7143
|
+
if (apiKey && apiKey !== WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER) {
|
|
7144
|
+
throw new OpenAIError('The `apiKey` and `workloadIdentity` arguments are mutually exclusive; only one can be passed at a time.');
|
|
7145
|
+
}
|
|
7146
|
+
apiKey = WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER;
|
|
7147
|
+
}
|
|
7148
|
+
else if (apiKey === undefined) {
|
|
7149
|
+
throw new OpenAIError('Missing credentials. Please pass an `apiKey`, `workloadIdentity`, or set the `OPENAI_API_KEY` environment variable.');
|
|
7027
7150
|
}
|
|
7028
7151
|
const options = {
|
|
7029
7152
|
apiKey,
|
|
7030
7153
|
organization,
|
|
7031
7154
|
project,
|
|
7032
7155
|
webhookSecret,
|
|
7156
|
+
workloadIdentity,
|
|
7033
7157
|
...opts,
|
|
7034
7158
|
baseURL: baseURL || `https://api.openai.com/v1`,
|
|
7035
7159
|
};
|
|
@@ -7051,6 +7175,9 @@ class OpenAI {
|
|
|
7051
7175
|
this.fetch = options.fetch ?? getDefaultFetch();
|
|
7052
7176
|
__classPrivateFieldSet(this, _OpenAI_encoder, FallbackEncoder);
|
|
7053
7177
|
this._options = options;
|
|
7178
|
+
if (workloadIdentity) {
|
|
7179
|
+
this._workloadIdentityAuth = new WorkloadIdentityAuth(workloadIdentity, this.fetch);
|
|
7180
|
+
}
|
|
7054
7181
|
this.apiKey = typeof apiKey === 'string' ? apiKey : 'Missing Key';
|
|
7055
7182
|
this.organization = organization;
|
|
7056
7183
|
this.project = project;
|
|
@@ -7070,6 +7197,7 @@ class OpenAI {
|
|
|
7070
7197
|
fetch: this.fetch,
|
|
7071
7198
|
fetchOptions: this.fetchOptions,
|
|
7072
7199
|
apiKey: this.apiKey,
|
|
7200
|
+
workloadIdentity: this._options.workloadIdentity,
|
|
7073
7201
|
organization: this.organization,
|
|
7074
7202
|
project: this.project,
|
|
7075
7203
|
webhookSecret: this.webhookSecret,
|
|
@@ -7196,7 +7324,7 @@ class OpenAI {
|
|
|
7196
7324
|
throw new APIUserAbortError();
|
|
7197
7325
|
}
|
|
7198
7326
|
const controller = new AbortController();
|
|
7199
|
-
const response = await this.
|
|
7327
|
+
const response = await this.fetchWithAuth(url, req, timeout, controller).catch(castToError);
|
|
7200
7328
|
const headersTime = Date.now();
|
|
7201
7329
|
if (response instanceof globalThis.Error) {
|
|
7202
7330
|
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
|
|
@@ -7226,6 +7354,9 @@ class OpenAI {
|
|
|
7226
7354
|
durationMs: headersTime - startTime,
|
|
7227
7355
|
message: response.message,
|
|
7228
7356
|
}));
|
|
7357
|
+
if (response instanceof OAuthError || response instanceof SubjectTokenProviderError) {
|
|
7358
|
+
throw response;
|
|
7359
|
+
}
|
|
7229
7360
|
if (isTimeout) {
|
|
7230
7361
|
throw new APIConnectionTimeoutError();
|
|
7231
7362
|
}
|
|
@@ -7237,6 +7368,20 @@ class OpenAI {
|
|
|
7237
7368
|
.join('');
|
|
7238
7369
|
const responseInfo = `[${requestLogID}${retryLogStr}${specialHeaders}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`;
|
|
7239
7370
|
if (!response.ok) {
|
|
7371
|
+
if (response.status === 401 &&
|
|
7372
|
+
this._workloadIdentityAuth &&
|
|
7373
|
+
!options.__metadata?.['hasStreamingBody'] &&
|
|
7374
|
+
!options.__metadata?.['workloadIdentityTokenRefreshed']) {
|
|
7375
|
+
await CancelReadableStream(response.body);
|
|
7376
|
+
this._workloadIdentityAuth.invalidateToken();
|
|
7377
|
+
return this.makeRequest({
|
|
7378
|
+
...options,
|
|
7379
|
+
__metadata: {
|
|
7380
|
+
...options.__metadata,
|
|
7381
|
+
workloadIdentityTokenRefreshed: true,
|
|
7382
|
+
},
|
|
7383
|
+
}, retriesRemaining, retryOfRequestLogID ?? requestLogID);
|
|
7384
|
+
}
|
|
7240
7385
|
const shouldRetry = await this.shouldRetry(response);
|
|
7241
7386
|
if (retriesRemaining && shouldRetry) {
|
|
7242
7387
|
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
|
|
@@ -7287,6 +7432,18 @@ class OpenAI {
|
|
|
7287
7432
|
const request = this.makeRequest(options, null, undefined);
|
|
7288
7433
|
return new PagePromise(this, request, Page);
|
|
7289
7434
|
}
|
|
7435
|
+
async fetchWithAuth(url, init, timeout, controller) {
|
|
7436
|
+
if (this._workloadIdentityAuth) {
|
|
7437
|
+
const headers = init.headers;
|
|
7438
|
+
const authHeader = headers.get('Authorization');
|
|
7439
|
+
if (!authHeader || authHeader === `Bearer ${WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER}`) {
|
|
7440
|
+
const token = await this._workloadIdentityAuth.getToken();
|
|
7441
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7444
|
+
const response = await this.fetchWithTimeout(url, init, timeout, controller);
|
|
7445
|
+
return response;
|
|
7446
|
+
}
|
|
7290
7447
|
async fetchWithTimeout(url, init, ms, controller) {
|
|
7291
7448
|
const { signal, method, ...options } = init || {};
|
|
7292
7449
|
const abort = this._makeAbort(controller);
|
|
@@ -7383,7 +7540,13 @@ class OpenAI {
|
|
|
7383
7540
|
if ('timeout' in options)
|
|
7384
7541
|
validatePositiveInteger('timeout', options.timeout);
|
|
7385
7542
|
options.timeout = options.timeout ?? this.timeout;
|
|
7386
|
-
const { bodyHeaders, body } = this.buildBody({ options });
|
|
7543
|
+
const { bodyHeaders, body, isStreamingBody } = this.buildBody({ options });
|
|
7544
|
+
if (isStreamingBody) {
|
|
7545
|
+
inputOptions.__metadata = {
|
|
7546
|
+
...inputOptions.__metadata,
|
|
7547
|
+
hasStreamingBody: true,
|
|
7548
|
+
};
|
|
7549
|
+
}
|
|
7387
7550
|
const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
|
|
7388
7551
|
const req = {
|
|
7389
7552
|
method,
|
|
@@ -7430,9 +7593,18 @@ class OpenAI {
|
|
|
7430
7593
|
}
|
|
7431
7594
|
buildBody({ options: { body, headers: rawHeaders } }) {
|
|
7432
7595
|
if (!body) {
|
|
7433
|
-
return { bodyHeaders: undefined, body: undefined };
|
|
7596
|
+
return { bodyHeaders: undefined, body: undefined, isStreamingBody: false };
|
|
7434
7597
|
}
|
|
7435
7598
|
const headers = buildHeaders([rawHeaders]);
|
|
7599
|
+
const isReadableStream = typeof globalThis.ReadableStream !== 'undefined' &&
|
|
7600
|
+
body instanceof globalThis.ReadableStream;
|
|
7601
|
+
const isRetryableBody = !isReadableStream &&
|
|
7602
|
+
(typeof body === 'string' ||
|
|
7603
|
+
body instanceof ArrayBuffer ||
|
|
7604
|
+
ArrayBuffer.isView(body) ||
|
|
7605
|
+
(typeof globalThis.Blob !== 'undefined' && body instanceof globalThis.Blob) ||
|
|
7606
|
+
body instanceof URLSearchParams ||
|
|
7607
|
+
body instanceof FormData);
|
|
7436
7608
|
if (
|
|
7437
7609
|
// Pass raw type verbatim
|
|
7438
7610
|
ArrayBuffer.isView(body) ||
|
|
@@ -7448,23 +7620,28 @@ class OpenAI {
|
|
|
7448
7620
|
// `URLSearchParams` -> `application/x-www-form-urlencoded`
|
|
7449
7621
|
body instanceof URLSearchParams ||
|
|
7450
7622
|
// Send chunked stream (each chunk has own `length`)
|
|
7451
|
-
|
|
7452
|
-
return { bodyHeaders: undefined, body: body };
|
|
7623
|
+
isReadableStream) {
|
|
7624
|
+
return { bodyHeaders: undefined, body: body, isStreamingBody: !isRetryableBody };
|
|
7453
7625
|
}
|
|
7454
7626
|
else if (typeof body === 'object' &&
|
|
7455
7627
|
(Symbol.asyncIterator in body ||
|
|
7456
7628
|
(Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) {
|
|
7457
|
-
return {
|
|
7629
|
+
return {
|
|
7630
|
+
bodyHeaders: undefined,
|
|
7631
|
+
body: ReadableStreamFrom(body),
|
|
7632
|
+
isStreamingBody: true,
|
|
7633
|
+
};
|
|
7458
7634
|
}
|
|
7459
7635
|
else if (typeof body === 'object' &&
|
|
7460
7636
|
headers.values.get('content-type') === 'application/x-www-form-urlencoded') {
|
|
7461
7637
|
return {
|
|
7462
7638
|
bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
7463
7639
|
body: this.stringifyQuery(body),
|
|
7640
|
+
isStreamingBody: false,
|
|
7464
7641
|
};
|
|
7465
7642
|
}
|
|
7466
7643
|
else {
|
|
7467
|
-
return __classPrivateFieldGet(this, _OpenAI_encoder, "f").call(this, { body, headers });
|
|
7644
|
+
return { ...__classPrivateFieldGet(this, _OpenAI_encoder, "f").call(this, { body, headers }), isStreamingBody: false };
|
|
7468
7645
|
}
|
|
7469
7646
|
}
|
|
7470
7647
|
}
|