@apicity/kie 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +569 -0
- package/dist/src/chat.d.ts +56 -0
- package/dist/src/chat.d.ts.map +1 -0
- package/dist/src/chat.js +75 -0
- package/dist/src/chat.js.map +1 -0
- package/dist/src/claude.d.ts +76 -0
- package/dist/src/claude.d.ts.map +1 -0
- package/dist/src/claude.js +83 -0
- package/dist/src/claude.js.map +1 -0
- package/dist/src/example.d.ts +8 -0
- package/dist/src/example.d.ts.map +1 -0
- package/dist/src/example.js +186 -0
- package/dist/src/example.js.map +1 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +14 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/kie.d.ts +5 -0
- package/dist/src/kie.d.ts.map +1 -0
- package/dist/src/kie.js +388 -0
- package/dist/src/kie.js.map +1 -0
- package/dist/src/middleware.d.ts +34 -0
- package/dist/src/middleware.d.ts.map +1 -0
- package/dist/src/middleware.js +219 -0
- package/dist/src/middleware.js.map +1 -0
- package/dist/src/model-schemas.d.ts +3 -0
- package/dist/src/model-schemas.d.ts.map +1 -0
- package/dist/src/model-schemas.js +1172 -0
- package/dist/src/model-schemas.js.map +1 -0
- package/dist/src/request.d.ts +9 -0
- package/dist/src/request.d.ts.map +1 -0
- package/dist/src/request.js +46 -0
- package/dist/src/request.js.map +1 -0
- package/dist/src/sse.d.ts +2 -0
- package/dist/src/sse.d.ts.map +1 -0
- package/dist/src/sse.js +41 -0
- package/dist/src/sse.js.map +1 -0
- package/dist/src/suno.d.ts +313 -0
- package/dist/src/suno.d.ts.map +1 -0
- package/dist/src/suno.js +391 -0
- package/dist/src/suno.js.map +1 -0
- package/dist/src/types.d.ts +119 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +14 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/veo.d.ts +52 -0
- package/dist/src/veo.d.ts.map +1 -0
- package/dist/src/veo.js +40 -0
- package/dist/src/veo.js.map +1 -0
- package/dist/src/zod.d.ts +1982 -0
- package/dist/src/zod.d.ts.map +1 -0
- package/dist/src/zod.js +866 -0
- package/dist/src/zod.js.map +1 -0
- package/package.json +61 -0
package/dist/src/kie.js
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import { KieError, } from "./types.js";
|
|
2
|
+
import { CreateTaskRequestSchema, DownloadUrlRequestSchema, UploadMediaRequestSchema, FileUrlUploadRequestSchema, FileBase64UploadRequestSchema, } from "./zod.js";
|
|
3
|
+
import { modelInputSchemas } from "./model-schemas.js";
|
|
4
|
+
import { createVeoProvider } from "./veo.js";
|
|
5
|
+
import { createSunoProvider } from "./suno.js";
|
|
6
|
+
import { createChatProvider } from "./chat.js";
|
|
7
|
+
import { createClaudeProvider } from "./claude.js";
|
|
8
|
+
import { attachExamples } from "./example.js";
|
|
9
|
+
const MIME_TYPES = {
|
|
10
|
+
jpg: "image/jpeg",
|
|
11
|
+
jpeg: "image/jpeg",
|
|
12
|
+
png: "image/png",
|
|
13
|
+
gif: "image/gif",
|
|
14
|
+
webp: "image/webp",
|
|
15
|
+
bmp: "image/bmp",
|
|
16
|
+
svg: "image/svg+xml",
|
|
17
|
+
mp4: "video/mp4",
|
|
18
|
+
webm: "video/webm",
|
|
19
|
+
mov: "video/quicktime",
|
|
20
|
+
avi: "video/x-msvideo",
|
|
21
|
+
mp3: "audio/mpeg",
|
|
22
|
+
wav: "audio/wav",
|
|
23
|
+
ogg: "audio/ogg",
|
|
24
|
+
flac: "audio/flac",
|
|
25
|
+
aac: "audio/aac",
|
|
26
|
+
m4a: "audio/mp4",
|
|
27
|
+
};
|
|
28
|
+
function inferMimeType(filename) {
|
|
29
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
30
|
+
return ext ? MIME_TYPES[ext] : undefined;
|
|
31
|
+
}
|
|
32
|
+
export function kie(opts) {
|
|
33
|
+
const baseURL = opts.baseURL ?? "https://api.kie.ai";
|
|
34
|
+
const uploadBaseURL = opts.uploadBaseURL ?? "https://kieai.redpandaai.co";
|
|
35
|
+
const doFetch = opts.fetch ?? fetch;
|
|
36
|
+
const timeout = opts.timeout ?? 30000;
|
|
37
|
+
// POST https://api.kie.ai/api/v1/jobs/createTask
|
|
38
|
+
// Docs: https://docs.kie.ai
|
|
39
|
+
async function createTask(req) {
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
42
|
+
try {
|
|
43
|
+
const res = await doFetch(`${baseURL}/api/v1/jobs/createTask`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: {
|
|
46
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify(req),
|
|
50
|
+
signal: controller.signal,
|
|
51
|
+
});
|
|
52
|
+
clearTimeout(timeoutId);
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
let message = `Kie API error: ${res.status}`;
|
|
55
|
+
let body = null;
|
|
56
|
+
try {
|
|
57
|
+
body = await res.json();
|
|
58
|
+
if (typeof body === "object" &&
|
|
59
|
+
body !== null &&
|
|
60
|
+
"msg" in body &&
|
|
61
|
+
typeof body.msg === "string") {
|
|
62
|
+
message = `Kie API error ${res.status}: ${body.msg}`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// ignore parse errors
|
|
67
|
+
}
|
|
68
|
+
throw new KieError(message, res.status, body);
|
|
69
|
+
}
|
|
70
|
+
return (await res.json());
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
clearTimeout(timeoutId);
|
|
74
|
+
if (error instanceof KieError)
|
|
75
|
+
throw error;
|
|
76
|
+
throw new KieError(`Failed to create task: ${error}`, 500);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// GET https://api.kie.ai/api/v1/jobs/recordInfo?taskId={taskId}
|
|
80
|
+
// Docs: https://docs.kie.ai
|
|
81
|
+
async function recordInfo(taskId) {
|
|
82
|
+
const controller = new AbortController();
|
|
83
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
84
|
+
try {
|
|
85
|
+
const res = await doFetch(`${baseURL}/api/v1/jobs/recordInfo?taskId=${encodeURIComponent(taskId)}`, {
|
|
86
|
+
method: "GET",
|
|
87
|
+
headers: {
|
|
88
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
89
|
+
"Content-Type": "application/json",
|
|
90
|
+
},
|
|
91
|
+
signal: controller.signal,
|
|
92
|
+
});
|
|
93
|
+
clearTimeout(timeoutId);
|
|
94
|
+
if (!res.ok) {
|
|
95
|
+
let message = `Kie API error: ${res.status}`;
|
|
96
|
+
let body = null;
|
|
97
|
+
try {
|
|
98
|
+
body = await res.json();
|
|
99
|
+
if (typeof body === "object" &&
|
|
100
|
+
body !== null &&
|
|
101
|
+
"msg" in body &&
|
|
102
|
+
typeof body.msg === "string") {
|
|
103
|
+
message = `Kie API error ${res.status}: ${body.msg}`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// ignore parse errors
|
|
108
|
+
}
|
|
109
|
+
throw new KieError(message, res.status, body);
|
|
110
|
+
}
|
|
111
|
+
return (await res.json());
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
clearTimeout(timeoutId);
|
|
115
|
+
if (error instanceof KieError)
|
|
116
|
+
throw error;
|
|
117
|
+
throw new KieError(`Failed to get task: ${error}`, 500);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// POST https://api.kie.ai/api/file-stream-upload
|
|
121
|
+
// Docs: https://docs.kie.ai
|
|
122
|
+
async function fileStreamUpload(req) {
|
|
123
|
+
const controller = new AbortController();
|
|
124
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
125
|
+
try {
|
|
126
|
+
const mimeType = req.mimeType ?? inferMimeType(req.filename);
|
|
127
|
+
if (!mimeType) {
|
|
128
|
+
throw new KieError(`Cannot determine MIME type for: ${req.filename}`, 400);
|
|
129
|
+
}
|
|
130
|
+
const formData = new FormData();
|
|
131
|
+
const file = new File([req.file], req.filename, { type: mimeType });
|
|
132
|
+
formData.append("file", file);
|
|
133
|
+
formData.append("uploadPath", req.uploadPath);
|
|
134
|
+
if (req.fileName) {
|
|
135
|
+
formData.append("fileName", req.fileName);
|
|
136
|
+
}
|
|
137
|
+
const res = await doFetch(`${uploadBaseURL}/api/file-stream-upload`, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: {
|
|
140
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
141
|
+
},
|
|
142
|
+
body: formData,
|
|
143
|
+
signal: controller.signal,
|
|
144
|
+
});
|
|
145
|
+
clearTimeout(timeoutId);
|
|
146
|
+
if (!res.ok) {
|
|
147
|
+
let message = `Kie upload error: ${res.status}`;
|
|
148
|
+
let body = null;
|
|
149
|
+
try {
|
|
150
|
+
body = await res.json();
|
|
151
|
+
if (typeof body === "object" &&
|
|
152
|
+
body !== null &&
|
|
153
|
+
"msg" in body &&
|
|
154
|
+
typeof body.msg === "string") {
|
|
155
|
+
message = `Kie upload error ${res.status}: ${body.msg}`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// ignore parse errors
|
|
160
|
+
}
|
|
161
|
+
throw new KieError(message, res.status, body);
|
|
162
|
+
}
|
|
163
|
+
return (await res.json());
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
clearTimeout(timeoutId);
|
|
167
|
+
if (error instanceof KieError)
|
|
168
|
+
throw error;
|
|
169
|
+
throw new KieError(`Failed to upload media: ${error}`, 500);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// POST https://api.kie.ai/api/file-url-upload
|
|
173
|
+
// Docs: https://docs.kie.ai
|
|
174
|
+
async function fileUrlUpload(req) {
|
|
175
|
+
const controller = new AbortController();
|
|
176
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
177
|
+
try {
|
|
178
|
+
const res = await doFetch(`${uploadBaseURL}/api/file-url-upload`, {
|
|
179
|
+
method: "POST",
|
|
180
|
+
headers: {
|
|
181
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
182
|
+
"Content-Type": "application/json",
|
|
183
|
+
},
|
|
184
|
+
body: JSON.stringify({
|
|
185
|
+
fileUrl: req.fileUrl,
|
|
186
|
+
uploadPath: req.uploadPath,
|
|
187
|
+
...(req.fileName ? { fileName: req.fileName } : {}),
|
|
188
|
+
}),
|
|
189
|
+
signal: controller.signal,
|
|
190
|
+
});
|
|
191
|
+
clearTimeout(timeoutId);
|
|
192
|
+
if (!res.ok) {
|
|
193
|
+
let message = `Kie upload error: ${res.status}`;
|
|
194
|
+
let body = null;
|
|
195
|
+
try {
|
|
196
|
+
body = await res.json();
|
|
197
|
+
if (typeof body === "object" &&
|
|
198
|
+
body !== null &&
|
|
199
|
+
"msg" in body &&
|
|
200
|
+
typeof body.msg === "string") {
|
|
201
|
+
message = `Kie upload error ${res.status}: ${body.msg}`;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
// ignore parse errors
|
|
206
|
+
}
|
|
207
|
+
throw new KieError(message, res.status, body);
|
|
208
|
+
}
|
|
209
|
+
return (await res.json());
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
clearTimeout(timeoutId);
|
|
213
|
+
if (error instanceof KieError)
|
|
214
|
+
throw error;
|
|
215
|
+
throw new KieError(`Failed to upload from URL: ${error}`, 500);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// POST https://api.kie.ai/api/file-base64-upload
|
|
219
|
+
// Docs: https://docs.kie.ai
|
|
220
|
+
async function fileBase64Upload(req) {
|
|
221
|
+
const controller = new AbortController();
|
|
222
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
223
|
+
try {
|
|
224
|
+
const res = await doFetch(`${uploadBaseURL}/api/file-base64-upload`, {
|
|
225
|
+
method: "POST",
|
|
226
|
+
headers: {
|
|
227
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
228
|
+
"Content-Type": "application/json",
|
|
229
|
+
},
|
|
230
|
+
body: JSON.stringify({
|
|
231
|
+
base64Data: req.base64Data,
|
|
232
|
+
uploadPath: req.uploadPath,
|
|
233
|
+
...(req.fileName ? { fileName: req.fileName } : {}),
|
|
234
|
+
...(req.mimeType ? { mimeType: req.mimeType } : {}),
|
|
235
|
+
}),
|
|
236
|
+
signal: controller.signal,
|
|
237
|
+
});
|
|
238
|
+
clearTimeout(timeoutId);
|
|
239
|
+
if (!res.ok) {
|
|
240
|
+
let message = `Kie upload error: ${res.status}`;
|
|
241
|
+
let body = null;
|
|
242
|
+
try {
|
|
243
|
+
body = await res.json();
|
|
244
|
+
if (typeof body === "object" &&
|
|
245
|
+
body !== null &&
|
|
246
|
+
"msg" in body &&
|
|
247
|
+
typeof body.msg === "string") {
|
|
248
|
+
message = `Kie upload error ${res.status}: ${body.msg}`;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
// ignore parse errors
|
|
253
|
+
}
|
|
254
|
+
throw new KieError(message, res.status, body);
|
|
255
|
+
}
|
|
256
|
+
return (await res.json());
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
clearTimeout(timeoutId);
|
|
260
|
+
if (error instanceof KieError)
|
|
261
|
+
throw error;
|
|
262
|
+
throw new KieError(`Failed to upload base64 file: ${error}`, 500);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// POST https://api.kie.ai/api/v1/common/download-url
|
|
266
|
+
// Docs: https://docs.kie.ai
|
|
267
|
+
async function downloadUrl(req) {
|
|
268
|
+
const controller = new AbortController();
|
|
269
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
270
|
+
try {
|
|
271
|
+
const res = await doFetch(`${baseURL}/api/v1/common/download-url`, {
|
|
272
|
+
method: "POST",
|
|
273
|
+
headers: {
|
|
274
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
275
|
+
"Content-Type": "application/json",
|
|
276
|
+
},
|
|
277
|
+
body: JSON.stringify(req),
|
|
278
|
+
signal: controller.signal,
|
|
279
|
+
});
|
|
280
|
+
clearTimeout(timeoutId);
|
|
281
|
+
if (!res.ok) {
|
|
282
|
+
let message = `Kie API error: ${res.status}`;
|
|
283
|
+
let body = null;
|
|
284
|
+
try {
|
|
285
|
+
body = await res.json();
|
|
286
|
+
if (typeof body === "object" &&
|
|
287
|
+
body !== null &&
|
|
288
|
+
"msg" in body &&
|
|
289
|
+
typeof body.msg === "string") {
|
|
290
|
+
message = `Kie API error ${res.status}: ${body.msg}`;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// ignore parse errors
|
|
295
|
+
}
|
|
296
|
+
throw new KieError(message, res.status, body);
|
|
297
|
+
}
|
|
298
|
+
return (await res.json());
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
clearTimeout(timeoutId);
|
|
302
|
+
if (error instanceof KieError)
|
|
303
|
+
throw error;
|
|
304
|
+
throw new KieError(`Failed to get download URL: ${error}`, 500);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// GET https://api.kie.ai/api/v1/chat/credit
|
|
308
|
+
// Docs: https://docs.kie.ai
|
|
309
|
+
async function credit() {
|
|
310
|
+
const res = await doFetch(`${baseURL}/api/v1/chat/credit`, {
|
|
311
|
+
method: "GET",
|
|
312
|
+
headers: {
|
|
313
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
314
|
+
"Content-Type": "application/json",
|
|
315
|
+
},
|
|
316
|
+
});
|
|
317
|
+
if (!res.ok) {
|
|
318
|
+
let body = null;
|
|
319
|
+
try {
|
|
320
|
+
body = await res.json();
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// ignore parse errors
|
|
324
|
+
}
|
|
325
|
+
throw new KieError(`Failed to get credits: ${res.status}`, res.status, body);
|
|
326
|
+
}
|
|
327
|
+
return (await res.json());
|
|
328
|
+
}
|
|
329
|
+
return attachExamples({
|
|
330
|
+
veo: createVeoProvider(baseURL, opts.apiKey, doFetch, timeout),
|
|
331
|
+
suno: createSunoProvider(baseURL, opts.apiKey, doFetch, timeout),
|
|
332
|
+
chat: createChatProvider(baseURL, opts.apiKey, doFetch, timeout),
|
|
333
|
+
...createClaudeProvider(baseURL, opts.apiKey, doFetch, timeout),
|
|
334
|
+
modelInputSchemas,
|
|
335
|
+
post: {
|
|
336
|
+
api: {
|
|
337
|
+
v1: {
|
|
338
|
+
jobs: {
|
|
339
|
+
createTask: Object.assign(createTask, {
|
|
340
|
+
schema: CreateTaskRequestSchema,
|
|
341
|
+
}),
|
|
342
|
+
},
|
|
343
|
+
common: {
|
|
344
|
+
downloadUrl: Object.assign(downloadUrl, {
|
|
345
|
+
schema: DownloadUrlRequestSchema,
|
|
346
|
+
}),
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
fileStreamUpload: Object.assign(fileStreamUpload, {
|
|
350
|
+
schema: UploadMediaRequestSchema,
|
|
351
|
+
}),
|
|
352
|
+
fileUrlUpload: Object.assign(fileUrlUpload, {
|
|
353
|
+
schema: FileUrlUploadRequestSchema,
|
|
354
|
+
}),
|
|
355
|
+
fileBase64Upload: Object.assign(fileBase64Upload, {
|
|
356
|
+
schema: FileBase64UploadRequestSchema,
|
|
357
|
+
}),
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
get: {
|
|
361
|
+
api: {
|
|
362
|
+
v1: {
|
|
363
|
+
jobs: { recordInfo },
|
|
364
|
+
chat: { credit },
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
export async function submitMediaJob(provider, request) {
|
|
371
|
+
const result = await provider.post.api.v1.jobs.createTask(request);
|
|
372
|
+
if (!result.data?.taskId) {
|
|
373
|
+
throw new KieError(`createTask failed: ${result.msg ?? "no taskId in response"}`, result.code);
|
|
374
|
+
}
|
|
375
|
+
return result.data.taskId;
|
|
376
|
+
}
|
|
377
|
+
export async function uploadFile(provider, file, filename, uploadPath = "uploads") {
|
|
378
|
+
const result = await provider.post.api.fileStreamUpload({
|
|
379
|
+
file,
|
|
380
|
+
filename,
|
|
381
|
+
uploadPath,
|
|
382
|
+
});
|
|
383
|
+
if (!result.data?.downloadUrl) {
|
|
384
|
+
throw new KieError(`upload failed: no downloadUrl in response`, result.code);
|
|
385
|
+
}
|
|
386
|
+
return result.data.downloadUrl;
|
|
387
|
+
}
|
|
388
|
+
//# sourceMappingURL=kie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kie.js","sourceRoot":"","sources":["../../src/kie.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,QAAQ,GAST,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,UAAU,GAA2B;IACzC,GAAG,EAAE,YAAY;IACjB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,eAAe;IACpB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;CACjB,CAAC;AAEF,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,CAAC;IACrD,OAAO,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAgB;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,oBAAoB,CAAC;IACrD,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,6BAA6B,CAAC;IAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC;IACtC,iDAAiD;IACjD,4BAA4B;IAC5B,KAAK,UAAU,UAAU,CACvB,GAA2B;QAE3B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,yBAAyB,EAAE;gBAC7D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;gBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,OAAO,GAAG,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC7C,IAAI,IAAI,GAAY,IAAI,CAAC;gBACzB,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBACxB,IACE,OAAO,IAAI,KAAK,QAAQ;wBACxB,IAAI,KAAK,IAAI;wBACb,KAAK,IAAI,IAAI;wBACb,OAAQ,IAAyB,CAAC,GAAG,KAAK,QAAQ,EAClD,CAAC;wBACD,OAAO,GAAG,iBAAiB,GAAG,CAAC,MAAM,KAAM,IAAwB,CAAC,GAAG,EAAE,CAAC;oBAC5E,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,sBAAsB;gBACxB,CAAC;gBACD,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAChD,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAiB,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,IAAI,KAAK,YAAY,QAAQ;gBAAE,MAAM,KAAK,CAAC;YAC3C,MAAM,IAAI,QAAQ,CAAC,0BAA0B,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,4BAA4B;IAC5B,KAAK,UAAU,UAAU,CAAC,MAAc;QACtC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,GAAG,OAAO,kCAAkC,kBAAkB,CAAC,MAAM,CAAC,EAAE,EACxE;gBACE,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CACF,CAAC;YAEF,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,OAAO,GAAG,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC7C,IAAI,IAAI,GAAY,IAAI,CAAC;gBACzB,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBACxB,IACE,OAAO,IAAI,KAAK,QAAQ;wBACxB,IAAI,KAAK,IAAI;wBACb,KAAK,IAAI,IAAI;wBACb,OAAQ,IAAyB,CAAC,GAAG,KAAK,QAAQ,EAClD,CAAC;wBACD,OAAO,GAAG,iBAAiB,GAAG,CAAC,MAAM,KAAM,IAAwB,CAAC,GAAG,EAAE,CAAC;oBAC5E,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,sBAAsB;gBACxB,CAAC;gBACD,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAChD,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgB,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,IAAI,KAAK,YAAY,QAAQ;gBAAE,MAAM,KAAK,CAAC;YAC3C,MAAM,IAAI,QAAQ,CAAC,uBAAuB,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,4BAA4B;IAC5B,KAAK,UAAU,gBAAgB,CAC7B,GAAuB;QAEvB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,QAAQ,CAChB,mCAAmC,GAAG,CAAC,QAAQ,EAAE,EACjD,GAAG,CACJ,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC9B,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;YAC9C,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBACjB,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC5C,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,aAAa,yBAAyB,EAAE;gBACnE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;iBACvC;gBACD,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,OAAO,GAAG,qBAAqB,GAAG,CAAC,MAAM,EAAE,CAAC;gBAChD,IAAI,IAAI,GAAY,IAAI,CAAC;gBACzB,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBACxB,IACE,OAAO,IAAI,KAAK,QAAQ;wBACxB,IAAI,KAAK,IAAI;wBACb,KAAK,IAAI,IAAI;wBACb,OAAQ,IAAyB,CAAC,GAAG,KAAK,QAAQ,EAClD,CAAC;wBACD,OAAO,GAAG,oBAAoB,GAAG,CAAC,MAAM,KAAM,IAAwB,CAAC,GAAG,EAAE,CAAC;oBAC/E,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,sBAAsB;gBACxB,CAAC;gBACD,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAChD,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,IAAI,KAAK,YAAY,QAAQ;gBAAE,MAAM,KAAK,CAAC;YAC3C,MAAM,IAAI,QAAQ,CAAC,2BAA2B,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,4BAA4B;IAC5B,KAAK,UAAU,aAAa,CAC1B,GAAyB;QAEzB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,aAAa,sBAAsB,EAAE;gBAChE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpD,CAAC;gBACF,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,OAAO,GAAG,qBAAqB,GAAG,CAAC,MAAM,EAAE,CAAC;gBAChD,IAAI,IAAI,GAAY,IAAI,CAAC;gBACzB,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBACxB,IACE,OAAO,IAAI,KAAK,QAAQ;wBACxB,IAAI,KAAK,IAAI;wBACb,KAAK,IAAI,IAAI;wBACb,OAAQ,IAAyB,CAAC,GAAG,KAAK,QAAQ,EAClD,CAAC;wBACD,OAAO,GAAG,oBAAoB,GAAG,CAAC,MAAM,KAAM,IAAwB,CAAC,GAAG,EAAE,CAAC;oBAC/E,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,sBAAsB;gBACxB,CAAC;gBACD,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAChD,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,IAAI,KAAK,YAAY,QAAQ;gBAAE,MAAM,KAAK,CAAC;YAC3C,MAAM,IAAI,QAAQ,CAAC,8BAA8B,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,4BAA4B;IAC5B,KAAK,UAAU,gBAAgB,CAC7B,GAA4B;QAE5B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,aAAa,yBAAyB,EAAE;gBACnE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACnD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpD,CAAC;gBACF,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,OAAO,GAAG,qBAAqB,GAAG,CAAC,MAAM,EAAE,CAAC;gBAChD,IAAI,IAAI,GAAY,IAAI,CAAC;gBACzB,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBACxB,IACE,OAAO,IAAI,KAAK,QAAQ;wBACxB,IAAI,KAAK,IAAI;wBACb,KAAK,IAAI,IAAI;wBACb,OAAQ,IAAyB,CAAC,GAAG,KAAK,QAAQ,EAClD,CAAC;wBACD,OAAO,GAAG,oBAAoB,GAAG,CAAC,MAAM,KAAM,IAAwB,CAAC,GAAG,EAAE,CAAC;oBAC/E,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,sBAAsB;gBACxB,CAAC;gBACD,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAChD,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,IAAI,KAAK,YAAY,QAAQ;gBAAE,MAAM,KAAK,CAAC;YAC3C,MAAM,IAAI,QAAQ,CAAC,iCAAiC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,4BAA4B;IAC5B,KAAK,UAAU,WAAW,CACxB,GAAuB;QAEvB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,6BAA6B,EAAE;gBACjE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;gBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,OAAO,GAAG,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC7C,IAAI,IAAI,GAAY,IAAI,CAAC;gBACzB,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBACxB,IACE,OAAO,IAAI,KAAK,QAAQ;wBACxB,IAAI,KAAK,IAAI;wBACb,KAAK,IAAI,IAAI;wBACb,OAAQ,IAAyB,CAAC,GAAG,KAAK,QAAQ,EAClD,CAAC;wBACD,OAAO,GAAG,iBAAiB,GAAG,CAAC,MAAM,KAAM,IAAwB,CAAC,GAAG,EAAE,CAAC;oBAC5E,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,sBAAsB;gBACxB,CAAC;gBACD,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAChD,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,IAAI,KAAK,YAAY,QAAQ;gBAAE,MAAM,KAAK,CAAC;YAC3C,MAAM,IAAI,QAAQ,CAAC,+BAA+B,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,4BAA4B;IAC5B,KAAK,UAAU,MAAM;QACnB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,qBAAqB,EAAE;YACzD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACtC,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,IAAI,GAAY,IAAI,CAAC;YACzB,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,sBAAsB;YACxB,CAAC;YACD,MAAM,IAAI,QAAQ,CAChB,0BAA0B,GAAG,CAAC,MAAM,EAAE,EACtC,GAAG,CAAC,MAAM,EACV,IAAI,CACL,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAC;IAClD,CAAC;IAED,OAAO,cAAc,CAAC;QACpB,GAAG,EAAE,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QAC9D,IAAI,EAAE,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QAChE,IAAI,EAAE,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QAChE,GAAG,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QAC/D,iBAAiB;QACjB,IAAI,EAAE;YACJ,GAAG,EAAE;gBACH,EAAE,EAAE;oBACF,IAAI,EAAE;wBACJ,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE;4BACpC,MAAM,EAAE,uBAAuB;yBAChC,CAAC;qBACH;oBACD,MAAM,EAAE;wBACN,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE;4BACtC,MAAM,EAAE,wBAAwB;yBACjC,CAAC;qBACH;iBACF;gBACD,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE;oBAChD,MAAM,EAAE,wBAAwB;iBACjC,CAAC;gBACF,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE;oBAC1C,MAAM,EAAE,0BAA0B;iBACnC,CAAC;gBACF,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE;oBAChD,MAAM,EAAE,6BAA6B;iBACtC,CAAC;aACH;SACF;QACD,GAAG,EAAE;YACH,GAAG,EAAE;gBACH,EAAE,EAAE;oBACF,IAAI,EAAE,EAAE,UAAU,EAAE;oBACpB,IAAI,EAAE,EAAE,MAAM,EAAE;iBACjB;aACF;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAqB,EACrB,OAA+B;IAE/B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,QAAQ,CAChB,sBAAsB,MAAM,CAAC,GAAG,IAAI,uBAAuB,EAAE,EAC7D,MAAM,CAAC,IAAI,CACZ,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,QAAqB,EACrB,IAAU,EACV,QAAgB,EAChB,aAAqB,SAAS;IAE9B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACtD,IAAI;QACJ,QAAQ;QACR,UAAU;KACX,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC;QAC9B,MAAM,IAAI,QAAQ,CAChB,2CAA2C,EAC3C,MAAM,CAAC,IAAI,CACZ,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface RetryOptions {
|
|
2
|
+
retries?: number;
|
|
3
|
+
baseMs?: number;
|
|
4
|
+
factor?: number;
|
|
5
|
+
jitter?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface FallbackOptions {
|
|
8
|
+
onFallback?: (error: unknown, index: number) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function withRetry<TReq, TRes>(fn: (req: TReq, signal?: AbortSignal) => Promise<TRes>, opts?: RetryOptions): (req: TReq, signal?: AbortSignal) => Promise<TRes>;
|
|
11
|
+
export declare function withFallback<TReq, TRes>(fns: Array<(req: TReq, signal?: AbortSignal) => Promise<TRes>>, opts?: FallbackOptions): (req: TReq, signal?: AbortSignal) => Promise<TRes>;
|
|
12
|
+
export interface RateLimiterOptions {
|
|
13
|
+
/** Maximum requests per minute (sliding window). Default: Infinity */
|
|
14
|
+
rpm?: number;
|
|
15
|
+
/** Maximum concurrent in-flight requests. Default: Infinity */
|
|
16
|
+
concurrent?: number;
|
|
17
|
+
/** Maximum time (ms) a request will wait in queue. Default: 60000 */
|
|
18
|
+
maxQueueMs?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface RateLimiter {
|
|
21
|
+
/** Current number of in-flight requests */
|
|
22
|
+
readonly active: number;
|
|
23
|
+
/** Current number of queued requests waiting for a slot */
|
|
24
|
+
readonly queued: number;
|
|
25
|
+
/** Reject all queued requests and clean up timers */
|
|
26
|
+
dispose(): void;
|
|
27
|
+
}
|
|
28
|
+
export interface RateLimitOptions {
|
|
29
|
+
/** Override maxQueueMs for this particular wrapped function */
|
|
30
|
+
maxQueueMs?: number;
|
|
31
|
+
}
|
|
32
|
+
export declare function createRateLimiter(opts?: RateLimiterOptions): RateLimiter;
|
|
33
|
+
export declare function withRateLimit<TReq, TRes>(fn: (req: TReq, signal?: AbortSignal) => Promise<TRes>, limiter: RateLimiter, opts?: RateLimitOptions): (req: TReq, signal?: AbortSignal) => Promise<TRes>;
|
|
34
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/middleware.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD;AA+BD,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAClC,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,EACtD,IAAI,GAAE,YAAiB,GACtB,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CA2BpD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EACrC,GAAG,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,EAC9D,IAAI,GAAE,eAAoB,GACzB,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAiBpD;AAED,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAkED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,kBAAuB,GAAG,WAAW,CAqH5E;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EACtC,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,EACtD,OAAO,EAAE,WAAW,EACpB,IAAI,GAAE,gBAAqB,GAC1B,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAcpD"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
function isTransientError(e) {
|
|
2
|
+
const status = (typeof e === "object" &&
|
|
3
|
+
e !== null &&
|
|
4
|
+
"status" in e &&
|
|
5
|
+
typeof e.status === "number" &&
|
|
6
|
+
e.status) ||
|
|
7
|
+
(typeof e === "object" &&
|
|
8
|
+
e !== null &&
|
|
9
|
+
"statusCode" in e &&
|
|
10
|
+
typeof e.statusCode === "number" &&
|
|
11
|
+
e.statusCode) ||
|
|
12
|
+
(typeof e === "object" &&
|
|
13
|
+
e !== null &&
|
|
14
|
+
"code" in e &&
|
|
15
|
+
typeof e.code === "number" &&
|
|
16
|
+
e.code) ||
|
|
17
|
+
null;
|
|
18
|
+
if (typeof status === "number") {
|
|
19
|
+
return status === 429 || status >= 500;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
function sleep(ms) {
|
|
24
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
25
|
+
}
|
|
26
|
+
export function withRetry(fn, opts = {}) {
|
|
27
|
+
const retries = opts.retries ?? 2;
|
|
28
|
+
const baseMs = opts.baseMs ?? 300;
|
|
29
|
+
const factor = opts.factor ?? 2;
|
|
30
|
+
const jitter = opts.jitter ?? true;
|
|
31
|
+
return async (req, signal) => {
|
|
32
|
+
let attempt = 0;
|
|
33
|
+
while (true) {
|
|
34
|
+
try {
|
|
35
|
+
return await fn(req, signal);
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
attempt += 1;
|
|
39
|
+
if (attempt > retries || !isTransientError(e) || signal?.aborted) {
|
|
40
|
+
throw e;
|
|
41
|
+
}
|
|
42
|
+
const delay = baseMs * Math.pow(factor, attempt - 1);
|
|
43
|
+
const wait = jitter
|
|
44
|
+
? Math.floor(delay * (0.8 + Math.random() * 0.4))
|
|
45
|
+
: delay;
|
|
46
|
+
await sleep(wait);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function withFallback(fns, opts = {}) {
|
|
52
|
+
if (fns.length === 0) {
|
|
53
|
+
throw new Error("withFallback requires at least one function");
|
|
54
|
+
}
|
|
55
|
+
return async (req, signal) => {
|
|
56
|
+
let lastError;
|
|
57
|
+
for (let i = 0; i < fns.length; i++) {
|
|
58
|
+
try {
|
|
59
|
+
return await fns[i](req, signal);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
lastError = e;
|
|
63
|
+
opts.onFallback?.(e, i);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw lastError;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function pruneTimestamps(state, now) {
|
|
70
|
+
const cutoff = now - 60_000;
|
|
71
|
+
while (state.timestamps.length > 0 && state.timestamps[0] <= cutoff) {
|
|
72
|
+
state.timestamps.shift();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function tryDrain(state) {
|
|
76
|
+
const now = Date.now();
|
|
77
|
+
pruneTimestamps(state, now);
|
|
78
|
+
while (state.queue.length > 0) {
|
|
79
|
+
if (state.timestamps.length >= state.rpm)
|
|
80
|
+
break;
|
|
81
|
+
if (state.activeCount >= state.concurrent)
|
|
82
|
+
break;
|
|
83
|
+
const entry = state.queue.shift();
|
|
84
|
+
clearTimeout(entry.timeoutId);
|
|
85
|
+
if (entry.signal && entry.abortHandler) {
|
|
86
|
+
entry.signal.removeEventListener("abort", entry.abortHandler);
|
|
87
|
+
}
|
|
88
|
+
state.timestamps.push(now);
|
|
89
|
+
state.activeCount++;
|
|
90
|
+
entry.resolve();
|
|
91
|
+
}
|
|
92
|
+
if (state.drainTimerId !== null) {
|
|
93
|
+
clearTimeout(state.drainTimerId);
|
|
94
|
+
state.drainTimerId = null;
|
|
95
|
+
}
|
|
96
|
+
if (state.queue.length > 0 &&
|
|
97
|
+
state.timestamps.length >= state.rpm &&
|
|
98
|
+
state.timestamps.length > 0) {
|
|
99
|
+
const oldestExpiry = state.timestamps[0] + 60_000;
|
|
100
|
+
const delay = Math.max(1, oldestExpiry - now);
|
|
101
|
+
state.drainTimerId = setTimeout(() => {
|
|
102
|
+
state.drainTimerId = null;
|
|
103
|
+
tryDrain(state);
|
|
104
|
+
}, delay);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export function createRateLimiter(opts = {}) {
|
|
108
|
+
const state = {
|
|
109
|
+
rpm: opts.rpm ?? Infinity,
|
|
110
|
+
concurrent: opts.concurrent ?? Infinity,
|
|
111
|
+
maxQueueMs: opts.maxQueueMs ?? 60_000,
|
|
112
|
+
timestamps: [],
|
|
113
|
+
activeCount: 0,
|
|
114
|
+
queue: [],
|
|
115
|
+
drainTimerId: null,
|
|
116
|
+
disposed: false,
|
|
117
|
+
};
|
|
118
|
+
function acquire(signal, maxQueueMs) {
|
|
119
|
+
if (state.disposed) {
|
|
120
|
+
return Promise.reject(new Error("RateLimiter is disposed"));
|
|
121
|
+
}
|
|
122
|
+
const now = Date.now();
|
|
123
|
+
pruneTimestamps(state, now);
|
|
124
|
+
if (state.timestamps.length < state.rpm &&
|
|
125
|
+
state.activeCount < state.concurrent) {
|
|
126
|
+
state.timestamps.push(now);
|
|
127
|
+
state.activeCount++;
|
|
128
|
+
return Promise.resolve();
|
|
129
|
+
}
|
|
130
|
+
if (signal?.aborted) {
|
|
131
|
+
return Promise.reject(new DOMException("Rate limit queue aborted", "AbortError"));
|
|
132
|
+
}
|
|
133
|
+
const queueTimeout = maxQueueMs ?? state.maxQueueMs;
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
const entry = {
|
|
136
|
+
resolve,
|
|
137
|
+
reject,
|
|
138
|
+
timeoutId: setTimeout(() => {
|
|
139
|
+
const idx = state.queue.indexOf(entry);
|
|
140
|
+
if (idx !== -1) {
|
|
141
|
+
state.queue.splice(idx, 1);
|
|
142
|
+
if (entry.signal && entry.abortHandler) {
|
|
143
|
+
entry.signal.removeEventListener("abort", entry.abortHandler);
|
|
144
|
+
}
|
|
145
|
+
reject(new Error(`Rate limit queue timeout after ${queueTimeout}ms`));
|
|
146
|
+
}
|
|
147
|
+
}, queueTimeout),
|
|
148
|
+
abortHandler: null,
|
|
149
|
+
signal,
|
|
150
|
+
};
|
|
151
|
+
if (signal) {
|
|
152
|
+
const abortHandler = () => {
|
|
153
|
+
const idx = state.queue.indexOf(entry);
|
|
154
|
+
if (idx !== -1) {
|
|
155
|
+
state.queue.splice(idx, 1);
|
|
156
|
+
clearTimeout(entry.timeoutId);
|
|
157
|
+
reject(new DOMException("Rate limit queue aborted", "AbortError"));
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
161
|
+
entry.abortHandler = abortHandler;
|
|
162
|
+
}
|
|
163
|
+
state.queue.push(entry);
|
|
164
|
+
if (state.timestamps.length >= state.rpm && state.timestamps.length > 0) {
|
|
165
|
+
if (state.drainTimerId === null) {
|
|
166
|
+
const oldestExpiry = state.timestamps[0] + 60_000;
|
|
167
|
+
const delay = Math.max(1, oldestExpiry - now);
|
|
168
|
+
state.drainTimerId = setTimeout(() => {
|
|
169
|
+
state.drainTimerId = null;
|
|
170
|
+
tryDrain(state);
|
|
171
|
+
}, delay);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function release() {
|
|
177
|
+
state.activeCount--;
|
|
178
|
+
tryDrain(state);
|
|
179
|
+
}
|
|
180
|
+
const limiter = {
|
|
181
|
+
get active() {
|
|
182
|
+
return state.activeCount;
|
|
183
|
+
},
|
|
184
|
+
get queued() {
|
|
185
|
+
return state.queue.length;
|
|
186
|
+
},
|
|
187
|
+
dispose() {
|
|
188
|
+
state.disposed = true;
|
|
189
|
+
if (state.drainTimerId !== null) {
|
|
190
|
+
clearTimeout(state.drainTimerId);
|
|
191
|
+
state.drainTimerId = null;
|
|
192
|
+
}
|
|
193
|
+
for (const entry of state.queue) {
|
|
194
|
+
clearTimeout(entry.timeoutId);
|
|
195
|
+
if (entry.signal && entry.abortHandler) {
|
|
196
|
+
entry.signal.removeEventListener("abort", entry.abortHandler);
|
|
197
|
+
}
|
|
198
|
+
entry.reject(new Error("RateLimiter disposed"));
|
|
199
|
+
}
|
|
200
|
+
state.queue.length = 0;
|
|
201
|
+
},
|
|
202
|
+
_acquire: acquire,
|
|
203
|
+
_release: release,
|
|
204
|
+
};
|
|
205
|
+
return limiter;
|
|
206
|
+
}
|
|
207
|
+
export function withRateLimit(fn, limiter, opts = {}) {
|
|
208
|
+
const internal = limiter;
|
|
209
|
+
return async (req, signal) => {
|
|
210
|
+
await internal._acquire(signal, opts.maxQueueMs);
|
|
211
|
+
try {
|
|
212
|
+
return await fn(req, signal);
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
internal._release();
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=middleware.js.map
|