@tryfinch/finch-api 5.0.0 → 5.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 +29 -0
- package/README.md +33 -0
- package/_shims/{ReadableStream.node.d.ts → ReadableStream-node.d.ts} +1 -1
- package/_shims/ReadableStream-node.d.ts.map +1 -0
- package/_shims/{ReadableStream.node.js → ReadableStream-node.js} +1 -1
- package/_shims/ReadableStream-node.js.map +1 -0
- package/_shims/{ReadableStream.node.mjs → ReadableStream-node.mjs} +1 -1
- package/_shims/ReadableStream-node.mjs.map +1 -0
- package/_shims/{agent.node.d.ts → agent-node.d.ts} +1 -1
- package/_shims/agent-node.d.ts.map +1 -0
- package/_shims/{agent.node.js → agent-node.js} +1 -1
- package/_shims/{agent.node.js.map → agent-node.js.map} +1 -1
- package/_shims/{agent.node.mjs → agent-node.mjs} +1 -1
- package/_shims/{agent.node.mjs.map → agent-node.mjs.map} +1 -1
- package/_shims/agent.d.ts +1 -1
- package/_shims/agent.js +1 -1
- package/_shims/agent.mjs +1 -1
- package/_shims/{fileFromPath.node.d.ts → fileFromPath-node.d.ts} +2 -2
- package/_shims/{fileFromPath.node.d.ts.map → fileFromPath-node.d.ts.map} +1 -1
- package/_shims/{fileFromPath.node.js → fileFromPath-node.js} +1 -1
- package/_shims/{fileFromPath.node.js.map → fileFromPath-node.js.map} +1 -1
- package/_shims/{fileFromPath.node.mjs → fileFromPath-node.mjs} +1 -1
- package/_shims/{fileFromPath.node.mjs.map → fileFromPath-node.mjs.map} +1 -1
- package/_shims/fileFromPath.d.ts +2 -2
- package/_shims/fileFromPath.d.ts.map +1 -1
- package/_shims/fileFromPath.js +1 -1
- package/_shims/fileFromPath.mjs +1 -1
- package/_shims/{getMultipartRequestOptions.node.d.ts → getMultipartRequestOptions-node.d.ts} +2 -2
- package/_shims/getMultipartRequestOptions-node.d.ts.map +1 -0
- package/_shims/{getMultipartRequestOptions.node.js → getMultipartRequestOptions-node.js} +1 -1
- package/_shims/{getMultipartRequestOptions.node.js.map → getMultipartRequestOptions-node.js.map} +1 -1
- package/_shims/{getMultipartRequestOptions.node.mjs → getMultipartRequestOptions-node.mjs} +1 -1
- package/_shims/{getMultipartRequestOptions.node.mjs.map → getMultipartRequestOptions-node.mjs.map} +1 -1
- package/_shims/getMultipartRequestOptions.d.ts +1 -1
- package/_shims/getMultipartRequestOptions.d.ts.map +1 -1
- package/_shims/{node-readable.node.d.ts → node-readable-node.d.ts} +1 -1
- package/_shims/{node-readable.node.d.ts.map → node-readable-node.d.ts.map} +1 -1
- package/_shims/{node-readable.node.js → node-readable-node.js} +1 -1
- package/_shims/node-readable-node.js.map +1 -0
- package/_shims/{node-readable.node.mjs → node-readable-node.mjs} +1 -1
- package/_shims/node-readable-node.mjs.map +1 -0
- package/core.d.ts +2 -1
- package/core.d.ts.map +1 -1
- package/core.js +3 -1
- package/core.js.map +1 -1
- package/core.mjs +1 -1
- package/core.mjs.map +1 -1
- package/error.d.ts +1 -1
- package/error.d.ts.map +1 -1
- package/error.js +2 -2
- package/error.js.map +1 -1
- package/error.mjs +2 -2
- package/error.mjs.map +1 -1
- package/index.d.mts +6 -1
- package/index.d.ts +6 -1
- package/index.d.ts.map +1 -1
- package/index.js +9 -3
- package/index.js.map +1 -1
- package/index.mjs +9 -3
- package/index.mjs.map +1 -1
- package/package.json +9 -4
- package/resources/index.d.ts +1 -0
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js +14 -1
- package/resources/index.js.map +1 -1
- package/resources/index.mjs +1 -0
- package/resources/index.mjs.map +1 -1
- package/resources/webhooks.d.ts +22 -0
- package/resources/webhooks.d.ts.map +1 -0
- package/resources/webhooks.js +118 -0
- package/resources/webhooks.js.map +1 -0
- package/resources/webhooks.mjs +114 -0
- package/resources/webhooks.mjs.map +1 -0
- package/src/_shims/ReadableStream.d.ts +5 -5
- package/src/_shims/agent.ts +1 -1
- package/src/_shims/{fetch.node.d.ts → fetch-node.d.ts} +8 -8
- package/src/_shims/fetch.d.ts +10 -10
- package/src/_shims/{fileFromPath.node.ts → fileFromPath-node.ts} +1 -1
- package/src/_shims/fileFromPath.ts +2 -2
- package/src/_shims/{formdata.node.d.ts → form-data-node.d.ts} +4 -4
- package/src/_shims/{formdata.d.ts → form-data.d.ts} +4 -4
- package/src/_shims/{getMultipartRequestOptions.node.ts → getMultipartRequestOptions-node.ts} +3 -3
- package/src/_shims/getMultipartRequestOptions.ts +3 -3
- package/src/core.ts +11 -10
- package/src/error.ts +3 -3
- package/src/index.ts +17 -7
- package/src/pagination.ts +3 -3
- package/src/resource.ts +1 -1
- package/src/resources/account.ts +3 -3
- package/src/resources/ats/applications.ts +6 -6
- package/src/resources/ats/ats.ts +7 -7
- package/src/resources/ats/candidates.ts +5 -5
- package/src/resources/ats/index.ts +6 -6
- package/src/resources/ats/jobs.ts +5 -5
- package/src/resources/ats/offers.ts +5 -5
- package/src/resources/ats/stages.ts +4 -4
- package/src/resources/hris/benefits/benefits.ts +6 -6
- package/src/resources/hris/benefits/index.ts +2 -2
- package/src/resources/hris/benefits/individuals.ts +6 -6
- package/src/resources/hris/company.ts +4 -4
- package/src/resources/hris/directory.ts +5 -5
- package/src/resources/hris/employments.ts +5 -5
- package/src/resources/hris/hris.ts +9 -9
- package/src/resources/hris/index.ts +8 -8
- package/src/resources/hris/individuals.ts +6 -6
- package/src/resources/hris/pay-statements.ts +6 -6
- package/src/resources/hris/payments.ts +5 -5
- package/src/resources/index.ts +6 -5
- package/src/resources/providers.ts +4 -4
- package/src/resources/webhooks.ts +151 -0
- package/src/tsconfig.json +11 -0
- package/src/uploads.ts +6 -6
- package/src/version.ts +1 -1
- package/uploads.d.ts +1 -1
- package/uploads.d.ts.map +1 -1
- package/uploads.js +4 -4
- package/uploads.js.map +1 -1
- package/uploads.mjs +1 -1
- package/uploads.mjs.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
- package/_shims/ReadableStream.node.d.ts.map +0 -1
- package/_shims/ReadableStream.node.js.map +0 -1
- package/_shims/ReadableStream.node.mjs.map +0 -1
- package/_shims/agent.node.d.ts.map +0 -1
- package/_shims/getMultipartRequestOptions.node.d.ts.map +0 -1
- package/_shims/node-readable.node.js.map +0 -1
- package/_shims/node-readable.node.mjs.map +0 -1
- package/src/_shims/fetch.deno.ts +0 -23
- package/src/_shims/formdata.deno.ts +0 -16
- /package/_shims/{fetch.node.d.ts → fetch-node.d.ts} +0 -0
- /package/_shims/{fetch.node.js → fetch-node.js} +0 -0
- /package/_shims/{fetch.node.mjs → fetch-node.mjs} +0 -0
- /package/_shims/{formdata.node.d.ts → form-data-node.d.ts} +0 -0
- /package/_shims/{formdata.node.js → form-data-node.js} +0 -0
- /package/_shims/{formdata.node.mjs → form-data-node.mjs} +0 -0
- /package/_shims/{formdata.d.ts → form-data.d.ts} +0 -0
- /package/_shims/{formdata.js → form-data.js} +0 -0
- /package/_shims/{formdata.mjs → form-data.mjs} +0 -0
- /package/src/_shims/{ReadableStream.node.ts → ReadableStream-node.ts} +0 -0
- /package/src/_shims/{agent.node.ts → agent-node.ts} +0 -0
- /package/src/_shims/{fetch.node.js → fetch-node.js} +0 -0
- /package/src/_shims/{fetch.node.mjs → fetch-node.mjs} +0 -0
- /package/src/_shims/{formdata.node.js → form-data-node.js} +0 -0
- /package/src/_shims/{formdata.node.mjs → form-data-node.mjs} +0 -0
- /package/src/_shims/{formdata.js → form-data.js} +0 -0
- /package/src/_shims/{formdata.mjs → form-data.mjs} +0 -0
- /package/src/_shims/{node-readable.node.ts → node-readable-node.ts} +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// File generated from our OpenAPI spec by Stainless.
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
exports.Webhooks = void 0;
|
|
5
|
+
const resource_1 = require('@tryfinch/finch-api/resource');
|
|
6
|
+
const crypto_1 = require('crypto');
|
|
7
|
+
const core_1 = require('@tryfinch/finch-api/core');
|
|
8
|
+
class Webhooks extends resource_1.APIResource {
|
|
9
|
+
/**
|
|
10
|
+
* Validates that the given payload was sent by Finch and parses the payload.
|
|
11
|
+
*/
|
|
12
|
+
unwrap(payload, headers, secret = this.client.webhookSecret) {
|
|
13
|
+
this.verifySignature(payload, headers, secret);
|
|
14
|
+
return JSON.parse(payload);
|
|
15
|
+
}
|
|
16
|
+
parseSecret(secret) {
|
|
17
|
+
if (!secret) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
"The webhook secret must either be set using the env var, FINCH_WEBHOOK_SECRET, on the client class, Finch({ webhook_secret: '123' }), or passed to this function",
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const buf = Buffer.from(secret, 'base64');
|
|
23
|
+
if (buf.toString('base64') !== secret) {
|
|
24
|
+
throw new Error(`Given secret is not valid`);
|
|
25
|
+
}
|
|
26
|
+
return new Uint8Array(buf);
|
|
27
|
+
}
|
|
28
|
+
signPayload(payload, { eventId, timestamp, secret }) {
|
|
29
|
+
const encoder = new TextEncoder();
|
|
30
|
+
const toSign = encoder.encode(`${eventId}.${timestamp.getTime() / 1000}.${payload}`);
|
|
31
|
+
const hmac = (0, crypto_1.createHmac)('sha256', secret);
|
|
32
|
+
hmac.update(toSign);
|
|
33
|
+
return `v1,${hmac.digest('base64')}`;
|
|
34
|
+
}
|
|
35
|
+
/** Make an assertion, if not `true`, then throw. */
|
|
36
|
+
assert(expr, msg = '') {
|
|
37
|
+
if (!expr) {
|
|
38
|
+
throw new Error(msg);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Compare to array buffers or data views in a way that timing based attacks
|
|
42
|
+
* cannot gain information about the platform. */
|
|
43
|
+
timingSafeEqual(a, b) {
|
|
44
|
+
if (a.byteLength !== b.byteLength) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (!(a instanceof DataView)) {
|
|
48
|
+
a = new DataView(ArrayBuffer.isView(a) ? a.buffer : a);
|
|
49
|
+
}
|
|
50
|
+
if (!(b instanceof DataView)) {
|
|
51
|
+
b = new DataView(ArrayBuffer.isView(b) ? b.buffer : b);
|
|
52
|
+
}
|
|
53
|
+
this.assert(a instanceof DataView);
|
|
54
|
+
this.assert(b instanceof DataView);
|
|
55
|
+
const length = a.byteLength;
|
|
56
|
+
let out = 0;
|
|
57
|
+
let i = -1;
|
|
58
|
+
while (++i < length) {
|
|
59
|
+
out |= a.getUint8(i) ^ b.getUint8(i);
|
|
60
|
+
}
|
|
61
|
+
return out === 0;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validates whether or not the webhook payload was sent by Finch.
|
|
65
|
+
*
|
|
66
|
+
* An error will be raised if the webhook payload was not sent by Finch.
|
|
67
|
+
*/
|
|
68
|
+
verifySignature(body, headers, secret = this.client.webhookSecret) {
|
|
69
|
+
const parsedSecret = this.parseSecret(secret);
|
|
70
|
+
const eventId = (0, core_1.getHeader)(headers, 'finch-event-id');
|
|
71
|
+
if (!eventId) {
|
|
72
|
+
throw new Error('Could not find finch-event-id header');
|
|
73
|
+
}
|
|
74
|
+
const msgTimestamp = (0, core_1.getHeader)(headers, 'finch-timestamp');
|
|
75
|
+
if (!msgTimestamp) {
|
|
76
|
+
throw new Error('Could not find finch-timestamp header');
|
|
77
|
+
}
|
|
78
|
+
const msgSignature = (0, core_1.getHeader)(headers, 'finch-signature');
|
|
79
|
+
if (!msgSignature) {
|
|
80
|
+
throw new Error('Could not find finch-signature header');
|
|
81
|
+
}
|
|
82
|
+
const now = Math.floor(Date.now() / 1000);
|
|
83
|
+
const timestampSeconds = parseInt(msgTimestamp, 10);
|
|
84
|
+
if (isNaN(timestampSeconds)) {
|
|
85
|
+
throw new Error(`Invalid timestamp header: ${msgTimestamp}`);
|
|
86
|
+
}
|
|
87
|
+
if (typeof body !== 'string') {
|
|
88
|
+
throw new Error(
|
|
89
|
+
'Webhook body must be passed as the raw JSON string sent from the server (do not parse it first).',
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
const webhook_tolerance_in_seconds = 5 * 60; // 5 minutes
|
|
93
|
+
if (now - timestampSeconds > webhook_tolerance_in_seconds) {
|
|
94
|
+
throw new Error('Webhook timestamp is too old');
|
|
95
|
+
}
|
|
96
|
+
if (timestampSeconds > now + webhook_tolerance_in_seconds) {
|
|
97
|
+
throw new Error('Webhook timestamp is too new');
|
|
98
|
+
}
|
|
99
|
+
const timestamp = new Date(timestampSeconds * 1000);
|
|
100
|
+
const computedSignature = this.signPayload(body, { eventId, timestamp, secret: parsedSecret });
|
|
101
|
+
const expectedSignature = computedSignature.split(',')[1];
|
|
102
|
+
const passedSignatures = msgSignature.split(' ');
|
|
103
|
+
const encoder = new globalThis.TextEncoder();
|
|
104
|
+
for (const versionedSignature of passedSignatures) {
|
|
105
|
+
const [version, signature] = versionedSignature.split(',');
|
|
106
|
+
if (version !== 'v1') {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (this.timingSafeEqual(encoder.encode(signature), encoder.encode(expectedSignature))) {
|
|
110
|
+
// valid!
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
throw new Error('None of the given webhook signatures match the expected signature');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.Webhooks = Webhooks;
|
|
118
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/resources/webhooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// File generated from our OpenAPI spec by Stainless.
|
|
2
|
+
import { APIResource } from '@tryfinch/finch-api/resource';
|
|
3
|
+
import { createHmac } from 'crypto';
|
|
4
|
+
import { getHeader } from '@tryfinch/finch-api/core';
|
|
5
|
+
export class Webhooks extends APIResource {
|
|
6
|
+
/**
|
|
7
|
+
* Validates that the given payload was sent by Finch and parses the payload.
|
|
8
|
+
*/
|
|
9
|
+
unwrap(payload, headers, secret = this.client.webhookSecret) {
|
|
10
|
+
this.verifySignature(payload, headers, secret);
|
|
11
|
+
return JSON.parse(payload);
|
|
12
|
+
}
|
|
13
|
+
parseSecret(secret) {
|
|
14
|
+
if (!secret) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
"The webhook secret must either be set using the env var, FINCH_WEBHOOK_SECRET, on the client class, Finch({ webhook_secret: '123' }), or passed to this function",
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
const buf = Buffer.from(secret, 'base64');
|
|
20
|
+
if (buf.toString('base64') !== secret) {
|
|
21
|
+
throw new Error(`Given secret is not valid`);
|
|
22
|
+
}
|
|
23
|
+
return new Uint8Array(buf);
|
|
24
|
+
}
|
|
25
|
+
signPayload(payload, { eventId, timestamp, secret }) {
|
|
26
|
+
const encoder = new TextEncoder();
|
|
27
|
+
const toSign = encoder.encode(`${eventId}.${timestamp.getTime() / 1000}.${payload}`);
|
|
28
|
+
const hmac = createHmac('sha256', secret);
|
|
29
|
+
hmac.update(toSign);
|
|
30
|
+
return `v1,${hmac.digest('base64')}`;
|
|
31
|
+
}
|
|
32
|
+
/** Make an assertion, if not `true`, then throw. */
|
|
33
|
+
assert(expr, msg = '') {
|
|
34
|
+
if (!expr) {
|
|
35
|
+
throw new Error(msg);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Compare to array buffers or data views in a way that timing based attacks
|
|
39
|
+
* cannot gain information about the platform. */
|
|
40
|
+
timingSafeEqual(a, b) {
|
|
41
|
+
if (a.byteLength !== b.byteLength) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (!(a instanceof DataView)) {
|
|
45
|
+
a = new DataView(ArrayBuffer.isView(a) ? a.buffer : a);
|
|
46
|
+
}
|
|
47
|
+
if (!(b instanceof DataView)) {
|
|
48
|
+
b = new DataView(ArrayBuffer.isView(b) ? b.buffer : b);
|
|
49
|
+
}
|
|
50
|
+
this.assert(a instanceof DataView);
|
|
51
|
+
this.assert(b instanceof DataView);
|
|
52
|
+
const length = a.byteLength;
|
|
53
|
+
let out = 0;
|
|
54
|
+
let i = -1;
|
|
55
|
+
while (++i < length) {
|
|
56
|
+
out |= a.getUint8(i) ^ b.getUint8(i);
|
|
57
|
+
}
|
|
58
|
+
return out === 0;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validates whether or not the webhook payload was sent by Finch.
|
|
62
|
+
*
|
|
63
|
+
* An error will be raised if the webhook payload was not sent by Finch.
|
|
64
|
+
*/
|
|
65
|
+
verifySignature(body, headers, secret = this.client.webhookSecret) {
|
|
66
|
+
const parsedSecret = this.parseSecret(secret);
|
|
67
|
+
const eventId = getHeader(headers, 'finch-event-id');
|
|
68
|
+
if (!eventId) {
|
|
69
|
+
throw new Error('Could not find finch-event-id header');
|
|
70
|
+
}
|
|
71
|
+
const msgTimestamp = getHeader(headers, 'finch-timestamp');
|
|
72
|
+
if (!msgTimestamp) {
|
|
73
|
+
throw new Error('Could not find finch-timestamp header');
|
|
74
|
+
}
|
|
75
|
+
const msgSignature = getHeader(headers, 'finch-signature');
|
|
76
|
+
if (!msgSignature) {
|
|
77
|
+
throw new Error('Could not find finch-signature header');
|
|
78
|
+
}
|
|
79
|
+
const now = Math.floor(Date.now() / 1000);
|
|
80
|
+
const timestampSeconds = parseInt(msgTimestamp, 10);
|
|
81
|
+
if (isNaN(timestampSeconds)) {
|
|
82
|
+
throw new Error(`Invalid timestamp header: ${msgTimestamp}`);
|
|
83
|
+
}
|
|
84
|
+
if (typeof body !== 'string') {
|
|
85
|
+
throw new Error(
|
|
86
|
+
'Webhook body must be passed as the raw JSON string sent from the server (do not parse it first).',
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
const webhook_tolerance_in_seconds = 5 * 60; // 5 minutes
|
|
90
|
+
if (now - timestampSeconds > webhook_tolerance_in_seconds) {
|
|
91
|
+
throw new Error('Webhook timestamp is too old');
|
|
92
|
+
}
|
|
93
|
+
if (timestampSeconds > now + webhook_tolerance_in_seconds) {
|
|
94
|
+
throw new Error('Webhook timestamp is too new');
|
|
95
|
+
}
|
|
96
|
+
const timestamp = new Date(timestampSeconds * 1000);
|
|
97
|
+
const computedSignature = this.signPayload(body, { eventId, timestamp, secret: parsedSecret });
|
|
98
|
+
const expectedSignature = computedSignature.split(',')[1];
|
|
99
|
+
const passedSignatures = msgSignature.split(' ');
|
|
100
|
+
const encoder = new globalThis.TextEncoder();
|
|
101
|
+
for (const versionedSignature of passedSignatures) {
|
|
102
|
+
const [version, signature] = versionedSignature.split(',');
|
|
103
|
+
if (version !== 'v1') {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (this.timingSafeEqual(encoder.encode(signature), encoder.encode(expectedSignature))) {
|
|
107
|
+
// valid!
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
throw new Error('None of the given webhook signatures match the expected signature');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=webhooks.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.mjs","sourceRoot":"","sources":["../src/resources/webhooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
// @ts-ignore
|
|
14
|
-
type _ReadableStream<R = any> =
|
|
14
|
+
type _ReadableStream<R = any> = ReadableStream<R>;
|
|
15
15
|
declare const _ReadableStream: {
|
|
16
16
|
prototype: _ReadableStream;
|
|
17
17
|
new (
|
|
@@ -26,13 +26,13 @@ declare const _ReadableStream: {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
// @ts-ignore
|
|
29
|
-
type _UnderlyingSource<R = any> =
|
|
29
|
+
type _UnderlyingSource<R = any> = UnderlyingSource<R>;
|
|
30
30
|
// @ts-ignore
|
|
31
|
-
type _UnderlyingByteSource =
|
|
31
|
+
type _UnderlyingByteSource = UnderlyingByteSource;
|
|
32
32
|
type _UnderlyingDefaultSource<R = any> =
|
|
33
33
|
// @ts-ignore
|
|
34
|
-
|
|
34
|
+
UnderlyingDefaultSource<R>;
|
|
35
35
|
// @ts-ignore
|
|
36
|
-
type _QueuingStrategy<R = any> =
|
|
36
|
+
type _QueuingStrategy<R = any> = QueuingStrategy<R>;
|
|
37
37
|
|
|
38
38
|
export { _ReadableStream as ReadableStream };
|
package/src/_shims/agent.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
3
3
|
*
|
|
4
4
|
* This is a stub for non-node environments.
|
|
5
|
-
* In node environments, it gets replaced agent
|
|
5
|
+
* In node environments, it gets replaced agent-node.ts by the package export map
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
export type Agent = any;
|
|
@@ -17,26 +17,26 @@ import * as nf from 'node-fetch';
|
|
|
17
17
|
// @ts-ignore
|
|
18
18
|
type _fetch = unknown extends typeof fetch ? typeof nf.default : typeof fetch;
|
|
19
19
|
// @ts-ignore
|
|
20
|
-
type _Request =
|
|
20
|
+
type _Request = Request;
|
|
21
21
|
// @ts-ignore
|
|
22
|
-
type _RequestInfo =
|
|
22
|
+
type _RequestInfo = RequestInfo;
|
|
23
23
|
// @ts-ignore
|
|
24
|
-
type _RequestInit =
|
|
24
|
+
type _RequestInit = RequestInit;
|
|
25
25
|
// @ts-ignore
|
|
26
|
-
type _Response =
|
|
26
|
+
type _Response = Response;
|
|
27
27
|
// @ts-ignore
|
|
28
|
-
type _ResponseInit =
|
|
28
|
+
type _ResponseInit = ResponseInit;
|
|
29
29
|
type _ResponseType =
|
|
30
30
|
// @ts-ignore
|
|
31
31
|
unknown extends ResponseType ? 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect'
|
|
32
32
|
: // @ts-ignore
|
|
33
33
|
ResponseType;
|
|
34
34
|
// @ts-ignore
|
|
35
|
-
type _BodyInit =
|
|
35
|
+
type _BodyInit = BodyInit;
|
|
36
36
|
// @ts-ignore
|
|
37
|
-
type _Headers =
|
|
37
|
+
type _Headers = Headers;
|
|
38
38
|
// @ts-ignore
|
|
39
|
-
type _HeadersInit =
|
|
39
|
+
type _HeadersInit = HeadersInit;
|
|
40
40
|
|
|
41
41
|
declare const _fetch: _fetch;
|
|
42
42
|
declare const _Request: {
|
package/src/_shims/fetch.d.ts
CHANGED
|
@@ -14,25 +14,25 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
// @ts-ignore
|
|
17
|
-
type _fetch =
|
|
17
|
+
type _fetch = typeof fetch;
|
|
18
18
|
// @ts-ignore
|
|
19
|
-
type _Request =
|
|
19
|
+
type _Request = Request;
|
|
20
20
|
// @ts-ignore
|
|
21
|
-
type _RequestInfo =
|
|
21
|
+
type _RequestInfo = RequestInfo;
|
|
22
22
|
// @ts-ignore
|
|
23
|
-
type _RequestInit =
|
|
23
|
+
type _RequestInit = RequestInit;
|
|
24
24
|
// @ts-ignore
|
|
25
|
-
type _Response =
|
|
25
|
+
type _Response = Response;
|
|
26
26
|
// @ts-ignore
|
|
27
|
-
type _ResponseInit =
|
|
27
|
+
type _ResponseInit = ResponseInit;
|
|
28
28
|
// @ts-ignore
|
|
29
|
-
type _ResponseType =
|
|
29
|
+
type _ResponseType = ResponseType;
|
|
30
30
|
// @ts-ignore
|
|
31
|
-
type _BodyInit =
|
|
31
|
+
type _BodyInit = BodyInit;
|
|
32
32
|
// @ts-ignore
|
|
33
|
-
type _Headers =
|
|
33
|
+
type _Headers = Headers;
|
|
34
34
|
// @ts-ignore
|
|
35
|
-
type _HeadersInit =
|
|
35
|
+
type _HeadersInit = HeadersInit;
|
|
36
36
|
|
|
37
37
|
declare const _fetch: _fetch;
|
|
38
38
|
declare const _Request: {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { fileFromPath as _fileFromPath } from 'formdata-node/file-from-path';
|
|
6
|
-
import type { File, FilePropertyBag } from './
|
|
6
|
+
import type { File, FilePropertyBag } from './form-data-node.js';
|
|
7
7
|
|
|
8
8
|
export type FileFromPathOptions = Omit<FilePropertyBag, 'lastModified'>;
|
|
9
9
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
3
3
|
*
|
|
4
|
-
* This is a stub that gets replaced by fileFromPath
|
|
4
|
+
* This is a stub that gets replaced by fileFromPath-node.js for node environments
|
|
5
5
|
* in the package export map
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { FilePropertyBag, File } from './
|
|
8
|
+
import type { FilePropertyBag, File } from './form-data.js';
|
|
9
9
|
|
|
10
10
|
export type FileFromPathOptions = Omit<FilePropertyBag, 'lastModified'>;
|
|
11
11
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import * as fd from 'formdata-node';
|
|
6
6
|
|
|
7
|
-
import type { BlobPart } from '../uploads';
|
|
7
|
+
import type { BlobPart } from '../uploads.js';
|
|
8
8
|
|
|
9
9
|
type EndingType = 'native' | 'transparent';
|
|
10
10
|
|
|
@@ -21,11 +21,11 @@ export interface FilePropertyBag extends BlobPropertyBag {
|
|
|
21
21
|
// Use builtin web types if present; else formdata-node types
|
|
22
22
|
|
|
23
23
|
// @ts-ignore
|
|
24
|
-
type _FormData =
|
|
24
|
+
type _FormData = FormData;
|
|
25
25
|
// @ts-ignore
|
|
26
|
-
type _File =
|
|
26
|
+
type _File = File;
|
|
27
27
|
// @ts-ignore
|
|
28
|
-
type _Blob =
|
|
28
|
+
type _Blob = Blob;
|
|
29
29
|
|
|
30
30
|
declare const _FormData: {
|
|
31
31
|
new (form?: any): _FormData;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { BlobPart } from '../uploads';
|
|
5
|
+
import type { BlobPart } from '../uploads.js';
|
|
6
6
|
|
|
7
7
|
type EndingType = 'native' | 'transparent';
|
|
8
8
|
|
|
@@ -19,11 +19,11 @@ export interface FilePropertyBag extends BlobPropertyBag {
|
|
|
19
19
|
// add appropriate lib or types to tsconfig)
|
|
20
20
|
|
|
21
21
|
// @ts-ignore
|
|
22
|
-
type _FormData =
|
|
22
|
+
type _FormData = FormData;
|
|
23
23
|
// @ts-ignore
|
|
24
|
-
type _File =
|
|
24
|
+
type _File = File;
|
|
25
25
|
// @ts-ignore
|
|
26
|
-
type _Blob =
|
|
26
|
+
type _Blob = Blob;
|
|
27
27
|
|
|
28
28
|
declare const _FormData: {
|
|
29
29
|
new (form?: any): _FormData;
|
package/src/_shims/{getMultipartRequestOptions.node.ts → getMultipartRequestOptions-node.ts}
RENAMED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { FormData } from './
|
|
6
|
-
import type { RequestOptions } from '../core';
|
|
5
|
+
import { FormData } from './form-data-node.js';
|
|
6
|
+
import type { RequestOptions } from '../core.js';
|
|
7
7
|
import { Readable } from 'node:stream';
|
|
8
8
|
import { FormDataEncoder } from 'form-data-encoder';
|
|
9
|
-
import { MultipartBody } from '../uploads';
|
|
9
|
+
import { MultipartBody } from '../uploads.js';
|
|
10
10
|
|
|
11
11
|
export async function getMultipartRequestOptions<T extends {} = Record<string, unknown>>(
|
|
12
12
|
form: FormData,
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { FormData } from './
|
|
6
|
-
import type { RequestOptions } from '../core';
|
|
7
|
-
import { MultipartBody } from '../uploads';
|
|
5
|
+
import { FormData } from './form-data.js';
|
|
6
|
+
import type { RequestOptions } from '../core.js';
|
|
7
|
+
import { MultipartBody } from '../uploads.js';
|
|
8
8
|
|
|
9
9
|
export async function getMultipartRequestOptions<T extends {} = Record<string, unknown>>(
|
|
10
10
|
form: FormData,
|
package/src/core.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { VERSION } from './version';
|
|
2
|
-
import { APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError } from './error';
|
|
3
|
-
import type { Readable } from './_shims/node-readable';
|
|
4
|
-
import { getDefaultAgent, type Agent } from './_shims/agent';
|
|
1
|
+
import { VERSION } from './version.js';
|
|
2
|
+
import { APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError } from './error.js';
|
|
3
|
+
import type { Readable } from './_shims/node-readable.js';
|
|
4
|
+
import { getDefaultAgent, type Agent } from './_shims/agent.js';
|
|
5
5
|
import {
|
|
6
6
|
fetch,
|
|
7
7
|
isPolyfilled as fetchIsPolyfilled,
|
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
type HeadersInit,
|
|
12
12
|
} from './_shims/fetch.js';
|
|
13
13
|
export { type Response };
|
|
14
|
-
import { isMultipartBody } from './uploads';
|
|
14
|
+
import { isMultipartBody } from './uploads.js';
|
|
15
15
|
export {
|
|
16
16
|
maybeMultipartFormRequestOptions,
|
|
17
17
|
multipartFormRequestOptions,
|
|
18
18
|
createForm,
|
|
19
19
|
type Uploadable,
|
|
20
|
-
} from './uploads';
|
|
20
|
+
} from './uploads.js';
|
|
21
21
|
|
|
22
22
|
const MAX_RETRIES = 2;
|
|
23
23
|
|
|
@@ -45,7 +45,7 @@ async function defaultParseResponse<T>(props: APIResponseProps): Promise<T> {
|
|
|
45
45
|
// TODO handle blob, arraybuffer, other content types, etc.
|
|
46
46
|
const text = await response.text();
|
|
47
47
|
debug('response', response.status, response.url, response.headers, text);
|
|
48
|
-
return text as T;
|
|
48
|
+
return text as any as T;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/**
|
|
@@ -306,7 +306,8 @@ export abstract class APIClient {
|
|
|
306
306
|
protected parseHeaders(headers: HeadersInit | null | undefined): Record<string, string> {
|
|
307
307
|
return (
|
|
308
308
|
!headers ? {}
|
|
309
|
-
: Symbol.iterator in headers ?
|
|
309
|
+
: Symbol.iterator in headers ?
|
|
310
|
+
Object.fromEntries(Array.from(headers as Iterable<string[]>).map((header) => [...header]))
|
|
310
311
|
: { ...headers }
|
|
311
312
|
);
|
|
312
313
|
}
|
|
@@ -390,7 +391,7 @@ export abstract class APIClient {
|
|
|
390
391
|
return new PagePromise<PageClass, Item>(this, request, Page);
|
|
391
392
|
}
|
|
392
393
|
|
|
393
|
-
buildURL<Req
|
|
394
|
+
buildURL<Req extends Record<string, unknown>>(path: string, query: Req | null | undefined): string {
|
|
394
395
|
const url =
|
|
395
396
|
isAbsoluteURL(path) ?
|
|
396
397
|
new URL(path)
|
|
@@ -893,7 +894,7 @@ const isAbsoluteURL = (url: string): boolean => {
|
|
|
893
894
|
return startsWithSchemeRegexp.test(url);
|
|
894
895
|
};
|
|
895
896
|
|
|
896
|
-
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
897
|
+
export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
897
898
|
|
|
898
899
|
const validatePositiveInteger = (name: string, n: unknown): number => {
|
|
899
900
|
if (typeof n !== 'number' || !Number.isInteger(n)) {
|
package/src/error.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless.
|
|
2
2
|
|
|
3
|
-
import { castToError, Headers } from './core';
|
|
3
|
+
import { castToError, Headers } from './core.js';
|
|
4
4
|
|
|
5
5
|
export class APIError extends Error {
|
|
6
6
|
readonly status: number | undefined;
|
|
@@ -97,8 +97,8 @@ export class APIConnectionError extends APIError {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
export class APIConnectionTimeoutError extends APIConnectionError {
|
|
100
|
-
constructor() {
|
|
101
|
-
super({ message: 'Request timed out.' });
|
|
100
|
+
constructor({ message }: { message?: string } = {}) {
|
|
101
|
+
super({ message: message ?? 'Request timed out.' });
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless.
|
|
2
2
|
|
|
3
|
-
import * as Core from './core';
|
|
4
|
-
import * as Pagination from './pagination';
|
|
5
|
-
import * as API from './resources/index';
|
|
6
|
-
import * as Errors from './error';
|
|
7
|
-
import type { Agent } from './_shims/agent';
|
|
8
|
-
import * as Uploads from './uploads';
|
|
3
|
+
import * as Core from './core.js';
|
|
4
|
+
import * as Pagination from './pagination.js';
|
|
5
|
+
import * as API from './resources/index.js';
|
|
6
|
+
import * as Errors from './error.js';
|
|
7
|
+
import type { Agent } from './_shims/agent.js';
|
|
8
|
+
import * as Uploads from './uploads.js';
|
|
9
9
|
|
|
10
10
|
export interface ClientOptions {
|
|
11
11
|
/**
|
|
@@ -70,6 +70,8 @@ export interface ClientOptions {
|
|
|
70
70
|
clientId?: string | null;
|
|
71
71
|
|
|
72
72
|
clientSecret?: string | null;
|
|
73
|
+
|
|
74
|
+
webhookSecret?: string | null;
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
/** API Client for interfacing with the Finch API. */
|
|
@@ -77,6 +79,7 @@ export class Finch extends Core.APIClient {
|
|
|
77
79
|
accessToken: string | null;
|
|
78
80
|
clientId?: string | null;
|
|
79
81
|
clientSecret?: string | null;
|
|
82
|
+
webhookSecret?: string | null;
|
|
80
83
|
|
|
81
84
|
private _options: ClientOptions;
|
|
82
85
|
|
|
@@ -93,19 +96,22 @@ export class Finch extends Core.APIClient {
|
|
|
93
96
|
* @param {Core.DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API.
|
|
94
97
|
* @param {string | null} [opts.clientId]
|
|
95
98
|
* @param {string | null} [opts.clientSecret]
|
|
99
|
+
* @param {string | null} [opts.webhookSecret]
|
|
96
100
|
*/
|
|
97
101
|
constructor({
|
|
98
102
|
accessToken = null,
|
|
99
103
|
clientId = Core.readEnv('FINCH_CLIENT_ID') ?? null,
|
|
100
104
|
clientSecret = Core.readEnv('FINCH_CLIENT_SECRET') ?? null,
|
|
105
|
+
webhookSecret = Core.readEnv('FINCH_WEBHOOK_SECRET') ?? null,
|
|
101
106
|
...opts
|
|
102
107
|
}: ClientOptions = {}) {
|
|
103
108
|
const options: ClientOptions = {
|
|
104
109
|
accessToken,
|
|
105
110
|
clientId,
|
|
106
111
|
clientSecret,
|
|
107
|
-
|
|
112
|
+
webhookSecret,
|
|
108
113
|
...opts,
|
|
114
|
+
baseURL: opts.baseURL ?? `https://api.tryfinch.com`,
|
|
109
115
|
};
|
|
110
116
|
|
|
111
117
|
super({
|
|
@@ -120,12 +126,14 @@ export class Finch extends Core.APIClient {
|
|
|
120
126
|
this.accessToken = accessToken;
|
|
121
127
|
this.clientId = clientId;
|
|
122
128
|
this.clientSecret = clientSecret;
|
|
129
|
+
this.webhookSecret = webhookSecret;
|
|
123
130
|
}
|
|
124
131
|
|
|
125
132
|
hris: API.HRIS = new API.HRIS(this);
|
|
126
133
|
ats: API.ATS = new API.ATS(this);
|
|
127
134
|
providers: API.Providers = new API.Providers(this);
|
|
128
135
|
account: API.Account = new API.Account(this);
|
|
136
|
+
webhooks: API.Webhooks = new API.Webhooks(this);
|
|
129
137
|
|
|
130
138
|
/**
|
|
131
139
|
* Returns an access token for the Finch API given an authorization code. An
|
|
@@ -293,6 +301,8 @@ export namespace Finch {
|
|
|
293
301
|
export import Account = API.Account;
|
|
294
302
|
export import DisconnectResponse = API.DisconnectResponse;
|
|
295
303
|
export import Introspection = API.Introspection;
|
|
304
|
+
|
|
305
|
+
export import Webhooks = API.Webhooks;
|
|
296
306
|
}
|
|
297
307
|
|
|
298
308
|
export default Finch;
|
package/src/pagination.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless.
|
|
2
2
|
|
|
3
|
-
import { AbstractPage, Response, APIClient, FinalRequestOptions, PageInfo } from './core';
|
|
4
|
-
import * as HRIS from './resources/hris/index';
|
|
5
|
-
import * as ATS from './resources/ats/index';
|
|
3
|
+
import { AbstractPage, Response, APIClient, FinalRequestOptions, PageInfo } from './core.js';
|
|
4
|
+
import * as HRIS from './resources/hris/index.js';
|
|
5
|
+
import * as ATS from './resources/ats/index.js';
|
|
6
6
|
|
|
7
7
|
export type SinglePageResponse<Item> = Item[];
|
|
8
8
|
|