listo-delivery 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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +182 -2
  3. package/dist/client.d.ts +17 -0
  4. package/dist/client.js +25 -0
  5. package/dist/errors.d.ts +43 -0
  6. package/dist/errors.js +95 -0
  7. package/dist/generated/client/client.gen.d.ts +2 -0
  8. package/dist/generated/client/client.gen.js +216 -0
  9. package/dist/generated/client/index.d.ts +10 -0
  10. package/dist/generated/client/index.js +6 -0
  11. package/dist/generated/client/types.gen.d.ts +120 -0
  12. package/dist/generated/client/types.gen.js +2 -0
  13. package/dist/generated/client/utils.gen.d.ts +37 -0
  14. package/dist/generated/client/utils.gen.js +228 -0
  15. package/dist/generated/client.gen.d.ts +12 -0
  16. package/dist/generated/client.gen.js +3 -0
  17. package/dist/generated/core/auth.gen.d.ts +25 -0
  18. package/dist/generated/core/auth.gen.js +14 -0
  19. package/dist/generated/core/bodySerializer.gen.d.ts +25 -0
  20. package/dist/generated/core/bodySerializer.gen.js +57 -0
  21. package/dist/generated/core/params.gen.d.ts +43 -0
  22. package/dist/generated/core/params.gen.js +109 -0
  23. package/dist/generated/core/pathSerializer.gen.d.ts +33 -0
  24. package/dist/generated/core/pathSerializer.gen.js +106 -0
  25. package/dist/generated/core/queryKeySerializer.gen.d.ts +18 -0
  26. package/dist/generated/core/queryKeySerializer.gen.js +92 -0
  27. package/dist/generated/core/serverSentEvents.gen.d.ts +71 -0
  28. package/dist/generated/core/serverSentEvents.gen.js +132 -0
  29. package/dist/generated/core/types.gen.d.ts +83 -0
  30. package/dist/generated/core/types.gen.js +2 -0
  31. package/dist/generated/core/utils.gen.d.ts +19 -0
  32. package/dist/generated/core/utils.gen.js +87 -0
  33. package/dist/generated/index.d.ts +2 -0
  34. package/dist/generated/index.js +2 -0
  35. package/dist/generated/sdk.gen.d.ts +1124 -0
  36. package/dist/generated/sdk.gen.js +1307 -0
  37. package/dist/generated/types.gen.d.ts +3331 -0
  38. package/dist/generated/types.gen.js +2 -0
  39. package/dist/http.d.ts +29 -0
  40. package/dist/http.js +148 -0
  41. package/dist/index.d.ts +10 -0
  42. package/dist/index.js +5 -0
  43. package/dist/meta.gen.d.ts +3 -0
  44. package/dist/meta.gen.js +5 -0
  45. package/dist/resources.gen.d.ts +381 -0
  46. package/dist/resources.gen.js +293 -0
  47. package/dist/transport.d.ts +40 -0
  48. package/dist/transport.js +4 -0
  49. package/dist/webhooks.d.ts +32 -0
  50. package/dist/webhooks.js +79 -0
  51. package/package.json +48 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cheto Labs, S.A.P.I. de C.V.
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,183 @@
1
- # Temporary Holding Version
1
+ # listo-delivery
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The official TypeScript SDK for the [Listo Delivery API](https://docs.listo.delivery).
4
+ It has no runtime dependencies: it uses the global `fetch` and `node:crypto`, and runs on Node 18 or later.
5
+
6
+ The types, the request code and the resources are generated from the published
7
+ OpenAPI schema, so a field the API documents is a field you get.
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npm i listo-delivery
13
+ ```
14
+
15
+ ## Quickstart: quote and book a test delivery
16
+
17
+ A key that starts with `lst_test_` dispatches simulated couriers and moves no
18
+ money. `lst_live_` books real ones. The prefix decides the mode: `listo.mode`
19
+ is `"test"` or `"live"`, and there is no separate option.
20
+
21
+ ```ts
22
+ import { Listo } from "listo-delivery";
23
+
24
+ const listo = new Listo({ apiKey: process.env.LISTO_API_KEY! });
25
+
26
+ const quote = await listo.quotes.create({
27
+ store_id: "st_...",
28
+ dropoff: { street: "Av. Vallarta 1234, Guadalajara" },
29
+ });
30
+
31
+ const delivery = await listo.deliveries.create(
32
+ {
33
+ store_id: "st_...",
34
+ quote_id: quote.id,
35
+ external_id: "order-841", // your own order id
36
+ payment_method: "prepaid",
37
+ order_value_cents: 18000,
38
+ dropoff: { name: "Ana", phone: "+523312345678", street: "Av. Vallarta 1234, Guadalajara" },
39
+ },
40
+ { idempotencyKey: "order-841" },
41
+ );
42
+
43
+ console.log(delivery.id, delivery.status);
44
+ ```
45
+
46
+ A file that uses top-level `await`, like this one, needs `"type": "module"` in
47
+ your project's `package.json` for `tsc` to accept it (Node runs it either way).
48
+
49
+ Field names are the wire names (`store_id`, `order_value_cents`). Every call is
50
+ `listo.<resource>.<method>(...pathValues, bodyOrQuery?, options?)`: path values
51
+ come first, in path order, then one object (the body of a write, the query of a
52
+ read), then the options. A body the schema requires is a required argument.
53
+
54
+ ```ts
55
+ await listo.deliveries.retrieve("dlv_...");
56
+ await listo.deliveries.cancel("dlv_...", { reason: "customer_canceled" });
57
+ await listo.ledger.listForStore("st_...", { cursor });
58
+ await listo.ping();
59
+ ```
60
+
61
+ Every operation of the API is a method, named after it and camel-cased here
62
+ (`listo.requestLogs`, `listo.cardOnboarding.createForStore`, ...); the API reference at
63
+ [docs.listo.delivery](https://docs.listo.delivery) lists them all.
64
+
65
+ ## Verify a webhook
66
+
67
+ Verify the RAW body exactly as it arrived, before any JSON parsing. A parsed and
68
+ re-serialised body has different bytes and will not match.
69
+
70
+ ```ts
71
+ import express from "express";
72
+ import { Listo, ListoError } from "listo-delivery";
73
+
74
+ const app = express();
75
+
76
+ app.post("/webhooks/listo", express.raw({ type: "application/json" }), (req, res) => {
77
+ try {
78
+ const event = Listo.webhooks.constructEvent(
79
+ req.body, // a Buffer
80
+ req.header("X-Listo-Signature"),
81
+ [process.env.LISTO_WEBHOOK_SECRET!], // two during a secret rotation
82
+ );
83
+ if (event.type === "delivery.status_changed") {
84
+ console.log(event.data.id, event.data.status); // narrowed to a Delivery
85
+ }
86
+ res.sendStatus(204);
87
+ } catch (error) {
88
+ // ListoError covers both refusals: invalid_signature (ListoSignatureError)
89
+ // and invalid_payload (a signed body that is not a JSON object).
90
+ if (error instanceof ListoError) return void res.sendStatus(400);
91
+ throw error;
92
+ }
93
+ });
94
+ ```
95
+
96
+ `Listo.webhooks` (also exported as `webhooks`) needs no API key. The same two
97
+ functions are on `listo.webhooks` next to the API's own webhook calls.
98
+
99
+ - `verify(rawBody, header, secrets, { tolerance?, now? })` returns a boolean and never throws.
100
+ The header must be `t=<unix seconds>,v1=<hex>`; the signed string is `"<t>.<raw body>"`;
101
+ a timestamp more than 300 seconds from now in either direction is refused, and so is
102
+ an upper-case signature. Blank secrets are ignored; with none left the answer is `false`.
103
+ - `constructEvent(...)` verifies, then parses the body into the `WebhookEvent` union,
104
+ discriminated on `type`. It throws `ListoSignatureError` (a `ListoError` with code
105
+ `invalid_signature`) on a bad signature, and a `ListoError` with code `invalid_payload`
106
+ when the signed body is not a JSON object. Beyond that it does not check the shape:
107
+ an event comes back as it arrived, typed by its `type` (the TypeScript types describe it,
108
+ they do not validate it), and one whose `type` this SDK does not know yet is not an
109
+ error either, so keep a default branch when you switch on `type`.
110
+
111
+ ## Errors
112
+
113
+ Every refusal and failure is one class, `ListoError`. Branch on `code`, never on `message`.
114
+
115
+ ```ts
116
+ import { ListoError, ListoConnectionError } from "listo-delivery";
117
+
118
+ try {
119
+ await listo.deliveries.create(body);
120
+ } catch (error) {
121
+ if (error instanceof ListoConnectionError) {
122
+ // No answer (DNS, refused, timeout). A write may have happened: retry with the SAME idempotency key.
123
+ } else if (error instanceof ListoError) {
124
+ console.log(error.code, error.status, error.param, error.retryable, error.requestId, error.docUrl);
125
+ }
126
+ }
127
+ ```
128
+
129
+ Fields: `code`, `message`, `param`, `retryable`, `status`, `requestId`, `docUrl`, and the
130
+ parsed response `body`. (Python and Ruby spell the last two `request_id` and `doc_url`.)
131
+ A response that is not the API's error envelope (an HTML page from a proxy) is still a
132
+ `ListoError`, with `code: "http_<status>"`. The API key is never put in an error message.
133
+
134
+ ## Idempotency
135
+
136
+ The operations whose schema takes an `Idempotency-Key` header (creating a delivery, a
137
+ refund, creating a store, reactivating or cancelling a store's plan) always send one:
138
+ yours when you pass `{ idempotencyKey }` (key it on your own order id; an empty or blank
139
+ key throws a `TypeError` before any request), otherwise a fresh UUID for that call.
140
+ Repeating a call with the same key within 24 hours returns the original answer instead of
141
+ doing the work again. No other operation sends the header, and passing `idempotencyKey` to
142
+ one is a compile-time error (and a `TypeError` before any request in plain JavaScript),
143
+ never silently dropped.
144
+
145
+ ## Pagination
146
+
147
+ List calls return the page as the schema has it: `data`, `has_more` and `cursor`.
148
+ Pass `cursor` back to get the next page.
149
+
150
+ ```ts
151
+ let cursor: string | undefined;
152
+ do {
153
+ const page = await listo.deliveries.list({ status: "delivered", cursor });
154
+ for (const delivery of page.data) console.log(delivery.id);
155
+ cursor = page.has_more && page.cursor ? page.cursor : undefined;
156
+ } while (cursor);
157
+ ```
158
+
159
+ ## Retries and timeouts
160
+
161
+ Nothing is retried by default. With `maxRetries: n`, only a `429` is retried, up to `n`
162
+ times, after the `Retry-After` wait (seconds or an HTTP date; 1 second when missing or
163
+ unreadable; never more than 60), with the same idempotency key. A `5xx` or a dropped
164
+ connection is never retried automatically, because a write may have happened.
165
+
166
+ ```ts
167
+ const listo = new Listo({
168
+ apiKey,
169
+ maxRetries: 2,
170
+ timeoutMs: 30_000, // per attempt, the default
171
+ baseUrl: "https://api.listo.delivery", // the default
172
+ fetch: customFetch, // optional; receives a Request
173
+ });
174
+ ```
175
+
176
+ A call also takes `{ signal }` to abort it.
177
+
178
+ ## About this repository
179
+
180
+ This code is generated from Listo's API definition. Issues and questions are
181
+ welcome in this repository. Changes are made upstream by Listo and released
182
+ here, so a pull request cannot be merged as it stands: open an issue and the
183
+ change is made at the source.
@@ -0,0 +1,17 @@
1
+ import type { ListoOptions } from "./http.ts";
2
+ import { Resources, WebhooksResource } from "./resources.gen.ts";
3
+ import type { WebhookVerifier } from "./webhooks.ts";
4
+ /** `listo.webhooks`: the API's webhook calls (send a test, read delivery attempts) plus the signature helpers. */
5
+ export declare class ListoWebhooks extends WebhooksResource {
6
+ verify(...args: Parameters<WebhookVerifier["verify"]>): boolean;
7
+ constructEvent(...args: Parameters<WebhookVerifier["constructEvent"]>): ReturnType<WebhookVerifier["constructEvent"]>;
8
+ }
9
+ export declare class Listo extends Resources {
10
+ /** The signature helpers without a client, for a receiver that holds no API key. */
11
+ static readonly webhooks: WebhookVerifier;
12
+ readonly webhooks: ListoWebhooks;
13
+ /** `"live"` or `"test"`, read from the key's prefix. */
14
+ readonly mode: "live" | "test";
15
+ readonly baseUrl: string;
16
+ constructor(options: ListoOptions);
17
+ }
package/dist/client.js ADDED
@@ -0,0 +1,25 @@
1
+ import { HttpTransport } from "./http.js";
2
+ import { Resources, WebhooksResource } from "./resources.gen.js";
3
+ import { constructEvent, verify, webhooks } from "./webhooks.js";
4
+ /** `listo.webhooks`: the API's webhook calls (send a test, read delivery attempts) plus the signature helpers. */
5
+ export class ListoWebhooks extends WebhooksResource {
6
+ verify(...args) {
7
+ return verify(...args);
8
+ }
9
+ constructEvent(...args) {
10
+ return constructEvent(...args);
11
+ }
12
+ }
13
+ export class Listo extends Resources {
14
+ /** The signature helpers without a client, for a receiver that holds no API key. */
15
+ static webhooks = webhooks;
16
+ /** `"live"` or `"test"`, read from the key's prefix. */
17
+ mode;
18
+ baseUrl;
19
+ constructor(options) {
20
+ const transport = new HttpTransport(options);
21
+ super(transport, { webhooks: new ListoWebhooks(transport) });
22
+ this.mode = transport.mode;
23
+ this.baseUrl = transport.baseUrl;
24
+ }
25
+ }
@@ -0,0 +1,43 @@
1
+ export interface ListoErrorFields {
2
+ code: string;
3
+ message: string;
4
+ param: string | null;
5
+ retryable: boolean;
6
+ status: number | null;
7
+ requestId: string | null;
8
+ docUrl: string | null;
9
+ body: unknown;
10
+ }
11
+ export declare class ListoError extends Error {
12
+ /** The stable name of what went wrong (`validation_failed`, `insufficient_balance`, ...). */
13
+ readonly code: string;
14
+ /** The request field the refusal is about, when one applies. */
15
+ readonly param: string | null;
16
+ /** Whether sending the identical request again could succeed. */
17
+ readonly retryable: boolean;
18
+ /** The HTTP status, or null when no response arrived. */
19
+ readonly status: number | null;
20
+ readonly requestId: string | null;
21
+ readonly docUrl: string | null;
22
+ /** The parsed response body (or its text when it was not JSON). */
23
+ readonly body: unknown;
24
+ constructor(fields: ListoErrorFields, options?: {
25
+ cause?: unknown;
26
+ });
27
+ }
28
+ /** DNS failure, refused connection or timeout: no answer arrived. A write may have happened. */
29
+ export declare class ListoConnectionError extends ListoError {
30
+ constructor(message: string, options?: {
31
+ cause?: unknown;
32
+ });
33
+ }
34
+ /** A webhook whose signature did not verify. A `ListoError` with code `invalid_signature`, as in Python and Ruby. */
35
+ export declare class ListoSignatureError extends ListoError {
36
+ constructor(message?: string);
37
+ }
38
+ /** A signed webhook body that is not a JSON object. Code `invalid_payload`, as in Python and Ruby. */
39
+ export declare function invalidPayload(message: string, options?: {
40
+ cause?: unknown;
41
+ }): ListoError;
42
+ /** Builds the error for a non-2xx answer from its parsed body (or text). */
43
+ export declare function errorFromResponse(status: number, requestIdHeader: string | null, body: unknown): ListoError;
package/dist/errors.js ADDED
@@ -0,0 +1,95 @@
1
+ // One error class for everything the API refuses, so a caller writes a single
2
+ // `catch (e) { if (e instanceof ListoError) ... }`. Branch on `code`, never on
3
+ // `message`, which is for a person reading a log.
4
+ const RETRYABLE_STATUSES = new Set([429, 502, 503, 504]);
5
+ export class ListoError extends Error {
6
+ /** The stable name of what went wrong (`validation_failed`, `insufficient_balance`, ...). */
7
+ code;
8
+ /** The request field the refusal is about, when one applies. */
9
+ param;
10
+ /** Whether sending the identical request again could succeed. */
11
+ retryable;
12
+ /** The HTTP status, or null when no response arrived. */
13
+ status;
14
+ requestId;
15
+ docUrl;
16
+ /** The parsed response body (or its text when it was not JSON). */
17
+ body;
18
+ constructor(fields, options) {
19
+ super(fields.message, options);
20
+ this.name = "ListoError";
21
+ this.code = fields.code;
22
+ this.param = fields.param;
23
+ this.retryable = fields.retryable;
24
+ this.status = fields.status;
25
+ this.requestId = fields.requestId;
26
+ this.docUrl = fields.docUrl;
27
+ this.body = fields.body;
28
+ }
29
+ }
30
+ /** DNS failure, refused connection or timeout: no answer arrived. A write may have happened. */
31
+ export class ListoConnectionError extends ListoError {
32
+ constructor(message, options) {
33
+ super({
34
+ code: "connection_error",
35
+ message,
36
+ param: null,
37
+ retryable: false,
38
+ status: null,
39
+ requestId: null,
40
+ docUrl: null,
41
+ body: null,
42
+ }, options);
43
+ this.name = "ListoConnectionError";
44
+ }
45
+ }
46
+ /** A webhook whose signature did not verify. A `ListoError` with code `invalid_signature`, as in Python and Ruby. */
47
+ export class ListoSignatureError extends ListoError {
48
+ constructor(message = "The webhook signature is not valid.") {
49
+ super({
50
+ code: "invalid_signature",
51
+ message,
52
+ param: null,
53
+ retryable: false,
54
+ status: null,
55
+ requestId: null,
56
+ docUrl: null,
57
+ body: null,
58
+ });
59
+ this.name = "ListoSignatureError";
60
+ }
61
+ }
62
+ /** A signed webhook body that is not a JSON object. Code `invalid_payload`, as in Python and Ruby. */
63
+ export function invalidPayload(message, options) {
64
+ return new ListoError({ code: "invalid_payload", message, param: null, retryable: false, status: null, requestId: null, docUrl: null, body: null }, options);
65
+ }
66
+ function isRecord(value) {
67
+ return typeof value === "object" && value !== null && !Array.isArray(value);
68
+ }
69
+ /** Builds the error for a non-2xx answer from its parsed body (or text). */
70
+ export function errorFromResponse(status, requestIdHeader, body) {
71
+ const envelope = isRecord(body) && isRecord(body.error) ? body.error : null;
72
+ if (envelope !== null && typeof envelope.code === "string") {
73
+ return new ListoError({
74
+ code: envelope.code,
75
+ message: typeof envelope.message === "string" ? envelope.message : `The API answered ${status}.`,
76
+ param: typeof envelope.param === "string" ? envelope.param : null,
77
+ retryable: typeof envelope.retryable === "boolean" ? envelope.retryable : RETRYABLE_STATUSES.has(status),
78
+ status,
79
+ requestId: typeof envelope.request_id === "string" ? envelope.request_id : requestIdHeader,
80
+ docUrl: typeof envelope.doc_url === "string" ? envelope.doc_url : null,
81
+ body,
82
+ });
83
+ }
84
+ // An HTML page from a proxy, or JSON of another shape.
85
+ return new ListoError({
86
+ code: `http_${status}`,
87
+ message: `Unexpected response with status ${status}`,
88
+ param: null,
89
+ retryable: RETRYABLE_STATUSES.has(status),
90
+ status,
91
+ requestId: requestIdHeader,
92
+ docUrl: null,
93
+ body,
94
+ });
95
+ }
@@ -0,0 +1,2 @@
1
+ import type { Client, Config } from './types.gen.ts';
2
+ export declare const createClient: (config?: Config) => Client;
@@ -0,0 +1,216 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+ import { createSseClient } from "../core/serverSentEvents.gen.js";
3
+ import { getValidRequestBody } from "../core/utils.gen.js";
4
+ import { buildUrl, createConfig, createInterceptors, getParseAs, mergeConfigs, mergeHeaders, setAuthParams, } from "./utils.gen.js";
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
+ };
@@ -0,0 +1,10 @@
1
+ export type { Auth } from '../core/auth.gen.ts';
2
+ export type { QuerySerializerOptions } from '../core/bodySerializer.gen.ts';
3
+ export { formDataBodySerializer, jsonBodySerializer, urlSearchParamsBodySerializer, } from '../core/bodySerializer.gen.ts';
4
+ export { buildClientParams } from '../core/params.gen.ts';
5
+ export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen.ts';
6
+ export type { ServerSentEventsResult } from '../core/serverSentEvents.gen.ts';
7
+ export type { ClientMeta } from '../core/types.gen.ts';
8
+ export { createClient } from './client.gen.ts';
9
+ export type { Client, ClientOptions, Config, CreateClientConfig, Options, RequestOptions, RequestResult, ResolvedRequestOptions, ResponseStyle, TDataShape, } from './types.gen.ts';
10
+ export { createConfig, mergeHeaders } from './utils.gen.ts';
@@ -0,0 +1,6 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+ export { formDataBodySerializer, jsonBodySerializer, urlSearchParamsBodySerializer, } from "../core/bodySerializer.gen.js";
3
+ export { buildClientParams } from "../core/params.gen.js";
4
+ export { serializeQueryKeyValue } from "../core/queryKeySerializer.gen.js";
5
+ export { createClient } from "./client.gen.js";
6
+ export { createConfig, mergeHeaders } from "./utils.gen.js";