@runtimescope/collector 0.7.1 → 0.7.2
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-VZSMLTUQ.js → chunk-TUFSIGGJ.js} +145 -39
- package/dist/chunk-TUFSIGGJ.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/standalone.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-VZSMLTUQ.js.map +0 -1
|
@@ -297,40 +297,84 @@ var EventStore = class {
|
|
|
297
297
|
|
|
298
298
|
// src/sqlite-store.ts
|
|
299
299
|
import Database from "better-sqlite3";
|
|
300
|
-
|
|
300
|
+
import { renameSync, existsSync } from "fs";
|
|
301
|
+
var SqliteStore = class _SqliteStore {
|
|
301
302
|
db;
|
|
302
303
|
writeBuffer = [];
|
|
303
304
|
flushTimer = null;
|
|
304
305
|
batchSize;
|
|
306
|
+
dbPath;
|
|
307
|
+
static MAX_SNAPSHOTS_PER_SESSION = 50;
|
|
305
308
|
insertEventStmt;
|
|
306
309
|
insertSessionStmt;
|
|
307
310
|
updateSessionDisconnectedStmt;
|
|
308
311
|
constructor(options) {
|
|
309
|
-
this.
|
|
312
|
+
this.dbPath = options.dbPath;
|
|
310
313
|
this.batchSize = options.batchSize ?? 50;
|
|
311
|
-
|
|
312
|
-
|
|
314
|
+
this.db = this.openDatabase(options);
|
|
315
|
+
const flushInterval = options.flushIntervalMs ?? 100;
|
|
316
|
+
this.flushTimer = setInterval(() => this.flush(), flushInterval);
|
|
317
|
+
}
|
|
318
|
+
openDatabase(options) {
|
|
319
|
+
try {
|
|
320
|
+
const db = new Database(options.dbPath);
|
|
321
|
+
if (options.walMode !== false) {
|
|
322
|
+
db.pragma("journal_mode = WAL");
|
|
323
|
+
}
|
|
324
|
+
db.pragma("synchronous = NORMAL");
|
|
325
|
+
const check = db.pragma("integrity_check");
|
|
326
|
+
if (check[0]?.integrity_check !== "ok") {
|
|
327
|
+
throw new Error("Integrity check failed");
|
|
328
|
+
}
|
|
329
|
+
this.createSchema(db);
|
|
330
|
+
this.prepareStatements(db);
|
|
331
|
+
return db;
|
|
332
|
+
} catch (err) {
|
|
333
|
+
console.error(
|
|
334
|
+
`[RuntimeScope] SQLite database corrupt or unreadable (${err.message}), recreating...`
|
|
335
|
+
);
|
|
336
|
+
try {
|
|
337
|
+
if (existsSync(options.dbPath)) {
|
|
338
|
+
const backupPath = `${options.dbPath}.corrupt.${Date.now()}`;
|
|
339
|
+
renameSync(options.dbPath, backupPath);
|
|
340
|
+
console.error(`[RuntimeScope] Renamed corrupt DB to ${backupPath}`);
|
|
341
|
+
}
|
|
342
|
+
for (const suffix of ["-wal", "-shm"]) {
|
|
343
|
+
const p = options.dbPath + suffix;
|
|
344
|
+
if (existsSync(p)) {
|
|
345
|
+
renameSync(p, `${p}.corrupt.${Date.now()}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
} catch {
|
|
349
|
+
}
|
|
350
|
+
const db = new Database(options.dbPath);
|
|
351
|
+
if (options.walMode !== false) {
|
|
352
|
+
db.pragma("journal_mode = WAL");
|
|
353
|
+
}
|
|
354
|
+
db.pragma("synchronous = NORMAL");
|
|
355
|
+
this.createSchema(db);
|
|
356
|
+
this.prepareStatements(db);
|
|
357
|
+
return db;
|
|
313
358
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
this.insertEventStmt =
|
|
359
|
+
}
|
|
360
|
+
prepareStatements(db) {
|
|
361
|
+
this.insertEventStmt = db.prepare(`
|
|
317
362
|
INSERT INTO events (event_id, session_id, project, event_type, timestamp, data)
|
|
318
363
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
319
364
|
`);
|
|
320
|
-
this.insertSessionStmt =
|
|
365
|
+
this.insertSessionStmt = db.prepare(`
|
|
321
366
|
INSERT OR REPLACE INTO sessions (
|
|
322
367
|
session_id, project, app_name, connected_at, sdk_version,
|
|
323
368
|
event_count, is_connected, build_meta
|
|
324
369
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
325
370
|
`);
|
|
326
|
-
this.updateSessionDisconnectedStmt =
|
|
371
|
+
this.updateSessionDisconnectedStmt = db.prepare(`
|
|
327
372
|
UPDATE sessions SET is_connected = 0, disconnected_at = ? WHERE session_id = ?
|
|
328
373
|
`);
|
|
329
|
-
const flushInterval = options.flushIntervalMs ?? 100;
|
|
330
|
-
this.flushTimer = setInterval(() => this.flush(), flushInterval);
|
|
331
374
|
}
|
|
332
|
-
createSchema() {
|
|
333
|
-
this.db
|
|
375
|
+
createSchema(db) {
|
|
376
|
+
const d = db ?? this.db;
|
|
377
|
+
d.exec(`
|
|
334
378
|
CREATE TABLE IF NOT EXISTS events (
|
|
335
379
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
336
380
|
event_id TEXT NOT NULL UNIQUE,
|
|
@@ -374,7 +418,7 @@ var SqliteStore = class {
|
|
|
374
418
|
CREATE INDEX IF NOT EXISTS idx_snapshots_session ON session_snapshots(session_id);
|
|
375
419
|
CREATE INDEX IF NOT EXISTS idx_snapshots_project ON session_snapshots(project, created_at);
|
|
376
420
|
`);
|
|
377
|
-
this.migrateSessionMetrics();
|
|
421
|
+
this.migrateSessionMetrics(d);
|
|
378
422
|
}
|
|
379
423
|
// --- Write Operations ---
|
|
380
424
|
addEvent(event, project) {
|
|
@@ -427,6 +471,21 @@ var SqliteStore = class {
|
|
|
427
471
|
INSERT INTO session_snapshots (session_id, project, label, metrics, created_at)
|
|
428
472
|
VALUES (?, ?, ?, ?, ?)
|
|
429
473
|
`).run(sessionId, project, label ?? null, JSON.stringify(metrics), Date.now());
|
|
474
|
+
this.pruneSnapshots(sessionId);
|
|
475
|
+
}
|
|
476
|
+
/** Remove oldest snapshots for a session beyond the retention limit */
|
|
477
|
+
pruneSnapshots(sessionId) {
|
|
478
|
+
const count = this.db.prepare("SELECT COUNT(*) as cnt FROM session_snapshots WHERE session_id = ?").get(sessionId).cnt;
|
|
479
|
+
if (count > _SqliteStore.MAX_SNAPSHOTS_PER_SESSION) {
|
|
480
|
+
this.db.prepare(`
|
|
481
|
+
DELETE FROM session_snapshots WHERE id IN (
|
|
482
|
+
SELECT id FROM session_snapshots
|
|
483
|
+
WHERE session_id = ?
|
|
484
|
+
ORDER BY created_at ASC
|
|
485
|
+
LIMIT ?
|
|
486
|
+
)
|
|
487
|
+
`).run(sessionId, count - _SqliteStore.MAX_SNAPSHOTS_PER_SESSION);
|
|
488
|
+
}
|
|
430
489
|
}
|
|
431
490
|
// --- Read Operations ---
|
|
432
491
|
getEvents(filter) {
|
|
@@ -552,17 +611,17 @@ var SqliteStore = class {
|
|
|
552
611
|
return rows.map((row) => JSON.parse(row.data));
|
|
553
612
|
}
|
|
554
613
|
// --- Migration ---
|
|
555
|
-
migrateSessionMetrics() {
|
|
556
|
-
const hasOldTable =
|
|
614
|
+
migrateSessionMetrics(db) {
|
|
615
|
+
const hasOldTable = db.prepare(
|
|
557
616
|
"SELECT name FROM sqlite_master WHERE type='table' AND name='session_metrics'"
|
|
558
617
|
).get();
|
|
559
618
|
if (hasOldTable) {
|
|
560
|
-
|
|
619
|
+
db.exec(`
|
|
561
620
|
INSERT OR IGNORE INTO session_snapshots (session_id, project, label, metrics, created_at)
|
|
562
621
|
SELECT session_id, project, 'auto-disconnect', metrics, created_at
|
|
563
622
|
FROM session_metrics
|
|
564
623
|
`);
|
|
565
|
-
|
|
624
|
+
db.exec("DROP TABLE session_metrics");
|
|
566
625
|
}
|
|
567
626
|
}
|
|
568
627
|
// --- Maintenance ---
|
|
@@ -727,6 +786,7 @@ var CollectorServer = class {
|
|
|
727
786
|
connectCallbacks = [];
|
|
728
787
|
disconnectCallbacks = [];
|
|
729
788
|
pruneTimer = null;
|
|
789
|
+
heartbeatTimer = null;
|
|
730
790
|
tlsConfig = null;
|
|
731
791
|
constructor(options = {}) {
|
|
732
792
|
this.store = new EventStore(options.bufferSize ?? 1e4);
|
|
@@ -786,6 +846,8 @@ var CollectorServer = class {
|
|
|
786
846
|
httpsServer.on("listening", () => {
|
|
787
847
|
this.wss = wss;
|
|
788
848
|
this.setupConnectionHandler(wss);
|
|
849
|
+
this.setupPersistentErrorHandler(wss);
|
|
850
|
+
this.startHeartbeat(wss);
|
|
789
851
|
console.error(`[RuntimeScope] Collector listening on wss://${host}:${port}`);
|
|
790
852
|
resolve2();
|
|
791
853
|
});
|
|
@@ -799,6 +861,8 @@ var CollectorServer = class {
|
|
|
799
861
|
wss.on("listening", () => {
|
|
800
862
|
this.wss = wss;
|
|
801
863
|
this.setupConnectionHandler(wss);
|
|
864
|
+
this.setupPersistentErrorHandler(wss);
|
|
865
|
+
this.startHeartbeat(wss);
|
|
802
866
|
console.error(`[RuntimeScope] Collector listening on ws://${host}:${port}`);
|
|
803
867
|
resolve2();
|
|
804
868
|
});
|
|
@@ -844,8 +908,33 @@ var CollectorServer = class {
|
|
|
844
908
|
}
|
|
845
909
|
return sqliteStore;
|
|
846
910
|
}
|
|
911
|
+
/** Catch runtime errors on the WSS so an unhandled error doesn't crash the process */
|
|
912
|
+
setupPersistentErrorHandler(wss) {
|
|
913
|
+
wss.on("error", (err) => {
|
|
914
|
+
console.error("[RuntimeScope] WebSocket server runtime error:", err.message);
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
/** Ping all connected clients every 15s — terminate those that don't respond */
|
|
918
|
+
startHeartbeat(wss) {
|
|
919
|
+
this.heartbeatTimer = setInterval(() => {
|
|
920
|
+
for (const ws of wss.clients) {
|
|
921
|
+
const ext = ws;
|
|
922
|
+
if (ext._rsAlive === false) {
|
|
923
|
+
ws.terminate();
|
|
924
|
+
continue;
|
|
925
|
+
}
|
|
926
|
+
ext._rsAlive = false;
|
|
927
|
+
ws.ping();
|
|
928
|
+
}
|
|
929
|
+
}, 15e3);
|
|
930
|
+
}
|
|
847
931
|
setupConnectionHandler(wss) {
|
|
848
932
|
wss.on("connection", (ws) => {
|
|
933
|
+
const ext = ws;
|
|
934
|
+
ext._rsAlive = true;
|
|
935
|
+
ws.on("pong", () => {
|
|
936
|
+
ext._rsAlive = true;
|
|
937
|
+
});
|
|
849
938
|
if (this.authManager?.isEnabled()) {
|
|
850
939
|
this.pendingHandshakes.add(ws);
|
|
851
940
|
const authTimeout = setTimeout(() => {
|
|
@@ -1040,10 +1129,27 @@ var CollectorServer = class {
|
|
|
1040
1129
|
});
|
|
1041
1130
|
}
|
|
1042
1131
|
stop() {
|
|
1132
|
+
if (this.heartbeatTimer) {
|
|
1133
|
+
clearInterval(this.heartbeatTimer);
|
|
1134
|
+
this.heartbeatTimer = null;
|
|
1135
|
+
}
|
|
1043
1136
|
if (this.pruneTimer) {
|
|
1044
1137
|
clearInterval(this.pruneTimer);
|
|
1045
1138
|
this.pruneTimer = null;
|
|
1046
1139
|
}
|
|
1140
|
+
if (this.wss) {
|
|
1141
|
+
for (const client of this.wss.clients) {
|
|
1142
|
+
if (client.readyState === 1) {
|
|
1143
|
+
try {
|
|
1144
|
+
client.send(JSON.stringify({
|
|
1145
|
+
type: "__server_restart",
|
|
1146
|
+
timestamp: Date.now()
|
|
1147
|
+
}));
|
|
1148
|
+
} catch {
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1047
1153
|
for (const [name, sqliteStore] of this.sqliteStores) {
|
|
1048
1154
|
try {
|
|
1049
1155
|
sqliteStore.close();
|
|
@@ -1061,7 +1167,7 @@ var CollectorServer = class {
|
|
|
1061
1167
|
};
|
|
1062
1168
|
|
|
1063
1169
|
// src/project-manager.ts
|
|
1064
|
-
import { mkdirSync, readFileSync as readFileSync2, writeFileSync, existsSync, readdirSync } from "fs";
|
|
1170
|
+
import { mkdirSync, readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, readdirSync } from "fs";
|
|
1065
1171
|
import { join } from "path";
|
|
1066
1172
|
import { homedir } from "os";
|
|
1067
1173
|
var DEFAULT_GLOBAL_CONFIG = {
|
|
@@ -1093,7 +1199,7 @@ var ProjectManager = class {
|
|
|
1093
1199
|
this.mkdirp(this.baseDir);
|
|
1094
1200
|
this.mkdirp(join(this.baseDir, "projects"));
|
|
1095
1201
|
const configPath = join(this.baseDir, "config.json");
|
|
1096
|
-
if (!
|
|
1202
|
+
if (!existsSync2(configPath)) {
|
|
1097
1203
|
this.writeJson(configPath, DEFAULT_GLOBAL_CONFIG);
|
|
1098
1204
|
}
|
|
1099
1205
|
}
|
|
@@ -1101,7 +1207,7 @@ var ProjectManager = class {
|
|
|
1101
1207
|
const projectDir = this.getProjectDir(projectName);
|
|
1102
1208
|
this.mkdirp(projectDir);
|
|
1103
1209
|
const configPath = join(projectDir, "config.json");
|
|
1104
|
-
if (!
|
|
1210
|
+
if (!existsSync2(configPath)) {
|
|
1105
1211
|
const config = {
|
|
1106
1212
|
name: projectName,
|
|
1107
1213
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1115,7 +1221,7 @@ var ProjectManager = class {
|
|
|
1115
1221
|
// --- Config ---
|
|
1116
1222
|
getGlobalConfig() {
|
|
1117
1223
|
const configPath = join(this.baseDir, "config.json");
|
|
1118
|
-
if (!
|
|
1224
|
+
if (!existsSync2(configPath)) return { ...DEFAULT_GLOBAL_CONFIG };
|
|
1119
1225
|
return { ...DEFAULT_GLOBAL_CONFIG, ...this.readJson(configPath) };
|
|
1120
1226
|
}
|
|
1121
1227
|
saveGlobalConfig(config) {
|
|
@@ -1123,7 +1229,7 @@ var ProjectManager = class {
|
|
|
1123
1229
|
}
|
|
1124
1230
|
getProjectConfig(projectName) {
|
|
1125
1231
|
const configPath = join(this.getProjectDir(projectName), "config.json");
|
|
1126
|
-
if (!
|
|
1232
|
+
if (!existsSync2(configPath)) return null;
|
|
1127
1233
|
return this.readJson(configPath);
|
|
1128
1234
|
}
|
|
1129
1235
|
saveProjectConfig(projectName, config) {
|
|
@@ -1131,12 +1237,12 @@ var ProjectManager = class {
|
|
|
1131
1237
|
}
|
|
1132
1238
|
getInfrastructureConfig(projectName) {
|
|
1133
1239
|
const jsonPath = join(this.getProjectDir(projectName), "infrastructure.json");
|
|
1134
|
-
if (
|
|
1240
|
+
if (existsSync2(jsonPath)) {
|
|
1135
1241
|
const config = this.readJson(jsonPath);
|
|
1136
1242
|
return this.resolveConfigEnvVars(config);
|
|
1137
1243
|
}
|
|
1138
1244
|
const yamlPath = join(this.getProjectDir(projectName), "infrastructure.yaml");
|
|
1139
|
-
if (
|
|
1245
|
+
if (existsSync2(yamlPath)) {
|
|
1140
1246
|
try {
|
|
1141
1247
|
const content = readFileSync2(yamlPath, "utf-8");
|
|
1142
1248
|
return this.resolveConfigEnvVars(this.parseSimpleYaml(content));
|
|
@@ -1148,17 +1254,17 @@ var ProjectManager = class {
|
|
|
1148
1254
|
}
|
|
1149
1255
|
getClaudeInstructions(projectName) {
|
|
1150
1256
|
const filePath = join(this.getProjectDir(projectName), "claude-instructions.md");
|
|
1151
|
-
if (!
|
|
1257
|
+
if (!existsSync2(filePath)) return null;
|
|
1152
1258
|
return readFileSync2(filePath, "utf-8");
|
|
1153
1259
|
}
|
|
1154
1260
|
// --- Discovery ---
|
|
1155
1261
|
listProjects() {
|
|
1156
1262
|
const projectsDir = join(this.baseDir, "projects");
|
|
1157
|
-
if (!
|
|
1263
|
+
if (!existsSync2(projectsDir)) return [];
|
|
1158
1264
|
return readdirSync(projectsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
1159
1265
|
}
|
|
1160
1266
|
projectExists(projectName) {
|
|
1161
|
-
return
|
|
1267
|
+
return existsSync2(this.getProjectDir(projectName));
|
|
1162
1268
|
}
|
|
1163
1269
|
// --- Environment variable resolution ---
|
|
1164
1270
|
resolveEnvVars(value) {
|
|
@@ -1168,7 +1274,7 @@ var ProjectManager = class {
|
|
|
1168
1274
|
}
|
|
1169
1275
|
// --- Private helpers ---
|
|
1170
1276
|
mkdirp(dir) {
|
|
1171
|
-
if (!
|
|
1277
|
+
if (!existsSync2(dir)) {
|
|
1172
1278
|
mkdirSync(dir, { recursive: true });
|
|
1173
1279
|
}
|
|
1174
1280
|
}
|
|
@@ -1508,14 +1614,14 @@ var SessionManager = class {
|
|
|
1508
1614
|
// src/http-server.ts
|
|
1509
1615
|
import { createServer } from "http";
|
|
1510
1616
|
import { createServer as createHttpsServer2 } from "https";
|
|
1511
|
-
import { readFileSync as readFileSync3, existsSync as
|
|
1617
|
+
import { readFileSync as readFileSync3, existsSync as existsSync4 } from "fs";
|
|
1512
1618
|
import { resolve, dirname } from "path";
|
|
1513
1619
|
import { fileURLToPath } from "url";
|
|
1514
1620
|
import { WebSocketServer as WebSocketServer2 } from "ws";
|
|
1515
1621
|
|
|
1516
1622
|
// src/pm/pm-routes.ts
|
|
1517
1623
|
import { readdir, readFile, writeFile, unlink, mkdir } from "fs/promises";
|
|
1518
|
-
import { existsSync as
|
|
1624
|
+
import { existsSync as existsSync3 } from "fs";
|
|
1519
1625
|
import { join as join2 } from "path";
|
|
1520
1626
|
import { homedir as homedir2 } from "os";
|
|
1521
1627
|
import { spawn, execSync, execFileSync } from "child_process";
|
|
@@ -2450,7 +2556,7 @@ function parseGitStatus(porcelain) {
|
|
|
2450
2556
|
}
|
|
2451
2557
|
async function readRuleFile(filePath) {
|
|
2452
2558
|
try {
|
|
2453
|
-
if (
|
|
2559
|
+
if (existsSync3(filePath)) {
|
|
2454
2560
|
const content = await readFile(filePath, "utf-8");
|
|
2455
2561
|
return { path: filePath, content, exists: true };
|
|
2456
2562
|
}
|
|
@@ -2745,7 +2851,7 @@ var HttpServer = class {
|
|
|
2745
2851
|
// npm installed
|
|
2746
2852
|
];
|
|
2747
2853
|
for (const p of candidates) {
|
|
2748
|
-
if (
|
|
2854
|
+
if (existsSync4(p)) {
|
|
2749
2855
|
this.sdkBundlePath = p;
|
|
2750
2856
|
return p;
|
|
2751
2857
|
}
|
|
@@ -4101,7 +4207,7 @@ async function parseSessionJsonl(jsonlPath, sessionId, projectId) {
|
|
|
4101
4207
|
// src/pm/project-discovery.ts
|
|
4102
4208
|
import { readdir as readdir2, readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
4103
4209
|
import { join as join3, basename as basename2 } from "path";
|
|
4104
|
-
import { existsSync as
|
|
4210
|
+
import { existsSync as existsSync5 } from "fs";
|
|
4105
4211
|
import { homedir as homedir3 } from "os";
|
|
4106
4212
|
var LOG_PREFIX = "[RuntimeScope PM]";
|
|
4107
4213
|
async function detectSdkInstalled(projectPath) {
|
|
@@ -4168,7 +4274,7 @@ function slugifyPath(fsPath) {
|
|
|
4168
4274
|
}
|
|
4169
4275
|
function decodeClaudeKey(key) {
|
|
4170
4276
|
const naive = "/" + key.slice(1).replace(/-/g, "/");
|
|
4171
|
-
if (
|
|
4277
|
+
if (existsSync5(naive)) return naive;
|
|
4172
4278
|
const parts = key.slice(1).split("-");
|
|
4173
4279
|
return resolvePathSegments(parts);
|
|
4174
4280
|
}
|
|
@@ -4176,16 +4282,16 @@ function resolvePathSegments(parts) {
|
|
|
4176
4282
|
if (parts.length === 0) return null;
|
|
4177
4283
|
function tryResolve(prefix, remaining) {
|
|
4178
4284
|
if (remaining.length === 0) {
|
|
4179
|
-
return
|
|
4285
|
+
return existsSync5(prefix) ? prefix : null;
|
|
4180
4286
|
}
|
|
4181
4287
|
for (let count = remaining.length; count >= 1; count--) {
|
|
4182
4288
|
const segment = remaining.slice(0, count).join("-");
|
|
4183
4289
|
const candidate = join3(prefix, segment);
|
|
4184
4290
|
if (count === remaining.length) {
|
|
4185
|
-
if (
|
|
4291
|
+
if (existsSync5(candidate)) return candidate;
|
|
4186
4292
|
} else {
|
|
4187
4293
|
try {
|
|
4188
|
-
if (
|
|
4294
|
+
if (existsSync5(candidate)) {
|
|
4189
4295
|
const result = tryResolve(candidate, remaining.slice(count));
|
|
4190
4296
|
if (result) return result;
|
|
4191
4297
|
}
|
|
@@ -4679,4 +4785,4 @@ export {
|
|
|
4679
4785
|
parseSessionJsonl,
|
|
4680
4786
|
ProjectDiscovery
|
|
4681
4787
|
};
|
|
4682
|
-
//# sourceMappingURL=chunk-
|
|
4788
|
+
//# sourceMappingURL=chunk-TUFSIGGJ.js.map
|