databar-mcp-server 1.3.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 +205 -0
- package/dist/audit.d.ts +15 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +33 -0
- package/dist/audit.js.map +1 -0
- package/dist/cache.d.ts +40 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +78 -0
- package/dist/cache.js.map +1 -0
- package/dist/databar-client.d.ts +47 -0
- package/dist/databar-client.d.ts.map +1 -0
- package/dist/databar-client.js +377 -0
- package/dist/databar-client.js.map +1 -0
- package/dist/guards.d.ts +42 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +108 -0
- package/dist/guards.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +637 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +240 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +65 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +226 -0
- package/dist/utils.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Databar API Client with async polling support
|
|
3
|
+
*/
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
const API_ROW_BATCH = 50;
|
|
6
|
+
function chunkArray(arr, size) {
|
|
7
|
+
const chunks = [];
|
|
8
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
9
|
+
chunks.push(arr.slice(i, i + size));
|
|
10
|
+
}
|
|
11
|
+
return chunks;
|
|
12
|
+
}
|
|
13
|
+
export class DatabarClient {
|
|
14
|
+
client;
|
|
15
|
+
config;
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.config = config;
|
|
18
|
+
this.client = axios.create({
|
|
19
|
+
baseURL: config.baseUrl,
|
|
20
|
+
headers: {
|
|
21
|
+
'x-apikey': config.apiKey,
|
|
22
|
+
'Content-Type': 'application/json'
|
|
23
|
+
},
|
|
24
|
+
timeout: 30000
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
sleep(ms) {
|
|
28
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
29
|
+
}
|
|
30
|
+
handleError(error) {
|
|
31
|
+
if (axios.isAxiosError(error)) {
|
|
32
|
+
const axiosError = error;
|
|
33
|
+
const status = axiosError.response?.status;
|
|
34
|
+
const data = axiosError.response?.data;
|
|
35
|
+
if (status === 401 || status === 403) {
|
|
36
|
+
throw new Error('Invalid API key or insufficient credits. Please check your API key and account balance.');
|
|
37
|
+
}
|
|
38
|
+
if (status === 422) {
|
|
39
|
+
if (data?.detail && Array.isArray(data.detail)) {
|
|
40
|
+
const errors = data.detail.map((d) => `${d.loc.join('.')}: ${d.msg}`).join(', ');
|
|
41
|
+
throw new Error(`Validation error: ${errors}`);
|
|
42
|
+
}
|
|
43
|
+
throw new Error('Invalid parameters provided');
|
|
44
|
+
}
|
|
45
|
+
if (status === 404) {
|
|
46
|
+
throw new Error('Resource not found');
|
|
47
|
+
}
|
|
48
|
+
if (status === 410) {
|
|
49
|
+
throw new Error('Resource has expired. Data is only stored for 1 hour after task completion.');
|
|
50
|
+
}
|
|
51
|
+
if (status === 429) {
|
|
52
|
+
throw new Error('Rate limit exceeded. Please try again later.');
|
|
53
|
+
}
|
|
54
|
+
if (data?.error) {
|
|
55
|
+
throw new Error(data.error + (data.details ? `: ${data.details}` : ''));
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`API error (${status}): ${axiosError.message}`);
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Unexpected error: ${error.message || 'Unknown error'}`);
|
|
60
|
+
}
|
|
61
|
+
async withRetry(fn, maxRetries = 3, baseDelay = 1000) {
|
|
62
|
+
let lastError;
|
|
63
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
64
|
+
try {
|
|
65
|
+
return await fn();
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
lastError = error;
|
|
69
|
+
if (axios.isAxiosError(error)) {
|
|
70
|
+
const status = error.response?.status;
|
|
71
|
+
if (status && status >= 400 && status < 500 && status !== 429) {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (attempt === maxRetries) {
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
const delay = baseDelay * Math.pow(2, attempt);
|
|
79
|
+
await this.sleep(delay);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
throw lastError;
|
|
83
|
+
}
|
|
84
|
+
// ============================================================================
|
|
85
|
+
// Enrichment Methods
|
|
86
|
+
// ============================================================================
|
|
87
|
+
async getAllEnrichments() {
|
|
88
|
+
try {
|
|
89
|
+
const response = await this.withRetry(() => this.client.get('/enrichments'));
|
|
90
|
+
return response.data;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
this.handleError(error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async getEnrichmentDetails(enrichmentId) {
|
|
97
|
+
try {
|
|
98
|
+
const response = await this.withRetry(() => this.client.get(`/enrichments/${enrichmentId}`));
|
|
99
|
+
return response.data;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
this.handleError(error);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async runEnrichment(enrichmentId, params) {
|
|
106
|
+
try {
|
|
107
|
+
const payload = { params };
|
|
108
|
+
const response = await this.withRetry(() => this.client.post(`/enrichments/${enrichmentId}/run`, payload));
|
|
109
|
+
return response.data;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
this.handleError(error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async runBulkEnrichment(enrichmentId, paramsList) {
|
|
116
|
+
try {
|
|
117
|
+
const payload = { params: paramsList };
|
|
118
|
+
const response = await this.withRetry(() => this.client.post(`/enrichments/${enrichmentId}/bulk-run`, payload));
|
|
119
|
+
return response.data;
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
this.handleError(error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async getTaskStatus(taskId) {
|
|
126
|
+
try {
|
|
127
|
+
const response = await this.withRetry(() => this.client.get(`/tasks/${taskId}`));
|
|
128
|
+
return response.data;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
this.handleError(error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async pollTaskUntilComplete(taskId) {
|
|
135
|
+
const maxAttempts = this.config.maxPollAttempts;
|
|
136
|
+
const pollInterval = this.config.pollIntervalMs;
|
|
137
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
138
|
+
await this.sleep(pollInterval);
|
|
139
|
+
const result = await this.getTaskStatus(taskId);
|
|
140
|
+
const status = result.status.toLowerCase();
|
|
141
|
+
if (status === 'completed' || status === 'success') {
|
|
142
|
+
return result.data;
|
|
143
|
+
}
|
|
144
|
+
if (status === 'failed' || status === 'error') {
|
|
145
|
+
const errorMsg = Array.isArray(result.error)
|
|
146
|
+
? result.error.join('; ')
|
|
147
|
+
: result.error;
|
|
148
|
+
throw new Error(errorMsg || 'Task failed');
|
|
149
|
+
}
|
|
150
|
+
if (status === 'gone') {
|
|
151
|
+
throw new Error('Task data has expired. Data is only stored for 1 hour after completion. Please re-run the enrichment.');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
throw new Error(`Task timed out after ${maxAttempts * pollInterval / 1000} seconds`);
|
|
155
|
+
}
|
|
156
|
+
async runEnrichmentSync(enrichmentId, params) {
|
|
157
|
+
const runResponse = await this.runEnrichment(enrichmentId, params);
|
|
158
|
+
return await this.pollTaskUntilComplete(runResponse.task_id);
|
|
159
|
+
}
|
|
160
|
+
async runBulkEnrichmentSync(enrichmentId, paramsList) {
|
|
161
|
+
const runResponse = await this.runBulkEnrichment(enrichmentId, paramsList);
|
|
162
|
+
return await this.pollTaskUntilComplete(runResponse.task_id);
|
|
163
|
+
}
|
|
164
|
+
// ============================================================================
|
|
165
|
+
// Waterfall Methods
|
|
166
|
+
// ============================================================================
|
|
167
|
+
async getAllWaterfalls() {
|
|
168
|
+
try {
|
|
169
|
+
const response = await this.withRetry(() => this.client.get('/waterfalls'));
|
|
170
|
+
return response.data;
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
this.handleError(error);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async getWaterfallDetails(identifier) {
|
|
177
|
+
try {
|
|
178
|
+
const response = await this.withRetry(() => this.client.get(`/waterfalls/${identifier}`));
|
|
179
|
+
return response.data;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
this.handleError(error);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async runWaterfall(identifier, params, enrichmentIds, emailVerifier) {
|
|
186
|
+
try {
|
|
187
|
+
if (!enrichmentIds || enrichmentIds.length === 0) {
|
|
188
|
+
const waterfall = await this.getWaterfallDetails(identifier);
|
|
189
|
+
enrichmentIds = waterfall.available_enrichments.map(e => e.id);
|
|
190
|
+
}
|
|
191
|
+
const payload = {
|
|
192
|
+
params,
|
|
193
|
+
enrichments: enrichmentIds
|
|
194
|
+
};
|
|
195
|
+
if (emailVerifier != null) {
|
|
196
|
+
payload.email_verifier = emailVerifier;
|
|
197
|
+
}
|
|
198
|
+
const response = await this.withRetry(() => this.client.post(`/waterfalls/${identifier}/run`, payload));
|
|
199
|
+
return response.data;
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
this.handleError(error);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async runBulkWaterfall(identifier, paramsList, enrichmentIds, emailVerifier) {
|
|
206
|
+
try {
|
|
207
|
+
if (!enrichmentIds || enrichmentIds.length === 0) {
|
|
208
|
+
const waterfall = await this.getWaterfallDetails(identifier);
|
|
209
|
+
enrichmentIds = waterfall.available_enrichments.map(e => e.id);
|
|
210
|
+
}
|
|
211
|
+
const payload = {
|
|
212
|
+
params: paramsList,
|
|
213
|
+
enrichments: enrichmentIds
|
|
214
|
+
};
|
|
215
|
+
if (emailVerifier != null) {
|
|
216
|
+
payload.email_verifier = emailVerifier;
|
|
217
|
+
}
|
|
218
|
+
const response = await this.withRetry(() => this.client.post(`/waterfalls/${identifier}/bulk-run`, payload));
|
|
219
|
+
return response.data;
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
this.handleError(error);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async runWaterfallSync(identifier, params, enrichmentIds, emailVerifier) {
|
|
226
|
+
const runResponse = await this.runWaterfall(identifier, params, enrichmentIds, emailVerifier);
|
|
227
|
+
const data = await this.pollTaskUntilComplete(runResponse.task_id);
|
|
228
|
+
return {
|
|
229
|
+
request_id: runResponse.task_id,
|
|
230
|
+
status: 'completed',
|
|
231
|
+
data: data,
|
|
232
|
+
error: null
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
async runBulkWaterfallSync(identifier, paramsList, enrichmentIds, emailVerifier) {
|
|
236
|
+
const runResponse = await this.runBulkWaterfall(identifier, paramsList, enrichmentIds, emailVerifier);
|
|
237
|
+
return await this.pollTaskUntilComplete(runResponse.task_id);
|
|
238
|
+
}
|
|
239
|
+
// ============================================================================
|
|
240
|
+
// Table Methods
|
|
241
|
+
// ============================================================================
|
|
242
|
+
async createTable() {
|
|
243
|
+
try {
|
|
244
|
+
const response = await this.withRetry(() => this.client.post('/table/create'));
|
|
245
|
+
return response.data;
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
this.handleError(error);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async getAllTables() {
|
|
252
|
+
try {
|
|
253
|
+
const response = await this.withRetry(() => this.client.get('/table/'));
|
|
254
|
+
return response.data;
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
this.handleError(error);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async getTableColumns(tableUuid) {
|
|
261
|
+
try {
|
|
262
|
+
const response = await this.withRetry(() => this.client.get(`/table/${tableUuid}/columns`));
|
|
263
|
+
return response.data;
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
this.handleError(error);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async getTableEnrichments(tableUuid) {
|
|
270
|
+
try {
|
|
271
|
+
const response = await this.withRetry(() => this.client.get(`/table/${tableUuid}/enrichments`));
|
|
272
|
+
return response.data;
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
this.handleError(error);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async addTableEnrichment(tableUuid, data) {
|
|
279
|
+
try {
|
|
280
|
+
const response = await this.withRetry(() => this.client.post(`/table/${tableUuid}/add-enrichment`, data));
|
|
281
|
+
return response.data;
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
this.handleError(error);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async runTableEnrichment(tableUuid, enrichmentId) {
|
|
288
|
+
try {
|
|
289
|
+
const response = await this.withRetry(() => this.client.get(`/table/${tableUuid}/run-enrichment/${enrichmentId}`));
|
|
290
|
+
return response.data;
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
this.handleError(error);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async getTableRows(tableUuid, page = 1, perPage = 1000) {
|
|
297
|
+
try {
|
|
298
|
+
const response = await this.withRetry(() => this.client.get(`/table/${tableUuid}/rows`, {
|
|
299
|
+
params: { page, per_page: perPage }
|
|
300
|
+
}));
|
|
301
|
+
return response.data;
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
this.handleError(error);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Insert rows, auto-batching into chunks of 50 (API limit).
|
|
309
|
+
*/
|
|
310
|
+
async createRows(tableId, request) {
|
|
311
|
+
const chunks = chunkArray(request.records, API_ROW_BATCH);
|
|
312
|
+
const allCreated = [];
|
|
313
|
+
const allErrors = [];
|
|
314
|
+
for (const chunk of chunks) {
|
|
315
|
+
try {
|
|
316
|
+
const response = await this.withRetry(() => this.client.post(`/tables/${tableId}/rows`, { records: chunk, options: request.options }));
|
|
317
|
+
if (response.data.created)
|
|
318
|
+
allCreated.push(...response.data.created);
|
|
319
|
+
if (response.data.errors)
|
|
320
|
+
allErrors.push(...response.data.errors);
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
this.handleError(error);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return { created: allCreated, errors: allErrors };
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Patch rows, auto-batching into chunks of 50 (API limit).
|
|
330
|
+
*/
|
|
331
|
+
async patchRows(tableId, request) {
|
|
332
|
+
const chunks = chunkArray(request.rows, API_ROW_BATCH);
|
|
333
|
+
const allResults = [];
|
|
334
|
+
for (const chunk of chunks) {
|
|
335
|
+
try {
|
|
336
|
+
const response = await this.withRetry(() => this.client.patch(`/tables/${tableId}/rows`, { rows: chunk, return_rows: request.return_rows, overwrite: request.overwrite }));
|
|
337
|
+
if (response.data.results)
|
|
338
|
+
allResults.push(...response.data.results);
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
this.handleError(error);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return { results: allResults };
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Upsert rows, auto-batching into chunks of 50 (API limit).
|
|
348
|
+
*/
|
|
349
|
+
async upsertRows(tableId, request) {
|
|
350
|
+
const chunks = chunkArray(request.rows, API_ROW_BATCH);
|
|
351
|
+
const allResults = [];
|
|
352
|
+
for (const chunk of chunks) {
|
|
353
|
+
try {
|
|
354
|
+
const response = await this.withRetry(() => this.client.post(`/tables/${tableId}/rows:upsert`, { rows: chunk }));
|
|
355
|
+
if (response.data.results)
|
|
356
|
+
allResults.push(...response.data.results);
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
this.handleError(error);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return { results: allResults };
|
|
363
|
+
}
|
|
364
|
+
// ============================================================================
|
|
365
|
+
// User Methods
|
|
366
|
+
// ============================================================================
|
|
367
|
+
async getUserInfo() {
|
|
368
|
+
try {
|
|
369
|
+
const response = await this.withRetry(() => this.client.get('/user/me'));
|
|
370
|
+
return response.data;
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
this.handleError(error);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
//# sourceMappingURL=databar-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"databar-client.js","sourceRoot":"","sources":["../src/databar-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAoC,MAAM,OAAO,CAAC;AA2BzD,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,SAAS,UAAU,CAAI,GAAQ,EAAE,IAAY;IAC3C,MAAM,MAAM,GAAU,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,OAAO,aAAa;IAChB,MAAM,CAAgB;IACtB,MAAM,CAAgB;IAE9B,YAAY,MAAqB;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YACzB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE;gBACP,UAAU,EAAE,MAAM,CAAC,MAAM;gBACzB,cAAc,EAAE,kBAAkB;aACnC;YACD,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,EAAU;QACtB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;IAEO,WAAW,CAAC,KAAU;QAC5B,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,KAAiC,CAAC;YACrD,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;YAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC;YAEvC,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACrC,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAC;YAC7G,CAAC;YAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,IAAI,IAAI,EAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACtF,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,EAAE,CAAC,CAAC;gBACjD,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACjD,CAAC;YAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACxC,CAAC;YAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;YACjG,CAAC;YAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;YAED,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1E,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,qBAAqB,KAAK,CAAC,OAAO,IAAI,eAAe,EAAE,CAAC,CAAC;IAC3E,CAAC;IAEO,KAAK,CAAC,SAAS,CACrB,EAAoB,EACpB,aAAqB,CAAC,EACtB,YAAoB,IAAI;QAExB,IAAI,SAAc,CAAC;QAEnB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,CAAC;gBACH,OAAO,MAAM,EAAE,EAAE,CAAC;YACpB,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,SAAS,GAAG,KAAK,CAAC;gBAElB,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC;oBACtC,IAAI,MAAM,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;wBAC9D,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;gBAED,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;oBAC3B,MAAM,KAAK,CAAC;gBACd,CAAC;gBAED,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC/C,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,MAAM,SAAS,CAAC;IAClB,CAAC;IAED,+EAA+E;IAC/E,qBAAqB;IACrB,+EAA+E;IAE/E,KAAK,CAAC,iBAAiB;QACrB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAe,cAAc,CAAC,CAC9C,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,YAAoB;QAC7C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAa,gBAAgB,YAAY,EAAE,CAAC,CAC5D,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,YAAoB,EACpB,MAA2B;QAE3B,IAAI,CAAC;YACH,MAAM,OAAO,GAAyB,EAAE,MAAM,EAAE,CAAC;YACjD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,gBAAgB,YAAY,MAAM,EAClC,OAAO,CACR,CACF,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,YAAoB,EACpB,UAAiC;QAEjC,IAAI,CAAC;YACH,MAAM,OAAO,GAA6B,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,gBAAgB,YAAY,WAAW,EACvC,OAAO,CACR,CACF,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAc;QAChC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAe,UAAU,MAAM,EAAE,CAAC,CAClD,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,MAAc;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;QAChD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;QAEhD,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;YACvD,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAE3C,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACnD,OAAO,MAAM,CAAC,IAAI,CAAC;YACrB,CAAC;YAED,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC9C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC1C,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;oBACzB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,aAAa,CAAC,CAAC;YAC7C,CAAC;YAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,uGAAuG,CAAC,CAAC;YAC3H,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,wBAAwB,WAAW,GAAG,YAAY,GAAG,IAAI,UAAU,CAAC,CAAC;IACvF,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,YAAoB,EACpB,MAA2B;QAE3B,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACnE,OAAO,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,qBAAqB,CACzB,YAAoB,EACpB,UAAiC;QAEjC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAC3E,OAAO,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED,+EAA+E;IAC/E,oBAAoB;IACpB,+EAA+E;IAE/E,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAc,aAAa,CAAC,CAC5C,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,UAAkB;QAC1C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAY,eAAe,UAAU,EAAE,CAAC,CACxD,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,UAAkB,EAClB,MAA2B,EAC3B,aAAwB,EACxB,aAAsB;QAEtB,IAAI,CAAC;YACH,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;gBAC7D,aAAa,GAAG,SAAS,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,OAAO,GAAwB;gBACnC,MAAM;gBACN,WAAW,EAAE,aAAa;aAC3B,CAAC;YACF,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;gBAC1B,OAAO,CAAC,cAAc,GAAG,aAAa,CAAC;YACzC,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,eAAe,UAAU,MAAM,EAC/B,OAAO,CACR,CACF,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,UAAkB,EAClB,UAAiC,EACjC,aAAwB,EACxB,aAAsB;QAEtB,IAAI,CAAC;YACH,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;gBAC7D,aAAa,GAAG,SAAS,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,OAAO,GAA4B;gBACvC,MAAM,EAAE,UAAU;gBAClB,WAAW,EAAE,aAAa;aAC3B,CAAC;YACF,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;gBAC1B,OAAO,CAAC,cAAc,GAAG,aAAa,CAAC;YACzC,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,eAAe,UAAU,WAAW,EACpC,OAAO,CACR,CACF,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,UAAkB,EAClB,MAA2B,EAC3B,aAAwB,EACxB,aAAsB;QAEtB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;QAC9F,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAEnE,OAAO;YACL,UAAU,EAAE,WAAW,CAAC,OAAO;YAC/B,MAAM,EAAE,WAAW;YACnB,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,oBAAoB,CACxB,UAAkB,EAClB,UAAiC,EACjC,aAAwB,EACxB,aAAsB;QAEtB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;QACtG,OAAO,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED,+EAA+E;IAC/E,gBAAgB;IAChB,+EAA+E;IAE/E,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAQ,eAAe,CAAC,CACzC,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAU,SAAS,CAAC,CACpC,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,SAAiB;QACrC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAW,UAAU,SAAS,UAAU,CAAC,CACzD,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,SAAiB;QACzC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAoB,UAAU,SAAS,cAAc,CAAC,CACtE,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,SAAiB,EACjB,IAA0B;QAE1B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,SAAS,iBAAiB,EAAE,IAAI,CAAC,CAC7D,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,SAAiB,EACjB,YAAoB;QAEpB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,SAAS,mBAAmB,YAAY,EAAE,CAAC,CACtE,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,SAAiB,EACjB,OAAe,CAAC,EAChB,UAAkB,IAAI;QAEtB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,SAAS,OAAO,EAAE;gBAC1C,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE;aACpC,CAAC,CACH,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CACd,OAAe,EACf,OAA0B;QAE1B,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAC1D,MAAM,UAAU,GAAkC,EAAE,CAAC;QACrD,MAAM,SAAS,GAAiC,EAAE,CAAC;QAEnD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,WAAW,OAAO,OAAO,EACzB,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAC7C,CACF,CAAC;gBACF,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO;oBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrE,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM;oBAAE,SAAS,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CACb,OAAe,EACf,OAAyB;QAEzB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACvD,MAAM,UAAU,GAAiC,EAAE,CAAC;QAEpD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,WAAW,OAAO,OAAO,EACzB,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAChF,CACF,CAAC;gBACF,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO;oBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CACd,OAAe,EACf,OAA0B;QAE1B,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACvD,MAAM,UAAU,GAAkC,EAAE,CAAC;QAErD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,WAAW,OAAO,cAAc,EAChC,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CACF,CAAC;gBACF,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO;oBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACjC,CAAC;IAED,+EAA+E;IAC/E,eAAe;IACf,+EAA+E;IAE/E,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAO,UAAU,CAAC,CAClC,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;CACF"}
|
package/dist/guards.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security guards: spending limits, input validation, result sanitization
|
|
3
|
+
*/
|
|
4
|
+
import { DatabarClient } from './databar-client.js';
|
|
5
|
+
export interface SpendingConfig {
|
|
6
|
+
safeMode: boolean;
|
|
7
|
+
maxCostPerRequest: number | null;
|
|
8
|
+
minBalance: number;
|
|
9
|
+
maxResultLength: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function loadSpendingConfig(): SpendingConfig;
|
|
12
|
+
/**
|
|
13
|
+
* Check spending guard. Behavior depends on safe mode:
|
|
14
|
+
*
|
|
15
|
+
* Safe mode (default):
|
|
16
|
+
* - Checks cost cap (local, fast)
|
|
17
|
+
* - Fetches balance from API and blocks if insufficient
|
|
18
|
+
* - Returns error string if blocked, null if OK
|
|
19
|
+
*
|
|
20
|
+
* Unsafe mode (DATABAR_SAFE_MODE=false):
|
|
21
|
+
* - Still checks cost cap (local, fast)
|
|
22
|
+
* - Skips the balance API call entirely
|
|
23
|
+
* - Returns null (never blocks on balance)
|
|
24
|
+
*/
|
|
25
|
+
export declare function checkSpendingGuard(client: DatabarClient, estimatedCost: number, config: SpendingConfig): Promise<string | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Build a cost warning string for unsafe mode.
|
|
28
|
+
* In safe mode, returns empty string (guard already checked).
|
|
29
|
+
*/
|
|
30
|
+
export declare function unsafeModeWarning(config: SpendingConfig, estimatedCost: number, recordCount?: number): string;
|
|
31
|
+
/**
|
|
32
|
+
* Validate that an array is non-empty.
|
|
33
|
+
* For enrichments/waterfalls there's no backend size limit.
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateBulkArray(items: any[], label: string): string | null;
|
|
36
|
+
/**
|
|
37
|
+
* Validate row operations — the Databar API limits these to 50 per request.
|
|
38
|
+
* We accept up to MAX_ROW_ITEMS and auto-batch into chunks of 50.
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateRowBatchSize(items: any[], label: string): string | null;
|
|
41
|
+
export declare function sanitizeResult(text: string, maxLength: number): string;
|
|
42
|
+
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,kBAAkB,IAAI,cAAc,CAYnD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyBxB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CASR;AAQD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW/E;AAMD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAMtE"}
|
package/dist/guards.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security guards: spending limits, input validation, result sanitization
|
|
3
|
+
*/
|
|
4
|
+
export function loadSpendingConfig() {
|
|
5
|
+
const safeMode = process.env.DATABAR_SAFE_MODE;
|
|
6
|
+
const maxCost = process.env.DATABAR_MAX_COST_PER_REQUEST;
|
|
7
|
+
const minBal = process.env.DATABAR_MIN_BALANCE;
|
|
8
|
+
const maxResult = process.env.DATABAR_MAX_RESULT_LENGTH;
|
|
9
|
+
return {
|
|
10
|
+
safeMode: safeMode !== 'false',
|
|
11
|
+
maxCostPerRequest: maxCost ? parseFloat(maxCost) : null,
|
|
12
|
+
minBalance: minBal ? parseFloat(minBal) : 1.0,
|
|
13
|
+
maxResultLength: maxResult ? parseInt(maxResult) : 50000,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check spending guard. Behavior depends on safe mode:
|
|
18
|
+
*
|
|
19
|
+
* Safe mode (default):
|
|
20
|
+
* - Checks cost cap (local, fast)
|
|
21
|
+
* - Fetches balance from API and blocks if insufficient
|
|
22
|
+
* - Returns error string if blocked, null if OK
|
|
23
|
+
*
|
|
24
|
+
* Unsafe mode (DATABAR_SAFE_MODE=false):
|
|
25
|
+
* - Still checks cost cap (local, fast)
|
|
26
|
+
* - Skips the balance API call entirely
|
|
27
|
+
* - Returns null (never blocks on balance)
|
|
28
|
+
*/
|
|
29
|
+
export async function checkSpendingGuard(client, estimatedCost, config) {
|
|
30
|
+
if (config.maxCostPerRequest !== null && estimatedCost > config.maxCostPerRequest) {
|
|
31
|
+
return `Blocked: estimated cost (${estimatedCost.toFixed(2)} credits) exceeds per-request limit (${config.maxCostPerRequest} credits). Adjust DATABAR_MAX_COST_PER_REQUEST to allow higher costs.`;
|
|
32
|
+
}
|
|
33
|
+
if (!config.safeMode) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const user = await client.getUserInfo();
|
|
38
|
+
const balance = user.balance;
|
|
39
|
+
if (balance < config.minBalance) {
|
|
40
|
+
return `Blocked: current balance (${balance.toFixed(2)} credits) is below minimum threshold (${config.minBalance} credits). Top up your account or adjust DATABAR_MIN_BALANCE.`;
|
|
41
|
+
}
|
|
42
|
+
if (balance < estimatedCost) {
|
|
43
|
+
return `Blocked: current balance (${balance.toFixed(2)} credits) is insufficient for estimated cost (${estimatedCost.toFixed(2)} credits).`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// If balance check fails, don't block — the API will reject if truly insufficient
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a cost warning string for unsafe mode.
|
|
53
|
+
* In safe mode, returns empty string (guard already checked).
|
|
54
|
+
*/
|
|
55
|
+
export function unsafeModeWarning(config, estimatedCost, recordCount) {
|
|
56
|
+
if (config.safeMode)
|
|
57
|
+
return '';
|
|
58
|
+
const parts = ['[Unsafe mode — no credit balance check]'];
|
|
59
|
+
if (recordCount != null) {
|
|
60
|
+
parts.push(`Records: ${recordCount}`);
|
|
61
|
+
}
|
|
62
|
+
parts.push(`Estimated cost: ~${estimatedCost.toFixed(2)} credits`);
|
|
63
|
+
return parts.join(' | ') + '\n\n';
|
|
64
|
+
}
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// Input Validation
|
|
67
|
+
// ============================================================================
|
|
68
|
+
const MAX_ROW_ITEMS = 100;
|
|
69
|
+
/**
|
|
70
|
+
* Validate that an array is non-empty.
|
|
71
|
+
* For enrichments/waterfalls there's no backend size limit.
|
|
72
|
+
*/
|
|
73
|
+
export function validateBulkArray(items, label) {
|
|
74
|
+
if (!Array.isArray(items)) {
|
|
75
|
+
return `${label} must be an array.`;
|
|
76
|
+
}
|
|
77
|
+
if (items.length === 0) {
|
|
78
|
+
return `${label} cannot be empty.`;
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Validate row operations — the Databar API limits these to 50 per request.
|
|
84
|
+
* We accept up to MAX_ROW_ITEMS and auto-batch into chunks of 50.
|
|
85
|
+
*/
|
|
86
|
+
export function validateRowBatchSize(items, label) {
|
|
87
|
+
if (!Array.isArray(items)) {
|
|
88
|
+
return `${label} must be an array.`;
|
|
89
|
+
}
|
|
90
|
+
if (items.length === 0) {
|
|
91
|
+
return `${label} cannot be empty.`;
|
|
92
|
+
}
|
|
93
|
+
if (items.length > MAX_ROW_ITEMS) {
|
|
94
|
+
return `${label} has ${items.length} items, but the maximum is ${MAX_ROW_ITEMS} per request. The API batches these into groups of 50 automatically.`;
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Result Sanitization
|
|
100
|
+
// ============================================================================
|
|
101
|
+
export function sanitizeResult(text, maxLength) {
|
|
102
|
+
if (text.length <= maxLength) {
|
|
103
|
+
return text;
|
|
104
|
+
}
|
|
105
|
+
const truncated = text.slice(0, maxLength);
|
|
106
|
+
return truncated + `\n\n[Result truncated — showing ${maxLength.toLocaleString()} of ${text.length.toLocaleString()} characters. Use more specific parameters to reduce output size.]`;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
|