@mastra/mssql 1.0.0-beta.0 → 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -150,6 +150,18 @@ var MemoryMSSQL = class extends MemoryStorage {
150
150
  }
151
151
  async listThreadsByResourceId(args) {
152
152
  const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
153
+ if (page < 0) {
154
+ throw new MastraError({
155
+ id: "MASTRA_STORAGE_MSSQL_STORE_INVALID_PAGE",
156
+ domain: ErrorDomain.STORAGE,
157
+ category: ErrorCategory.USER,
158
+ text: "Page number must be non-negative",
159
+ details: {
160
+ resourceId,
161
+ page
162
+ }
163
+ });
164
+ }
153
165
  const perPage = normalizePerPage(perPageInput, 100);
154
166
  const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
155
167
  const { field, direction } = this.parseOrderBy(orderBy);
@@ -505,43 +517,59 @@ var MemoryMSSQL = class extends MemoryStorage {
505
517
  new Error("threadId must be a non-empty string")
506
518
  );
507
519
  }
520
+ if (page < 0) {
521
+ throw new MastraError({
522
+ id: "MASTRA_STORAGE_MSSQL_STORE_INVALID_PAGE",
523
+ domain: ErrorDomain.STORAGE,
524
+ category: ErrorCategory.USER,
525
+ text: "Page number must be non-negative",
526
+ details: {
527
+ threadId,
528
+ page
529
+ }
530
+ });
531
+ }
508
532
  const perPage = normalizePerPage(perPageInput, 40);
509
533
  const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
510
534
  try {
511
535
  const { field, direction } = this.parseOrderBy(orderBy, "ASC");
512
- const orderByStatement = `ORDER BY [${field}] ${direction}`;
513
- const selectStatement = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId`;
536
+ const orderByStatement = `ORDER BY [${field}] ${direction}, [seq_id] ${direction}`;
514
537
  const tableName = getTableName({ indexName: TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
515
- const conditions = ["[thread_id] = @threadId"];
516
- const request = this.pool.request();
517
- request.input("threadId", threadId);
518
- if (resourceId) {
519
- conditions.push("[resourceId] = @resourceId");
520
- request.input("resourceId", resourceId);
521
- }
522
- if (filter?.dateRange?.start) {
523
- conditions.push("[createdAt] >= @fromDate");
524
- request.input("fromDate", filter.dateRange.start);
525
- }
526
- if (filter?.dateRange?.end) {
527
- conditions.push("[createdAt] <= @toDate");
528
- request.input("toDate", filter.dateRange.end);
529
- }
530
- const whereClause = `WHERE ${conditions.join(" AND ")}`;
531
- const countQuery = `SELECT COUNT(*) as total FROM ${tableName} ${whereClause}`;
532
- const countResult = await request.query(countQuery);
538
+ const baseQuery = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId FROM ${tableName}`;
539
+ const filters = {
540
+ thread_id: threadId,
541
+ ...resourceId ? { resourceId } : {},
542
+ ...buildDateRangeFilter(filter?.dateRange, "createdAt")
543
+ };
544
+ const { sql: actualWhereClause = "", params: whereParams } = prepareWhereClause(
545
+ filters);
546
+ const bindWhereParams = (req) => {
547
+ Object.entries(whereParams).forEach(([paramName, paramValue]) => req.input(paramName, paramValue));
548
+ };
549
+ const countRequest = this.pool.request();
550
+ bindWhereParams(countRequest);
551
+ const countResult = await countRequest.query(`SELECT COUNT(*) as total FROM ${tableName}${actualWhereClause}`);
533
552
  const total = parseInt(countResult.recordset[0]?.total, 10) || 0;
534
- const limitValue = perPageInput === false ? total : perPage;
535
- const dataQuery = `${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement} OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`;
536
- request.input("offset", offset);
537
- if (limitValue > 2147483647) {
538
- request.input("limit", sql2.BigInt, limitValue);
539
- } else {
540
- request.input("limit", limitValue);
541
- }
542
- const rowsResult = await request.query(dataQuery);
543
- const rows = rowsResult.recordset || [];
544
- const messages = [...rows];
553
+ const fetchBaseMessages = async () => {
554
+ const request = this.pool.request();
555
+ bindWhereParams(request);
556
+ if (perPageInput === false) {
557
+ const result2 = await request.query(`${baseQuery}${actualWhereClause} ${orderByStatement}`);
558
+ return result2.recordset || [];
559
+ }
560
+ request.input("offset", offset);
561
+ request.input("limit", perPage > 2147483647 ? sql2.BigInt : sql2.Int, perPage);
562
+ const result = await request.query(
563
+ `${baseQuery}${actualWhereClause} ${orderByStatement} OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`
564
+ );
565
+ return result.recordset || [];
566
+ };
567
+ const baseRows = perPage === 0 ? [] : await fetchBaseMessages();
568
+ const messages = [...baseRows];
569
+ const seqById = /* @__PURE__ */ new Map();
570
+ messages.forEach((msg) => {
571
+ if (typeof msg.seq_id === "number") seqById.set(msg.id, msg.seq_id);
572
+ });
545
573
  if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
546
574
  return {
547
575
  messages: [],
@@ -551,28 +579,33 @@ var MemoryMSSQL = class extends MemoryStorage {
551
579
  hasMore: false
552
580
  };
553
581
  }
554
- const messageIds = new Set(messages.map((m) => m.id));
555
- if (include && include.length > 0) {
582
+ if (include?.length) {
583
+ const messageIds = new Set(messages.map((m) => m.id));
556
584
  const includeMessages = await this._getIncludedMessages({ threadId, include });
557
- if (includeMessages) {
558
- for (const includeMsg of includeMessages) {
559
- if (!messageIds.has(includeMsg.id)) {
560
- messages.push(includeMsg);
561
- messageIds.add(includeMsg.id);
562
- }
585
+ includeMessages?.forEach((msg) => {
586
+ if (!messageIds.has(msg.id)) {
587
+ messages.push(msg);
588
+ messageIds.add(msg.id);
589
+ if (typeof msg.seq_id === "number") seqById.set(msg.id, msg.seq_id);
563
590
  }
564
- }
591
+ });
565
592
  }
566
593
  const parsed = this._parseAndFormatMessages(messages, "v2");
567
- let finalMessages = parsed;
568
- finalMessages = finalMessages.sort((a, b) => {
569
- const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
570
- const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
571
- return direction === "ASC" ? aValue - bValue : bValue - aValue;
594
+ const mult = direction === "ASC" ? 1 : -1;
595
+ const finalMessages = parsed.sort((a, b) => {
596
+ const aVal = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
597
+ const bVal = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
598
+ if (aVal == null || bVal == null) {
599
+ return aVal == null && bVal == null ? a.id.localeCompare(b.id) : aVal == null ? 1 : -1;
600
+ }
601
+ const diff = (typeof aVal === "number" && typeof bVal === "number" ? aVal - bVal : String(aVal).localeCompare(String(bVal))) * mult;
602
+ if (diff !== 0) return diff;
603
+ const seqA = seqById.get(a.id);
604
+ const seqB = seqById.get(b.id);
605
+ return seqA != null && seqB != null ? (seqA - seqB) * mult : a.id.localeCompare(b.id);
572
606
  });
573
- const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
574
- const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
575
- const hasMore = perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
607
+ const returnedThreadMessageCount = finalMessages.filter((m) => m.threadId === threadId).length;
608
+ const hasMore = perPageInput !== false && returnedThreadMessageCount < total && offset + perPage < total;
576
609
  return {
577
610
  messages: finalMessages,
578
611
  total,
@@ -1679,6 +1712,20 @@ ${columns}
1679
1712
  return value ? 1 : 0;
1680
1713
  }
1681
1714
  if (columnSchema?.type === "jsonb") {
1715
+ if (typeof value === "string") {
1716
+ const trimmed = value.trim();
1717
+ if (trimmed.length > 0) {
1718
+ try {
1719
+ JSON.parse(trimmed);
1720
+ return trimmed;
1721
+ } catch {
1722
+ }
1723
+ }
1724
+ return JSON.stringify(value);
1725
+ }
1726
+ if (typeof value === "bigint") {
1727
+ return value.toString();
1728
+ }
1682
1729
  return JSON.stringify(value);
1683
1730
  }
1684
1731
  if (typeof value === "object") {
@@ -2624,13 +2671,14 @@ var WorkflowsMSSQL = class extends WorkflowsStorage {
2624
2671
  snapshot = {
2625
2672
  context: {},
2626
2673
  activePaths: [],
2674
+ activeStepsPath: {},
2627
2675
  timestamp: Date.now(),
2628
2676
  suspendedPaths: {},
2629
2677
  resumeLabels: {},
2630
2678
  serializedStepGraph: [],
2679
+ status: "pending",
2631
2680
  value: {},
2632
2681
  waitingPaths: {},
2633
- status: "pending",
2634
2682
  runId,
2635
2683
  requestContext: {}
2636
2684
  };
@@ -2860,7 +2908,8 @@ var WorkflowsMSSQL = class extends WorkflowsStorage {
2860
2908
  toDate,
2861
2909
  page,
2862
2910
  perPage,
2863
- resourceId
2911
+ resourceId,
2912
+ status
2864
2913
  } = {}) {
2865
2914
  try {
2866
2915
  const conditions = [];
@@ -2869,6 +2918,10 @@ var WorkflowsMSSQL = class extends WorkflowsStorage {
2869
2918
  conditions.push(`[workflow_name] = @workflowName`);
2870
2919
  paramMap["workflowName"] = workflowName;
2871
2920
  }
2921
+ if (status) {
2922
+ conditions.push(`JSON_VALUE([snapshot], '$.status') = @status`);
2923
+ paramMap["status"] = status;
2924
+ }
2872
2925
  if (resourceId) {
2873
2926
  const hasResourceId = await this.operations.hasColumn(TABLE_WORKFLOW_SNAPSHOT, "resourceId");
2874
2927
  if (hasResourceId) {
@@ -3137,15 +3190,8 @@ var MSSQLStore = class extends MastraStorage {
3137
3190
  }) {
3138
3191
  return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
3139
3192
  }
3140
- async listWorkflowRuns({
3141
- workflowName,
3142
- fromDate,
3143
- toDate,
3144
- perPage,
3145
- page,
3146
- resourceId
3147
- } = {}) {
3148
- return this.stores.workflows.listWorkflowRuns({ workflowName, fromDate, toDate, perPage, page, resourceId });
3193
+ async listWorkflowRuns(args = {}) {
3194
+ return this.stores.workflows.listWorkflowRuns(args);
3149
3195
  }
3150
3196
  async getWorkflowRunById({
3151
3197
  runId,