@jeffusion/bungee-core 2.4.0 → 3.0.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/dist/master.js +489 -39
- package/dist/worker.js +6693 -3509
- package/package.json +9 -3
package/dist/master.js
CHANGED
|
@@ -4,25 +4,43 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
function __accessProp(key) {
|
|
8
|
+
return this[key];
|
|
9
|
+
}
|
|
10
|
+
var __toESMCache_node;
|
|
11
|
+
var __toESMCache_esm;
|
|
7
12
|
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
+
var canCache = mod != null && typeof mod === "object";
|
|
14
|
+
if (canCache) {
|
|
15
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
+
var cached = cache.get(mod);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
8
20
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
21
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
22
|
for (let key of __getOwnPropNames(mod))
|
|
11
23
|
if (!__hasOwnProp.call(to, key))
|
|
12
24
|
__defProp(to, key, {
|
|
13
|
-
get: (
|
|
25
|
+
get: __accessProp.bind(mod, key),
|
|
14
26
|
enumerable: true
|
|
15
27
|
});
|
|
28
|
+
if (canCache)
|
|
29
|
+
cache.set(mod, to);
|
|
16
30
|
return to;
|
|
17
31
|
};
|
|
18
32
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
33
|
+
var __returnValue = (v) => v;
|
|
34
|
+
function __exportSetter(name, newValue) {
|
|
35
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
36
|
+
}
|
|
19
37
|
var __export = (target, all) => {
|
|
20
38
|
for (var name in all)
|
|
21
39
|
__defProp(target, name, {
|
|
22
40
|
get: all[name],
|
|
23
41
|
enumerable: true,
|
|
24
42
|
configurable: true,
|
|
25
|
-
set: (
|
|
43
|
+
set: __exportSetter.bind(all, name)
|
|
26
44
|
});
|
|
27
45
|
};
|
|
28
46
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -566,7 +584,7 @@ var require_colors = __commonJS((exports, module) => {
|
|
|
566
584
|
colors.stripColors = colors.strip = function(str) {
|
|
567
585
|
return ("" + str).replace(/\x1B\[\d+m/g, "");
|
|
568
586
|
};
|
|
569
|
-
var stylize = colors.stylize = function
|
|
587
|
+
var stylize = colors.stylize = function stylize2(str, style) {
|
|
570
588
|
if (!colors.enabled) {
|
|
571
589
|
return str + "";
|
|
572
590
|
}
|
|
@@ -584,8 +602,8 @@ var require_colors = __commonJS((exports, module) => {
|
|
|
584
602
|
return str.replace(matchOperatorsRe, "\\$&");
|
|
585
603
|
};
|
|
586
604
|
function build(_styles) {
|
|
587
|
-
var builder = function
|
|
588
|
-
return applyStyle.apply(
|
|
605
|
+
var builder = function builder2() {
|
|
606
|
+
return applyStyle.apply(builder2, arguments);
|
|
589
607
|
};
|
|
590
608
|
builder._styles = _styles;
|
|
591
609
|
builder.__proto__ = proto;
|
|
@@ -604,7 +622,7 @@ var require_colors = __commonJS((exports, module) => {
|
|
|
604
622
|
});
|
|
605
623
|
return ret;
|
|
606
624
|
}();
|
|
607
|
-
var proto = defineProps(function
|
|
625
|
+
var proto = defineProps(function colors2() {}, styles);
|
|
608
626
|
function applyStyle() {
|
|
609
627
|
var args = Array.prototype.slice.call(arguments);
|
|
610
628
|
var str = args.map(function(arg) {
|
|
@@ -663,7 +681,7 @@ var require_colors = __commonJS((exports, module) => {
|
|
|
663
681
|
});
|
|
664
682
|
return ret;
|
|
665
683
|
}
|
|
666
|
-
var sequencer = function
|
|
684
|
+
var sequencer = function sequencer2(map2, str) {
|
|
667
685
|
var exploded = str.split("");
|
|
668
686
|
exploded = exploded.map(map2);
|
|
669
687
|
return exploded.join("");
|
|
@@ -3389,28 +3407,28 @@ var require_end_of_stream = __commonJS((exports, module) => {
|
|
|
3389
3407
|
callback = once(callback || noop);
|
|
3390
3408
|
var readable = opts.readable || opts.readable !== false && stream.readable;
|
|
3391
3409
|
var writable = opts.writable || opts.writable !== false && stream.writable;
|
|
3392
|
-
var onlegacyfinish = function
|
|
3410
|
+
var onlegacyfinish = function onlegacyfinish2() {
|
|
3393
3411
|
if (!stream.writable)
|
|
3394
3412
|
onfinish();
|
|
3395
3413
|
};
|
|
3396
3414
|
var writableEnded = stream._writableState && stream._writableState.finished;
|
|
3397
|
-
var onfinish = function
|
|
3415
|
+
var onfinish = function onfinish2() {
|
|
3398
3416
|
writable = false;
|
|
3399
3417
|
writableEnded = true;
|
|
3400
3418
|
if (!readable)
|
|
3401
3419
|
callback.call(stream);
|
|
3402
3420
|
};
|
|
3403
3421
|
var readableEnded = stream._readableState && stream._readableState.endEmitted;
|
|
3404
|
-
var onend = function
|
|
3422
|
+
var onend = function onend2() {
|
|
3405
3423
|
readable = false;
|
|
3406
3424
|
readableEnded = true;
|
|
3407
3425
|
if (!writable)
|
|
3408
3426
|
callback.call(stream);
|
|
3409
3427
|
};
|
|
3410
|
-
var onerror = function
|
|
3428
|
+
var onerror = function onerror2(err) {
|
|
3411
3429
|
callback.call(stream, err);
|
|
3412
3430
|
};
|
|
3413
|
-
var onclose = function
|
|
3431
|
+
var onclose = function onclose2() {
|
|
3414
3432
|
var err;
|
|
3415
3433
|
if (readable && !readableEnded) {
|
|
3416
3434
|
if (!stream._readableState || !stream._readableState.ended)
|
|
@@ -3423,7 +3441,7 @@ var require_end_of_stream = __commonJS((exports, module) => {
|
|
|
3423
3441
|
return callback.call(stream, err);
|
|
3424
3442
|
}
|
|
3425
3443
|
};
|
|
3426
|
-
var onrequest = function
|
|
3444
|
+
var onrequest = function onrequest2() {
|
|
3427
3445
|
stream.req.on("finish", onfinish);
|
|
3428
3446
|
};
|
|
3429
3447
|
if (isRequest(stream)) {
|
|
@@ -3580,7 +3598,7 @@ var require_async_iterator = __commonJS((exports, module) => {
|
|
|
3580
3598
|
});
|
|
3581
3599
|
});
|
|
3582
3600
|
}), _Object$setPrototypeO), AsyncIteratorPrototype);
|
|
3583
|
-
var createReadableStreamAsyncIterator = function
|
|
3601
|
+
var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator2(stream) {
|
|
3584
3602
|
var _Object$create;
|
|
3585
3603
|
var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, {
|
|
3586
3604
|
value: stream,
|
|
@@ -3769,7 +3787,7 @@ var require__stream_readable = __commonJS((exports, module) => {
|
|
|
3769
3787
|
var Duplex;
|
|
3770
3788
|
Readable.ReadableState = ReadableState;
|
|
3771
3789
|
var EE = __require("events").EventEmitter;
|
|
3772
|
-
var EElistenerCount = function
|
|
3790
|
+
var EElistenerCount = function EElistenerCount2(emitter, type) {
|
|
3773
3791
|
return emitter.listeners(type).length;
|
|
3774
3792
|
};
|
|
3775
3793
|
var Stream = __require("stream");
|
|
@@ -3786,7 +3804,7 @@ var require__stream_readable = __commonJS((exports, module) => {
|
|
|
3786
3804
|
if (debugUtil && debugUtil.debuglog) {
|
|
3787
3805
|
debug = debugUtil.debuglog("stream");
|
|
3788
3806
|
} else {
|
|
3789
|
-
debug = function
|
|
3807
|
+
debug = function debug2() {};
|
|
3790
3808
|
}
|
|
3791
3809
|
var BufferList = require_buffer_list();
|
|
3792
3810
|
var destroyImpl = require_destroy();
|
|
@@ -4732,7 +4750,7 @@ var require__stream_writable = __commonJS((exports, module) => {
|
|
|
4732
4750
|
}
|
|
4733
4751
|
});
|
|
4734
4752
|
} else {
|
|
4735
|
-
realHasInstance = function
|
|
4753
|
+
realHasInstance = function realHasInstance2(object) {
|
|
4736
4754
|
return object instanceof this;
|
|
4737
4755
|
};
|
|
4738
4756
|
}
|
|
@@ -5110,7 +5128,7 @@ var require_modern = __commonJS((exports, module) => {
|
|
|
5110
5128
|
var util = __require("util");
|
|
5111
5129
|
var Writable = require__stream_writable();
|
|
5112
5130
|
var { LEVEL } = require_triple_beam();
|
|
5113
|
-
var TransportStream = module.exports = function
|
|
5131
|
+
var TransportStream = module.exports = function TransportStream2(options = {}) {
|
|
5114
5132
|
Writable.call(this, { objectMode: true, highWaterMark: options.highWaterMark });
|
|
5115
5133
|
this.format = options.format;
|
|
5116
5134
|
this.level = options.level;
|
|
@@ -5221,7 +5239,7 @@ var require_legacy = __commonJS((exports, module) => {
|
|
|
5221
5239
|
var util = __require("util");
|
|
5222
5240
|
var { LEVEL } = require_triple_beam();
|
|
5223
5241
|
var TransportStream = require_modern();
|
|
5224
|
-
var LegacyTransportStream = module.exports = function
|
|
5242
|
+
var LegacyTransportStream = module.exports = function LegacyTransportStream2(options = {}) {
|
|
5225
5243
|
TransportStream.call(this, options);
|
|
5226
5244
|
if (!options.transport || typeof options.transport.log !== "function") {
|
|
5227
5245
|
throw new Error("Invalid transport, must be an object with a log method.");
|
|
@@ -7739,7 +7757,7 @@ var require_index_cjs = __commonJS((exports, module) => {
|
|
|
7739
7757
|
function getDefaultExportFromCjs(x) {
|
|
7740
7758
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
7741
7759
|
}
|
|
7742
|
-
var textHex = function
|
|
7760
|
+
var textHex = function hex2(str) {
|
|
7743
7761
|
for (var i = 0, hash = 0;i < str.length; hash = str.charCodeAt(i++) + ((hash << 5) - hash))
|
|
7744
7762
|
;
|
|
7745
7763
|
var color = Math.floor(Math.abs(Math.sin(hash) * 1e4 % 1 * 16777216)).toString(16);
|
|
@@ -14448,7 +14466,7 @@ var require_FileStreamRotator = __commonJS((exports, module) => {
|
|
|
14448
14466
|
return fullPath;
|
|
14449
14467
|
}, "");
|
|
14450
14468
|
};
|
|
14451
|
-
var BubbleEvents = function
|
|
14469
|
+
var BubbleEvents = function BubbleEvents2(emitter, proxy) {
|
|
14452
14470
|
emitter.on("close", function() {
|
|
14453
14471
|
proxy.emit("close");
|
|
14454
14472
|
});
|
|
@@ -15159,16 +15177,26 @@ var require_main = __commonJS((exports, module) => {
|
|
|
15159
15177
|
// src/logger.ts
|
|
15160
15178
|
import path from "path";
|
|
15161
15179
|
import fs from "fs";
|
|
15162
|
-
function createLogMethod(level) {
|
|
15180
|
+
function createLogMethod(level, defaultMeta = {}) {
|
|
15163
15181
|
return function(objOrMsg, msg) {
|
|
15164
15182
|
if (typeof objOrMsg === "string") {
|
|
15165
|
-
winstonLogger.log(level, objOrMsg);
|
|
15183
|
+
winstonLogger.log(level, objOrMsg, defaultMeta);
|
|
15166
15184
|
} else {
|
|
15167
15185
|
const message = msg || "";
|
|
15168
|
-
winstonLogger.log(level, message, objOrMsg);
|
|
15186
|
+
winstonLogger.log(level, message, { ...defaultMeta, ...objOrMsg });
|
|
15169
15187
|
}
|
|
15170
15188
|
};
|
|
15171
15189
|
}
|
|
15190
|
+
function createLogger(defaultMeta = {}) {
|
|
15191
|
+
return {
|
|
15192
|
+
info: createLogMethod("info", defaultMeta),
|
|
15193
|
+
warn: createLogMethod("warn", defaultMeta),
|
|
15194
|
+
error: createLogMethod("error", defaultMeta),
|
|
15195
|
+
debug: createLogMethod("debug", defaultMeta),
|
|
15196
|
+
fatal: createLogMethod("error", defaultMeta),
|
|
15197
|
+
child: (bindings) => createLogger({ ...defaultMeta, ...bindings })
|
|
15198
|
+
};
|
|
15199
|
+
}
|
|
15172
15200
|
var import_winston, import_winston_daily_rotate_file, import_dotenv, logsDir, logLevel, isDevelopment = true, isMaster, pinoStyleConsoleFormat, transports, winstonLogger, logger;
|
|
15173
15201
|
var init_logger = __esm(() => {
|
|
15174
15202
|
import_winston = __toESM(require_winston(), 1);
|
|
@@ -15216,13 +15244,7 @@ var init_logger = __esm(() => {
|
|
|
15216
15244
|
level: logLevel,
|
|
15217
15245
|
transports
|
|
15218
15246
|
});
|
|
15219
|
-
logger =
|
|
15220
|
-
info: createLogMethod("info"),
|
|
15221
|
-
warn: createLogMethod("warn"),
|
|
15222
|
-
error: createLogMethod("error"),
|
|
15223
|
-
debug: createLogMethod("debug"),
|
|
15224
|
-
fatal: createLogMethod("error")
|
|
15225
|
-
};
|
|
15247
|
+
logger = createLogger();
|
|
15226
15248
|
});
|
|
15227
15249
|
|
|
15228
15250
|
// src/logger/access-log-writer.ts
|
|
@@ -15233,6 +15255,7 @@ import fs2 from "fs";
|
|
|
15233
15255
|
class AccessLogWriter {
|
|
15234
15256
|
db;
|
|
15235
15257
|
writeQueue = [];
|
|
15258
|
+
pendingRespBodyIdUpdates = new Map;
|
|
15236
15259
|
isProcessing = false;
|
|
15237
15260
|
flushInterval = null;
|
|
15238
15261
|
constructor(dbPath) {
|
|
@@ -15246,6 +15269,10 @@ class AccessLogWriter {
|
|
|
15246
15269
|
this.startFlushInterval();
|
|
15247
15270
|
}
|
|
15248
15271
|
write(entry) {
|
|
15272
|
+
const pendingRespBodyId = this.pendingRespBodyIdUpdates.get(entry.requestId);
|
|
15273
|
+
if (pendingRespBodyId) {
|
|
15274
|
+
entry.respBodyId = pendingRespBodyId;
|
|
15275
|
+
}
|
|
15249
15276
|
this.writeQueue.push(entry);
|
|
15250
15277
|
if (this.writeQueue.length >= 100) {
|
|
15251
15278
|
this.flush().catch((err) => {
|
|
@@ -15276,12 +15303,19 @@ class AccessLogWriter {
|
|
|
15276
15303
|
let insertedCount = 0;
|
|
15277
15304
|
let ignoredCount = 0;
|
|
15278
15305
|
for (const entry of batch) {
|
|
15306
|
+
const pendingRespBodyId = this.pendingRespBodyIdUpdates.get(entry.requestId);
|
|
15307
|
+
if (pendingRespBodyId) {
|
|
15308
|
+
entry.respBodyId = pendingRespBodyId;
|
|
15309
|
+
}
|
|
15279
15310
|
const result = insert.run(entry.requestId, entry.timestamp, entry.method, entry.path, entry.query || null, entry.status, entry.duration, entry.routePath || null, entry.upstream || null, entry.transformer || null, entry.processingSteps ? JSON.stringify(entry.processingSteps) : null, entry.authSuccess !== undefined ? entry.authSuccess ? 1 : 0 : 1, entry.authLevel || null, entry.errorMessage || null, entry.reqBodyId || null, entry.respBodyId || null, entry.reqHeaderId || null, entry.respHeaderId || null, entry.originalReqHeaderId || null, entry.originalReqBodyId || null, entry.transformedPath || null, entry.status < 400 ? 1 : 0, Math.floor(entry.timestamp / 1000), entry.isFailoverAttempt ? 1 : 0, entry.parentRequestId || null, entry.attemptNumber || null, entry.attemptUpstream || null, entry.requestType || "final");
|
|
15280
15311
|
if (result.changes > 0) {
|
|
15281
15312
|
insertedCount++;
|
|
15282
15313
|
} else {
|
|
15283
15314
|
ignoredCount++;
|
|
15284
15315
|
}
|
|
15316
|
+
if (pendingRespBodyId) {
|
|
15317
|
+
this.pendingRespBodyIdUpdates.delete(entry.requestId);
|
|
15318
|
+
}
|
|
15285
15319
|
}
|
|
15286
15320
|
this.db.run("COMMIT");
|
|
15287
15321
|
transactionStarted = false;
|
|
@@ -15322,6 +15356,29 @@ class AccessLogWriter {
|
|
|
15322
15356
|
getDatabase() {
|
|
15323
15357
|
return this.db;
|
|
15324
15358
|
}
|
|
15359
|
+
updateResponseBodyId(requestId, respBodyId) {
|
|
15360
|
+
if (!requestId || !respBodyId) {
|
|
15361
|
+
return;
|
|
15362
|
+
}
|
|
15363
|
+
this.pendingRespBodyIdUpdates.set(requestId, respBodyId);
|
|
15364
|
+
for (const entry of this.writeQueue) {
|
|
15365
|
+
if (entry.requestId === requestId) {
|
|
15366
|
+
entry.respBodyId = respBodyId;
|
|
15367
|
+
}
|
|
15368
|
+
}
|
|
15369
|
+
try {
|
|
15370
|
+
const result = this.db.prepare("UPDATE access_logs SET resp_body_id = ? WHERE request_id = ?").run(respBodyId, requestId);
|
|
15371
|
+
if (result.changes > 0) {
|
|
15372
|
+
this.pendingRespBodyIdUpdates.delete(requestId);
|
|
15373
|
+
}
|
|
15374
|
+
} catch (error) {
|
|
15375
|
+
console.error("Failed to update response body id for streamed log:", {
|
|
15376
|
+
requestId,
|
|
15377
|
+
respBodyId,
|
|
15378
|
+
error
|
|
15379
|
+
});
|
|
15380
|
+
}
|
|
15381
|
+
}
|
|
15325
15382
|
}
|
|
15326
15383
|
var dbPath, accessLogWriter;
|
|
15327
15384
|
var init_access_log_writer = __esm(() => {
|
|
@@ -15777,6 +15834,58 @@ var init_001_initial_schema_with_failover = __esm(() => {
|
|
|
15777
15834
|
};
|
|
15778
15835
|
});
|
|
15779
15836
|
|
|
15837
|
+
// src/migrations/versions/002_add_plugin_storage.ts
|
|
15838
|
+
var migration2;
|
|
15839
|
+
var init_002_add_plugin_storage = __esm(() => {
|
|
15840
|
+
migration2 = {
|
|
15841
|
+
version: "002",
|
|
15842
|
+
name: "add_plugin_storage",
|
|
15843
|
+
up: (db) => {
|
|
15844
|
+
db.run(`
|
|
15845
|
+
CREATE TABLE IF NOT EXISTS plugin_storage (
|
|
15846
|
+
plugin_name TEXT NOT NULL,
|
|
15847
|
+
key TEXT NOT NULL,
|
|
15848
|
+
value TEXT NOT NULL,
|
|
15849
|
+
ttl INTEGER, -- \u8FC7\u671F\u65F6\u95F4\u6233\uFF08\u79D2\uFF09\uFF0CNULL \u8868\u793A\u6C38\u4E0D\u8FC7\u671F
|
|
15850
|
+
updated_at INTEGER NOT NULL,
|
|
15851
|
+
PRIMARY KEY (plugin_name, key)
|
|
15852
|
+
)
|
|
15853
|
+
`);
|
|
15854
|
+
db.run(`
|
|
15855
|
+
CREATE INDEX IF NOT EXISTS idx_plugin_storage_ttl
|
|
15856
|
+
ON plugin_storage(ttl)
|
|
15857
|
+
WHERE ttl IS NOT NULL
|
|
15858
|
+
`);
|
|
15859
|
+
}
|
|
15860
|
+
};
|
|
15861
|
+
});
|
|
15862
|
+
|
|
15863
|
+
// src/migrations/versions/003_add_plugin_registry.ts
|
|
15864
|
+
var migration3;
|
|
15865
|
+
var init_003_add_plugin_registry = __esm(() => {
|
|
15866
|
+
migration3 = {
|
|
15867
|
+
version: "003",
|
|
15868
|
+
name: "add_plugin_registry",
|
|
15869
|
+
up: (db) => {
|
|
15870
|
+
db.run(`
|
|
15871
|
+
CREATE TABLE IF NOT EXISTS plugin_registry (
|
|
15872
|
+
name TEXT PRIMARY KEY,
|
|
15873
|
+
version TEXT NOT NULL,
|
|
15874
|
+
description TEXT,
|
|
15875
|
+
path TEXT,
|
|
15876
|
+
enabled INTEGER NOT NULL DEFAULT 0,
|
|
15877
|
+
created_at INTEGER NOT NULL,
|
|
15878
|
+
updated_at INTEGER NOT NULL
|
|
15879
|
+
)
|
|
15880
|
+
`);
|
|
15881
|
+
db.run(`
|
|
15882
|
+
CREATE INDEX IF NOT EXISTS idx_plugin_registry_enabled
|
|
15883
|
+
ON plugin_registry(enabled)
|
|
15884
|
+
`);
|
|
15885
|
+
}
|
|
15886
|
+
};
|
|
15887
|
+
});
|
|
15888
|
+
|
|
15780
15889
|
// src/migrations/migration-manager.ts
|
|
15781
15890
|
import { Database as Database2 } from "bun:sqlite";
|
|
15782
15891
|
import fs5 from "fs";
|
|
@@ -15805,11 +15914,11 @@ class MigrationManager {
|
|
|
15805
15914
|
logger.info({ count: pending.length, migrations: pending.map((m) => m.name) }, "Executing pending migrations");
|
|
15806
15915
|
this.db.run("BEGIN TRANSACTION");
|
|
15807
15916
|
try {
|
|
15808
|
-
for (const
|
|
15809
|
-
logger.debug({ migration:
|
|
15810
|
-
|
|
15811
|
-
this.recordMigration(
|
|
15812
|
-
logger.info({ migration:
|
|
15917
|
+
for (const migration4 of pending) {
|
|
15918
|
+
logger.debug({ migration: migration4.name }, "Applying migration");
|
|
15919
|
+
migration4.up(this.db);
|
|
15920
|
+
this.recordMigration(migration4);
|
|
15921
|
+
logger.info({ migration: migration4.name }, "Migration applied successfully");
|
|
15813
15922
|
}
|
|
15814
15923
|
this.db.run("COMMIT");
|
|
15815
15924
|
logger.info("All migrations completed successfully");
|
|
@@ -15859,12 +15968,12 @@ class MigrationManager {
|
|
|
15859
15968
|
const appliedVersions = new Set(applied.map((r) => r.version));
|
|
15860
15969
|
return migrations.filter((m) => !appliedVersions.has(m.version));
|
|
15861
15970
|
}
|
|
15862
|
-
recordMigration(
|
|
15971
|
+
recordMigration(migration4) {
|
|
15863
15972
|
if (!this.db) {
|
|
15864
15973
|
throw new Error("Database not initialized");
|
|
15865
15974
|
}
|
|
15866
15975
|
const stmt = this.db.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)");
|
|
15867
|
-
stmt.run(
|
|
15976
|
+
stmt.run(migration4.version, migration4.name, Date.now());
|
|
15868
15977
|
}
|
|
15869
15978
|
async attemptAutoRecovery(error) {
|
|
15870
15979
|
const errorMessage = error.message.toLowerCase();
|
|
@@ -15927,9 +16036,13 @@ var init_migration_manager = __esm(() => {
|
|
|
15927
16036
|
var migrations;
|
|
15928
16037
|
var init_migrations = __esm(() => {
|
|
15929
16038
|
init_001_initial_schema_with_failover();
|
|
16039
|
+
init_002_add_plugin_storage();
|
|
16040
|
+
init_003_add_plugin_registry();
|
|
15930
16041
|
init_migration_manager();
|
|
15931
16042
|
migrations = [
|
|
15932
|
-
migration
|
|
16043
|
+
migration,
|
|
16044
|
+
migration2,
|
|
16045
|
+
migration3
|
|
15933
16046
|
];
|
|
15934
16047
|
});
|
|
15935
16048
|
|
|
@@ -16087,17 +16200,339 @@ var init_config = __esm(() => {
|
|
|
16087
16200
|
init_logger();
|
|
16088
16201
|
});
|
|
16089
16202
|
|
|
16203
|
+
// src/plugin-storage-cleanup.ts
|
|
16204
|
+
class PluginStorageCleanupService {
|
|
16205
|
+
db;
|
|
16206
|
+
config;
|
|
16207
|
+
timer = null;
|
|
16208
|
+
running = false;
|
|
16209
|
+
stats = {
|
|
16210
|
+
totalRuns: 0,
|
|
16211
|
+
totalDeleted: 0,
|
|
16212
|
+
lastRunTime: 0,
|
|
16213
|
+
lastDeletedCount: 0,
|
|
16214
|
+
lastDuration: 0
|
|
16215
|
+
};
|
|
16216
|
+
constructor(db, config) {
|
|
16217
|
+
this.db = db;
|
|
16218
|
+
this.config = { ...DEFAULT_CONFIG3, ...config };
|
|
16219
|
+
logger.info({ config: this.config }, "PluginStorageCleanupService initialized");
|
|
16220
|
+
}
|
|
16221
|
+
start() {
|
|
16222
|
+
if (!this.config.enabled) {
|
|
16223
|
+
logger.info("PluginStorageCleanupService is disabled");
|
|
16224
|
+
return;
|
|
16225
|
+
}
|
|
16226
|
+
if (this.timer) {
|
|
16227
|
+
logger.warn("PluginStorageCleanupService already started");
|
|
16228
|
+
return;
|
|
16229
|
+
}
|
|
16230
|
+
logger.info({ interval: this.config.interval }, "Starting PluginStorageCleanupService");
|
|
16231
|
+
this.cleanup().catch((err) => {
|
|
16232
|
+
logger.error({ error: err }, "Initial cleanup failed");
|
|
16233
|
+
});
|
|
16234
|
+
this.timer = setInterval(() => {
|
|
16235
|
+
this.cleanup().catch((err) => {
|
|
16236
|
+
logger.error({ error: err }, "Scheduled cleanup failed");
|
|
16237
|
+
});
|
|
16238
|
+
}, this.config.interval);
|
|
16239
|
+
}
|
|
16240
|
+
stop() {
|
|
16241
|
+
if (this.timer) {
|
|
16242
|
+
clearInterval(this.timer);
|
|
16243
|
+
this.timer = null;
|
|
16244
|
+
logger.info("PluginStorageCleanupService stopped");
|
|
16245
|
+
}
|
|
16246
|
+
}
|
|
16247
|
+
async cleanup() {
|
|
16248
|
+
if (this.running) {
|
|
16249
|
+
logger.warn("Cleanup already running, skipping");
|
|
16250
|
+
return 0;
|
|
16251
|
+
}
|
|
16252
|
+
this.running = true;
|
|
16253
|
+
const startTime = Date.now();
|
|
16254
|
+
let totalDeleted = 0;
|
|
16255
|
+
try {
|
|
16256
|
+
logger.info("Starting plugin storage cleanup");
|
|
16257
|
+
const now = Math.floor(Date.now() / 1000);
|
|
16258
|
+
let batchCount = 0;
|
|
16259
|
+
let hasMore = true;
|
|
16260
|
+
while (hasMore && batchCount < 10) {
|
|
16261
|
+
const deleteStmt = this.db.prepare(`
|
|
16262
|
+
DELETE FROM plugin_storage
|
|
16263
|
+
WHERE rowid IN (
|
|
16264
|
+
SELECT rowid FROM plugin_storage
|
|
16265
|
+
WHERE ttl IS NOT NULL AND ttl < ?
|
|
16266
|
+
LIMIT ?
|
|
16267
|
+
)
|
|
16268
|
+
`);
|
|
16269
|
+
const result = deleteStmt.run(now, this.config.batchSize);
|
|
16270
|
+
const deleted = result.changes;
|
|
16271
|
+
totalDeleted += deleted;
|
|
16272
|
+
batchCount++;
|
|
16273
|
+
logger.debug({ batch: batchCount, deleted, totalDeleted }, "Cleanup batch completed");
|
|
16274
|
+
hasMore = deleted >= this.config.batchSize;
|
|
16275
|
+
if (hasMore) {
|
|
16276
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
16277
|
+
}
|
|
16278
|
+
}
|
|
16279
|
+
if (this.config.vacuumAfterCleanup && totalDeleted > 0) {
|
|
16280
|
+
logger.info("Running VACUUM after cleanup");
|
|
16281
|
+
this.db.run("VACUUM");
|
|
16282
|
+
}
|
|
16283
|
+
const duration = Date.now() - startTime;
|
|
16284
|
+
this.stats.totalRuns++;
|
|
16285
|
+
this.stats.totalDeleted += totalDeleted;
|
|
16286
|
+
this.stats.lastRunTime = startTime;
|
|
16287
|
+
this.stats.lastDeletedCount = totalDeleted;
|
|
16288
|
+
this.stats.lastDuration = duration;
|
|
16289
|
+
logger.info({
|
|
16290
|
+
deleted: totalDeleted,
|
|
16291
|
+
duration,
|
|
16292
|
+
batches: batchCount
|
|
16293
|
+
}, "Plugin storage cleanup completed");
|
|
16294
|
+
return totalDeleted;
|
|
16295
|
+
} catch (error) {
|
|
16296
|
+
logger.error({ error }, "Plugin storage cleanup failed");
|
|
16297
|
+
throw error;
|
|
16298
|
+
} finally {
|
|
16299
|
+
this.running = false;
|
|
16300
|
+
}
|
|
16301
|
+
}
|
|
16302
|
+
getStats() {
|
|
16303
|
+
return {
|
|
16304
|
+
...this.stats,
|
|
16305
|
+
running: this.running,
|
|
16306
|
+
enabled: this.config.enabled
|
|
16307
|
+
};
|
|
16308
|
+
}
|
|
16309
|
+
resetStats() {
|
|
16310
|
+
this.stats = {
|
|
16311
|
+
totalRuns: 0,
|
|
16312
|
+
totalDeleted: 0,
|
|
16313
|
+
lastRunTime: 0,
|
|
16314
|
+
lastDeletedCount: 0,
|
|
16315
|
+
lastDuration: 0
|
|
16316
|
+
};
|
|
16317
|
+
}
|
|
16318
|
+
async getExpiredCount() {
|
|
16319
|
+
const now = Math.floor(Date.now() / 1000);
|
|
16320
|
+
const stmt = this.db.prepare(`
|
|
16321
|
+
SELECT COUNT(*) as count FROM plugin_storage
|
|
16322
|
+
WHERE ttl IS NOT NULL AND ttl < ?
|
|
16323
|
+
`);
|
|
16324
|
+
const result = stmt.get(now);
|
|
16325
|
+
return result.count;
|
|
16326
|
+
}
|
|
16327
|
+
async getStorageStats() {
|
|
16328
|
+
const now = Math.floor(Date.now() / 1000);
|
|
16329
|
+
const totalEntriesStmt = this.db.prepare(`
|
|
16330
|
+
SELECT COUNT(*) as count FROM plugin_storage
|
|
16331
|
+
`);
|
|
16332
|
+
const totalEntries = totalEntriesStmt.get().count;
|
|
16333
|
+
const totalWithTTLStmt = this.db.prepare(`
|
|
16334
|
+
SELECT COUNT(*) as count FROM plugin_storage
|
|
16335
|
+
WHERE ttl IS NOT NULL
|
|
16336
|
+
`);
|
|
16337
|
+
const totalWithTTL = totalWithTTLStmt.get().count;
|
|
16338
|
+
const totalExpiredStmt = this.db.prepare(`
|
|
16339
|
+
SELECT COUNT(*) as count FROM plugin_storage
|
|
16340
|
+
WHERE ttl IS NOT NULL AND ttl < ?
|
|
16341
|
+
`);
|
|
16342
|
+
const totalExpired = totalExpiredStmt.get(now).count;
|
|
16343
|
+
const totalPluginsStmt = this.db.prepare(`
|
|
16344
|
+
SELECT COUNT(DISTINCT plugin_name) as count FROM plugin_storage
|
|
16345
|
+
`);
|
|
16346
|
+
const totalPlugins = totalPluginsStmt.get().count;
|
|
16347
|
+
return {
|
|
16348
|
+
totalEntries,
|
|
16349
|
+
totalWithTTL,
|
|
16350
|
+
totalExpired,
|
|
16351
|
+
totalPlugins
|
|
16352
|
+
};
|
|
16353
|
+
}
|
|
16354
|
+
}
|
|
16355
|
+
var DEFAULT_CONFIG3;
|
|
16356
|
+
var init_plugin_storage_cleanup = __esm(() => {
|
|
16357
|
+
init_logger();
|
|
16358
|
+
DEFAULT_CONFIG3 = {
|
|
16359
|
+
enabled: true,
|
|
16360
|
+
interval: 3600000,
|
|
16361
|
+
batchSize: 1000,
|
|
16362
|
+
vacuumAfterCleanup: false
|
|
16363
|
+
};
|
|
16364
|
+
});
|
|
16365
|
+
|
|
16366
|
+
// src/plugin-permissions.ts
|
|
16367
|
+
class PluginPermissionManager {
|
|
16368
|
+
permissions = new Map;
|
|
16369
|
+
registerPlugin(pluginName, metadata) {
|
|
16370
|
+
const permissions = new Set;
|
|
16371
|
+
permissions.add("storage" /* STORAGE */);
|
|
16372
|
+
if (metadata.permissions && Array.isArray(metadata.permissions)) {
|
|
16373
|
+
for (const perm of metadata.permissions) {
|
|
16374
|
+
if (perm === "network")
|
|
16375
|
+
permissions.add("network" /* NETWORK */);
|
|
16376
|
+
else if (perm === "filesystem")
|
|
16377
|
+
permissions.add("filesystem" /* FILESYSTEM */);
|
|
16378
|
+
else if (perm === "storage")
|
|
16379
|
+
permissions.add("storage" /* STORAGE */);
|
|
16380
|
+
else if (perm === "ui:modals")
|
|
16381
|
+
permissions.add("ui:modals" /* UI_MODALS */);
|
|
16382
|
+
else if (perm === "ui:popups")
|
|
16383
|
+
permissions.add("ui:popups" /* UI_POPUPS */);
|
|
16384
|
+
else if (perm === "ui:forms")
|
|
16385
|
+
permissions.add("ui:forms" /* UI_FORMS */);
|
|
16386
|
+
else if (perm === "ui:navigation")
|
|
16387
|
+
permissions.add("ui:navigation" /* UI_NAVIGATION */);
|
|
16388
|
+
else if (perm === "api:routes")
|
|
16389
|
+
permissions.add("api:routes" /* API_ROUTES */);
|
|
16390
|
+
else if (perm === "api:plugins")
|
|
16391
|
+
permissions.add("api:plugins" /* API_PLUGINS */);
|
|
16392
|
+
else if (perm === "api:logs")
|
|
16393
|
+
permissions.add("api:logs" /* API_LOGS */);
|
|
16394
|
+
}
|
|
16395
|
+
}
|
|
16396
|
+
if (metadata.capabilities) {
|
|
16397
|
+
const { network, filesystem, database } = metadata.capabilities;
|
|
16398
|
+
if (network)
|
|
16399
|
+
permissions.add("network" /* NETWORK */);
|
|
16400
|
+
if (filesystem)
|
|
16401
|
+
permissions.add("filesystem" /* FILESYSTEM */);
|
|
16402
|
+
if (database)
|
|
16403
|
+
permissions.add("database" /* DATABASE */);
|
|
16404
|
+
}
|
|
16405
|
+
if (metadata.contributes) {
|
|
16406
|
+
if (metadata.contributes.navigation?.length) {
|
|
16407
|
+
permissions.add("ui:navigation" /* UI_NAVIGATION */);
|
|
16408
|
+
}
|
|
16409
|
+
if (metadata.contributes.commands?.length) {
|
|
16410
|
+
permissions.add("api:routes" /* API_ROUTES */);
|
|
16411
|
+
}
|
|
16412
|
+
}
|
|
16413
|
+
if (metadata.contributes?.navigation || metadata.contributes?.widgets) {
|
|
16414
|
+
permissions.add("ui:forms" /* UI_FORMS */);
|
|
16415
|
+
permissions.add("ui:modals" /* UI_MODALS */);
|
|
16416
|
+
}
|
|
16417
|
+
this.permissions.set(pluginName, permissions);
|
|
16418
|
+
logger.debug({ pluginName, permissions: Array.from(permissions) }, "Registered plugin permissions");
|
|
16419
|
+
}
|
|
16420
|
+
hasPermission(pluginName, permission) {
|
|
16421
|
+
const perms = this.permissions.get(pluginName);
|
|
16422
|
+
if (!perms) {
|
|
16423
|
+
logger.warn({ pluginName, permission }, "Plugin not registered in permission manager");
|
|
16424
|
+
return false;
|
|
16425
|
+
}
|
|
16426
|
+
return perms.has(permission);
|
|
16427
|
+
}
|
|
16428
|
+
hasPermissions(pluginName, requiredPermissions) {
|
|
16429
|
+
return requiredPermissions.every((perm) => this.hasPermission(pluginName, perm));
|
|
16430
|
+
}
|
|
16431
|
+
getPermissions(pluginName) {
|
|
16432
|
+
return this.permissions.get(pluginName) || new Set;
|
|
16433
|
+
}
|
|
16434
|
+
getSandboxAttributes(pluginName) {
|
|
16435
|
+
const perms = this.permissions.get(pluginName);
|
|
16436
|
+
if (!perms) {
|
|
16437
|
+
return "allow-scripts";
|
|
16438
|
+
}
|
|
16439
|
+
const sandboxAttrs = new Set([
|
|
16440
|
+
"allow-scripts",
|
|
16441
|
+
"allow-same-origin"
|
|
16442
|
+
]);
|
|
16443
|
+
for (const perm of perms) {
|
|
16444
|
+
const sandboxAttr = PERMISSION_TO_SANDBOX[perm];
|
|
16445
|
+
if (sandboxAttr) {
|
|
16446
|
+
sandboxAttr.split(" ").forEach((attr) => sandboxAttrs.add(attr));
|
|
16447
|
+
}
|
|
16448
|
+
}
|
|
16449
|
+
return Array.from(sandboxAttrs).join(" ");
|
|
16450
|
+
}
|
|
16451
|
+
getCSP(pluginName) {
|
|
16452
|
+
const perms = this.permissions.get(pluginName);
|
|
16453
|
+
if (!perms) {
|
|
16454
|
+
return "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'";
|
|
16455
|
+
}
|
|
16456
|
+
const cspDirectives = [];
|
|
16457
|
+
cspDirectives.push("default-src 'self'");
|
|
16458
|
+
cspDirectives.push("script-src 'self' 'unsafe-inline' 'unsafe-eval'");
|
|
16459
|
+
cspDirectives.push("style-src 'self' 'unsafe-inline'");
|
|
16460
|
+
cspDirectives.push("font-src 'self' data:");
|
|
16461
|
+
cspDirectives.push("img-src 'self' data: blob:");
|
|
16462
|
+
if (perms.has("network" /* NETWORK */)) {
|
|
16463
|
+
cspDirectives.push("connect-src 'self' https: wss:");
|
|
16464
|
+
} else {
|
|
16465
|
+
cspDirectives.push("connect-src 'self'");
|
|
16466
|
+
}
|
|
16467
|
+
cspDirectives.push("frame-ancestors 'self'");
|
|
16468
|
+
cspDirectives.push("object-src 'none'");
|
|
16469
|
+
cspDirectives.push("base-uri 'self'");
|
|
16470
|
+
return cspDirectives.join("; ");
|
|
16471
|
+
}
|
|
16472
|
+
canAccessAPI(pluginName, apiPath) {
|
|
16473
|
+
const apiPermissionMap = {
|
|
16474
|
+
"/api/plugins": "api:plugins" /* API_PLUGINS */,
|
|
16475
|
+
"/api/routes": "api:routes" /* API_ROUTES */,
|
|
16476
|
+
"/api/logs": "api:logs" /* API_LOGS */
|
|
16477
|
+
};
|
|
16478
|
+
for (const [prefix, permission] of Object.entries(apiPermissionMap)) {
|
|
16479
|
+
if (apiPath.startsWith(prefix)) {
|
|
16480
|
+
return this.hasPermission(pluginName, permission);
|
|
16481
|
+
}
|
|
16482
|
+
}
|
|
16483
|
+
return true;
|
|
16484
|
+
}
|
|
16485
|
+
unregisterPlugin(pluginName) {
|
|
16486
|
+
this.permissions.delete(pluginName);
|
|
16487
|
+
logger.debug({ pluginName }, "Unregistered plugin permissions");
|
|
16488
|
+
}
|
|
16489
|
+
clear() {
|
|
16490
|
+
this.permissions.clear();
|
|
16491
|
+
}
|
|
16492
|
+
getStats() {
|
|
16493
|
+
return {
|
|
16494
|
+
totalPlugins: this.permissions.size,
|
|
16495
|
+
plugins: Array.from(this.permissions.keys())
|
|
16496
|
+
};
|
|
16497
|
+
}
|
|
16498
|
+
}
|
|
16499
|
+
function initializePermissionManager() {
|
|
16500
|
+
if (!globalPermissionManager) {
|
|
16501
|
+
globalPermissionManager = new PluginPermissionManager;
|
|
16502
|
+
logger.info("Plugin permission manager initialized");
|
|
16503
|
+
}
|
|
16504
|
+
return globalPermissionManager;
|
|
16505
|
+
}
|
|
16506
|
+
function getPermissionManager() {
|
|
16507
|
+
if (!globalPermissionManager) {
|
|
16508
|
+
throw new Error("PermissionManager not initialized. Call initializePermissionManager() first.");
|
|
16509
|
+
}
|
|
16510
|
+
return globalPermissionManager;
|
|
16511
|
+
}
|
|
16512
|
+
var PERMISSION_TO_SANDBOX, globalPermissionManager = null;
|
|
16513
|
+
var init_plugin_permissions = __esm(() => {
|
|
16514
|
+
init_logger();
|
|
16515
|
+
PERMISSION_TO_SANDBOX = {
|
|
16516
|
+
["ui:modals" /* UI_MODALS */]: "allow-modals",
|
|
16517
|
+
["ui:popups" /* UI_POPUPS */]: "allow-popups allow-popups-to-escape-sandbox",
|
|
16518
|
+
["ui:forms" /* UI_FORMS */]: "allow-forms",
|
|
16519
|
+
["ui:navigation" /* UI_NAVIGATION */]: "allow-top-navigation-by-user-activation"
|
|
16520
|
+
};
|
|
16521
|
+
});
|
|
16522
|
+
|
|
16090
16523
|
// src/master.ts
|
|
16091
16524
|
var exports_master = {};
|
|
16092
16525
|
import path7 from "path";
|
|
16093
16526
|
import { spawn } from "child_process";
|
|
16094
16527
|
import fs7 from "fs";
|
|
16528
|
+
import { Database as Database3 } from "bun:sqlite";
|
|
16095
16529
|
|
|
16096
16530
|
class Master {
|
|
16097
16531
|
workers = new Map;
|
|
16098
16532
|
config;
|
|
16099
16533
|
isReloading = false;
|
|
16100
16534
|
reloadTimeout = null;
|
|
16535
|
+
pluginStorageCleanupService = null;
|
|
16101
16536
|
constructor() {
|
|
16102
16537
|
this.loadAndStart();
|
|
16103
16538
|
this.watchConfig();
|
|
@@ -16125,6 +16560,16 @@ class Master {
|
|
|
16125
16560
|
} else {
|
|
16126
16561
|
logger.info("Database migrations completed successfully");
|
|
16127
16562
|
}
|
|
16563
|
+
const db = new Database3(dbPath2);
|
|
16564
|
+
this.pluginStorageCleanupService = new PluginStorageCleanupService(db, {
|
|
16565
|
+
enabled: true,
|
|
16566
|
+
interval: 3600000,
|
|
16567
|
+
batchSize: 1000,
|
|
16568
|
+
vacuumAfterCleanup: false
|
|
16569
|
+
});
|
|
16570
|
+
this.pluginStorageCleanupService.start();
|
|
16571
|
+
initializePermissionManager();
|
|
16572
|
+
logger.info("Plugin permission manager initialized");
|
|
16128
16573
|
await this.startWorkers();
|
|
16129
16574
|
} catch (error) {
|
|
16130
16575
|
logger.error({ error }, "Failed to load or parse config.json");
|
|
@@ -16332,6 +16777,9 @@ class Master {
|
|
|
16332
16777
|
await Promise.all(shutdownPromises);
|
|
16333
16778
|
this.workers.clear();
|
|
16334
16779
|
logCleanupService.stop();
|
|
16780
|
+
if (this.pluginStorageCleanupService) {
|
|
16781
|
+
this.pluginStorageCleanupService.stop();
|
|
16782
|
+
}
|
|
16335
16783
|
}
|
|
16336
16784
|
}
|
|
16337
16785
|
var import_dotenv2, CONFIG_PATH, WORKER_COUNT, PORT;
|
|
@@ -16340,6 +16788,8 @@ var init_master = __esm(() => {
|
|
|
16340
16788
|
init_log_cleanup();
|
|
16341
16789
|
init_migrations();
|
|
16342
16790
|
init_config();
|
|
16791
|
+
init_plugin_storage_cleanup();
|
|
16792
|
+
init_plugin_permissions();
|
|
16343
16793
|
import_dotenv2 = __toESM(require_main(), 1);
|
|
16344
16794
|
import_dotenv2.default.config();
|
|
16345
16795
|
CONFIG_PATH = process.env.CONFIG_PATH || path7.resolve(process.cwd(), "config.json");
|