@tryfinch/finch-api 6.4.1 → 6.6.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 +40 -0
- package/_shims/node-types.d.ts +1 -1
- package/core.d.ts +5 -2
- package/core.d.ts.map +1 -1
- package/core.js +28 -8
- package/core.js.map +1 -1
- package/core.mjs +25 -6
- package/core.mjs.map +1 -1
- package/error.d.ts +1 -1
- package/error.d.ts.map +1 -1
- package/error.js +1 -1
- package/error.js.map +1 -1
- package/error.mjs +1 -1
- package/error.mjs.map +1 -1
- package/index.d.mts +3 -13
- package/index.d.ts +3 -13
- package/index.d.ts.map +1 -1
- package/index.js +9 -13
- package/index.js.map +1 -1
- package/index.mjs +9 -13
- package/index.mjs.map +1 -1
- package/internal/qs/formats.d.ts +6 -0
- package/internal/qs/formats.d.ts.map +1 -0
- package/internal/qs/formats.js +11 -0
- package/internal/qs/formats.js.map +1 -0
- package/internal/qs/formats.mjs +8 -0
- package/internal/qs/formats.mjs.map +1 -0
- package/internal/qs/index.d.ts +10 -0
- package/internal/qs/index.d.ts.map +1 -0
- package/internal/qs/index.js +14 -0
- package/internal/qs/index.js.map +1 -0
- package/internal/qs/index.mjs +10 -0
- package/internal/qs/index.mjs.map +1 -0
- package/internal/qs/stringify.d.ts +3 -0
- package/internal/qs/stringify.d.ts.map +1 -0
- package/internal/qs/stringify.js +280 -0
- package/internal/qs/stringify.js.map +1 -0
- package/internal/qs/stringify.mjs +276 -0
- package/internal/qs/stringify.mjs.map +1 -0
- package/internal/qs/types.d.ts +57 -0
- package/internal/qs/types.d.ts.map +1 -0
- package/internal/qs/types.js +3 -0
- package/internal/qs/types.js.map +1 -0
- package/internal/qs/types.mjs +2 -0
- package/internal/qs/types.mjs.map +1 -0
- package/internal/qs/utils.d.ts +14 -0
- package/internal/qs/utils.d.ts.map +1 -0
- package/internal/qs/utils.js +229 -0
- package/internal/qs/utils.js.map +1 -0
- package/internal/qs/utils.mjs +217 -0
- package/internal/qs/utils.mjs.map +1 -0
- package/package.json +2 -4
- package/resources/access-tokens.d.ts +5 -0
- package/resources/access-tokens.d.ts.map +1 -1
- package/resources/access-tokens.js.map +1 -1
- package/resources/access-tokens.mjs.map +1 -1
- package/resources/account.d.ts +15 -0
- package/resources/account.d.ts.map +1 -1
- package/resources/account.js.map +1 -1
- package/resources/account.mjs.map +1 -1
- package/resources/connect/connect.d.ts +13 -0
- package/resources/connect/connect.d.ts.map +1 -0
- package/resources/connect/connect.js +40 -0
- package/resources/connect/connect.js.map +1 -0
- package/resources/connect/connect.mjs +13 -0
- package/resources/connect/connect.mjs.map +1 -0
- package/resources/connect/index.d.ts +3 -0
- package/resources/connect/index.d.ts.map +1 -0
- package/resources/connect/index.js +9 -0
- package/resources/connect/index.js.map +1 -0
- package/resources/connect/index.mjs +4 -0
- package/resources/connect/index.mjs.map +1 -0
- package/resources/connect/sessions.d.ts +80 -0
- package/resources/connect/sessions.d.ts.map +1 -0
- package/resources/connect/sessions.js +23 -0
- package/resources/connect/sessions.js.map +1 -0
- package/resources/connect/sessions.mjs +19 -0
- package/resources/connect/sessions.mjs.map +1 -0
- package/resources/index.d.ts +1 -0
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js +3 -1
- package/resources/index.js.map +1 -1
- package/resources/index.mjs +1 -0
- package/resources/index.mjs.map +1 -1
- package/resources/sandbox/directory.d.ts +1 -0
- package/resources/sandbox/directory.d.ts.map +1 -1
- package/resources/sandbox/directory.js.map +1 -1
- package/resources/sandbox/directory.mjs.map +1 -1
- package/resources/sandbox/employment.d.ts +2 -0
- package/resources/sandbox/employment.d.ts.map +1 -1
- package/resources/sandbox/employment.js.map +1 -1
- package/resources/sandbox/employment.mjs.map +1 -1
- package/resources/webhooks.d.ts +1 -1
- package/resources/webhooks.d.ts.map +1 -1
- package/shims/node.d.ts +1 -0
- package/shims/node.d.ts.map +1 -1
- package/src/_shims/node-types.d.ts +1 -1
- package/src/core.ts +31 -6
- package/src/error.ts +2 -2
- package/src/index.ts +9 -26
- package/src/internal/qs/LICENSE.md +13 -0
- package/src/internal/qs/README.md +3 -0
- package/src/internal/qs/formats.ts +9 -0
- package/src/internal/qs/index.ts +13 -0
- package/src/internal/qs/stringify.ts +388 -0
- package/src/internal/qs/types.ts +71 -0
- package/src/internal/qs/utils.ts +265 -0
- package/src/resources/access-tokens.ts +6 -0
- package/src/resources/account.ts +18 -0
- package/src/resources/connect/connect.ts +16 -0
- package/src/resources/connect/index.ts +10 -0
- package/src/resources/connect/sessions.ts +114 -0
- package/src/resources/index.ts +1 -0
- package/src/resources/sandbox/directory.ts +2 -0
- package/src/resources/sandbox/employment.ts +4 -0
- package/src/resources/webhooks.ts +6 -6
- package/src/uploads.ts +5 -3
- package/src/version.ts +1 -1
- package/uploads.d.ts.map +1 -1
- package/uploads.js +5 -3
- package/uploads.js.map +1 -1
- package/uploads.mjs +5 -3
- package/uploads.mjs.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import * as Errors from './error';
|
|
4
4
|
import * as Uploads from './uploads';
|
|
5
5
|
import { type Agent } from './_shims/index';
|
|
6
|
-
import * as qs from 'qs';
|
|
6
|
+
import * as qs from './internal/qs';
|
|
7
7
|
import * as Core from './core';
|
|
8
8
|
import * as Pagination from './pagination';
|
|
9
9
|
import * as API from './resources/index';
|
|
@@ -21,16 +21,6 @@ export interface ClientOptions {
|
|
|
21
21
|
*/
|
|
22
22
|
clientSecret?: string | null | undefined;
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* Defaults to process.env['FINCH_SANDBOX_CLIENT_ID'].
|
|
26
|
-
*/
|
|
27
|
-
sandboxClientId?: string | null | undefined;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Defaults to process.env['FINCH_SANDBOX_CLIENT_SECRET'].
|
|
31
|
-
*/
|
|
32
|
-
sandboxClientSecret?: string | null | undefined;
|
|
33
|
-
|
|
34
24
|
/**
|
|
35
25
|
* Defaults to process.env['FINCH_WEBHOOK_SECRET'].
|
|
36
26
|
*/
|
|
@@ -100,8 +90,6 @@ export class Finch extends Core.APIClient {
|
|
|
100
90
|
accessToken: string | null;
|
|
101
91
|
clientId: string | null;
|
|
102
92
|
clientSecret: string | null;
|
|
103
|
-
sandboxClientId: string | null;
|
|
104
|
-
sandboxClientSecret: string | null;
|
|
105
93
|
webhookSecret: string | null;
|
|
106
94
|
|
|
107
95
|
private _options: ClientOptions;
|
|
@@ -112,8 +100,6 @@ export class Finch extends Core.APIClient {
|
|
|
112
100
|
* @param {string | null | undefined} [opts.accessToken]
|
|
113
101
|
* @param {string | null | undefined} [opts.clientId=process.env['FINCH_CLIENT_ID'] ?? null]
|
|
114
102
|
* @param {string | null | undefined} [opts.clientSecret=process.env['FINCH_CLIENT_SECRET'] ?? null]
|
|
115
|
-
* @param {string | null | undefined} [opts.sandboxClientId=process.env['FINCH_SANDBOX_CLIENT_ID'] ?? null]
|
|
116
|
-
* @param {string | null | undefined} [opts.sandboxClientSecret=process.env['FINCH_SANDBOX_CLIENT_SECRET'] ?? null]
|
|
117
103
|
* @param {string | null | undefined} [opts.webhookSecret=process.env['FINCH_WEBHOOK_SECRET'] ?? null]
|
|
118
104
|
* @param {string} [opts.baseURL=process.env['FINCH_BASE_URL'] ?? https://api.tryfinch.com] - Override the default base URL for the API.
|
|
119
105
|
* @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
|
@@ -128,8 +114,6 @@ export class Finch extends Core.APIClient {
|
|
|
128
114
|
accessToken = null,
|
|
129
115
|
clientId = Core.readEnv('FINCH_CLIENT_ID') ?? null,
|
|
130
116
|
clientSecret = Core.readEnv('FINCH_CLIENT_SECRET') ?? null,
|
|
131
|
-
sandboxClientId = Core.readEnv('FINCH_SANDBOX_CLIENT_ID') ?? null,
|
|
132
|
-
sandboxClientSecret = Core.readEnv('FINCH_SANDBOX_CLIENT_SECRET') ?? null,
|
|
133
117
|
webhookSecret = Core.readEnv('FINCH_WEBHOOK_SECRET') ?? null,
|
|
134
118
|
...opts
|
|
135
119
|
}: ClientOptions = {}) {
|
|
@@ -137,8 +121,6 @@ export class Finch extends Core.APIClient {
|
|
|
137
121
|
accessToken,
|
|
138
122
|
clientId,
|
|
139
123
|
clientSecret,
|
|
140
|
-
sandboxClientId,
|
|
141
|
-
sandboxClientSecret,
|
|
142
124
|
webhookSecret,
|
|
143
125
|
...opts,
|
|
144
126
|
baseURL: baseURL || `https://api.tryfinch.com`,
|
|
@@ -157,8 +139,6 @@ export class Finch extends Core.APIClient {
|
|
|
157
139
|
this.accessToken = accessToken;
|
|
158
140
|
this.clientId = clientId;
|
|
159
141
|
this.clientSecret = clientSecret;
|
|
160
|
-
this.sandboxClientId = sandboxClientId;
|
|
161
|
-
this.sandboxClientSecret = sandboxClientSecret;
|
|
162
142
|
this.webhookSecret = webhookSecret;
|
|
163
143
|
}
|
|
164
144
|
|
|
@@ -171,6 +151,7 @@ export class Finch extends Core.APIClient {
|
|
|
171
151
|
jobs: API.Jobs = new API.Jobs(this);
|
|
172
152
|
sandbox: API.Sandbox = new API.Sandbox(this);
|
|
173
153
|
payroll: API.Payroll = new API.Payroll(this);
|
|
154
|
+
connect: API.Connect = new API.Connect(this);
|
|
174
155
|
|
|
175
156
|
/**
|
|
176
157
|
* DEPRECATED: use client.accessTokens.create instead.
|
|
@@ -250,7 +231,7 @@ export class Finch extends Core.APIClient {
|
|
|
250
231
|
return;
|
|
251
232
|
}
|
|
252
233
|
|
|
253
|
-
if (this.
|
|
234
|
+
if (this.clientId && this.clientSecret && headers['authorization']) {
|
|
254
235
|
return;
|
|
255
236
|
}
|
|
256
237
|
if (customHeaders['authorization'] === null) {
|
|
@@ -258,7 +239,7 @@ export class Finch extends Core.APIClient {
|
|
|
258
239
|
}
|
|
259
240
|
|
|
260
241
|
throw new Error(
|
|
261
|
-
'Could not resolve authentication method. Expected either accessToken,
|
|
242
|
+
'Could not resolve authentication method. Expected either accessToken, clientId or clientSecret to be set. Or for one of the "Authorization" or "Authorization" headers to be explicitly omitted',
|
|
262
243
|
);
|
|
263
244
|
}
|
|
264
245
|
|
|
@@ -280,15 +261,15 @@ export class Finch extends Core.APIClient {
|
|
|
280
261
|
}
|
|
281
262
|
|
|
282
263
|
protected basicAuth(opts: Core.FinalRequestOptions): Core.Headers {
|
|
283
|
-
if (!this.
|
|
264
|
+
if (!this.clientId) {
|
|
284
265
|
return {};
|
|
285
266
|
}
|
|
286
267
|
|
|
287
|
-
if (!this.
|
|
268
|
+
if (!this.clientSecret) {
|
|
288
269
|
return {};
|
|
289
270
|
}
|
|
290
271
|
|
|
291
|
-
const credentials = `${this.
|
|
272
|
+
const credentials = `${this.clientId}:${this.clientSecret}`;
|
|
292
273
|
const Authorization = `Basic ${Core.toBase64(credentials)}`;
|
|
293
274
|
return { Authorization };
|
|
294
275
|
}
|
|
@@ -393,6 +374,8 @@ export namespace Finch {
|
|
|
393
374
|
|
|
394
375
|
export import Payroll = API.Payroll;
|
|
395
376
|
|
|
377
|
+
export import Connect = API.Connect;
|
|
378
|
+
|
|
396
379
|
export import ConnectionStatusType = API.ConnectionStatusType;
|
|
397
380
|
export import OperationSupport = API.OperationSupport;
|
|
398
381
|
export import OperationSupportMatrix = API.OperationSupportMatrix;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/puruvj/neoqs/graphs/contributors) All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
8
|
+
|
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
10
|
+
|
|
11
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
12
|
+
|
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Format } from './types';
|
|
2
|
+
|
|
3
|
+
export const default_format: Format = 'RFC3986';
|
|
4
|
+
export const formatters: Record<Format, (str: PropertyKey) => string> = {
|
|
5
|
+
RFC1738: (v: PropertyKey) => String(v).replace(/%20/g, '+'),
|
|
6
|
+
RFC3986: (v: PropertyKey) => String(v),
|
|
7
|
+
};
|
|
8
|
+
export const RFC1738 = 'RFC1738';
|
|
9
|
+
export const RFC3986 = 'RFC3986';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default_format, formatters, RFC1738, RFC3986 } from './formats';
|
|
2
|
+
|
|
3
|
+
const formats = {
|
|
4
|
+
formatters,
|
|
5
|
+
RFC1738,
|
|
6
|
+
RFC3986,
|
|
7
|
+
default: default_format,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export { stringify } from './stringify';
|
|
11
|
+
export { formats };
|
|
12
|
+
|
|
13
|
+
export type { DefaultDecoder, DefaultEncoder, Format, ParseOptions, StringifyOptions } from './types';
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import { encode, is_buffer, maybe_map } from './utils';
|
|
2
|
+
import { default_format, formatters } from './formats';
|
|
3
|
+
import type { NonNullableProperties, StringifyOptions } from './types';
|
|
4
|
+
|
|
5
|
+
const has = Object.prototype.hasOwnProperty;
|
|
6
|
+
|
|
7
|
+
const array_prefix_generators = {
|
|
8
|
+
brackets(prefix: PropertyKey) {
|
|
9
|
+
return String(prefix) + '[]';
|
|
10
|
+
},
|
|
11
|
+
comma: 'comma',
|
|
12
|
+
indices(prefix: PropertyKey, key: string) {
|
|
13
|
+
return String(prefix) + '[' + key + ']';
|
|
14
|
+
},
|
|
15
|
+
repeat(prefix: PropertyKey) {
|
|
16
|
+
return String(prefix);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const is_array = Array.isArray;
|
|
21
|
+
const push = Array.prototype.push;
|
|
22
|
+
const push_to_array = function (arr: any[], value_or_array: any) {
|
|
23
|
+
push.apply(arr, is_array(value_or_array) ? value_or_array : [value_or_array]);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const to_ISO = Date.prototype.toISOString;
|
|
27
|
+
|
|
28
|
+
const defaults = {
|
|
29
|
+
addQueryPrefix: false,
|
|
30
|
+
allowDots: false,
|
|
31
|
+
allowEmptyArrays: false,
|
|
32
|
+
arrayFormat: 'indices',
|
|
33
|
+
charset: 'utf-8',
|
|
34
|
+
charsetSentinel: false,
|
|
35
|
+
delimiter: '&',
|
|
36
|
+
encode: true,
|
|
37
|
+
encodeDotInKeys: false,
|
|
38
|
+
encoder: encode,
|
|
39
|
+
encodeValuesOnly: false,
|
|
40
|
+
format: default_format,
|
|
41
|
+
formatter: formatters[default_format],
|
|
42
|
+
/** @deprecated */
|
|
43
|
+
indices: false,
|
|
44
|
+
serializeDate(date) {
|
|
45
|
+
return to_ISO.call(date);
|
|
46
|
+
},
|
|
47
|
+
skipNulls: false,
|
|
48
|
+
strictNullHandling: false,
|
|
49
|
+
} as NonNullableProperties<StringifyOptions & { formatter: (typeof formatters)['RFC1738'] }>;
|
|
50
|
+
|
|
51
|
+
function is_non_nullish_primitive(v: unknown): v is string | number | boolean | symbol | bigint {
|
|
52
|
+
return (
|
|
53
|
+
typeof v === 'string' ||
|
|
54
|
+
typeof v === 'number' ||
|
|
55
|
+
typeof v === 'boolean' ||
|
|
56
|
+
typeof v === 'symbol' ||
|
|
57
|
+
typeof v === 'bigint'
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const sentinel = {};
|
|
62
|
+
|
|
63
|
+
function inner_stringify(
|
|
64
|
+
object: any,
|
|
65
|
+
prefix: PropertyKey,
|
|
66
|
+
generateArrayPrefix: StringifyOptions['arrayFormat'] | ((prefix: string, key: string) => string),
|
|
67
|
+
commaRoundTrip: boolean,
|
|
68
|
+
allowEmptyArrays: boolean,
|
|
69
|
+
strictNullHandling: boolean,
|
|
70
|
+
skipNulls: boolean,
|
|
71
|
+
encodeDotInKeys: boolean,
|
|
72
|
+
encoder: StringifyOptions['encoder'],
|
|
73
|
+
filter: StringifyOptions['filter'],
|
|
74
|
+
sort: StringifyOptions['sort'],
|
|
75
|
+
allowDots: StringifyOptions['allowDots'],
|
|
76
|
+
serializeDate: StringifyOptions['serializeDate'],
|
|
77
|
+
format: StringifyOptions['format'],
|
|
78
|
+
formatter: StringifyOptions['formatter'],
|
|
79
|
+
encodeValuesOnly: boolean,
|
|
80
|
+
charset: StringifyOptions['charset'],
|
|
81
|
+
sideChannel: WeakMap<any, any>,
|
|
82
|
+
) {
|
|
83
|
+
let obj = object;
|
|
84
|
+
|
|
85
|
+
let tmp_sc = sideChannel;
|
|
86
|
+
let step = 0;
|
|
87
|
+
let find_flag = false;
|
|
88
|
+
while ((tmp_sc = tmp_sc.get(sentinel)) !== void undefined && !find_flag) {
|
|
89
|
+
// Where object last appeared in the ref tree
|
|
90
|
+
const pos = tmp_sc.get(object);
|
|
91
|
+
step += 1;
|
|
92
|
+
if (typeof pos !== 'undefined') {
|
|
93
|
+
if (pos === step) {
|
|
94
|
+
throw new RangeError('Cyclic object value');
|
|
95
|
+
} else {
|
|
96
|
+
find_flag = true; // Break while
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (typeof tmp_sc.get(sentinel) === 'undefined') {
|
|
100
|
+
step = 0;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (typeof filter === 'function') {
|
|
105
|
+
obj = filter(prefix, obj);
|
|
106
|
+
} else if (obj instanceof Date) {
|
|
107
|
+
obj = serializeDate?.(obj);
|
|
108
|
+
} else if (generateArrayPrefix === 'comma' && is_array(obj)) {
|
|
109
|
+
obj = maybe_map(obj, function (value) {
|
|
110
|
+
if (value instanceof Date) {
|
|
111
|
+
return serializeDate?.(value);
|
|
112
|
+
}
|
|
113
|
+
return value;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (obj === null) {
|
|
118
|
+
if (strictNullHandling) {
|
|
119
|
+
return encoder && !encodeValuesOnly ?
|
|
120
|
+
// @ts-expect-error
|
|
121
|
+
encoder(prefix, defaults.encoder, charset, 'key', format)
|
|
122
|
+
: prefix;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
obj = '';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (is_non_nullish_primitive(obj) || is_buffer(obj)) {
|
|
129
|
+
if (encoder) {
|
|
130
|
+
const key_value =
|
|
131
|
+
encodeValuesOnly ? prefix
|
|
132
|
+
// @ts-expect-error
|
|
133
|
+
: encoder(prefix, defaults.encoder, charset, 'key', format);
|
|
134
|
+
return [
|
|
135
|
+
formatter?.(key_value) +
|
|
136
|
+
'=' +
|
|
137
|
+
// @ts-expect-error
|
|
138
|
+
formatter?.(encoder(obj, defaults.encoder, charset, 'value', format)),
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
return [formatter?.(prefix) + '=' + formatter?.(String(obj))];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const values: string[] = [];
|
|
145
|
+
|
|
146
|
+
if (typeof obj === 'undefined') {
|
|
147
|
+
return values;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let obj_keys;
|
|
151
|
+
if (generateArrayPrefix === 'comma' && is_array(obj)) {
|
|
152
|
+
// we need to join elements in
|
|
153
|
+
if (encodeValuesOnly && encoder) {
|
|
154
|
+
// @ts-expect-error values only
|
|
155
|
+
obj = maybe_map(obj, encoder);
|
|
156
|
+
}
|
|
157
|
+
obj_keys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];
|
|
158
|
+
} else if (is_array(filter)) {
|
|
159
|
+
obj_keys = filter;
|
|
160
|
+
} else {
|
|
161
|
+
const keys = Object.keys(obj);
|
|
162
|
+
obj_keys = sort ? keys.sort(sort) : keys;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const encoded_prefix = encodeDotInKeys ? String(prefix).replace(/\./g, '%2E') : String(prefix);
|
|
166
|
+
|
|
167
|
+
const adjusted_prefix =
|
|
168
|
+
commaRoundTrip && is_array(obj) && obj.length === 1 ? encoded_prefix + '[]' : encoded_prefix;
|
|
169
|
+
|
|
170
|
+
if (allowEmptyArrays && is_array(obj) && obj.length === 0) {
|
|
171
|
+
return adjusted_prefix + '[]';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (let j = 0; j < obj_keys.length; ++j) {
|
|
175
|
+
const key = obj_keys[j];
|
|
176
|
+
const value =
|
|
177
|
+
// @ts-ignore
|
|
178
|
+
typeof key === 'object' && typeof key.value !== 'undefined' ? key.value : obj[key as any];
|
|
179
|
+
|
|
180
|
+
if (skipNulls && value === null) {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// @ts-ignore
|
|
185
|
+
const encoded_key = allowDots && encodeDotInKeys ? (key as any).replace(/\./g, '%2E') : key;
|
|
186
|
+
const key_prefix =
|
|
187
|
+
is_array(obj) ?
|
|
188
|
+
typeof generateArrayPrefix === 'function' ?
|
|
189
|
+
generateArrayPrefix(adjusted_prefix, encoded_key)
|
|
190
|
+
: adjusted_prefix
|
|
191
|
+
: adjusted_prefix + (allowDots ? '.' + encoded_key : '[' + encoded_key + ']');
|
|
192
|
+
|
|
193
|
+
sideChannel.set(object, step);
|
|
194
|
+
const valueSideChannel = new WeakMap();
|
|
195
|
+
valueSideChannel.set(sentinel, sideChannel);
|
|
196
|
+
push_to_array(
|
|
197
|
+
values,
|
|
198
|
+
inner_stringify(
|
|
199
|
+
value,
|
|
200
|
+
key_prefix,
|
|
201
|
+
generateArrayPrefix,
|
|
202
|
+
commaRoundTrip,
|
|
203
|
+
allowEmptyArrays,
|
|
204
|
+
strictNullHandling,
|
|
205
|
+
skipNulls,
|
|
206
|
+
encodeDotInKeys,
|
|
207
|
+
// @ts-ignore
|
|
208
|
+
generateArrayPrefix === 'comma' && encodeValuesOnly && is_array(obj) ? null : encoder,
|
|
209
|
+
filter,
|
|
210
|
+
sort,
|
|
211
|
+
allowDots,
|
|
212
|
+
serializeDate,
|
|
213
|
+
format,
|
|
214
|
+
formatter,
|
|
215
|
+
encodeValuesOnly,
|
|
216
|
+
charset,
|
|
217
|
+
valueSideChannel,
|
|
218
|
+
),
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return values;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function normalize_stringify_options(
|
|
226
|
+
opts: StringifyOptions = defaults,
|
|
227
|
+
): NonNullableProperties<Omit<StringifyOptions, 'indices'>> & { indices?: boolean } {
|
|
228
|
+
if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {
|
|
229
|
+
throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') {
|
|
233
|
+
throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') {
|
|
237
|
+
throw new TypeError('Encoder has to be a function.');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const charset = opts.charset || defaults.charset;
|
|
241
|
+
if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
|
|
242
|
+
throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
let format = default_format;
|
|
246
|
+
if (typeof opts.format !== 'undefined') {
|
|
247
|
+
if (!has.call(formatters, opts.format)) {
|
|
248
|
+
throw new TypeError('Unknown format option provided.');
|
|
249
|
+
}
|
|
250
|
+
format = opts.format;
|
|
251
|
+
}
|
|
252
|
+
const formatter = formatters[format];
|
|
253
|
+
|
|
254
|
+
let filter = defaults.filter;
|
|
255
|
+
if (typeof opts.filter === 'function' || is_array(opts.filter)) {
|
|
256
|
+
filter = opts.filter;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
let arrayFormat: StringifyOptions['arrayFormat'];
|
|
260
|
+
if (opts.arrayFormat && opts.arrayFormat in array_prefix_generators) {
|
|
261
|
+
arrayFormat = opts.arrayFormat;
|
|
262
|
+
} else if ('indices' in opts) {
|
|
263
|
+
arrayFormat = opts.indices ? 'indices' : 'repeat';
|
|
264
|
+
} else {
|
|
265
|
+
arrayFormat = defaults.arrayFormat;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') {
|
|
269
|
+
throw new TypeError('`commaRoundTrip` must be a boolean, or absent');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const allowDots =
|
|
273
|
+
typeof opts.allowDots === 'undefined' ?
|
|
274
|
+
!!opts.encodeDotInKeys === true ?
|
|
275
|
+
true
|
|
276
|
+
: defaults.allowDots
|
|
277
|
+
: !!opts.allowDots;
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,
|
|
281
|
+
// @ts-ignore
|
|
282
|
+
allowDots: allowDots,
|
|
283
|
+
allowEmptyArrays:
|
|
284
|
+
typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
|
|
285
|
+
arrayFormat: arrayFormat,
|
|
286
|
+
charset: charset,
|
|
287
|
+
charsetSentinel:
|
|
288
|
+
typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
|
|
289
|
+
commaRoundTrip: !!opts.commaRoundTrip,
|
|
290
|
+
delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,
|
|
291
|
+
encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,
|
|
292
|
+
encodeDotInKeys:
|
|
293
|
+
typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys,
|
|
294
|
+
encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,
|
|
295
|
+
encodeValuesOnly:
|
|
296
|
+
typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,
|
|
297
|
+
filter: filter,
|
|
298
|
+
format: format,
|
|
299
|
+
formatter: formatter,
|
|
300
|
+
serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate,
|
|
301
|
+
skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls,
|
|
302
|
+
// @ts-ignore
|
|
303
|
+
sort: typeof opts.sort === 'function' ? opts.sort : null,
|
|
304
|
+
strictNullHandling:
|
|
305
|
+
typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export function stringify(object: any, opts: StringifyOptions = {}) {
|
|
310
|
+
let obj = object;
|
|
311
|
+
const options = normalize_stringify_options(opts);
|
|
312
|
+
|
|
313
|
+
let obj_keys: PropertyKey[] | undefined;
|
|
314
|
+
let filter;
|
|
315
|
+
|
|
316
|
+
if (typeof options.filter === 'function') {
|
|
317
|
+
filter = options.filter;
|
|
318
|
+
obj = filter('', obj);
|
|
319
|
+
} else if (is_array(options.filter)) {
|
|
320
|
+
filter = options.filter;
|
|
321
|
+
obj_keys = filter;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const keys: string[] = [];
|
|
325
|
+
|
|
326
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
327
|
+
return '';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const generateArrayPrefix = array_prefix_generators[options.arrayFormat];
|
|
331
|
+
const commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip;
|
|
332
|
+
|
|
333
|
+
if (!obj_keys) {
|
|
334
|
+
obj_keys = Object.keys(obj);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (options.sort) {
|
|
338
|
+
obj_keys.sort(options.sort);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const sideChannel = new WeakMap();
|
|
342
|
+
for (let i = 0; i < obj_keys.length; ++i) {
|
|
343
|
+
const key = obj_keys[i]!;
|
|
344
|
+
|
|
345
|
+
if (options.skipNulls && obj[key] === null) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
push_to_array(
|
|
349
|
+
keys,
|
|
350
|
+
inner_stringify(
|
|
351
|
+
obj[key],
|
|
352
|
+
key,
|
|
353
|
+
// @ts-expect-error
|
|
354
|
+
generateArrayPrefix,
|
|
355
|
+
commaRoundTrip,
|
|
356
|
+
options.allowEmptyArrays,
|
|
357
|
+
options.strictNullHandling,
|
|
358
|
+
options.skipNulls,
|
|
359
|
+
options.encodeDotInKeys,
|
|
360
|
+
options.encode ? options.encoder : null,
|
|
361
|
+
options.filter,
|
|
362
|
+
options.sort,
|
|
363
|
+
options.allowDots,
|
|
364
|
+
options.serializeDate,
|
|
365
|
+
options.format,
|
|
366
|
+
options.formatter,
|
|
367
|
+
options.encodeValuesOnly,
|
|
368
|
+
options.charset,
|
|
369
|
+
sideChannel,
|
|
370
|
+
),
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const joined = keys.join(options.delimiter);
|
|
375
|
+
let prefix = options.addQueryPrefix === true ? '?' : '';
|
|
376
|
+
|
|
377
|
+
if (options.charsetSentinel) {
|
|
378
|
+
if (options.charset === 'iso-8859-1') {
|
|
379
|
+
// encodeURIComponent('✓'), the "numeric entity" representation of a checkmark
|
|
380
|
+
prefix += 'utf8=%26%2310003%3B&';
|
|
381
|
+
} else {
|
|
382
|
+
// encodeURIComponent('✓')
|
|
383
|
+
prefix += 'utf8=%E2%9C%93&';
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return joined.length > 0 ? prefix + joined : '';
|
|
388
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export type Format = 'RFC1738' | 'RFC3986';
|
|
2
|
+
|
|
3
|
+
export type DefaultEncoder = (str: any, defaultEncoder?: any, charset?: string) => string;
|
|
4
|
+
export type DefaultDecoder = (str: string, decoder?: any, charset?: string) => string;
|
|
5
|
+
|
|
6
|
+
export type BooleanOptional = boolean | undefined;
|
|
7
|
+
|
|
8
|
+
export type StringifyBaseOptions = {
|
|
9
|
+
delimiter?: string;
|
|
10
|
+
allowDots?: boolean;
|
|
11
|
+
encodeDotInKeys?: boolean;
|
|
12
|
+
strictNullHandling?: boolean;
|
|
13
|
+
skipNulls?: boolean;
|
|
14
|
+
encode?: boolean;
|
|
15
|
+
encoder?: (
|
|
16
|
+
str: any,
|
|
17
|
+
defaultEncoder: DefaultEncoder,
|
|
18
|
+
charset: string,
|
|
19
|
+
type: 'key' | 'value',
|
|
20
|
+
format?: Format,
|
|
21
|
+
) => string;
|
|
22
|
+
filter?: Array<PropertyKey> | ((prefix: PropertyKey, value: any) => any);
|
|
23
|
+
arrayFormat?: 'indices' | 'brackets' | 'repeat' | 'comma';
|
|
24
|
+
indices?: boolean;
|
|
25
|
+
sort?: ((a: PropertyKey, b: PropertyKey) => number) | null;
|
|
26
|
+
serializeDate?: (d: Date) => string;
|
|
27
|
+
format?: 'RFC1738' | 'RFC3986';
|
|
28
|
+
formatter?: (str: PropertyKey) => string;
|
|
29
|
+
encodeValuesOnly?: boolean;
|
|
30
|
+
addQueryPrefix?: boolean;
|
|
31
|
+
charset?: 'utf-8' | 'iso-8859-1';
|
|
32
|
+
charsetSentinel?: boolean;
|
|
33
|
+
allowEmptyArrays?: boolean;
|
|
34
|
+
commaRoundTrip?: boolean;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type StringifyOptions = StringifyBaseOptions;
|
|
38
|
+
|
|
39
|
+
export type ParseBaseOptions = {
|
|
40
|
+
comma?: boolean;
|
|
41
|
+
delimiter?: string | RegExp;
|
|
42
|
+
depth?: number | false;
|
|
43
|
+
decoder?: (str: string, defaultDecoder: DefaultDecoder, charset: string, type: 'key' | 'value') => any;
|
|
44
|
+
arrayLimit?: number;
|
|
45
|
+
parseArrays?: boolean;
|
|
46
|
+
plainObjects?: boolean;
|
|
47
|
+
allowPrototypes?: boolean;
|
|
48
|
+
allowSparse?: boolean;
|
|
49
|
+
parameterLimit?: number;
|
|
50
|
+
strictDepth?: boolean;
|
|
51
|
+
strictNullHandling?: boolean;
|
|
52
|
+
ignoreQueryPrefix?: boolean;
|
|
53
|
+
charset?: 'utf-8' | 'iso-8859-1';
|
|
54
|
+
charsetSentinel?: boolean;
|
|
55
|
+
interpretNumericEntities?: boolean;
|
|
56
|
+
allowEmptyArrays?: boolean;
|
|
57
|
+
duplicates?: 'combine' | 'first' | 'last';
|
|
58
|
+
allowDots?: boolean;
|
|
59
|
+
decodeDotInKeys?: boolean;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type ParseOptions = ParseBaseOptions;
|
|
63
|
+
|
|
64
|
+
export type ParsedQs = {
|
|
65
|
+
[key: string]: undefined | string | string[] | ParsedQs | ParsedQs[];
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Type to remove null or undefined union from each property
|
|
69
|
+
export type NonNullableProperties<T> = {
|
|
70
|
+
[K in keyof T]-?: Exclude<T[K], undefined | null>;
|
|
71
|
+
};
|