@mastra/pg 1.19.0-alpha.0 → 1.19.0-alpha.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/CHANGELOG.md +53 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-deployment-workers.md +14 -14
- package/dist/index.cjs +482 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +483 -26
- package/dist/index.js.map +1 -1
- package/dist/storage/client.d.ts +13 -1
- package/dist/storage/client.d.ts.map +1 -1
- package/dist/storage/db/index.d.ts +63 -0
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/db/schema-snapshot.d.ts +71 -0
- package/dist/storage/db/schema-snapshot.d.ts.map +1 -0
- package/dist/storage/domains/agents/index.d.ts.map +1 -1
- package/dist/storage/domains/datasets/index.d.ts.map +1 -1
- package/dist/storage/domains/favorites/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/workflow-definitions/index.d.ts +20 -0
- package/dist/storage/domains/workflow-definitions/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
|
|
2
|
-
import { AgentsStorage, BRANCH_SPAN_TYPES, BackgroundTasksStorage, BlobStore, ChannelsStorage, DATASETS_SCHEMA, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, DatasetsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, EntityType, ExperimentsStorage, FactoryStorage, FavoritesStorage, MCPClientsStorage, MCPServersStorage, METRIC_DISTINCT_COLUMNS, MastraCompositeStore, MemoryStorage, NotificationsStorage, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, ObservabilityStorage, PromptBlocksStorage, SchedulesStorage, ScorerDefinitionsStorage, ScoresStorage, SkillsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, TABLE_BACKGROUND_TASKS, TABLE_CHANNEL_CONFIG, TABLE_CHANNEL_INSTALLATIONS, TABLE_CONFIGS, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, TABLE_FAVORITES, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, TABLE_MESSAGES, TABLE_NOTIFICATIONS, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, TABLE_RESOURCES, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEMAS, TABLE_SCORERS, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, TABLE_SKILLS, TABLE_SKILL_BLOBS, TABLE_SKILL_VERSIONS, TABLE_SPANS, TABLE_THREADS, TABLE_TOOL_PROVIDER_CONNECTIONS, TABLE_WORKFLOW_SNAPSHOT, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, ToolProviderConnectionsStorage, TraceStatus, UniqueViolationError, WorkflowsStorage, WorkspacesStorage, calculatePagination, createStorageErrorId, createVectorErrorId, ensureDate, getDefaultValue, getSqlType, hasErrorCode, listBranchesArgsSchema, listFeedbackArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listTracesArgsSchema, mergeWorkflowStepResult, normalizePerPage, normalizeScheduleTarget, parseDuration, safelyParseJSON, storageMessageMatchesMetadataFilter, toTraceSpans, transformScoreRow, validateStorageMetadataFilter } from "@mastra/core/storage";
|
|
2
|
+
import { AgentsStorage, BRANCH_SPAN_TYPES, BackgroundTasksStorage, BlobStore, ChannelsStorage, DATASETS_SCHEMA, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, DatasetsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, EntityType, ExperimentsStorage, FactoryStorage, FavoritesStorage, MCPClientsStorage, MCPServersStorage, METRIC_DISTINCT_COLUMNS, MastraCompositeStore, MemoryStorage, NotificationsStorage, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, ObservabilityStorage, PromptBlocksStorage, SchedulesStorage, ScorerDefinitionsStorage, ScoresStorage, SkillsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, TABLE_BACKGROUND_TASKS, TABLE_CHANNEL_CONFIG, TABLE_CHANNEL_INSTALLATIONS, TABLE_CONFIGS, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, TABLE_FAVORITES, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, TABLE_MESSAGES, TABLE_NOTIFICATIONS, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, TABLE_RESOURCES, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEMAS, TABLE_SCORERS, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, TABLE_SKILLS, TABLE_SKILL_BLOBS, TABLE_SKILL_VERSIONS, TABLE_SPANS, TABLE_THREADS, TABLE_TOOL_PROVIDER_CONNECTIONS, TABLE_WORKFLOW_DEFINITIONS, TABLE_WORKFLOW_SNAPSHOT, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, ToolProviderConnectionsStorage, TraceStatus, UniqueViolationError, WorkflowDefinitionsStorage, WorkflowsStorage, WorkspacesStorage, calculatePagination, createStorageErrorId, createVectorErrorId, ensureDate, getDefaultValue, getSqlType, hasErrorCode, listBranchesArgsSchema, listFeedbackArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listTracesArgsSchema, mergeWorkflowStepResult, normalizePerPage, normalizeScheduleTarget, parseDuration, safelyParseJSON, storageMessageMatchesMetadataFilter, toTraceSpans, transformScoreRow, validateStorageMetadataFilter } from "@mastra/core/storage";
|
|
3
3
|
import { parseFieldKey, parseSqlIdentifier } from "@mastra/core/utils";
|
|
4
4
|
import { MastraVector, validateTopK, validateUpsertInput } from "@mastra/core/vector";
|
|
5
5
|
import { Mutex } from "async-mutex";
|
|
@@ -1947,9 +1947,25 @@ var PinnedClientAdapter = class {
|
|
|
1947
1947
|
var RoutingDbClient = class {
|
|
1948
1948
|
#base;
|
|
1949
1949
|
#pinned = null;
|
|
1950
|
+
#schemaSnapshot = null;
|
|
1950
1951
|
constructor(base) {
|
|
1951
1952
|
this.#base = base;
|
|
1952
1953
|
}
|
|
1954
|
+
/**
|
|
1955
|
+
* Catalog snapshot for the current init window, or `null` outside it.
|
|
1956
|
+
*
|
|
1957
|
+
* It lives here rather than on `PgDB` because every storage domain builds its
|
|
1958
|
+
* own `PgDB` over this one shared client — hanging the snapshot off the
|
|
1959
|
+
* client means one load serves all of them, and its lifetime lines up exactly
|
|
1960
|
+
* with the pinned-init window that `pin()`/`unpin()` already delimit.
|
|
1961
|
+
*/
|
|
1962
|
+
get schemaSnapshot() {
|
|
1963
|
+
return this.#schemaSnapshot;
|
|
1964
|
+
}
|
|
1965
|
+
/** Install (or clear, with `null`) the init-window catalog snapshot. */
|
|
1966
|
+
setSchemaSnapshot(snapshot) {
|
|
1967
|
+
this.#schemaSnapshot = snapshot;
|
|
1968
|
+
}
|
|
1953
1969
|
/** Returns the currently active client (pinned if set, otherwise base). */
|
|
1954
1970
|
get active() {
|
|
1955
1971
|
return this.#pinned ?? this.#base;
|
|
@@ -2050,6 +2066,67 @@ function isDuplicateSchemaError(error) {
|
|
|
2050
2066
|
return /schema .* already exists/i.test(message);
|
|
2051
2067
|
}
|
|
2052
2068
|
//#endregion
|
|
2069
|
+
//#region src/storage/db/schema-snapshot.ts
|
|
2070
|
+
/**
|
|
2071
|
+
* Returns the snapshot currently installed on `client`, but only when it was
|
|
2072
|
+
* taken from the schema the caller operates on. A store configured for another
|
|
2073
|
+
* schema (or a client with no snapshot at all) gets `null` and falls back to
|
|
2074
|
+
* probing the live catalog.
|
|
2075
|
+
*/
|
|
2076
|
+
function getSchemaSnapshot(client, schemaName) {
|
|
2077
|
+
const snapshot = client?.schemaSnapshot;
|
|
2078
|
+
if (!snapshot) return null;
|
|
2079
|
+
return snapshot.schemaName === (schemaName || "public") ? snapshot : null;
|
|
2080
|
+
}
|
|
2081
|
+
/**
|
|
2082
|
+
* Reads the catalog for `schemaName` in three queries. Must be called on the
|
|
2083
|
+
* pinned init client so the snapshot reflects what that connection will see.
|
|
2084
|
+
*/
|
|
2085
|
+
async function loadSchemaSnapshot(client, schemaName) {
|
|
2086
|
+
const schema = schemaName || "public";
|
|
2087
|
+
const [tableRows, columnRows, indexRows] = await Promise.all([
|
|
2088
|
+
client.manyOrNone(`SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = $1`, [schema]),
|
|
2089
|
+
client.manyOrNone(`SELECT c.relname AS table_name, a.attname AS column_name
|
|
2090
|
+
FROM pg_catalog.pg_class c
|
|
2091
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
2092
|
+
JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
|
|
2093
|
+
WHERE n.nspname = $1
|
|
2094
|
+
AND c.relkind IN ('r', 'p')
|
|
2095
|
+
AND a.attnum > 0
|
|
2096
|
+
AND NOT a.attisdropped`, [schema]),
|
|
2097
|
+
client.manyOrNone(`SELECT c.relname AS indexname, i.indisreplident AS is_replica_identity, i.indisprimary AS is_primary
|
|
2098
|
+
FROM pg_catalog.pg_index i
|
|
2099
|
+
JOIN pg_catalog.pg_class c ON c.oid = i.indexrelid
|
|
2100
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
2101
|
+
WHERE n.nspname = $1`, [schema])
|
|
2102
|
+
]);
|
|
2103
|
+
const columns = /* @__PURE__ */ new Map();
|
|
2104
|
+
for (const row of columnRows) {
|
|
2105
|
+
let set = columns.get(row.table_name);
|
|
2106
|
+
if (!set) {
|
|
2107
|
+
set = /* @__PURE__ */ new Set();
|
|
2108
|
+
columns.set(row.table_name, set);
|
|
2109
|
+
}
|
|
2110
|
+
set.add(row.column_name);
|
|
2111
|
+
}
|
|
2112
|
+
const indexes = /* @__PURE__ */ new Set();
|
|
2113
|
+
const replicaIdentityIndexes = /* @__PURE__ */ new Set();
|
|
2114
|
+
const primaryKeyIndexes = /* @__PURE__ */ new Set();
|
|
2115
|
+
for (const row of indexRows) {
|
|
2116
|
+
indexes.add(row.indexname);
|
|
2117
|
+
if (row.is_replica_identity) replicaIdentityIndexes.add(row.indexname);
|
|
2118
|
+
if (row.is_primary) primaryKeyIndexes.add(row.indexname.toLowerCase());
|
|
2119
|
+
}
|
|
2120
|
+
return {
|
|
2121
|
+
schemaName: schema,
|
|
2122
|
+
tables: new Set(tableRows.map((r) => r.tablename)),
|
|
2123
|
+
columns,
|
|
2124
|
+
indexes,
|
|
2125
|
+
replicaIdentityIndexes,
|
|
2126
|
+
primaryKeyIndexes
|
|
2127
|
+
};
|
|
2128
|
+
}
|
|
2129
|
+
//#endregion
|
|
2053
2130
|
//#region src/storage/db/index.ts
|
|
2054
2131
|
/**
|
|
2055
2132
|
* Resolves PgDomainConfig to a database client and schema.
|
|
@@ -2229,7 +2306,8 @@ function generateTimestampTriggerSQL(tableName, schemaName) {
|
|
|
2229
2306
|
schemaName: quotedSchemaName
|
|
2230
2307
|
});
|
|
2231
2308
|
const functionName = `${quotedSchemaName}.trigger_set_timestamps`;
|
|
2232
|
-
const
|
|
2309
|
+
const parsedTriggerName = parseSqlIdentifier(`${tableName}_timestamps`, "trigger name");
|
|
2310
|
+
const triggerName = `"${parsedTriggerName}"`;
|
|
2233
2311
|
return `CREATE OR REPLACE FUNCTION ${functionName}()
|
|
2234
2312
|
RETURNS TRIGGER AS $$
|
|
2235
2313
|
BEGIN
|
|
@@ -2248,12 +2326,38 @@ BEGIN
|
|
|
2248
2326
|
END;
|
|
2249
2327
|
$$ LANGUAGE plpgsql;
|
|
2250
2328
|
|
|
2251
|
-
|
|
2329
|
+
DO $mastra_timestamps_trigger$
|
|
2330
|
+
BEGIN
|
|
2331
|
+
-- Recreating the trigger unconditionally would take an ACCESS EXCLUSIVE
|
|
2332
|
+
-- lock on the table (DROP TRIGGER does, even when nothing changes), and
|
|
2333
|
+
-- init runs on every process start. Skip when the trigger is already
|
|
2334
|
+
-- exactly what the CREATE below would produce.
|
|
2335
|
+
--
|
|
2336
|
+
-- tgtype 23 = ROW (1) | BEFORE (2) | INSERT (4) | UPDATE (16), so a trigger
|
|
2337
|
+
-- whose timing or events differ still falls through and gets rebuilt. The
|
|
2338
|
+
-- behaviour itself lives in the function, which is replaced above on every
|
|
2339
|
+
-- init, so an upgraded function body lands without touching the trigger.
|
|
2340
|
+
IF NOT EXISTS (
|
|
2341
|
+
SELECT 1
|
|
2342
|
+
FROM pg_catalog.pg_trigger tg
|
|
2343
|
+
JOIN pg_catalog.pg_class c ON c.oid = tg.tgrelid
|
|
2344
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
2345
|
+
WHERE tg.tgname = ${`'${parsedTriggerName}'`}
|
|
2346
|
+
AND c.relname = ${`'${parseSqlIdentifier(tableName, "table name")}'`}
|
|
2347
|
+
AND n.nspname = ${schemaName ? `'${parseSqlIdentifier(schemaName, "schema name")}'` : `'public'`}
|
|
2348
|
+
AND NOT tg.tgisinternal
|
|
2349
|
+
AND tg.tgtype = 23
|
|
2350
|
+
AND tg.tgfoid = '${functionName}()'::regprocedure
|
|
2351
|
+
) THEN
|
|
2352
|
+
DROP TRIGGER IF EXISTS ${triggerName} ON ${fullTableName};
|
|
2252
2353
|
|
|
2253
|
-
CREATE TRIGGER ${triggerName}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2354
|
+
CREATE TRIGGER ${triggerName}
|
|
2355
|
+
BEFORE INSERT OR UPDATE ON ${fullTableName}
|
|
2356
|
+
FOR EACH ROW
|
|
2357
|
+
EXECUTE FUNCTION ${functionName}();
|
|
2358
|
+
END IF;
|
|
2359
|
+
END
|
|
2360
|
+
$mastra_timestamps_trigger$;`;
|
|
2257
2361
|
}
|
|
2258
2362
|
const schemaSetupRegistry = /* @__PURE__ */ new Map();
|
|
2259
2363
|
/**
|
|
@@ -2280,6 +2384,99 @@ var PgDB = class extends MastraBase {
|
|
|
2280
2384
|
this.skipDefaultIndexes = config.skipDefaultIndexes;
|
|
2281
2385
|
}
|
|
2282
2386
|
/**
|
|
2387
|
+
* Catalog snapshot for the current init window, or `null` outside it.
|
|
2388
|
+
*
|
|
2389
|
+
* When non-null, the init-path methods below answer existence questions from
|
|
2390
|
+
* it instead of round-tripping to the server, and record the objects they
|
|
2391
|
+
* create so later callers in the same init see them. See
|
|
2392
|
+
* {@link SchemaSnapshot} for why it is scoped to init only.
|
|
2393
|
+
*/
|
|
2394
|
+
get schemaSnapshot() {
|
|
2395
|
+
return getSchemaSnapshot(this.client, this.schemaName);
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Whether the snapshot proves `generateTableSQL` would be a no-op for this
|
|
2399
|
+
* table — i.e. the CREATE statement can be skipped.
|
|
2400
|
+
*
|
|
2401
|
+
* For most tables that is just "the table exists". `workflow_snapshot` is the
|
|
2402
|
+
* exception: its generated SQL also carries a DO block that back-fills the
|
|
2403
|
+
* `(workflow_name, run_id)` unique constraint and promotes it to the table's
|
|
2404
|
+
* replica identity, so a table created by an older version still needs the
|
|
2405
|
+
* statement to run.
|
|
2406
|
+
*/
|
|
2407
|
+
snapshotShowsTableConverged(snapshot, tableName) {
|
|
2408
|
+
if (!snapshot.tables.has(tableName)) return false;
|
|
2409
|
+
if (tableName === TABLE_WORKFLOW_SNAPSHOT) {
|
|
2410
|
+
const constraintName = buildConstraintName({
|
|
2411
|
+
baseName: "mastra_workflow_snapshot_workflow_name_run_id_key",
|
|
2412
|
+
schemaName: this.schemaName ? parseSqlIdentifier(this.schemaName, "schema name") : void 0
|
|
2413
|
+
}).toLowerCase();
|
|
2414
|
+
return snapshot.indexes.has(constraintName) && snapshot.replicaIdentityIndexes.has(constraintName);
|
|
2415
|
+
}
|
|
2416
|
+
return true;
|
|
2417
|
+
}
|
|
2418
|
+
/** Column set for `tableName` in the snapshot, created empty if absent. */
|
|
2419
|
+
snapshotColumns(snapshot, tableName) {
|
|
2420
|
+
let columns = snapshot.columns.get(tableName);
|
|
2421
|
+
if (!columns) {
|
|
2422
|
+
columns = /* @__PURE__ */ new Set();
|
|
2423
|
+
snapshot.columns.set(tableName, columns);
|
|
2424
|
+
}
|
|
2425
|
+
return columns;
|
|
2426
|
+
}
|
|
2427
|
+
/**
|
|
2428
|
+
* Records an out-of-band `ALTER TABLE … RENAME TO` in the init snapshot.
|
|
2429
|
+
*
|
|
2430
|
+
* Init-time migrations that issue raw DDL on `this.client` (instead of going
|
|
2431
|
+
* through createTable/alterTable/createIndex, which maintain the snapshot
|
|
2432
|
+
* themselves) MUST report it through these `note*` methods. A snapshot that
|
|
2433
|
+
* still lists a renamed-away table makes a later createTable() in the same
|
|
2434
|
+
* init skip the rebuild the migration depends on — stranding data. No-op
|
|
2435
|
+
* outside the init window.
|
|
2436
|
+
*
|
|
2437
|
+
* Indexes riding along with a rename keep their names, so the snapshot's
|
|
2438
|
+
* index set stays accurate without changes here.
|
|
2439
|
+
*/
|
|
2440
|
+
noteTableRenamed(oldName, newName) {
|
|
2441
|
+
const snapshot = this.schemaSnapshot;
|
|
2442
|
+
if (snapshot) {
|
|
2443
|
+
if (snapshot.tables.delete(oldName)) snapshot.tables.add(newName);
|
|
2444
|
+
const columns = snapshot.columns.get(oldName);
|
|
2445
|
+
if (columns) {
|
|
2446
|
+
snapshot.columns.delete(oldName);
|
|
2447
|
+
snapshot.columns.set(newName, columns);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
this.tableColumnsCache.delete(oldName);
|
|
2451
|
+
this.tableColumnsCache.delete(newName);
|
|
2452
|
+
}
|
|
2453
|
+
/**
|
|
2454
|
+
* Records an out-of-band `DROP TABLE` in the init snapshot. See
|
|
2455
|
+
* {@link noteTableRenamed} for why raw-DDL migrations must call this.
|
|
2456
|
+
*
|
|
2457
|
+
* The dropped table's indexes vanish with it, but the snapshot's flat index
|
|
2458
|
+
* set cannot map names back to tables. Stale entries only make a later
|
|
2459
|
+
* createIndex() skip a recreate until the next init re-reads the catalog —
|
|
2460
|
+
* the same self-healing bound the rest of the snapshot design accepts.
|
|
2461
|
+
*/
|
|
2462
|
+
noteTableDropped(tableName) {
|
|
2463
|
+
const snapshot = this.schemaSnapshot;
|
|
2464
|
+
if (snapshot) {
|
|
2465
|
+
snapshot.tables.delete(tableName);
|
|
2466
|
+
snapshot.columns.delete(tableName);
|
|
2467
|
+
}
|
|
2468
|
+
this.tableColumnsCache.delete(tableName);
|
|
2469
|
+
}
|
|
2470
|
+
/**
|
|
2471
|
+
* Records an out-of-band `ALTER TABLE … ADD COLUMN` in the init snapshot.
|
|
2472
|
+
* See {@link noteTableRenamed} for why raw-DDL migrations must call this.
|
|
2473
|
+
*/
|
|
2474
|
+
noteColumnAdded(tableName, column) {
|
|
2475
|
+
const snapshot = this.schemaSnapshot;
|
|
2476
|
+
if (snapshot) this.snapshotColumns(snapshot, tableName).add(column);
|
|
2477
|
+
this.tableColumnsCache.delete(tableName);
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2283
2480
|
* Gets the set of column names that actually exist in the database table.
|
|
2284
2481
|
* Results are cached; the cache is invalidated when alterTable() adds new columns.
|
|
2285
2482
|
*/
|
|
@@ -2306,6 +2503,12 @@ var PgDB = class extends MastraBase {
|
|
|
2306
2503
|
}
|
|
2307
2504
|
async hasColumn(table, column) {
|
|
2308
2505
|
const schema = this.schemaName || "public";
|
|
2506
|
+
const snapshot = this.schemaSnapshot;
|
|
2507
|
+
if (snapshot) {
|
|
2508
|
+
const columns = snapshot.columns.get(table);
|
|
2509
|
+
if (!columns) return false;
|
|
2510
|
+
return columns.has(column) || columns.has(column.toLowerCase());
|
|
2511
|
+
}
|
|
2309
2512
|
return !!await this.client.oneOrNone(`SELECT 1 FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 AND (column_name = $3 OR column_name = $4)`, [
|
|
2310
2513
|
schema,
|
|
2311
2514
|
table,
|
|
@@ -2344,6 +2547,14 @@ var PgDB = class extends MastraBase {
|
|
|
2344
2547
|
if (!this.schemaName) return;
|
|
2345
2548
|
let registryEntry = schemaSetupRegistry.get(this.schemaName);
|
|
2346
2549
|
if (registryEntry?.complete) return;
|
|
2550
|
+
const snapshot = this.schemaSnapshot;
|
|
2551
|
+
if (snapshot && snapshot.tables.size > 0) {
|
|
2552
|
+
schemaSetupRegistry.set(this.schemaName, {
|
|
2553
|
+
promise: null,
|
|
2554
|
+
complete: true
|
|
2555
|
+
});
|
|
2556
|
+
return;
|
|
2557
|
+
}
|
|
2347
2558
|
const quotedSchemaName = getSchemaName$6(this.schemaName);
|
|
2348
2559
|
if (!registryEntry?.promise) {
|
|
2349
2560
|
const schemaNameCapture = this.schemaName;
|
|
@@ -2448,16 +2659,28 @@ var PgDB = class extends MastraBase {
|
|
|
2448
2659
|
try {
|
|
2449
2660
|
const timeZColumnNames = Object.entries(schema).filter(([_, def]) => def.type === "timestamp").map(([name]) => name);
|
|
2450
2661
|
if (this.schemaName) await this.setupSchema();
|
|
2451
|
-
const
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2662
|
+
const snapshot = this.schemaSnapshot;
|
|
2663
|
+
if (!snapshot || !this.snapshotShowsTableConverged(snapshot, tableName)) {
|
|
2664
|
+
const sql = generateTableSQL({
|
|
2665
|
+
tableName,
|
|
2666
|
+
schema,
|
|
2667
|
+
schemaName: this.schemaName,
|
|
2668
|
+
compositePrimaryKey
|
|
2669
|
+
});
|
|
2670
|
+
try {
|
|
2671
|
+
await this.client.none(sql);
|
|
2672
|
+
} catch (error) {
|
|
2673
|
+
if (!isDuplicateRelationError(error)) throw error;
|
|
2674
|
+
}
|
|
2675
|
+
if (snapshot) {
|
|
2676
|
+
snapshot.tables.add(tableName);
|
|
2677
|
+
const created = this.snapshotColumns(snapshot, tableName);
|
|
2678
|
+
for (const [name, def] of Object.entries(schema)) {
|
|
2679
|
+
const parsedName = parseSqlIdentifier(name, "column name");
|
|
2680
|
+
created.add(parsedName);
|
|
2681
|
+
if (def.type === "timestamp") created.add(`${parsedName}Z`);
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2461
2684
|
}
|
|
2462
2685
|
await this.alterTable({
|
|
2463
2686
|
tableName,
|
|
@@ -2523,10 +2746,12 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2523
2746
|
const sqlType = mapToSqlType(columnDef.type);
|
|
2524
2747
|
const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}" ${sqlType} ${columnDef.nullable ? "" : "NOT NULL"} ${!columnDef.nullable ? this.getDefaultValue(columnDef.type) : ""}`.trim();
|
|
2525
2748
|
await this.client.none(alterSql);
|
|
2749
|
+
this.noteColumnAdded(TABLE_SPANS, columnName);
|
|
2526
2750
|
this.logger?.debug?.(`Added column '${columnName}' to ${fullTableName}`);
|
|
2527
2751
|
if (sqlType === "TIMESTAMP") {
|
|
2528
2752
|
const timestampZSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}Z" TIMESTAMPTZ DEFAULT NOW()`.trim();
|
|
2529
2753
|
await this.client.none(timestampZSql);
|
|
2754
|
+
this.noteColumnAdded(TABLE_SPANS, `${columnName}Z`);
|
|
2530
2755
|
this.logger?.debug?.(`Added timezone column '${columnName}Z' to ${fullTableName}`);
|
|
2531
2756
|
}
|
|
2532
2757
|
}
|
|
@@ -2535,6 +2760,7 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2535
2760
|
if (!await this.hasColumn(TABLE_SPANS, tzColumnName)) {
|
|
2536
2761
|
const timestampZSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parseSqlIdentifier(tzColumnName, "column name")}" TIMESTAMPTZ DEFAULT NOW()`.trim();
|
|
2537
2762
|
await this.client.none(timestampZSql);
|
|
2763
|
+
this.noteColumnAdded(TABLE_SPANS, tzColumnName);
|
|
2538
2764
|
this.logger?.debug?.(`Added timezone column '${tzColumnName}' to ${fullTableName}`);
|
|
2539
2765
|
}
|
|
2540
2766
|
}
|
|
@@ -2657,6 +2883,12 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2657
2883
|
schemaName: (this.schemaName ? parseSqlIdentifier(this.schemaName, "schema name") : "") || void 0
|
|
2658
2884
|
});
|
|
2659
2885
|
const schemaFilter = this.schemaName || "public";
|
|
2886
|
+
const snapshot = this.schemaSnapshot;
|
|
2887
|
+
if (snapshot) return snapshot.primaryKeyIndexes.has(constraintName.toLowerCase());
|
|
2888
|
+
return this.spansPrimaryKeyExistsLive(constraintName, schemaFilter);
|
|
2889
|
+
}
|
|
2890
|
+
/** Live-catalog variant of {@link spansPrimaryKeyExists}, bypassing the snapshot. */
|
|
2891
|
+
async spansPrimaryKeyExistsLive(constraintName, schemaFilter) {
|
|
2660
2892
|
return (await this.client.oneOrNone(`SELECT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = lower($1) AND connamespace = (SELECT oid FROM pg_namespace WHERE nspname = $2)) as exists`, [constraintName, schemaFilter]))?.exists ?? false;
|
|
2661
2893
|
}
|
|
2662
2894
|
/**
|
|
@@ -2687,10 +2919,12 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2687
2919
|
ADD CONSTRAINT ${constraintName}
|
|
2688
2920
|
PRIMARY KEY ("traceId", "spanId")
|
|
2689
2921
|
`);
|
|
2922
|
+
this.schemaSnapshot?.primaryKeyIndexes.add(constraintName.toLowerCase());
|
|
2690
2923
|
this.logger?.info?.(`Added PRIMARY KEY constraint ${constraintName} to ${fullTableName}`);
|
|
2691
2924
|
} catch (error) {
|
|
2692
2925
|
if (isDuplicateRelationError(error)) {
|
|
2693
|
-
if (await this.
|
|
2926
|
+
if (await this.spansPrimaryKeyExistsLive(constraintName, schemaFilter)) {
|
|
2927
|
+
this.schemaSnapshot?.primaryKeyIndexes.add(constraintName.toLowerCase());
|
|
2694
2928
|
this.logger?.debug?.(`PRIMARY KEY constraint ${constraintName} was created by another process`);
|
|
2695
2929
|
return;
|
|
2696
2930
|
}
|
|
@@ -2772,16 +3006,25 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2772
3006
|
indexName: tableName,
|
|
2773
3007
|
schemaName: getSchemaName$6(this.schemaName)
|
|
2774
3008
|
});
|
|
3009
|
+
const snapshot = this.schemaSnapshot;
|
|
3010
|
+
const knownColumns = snapshot ? this.snapshotColumns(snapshot, tableName) : null;
|
|
2775
3011
|
try {
|
|
2776
3012
|
for (const columnName of ifNotExists) if (schema[columnName]) {
|
|
2777
3013
|
const columnDef = schema[columnName];
|
|
2778
3014
|
const parsedColumnName = parseSqlIdentifier(columnName, "column name");
|
|
2779
3015
|
const sqlType = mapToSqlType(columnDef.type);
|
|
2780
3016
|
const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}" ${sqlType} ${columnDef.nullable ? "" : "NOT NULL"} ${!columnDef.nullable ? this.getDefaultValue(columnDef.type) : ""}`.trim();
|
|
2781
|
-
|
|
3017
|
+
if (!knownColumns?.has(parsedColumnName)) {
|
|
3018
|
+
await this.client.none(alterSql);
|
|
3019
|
+
knownColumns?.add(parsedColumnName);
|
|
3020
|
+
}
|
|
2782
3021
|
if (sqlType === "TIMESTAMP") {
|
|
2783
|
-
const
|
|
2784
|
-
|
|
3022
|
+
const tzColumnName = `${parsedColumnName}Z`;
|
|
3023
|
+
if (!knownColumns?.has(tzColumnName)) {
|
|
3024
|
+
const timestampZSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${tzColumnName}" TIMESTAMPTZ DEFAULT NOW()`.trim();
|
|
3025
|
+
await this.client.none(timestampZSql);
|
|
3026
|
+
knownColumns?.add(tzColumnName);
|
|
3027
|
+
}
|
|
2785
3028
|
}
|
|
2786
3029
|
this.logger?.debug?.(`Ensured column ${parsedColumnName} exists in table ${fullTableName}`);
|
|
2787
3030
|
}
|
|
@@ -2867,7 +3110,10 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2867
3110
|
indexName: table,
|
|
2868
3111
|
schemaName: getSchemaName$6(this.schemaName)
|
|
2869
3112
|
});
|
|
2870
|
-
|
|
3113
|
+
const snapshot = this.schemaSnapshot;
|
|
3114
|
+
if (snapshot) {
|
|
3115
|
+
if (snapshot.indexes.has(name)) return;
|
|
3116
|
+
} else if (await this.client.oneOrNone(`SELECT 1 FROM pg_indexes
|
|
2871
3117
|
WHERE indexname = $1
|
|
2872
3118
|
AND schemaname = $2`, [name, schemaName])) return;
|
|
2873
3119
|
const uniqueStr = unique ? "UNIQUE " : "";
|
|
@@ -2889,6 +3135,7 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2889
3135
|
if (storage && Object.keys(storage).length > 0) withStr = ` WITH (${Object.entries(storage).map(([key, value]) => `${key} = ${value}`).join(", ")})`;
|
|
2890
3136
|
const sql = `CREATE ${uniqueStr}INDEX ${concurrentStr}${`"${parseSqlIdentifier(name, "index name")}"`} ON ${fullTableName} ${methodStr}(${columnsStr})${withStr}${tablespaceStr}${whereStr}`;
|
|
2891
3137
|
await this.client.none(sql);
|
|
3138
|
+
snapshot?.indexes.add(name);
|
|
2892
3139
|
} catch (error) {
|
|
2893
3140
|
if (error instanceof Error && error.message.includes("CONCURRENTLY")) {
|
|
2894
3141
|
const retryOptions = {
|
|
@@ -2908,15 +3155,34 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2908
3155
|
}, error);
|
|
2909
3156
|
}
|
|
2910
3157
|
}
|
|
3158
|
+
/**
|
|
3159
|
+
* Runs a caller-built `CREATE INDEX IF NOT EXISTS` statement, unless the init
|
|
3160
|
+
* snapshot already proves `indexName` exists.
|
|
3161
|
+
*
|
|
3162
|
+
* `createIndex` covers the indexes described by {@link CreateIndexOptions};
|
|
3163
|
+
* this is for the two init paths that hand-write their statement (a partial
|
|
3164
|
+
* or otherwise non-standard index) and would otherwise send a no-op DDL on
|
|
3165
|
+
* every warm init.
|
|
3166
|
+
*/
|
|
3167
|
+
async createIndexFromStatement(indexName, sql) {
|
|
3168
|
+
const snapshot = this.schemaSnapshot;
|
|
3169
|
+
if (snapshot?.indexes.has(indexName)) return;
|
|
3170
|
+
await this.client.none(sql);
|
|
3171
|
+
snapshot?.indexes.add(indexName);
|
|
3172
|
+
}
|
|
2911
3173
|
async dropIndex(indexName) {
|
|
2912
3174
|
try {
|
|
2913
3175
|
const schemaName = this.schemaName || "public";
|
|
2914
|
-
|
|
3176
|
+
const snapshot = this.schemaSnapshot;
|
|
3177
|
+
if (snapshot) {
|
|
3178
|
+
if (!snapshot.indexes.has(indexName)) return;
|
|
3179
|
+
} else if (!await this.client.oneOrNone(`SELECT 1 FROM pg_indexes
|
|
2915
3180
|
WHERE indexname = $1
|
|
2916
3181
|
AND schemaname = $2`, [indexName, schemaName])) return;
|
|
2917
3182
|
const quotedIndexName = `"${parseSqlIdentifier(indexName, "index name")}"`;
|
|
2918
3183
|
const sql = `DROP INDEX IF EXISTS ${getSchemaName$6(this.schemaName)}.${quotedIndexName}`;
|
|
2919
3184
|
await this.client.none(sql);
|
|
3185
|
+
snapshot?.indexes.delete(indexName);
|
|
2920
3186
|
} catch (error) {
|
|
2921
3187
|
throw new MastraError({
|
|
2922
3188
|
id: createStorageErrorId("PG", "INDEX_DROP", "FAILED"),
|
|
@@ -3413,7 +3679,9 @@ var AgentsPG = class AgentsPG extends AgentsStorage {
|
|
|
3413
3679
|
});
|
|
3414
3680
|
if (await this.#db.hasColumn(TABLE_AGENTS, "name")) {
|
|
3415
3681
|
await this.#db.client.none(`ALTER TABLE ${fullTableName} RENAME TO "${TABLE_AGENTS}_legacy"`);
|
|
3682
|
+
this.#db.noteTableRenamed(TABLE_AGENTS, `${TABLE_AGENTS}_legacy`);
|
|
3416
3683
|
await this.#db.client.none(`DROP TABLE IF EXISTS ${fullVersionsTableName}`);
|
|
3684
|
+
this.#db.noteTableDropped(TABLE_AGENT_VERSIONS);
|
|
3417
3685
|
}
|
|
3418
3686
|
if (!await this.#db.hasColumn(`${TABLE_AGENTS}_legacy`, "name")) return;
|
|
3419
3687
|
const oldAgents = await this.#db.client.manyOrNone(`SELECT * FROM ${legacyTableName}`);
|
|
@@ -3470,6 +3738,7 @@ var AgentsPG = class AgentsPG extends AgentsStorage {
|
|
|
3470
3738
|
]);
|
|
3471
3739
|
}
|
|
3472
3740
|
await this.#db.client.none(`DROP TABLE IF EXISTS ${legacyTableName}`);
|
|
3741
|
+
this.#db.noteTableDropped(`${TABLE_AGENTS}_legacy`);
|
|
3473
3742
|
}
|
|
3474
3743
|
/**
|
|
3475
3744
|
* Migrates the agent_versions table from the old snapshot-based schema (single `snapshot` JSON column)
|
|
@@ -3487,7 +3756,9 @@ var AgentsPG = class AgentsPG extends AgentsStorage {
|
|
|
3487
3756
|
schemaName: getSchemaName$5(this.#schema)
|
|
3488
3757
|
});
|
|
3489
3758
|
await this.#db.client.none(`DROP TABLE IF EXISTS ${fullVersionsTableName}`);
|
|
3759
|
+
this.#db.noteTableDropped(TABLE_AGENT_VERSIONS);
|
|
3490
3760
|
await this.#db.client.none(`DROP TABLE IF EXISTS ${legacyTableName}`);
|
|
3761
|
+
this.#db.noteTableDropped(`${TABLE_AGENTS}_legacy`);
|
|
3491
3762
|
}
|
|
3492
3763
|
/**
|
|
3493
3764
|
* Migrates the tools field from string[] format to JSONB format { "tool-key": { "description": "..." } }.
|
|
@@ -5015,6 +5286,7 @@ var DatasetsPG = class DatasetsPG extends DatasetsStorage {
|
|
|
5015
5286
|
schemaName: getSchemaName$5(this.#schema)
|
|
5016
5287
|
});
|
|
5017
5288
|
await this.#db.client.none(`ALTER TABLE ${fullTableName} ADD COLUMN "${column}" ${sqlType}`);
|
|
5289
|
+
this.#db.noteColumnAdded(table, column);
|
|
5018
5290
|
}
|
|
5019
5291
|
}
|
|
5020
5292
|
getDefaultIndexDefinitions() {
|
|
@@ -6884,7 +7156,7 @@ var FavoritesPG = class FavoritesPG extends FavoritesStorage {
|
|
|
6884
7156
|
indexName: TABLE_FAVORITES,
|
|
6885
7157
|
schemaName: getSchemaName$5(this.#schema)
|
|
6886
7158
|
});
|
|
6887
|
-
await this.#db.
|
|
7159
|
+
await this.#db.createIndexFromStatement("idx_favorites_entity", `CREATE INDEX IF NOT EXISTS idx_favorites_entity ON ${fullTableName} ("entityType", "entityId")`);
|
|
6888
7160
|
}
|
|
6889
7161
|
async dangerouslyClearAll() {
|
|
6890
7162
|
const fullTableName = getTableName$5({
|
|
@@ -8380,7 +8652,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
8380
8652
|
indexName: OM_TABLE,
|
|
8381
8653
|
schemaName: getSchemaName$3(this.#schema)
|
|
8382
8654
|
});
|
|
8383
|
-
await this.#db.
|
|
8655
|
+
await this.#db.createIndexFromStatement("idx_om_lookup_key", `CREATE INDEX IF NOT EXISTS idx_om_lookup_key ON ${omTableName} ("lookupKey")`);
|
|
8384
8656
|
}
|
|
8385
8657
|
await this.createDefaultIndexes();
|
|
8386
8658
|
await this.createCustomIndexes();
|
|
@@ -18476,6 +18748,187 @@ var ToolProviderConnectionsPG = class ToolProviderConnectionsPG extends ToolProv
|
|
|
18476
18748
|
}
|
|
18477
18749
|
};
|
|
18478
18750
|
//#endregion
|
|
18751
|
+
//#region src/storage/domains/workflow-definitions/index.ts
|
|
18752
|
+
function rowToDefinition(row) {
|
|
18753
|
+
const inputSchema = parseJsonResilient(row.inputSchema);
|
|
18754
|
+
const outputSchema = parseJsonResilient(row.outputSchema);
|
|
18755
|
+
const graph = parseJsonResilient(row.graph);
|
|
18756
|
+
if (inputSchema === void 0 || outputSchema === void 0 || graph === void 0) throw new Error(`Workflow definition row "${String(row.id)}" is missing required JSON columns.`);
|
|
18757
|
+
const def = {
|
|
18758
|
+
id: String(row.id),
|
|
18759
|
+
inputSchema,
|
|
18760
|
+
outputSchema,
|
|
18761
|
+
graph,
|
|
18762
|
+
status: String(row.status),
|
|
18763
|
+
source: String(row.source),
|
|
18764
|
+
createdAt: new Date(row.createdAtZ ?? row.createdAt),
|
|
18765
|
+
updatedAt: new Date(row.updatedAtZ ?? row.updatedAt)
|
|
18766
|
+
};
|
|
18767
|
+
if (row.description != null) def.description = String(row.description);
|
|
18768
|
+
const metadata = parseJsonResilient(row.metadata);
|
|
18769
|
+
if (metadata !== void 0 && metadata !== null) def.metadata = metadata;
|
|
18770
|
+
const stateSchema = parseJsonResilient(row.stateSchema);
|
|
18771
|
+
if (stateSchema !== void 0 && stateSchema !== null) def.stateSchema = stateSchema;
|
|
18772
|
+
const requestContextSchema = parseJsonResilient(row.requestContextSchema);
|
|
18773
|
+
if (requestContextSchema !== void 0 && requestContextSchema !== null) def.requestContextSchema = requestContextSchema;
|
|
18774
|
+
if (row.authorId != null) def.authorId = String(row.authorId);
|
|
18775
|
+
return def;
|
|
18776
|
+
}
|
|
18777
|
+
var WorkflowDefinitionsPG = class WorkflowDefinitionsPG extends WorkflowDefinitionsStorage {
|
|
18778
|
+
#db;
|
|
18779
|
+
#schema;
|
|
18780
|
+
#skipDefaultIndexes;
|
|
18781
|
+
#indexes;
|
|
18782
|
+
static MANAGED_TABLES = [TABLE_WORKFLOW_DEFINITIONS];
|
|
18783
|
+
constructor(config) {
|
|
18784
|
+
super();
|
|
18785
|
+
const { client, schemaName, skipDefaultIndexes, indexes } = resolvePgConfig(config);
|
|
18786
|
+
this.#db = new PgDB({
|
|
18787
|
+
client,
|
|
18788
|
+
schemaName,
|
|
18789
|
+
skipDefaultIndexes
|
|
18790
|
+
});
|
|
18791
|
+
this.#schema = schemaName || "public";
|
|
18792
|
+
this.#skipDefaultIndexes = skipDefaultIndexes;
|
|
18793
|
+
this.#indexes = indexes?.filter((idx) => WorkflowDefinitionsPG.MANAGED_TABLES.includes(idx.table));
|
|
18794
|
+
}
|
|
18795
|
+
static getExportDDL(schemaName) {
|
|
18796
|
+
return [generateTableSQL({
|
|
18797
|
+
tableName: TABLE_WORKFLOW_DEFINITIONS,
|
|
18798
|
+
schema: TABLE_SCHEMAS[TABLE_WORKFLOW_DEFINITIONS],
|
|
18799
|
+
schemaName,
|
|
18800
|
+
includeAllConstraints: true
|
|
18801
|
+
})];
|
|
18802
|
+
}
|
|
18803
|
+
getDefaultIndexDefinitions() {
|
|
18804
|
+
return [{
|
|
18805
|
+
name: `${this.#schema !== "public" ? `${this.#schema}_` : ""}idx_workflow_definitions_status`,
|
|
18806
|
+
table: TABLE_WORKFLOW_DEFINITIONS,
|
|
18807
|
+
columns: ["status"]
|
|
18808
|
+
}];
|
|
18809
|
+
}
|
|
18810
|
+
async createDefaultIndexes() {
|
|
18811
|
+
if (this.#skipDefaultIndexes) return;
|
|
18812
|
+
for (const indexDef of this.getDefaultIndexDefinitions()) try {
|
|
18813
|
+
await this.#db.createIndex(indexDef);
|
|
18814
|
+
} catch (error) {
|
|
18815
|
+
this.logger?.warn?.(`Failed to create index ${indexDef.name}:`, error);
|
|
18816
|
+
}
|
|
18817
|
+
}
|
|
18818
|
+
async createCustomIndexes() {
|
|
18819
|
+
if (!this.#indexes || this.#indexes.length === 0) return;
|
|
18820
|
+
for (const indexDef of this.#indexes) try {
|
|
18821
|
+
await this.#db.createIndex(indexDef);
|
|
18822
|
+
} catch (error) {
|
|
18823
|
+
this.logger?.warn?.(`Failed to create custom index ${indexDef.name}:`, error);
|
|
18824
|
+
}
|
|
18825
|
+
}
|
|
18826
|
+
async init() {
|
|
18827
|
+
await this.#db.createTable({
|
|
18828
|
+
tableName: TABLE_WORKFLOW_DEFINITIONS,
|
|
18829
|
+
schema: TABLE_SCHEMAS[TABLE_WORKFLOW_DEFINITIONS]
|
|
18830
|
+
});
|
|
18831
|
+
await this.createDefaultIndexes();
|
|
18832
|
+
await this.createCustomIndexes();
|
|
18833
|
+
}
|
|
18834
|
+
async dangerouslyClearAll() {
|
|
18835
|
+
await this.#db.clearTable({ tableName: TABLE_WORKFLOW_DEFINITIONS });
|
|
18836
|
+
}
|
|
18837
|
+
async upsert(input) {
|
|
18838
|
+
const now = /* @__PURE__ */ new Date();
|
|
18839
|
+
if (!await this.get(input.id)) {
|
|
18840
|
+
if (!("inputSchema" in input) || !input.inputSchema) throw new Error(`Cannot create workflow definition "${input.id}": inputSchema is required.`);
|
|
18841
|
+
if (!("outputSchema" in input) || !input.outputSchema) throw new Error(`Cannot create workflow definition "${input.id}": outputSchema is required.`);
|
|
18842
|
+
if (!("graph" in input) || !input.graph) throw new Error(`Cannot create workflow definition "${input.id}": graph is required.`);
|
|
18843
|
+
const record = {
|
|
18844
|
+
id: input.id,
|
|
18845
|
+
description: input.description ?? null,
|
|
18846
|
+
metadata: input.metadata ?? null,
|
|
18847
|
+
inputSchema: input.inputSchema,
|
|
18848
|
+
outputSchema: input.outputSchema,
|
|
18849
|
+
stateSchema: input.stateSchema ?? null,
|
|
18850
|
+
requestContextSchema: input.requestContextSchema ?? null,
|
|
18851
|
+
graph: input.graph,
|
|
18852
|
+
status: "active",
|
|
18853
|
+
source: "storage",
|
|
18854
|
+
authorId: "authorId" in input ? input.authorId ?? null : null,
|
|
18855
|
+
createdAt: now,
|
|
18856
|
+
updatedAt: now
|
|
18857
|
+
};
|
|
18858
|
+
try {
|
|
18859
|
+
await this.#db.insert({
|
|
18860
|
+
tableName: TABLE_WORKFLOW_DEFINITIONS,
|
|
18861
|
+
record
|
|
18862
|
+
});
|
|
18863
|
+
} catch (error) {
|
|
18864
|
+
if (!await this.get(input.id)) throw error;
|
|
18865
|
+
return this.applyUpdate(input, now);
|
|
18866
|
+
}
|
|
18867
|
+
const created = await this.get(input.id);
|
|
18868
|
+
if (!created) throw new Error(`Failed to persist workflow definition "${input.id}".`);
|
|
18869
|
+
return created;
|
|
18870
|
+
}
|
|
18871
|
+
return this.applyUpdate(input, now);
|
|
18872
|
+
}
|
|
18873
|
+
async applyUpdate(input, now) {
|
|
18874
|
+
const data = { updatedAt: now };
|
|
18875
|
+
if ("description" in input && input.description !== void 0) data.description = input.description;
|
|
18876
|
+
if ("metadata" in input && input.metadata !== void 0) data.metadata = input.metadata;
|
|
18877
|
+
if ("inputSchema" in input && input.inputSchema !== void 0) data.inputSchema = input.inputSchema;
|
|
18878
|
+
if ("outputSchema" in input && input.outputSchema !== void 0) data.outputSchema = input.outputSchema;
|
|
18879
|
+
if ("stateSchema" in input && input.stateSchema !== void 0) data.stateSchema = input.stateSchema;
|
|
18880
|
+
if ("requestContextSchema" in input && input.requestContextSchema !== void 0) data.requestContextSchema = input.requestContextSchema;
|
|
18881
|
+
if ("graph" in input && input.graph !== void 0) data.graph = input.graph;
|
|
18882
|
+
if ("status" in input && input.status !== void 0) data.status = input.status;
|
|
18883
|
+
if ("authorId" in input && input.authorId !== void 0) data.authorId = input.authorId;
|
|
18884
|
+
await this.#db.update({
|
|
18885
|
+
tableName: TABLE_WORKFLOW_DEFINITIONS,
|
|
18886
|
+
keys: { id: input.id },
|
|
18887
|
+
data
|
|
18888
|
+
});
|
|
18889
|
+
const updated = await this.get(input.id);
|
|
18890
|
+
if (!updated) throw new Error(`Failed to update workflow definition "${input.id}".`);
|
|
18891
|
+
return updated;
|
|
18892
|
+
}
|
|
18893
|
+
async get(id) {
|
|
18894
|
+
const tableName = getTableName$5({
|
|
18895
|
+
indexName: TABLE_WORKFLOW_DEFINITIONS,
|
|
18896
|
+
schemaName: getSchemaName$5(this.#schema)
|
|
18897
|
+
});
|
|
18898
|
+
const row = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE "id" = $1`, [id]);
|
|
18899
|
+
return row ? rowToDefinition(row) : null;
|
|
18900
|
+
}
|
|
18901
|
+
async list(args) {
|
|
18902
|
+
const tableName = getTableName$5({
|
|
18903
|
+
indexName: TABLE_WORKFLOW_DEFINITIONS,
|
|
18904
|
+
schemaName: getSchemaName$5(this.#schema)
|
|
18905
|
+
});
|
|
18906
|
+
const conditions = [];
|
|
18907
|
+
const params = [];
|
|
18908
|
+
if (args?.status) {
|
|
18909
|
+
params.push(args.status);
|
|
18910
|
+
conditions.push(`"status" = $${params.length}`);
|
|
18911
|
+
}
|
|
18912
|
+
if (args?.authorId !== void 0) {
|
|
18913
|
+
params.push(args.authorId);
|
|
18914
|
+
conditions.push(`"authorId" = $${params.length}`);
|
|
18915
|
+
}
|
|
18916
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
18917
|
+
const definitions = (await this.#db.client.manyOrNone(`SELECT * FROM ${tableName} ${where} ORDER BY "updatedAt" DESC`, params)).map((row) => rowToDefinition(row));
|
|
18918
|
+
return {
|
|
18919
|
+
definitions,
|
|
18920
|
+
total: definitions.length
|
|
18921
|
+
};
|
|
18922
|
+
}
|
|
18923
|
+
async delete(id) {
|
|
18924
|
+
const tableName = getTableName$5({
|
|
18925
|
+
indexName: TABLE_WORKFLOW_DEFINITIONS,
|
|
18926
|
+
schemaName: getSchemaName$5(this.#schema)
|
|
18927
|
+
});
|
|
18928
|
+
await this.#db.client.none(`DELETE FROM ${tableName} WHERE "id" = $1`, [id]);
|
|
18929
|
+
}
|
|
18930
|
+
};
|
|
18931
|
+
//#endregion
|
|
18479
18932
|
//#region src/storage/domains/workflows/index.ts
|
|
18480
18933
|
function getSchemaName(schema) {
|
|
18481
18934
|
return schema ? `"${schema}"` : "\"public\"";
|
|
@@ -19968,6 +20421,7 @@ const ALL_DOMAINS = [
|
|
|
19968
20421
|
BlobsPG,
|
|
19969
20422
|
ToolProviderConnectionsPG,
|
|
19970
20423
|
WorkflowsPG,
|
|
20424
|
+
WorkflowDefinitionsPG,
|
|
19971
20425
|
DatasetsPG,
|
|
19972
20426
|
ExperimentsPG,
|
|
19973
20427
|
BackgroundTasksPG,
|
|
@@ -20049,6 +20503,7 @@ var PostgresStore = class extends MastraCompositeStore {
|
|
|
20049
20503
|
this.stores = {
|
|
20050
20504
|
scores: new ScoresPG(domainConfig),
|
|
20051
20505
|
workflows: new WorkflowsPG(domainConfig),
|
|
20506
|
+
workflowDefinitions: new WorkflowDefinitionsPG(domainConfig),
|
|
20052
20507
|
memory: new MemoryPG(domainConfig),
|
|
20053
20508
|
notifications: new NotificationsPG(domainConfig),
|
|
20054
20509
|
observability: new ObservabilityPG(domainConfig),
|
|
@@ -20101,6 +20556,7 @@ var PostgresStore = class extends MastraCompositeStore {
|
|
|
20101
20556
|
pinnedClient = await this.#pool.connect();
|
|
20102
20557
|
const pinned = new PinnedClientAdapter(this.#pool, pinnedClient);
|
|
20103
20558
|
this.#db.pin(pinned);
|
|
20559
|
+
this.#db.setSchemaSnapshot(await loadSchemaSnapshot(pinned, this.schema));
|
|
20104
20560
|
await super.init();
|
|
20105
20561
|
this.isInitialized = true;
|
|
20106
20562
|
} catch (error) {
|
|
@@ -20112,6 +20568,7 @@ var PostgresStore = class extends MastraCompositeStore {
|
|
|
20112
20568
|
category: ErrorCategory.THIRD_PARTY
|
|
20113
20569
|
}, error);
|
|
20114
20570
|
} finally {
|
|
20571
|
+
this.#db.setSchemaSnapshot(null);
|
|
20115
20572
|
if (pinnedClient) {
|
|
20116
20573
|
this.#db.unpin();
|
|
20117
20574
|
pinnedClient.release();
|
|
@@ -20371,6 +20828,6 @@ Example Complex Query:
|
|
|
20371
20828
|
]
|
|
20372
20829
|
}`;
|
|
20373
20830
|
//#endregion
|
|
20374
|
-
export { AgentsPG, BackgroundTasksPG, BlobsPG, ChannelsPG, DatasetsPG, ExperimentsPG, FavoritesPG, MCPClientsPG, MCPServersPG, MemoryPG, NotificationsPG, ObservabilityPG, ObservabilityStoragePostgresVNext, PGVECTOR_PROMPT, PgFactoryStorage, PgVector, PoolAdapter, PostgresStore, PostgresStoreVNext, PromptBlocksPG, SchedulesPG, ScorerDefinitionsPG, ScoresPG, SkillsPG, ToolProviderConnectionsPG, WorkflowsPG, WorkspacesPG, exportSchemas };
|
|
20831
|
+
export { AgentsPG, BackgroundTasksPG, BlobsPG, ChannelsPG, DatasetsPG, ExperimentsPG, FavoritesPG, MCPClientsPG, MCPServersPG, MemoryPG, NotificationsPG, ObservabilityPG, ObservabilityStoragePostgresVNext, PGVECTOR_PROMPT, PgFactoryStorage, PgVector, PoolAdapter, PostgresStore, PostgresStoreVNext, PromptBlocksPG, SchedulesPG, ScorerDefinitionsPG, ScoresPG, SkillsPG, ToolProviderConnectionsPG, WorkflowDefinitionsPG, WorkflowsPG, WorkspacesPG, exportSchemas };
|
|
20375
20832
|
|
|
20376
20833
|
//# sourceMappingURL=index.js.map
|