@mastra/mssql 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/docs/SKILL.md +2 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-mssql.md +6 -6
- package/dist/index.cjs +85 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +86 -7
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +12 -0
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +1 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
2
|
-
import { MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCHEMAS, createStorageErrorId, normalizePerPage, calculatePagination, ObservabilityStorage, TABLE_SPANS, SPAN_SCHEMA, listTracesArgsSchema, toTraceSpans, ScoresStorage, TABLE_SCORERS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, MastraCompositeStore,
|
|
2
|
+
import { MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCHEMAS, createStorageErrorId, normalizePerPage, calculatePagination, ObservabilityStorage, TABLE_SPANS, SPAN_SCHEMA, listTracesArgsSchema, toTraceSpans, ScoresStorage, TABLE_SCORERS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, MastraCompositeStore, getDefaultValue, transformScoreRow as transformScoreRow$1, TraceStatus } from '@mastra/core/storage';
|
|
3
3
|
import sql from 'mssql';
|
|
4
4
|
import { MessageList } from '@mastra/core/agent';
|
|
5
5
|
import { MastraBase } from '@mastra/core/base';
|
|
@@ -52,6 +52,8 @@ var MssqlDB = class extends MastraBase {
|
|
|
52
52
|
skipDefaultIndexes;
|
|
53
53
|
setupSchemaPromise = null;
|
|
54
54
|
schemaSetupComplete = void 0;
|
|
55
|
+
/** Cache of actual table columns: tableName -> Set<columnName> */
|
|
56
|
+
tableColumnsCache = /* @__PURE__ */ new Map();
|
|
55
57
|
/**
|
|
56
58
|
* Columns that participate in composite indexes need smaller sizes (NVARCHAR(100)).
|
|
57
59
|
* MSSQL has a 900-byte index key limit, so composite indexes with NVARCHAR(400) columns fail.
|
|
@@ -136,6 +138,41 @@ var MssqlDB = class extends MastraBase {
|
|
|
136
138
|
this.schemaName = schemaName;
|
|
137
139
|
this.skipDefaultIndexes = skipDefaultIndexes;
|
|
138
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Gets the set of column names that actually exist in the database table.
|
|
143
|
+
* Results are cached; the cache is invalidated when alterTable() adds new columns.
|
|
144
|
+
*/
|
|
145
|
+
async getTableColumns(tableName) {
|
|
146
|
+
const cached = this.tableColumnsCache.get(tableName);
|
|
147
|
+
if (cached) return cached;
|
|
148
|
+
const schema = this.schemaName || "dbo";
|
|
149
|
+
const request = this.pool.request();
|
|
150
|
+
request.input("schema", schema);
|
|
151
|
+
request.input("tableName", tableName);
|
|
152
|
+
const result = await request.query(
|
|
153
|
+
`SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @tableName`
|
|
154
|
+
);
|
|
155
|
+
const columns = new Set((result.recordset || []).map((r) => r.COLUMN_NAME));
|
|
156
|
+
if (columns.size > 0) {
|
|
157
|
+
this.tableColumnsCache.set(tableName, columns);
|
|
158
|
+
}
|
|
159
|
+
return columns;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Filters a record to only include columns that exist in the actual database table.
|
|
163
|
+
* Unknown columns are silently dropped to ensure forward compatibility.
|
|
164
|
+
*/
|
|
165
|
+
async filterRecordToKnownColumns(tableName, record) {
|
|
166
|
+
const knownColumns = await this.getTableColumns(tableName);
|
|
167
|
+
if (knownColumns.size === 0) return record;
|
|
168
|
+
const filtered = {};
|
|
169
|
+
for (const [key, value] of Object.entries(record)) {
|
|
170
|
+
if (knownColumns.has(key)) {
|
|
171
|
+
filtered[key] = value;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return filtered;
|
|
175
|
+
}
|
|
139
176
|
async hasColumn(table, column) {
|
|
140
177
|
const schema = this.schemaName || "dbo";
|
|
141
178
|
const request = this.pool.request();
|
|
@@ -191,13 +228,15 @@ var MssqlDB = class extends MastraBase {
|
|
|
191
228
|
transaction
|
|
192
229
|
}) {
|
|
193
230
|
try {
|
|
194
|
-
const
|
|
231
|
+
const filteredRecord = await this.filterRecordToKnownColumns(tableName, record);
|
|
232
|
+
const columns = Object.keys(filteredRecord);
|
|
233
|
+
if (columns.length === 0) return;
|
|
195
234
|
const parsedColumns = columns.map((col) => parseSqlIdentifier(col, "column name"));
|
|
196
235
|
const paramNames = columns.map((_, i) => `@param${i}`);
|
|
197
236
|
const insertSql = `INSERT INTO ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} (${parsedColumns.map((c) => `[${c}]`).join(", ")}) VALUES (${paramNames.join(", ")})`;
|
|
198
237
|
const request = transaction ? transaction.request() : this.pool.request();
|
|
199
238
|
columns.forEach((col, i) => {
|
|
200
|
-
const value =
|
|
239
|
+
const value = filteredRecord[col];
|
|
201
240
|
const preparedValue = this.prepareValue(value, col, tableName);
|
|
202
241
|
if (preparedValue instanceof Date) {
|
|
203
242
|
request.input(`param${i}`, sql.DateTime2, preparedValue);
|
|
@@ -388,6 +427,8 @@ Note: This migration may take some time for large tables.
|
|
|
388
427
|
},
|
|
389
428
|
error
|
|
390
429
|
);
|
|
430
|
+
} finally {
|
|
431
|
+
this.tableColumnsCache.delete(tableName);
|
|
391
432
|
}
|
|
392
433
|
}
|
|
393
434
|
/**
|
|
@@ -615,6 +656,8 @@ Note: This migration may take some time for large tables.
|
|
|
615
656
|
},
|
|
616
657
|
error
|
|
617
658
|
);
|
|
659
|
+
} finally {
|
|
660
|
+
this.tableColumnsCache.delete(tableName);
|
|
618
661
|
}
|
|
619
662
|
}
|
|
620
663
|
async load({ tableName, keys }) {
|
|
@@ -698,6 +741,8 @@ Note: This migration may take some time for large tables.
|
|
|
698
741
|
},
|
|
699
742
|
error
|
|
700
743
|
);
|
|
744
|
+
} finally {
|
|
745
|
+
this.tableColumnsCache.delete(tableName);
|
|
701
746
|
}
|
|
702
747
|
}
|
|
703
748
|
/**
|
|
@@ -789,10 +834,12 @@ Note: This migration may take some time for large tables.
|
|
|
789
834
|
text: "Cannot update without keys to identify records"
|
|
790
835
|
});
|
|
791
836
|
}
|
|
837
|
+
const filteredData = await this.filterRecordToKnownColumns(tableName, data);
|
|
838
|
+
if (Object.keys(filteredData).length === 0) return;
|
|
792
839
|
const setClauses = [];
|
|
793
840
|
const request = transaction ? transaction.request() : this.pool.request();
|
|
794
841
|
let paramIndex = 0;
|
|
795
|
-
Object.entries(
|
|
842
|
+
Object.entries(filteredData).forEach(([key, value]) => {
|
|
796
843
|
const parsedKey = parseSqlIdentifier(key, "column name");
|
|
797
844
|
const paramName = `set${paramIndex++}`;
|
|
798
845
|
setClauses.push(`[${parsedKey}] = @${paramName}`);
|
|
@@ -1728,6 +1775,18 @@ var MemoryMSSQL = class _MemoryMSSQL extends MemoryStorage {
|
|
|
1728
1775
|
);
|
|
1729
1776
|
}
|
|
1730
1777
|
}
|
|
1778
|
+
_sortMessages(messages, field, direction) {
|
|
1779
|
+
const mult = direction === "ASC" ? 1 : -1;
|
|
1780
|
+
return messages.sort((a, b) => {
|
|
1781
|
+
const aVal = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
1782
|
+
const bVal = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
1783
|
+
if (aVal == null || bVal == null) {
|
|
1784
|
+
return aVal == null && bVal == null ? a.id.localeCompare(b.id) : aVal == null ? 1 : -1;
|
|
1785
|
+
}
|
|
1786
|
+
const diff = (typeof aVal === "number" && typeof bVal === "number" ? aVal - bVal : String(aVal).localeCompare(String(bVal))) * mult;
|
|
1787
|
+
return diff !== 0 ? diff : a.id.localeCompare(b.id);
|
|
1788
|
+
});
|
|
1789
|
+
}
|
|
1731
1790
|
async _getIncludedMessages({ include }) {
|
|
1732
1791
|
if (!include || include.length === 0) return null;
|
|
1733
1792
|
const unionQueries = [];
|
|
@@ -1889,6 +1948,20 @@ var MemoryMSSQL = class _MemoryMSSQL extends MemoryStorage {
|
|
|
1889
1948
|
const bindWhereParams = (req) => {
|
|
1890
1949
|
Object.entries(whereParams).forEach(([paramName, paramValue]) => req.input(paramName, paramValue));
|
|
1891
1950
|
};
|
|
1951
|
+
if (perPage === 0 && (!include || include.length === 0)) {
|
|
1952
|
+
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
1953
|
+
}
|
|
1954
|
+
if (perPage === 0 && include && include.length > 0) {
|
|
1955
|
+
const includeMessages = await this._getIncludedMessages({ include });
|
|
1956
|
+
const messages2 = this._parseAndFormatMessages(includeMessages ?? [], "v2");
|
|
1957
|
+
return {
|
|
1958
|
+
messages: this._sortMessages(messages2, field, direction),
|
|
1959
|
+
total: 0,
|
|
1960
|
+
page,
|
|
1961
|
+
perPage: perPageForResponse,
|
|
1962
|
+
hasMore: false
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1892
1965
|
const countRequest = this.pool.request();
|
|
1893
1966
|
bindWhereParams(countRequest);
|
|
1894
1967
|
const countResult = await countRequest.query(`SELECT COUNT(*) as total FROM ${tableName}${actualWhereClause}`);
|
|
@@ -2354,6 +2427,11 @@ var ObservabilityMSSQL = class _ObservabilityMSSQL extends ObservabilityStorage
|
|
|
2354
2427
|
this.needsConnect = false;
|
|
2355
2428
|
}
|
|
2356
2429
|
await this.db.createTable({ tableName: TABLE_SPANS, schema: SPAN_SCHEMA });
|
|
2430
|
+
await this.db.alterTable({
|
|
2431
|
+
tableName: TABLE_SPANS,
|
|
2432
|
+
schema: SPAN_SCHEMA,
|
|
2433
|
+
ifNotExists: ["requestContext"]
|
|
2434
|
+
});
|
|
2357
2435
|
await this.createDefaultIndexes();
|
|
2358
2436
|
await this.createCustomIndexes();
|
|
2359
2437
|
}
|
|
@@ -2666,7 +2744,8 @@ var ObservabilityMSSQL = class _ObservabilityMSSQL extends ObservabilityStorage
|
|
|
2666
2744
|
}
|
|
2667
2745
|
async listTraces(args) {
|
|
2668
2746
|
const { filters, pagination, orderBy } = listTracesArgsSchema.parse(args);
|
|
2669
|
-
const
|
|
2747
|
+
const page = pagination?.page ?? 0;
|
|
2748
|
+
const perPage = pagination?.perPage ?? 10;
|
|
2670
2749
|
const tableName = getTableName2({
|
|
2671
2750
|
indexName: TABLE_SPANS,
|
|
2672
2751
|
schemaName: getSchemaName2(this.schema)
|
|
@@ -2831,8 +2910,8 @@ var ObservabilityMSSQL = class _ObservabilityMSSQL extends ObservabilityStorage
|
|
|
2831
2910
|
}
|
|
2832
2911
|
}
|
|
2833
2912
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2834
|
-
const sortField = orderBy
|
|
2835
|
-
const sortDirection = orderBy
|
|
2913
|
+
const sortField = orderBy?.field ?? "startedAt";
|
|
2914
|
+
const sortDirection = orderBy?.direction ?? "DESC";
|
|
2836
2915
|
const countRequest = this.pool.request();
|
|
2837
2916
|
Object.entries(params).forEach(([key, value]) => {
|
|
2838
2917
|
countRequest.input(key, value);
|