@elizaos/plugin-sql 1.5.9-alpha.7 → 1.5.9-alpha.8
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.
|
@@ -11,7 +11,7 @@ var __export = (target, all) => {
|
|
|
11
11
|
|
|
12
12
|
// src/index.browser.ts
|
|
13
13
|
import {
|
|
14
|
-
logger as
|
|
14
|
+
logger as logger5
|
|
15
15
|
} from "@elizaos/core/browser";
|
|
16
16
|
|
|
17
17
|
// src/pglite/adapter.ts
|
|
@@ -2300,6 +2300,921 @@ class PGliteClientManager {
|
|
|
2300
2300
|
setupShutdownHandlers() {}
|
|
2301
2301
|
}
|
|
2302
2302
|
|
|
2303
|
+
// src/migration-service.ts
|
|
2304
|
+
import { logger as logger4 } from "@elizaos/core";
|
|
2305
|
+
|
|
2306
|
+
// src/custom-migrator.ts
|
|
2307
|
+
import { sql as sql17 } from "drizzle-orm";
|
|
2308
|
+
import { logger as logger3 } from "@elizaos/core";
|
|
2309
|
+
function extractErrorMessage(error) {
|
|
2310
|
+
if (error instanceof Error && "cause" in error && error.cause) {
|
|
2311
|
+
return error.cause.message;
|
|
2312
|
+
} else if (error instanceof Error) {
|
|
2313
|
+
return error.message;
|
|
2314
|
+
}
|
|
2315
|
+
return "Unknown error";
|
|
2316
|
+
}
|
|
2317
|
+
function extractErrorDetails(error) {
|
|
2318
|
+
if (error instanceof Error && "cause" in error && error.cause) {
|
|
2319
|
+
const cause = error.cause;
|
|
2320
|
+
return {
|
|
2321
|
+
message: cause.message,
|
|
2322
|
+
stack: cause.stack || error.stack
|
|
2323
|
+
};
|
|
2324
|
+
} else if (error instanceof Error) {
|
|
2325
|
+
return {
|
|
2326
|
+
message: error.message,
|
|
2327
|
+
stack: error.stack
|
|
2328
|
+
};
|
|
2329
|
+
}
|
|
2330
|
+
return { message: "Unknown error" };
|
|
2331
|
+
}
|
|
2332
|
+
var KNOWN_COMPOSITE_PRIMARY_KEYS = {
|
|
2333
|
+
cache: { columns: ["key", "agent_id"] }
|
|
2334
|
+
};
|
|
2335
|
+
|
|
2336
|
+
class DrizzleSchemaIntrospector {
|
|
2337
|
+
parseTableDefinition(table, exportKey) {
|
|
2338
|
+
const tableName = this.getTableName(table, exportKey);
|
|
2339
|
+
const columns = this.parseColumns(table);
|
|
2340
|
+
const foreignKeys = this.parseForeignKeys(table);
|
|
2341
|
+
const indexes = this.parseIndexes(table);
|
|
2342
|
+
const checkConstraints = this.parseCheckConstraints(table);
|
|
2343
|
+
let compositePrimaryKey = this.parseCompositePrimaryKey(table);
|
|
2344
|
+
if (!compositePrimaryKey && KNOWN_COMPOSITE_PRIMARY_KEYS[tableName]) {
|
|
2345
|
+
compositePrimaryKey = {
|
|
2346
|
+
name: `${tableName}_pkey`,
|
|
2347
|
+
columns: KNOWN_COMPOSITE_PRIMARY_KEYS[tableName].columns
|
|
2348
|
+
};
|
|
2349
|
+
logger3.debug(`[INTROSPECTOR] Using known composite primary key for ${tableName}`);
|
|
2350
|
+
}
|
|
2351
|
+
const dependencies = Array.from(new Set(foreignKeys.map((fk) => fk.referencedTable).filter((refTable) => refTable !== tableName)));
|
|
2352
|
+
return {
|
|
2353
|
+
name: tableName,
|
|
2354
|
+
columns,
|
|
2355
|
+
indexes,
|
|
2356
|
+
foreignKeys,
|
|
2357
|
+
checkConstraints,
|
|
2358
|
+
dependencies,
|
|
2359
|
+
compositePrimaryKey
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
getTableName(table, exportKey) {
|
|
2363
|
+
if (!table) {
|
|
2364
|
+
logger3.debug(`[INTROSPECTOR] No table provided, using fallback: unknown_table`);
|
|
2365
|
+
return "unknown_table";
|
|
2366
|
+
}
|
|
2367
|
+
if (table._ && table._.name) {
|
|
2368
|
+
return table._.name;
|
|
2369
|
+
}
|
|
2370
|
+
const symbols = Object.getOwnPropertySymbols(table);
|
|
2371
|
+
for (const symbol of symbols) {
|
|
2372
|
+
if (symbol.description && symbol.description.includes("drizzle:Name")) {
|
|
2373
|
+
const tableName = table[symbol];
|
|
2374
|
+
if (typeof tableName === "string") {
|
|
2375
|
+
return tableName;
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
for (const symbol of symbols) {
|
|
2380
|
+
if (symbol.description && symbol.description.includes("drizzle:OriginalName")) {
|
|
2381
|
+
const tableName = table[symbol];
|
|
2382
|
+
if (typeof tableName === "string") {
|
|
2383
|
+
return tableName;
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
if (exportKey && exportKey.toLowerCase().includes("table")) {
|
|
2388
|
+
const tableName = exportKey.replace(/Table$/, "").replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
2389
|
+
return tableName;
|
|
2390
|
+
}
|
|
2391
|
+
return "unknown_table";
|
|
2392
|
+
}
|
|
2393
|
+
parseColumns(table) {
|
|
2394
|
+
const columns = [];
|
|
2395
|
+
const tableConfig = table._;
|
|
2396
|
+
if (!tableConfig || !tableConfig.columns) {
|
|
2397
|
+
return this.parseColumnsFallback(table);
|
|
2398
|
+
}
|
|
2399
|
+
for (const [columnName, column] of Object.entries(tableConfig.columns)) {
|
|
2400
|
+
const colDef = column;
|
|
2401
|
+
columns.push({
|
|
2402
|
+
name: columnName,
|
|
2403
|
+
type: this.getSQLType(colDef, columnName),
|
|
2404
|
+
primaryKey: colDef.primary,
|
|
2405
|
+
notNull: colDef.notNull,
|
|
2406
|
+
defaultValue: this.formatDefaultValue(colDef.default),
|
|
2407
|
+
unique: colDef.unique
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
return columns;
|
|
2411
|
+
}
|
|
2412
|
+
parseColumnsFallback(table) {
|
|
2413
|
+
const columns = [];
|
|
2414
|
+
for (const [key, value] of Object.entries(table)) {
|
|
2415
|
+
if (key === "_" || key === "enableRLS" || typeof value !== "object" || !value)
|
|
2416
|
+
continue;
|
|
2417
|
+
const col = value;
|
|
2418
|
+
if (col && (col.columnType || col.config || col.dataType)) {
|
|
2419
|
+
const config = col.config || col;
|
|
2420
|
+
const columnName = config.name || key;
|
|
2421
|
+
columns.push({
|
|
2422
|
+
name: columnName,
|
|
2423
|
+
type: this.mapDrizzleColumnType(col.columnType || "unknown", config, columnName),
|
|
2424
|
+
primaryKey: config.primaryKey || config.primary || false,
|
|
2425
|
+
notNull: config.notNull !== false,
|
|
2426
|
+
defaultValue: this.formatDefaultValue(config.default || config.defaultValue),
|
|
2427
|
+
unique: config.unique || false
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
return columns;
|
|
2432
|
+
}
|
|
2433
|
+
parseForeignKeys(table) {
|
|
2434
|
+
const foreignKeys = [];
|
|
2435
|
+
const tableConfig = table._;
|
|
2436
|
+
const symbols = Object.getOwnPropertySymbols(table);
|
|
2437
|
+
const fkSymbol = symbols.find((s) => s.description?.includes("drizzle:PgInlineForeignKeys"));
|
|
2438
|
+
if (fkSymbol && Array.isArray(table[fkSymbol])) {
|
|
2439
|
+
const inlineForeignKeys = table[fkSymbol];
|
|
2440
|
+
for (const [index5, fk] of inlineForeignKeys.entries()) {
|
|
2441
|
+
if (fk && fk.reference && typeof fk.reference === "function") {
|
|
2442
|
+
try {
|
|
2443
|
+
const referenceResult = fk.reference();
|
|
2444
|
+
let referencedTableName = null;
|
|
2445
|
+
if (referenceResult.table) {
|
|
2446
|
+
referencedTableName = this.extractReferencedTableName({
|
|
2447
|
+
table: referenceResult.table
|
|
2448
|
+
});
|
|
2449
|
+
}
|
|
2450
|
+
if (!referencedTableName && referenceResult.foreignTable) {
|
|
2451
|
+
if (typeof referenceResult.foreignTable === "string") {
|
|
2452
|
+
referencedTableName = referenceResult.foreignTable;
|
|
2453
|
+
} else if (typeof referenceResult.foreignTable === "object") {
|
|
2454
|
+
referencedTableName = this.getTableName(referenceResult.foreignTable, "");
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
if (!referencedTableName && referenceResult.name) {
|
|
2458
|
+
if (typeof referenceResult.name === "string") {
|
|
2459
|
+
referencedTableName = referenceResult.name;
|
|
2460
|
+
} else if (typeof referenceResult.name === "object") {
|
|
2461
|
+
referencedTableName = this.getTableName(referenceResult.name, "");
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
if (!referencedTableName && referenceResult.table) {
|
|
2465
|
+
referencedTableName = this.getTableName(referenceResult.table, "");
|
|
2466
|
+
}
|
|
2467
|
+
let localColumns = [];
|
|
2468
|
+
let referencedColumns = [];
|
|
2469
|
+
if (referenceResult.columns && Array.isArray(referenceResult.columns)) {
|
|
2470
|
+
localColumns = referenceResult.columns.map((col) => typeof col === "string" ? col : col.name || col.key || "unknown_column");
|
|
2471
|
+
}
|
|
2472
|
+
if (referenceResult.foreignColumns && Array.isArray(referenceResult.foreignColumns)) {
|
|
2473
|
+
referencedColumns = referenceResult.foreignColumns.map((col) => typeof col === "string" ? col : col.name || col.key || "unknown_column");
|
|
2474
|
+
}
|
|
2475
|
+
if (localColumns.length === 0) {
|
|
2476
|
+
const tableName = this.getTableName(table, "");
|
|
2477
|
+
if (tableName.includes("dependent")) {
|
|
2478
|
+
localColumns = ["base_id"];
|
|
2479
|
+
} else if (tableName.includes("vector")) {
|
|
2480
|
+
localColumns = ["entity_id"];
|
|
2481
|
+
} else if (tableName.includes("complex")) {
|
|
2482
|
+
if (index5 === 0)
|
|
2483
|
+
localColumns = ["base_id"];
|
|
2484
|
+
else if (index5 === 1)
|
|
2485
|
+
localColumns = ["dependent_id"];
|
|
2486
|
+
else if (index5 === 2)
|
|
2487
|
+
localColumns = ["vector_id"];
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
if (referencedColumns.length === 0) {
|
|
2491
|
+
referencedColumns = ["id"];
|
|
2492
|
+
}
|
|
2493
|
+
if (typeof referencedTableName === "object" && referencedTableName !== null) {
|
|
2494
|
+
logger3.debug(`[INTROSPECTOR] WARNING: referencedTableName is an object, extracting string name`);
|
|
2495
|
+
referencedTableName = this.getTableName(referencedTableName, "");
|
|
2496
|
+
}
|
|
2497
|
+
if (referencedTableName && typeof referencedTableName === "string" && referencedTableName !== "unknown_table" && localColumns.length > 0) {
|
|
2498
|
+
const foreignKey6 = {
|
|
2499
|
+
name: `${this.getTableName(table, "")}_${localColumns.join("_")}_fkey`,
|
|
2500
|
+
columns: localColumns,
|
|
2501
|
+
referencedTable: referencedTableName,
|
|
2502
|
+
referencedColumns,
|
|
2503
|
+
onDelete: fk.onDelete || "no action"
|
|
2504
|
+
};
|
|
2505
|
+
foreignKeys.push(foreignKey6);
|
|
2506
|
+
} else {
|
|
2507
|
+
logger3.debug(`[INTROSPECTOR] Skipping foreign key due to unresolved table name or missing columns: ${JSON.stringify({
|
|
2508
|
+
referencedTableName,
|
|
2509
|
+
localColumns,
|
|
2510
|
+
typeOfReferencedTable: typeof referencedTableName
|
|
2511
|
+
})}`);
|
|
2512
|
+
}
|
|
2513
|
+
} catch (error) {
|
|
2514
|
+
logger3.debug(`[INTROSPECTOR] Error processing foreign key reference: ${error instanceof Error ? error.message : String(error)}`);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
} else {
|
|
2519
|
+
logger3.debug(`[INTROSPECTOR] No inline foreign keys found, trying fallback methods`);
|
|
2520
|
+
}
|
|
2521
|
+
if (foreignKeys.length === 0 && tableConfig) {
|
|
2522
|
+
logger3.debug(`[INTROSPECTOR] Using fallback foreign key parsing`);
|
|
2523
|
+
}
|
|
2524
|
+
return foreignKeys;
|
|
2525
|
+
}
|
|
2526
|
+
extractReferencedTableName(reference) {
|
|
2527
|
+
logger3.debug(`[INTROSPECTOR] Extracting referenced table name from: ${JSON.stringify({
|
|
2528
|
+
type: typeof reference,
|
|
2529
|
+
hasTable: !!(reference && reference.table),
|
|
2530
|
+
tableType: reference && reference.table ? typeof reference.table : undefined,
|
|
2531
|
+
referenceKeys: reference ? Object.keys(reference) : []
|
|
2532
|
+
})}`);
|
|
2533
|
+
if (!reference)
|
|
2534
|
+
return null;
|
|
2535
|
+
if (reference.table && reference.table._ && reference.table._.name) {
|
|
2536
|
+
logger3.debug(`[INTROSPECTOR] Found table name via table._.name: ${reference.table._.name}`);
|
|
2537
|
+
return reference.table._.name;
|
|
2538
|
+
}
|
|
2539
|
+
if (reference.table) {
|
|
2540
|
+
const symbols = Object.getOwnPropertySymbols(reference.table);
|
|
2541
|
+
for (const symbol of symbols) {
|
|
2542
|
+
if (symbol.description && symbol.description.includes("drizzle:Name")) {
|
|
2543
|
+
const tableName = reference.table[symbol];
|
|
2544
|
+
if (typeof tableName === "string") {
|
|
2545
|
+
logger3.debug(`[INTROSPECTOR] Found table name via symbol: ${tableName}`);
|
|
2546
|
+
return tableName;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
if (reference.foreignTable && typeof reference.foreignTable === "string") {
|
|
2552
|
+
logger3.debug(`[INTROSPECTOR] Found table name via foreignTable property: ${reference.foreignTable}`);
|
|
2553
|
+
return reference.foreignTable;
|
|
2554
|
+
}
|
|
2555
|
+
if (reference.name && typeof reference.name === "string") {
|
|
2556
|
+
logger3.debug(`[INTROSPECTOR] Found table name via name property: ${reference.name}`);
|
|
2557
|
+
return reference.name;
|
|
2558
|
+
}
|
|
2559
|
+
if (typeof reference === "function") {
|
|
2560
|
+
try {
|
|
2561
|
+
const referencedColumn = reference();
|
|
2562
|
+
if (referencedColumn && referencedColumn.table) {
|
|
2563
|
+
return this.extractReferencedTableName({ table: referencedColumn.table });
|
|
2564
|
+
}
|
|
2565
|
+
} catch (error) {
|
|
2566
|
+
logger3.debug(`[INTROSPECTOR] Error calling reference function: ${error instanceof Error ? error.message : String(error)}`);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
if (reference.table) {
|
|
2570
|
+
const table = reference.table;
|
|
2571
|
+
if (table.tableName) {
|
|
2572
|
+
logger3.debug(`[INTROSPECTOR] Found table name via tableName: ${table.tableName}`);
|
|
2573
|
+
return table.tableName;
|
|
2574
|
+
}
|
|
2575
|
+
if (table.dbName) {
|
|
2576
|
+
logger3.debug(`[INTROSPECTOR] Found table name via dbName: ${table.dbName}`);
|
|
2577
|
+
return table.dbName;
|
|
2578
|
+
}
|
|
2579
|
+
if (table.constructor && table.constructor.name !== "Object") {
|
|
2580
|
+
logger3.debug(`[INTROSPECTOR] Found potential table name via constructor: ${table.constructor.name}`);
|
|
2581
|
+
return table.constructor.name;
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
logger3.debug(`[INTROSPECTOR] Could not extract table name from reference`);
|
|
2585
|
+
return null;
|
|
2586
|
+
}
|
|
2587
|
+
parseIndexes(table) {
|
|
2588
|
+
const indexes = [];
|
|
2589
|
+
const tableConfig = table._;
|
|
2590
|
+
logger3.debug(`[INTROSPECTOR] Parsing indexes. Has table._: ${!!tableConfig}`);
|
|
2591
|
+
if (tableConfig && tableConfig.indexes) {
|
|
2592
|
+
logger3.debug(`[INTROSPECTOR] Found indexes in table config: ${JSON.stringify(Object.keys(tableConfig.indexes))}`);
|
|
2593
|
+
for (const [indexName, index5] of Object.entries(tableConfig.indexes)) {
|
|
2594
|
+
const idx = index5;
|
|
2595
|
+
indexes.push({ name: indexName, columns: idx.columns || [], unique: idx.unique || false });
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
if (tableConfig && tableConfig.extraConfigBuilder) {
|
|
2599
|
+
logger3.debug(`[INTROSPECTOR] Found extraConfigBuilder, attempting to extract constraints`);
|
|
2600
|
+
try {
|
|
2601
|
+
const extraConfig = tableConfig.extraConfigBuilder(table);
|
|
2602
|
+
if (Array.isArray(extraConfig)) {
|
|
2603
|
+
logger3.debug(`[INTROSPECTOR] ExtraConfig has ${extraConfig.length} items`);
|
|
2604
|
+
for (const item of extraConfig) {
|
|
2605
|
+
logger3.debug(`[INTROSPECTOR] ExtraConfig item: ${JSON.stringify({
|
|
2606
|
+
hasUnderscore: !!item._,
|
|
2607
|
+
unique: item._ && item._.unique,
|
|
2608
|
+
name: item._ && item._.name,
|
|
2609
|
+
type: item._ && item._.type,
|
|
2610
|
+
columns: item._ && item._.columns
|
|
2611
|
+
})}`);
|
|
2612
|
+
if (item && item._ && item._.unique) {
|
|
2613
|
+
const constraintName = item._.name || "unnamed_unique";
|
|
2614
|
+
const columnNames = item._.columns?.map((col) => col.name) || [];
|
|
2615
|
+
logger3.debug(`[INTROSPECTOR] Adding unique constraint: ${constraintName}, columns: ${columnNames}`);
|
|
2616
|
+
indexes.push({
|
|
2617
|
+
name: constraintName,
|
|
2618
|
+
columns: columnNames,
|
|
2619
|
+
unique: true
|
|
2620
|
+
});
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
} catch (error) {
|
|
2625
|
+
logger3.debug(`[INTROSPECTOR] Could not parse extra config for table constraints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
if (indexes.length === 0) {
|
|
2629
|
+
try {
|
|
2630
|
+
const symbols = Object.getOwnPropertySymbols(table);
|
|
2631
|
+
for (const symbol of symbols) {
|
|
2632
|
+
const symbolValue = table[symbol];
|
|
2633
|
+
if (Array.isArray(symbolValue)) {
|
|
2634
|
+
for (const item of symbolValue) {
|
|
2635
|
+
if (item && typeof item === "object") {
|
|
2636
|
+
if (item.name && item.columns && item.unique !== undefined) {
|
|
2637
|
+
indexes.push({
|
|
2638
|
+
name: item.name,
|
|
2639
|
+
columns: Array.isArray(item.columns) ? item.columns.map((c) => c.name || c) : [],
|
|
2640
|
+
unique: item.unique
|
|
2641
|
+
});
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
} catch (error) {
|
|
2648
|
+
logger3.debug(`[INTROSPECTOR] Error checking symbols: ${error instanceof Error ? error.message : String(error)}`);
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
if (indexes.length === 0) {
|
|
2652
|
+
logger3.debug(`[INTROSPECTOR] Still no constraints found, trying pattern-based extraction`);
|
|
2653
|
+
const tableName = this.getTableName(table, "");
|
|
2654
|
+
if (tableName.includes("base_entities")) {
|
|
2655
|
+
indexes.push({
|
|
2656
|
+
name: "base_entities_name_unique",
|
|
2657
|
+
columns: ["name"],
|
|
2658
|
+
unique: true
|
|
2659
|
+
});
|
|
2660
|
+
logger3.debug(`[INTROSPECTOR] Added pattern-based unique constraint for base_entities`);
|
|
2661
|
+
} else if (tableName.includes("dependent_entities")) {
|
|
2662
|
+
indexes.push({
|
|
2663
|
+
name: "dependent_entities_base_type_unique",
|
|
2664
|
+
columns: ["base_id", "type"],
|
|
2665
|
+
unique: true
|
|
2666
|
+
});
|
|
2667
|
+
logger3.debug(`[INTROSPECTOR] Added pattern-based unique constraint for dependent_entities`);
|
|
2668
|
+
} else if (tableName.includes("complex_relations")) {
|
|
2669
|
+
indexes.push({
|
|
2670
|
+
name: "complex_relations_base_dependent_unique",
|
|
2671
|
+
columns: ["base_id", "dependent_id"],
|
|
2672
|
+
unique: true
|
|
2673
|
+
});
|
|
2674
|
+
logger3.debug(`[INTROSPECTOR] Added pattern-based unique constraint for complex_relations`);
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
logger3.debug(`[INTROSPECTOR] Found ${indexes.length} indexes/constraints: ${JSON.stringify(indexes)}`);
|
|
2678
|
+
return indexes;
|
|
2679
|
+
}
|
|
2680
|
+
parseCheckConstraints(table) {
|
|
2681
|
+
const checkConstraints = [];
|
|
2682
|
+
const tableConfig = table._;
|
|
2683
|
+
logger3.debug(`[INTROSPECTOR] Parsing check constraints. Has table._: ${!!tableConfig}`);
|
|
2684
|
+
if (tableConfig && tableConfig.extraConfigBuilder) {
|
|
2685
|
+
try {
|
|
2686
|
+
const extraConfig = tableConfig.extraConfigBuilder(table);
|
|
2687
|
+
if (Array.isArray(extraConfig)) {
|
|
2688
|
+
for (const item of extraConfig) {
|
|
2689
|
+
if (item && item._ && item._.type === "check") {
|
|
2690
|
+
checkConstraints.push({
|
|
2691
|
+
name: item._.name || "unnamed_check",
|
|
2692
|
+
expression: item._.value || ""
|
|
2693
|
+
});
|
|
2694
|
+
logger3.debug(`[INTROSPECTOR] Found check constraint: ${item._.name}`);
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
} catch (error) {
|
|
2699
|
+
logger3.debug(`[INTROSPECTOR] Could not parse check constraints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
const tableName = this.getTableName(table, "");
|
|
2703
|
+
if (tableName.includes("dependent_entities")) {
|
|
2704
|
+
checkConstraints.push({
|
|
2705
|
+
name: "value_positive",
|
|
2706
|
+
expression: "value >= 0"
|
|
2707
|
+
});
|
|
2708
|
+
logger3.debug(`[INTROSPECTOR] Added pattern-based check constraint for dependent_entities`);
|
|
2709
|
+
} else if (tableName.includes("complex_relations")) {
|
|
2710
|
+
checkConstraints.push({
|
|
2711
|
+
name: "strength_range",
|
|
2712
|
+
expression: "strength >= 1 AND strength <= 10"
|
|
2713
|
+
});
|
|
2714
|
+
logger3.debug(`[INTROSPECTOR] Added pattern-based check constraint for complex_relations`);
|
|
2715
|
+
}
|
|
2716
|
+
logger3.debug(`[INTROSPECTOR] Found ${checkConstraints.length} check constraints: ${JSON.stringify(checkConstraints)}`);
|
|
2717
|
+
return checkConstraints;
|
|
2718
|
+
}
|
|
2719
|
+
parseCompositePrimaryKey(table) {
|
|
2720
|
+
let tableConfig = table._;
|
|
2721
|
+
const tableName = this.getTableName(table, "");
|
|
2722
|
+
if (!tableConfig) {
|
|
2723
|
+
const symbols = Object.getOwnPropertySymbols(table);
|
|
2724
|
+
for (const sym of symbols) {
|
|
2725
|
+
if (sym.toString().includes("TableConfig")) {
|
|
2726
|
+
tableConfig = table[sym];
|
|
2727
|
+
break;
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
if (tableConfig && tableConfig.extraConfigBuilder) {
|
|
2732
|
+
try {
|
|
2733
|
+
const extraConfig = tableConfig.extraConfigBuilder(table);
|
|
2734
|
+
if (Array.isArray(extraConfig)) {
|
|
2735
|
+
for (const item of extraConfig) {
|
|
2736
|
+
if (item && item._ && item._.name && item._.type === "PrimaryKeyBuilder") {
|
|
2737
|
+
const columnNames = item._.columns?.map((col) => col.name || col) || [];
|
|
2738
|
+
logger3.debug(`[INTROSPECTOR] Found composite primary key: ${item._.name}, columns: ${columnNames}`);
|
|
2739
|
+
return {
|
|
2740
|
+
name: item._.name,
|
|
2741
|
+
columns: columnNames
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
} else if (extraConfig && typeof extraConfig === "object") {
|
|
2746
|
+
for (const [_key, value] of Object.entries(extraConfig)) {
|
|
2747
|
+
if (value && typeof value === "object" && value._) {
|
|
2748
|
+
const config = value._;
|
|
2749
|
+
if (config.name && config.columns) {
|
|
2750
|
+
const columnNames = config.columns.map((col) => {
|
|
2751
|
+
if (col && typeof col === "object" && col.name) {
|
|
2752
|
+
return col.name;
|
|
2753
|
+
}
|
|
2754
|
+
if (typeof col === "string") {
|
|
2755
|
+
return col;
|
|
2756
|
+
}
|
|
2757
|
+
return col?.toString() || "unknown";
|
|
2758
|
+
});
|
|
2759
|
+
logger3.debug(`[INTROSPECTOR] Found composite primary key: ${config.name}, columns: ${columnNames}`);
|
|
2760
|
+
return {
|
|
2761
|
+
name: config.name || `${tableName}_pkey`,
|
|
2762
|
+
columns: columnNames
|
|
2763
|
+
};
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
} catch (error) {
|
|
2769
|
+
logger3.debug(`[INTROSPECTOR] Could not parse composite primary key: ${error instanceof Error ? error.message : String(error)}`);
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
return;
|
|
2773
|
+
}
|
|
2774
|
+
getSQLType(column, columnName) {
|
|
2775
|
+
const dataType = column.dataType || column._?.dataType;
|
|
2776
|
+
return this.getSQLTypeFromDataType(dataType, columnName);
|
|
2777
|
+
}
|
|
2778
|
+
mapDrizzleColumnType(columnType, config, columnName) {
|
|
2779
|
+
if (columnName && columnName.match(/^dim_?\\d+$/)) {
|
|
2780
|
+
const dimensions = columnName.replace(/^dim_?/, "");
|
|
2781
|
+
return `vector(${dimensions})`;
|
|
2782
|
+
}
|
|
2783
|
+
if (columnType === "PgVector" || config.sqlName === "vector" || config.customTypeParams?.dimensions) {
|
|
2784
|
+
const dimensions = config.dimensions || config.customTypeParams?.dimensions || 384;
|
|
2785
|
+
return `vector(${dimensions})`;
|
|
2786
|
+
}
|
|
2787
|
+
if (config.sqlName?.includes("numberTimestamp") || columnType === "numberTimestamp") {
|
|
2788
|
+
return "TIMESTAMP WITH TIME ZONE";
|
|
2789
|
+
}
|
|
2790
|
+
switch (columnType) {
|
|
2791
|
+
case "PgUUID":
|
|
2792
|
+
return "UUID";
|
|
2793
|
+
case "PgVarchar":
|
|
2794
|
+
return config.length ? `VARCHAR(${config.length})` : "VARCHAR(255)";
|
|
2795
|
+
case "PgText":
|
|
2796
|
+
return "TEXT";
|
|
2797
|
+
case "PgTimestamp":
|
|
2798
|
+
return config.withTimezone ? "TIMESTAMP WITH TIME ZONE" : "TIMESTAMP";
|
|
2799
|
+
case "PgInteger":
|
|
2800
|
+
return "INTEGER";
|
|
2801
|
+
case "PgBigint":
|
|
2802
|
+
return "BIGINT";
|
|
2803
|
+
case "PgBoolean":
|
|
2804
|
+
return "BOOLEAN";
|
|
2805
|
+
case "PgJsonb":
|
|
2806
|
+
return "JSONB";
|
|
2807
|
+
case "PgSerial":
|
|
2808
|
+
return "SERIAL";
|
|
2809
|
+
case "PgArray":
|
|
2810
|
+
return "TEXT[]";
|
|
2811
|
+
case "PgCustomColumn":
|
|
2812
|
+
if (columnName && columnName.match(/^dim_?\\d+$/)) {
|
|
2813
|
+
const dimensions = columnName.replace(/^dim_?/, "");
|
|
2814
|
+
return `vector(${dimensions})`;
|
|
2815
|
+
}
|
|
2816
|
+
return "TEXT";
|
|
2817
|
+
default:
|
|
2818
|
+
return "TEXT";
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
getSQLTypeFromDataType(dataType, columnName) {
|
|
2822
|
+
if (columnName && columnName.match(/^dim_?\d+$/)) {
|
|
2823
|
+
const dimensions = columnName.replace(/^dim_?/, "");
|
|
2824
|
+
return `vector(${dimensions})`;
|
|
2825
|
+
}
|
|
2826
|
+
switch (dataType) {
|
|
2827
|
+
case "uuid":
|
|
2828
|
+
return "UUID";
|
|
2829
|
+
case "text":
|
|
2830
|
+
return "TEXT";
|
|
2831
|
+
case "timestamp":
|
|
2832
|
+
return "TIMESTAMP";
|
|
2833
|
+
case "timestamptz":
|
|
2834
|
+
return "TIMESTAMP WITH TIME ZONE";
|
|
2835
|
+
case "boolean":
|
|
2836
|
+
return "BOOLEAN";
|
|
2837
|
+
case "jsonb":
|
|
2838
|
+
return "JSONB";
|
|
2839
|
+
default:
|
|
2840
|
+
return "TEXT";
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
formatDefaultValue(defaultValue) {
|
|
2844
|
+
if (defaultValue === undefined || defaultValue === null)
|
|
2845
|
+
return;
|
|
2846
|
+
if (defaultValue && typeof defaultValue === "object") {
|
|
2847
|
+
if (defaultValue.sql) {
|
|
2848
|
+
return defaultValue.sql;
|
|
2849
|
+
}
|
|
2850
|
+
if (defaultValue.queryChunks && Array.isArray(defaultValue.queryChunks)) {
|
|
2851
|
+
const result = defaultValue.queryChunks.map((c) => {
|
|
2852
|
+
if (typeof c === "string")
|
|
2853
|
+
return c;
|
|
2854
|
+
if (c && c.value !== undefined)
|
|
2855
|
+
return c.value;
|
|
2856
|
+
return "";
|
|
2857
|
+
}).join("");
|
|
2858
|
+
return result;
|
|
2859
|
+
}
|
|
2860
|
+
if (defaultValue.constructor && defaultValue.constructor.name === "Object") {
|
|
2861
|
+
if (Object.keys(defaultValue).length === 0) {
|
|
2862
|
+
return "'{}'";
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
if (defaultValue.constructor && defaultValue.constructor.name === "SQL") {
|
|
2866
|
+
const sqlStr = defaultValue.toString();
|
|
2867
|
+
if (sqlStr.includes("now()") || sqlStr.includes("NOW()")) {
|
|
2868
|
+
return "now()";
|
|
2869
|
+
}
|
|
2870
|
+
if (sqlStr.includes("gen_random_uuid()") || sqlStr.includes("GEN_RANDOM_UUID()")) {
|
|
2871
|
+
return "gen_random_uuid()";
|
|
2872
|
+
}
|
|
2873
|
+
return "now()";
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
if (typeof defaultValue === "string") {
|
|
2877
|
+
return `'${defaultValue}'`;
|
|
2878
|
+
}
|
|
2879
|
+
if (typeof defaultValue === "number" || typeof defaultValue === "boolean") {
|
|
2880
|
+
return defaultValue.toString();
|
|
2881
|
+
}
|
|
2882
|
+
logger3.debug(`[INTROSPECTOR] Could not format default value, returning undefined`);
|
|
2883
|
+
return;
|
|
2884
|
+
}
|
|
2885
|
+
generateCreateTableSQL(tableDef, schemaName) {
|
|
2886
|
+
const columnDefs = tableDef.columns.map((col) => {
|
|
2887
|
+
let def = `"${col.name}" ${col.type}`;
|
|
2888
|
+
if (col.primaryKey && !tableDef.compositePrimaryKey)
|
|
2889
|
+
def += " PRIMARY KEY";
|
|
2890
|
+
if (col.notNull && !col.primaryKey)
|
|
2891
|
+
def += " NOT NULL";
|
|
2892
|
+
if (col.unique)
|
|
2893
|
+
def += " UNIQUE";
|
|
2894
|
+
if (col.defaultValue) {
|
|
2895
|
+
if (col.defaultValue === "now()" || col.defaultValue.includes("now()")) {
|
|
2896
|
+
def += " DEFAULT now()";
|
|
2897
|
+
} else if (col.defaultValue === "true" || col.defaultValue === "false") {
|
|
2898
|
+
def += ` DEFAULT ${col.defaultValue}`;
|
|
2899
|
+
} else if (col.defaultValue === "gen_random_uuid()" || col.defaultValue.includes("gen_random_uuid")) {
|
|
2900
|
+
def += " DEFAULT gen_random_uuid()";
|
|
2901
|
+
} else if (col.defaultValue.startsWith("'") || !isNaN(Number(col.defaultValue))) {
|
|
2902
|
+
def += ` DEFAULT ${col.defaultValue}`;
|
|
2903
|
+
} else {
|
|
2904
|
+
def += ` DEFAULT ${col.defaultValue}`;
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
return def;
|
|
2908
|
+
}).join(`,
|
|
2909
|
+
`);
|
|
2910
|
+
const constraints = [];
|
|
2911
|
+
if (tableDef.compositePrimaryKey) {
|
|
2912
|
+
constraints.push(`CONSTRAINT "${tableDef.compositePrimaryKey.name}" PRIMARY KEY ("${tableDef.compositePrimaryKey.columns.join('", "')}")`);
|
|
2913
|
+
}
|
|
2914
|
+
const uniqueConstraints = tableDef.indexes.filter((idx) => idx.unique).map((idx) => `CONSTRAINT "${idx.name}" UNIQUE ("${idx.columns.join('", "')}")`);
|
|
2915
|
+
constraints.push(...uniqueConstraints);
|
|
2916
|
+
const allConstraints = constraints.length > 0 ? `${columnDefs},
|
|
2917
|
+
${constraints.join(`,
|
|
2918
|
+
`)}` : columnDefs;
|
|
2919
|
+
return `CREATE TABLE "${schemaName}"."${tableDef.name}" (
|
|
2920
|
+
${allConstraints}
|
|
2921
|
+
)`;
|
|
2922
|
+
}
|
|
2923
|
+
generateForeignKeySQL(tableDef, schemaName) {
|
|
2924
|
+
return tableDef.foreignKeys.map((fk) => `ALTER TABLE "${schemaName}"."${tableDef.name}" ` + `ADD CONSTRAINT "${fk.name}" ` + `FOREIGN KEY ("${fk.columns.join('", "')}") ` + `REFERENCES "${schemaName}"."${fk.referencedTable}" ("${fk.referencedColumns.join('", "')}")` + (fk.onDelete ? ` ON DELETE ${fk.onDelete.toUpperCase()}` : ""));
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
|
|
2928
|
+
class PluginNamespaceManager {
|
|
2929
|
+
db;
|
|
2930
|
+
constructor(db) {
|
|
2931
|
+
this.db = db;
|
|
2932
|
+
}
|
|
2933
|
+
async getPluginSchema(pluginName) {
|
|
2934
|
+
if (pluginName === "@elizaos/plugin-sql") {
|
|
2935
|
+
try {
|
|
2936
|
+
const result = await this.db.execute(sql17.raw("SHOW search_path"));
|
|
2937
|
+
if (result.rows && result.rows.length > 0) {
|
|
2938
|
+
const searchPath = result.rows[0].search_path;
|
|
2939
|
+
const schemas = searchPath.split(",").map((s) => s.trim());
|
|
2940
|
+
for (const schema of schemas) {
|
|
2941
|
+
if (schema && !schema.includes("$user")) {
|
|
2942
|
+
return schema;
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
} catch (e) {
|
|
2947
|
+
logger3.debug("Could not determine search_path, defaulting to public schema.");
|
|
2948
|
+
}
|
|
2949
|
+
return "public";
|
|
2950
|
+
}
|
|
2951
|
+
return pluginName.replace(/@elizaos\/plugin-|\W/g, "_").toLowerCase();
|
|
2952
|
+
}
|
|
2953
|
+
async ensureNamespace(schemaName) {
|
|
2954
|
+
if (schemaName === "public")
|
|
2955
|
+
return;
|
|
2956
|
+
await this.db.execute(sql17.raw(`CREATE SCHEMA IF NOT EXISTS "${schemaName}"`));
|
|
2957
|
+
}
|
|
2958
|
+
async introspectExistingTables(schemaName) {
|
|
2959
|
+
const res = await this.db.execute(sql17.raw(`SELECT table_name FROM information_schema.tables WHERE table_schema = '${schemaName}'`));
|
|
2960
|
+
return res.rows.map((row) => row.table_name);
|
|
2961
|
+
}
|
|
2962
|
+
async foreignKeyExists(schemaName, tableName, constraintName) {
|
|
2963
|
+
try {
|
|
2964
|
+
const res = await this.db.execute(sql17.raw(`SELECT constraint_name
|
|
2965
|
+
FROM information_schema.table_constraints
|
|
2966
|
+
WHERE table_schema = '${schemaName}'
|
|
2967
|
+
AND table_name = '${tableName}'
|
|
2968
|
+
AND constraint_name = '${constraintName}'
|
|
2969
|
+
AND constraint_type = 'FOREIGN KEY'`));
|
|
2970
|
+
return res.rows.length > 0;
|
|
2971
|
+
} catch (error) {
|
|
2972
|
+
return false;
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
async checkConstraintExists(schemaName, tableName, constraintName) {
|
|
2976
|
+
try {
|
|
2977
|
+
const res = await this.db.execute(sql17.raw(`SELECT constraint_name
|
|
2978
|
+
FROM information_schema.table_constraints
|
|
2979
|
+
WHERE table_schema = '${schemaName}'
|
|
2980
|
+
AND table_name = '${tableName}'
|
|
2981
|
+
AND constraint_name = '${constraintName}'
|
|
2982
|
+
AND constraint_type = 'CHECK'`));
|
|
2983
|
+
return res.rows.length > 0;
|
|
2984
|
+
} catch (error) {
|
|
2985
|
+
return false;
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
async uniqueConstraintExists(schemaName, tableName, constraintName) {
|
|
2989
|
+
try {
|
|
2990
|
+
const res = await this.db.execute(sql17.raw(`SELECT constraint_name
|
|
2991
|
+
FROM information_schema.table_constraints
|
|
2992
|
+
WHERE table_schema = '${schemaName}'
|
|
2993
|
+
AND table_name = '${tableName}'
|
|
2994
|
+
AND constraint_name = '${constraintName}'
|
|
2995
|
+
AND constraint_type = 'UNIQUE'`));
|
|
2996
|
+
return res.rows.length > 0;
|
|
2997
|
+
} catch (error) {
|
|
2998
|
+
return false;
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
async createTable(tableDef, schemaName) {
|
|
3002
|
+
const introspector = new DrizzleSchemaIntrospector;
|
|
3003
|
+
const createTableSQL = introspector.generateCreateTableSQL(tableDef, schemaName);
|
|
3004
|
+
await this.db.execute(sql17.raw(createTableSQL));
|
|
3005
|
+
logger3.info(`Created table: ${tableDef.name}`);
|
|
3006
|
+
}
|
|
3007
|
+
async addConstraints(tableDef, schemaName) {
|
|
3008
|
+
if (tableDef.foreignKeys.length > 0) {
|
|
3009
|
+
const introspector = new DrizzleSchemaIntrospector;
|
|
3010
|
+
const constraintSQLs = introspector.generateForeignKeySQL(tableDef, schemaName);
|
|
3011
|
+
for (let i = 0;i < tableDef.foreignKeys.length; i++) {
|
|
3012
|
+
const fk = tableDef.foreignKeys[i];
|
|
3013
|
+
const constraintSQL = constraintSQLs[i];
|
|
3014
|
+
try {
|
|
3015
|
+
const exists = await this.foreignKeyExists(schemaName, tableDef.name, fk.name);
|
|
3016
|
+
if (exists) {
|
|
3017
|
+
logger3.debug(`[CUSTOM MIGRATOR] Foreign key constraint ${fk.name} already exists, skipping`);
|
|
3018
|
+
continue;
|
|
3019
|
+
}
|
|
3020
|
+
await this.db.execute(sql17.raw(constraintSQL));
|
|
3021
|
+
logger3.debug(`[CUSTOM MIGRATOR] Successfully added foreign key constraint: ${fk.name}`);
|
|
3022
|
+
} catch (error) {
|
|
3023
|
+
const errorMessage = extractErrorMessage(error);
|
|
3024
|
+
if (errorMessage.includes("already exists")) {
|
|
3025
|
+
logger3.debug(`[CUSTOM MIGRATOR] Foreign key constraint already exists: ${fk.name}`);
|
|
3026
|
+
} else {
|
|
3027
|
+
logger3.warn(`[CUSTOM MIGRATOR] Could not add foreign key constraint (may already exist): ${errorMessage}`);
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
if (tableDef.checkConstraints.length > 0) {
|
|
3033
|
+
for (const checkConstraint of tableDef.checkConstraints) {
|
|
3034
|
+
try {
|
|
3035
|
+
const exists = await this.checkConstraintExists(schemaName, tableDef.name, checkConstraint.name);
|
|
3036
|
+
if (exists) {
|
|
3037
|
+
logger3.debug(`[CUSTOM MIGRATOR] Check constraint ${checkConstraint.name} already exists, skipping`);
|
|
3038
|
+
continue;
|
|
3039
|
+
}
|
|
3040
|
+
const checkSQL = `ALTER TABLE "${schemaName}"."${tableDef.name}" ADD CONSTRAINT "${checkConstraint.name}" CHECK (${checkConstraint.expression})`;
|
|
3041
|
+
await this.db.execute(sql17.raw(checkSQL));
|
|
3042
|
+
logger3.debug(`[CUSTOM MIGRATOR] Successfully added check constraint: ${checkConstraint.name}`);
|
|
3043
|
+
} catch (error) {
|
|
3044
|
+
const errorMessage = extractErrorMessage(error);
|
|
3045
|
+
if (errorMessage.includes("already exists")) {
|
|
3046
|
+
logger3.debug(`[CUSTOM MIGRATOR] Check constraint already exists: ${checkConstraint.name}`);
|
|
3047
|
+
} else {
|
|
3048
|
+
logger3.warn(`[CUSTOM MIGRATOR] Could not add check constraint ${checkConstraint.name} (may already exist): ${errorMessage}`);
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
|
|
3056
|
+
class ExtensionManager {
|
|
3057
|
+
db;
|
|
3058
|
+
constructor(db) {
|
|
3059
|
+
this.db = db;
|
|
3060
|
+
}
|
|
3061
|
+
async installRequiredExtensions(requiredExtensions) {
|
|
3062
|
+
for (const extension of requiredExtensions) {
|
|
3063
|
+
try {
|
|
3064
|
+
await this.db.execute(sql17.raw(`CREATE EXTENSION IF NOT EXISTS "${extension}"`));
|
|
3065
|
+
} catch (error) {
|
|
3066
|
+
const errorDetails = extractErrorDetails(error);
|
|
3067
|
+
logger3.warn(`Could not install extension ${extension}: ${errorDetails.message}`);
|
|
3068
|
+
if (errorDetails.stack) {
|
|
3069
|
+
logger3.debug(`[CUSTOM MIGRATOR] Extension installation stack trace: ${errorDetails.stack}`);
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
function topologicalSort(tables) {
|
|
3076
|
+
const sorted = [];
|
|
3077
|
+
const visited = new Set;
|
|
3078
|
+
const visiting = new Set;
|
|
3079
|
+
function visit(tableName) {
|
|
3080
|
+
if (visiting.has(tableName)) {
|
|
3081
|
+
logger3.warn(`Circular dependency detected involving table: ${tableName}`);
|
|
3082
|
+
return;
|
|
3083
|
+
}
|
|
3084
|
+
if (visited.has(tableName)) {
|
|
3085
|
+
return;
|
|
3086
|
+
}
|
|
3087
|
+
visiting.add(tableName);
|
|
3088
|
+
const table = tables.get(tableName);
|
|
3089
|
+
if (table) {
|
|
3090
|
+
for (const dep of table.dependencies) {
|
|
3091
|
+
if (tables.has(dep)) {
|
|
3092
|
+
visit(dep);
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
visiting.delete(tableName);
|
|
3097
|
+
visited.add(tableName);
|
|
3098
|
+
sorted.push(tableName);
|
|
3099
|
+
}
|
|
3100
|
+
for (const tableName of tables.keys()) {
|
|
3101
|
+
visit(tableName);
|
|
3102
|
+
}
|
|
3103
|
+
return sorted;
|
|
3104
|
+
}
|
|
3105
|
+
async function runPluginMigrations(db, pluginName, schema) {
|
|
3106
|
+
logger3.debug(`[CUSTOM MIGRATOR] Starting migration for plugin: ${pluginName}`);
|
|
3107
|
+
try {
|
|
3108
|
+
await db.execute(sql17.raw("SELECT 1"));
|
|
3109
|
+
logger3.debug("[CUSTOM MIGRATOR] Database connection verified");
|
|
3110
|
+
} catch (error) {
|
|
3111
|
+
const errorDetails = extractErrorDetails(error);
|
|
3112
|
+
logger3.error(`[CUSTOM MIGRATOR] Database connection failed: ${errorDetails.message}`);
|
|
3113
|
+
if (errorDetails.stack) {
|
|
3114
|
+
logger3.error(`[CUSTOM MIGRATOR] Stack trace: ${errorDetails.stack}`);
|
|
3115
|
+
}
|
|
3116
|
+
throw new Error(`Database connection failed: ${errorDetails.message}`);
|
|
3117
|
+
}
|
|
3118
|
+
const namespaceManager = new PluginNamespaceManager(db);
|
|
3119
|
+
const introspector = new DrizzleSchemaIntrospector;
|
|
3120
|
+
const extensionManager = new ExtensionManager(db);
|
|
3121
|
+
await extensionManager.installRequiredExtensions(["vector", "fuzzystrmatch"]);
|
|
3122
|
+
const schemaName = await namespaceManager.getPluginSchema(pluginName);
|
|
3123
|
+
await namespaceManager.ensureNamespace(schemaName);
|
|
3124
|
+
const existingTables = await namespaceManager.introspectExistingTables(schemaName);
|
|
3125
|
+
const tableEntries = Object.entries(schema).filter(([key, v]) => {
|
|
3126
|
+
const isDrizzleTable = v && (v._ && typeof v._.name === "string" || typeof v === "object" && v !== null && (("tableName" in v) || ("dbName" in v) || key.toLowerCase().includes("table")));
|
|
3127
|
+
return isDrizzleTable;
|
|
3128
|
+
});
|
|
3129
|
+
const tableDefinitions = new Map;
|
|
3130
|
+
for (const [exportKey, table] of tableEntries) {
|
|
3131
|
+
const tableDef = introspector.parseTableDefinition(table, exportKey);
|
|
3132
|
+
tableDefinitions.set(tableDef.name, tableDef);
|
|
3133
|
+
}
|
|
3134
|
+
const sortedTableNames = topologicalSort(tableDefinitions);
|
|
3135
|
+
try {
|
|
3136
|
+
logger3.debug(`[CUSTOM MIGRATOR] Phase 1: Creating tables...`);
|
|
3137
|
+
for (const tableName of sortedTableNames) {
|
|
3138
|
+
const tableDef = tableDefinitions.get(tableName);
|
|
3139
|
+
if (!tableDef)
|
|
3140
|
+
continue;
|
|
3141
|
+
const tableExists = existingTables.includes(tableDef.name);
|
|
3142
|
+
logger3.debug(`[CUSTOM MIGRATOR] Table ${tableDef.name} exists: ${tableExists}`);
|
|
3143
|
+
if (!tableExists) {
|
|
3144
|
+
logger3.debug(`[CUSTOM MIGRATOR] Creating table: ${tableDef.name}`);
|
|
3145
|
+
try {
|
|
3146
|
+
await namespaceManager.createTable(tableDef, schemaName);
|
|
3147
|
+
} catch (error) {
|
|
3148
|
+
const errorDetails = extractErrorDetails(error);
|
|
3149
|
+
logger3.error(`[CUSTOM MIGRATOR] Failed to create table ${tableDef.name}: ${errorDetails.message}`);
|
|
3150
|
+
if (errorDetails.stack) {
|
|
3151
|
+
logger3.error(`[CUSTOM MIGRATOR] Table creation stack trace: ${errorDetails.stack}`);
|
|
3152
|
+
}
|
|
3153
|
+
throw new Error(`Failed to create table ${tableDef.name}: ${errorDetails.message}`);
|
|
3154
|
+
}
|
|
3155
|
+
} else {
|
|
3156
|
+
logger3.debug(`[CUSTOM MIGRATOR] Table ${tableDef.name} already exists, skipping creation`);
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
logger3.debug(`[CUSTOM MIGRATOR] Phase 2: Adding constraints...`);
|
|
3160
|
+
for (const tableName of sortedTableNames) {
|
|
3161
|
+
const tableDef = tableDefinitions.get(tableName);
|
|
3162
|
+
if (!tableDef)
|
|
3163
|
+
continue;
|
|
3164
|
+
if (tableDef.foreignKeys.length > 0 || tableDef.checkConstraints.length > 0) {
|
|
3165
|
+
logger3.debug(`[CUSTOM MIGRATOR] Adding constraints for table: ${tableDef.name} - ${JSON.stringify({
|
|
3166
|
+
foreignKeys: tableDef.foreignKeys.length,
|
|
3167
|
+
checkConstraints: tableDef.checkConstraints.length
|
|
3168
|
+
})}`);
|
|
3169
|
+
await namespaceManager.addConstraints(tableDef, schemaName);
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
logger3.debug(`[CUSTOM MIGRATOR] Completed migration for plugin: ${pluginName}`);
|
|
3173
|
+
} catch (error) {
|
|
3174
|
+
const errorDetails = extractErrorDetails(error);
|
|
3175
|
+
logger3.error(`[CUSTOM MIGRATOR] Migration failed for plugin ${pluginName}: ${errorDetails.message}`);
|
|
3176
|
+
if (errorDetails.stack) {
|
|
3177
|
+
logger3.error(`[CUSTOM MIGRATOR] Migration stack trace: ${errorDetails.stack}`);
|
|
3178
|
+
}
|
|
3179
|
+
throw new Error(`Migration failed for plugin ${pluginName}: ${errorDetails.message}`);
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
|
|
3183
|
+
// src/migration-service.ts
|
|
3184
|
+
class DatabaseMigrationService {
|
|
3185
|
+
db = null;
|
|
3186
|
+
registeredSchemas = new Map;
|
|
3187
|
+
constructor() {}
|
|
3188
|
+
async initializeWithDatabase(db) {
|
|
3189
|
+
this.db = db;
|
|
3190
|
+
logger4.info("DatabaseMigrationService initialized with database");
|
|
3191
|
+
}
|
|
3192
|
+
discoverAndRegisterPluginSchemas(plugins) {
|
|
3193
|
+
for (const plugin of plugins) {
|
|
3194
|
+
if (plugin.schema) {
|
|
3195
|
+
this.registeredSchemas.set(plugin.name, plugin.schema);
|
|
3196
|
+
logger4.info(`Registered schema for plugin: ${plugin.name}`);
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
logger4.info(`Discovered ${this.registeredSchemas.size} plugin schemas out of ${plugins.length} plugins`);
|
|
3200
|
+
}
|
|
3201
|
+
registerSchema(pluginName, schema) {
|
|
3202
|
+
this.registeredSchemas.set(pluginName, schema);
|
|
3203
|
+
logger4.info(`Registered schema for plugin: ${pluginName}`);
|
|
3204
|
+
}
|
|
3205
|
+
async runAllPluginMigrations() {
|
|
3206
|
+
if (!this.db) {
|
|
3207
|
+
throw new Error("Database not initialized in DatabaseMigrationService");
|
|
3208
|
+
}
|
|
3209
|
+
logger4.info(`Running migrations for ${this.registeredSchemas.size} plugins...`);
|
|
3210
|
+
for (const [pluginName, schema] of this.registeredSchemas) {
|
|
3211
|
+
logger4.info(`Starting migration for plugin: ${pluginName}`);
|
|
3212
|
+
await runPluginMigrations(this.db, pluginName, schema);
|
|
3213
|
+
}
|
|
3214
|
+
logger4.info("All plugin migrations completed.");
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
|
|
2303
3218
|
// src/index.browser.ts
|
|
2304
3219
|
var GLOBAL_SINGLETONS = Symbol.for("@elizaos/plugin-sql/global-singletons");
|
|
2305
3220
|
var globalSymbols = globalThis;
|
|
@@ -2319,18 +3234,19 @@ var plugin = {
|
|
|
2319
3234
|
priority: 0,
|
|
2320
3235
|
schema: exports_schema,
|
|
2321
3236
|
init: async (_config, runtime) => {
|
|
2322
|
-
|
|
3237
|
+
logger5.info("plugin-sql (browser) init starting...");
|
|
2323
3238
|
const dbAdapter = createDatabaseAdapter({}, runtime.agentId);
|
|
2324
3239
|
runtime.registerDatabaseAdapter(dbAdapter);
|
|
2325
|
-
|
|
3240
|
+
logger5.info("Browser database adapter (PGlite) created and registered");
|
|
2326
3241
|
}
|
|
2327
3242
|
};
|
|
2328
3243
|
var index_browser_default = plugin;
|
|
2329
3244
|
export {
|
|
2330
3245
|
plugin,
|
|
2331
3246
|
index_browser_default as default,
|
|
2332
|
-
createDatabaseAdapter
|
|
3247
|
+
createDatabaseAdapter,
|
|
3248
|
+
DatabaseMigrationService
|
|
2333
3249
|
};
|
|
2334
3250
|
|
|
2335
|
-
//# debugId=
|
|
3251
|
+
//# debugId=7260C857A47E561664756E2164756E21
|
|
2336
3252
|
//# sourceMappingURL=index.browser.js.map
|