@gusnips/sdkgen 0.1.0 → 0.2.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/README.md +148 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/methods.d.ts +119 -0
- package/dist/methods.d.ts.map +1 -0
- package/dist/methods.js +248 -0
- package/dist/methods.js.map +1 -0
- package/dist/transport.d.ts +88 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +198 -0
- package/dist/transport.js.map +1 -0
- package/package.json +4 -1
- package/src/index.ts +11 -0
- package/src/methods.test.ts +538 -0
- package/src/methods.ts +393 -0
- package/src/readme.test.ts +27 -1
- package/src/transport.test.ts +426 -0
- package/src/transport.ts +320 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
2
|
+
/** What a generated method tells the transport about its operation. */
|
|
3
|
+
export interface RequestSpec {
|
|
4
|
+
method: HttpMethod;
|
|
5
|
+
/** `/numbers/:numberId/pair`. Each `:name` is filled from the params field of that name. */
|
|
6
|
+
path: string;
|
|
7
|
+
/** The operation reads an `Idempotency-Key`, so the server answers a repeat from the first run. */
|
|
8
|
+
keyed?: boolean;
|
|
9
|
+
/** Safe to run twice with no key, such as a read sent as a POST. Absent: true for a GET only. */
|
|
10
|
+
repeatable?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** The last argument of every generated method. */
|
|
13
|
+
export interface RequestOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Your own key for a call that takes one, such as a UUID saved with the message you send.
|
|
16
|
+
* Every attempt sends the same key, and so can your own retry after a crash.
|
|
17
|
+
*/
|
|
18
|
+
idempotencyKey?: string;
|
|
19
|
+
/** How long one attempt waits for an answer, in milliseconds. Overrides the SDK's. */
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
}
|
|
22
|
+
/** The `error` of the envelope, as the answer carried it. */
|
|
23
|
+
export interface EnvelopeError {
|
|
24
|
+
/** What went wrong, as a word a program can check. */
|
|
25
|
+
code: string;
|
|
26
|
+
message: string | undefined;
|
|
27
|
+
messageKey: string | undefined;
|
|
28
|
+
params: Record<string, string | number> | undefined;
|
|
29
|
+
/** As sent. `{ retryAfterSecs: null }` means waiting never helps. */
|
|
30
|
+
details: unknown;
|
|
31
|
+
}
|
|
32
|
+
/** A call that did not work, as `error` gets it to build the SDK's own error. */
|
|
33
|
+
export interface Failure {
|
|
34
|
+
method: HttpMethod;
|
|
35
|
+
/** The path with its values filled in: `/numbers/n_1/pair`. */
|
|
36
|
+
path: string;
|
|
37
|
+
/** The HTTP status, or 0 when no answer came back: offline, a dropped connection, a timeout. */
|
|
38
|
+
status: number;
|
|
39
|
+
/** No answer within `timeoutMs`. The call may still have run. */
|
|
40
|
+
timedOut: boolean;
|
|
41
|
+
timeoutMs: number;
|
|
42
|
+
/** The envelope's `error`, when the answer carried one. */
|
|
43
|
+
error: EnvelopeError | undefined;
|
|
44
|
+
/** An answer that was not the envelope, such as a gateway's HTML page: its first 500 characters. */
|
|
45
|
+
text: string | undefined;
|
|
46
|
+
/** `Retry-After` in seconds, whichever of its two forms it came in. */
|
|
47
|
+
retryAfterSecs: number | undefined;
|
|
48
|
+
/** The `x-request-id` header, for the API's support to find the call. */
|
|
49
|
+
requestId: string | undefined;
|
|
50
|
+
/** The key the call was sent with. Retry with it, and a call that ran answers from its first run. */
|
|
51
|
+
idempotencyKey: string | undefined;
|
|
52
|
+
/** What fetch threw, when no answer came back. */
|
|
53
|
+
cause: unknown;
|
|
54
|
+
}
|
|
55
|
+
/** One SDK's settings. */
|
|
56
|
+
export interface Transport {
|
|
57
|
+
/** Where the API lives, with its base path: `https://api.example.com/v1`. */
|
|
58
|
+
baseUrl: string;
|
|
59
|
+
/** Sent on every call, such as the credential and the SDK's version. */
|
|
60
|
+
headers?: Readonly<Record<string, string>>;
|
|
61
|
+
/** Default: the global `fetch`. */
|
|
62
|
+
fetch?: typeof fetch;
|
|
63
|
+
/** How long one attempt of this call waits for an answer, in milliseconds. Default 30,000. */
|
|
64
|
+
timeoutMs?: (spec: RequestSpec, params: object) => number;
|
|
65
|
+
/** Extra attempts after a failure the retry rule says is worth repeating. Default 2. */
|
|
66
|
+
maxRetries?: number;
|
|
67
|
+
/** Error codes that waiting does not clear, such as a spent monthly quota. */
|
|
68
|
+
durableCodes?: readonly string[];
|
|
69
|
+
/**
|
|
70
|
+
* Make up a key for a call that takes one when the caller sent none, so the call can be retried.
|
|
71
|
+
* Default false: without a key, a write that may have run is not sent again.
|
|
72
|
+
*/
|
|
73
|
+
mintKeys?: boolean;
|
|
74
|
+
/** Builds the SDK's own error for a failed call. The transport throws what this returns. */
|
|
75
|
+
error: (failure: Failure) => Error;
|
|
76
|
+
}
|
|
77
|
+
/** A call that worked. `data` is `undefined` for a 204 or any other empty answer. */
|
|
78
|
+
export interface Answer<T, M> {
|
|
79
|
+
data: T;
|
|
80
|
+
meta: M | undefined;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Sends one call, retries it while the rule says so, and returns `{ data, meta }` or throws
|
|
84
|
+
* `transport.error(failure)`. A value the path needs and did not get throws a TypeError before
|
|
85
|
+
* anything is sent.
|
|
86
|
+
*/
|
|
87
|
+
export declare function send<T = unknown, M = unknown>(transport: Transport, spec: RequestSpec, params?: object, opts?: RequestOptions): Promise<Answer<T, M>>;
|
|
88
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,uEAAuE;AACvE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iGAAiG;IACjG,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC;IACpD,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,iFAAiF;AACjF,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,UAAU,CAAC;IACnB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,KAAK,EAAE,aAAa,GAAG,SAAS,CAAC;IACjC,oGAAoG;IACpG,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,uEAAuE;IACvE,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,yEAAyE;IACzE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,qGAAqG;IACrG,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,kDAAkD;IAClD,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,0BAA0B;AAC1B,MAAM,WAAW,SAAS;IACxB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1D,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4FAA4F;IAC5F,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,KAAK,CAAC;CACpC;AAED,qFAAqF;AACrF,MAAM,WAAW,MAAM,CAAC,CAAC,EAAE,CAAC;IAC1B,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;CACrB;AAKD;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACjD,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,MAAW,EACnB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAsCvB"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The transport under every generated SDK method: one request, one retry rule, one error.
|
|
3
|
+
*
|
|
4
|
+
* This file is a template. `transportSource()` hands it to a generator, which writes it into each
|
|
5
|
+
* SDK as `generated/transport.ts` beside `generated/retry.ts`, so the SDK keeps zero runtime
|
|
6
|
+
* dependencies. It lives here as code rather than as a string so that this package typechecks it
|
|
7
|
+
* and its tests run it. It may import nothing but the retry rule, and only globals that Node, Bun,
|
|
8
|
+
* Deno, a Worker and a browser all have.
|
|
9
|
+
*
|
|
10
|
+
* Whether a failed call is tried again is `@gusnips/http`'s rule, not this file's. What this file
|
|
11
|
+
* decides is what the rule is asked, and the SDKs that wrote their own asked it wrong:
|
|
12
|
+
* - **A write is repeatable only with a key the server reads.** A retried send is a second
|
|
13
|
+
* message to a real person; with an `Idempotency-Key` the server answers the retry from the
|
|
14
|
+
* first run instead.
|
|
15
|
+
* - **The rule reads the answer, not the SDK's error.** Three copies decided from their error
|
|
16
|
+
* class's `retryAfter`, a number or nothing, so the server's explicit
|
|
17
|
+
* `details.retryAfterSecs: null`, which says waiting never helps, never reached the decision.
|
|
18
|
+
* - **The header is read first, in both its forms.** Two copies read the body's wait before the
|
|
19
|
+
* `Retry-After` header, and read the header only as seconds, so an HTTP date was no wait at all.
|
|
20
|
+
*/
|
|
21
|
+
import { parseRetryAfter, retryDelayMs, shouldRetry } from "@gusnips/http/retry";
|
|
22
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
23
|
+
const DEFAULT_MAX_RETRIES = 2;
|
|
24
|
+
/**
|
|
25
|
+
* Sends one call, retries it while the rule says so, and returns `{ data, meta }` or throws
|
|
26
|
+
* `transport.error(failure)`. A value the path needs and did not get throws a TypeError before
|
|
27
|
+
* anything is sent.
|
|
28
|
+
*/
|
|
29
|
+
export async function send(transport, spec, params = {}, opts = {}) {
|
|
30
|
+
// A key the server does not read cannot stop a second run, and treating the call as
|
|
31
|
+
// repeatable because it carries one would send a write twice.
|
|
32
|
+
if (!spec.keyed && opts.idempotencyKey !== undefined) {
|
|
33
|
+
throw new TypeError(`${spec.method} ${spec.path} takes no idempotency key, so a key cannot stop it running twice. Leave it out.`);
|
|
34
|
+
}
|
|
35
|
+
// One key per call, not per attempt: a retry has to send the same key to get the first answer.
|
|
36
|
+
const key = spec.keyed
|
|
37
|
+
? (opts.idempotencyKey ?? (transport.mintKeys ? globalThis.crypto.randomUUID() : undefined))
|
|
38
|
+
: undefined;
|
|
39
|
+
const repeatable = (spec.repeatable ?? spec.method === "GET") || key !== undefined;
|
|
40
|
+
const request = prepare(transport, spec, params, key);
|
|
41
|
+
const timeoutMs = opts.timeoutMs ?? transport.timeoutMs?.(spec, params) ?? DEFAULT_TIMEOUT_MS;
|
|
42
|
+
const maxRetries = transport.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
43
|
+
// A local, never `transport.fetch(...)`: called as a method, a browser's fetch gets the
|
|
44
|
+
// settings object as `this` and throws "Illegal invocation".
|
|
45
|
+
const fetchImpl = transport.fetch ?? globalThis.fetch;
|
|
46
|
+
for (let attempt = 0;; attempt++) {
|
|
47
|
+
const outcome = await once(fetchImpl, request, timeoutMs);
|
|
48
|
+
if (outcome.ok)
|
|
49
|
+
return outcome.answer;
|
|
50
|
+
const failure = { ...outcome.failure, idempotencyKey: key };
|
|
51
|
+
// The rule reads these fields as the answer sent them: the header's wait apart from the
|
|
52
|
+
// body's, and `details` untouched, so an explicit `retryAfterSecs: null` still says never.
|
|
53
|
+
const answer = {
|
|
54
|
+
status: failure.status,
|
|
55
|
+
code: failure.error?.code,
|
|
56
|
+
details: failure.error?.details,
|
|
57
|
+
retryAfterSecs: failure.retryAfterSecs,
|
|
58
|
+
};
|
|
59
|
+
const again = attempt < maxRetries &&
|
|
60
|
+
shouldRetry(answer, { repeatable, durableCodes: transport.durableCodes });
|
|
61
|
+
if (!again)
|
|
62
|
+
throw transport.error(failure);
|
|
63
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs(attempt, answer)));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** The request every attempt sends: the path filled in, the rest in the query or the body. */
|
|
67
|
+
function prepare(transport, spec, params, key) {
|
|
68
|
+
const values = new Map(Object.entries(params));
|
|
69
|
+
const path = spec.path.replace(/:(\w+)/g, (_slot, name) => {
|
|
70
|
+
const value = values.get(name);
|
|
71
|
+
// An empty segment would send the call to a different route: `/numbers//pair`.
|
|
72
|
+
if ((typeof value !== "string" && typeof value !== "number") || value === "") {
|
|
73
|
+
throw new TypeError(`${spec.method} ${spec.path} needs \`${name}\` for its path.`);
|
|
74
|
+
}
|
|
75
|
+
return encodeURIComponent(String(value));
|
|
76
|
+
});
|
|
77
|
+
for (const name of spec.path.match(/:\w+/g) ?? [])
|
|
78
|
+
values.delete(name.slice(1));
|
|
79
|
+
const url = new URL(transport.baseUrl.replace(/\/+$/, "") + path);
|
|
80
|
+
const inQuery = spec.method === "GET" || spec.method === "DELETE";
|
|
81
|
+
if (inQuery) {
|
|
82
|
+
for (const [name, value] of values) {
|
|
83
|
+
// An array is the name repeated, `?tag=a&tag=b`, which is how a query string carries a list.
|
|
84
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
85
|
+
if (item === undefined || item === null)
|
|
86
|
+
continue;
|
|
87
|
+
if (typeof item === "object") {
|
|
88
|
+
throw new TypeError(`${spec.method} ${spec.path}: \`${name}\` cannot go in a query string.`);
|
|
89
|
+
}
|
|
90
|
+
url.searchParams.append(name, String(item));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const headers = new Headers(transport.headers);
|
|
95
|
+
if (!headers.has("accept"))
|
|
96
|
+
headers.set("accept", "application/json");
|
|
97
|
+
if (!inQuery)
|
|
98
|
+
headers.set("content-type", "application/json");
|
|
99
|
+
if (key !== undefined)
|
|
100
|
+
headers.set("idempotency-key", key);
|
|
101
|
+
return {
|
|
102
|
+
method: spec.method,
|
|
103
|
+
path,
|
|
104
|
+
url: url.toString(),
|
|
105
|
+
headers,
|
|
106
|
+
// Every write sends a body, `{}` included: a handler that parses JSON answers 400 to none.
|
|
107
|
+
body: inQuery ? undefined : JSON.stringify(Object.fromEntries(values)),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** One attempt. Never throws: a failure is a value, so the loop can ask the rule about it. */
|
|
111
|
+
async function once(fetchImpl, request, timeoutMs) {
|
|
112
|
+
const base = { method: request.method, path: request.path, timeoutMs };
|
|
113
|
+
let response;
|
|
114
|
+
let text;
|
|
115
|
+
try {
|
|
116
|
+
response = await fetchImpl(request.url, {
|
|
117
|
+
method: request.method,
|
|
118
|
+
headers: request.headers,
|
|
119
|
+
body: request.body,
|
|
120
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
121
|
+
});
|
|
122
|
+
// Inside the try: a connection that drops halfway through the body is no answer either.
|
|
123
|
+
text = await response.text();
|
|
124
|
+
}
|
|
125
|
+
catch (cause) {
|
|
126
|
+
return {
|
|
127
|
+
ok: false,
|
|
128
|
+
failure: {
|
|
129
|
+
...base,
|
|
130
|
+
status: 0,
|
|
131
|
+
timedOut: isTimeout(cause),
|
|
132
|
+
error: undefined,
|
|
133
|
+
text: undefined,
|
|
134
|
+
retryAfterSecs: undefined,
|
|
135
|
+
requestId: undefined,
|
|
136
|
+
cause,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const body = parse(text);
|
|
141
|
+
if (response.ok && body !== undefined) {
|
|
142
|
+
// The one place the SDK takes the API's word for a type: the contract says what `data` is.
|
|
143
|
+
return { ok: true, answer: { data: body["data"], meta: body["meta"] } };
|
|
144
|
+
}
|
|
145
|
+
const error = envelopeError(body?.["error"]);
|
|
146
|
+
return {
|
|
147
|
+
ok: false,
|
|
148
|
+
failure: {
|
|
149
|
+
...base,
|
|
150
|
+
// A 2xx lands here only when its body is not JSON, which is not the API answering.
|
|
151
|
+
status: response.status,
|
|
152
|
+
timedOut: false,
|
|
153
|
+
error,
|
|
154
|
+
text: error === undefined && text !== "" ? text.slice(0, 500) : undefined,
|
|
155
|
+
retryAfterSecs: parseRetryAfter(response.headers.get("retry-after")),
|
|
156
|
+
requestId: response.headers.get("x-request-id") ?? undefined,
|
|
157
|
+
cause: undefined,
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/** The body as a JSON object: `{}` when empty, `undefined` when it is not a JSON object. */
|
|
162
|
+
function parse(text) {
|
|
163
|
+
if (text === "")
|
|
164
|
+
return {};
|
|
165
|
+
try {
|
|
166
|
+
const value = JSON.parse(text);
|
|
167
|
+
return isRecord(value) ? value : undefined;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function envelopeError(value) {
|
|
174
|
+
if (!isRecord(value))
|
|
175
|
+
return undefined;
|
|
176
|
+
const { code, message, messageKey, params, details } = value;
|
|
177
|
+
if (typeof code !== "string")
|
|
178
|
+
return undefined;
|
|
179
|
+
return {
|
|
180
|
+
code,
|
|
181
|
+
message: typeof message === "string" ? message : undefined,
|
|
182
|
+
messageKey: typeof messageKey === "string" ? messageKey : undefined,
|
|
183
|
+
params: isParams(params) ? params : undefined,
|
|
184
|
+
details,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function isParams(value) {
|
|
188
|
+
return (isRecord(value) &&
|
|
189
|
+
Object.values(value).every((v) => typeof v === "string" || typeof v === "number"));
|
|
190
|
+
}
|
|
191
|
+
function isRecord(value) {
|
|
192
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
193
|
+
}
|
|
194
|
+
/** `AbortSignal.timeout` rejects with a DOMException named TimeoutError. */
|
|
195
|
+
function isTimeout(cause) {
|
|
196
|
+
return (typeof cause === "object" && cause !== null && "name" in cause && cause.name === "TimeoutError");
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gusnips/sdkgen",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "The pieces of an SDK generator: copy your API's types with their comments, write a schema as a TypeScript type, and keep the output current.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,6 +48,9 @@
|
|
|
48
48
|
"release:minor": "bun pm version minor && bun publish --access public",
|
|
49
49
|
"release:major": "bun pm version major && bun publish --access public"
|
|
50
50
|
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@gusnips/http": "^0.1.5"
|
|
53
|
+
},
|
|
51
54
|
"peerDependencies": {
|
|
52
55
|
"prettier": ">=3.4 <4"
|
|
53
56
|
},
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
export { liftContract, type LiftOptions } from "./contract.ts";
|
|
2
|
+
export {
|
|
3
|
+
retrySource,
|
|
4
|
+
sdkMethods,
|
|
5
|
+
transportSource,
|
|
6
|
+
type InjectedMember,
|
|
7
|
+
type SdkMethods,
|
|
8
|
+
type SdkMethodsOptions,
|
|
9
|
+
type SdkOperation,
|
|
10
|
+
type SdkPlacement,
|
|
11
|
+
type SdkRoute,
|
|
12
|
+
} from "./methods.ts";
|
|
2
13
|
export {
|
|
3
14
|
camelCase,
|
|
4
15
|
docComment,
|