@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.
Files changed (149) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +33 -0
  3. package/_shims/{ReadableStream.node.d.ts → ReadableStream-node.d.ts} +1 -1
  4. package/_shims/ReadableStream-node.d.ts.map +1 -0
  5. package/_shims/{ReadableStream.node.js → ReadableStream-node.js} +1 -1
  6. package/_shims/ReadableStream-node.js.map +1 -0
  7. package/_shims/{ReadableStream.node.mjs → ReadableStream-node.mjs} +1 -1
  8. package/_shims/ReadableStream-node.mjs.map +1 -0
  9. package/_shims/{agent.node.d.ts → agent-node.d.ts} +1 -1
  10. package/_shims/agent-node.d.ts.map +1 -0
  11. package/_shims/{agent.node.js → agent-node.js} +1 -1
  12. package/_shims/{agent.node.js.map → agent-node.js.map} +1 -1
  13. package/_shims/{agent.node.mjs → agent-node.mjs} +1 -1
  14. package/_shims/{agent.node.mjs.map → agent-node.mjs.map} +1 -1
  15. package/_shims/agent.d.ts +1 -1
  16. package/_shims/agent.js +1 -1
  17. package/_shims/agent.mjs +1 -1
  18. package/_shims/{fileFromPath.node.d.ts → fileFromPath-node.d.ts} +2 -2
  19. package/_shims/{fileFromPath.node.d.ts.map → fileFromPath-node.d.ts.map} +1 -1
  20. package/_shims/{fileFromPath.node.js → fileFromPath-node.js} +1 -1
  21. package/_shims/{fileFromPath.node.js.map → fileFromPath-node.js.map} +1 -1
  22. package/_shims/{fileFromPath.node.mjs → fileFromPath-node.mjs} +1 -1
  23. package/_shims/{fileFromPath.node.mjs.map → fileFromPath-node.mjs.map} +1 -1
  24. package/_shims/fileFromPath.d.ts +2 -2
  25. package/_shims/fileFromPath.d.ts.map +1 -1
  26. package/_shims/fileFromPath.js +1 -1
  27. package/_shims/fileFromPath.mjs +1 -1
  28. package/_shims/{getMultipartRequestOptions.node.d.ts → getMultipartRequestOptions-node.d.ts} +2 -2
  29. package/_shims/getMultipartRequestOptions-node.d.ts.map +1 -0
  30. package/_shims/{getMultipartRequestOptions.node.js → getMultipartRequestOptions-node.js} +1 -1
  31. package/_shims/{getMultipartRequestOptions.node.js.map → getMultipartRequestOptions-node.js.map} +1 -1
  32. package/_shims/{getMultipartRequestOptions.node.mjs → getMultipartRequestOptions-node.mjs} +1 -1
  33. package/_shims/{getMultipartRequestOptions.node.mjs.map → getMultipartRequestOptions-node.mjs.map} +1 -1
  34. package/_shims/getMultipartRequestOptions.d.ts +1 -1
  35. package/_shims/getMultipartRequestOptions.d.ts.map +1 -1
  36. package/_shims/{node-readable.node.d.ts → node-readable-node.d.ts} +1 -1
  37. package/_shims/{node-readable.node.d.ts.map → node-readable-node.d.ts.map} +1 -1
  38. package/_shims/{node-readable.node.js → node-readable-node.js} +1 -1
  39. package/_shims/node-readable-node.js.map +1 -0
  40. package/_shims/{node-readable.node.mjs → node-readable-node.mjs} +1 -1
  41. package/_shims/node-readable-node.mjs.map +1 -0
  42. package/core.d.ts +2 -1
  43. package/core.d.ts.map +1 -1
  44. package/core.js +3 -1
  45. package/core.js.map +1 -1
  46. package/core.mjs +1 -1
  47. package/core.mjs.map +1 -1
  48. package/error.d.ts +1 -1
  49. package/error.d.ts.map +1 -1
  50. package/error.js +2 -2
  51. package/error.js.map +1 -1
  52. package/error.mjs +2 -2
  53. package/error.mjs.map +1 -1
  54. package/index.d.mts +6 -1
  55. package/index.d.ts +6 -1
  56. package/index.d.ts.map +1 -1
  57. package/index.js +9 -3
  58. package/index.js.map +1 -1
  59. package/index.mjs +9 -3
  60. package/index.mjs.map +1 -1
  61. package/package.json +9 -4
  62. package/resources/index.d.ts +1 -0
  63. package/resources/index.d.ts.map +1 -1
  64. package/resources/index.js +14 -1
  65. package/resources/index.js.map +1 -1
  66. package/resources/index.mjs +1 -0
  67. package/resources/index.mjs.map +1 -1
  68. package/resources/webhooks.d.ts +22 -0
  69. package/resources/webhooks.d.ts.map +1 -0
  70. package/resources/webhooks.js +118 -0
  71. package/resources/webhooks.js.map +1 -0
  72. package/resources/webhooks.mjs +114 -0
  73. package/resources/webhooks.mjs.map +1 -0
  74. package/src/_shims/ReadableStream.d.ts +5 -5
  75. package/src/_shims/agent.ts +1 -1
  76. package/src/_shims/{fetch.node.d.ts → fetch-node.d.ts} +8 -8
  77. package/src/_shims/fetch.d.ts +10 -10
  78. package/src/_shims/{fileFromPath.node.ts → fileFromPath-node.ts} +1 -1
  79. package/src/_shims/fileFromPath.ts +2 -2
  80. package/src/_shims/{formdata.node.d.ts → form-data-node.d.ts} +4 -4
  81. package/src/_shims/{formdata.d.ts → form-data.d.ts} +4 -4
  82. package/src/_shims/{getMultipartRequestOptions.node.ts → getMultipartRequestOptions-node.ts} +3 -3
  83. package/src/_shims/getMultipartRequestOptions.ts +3 -3
  84. package/src/core.ts +11 -10
  85. package/src/error.ts +3 -3
  86. package/src/index.ts +17 -7
  87. package/src/pagination.ts +3 -3
  88. package/src/resource.ts +1 -1
  89. package/src/resources/account.ts +3 -3
  90. package/src/resources/ats/applications.ts +6 -6
  91. package/src/resources/ats/ats.ts +7 -7
  92. package/src/resources/ats/candidates.ts +5 -5
  93. package/src/resources/ats/index.ts +6 -6
  94. package/src/resources/ats/jobs.ts +5 -5
  95. package/src/resources/ats/offers.ts +5 -5
  96. package/src/resources/ats/stages.ts +4 -4
  97. package/src/resources/hris/benefits/benefits.ts +6 -6
  98. package/src/resources/hris/benefits/index.ts +2 -2
  99. package/src/resources/hris/benefits/individuals.ts +6 -6
  100. package/src/resources/hris/company.ts +4 -4
  101. package/src/resources/hris/directory.ts +5 -5
  102. package/src/resources/hris/employments.ts +5 -5
  103. package/src/resources/hris/hris.ts +9 -9
  104. package/src/resources/hris/index.ts +8 -8
  105. package/src/resources/hris/individuals.ts +6 -6
  106. package/src/resources/hris/pay-statements.ts +6 -6
  107. package/src/resources/hris/payments.ts +5 -5
  108. package/src/resources/index.ts +6 -5
  109. package/src/resources/providers.ts +4 -4
  110. package/src/resources/webhooks.ts +151 -0
  111. package/src/tsconfig.json +11 -0
  112. package/src/uploads.ts +6 -6
  113. package/src/version.ts +1 -1
  114. package/uploads.d.ts +1 -1
  115. package/uploads.d.ts.map +1 -1
  116. package/uploads.js +4 -4
  117. package/uploads.js.map +1 -1
  118. package/uploads.mjs +1 -1
  119. package/uploads.mjs.map +1 -1
  120. package/version.d.ts +1 -1
  121. package/version.js +1 -1
  122. package/version.mjs +1 -1
  123. package/_shims/ReadableStream.node.d.ts.map +0 -1
  124. package/_shims/ReadableStream.node.js.map +0 -1
  125. package/_shims/ReadableStream.node.mjs.map +0 -1
  126. package/_shims/agent.node.d.ts.map +0 -1
  127. package/_shims/getMultipartRequestOptions.node.d.ts.map +0 -1
  128. package/_shims/node-readable.node.js.map +0 -1
  129. package/_shims/node-readable.node.mjs.map +0 -1
  130. package/src/_shims/fetch.deno.ts +0 -23
  131. package/src/_shims/formdata.deno.ts +0 -16
  132. /package/_shims/{fetch.node.d.ts → fetch-node.d.ts} +0 -0
  133. /package/_shims/{fetch.node.js → fetch-node.js} +0 -0
  134. /package/_shims/{fetch.node.mjs → fetch-node.mjs} +0 -0
  135. /package/_shims/{formdata.node.d.ts → form-data-node.d.ts} +0 -0
  136. /package/_shims/{formdata.node.js → form-data-node.js} +0 -0
  137. /package/_shims/{formdata.node.mjs → form-data-node.mjs} +0 -0
  138. /package/_shims/{formdata.d.ts → form-data.d.ts} +0 -0
  139. /package/_shims/{formdata.js → form-data.js} +0 -0
  140. /package/_shims/{formdata.mjs → form-data.mjs} +0 -0
  141. /package/src/_shims/{ReadableStream.node.ts → ReadableStream-node.ts} +0 -0
  142. /package/src/_shims/{agent.node.ts → agent-node.ts} +0 -0
  143. /package/src/_shims/{fetch.node.js → fetch-node.js} +0 -0
  144. /package/src/_shims/{fetch.node.mjs → fetch-node.mjs} +0 -0
  145. /package/src/_shims/{formdata.node.js → form-data-node.js} +0 -0
  146. /package/src/_shims/{formdata.node.mjs → form-data-node.mjs} +0 -0
  147. /package/src/_shims/{formdata.js → form-data.js} +0 -0
  148. /package/src/_shims/{formdata.mjs → form-data.mjs} +0 -0
  149. /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> = unknown extends ReadableStream ? never : ReadableStream<R>;
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> = unknown extends UnderlyingSource ? never : UnderlyingSource<R>;
29
+ type _UnderlyingSource<R = any> = UnderlyingSource<R>;
30
30
  // @ts-ignore
31
- type _UnderlyingByteSource = unknown extends UnderlyingByteSource ? never : UnderlyingByteSource;
31
+ type _UnderlyingByteSource = UnderlyingByteSource;
32
32
  type _UnderlyingDefaultSource<R = any> =
33
33
  // @ts-ignore
34
- unknown extends UnderlyingDefaultSource ? never : UnderlyingDefaultSource<R>;
34
+ UnderlyingDefaultSource<R>;
35
35
  // @ts-ignore
36
- type _QueuingStrategy<R = any> = unknown extends QueuingStrategy ? never : QueuingStrategy<R>;
36
+ type _QueuingStrategy<R = any> = QueuingStrategy<R>;
37
37
 
38
38
  export { _ReadableStream as ReadableStream };
@@ -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.node.ts by the package export map
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 = unknown extends Request ? nf.Request : Request;
20
+ type _Request = Request;
21
21
  // @ts-ignore
22
- type _RequestInfo = unknown extends RequestInfo ? nf.RequestInfo : RequestInfo;
22
+ type _RequestInfo = RequestInfo;
23
23
  // @ts-ignore
24
- type _RequestInit = unknown extends RequestInit ? nf.RequestInit : RequestInit;
24
+ type _RequestInit = RequestInit;
25
25
  // @ts-ignore
26
- type _Response = unknown extends Response ? nf.Response : Response;
26
+ type _Response = Response;
27
27
  // @ts-ignore
28
- type _ResponseInit = unknown extends ResponseInit ? nf.ResponseInit : 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 = unknown extends BodyInit ? nf.BodyInit : BodyInit;
35
+ type _BodyInit = BodyInit;
36
36
  // @ts-ignore
37
- type _Headers = unknown extends Headers ? nf.Headers : Headers;
37
+ type _Headers = Headers;
38
38
  // @ts-ignore
39
- type _HeadersInit = unknown extends HeadersInit ? nf.HeadersInit : HeadersInit;
39
+ type _HeadersInit = HeadersInit;
40
40
 
41
41
  declare const _fetch: _fetch;
42
42
  declare const _Request: {
@@ -14,25 +14,25 @@
14
14
  */
15
15
 
16
16
  // @ts-ignore
17
- type _fetch = unknown extends typeof fetch ? never : typeof fetch;
17
+ type _fetch = typeof fetch;
18
18
  // @ts-ignore
19
- type _Request = unknown extends Request ? never : Request;
19
+ type _Request = Request;
20
20
  // @ts-ignore
21
- type _RequestInfo = unknown extends RequestInfo ? never : RequestInfo;
21
+ type _RequestInfo = RequestInfo;
22
22
  // @ts-ignore
23
- type _RequestInit = unknown extends RequestInit ? never : RequestInit;
23
+ type _RequestInit = RequestInit;
24
24
  // @ts-ignore
25
- type _Response = unknown extends Response ? never : Response;
25
+ type _Response = Response;
26
26
  // @ts-ignore
27
- type _ResponseInit = unknown extends ResponseInit ? never : ResponseInit;
27
+ type _ResponseInit = ResponseInit;
28
28
  // @ts-ignore
29
- type _ResponseType = unknown extends ResponseType ? never : ResponseType;
29
+ type _ResponseType = ResponseType;
30
30
  // @ts-ignore
31
- type _BodyInit = unknown extends BodyInit ? never : BodyInit;
31
+ type _BodyInit = BodyInit;
32
32
  // @ts-ignore
33
- type _Headers = unknown extends Headers ? never : Headers;
33
+ type _Headers = Headers;
34
34
  // @ts-ignore
35
- type _HeadersInit = unknown extends HeadersInit ? never : 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 './formdata.node.js';
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.node.js for node environments
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 './formdata.js';
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 = unknown extends FormData ? fd.FormData : FormData;
24
+ type _FormData = FormData;
25
25
  // @ts-ignore
26
- type _File = unknown extends File ? fd.File : File;
26
+ type _File = File;
27
27
  // @ts-ignore
28
- type _Blob = unknown extends Blob ? fd.Blob : 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 = unknown extends FormData ? never : FormData;
22
+ type _FormData = FormData;
23
23
  // @ts-ignore
24
- type _File = unknown extends File ? never : File;
24
+ type _File = File;
25
25
  // @ts-ignore
26
- type _Blob = unknown extends Blob ? never : Blob;
26
+ type _Blob = Blob;
27
27
 
28
28
  declare const _FormData: {
29
29
  new (form?: any): _FormData;
@@ -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 './formdata.node.js';
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 './formdata.js';
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 ? Object.fromEntries(Array.from(headers).map((header) => [...header]))
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>(path: string, query: Req | undefined): string {
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
- baseURL: `https://api.tryfinch.com`,
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
 
package/src/resource.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // File generated from our OpenAPI spec by Stainless.
2
2
 
3
- import type { Finch } from './index';
3
+ import type { Finch } from './index.js';
4
4
 
5
5
  export class APIResource {
6
6
  protected client: Finch;