intelicoreact 2.0.5 → 2.0.6
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/dist/Atomic/FormElements/CheckboxInput/CheckboxInput.interface.d.ts +2 -1
- package/dist/Atomic/FormElements/FileLoaderDescription/FileLoaderDescription.interface.d.ts +3 -3
- package/dist/Atomic/FormElements/Switcher/Switcher.interface.d.ts +2 -1
- package/dist/Atomic/UI/AccordionText/AccordionText.interface.d.ts +13 -0
- package/dist/Atomic/UI/Alert/Alert.interface.d.ts +1 -1
- package/dist/Functions/sdk/runtime-sdk/client.d.ts +19 -0
- package/dist/Functions/sdk/runtime-sdk/config.d.ts +32 -0
- package/dist/Functions/sdk/runtime-sdk/index.d.ts +3 -0
- package/dist/Functions/sdk/runtime-sdk/queue.d.ts +70 -0
- package/dist/Functions/sdk/runtime-sdk/transport.d.ts +41 -0
- package/dist/Functions/sdk/runtime-sdk/types.d.ts +84 -0
- package/dist/Molecular/FormElement/FormElement.interface.d.ts +1 -1
- package/dist/Molecular/FormWithDependOn/FormWithDependOn.interface.d.ts +99 -0
- package/dist/classes.cjs +10 -8
- package/dist/classes.cjs.map +2 -2
- package/dist/classes.js +10 -8
- package/dist/classes.js.map +2 -2
- package/dist/index.cjs +10 -8
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +10 -8
- package/dist/index.js.map +2 -2
- package/dist/sdk.cjs +451 -0
- package/dist/sdk.cjs.map +7 -0
- package/dist/sdk.d.ts +5 -0
- package/dist/sdk.js +429 -0
- package/dist/sdk.js.map +7 -0
- package/package.json +11 -1
- package/sdk/package.json +5 -0
package/dist/sdk.cjs
ADDED
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/sdk.ts
|
|
20
|
+
var sdk_exports = {};
|
|
21
|
+
__export(sdk_exports, {
|
|
22
|
+
HttpError: () => HttpError,
|
|
23
|
+
createRuntimeClient: () => createRuntimeClient
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(sdk_exports);
|
|
26
|
+
|
|
27
|
+
// src/Functions/sdk/runtime-sdk/config.ts
|
|
28
|
+
var noopLogger = () => {
|
|
29
|
+
};
|
|
30
|
+
var consoleLogger = (level, message, meta) => {
|
|
31
|
+
const tag = "[runtime-sdk]";
|
|
32
|
+
if (level === "error") console.error(tag, message, meta ?? "");
|
|
33
|
+
else if (level === "warn") console.warn(tag, message, meta ?? "");
|
|
34
|
+
else console.debug(tag, message, meta ?? "");
|
|
35
|
+
};
|
|
36
|
+
function resolveConfig(config) {
|
|
37
|
+
if (!config.baseUrl || typeof config.baseUrl !== "string") {
|
|
38
|
+
throw new Error("[runtime-sdk] baseUrl is required");
|
|
39
|
+
}
|
|
40
|
+
const baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
41
|
+
const debug = config.debug ?? false;
|
|
42
|
+
const fetchImpl = config.fetchImpl ?? (typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0);
|
|
43
|
+
if (!fetchImpl) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
"[runtime-sdk] fetch is not available; pass fetchImpl in config"
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
baseUrl,
|
|
50
|
+
apiKey: config.apiKey,
|
|
51
|
+
enabled: config.enabled ?? true,
|
|
52
|
+
debug,
|
|
53
|
+
batchSize: clamp(config.batchSize ?? 25, 1, 200),
|
|
54
|
+
flushIntervalMs: clamp(config.flushIntervalMs ?? 5e3, 500, 6e4),
|
|
55
|
+
maxQueueSize: clamp(config.maxQueueSize ?? 1e3, 50, 1e4),
|
|
56
|
+
maxRetries: clamp(config.maxRetries ?? 2, 0, 5),
|
|
57
|
+
requestTimeoutMs: clamp(config.requestTimeoutMs ?? 8e3, 1e3, 3e4),
|
|
58
|
+
flushOnUnload: config.flushOnUnload ?? true,
|
|
59
|
+
fetchImpl,
|
|
60
|
+
logger: config.logger ?? (debug ? consoleLogger : noopLogger),
|
|
61
|
+
onError: config.onError,
|
|
62
|
+
headers: { ...config.headers ?? {} }
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function clamp(value, min, max) {
|
|
66
|
+
if (!Number.isFinite(value)) return min;
|
|
67
|
+
return Math.min(Math.max(value, min), max);
|
|
68
|
+
}
|
|
69
|
+
function buildHeaders(config, extra) {
|
|
70
|
+
const headers = {
|
|
71
|
+
"Content-Type": "application/json",
|
|
72
|
+
...config.headers,
|
|
73
|
+
...extra ?? {}
|
|
74
|
+
};
|
|
75
|
+
if (config.apiKey) headers["X-API-Key"] = config.apiKey;
|
|
76
|
+
return headers;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/Functions/sdk/runtime-sdk/transport.ts
|
|
80
|
+
var HttpError = class extends Error {
|
|
81
|
+
constructor(status, body, retryAfterMs) {
|
|
82
|
+
super(`HTTP ${status}: ${body.slice(0, 200)}`);
|
|
83
|
+
this.status = status;
|
|
84
|
+
this.body = body;
|
|
85
|
+
this.retryAfterMs = retryAfterMs;
|
|
86
|
+
this.name = "HttpError";
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
async function request(config, options) {
|
|
90
|
+
const url = new URL(config.baseUrl + options.path);
|
|
91
|
+
if (options.query) {
|
|
92
|
+
for (const [k, v] of Object.entries(options.query))
|
|
93
|
+
url.searchParams.set(k, v);
|
|
94
|
+
}
|
|
95
|
+
const controller = new AbortController();
|
|
96
|
+
const timer = setTimeout(() => controller.abort(), config.requestTimeoutMs);
|
|
97
|
+
const signal = options.signal ?? controller.signal;
|
|
98
|
+
try {
|
|
99
|
+
const res = await config.fetchImpl(url.toString(), {
|
|
100
|
+
method: options.method,
|
|
101
|
+
headers: buildHeaders(config),
|
|
102
|
+
body: options.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
103
|
+
signal
|
|
104
|
+
});
|
|
105
|
+
if (!res.ok) {
|
|
106
|
+
const text = await safeText(res);
|
|
107
|
+
const retryAfter = parseRetryAfter(res.headers.get("Retry-After"));
|
|
108
|
+
throw new HttpError(res.status, text, retryAfter);
|
|
109
|
+
}
|
|
110
|
+
if (res.status === 204) return void 0;
|
|
111
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
112
|
+
if (ct.includes("application/json")) return await res.json();
|
|
113
|
+
return await safeText(res);
|
|
114
|
+
} finally {
|
|
115
|
+
clearTimeout(timer);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function requestWithRetry(config, options, phase) {
|
|
119
|
+
let attempt = 0;
|
|
120
|
+
let lastError;
|
|
121
|
+
while (attempt <= config.maxRetries) {
|
|
122
|
+
try {
|
|
123
|
+
return await request(config, options);
|
|
124
|
+
} catch (err) {
|
|
125
|
+
lastError = err;
|
|
126
|
+
attempt += 1;
|
|
127
|
+
const shouldRetry = isRetryable(err) && attempt <= config.maxRetries;
|
|
128
|
+
config.logger(
|
|
129
|
+
shouldRetry ? "warn" : "error",
|
|
130
|
+
`${options.method} ${options.path} failed (attempt ${attempt})`,
|
|
131
|
+
err
|
|
132
|
+
);
|
|
133
|
+
config.onError?.(err, { phase, attempt });
|
|
134
|
+
if (!shouldRetry) break;
|
|
135
|
+
const delayMs = computeBackoff(err, attempt);
|
|
136
|
+
await sleep(delayMs);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
throw lastError;
|
|
140
|
+
}
|
|
141
|
+
function isRetryable(err) {
|
|
142
|
+
if (err instanceof HttpError) {
|
|
143
|
+
return err.status === 429 || err.status >= 500;
|
|
144
|
+
}
|
|
145
|
+
if (err instanceof Error && (err.name === "AbortError" || err.name === "TypeError")) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
function computeBackoff(err, attempt) {
|
|
151
|
+
if (err instanceof HttpError && err.retryAfterMs !== void 0) {
|
|
152
|
+
return err.retryAfterMs;
|
|
153
|
+
}
|
|
154
|
+
const base = 300;
|
|
155
|
+
const jitter = Math.random() * 200;
|
|
156
|
+
return Math.min(base * 2 ** (attempt - 1) + jitter, 1e4);
|
|
157
|
+
}
|
|
158
|
+
function parseRetryAfter(header) {
|
|
159
|
+
if (!header) return void 0;
|
|
160
|
+
const asSeconds = Number(header);
|
|
161
|
+
if (!Number.isNaN(asSeconds)) return asSeconds * 1e3;
|
|
162
|
+
const asDate = Date.parse(header);
|
|
163
|
+
if (!Number.isNaN(asDate)) return Math.max(asDate - Date.now(), 0);
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
async function safeText(res) {
|
|
167
|
+
try {
|
|
168
|
+
return await res.text();
|
|
169
|
+
} catch {
|
|
170
|
+
return "";
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function sleep(ms) {
|
|
174
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/Functions/sdk/runtime-sdk/queue.ts
|
|
178
|
+
var BatchQueue = class {
|
|
179
|
+
/**
|
|
180
|
+
* Создаёт очередь и, если `flushIntervalMs > 0`, запускает
|
|
181
|
+
* периодический таймер флаша. Таймер будет тикать до тех пор,
|
|
182
|
+
* пока не вызовут `destroy()`.
|
|
183
|
+
*/
|
|
184
|
+
constructor(config) {
|
|
185
|
+
this.config = config;
|
|
186
|
+
if (config.flushIntervalMs > 0) {
|
|
187
|
+
this.timer = setInterval(() => {
|
|
188
|
+
void this.flush();
|
|
189
|
+
}, config.flushIntervalMs);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
buffer = [];
|
|
193
|
+
timer = null;
|
|
194
|
+
inflight = null;
|
|
195
|
+
destroyed = false;
|
|
196
|
+
/**
|
|
197
|
+
* Текущее количество событий в буфере (ещё не отправленных).
|
|
198
|
+
* Полезно для метрик/дебага.
|
|
199
|
+
*/
|
|
200
|
+
size() {
|
|
201
|
+
return this.buffer.length;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Добавить события в буфер.
|
|
205
|
+
*
|
|
206
|
+
* Триггеры автоматического флаша:
|
|
207
|
+
* - буфер достиг `batchSize` → сразу уходит HTTP-запрос
|
|
208
|
+
* - буфер превысил `maxQueueSize` → лишние **старые** события
|
|
209
|
+
* дропаются (FIFO), чтобы не раздувать память при сбое сети
|
|
210
|
+
*
|
|
211
|
+
* После `destroy()` вызов игнорируется.
|
|
212
|
+
*/
|
|
213
|
+
enqueue(logs) {
|
|
214
|
+
if (this.destroyed) return;
|
|
215
|
+
if (logs.length === 0) return;
|
|
216
|
+
this.buffer.push(...logs);
|
|
217
|
+
if (this.buffer.length > this.config.maxQueueSize) {
|
|
218
|
+
const overflow = this.buffer.length - this.config.maxQueueSize;
|
|
219
|
+
this.buffer.splice(0, overflow);
|
|
220
|
+
this.config.logger(
|
|
221
|
+
"warn",
|
|
222
|
+
`queue overflow; dropped ${overflow} oldest events`
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
if (this.buffer.length >= this.config.batchSize) {
|
|
226
|
+
void this.flush();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Забрать всё из буфера и отправить одним батчем в
|
|
231
|
+
* `POST /api/runtime/ingest`.
|
|
232
|
+
*
|
|
233
|
+
* Если уже есть активный in-flight запрос — возвращаем его же
|
|
234
|
+
* промис (защита от параллельных флашей по таймеру и по размеру).
|
|
235
|
+
*
|
|
236
|
+
* Ошибки HTTP/сети сюда не всплывают — они проглатываются
|
|
237
|
+
* после всех retry-попыток и логируются как 'error'. Дроп
|
|
238
|
+
* целого батча при окончательном фейле — осознанный компромисс:
|
|
239
|
+
* лучше потерять часть телеметрии, чем заблокировать очередь.
|
|
240
|
+
*/
|
|
241
|
+
async flush() {
|
|
242
|
+
if (this.destroyed) return;
|
|
243
|
+
if (this.buffer.length === 0) return;
|
|
244
|
+
if (this.inflight) return this.inflight;
|
|
245
|
+
const batch = this.buffer.splice(0, this.buffer.length);
|
|
246
|
+
this.inflight = (async () => {
|
|
247
|
+
try {
|
|
248
|
+
const body = { logs: batch };
|
|
249
|
+
const res = await requestWithRetry(
|
|
250
|
+
this.config,
|
|
251
|
+
{ method: "POST", path: "/api/runtime/ingest", body },
|
|
252
|
+
"ingest"
|
|
253
|
+
);
|
|
254
|
+
this.config.logger("debug", `flushed ${batch.length} logs`, res);
|
|
255
|
+
} catch (err) {
|
|
256
|
+
this.config.logger(
|
|
257
|
+
"error",
|
|
258
|
+
`flush failed; dropping ${batch.length} logs`,
|
|
259
|
+
err
|
|
260
|
+
);
|
|
261
|
+
} finally {
|
|
262
|
+
this.inflight = null;
|
|
263
|
+
}
|
|
264
|
+
})();
|
|
265
|
+
return this.inflight;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Отправить буфер через `navigator.sendBeacon` при закрытии вкладки.
|
|
269
|
+
*
|
|
270
|
+
* В отличие от обычного `flush()`:
|
|
271
|
+
* - fire-and-forget: нет ответа и нет retry
|
|
272
|
+
* - браузер гарантирует доставку даже после того как страница
|
|
273
|
+
* уже уничтожается (unload / pagehide)
|
|
274
|
+
* - нет заголовка `X-API-Key` (sendBeacon не даёт менять headers,
|
|
275
|
+
* но `Content-Type` нам выставляет сам тип Blob)
|
|
276
|
+
*
|
|
277
|
+
* Возвращает `true` если браузер принял пачку в свою очередь,
|
|
278
|
+
* `false` при отсутствии API или отказе (например слишком
|
|
279
|
+
* большой payload — лимит обычно 64 КБ).
|
|
280
|
+
*/
|
|
281
|
+
flushBeacon() {
|
|
282
|
+
if (this.destroyed) return false;
|
|
283
|
+
if (this.buffer.length === 0) return true;
|
|
284
|
+
if (typeof navigator === "undefined" || typeof navigator.sendBeacon !== "function") {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
const batch = this.buffer.splice(0, this.buffer.length);
|
|
288
|
+
const body = { logs: batch };
|
|
289
|
+
const blob = new Blob([JSON.stringify(body)], { type: "application/json" });
|
|
290
|
+
const url = `${this.config.baseUrl}/api/runtime/ingest`;
|
|
291
|
+
const ok = navigator.sendBeacon(url, blob);
|
|
292
|
+
if (!ok)
|
|
293
|
+
this.config.logger("warn", `sendBeacon rejected ${batch.length} logs`);
|
|
294
|
+
return ok;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Остановить очередь и освободить ресурсы.
|
|
298
|
+
*
|
|
299
|
+
* Чистит таймер флаша, обнуляет буфер, помечает инстанс
|
|
300
|
+
* уничтоженным — последующие `enqueue`/`flush`/`flushBeacon`
|
|
301
|
+
* становятся no-op. Идемпотентна.
|
|
302
|
+
*
|
|
303
|
+
* Важно: in-flight запрос, если он был запущен до `destroy`,
|
|
304
|
+
* не отменяется — он либо завершится штатно, либо по таймауту
|
|
305
|
+
* `requestTimeoutMs`.
|
|
306
|
+
*/
|
|
307
|
+
destroy() {
|
|
308
|
+
if (this.destroyed) return;
|
|
309
|
+
this.destroyed = true;
|
|
310
|
+
if (this.timer) {
|
|
311
|
+
clearInterval(this.timer);
|
|
312
|
+
this.timer = null;
|
|
313
|
+
}
|
|
314
|
+
this.buffer = [];
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// src/Functions/sdk/runtime-sdk/client.ts
|
|
319
|
+
function createRuntimeClient(rawConfig) {
|
|
320
|
+
const config = resolveConfig(rawConfig);
|
|
321
|
+
const queue = new BatchQueue(config);
|
|
322
|
+
let enabled = config.enabled;
|
|
323
|
+
let unloadHandler = null;
|
|
324
|
+
if (config.flushOnUnload && typeof window !== "undefined" && typeof window.addEventListener === "function") {
|
|
325
|
+
unloadHandler = () => {
|
|
326
|
+
queue.flushBeacon();
|
|
327
|
+
};
|
|
328
|
+
window.addEventListener("pagehide", unloadHandler);
|
|
329
|
+
window.addEventListener("beforeunload", unloadHandler);
|
|
330
|
+
}
|
|
331
|
+
const client = {
|
|
332
|
+
/**
|
|
333
|
+
* Поставить одно событие в очередь на отправку.
|
|
334
|
+
*
|
|
335
|
+
* Не делает HTTP-запрос сразу: событие попадает в батч и уйдёт
|
|
336
|
+
* либо при достижении `batchSize`, либо по таймеру `flushIntervalMs`,
|
|
337
|
+
* либо при закрытии вкладки (`sendBeacon`).
|
|
338
|
+
*
|
|
339
|
+
* Если клиент выключен (`enabled=false`) — вызов игнорируется.
|
|
340
|
+
*/
|
|
341
|
+
track(log) {
|
|
342
|
+
if (!enabled) return;
|
|
343
|
+
queue.enqueue([log]);
|
|
344
|
+
},
|
|
345
|
+
/**
|
|
346
|
+
* Поставить сразу пачку событий в очередь.
|
|
347
|
+
*
|
|
348
|
+
* Удобно когда набрали события где-то локально (interceptor,
|
|
349
|
+
* буфер в компоненте и т.п.) и хотим отдать их все разом.
|
|
350
|
+
* Если итоговый размер очереди превысил `maxQueueSize` —
|
|
351
|
+
* старые события будут выброшены (FIFO drop).
|
|
352
|
+
*/
|
|
353
|
+
trackMany(logs) {
|
|
354
|
+
if (!enabled) return;
|
|
355
|
+
queue.enqueue(logs);
|
|
356
|
+
},
|
|
357
|
+
/**
|
|
358
|
+
* Принудительно отправить всё что сейчас в очереди.
|
|
359
|
+
*
|
|
360
|
+
* Возвращает промис, резолвящийся после завершения HTTP-запроса
|
|
361
|
+
* (успешного или нет — SDK проглатывает ошибки). Полезно перед
|
|
362
|
+
* критичными переходами: logout, route change, submit формы.
|
|
363
|
+
*
|
|
364
|
+
* Если очередь пуста или клиент выключен — no-op.
|
|
365
|
+
*/
|
|
366
|
+
async flush() {
|
|
367
|
+
if (!enabled) return;
|
|
368
|
+
await queue.flush();
|
|
369
|
+
},
|
|
370
|
+
/**
|
|
371
|
+
* Удалить накопленные runtime-логи на сервере по фильтру.
|
|
372
|
+
*
|
|
373
|
+
* В отличие от `track`, идёт напрямую в `DELETE /api/runtime/logs`
|
|
374
|
+
* без очереди и батчинга — это низкочастотная административная
|
|
375
|
+
* операция.
|
|
376
|
+
*
|
|
377
|
+
* Фильтр — дискриминированный union:
|
|
378
|
+
* - REST: `{ service, type: 'rest', path, method }`
|
|
379
|
+
* - WS: `{ service, type: 'ws', event }`
|
|
380
|
+
*
|
|
381
|
+
* Возвращает `{ deleted: N }`. При сетевой ошибке/5xx/429
|
|
382
|
+
* произойдёт до `maxRetries` повторов с бэкоффом.
|
|
383
|
+
*/
|
|
384
|
+
async deleteLogs(filter) {
|
|
385
|
+
const query = toDeleteQuery(filter);
|
|
386
|
+
return requestWithRetry(
|
|
387
|
+
config,
|
|
388
|
+
{ method: "DELETE", path: "/api/runtime/logs", query },
|
|
389
|
+
"delete"
|
|
390
|
+
);
|
|
391
|
+
},
|
|
392
|
+
/**
|
|
393
|
+
* Возвращает текущее состояние флага `enabled`.
|
|
394
|
+
*
|
|
395
|
+
* Пригодится для дев-тулзов/отладочных панелей, где видно
|
|
396
|
+
* активен ли сбор телеметрии в рантайме.
|
|
397
|
+
*/
|
|
398
|
+
isEnabled() {
|
|
399
|
+
return enabled;
|
|
400
|
+
},
|
|
401
|
+
/**
|
|
402
|
+
* Включить/выключить сбор событий на ходу.
|
|
403
|
+
*
|
|
404
|
+
* Используется для opt-out по согласию пользователя (cookie consent),
|
|
405
|
+
* для временного отключения при инцидентах, или для точечного
|
|
406
|
+
* включения через debug-панель.
|
|
407
|
+
*
|
|
408
|
+
* Выключение не чистит уже накопленную очередь — только перестаёт
|
|
409
|
+
* принимать новые события. Полный сброс — через `destroy()`.
|
|
410
|
+
*/
|
|
411
|
+
setEnabled(next) {
|
|
412
|
+
enabled = next;
|
|
413
|
+
config.logger("debug", `enabled=${next}`);
|
|
414
|
+
},
|
|
415
|
+
/**
|
|
416
|
+
* Полностью освободить ресурсы клиента.
|
|
417
|
+
*
|
|
418
|
+
* Останавливает таймер флаша, отписывается от `pagehide`/
|
|
419
|
+
* `beforeunload`, очищает буфер. Повторные вызовы безопасны.
|
|
420
|
+
*
|
|
421
|
+
* Обычно не требуется — клиент живёт всё время жизни вкладки.
|
|
422
|
+
* Полезно в SSR/тестах и при hot-reload'е на деве, чтобы не
|
|
423
|
+
* плодить дубликаты listener'ов.
|
|
424
|
+
*/
|
|
425
|
+
destroy() {
|
|
426
|
+
if (unloadHandler && typeof window !== "undefined") {
|
|
427
|
+
window.removeEventListener("pagehide", unloadHandler);
|
|
428
|
+
window.removeEventListener("beforeunload", unloadHandler);
|
|
429
|
+
unloadHandler = null;
|
|
430
|
+
}
|
|
431
|
+
queue.destroy();
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
return client;
|
|
435
|
+
}
|
|
436
|
+
function toDeleteQuery(filter) {
|
|
437
|
+
if (filter.type === "rest") {
|
|
438
|
+
return {
|
|
439
|
+
service: filter.service,
|
|
440
|
+
type: "rest",
|
|
441
|
+
path: filter.path,
|
|
442
|
+
method: filter.method
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
service: filter.service,
|
|
447
|
+
type: "ws",
|
|
448
|
+
event: filter.event
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
//# sourceMappingURL=sdk.cjs.map
|
package/dist/sdk.cjs.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/sdk.ts", "../src/Functions/sdk/runtime-sdk/config.ts", "../src/Functions/sdk/runtime-sdk/transport.ts", "../src/Functions/sdk/runtime-sdk/queue.ts", "../src/Functions/sdk/runtime-sdk/client.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * IntelicoKit \u2014 Public subpath: \"intelicoreact/sdk\"\n * Runtime SDK clients (MCP Contract Intelligence runtime-logs \u0438 \u0442.\u043F.)\n */\n\nexport * from './Functions/sdk/runtime-sdk';\n", "/* eslint-disable no-console */\nimport type { Logger, ResolvedConfig, RuntimeClientConfig } from './types';\n\nconst noopLogger: Logger = () => {};\n\nconst consoleLogger: Logger = (level, message, meta) => {\n const tag = '[runtime-sdk]';\n if (level === 'error') console.error(tag, message, meta ?? '');\n else if (level === 'warn') console.warn(tag, message, meta ?? '');\n else console.debug(tag, message, meta ?? '');\n};\n\n/**\n * \u041D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u0443\u0435\u0442 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0439 \u043A\u043E\u043D\u0444\u0438\u0433 \u0432 `ResolvedConfig` \u0441\u043E \u0432\u0441\u0435\u043C\u0438\n * \u0434\u0435\u0444\u043E\u043B\u0442\u0430\u043C\u0438 \u0438 \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u0435\u0439.\n *\n * \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0435\u0442:\n * - \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u0442 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u043E\u043B\u044F (`baseUrl`)\n * - \u043E\u0431\u0440\u0435\u0437\u0430\u0435\u0442 \u0445\u0432\u043E\u0441\u0442\u043E\u0432\u044B\u0435 \u0441\u043B\u044D\u0448\u0438 \u0443 `baseUrl`\n * - \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442 `fetch` \u0438\u0437 \u0433\u043B\u043E\u0431\u0430\u043B\u043E\u0432 \u0438\u043B\u0438 \u0438\u0437 `config.fetchImpl`\n * (\u043D\u0443\u0436\u0435\u043D \u0434\u043B\u044F SSR/Node-\u0442\u0435\u0441\u0442\u043E\u0432, \u0433\u0434\u0435 `globalThis.fetch` \u043C\u043E\u0436\u0435\u0442 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043E\u0432\u0430\u0442\u044C)\n * - \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0435\u0442 \u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u0434\u0435\u0444\u043E\u043B\u0442\u044B \u0438 clamp \u043D\u0430 \u0440\u0430\u0437\u0443\u043C\u043D\u044B\u0435 \u0433\u0440\u0430\u043D\u0438\u0446\u044B,\n * \u0447\u0442\u043E\u0431\u044B \u043A\u0440\u0438\u0432\u044B\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F (0, Infinity, \u043E\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435) \u043D\u0435 \u043B\u043E\u043C\u0430\u043B\u0438 SDK\n * - \u0432\u044B\u0431\u0438\u0440\u0430\u0435\u0442 logger: \u044F\u0432\u043D\u044B\u0439 \u2192 \u043F\u0435\u0440\u0435\u0434\u0430\u043D, \u0438\u043D\u0430\u0447\u0435 console-\u043B\u043E\u0433\u0433\u0435\u0440 \u0432 debug,\n * \u0438\u043D\u0430\u0447\u0435 no-op\n *\n * \u0411\u0440\u043E\u0441\u0430\u0435\u0442 `Error` \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u0438 \u0444\u0430\u0442\u0430\u043B\u044C\u043D\u043E \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\u0439 \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438.\n */\nexport function resolveConfig(config: RuntimeClientConfig): ResolvedConfig {\n if (!config.baseUrl || typeof config.baseUrl !== 'string') {\n throw new Error('[runtime-sdk] baseUrl is required');\n }\n\n const baseUrl = config.baseUrl.replace(/\\/+$/, '');\n const debug = config.debug ?? false;\n const fetchImpl\n = config.fetchImpl\n ?? (typeof fetch !== 'undefined' ? fetch.bind(globalThis) : undefined);\n\n if (!fetchImpl) {\n throw new Error(\n '[runtime-sdk] fetch is not available; pass fetchImpl in config',\n );\n }\n\n return {\n baseUrl,\n apiKey: config.apiKey,\n enabled: config.enabled ?? true,\n debug,\n batchSize: clamp(config.batchSize ?? 25, 1, 200),\n flushIntervalMs: clamp(config.flushIntervalMs ?? 5000, 500, 60_000),\n maxQueueSize: clamp(config.maxQueueSize ?? 1000, 50, 10_000),\n maxRetries: clamp(config.maxRetries ?? 2, 0, 5),\n requestTimeoutMs: clamp(config.requestTimeoutMs ?? 8000, 1000, 30_000),\n flushOnUnload: config.flushOnUnload ?? true,\n fetchImpl,\n logger: config.logger ?? (debug ? consoleLogger : noopLogger),\n onError: config.onError,\n headers: { ...(config.headers ?? {}) },\n };\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return min;\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * \u0421\u043E\u0431\u0438\u0440\u0430\u0435\u0442 \u0444\u0438\u043D\u0430\u043B\u044C\u043D\u044B\u0439 \u043D\u0430\u0431\u043E\u0440 HTTP-\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432 \u0434\u043B\u044F \u0437\u0430\u043F\u0440\u043E\u0441\u0430.\n *\n * \u041F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442 (\u043F\u043E\u0437\u0434\u043D\u0438\u0439 \u043F\u0435\u0440\u0435\u0437\u0430\u0442\u0438\u0440\u0430\u0435\u0442 \u0440\u0430\u043D\u043D\u0438\u0439):\n * 1. `Content-Type: application/json` \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E\n * 2. `config.headers` \u0438\u0437 \u043A\u043E\u043D\u0444\u0438\u0433\u0430 SDK\n * 3. `extra` \u2014 \u0442\u043E\u0447\u0435\u0447\u043D\u044B\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0438 \u043A\u043E\u043D\u043A\u0440\u0435\u0442\u043D\u043E\u0433\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0430\n * 4. `X-API-Key` \u0438\u0437 `config.apiKey`, \u0435\u0441\u043B\u0438 \u0437\u0430\u0434\u0430\u043D \u2014 \u0432\u0441\u0435\u0433\u0434\u0430 \u043F\u043E\u0432\u0435\u0440\u0445 \u0432\u0441\u0435\u0433\u043E,\n * \u0447\u0442\u043E\u0431\u044B \u0435\u0433\u043E \u043D\u0435\u043B\u044C\u0437\u044F \u0431\u044B\u043B\u043E \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u043E \u043F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0438\u0442\u044C \u0447\u0435\u0440\u0435\u0437 `headers`\n *\n * \u0421\u0435\u0440\u0432\u0435\u0440 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442 `X-API-Key` \u043A\u0430\u043A bucket-key \u0434\u043B\u044F rate-limiter'\u0430\n * (\u0441\u043C. `ingestion-rate-limit.guard.ts`). \u042D\u0442\u043E **\u043D\u0435** \u0442\u043E\u043A\u0435\u043D \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0438.\n */\nexport function buildHeaders(\n config: ResolvedConfig,\n extra?: Record<string, string>,\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...config.headers,\n ...(extra ?? {}),\n };\n if (config.apiKey) headers['X-API-Key'] = config.apiKey;\n return headers;\n}\n", "import type { ResolvedConfig } from './types';\nimport { buildHeaders } from './config';\n\nexport class HttpError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: string,\n public readonly retryAfterMs?: number,\n ) {\n super(`HTTP ${status}: ${body.slice(0, 200)}`);\n this.name = 'HttpError';\n }\n}\n\ninterface RequestOptions {\n method: 'POST' | 'DELETE' | 'GET';\n path: string;\n body?: unknown;\n query?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * \u041E\u0434\u043D\u043E\u043A\u0440\u0430\u0442\u043D\u044B\u0439 HTTP-\u0437\u0430\u043F\u0440\u043E\u0441 \u0431\u0435\u0437 retry-\u043B\u043E\u0433\u0438\u043A\u0438.\n *\n * \u041E\u0441\u043E\u0431\u0435\u043D\u043D\u043E\u0441\u0442\u0438:\n * - \u0442\u0430\u0439\u043C\u0430\u0443\u0442 \u0447\u0435\u0440\u0435\u0437 `AbortController`, \u0434\u0435\u0444\u043E\u043B\u0442 8 \u0441\n * - non-2xx \u043E\u0442\u0432\u0435\u0442 \u2192 `HttpError` \u0441 \u0440\u0430\u0441\u043F\u0430\u0440\u0441\u0435\u043D\u043D\u044B\u043C `Retry-After`\n * - \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 `application/json` \u0438 text-\u043E\u0442\u0432\u0435\u0442\u044B\n * - 204 No Content \u2192 \u0440\u0435\u0437\u043E\u043B\u0432 `undefined`\n *\n * \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u043A\u0430\u043A \u0441\u0442\u0440\u043E\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u0431\u043B\u043E\u043A \u0434\u043B\u044F `requestWithRetry`\n * \u0438 \u0434\u043B\u044F \u0441\u043B\u0443\u0447\u0430\u0435\u0432, \u0433\u0434\u0435 retry \u043D\u0435 \u043D\u0443\u0436\u0435\u043D (\u043D\u0430\u043F\u0440. \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u043D\u0430\u044F \u043E\u0442\u043C\u0435\u043D\u0430).\n */\nexport async function request<T>(\n config: ResolvedConfig,\n options: RequestOptions,\n): Promise<T> {\n const url = new URL(config.baseUrl + options.path);\n if (options.query) {\n for (const [k, v] of Object.entries(options.query))\n url.searchParams.set(k, v);\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), config.requestTimeoutMs);\n const signal = options.signal ?? controller.signal;\n\n try {\n const res = await config.fetchImpl(url.toString(), {\n method: options.method,\n headers: buildHeaders(config),\n body:\n options.body !== undefined ? JSON.stringify(options.body) : undefined,\n signal,\n });\n\n if (!res.ok) {\n const text = await safeText(res);\n const retryAfter = parseRetryAfter(res.headers.get('Retry-After'));\n throw new HttpError(res.status, text, retryAfter);\n }\n\n if (res.status === 204) return undefined as T;\n const ct = res.headers.get('content-type') ?? '';\n if (ct.includes('application/json')) return (await res.json()) as T;\n return (await safeText(res)) as unknown as T;\n }\n finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * HTTP-\u0437\u0430\u043F\u0440\u043E\u0441 \u0441 \u044D\u043A\u0441\u043F\u043E\u043D\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u043C \u0431\u044D\u043A\u043E\u0444\u0444\u043E\u043C \u0438 \u0443\u0432\u0430\u0436\u0435\u043D\u0438\u0435\u043C \u043A `Retry-After`.\n *\n * Retry-\u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044F:\n * - 429 Too Many Requests \u2192 \u0436\u0434\u0451\u043C `Retry-After` (\u0441\u0435\u043A\u0443\u043D\u0434\u044B \u0438\u043B\u0438 HTTP-date)\n * - 5xx \u2192 \u044D\u043A\u0441\u043F\u043E\u043D\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0439 \u0431\u044D\u043A\u043E\u0444\u0444 `300 * 2^attempt + jitter`, cap 10 \u0441\n * - `AbortError` / `TypeError` (\u0441\u0435\u0442\u0435\u0432\u044B\u0435) \u2192 \u0442\u043E\u0436\u0435 retry\n * - 4xx \u043A\u0440\u043E\u043C\u0435 429 \u2192 \u0441\u0440\u0430\u0437\u0443 \u0444\u0438\u043D\u0430\u043B\u044C\u043D\u044B\u0439 reject (\u0447\u0438\u043D\u0438\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E)\n *\n * \u041A\u0430\u0436\u0434\u0430\u044F \u043F\u043E\u043F\u044B\u0442\u043A\u0430 (\u0443\u0441\u043F\u0435\u0445 \u0438\u043B\u0438 \u043D\u0435\u0442) \u043F\u0440\u043E\u0445\u043E\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 `logger` \u0438 `onError`\n * \u0441 \u0443\u043A\u0430\u0437\u0430\u043D\u0438\u0435\u043C `phase` \u2014 \u044D\u0442\u043E \u0434\u0430\u0451\u0442 \u043D\u0430\u0431\u043B\u044E\u0434\u0430\u0435\u043C\u043E\u0441\u0442\u044C \u0431\u0435\u0437 \u043F\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 \u043F\u0440\u043E\u043C\u0438\u0441\u0430.\n */\nexport async function requestWithRetry<T>(\n config: ResolvedConfig,\n options: RequestOptions,\n phase: 'ingest' | 'delete',\n): Promise<T> {\n let attempt = 0;\n let lastError: unknown;\n\n while (attempt <= config.maxRetries) {\n try {\n return await request<T>(config, options);\n }\n catch (err) {\n lastError = err;\n attempt += 1;\n\n const shouldRetry = isRetryable(err) && attempt <= config.maxRetries;\n config.logger(\n shouldRetry ? 'warn' : 'error',\n `${options.method} ${options.path} failed (attempt ${attempt})`,\n err,\n );\n config.onError?.(err, { phase, attempt });\n\n if (!shouldRetry) break;\n\n const delayMs = computeBackoff(err, attempt);\n await sleep(delayMs);\n }\n }\n\n throw lastError;\n}\n\nfunction isRetryable(err: unknown): boolean {\n if (err instanceof HttpError) {\n return err.status === 429 || err.status >= 500;\n }\n if (\n err instanceof Error\n && (err.name === 'AbortError' || err.name === 'TypeError')\n ) {\n return true;\n }\n return false;\n}\n\nfunction computeBackoff(err: unknown, attempt: number): number {\n if (err instanceof HttpError && err.retryAfterMs !== undefined) {\n return err.retryAfterMs;\n }\n const base = 300;\n const jitter = Math.random() * 200;\n return Math.min(base * 2 ** (attempt - 1) + jitter, 10_000);\n}\n\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n const asSeconds = Number(header);\n if (!Number.isNaN(asSeconds)) return asSeconds * 1000;\n const asDate = Date.parse(header);\n if (!Number.isNaN(asDate)) return Math.max(asDate - Date.now(), 0);\n return undefined;\n}\n\nasync function safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n }\n catch {\n return '';\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n", "import type {\n BatchIngestRequest,\n BatchIngestResponse,\n ResolvedConfig,\n RuntimeLog,\n} from './types';\nimport { requestWithRetry } from './transport';\n\nexport class BatchQueue {\n private buffer: RuntimeLog[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private inflight: Promise<void> | null = null;\n private destroyed = false;\n\n /**\n * \u0421\u043E\u0437\u0434\u0430\u0451\u0442 \u043E\u0447\u0435\u0440\u0435\u0434\u044C \u0438, \u0435\u0441\u043B\u0438 `flushIntervalMs > 0`, \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0435\u0442\n * \u043F\u0435\u0440\u0438\u043E\u0434\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0442\u0430\u0439\u043C\u0435\u0440 \u0444\u043B\u0430\u0448\u0430. \u0422\u0430\u0439\u043C\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0442\u0438\u043A\u0430\u0442\u044C \u0434\u043E \u0442\u0435\u0445 \u043F\u043E\u0440,\n * \u043F\u043E\u043A\u0430 \u043D\u0435 \u0432\u044B\u0437\u043E\u0432\u0443\u0442 `destroy()`.\n */\n constructor(private readonly config: ResolvedConfig) {\n if (config.flushIntervalMs > 0) {\n this.timer = setInterval(() => {\n void this.flush();\n }, config.flushIntervalMs);\n }\n }\n\n /**\n * \u0422\u0435\u043A\u0443\u0449\u0435\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u0439 \u0432 \u0431\u0443\u0444\u0435\u0440\u0435 (\u0435\u0449\u0451 \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044B\u0445).\n * \u041F\u043E\u043B\u0435\u0437\u043D\u043E \u0434\u043B\u044F \u043C\u0435\u0442\u0440\u0438\u043A/\u0434\u0435\u0431\u0430\u0433\u0430.\n */\n size(): number {\n return this.buffer.length;\n }\n\n /**\n * \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0441\u043E\u0431\u044B\u0442\u0438\u044F \u0432 \u0431\u0443\u0444\u0435\u0440.\n *\n * \u0422\u0440\u0438\u0433\u0433\u0435\u0440\u044B \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u043E\u0433\u043E \u0444\u043B\u0430\u0448\u0430:\n * - \u0431\u0443\u0444\u0435\u0440 \u0434\u043E\u0441\u0442\u0438\u0433 `batchSize` \u2192 \u0441\u0440\u0430\u0437\u0443 \u0443\u0445\u043E\u0434\u0438\u0442 HTTP-\u0437\u0430\u043F\u0440\u043E\u0441\n * - \u0431\u0443\u0444\u0435\u0440 \u043F\u0440\u0435\u0432\u044B\u0441\u0438\u043B `maxQueueSize` \u2192 \u043B\u0438\u0448\u043D\u0438\u0435 **\u0441\u0442\u0430\u0440\u044B\u0435** \u0441\u043E\u0431\u044B\u0442\u0438\u044F\n * \u0434\u0440\u043E\u043F\u0430\u044E\u0442\u0441\u044F (FIFO), \u0447\u0442\u043E\u0431\u044B \u043D\u0435 \u0440\u0430\u0437\u0434\u0443\u0432\u0430\u0442\u044C \u043F\u0430\u043C\u044F\u0442\u044C \u043F\u0440\u0438 \u0441\u0431\u043E\u0435 \u0441\u0435\u0442\u0438\n *\n * \u041F\u043E\u0441\u043B\u0435 `destroy()` \u0432\u044B\u0437\u043E\u0432 \u0438\u0433\u043D\u043E\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044F.\n */\n enqueue(logs: RuntimeLog[]): void {\n if (this.destroyed) return;\n if (logs.length === 0) return;\n\n this.buffer.push(...logs);\n\n if (this.buffer.length > this.config.maxQueueSize) {\n const overflow = this.buffer.length - this.config.maxQueueSize;\n this.buffer.splice(0, overflow);\n this.config.logger(\n 'warn',\n `queue overflow; dropped ${overflow} oldest events`,\n );\n }\n\n if (this.buffer.length >= this.config.batchSize) {\n void this.flush();\n }\n }\n\n /**\n * \u0417\u0430\u0431\u0440\u0430\u0442\u044C \u0432\u0441\u0451 \u0438\u0437 \u0431\u0443\u0444\u0435\u0440\u0430 \u0438 \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u043E\u0434\u043D\u0438\u043C \u0431\u0430\u0442\u0447\u0435\u043C \u0432\n * `POST /api/runtime/ingest`.\n *\n * \u0415\u0441\u043B\u0438 \u0443\u0436\u0435 \u0435\u0441\u0442\u044C \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 in-flight \u0437\u0430\u043F\u0440\u043E\u0441 \u2014 \u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043C \u0435\u0433\u043E \u0436\u0435\n * \u043F\u0440\u043E\u043C\u0438\u0441 (\u0437\u0430\u0449\u0438\u0442\u0430 \u043E\u0442 \u043F\u0430\u0440\u0430\u043B\u043B\u0435\u043B\u044C\u043D\u044B\u0445 \u0444\u043B\u0430\u0448\u0435\u0439 \u043F\u043E \u0442\u0430\u0439\u043C\u0435\u0440\u0443 \u0438 \u043F\u043E \u0440\u0430\u0437\u043C\u0435\u0440\u0443).\n *\n * \u041E\u0448\u0438\u0431\u043A\u0438 HTTP/\u0441\u0435\u0442\u0438 \u0441\u044E\u0434\u0430 \u043D\u0435 \u0432\u0441\u043F\u043B\u044B\u0432\u0430\u044E\u0442 \u2014 \u043E\u043D\u0438 \u043F\u0440\u043E\u0433\u043B\u0430\u0442\u044B\u0432\u0430\u044E\u0442\u0441\u044F\n * \u043F\u043E\u0441\u043B\u0435 \u0432\u0441\u0435\u0445 retry-\u043F\u043E\u043F\u044B\u0442\u043E\u043A \u0438 \u043B\u043E\u0433\u0438\u0440\u0443\u044E\u0442\u0441\u044F \u043A\u0430\u043A 'error'. \u0414\u0440\u043E\u043F\n * \u0446\u0435\u043B\u043E\u0433\u043E \u0431\u0430\u0442\u0447\u0430 \u043F\u0440\u0438 \u043E\u043A\u043E\u043D\u0447\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u043C \u0444\u0435\u0439\u043B\u0435 \u2014 \u043E\u0441\u043E\u0437\u043D\u0430\u043D\u043D\u044B\u0439 \u043A\u043E\u043C\u043F\u0440\u043E\u043C\u0438\u0441\u0441:\n * \u043B\u0443\u0447\u0448\u0435 \u043F\u043E\u0442\u0435\u0440\u044F\u0442\u044C \u0447\u0430\u0441\u0442\u044C \u0442\u0435\u043B\u0435\u043C\u0435\u0442\u0440\u0438\u0438, \u0447\u0435\u043C \u0437\u0430\u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043E\u0447\u0435\u0440\u0435\u0434\u044C.\n */\n async flush(): Promise<void> {\n if (this.destroyed) return;\n if (this.buffer.length === 0) return;\n if (this.inflight) return this.inflight;\n\n const batch = this.buffer.splice(0, this.buffer.length);\n\n this.inflight = (async () => {\n try {\n const body: BatchIngestRequest = { logs: batch };\n const res = await requestWithRetry<BatchIngestResponse>(\n this.config,\n { method: 'POST', path: '/api/runtime/ingest', body },\n 'ingest',\n );\n this.config.logger('debug', `flushed ${batch.length} logs`, res);\n }\n catch (err) {\n this.config.logger(\n 'error',\n `flush failed; dropping ${batch.length} logs`,\n err,\n );\n }\n finally {\n this.inflight = null;\n }\n })();\n\n return this.inflight;\n }\n\n /**\n * \u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0431\u0443\u0444\u0435\u0440 \u0447\u0435\u0440\u0435\u0437 `navigator.sendBeacon` \u043F\u0440\u0438 \u0437\u0430\u043A\u0440\u044B\u0442\u0438\u0438 \u0432\u043A\u043B\u0430\u0434\u043A\u0438.\n *\n * \u0412 \u043E\u0442\u043B\u0438\u0447\u0438\u0435 \u043E\u0442 \u043E\u0431\u044B\u0447\u043D\u043E\u0433\u043E `flush()`:\n * - fire-and-forget: \u043D\u0435\u0442 \u043E\u0442\u0432\u0435\u0442\u0430 \u0438 \u043D\u0435\u0442 retry\n * - \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0433\u0430\u0440\u0430\u043D\u0442\u0438\u0440\u0443\u0435\u0442 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0443 \u0434\u0430\u0436\u0435 \u043F\u043E\u0441\u043B\u0435 \u0442\u043E\u0433\u043E \u043A\u0430\u043A \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430\n * \u0443\u0436\u0435 \u0443\u043D\u0438\u0447\u0442\u043E\u0436\u0430\u0435\u0442\u0441\u044F (unload / pagehide)\n * - \u043D\u0435\u0442 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430 `X-API-Key` (sendBeacon \u043D\u0435 \u0434\u0430\u0451\u0442 \u043C\u0435\u043D\u044F\u0442\u044C headers,\n * \u043D\u043E `Content-Type` \u043D\u0430\u043C \u0432\u044B\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442 \u0441\u0430\u043C \u0442\u0438\u043F Blob)\n *\n * \u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 `true` \u0435\u0441\u043B\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043F\u0440\u0438\u043D\u044F\u043B \u043F\u0430\u0447\u043A\u0443 \u0432 \u0441\u0432\u043E\u044E \u043E\u0447\u0435\u0440\u0435\u0434\u044C,\n * `false` \u043F\u0440\u0438 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 API \u0438\u043B\u0438 \u043E\u0442\u043A\u0430\u0437\u0435 (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 \u0441\u043B\u0438\u0448\u043A\u043E\u043C\n * \u0431\u043E\u043B\u044C\u0448\u043E\u0439 payload \u2014 \u043B\u0438\u043C\u0438\u0442 \u043E\u0431\u044B\u0447\u043D\u043E 64 \u041A\u0411).\n */\n flushBeacon(): boolean {\n if (this.destroyed) return false;\n if (this.buffer.length === 0) return true;\n if (\n typeof navigator === 'undefined'\n || typeof navigator.sendBeacon !== 'function'\n ) {\n return false;\n }\n\n const batch = this.buffer.splice(0, this.buffer.length);\n const body: BatchIngestRequest = { logs: batch };\n const blob = new Blob([JSON.stringify(body)], { type: 'application/json' });\n const url = `${this.config.baseUrl}/api/runtime/ingest`;\n const ok = navigator.sendBeacon(url, blob);\n if (!ok)\n this.config.logger('warn', `sendBeacon rejected ${batch.length} logs`);\n return ok;\n }\n\n /**\n * \u041E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043E\u0447\u0435\u0440\u0435\u0434\u044C \u0438 \u043E\u0441\u0432\u043E\u0431\u043E\u0434\u0438\u0442\u044C \u0440\u0435\u0441\u0443\u0440\u0441\u044B.\n *\n * \u0427\u0438\u0441\u0442\u0438\u0442 \u0442\u0430\u0439\u043C\u0435\u0440 \u0444\u043B\u0430\u0448\u0430, \u043E\u0431\u043D\u0443\u043B\u044F\u0435\u0442 \u0431\u0443\u0444\u0435\u0440, \u043F\u043E\u043C\u0435\u0447\u0430\u0435\u0442 \u0438\u043D\u0441\u0442\u0430\u043D\u0441\n * \u0443\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D\u043D\u044B\u043C \u2014 \u043F\u043E\u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0435 `enqueue`/`flush`/`flushBeacon`\n * \u0441\u0442\u0430\u043D\u043E\u0432\u044F\u0442\u0441\u044F no-op. \u0418\u0434\u0435\u043C\u043F\u043E\u0442\u0435\u043D\u0442\u043D\u0430.\n *\n * \u0412\u0430\u0436\u043D\u043E: in-flight \u0437\u0430\u043F\u0440\u043E\u0441, \u0435\u0441\u043B\u0438 \u043E\u043D \u0431\u044B\u043B \u0437\u0430\u043F\u0443\u0449\u0435\u043D \u0434\u043E `destroy`,\n * \u043D\u0435 \u043E\u0442\u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F \u2014 \u043E\u043D \u043B\u0438\u0431\u043E \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044F \u0448\u0442\u0430\u0442\u043D\u043E, \u043B\u0438\u0431\u043E \u043F\u043E \u0442\u0430\u0439\u043C\u0430\u0443\u0442\u0443\n * `requestTimeoutMs`.\n */\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.buffer = [];\n }\n}\n", "import type {\n DeleteLogsFilter,\n DeleteLogsResponse,\n ResolvedConfig,\n RuntimeClient,\n RuntimeClientConfig,\n RuntimeLog,\n} from './types';\nimport { resolveConfig } from './config';\nimport { BatchQueue } from './queue';\nimport { requestWithRetry } from './transport';\n\n/**\n * \u0421\u043E\u0437\u0434\u0430\u0451\u0442 \u0438 \u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 singleton-\u0438\u043D\u0441\u0442\u0430\u043D\u0441 \u043A\u043B\u0438\u0435\u043D\u0442\u0430 \u0434\u043B\u044F \u0440\u0430\u0431\u043E\u0442\u044B \u0441\n * runtime-\u044D\u043D\u0434\u043F\u043E\u0438\u043D\u0442\u0430\u043C\u0438 MCP Contract Intelligence \u0441\u0435\u0440\u0432\u0435\u0440\u0430.\n *\n * \u0412\u044B\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u043E\u0434\u0438\u043D \u0440\u0430\u0437 \u043F\u0440\u0438 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0440\u043E\u043D\u0442\u0430. \u041F\u043E\u043B\u0443\u0447\u0435\u043D\u043D\u044B\u0439 \u0438\u043D\u0441\u0442\u0430\u043D\u0441\n * \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u0432\u043E \u0432\u0441\u0451\u043C \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0438 \u0434\u043B\u044F \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438 runtime-\u043B\u043E\u0433\u043E\u0432 (REST/WS)\n * \u0438 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u043D\u0430\u043A\u043E\u043F\u043B\u0435\u043D\u043D\u044B\u0445 \u043B\u043E\u0433\u043E\u0432 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.\n *\n * \u0412\u043D\u0443\u0442\u0440\u0438:\n * - \u043D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u0443\u0435\u0442 \u043A\u043E\u043D\u0444\u0438\u0433 \u0438 \u0432\u044B\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442 \u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u0434\u0435\u0444\u043E\u043B\u0442\u044B\n * - \u043F\u043E\u0434\u043D\u0438\u043C\u0430\u0435\u0442 \u0432\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044E\u044E \u043E\u0447\u0435\u0440\u0435\u0434\u044C-\u0431\u0430\u0442\u0447\u0435\u0440 (interval + size triggers)\n * - \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 `pagehide` / `beforeunload` listener'\u044B \u0434\u043B\u044F\n * \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0431\u0430\u0442\u0447\u0430 \u0447\u0435\u0440\u0435\u0437 `navigator.sendBeacon`\n *\n * SDK \u043D\u0435 \u0431\u0440\u043E\u0441\u0430\u0435\u0442 \u043E\u0448\u0438\u0431\u043A\u0438 \u043D\u0430\u0440\u0443\u0436\u0443 \u043F\u0440\u0438 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0430\u0445 \u0441\u0435\u0442\u0438/\u043B\u0438\u043C\u0438\u0442\u043E\u0432 \u2014\n * \u0432\u0441\u0451 \u0443\u0445\u043E\u0434\u0438\u0442 \u0432 `logger` \u0438 `onError`, \u0447\u0442\u043E\u0431\u044B \u043D\u0435 \u0440\u043E\u043D\u044F\u0442\u044C \u043F\u0440\u043E\u0434.\n */\nexport function createRuntimeClient(\n rawConfig: RuntimeClientConfig,\n): RuntimeClient {\n const config: ResolvedConfig = resolveConfig(rawConfig);\n const queue = new BatchQueue(config);\n\n let enabled = config.enabled;\n let unloadHandler: (() => void) | null = null;\n\n if (\n config.flushOnUnload\n && typeof window !== 'undefined'\n && typeof window.addEventListener === 'function'\n ) {\n unloadHandler = () => {\n queue.flushBeacon();\n };\n window.addEventListener('pagehide', unloadHandler);\n window.addEventListener('beforeunload', unloadHandler);\n }\n\n const client: RuntimeClient = {\n /**\n * \u041F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u043E\u0434\u043D\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u0435 \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u044C \u043D\u0430 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0443.\n *\n * \u041D\u0435 \u0434\u0435\u043B\u0430\u0435\u0442 HTTP-\u0437\u0430\u043F\u0440\u043E\u0441 \u0441\u0440\u0430\u0437\u0443: \u0441\u043E\u0431\u044B\u0442\u0438\u0435 \u043F\u043E\u043F\u0430\u0434\u0430\u0435\u0442 \u0432 \u0431\u0430\u0442\u0447 \u0438 \u0443\u0439\u0434\u0451\u0442\n * \u043B\u0438\u0431\u043E \u043F\u0440\u0438 \u0434\u043E\u0441\u0442\u0438\u0436\u0435\u043D\u0438\u0438 `batchSize`, \u043B\u0438\u0431\u043E \u043F\u043E \u0442\u0430\u0439\u043C\u0435\u0440\u0443 `flushIntervalMs`,\n * \u043B\u0438\u0431\u043E \u043F\u0440\u0438 \u0437\u0430\u043A\u0440\u044B\u0442\u0438\u0438 \u0432\u043A\u043B\u0430\u0434\u043A\u0438 (`sendBeacon`).\n *\n * \u0415\u0441\u043B\u0438 \u043A\u043B\u0438\u0435\u043D\u0442 \u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D (`enabled=false`) \u2014 \u0432\u044B\u0437\u043E\u0432 \u0438\u0433\u043D\u043E\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044F.\n */\n track(log: RuntimeLog) {\n if (!enabled) return;\n queue.enqueue([log]);\n },\n\n /**\n * \u041F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0441\u0440\u0430\u0437\u0443 \u043F\u0430\u0447\u043A\u0443 \u0441\u043E\u0431\u044B\u0442\u0438\u0439 \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u044C.\n *\n * \u0423\u0434\u043E\u0431\u043D\u043E \u043A\u043E\u0433\u0434\u0430 \u043D\u0430\u0431\u0440\u0430\u043B\u0438 \u0441\u043E\u0431\u044B\u0442\u0438\u044F \u0433\u0434\u0435-\u0442\u043E \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u043E (interceptor,\n * \u0431\u0443\u0444\u0435\u0440 \u0432 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0435 \u0438 \u0442.\u043F.) \u0438 \u0445\u043E\u0442\u0438\u043C \u043E\u0442\u0434\u0430\u0442\u044C \u0438\u0445 \u0432\u0441\u0435 \u0440\u0430\u0437\u043E\u043C.\n * \u0415\u0441\u043B\u0438 \u0438\u0442\u043E\u0433\u043E\u0432\u044B\u0439 \u0440\u0430\u0437\u043C\u0435\u0440 \u043E\u0447\u0435\u0440\u0435\u0434\u0438 \u043F\u0440\u0435\u0432\u044B\u0441\u0438\u043B `maxQueueSize` \u2014\n * \u0441\u0442\u0430\u0440\u044B\u0435 \u0441\u043E\u0431\u044B\u0442\u0438\u044F \u0431\u0443\u0434\u0443\u0442 \u0432\u044B\u0431\u0440\u043E\u0448\u0435\u043D\u044B (FIFO drop).\n */\n trackMany(logs: RuntimeLog[]) {\n if (!enabled) return;\n queue.enqueue(logs);\n },\n\n /**\n * \u041F\u0440\u0438\u043D\u0443\u0434\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0432\u0441\u0451 \u0447\u0442\u043E \u0441\u0435\u0439\u0447\u0430\u0441 \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u0438.\n *\n * \u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043F\u0440\u043E\u043C\u0438\u0441, \u0440\u0435\u0437\u043E\u043B\u0432\u044F\u0449\u0438\u0439\u0441\u044F \u043F\u043E\u0441\u043B\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F HTTP-\u0437\u0430\u043F\u0440\u043E\u0441\u0430\n * (\u0443\u0441\u043F\u0435\u0448\u043D\u043E\u0433\u043E \u0438\u043B\u0438 \u043D\u0435\u0442 \u2014 SDK \u043F\u0440\u043E\u0433\u043B\u0430\u0442\u044B\u0432\u0430\u0435\u0442 \u043E\u0448\u0438\u0431\u043A\u0438). \u041F\u043E\u043B\u0435\u0437\u043D\u043E \u043F\u0435\u0440\u0435\u0434\n * \u043A\u0440\u0438\u0442\u0438\u0447\u043D\u044B\u043C\u0438 \u043F\u0435\u0440\u0435\u0445\u043E\u0434\u0430\u043C\u0438: logout, route change, submit \u0444\u043E\u0440\u043C\u044B.\n *\n * \u0415\u0441\u043B\u0438 \u043E\u0447\u0435\u0440\u0435\u0434\u044C \u043F\u0443\u0441\u0442\u0430 \u0438\u043B\u0438 \u043A\u043B\u0438\u0435\u043D\u0442 \u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D \u2014 no-op.\n */\n async flush() {\n if (!enabled) return;\n await queue.flush();\n },\n\n /**\n * \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043D\u0430\u043A\u043E\u043F\u043B\u0435\u043D\u043D\u044B\u0435 runtime-\u043B\u043E\u0433\u0438 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043F\u043E \u0444\u0438\u043B\u044C\u0442\u0440\u0443.\n *\n * \u0412 \u043E\u0442\u043B\u0438\u0447\u0438\u0435 \u043E\u0442 `track`, \u0438\u0434\u0451\u0442 \u043D\u0430\u043F\u0440\u044F\u043C\u0443\u044E \u0432 `DELETE /api/runtime/logs`\n * \u0431\u0435\u0437 \u043E\u0447\u0435\u0440\u0435\u0434\u0438 \u0438 \u0431\u0430\u0442\u0447\u0438\u043D\u0433\u0430 \u2014 \u044D\u0442\u043E \u043D\u0438\u0437\u043A\u043E\u0447\u0430\u0441\u0442\u043E\u0442\u043D\u0430\u044F \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043D\u0430\u044F\n * \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F.\n *\n * \u0424\u0438\u043B\u044C\u0442\u0440 \u2014 \u0434\u0438\u0441\u043A\u0440\u0438\u043C\u0438\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 union:\n * - REST: `{ service, type: 'rest', path, method }`\n * - WS: `{ service, type: 'ws', event }`\n *\n * \u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 `{ deleted: N }`. \u041F\u0440\u0438 \u0441\u0435\u0442\u0435\u0432\u043E\u0439 \u043E\u0448\u0438\u0431\u043A\u0435/5xx/429\n * \u043F\u0440\u043E\u0438\u0437\u043E\u0439\u0434\u0451\u0442 \u0434\u043E `maxRetries` \u043F\u043E\u0432\u0442\u043E\u0440\u043E\u0432 \u0441 \u0431\u044D\u043A\u043E\u0444\u0444\u043E\u043C.\n */\n async deleteLogs(filter: DeleteLogsFilter): Promise<DeleteLogsResponse> {\n const query = toDeleteQuery(filter);\n return requestWithRetry<DeleteLogsResponse>(\n config,\n { method: 'DELETE', path: '/api/runtime/logs', query },\n 'delete',\n );\n },\n\n /**\n * \u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043A\u0443\u0449\u0435\u0435 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0444\u043B\u0430\u0433\u0430 `enabled`.\n *\n * \u041F\u0440\u0438\u0433\u043E\u0434\u0438\u0442\u0441\u044F \u0434\u043B\u044F \u0434\u0435\u0432-\u0442\u0443\u043B\u0437\u043E\u0432/\u043E\u0442\u043B\u0430\u0434\u043E\u0447\u043D\u044B\u0445 \u043F\u0430\u043D\u0435\u043B\u0435\u0439, \u0433\u0434\u0435 \u0432\u0438\u0434\u043D\u043E\n * \u0430\u043A\u0442\u0438\u0432\u0435\u043D \u043B\u0438 \u0441\u0431\u043E\u0440 \u0442\u0435\u043B\u0435\u043C\u0435\u0442\u0440\u0438\u0438 \u0432 \u0440\u0430\u043D\u0442\u0430\u0439\u043C\u0435.\n */\n isEnabled() {\n return enabled;\n },\n\n /**\n * \u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C/\u0432\u044B\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0441\u0431\u043E\u0440 \u0441\u043E\u0431\u044B\u0442\u0438\u0439 \u043D\u0430 \u0445\u043E\u0434\u0443.\n *\n * \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u0434\u043B\u044F opt-out \u043F\u043E \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u044E \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F (cookie consent),\n * \u0434\u043B\u044F \u0432\u0440\u0435\u043C\u0435\u043D\u043D\u043E\u0433\u043E \u043E\u0442\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \u043F\u0440\u0438 \u0438\u043D\u0446\u0438\u0434\u0435\u043D\u0442\u0430\u0445, \u0438\u043B\u0438 \u0434\u043B\u044F \u0442\u043E\u0447\u0435\u0447\u043D\u043E\u0433\u043E\n * \u0432\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \u0447\u0435\u0440\u0435\u0437 debug-\u043F\u0430\u043D\u0435\u043B\u044C.\n *\n * \u0412\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u043D\u0435 \u0447\u0438\u0441\u0442\u0438\u0442 \u0443\u0436\u0435 \u043D\u0430\u043A\u043E\u043F\u043B\u0435\u043D\u043D\u0443\u044E \u043E\u0447\u0435\u0440\u0435\u0434\u044C \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442\n * \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0442\u044C \u043D\u043E\u0432\u044B\u0435 \u0441\u043E\u0431\u044B\u0442\u0438\u044F. \u041F\u043E\u043B\u043D\u044B\u0439 \u0441\u0431\u0440\u043E\u0441 \u2014 \u0447\u0435\u0440\u0435\u0437 `destroy()`.\n */\n setEnabled(next: boolean) {\n enabled = next;\n config.logger('debug', `enabled=${next}`);\n },\n\n /**\n * \u041F\u043E\u043B\u043D\u043E\u0441\u0442\u044C\u044E \u043E\u0441\u0432\u043E\u0431\u043E\u0434\u0438\u0442\u044C \u0440\u0435\u0441\u0443\u0440\u0441\u044B \u043A\u043B\u0438\u0435\u043D\u0442\u0430.\n *\n * \u041E\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u0442 \u0442\u0430\u0439\u043C\u0435\u0440 \u0444\u043B\u0430\u0448\u0430, \u043E\u0442\u043F\u0438\u0441\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u043E\u0442 `pagehide`/\n * `beforeunload`, \u043E\u0447\u0438\u0449\u0430\u0435\u0442 \u0431\u0443\u0444\u0435\u0440. \u041F\u043E\u0432\u0442\u043E\u0440\u043D\u044B\u0435 \u0432\u044B\u0437\u043E\u0432\u044B \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u044B.\n *\n * \u041E\u0431\u044B\u0447\u043D\u043E \u043D\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u2014 \u043A\u043B\u0438\u0435\u043D\u0442 \u0436\u0438\u0432\u0451\u0442 \u0432\u0441\u0451 \u0432\u0440\u0435\u043C\u044F \u0436\u0438\u0437\u043D\u0438 \u0432\u043A\u043B\u0430\u0434\u043A\u0438.\n * \u041F\u043E\u043B\u0435\u0437\u043D\u043E \u0432 SSR/\u0442\u0435\u0441\u0442\u0430\u0445 \u0438 \u043F\u0440\u0438 hot-reload'\u0435 \u043D\u0430 \u0434\u0435\u0432\u0435, \u0447\u0442\u043E\u0431\u044B \u043D\u0435\n * \u043F\u043B\u043E\u0434\u0438\u0442\u044C \u0434\u0443\u0431\u043B\u0438\u043A\u0430\u0442\u044B listener'\u043E\u0432.\n */\n destroy() {\n if (unloadHandler && typeof window !== 'undefined') {\n window.removeEventListener('pagehide', unloadHandler);\n window.removeEventListener('beforeunload', unloadHandler);\n unloadHandler = null;\n }\n queue.destroy();\n },\n };\n\n return client;\n}\n\n/**\n * \u041F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0434\u0438\u0441\u043A\u0440\u0438\u043C\u0438\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0444\u0438\u043B\u044C\u0442\u0440 \u0432 \u043F\u043B\u043E\u0441\u043A\u0438\u0439 query-\u043E\u0431\u044A\u0435\u043A\u0442\n * \u0434\u043B\u044F `URLSearchParams`.\n *\n * \u0421\u0435\u0440\u0432\u0435\u0440\u043D\u044B\u0439 zod-union (`DeleteRestFilterSchema | DeleteWsFilterSchema`)\n * \u043E\u0436\u0438\u0434\u0430\u0435\u0442 \u0440\u0430\u0437\u043D\u044B\u0435 \u043D\u0430\u0431\u043E\u0440\u044B \u043F\u043E\u043B\u0435\u0439 \u2014 \u0442\u0443\u0442 \u043D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u0443\u0435\u043C \u043F\u043E\u0434 \u043D\u0443\u0436\u043D\u044B\u0439 \u0432\u0430\u0440\u0438\u0430\u043D\u0442.\n */\nfunction toDeleteQuery(filter: DeleteLogsFilter): Record<string, string> {\n if (filter.type === 'rest') {\n return {\n service: filter.service,\n type: 'rest',\n path: filter.path,\n method: filter.method,\n };\n }\n return {\n service: filter.service,\n type: 'ws',\n event: filter.event,\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|