@rwa-xyz/partners 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +162 -2
- package/dist/cjs/assets.d.ts +38 -0
- package/dist/cjs/assets.js +56 -0
- package/dist/cjs/client.d.ts +38 -0
- package/dist/cjs/client.js +44 -0
- package/dist/cjs/errors.d.ts +78 -0
- package/dist/cjs/errors.js +137 -0
- package/dist/cjs/generated/openapi.d.ts +740 -0
- package/dist/cjs/generated/openapi.js +9 -0
- package/dist/cjs/http.d.ts +52 -0
- package/dist/cjs/http.js +183 -0
- package/dist/cjs/index.d.ts +11 -0
- package/dist/cjs/index.js +31 -0
- package/dist/cjs/metrics.d.ts +70 -0
- package/dist/cjs/metrics.js +157 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/version.d.ts +7 -0
- package/dist/cjs/version.js +11 -0
- package/dist/esm/assets.d.ts +38 -0
- package/dist/esm/assets.js +52 -0
- package/dist/esm/client.d.ts +38 -0
- package/dist/esm/client.js +40 -0
- package/dist/esm/errors.d.ts +78 -0
- package/dist/esm/errors.js +121 -0
- package/dist/esm/generated/openapi.d.ts +740 -0
- package/dist/esm/generated/openapi.js +6 -0
- package/dist/esm/http.d.ts +52 -0
- package/dist/esm/http.js +177 -0
- package/dist/esm/index.d.ts +11 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/metrics.d.ts +70 -0
- package/dist/esm/metrics.js +152 -0
- package/dist/esm/version.d.ts +7 -0
- package/dist/esm/version.js +8 -0
- package/package.json +42 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RWA.xyz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,163 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @rwa-xyz/partners
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The RWA.xyz Partners API client for TypeScript and JavaScript: submit your
|
|
4
|
+
assets' NAV and yield, and read back what RWA.xyz stored.
|
|
5
|
+
|
|
6
|
+
**Beta.** This client is in beta until 1.0: a new minor version may change a
|
|
7
|
+
call or an option you use, so pin it (see Versions below). The Partners API it
|
|
8
|
+
calls isn't in beta.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install @rwa-xyz/partners
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Node 20 or later. No dependencies. ES modules and CommonJS. Run it on a server,
|
|
15
|
+
never in a browser: your key must stay private.
|
|
16
|
+
|
|
17
|
+
## Submit metrics
|
|
18
|
+
|
|
19
|
+
Create a key in RWA.xyz Partners under **Settings → API Keys**, and set it as
|
|
20
|
+
`RWA_API_KEY`. There is no sandbox: what you submit is saved for real.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { RwaPartners } from "@rwa-xyz/partners";
|
|
24
|
+
|
|
25
|
+
const client = new RwaPartners(); // reads RWA_API_KEY
|
|
26
|
+
|
|
27
|
+
const me = await client.me();
|
|
28
|
+
console.log(me.organization.name, me.key.scopes);
|
|
29
|
+
|
|
30
|
+
const report = await client.metrics.submit([
|
|
31
|
+
{ id: "USDY", date: "2026-10-28", metrics: { net_asset_value: 1.0012 } },
|
|
32
|
+
{ id: "USDY", date: "2026-10-29", metrics: { net_asset_value: 1.0013 } },
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
console.log(`Stored ${report.succeeded} of ${report.submitted}`);
|
|
36
|
+
for (const failure of report.failures) {
|
|
37
|
+
console.error(failure.id, failure.date, failure.code, failure.message);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A record's `id` is the asset's ticker or UUID. Until the asset is published, use
|
|
42
|
+
the ticker on your saved listing: save its name and ticker in RWA.xyz Partners
|
|
43
|
+
first. Its `date` is the UTC day the values apply to, never the day you send
|
|
44
|
+
them, and no later than tomorrow. A field you leave out keeps its saved value.
|
|
45
|
+
|
|
46
|
+
The two fields most assets send, as JSON numbers at full precision:
|
|
47
|
+
|
|
48
|
+
- `net_asset_value`: per token, not total AUM, in your listing's Denomination
|
|
49
|
+
Currency.
|
|
50
|
+
- `net_yield_1d_rate`: the unannualized 1-day yield as a decimal, not a percent.
|
|
51
|
+
|
|
52
|
+
`client.assets.get(id)` answers `expected_metrics`, the fields RWA.xyz expects for
|
|
53
|
+
that asset. Send them when NAV changes or yield is updated, before 1:00 AM UTC the
|
|
54
|
+
following day.
|
|
55
|
+
|
|
56
|
+
`submit` takes any number of records, for any assets and dates, and sends them
|
|
57
|
+
200 to a request (`batchSize` changes that). It answers one result per record,
|
|
58
|
+
in the order you passed them. A refused record does not throw: read
|
|
59
|
+
`report.failures`, or call `report.throwIfFailed()`. Each failure has a `code` to
|
|
60
|
+
branch on (`invalid_id`, `invalid_date`, `invalid_record`, `unknown_field`,
|
|
61
|
+
`invalid_value`, `unowned_asset`, `rejected_registration`, `ambiguous_asset`,
|
|
62
|
+
`write_failed`) and a `message`
|
|
63
|
+
for a person. Only `write_failed` is worth sending again unchanged, and the
|
|
64
|
+
client has already tried once, unless a later record in its batch is for the
|
|
65
|
+
same asset and day. Send it with every later record for that asset and day
|
|
66
|
+
after it, or it puts back the values they replaced. `report.deprecatedFields`
|
|
67
|
+
lists retired fields you sent. A NaN or
|
|
68
|
+
infinite value is refused before anything is sent: JSON would carry it as `null`,
|
|
69
|
+
which means "keep the saved value".
|
|
70
|
+
|
|
71
|
+
If a request fails outright, the error carries `partialReport`: the results of
|
|
72
|
+
every batch answered before it. Every record is an upsert keyed by asset and
|
|
73
|
+
date, so sending the same records again is safe either way.
|
|
74
|
+
|
|
75
|
+
## Read back
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
const assets = await client.assets.list();
|
|
79
|
+
console.log(assets.map((asset) => asset.ticker));
|
|
80
|
+
|
|
81
|
+
const usdy = await client.assets.get("USDY", { limit: 30, order: "desc" });
|
|
82
|
+
console.log(usdy.status, usdy.expected_metrics, usdy.quarantines);
|
|
83
|
+
|
|
84
|
+
for await (const day of client.assets.history("USDY", { order: "asc" })) {
|
|
85
|
+
console.log(day.date, day.net_asset_value);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`expected_metrics` lists the fields RWA.xyz expects for the asset. An asset
|
|
90
|
+
still in review is not listed, but is found by its ticker, with `status`
|
|
91
|
+
`"in_review"`. `quarantines` lists values held back while they are reviewed.
|
|
92
|
+
`history` walks every stored day, fetching each page as you reach it.
|
|
93
|
+
|
|
94
|
+
## Errors and retries
|
|
95
|
+
|
|
96
|
+
A request RWA.xyz refuses throws an `APIError` subclass: `BadRequestError` (400),
|
|
97
|
+
`AuthenticationError` (401), `PermissionDeniedError` (403), `NotFoundError`
|
|
98
|
+
(404), `PayloadTooLargeError` (413), `RateLimitError` (429) or
|
|
99
|
+
`InternalServerError` (5xx), with `status`, `headers` and the response `body`. No
|
|
100
|
+
answer at all throws `APIConnectionError`, or `APITimeoutError`. All of them are
|
|
101
|
+
a `RwaPartnersError`.
|
|
102
|
+
|
|
103
|
+
A read is retried twice after a 408, 429, 500, 502, 503 or 504, no answer, or
|
|
104
|
+
an answer cut off part-way, honouring `Retry-After`. A submission is retried
|
|
105
|
+
only when the API has stopped working on it: after a 408, 429, 500 or 503, a
|
|
106
|
+
connection that never opened, or an answer cut off part-way. After no answer,
|
|
107
|
+
or a 502 or 504, the API may still be saving it, so the client throws rather
|
|
108
|
+
than send it again, which could put an old value back over a newer one.
|
|
109
|
+
|
|
110
|
+
## Configuration
|
|
111
|
+
|
|
112
|
+
| Option | Default | |
|
|
113
|
+
| --- | --- | --- |
|
|
114
|
+
| `apiKey` | `RWA_API_KEY` | Your API key. |
|
|
115
|
+
| `baseUrl` | `RWA_API_BASE_URL`, then production | Where requests go. |
|
|
116
|
+
| `maxRetries` | `2` | How many times a failed request is retried. |
|
|
117
|
+
| `timeoutMs` | `120000` | How long each attempt may take. |
|
|
118
|
+
| `fetch` | The global one | What sends requests: for a proxy, or your own headers. |
|
|
119
|
+
|
|
120
|
+
## Test your code
|
|
121
|
+
|
|
122
|
+
Pass a stand-in for `fetch`, and everything else runs for real.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import assert from "node:assert/strict";
|
|
126
|
+
import { RwaPartners } from "@rwa-xyz/partners";
|
|
127
|
+
|
|
128
|
+
const client = new RwaPartners({
|
|
129
|
+
apiKey: "test",
|
|
130
|
+
fetch: async () =>
|
|
131
|
+
Response.json({
|
|
132
|
+
results: [
|
|
133
|
+
{
|
|
134
|
+
id: "USDY",
|
|
135
|
+
date: "2026-10-28",
|
|
136
|
+
status: "error",
|
|
137
|
+
code: "unowned_asset",
|
|
138
|
+
error: "Asset not found in organization",
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const report = await client.metrics.submit([
|
|
145
|
+
{ id: "USDY", date: "2026-10-28", metrics: { net_asset_value: 1.0012 } },
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
assert.equal(report.failures[0]?.code, "unowned_asset");
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Versions
|
|
152
|
+
|
|
153
|
+
This package and `rwa-partners` for Python share one version number. Until 1.0
|
|
154
|
+
it's in beta, and a new minor version may change anything, so pin it: `~0.1.0`. New fields, calls
|
|
155
|
+
and refusal codes can arrive in any version.
|
|
156
|
+
|
|
157
|
+
## Documentation
|
|
158
|
+
|
|
159
|
+
The full guides are at https://partners.rwa.xyz/docs/sdks (sign in to RWA.xyz
|
|
160
|
+
Partners).
|
|
161
|
+
|
|
162
|
+
For help, use **Contact Support** in RWA.xyz Partners, or email team@rwa.xyz.
|
|
163
|
+
Include the asset, the date and the error's message, never your API key.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading assets: the ones a key may submit for, and each one's attributes,
|
|
3
|
+
* expected metrics and metric history.
|
|
4
|
+
*
|
|
5
|
+
* @module sdk/typescript/assets
|
|
6
|
+
*/
|
|
7
|
+
import type { components, operations } from "./generated/openapi.js";
|
|
8
|
+
import { type TransportOptions } from "./http.js";
|
|
9
|
+
type Schemas = components["schemas"];
|
|
10
|
+
/** An asset in the catalogue: one your key may submit metrics for. */
|
|
11
|
+
export type CatalogueAsset = Schemas["CatalogueAsset"];
|
|
12
|
+
/** One asset, its expected metrics and a page of its metric history. */
|
|
13
|
+
export type AssetDetail = Schemas["AssetDetail"];
|
|
14
|
+
/** One day of an asset's stored metrics. */
|
|
15
|
+
export type MetricHistoryRow = Schemas["MetricHistoryRow"];
|
|
16
|
+
export type GetAssetOptions = NonNullable<operations["getAsset"]["parameters"]["query"]>;
|
|
17
|
+
export interface HistoryOptions {
|
|
18
|
+
/** `desc` (newest first, the default) or `asc`. */
|
|
19
|
+
readonly order?: "asc" | "desc";
|
|
20
|
+
/** Rows per request, 1 to 365. */
|
|
21
|
+
readonly pageSize?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare class Assets {
|
|
24
|
+
private readonly transport;
|
|
25
|
+
constructor(transport: TransportOptions);
|
|
26
|
+
/** The published assets your organization may submit metrics for. */
|
|
27
|
+
list(options?: {
|
|
28
|
+
organizationId?: string;
|
|
29
|
+
}): Promise<CatalogueAsset[]>;
|
|
30
|
+
/**
|
|
31
|
+
* One asset by ticker, uuid or Partners id, with one page of its history.
|
|
32
|
+
* An asset still in review is found by its ticker, `status: "in_review"`.
|
|
33
|
+
*/
|
|
34
|
+
get(identifier: string, options?: GetAssetOptions): Promise<AssetDetail>;
|
|
35
|
+
/** Every day of an asset's stored metrics, page after page. */
|
|
36
|
+
history(identifier: string, options?: HistoryOptions): AsyncGenerator<MetricHistoryRow, void, undefined>;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Reading assets: the ones a key may submit for, and each one's attributes,
|
|
4
|
+
* expected metrics and metric history.
|
|
5
|
+
*
|
|
6
|
+
* @module sdk/typescript/assets
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.Assets = void 0;
|
|
10
|
+
const http_js_1 = require("./http.js");
|
|
11
|
+
class Assets {
|
|
12
|
+
transport;
|
|
13
|
+
constructor(transport) {
|
|
14
|
+
this.transport = transport;
|
|
15
|
+
}
|
|
16
|
+
/** The published assets your organization may submit metrics for. */
|
|
17
|
+
async list(options = {}) {
|
|
18
|
+
const { body } = await (0, http_js_1.send)(this.transport, {
|
|
19
|
+
method: "GET",
|
|
20
|
+
path: "/v1/assets",
|
|
21
|
+
query: { organization_id: options.organizationId },
|
|
22
|
+
});
|
|
23
|
+
return body.assets;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* One asset by ticker, uuid or Partners id, with one page of its history.
|
|
27
|
+
* An asset still in review is found by its ticker, `status: "in_review"`.
|
|
28
|
+
*/
|
|
29
|
+
async get(identifier, options = {}) {
|
|
30
|
+
const { body } = await (0, http_js_1.send)(this.transport, {
|
|
31
|
+
method: "GET",
|
|
32
|
+
path: `/v1/assets/${encodeURIComponent(identifier)}`,
|
|
33
|
+
query: { ...options },
|
|
34
|
+
});
|
|
35
|
+
return body;
|
|
36
|
+
}
|
|
37
|
+
/** Every day of an asset's stored metrics, page after page. */
|
|
38
|
+
async *history(identifier, options = {}) {
|
|
39
|
+
let cursor;
|
|
40
|
+
for (;;) {
|
|
41
|
+
const page = await this.get(identifier, {
|
|
42
|
+
order: options.order,
|
|
43
|
+
limit: options.pageSize,
|
|
44
|
+
cursor,
|
|
45
|
+
});
|
|
46
|
+
yield* page.metrics;
|
|
47
|
+
const next = page.pagination.has_more
|
|
48
|
+
? page.pagination.next_cursor
|
|
49
|
+
: null;
|
|
50
|
+
if (!next)
|
|
51
|
+
return;
|
|
52
|
+
cursor = next;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.Assets = Assets;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client: one API key, one base URL, and the calls an integration makes.
|
|
3
|
+
*
|
|
4
|
+
* @module sdk/typescript/client
|
|
5
|
+
*/
|
|
6
|
+
import { Assets } from "./assets.js";
|
|
7
|
+
import { type components } from "./generated/openapi.js";
|
|
8
|
+
import { Metrics } from "./metrics.js";
|
|
9
|
+
/** Who a key is: its scopes, its user and the organization it acts for. */
|
|
10
|
+
export type Caller = components["schemas"]["Caller"];
|
|
11
|
+
export interface ClientOptions {
|
|
12
|
+
/** Your Partners API key. Defaults to the `RWA_API_KEY` variable. */
|
|
13
|
+
readonly apiKey?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Where requests go. Defaults to the `RWA_API_BASE_URL` variable, then
|
|
16
|
+
* production (`DEFAULT_BASE_URL`).
|
|
17
|
+
*/
|
|
18
|
+
readonly baseUrl?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Retries after a 408, 429, 5xx or no answer; a submission only when the
|
|
21
|
+
* API has stopped working on it. Default 2.
|
|
22
|
+
*/
|
|
23
|
+
readonly maxRetries?: number;
|
|
24
|
+
/** Per attempt. Default 120 000: a 200-record batch takes up to a minute. */
|
|
25
|
+
readonly timeoutMs?: number;
|
|
26
|
+
/** A `fetch` to send requests with. Defaults to the global one. */
|
|
27
|
+
readonly fetch?: typeof fetch;
|
|
28
|
+
}
|
|
29
|
+
/** Production: the server the API's own description names. */
|
|
30
|
+
export declare const DEFAULT_BASE_URL = "https://partners-api.rwa.xyz";
|
|
31
|
+
export declare class RwaPartners {
|
|
32
|
+
readonly assets: Assets;
|
|
33
|
+
readonly metrics: Metrics;
|
|
34
|
+
private readonly transport;
|
|
35
|
+
constructor(options?: ClientOptions);
|
|
36
|
+
/** What this key is and may do: also the check that it still works. */
|
|
37
|
+
me(): Promise<Caller>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The client: one API key, one base URL, and the calls an integration makes.
|
|
4
|
+
*
|
|
5
|
+
* @module sdk/typescript/client
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.RwaPartners = exports.DEFAULT_BASE_URL = void 0;
|
|
9
|
+
const assets_js_1 = require("./assets.js");
|
|
10
|
+
const openapi_js_1 = require("./generated/openapi.js");
|
|
11
|
+
const http_js_1 = require("./http.js");
|
|
12
|
+
const metrics_js_1 = require("./metrics.js");
|
|
13
|
+
/** Production: the server the API's own description names. */
|
|
14
|
+
exports.DEFAULT_BASE_URL = openapi_js_1.SERVER_URL;
|
|
15
|
+
class RwaPartners {
|
|
16
|
+
assets;
|
|
17
|
+
metrics;
|
|
18
|
+
transport;
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
this.transport = {
|
|
21
|
+
apiKey: (0, http_js_1.resolveApiKey)(options.apiKey),
|
|
22
|
+
baseUrl: options.baseUrl ||
|
|
23
|
+
(0, http_js_1.environmentVariable)("RWA_API_BASE_URL") ||
|
|
24
|
+
exports.DEFAULT_BASE_URL,
|
|
25
|
+
fetch: options.fetch ?? globalThis.fetch.bind(globalThis),
|
|
26
|
+
maxRetries: options.maxRetries ?? 2,
|
|
27
|
+
timeoutMs: options.timeoutMs ?? 120_000,
|
|
28
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
29
|
+
};
|
|
30
|
+
// Not enumerable, so logging or serializing the client never prints it.
|
|
31
|
+
Object.defineProperty(this.transport, "apiKey", { enumerable: false });
|
|
32
|
+
this.assets = new assets_js_1.Assets(this.transport);
|
|
33
|
+
this.metrics = new metrics_js_1.Metrics(this.transport);
|
|
34
|
+
}
|
|
35
|
+
/** What this key is and may do: also the check that it still works. */
|
|
36
|
+
async me() {
|
|
37
|
+
const { body } = await (0, http_js_1.send)(this.transport, {
|
|
38
|
+
method: "GET",
|
|
39
|
+
path: "/v1/me",
|
|
40
|
+
});
|
|
41
|
+
return body;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.RwaPartners = RwaPartners;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the client throws. An `APIError` is an answer the API gave; an
|
|
3
|
+
* `APIConnectionError` is no answer at all; `SubmissionFailedError` is a
|
|
4
|
+
* report you asked to throw (`SubmissionReport.throwIfFailed`).
|
|
5
|
+
*
|
|
6
|
+
* @module sdk/typescript/errors
|
|
7
|
+
*/
|
|
8
|
+
import type { SubmissionReport } from "./metrics.js";
|
|
9
|
+
/** Everything this package throws. */
|
|
10
|
+
export declare class RwaPartnersError extends Error {
|
|
11
|
+
name: string;
|
|
12
|
+
/**
|
|
13
|
+
* When `metrics.submit` stops part-way, the results of every batch it
|
|
14
|
+
* had answered in full: what to skip when you send the rest again.
|
|
15
|
+
*/
|
|
16
|
+
partialReport?: SubmissionReport;
|
|
17
|
+
}
|
|
18
|
+
/** The API answered, with an error status. */
|
|
19
|
+
export declare class APIError extends RwaPartnersError {
|
|
20
|
+
readonly status: number;
|
|
21
|
+
/** The parsed response body, or its text when it was not JSON. */
|
|
22
|
+
readonly body: unknown;
|
|
23
|
+
readonly headers: Headers;
|
|
24
|
+
name: string;
|
|
25
|
+
constructor(status: number,
|
|
26
|
+
/** The parsed response body, or its text when it was not JSON. */
|
|
27
|
+
body: unknown, headers: Headers);
|
|
28
|
+
}
|
|
29
|
+
/** 400: the request itself was malformed, and nothing was saved. */
|
|
30
|
+
export declare class BadRequestError extends APIError {
|
|
31
|
+
name: string;
|
|
32
|
+
}
|
|
33
|
+
/** 401: no key was sent, or it is unknown, revoked or expired. */
|
|
34
|
+
export declare class AuthenticationError extends APIError {
|
|
35
|
+
name: string;
|
|
36
|
+
}
|
|
37
|
+
/** 403: the key may not do this; `body.reason` says why. */
|
|
38
|
+
export declare class PermissionDeniedError extends APIError {
|
|
39
|
+
name: string;
|
|
40
|
+
}
|
|
41
|
+
/** 404: nothing your key may read goes by that identifier. */
|
|
42
|
+
export declare class NotFoundError extends APIError {
|
|
43
|
+
name: string;
|
|
44
|
+
}
|
|
45
|
+
/** 413: the body is over the API's size limit. */
|
|
46
|
+
export declare class PayloadTooLargeError extends APIError {
|
|
47
|
+
name: string;
|
|
48
|
+
}
|
|
49
|
+
/** 429: too many requests, after every retry the client was allowed. */
|
|
50
|
+
export declare class RateLimitError extends APIError {
|
|
51
|
+
name: string;
|
|
52
|
+
}
|
|
53
|
+
/** 5xx: a failure on RWA.xyz's side, after any retries. */
|
|
54
|
+
export declare class InternalServerError extends APIError {
|
|
55
|
+
name: string;
|
|
56
|
+
}
|
|
57
|
+
/** The error class for an error status. */
|
|
58
|
+
export declare function apiErrorFor(status: number, body: unknown, headers: Headers): APIError;
|
|
59
|
+
/**
|
|
60
|
+
* No answer: the network failed, after any retries. A submission is not sent
|
|
61
|
+
* again while the API may still be saving it.
|
|
62
|
+
*/
|
|
63
|
+
export declare class APIConnectionError extends RwaPartnersError {
|
|
64
|
+
name: string;
|
|
65
|
+
constructor(message: string, options?: {
|
|
66
|
+
cause?: unknown;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** No answer within the timeout, after any retries. */
|
|
70
|
+
export declare class APITimeoutError extends APIConnectionError {
|
|
71
|
+
name: string;
|
|
72
|
+
}
|
|
73
|
+
/** Thrown by `SubmissionReport.throwIfFailed` when a record was refused. */
|
|
74
|
+
export declare class SubmissionFailedError extends RwaPartnersError {
|
|
75
|
+
readonly report: SubmissionReport;
|
|
76
|
+
name: string;
|
|
77
|
+
constructor(report: SubmissionReport);
|
|
78
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What the client throws. An `APIError` is an answer the API gave; an
|
|
4
|
+
* `APIConnectionError` is no answer at all; `SubmissionFailedError` is a
|
|
5
|
+
* report you asked to throw (`SubmissionReport.throwIfFailed`).
|
|
6
|
+
*
|
|
7
|
+
* @module sdk/typescript/errors
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SubmissionFailedError = exports.APITimeoutError = exports.APIConnectionError = exports.InternalServerError = exports.RateLimitError = exports.PayloadTooLargeError = exports.NotFoundError = exports.PermissionDeniedError = exports.AuthenticationError = exports.BadRequestError = exports.APIError = exports.RwaPartnersError = void 0;
|
|
11
|
+
exports.apiErrorFor = apiErrorFor;
|
|
12
|
+
// // // //
|
|
13
|
+
/** Everything this package throws. */
|
|
14
|
+
class RwaPartnersError extends Error {
|
|
15
|
+
name = "RwaPartnersError";
|
|
16
|
+
/**
|
|
17
|
+
* When `metrics.submit` stops part-way, the results of every batch it
|
|
18
|
+
* had answered in full: what to skip when you send the rest again.
|
|
19
|
+
*/
|
|
20
|
+
partialReport;
|
|
21
|
+
}
|
|
22
|
+
exports.RwaPartnersError = RwaPartnersError;
|
|
23
|
+
/** The message an error body carries, in whichever field it carries it. */
|
|
24
|
+
function messageOf(status, body) {
|
|
25
|
+
if (body && typeof body === "object") {
|
|
26
|
+
const fields = body;
|
|
27
|
+
for (const key of ["message", "error"]) {
|
|
28
|
+
if (typeof fields[key] === "string") {
|
|
29
|
+
const reason = typeof fields.reason === "string"
|
|
30
|
+
? `: ${fields.reason}`
|
|
31
|
+
: "";
|
|
32
|
+
return `${status} ${fields[key]}${reason}`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return `${status} ${typeof body === "string" ? body : "error"}`;
|
|
37
|
+
}
|
|
38
|
+
/** The API answered, with an error status. */
|
|
39
|
+
class APIError extends RwaPartnersError {
|
|
40
|
+
status;
|
|
41
|
+
body;
|
|
42
|
+
headers;
|
|
43
|
+
name = "APIError";
|
|
44
|
+
constructor(status,
|
|
45
|
+
/** The parsed response body, or its text when it was not JSON. */
|
|
46
|
+
body, headers) {
|
|
47
|
+
super(messageOf(status, body));
|
|
48
|
+
this.status = status;
|
|
49
|
+
this.body = body;
|
|
50
|
+
this.headers = headers;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.APIError = APIError;
|
|
54
|
+
/** 400: the request itself was malformed, and nothing was saved. */
|
|
55
|
+
class BadRequestError extends APIError {
|
|
56
|
+
name = "BadRequestError";
|
|
57
|
+
}
|
|
58
|
+
exports.BadRequestError = BadRequestError;
|
|
59
|
+
/** 401: no key was sent, or it is unknown, revoked or expired. */
|
|
60
|
+
class AuthenticationError extends APIError {
|
|
61
|
+
name = "AuthenticationError";
|
|
62
|
+
}
|
|
63
|
+
exports.AuthenticationError = AuthenticationError;
|
|
64
|
+
/** 403: the key may not do this; `body.reason` says why. */
|
|
65
|
+
class PermissionDeniedError extends APIError {
|
|
66
|
+
name = "PermissionDeniedError";
|
|
67
|
+
}
|
|
68
|
+
exports.PermissionDeniedError = PermissionDeniedError;
|
|
69
|
+
/** 404: nothing your key may read goes by that identifier. */
|
|
70
|
+
class NotFoundError extends APIError {
|
|
71
|
+
name = "NotFoundError";
|
|
72
|
+
}
|
|
73
|
+
exports.NotFoundError = NotFoundError;
|
|
74
|
+
/** 413: the body is over the API's size limit. */
|
|
75
|
+
class PayloadTooLargeError extends APIError {
|
|
76
|
+
name = "PayloadTooLargeError";
|
|
77
|
+
}
|
|
78
|
+
exports.PayloadTooLargeError = PayloadTooLargeError;
|
|
79
|
+
/** 429: too many requests, after every retry the client was allowed. */
|
|
80
|
+
class RateLimitError extends APIError {
|
|
81
|
+
name = "RateLimitError";
|
|
82
|
+
}
|
|
83
|
+
exports.RateLimitError = RateLimitError;
|
|
84
|
+
/** 5xx: a failure on RWA.xyz's side, after any retries. */
|
|
85
|
+
class InternalServerError extends APIError {
|
|
86
|
+
name = "InternalServerError";
|
|
87
|
+
}
|
|
88
|
+
exports.InternalServerError = InternalServerError;
|
|
89
|
+
/** The error class for an error status. */
|
|
90
|
+
function apiErrorFor(status, body, headers) {
|
|
91
|
+
const ErrorClass = status === 400
|
|
92
|
+
? BadRequestError
|
|
93
|
+
: status === 401
|
|
94
|
+
? AuthenticationError
|
|
95
|
+
: status === 403
|
|
96
|
+
? PermissionDeniedError
|
|
97
|
+
: status === 404
|
|
98
|
+
? NotFoundError
|
|
99
|
+
: status === 413
|
|
100
|
+
? PayloadTooLargeError
|
|
101
|
+
: status === 429
|
|
102
|
+
? RateLimitError
|
|
103
|
+
: status >= 500
|
|
104
|
+
? InternalServerError
|
|
105
|
+
: APIError;
|
|
106
|
+
return new ErrorClass(status, body, headers);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* No answer: the network failed, after any retries. A submission is not sent
|
|
110
|
+
* again while the API may still be saving it.
|
|
111
|
+
*/
|
|
112
|
+
class APIConnectionError extends RwaPartnersError {
|
|
113
|
+
name = "APIConnectionError";
|
|
114
|
+
constructor(message, options) {
|
|
115
|
+
super(message, options);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.APIConnectionError = APIConnectionError;
|
|
119
|
+
/** No answer within the timeout, after any retries. */
|
|
120
|
+
class APITimeoutError extends APIConnectionError {
|
|
121
|
+
name = "APITimeoutError";
|
|
122
|
+
}
|
|
123
|
+
exports.APITimeoutError = APITimeoutError;
|
|
124
|
+
/** Thrown by `SubmissionReport.throwIfFailed` when a record was refused. */
|
|
125
|
+
class SubmissionFailedError extends RwaPartnersError {
|
|
126
|
+
report;
|
|
127
|
+
name = "SubmissionFailedError";
|
|
128
|
+
constructor(report) {
|
|
129
|
+
const [first] = report.failures;
|
|
130
|
+
super(`${report.failures.length} of ${report.submitted} records were not saved` +
|
|
131
|
+
(first
|
|
132
|
+
? `; the first, ${first.id} on ${first.date}: ${first.message}`
|
|
133
|
+
: ""));
|
|
134
|
+
this.report = report;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
exports.SubmissionFailedError = SubmissionFailedError;
|