@mastra/pg 1.36.0-alpha.3 → 1.36.0-alpha.5
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/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +32 -32
- package/dist/index.cjs +128 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +128 -56
- package/dist/index.js.map +1 -1
- package/dist/storage/client.d.ts +5 -2
- package/dist/storage/client.d.ts.map +1 -1
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/schedules/index.d.ts.map +1 -1
- package/dist/storage/factory-storage.d.ts.map +1 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/sql-builder.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -250,31 +250,29 @@ function buildElemMatchConditions(value, paramIndex) {
|
|
|
250
250
|
if (typeof value !== "object" || Array.isArray(value)) throw new Error("$elemMatch requires an object with conditions");
|
|
251
251
|
const conditions = [];
|
|
252
252
|
const values = [];
|
|
253
|
+
function buildFieldCondition(field, operator, operatorValue) {
|
|
254
|
+
if (operator === "$not") {
|
|
255
|
+
const nested = Object.entries(operatorValue);
|
|
256
|
+
if (nested.length === 0) throw new Error("$not requires at least one operator");
|
|
257
|
+
return `NOT (COALESCE(${nested.map(([nestedOp, nestedValue]) => buildFieldCondition(field, nestedOp, nestedValue)).join(" AND ")}, FALSE))`;
|
|
258
|
+
}
|
|
259
|
+
const operatorFn = FILTER_OPERATORS[operator];
|
|
260
|
+
if (!operatorFn) throw new Error(`Invalid operator: ${operator}`);
|
|
261
|
+
const scalarElement = field.startsWith("$");
|
|
262
|
+
const result = operatorFn(scalarElement ? "" : field, paramIndex + values.length, operatorValue);
|
|
263
|
+
const sql = result.sql.replaceAll("metadata->>", "elem->>").replaceAll("metadata->", "elem->").replaceAll("metadata#>>", "elem#>>").replaceAll("metadata#>", "elem#>").replaceAll("metadata ?", "elem ?");
|
|
264
|
+
const elementSql = scalarElement ? sql.replaceAll("elem->>''", "elem #>> '{}'").replaceAll("elem->''", "elem") : sql;
|
|
265
|
+
if (result.needsValue) {
|
|
266
|
+
const transformedValue = result.transformValue ? result.transformValue() : operatorValue;
|
|
267
|
+
if (operator === "$elemMatch") values.push(...transformedValue);
|
|
268
|
+
else values.push(transformedValue);
|
|
269
|
+
}
|
|
270
|
+
return elementSql;
|
|
271
|
+
}
|
|
253
272
|
Object.entries(value).forEach(([field, val]) => {
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
let paramValue;
|
|
258
|
-
if (field.startsWith("$")) {
|
|
259
|
-
paramOperator = field;
|
|
260
|
-
paramKey = "";
|
|
261
|
-
paramValue = val;
|
|
262
|
-
} else if (typeof val === "object" && !Array.isArray(val)) {
|
|
263
|
-
const [op, opValue] = Object.entries(val || {})[0] || [];
|
|
264
|
-
paramOperator = op;
|
|
265
|
-
paramKey = field;
|
|
266
|
-
paramValue = opValue;
|
|
267
|
-
} else {
|
|
268
|
-
paramOperator = "$eq";
|
|
269
|
-
paramKey = field;
|
|
270
|
-
paramValue = val;
|
|
271
|
-
}
|
|
272
|
-
const operatorFn = FILTER_OPERATORS[paramOperator];
|
|
273
|
-
if (!operatorFn) throw new Error(`Invalid operator: ${paramOperator}`);
|
|
274
|
-
const result = operatorFn(paramKey, nextParamIndex, paramValue);
|
|
275
|
-
const sql = result.sql.replaceAll("metadata->>", "elem->>").replaceAll("metadata->", "elem->").replaceAll("metadata#>>", "elem#>>").replaceAll("metadata#>", "elem#>");
|
|
276
|
-
conditions.push(sql);
|
|
277
|
-
if (result.needsValue) values.push(paramValue);
|
|
273
|
+
const operators = field.startsWith("$") ? [[field, val]] : typeof val === "object" && val !== null && !Array.isArray(val) ? Object.entries(val) : [["$eq", val]];
|
|
274
|
+
if (operators.length === 0) throw new Error(`$elemMatch field ${field} requires at least one operator`);
|
|
275
|
+
for (const [operator, operatorValue] of operators) conditions.push(buildFieldCondition(field, operator, operatorValue));
|
|
278
276
|
});
|
|
279
277
|
return {
|
|
280
278
|
sql: conditions.join(" AND "),
|
|
@@ -2068,8 +2066,10 @@ function truncateQuery(query, maxLength = 100) {
|
|
|
2068
2066
|
*/
|
|
2069
2067
|
var PoolAdapter = class {
|
|
2070
2068
|
$pool;
|
|
2071
|
-
|
|
2069
|
+
onRollbackError;
|
|
2070
|
+
constructor($pool, onRollbackError) {
|
|
2072
2071
|
this.$pool = $pool;
|
|
2072
|
+
this.onRollbackError = onRollbackError;
|
|
2073
2073
|
}
|
|
2074
2074
|
connect() {
|
|
2075
2075
|
return this.$pool.connect();
|
|
@@ -2106,8 +2106,14 @@ var PoolAdapter = class {
|
|
|
2106
2106
|
}
|
|
2107
2107
|
async tx(callback) {
|
|
2108
2108
|
const client = await this.$pool.connect();
|
|
2109
|
+
let destroyClient = false;
|
|
2109
2110
|
try {
|
|
2110
|
-
|
|
2111
|
+
try {
|
|
2112
|
+
await client.query("BEGIN");
|
|
2113
|
+
} catch (error) {
|
|
2114
|
+
destroyClient = true;
|
|
2115
|
+
throw error;
|
|
2116
|
+
}
|
|
2111
2117
|
const txClient = new TransactionClient(client);
|
|
2112
2118
|
try {
|
|
2113
2119
|
const result = await callback(txClient);
|
|
@@ -2119,12 +2125,16 @@ var PoolAdapter = class {
|
|
|
2119
2125
|
try {
|
|
2120
2126
|
await client.query("ROLLBACK");
|
|
2121
2127
|
} catch (rollbackError) {
|
|
2122
|
-
|
|
2128
|
+
destroyClient = true;
|
|
2129
|
+
try {
|
|
2130
|
+
if (this.onRollbackError) await this.onRollbackError(rollbackError);
|
|
2131
|
+
else console.error("Failed to rollback transaction:", rollbackError);
|
|
2132
|
+
} catch {}
|
|
2123
2133
|
}
|
|
2124
2134
|
throw error;
|
|
2125
2135
|
}
|
|
2126
2136
|
} finally {
|
|
2127
|
-
client.release();
|
|
2137
|
+
client.release(destroyClient || void 0);
|
|
2128
2138
|
}
|
|
2129
2139
|
}
|
|
2130
2140
|
};
|
|
@@ -2231,6 +2241,7 @@ var TransactionClient = class {
|
|
|
2231
2241
|
var PinnedClientAdapter = class {
|
|
2232
2242
|
$pool;
|
|
2233
2243
|
pinnedClient;
|
|
2244
|
+
onRollbackError;
|
|
2234
2245
|
/**
|
|
2235
2246
|
* Serialization tail. Domain init() methods fire via Promise.all in
|
|
2236
2247
|
* MastraCompositeStore.#runInit(), so without our own gate every domain's
|
|
@@ -2241,9 +2252,14 @@ var PinnedClientAdapter = class {
|
|
|
2241
2252
|
* the reliance on pg's internal queue.
|
|
2242
2253
|
*/
|
|
2243
2254
|
#tail = Promise.resolve();
|
|
2244
|
-
|
|
2255
|
+
#rollbackError;
|
|
2256
|
+
constructor($pool, pinnedClient, onRollbackError) {
|
|
2245
2257
|
this.$pool = $pool;
|
|
2246
2258
|
this.pinnedClient = pinnedClient;
|
|
2259
|
+
this.onRollbackError = onRollbackError;
|
|
2260
|
+
}
|
|
2261
|
+
get shouldDestroyClient() {
|
|
2262
|
+
return this.#rollbackError !== void 0;
|
|
2247
2263
|
}
|
|
2248
2264
|
/**
|
|
2249
2265
|
* Run `fn` after any previously enqueued work on this pinned client has
|
|
@@ -2251,7 +2267,11 @@ var PinnedClientAdapter = class {
|
|
|
2251
2267
|
* resume on the next caller's turn.
|
|
2252
2268
|
*/
|
|
2253
2269
|
#enqueue(fn) {
|
|
2254
|
-
const
|
|
2270
|
+
const run = async () => {
|
|
2271
|
+
if (this.shouldDestroyClient) throw this.#rollbackError;
|
|
2272
|
+
return fn();
|
|
2273
|
+
};
|
|
2274
|
+
const next = this.#tail.then(run, run);
|
|
2255
2275
|
this.#tail = next.catch(() => void 0);
|
|
2256
2276
|
return next;
|
|
2257
2277
|
}
|
|
@@ -2303,7 +2323,12 @@ var PinnedClientAdapter = class {
|
|
|
2303
2323
|
}
|
|
2304
2324
|
tx(callback) {
|
|
2305
2325
|
return this.#enqueue(async () => {
|
|
2306
|
-
|
|
2326
|
+
try {
|
|
2327
|
+
await this.pinnedClient.query("BEGIN");
|
|
2328
|
+
} catch (error) {
|
|
2329
|
+
this.#rollbackError = error;
|
|
2330
|
+
throw error;
|
|
2331
|
+
}
|
|
2307
2332
|
const txClient = new TransactionClient(this.pinnedClient);
|
|
2308
2333
|
try {
|
|
2309
2334
|
const result = await callback(txClient);
|
|
@@ -2315,7 +2340,11 @@ var PinnedClientAdapter = class {
|
|
|
2315
2340
|
try {
|
|
2316
2341
|
await this.pinnedClient.query("ROLLBACK");
|
|
2317
2342
|
} catch (rollbackError) {
|
|
2318
|
-
|
|
2343
|
+
this.#rollbackError = rollbackError;
|
|
2344
|
+
try {
|
|
2345
|
+
if (this.onRollbackError) await this.onRollbackError(rollbackError);
|
|
2346
|
+
else console.error("Failed to rollback transaction:", rollbackError);
|
|
2347
|
+
} catch {}
|
|
2319
2348
|
}
|
|
2320
2349
|
throw error;
|
|
2321
2350
|
}
|
|
@@ -3405,12 +3434,16 @@ var PgDB = class extends MastraBase {
|
|
|
3405
3434
|
}
|
|
3406
3435
|
if (snapshot) {
|
|
3407
3436
|
snapshot.tables.add(tableName);
|
|
3408
|
-
if (isNewTable)
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
created.
|
|
3413
|
-
|
|
3437
|
+
if (isNewTable) {
|
|
3438
|
+
snapshot.createdTables.add(tableName);
|
|
3439
|
+
snapshot.columns.set(tableName, new Set(await this.getTableColumns(tableName)));
|
|
3440
|
+
} else {
|
|
3441
|
+
const created = this.snapshotColumns(snapshot, tableName);
|
|
3442
|
+
for (const [name, def] of Object.entries(schema)) {
|
|
3443
|
+
const parsedName = parseSqlIdentifier(name, "column name");
|
|
3444
|
+
created.add(parsedName);
|
|
3445
|
+
if (def.type === "timestamp") created.add(`${parsedName}Z`);
|
|
3446
|
+
}
|
|
3414
3447
|
}
|
|
3415
3448
|
}
|
|
3416
3449
|
}
|
|
@@ -11799,15 +11832,25 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
11799
11832
|
* @param schemaPrefix - Prefix for index names (e.g. "my_schema_" or "")
|
|
11800
11833
|
*/
|
|
11801
11834
|
static getDefaultIndexDefs(schemaPrefix) {
|
|
11802
|
-
return [
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11835
|
+
return [
|
|
11836
|
+
{
|
|
11837
|
+
name: `${schemaPrefix}mastra_threads_resourceid_createdat_idx`,
|
|
11838
|
+
table: TABLE_THREADS,
|
|
11839
|
+
columns: ["resourceId", "createdAt DESC"]
|
|
11840
|
+
},
|
|
11841
|
+
{
|
|
11842
|
+
name: `${schemaPrefix}mastra_threads_metadata_gin_idx`,
|
|
11843
|
+
table: TABLE_THREADS,
|
|
11844
|
+
columns: ["metadata"],
|
|
11845
|
+
method: "gin",
|
|
11846
|
+
opclass: "jsonb_path_ops"
|
|
11847
|
+
},
|
|
11848
|
+
{
|
|
11849
|
+
name: `${schemaPrefix}mastra_messages_thread_id_createdat_idx`,
|
|
11850
|
+
table: TABLE_MESSAGES,
|
|
11851
|
+
columns: ["thread_id", "createdAt DESC"]
|
|
11852
|
+
}
|
|
11853
|
+
];
|
|
11811
11854
|
}
|
|
11812
11855
|
/**
|
|
11813
11856
|
* Returns all DDL statements for this domain: tables (threads, messages, resources, OM), indexes.
|
|
@@ -21926,6 +21969,7 @@ async function dangerouslyClearTracing(client, schema) {
|
|
|
21926
21969
|
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? [
|
|
21927
21970
|
"span-query",
|
|
21928
21971
|
"span-query-context-fields",
|
|
21972
|
+
...coreStorage.SPAN_QUERY_ORDER_FIELDS?.includes("durationMs") ? ["span-query-duration-sort"] : [],
|
|
21929
21973
|
..."model" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {}) ? ["span-query-model-fields"] : []
|
|
21930
21974
|
] : [];
|
|
21931
21975
|
const spanAggregateFeatures = typeof coreStorage.planSpanAggregate === "function" ? ["span-aggregate", ..."model" in (coreStorage.SPAN_AGGREGATE_DIMENSION_REGISTRY ?? {}) ? ["span-aggregate-model-dimensions"] : []] : [];
|
|
@@ -22997,6 +23041,8 @@ function rowToSchedule(row) {
|
|
|
22997
23041
|
if (metadata !== void 0) schedule.metadata = metadata;
|
|
22998
23042
|
if (row.owner_type != null) schedule.ownerType = String(row.owner_type);
|
|
22999
23043
|
if (row.owner_id != null) schedule.ownerId = String(row.owner_id);
|
|
23044
|
+
if (row.run_at != null) schedule.runAt = Number(row.run_at);
|
|
23045
|
+
if (row.end_at != null) schedule.endAt = Number(row.end_at);
|
|
23000
23046
|
return schedule;
|
|
23001
23047
|
}
|
|
23002
23048
|
function rowToTrigger(row) {
|
|
@@ -23056,6 +23102,11 @@ var SchedulesPG = class SchedulesPG extends SchedulesStorage {
|
|
|
23056
23102
|
tableName: TABLE_SCHEDULES,
|
|
23057
23103
|
schema: TABLE_SCHEMAS[TABLE_SCHEDULES]
|
|
23058
23104
|
});
|
|
23105
|
+
await this.#db.alterTable({
|
|
23106
|
+
tableName: TABLE_SCHEDULES,
|
|
23107
|
+
schema: TABLE_SCHEMAS[TABLE_SCHEDULES],
|
|
23108
|
+
ifNotExists: ["run_at", "end_at"]
|
|
23109
|
+
});
|
|
23059
23110
|
await this.#db.createTable({
|
|
23060
23111
|
tableName: TABLE_SCHEDULE_TRIGGERS,
|
|
23061
23112
|
schema: TABLE_SCHEMAS[TABLE_SCHEDULE_TRIGGERS]
|
|
@@ -23183,7 +23234,9 @@ var SchedulesPG = class SchedulesPG extends SchedulesStorage {
|
|
|
23183
23234
|
updated_at: schedule.updatedAt,
|
|
23184
23235
|
metadata: schedule.metadata ?? null,
|
|
23185
23236
|
owner_type: schedule.ownerType ?? null,
|
|
23186
|
-
owner_id: schedule.ownerId ?? null
|
|
23237
|
+
owner_id: schedule.ownerId ?? null,
|
|
23238
|
+
run_at: schedule.runAt ?? null,
|
|
23239
|
+
end_at: schedule.endAt ?? null
|
|
23187
23240
|
}
|
|
23188
23241
|
});
|
|
23189
23242
|
return schedule;
|
|
@@ -23253,6 +23306,8 @@ var SchedulesPG = class SchedulesPG extends SchedulesStorage {
|
|
|
23253
23306
|
if ("metadata" in patch) push("metadata = ?::jsonb", patch.metadata != null ? toPgJson(patch.metadata) : null);
|
|
23254
23307
|
if ("ownerType" in patch) push("owner_type = ?", patch.ownerType ?? null);
|
|
23255
23308
|
if ("ownerId" in patch) push("owner_id = ?", patch.ownerId ?? null);
|
|
23309
|
+
if ("runAt" in patch) push("run_at = ?", patch.runAt ?? null);
|
|
23310
|
+
if ("endAt" in patch) push("end_at = ?", patch.endAt ?? null);
|
|
23256
23311
|
push("updated_at = ?", Date.now());
|
|
23257
23312
|
if (setClauses.length === 1) {
|
|
23258
23313
|
const existing = await this.#getSchedule(this.#client, id);
|
|
@@ -28077,18 +28132,29 @@ var PgFactoryStorageOps = class {
|
|
|
28077
28132
|
};
|
|
28078
28133
|
if (this.#transactionClient) return run(this.#transactionClient);
|
|
28079
28134
|
const client = await this.#queryable.connect();
|
|
28135
|
+
let releaseError;
|
|
28080
28136
|
try {
|
|
28081
|
-
|
|
28137
|
+
try {
|
|
28138
|
+
await client.query("BEGIN");
|
|
28139
|
+
} catch (error) {
|
|
28140
|
+
releaseError = error instanceof Error ? error : new Error(String(error));
|
|
28141
|
+
throw error;
|
|
28142
|
+
}
|
|
28082
28143
|
try {
|
|
28083
28144
|
const result = await run(client);
|
|
28084
28145
|
await client.query("COMMIT");
|
|
28085
28146
|
return result;
|
|
28086
28147
|
} catch (error) {
|
|
28087
|
-
|
|
28148
|
+
try {
|
|
28149
|
+
await client.query("ROLLBACK");
|
|
28150
|
+
} catch (rollbackError) {
|
|
28151
|
+
releaseError = rollbackError instanceof Error ? rollbackError : new Error(String(rollbackError));
|
|
28152
|
+
throw new AggregateError([error, rollbackError], "Factory transaction and rollback both failed");
|
|
28153
|
+
}
|
|
28088
28154
|
throw error;
|
|
28089
28155
|
}
|
|
28090
28156
|
} finally {
|
|
28091
|
-
client.release();
|
|
28157
|
+
client.release(releaseError);
|
|
28092
28158
|
}
|
|
28093
28159
|
}
|
|
28094
28160
|
};
|
|
@@ -28145,7 +28211,12 @@ var PgFactoryStorage = class extends FactoryStorage {
|
|
|
28145
28211
|
let transactionOpen = false;
|
|
28146
28212
|
let releaseError;
|
|
28147
28213
|
try {
|
|
28148
|
-
|
|
28214
|
+
try {
|
|
28215
|
+
await client.query(options?.isolationLevel === "serializable" ? "BEGIN ISOLATION LEVEL SERIALIZABLE" : "BEGIN");
|
|
28216
|
+
} catch (error) {
|
|
28217
|
+
releaseError = error instanceof Error ? error : new Error(String(error));
|
|
28218
|
+
throw error;
|
|
28219
|
+
}
|
|
28149
28220
|
transactionOpen = true;
|
|
28150
28221
|
const result = await fn(new PgFactoryStorageOps(client, this.#schemas, client));
|
|
28151
28222
|
await client.query("COMMIT");
|
|
@@ -28347,8 +28418,9 @@ var PostgresStore = class extends MastraCompositeStore {
|
|
|
28347
28418
|
this.#ownsWritePool = true;
|
|
28348
28419
|
}
|
|
28349
28420
|
this.#readPool = config.readPool ?? this.#writePool;
|
|
28350
|
-
|
|
28351
|
-
this.#
|
|
28421
|
+
const onRollbackError = (error) => this.logger?.error?.("Transaction rollback failed", { error });
|
|
28422
|
+
this.#db = new RoutingDbClient(new PoolAdapter(this.#writePool, onRollbackError));
|
|
28423
|
+
this.#readDb = this.#readPool === this.#writePool ? this.#db : new PoolAdapter(this.#readPool, onRollbackError);
|
|
28352
28424
|
const domainConfig = {
|
|
28353
28425
|
client: this.#db,
|
|
28354
28426
|
readClient: this.#readDb,
|
|
@@ -28417,7 +28489,7 @@ var PostgresStore = class extends MastraCompositeStore {
|
|
|
28417
28489
|
let pinned;
|
|
28418
28490
|
try {
|
|
28419
28491
|
pinnedClient = await this.#writePool.connect();
|
|
28420
|
-
pinned = new PinnedClientAdapter(this.#writePool, pinnedClient);
|
|
28492
|
+
pinned = new PinnedClientAdapter(this.#writePool, pinnedClient, (error) => this.logger?.error?.("Transaction rollback failed", { error }));
|
|
28421
28493
|
this.#db.pin(pinned);
|
|
28422
28494
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
28423
28495
|
this.#db.setSchemaSnapshot(await loadSchemaSnapshot(pinned, this.schema));
|
|
@@ -28442,7 +28514,7 @@ var PostgresStore = class extends MastraCompositeStore {
|
|
|
28442
28514
|
this.#db.setSchemaSnapshot(null);
|
|
28443
28515
|
if (pinnedClient) {
|
|
28444
28516
|
this.#db.unpin();
|
|
28445
|
-
pinnedClient.release();
|
|
28517
|
+
pinnedClient.release(pinned?.shouldDestroyClient || void 0);
|
|
28446
28518
|
}
|
|
28447
28519
|
}
|
|
28448
28520
|
}
|