@tryfinch/finch-api 3.1.3 → 4.1.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 +48 -0
- package/README.md +39 -15
- package/_shims/ReadableStream.d.ts +38 -0
- package/_shims/ReadableStream.js +5 -0
- package/_shims/ReadableStream.mjs +7 -0
- package/_shims/ReadableStream.node.d.ts +6 -0
- package/_shims/ReadableStream.node.d.ts.map +1 -0
- package/_shims/ReadableStream.node.js +14 -0
- package/_shims/ReadableStream.node.js.map +1 -0
- package/_shims/ReadableStream.node.mjs +3 -0
- package/_shims/ReadableStream.node.mjs.map +1 -0
- package/_shims/fetch.d.ts +8 -1
- package/_shims/fetch.node.d.ts +11 -1
- package/_shims/formdata.js +9 -1
- package/_shims/formdata.mjs +10 -1
- package/core.d.ts +78 -29
- package/core.d.ts.map +1 -1
- package/core.js +186 -62
- package/core.js.map +1 -1
- package/core.mjs +180 -62
- package/core.mjs.map +1 -1
- package/index.d.mts +15 -1
- package/index.d.ts +15 -1
- package/index.d.ts.map +1 -1
- package/index.js +17 -3
- package/index.js.map +1 -1
- package/index.mjs +17 -3
- package/index.mjs.map +1 -1
- package/package.json +1 -1
- package/pagination.d.ts +17 -8
- package/pagination.d.ts.map +1 -1
- package/pagination.js +26 -26
- package/pagination.js.map +1 -1
- package/pagination.mjs +26 -26
- package/pagination.mjs.map +1 -1
- package/resources/account.d.ts +2 -2
- package/resources/account.d.ts.map +1 -1
- package/resources/ats/applications.d.ts +6 -3
- package/resources/ats/applications.d.ts.map +1 -1
- package/resources/ats/applications.js.map +1 -1
- package/resources/ats/applications.mjs.map +1 -1
- package/resources/ats/candidates.d.ts +6 -3
- package/resources/ats/candidates.d.ts.map +1 -1
- package/resources/ats/candidates.js.map +1 -1
- package/resources/ats/candidates.mjs.map +1 -1
- package/resources/ats/jobs.d.ts +3 -3
- package/resources/ats/jobs.d.ts.map +1 -1
- package/resources/ats/offers.d.ts +3 -3
- package/resources/ats/offers.d.ts.map +1 -1
- package/resources/ats/stages.d.ts +1 -1
- package/resources/ats/stages.d.ts.map +1 -1
- package/resources/hris/benefits/benefits.d.ts +9 -10
- package/resources/hris/benefits/benefits.d.ts.map +1 -1
- package/resources/hris/benefits/benefits.js.map +1 -1
- package/resources/hris/benefits/benefits.mjs.map +1 -1
- package/resources/hris/benefits/individuals.d.ts +6 -6
- package/resources/hris/benefits/individuals.d.ts.map +1 -1
- package/resources/hris/company.d.ts +1 -1
- package/resources/hris/company.d.ts.map +1 -1
- package/resources/hris/directory.d.ts +2 -2
- package/resources/hris/directory.d.ts.map +1 -1
- package/resources/hris/individuals/employment-data.d.ts +1 -1
- package/resources/hris/individuals/employment-data.d.ts.map +1 -1
- package/resources/hris/individuals/individuals.d.ts +4 -2
- package/resources/hris/individuals/individuals.d.ts.map +1 -1
- package/resources/hris/individuals/individuals.js.map +1 -1
- package/resources/hris/individuals/individuals.mjs.map +1 -1
- package/resources/hris/pay-statements.d.ts +1 -1
- package/resources/hris/pay-statements.d.ts.map +1 -1
- package/resources/hris/payments.d.ts +4 -1
- package/resources/hris/payments.d.ts.map +1 -1
- package/resources/hris/payments.js.map +1 -1
- package/resources/hris/payments.mjs.map +1 -1
- package/resources/providers.d.ts +1 -1
- package/resources/providers.d.ts.map +1 -1
- package/src/_shims/ReadableStream.d.ts +38 -0
- package/src/_shims/ReadableStream.js +5 -0
- package/src/_shims/ReadableStream.mjs +7 -0
- package/src/_shims/ReadableStream.node.ts +6 -0
- package/src/_shims/fetch.d.ts +8 -1
- package/src/_shims/fetch.node.d.ts +11 -1
- package/src/_shims/formdata.js +9 -1
- package/src/_shims/formdata.mjs +10 -1
- package/src/core.ts +248 -83
- package/src/index.ts +16 -2
- package/src/pagination.ts +32 -27
- package/src/resources/account.ts +2 -2
- package/src/resources/ats/applications.ts +7 -4
- package/src/resources/ats/candidates.ts +7 -4
- package/src/resources/ats/jobs.ts +4 -4
- package/src/resources/ats/offers.ts +4 -4
- package/src/resources/ats/stages.ts +1 -1
- package/src/resources/hris/benefits/benefits.ts +11 -12
- package/src/resources/hris/benefits/individuals.ts +8 -8
- package/src/resources/hris/company.ts +1 -1
- package/src/resources/hris/directory.ts +3 -3
- package/src/resources/hris/individuals/employment-data.ts +1 -1
- package/src/resources/hris/individuals/individuals.ts +5 -3
- package/src/resources/hris/pay-statements.ts +1 -1
- package/src/resources/hris/payments.ts +4 -1
- package/src/resources/providers.ts +1 -1
- package/src/version.ts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
package/src/core.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type RequestInit,
|
|
10
10
|
type Response,
|
|
11
11
|
} from './_shims/fetch.js';
|
|
12
|
+
export { type Response };
|
|
12
13
|
import { isMultipartBody } from './uploads';
|
|
13
14
|
export {
|
|
14
15
|
maybeMultipartFormRequestOptions,
|
|
@@ -21,6 +22,100 @@ const MAX_RETRIES = 2;
|
|
|
21
22
|
|
|
22
23
|
export type Fetch = (url: RequestInfo, init?: RequestInit) => Promise<Response>;
|
|
23
24
|
|
|
25
|
+
type PromiseOrValue<T> = T | Promise<T>;
|
|
26
|
+
|
|
27
|
+
type APIResponseProps = {
|
|
28
|
+
response: Response;
|
|
29
|
+
options: FinalRequestOptions;
|
|
30
|
+
controller: AbortController;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
async function defaultParseResponse<T>(props: APIResponseProps): Promise<T> {
|
|
34
|
+
const { response } = props;
|
|
35
|
+
const contentType = response.headers.get('content-type');
|
|
36
|
+
if (contentType?.includes('application/json')) {
|
|
37
|
+
const json = await response.json();
|
|
38
|
+
|
|
39
|
+
debug('response', response.status, response.url, response.headers, json);
|
|
40
|
+
|
|
41
|
+
return json as T;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// TODO handle blob, arraybuffer, other content types, etc.
|
|
45
|
+
const text = await response.text();
|
|
46
|
+
debug('response', response.status, response.url, response.headers, text);
|
|
47
|
+
return text as T;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* A subclass of `Promise` providing additional helper methods
|
|
52
|
+
* for interacting with the SDK.
|
|
53
|
+
*/
|
|
54
|
+
export class APIPromise<T> extends Promise<T> {
|
|
55
|
+
private parsedPromise: Promise<T> | undefined;
|
|
56
|
+
|
|
57
|
+
constructor(
|
|
58
|
+
private responsePromise: Promise<APIResponseProps>,
|
|
59
|
+
private parseResponse: (props: APIResponseProps) => PromiseOrValue<T> = defaultParseResponse,
|
|
60
|
+
) {
|
|
61
|
+
super((resolve) => {
|
|
62
|
+
// this is maybe a bit weird but this has to be a no-op to not implicitly
|
|
63
|
+
// parse the response body; instead .then, .catch, .finally are overridden
|
|
64
|
+
// to parse the response
|
|
65
|
+
resolve(null as any);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
_thenUnwrap<U>(transform: (data: T) => U): APIPromise<U> {
|
|
70
|
+
return new APIPromise(this.responsePromise, async (props) => transform(await this.parseResponse(props)));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Gets the raw `Response` instance instead of parsing the response
|
|
75
|
+
* data.
|
|
76
|
+
*
|
|
77
|
+
* If you want to parse the response body but still get the `Response`
|
|
78
|
+
* instance, you can use {@link withResponse()}.
|
|
79
|
+
*/
|
|
80
|
+
asResponse(): Promise<Response> {
|
|
81
|
+
return this.responsePromise.then((p) => p.response);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Gets the parsed response data and the raw `Response` instance.
|
|
85
|
+
*
|
|
86
|
+
* If you just want to get the raw `Response` instance without parsing it,
|
|
87
|
+
* you can use {@link asResponse()}.
|
|
88
|
+
*/
|
|
89
|
+
async withResponse(): Promise<{ data: T; response: Response }> {
|
|
90
|
+
const [data, response] = await Promise.all([this.parse(), this.asResponse()]);
|
|
91
|
+
return { data, response };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private parse(): Promise<T> {
|
|
95
|
+
if (!this.parsedPromise) {
|
|
96
|
+
this.parsedPromise = this.responsePromise.then(this.parseResponse);
|
|
97
|
+
}
|
|
98
|
+
return this.parsedPromise;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
override then<TResult1 = T, TResult2 = never>(
|
|
102
|
+
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
|
|
103
|
+
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,
|
|
104
|
+
): Promise<TResult1 | TResult2> {
|
|
105
|
+
return this.parse().then(onfulfilled, onrejected);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
override catch<TResult = never>(
|
|
109
|
+
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null,
|
|
110
|
+
): Promise<T | TResult> {
|
|
111
|
+
return this.parse().catch(onrejected);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
override finally(onfinally?: (() => void) | undefined | null): Promise<T> {
|
|
115
|
+
return this.parse().finally(onfinally);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
24
119
|
export abstract class APIClient {
|
|
25
120
|
baseURL: string;
|
|
26
121
|
maxRetries: number;
|
|
@@ -33,7 +128,7 @@ export abstract class APIClient {
|
|
|
33
128
|
constructor({
|
|
34
129
|
baseURL,
|
|
35
130
|
maxRetries,
|
|
36
|
-
timeout =
|
|
131
|
+
timeout = 60000, // 1 minute
|
|
37
132
|
httpAgent,
|
|
38
133
|
fetch: overridenFetch,
|
|
39
134
|
}: {
|
|
@@ -84,27 +179,39 @@ export abstract class APIClient {
|
|
|
84
179
|
return `stainless-node-retry-${uuid4()}`;
|
|
85
180
|
}
|
|
86
181
|
|
|
87
|
-
get<Req extends {}, Rsp>(path: string, opts?: RequestOptions<Req
|
|
88
|
-
return this.
|
|
182
|
+
get<Req extends {}, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {
|
|
183
|
+
return this.methodRequest('get', path, opts);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
post<Req extends {}, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {
|
|
187
|
+
return this.methodRequest('post', path, opts);
|
|
89
188
|
}
|
|
90
|
-
|
|
91
|
-
|
|
189
|
+
|
|
190
|
+
patch<Req extends {}, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {
|
|
191
|
+
return this.methodRequest('patch', path, opts);
|
|
92
192
|
}
|
|
93
|
-
|
|
94
|
-
|
|
193
|
+
|
|
194
|
+
put<Req extends {}, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {
|
|
195
|
+
return this.methodRequest('put', path, opts);
|
|
95
196
|
}
|
|
96
|
-
|
|
97
|
-
|
|
197
|
+
|
|
198
|
+
delete<Req extends {}, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {
|
|
199
|
+
return this.methodRequest('delete', path, opts);
|
|
98
200
|
}
|
|
99
|
-
|
|
100
|
-
|
|
201
|
+
|
|
202
|
+
private methodRequest<Req extends {}, Rsp>(
|
|
203
|
+
method: HTTPMethod,
|
|
204
|
+
path: string,
|
|
205
|
+
opts?: PromiseOrValue<RequestOptions<Req>>,
|
|
206
|
+
): APIPromise<Rsp> {
|
|
207
|
+
return this.request(Promise.resolve(opts).then((opts) => ({ method, path, ...opts })));
|
|
101
208
|
}
|
|
102
209
|
|
|
103
210
|
getAPIList<Item, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(
|
|
104
211
|
path: string,
|
|
105
212
|
Page: new (...args: any[]) => PageClass,
|
|
106
213
|
opts?: RequestOptions<any>,
|
|
107
|
-
): PagePromise<PageClass> {
|
|
214
|
+
): PagePromise<PageClass, Item> {
|
|
108
215
|
return this.requestAPIList(Page, { method: 'get', path, ...opts });
|
|
109
216
|
}
|
|
110
217
|
|
|
@@ -140,7 +247,10 @@ export abstract class APIClient {
|
|
|
140
247
|
const timeout = options.timeout ?? this.timeout;
|
|
141
248
|
const httpAgent = options.httpAgent ?? this.httpAgent ?? getDefaultAgent(url);
|
|
142
249
|
const minAgentTimeout = timeout + 1000;
|
|
143
|
-
if (
|
|
250
|
+
if (
|
|
251
|
+
typeof (httpAgent as any)?.options?.timeout === 'number' &&
|
|
252
|
+
minAgentTimeout > ((httpAgent as any).options.timeout ?? 0)
|
|
253
|
+
) {
|
|
144
254
|
// Allow any given request to bump our agent active socket timeout.
|
|
145
255
|
// This may seem strange, but leaking active sockets should be rare and not particularly problematic,
|
|
146
256
|
// and without mutating agent we would need to create more of them.
|
|
@@ -198,14 +308,27 @@ export abstract class APIClient {
|
|
|
198
308
|
return APIError.generate(status, error, message, headers);
|
|
199
309
|
}
|
|
200
310
|
|
|
201
|
-
|
|
202
|
-
options: FinalRequestOptions<Req
|
|
203
|
-
|
|
204
|
-
):
|
|
311
|
+
request<Req extends {}, Rsp>(
|
|
312
|
+
options: PromiseOrValue<FinalRequestOptions<Req>>,
|
|
313
|
+
remainingRetries: number | null = null,
|
|
314
|
+
): APIPromise<Rsp> {
|
|
315
|
+
return new APIPromise(this.makeRequest(options, remainingRetries));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
private async makeRequest(
|
|
319
|
+
optionsInput: PromiseOrValue<FinalRequestOptions>,
|
|
320
|
+
retriesRemaining: number | null,
|
|
321
|
+
): Promise<APIResponseProps> {
|
|
322
|
+
const options = await optionsInput;
|
|
323
|
+
if (retriesRemaining == null) {
|
|
324
|
+
retriesRemaining = options.maxRetries ?? this.maxRetries;
|
|
325
|
+
}
|
|
326
|
+
|
|
205
327
|
const { req, url, timeout } = this.buildRequest(options);
|
|
328
|
+
|
|
206
329
|
await this.prepareRequest(req, { url });
|
|
207
330
|
|
|
208
|
-
|
|
331
|
+
debug('request', url, options, req.headers);
|
|
209
332
|
|
|
210
333
|
if (options.signal?.aborted) {
|
|
211
334
|
throw new APIUserAbortError();
|
|
@@ -238,42 +361,21 @@ export abstract class APIClient {
|
|
|
238
361
|
const errJSON = safeJSON(errText);
|
|
239
362
|
const errMessage = errJSON ? undefined : errText;
|
|
240
363
|
|
|
241
|
-
|
|
364
|
+
debug('response', response.status, url, responseHeaders, errMessage);
|
|
242
365
|
|
|
243
366
|
const err = this.makeStatusError(response.status, errJSON, errMessage, responseHeaders);
|
|
244
367
|
throw err;
|
|
245
368
|
}
|
|
246
369
|
|
|
247
|
-
|
|
248
|
-
if (contentType?.includes('application/json')) {
|
|
249
|
-
const json = await response.json();
|
|
250
|
-
|
|
251
|
-
if (typeof json === 'object' && json != null) {
|
|
252
|
-
/** @deprecated – we expect to change this interface in the near future. */
|
|
253
|
-
Object.defineProperty(json, 'responseHeaders', {
|
|
254
|
-
enumerable: false,
|
|
255
|
-
writable: false,
|
|
256
|
-
value: responseHeaders,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
this.debug('response', response.status, url, responseHeaders, json);
|
|
261
|
-
|
|
262
|
-
return json as APIResponse<Rsp>;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// TODO handle blob, arraybuffer, other content types, etc.
|
|
266
|
-
const text = response.text();
|
|
267
|
-
this.debug('response', response.status, url, responseHeaders, text);
|
|
268
|
-
return text as Promise<any>;
|
|
370
|
+
return { response, options, controller };
|
|
269
371
|
}
|
|
270
372
|
|
|
271
373
|
requestAPIList<Item = unknown, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(
|
|
272
374
|
Page: new (...args: ConstructorParameters<typeof AbstractPage>) => PageClass,
|
|
273
375
|
options: FinalRequestOptions,
|
|
274
|
-
): PagePromise<PageClass> {
|
|
275
|
-
const
|
|
276
|
-
return new PagePromise(this,
|
|
376
|
+
): PagePromise<PageClass, Item> {
|
|
377
|
+
const request = this.makeRequest(options, null);
|
|
378
|
+
return new PagePromise<PageClass, Item>(this, request, Page);
|
|
277
379
|
}
|
|
278
380
|
|
|
279
381
|
buildURL<Req>(path: string, query: Req | undefined): string {
|
|
@@ -353,11 +455,11 @@ export abstract class APIClient {
|
|
|
353
455
|
return false;
|
|
354
456
|
}
|
|
355
457
|
|
|
356
|
-
private async retryRequest
|
|
357
|
-
options: FinalRequestOptions
|
|
458
|
+
private async retryRequest(
|
|
459
|
+
options: FinalRequestOptions,
|
|
358
460
|
retriesRemaining: number,
|
|
359
461
|
responseHeaders?: Headers | undefined,
|
|
360
|
-
): Promise<
|
|
462
|
+
): Promise<APIResponseProps> {
|
|
361
463
|
retriesRemaining -= 1;
|
|
362
464
|
|
|
363
465
|
// About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
|
|
@@ -370,7 +472,7 @@ export abstract class APIClient {
|
|
|
370
472
|
const timeout = this.calculateRetryTimeoutSeconds(retriesRemaining, retryAfter, maxRetries) * 1000;
|
|
371
473
|
await sleep(timeout);
|
|
372
474
|
|
|
373
|
-
return this.
|
|
475
|
+
return this.makeRequest(options, retriesRemaining);
|
|
374
476
|
}
|
|
375
477
|
|
|
376
478
|
private calculateRetryTimeoutSeconds(
|
|
@@ -401,12 +503,6 @@ export abstract class APIClient {
|
|
|
401
503
|
private getUserAgent(): string {
|
|
402
504
|
return `${this.constructor.name}/JS ${VERSION}`;
|
|
403
505
|
}
|
|
404
|
-
|
|
405
|
-
private debug(action: string, ...args: any[]) {
|
|
406
|
-
if (typeof process !== 'undefined' && process.env['DEBUG'] === 'true') {
|
|
407
|
-
console.log(`${this.constructor.name}:DEBUG:${action}`, ...args);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
506
|
}
|
|
411
507
|
|
|
412
508
|
export class APIResource {
|
|
@@ -436,9 +532,14 @@ export abstract class AbstractPage<Item> implements AsyncIterable<Item> {
|
|
|
436
532
|
#client: APIClient;
|
|
437
533
|
protected options: FinalRequestOptions;
|
|
438
534
|
|
|
439
|
-
|
|
535
|
+
protected response: Response;
|
|
536
|
+
protected body: unknown;
|
|
537
|
+
|
|
538
|
+
constructor(client: APIClient, response: Response, body: unknown, options: FinalRequestOptions) {
|
|
440
539
|
this.#client = client;
|
|
441
540
|
this.options = options;
|
|
541
|
+
this.response = response;
|
|
542
|
+
this.body = body;
|
|
442
543
|
}
|
|
443
544
|
|
|
444
545
|
/**
|
|
@@ -495,35 +596,33 @@ export abstract class AbstractPage<Item> implements AsyncIterable<Item> {
|
|
|
495
596
|
}
|
|
496
597
|
}
|
|
497
598
|
|
|
599
|
+
/**
|
|
600
|
+
* This subclass of Promise will resolve to an instantiated Page once the request completes.
|
|
601
|
+
*
|
|
602
|
+
* It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg:
|
|
603
|
+
*
|
|
604
|
+
* for await (const item of client.items.list()) {
|
|
605
|
+
* console.log(item)
|
|
606
|
+
* }
|
|
607
|
+
*/
|
|
498
608
|
export class PagePromise<
|
|
499
609
|
PageClass extends AbstractPage<Item>,
|
|
500
610
|
Item = ReturnType<PageClass['getPaginatedItems']>[number],
|
|
501
611
|
>
|
|
502
|
-
extends
|
|
612
|
+
extends APIPromise<PageClass>
|
|
503
613
|
implements AsyncIterable<Item>
|
|
504
614
|
{
|
|
505
|
-
/**
|
|
506
|
-
* This subclass of Promise will resolve to an instantiated Page once the request completes.
|
|
507
|
-
*/
|
|
508
615
|
constructor(
|
|
509
616
|
client: APIClient,
|
|
510
|
-
|
|
511
|
-
options: FinalRequestOptions,
|
|
617
|
+
request: Promise<APIResponseProps>,
|
|
512
618
|
Page: new (...args: ConstructorParameters<typeof AbstractPage>) => PageClass,
|
|
513
619
|
) {
|
|
514
|
-
super(
|
|
515
|
-
|
|
620
|
+
super(
|
|
621
|
+
request,
|
|
622
|
+
async (props) => new Page(client, props.response, await defaultParseResponse(props), props.options),
|
|
516
623
|
);
|
|
517
624
|
}
|
|
518
625
|
|
|
519
|
-
/**
|
|
520
|
-
* Enable subclassing Promise.
|
|
521
|
-
* Ref: https://stackoverflow.com/a/60328122
|
|
522
|
-
*/
|
|
523
|
-
static get [Symbol.species]() {
|
|
524
|
-
return Promise;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
626
|
/**
|
|
528
627
|
* Allow auto-paginating iteration on an unawaited list call, eg:
|
|
529
628
|
*
|
|
@@ -610,11 +709,6 @@ export type FinalRequestOptions<Req extends {} = Record<string, unknown> | Reada
|
|
|
610
709
|
path: string;
|
|
611
710
|
};
|
|
612
711
|
|
|
613
|
-
export type APIResponse<T> = T & {
|
|
614
|
-
/** @deprecated - we plan to add a different way to access raw response information shortly. */
|
|
615
|
-
responseHeaders: Headers;
|
|
616
|
-
};
|
|
617
|
-
|
|
618
712
|
declare const Deno: any;
|
|
619
713
|
declare const EdgeRuntime: any;
|
|
620
714
|
type Arch = 'x32' | 'x64' | 'arm' | 'arm64' | `other:${string}` | 'unknown';
|
|
@@ -628,12 +722,13 @@ type PlatformName =
|
|
|
628
722
|
| 'Android'
|
|
629
723
|
| `Other:${string}`
|
|
630
724
|
| 'Unknown';
|
|
725
|
+
type Browser = 'ie' | 'edge' | 'chrome' | 'firefox' | 'safari';
|
|
631
726
|
type PlatformProperties = {
|
|
632
727
|
'X-Stainless-Lang': 'js';
|
|
633
728
|
'X-Stainless-Package-Version': string;
|
|
634
729
|
'X-Stainless-OS': PlatformName;
|
|
635
730
|
'X-Stainless-Arch': Arch;
|
|
636
|
-
'X-Stainless-Runtime': 'node' | 'deno' | 'edge' | 'unknown';
|
|
731
|
+
'X-Stainless-Runtime': 'node' | 'deno' | 'edge' | `browser:${Browser}` | 'unknown';
|
|
637
732
|
'X-Stainless-Runtime-Version': string;
|
|
638
733
|
};
|
|
639
734
|
const getPlatformProperties = (): PlatformProperties => {
|
|
@@ -668,7 +763,20 @@ const getPlatformProperties = (): PlatformProperties => {
|
|
|
668
763
|
'X-Stainless-Runtime-Version': process.version,
|
|
669
764
|
};
|
|
670
765
|
}
|
|
671
|
-
|
|
766
|
+
|
|
767
|
+
const browserInfo = getBrowserInfo();
|
|
768
|
+
if (browserInfo) {
|
|
769
|
+
return {
|
|
770
|
+
'X-Stainless-Lang': 'js',
|
|
771
|
+
'X-Stainless-Package-Version': VERSION,
|
|
772
|
+
'X-Stainless-OS': 'Unknown',
|
|
773
|
+
'X-Stainless-Arch': 'unknown',
|
|
774
|
+
'X-Stainless-Runtime': `browser:${browserInfo.browser}`,
|
|
775
|
+
'X-Stainless-Runtime-Version': browserInfo.version,
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// TODO add support for Cloudflare workers, etc.
|
|
672
780
|
return {
|
|
673
781
|
'X-Stainless-Lang': 'js',
|
|
674
782
|
'X-Stainless-Package-Version': VERSION,
|
|
@@ -679,6 +787,44 @@ const getPlatformProperties = (): PlatformProperties => {
|
|
|
679
787
|
};
|
|
680
788
|
};
|
|
681
789
|
|
|
790
|
+
type BrowserInfo = {
|
|
791
|
+
browser: Browser;
|
|
792
|
+
version: string;
|
|
793
|
+
};
|
|
794
|
+
|
|
795
|
+
declare const navigator: { userAgent: string } | undefined;
|
|
796
|
+
|
|
797
|
+
// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts
|
|
798
|
+
function getBrowserInfo(): BrowserInfo | null {
|
|
799
|
+
if (!navigator || typeof navigator === 'undefined') {
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// NOTE: The order matters here!
|
|
804
|
+
const browserPatterns = [
|
|
805
|
+
{ key: 'edge' as const, pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
|
806
|
+
{ key: 'ie' as const, pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
|
807
|
+
{ key: 'ie' as const, pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
|
808
|
+
{ key: 'chrome' as const, pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
|
809
|
+
{ key: 'firefox' as const, pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
|
810
|
+
{ key: 'safari' as const, pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ },
|
|
811
|
+
];
|
|
812
|
+
|
|
813
|
+
// Find the FIRST matching browser
|
|
814
|
+
for (const { key, pattern } of browserPatterns) {
|
|
815
|
+
const match = pattern.exec(navigator.userAgent);
|
|
816
|
+
if (match) {
|
|
817
|
+
const major = match[1] || 0;
|
|
818
|
+
const minor = match[2] || 0;
|
|
819
|
+
const patch = match[3] || 0;
|
|
820
|
+
|
|
821
|
+
return { browser: key, version: `${major}.${minor}.${patch}` };
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
return null;
|
|
826
|
+
}
|
|
827
|
+
|
|
682
828
|
const normalizeArch = (arch: string): Arch => {
|
|
683
829
|
// Node docs:
|
|
684
830
|
// - https://nodejs.org/api/process.html#processarch
|
|
@@ -760,14 +906,16 @@ export const ensurePresent = <T>(value: T | null | undefined): T => {
|
|
|
760
906
|
/**
|
|
761
907
|
* Read an environment variable.
|
|
762
908
|
*
|
|
763
|
-
* Will return
|
|
909
|
+
* Will return undefined if the environment variable doesn't exist or cannot be accessed.
|
|
764
910
|
*/
|
|
765
911
|
export const readEnv = (env: string): string | undefined => {
|
|
766
|
-
if (typeof process
|
|
767
|
-
return undefined;
|
|
912
|
+
if (typeof process !== 'undefined') {
|
|
913
|
+
return process.env?.[env] ?? undefined;
|
|
768
914
|
}
|
|
769
|
-
|
|
770
|
-
|
|
915
|
+
if (typeof Deno !== 'undefined') {
|
|
916
|
+
return Deno.env?.get?.(env);
|
|
917
|
+
}
|
|
918
|
+
return undefined;
|
|
771
919
|
};
|
|
772
920
|
|
|
773
921
|
export const coerceInteger = (value: unknown): number => {
|
|
@@ -823,6 +971,12 @@ export function hasOwn(obj: Object, key: string): boolean {
|
|
|
823
971
|
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
824
972
|
}
|
|
825
973
|
|
|
974
|
+
export function debug(action: string, ...args: any[]) {
|
|
975
|
+
if (typeof process !== 'undefined' && process.env['DEBUG'] === 'true') {
|
|
976
|
+
console.log(`Finch:DEBUG:${action}`, ...args);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
826
980
|
/**
|
|
827
981
|
* https://stackoverflow.com/a/2117523
|
|
828
982
|
*/
|
|
@@ -834,6 +988,17 @@ const uuid4 = () => {
|
|
|
834
988
|
});
|
|
835
989
|
};
|
|
836
990
|
|
|
991
|
+
export const isRunningInBrowser = () => {
|
|
992
|
+
return (
|
|
993
|
+
// @ts-ignore
|
|
994
|
+
typeof window !== 'undefined' &&
|
|
995
|
+
// @ts-ignore
|
|
996
|
+
typeof window.document !== 'undefined' &&
|
|
997
|
+
// @ts-ignore
|
|
998
|
+
typeof navigator !== 'undefined'
|
|
999
|
+
);
|
|
1000
|
+
};
|
|
1001
|
+
|
|
837
1002
|
export interface HeadersProtocol {
|
|
838
1003
|
get: (header: string) => string | null | undefined;
|
|
839
1004
|
}
|
package/src/index.ts
CHANGED
|
@@ -72,7 +72,7 @@ export interface ClientOptions {
|
|
|
72
72
|
clientSecret?: string | null;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
/**
|
|
75
|
+
/** API Client for interfacing with the Finch API. */
|
|
76
76
|
export class Finch extends Core.APIClient {
|
|
77
77
|
accessToken: string | null;
|
|
78
78
|
clientId?: string | null;
|
|
@@ -80,6 +80,20 @@ export class Finch extends Core.APIClient {
|
|
|
80
80
|
|
|
81
81
|
private _options: ClientOptions;
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* API Client for interfacing with the Finch API.
|
|
85
|
+
*
|
|
86
|
+
* @param {string | null} opts.accessToken - The Access Token to send to the API.
|
|
87
|
+
* @param {string} [opts.baseURL] - Override the default base URL for the API.
|
|
88
|
+
* @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
|
89
|
+
* @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections.
|
|
90
|
+
* @param {Core.Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
|
|
91
|
+
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
|
|
92
|
+
* @param {Core.Headers} opts.defaultHeaders - Default headers to include with every request to the API.
|
|
93
|
+
* @param {Core.DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API.
|
|
94
|
+
* @param {string | null} [opts.clientId]
|
|
95
|
+
* @param {string | null} [opts.clientSecret]
|
|
96
|
+
*/
|
|
83
97
|
constructor({
|
|
84
98
|
accessToken = null,
|
|
85
99
|
clientId = Core.readEnv('FINCH_CLIENT_ID') ?? null,
|
|
@@ -98,7 +112,7 @@ export class Finch extends Core.APIClient {
|
|
|
98
112
|
|
|
99
113
|
super({
|
|
100
114
|
baseURL: options.baseURL!,
|
|
101
|
-
timeout: options.timeout
|
|
115
|
+
timeout: options.timeout ?? 60000 /* 1 minute */,
|
|
102
116
|
httpAgent: options.httpAgent,
|
|
103
117
|
maxRetries: options.maxRetries,
|
|
104
118
|
fetch: options.fetch,
|
package/src/pagination.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless.
|
|
2
2
|
|
|
3
|
-
import { AbstractPage,
|
|
3
|
+
import { AbstractPage, Response, APIClient, FinalRequestOptions, PageInfo } from './core';
|
|
4
4
|
import * as HRIS from './resources/hris/index';
|
|
5
5
|
import * as ATS from './resources/ats/index';
|
|
6
6
|
|
|
@@ -11,12 +11,13 @@ export class SinglePage<Item> extends AbstractPage<Item> {
|
|
|
11
11
|
|
|
12
12
|
constructor(
|
|
13
13
|
client: APIClient,
|
|
14
|
-
response:
|
|
14
|
+
response: Response,
|
|
15
|
+
body: SinglePageResponse<Item>,
|
|
15
16
|
options: FinalRequestOptions,
|
|
16
17
|
) {
|
|
17
|
-
super(client, response, options);
|
|
18
|
+
super(client, response, body, options);
|
|
18
19
|
|
|
19
|
-
this.items =
|
|
20
|
+
this.items = body || [];
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
getPaginatedItems(): Item[] {
|
|
@@ -46,12 +47,13 @@ export class ResponsesPage<Item> extends AbstractPage<Item> implements Responses
|
|
|
46
47
|
|
|
47
48
|
constructor(
|
|
48
49
|
client: APIClient,
|
|
49
|
-
response:
|
|
50
|
+
response: Response,
|
|
51
|
+
body: ResponsesPageResponse<Item>,
|
|
50
52
|
options: FinalRequestOptions,
|
|
51
53
|
) {
|
|
52
|
-
super(client, response, options);
|
|
54
|
+
super(client, response, body, options);
|
|
53
55
|
|
|
54
|
-
this.responses =
|
|
56
|
+
this.responses = body.responses;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
getPaginatedItems(): Item[] {
|
|
@@ -106,13 +108,14 @@ export class IndividualsPage
|
|
|
106
108
|
|
|
107
109
|
constructor(
|
|
108
110
|
client: APIClient,
|
|
109
|
-
response:
|
|
111
|
+
response: Response,
|
|
112
|
+
body: IndividualsPageResponse,
|
|
110
113
|
options: FinalRequestOptions,
|
|
111
114
|
) {
|
|
112
|
-
super(client, response, options);
|
|
115
|
+
super(client, response, body, options);
|
|
113
116
|
|
|
114
|
-
this.paging =
|
|
115
|
-
this.individuals =
|
|
117
|
+
this.paging = body.paging;
|
|
118
|
+
this.individuals = body.individuals;
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
getPaginatedItems(): HRIS.IndividualInDirectory[] {
|
|
@@ -172,13 +175,14 @@ export class CandidatesPage extends AbstractPage<ATS.Candidate> implements Candi
|
|
|
172
175
|
|
|
173
176
|
constructor(
|
|
174
177
|
client: APIClient,
|
|
175
|
-
response:
|
|
178
|
+
response: Response,
|
|
179
|
+
body: CandidatesPageResponse,
|
|
176
180
|
options: FinalRequestOptions,
|
|
177
181
|
) {
|
|
178
|
-
super(client, response, options);
|
|
182
|
+
super(client, response, body, options);
|
|
179
183
|
|
|
180
|
-
this.paging =
|
|
181
|
-
this.candidates =
|
|
184
|
+
this.paging = body.paging;
|
|
185
|
+
this.candidates = body.candidates;
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
getPaginatedItems(): ATS.Candidate[] {
|
|
@@ -238,13 +242,14 @@ export class ApplicationsPage extends AbstractPage<ATS.Application> implements A
|
|
|
238
242
|
|
|
239
243
|
constructor(
|
|
240
244
|
client: APIClient,
|
|
241
|
-
response:
|
|
245
|
+
response: Response,
|
|
246
|
+
body: ApplicationsPageResponse,
|
|
242
247
|
options: FinalRequestOptions,
|
|
243
248
|
) {
|
|
244
|
-
super(client, response, options);
|
|
249
|
+
super(client, response, body, options);
|
|
245
250
|
|
|
246
|
-
this.paging =
|
|
247
|
-
this.applications =
|
|
251
|
+
this.paging = body.paging;
|
|
252
|
+
this.applications = body.applications;
|
|
248
253
|
}
|
|
249
254
|
|
|
250
255
|
getPaginatedItems(): ATS.Application[] {
|
|
@@ -302,11 +307,11 @@ export class JobsPage extends AbstractPage<ATS.Job> implements JobsPageResponse
|
|
|
302
307
|
|
|
303
308
|
jobs: Array<ATS.Job>;
|
|
304
309
|
|
|
305
|
-
constructor(client: APIClient, response:
|
|
306
|
-
super(client, response, options);
|
|
310
|
+
constructor(client: APIClient, response: Response, body: JobsPageResponse, options: FinalRequestOptions) {
|
|
311
|
+
super(client, response, body, options);
|
|
307
312
|
|
|
308
|
-
this.paging =
|
|
309
|
-
this.jobs =
|
|
313
|
+
this.paging = body.paging;
|
|
314
|
+
this.jobs = body.jobs;
|
|
310
315
|
}
|
|
311
316
|
|
|
312
317
|
getPaginatedItems(): ATS.Job[] {
|
|
@@ -364,11 +369,11 @@ export class OffersPage extends AbstractPage<ATS.Offer> implements OffersPageRes
|
|
|
364
369
|
|
|
365
370
|
offers: Array<ATS.Offer>;
|
|
366
371
|
|
|
367
|
-
constructor(client: APIClient, response:
|
|
368
|
-
super(client, response, options);
|
|
372
|
+
constructor(client: APIClient, response: Response, body: OffersPageResponse, options: FinalRequestOptions) {
|
|
373
|
+
super(client, response, body, options);
|
|
369
374
|
|
|
370
|
-
this.paging =
|
|
371
|
-
this.offers =
|
|
375
|
+
this.paging = body.paging;
|
|
376
|
+
this.offers = body.offers;
|
|
372
377
|
}
|
|
373
378
|
|
|
374
379
|
getPaginatedItems(): ATS.Offer[] {
|
package/src/resources/account.ts
CHANGED
|
@@ -10,14 +10,14 @@ export class Account extends APIResource {
|
|
|
10
10
|
* associated with the employer. We require applications to implement the
|
|
11
11
|
* Disconnect endpoint for billing and security purposes.
|
|
12
12
|
*/
|
|
13
|
-
disconnect(options?: Core.RequestOptions):
|
|
13
|
+
disconnect(options?: Core.RequestOptions): Core.APIPromise<DisconnectResponse> {
|
|
14
14
|
return this.post('/disconnect', options);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Read account information associated with an `access_token`
|
|
19
19
|
*/
|
|
20
|
-
introspect(options?: Core.RequestOptions):
|
|
20
|
+
introspect(options?: Core.RequestOptions): Core.APIPromise<Introspection> {
|
|
21
21
|
return this.get('/introspect', options);
|
|
22
22
|
}
|
|
23
23
|
}
|