@v3finance/core-sdk 0.1.0 → 0.2.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 +397 -7
- package/README.md +215 -72
- package/dist/cjs/client.d.ts +67 -22
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +38 -2
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/core/errors.d.ts +30 -10
- package/dist/cjs/core/errors.d.ts.map +1 -1
- package/dist/cjs/core/errors.js +47 -15
- package/dist/cjs/core/errors.js.map +1 -1
- package/dist/cjs/core/gated.d.ts +21 -3
- package/dist/cjs/core/gated.d.ts.map +1 -1
- package/dist/cjs/core/gated.js +12 -3
- package/dist/cjs/core/gated.js.map +1 -1
- package/dist/cjs/core/http.d.ts +12 -8
- package/dist/cjs/core/http.d.ts.map +1 -1
- package/dist/cjs/core/http.js +130 -40
- package/dist/cjs/core/http.js.map +1 -1
- package/dist/cjs/core/pagination.d.ts +28 -1
- package/dist/cjs/core/pagination.d.ts.map +1 -1
- package/dist/cjs/core/pagination.js +36 -1
- package/dist/cjs/core/pagination.js.map +1 -1
- package/dist/cjs/generated/operations.js +1 -1
- package/dist/cjs/generated/types.d.ts +948 -172
- package/dist/cjs/generated/types.d.ts.map +1 -1
- package/dist/cjs/index.d.ts +32 -8
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/resources/addresses.d.ts +22 -8
- package/dist/cjs/resources/addresses.d.ts.map +1 -1
- package/dist/cjs/resources/addresses.js +7 -1
- package/dist/cjs/resources/addresses.js.map +1 -1
- package/dist/cjs/resources/admin.d.ts +150 -25
- package/dist/cjs/resources/admin.d.ts.map +1 -1
- package/dist/cjs/resources/admin.js +94 -23
- package/dist/cjs/resources/admin.js.map +1 -1
- package/dist/cjs/resources/approvals.d.ts +46 -5
- package/dist/cjs/resources/approvals.d.ts.map +1 -1
- package/dist/cjs/resources/approvals.js +27 -4
- package/dist/cjs/resources/approvals.js.map +1 -1
- package/dist/cjs/resources/balances.d.ts +152 -16
- package/dist/cjs/resources/balances.d.ts.map +1 -1
- package/dist/cjs/resources/balances.js +9 -5
- package/dist/cjs/resources/balances.js.map +1 -1
- package/dist/cjs/resources/categories.d.ts +93 -21
- package/dist/cjs/resources/categories.d.ts.map +1 -1
- package/dist/cjs/resources/categories.js +65 -18
- package/dist/cjs/resources/categories.js.map +1 -1
- package/dist/cjs/resources/counterparties.d.ts +26 -3
- package/dist/cjs/resources/counterparties.d.ts.map +1 -1
- package/dist/cjs/resources/counterparties.js +17 -0
- package/dist/cjs/resources/counterparties.js.map +1 -1
- package/dist/cjs/resources/folders.d.ts +51 -10
- package/dist/cjs/resources/folders.d.ts.map +1 -1
- package/dist/cjs/resources/folders.js +36 -5
- package/dist/cjs/resources/folders.js.map +1 -1
- package/dist/cjs/resources/history.d.ts +20 -2
- package/dist/cjs/resources/history.d.ts.map +1 -1
- package/dist/cjs/resources/history.js.map +1 -1
- package/dist/cjs/resources/me.d.ts +27 -4
- package/dist/cjs/resources/me.d.ts.map +1 -1
- package/dist/cjs/resources/me.js +22 -1
- package/dist/cjs/resources/me.js.map +1 -1
- package/dist/cjs/resources/members.d.ts +19 -4
- package/dist/cjs/resources/members.d.ts.map +1 -1
- package/dist/cjs/resources/members.js +15 -6
- package/dist/cjs/resources/members.js.map +1 -1
- package/dist/cjs/resources/operations.d.ts +64 -8
- package/dist/cjs/resources/operations.d.ts.map +1 -1
- package/dist/cjs/resources/operations.js +26 -2
- package/dist/cjs/resources/operations.js.map +1 -1
- package/dist/cjs/resources/registries.d.ts +87 -9
- package/dist/cjs/resources/registries.d.ts.map +1 -1
- package/dist/cjs/resources/registries.js +54 -11
- package/dist/cjs/resources/registries.js.map +1 -1
- package/dist/cjs/resources/reports.d.ts +300 -41
- package/dist/cjs/resources/reports.d.ts.map +1 -1
- package/dist/cjs/resources/reports.js +135 -7
- package/dist/cjs/resources/reports.js.map +1 -1
- package/dist/cjs/resources/sharing.d.ts +61 -10
- package/dist/cjs/resources/sharing.d.ts.map +1 -1
- package/dist/cjs/resources/sharing.js +51 -4
- package/dist/cjs/resources/sharing.js.map +1 -1
- package/dist/cjs/resources/transfers.d.ts +26 -4
- package/dist/cjs/resources/transfers.d.ts.map +1 -1
- package/dist/cjs/resources/transfers.js +23 -1
- package/dist/cjs/resources/transfers.js.map +1 -1
- package/dist/cjs/resources/types.d.ts +20 -0
- package/dist/cjs/resources/types.d.ts.map +1 -1
- package/dist/cjs/units.d.ts.map +1 -1
- package/dist/cjs/units.js +18 -2
- package/dist/cjs/units.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client.d.ts +67 -22
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +38 -2
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/core/errors.d.ts +30 -10
- package/dist/esm/core/errors.d.ts.map +1 -1
- package/dist/esm/core/errors.js +47 -15
- package/dist/esm/core/errors.js.map +1 -1
- package/dist/esm/core/gated.d.ts +21 -3
- package/dist/esm/core/gated.d.ts.map +1 -1
- package/dist/esm/core/gated.js +12 -3
- package/dist/esm/core/gated.js.map +1 -1
- package/dist/esm/core/http.d.ts +12 -8
- package/dist/esm/core/http.d.ts.map +1 -1
- package/dist/esm/core/http.js +131 -41
- package/dist/esm/core/http.js.map +1 -1
- package/dist/esm/core/pagination.d.ts +28 -1
- package/dist/esm/core/pagination.d.ts.map +1 -1
- package/dist/esm/core/pagination.js +36 -1
- package/dist/esm/core/pagination.js.map +1 -1
- package/dist/esm/generated/operations.js +1 -1
- package/dist/esm/generated/types.d.ts +948 -172
- package/dist/esm/generated/types.d.ts.map +1 -1
- package/dist/esm/index.d.ts +32 -8
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +17 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/resources/addresses.d.ts +22 -8
- package/dist/esm/resources/addresses.d.ts.map +1 -1
- package/dist/esm/resources/addresses.js +7 -1
- package/dist/esm/resources/addresses.js.map +1 -1
- package/dist/esm/resources/admin.d.ts +150 -25
- package/dist/esm/resources/admin.d.ts.map +1 -1
- package/dist/esm/resources/admin.js +94 -23
- package/dist/esm/resources/admin.js.map +1 -1
- package/dist/esm/resources/approvals.d.ts +46 -5
- package/dist/esm/resources/approvals.d.ts.map +1 -1
- package/dist/esm/resources/approvals.js +27 -4
- package/dist/esm/resources/approvals.js.map +1 -1
- package/dist/esm/resources/balances.d.ts +152 -16
- package/dist/esm/resources/balances.d.ts.map +1 -1
- package/dist/esm/resources/balances.js +9 -5
- package/dist/esm/resources/balances.js.map +1 -1
- package/dist/esm/resources/categories.d.ts +93 -21
- package/dist/esm/resources/categories.d.ts.map +1 -1
- package/dist/esm/resources/categories.js +65 -18
- package/dist/esm/resources/categories.js.map +1 -1
- package/dist/esm/resources/counterparties.d.ts +26 -3
- package/dist/esm/resources/counterparties.d.ts.map +1 -1
- package/dist/esm/resources/counterparties.js +17 -0
- package/dist/esm/resources/counterparties.js.map +1 -1
- package/dist/esm/resources/folders.d.ts +51 -10
- package/dist/esm/resources/folders.d.ts.map +1 -1
- package/dist/esm/resources/folders.js +36 -5
- package/dist/esm/resources/folders.js.map +1 -1
- package/dist/esm/resources/history.d.ts +20 -2
- package/dist/esm/resources/history.d.ts.map +1 -1
- package/dist/esm/resources/history.js.map +1 -1
- package/dist/esm/resources/me.d.ts +27 -4
- package/dist/esm/resources/me.d.ts.map +1 -1
- package/dist/esm/resources/me.js +22 -1
- package/dist/esm/resources/me.js.map +1 -1
- package/dist/esm/resources/members.d.ts +19 -4
- package/dist/esm/resources/members.d.ts.map +1 -1
- package/dist/esm/resources/members.js +15 -6
- package/dist/esm/resources/members.js.map +1 -1
- package/dist/esm/resources/operations.d.ts +64 -8
- package/dist/esm/resources/operations.d.ts.map +1 -1
- package/dist/esm/resources/operations.js +26 -2
- package/dist/esm/resources/operations.js.map +1 -1
- package/dist/esm/resources/registries.d.ts +87 -9
- package/dist/esm/resources/registries.d.ts.map +1 -1
- package/dist/esm/resources/registries.js +54 -11
- package/dist/esm/resources/registries.js.map +1 -1
- package/dist/esm/resources/reports.d.ts +300 -41
- package/dist/esm/resources/reports.d.ts.map +1 -1
- package/dist/esm/resources/reports.js +135 -7
- package/dist/esm/resources/reports.js.map +1 -1
- package/dist/esm/resources/sharing.d.ts +61 -10
- package/dist/esm/resources/sharing.d.ts.map +1 -1
- package/dist/esm/resources/sharing.js +51 -4
- package/dist/esm/resources/sharing.js.map +1 -1
- package/dist/esm/resources/transfers.d.ts +26 -4
- package/dist/esm/resources/transfers.d.ts.map +1 -1
- package/dist/esm/resources/transfers.js +23 -1
- package/dist/esm/resources/transfers.js.map +1 -1
- package/dist/esm/resources/types.d.ts +20 -0
- package/dist/esm/resources/types.d.ts.map +1 -1
- package/dist/esm/units.d.ts.map +1 -1
- package/dist/esm/units.js +18 -2
- package/dist/esm/units.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/docs/concepts.md +191 -0
- package/docs/errors.md +471 -0
- package/package.json +7 -6
- package/src/client.ts +89 -25
- package/src/core/errors.ts +49 -15
- package/src/core/gated.ts +22 -4
- package/src/core/http.ts +156 -46
- package/src/core/pagination.ts +38 -1
- package/src/generated/operations.ts +1 -1
- package/src/generated/types.ts +983 -173
- package/src/index.ts +64 -7
- package/src/resources/addresses.ts +23 -8
- package/src/resources/admin.ts +186 -33
- package/src/resources/approvals.ts +55 -9
- package/src/resources/balances.ts +186 -14
- package/src/resources/categories.ts +125 -30
- package/src/resources/counterparties.ts +23 -6
- package/src/resources/folders.ts +74 -18
- package/src/resources/history.ts +27 -2
- package/src/resources/me.ts +30 -5
- package/src/resources/members.ts +26 -7
- package/src/resources/operations.ts +73 -8
- package/src/resources/registries.ts +90 -11
- package/src/resources/reports.ts +348 -67
- package/src/resources/sharing.ts +71 -18
- package/src/resources/transfers.ts +33 -5
- package/src/resources/types.ts +20 -0
- package/src/units.ts +19 -2
- package/src/version.ts +1 -1
package/dist/esm/core/http.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { abortedError, networkError, parseError, parseErrorBody, timeoutError, } from './errors.js';
|
|
1
|
+
import { abortedError, isCoreError, networkError, parseError, parseErrorBody, timeoutError, } from './errors.js';
|
|
2
2
|
import { SDK_VERSION } from '../version.js';
|
|
3
3
|
/**
|
|
4
4
|
* The HTTP layer shared by every resource.
|
|
@@ -81,13 +81,18 @@ export class HttpClient {
|
|
|
81
81
|
* time. Read it with `.blob()`, `.text()` or `.arrayBuffer()`.
|
|
82
82
|
*/
|
|
83
83
|
async fetchRaw(method, path, options = {}) {
|
|
84
|
-
|
|
84
|
+
// The body is touched only when the call FAILED — and then by the same
|
|
85
|
+
// reader a JSON call uses, so one 502 from the edge produces one message
|
|
86
|
+
// whichever method asked for it. The two used to disagree: this one fell
|
|
87
|
+
// back to neutral wording while `requestRaw` put the proxy's HTML page
|
|
88
|
+
// into `message`.
|
|
89
|
+
//
|
|
90
|
+
// On success the response is handed over unread, which also means the
|
|
91
|
+
// timeout ends at the headers here: the file body is the caller's to read
|
|
92
|
+
// and to bound, with their own signal.
|
|
93
|
+
const { response, endpoint, payload } = await this.#send(method, path, options, (r, ep) => r.ok ? Promise.resolve(undefined) : readJsonBody(r, ep));
|
|
85
94
|
if (!response.ok) {
|
|
86
|
-
const
|
|
87
|
-
.clone()
|
|
88
|
-
.json()
|
|
89
|
-
.catch(() => undefined);
|
|
90
|
-
const error = parseErrorBody(response.status, body, endpoint);
|
|
95
|
+
const error = parseErrorBody(response.status, payload, endpoint);
|
|
91
96
|
if (response.status === 401 && this.#options.onUnauthorized) {
|
|
92
97
|
await this.#options.onUnauthorized(error);
|
|
93
98
|
}
|
|
@@ -97,18 +102,28 @@ export class HttpClient {
|
|
|
97
102
|
}
|
|
98
103
|
/** Same, but exposes the status — needed where 200 and 202 mean different things. */
|
|
99
104
|
async requestRaw(method, path, options = {}) {
|
|
100
|
-
const { response, endpoint } = await this.#send(method, path, options);
|
|
101
|
-
const data = await readBody(response, endpoint);
|
|
105
|
+
const { response, endpoint, payload } = await this.#send(method, path, options, readJsonBody);
|
|
102
106
|
if (!response.ok) {
|
|
103
|
-
const error = parseErrorBody(response.status,
|
|
107
|
+
const error = parseErrorBody(response.status, payload, endpoint);
|
|
104
108
|
if (response.status === 401 && this.#options.onUnauthorized) {
|
|
105
109
|
await this.#options.onUnauthorized(error);
|
|
106
110
|
}
|
|
107
111
|
throw error;
|
|
108
112
|
}
|
|
109
|
-
return { status: response.status, data:
|
|
113
|
+
return { status: response.status, data: payload, headers: response.headers };
|
|
110
114
|
}
|
|
111
|
-
|
|
115
|
+
/**
|
|
116
|
+
* One attempt: headers out, body in, cleanup.
|
|
117
|
+
*
|
|
118
|
+
* The body is read HERE, through `readPayload`, instead of by the caller
|
|
119
|
+
* afterwards — because the timeout and the caller's signal have to stay
|
|
120
|
+
* armed until the body is in hand. Headers arrive first and the body streams
|
|
121
|
+
* after; with the timer cleared at the headers, a server that answers and
|
|
122
|
+
* then stalls mid-body left a request hanging with nothing to end it. On a
|
|
123
|
+
* money path that is a transfer whose outcome is never learned, and no
|
|
124
|
+
* retry decision either.
|
|
125
|
+
*/
|
|
126
|
+
async #send(method, path, options, readPayload) {
|
|
112
127
|
const endpoint = `${method.toUpperCase()} ${path}`;
|
|
113
128
|
const url = `${this.baseUrl}${path}${serializeQuery(options.query)}`;
|
|
114
129
|
const timeoutMs = options.timeoutMs ?? this.#timeoutMs;
|
|
@@ -121,8 +136,14 @@ export class HttpClient {
|
|
|
121
136
|
};
|
|
122
137
|
if (options.body !== undefined)
|
|
123
138
|
headers['content-type'] = 'application/json';
|
|
124
|
-
|
|
125
|
-
|
|
139
|
+
// NOTHING ELSE IS ADDED BY DEFAULT, and that is a browser constraint
|
|
140
|
+
// rather than minimalism: the API's CORS preflight allows exactly
|
|
141
|
+
// `Content-Type` and `Authorization`, so any further header of ours makes
|
|
142
|
+
// the preflight fail and the request is never sent. These three are safe —
|
|
143
|
+
// `accept` is CORS-safelisted, and `user-agent` is a forbidden header name
|
|
144
|
+
// the browser drops before it can be preflighted (it still reaches the API
|
|
145
|
+
// from Node and React Native, which is where it is useful). A header
|
|
146
|
+
// passed in through `headers` is the caller's own risk.
|
|
126
147
|
// A timer of our own on top of the caller's signal: `AbortSignal.timeout`
|
|
127
148
|
// is missing in some React Native runtimes, and "the caller cancelled" has
|
|
128
149
|
// to stay distinguishable from "time ran out" — on money paths those call
|
|
@@ -135,44 +156,88 @@ export class HttpClient {
|
|
|
135
156
|
}, timeoutMs);
|
|
136
157
|
const onExternalAbort = () => controller.abort();
|
|
137
158
|
options.signal?.addEventListener('abort', onExternalAbort, { once: true });
|
|
138
|
-
|
|
159
|
+
const classify = (cause) => transportError(cause, { timedOut, timeoutMs, endpoint, signal: options.signal });
|
|
160
|
+
// The cleanup is an OUTER finally, so it also runs when `onTokenRotated`
|
|
161
|
+
// throws — a caller's storage failure should not leave our timer armed,
|
|
162
|
+
// ready to abort an unrelated stream seconds later.
|
|
139
163
|
try {
|
|
140
|
-
response
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
? {}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
164
|
+
let response;
|
|
165
|
+
try {
|
|
166
|
+
response = await this.#fetch(url, {
|
|
167
|
+
method: method.toUpperCase(),
|
|
168
|
+
headers,
|
|
169
|
+
...(options.body === undefined ? {} : { body: JSON.stringify(options.body) }),
|
|
170
|
+
...(this.#options.credentials === undefined
|
|
171
|
+
? {}
|
|
172
|
+
: { credentials: this.#options.credentials }),
|
|
173
|
+
signal: controller.signal,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (cause) {
|
|
177
|
+
throw classify(cause);
|
|
178
|
+
}
|
|
179
|
+
// Rotation arrives on successful responses too, and is taken BEFORE the
|
|
180
|
+
// body: the token is valid whatever the body turns out to be, and a
|
|
181
|
+
// rotation we drop signs the client out at the next one.
|
|
182
|
+
const rotated = response.headers.get(ROTATED_TOKEN_HEADER);
|
|
183
|
+
if (rotated && this.#options.onTokenRotated)
|
|
184
|
+
await this.#options.onTokenRotated(rotated);
|
|
185
|
+
let payload;
|
|
186
|
+
try {
|
|
187
|
+
payload = await readPayload(response, endpoint);
|
|
188
|
+
}
|
|
189
|
+
catch (cause) {
|
|
190
|
+
throw classify(cause);
|
|
191
|
+
}
|
|
192
|
+
return { response, endpoint, payload };
|
|
156
193
|
}
|
|
157
194
|
finally {
|
|
158
195
|
clearTimeout(timer);
|
|
159
196
|
options.signal?.removeEventListener('abort', onExternalAbort);
|
|
160
197
|
}
|
|
161
|
-
// Rotation arrives on successful responses too.
|
|
162
|
-
const rotated = response.headers.get(ROTATED_TOKEN_HEADER);
|
|
163
|
-
if (rotated && this.#options.onTokenRotated)
|
|
164
|
-
await this.#options.onTokenRotated(rotated);
|
|
165
|
-
return { response, endpoint };
|
|
166
198
|
}
|
|
167
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Names a transport failure, of the request or of the body behind it.
|
|
202
|
+
*
|
|
203
|
+
* The distinction is not cosmetic on a money path: a timeout may have been
|
|
204
|
+
* applied server-side (retry only with the same idempotency key), a cancel is
|
|
205
|
+
* the caller's own decision and must not be shown as a failure, and a network
|
|
206
|
+
* error never left the device. A `CoreError` arrives already named — the body
|
|
207
|
+
* reader raises one when a successful response is not the JSON the contract
|
|
208
|
+
* promises — and is passed through, so "the contract is wrong" is not reported
|
|
209
|
+
* as "the network is down".
|
|
210
|
+
*
|
|
211
|
+
* Our own timeout wins over the caller's signal, and both win over the cause:
|
|
212
|
+
* an abort mid-body surfaces as the abort that caused it, not as the opaque
|
|
213
|
+
* `AbortError` the stream rejects with.
|
|
214
|
+
*/
|
|
215
|
+
function transportError(cause, ctx) {
|
|
216
|
+
if (ctx.timedOut)
|
|
217
|
+
return timeoutError(ctx.timeoutMs, ctx.endpoint);
|
|
218
|
+
if (ctx.signal?.aborted)
|
|
219
|
+
return abortedError(ctx.endpoint);
|
|
220
|
+
if (isCoreError(cause))
|
|
221
|
+
return cause;
|
|
222
|
+
return networkError(cause, ctx.endpoint);
|
|
223
|
+
}
|
|
224
|
+
/** The longest fragment of a non-JSON error body worth carrying into a message. */
|
|
225
|
+
const MAX_PLAIN_ERROR_CHARS = 200;
|
|
168
226
|
/**
|
|
169
227
|
* An empty body (204, DELETE) is `undefined`, not a parse failure. Invalid
|
|
170
228
|
* JSON on a SUCCESSFUL status is a failure: the contract is not what we think
|
|
171
|
-
* it is, and returning `undefined` quietly is worse than throwing.
|
|
172
|
-
*
|
|
229
|
+
* it is, and returning `undefined` quietly is worse than throwing.
|
|
230
|
+
*
|
|
231
|
+
* A read that fails halfway is no longer swallowed. It used to be caught into
|
|
232
|
+
* an empty string, which turned a truncated response — a dropped connection,
|
|
233
|
+
* our own timeout firing while the body streamed — into `data: undefined`
|
|
234
|
+
* typed as the shape the caller asked for: a failure wearing the face of a
|
|
235
|
+
* successful empty answer, and on a balance or a transfer the worst possible
|
|
236
|
+
* disguise. The rejection now travels out to `transportError`, which names it
|
|
237
|
+
* a timeout, a cancel or a network failure.
|
|
173
238
|
*/
|
|
174
|
-
async function
|
|
175
|
-
const text = await response.text()
|
|
239
|
+
async function readJsonBody(response, endpoint) {
|
|
240
|
+
const text = await response.text();
|
|
176
241
|
if (!text)
|
|
177
242
|
return undefined;
|
|
178
243
|
try {
|
|
@@ -181,7 +246,32 @@ async function readBody(response, endpoint) {
|
|
|
181
246
|
catch (cause) {
|
|
182
247
|
if (response.ok)
|
|
183
248
|
throw parseError(cause, endpoint);
|
|
184
|
-
return
|
|
249
|
+
return plainTextError(text);
|
|
185
250
|
}
|
|
186
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* A non-JSON error body reduced to something showable — or to nothing.
|
|
254
|
+
*
|
|
255
|
+
* Who sends these: everything in front of the API, never the API itself. A
|
|
256
|
+
* 502/504 while the worker is being replaced, a 403 from a WAF, a platform
|
|
257
|
+
* 429 — they answer with a whole HTML page (2318 bytes in one measured case).
|
|
258
|
+
* Passing that on as `{error: text}` put the page into `message`, which is the
|
|
259
|
+
* one field meant to be read by a person.
|
|
260
|
+
*
|
|
261
|
+
* Markup is therefore dropped and `parseErrorBody` falls back to its own
|
|
262
|
+
* wording for the status. A short line of plain text is kept instead of being
|
|
263
|
+
* dropped with it, because a proxy occasionally says something the status does
|
|
264
|
+
* not ("upstream connect error", "no healthy upstream").
|
|
265
|
+
*/
|
|
266
|
+
function plainTextError(text) {
|
|
267
|
+
// A leading `<` catches HTML and XML error documents alike; neither is ours.
|
|
268
|
+
const collapsed = text.trim().replace(/\s+/g, ' ');
|
|
269
|
+
if (!collapsed || collapsed.startsWith('<'))
|
|
270
|
+
return undefined;
|
|
271
|
+
return {
|
|
272
|
+
error: collapsed.length > MAX_PLAIN_ERROR_CHARS
|
|
273
|
+
? `${collapsed.slice(0, MAX_PLAIN_ERROR_CHARS)}…`
|
|
274
|
+
: collapsed,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
187
277
|
//# sourceMappingURL=http.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/core/http.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,GAEb,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;;;;;;;;;;GAaG;AAEH,iDAAiD;AACjD,MAAM,oBAAoB,GAAG,gBAAgB,CAAA;AAE7C,2EAA2E;AAC3E,MAAM,kBAAkB,GAAG,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/core/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Keyset pagination
|
|
2
|
+
* Keyset pagination — for the eleven endpoints that have it.
|
|
3
|
+
*
|
|
4
|
+
* "Every list returns `{items, nextCursor}`" is what this file used to claim,
|
|
5
|
+
* and it is not what the API does. Counted over the spec snapshot
|
|
6
|
+
* (`openapi/spec.json`), the reading endpoints fall into three shapes:
|
|
7
|
+
*
|
|
8
|
+
* • 11 GETs take `cursor`/`limit` and answer a `nextCursor` — addresses,
|
|
9
|
+
* history, approval requests, members, counterparties, counterparty
|
|
10
|
+
* groups, operation categories, operation relations, ledger entries, a
|
|
11
|
+
* vault's policies, balances. These are what `paginate` is for;
|
|
12
|
+
* • 18 answer `{items}` with NO cursor parameter at all — folders and their
|
|
13
|
+
* grants, address shares, shared-with-me / shared-by-me, visibility
|
|
14
|
+
* grants, category assignments and their versions, report templates and
|
|
15
|
+
* snapshots, user groups and their members, status history, the
|
|
16
|
+
* admin-level `/policies` list and one policy's versions (18 paths, two
|
|
17
|
+
* of them the older `/address-groups` prefix of the folder endpoints).
|
|
18
|
+
* What you get is everything there is; `paginate` over one of them yields
|
|
19
|
+
* that single page and stops, because an absent `nextCursor` is the
|
|
20
|
+
* end-of-list signal;
|
|
21
|
+
* • 8 answer a BARE ARRAY rather than an object: `/networks`, `/tokens`,
|
|
22
|
+
* `/vaults`, a vault's `/policy-groups` and `/invitations`, one
|
|
23
|
+
* operation's `/relations`, a policy group's `/policies`, a user's
|
|
24
|
+
* `/policy-groups`. There is no `items` to walk, so `paginate` refuses
|
|
25
|
+
* them by name instead of quietly yielding nothing.
|
|
26
|
+
*
|
|
27
|
+
* `/balances` is the one cursored endpoint `paginate` CANNOT walk: its page is
|
|
28
|
+
* `{vaultId, totals, accounts, nextCursor}` and the array is called
|
|
29
|
+
* `accounts`. Pass the cursor by hand there.
|
|
3
30
|
*
|
|
4
31
|
* The cursor is opaque: do not parse it, build it or compare it. A
|
|
5
32
|
* `nextCursor` of `null` is the only end-of-list signal — an empty page is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../src/core/pagination.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../src/core/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,WAAW,IAAI,CAAC,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,CAAA;IACnB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAuB,QAAQ,CAAC,CAAC,EAC/B,SAAS,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EACnD,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClD,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAmCpC;AAED,uEAAuE;AACvE,wBAAsB,UAAU,CAAC,CAAC,EAChC,SAAS,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EACnD,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClD,OAAO,CAAC,CAAC,EAAE,CAAC,CAId"}
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Keyset pagination
|
|
2
|
+
* Keyset pagination — for the eleven endpoints that have it.
|
|
3
|
+
*
|
|
4
|
+
* "Every list returns `{items, nextCursor}`" is what this file used to claim,
|
|
5
|
+
* and it is not what the API does. Counted over the spec snapshot
|
|
6
|
+
* (`openapi/spec.json`), the reading endpoints fall into three shapes:
|
|
7
|
+
*
|
|
8
|
+
* • 11 GETs take `cursor`/`limit` and answer a `nextCursor` — addresses,
|
|
9
|
+
* history, approval requests, members, counterparties, counterparty
|
|
10
|
+
* groups, operation categories, operation relations, ledger entries, a
|
|
11
|
+
* vault's policies, balances. These are what `paginate` is for;
|
|
12
|
+
* • 18 answer `{items}` with NO cursor parameter at all — folders and their
|
|
13
|
+
* grants, address shares, shared-with-me / shared-by-me, visibility
|
|
14
|
+
* grants, category assignments and their versions, report templates and
|
|
15
|
+
* snapshots, user groups and their members, status history, the
|
|
16
|
+
* admin-level `/policies` list and one policy's versions (18 paths, two
|
|
17
|
+
* of them the older `/address-groups` prefix of the folder endpoints).
|
|
18
|
+
* What you get is everything there is; `paginate` over one of them yields
|
|
19
|
+
* that single page and stops, because an absent `nextCursor` is the
|
|
20
|
+
* end-of-list signal;
|
|
21
|
+
* • 8 answer a BARE ARRAY rather than an object: `/networks`, `/tokens`,
|
|
22
|
+
* `/vaults`, a vault's `/policy-groups` and `/invitations`, one
|
|
23
|
+
* operation's `/relations`, a policy group's `/policies`, a user's
|
|
24
|
+
* `/policy-groups`. There is no `items` to walk, so `paginate` refuses
|
|
25
|
+
* them by name instead of quietly yielding nothing.
|
|
26
|
+
*
|
|
27
|
+
* `/balances` is the one cursored endpoint `paginate` CANNOT walk: its page is
|
|
28
|
+
* `{vaultId, totals, accounts, nextCursor}` and the array is called
|
|
29
|
+
* `accounts`. Pass the cursor by hand there.
|
|
3
30
|
*
|
|
4
31
|
* The cursor is opaque: do not parse it, build it or compare it. A
|
|
5
32
|
* `nextCursor` of `null` is the only end-of-list signal — an empty page is
|
|
@@ -24,6 +51,14 @@ export async function* paginate(fetchPage, options = {}) {
|
|
|
24
51
|
...(options.limit === undefined ? {} : { limit: options.limit }),
|
|
25
52
|
...(cursor === undefined ? {} : { cursor }),
|
|
26
53
|
});
|
|
54
|
+
// A bare-array endpoint (or `/balances`, whose array is `accounts`) has no
|
|
55
|
+
// `items`, and `for…of undefined` would report that as an unexplained
|
|
56
|
+
// TypeError from inside the SDK. Say what is wrong instead.
|
|
57
|
+
if (!Array.isArray(result.items)) {
|
|
58
|
+
throw new Error('@v3finance/core-sdk: this response has no `items` array, so it cannot be paged. ' +
|
|
59
|
+
'Endpoints answering a bare array, and /balances (its array is `accounts`), ' +
|
|
60
|
+
'are read with a single call — see the note at the top of core/pagination.ts.');
|
|
61
|
+
}
|
|
27
62
|
for (const item of result.items)
|
|
28
63
|
yield item;
|
|
29
64
|
seen += result.items.length;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../../src/core/pagination.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../../src/core/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAcH;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,QAAQ,CAC7B,SAAmD,EACnD,OAAO,GAA0C,EAAE;IAEnD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAA;IACzC,IAAI,MAA0B,CAAA;IAC9B,IAAI,IAAI,GAAG,CAAC,CAAA;IAEZ,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAY,MAAM,SAAS,CAAC;YACtC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;YAChE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;SAC5C,CAAC,CAAA;QACF,2EAA2E;QAC3E,sEAAsE;QACtE,4DAA4D;QAC5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,kFAAkF;gBAChF,6EAA6E;gBAC7E,8EAA8E,CACjF,CAAA;QACH,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,IAAI,CAAA;QAC3C,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAA;QAE3B,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;YAAE,OAAM;QACzE,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,wEAAwE,IAAI,SAAS,CACtF,CAAA;QACH,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,UAAU,CAAA;IAC5B,CAAC;IAED,MAAM,IAAI,KAAK,CACb,kCAAkC,QAAQ,0DAA0D,CACrG,CAAA;AACH,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,SAAmD,EACnD,OAAO,GAA0C,EAAE;IAEnD,MAAM,GAAG,GAAQ,EAAE,CAAA;IACnB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACrE,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// the API does not slip in unclassified.
|
|
10
10
|
//
|
|
11
11
|
// Operations: 171 · admin: 40 · both: 1 · member: 127 · service: 3
|
|
12
|
-
// Spec sha256:
|
|
12
|
+
// Spec sha256: a03bd2e06186734bd8816c3d764dd90a48c1c31d7edda2743a3ae29550601cd1
|
|
13
13
|
export const OPERATIONS = {
|
|
14
14
|
"DELETE /api/v1/me/push-tokens/{token}": {
|
|
15
15
|
"method": "delete",
|