@pulsight-xyz/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -0
- package/dist/backtest.d.ts +18 -0
- package/dist/backtest.d.ts.map +1 -0
- package/dist/backtest.js +48 -0
- package/dist/backtest.js.map +1 -0
- package/dist/client.d.ts +34 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +77 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +41 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +96 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/client/client.gen.d.ts +3 -0
- package/dist/generated/client/client.gen.d.ts.map +1 -0
- package/dist/generated/client/client.gen.js +217 -0
- package/dist/generated/client/client.gen.js.map +1 -0
- package/dist/generated/client/index.d.ts +9 -0
- package/dist/generated/client/index.d.ts.map +1 -0
- package/dist/generated/client/index.js +7 -0
- package/dist/generated/client/index.js.map +1 -0
- package/dist/generated/client/types.gen.d.ts +121 -0
- package/dist/generated/client/types.gen.d.ts.map +1 -0
- package/dist/generated/client/types.gen.js +3 -0
- package/dist/generated/client/types.gen.js.map +1 -0
- package/dist/generated/client/utils.gen.d.ts +38 -0
- package/dist/generated/client/utils.gen.d.ts.map +1 -0
- package/dist/generated/client/utils.gen.js +229 -0
- package/dist/generated/client/utils.gen.js.map +1 -0
- package/dist/generated/client.gen.d.ts +13 -0
- package/dist/generated/client.gen.d.ts.map +1 -0
- package/dist/generated/client.gen.js +4 -0
- package/dist/generated/client.gen.js.map +1 -0
- package/dist/generated/core/auth.gen.d.ts +19 -0
- package/dist/generated/core/auth.gen.d.ts.map +1 -0
- package/dist/generated/core/auth.gen.js +15 -0
- package/dist/generated/core/auth.gen.js.map +1 -0
- package/dist/generated/core/bodySerializer.gen.d.ts +26 -0
- package/dist/generated/core/bodySerializer.gen.d.ts.map +1 -0
- package/dist/generated/core/bodySerializer.gen.js +58 -0
- package/dist/generated/core/bodySerializer.gen.js.map +1 -0
- package/dist/generated/core/params.gen.d.ts +44 -0
- package/dist/generated/core/params.gen.d.ts.map +1 -0
- package/dist/generated/core/params.gen.js +101 -0
- package/dist/generated/core/params.gen.js.map +1 -0
- package/dist/generated/core/pathSerializer.gen.d.ts +34 -0
- package/dist/generated/core/pathSerializer.gen.d.ts.map +1 -0
- package/dist/generated/core/pathSerializer.gen.js +107 -0
- package/dist/generated/core/pathSerializer.gen.js.map +1 -0
- package/dist/generated/core/queryKeySerializer.gen.d.ts +19 -0
- package/dist/generated/core/queryKeySerializer.gen.d.ts.map +1 -0
- package/dist/generated/core/queryKeySerializer.gen.js +93 -0
- package/dist/generated/core/queryKeySerializer.gen.js.map +1 -0
- package/dist/generated/core/serverSentEvents.gen.d.ts +72 -0
- package/dist/generated/core/serverSentEvents.gen.d.ts.map +1 -0
- package/dist/generated/core/serverSentEvents.gen.js +133 -0
- package/dist/generated/core/serverSentEvents.gen.js.map +1 -0
- package/dist/generated/core/types.gen.d.ts +79 -0
- package/dist/generated/core/types.gen.d.ts.map +1 -0
- package/dist/generated/core/types.gen.js +3 -0
- package/dist/generated/core/types.gen.js.map +1 -0
- package/dist/generated/core/utils.gen.d.ts +20 -0
- package/dist/generated/core/utils.gen.d.ts.map +1 -0
- package/dist/generated/core/utils.gen.js +88 -0
- package/dist/generated/core/utils.gen.js.map +1 -0
- package/dist/generated/index.d.ts +3 -0
- package/dist/generated/index.d.ts.map +1 -0
- package/dist/generated/index.js +3 -0
- package/dist/generated/index.js.map +1 -0
- package/dist/generated/sdk.gen.d.ts +322 -0
- package/dist/generated/sdk.gen.d.ts.map +1 -0
- package/dist/generated/sdk.gen.js +550 -0
- package/dist/generated/sdk.gen.js.map +1 -0
- package/dist/generated/types.gen.d.ts +3337 -0
- package/dist/generated/types.gen.d.ts.map +1 -0
- package/dist/generated/types.gen.js +3 -0
- package/dist/generated/types.gen.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
- package/src/backtest.ts +72 -0
- package/src/client.ts +98 -0
- package/src/errors.ts +99 -0
- package/src/generated/client/client.gen.ts +277 -0
- package/src/generated/client/index.ts +25 -0
- package/src/generated/client/types.gen.ts +218 -0
- package/src/generated/client/utils.gen.ts +316 -0
- package/src/generated/client.gen.ts +16 -0
- package/src/generated/core/auth.gen.ts +41 -0
- package/src/generated/core/bodySerializer.gen.ts +82 -0
- package/src/generated/core/params.gen.ts +169 -0
- package/src/generated/core/pathSerializer.gen.ts +171 -0
- package/src/generated/core/queryKeySerializer.gen.ts +117 -0
- package/src/generated/core/serverSentEvents.gen.ts +242 -0
- package/src/generated/core/types.gen.ts +104 -0
- package/src/generated/core/utils.gen.ts +140 -0
- package/src/generated/index.ts +4 -0
- package/src/generated/sdk.gen.ts +625 -0
- package/src/generated/types.gen.ts +3730 -0
- package/src/index.ts +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @pulsight-xyz/sdk
|
|
2
|
+
|
|
3
|
+
Official JavaScript/TypeScript client for the [Pulsight](https://pulsight.xyz)
|
|
4
|
+
public API (data reads, backtests, strategies).
|
|
5
|
+
|
|
6
|
+
> This directory is the source of truth; CI mirrors it to
|
|
7
|
+
> `github.com/pulsight-xyz/pulsight-js` and publishes `@pulsight-xyz/sdk` to npm
|
|
8
|
+
> on a `publish-{VERSION}` tag (see the `sdk-*` jobs in `.gitlab-ci.yml`).
|
|
9
|
+
> Distinct from the repo-internal `pulsight-sdk/` (that one is the private
|
|
10
|
+
> in-app client for `new-front/`; this one is the published external SDK).
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install @pulsight-xyz/sdk
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Layout
|
|
19
|
+
|
|
20
|
+
- `src/generated/` — protocol core emitted by [`@hey-api/openapi-ts`](https://github.com/hey-api/openapi-ts) from `sdks/openapi/public.json` (the client runtime is vendored in, so the package has **no runtime dependencies**). **`.gitignore`d in the elio repo, never hand-edited**; regenerated by `make sdk-js` (locally) or in CI before publish, and carried in the published `pulsight-xyz/pulsight-js` repo. Run `make sdk-js` after cloning before typechecking.
|
|
21
|
+
- `src/{client,errors,backtest}.ts` — the handwritten ergonomic layer: api-token auth, 429 retry, typed errors, credits accessor, `submitAndWait`. `client.ts` builds on the vendored `./generated/client` so the client it returns is type-compatible with the generated operations.
|
|
22
|
+
|
|
23
|
+
## Generate
|
|
24
|
+
|
|
25
|
+
From the repo root (refreshes the spec first, then regenerates + typechecks):
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
make sdk-js
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { createPulsightClient, getApiTraders, CreditExhaustedError, creditsRemaining } from '@pulsight-xyz/sdk';
|
|
35
|
+
|
|
36
|
+
const client = createPulsightClient('pk_live_…'); // api token from the settings UI
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const { data, response } = await getApiTraders({ client });
|
|
40
|
+
console.log('credits left:', creditsRemaining(response.headers));
|
|
41
|
+
} catch (err) {
|
|
42
|
+
if (err instanceof CreditExhaustedError) {
|
|
43
|
+
// out of api credits for this cycle
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`submitAndWait` runs a backtest to completion:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { submitAndWait } from '@pulsight-xyz/sdk';
|
|
52
|
+
|
|
53
|
+
const result = await submitAndWait('pk_live_…', { /* backtest request */ }, {
|
|
54
|
+
onProgress: (status) => console.log(status),
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Error mapping
|
|
59
|
+
|
|
60
|
+
The handwritten layer turns the wire contract into first-class errors:
|
|
61
|
+
|
|
62
|
+
| HTTP | Error |
|
|
63
|
+
|---|---|
|
|
64
|
+
| 402 `CREDIT_EXHAUSTED` | `CreditExhaustedError { pool }` |
|
|
65
|
+
| 429 | `RateLimitedError { retryAfter }` (idempotent GETs auto-retry) |
|
|
66
|
+
| 403 (missing scope) | `MissingScopeError { reason }` |
|
|
67
|
+
| other non-2xx | `ApiError { status, body }` |
|
|
68
|
+
|
|
69
|
+
Use `raiseForResponse(response)` to map a raw `Response`, and
|
|
70
|
+
`creditsRemaining(headers)` to read `X-Credits-Remaining`.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface SubmitAndWaitOptions {
|
|
2
|
+
/** API root override. Defaults to {@link DEFAULT_BASE_URL}. */
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
/** Poll cadence in ms (default 2000). */
|
|
5
|
+
pollIntervalMs?: number;
|
|
6
|
+
/** Give up after this many ms (default 300000 = 5 min). */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
/** Invoked with the backtest status each poll (e.g. for progress UI). */
|
|
9
|
+
onProgress?: (status: string) => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Submit a backtest (`POST /api/backtests`) and poll `GET /api/backtests/{id}`
|
|
13
|
+
* with backoff until the record reaches a terminal status, returning it.
|
|
14
|
+
* Throws a typed error (see ./errors) on any non-2xx, or a plain Error if the
|
|
15
|
+
* run does not finish within `timeoutMs`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function submitAndWait(apiToken: string, body: unknown, opts?: SubmitAndWaitOptions): Promise<Record<string, unknown>>;
|
|
18
|
+
//# sourceMappingURL=backtest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backtest.d.ts","sourceRoot":"","sources":["../src/backtest.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,IAAI,GAAE,oBAAyB,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAuClC"}
|
package/dist/backtest.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `submitAndWait` — submit a backtest and poll until it reaches a terminal
|
|
3
|
+
* state, the ergonomic counterpart to the raw submit/poll operations. Kept
|
|
4
|
+
* self-contained (plain `fetch`) so it typechecks before generation and does
|
|
5
|
+
* not couple to the generated operation names.
|
|
6
|
+
*/
|
|
7
|
+
import { DEFAULT_BASE_URL } from './client';
|
|
8
|
+
import { raiseForResponse } from './errors';
|
|
9
|
+
const TERMINAL = new Set(['done', 'completed', 'failed', 'cancelled', 'canceled', 'error']);
|
|
10
|
+
/**
|
|
11
|
+
* Submit a backtest (`POST /api/backtests`) and poll `GET /api/backtests/{id}`
|
|
12
|
+
* with backoff until the record reaches a terminal status, returning it.
|
|
13
|
+
* Throws a typed error (see ./errors) on any non-2xx, or a plain Error if the
|
|
14
|
+
* run does not finish within `timeoutMs`.
|
|
15
|
+
*/
|
|
16
|
+
export async function submitAndWait(apiToken, body, opts = {}) {
|
|
17
|
+
const { baseUrl = DEFAULT_BASE_URL, pollIntervalMs = 2000, timeoutMs = 300_000, onProgress, } = opts;
|
|
18
|
+
const headers = {
|
|
19
|
+
Authorization: `Bearer ${apiToken}`,
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
};
|
|
22
|
+
const submit = await fetch(`${baseUrl}/api/backtests`, {
|
|
23
|
+
method: 'POST',
|
|
24
|
+
headers,
|
|
25
|
+
body: JSON.stringify(body),
|
|
26
|
+
});
|
|
27
|
+
await raiseForResponse(submit);
|
|
28
|
+
const submitted = (await submit.json());
|
|
29
|
+
const id = submitted?.id;
|
|
30
|
+
if (id === undefined || id === null) {
|
|
31
|
+
throw new Error('pulsight: backtest submit returned no id');
|
|
32
|
+
}
|
|
33
|
+
const deadline = Date.now() + timeoutMs;
|
|
34
|
+
for (;;) {
|
|
35
|
+
const poll = await fetch(`${baseUrl}/api/backtests/${id}`, { headers });
|
|
36
|
+
await raiseForResponse(poll);
|
|
37
|
+
const record = (await poll.json());
|
|
38
|
+
const status = String(record?.status ?? '').toLowerCase();
|
|
39
|
+
onProgress?.(status);
|
|
40
|
+
if (TERMINAL.has(status))
|
|
41
|
+
return record;
|
|
42
|
+
if (Date.now() > deadline) {
|
|
43
|
+
throw new Error(`pulsight: backtest ${id} did not finish within ${timeoutMs}ms (last status: ${status || 'unknown'})`);
|
|
44
|
+
}
|
|
45
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=backtest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backtest.js","sourceRoot":"","sources":["../src/backtest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AAa5F;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,IAAa,EACb,OAA6B,EAAE;IAE/B,MAAM,EACJ,OAAO,GAAG,gBAAgB,EAC1B,cAAc,GAAG,IAAI,EACrB,SAAS,GAAG,OAAO,EACnB,UAAU,GACX,GAAG,IAAI,CAAC;IACT,MAAM,OAAO,GAAG;QACd,aAAa,EAAE,UAAU,QAAQ,EAAE;QACnC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,gBAAgB,EAAE;QACrD,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IACH,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,SAAS,GAAG,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAA6B,CAAC;IACpE,MAAM,EAAE,GAAG,SAAS,EAAE,EAAE,CAAC;IACzB,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,kBAAkB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACxE,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAA4B,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1D,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC;QACrB,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACxC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,sBAAsB,EAAE,0BAA0B,SAAS,oBAAoB,MAAM,IAAI,SAAS,GAAG,CACtG,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IACtE,CAAC;AACH,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authenticated fetch client for the Pulsight API.
|
|
3
|
+
*
|
|
4
|
+
* Builds a `@hey-api/client-fetch` client (the same runtime the generated
|
|
5
|
+
* operations in ./generated expect) configured with api-token auth and 429
|
|
6
|
+
* retry. Pass the returned client to any generated operation:
|
|
7
|
+
*
|
|
8
|
+
* import { createPulsightClient, getApiTraders } from '@pulsight-xyz/sdk';
|
|
9
|
+
* const client = createPulsightClient('pk_live_…');
|
|
10
|
+
* const { data } = await getApiTraders({ client });
|
|
11
|
+
*
|
|
12
|
+
* Built on the GENERATED client runtime (`./generated/client`), which
|
|
13
|
+
* @hey-api/openapi-ts vendors into the package — the generated operations
|
|
14
|
+
* expect exactly that `Client` type, so the standalone `@hey-api/client-fetch`
|
|
15
|
+
* npm package (whose types differ subtly) must NOT be used here.
|
|
16
|
+
*/
|
|
17
|
+
import { type Client } from './generated/client';
|
|
18
|
+
/** The production Pulsight API root. */
|
|
19
|
+
export declare const DEFAULT_BASE_URL = "https://pulsight.xyz";
|
|
20
|
+
export interface CreatePulsightClientOptions {
|
|
21
|
+
/** API root override, e.g. a staging URL. Defaults to {@link DEFAULT_BASE_URL}. */
|
|
22
|
+
baseUrl?: string;
|
|
23
|
+
/** Retries for idempotent (GET/HEAD) requests on HTTP 429. Default 2; 0 disables. */
|
|
24
|
+
retries?: number;
|
|
25
|
+
/** Per-request timeout in ms (default 30000). */
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build an authenticated client for the given api token (`pk_live_…`). The
|
|
30
|
+
* token rides the `Authorization` header on every request; product docs call
|
|
31
|
+
* it an "api token", never a "Bearer token".
|
|
32
|
+
*/
|
|
33
|
+
export declare function createPulsightClient(apiToken: string, opts?: CreatePulsightClientOptions): Client;
|
|
34
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAA8B,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAI7E,wCAAwC;AACxC,eAAO,MAAM,gBAAgB,yBAAyB,CAAC;AAEvD,MAAM,WAAW,2BAA2B;IAC1C,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,2BAAgC,GACrC,MAAM,CAgBR"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authenticated fetch client for the Pulsight API.
|
|
3
|
+
*
|
|
4
|
+
* Builds a `@hey-api/client-fetch` client (the same runtime the generated
|
|
5
|
+
* operations in ./generated expect) configured with api-token auth and 429
|
|
6
|
+
* retry. Pass the returned client to any generated operation:
|
|
7
|
+
*
|
|
8
|
+
* import { createPulsightClient, getApiTraders } from '@pulsight-xyz/sdk';
|
|
9
|
+
* const client = createPulsightClient('pk_live_…');
|
|
10
|
+
* const { data } = await getApiTraders({ client });
|
|
11
|
+
*
|
|
12
|
+
* Built on the GENERATED client runtime (`./generated/client`), which
|
|
13
|
+
* @hey-api/openapi-ts vendors into the package — the generated operations
|
|
14
|
+
* expect exactly that `Client` type, so the standalone `@hey-api/client-fetch`
|
|
15
|
+
* npm package (whose types differ subtly) must NOT be used here.
|
|
16
|
+
*/
|
|
17
|
+
import { createClient, createConfig } from './generated/client';
|
|
18
|
+
import { retryAfterSeconds } from './errors';
|
|
19
|
+
/** The production Pulsight API root. */
|
|
20
|
+
export const DEFAULT_BASE_URL = 'https://pulsight.xyz';
|
|
21
|
+
/**
|
|
22
|
+
* Build an authenticated client for the given api token (`pk_live_…`). The
|
|
23
|
+
* token rides the `Authorization` header on every request; product docs call
|
|
24
|
+
* it an "api token", never a "Bearer token".
|
|
25
|
+
*/
|
|
26
|
+
export function createPulsightClient(apiToken, opts = {}) {
|
|
27
|
+
const { baseUrl = DEFAULT_BASE_URL, retries = 2, timeoutMs = 30_000 } = opts;
|
|
28
|
+
const client = createClient(createConfig({
|
|
29
|
+
baseUrl,
|
|
30
|
+
fetch: retryingFetch(retries, timeoutMs),
|
|
31
|
+
}));
|
|
32
|
+
client.interceptors.request.use((request) => {
|
|
33
|
+
request.headers.set('Authorization', `Bearer ${apiToken}`);
|
|
34
|
+
return request;
|
|
35
|
+
});
|
|
36
|
+
return client;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A `fetch` wrapper that retries idempotent (GET/HEAD) requests on HTTP 429,
|
|
40
|
+
* honouring `Retry-After` (else exponential backoff), and applies a per-attempt
|
|
41
|
+
* timeout when the caller did not pass their own `AbortSignal`.
|
|
42
|
+
*/
|
|
43
|
+
function retryingFetch(retries, timeoutMs) {
|
|
44
|
+
return async (input, init) => {
|
|
45
|
+
const method = (init?.method ?? 'GET').toUpperCase();
|
|
46
|
+
const idempotent = method === 'GET' || method === 'HEAD';
|
|
47
|
+
const attempts = 1 + (idempotent ? Math.max(0, retries) : 0);
|
|
48
|
+
let response;
|
|
49
|
+
for (let i = 0; i < attempts; i++) {
|
|
50
|
+
const controller = new AbortController();
|
|
51
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
52
|
+
try {
|
|
53
|
+
response = await fetch(input, {
|
|
54
|
+
...init,
|
|
55
|
+
signal: init?.signal ?? controller.signal,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
}
|
|
61
|
+
if (response.status !== 429 || i === attempts - 1)
|
|
62
|
+
return response;
|
|
63
|
+
const waitMs = retryAfterSeconds(response.headers) * 1000 || backoffMs(i);
|
|
64
|
+
await sleep(waitMs);
|
|
65
|
+
}
|
|
66
|
+
// Unreachable (attempts >= 1), but keeps the type checker happy.
|
|
67
|
+
return response;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Exponential backoff (200ms base) with up to 100ms of jitter. */
|
|
71
|
+
function backoffMs(attempt) {
|
|
72
|
+
return (1 << attempt) * 200 + Math.floor(Math.random() * 100);
|
|
73
|
+
}
|
|
74
|
+
function sleep(ms) {
|
|
75
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed errors for the Pulsight API wire contract.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors sdks/go/errors.go, sdks/python/pulsight/errors.py and
|
|
5
|
+
* sdks/rust/src/errors.rs — the 402 / 429 / 403 responses map to first-class
|
|
6
|
+
* classes so callers branch on `instanceof` instead of string-matching a body.
|
|
7
|
+
*/
|
|
8
|
+
/** Base class for every Pulsight client error. */
|
|
9
|
+
export declare class PulsightError extends Error {
|
|
10
|
+
}
|
|
11
|
+
/** HTTP 402 CREDIT_EXHAUSTED — the api credit pool is empty this cycle. */
|
|
12
|
+
export declare class CreditExhaustedError extends PulsightError {
|
|
13
|
+
readonly pool: string;
|
|
14
|
+
constructor(pool: string);
|
|
15
|
+
}
|
|
16
|
+
/** HTTP 429 — too many requests. `retryAfter` is seconds (0 when absent). */
|
|
17
|
+
export declare class RateLimitedError extends PulsightError {
|
|
18
|
+
readonly retryAfter: number;
|
|
19
|
+
constructor(retryAfter: number);
|
|
20
|
+
}
|
|
21
|
+
/** HTTP 403 — the api token lacks a required scope. */
|
|
22
|
+
export declare class MissingScopeError extends PulsightError {
|
|
23
|
+
readonly reason: string;
|
|
24
|
+
constructor(reason: string);
|
|
25
|
+
}
|
|
26
|
+
/** Any other non-2xx response. */
|
|
27
|
+
export declare class ApiError extends PulsightError {
|
|
28
|
+
readonly status: number;
|
|
29
|
+
readonly body: string;
|
|
30
|
+
constructor(status: number, body: string);
|
|
31
|
+
}
|
|
32
|
+
/** Remaining api credits from the `X-Credits-Remaining` header, or null. */
|
|
33
|
+
export declare function creditsRemaining(headers: Headers): number | null;
|
|
34
|
+
/** Seconds from the `Retry-After` header (0 when absent/unparseable). */
|
|
35
|
+
export declare function retryAfterSeconds(headers: Headers): number;
|
|
36
|
+
/**
|
|
37
|
+
* Throw a typed error for a non-2xx {@link Response}; no-op on 2xx. Clones the
|
|
38
|
+
* response to read the body, so the caller can still consume `response` after.
|
|
39
|
+
*/
|
|
40
|
+
export declare function raiseForResponse(response: Response): Promise<void>;
|
|
41
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,kDAAkD;AAClD,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAE3C,2EAA2E;AAC3E,qBAAa,oBAAqB,SAAQ,aAAa;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,IAAI,EAAE,MAAM;CAKzB;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAChB,UAAU,EAAE,MAAM;CAK/B;AAED,uDAAuD;AACvD,qBAAa,iBAAkB,SAAQ,aAAa;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM;CAK3B;AAED,kCAAkC;AAClC,qBAAa,QAAS,SAAQ,aAAa;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAMzC;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAKhE;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAK1D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBxE"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed errors for the Pulsight API wire contract.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors sdks/go/errors.go, sdks/python/pulsight/errors.py and
|
|
5
|
+
* sdks/rust/src/errors.rs — the 402 / 429 / 403 responses map to first-class
|
|
6
|
+
* classes so callers branch on `instanceof` instead of string-matching a body.
|
|
7
|
+
*/
|
|
8
|
+
/** Base class for every Pulsight client error. */
|
|
9
|
+
export class PulsightError extends Error {
|
|
10
|
+
}
|
|
11
|
+
/** HTTP 402 CREDIT_EXHAUSTED — the api credit pool is empty this cycle. */
|
|
12
|
+
export class CreditExhaustedError extends PulsightError {
|
|
13
|
+
pool;
|
|
14
|
+
constructor(pool) {
|
|
15
|
+
super(`credit pool ${JSON.stringify(pool)} exhausted (HTTP 402)`);
|
|
16
|
+
this.name = 'CreditExhaustedError';
|
|
17
|
+
this.pool = pool;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** HTTP 429 — too many requests. `retryAfter` is seconds (0 when absent). */
|
|
21
|
+
export class RateLimitedError extends PulsightError {
|
|
22
|
+
retryAfter;
|
|
23
|
+
constructor(retryAfter) {
|
|
24
|
+
super(`rate limited, retry after ${retryAfter}s (HTTP 429)`);
|
|
25
|
+
this.name = 'RateLimitedError';
|
|
26
|
+
this.retryAfter = retryAfter;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** HTTP 403 — the api token lacks a required scope. */
|
|
30
|
+
export class MissingScopeError extends PulsightError {
|
|
31
|
+
reason;
|
|
32
|
+
constructor(reason) {
|
|
33
|
+
super(`${reason} (HTTP 403)`);
|
|
34
|
+
this.name = 'MissingScopeError';
|
|
35
|
+
this.reason = reason;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Any other non-2xx response. */
|
|
39
|
+
export class ApiError extends PulsightError {
|
|
40
|
+
status;
|
|
41
|
+
body;
|
|
42
|
+
constructor(status, body) {
|
|
43
|
+
super(`unexpected status ${status}: ${body}`);
|
|
44
|
+
this.name = 'ApiError';
|
|
45
|
+
this.status = status;
|
|
46
|
+
this.body = body;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Remaining api credits from the `X-Credits-Remaining` header, or null. */
|
|
50
|
+
export function creditsRemaining(headers) {
|
|
51
|
+
const raw = headers.get('X-Credits-Remaining');
|
|
52
|
+
if (raw === null)
|
|
53
|
+
return null;
|
|
54
|
+
const n = Number.parseInt(raw, 10);
|
|
55
|
+
return Number.isFinite(n) ? n : null;
|
|
56
|
+
}
|
|
57
|
+
/** Seconds from the `Retry-After` header (0 when absent/unparseable). */
|
|
58
|
+
export function retryAfterSeconds(headers) {
|
|
59
|
+
const raw = headers.get('Retry-After');
|
|
60
|
+
if (!raw)
|
|
61
|
+
return 0;
|
|
62
|
+
const n = Number.parseInt(raw, 10);
|
|
63
|
+
return Number.isFinite(n) ? n : 0;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Throw a typed error for a non-2xx {@link Response}; no-op on 2xx. Clones the
|
|
67
|
+
* response to read the body, so the caller can still consume `response` after.
|
|
68
|
+
*/
|
|
69
|
+
export async function raiseForResponse(response) {
|
|
70
|
+
if (response.ok)
|
|
71
|
+
return;
|
|
72
|
+
const text = await response
|
|
73
|
+
.clone()
|
|
74
|
+
.text()
|
|
75
|
+
.catch(() => '');
|
|
76
|
+
const json = safeJson(text);
|
|
77
|
+
switch (response.status) {
|
|
78
|
+
case 402:
|
|
79
|
+
throw new CreditExhaustedError(typeof json?.pool === 'string' ? json.pool : '');
|
|
80
|
+
case 429:
|
|
81
|
+
throw new RateLimitedError(retryAfterSeconds(response.headers));
|
|
82
|
+
case 403:
|
|
83
|
+
throw new MissingScopeError(typeof json?.error === 'string' ? json.error : 'forbidden');
|
|
84
|
+
default:
|
|
85
|
+
throw new ApiError(response.status, text);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function safeJson(text) {
|
|
89
|
+
try {
|
|
90
|
+
return JSON.parse(text);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.gen.d.ts","sourceRoot":"","sources":["../../../src/generated/client/client.gen.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAA0C,MAAM,aAAa,CAAC;AAgB1F,eAAO,MAAM,YAAY,GAAI,SAAQ,MAAW,KAAG,MA+PlD,CAAC"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// This file is auto-generated by @hey-api/openapi-ts
|
|
2
|
+
import { createSseClient } from '../core/serverSentEvents.gen';
|
|
3
|
+
import { getValidRequestBody } from '../core/utils.gen';
|
|
4
|
+
import { buildUrl, createConfig, createInterceptors, getParseAs, mergeConfigs, mergeHeaders, setAuthParams, } from './utils.gen';
|
|
5
|
+
export const createClient = (config = {}) => {
|
|
6
|
+
let _config = mergeConfigs(createConfig(), config);
|
|
7
|
+
const getConfig = () => ({ ..._config });
|
|
8
|
+
const setConfig = (config) => {
|
|
9
|
+
_config = mergeConfigs(_config, config);
|
|
10
|
+
return getConfig();
|
|
11
|
+
};
|
|
12
|
+
const interceptors = createInterceptors();
|
|
13
|
+
const beforeRequest = async (options) => {
|
|
14
|
+
const opts = {
|
|
15
|
+
..._config,
|
|
16
|
+
...options,
|
|
17
|
+
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
|
18
|
+
headers: mergeHeaders(_config.headers, options.headers),
|
|
19
|
+
serializedBody: undefined,
|
|
20
|
+
};
|
|
21
|
+
if (opts.security) {
|
|
22
|
+
await setAuthParams(opts);
|
|
23
|
+
}
|
|
24
|
+
if (opts.requestValidator) {
|
|
25
|
+
await opts.requestValidator(opts);
|
|
26
|
+
}
|
|
27
|
+
if (opts.body !== undefined && opts.bodySerializer) {
|
|
28
|
+
opts.serializedBody = opts.bodySerializer(opts.body);
|
|
29
|
+
}
|
|
30
|
+
// remove Content-Type header if body is empty to avoid sending invalid requests
|
|
31
|
+
if (opts.body === undefined || opts.serializedBody === '') {
|
|
32
|
+
opts.headers.delete('Content-Type');
|
|
33
|
+
}
|
|
34
|
+
const resolvedOpts = opts;
|
|
35
|
+
const url = buildUrl(resolvedOpts);
|
|
36
|
+
return { opts: resolvedOpts, url };
|
|
37
|
+
};
|
|
38
|
+
const request = async (options) => {
|
|
39
|
+
const throwOnError = options.throwOnError ?? _config.throwOnError;
|
|
40
|
+
const responseStyle = options.responseStyle ?? _config.responseStyle;
|
|
41
|
+
let request;
|
|
42
|
+
let response;
|
|
43
|
+
try {
|
|
44
|
+
const { opts, url } = await beforeRequest(options);
|
|
45
|
+
const requestInit = {
|
|
46
|
+
redirect: 'follow',
|
|
47
|
+
...opts,
|
|
48
|
+
body: getValidRequestBody(opts),
|
|
49
|
+
};
|
|
50
|
+
request = new Request(url, requestInit);
|
|
51
|
+
for (const fn of interceptors.request.fns) {
|
|
52
|
+
if (fn) {
|
|
53
|
+
request = await fn(request, opts);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// fetch must be assigned here, otherwise it would throw the error:
|
|
57
|
+
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
|
|
58
|
+
const _fetch = opts.fetch;
|
|
59
|
+
response = await _fetch(request);
|
|
60
|
+
for (const fn of interceptors.response.fns) {
|
|
61
|
+
if (fn) {
|
|
62
|
+
response = await fn(response, request, opts);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const result = {
|
|
66
|
+
request,
|
|
67
|
+
response,
|
|
68
|
+
};
|
|
69
|
+
if (response.ok) {
|
|
70
|
+
const parseAs = (opts.parseAs === 'auto'
|
|
71
|
+
? getParseAs(response.headers.get('Content-Type'))
|
|
72
|
+
: opts.parseAs) ?? 'json';
|
|
73
|
+
if (response.status === 204 || response.headers.get('Content-Length') === '0') {
|
|
74
|
+
let emptyData;
|
|
75
|
+
switch (parseAs) {
|
|
76
|
+
case 'arrayBuffer':
|
|
77
|
+
case 'blob':
|
|
78
|
+
case 'text':
|
|
79
|
+
emptyData = await response[parseAs]();
|
|
80
|
+
break;
|
|
81
|
+
case 'formData':
|
|
82
|
+
emptyData = new FormData();
|
|
83
|
+
break;
|
|
84
|
+
case 'stream':
|
|
85
|
+
emptyData = response.body;
|
|
86
|
+
break;
|
|
87
|
+
case 'json':
|
|
88
|
+
default:
|
|
89
|
+
emptyData = {};
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
return opts.responseStyle === 'data'
|
|
93
|
+
? emptyData
|
|
94
|
+
: {
|
|
95
|
+
data: emptyData,
|
|
96
|
+
...result,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
let data;
|
|
100
|
+
switch (parseAs) {
|
|
101
|
+
case 'arrayBuffer':
|
|
102
|
+
case 'blob':
|
|
103
|
+
case 'formData':
|
|
104
|
+
case 'text':
|
|
105
|
+
data = await response[parseAs]();
|
|
106
|
+
break;
|
|
107
|
+
case 'json': {
|
|
108
|
+
// Some servers return 200 with no Content-Length and empty body.
|
|
109
|
+
// response.json() would throw; read as text and parse if non-empty.
|
|
110
|
+
const text = await response.text();
|
|
111
|
+
data = text ? JSON.parse(text) : {};
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
case 'stream':
|
|
115
|
+
return opts.responseStyle === 'data'
|
|
116
|
+
? response.body
|
|
117
|
+
: {
|
|
118
|
+
data: response.body,
|
|
119
|
+
...result,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (parseAs === 'json') {
|
|
123
|
+
if (opts.responseValidator) {
|
|
124
|
+
await opts.responseValidator(data);
|
|
125
|
+
}
|
|
126
|
+
if (opts.responseTransformer) {
|
|
127
|
+
data = await opts.responseTransformer(data);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return opts.responseStyle === 'data'
|
|
131
|
+
? data
|
|
132
|
+
: {
|
|
133
|
+
data,
|
|
134
|
+
...result,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const textError = await response.text();
|
|
138
|
+
let jsonError;
|
|
139
|
+
try {
|
|
140
|
+
jsonError = JSON.parse(textError);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// noop
|
|
144
|
+
}
|
|
145
|
+
throw jsonError ?? textError;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
let finalError = error;
|
|
149
|
+
for (const fn of interceptors.error.fns) {
|
|
150
|
+
if (fn) {
|
|
151
|
+
finalError = await fn(finalError, response, request, options);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
finalError = finalError || {};
|
|
155
|
+
if (throwOnError) {
|
|
156
|
+
throw finalError;
|
|
157
|
+
}
|
|
158
|
+
// TODO: we probably want to return error and improve types
|
|
159
|
+
return responseStyle === 'data'
|
|
160
|
+
? undefined
|
|
161
|
+
: {
|
|
162
|
+
error: finalError,
|
|
163
|
+
request,
|
|
164
|
+
response,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const makeMethodFn = (method) => (options) => request({ ...options, method });
|
|
169
|
+
const makeSseFn = (method) => async (options) => {
|
|
170
|
+
const { opts, url } = await beforeRequest(options);
|
|
171
|
+
return createSseClient({
|
|
172
|
+
...opts,
|
|
173
|
+
body: opts.body,
|
|
174
|
+
method,
|
|
175
|
+
onRequest: async (url, init) => {
|
|
176
|
+
let request = new Request(url, init);
|
|
177
|
+
for (const fn of interceptors.request.fns) {
|
|
178
|
+
if (fn) {
|
|
179
|
+
request = await fn(request, opts);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return request;
|
|
183
|
+
},
|
|
184
|
+
serializedBody: getValidRequestBody(opts),
|
|
185
|
+
url,
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
const _buildUrl = (options) => buildUrl({ ..._config, ...options });
|
|
189
|
+
return {
|
|
190
|
+
buildUrl: _buildUrl,
|
|
191
|
+
connect: makeMethodFn('CONNECT'),
|
|
192
|
+
delete: makeMethodFn('DELETE'),
|
|
193
|
+
get: makeMethodFn('GET'),
|
|
194
|
+
getConfig,
|
|
195
|
+
head: makeMethodFn('HEAD'),
|
|
196
|
+
interceptors,
|
|
197
|
+
options: makeMethodFn('OPTIONS'),
|
|
198
|
+
patch: makeMethodFn('PATCH'),
|
|
199
|
+
post: makeMethodFn('POST'),
|
|
200
|
+
put: makeMethodFn('PUT'),
|
|
201
|
+
request,
|
|
202
|
+
setConfig,
|
|
203
|
+
sse: {
|
|
204
|
+
connect: makeSseFn('CONNECT'),
|
|
205
|
+
delete: makeSseFn('DELETE'),
|
|
206
|
+
get: makeSseFn('GET'),
|
|
207
|
+
head: makeSseFn('HEAD'),
|
|
208
|
+
options: makeSseFn('OPTIONS'),
|
|
209
|
+
patch: makeSseFn('PATCH'),
|
|
210
|
+
post: makeSseFn('POST'),
|
|
211
|
+
put: makeSseFn('PUT'),
|
|
212
|
+
trace: makeSseFn('TRACE'),
|
|
213
|
+
},
|
|
214
|
+
trace: makeMethodFn('TRACE'),
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
//# sourceMappingURL=client.gen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.gen.js","sourceRoot":"","sources":["../../../src/generated/client/client.gen.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,aAAa,CAAC;AAOrB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAiB,EAAE,EAAU,EAAE;IAC1D,IAAI,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,EAAE,MAAM,CAAC,CAAC;IAEnD,MAAM,SAAS,GAAG,GAAW,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAEjD,MAAM,SAAS,GAAG,CAAC,MAAc,EAAU,EAAE;QAC3C,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxC,OAAO,SAAS,EAAE,CAAC;IACrB,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,kBAAkB,EAAsD,CAAC;IAE9F,MAAM,aAAa,GAAG,KAAK,EAMzB,OAAiE,EACjE,EAAE;QACF,MAAM,IAAI,GAAG;YACX,GAAG,OAAO;YACV,GAAG,OAAO;YACV,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK;YACzD,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;YACvD,cAAc,EAAE,SAA+B;SAChD,CAAC;QAEF,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACnD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAuB,CAAC;QAC7E,CAAC;QAED,gFAAgF;QAChF,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,KAAK,EAAE,EAAE,CAAC;YAC1D,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,YAAY,GAAG,IACsC,CAAC;QAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QAEnC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;IACrC,CAAC,CAAC;IAEF,MAAM,OAAO,GAAsB,KAAK,EAAE,OAAO,EAAE,EAAE;QACnD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;QAClE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;QAErE,IAAI,OAA4B,CAAC;QACjC,IAAI,QAA8B,CAAC;QAEnC,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;YACnD,MAAM,WAAW,GAAY;gBAC3B,QAAQ,EAAE,QAAQ;gBAClB,GAAG,IAAI;gBACP,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC;aAChC,CAAC;YAEF,OAAO,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAExC,KAAK,MAAM,EAAE,IAAI,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;gBAC1C,IAAI,EAAE,EAAE,CAAC;oBACP,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;YAED,mEAAmE;YACnE,uEAAuE;YACvE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAM,CAAC;YAE3B,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;YAEjC,KAAK,MAAM,EAAE,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBAC3C,IAAI,EAAE,EAAE,CAAC;oBACP,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG;gBACb,OAAO;gBACP,QAAQ;aACT,CAAC;YAEF,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,MAAM,OAAO,GACX,CAAC,IAAI,CAAC,OAAO,KAAK,MAAM;oBACtB,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;oBAClD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC;gBAE9B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,GAAG,EAAE,CAAC;oBAC9E,IAAI,SAAc,CAAC;oBACnB,QAAQ,OAAO,EAAE,CAAC;wBAChB,KAAK,aAAa,CAAC;wBACnB,KAAK,MAAM,CAAC;wBACZ,KAAK,MAAM;4BACT,SAAS,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;4BACtC,MAAM;wBACR,KAAK,UAAU;4BACb,SAAS,GAAG,IAAI,QAAQ,EAAE,CAAC;4BAC3B,MAAM;wBACR,KAAK,QAAQ;4BACX,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC;4BAC1B,MAAM;wBACR,KAAK,MAAM,CAAC;wBACZ;4BACE,SAAS,GAAG,EAAE,CAAC;4BACf,MAAM;oBACV,CAAC;oBACD,OAAO,IAAI,CAAC,aAAa,KAAK,MAAM;wBAClC,CAAC,CAAC,SAAS;wBACX,CAAC,CAAC;4BACE,IAAI,EAAE,SAAS;4BACf,GAAG,MAAM;yBACV,CAAC;gBACR,CAAC;gBAED,IAAI,IAAS,CAAC;gBACd,QAAQ,OAAO,EAAE,CAAC;oBAChB,KAAK,aAAa,CAAC;oBACnB,KAAK,MAAM,CAAC;oBACZ,KAAK,UAAU,CAAC;oBAChB,KAAK,MAAM;wBACT,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;wBACjC,MAAM;oBACR,KAAK,MAAM,CAAC,CAAC,CAAC;wBACZ,iEAAiE;wBACjE,oEAAoE;wBACpE,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;wBACnC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;wBACpC,MAAM;oBACR,CAAC;oBACD,KAAK,QAAQ;wBACX,OAAO,IAAI,CAAC,aAAa,KAAK,MAAM;4BAClC,CAAC,CAAC,QAAQ,CAAC,IAAI;4BACf,CAAC,CAAC;gCACE,IAAI,EAAE,QAAQ,CAAC,IAAI;gCACnB,GAAG,MAAM;6BACV,CAAC;gBACV,CAAC;gBAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;oBACvB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;wBAC3B,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;oBACrC,CAAC;oBAED,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;wBAC7B,IAAI,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;oBAC9C,CAAC;gBACH,CAAC;gBAED,OAAO,IAAI,CAAC,aAAa,KAAK,MAAM;oBAClC,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC;wBACE,IAAI;wBACJ,GAAG,MAAM;qBACV,CAAC;YACR,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,IAAI,SAAkB,CAAC;YAEvB,IAAI,CAAC;gBACH,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;YAED,MAAM,SAAS,IAAI,SAAS,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,UAAU,GAAG,KAAK,CAAC;YAEvB,KAAK,MAAM,EAAE,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBACxC,IAAI,EAAE,EAAE,CAAC;oBACP,UAAU,GAAG,MAAM,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAiC,CAAC,CAAC;gBAC1F,CAAC;YACH,CAAC;YAED,UAAU,GAAG,UAAU,IAAI,EAAE,CAAC;YAE9B,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,UAAU,CAAC;YACnB,CAAC;YAED,2DAA2D;YAC3D,OAAO,aAAa,KAAK,MAAM;gBAC7B,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC;oBACE,KAAK,EAAE,UAAU;oBACjB,OAAO;oBACP,QAAQ;iBACT,CAAC;QACR,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,MAA6B,EAAE,EAAE,CAAC,CAAC,OAAuB,EAAE,EAAE,CAClF,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAElC,MAAM,SAAS,GAAG,CAAC,MAA6B,EAAE,EAAE,CAAC,KAAK,EAAE,OAAuB,EAAE,EAAE;QACrF,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;QACnD,OAAO,eAAe,CAAC;YACrB,GAAG,IAAI;YACP,IAAI,EAAE,IAAI,CAAC,IAAmC;YAC9C,MAAM;YACN,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;gBAC7B,IAAI,OAAO,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACrC,KAAK,MAAM,EAAE,IAAI,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;oBAC1C,IAAI,EAAE,EAAE,CAAC;wBACP,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBACpC,CAAC;gBACH,CAAC;gBACD,OAAO,OAAO,CAAC;YACjB,CAAC;YACD,cAAc,EAAE,mBAAmB,CAAC,IAAI,CAAgC;YACxE,GAAG;SACJ,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,SAAS,GAAuB,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAExF,OAAO;QACL,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC;QAChC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC;QAC9B,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC;QACxB,SAAS;QACT,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;QAC1B,YAAY;QACZ,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC;QAChC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC;QAC5B,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;QAC1B,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC;QACxB,OAAO;QACP,SAAS;QACT,GAAG,EAAE;YACH,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC;YAC7B,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC;YAC3B,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC;YACrB,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC;YAC7B,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC;YACzB,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC;YACvB,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC;YACrB,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC;SAC1B;QACD,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC;KACnB,CAAC;AACd,CAAC,CAAC"}
|