@limitry/sdk 0.0.0-stage → 1.0.0-rc.3
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 +202 -0
- package/NOTICE +2 -0
- package/README.md +25 -2
- package/dist/brand.d.ts +6 -0
- package/dist/brand.js +7 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.js +18 -0
- package/dist/index.d.ts +483 -0
- package/dist/index.js +73 -0
- package/dist/product/index.d.ts +24 -0
- package/dist/product/index.js +7 -0
- package/dist/product/limits.d.ts +110 -0
- package/dist/product/limits.js +234 -0
- package/dist/resources.d.ts +71 -0
- package/dist/resources.gen.d.ts +400 -0
- package/dist/resources.gen.js +83 -0
- package/dist/resources.js +40 -0
- package/dist/retry.d.ts +42 -0
- package/dist/retry.js +116 -0
- package/dist/v1.gen.d.ts +4207 -0
- package/dist/v1.gen.js +1 -0
- package/dist/webhooks.d.ts +39 -0
- package/dist/webhooks.js +88 -0
- package/package.json +36 -4
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import * as product from "./product/index.ts";
|
|
2
|
+
import { verifyWebhook } from "./webhooks.ts";
|
|
3
|
+
import type { components, paths } from "./v1.gen.ts";
|
|
4
|
+
/**
|
|
5
|
+
* The product's API client: openapi-fetch over the types GENERATED from
|
|
6
|
+
* the /v1 routes (./v1.gen.ts — generated, gitignored). Every call is
|
|
7
|
+
* typed by path and method; responses come back as `{ data, error,
|
|
8
|
+
* response }`, or use `unwrap()` to throw an ApiError instead.
|
|
9
|
+
*
|
|
10
|
+
* const api = createClient({ token: process.env.TOKEN!, workspace: "acme" });
|
|
11
|
+
* const { data } = await api.GET("/workspace");
|
|
12
|
+
*
|
|
13
|
+
* Without `token`, the key is read from `<NAME>_API_KEY` (API_KEY_ENV)
|
|
14
|
+
* where `process.env` exists (Node, Bun, Deno); elsewhere — a browser, a
|
|
15
|
+
* Worker, whose secrets arrive on `env` — pass it. Decided 2026-10-11:
|
|
16
|
+
* one line fewer for most customers, as OpenAI's SDK does.
|
|
17
|
+
*
|
|
18
|
+
* Authentication is `Authorization: Bearer <token>` — a Workspace API
|
|
19
|
+
* key, or a personal access token plus `X-Workspace: <slug>` on workspace
|
|
20
|
+
* routes (docs/architecture.md "Public API"). Where the product has
|
|
21
|
+
* environments, `environment` names the one to act in (`X-Environment`;
|
|
22
|
+
* a key bound to one always acts in its own) — without it, the product's
|
|
23
|
+
* default. The default origin is the product's API host per brand.json;
|
|
24
|
+
* pass `api` to point elsewhere.
|
|
25
|
+
*
|
|
26
|
+
* Every write sends an Idempotency-Key (yours, from `{ idempotencyKey }`,
|
|
27
|
+
* else one per call) and a failed attempt — network error, 5xx, 429 —
|
|
28
|
+
* is retried with the same key, twice by default (./retry.ts), so a
|
|
29
|
+
* retried write runs once.
|
|
30
|
+
*/
|
|
31
|
+
export type { components, paths };
|
|
32
|
+
export type Schemas = components["schemas"];
|
|
33
|
+
export { ApiError, apiErrorFrom } from "./errors.ts";
|
|
34
|
+
export { verifyWebhook, WebhookVerificationError, type VerifyOptions, type WebhookEvent, } from "./webhooks.ts";
|
|
35
|
+
export type { Content, RequestOptions } from "./resources.ts";
|
|
36
|
+
export { DEFAULT_MAX_RETRIES, keysFrom, withRetries } from "./retry.ts";
|
|
37
|
+
/** The variable a missing `token` is read from: <NAME>_API_KEY. */
|
|
38
|
+
export declare const API_KEY_ENV: string;
|
|
39
|
+
/** The product's API origin (no path): https://api.<domain>. */
|
|
40
|
+
export declare const DEFAULT_API: string;
|
|
41
|
+
export type ClientOptions = {
|
|
42
|
+
/**
|
|
43
|
+
* Bearer credential: a Workspace API key or a personal access token.
|
|
44
|
+
* Default: the API_KEY_ENV environment variable, where there is one.
|
|
45
|
+
*/
|
|
46
|
+
token?: string;
|
|
47
|
+
/** Workspace slug sent as X-Workspace (personal access tokens only). */
|
|
48
|
+
workspace?: string;
|
|
49
|
+
/** Environment sent as X-Environment (where the product has them; else ignored). */
|
|
50
|
+
environment?: string;
|
|
51
|
+
/** API origin, without /v1 (default: DEFAULT_API). */
|
|
52
|
+
api?: string;
|
|
53
|
+
/** Custom fetch (tests, Workers service bindings). */
|
|
54
|
+
fetch?: (input: Request) => Promise<Response>;
|
|
55
|
+
/**
|
|
56
|
+
* Automatic retries of a failed attempt (network error, 5xx, 429, a
|
|
57
|
+
* write still in progress), each with the call's same Idempotency-Key.
|
|
58
|
+
* Default 2; 0 turns them off.
|
|
59
|
+
*/
|
|
60
|
+
maxRetries?: number;
|
|
61
|
+
};
|
|
62
|
+
/** The client before a product's own methods: raw calls plus the generated ones. */
|
|
63
|
+
export type BaseClient = ReturnType<typeof createBaseClient>;
|
|
64
|
+
/**
|
|
65
|
+
* A product's own methods on the client (./product/index.ts may export
|
|
66
|
+
* `productMethods(client: BaseClient)`; decided 2026-10-11): its hero
|
|
67
|
+
* helpers sit beside the generated ones — `limitry.guard(…)`,
|
|
68
|
+
* `reminix.run(…)` — instead of a second object to create.
|
|
69
|
+
*/
|
|
70
|
+
type ProductMethods = typeof product extends {
|
|
71
|
+
productMethods: (client: never) => infer M;
|
|
72
|
+
} ? M : unknown;
|
|
73
|
+
export declare function createClient(options?: ClientOptions): BaseClient & ProductMethods;
|
|
74
|
+
declare function createBaseClient(options: ClientOptions): import("openapi-fetch").Client<paths, `${string}/${string}`> & {
|
|
75
|
+
checks: {
|
|
76
|
+
create: (input: import("./resources.ts").Input<"/checks", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
77
|
+
allowed: boolean;
|
|
78
|
+
id: string;
|
|
79
|
+
reason: {
|
|
80
|
+
code: "limit_exceeded" | "too_many_reservations";
|
|
81
|
+
limit: string | null;
|
|
82
|
+
} | null;
|
|
83
|
+
remaining: components["schemas"]["CheckRemaining"][];
|
|
84
|
+
reservation?: {
|
|
85
|
+
expiresAt: string;
|
|
86
|
+
id: string;
|
|
87
|
+
};
|
|
88
|
+
retryAfterSeconds: number | null;
|
|
89
|
+
}>;
|
|
90
|
+
};
|
|
91
|
+
limits: {
|
|
92
|
+
archive: (limitId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<undefined>;
|
|
93
|
+
create: (input: import("./resources.ts").Input<"/limits", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
94
|
+
action: string;
|
|
95
|
+
amount: number;
|
|
96
|
+
archivedAt: string | null;
|
|
97
|
+
createdAt: string;
|
|
98
|
+
enabled: boolean;
|
|
99
|
+
every: number;
|
|
100
|
+
failMode: "open" | "closed";
|
|
101
|
+
id: string;
|
|
102
|
+
name: string;
|
|
103
|
+
rolling: boolean;
|
|
104
|
+
start: "calendar" | "anchor" | "first_use";
|
|
105
|
+
subject: components["schemas"]["LimitSubject"];
|
|
106
|
+
unit: string;
|
|
107
|
+
updatedAt: string;
|
|
108
|
+
version: number;
|
|
109
|
+
window: "minute" | "hour" | "day" | "week" | "month" | "year" | "total" | "concurrent";
|
|
110
|
+
}>;
|
|
111
|
+
get: (limitId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
112
|
+
action: string;
|
|
113
|
+
amount: number;
|
|
114
|
+
archivedAt: string | null;
|
|
115
|
+
createdAt: string;
|
|
116
|
+
enabled: boolean;
|
|
117
|
+
every: number;
|
|
118
|
+
failMode: "open" | "closed";
|
|
119
|
+
id: string;
|
|
120
|
+
name: string;
|
|
121
|
+
rolling: boolean;
|
|
122
|
+
start: "calendar" | "anchor" | "first_use";
|
|
123
|
+
subject: components["schemas"]["LimitSubject"];
|
|
124
|
+
unit: string;
|
|
125
|
+
updatedAt: string;
|
|
126
|
+
version: number;
|
|
127
|
+
window: "minute" | "hour" | "day" | "week" | "month" | "year" | "total" | "concurrent";
|
|
128
|
+
}>;
|
|
129
|
+
grants: {
|
|
130
|
+
create: (limitId: string | number, input: import("./resources.ts").Input<"/limits/{limitId}/grants", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
131
|
+
amount: number;
|
|
132
|
+
createdAt: string;
|
|
133
|
+
createdByUserId: string | null;
|
|
134
|
+
id: string;
|
|
135
|
+
limitId: string;
|
|
136
|
+
note: string;
|
|
137
|
+
subject: {
|
|
138
|
+
id: string;
|
|
139
|
+
kind: string;
|
|
140
|
+
};
|
|
141
|
+
}>;
|
|
142
|
+
list: (limitId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
143
|
+
items: components["schemas"]["LimitGrant"][];
|
|
144
|
+
}>;
|
|
145
|
+
};
|
|
146
|
+
list: (input?: import("./resources.ts").Input<"/limits", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
147
|
+
items: components["schemas"]["Limit"][];
|
|
148
|
+
nextCursor: string | null;
|
|
149
|
+
}>;
|
|
150
|
+
restore: (limitId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
151
|
+
action: string;
|
|
152
|
+
amount: number;
|
|
153
|
+
archivedAt: string | null;
|
|
154
|
+
createdAt: string;
|
|
155
|
+
enabled: boolean;
|
|
156
|
+
every: number;
|
|
157
|
+
failMode: "open" | "closed";
|
|
158
|
+
id: string;
|
|
159
|
+
name: string;
|
|
160
|
+
rolling: boolean;
|
|
161
|
+
start: "calendar" | "anchor" | "first_use";
|
|
162
|
+
subject: components["schemas"]["LimitSubject"];
|
|
163
|
+
unit: string;
|
|
164
|
+
updatedAt: string;
|
|
165
|
+
version: number;
|
|
166
|
+
window: "minute" | "hour" | "day" | "week" | "month" | "year" | "total" | "concurrent";
|
|
167
|
+
}>;
|
|
168
|
+
sync: (input: import("./resources.ts").Input<"/limits/sync", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
169
|
+
archived: string[];
|
|
170
|
+
created: string[];
|
|
171
|
+
dryRun: boolean;
|
|
172
|
+
unchanged: string[];
|
|
173
|
+
updated: {
|
|
174
|
+
changes: {
|
|
175
|
+
[key: string]: {
|
|
176
|
+
from: string | number | boolean | null;
|
|
177
|
+
to: string | number | boolean | null;
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
name: string;
|
|
181
|
+
}[];
|
|
182
|
+
}>;
|
|
183
|
+
update: (limitId: string | number, input?: import("./resources.ts").Input<"/limits/{limitId}", "patch">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
184
|
+
action: string;
|
|
185
|
+
amount: number;
|
|
186
|
+
archivedAt: string | null;
|
|
187
|
+
createdAt: string;
|
|
188
|
+
enabled: boolean;
|
|
189
|
+
every: number;
|
|
190
|
+
failMode: "open" | "closed";
|
|
191
|
+
id: string;
|
|
192
|
+
name: string;
|
|
193
|
+
rolling: boolean;
|
|
194
|
+
start: "calendar" | "anchor" | "first_use";
|
|
195
|
+
subject: components["schemas"]["LimitSubject"];
|
|
196
|
+
unit: string;
|
|
197
|
+
updatedAt: string;
|
|
198
|
+
version: number;
|
|
199
|
+
window: "minute" | "hour" | "day" | "week" | "month" | "year" | "total" | "concurrent";
|
|
200
|
+
}>;
|
|
201
|
+
};
|
|
202
|
+
reservations: {
|
|
203
|
+
commit: (reservationId: string | number, input: import("./resources.ts").Input<"/reservations/{reservationId}/commit", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
204
|
+
cost: number;
|
|
205
|
+
expiresAt: string;
|
|
206
|
+
id: string;
|
|
207
|
+
reserved: number;
|
|
208
|
+
status: "held" | "committed" | "released" | "expired";
|
|
209
|
+
}>;
|
|
210
|
+
extend: (reservationId: string | number, input?: import("./resources.ts").Input<"/reservations/{reservationId}/extend", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
211
|
+
cost: number;
|
|
212
|
+
expiresAt: string;
|
|
213
|
+
id: string;
|
|
214
|
+
reserved: number;
|
|
215
|
+
status: "held" | "committed" | "released" | "expired";
|
|
216
|
+
}>;
|
|
217
|
+
release: (reservationId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
218
|
+
cost: number;
|
|
219
|
+
expiresAt: string;
|
|
220
|
+
id: string;
|
|
221
|
+
reserved: number;
|
|
222
|
+
status: "held" | "committed" | "released" | "expired";
|
|
223
|
+
}>;
|
|
224
|
+
};
|
|
225
|
+
subjects: {
|
|
226
|
+
get: (subjectKind: string | number, subjectId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
227
|
+
anchor: string | null;
|
|
228
|
+
subject: components["schemas"]["SubjectRef"];
|
|
229
|
+
}>;
|
|
230
|
+
reset: (subjectKind: string | number, subjectId: string | number, input?: import("./resources.ts").Input<"/subjects/{subjectKind}/{subjectId}/reset", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
231
|
+
reset: string[];
|
|
232
|
+
subject: components["schemas"]["SubjectRef"];
|
|
233
|
+
}>;
|
|
234
|
+
update: (subjectKind: string | number, subjectId: string | number, input: import("./resources.ts").Input<"/subjects/{subjectKind}/{subjectId}", "patch">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
235
|
+
anchor: string | null;
|
|
236
|
+
subject: components["schemas"]["SubjectRef"];
|
|
237
|
+
}>;
|
|
238
|
+
};
|
|
239
|
+
usage: {
|
|
240
|
+
query: (input: import("./resources.ts").Input<"/usage", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
241
|
+
granularity: "hour" | "day";
|
|
242
|
+
limitId: string;
|
|
243
|
+
points: {
|
|
244
|
+
allowed: number;
|
|
245
|
+
denied: number;
|
|
246
|
+
start: string;
|
|
247
|
+
used: number;
|
|
248
|
+
}[];
|
|
249
|
+
}>;
|
|
250
|
+
standing: (input: import("./resources.ts").Input<"/usage/standing", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
251
|
+
environment: string;
|
|
252
|
+
limits: {
|
|
253
|
+
action: string;
|
|
254
|
+
amount: number;
|
|
255
|
+
limit: string;
|
|
256
|
+
name: string;
|
|
257
|
+
remaining: number;
|
|
258
|
+
resetsAt: string | null;
|
|
259
|
+
rolling: boolean;
|
|
260
|
+
shared: boolean;
|
|
261
|
+
subject: {
|
|
262
|
+
id: string;
|
|
263
|
+
kind: string;
|
|
264
|
+
};
|
|
265
|
+
unit: string;
|
|
266
|
+
used: number;
|
|
267
|
+
window: "minute" | "hour" | "day" | "week" | "month" | "year" | "total" | "concurrent";
|
|
268
|
+
}[];
|
|
269
|
+
subject: {
|
|
270
|
+
id: string;
|
|
271
|
+
kind: string;
|
|
272
|
+
};
|
|
273
|
+
}>;
|
|
274
|
+
subjects: (input: import("./resources.ts").Input<"/usage/subjects", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
275
|
+
items: {
|
|
276
|
+
denied: number;
|
|
277
|
+
over: boolean;
|
|
278
|
+
remaining: number;
|
|
279
|
+
subject: {
|
|
280
|
+
id: string;
|
|
281
|
+
kind: string;
|
|
282
|
+
};
|
|
283
|
+
used: number;
|
|
284
|
+
}[];
|
|
285
|
+
limitId: string;
|
|
286
|
+
windowStart: string;
|
|
287
|
+
}>;
|
|
288
|
+
};
|
|
289
|
+
user: {
|
|
290
|
+
me: (options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
291
|
+
email: string;
|
|
292
|
+
id: string;
|
|
293
|
+
name: string;
|
|
294
|
+
workspaces: {
|
|
295
|
+
id: string;
|
|
296
|
+
name: string;
|
|
297
|
+
role: string;
|
|
298
|
+
slug: string;
|
|
299
|
+
}[];
|
|
300
|
+
}>;
|
|
301
|
+
revokeToken: (options?: import("./resources.ts").RequestOptions) => Promise<undefined>;
|
|
302
|
+
};
|
|
303
|
+
workspace: {
|
|
304
|
+
approvalActions: {
|
|
305
|
+
list: (options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
306
|
+
items: {
|
|
307
|
+
approverRoles: string[];
|
|
308
|
+
createsSecret: boolean;
|
|
309
|
+
id: string;
|
|
310
|
+
input: {
|
|
311
|
+
[key: string]: unknown;
|
|
312
|
+
};
|
|
313
|
+
title: string;
|
|
314
|
+
}[];
|
|
315
|
+
}>;
|
|
316
|
+
};
|
|
317
|
+
approvalRequests: {
|
|
318
|
+
create: (input: import("./resources.ts").Input<"/workspace/approval-requests", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
319
|
+
action: string;
|
|
320
|
+
approveUrl: string;
|
|
321
|
+
createdAt: string;
|
|
322
|
+
decidedAt: string | null;
|
|
323
|
+
expiresAt: string;
|
|
324
|
+
id: string;
|
|
325
|
+
input: {
|
|
326
|
+
[key: string]: unknown;
|
|
327
|
+
};
|
|
328
|
+
reason: string;
|
|
329
|
+
requestedBy: string | null;
|
|
330
|
+
result: {
|
|
331
|
+
[key: string]: unknown;
|
|
332
|
+
} | null;
|
|
333
|
+
secret: {
|
|
334
|
+
envVar: string;
|
|
335
|
+
name: string;
|
|
336
|
+
} | null;
|
|
337
|
+
status: "pending" | "approved" | "completed" | "denied" | "failed" | "expired";
|
|
338
|
+
summary: string;
|
|
339
|
+
title: string;
|
|
340
|
+
}>;
|
|
341
|
+
get: (requestId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
342
|
+
action: string;
|
|
343
|
+
approveUrl: string;
|
|
344
|
+
createdAt: string;
|
|
345
|
+
decidedAt: string | null;
|
|
346
|
+
expiresAt: string;
|
|
347
|
+
id: string;
|
|
348
|
+
input: {
|
|
349
|
+
[key: string]: unknown;
|
|
350
|
+
};
|
|
351
|
+
reason: string;
|
|
352
|
+
requestedBy: string | null;
|
|
353
|
+
result: {
|
|
354
|
+
[key: string]: unknown;
|
|
355
|
+
} | null;
|
|
356
|
+
secret: {
|
|
357
|
+
envVar: string;
|
|
358
|
+
name: string;
|
|
359
|
+
} | null;
|
|
360
|
+
status: "pending" | "approved" | "completed" | "denied" | "failed" | "expired";
|
|
361
|
+
summary: string;
|
|
362
|
+
title: string;
|
|
363
|
+
}>;
|
|
364
|
+
redeem: (requestId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
365
|
+
envVar: string | null;
|
|
366
|
+
request: components["schemas"]["ApprovalRequest"];
|
|
367
|
+
secret: string | null;
|
|
368
|
+
}>;
|
|
369
|
+
};
|
|
370
|
+
auditEvents: {
|
|
371
|
+
list: (input?: import("./resources.ts").Input<"/workspace/audit-events", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
372
|
+
items: components["schemas"]["AuditEvent"][];
|
|
373
|
+
nextCursor: string | null;
|
|
374
|
+
}>;
|
|
375
|
+
};
|
|
376
|
+
eventTypes: {
|
|
377
|
+
list: (options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
378
|
+
items: {
|
|
379
|
+
description: string;
|
|
380
|
+
type: string;
|
|
381
|
+
}[];
|
|
382
|
+
}>;
|
|
383
|
+
};
|
|
384
|
+
get: (options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
385
|
+
id: string;
|
|
386
|
+
name: string;
|
|
387
|
+
}>;
|
|
388
|
+
invitations: {
|
|
389
|
+
list: (input?: import("./resources.ts").Input<"/workspace/invitations", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
390
|
+
items: components["schemas"]["Invitation"][];
|
|
391
|
+
nextCursor: string | null;
|
|
392
|
+
}>;
|
|
393
|
+
};
|
|
394
|
+
members: {
|
|
395
|
+
list: (input?: import("./resources.ts").Input<"/workspace/members", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
396
|
+
items: components["schemas"]["Member"][];
|
|
397
|
+
nextCursor: string | null;
|
|
398
|
+
}>;
|
|
399
|
+
};
|
|
400
|
+
teams: {
|
|
401
|
+
list: (input?: import("./resources.ts").Input<"/workspace/teams", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
402
|
+
items: components["schemas"]["Team"][];
|
|
403
|
+
nextCursor: string | null;
|
|
404
|
+
}>;
|
|
405
|
+
};
|
|
406
|
+
usage: (options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
407
|
+
meters: {
|
|
408
|
+
description: string;
|
|
409
|
+
id: string;
|
|
410
|
+
limit: number | null;
|
|
411
|
+
used: number;
|
|
412
|
+
}[];
|
|
413
|
+
notices?: string[];
|
|
414
|
+
periodEnd: string;
|
|
415
|
+
periodStart: string;
|
|
416
|
+
}>;
|
|
417
|
+
webhookDeliveries: {
|
|
418
|
+
list: (endpointId: string | number, input?: import("./resources.ts").Input<"/workspace/webhook-endpoints/{endpointId}/deliveries", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
419
|
+
items: components["schemas"]["WebhookDelivery"][];
|
|
420
|
+
nextCursor: string | null;
|
|
421
|
+
}>;
|
|
422
|
+
redeliver: (endpointId: string | number, deliveryId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
423
|
+
deliveryId: string;
|
|
424
|
+
ok?: boolean;
|
|
425
|
+
queued: boolean;
|
|
426
|
+
status?: number | null;
|
|
427
|
+
}>;
|
|
428
|
+
};
|
|
429
|
+
webhookEndpoints: {
|
|
430
|
+
create: (input: import("./resources.ts").Input<"/workspace/webhook-endpoints", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
431
|
+
endpoint: components["schemas"]["WebhookEndpoint"];
|
|
432
|
+
secret: string;
|
|
433
|
+
}>;
|
|
434
|
+
delete: (endpointId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<undefined>;
|
|
435
|
+
enable: (endpointId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
436
|
+
consecutiveFailures: number;
|
|
437
|
+
createdAt: string;
|
|
438
|
+
description: string | null;
|
|
439
|
+
enabled: boolean;
|
|
440
|
+
environment: string | null;
|
|
441
|
+
eventTypes: string[] | null;
|
|
442
|
+
id: string;
|
|
443
|
+
lastAttemptAt: string | null;
|
|
444
|
+
lastStatus: number | null;
|
|
445
|
+
url: string;
|
|
446
|
+
}>;
|
|
447
|
+
get: (endpointId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
448
|
+
consecutiveFailures: number;
|
|
449
|
+
createdAt: string;
|
|
450
|
+
description: string | null;
|
|
451
|
+
enabled: boolean;
|
|
452
|
+
environment: string | null;
|
|
453
|
+
eventTypes: string[] | null;
|
|
454
|
+
id: string;
|
|
455
|
+
lastAttemptAt: string | null;
|
|
456
|
+
lastStatus: number | null;
|
|
457
|
+
url: string;
|
|
458
|
+
}>;
|
|
459
|
+
list: (options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
460
|
+
items: components["schemas"]["WebhookEndpoint"][];
|
|
461
|
+
nextCursor: string | null;
|
|
462
|
+
}>;
|
|
463
|
+
test: (endpointId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
|
|
464
|
+
deliveryId: string;
|
|
465
|
+
ok?: boolean;
|
|
466
|
+
queued: boolean;
|
|
467
|
+
status?: number | null;
|
|
468
|
+
}>;
|
|
469
|
+
};
|
|
470
|
+
};
|
|
471
|
+
} & {
|
|
472
|
+
webhooks: {
|
|
473
|
+
verify: typeof verifyWebhook;
|
|
474
|
+
};
|
|
475
|
+
};
|
|
476
|
+
export type Client = ReturnType<typeof createClient>;
|
|
477
|
+
/** `data` of a successful result; throws ApiError for an error result. */
|
|
478
|
+
export declare function unwrap<T extends {
|
|
479
|
+
data?: unknown;
|
|
480
|
+
error?: unknown;
|
|
481
|
+
response: Response;
|
|
482
|
+
}>(result: T): NonNullable<T["data"]>;
|
|
483
|
+
export * from "./product/index.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { brand } from "./brand.js";
|
|
2
|
+
import createOpenApiClient from "openapi-fetch";
|
|
3
|
+
import { apiErrorFrom } from "./errors.js";
|
|
4
|
+
import * as product from "./product/index.js";
|
|
5
|
+
import { resources } from "./resources.gen.js";
|
|
6
|
+
import { withRetries } from "./retry.js";
|
|
7
|
+
import { verifyWebhook } from "./webhooks.js";
|
|
8
|
+
export { ApiError, apiErrorFrom } from "./errors.js";
|
|
9
|
+
export { verifyWebhook, WebhookVerificationError, } from "./webhooks.js";
|
|
10
|
+
export { DEFAULT_MAX_RETRIES, keysFrom, withRetries } from "./retry.js";
|
|
11
|
+
/** The variable a missing `token` is read from: <NAME>_API_KEY. */
|
|
12
|
+
export const API_KEY_ENV = `${brand.identifier.toUpperCase()}_API_KEY`;
|
|
13
|
+
/** The product's API origin (no path): https://api.<domain>. */
|
|
14
|
+
export const DEFAULT_API = `https://api.${brand.domain}`;
|
|
15
|
+
export function createClient(options = {}) {
|
|
16
|
+
const client = createBaseClient(options);
|
|
17
|
+
const extend = product.productMethods;
|
|
18
|
+
if (!extend)
|
|
19
|
+
return client;
|
|
20
|
+
const methods = extend(client);
|
|
21
|
+
for (const name of Object.keys(methods)) {
|
|
22
|
+
if (name in client) {
|
|
23
|
+
throw new Error(`productMethods: "${name}" is already a client method`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return Object.assign(client, methods);
|
|
27
|
+
}
|
|
28
|
+
function createBaseClient(options) {
|
|
29
|
+
const token = options.token ?? keyFromEnvironment();
|
|
30
|
+
if (!token) {
|
|
31
|
+
throw new Error(`${brand.productName}: no API key. Pass { token } or set ${API_KEY_ENV}.`);
|
|
32
|
+
}
|
|
33
|
+
const origin = (options.api ?? DEFAULT_API).replace(/\/+$/, "");
|
|
34
|
+
const send = options.fetch ?? ((request) => fetch(request));
|
|
35
|
+
const client = createOpenApiClient({
|
|
36
|
+
baseUrl: `${origin}/v1`,
|
|
37
|
+
fetch: options.maxRetries === 0
|
|
38
|
+
? send
|
|
39
|
+
: withRetries(send, { maxRetries: options.maxRetries }),
|
|
40
|
+
});
|
|
41
|
+
client.use({
|
|
42
|
+
onRequest({ request }) {
|
|
43
|
+
request.headers.set("authorization", `Bearer ${token}`);
|
|
44
|
+
if (options.workspace && !request.headers.has("x-workspace")) {
|
|
45
|
+
request.headers.set("x-workspace", options.workspace);
|
|
46
|
+
}
|
|
47
|
+
if (options.environment && !request.headers.has("x-environment")) {
|
|
48
|
+
request.headers.set("x-environment", options.environment);
|
|
49
|
+
}
|
|
50
|
+
return request;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
// A method per operation, named as the CLI names it (./resources.gen.ts):
|
|
54
|
+
// `limits list` → client.limits.list(). The raw GET/POST/… stay.
|
|
55
|
+
// `webhooks.verify` checks a delivery you received (./webhooks.ts); it
|
|
56
|
+
// calls nothing, so it's also exported on its own as verifyWebhook.
|
|
57
|
+
return Object.assign(client, resources(client), {
|
|
58
|
+
webhooks: { verify: verifyWebhook },
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function keyFromEnvironment() {
|
|
62
|
+
const runtime = globalThis;
|
|
63
|
+
return runtime.process?.env?.[API_KEY_ENV] || undefined;
|
|
64
|
+
}
|
|
65
|
+
/** `data` of a successful result; throws ApiError for an error result. */
|
|
66
|
+
export function unwrap(result) {
|
|
67
|
+
if (result.error !== undefined || !result.response.ok) {
|
|
68
|
+
throw apiErrorFrom(result.error, result.response);
|
|
69
|
+
}
|
|
70
|
+
return result.data;
|
|
71
|
+
}
|
|
72
|
+
// The product's own helpers (fork-owned seam: ./product/).
|
|
73
|
+
export * from "./product/index.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRODUCT-OWNED: Limitry's SDK helpers (fork-owned seam — docs/conventions.md
|
|
3
|
+
* "Fork-owned seams"): re-exported by the SDK entry and published with
|
|
4
|
+
* it. `guard` / `hold` (docs/product/roadmap.md slice 6) sit on the client
|
|
5
|
+
* (`limitry.guard(…)`, the SDK's `productMethods` seam); `createLimits(client,
|
|
6
|
+
* options)` gives them with your own timeout or fail mode.
|
|
7
|
+
*/
|
|
8
|
+
import type { BaseClient } from "../index.ts";
|
|
9
|
+
export { createLimits, LimitExceeded, type GuardRequest, type Held, type HoldRequest, type Limits, type LimitsOptions, } from "./limits.ts";
|
|
10
|
+
/** Limitry's methods on the client: `limitry.guard(…)`, `limitry.hold(…)`, `limitry.standing(…)`. */
|
|
11
|
+
export declare const productMethods: (client: BaseClient) => {
|
|
12
|
+
guard: <T>(request: import("./limits.ts").GuardRequest, fn: () => Promise<T>) => Promise<T>;
|
|
13
|
+
hold: <T>(request: import("./limits.ts").HoldRequest, fn: (held: import("./limits.ts").Held) => Promise<T>) => Promise<T>;
|
|
14
|
+
standing: (request: {
|
|
15
|
+
subject: {
|
|
16
|
+
kind: string;
|
|
17
|
+
id: string;
|
|
18
|
+
};
|
|
19
|
+
shared?: {
|
|
20
|
+
kind: string;
|
|
21
|
+
id: string;
|
|
22
|
+
}[];
|
|
23
|
+
}) => Promise<import("../index.ts").Schemas["UsageStanding"]>;
|
|
24
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createLimits } from "./limits.js";
|
|
2
|
+
export { createLimits, LimitExceeded, } from "./limits.js";
|
|
3
|
+
/** Limitry's methods on the client: `limitry.guard(…)`, `limitry.hold(…)`, `limitry.standing(…)`. */
|
|
4
|
+
export const productMethods = (client) => {
|
|
5
|
+
const limits = createLimits(client);
|
|
6
|
+
return { guard: limits.guard, hold: limits.hold, standing: limits.standing };
|
|
7
|
+
};
|