@burdenoff/be-sdk 2026.1015.2 → 2026.1017.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-N2UT3ESH.js +1506 -0
- package/dist/chunk-N2UT3ESH.js.map +1 -0
- package/dist/index-DfYu1p9e.d.ts +530 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.js +2 -1
- package/package.json +1 -1
- package/dist/chunk-Z5BURBFZ.js +0 -694
- package/dist/chunk-Z5BURBFZ.js.map +0 -1
- package/dist/index-PJZzGd8r.d.ts +0 -324
package/dist/chunk-Z5BURBFZ.js
DELETED
|
@@ -1,694 +0,0 @@
|
|
|
1
|
-
import { logger } from './chunk-RU266375.js';
|
|
2
|
-
import { __export, __name } from './chunk-XE4OXN2W.js';
|
|
3
|
-
|
|
4
|
-
// src/platform/index.ts
|
|
5
|
-
var platform_exports = {};
|
|
6
|
-
__export(platform_exports, {
|
|
7
|
-
CircuitBreakerOpenError: () => CircuitBreakerOpenError,
|
|
8
|
-
DEFAULT_GRAPHQL_PAGE_LIMIT: () => DEFAULT_GRAPHQL_PAGE_LIMIT,
|
|
9
|
-
LLMRouter: () => LLMRouter,
|
|
10
|
-
MAX_GRAPHQL_PAGE_LIMIT: () => MAX_GRAPHQL_PAGE_LIMIT,
|
|
11
|
-
__resetHttpClientBreakers: () => __resetHttpClientBreakers,
|
|
12
|
-
buildCacheKey: () => buildCacheKey,
|
|
13
|
-
buildConnection: () => buildConnection,
|
|
14
|
-
buildLoaders: () => buildLoaders,
|
|
15
|
-
buildOffsetPage: () => buildOffsetPage,
|
|
16
|
-
clampGraphqlLimit: () => clampGraphqlLimit,
|
|
17
|
-
clampLimit: () => clampLimit,
|
|
18
|
-
clampOffset: () => clampOffset,
|
|
19
|
-
createHttpClient: () => createHttpClient,
|
|
20
|
-
createLeaderLease: () => createLeaderLease,
|
|
21
|
-
decodeCursor: () => decodeCursor,
|
|
22
|
-
dropOldPartitions: () => dropOldPartitions,
|
|
23
|
-
encodeCursor: () => encodeCursor,
|
|
24
|
-
ensureMonthlyPartitions: () => ensureMonthlyPartitions,
|
|
25
|
-
getNamespaceVersion: () => getNamespaceVersion,
|
|
26
|
-
httpClient: () => httpClient,
|
|
27
|
-
invalidateNamespace: () => invalidateNamespace,
|
|
28
|
-
monthlyPartitionName: () => monthlyPartitionName,
|
|
29
|
-
normalizeCursorPagination: () => normalizeCursorPagination,
|
|
30
|
-
normalizeOffsetPagination: () => normalizeOffsetPagination,
|
|
31
|
-
normalizeRedisUrl: () => normalizeRedisUrl,
|
|
32
|
-
paginate: () => paginate,
|
|
33
|
-
rateLimitIncr: () => rateLimitIncr,
|
|
34
|
-
resolveReferenceLoader: () => resolveReferenceLoader,
|
|
35
|
-
toPrismaPage: () => toPrismaPage,
|
|
36
|
-
withLeaderLock: () => withLeaderLock
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// src/platform/httpClient.ts
|
|
40
|
-
var breakers = /* @__PURE__ */ new Map();
|
|
41
|
-
function hostOf(url) {
|
|
42
|
-
try {
|
|
43
|
-
return new URL(url).host;
|
|
44
|
-
} catch {
|
|
45
|
-
return url;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
__name(hostOf, "hostOf");
|
|
49
|
-
function getBreaker(host) {
|
|
50
|
-
let b = breakers.get(host);
|
|
51
|
-
if (!b) {
|
|
52
|
-
b = {
|
|
53
|
-
failures: 0,
|
|
54
|
-
openedAt: null,
|
|
55
|
-
state: "CLOSED"
|
|
56
|
-
};
|
|
57
|
-
breakers.set(host, b);
|
|
58
|
-
}
|
|
59
|
-
return b;
|
|
60
|
-
}
|
|
61
|
-
__name(getBreaker, "getBreaker");
|
|
62
|
-
function defaultRetryOn(status) {
|
|
63
|
-
return status === 408 || status === 425 || status === 429 || status >= 500 && status <= 599;
|
|
64
|
-
}
|
|
65
|
-
__name(defaultRetryOn, "defaultRetryOn");
|
|
66
|
-
function jitter(delay) {
|
|
67
|
-
return Math.floor(Math.random() * delay);
|
|
68
|
-
}
|
|
69
|
-
__name(jitter, "jitter");
|
|
70
|
-
function sleep(ms) {
|
|
71
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
72
|
-
}
|
|
73
|
-
__name(sleep, "sleep");
|
|
74
|
-
var CircuitBreakerOpenError = class extends Error {
|
|
75
|
-
static {
|
|
76
|
-
__name(this, "CircuitBreakerOpenError");
|
|
77
|
-
}
|
|
78
|
-
constructor(host) {
|
|
79
|
-
super(`circuit breaker OPEN for host=${host}`);
|
|
80
|
-
this.name = "CircuitBreakerOpenError";
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
function __resetHttpClientBreakers() {
|
|
84
|
-
breakers.clear();
|
|
85
|
-
}
|
|
86
|
-
__name(__resetHttpClientBreakers, "__resetHttpClientBreakers");
|
|
87
|
-
async function executeOnce(url, init, timeoutMs) {
|
|
88
|
-
const signal = init.signal ?? AbortSignal.timeout(timeoutMs);
|
|
89
|
-
return fetch(url, {
|
|
90
|
-
...init,
|
|
91
|
-
signal
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
__name(executeOnce, "executeOnce");
|
|
95
|
-
async function httpClient(url, init = {}, config = {}) {
|
|
96
|
-
const fullUrl = config.baseUrl && !/^https?:\/\//i.test(url) ? `${config.baseUrl.replace(/\/$/, "")}/${url.replace(/^\//, "")}` : url;
|
|
97
|
-
const host = hostOf(fullUrl);
|
|
98
|
-
const breaker = getBreaker(host);
|
|
99
|
-
const breakerThreshold = config.breaker?.threshold ?? 5;
|
|
100
|
-
const cooldownMs = config.breaker?.cooldownMs ?? 3e4;
|
|
101
|
-
if (breaker.state === "OPEN") {
|
|
102
|
-
if (breaker.openedAt && Date.now() - breaker.openedAt >= cooldownMs) {
|
|
103
|
-
breaker.state = "HALF_OPEN";
|
|
104
|
-
logger.info("httpClient.breaker.halfOpen", {
|
|
105
|
-
host
|
|
106
|
-
});
|
|
107
|
-
} else {
|
|
108
|
-
throw new CircuitBreakerOpenError(host);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const attempts = init.retry?.attempts ?? config.retry?.attempts ?? 3;
|
|
112
|
-
const initialDelay = init.retry?.initialDelayMs ?? config.retry?.initialDelayMs ?? 100;
|
|
113
|
-
const maxDelay = init.retry?.maxDelayMs ?? config.retry?.maxDelayMs ?? 2e3;
|
|
114
|
-
const retryOn = init.retry?.retryOn ?? config.retry?.retryOn ?? defaultRetryOn;
|
|
115
|
-
const timeoutMs = init.timeoutMs ?? config.defaultTimeoutMs ?? 5e3;
|
|
116
|
-
const headers = {
|
|
117
|
-
...config.defaultHeaders ?? {},
|
|
118
|
-
...init.headers ?? {}
|
|
119
|
-
};
|
|
120
|
-
let lastErr;
|
|
121
|
-
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
122
|
-
try {
|
|
123
|
-
const response = await executeOnce(fullUrl, {
|
|
124
|
-
...init,
|
|
125
|
-
headers
|
|
126
|
-
}, timeoutMs);
|
|
127
|
-
if (response.status >= 500) {
|
|
128
|
-
breaker.failures += 1;
|
|
129
|
-
if (breaker.failures >= breakerThreshold) {
|
|
130
|
-
breaker.state = "OPEN";
|
|
131
|
-
breaker.openedAt = Date.now();
|
|
132
|
-
logger.warn("httpClient.breaker.open", {
|
|
133
|
-
host,
|
|
134
|
-
failures: breaker.failures
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
if (attempt < attempts && retryOn(response.status)) {
|
|
138
|
-
const delay = Math.min(initialDelay * 2 ** (attempt - 1), maxDelay);
|
|
139
|
-
await sleep(jitter(delay));
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
return response;
|
|
143
|
-
}
|
|
144
|
-
breaker.failures = 0;
|
|
145
|
-
if (breaker.state === "HALF_OPEN") {
|
|
146
|
-
breaker.state = "CLOSED";
|
|
147
|
-
breaker.openedAt = null;
|
|
148
|
-
logger.info("httpClient.breaker.closed", {
|
|
149
|
-
host
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
if (attempt < attempts && retryOn(response.status)) {
|
|
153
|
-
const delay = Math.min(initialDelay * 2 ** (attempt - 1), maxDelay);
|
|
154
|
-
await sleep(jitter(delay));
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
return response;
|
|
158
|
-
} catch (err) {
|
|
159
|
-
lastErr = err;
|
|
160
|
-
breaker.failures += 1;
|
|
161
|
-
if (breaker.failures >= breakerThreshold) {
|
|
162
|
-
breaker.state = "OPEN";
|
|
163
|
-
breaker.openedAt = Date.now();
|
|
164
|
-
logger.warn("httpClient.breaker.open", {
|
|
165
|
-
host,
|
|
166
|
-
failures: breaker.failures
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
if (attempt >= attempts) break;
|
|
170
|
-
const delay = Math.min(initialDelay * 2 ** (attempt - 1), maxDelay);
|
|
171
|
-
await sleep(jitter(delay));
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
logger.error("httpClient.exhausted", {
|
|
175
|
-
url: fullUrl,
|
|
176
|
-
attempts,
|
|
177
|
-
host
|
|
178
|
-
});
|
|
179
|
-
throw lastErr instanceof Error ? lastErr : new Error(`httpClient failed: ${String(lastErr)}`);
|
|
180
|
-
}
|
|
181
|
-
__name(httpClient, "httpClient");
|
|
182
|
-
function createHttpClient(config = {}) {
|
|
183
|
-
return (url, init = {}) => httpClient(url, init, config);
|
|
184
|
-
}
|
|
185
|
-
__name(createHttpClient, "createHttpClient");
|
|
186
|
-
|
|
187
|
-
// src/platform/leaderLock.ts
|
|
188
|
-
var RELEASE_LUA = `
|
|
189
|
-
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
190
|
-
return redis.call("del", KEYS[1])
|
|
191
|
-
else
|
|
192
|
-
return 0
|
|
193
|
-
end
|
|
194
|
-
`;
|
|
195
|
-
var RENEW_LUA = `
|
|
196
|
-
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
197
|
-
return redis.call("pexpire", KEYS[1], ARGV[2])
|
|
198
|
-
else
|
|
199
|
-
return 0
|
|
200
|
-
end
|
|
201
|
-
`;
|
|
202
|
-
function leaderKey(name) {
|
|
203
|
-
return `besdk:leader:${name}`;
|
|
204
|
-
}
|
|
205
|
-
__name(leaderKey, "leaderKey");
|
|
206
|
-
function generateToken() {
|
|
207
|
-
return `${Date.now()}-${Math.random().toString(36).slice(2)}-${process.pid}`;
|
|
208
|
-
}
|
|
209
|
-
__name(generateToken, "generateToken");
|
|
210
|
-
function defaultRenewMs(ttlMs) {
|
|
211
|
-
return Math.max(1e3, Math.floor(ttlMs / 3));
|
|
212
|
-
}
|
|
213
|
-
__name(defaultRenewMs, "defaultRenewMs");
|
|
214
|
-
async function acquireLease(redis, key, token, ttlMs) {
|
|
215
|
-
const ttlSeconds = Math.max(1, Math.ceil(ttlMs / 1e3));
|
|
216
|
-
return await redis.set(key, token, "EX", ttlSeconds, "NX") === "OK";
|
|
217
|
-
}
|
|
218
|
-
__name(acquireLease, "acquireLease");
|
|
219
|
-
async function renewLease(redis, key, token, ttlMs) {
|
|
220
|
-
return await redis.eval(RENEW_LUA, 1, key, token, String(ttlMs)) === 1;
|
|
221
|
-
}
|
|
222
|
-
__name(renewLease, "renewLease");
|
|
223
|
-
async function releaseLease(redis, key, token) {
|
|
224
|
-
await redis.eval(RELEASE_LUA, 1, key, token);
|
|
225
|
-
}
|
|
226
|
-
__name(releaseLease, "releaseLease");
|
|
227
|
-
function normalizeRedisUrl(url) {
|
|
228
|
-
if (url.startsWith("valkeys://")) return url.replace(/^valkeys:\/\//, "rediss://");
|
|
229
|
-
if (url.startsWith("valkey://")) return url.replace(/^valkey:\/\//, "redis://");
|
|
230
|
-
return url;
|
|
231
|
-
}
|
|
232
|
-
__name(normalizeRedisUrl, "normalizeRedisUrl");
|
|
233
|
-
async function withLeaderLock(redis, name, fn, options) {
|
|
234
|
-
const key = leaderKey(name);
|
|
235
|
-
const token = generateToken();
|
|
236
|
-
const ttlMs = options.ttlMs;
|
|
237
|
-
const renewMs = options.renewMs ?? defaultRenewMs(ttlMs);
|
|
238
|
-
const acquired = await acquireLease(redis, key, token, ttlMs);
|
|
239
|
-
if (!acquired) {
|
|
240
|
-
return {
|
|
241
|
-
acquired: false
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
logger.info("leaderLock.acquired", {
|
|
245
|
-
name,
|
|
246
|
-
token,
|
|
247
|
-
ttlMs
|
|
248
|
-
});
|
|
249
|
-
let stopped = false;
|
|
250
|
-
const renewTimer = setInterval(() => {
|
|
251
|
-
if (stopped) return;
|
|
252
|
-
renewLease(redis, key, token, ttlMs).catch((err) => {
|
|
253
|
-
logger.warn("leaderLock.renew.failed", {
|
|
254
|
-
name,
|
|
255
|
-
err: String(err)
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
}, renewMs);
|
|
259
|
-
if (typeof renewTimer.unref === "function") {
|
|
260
|
-
renewTimer.unref();
|
|
261
|
-
}
|
|
262
|
-
try {
|
|
263
|
-
const result = await fn();
|
|
264
|
-
return {
|
|
265
|
-
acquired: true,
|
|
266
|
-
result
|
|
267
|
-
};
|
|
268
|
-
} finally {
|
|
269
|
-
stopped = true;
|
|
270
|
-
clearInterval(renewTimer);
|
|
271
|
-
try {
|
|
272
|
-
await releaseLease(redis, key, token);
|
|
273
|
-
logger.info("leaderLock.released", {
|
|
274
|
-
name,
|
|
275
|
-
token
|
|
276
|
-
});
|
|
277
|
-
} catch (err) {
|
|
278
|
-
logger.warn("leaderLock.release.failed", {
|
|
279
|
-
name,
|
|
280
|
-
err: String(err)
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
__name(withLeaderLock, "withLeaderLock");
|
|
286
|
-
function createLeaderLease(options) {
|
|
287
|
-
const { name, ttlMs, redis } = options;
|
|
288
|
-
const key = leaderKey(name);
|
|
289
|
-
const token = generateToken();
|
|
290
|
-
const renewMs = options.renewMs ?? defaultRenewMs(ttlMs);
|
|
291
|
-
let held = false;
|
|
292
|
-
let released = false;
|
|
293
|
-
let inFlight = null;
|
|
294
|
-
const acquireOrRenew = /* @__PURE__ */ __name(async () => {
|
|
295
|
-
if (released) return false;
|
|
296
|
-
try {
|
|
297
|
-
if (held) {
|
|
298
|
-
if (await renewLease(redis, key, token, ttlMs)) {
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
held = false;
|
|
302
|
-
}
|
|
303
|
-
const acquired = await acquireLease(redis, key, token, ttlMs);
|
|
304
|
-
if (acquired && !held) {
|
|
305
|
-
logger.info("leaderLease.acquired", {
|
|
306
|
-
name,
|
|
307
|
-
token,
|
|
308
|
-
ttlMs
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
held = acquired;
|
|
312
|
-
return held;
|
|
313
|
-
} catch (err) {
|
|
314
|
-
logger.warn("leaderLease.renew.failed", {
|
|
315
|
-
name,
|
|
316
|
-
err: String(err)
|
|
317
|
-
});
|
|
318
|
-
return held;
|
|
319
|
-
}
|
|
320
|
-
}, "acquireOrRenew");
|
|
321
|
-
const runAttempt = /* @__PURE__ */ __name(() => {
|
|
322
|
-
if (inFlight) return inFlight;
|
|
323
|
-
const attempt = acquireOrRenew().finally(() => {
|
|
324
|
-
if (inFlight === attempt) inFlight = null;
|
|
325
|
-
});
|
|
326
|
-
inFlight = attempt;
|
|
327
|
-
return attempt;
|
|
328
|
-
}, "runAttempt");
|
|
329
|
-
const timer = setInterval(() => {
|
|
330
|
-
if (released) return;
|
|
331
|
-
void runAttempt();
|
|
332
|
-
}, renewMs);
|
|
333
|
-
if (typeof timer.unref === "function") {
|
|
334
|
-
timer.unref();
|
|
335
|
-
}
|
|
336
|
-
return {
|
|
337
|
-
renew() {
|
|
338
|
-
return runAttempt();
|
|
339
|
-
},
|
|
340
|
-
async release() {
|
|
341
|
-
if (released) return;
|
|
342
|
-
released = true;
|
|
343
|
-
clearInterval(timer);
|
|
344
|
-
if (inFlight) {
|
|
345
|
-
try {
|
|
346
|
-
await inFlight;
|
|
347
|
-
} catch {
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
if (!held) return;
|
|
351
|
-
held = false;
|
|
352
|
-
try {
|
|
353
|
-
await releaseLease(redis, key, token);
|
|
354
|
-
logger.info("leaderLease.released", {
|
|
355
|
-
name,
|
|
356
|
-
token
|
|
357
|
-
});
|
|
358
|
-
} catch (err) {
|
|
359
|
-
logger.warn("leaderLease.release.failed", {
|
|
360
|
-
name,
|
|
361
|
-
err: String(err)
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
},
|
|
365
|
-
isHeld() {
|
|
366
|
-
return held && !released;
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
__name(createLeaderLease, "createLeaderLease");
|
|
371
|
-
|
|
372
|
-
// src/platform/rateLimit.ts
|
|
373
|
-
async function rateLimitIncr(redis, input) {
|
|
374
|
-
const fullKey = `besdk:rl:${input.key}`;
|
|
375
|
-
const count = await redis.incr(fullKey);
|
|
376
|
-
if (count === 1) {
|
|
377
|
-
await redis.pexpire(fullKey, input.windowMs);
|
|
378
|
-
}
|
|
379
|
-
let ttl = -1;
|
|
380
|
-
try {
|
|
381
|
-
ttl = await redis.pttl(fullKey);
|
|
382
|
-
} catch {
|
|
383
|
-
ttl = input.windowMs;
|
|
384
|
-
}
|
|
385
|
-
const resetAt = Date.now() + (ttl > 0 ? ttl : input.windowMs);
|
|
386
|
-
const remaining = Math.max(0, input.limit - count);
|
|
387
|
-
return {
|
|
388
|
-
allowed: count <= input.limit,
|
|
389
|
-
count,
|
|
390
|
-
remaining,
|
|
391
|
-
resetAt
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
__name(rateLimitIncr, "rateLimitIncr");
|
|
395
|
-
|
|
396
|
-
// src/platform/paginator.ts
|
|
397
|
-
var DEFAULT_GRAPHQL_PAGE_LIMIT = 50;
|
|
398
|
-
var MAX_GRAPHQL_PAGE_LIMIT = 100;
|
|
399
|
-
function clampLimit(input, opts = {}) {
|
|
400
|
-
const def = opts.defaultLimit ?? 50;
|
|
401
|
-
const max = opts.maxLimit ?? 200;
|
|
402
|
-
const min = opts.minLimit ?? 1;
|
|
403
|
-
if (input == null || Number.isNaN(input)) return def;
|
|
404
|
-
return Math.min(Math.max(Math.floor(input), min), max);
|
|
405
|
-
}
|
|
406
|
-
__name(clampLimit, "clampLimit");
|
|
407
|
-
function clampOffset(input) {
|
|
408
|
-
if (input == null || Number.isNaN(input)) return 0;
|
|
409
|
-
return Math.max(0, Math.floor(input));
|
|
410
|
-
}
|
|
411
|
-
__name(clampOffset, "clampOffset");
|
|
412
|
-
function clampGraphqlLimit(input, opts = {}) {
|
|
413
|
-
return clampLimit(input, {
|
|
414
|
-
defaultLimit: opts.defaultLimit ?? DEFAULT_GRAPHQL_PAGE_LIMIT,
|
|
415
|
-
maxLimit: opts.maxLimit ?? MAX_GRAPHQL_PAGE_LIMIT,
|
|
416
|
-
minLimit: opts.minLimit ?? 1
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
__name(clampGraphqlLimit, "clampGraphqlLimit");
|
|
420
|
-
function normalizeOffsetPagination(input, opts = {}) {
|
|
421
|
-
return {
|
|
422
|
-
limit: clampGraphqlLimit(input?.limit, opts),
|
|
423
|
-
offset: clampOffset(input?.offset)
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
__name(normalizeOffsetPagination, "normalizeOffsetPagination");
|
|
427
|
-
function normalizeCursorPagination(input, opts = {}) {
|
|
428
|
-
const first = clampGraphqlLimit(input?.first, opts);
|
|
429
|
-
const after = typeof input?.after === "string" && input.after.trim().length > 0 ? input.after : null;
|
|
430
|
-
return {
|
|
431
|
-
first,
|
|
432
|
-
after,
|
|
433
|
-
take: first + 1
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
__name(normalizeCursorPagination, "normalizeCursorPagination");
|
|
437
|
-
function encodeCursor(payload) {
|
|
438
|
-
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
439
|
-
}
|
|
440
|
-
__name(encodeCursor, "encodeCursor");
|
|
441
|
-
function decodeCursor(cursor) {
|
|
442
|
-
if (typeof cursor !== "string" || cursor.trim().length === 0) return null;
|
|
443
|
-
try {
|
|
444
|
-
const decoded = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
|
|
445
|
-
if (decoded == null || typeof decoded !== "object" || Array.isArray(decoded)) return null;
|
|
446
|
-
const payload = {};
|
|
447
|
-
for (const [key, value] of Object.entries(decoded)) {
|
|
448
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value == null) {
|
|
449
|
-
payload[key] = value;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
return Object.keys(payload).length > 0 ? payload : null;
|
|
453
|
-
} catch {
|
|
454
|
-
return null;
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
__name(decodeCursor, "decodeCursor");
|
|
458
|
-
function buildConnection(items, opts) {
|
|
459
|
-
const nodes = items.length > opts.limit ? items.slice(0, opts.limit) : items;
|
|
460
|
-
const edges = nodes.map((node) => ({
|
|
461
|
-
node,
|
|
462
|
-
cursor: opts.cursorForNode(node)
|
|
463
|
-
}));
|
|
464
|
-
const firstEdge = edges[0];
|
|
465
|
-
const lastEdge = edges.at(-1);
|
|
466
|
-
return {
|
|
467
|
-
edges,
|
|
468
|
-
nodes,
|
|
469
|
-
pageInfo: {
|
|
470
|
-
hasNextPage: items.length > opts.limit,
|
|
471
|
-
hasPreviousPage: opts.hasPreviousPage ?? false,
|
|
472
|
-
startCursor: firstEdge?.cursor ?? null,
|
|
473
|
-
endCursor: lastEdge?.cursor ?? null
|
|
474
|
-
},
|
|
475
|
-
totalCount: opts.totalCount
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
__name(buildConnection, "buildConnection");
|
|
479
|
-
function buildOffsetPage(items, total, pagination) {
|
|
480
|
-
const nextOffset = pagination.offset + items.length;
|
|
481
|
-
const hasMore = nextOffset < total;
|
|
482
|
-
return {
|
|
483
|
-
items,
|
|
484
|
-
total,
|
|
485
|
-
limit: pagination.limit,
|
|
486
|
-
offset: pagination.offset,
|
|
487
|
-
hasMore,
|
|
488
|
-
nextOffset: hasMore ? nextOffset : null
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
__name(buildOffsetPage, "buildOffsetPage");
|
|
492
|
-
function toPrismaPage(pagination) {
|
|
493
|
-
return {
|
|
494
|
-
take: pagination.limit,
|
|
495
|
-
skip: pagination.offset
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
__name(toPrismaPage, "toPrismaPage");
|
|
499
|
-
async function paginate(model, input, opts = {}) {
|
|
500
|
-
const take = clampGraphqlLimit(input.take ?? void 0, opts);
|
|
501
|
-
const items = await model.findMany({
|
|
502
|
-
take: take + 1,
|
|
503
|
-
skip: input.cursor ? 1 : 0,
|
|
504
|
-
cursor: input.cursor ? {
|
|
505
|
-
id: input.cursor
|
|
506
|
-
} : void 0,
|
|
507
|
-
where: input.where,
|
|
508
|
-
orderBy: input.orderBy
|
|
509
|
-
});
|
|
510
|
-
const hasMore = items.length > take;
|
|
511
|
-
const trimmed = hasMore ? items.slice(0, take) : items;
|
|
512
|
-
const nextCursor = hasMore && trimmed.length > 0 ? trimmed[trimmed.length - 1].id : null;
|
|
513
|
-
return {
|
|
514
|
-
items: trimmed,
|
|
515
|
-
hasMore,
|
|
516
|
-
nextCursor
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
__name(paginate, "paginate");
|
|
520
|
-
|
|
521
|
-
// src/platform/dataLoaderFactory.ts
|
|
522
|
-
function buildLoaders(ctx, builder) {
|
|
523
|
-
return builder(ctx);
|
|
524
|
-
}
|
|
525
|
-
__name(buildLoaders, "buildLoaders");
|
|
526
|
-
function resolveReferenceLoader(loaderName, keyField = "id") {
|
|
527
|
-
return async (reference, ctx) => {
|
|
528
|
-
const loader = ctx.loaders[loaderName];
|
|
529
|
-
if (!loader) {
|
|
530
|
-
throw new Error(`resolveReferenceLoader: loader "${loaderName}" not found on ctx.loaders`);
|
|
531
|
-
}
|
|
532
|
-
const key = reference[keyField];
|
|
533
|
-
if (typeof key !== "string") {
|
|
534
|
-
return null;
|
|
535
|
-
}
|
|
536
|
-
return loader.load(key);
|
|
537
|
-
};
|
|
538
|
-
}
|
|
539
|
-
__name(resolveReferenceLoader, "resolveReferenceLoader");
|
|
540
|
-
|
|
541
|
-
// src/platform/cacheInvalidation.ts
|
|
542
|
-
var VERSION_PREFIX = "besdk:cv:";
|
|
543
|
-
async function getNamespaceVersion(redis, namespace) {
|
|
544
|
-
const v = await redis.get(`${VERSION_PREFIX}${namespace}`);
|
|
545
|
-
if (!v) return 1;
|
|
546
|
-
const n = Number.parseInt(v, 10);
|
|
547
|
-
return Number.isFinite(n) && n > 0 ? n : 1;
|
|
548
|
-
}
|
|
549
|
-
__name(getNamespaceVersion, "getNamespaceVersion");
|
|
550
|
-
async function buildCacheKey(redis, namespace, ...parts) {
|
|
551
|
-
const ver = await getNamespaceVersion(redis, namespace);
|
|
552
|
-
return `${namespace}:v${ver}:${parts.join(":")}`;
|
|
553
|
-
}
|
|
554
|
-
__name(buildCacheKey, "buildCacheKey");
|
|
555
|
-
async function invalidateNamespace(redis, namespace) {
|
|
556
|
-
return redis.incr(`${VERSION_PREFIX}${namespace}`);
|
|
557
|
-
}
|
|
558
|
-
__name(invalidateNamespace, "invalidateNamespace");
|
|
559
|
-
|
|
560
|
-
// src/platform/pgPartition.ts
|
|
561
|
-
function pad2(n) {
|
|
562
|
-
return n < 10 ? `0${n}` : `${n}`;
|
|
563
|
-
}
|
|
564
|
-
__name(pad2, "pad2");
|
|
565
|
-
function monthlyPartitionName(table, year, month) {
|
|
566
|
-
return `${table}_y${year}m${pad2(month)}`;
|
|
567
|
-
}
|
|
568
|
-
__name(monthlyPartitionName, "monthlyPartitionName");
|
|
569
|
-
async function ensureMonthlyPartitions(prisma, opts) {
|
|
570
|
-
const created = [];
|
|
571
|
-
const cur = new Date(Date.UTC(opts.from.getUTCFullYear(), opts.from.getUTCMonth(), 1));
|
|
572
|
-
const end = new Date(Date.UTC(opts.to.getUTCFullYear(), opts.to.getUTCMonth(), 1));
|
|
573
|
-
while (cur <= end) {
|
|
574
|
-
const y = cur.getUTCFullYear();
|
|
575
|
-
const m = cur.getUTCMonth() + 1;
|
|
576
|
-
const next = new Date(Date.UTC(y, m, 1));
|
|
577
|
-
const partition = monthlyPartitionName(opts.table, y, m);
|
|
578
|
-
const lower = `${y}-${pad2(m)}-01`;
|
|
579
|
-
const upper = `${next.getUTCFullYear()}-${pad2(next.getUTCMonth() + 1)}-01`;
|
|
580
|
-
await prisma.$executeRawUnsafe(`CREATE TABLE IF NOT EXISTS "${partition}" PARTITION OF "${opts.table}" FOR VALUES FROM ('${lower}') TO ('${upper}');`);
|
|
581
|
-
created.push(partition);
|
|
582
|
-
cur.setUTCMonth(cur.getUTCMonth() + 1);
|
|
583
|
-
}
|
|
584
|
-
return created;
|
|
585
|
-
}
|
|
586
|
-
__name(ensureMonthlyPartitions, "ensureMonthlyPartitions");
|
|
587
|
-
async function dropOldPartitions(prisma, opts) {
|
|
588
|
-
const rows = await prisma.$queryRawUnsafe(`SELECT child.relname AS partition_name
|
|
589
|
-
FROM pg_inherits
|
|
590
|
-
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
|
|
591
|
-
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
|
|
592
|
-
WHERE parent.relname = $1`, opts.table);
|
|
593
|
-
const dropped = [];
|
|
594
|
-
const cutoffYear = opts.beforeDate.getUTCFullYear();
|
|
595
|
-
const cutoffMonth = opts.beforeDate.getUTCMonth() + 1;
|
|
596
|
-
for (const row of rows) {
|
|
597
|
-
const partitionRe = /_y(\d{4})m(\d{2})$/;
|
|
598
|
-
const m = partitionRe.exec(row.partition_name);
|
|
599
|
-
if (!m) continue;
|
|
600
|
-
const y = Number(m[1]);
|
|
601
|
-
const mo = Number(m[2]);
|
|
602
|
-
if (y < cutoffYear || y === cutoffYear && mo < cutoffMonth) {
|
|
603
|
-
await prisma.$executeRawUnsafe(`DROP TABLE IF EXISTS "${row.partition_name}";`);
|
|
604
|
-
dropped.push(row.partition_name);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
return dropped;
|
|
608
|
-
}
|
|
609
|
-
__name(dropOldPartitions, "dropOldPartitions");
|
|
610
|
-
|
|
611
|
-
// src/platform/llmClient.ts
|
|
612
|
-
var DEFAULTS = {
|
|
613
|
-
timeoutMs: 3e4,
|
|
614
|
-
maxAttempts: 3,
|
|
615
|
-
initialDelayMs: 500,
|
|
616
|
-
maxOutputTokensCap: 4096
|
|
617
|
-
};
|
|
618
|
-
function jitter2(n) {
|
|
619
|
-
return Math.floor(Math.random() * n);
|
|
620
|
-
}
|
|
621
|
-
__name(jitter2, "jitter");
|
|
622
|
-
function sleep2(ms) {
|
|
623
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
624
|
-
}
|
|
625
|
-
__name(sleep2, "sleep");
|
|
626
|
-
var LLMRouter = class {
|
|
627
|
-
static {
|
|
628
|
-
__name(this, "LLMRouter");
|
|
629
|
-
}
|
|
630
|
-
adapters = /* @__PURE__ */ new Map();
|
|
631
|
-
opts;
|
|
632
|
-
constructor(opts = {}) {
|
|
633
|
-
this.opts = {
|
|
634
|
-
...DEFAULTS,
|
|
635
|
-
...opts
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
register(adapter) {
|
|
639
|
-
this.adapters.set(adapter.name, adapter);
|
|
640
|
-
}
|
|
641
|
-
resolveChain() {
|
|
642
|
-
const envChain = process.env["LLM_PROVIDER_CHAIN"]?.trim();
|
|
643
|
-
if (envChain) {
|
|
644
|
-
return envChain.split(",").map((s) => s.trim()).filter(Boolean);
|
|
645
|
-
}
|
|
646
|
-
return Array.from(this.adapters.keys());
|
|
647
|
-
}
|
|
648
|
-
async complete(req) {
|
|
649
|
-
const cappedReq = {
|
|
650
|
-
...req,
|
|
651
|
-
maxTokens: Math.min(req.maxTokens ?? this.opts.maxOutputTokensCap, this.opts.maxOutputTokensCap)
|
|
652
|
-
};
|
|
653
|
-
const chain = this.resolveChain();
|
|
654
|
-
if (chain.length === 0) {
|
|
655
|
-
throw new Error("LLMRouter: no providers registered");
|
|
656
|
-
}
|
|
657
|
-
let lastErr = null;
|
|
658
|
-
for (let attempt = 0; attempt < this.opts.maxAttempts; attempt++) {
|
|
659
|
-
const providerName = chain[attempt % chain.length];
|
|
660
|
-
const adapter = providerName ? this.adapters.get(providerName) : void 0;
|
|
661
|
-
if (!adapter) {
|
|
662
|
-
logger.warn("llmRouter.provider.notRegistered", {
|
|
663
|
-
providerName
|
|
664
|
-
});
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
const timeoutMs = req.timeoutMs ?? this.opts.timeoutMs;
|
|
668
|
-
const ctrl = new AbortController();
|
|
669
|
-
const t = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
670
|
-
try {
|
|
671
|
-
const response = await adapter.complete(cappedReq, ctrl.signal);
|
|
672
|
-
return response;
|
|
673
|
-
} catch (err) {
|
|
674
|
-
lastErr = err;
|
|
675
|
-
logger.warn("llmRouter.attempt.failed", {
|
|
676
|
-
provider: adapter.name,
|
|
677
|
-
attempt,
|
|
678
|
-
err: String(err)
|
|
679
|
-
});
|
|
680
|
-
if (attempt < this.opts.maxAttempts - 1) {
|
|
681
|
-
const delay = this.opts.initialDelayMs * 2 ** attempt;
|
|
682
|
-
await sleep2(jitter2(delay));
|
|
683
|
-
}
|
|
684
|
-
} finally {
|
|
685
|
-
clearTimeout(t);
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
throw lastErr instanceof Error ? lastErr : new Error(`LLMRouter exhausted ${this.opts.maxAttempts} attempts`);
|
|
689
|
-
}
|
|
690
|
-
};
|
|
691
|
-
|
|
692
|
-
export { CircuitBreakerOpenError, DEFAULT_GRAPHQL_PAGE_LIMIT, LLMRouter, MAX_GRAPHQL_PAGE_LIMIT, __resetHttpClientBreakers, buildCacheKey, buildConnection, buildLoaders, buildOffsetPage, clampGraphqlLimit, clampLimit, clampOffset, createHttpClient, createLeaderLease, decodeCursor, dropOldPartitions, encodeCursor, ensureMonthlyPartitions, getNamespaceVersion, httpClient, invalidateNamespace, monthlyPartitionName, normalizeCursorPagination, normalizeOffsetPagination, normalizeRedisUrl, paginate, platform_exports, rateLimitIncr, resolveReferenceLoader, toPrismaPage, withLeaderLock };
|
|
693
|
-
//# sourceMappingURL=chunk-Z5BURBFZ.js.map
|
|
694
|
-
//# sourceMappingURL=chunk-Z5BURBFZ.js.map
|