@tryfinch/finch-api 3.1.0 → 3.1.3

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 (98) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/_shims/fetch.js +1 -1
  3. package/_shims/formdata.node.d.ts +1 -0
  4. package/core.d.ts +14 -10
  5. package/core.d.ts.map +1 -1
  6. package/core.js +82 -66
  7. package/core.js.map +1 -1
  8. package/core.mjs +71 -25
  9. package/core.mjs.map +1 -1
  10. package/error.d.ts +1 -0
  11. package/error.d.ts.map +1 -1
  12. package/error.js +12 -3
  13. package/error.js.map +1 -1
  14. package/error.mjs +12 -3
  15. package/error.mjs.map +1 -1
  16. package/index.d.mts +4 -5
  17. package/index.d.ts +4 -5
  18. package/index.d.ts.map +1 -1
  19. package/index.js +26 -26
  20. package/index.js.map +1 -1
  21. package/index.mjs +26 -26
  22. package/index.mjs.map +1 -1
  23. package/package.json +6 -8
  24. package/pagination.d.ts.map +1 -1
  25. package/resources/account.d.ts.map +1 -1
  26. package/resources/ats/applications.d.ts.map +1 -1
  27. package/resources/ats/ats.d.ts.map +1 -1
  28. package/resources/ats/ats.js.map +1 -1
  29. package/resources/ats/candidates.d.ts.map +1 -1
  30. package/resources/ats/jobs.d.ts.map +1 -1
  31. package/resources/ats/offers.d.ts.map +1 -1
  32. package/resources/ats/stages.d.ts.map +1 -1
  33. package/resources/hris/benefits/benefits.d.ts.map +1 -1
  34. package/resources/hris/benefits/benefits.js.map +1 -1
  35. package/resources/hris/benefits/individuals.d.ts.map +1 -1
  36. package/resources/hris/company.d.ts.map +1 -1
  37. package/resources/hris/directory.d.ts.map +1 -1
  38. package/resources/hris/hris.d.ts.map +1 -1
  39. package/resources/hris/hris.js.map +1 -1
  40. package/resources/hris/index.d.ts.map +1 -1
  41. package/resources/hris/index.js +7 -7
  42. package/resources/hris/index.js.map +1 -1
  43. package/resources/hris/individuals/employment-data.d.ts.map +1 -1
  44. package/resources/hris/individuals/employment-data.js.map +1 -1
  45. package/resources/hris/individuals/individuals.d.ts.map +1 -1
  46. package/resources/hris/individuals/individuals.js.map +1 -1
  47. package/resources/hris/pay-statements.d.ts.map +1 -1
  48. package/resources/hris/payments.d.ts.map +1 -1
  49. package/resources/index.d.ts +1 -0
  50. package/resources/index.d.ts.map +1 -1
  51. package/resources/index.js.map +1 -1
  52. package/resources/index.mjs.map +1 -1
  53. package/resources/providers.d.ts.map +1 -1
  54. package/src/_shims/fetch.deno.ts +23 -0
  55. package/src/_shims/fetch.js +1 -1
  56. package/src/_shims/formdata.deno.ts +16 -0
  57. package/src/_shims/formdata.node.d.ts +1 -0
  58. package/src/core.ts +79 -26
  59. package/src/error.ts +11 -1
  60. package/src/index.ts +28 -25
  61. package/src/pagination.ts +2 -2
  62. package/src/resources/account.ts +1 -1
  63. package/src/resources/ats/applications.ts +1 -1
  64. package/src/resources/ats/ats.ts +1 -1
  65. package/src/resources/ats/candidates.ts +1 -1
  66. package/src/resources/ats/jobs.ts +1 -1
  67. package/src/resources/ats/offers.ts +1 -1
  68. package/src/resources/ats/stages.ts +1 -1
  69. package/src/resources/hris/benefits/benefits.ts +1 -1
  70. package/src/resources/hris/benefits/individuals.ts +1 -1
  71. package/src/resources/hris/company.ts +1 -1
  72. package/src/resources/hris/directory.ts +1 -1
  73. package/src/resources/hris/hris.ts +1 -1
  74. package/src/resources/hris/index.ts +2 -2
  75. package/src/resources/hris/individuals/employment-data.ts +1 -1
  76. package/src/resources/hris/individuals/individuals.ts +1 -1
  77. package/src/resources/hris/pay-statements.ts +1 -1
  78. package/src/resources/hris/payments.ts +1 -1
  79. package/src/resources/index.ts +1 -0
  80. package/src/resources/providers.ts +1 -1
  81. package/src/uploads.ts +11 -10
  82. package/src/version.ts +1 -1
  83. package/uploads.d.ts +5 -4
  84. package/uploads.d.ts.map +1 -1
  85. package/uploads.js +4 -4
  86. package/uploads.js.map +1 -1
  87. package/uploads.mjs +4 -4
  88. package/uploads.mjs.map +1 -1
  89. package/version.d.ts +1 -1
  90. package/version.js +1 -1
  91. package/version.mjs +1 -1
  92. package/src/streaming.ts +0 -274
  93. package/streaming.d.ts +0 -14
  94. package/streaming.d.ts.map +0 -1
  95. package/streaming.js +0 -213
  96. package/streaming.js.map +0 -1
  97. package/streaming.mjs +0 -209
  98. package/streaming.mjs.map +0 -1
package/src/core.ts CHANGED
@@ -1,6 +1,4 @@
1
- import * as qs from 'qs';
2
1
  import { VERSION } from './version';
3
- import { Stream } from './streaming';
4
2
  import { APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError } from './error';
5
3
  import type { Readable } from './_shims/node-readable';
6
4
  import { getDefaultAgent, type Agent } from './_shims/agent';
@@ -82,18 +80,6 @@ export abstract class APIClient {
82
80
  */
83
81
  protected validateHeaders(headers: Headers, customHeaders: Headers) {}
84
82
 
85
- /**
86
- * Override this to add your own qs.stringify options, for example:
87
- *
88
- * {
89
- * ...super.qsOptions(),
90
- * strictNullHandling: true,
91
- * }
92
- */
93
- protected qsOptions(): qs.IStringifyOptions | undefined {
94
- return {};
95
- }
96
-
97
83
  protected defaultIdempotencyKey(): string {
98
84
  return `stainless-node-retry-${uuid4()}`;
99
85
  }
@@ -128,9 +114,11 @@ export abstract class APIClient {
128
114
  return Buffer.byteLength(body, 'utf8').toString();
129
115
  }
130
116
 
131
- const encoder = new TextEncoder();
132
- const encoded = encoder.encode(body);
133
- return encoded.length.toString();
117
+ if (typeof TextEncoder !== 'undefined') {
118
+ const encoder = new TextEncoder();
119
+ const encoded = encoder.encode(body);
120
+ return encoded.length.toString();
121
+ }
134
122
  }
135
123
 
136
124
  return null;
@@ -219,6 +207,10 @@ export abstract class APIClient {
219
207
 
220
208
  this.debug('request', url, options, req.headers);
221
209
 
210
+ if (options.signal?.aborted) {
211
+ throw new APIUserAbortError();
212
+ }
213
+
222
214
  const controller = new AbortController();
223
215
  const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
224
216
 
@@ -252,12 +244,6 @@ export abstract class APIClient {
252
244
  throw err;
253
245
  }
254
246
 
255
- if (options.stream) {
256
- // Note: there is an invariant here that isn't represented in the type system
257
- // that if you set `stream: true` the response type must also be `Stream<T>`
258
- return new Stream<Rsp>(response, controller) as any;
259
- }
260
-
261
247
  const contentType = response.headers.get('content-type');
262
248
  if (contentType?.includes('application/json')) {
263
249
  const json = await response.json();
@@ -302,12 +288,29 @@ export abstract class APIClient {
302
288
  }
303
289
 
304
290
  if (query) {
305
- url.search = qs.stringify(query, this.qsOptions());
291
+ url.search = this.stringifyQuery(query);
306
292
  }
307
293
 
308
294
  return url.toString();
309
295
  }
310
296
 
297
+ protected stringifyQuery(query: Record<string, unknown>): string {
298
+ return Object.entries(query)
299
+ .filter(([_, value]) => typeof value !== 'undefined')
300
+ .map(([key, value]) => {
301
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
302
+ return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
303
+ }
304
+ if (value === null) {
305
+ return `${encodeURIComponent(key)}=`;
306
+ }
307
+ throw new Error(
308
+ `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,
309
+ );
310
+ })
311
+ .join('&');
312
+ }
313
+
311
314
  async fetchWithTimeout(
312
315
  url: RequestInfo,
313
316
  init: RequestInit | undefined,
@@ -734,8 +737,8 @@ const isAbsoluteURL = (url: string): boolean => {
734
737
 
735
738
  const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
736
739
 
737
- const validatePositiveInteger = (name: string, n: number) => {
738
- if (!Number.isInteger(n)) {
740
+ const validatePositiveInteger = (name: string, n: unknown): number => {
741
+ if (typeof n !== 'number' || !Number.isInteger(n)) {
739
742
  throw new Error(`${name} must be an integer`);
740
743
  }
741
744
  if (n < 0) {
@@ -754,6 +757,19 @@ export const ensurePresent = <T>(value: T | null | undefined): T => {
754
757
  return value;
755
758
  };
756
759
 
760
+ /**
761
+ * Read an environment variable.
762
+ *
763
+ * Will return an empty string if the environment variable doesn't exist or cannot be accessed.
764
+ */
765
+ export const readEnv = (env: string): string | undefined => {
766
+ if (typeof process === 'undefined') {
767
+ return undefined;
768
+ }
769
+
770
+ return process.env[env] ?? undefined;
771
+ };
772
+
757
773
  export const coerceInteger = (value: unknown): number => {
758
774
  if (typeof value === 'number') return Math.round(value);
759
775
  if (typeof value === 'string') return parseInt(value, 10);
@@ -774,6 +790,27 @@ export const coerceBoolean = (value: unknown): boolean => {
774
790
  return Boolean(value);
775
791
  };
776
792
 
793
+ export const maybeCoerceInteger = (value: unknown): number | undefined => {
794
+ if (value === undefined) {
795
+ return undefined;
796
+ }
797
+ return coerceInteger(value);
798
+ };
799
+
800
+ export const maybeCoerceFloat = (value: unknown): number | undefined => {
801
+ if (value === undefined) {
802
+ return undefined;
803
+ }
804
+ return coerceFloat(value);
805
+ };
806
+
807
+ export const maybeCoerceBoolean = (value: unknown): boolean | undefined => {
808
+ if (value === undefined) {
809
+ return undefined;
810
+ }
811
+ return coerceBoolean(value);
812
+ };
813
+
777
814
  // https://stackoverflow.com/a/34491287
778
815
  export function isEmptyObj(obj: Object | null | undefined): boolean {
779
816
  if (!obj) return true;
@@ -817,3 +854,19 @@ export const getHeader = (headers: HeadersLike, key: string): string | null | un
817
854
  }
818
855
  return value;
819
856
  };
857
+
858
+ /**
859
+ * Encodes a string to Base64 format.
860
+ */
861
+ export const toBase64 = (str: string | null | undefined): string => {
862
+ if (!str) return '';
863
+ if (typeof Buffer !== 'undefined') {
864
+ return Buffer.from(str).toString('base64');
865
+ }
866
+
867
+ if (typeof btoa !== 'undefined') {
868
+ return btoa(str);
869
+ }
870
+
871
+ throw new Error('Cannot generate b64 string; Expected `Buffer` or `btoa` to be defined');
872
+ };
package/src/error.ts CHANGED
@@ -13,12 +13,22 @@ export class APIError extends Error {
13
13
  message: string | undefined,
14
14
  headers: Headers | undefined,
15
15
  ) {
16
- super(message || (error as any)?.message || 'Unknown error occurred.');
16
+ super(APIError.makeMessage(error, message));
17
17
  this.status = status;
18
18
  this.headers = headers;
19
19
  this.error = error;
20
20
  }
21
21
 
22
+ private static makeMessage(error: any, message: string | undefined) {
23
+ return (
24
+ error?.message ?
25
+ typeof error.message === 'string' ? error.message
26
+ : JSON.stringify(error.message)
27
+ : error ? JSON.stringify(error)
28
+ : message || 'Unknown error occurred'
29
+ );
30
+ }
31
+
22
32
  static generate(
23
33
  status: number | undefined,
24
34
  errorResponse: Object | undefined,
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  // File generated from our OpenAPI spec by Stainless.
2
2
 
3
- import * as qs from 'qs';
4
3
  import * as Core from './core';
5
4
  import * as Pagination from './pagination';
6
5
  import * as API from './resources/index';
@@ -8,7 +7,7 @@ import * as Errors from './error';
8
7
  import type { Agent } from './_shims/agent';
9
8
  import * as Uploads from './uploads';
10
9
 
11
- type Config = {
10
+ export interface ClientOptions {
12
11
  /**
13
12
  * Set it to null if you want to send unauthenticated requests.
14
13
  */
@@ -71,7 +70,7 @@ type Config = {
71
70
  clientId?: string | null;
72
71
 
73
72
  clientSecret?: string | null;
74
- };
73
+ }
75
74
 
76
75
  /** Instantiate the API Client. */
77
76
  export class Finch extends Core.APIClient {
@@ -79,13 +78,22 @@ export class Finch extends Core.APIClient {
79
78
  clientId?: string | null;
80
79
  clientSecret?: string | null;
81
80
 
82
- private _options: Config;
83
-
84
- constructor(config?: Config) {
85
- const options: Config = {
86
- accessToken: null,
87
- baseURL: 'https://api.tryfinch.com',
88
- ...config,
81
+ private _options: ClientOptions;
82
+
83
+ constructor({
84
+ accessToken = null,
85
+ clientId = Core.readEnv('FINCH_CLIENT_ID') ?? null,
86
+ clientSecret = Core.readEnv('FINCH_CLIENT_SECRET') ?? null,
87
+ ...opts
88
+ }: ClientOptions = {}) {
89
+ undefined;
90
+
91
+ const options: ClientOptions = {
92
+ accessToken,
93
+ clientId,
94
+ clientSecret,
95
+ baseURL: `https://api.tryfinch.com`,
96
+ ...opts,
89
97
  };
90
98
 
91
99
  super({
@@ -95,11 +103,11 @@ export class Finch extends Core.APIClient {
95
103
  maxRetries: options.maxRetries,
96
104
  fetch: options.fetch,
97
105
  });
98
- this.accessToken = options.accessToken || null;
99
106
  this._options = options;
100
107
 
101
- this.clientId = config?.clientId || process.env['FINCH_CLIENT_ID'] || null;
102
- this.clientSecret = config?.clientSecret || process.env['FINCH_CLIENT_SECRET'] || null;
108
+ this.accessToken = accessToken;
109
+ this.clientId = clientId;
110
+ this.clientSecret = clientSecret;
103
111
  }
104
112
 
105
113
  ats: API.ATS = new API.ATS(this);
@@ -150,15 +158,12 @@ export class Finch extends Core.APIClient {
150
158
  throw new Error('Expected the clientId to be set in order to call getAuthUrl');
151
159
  }
152
160
  const url = new URL('/authorize', 'https://connect.tryfinch.com/authorize');
153
- url.search = qs.stringify(
154
- {
155
- client_id: this.clientId,
156
- products: products,
157
- redirect_uri: redirectUri,
158
- sandbox: sandbox,
159
- },
160
- this.qsOptions(),
161
- );
161
+ url.search = this.stringifyQuery({
162
+ client_id: this.clientId,
163
+ products: products,
164
+ redirect_uri: redirectUri,
165
+ sandbox: sandbox,
166
+ });
162
167
  return url.toString();
163
168
  }
164
169
 
@@ -194,9 +199,7 @@ export class Finch extends Core.APIClient {
194
199
  return { Authorization: `Bearer ${this.accessToken}` };
195
200
  }
196
201
 
197
- protected override qsOptions(): qs.IStringifyOptions {
198
- return { arrayFormat: 'comma' };
199
- }
202
+ static Finch = this;
200
203
 
201
204
  static APIError = Errors.APIError;
202
205
  static APIConnectionError = Errors.APIConnectionError;
package/src/pagination.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  // File generated from our OpenAPI spec by Stainless.
2
2
 
3
3
  import { AbstractPage, APIResponse, APIClient, FinalRequestOptions, PageInfo } from './core';
4
- import * as HRIS from './resources/hris';
5
- import * as ATS from './resources/ats';
4
+ import * as HRIS from './resources/hris/index';
5
+ import * as ATS from './resources/ats/index';
6
6
 
7
7
  export type SinglePageResponse<Item> = Item[];
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as Core from '../core';
4
4
  import { APIResource } from '../resource';
5
- import * as API from '.';
5
+ import * as API from './index';
6
6
 
7
7
  export class Account extends APIResource {
8
8
  /**
@@ -4,7 +4,7 @@ import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
5
  import { isRequestOptions } from '../../core';
6
6
  import * as Stages from './stages';
7
- import * as API from '.';
7
+ import * as API from './index';
8
8
  import { ApplicationsPage, ApplicationsPageParams } from '../../pagination';
9
9
 
10
10
  export class Applications extends APIResource {
@@ -6,7 +6,7 @@ import { Applications } from './applications';
6
6
  import { Stages } from './stages';
7
7
  import { Jobs } from './jobs';
8
8
  import { Offers } from './offers';
9
- import * as API from '.';
9
+ import * as API from './index';
10
10
 
11
11
  export class ATS extends APIResource {
12
12
  candidates: Candidates = new Candidates(this.client);
@@ -3,7 +3,7 @@
3
3
  import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
5
  import { isRequestOptions } from '../../core';
6
- import * as API from '.';
6
+ import * as API from './index';
7
7
  import { CandidatesPage, CandidatesPageParams } from '../../pagination';
8
8
 
9
9
  export class Candidates extends APIResource {
@@ -3,7 +3,7 @@
3
3
  import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
5
  import { isRequestOptions } from '../../core';
6
- import * as API from '.';
6
+ import * as API from './index';
7
7
  import { JobsPage, JobsPageParams } from '../../pagination';
8
8
 
9
9
  export class Jobs extends APIResource {
@@ -3,7 +3,7 @@
3
3
  import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
5
  import { isRequestOptions } from '../../core';
6
- import * as API from '.';
6
+ import * as API from './index';
7
7
  import { OffersPage, OffersPageParams } from '../../pagination';
8
8
 
9
9
  export class Offers extends APIResource {
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
- import * as API from '.';
5
+ import * as API from './index';
6
6
  import { SinglePage } from '../../pagination';
7
7
 
8
8
  export class Stages extends APIResource {
@@ -4,7 +4,7 @@ import * as Core from '../../../core';
4
4
  import { APIResource } from '../../../resource';
5
5
  import { isRequestOptions } from '../../../core';
6
6
  import { Individuals } from './individuals';
7
- import * as API from '.';
7
+ import * as API from './index';
8
8
  import { SinglePage } from '../../../pagination';
9
9
 
10
10
  export class Benefits extends APIResource {
@@ -4,7 +4,7 @@ import * as Core from '../../../core';
4
4
  import { APIResource } from '../../../resource';
5
5
  import { isRequestOptions } from '../../../core';
6
6
  import * as Benefits from './index';
7
- import * as API from '.';
7
+ import * as API from './index';
8
8
  import { SinglePage } from '../../../pagination';
9
9
 
10
10
  export class Individuals extends APIResource {
@@ -3,7 +3,7 @@
3
3
  import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
5
  import * as HRIS from './index';
6
- import * as API from '.';
6
+ import * as API from './index';
7
7
 
8
8
  export class CompanyResource extends APIResource {
9
9
  /**
@@ -3,7 +3,7 @@
3
3
  import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
5
  import { isRequestOptions } from '../../core';
6
- import * as API from '.';
6
+ import * as API from './index';
7
7
  import { IndividualsPage, IndividualsPageParams } from '../../pagination';
8
8
 
9
9
  export class Directory extends APIResource {
@@ -7,7 +7,7 @@ import { PayStatements } from './pay-statements';
7
7
  import { Directory } from './directory';
8
8
  import { Individuals } from './individuals/individuals';
9
9
  import { Benefits } from './benefits/benefits';
10
- import * as API from '.';
10
+ import * as API from './index';
11
11
 
12
12
  export class HRIS extends APIResource {
13
13
  company: CompanyResource = new CompanyResource(this.client);
@@ -13,7 +13,7 @@ export {
13
13
  CompanyBenefitsSinglePage,
14
14
  SupportedBenefitsSinglePage,
15
15
  Benefits,
16
- } from './benefits';
16
+ } from './benefits/index';
17
17
  export { Company, CompanyResource } from './company';
18
18
  export { Income, Location, Money, Paging, HRIS } from './hris';
19
19
  export {
@@ -22,7 +22,7 @@ export {
22
22
  IndividualRetrieveManyParams,
23
23
  IndividualResponsesResponsesPage,
24
24
  Individuals,
25
- } from './individuals';
25
+ } from './individuals/index';
26
26
  export { IndividualInDirectory, DirectoryListIndividualsParams, Directory } from './directory';
27
27
  export {
28
28
  PayStatement,
@@ -3,7 +3,7 @@
3
3
  import * as Core from '../../../core';
4
4
  import { APIResource } from '../../../resource';
5
5
  import * as HRIS from '../index';
6
- import * as API from '.';
6
+ import * as API from './index';
7
7
  import { ResponsesPage } from '../../../pagination';
8
8
 
9
9
  export class EmploymentData extends APIResource {
@@ -5,7 +5,7 @@ import { APIResource } from '../../../resource';
5
5
  import { isRequestOptions } from '../../../core';
6
6
  import * as HRIS from '../index';
7
7
  import { EmploymentData } from './employment-data';
8
- import * as API from '.';
8
+ import * as API from './index';
9
9
  import { ResponsesPage } from '../../../pagination';
10
10
 
11
11
  export class Individuals extends APIResource {
@@ -4,7 +4,7 @@ import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
5
  import * as HRIS from './index';
6
6
  import * as Benefits from './benefits/index';
7
- import * as API from '.';
7
+ import * as API from './index';
8
8
  import { ResponsesPage } from '../../pagination';
9
9
 
10
10
  export class PayStatements extends APIResource {
@@ -3,7 +3,7 @@
3
3
  import * as Core from '../../core';
4
4
  import { APIResource } from '../../resource';
5
5
  import * as HRIS from './index';
6
- import * as API from '.';
6
+ import * as API from './index';
7
7
  import { SinglePage } from '../../pagination';
8
8
 
9
9
  export class Payments extends APIResource {
@@ -1,5 +1,6 @@
1
1
  // File generated from our OpenAPI spec by Stainless.
2
2
 
3
+ export {} from './top-level';
3
4
  export { ATS } from './ats/ats';
4
5
  export { DisconnectResponse, Introspection, Account } from './account';
5
6
  export { Income, Location, Money, Paging, HRIS } from './hris/hris';
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as Core from '../core';
4
4
  import { APIResource } from '../resource';
5
- import * as API from '.';
5
+ import * as API from './index';
6
6
  import { SinglePage } from '../pagination';
7
7
 
8
8
  export class Providers extends APIResource {
package/src/uploads.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  import { type RequestOptions } from './core';
2
2
  import { type Readable } from './_shims/node-readable';
3
3
  import { type BodyInit } from './_shims/fetch.js';
4
- import { FormData, File, type FilePropertyBag } from './_shims/formdata.js';
4
+ import { FormData, File, type Blob, type FilePropertyBag } from './_shims/formdata.js';
5
5
  import { getMultipartRequestOptions } from './_shims/getMultipartRequestOptions';
6
6
  import { fileFromPath } from './_shims/fileFromPath';
7
7
  import { type FsReadStream, isFsReadStream } from './_shims/node-readable';
8
8
 
9
9
  export { fileFromPath };
10
10
 
11
- export type BlobPart = string | ArrayBuffer | ArrayBufferView | BlobLike | Uint8Array | DataView;
11
+ type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | Uint8Array | DataView;
12
+ export type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | Uint8Array | DataView;
12
13
 
13
14
  /**
14
15
  * Typically, this is a native "File" class.
@@ -84,11 +85,11 @@ export const isUploadable = (value: any): value is Uploadable => {
84
85
  return isFileLike(value) || isResponseLike(value) || isFsReadStream(value);
85
86
  };
86
87
 
87
- export type ToFileInput = Uploadable | Exclude<BlobPart, string> | AsyncIterable<BlobPart>;
88
+ export type ToFileInput = Uploadable | Exclude<BlobLikePart, string> | AsyncIterable<BlobLikePart>;
88
89
 
89
90
  /**
90
91
  * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats
91
- * @param bits the raw content of the file. Can be an {@link Uploadable}, {@link BlobPart}, or {@link AsyncIterable} of {@link BlobPart}s
92
+ * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s
92
93
  * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible
93
94
  * @param {Object=} options additional properties
94
95
  * @param {string=} options.type the MIME type of the content
@@ -100,6 +101,9 @@ export async function toFile(
100
101
  name?: string | null | undefined,
101
102
  options: FilePropertyBag | undefined = {},
102
103
  ): Promise<FileLike> {
104
+ // If it's a promise, resolve it.
105
+ value = await value;
106
+
103
107
  if (isResponseLike(value)) {
104
108
  const blob = await value.blob();
105
109
  name ||= new URL(value.url).pathname.split(/[\\/]/).pop() ?? 'unknown_file';
@@ -121,10 +125,7 @@ export async function toFile(
121
125
  return new File(bits, name, options);
122
126
  }
123
127
 
124
- async function getBytes(value: ToFileInput | PromiseLike<ToFileInput>): Promise<Array<BlobPart>> {
125
- // resolve input promise or promiselike object
126
- value = await value;
127
-
128
+ async function getBytes(value: ToFileInput): Promise<Array<BlobPart>> {
128
129
  let parts: Array<BlobPart> = [];
129
130
  if (
130
131
  typeof value === 'string' ||
@@ -231,10 +232,10 @@ const addFormValue = async (form: FormData, key: string, value: unknown): Promis
231
232
 
232
233
  // TODO: make nested formats configurable
233
234
  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
234
- form.append(key, value);
235
+ form.append(key, String(value));
235
236
  } else if (isUploadable(value)) {
236
237
  const file = await toFile(value);
237
- form.append(key, file);
238
+ form.append(key, file as File);
238
239
  } else if (Array.isArray(value)) {
239
240
  await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry)));
240
241
  } else if (typeof value === 'object') {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '3.1.0'; // x-release-please-version
1
+ export const VERSION = '3.1.3'; // x-release-please-version
package/uploads.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { type RequestOptions } from './core.js';
2
2
  import { type Readable } from '@tryfinch/finch-api/_shims/node-readable';
3
3
  import { type BodyInit } from '@tryfinch/finch-api/_shims/fetch';
4
- import { FormData, type FilePropertyBag } from '@tryfinch/finch-api/_shims/formdata';
4
+ import { FormData, type Blob, type FilePropertyBag } from '@tryfinch/finch-api/_shims/formdata';
5
5
  import { fileFromPath } from '@tryfinch/finch-api/_shims/fileFromPath';
6
6
  import { type FsReadStream } from '@tryfinch/finch-api/_shims/node-readable';
7
7
  export { fileFromPath };
8
- export type BlobPart = string | ArrayBuffer | ArrayBufferView | BlobLike | Uint8Array | DataView;
8
+ type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | Uint8Array | DataView;
9
+ export type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | Uint8Array | DataView;
9
10
  /**
10
11
  * Typically, this is a native "File" class.
11
12
  *
@@ -55,10 +56,10 @@ export declare const isBlobLike: (value: any) => value is BlobLike & {
55
56
  arrayBuffer(): Promise<ArrayBuffer>;
56
57
  };
57
58
  export declare const isUploadable: (value: any) => value is Uploadable;
58
- export type ToFileInput = Uploadable | Exclude<BlobPart, string> | AsyncIterable<BlobPart>;
59
+ export type ToFileInput = Uploadable | Exclude<BlobLikePart, string> | AsyncIterable<BlobLikePart>;
59
60
  /**
60
61
  * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats
61
- * @param bits the raw content of the file. Can be an {@link Uploadable}, {@link BlobPart}, or {@link AsyncIterable} of {@link BlobPart}s
62
+ * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s
62
63
  * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible
63
64
  * @param {Object=} options additional properties
64
65
  * @param {string=} options.type the MIME type of the content
package/uploads.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["src/uploads.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AACzE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAQ,KAAK,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAE3F,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,0CAA0C,CAAC;AAE7F,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEjG;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,6EAA6E;IAC7E,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAE/C;AAED;;GAEG;AACH,MAAM,WAAW,QAAS,SAAQ,QAAQ;IACxC,oFAAoF;IACpF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,UAAW,GAAG,0BAIP,CAAC;AAEnC,eAAO,MAAM,UAAU,UAAW,GAAG,sBAKlB,CAAC;AAEpB;;;GAGG;AACH,eAAO,MAAM,UAAU,UAAW,GAAG;mBAAwC,QAAQ,WAAW,CAAC;CAOxD,CAAC;AAE1C,eAAO,MAAM,YAAY,UAAW,GAAG,wBAEtC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;AAE3F;;;;;;;;GAQG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,EAC7C,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,OAAO,GAAE,eAAe,GAAG,SAAc,GACxC,OAAO,CAAC,QAAQ,CAAC,CAoBnB;AAuDD,qBAAa,aAAa;IACL,IAAI,EAAE,QAAQ,GAAG,QAAQ;gBAAzB,IAAI,EAAE,QAAQ,GAAG,QAAQ;IAC5C,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAEjC;CACF;AAED,eAAO,MAAM,eAAe,SAAU,GAAG,0BACsD,CAAC;AAEhG;;;GAGG;AACH,eAAO,MAAM,gCAAgC,iHAO5C,CAAC;AAEF,eAAO,MAAM,2BAA2B,iHAKvC,CAAC;AAEF,eAAO,MAAM,UAAU,wDAA6D,QAAQ,QAAQ,CAInG,CAAC"}
1
+ {"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["src/uploads.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AACzE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAQ,KAAK,IAAI,EAAE,KAAK,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAEtG,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,0CAA0C,CAAC;AAE7F,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB,KAAK,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;AAC9F,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE7F;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,6EAA6E;IAC7E,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAE/C;AAED;;GAEG;AACH,MAAM,WAAW,QAAS,SAAQ,QAAQ;IACxC,oFAAoF;IACpF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,UAAW,GAAG,0BAIP,CAAC;AAEnC,eAAO,MAAM,UAAU,UAAW,GAAG,sBAKlB,CAAC;AAEpB;;;GAGG;AACH,eAAO,MAAM,UAAU,UAAW,GAAG;mBAAwC,QAAQ,WAAW,CAAC;CAOxD,CAAC;AAE1C,eAAO,MAAM,YAAY,UAAW,GAAG,wBAEtC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;AAEnG;;;;;;;;GAQG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,EAC7C,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,OAAO,GAAE,eAAe,GAAG,SAAc,GACxC,OAAO,CAAC,QAAQ,CAAC,CAuBnB;AAoDD,qBAAa,aAAa;IACL,IAAI,EAAE,QAAQ,GAAG,QAAQ;gBAAzB,IAAI,EAAE,QAAQ,GAAG,QAAQ;IAC5C,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAEjC;CACF;AAED,eAAO,MAAM,eAAe,SAAU,GAAG,0BACsD,CAAC;AAEhG;;;GAGG;AACH,eAAO,MAAM,gCAAgC,iHAO5C,CAAC;AAEF,eAAO,MAAM,2BAA2B,iHAKvC,CAAC;AAEF,eAAO,MAAM,UAAU,wDAA6D,QAAQ,QAAQ,CAInG,CAAC"}
package/uploads.js CHANGED
@@ -58,7 +58,7 @@ const isUploadable = (value) => {
58
58
  exports.isUploadable = isUploadable;
59
59
  /**
60
60
  * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats
61
- * @param bits the raw content of the file. Can be an {@link Uploadable}, {@link BlobPart}, or {@link AsyncIterable} of {@link BlobPart}s
61
+ * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s
62
62
  * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible
63
63
  * @param {Object=} options additional properties
64
64
  * @param {string=} options.type the MIME type of the content
@@ -67,6 +67,8 @@ exports.isUploadable = isUploadable;
67
67
  */
68
68
  async function toFile(value, name, options = {}) {
69
69
  var _a, _b, _c;
70
+ // If it's a promise, resolve it.
71
+ value = await value;
70
72
  if ((0, exports.isResponseLike)(value)) {
71
73
  const blob = await value.blob();
72
74
  name ||
@@ -89,8 +91,6 @@ async function toFile(value, name, options = {}) {
89
91
  exports.toFile = toFile;
90
92
  async function getBytes(value) {
91
93
  var _a;
92
- // resolve input promise or promiselike object
93
- value = await value;
94
94
  let parts = [];
95
95
  if (
96
96
  typeof value === 'string' ||
@@ -189,7 +189,7 @@ const addFormValue = async (form, key, value) => {
189
189
  }
190
190
  // TODO: make nested formats configurable
191
191
  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
192
- form.append(key, value);
192
+ form.append(key, String(value));
193
193
  } else if ((0, exports.isUploadable)(value)) {
194
194
  const file = await toFile(value);
195
195
  form.append(key, file);