@mastra/cloudflare-d1 1.0.0-beta.10 → 1.0.0-beta.12

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 CHANGED
@@ -1,5 +1,84 @@
1
1
  # @mastra/cloudflare-d1
2
2
 
3
+ ## 1.0.0-beta.12
4
+
5
+ ### Patch Changes
6
+
7
+ - Renamed MastraStorage to MastraCompositeStore for better clarity. The old MastraStorage name remains available as a deprecated alias for backward compatibility, but will be removed in a future version. ([#12093](https://github.com/mastra-ai/mastra/pull/12093))
8
+
9
+ **Migration:**
10
+
11
+ Update your imports and usage:
12
+
13
+ ```typescript
14
+ // Before
15
+ import { MastraStorage } from '@mastra/core/storage';
16
+
17
+ const storage = new MastraStorage({
18
+ id: 'composite',
19
+ domains: { ... }
20
+ });
21
+
22
+ // After
23
+ import { MastraCompositeStore } from '@mastra/core/storage';
24
+
25
+ const storage = new MastraCompositeStore({
26
+ id: 'composite',
27
+ domains: { ... }
28
+ });
29
+ ```
30
+
31
+ The new name better reflects that this is a composite storage implementation that routes different domains (workflows, traces, messages) to different underlying stores, avoiding confusion with the general "Mastra Storage" concept.
32
+
33
+ - Updated dependencies [[`026b848`](https://github.com/mastra-ai/mastra/commit/026b8483fbf5b6d977be8f7e6aac8d15c75558ac), [`ffa553a`](https://github.com/mastra-ai/mastra/commit/ffa553a3edc1bd17d73669fba66d6b6f4ac10897)]:
34
+ - @mastra/core@1.0.0-beta.26
35
+
36
+ ## 1.0.0-beta.11
37
+
38
+ ### Patch Changes
39
+
40
+ - Added new `listThreads` method for flexible thread filtering across all storage adapters. ([#11832](https://github.com/mastra-ai/mastra/pull/11832))
41
+
42
+ **New Features**
43
+ - Filter threads by `resourceId`, `metadata`, or both (with AND logic for metadata key-value pairs)
44
+ - All filter parameters are optional, allowing you to list all threads or filter as needed
45
+ - Full pagination and sorting support
46
+
47
+ **Example Usage**
48
+
49
+ ```typescript
50
+ // List all threads
51
+ const allThreads = await memory.listThreads({});
52
+
53
+ // Filter by resourceId only
54
+ const userThreads = await memory.listThreads({
55
+ filter: { resourceId: 'user-123' },
56
+ });
57
+
58
+ // Filter by metadata only
59
+ const supportThreads = await memory.listThreads({
60
+ filter: { metadata: { category: 'support' } },
61
+ });
62
+
63
+ // Filter by both with pagination
64
+ const filteredThreads = await memory.listThreads({
65
+ filter: {
66
+ resourceId: 'user-123',
67
+ metadata: { priority: 'high', status: 'open' },
68
+ },
69
+ orderBy: { field: 'updatedAt', direction: 'DESC' },
70
+ page: 0,
71
+ perPage: 20,
72
+ });
73
+ ```
74
+
75
+ **Security Improvements**
76
+ - Added validation to prevent SQL injection via malicious metadata keys
77
+ - Added pagination parameter validation to prevent integer overflow attacks
78
+
79
+ - Updated dependencies [[`ed3e3dd`](https://github.com/mastra-ai/mastra/commit/ed3e3ddec69d564fe2b125e083437f76331f1283), [`6833c69`](https://github.com/mastra-ai/mastra/commit/6833c69607418d257750bbcdd84638993d343539), [`47b1c16`](https://github.com/mastra-ai/mastra/commit/47b1c16a01c7ffb6765fe1e499b49092f8b7eba3), [`3a76a80`](https://github.com/mastra-ai/mastra/commit/3a76a80284cb71a0faa975abb3d4b2a9631e60cd), [`8538a0d`](https://github.com/mastra-ai/mastra/commit/8538a0d232619bf55dad7ddc2a8b0ca77c679a87), [`9312dcd`](https://github.com/mastra-ai/mastra/commit/9312dcd1c6f5b321929e7d382e763d95fdc030f5)]:
80
+ - @mastra/core@1.0.0-beta.25
81
+
3
82
  ## 1.0.0-beta.10
4
83
 
5
84
  ### Patch Changes
@@ -28,4 +28,4 @@ docs/
28
28
  ## Version
29
29
 
30
30
  Package: @mastra/cloudflare-d1
31
- Version: 1.0.0-beta.10
31
+ Version: 1.0.0-beta.12
@@ -5,7 +5,7 @@ description: Documentation for @mastra/cloudflare-d1. Includes links to type def
5
5
 
6
6
  # @mastra/cloudflare-d1 Documentation
7
7
 
8
- > **Version**: 1.0.0-beta.10
8
+ > **Version**: 1.0.0-beta.12
9
9
  > **Package**: @mastra/cloudflare-d1
10
10
 
11
11
  ## Quick Navigation
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.0-beta.10",
2
+ "version": "1.0.0-beta.12",
3
3
  "package": "@mastra/cloudflare-d1",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -846,18 +846,33 @@ var MemoryStorageD1 = class extends storage.MemoryStorage {
846
846
  return null;
847
847
  }
848
848
  }
849
- async listThreadsByResourceId(args) {
850
- const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
849
+ async listThreads(args) {
850
+ const { page = 0, perPage: perPageInput, orderBy, filter } = args;
851
+ try {
852
+ this.validatePaginationInput(page, perPageInput ?? 100);
853
+ } catch (error$1) {
854
+ throw new error.MastraError(
855
+ {
856
+ id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_THREADS", "INVALID_PAGE"),
857
+ domain: error.ErrorDomain.STORAGE,
858
+ category: error.ErrorCategory.USER,
859
+ details: { page, ...perPageInput !== void 0 && { perPage: perPageInput } }
860
+ },
861
+ error$1 instanceof Error ? error$1 : new Error("Invalid pagination parameters")
862
+ );
863
+ }
851
864
  const perPage = storage.normalizePerPage(perPageInput, 100);
852
- if (page < 0) {
865
+ try {
866
+ this.validateMetadataKeys(filter?.metadata);
867
+ } catch (error$1) {
853
868
  throw new error.MastraError(
854
869
  {
855
- id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
870
+ id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_THREADS", "INVALID_METADATA_KEY"),
856
871
  domain: error.ErrorDomain.STORAGE,
857
872
  category: error.ErrorCategory.USER,
858
- details: { page }
873
+ details: { metadataKeys: filter?.metadata ? Object.keys(filter.metadata).join(", ") : "" }
859
874
  },
860
- new Error("page must be >= 0")
875
+ error$1 instanceof Error ? error$1 : new Error("Invalid metadata key")
861
876
  );
862
877
  }
863
878
  const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
@@ -870,11 +885,51 @@ var MemoryStorageD1 = class extends storage.MemoryStorage {
870
885
  metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata || "{}") : row.metadata || {}
871
886
  });
872
887
  try {
873
- const countQuery = createSqlBuilder().count().from(fullTableName).where("resourceId = ?", resourceId);
888
+ let countQuery = createSqlBuilder().count().from(fullTableName);
889
+ let selectQuery = createSqlBuilder().select("*").from(fullTableName);
890
+ if (filter?.resourceId) {
891
+ countQuery = countQuery.whereAnd("resourceId = ?", filter.resourceId);
892
+ selectQuery = selectQuery.whereAnd("resourceId = ?", filter.resourceId);
893
+ }
894
+ if (filter?.metadata && Object.keys(filter.metadata).length > 0) {
895
+ for (const [key, value] of Object.entries(filter.metadata)) {
896
+ if (value !== null && typeof value === "object") {
897
+ throw new error.MastraError(
898
+ {
899
+ id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_THREADS", "INVALID_METADATA_VALUE"),
900
+ domain: error.ErrorDomain.STORAGE,
901
+ category: error.ErrorCategory.USER,
902
+ text: `Metadata filter value for key "${key}" must be a scalar type (string, number, boolean, or null), got ${Array.isArray(value) ? "array" : "object"}`,
903
+ details: { key, valueType: Array.isArray(value) ? "array" : "object" }
904
+ },
905
+ new Error("Invalid metadata filter value type")
906
+ );
907
+ }
908
+ if (value === null) {
909
+ const condition = `json_extract(metadata, '$.${key}') IS NULL`;
910
+ countQuery = countQuery.whereAnd(condition);
911
+ selectQuery = selectQuery.whereAnd(condition);
912
+ } else {
913
+ const condition = `json_extract(metadata, '$.${key}') = ?`;
914
+ const filterValue = value;
915
+ countQuery = countQuery.whereAnd(condition, filterValue);
916
+ selectQuery = selectQuery.whereAnd(condition, filterValue);
917
+ }
918
+ }
919
+ }
874
920
  const countResult = await this.#db.executeQuery(countQuery.build());
875
921
  const total = Number(countResult?.[0]?.count ?? 0);
922
+ if (total === 0) {
923
+ return {
924
+ threads: [],
925
+ total: 0,
926
+ page,
927
+ perPage: perPageForResponse,
928
+ hasMore: false
929
+ };
930
+ }
876
931
  const limitValue = perPageInput === false ? total : perPage;
877
- const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("resourceId = ?", resourceId).orderBy(field, direction).limit(limitValue).offset(offset);
932
+ selectQuery = selectQuery.orderBy(field, direction).limit(limitValue).offset(offset);
878
933
  const results = await this.#db.executeQuery(selectQuery.build());
879
934
  const threads = results.map(mapRowToStorageThreadType);
880
935
  return {
@@ -885,13 +940,19 @@ var MemoryStorageD1 = class extends storage.MemoryStorage {
885
940
  hasMore: perPageInput === false ? false : offset + perPage < total
886
941
  };
887
942
  } catch (error$1) {
943
+ if (error$1 instanceof error.MastraError && error$1.category === error.ErrorCategory.USER) {
944
+ throw error$1;
945
+ }
888
946
  const mastraError = new error.MastraError(
889
947
  {
890
- id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
948
+ id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_THREADS", "FAILED"),
891
949
  domain: error.ErrorDomain.STORAGE,
892
950
  category: error.ErrorCategory.THIRD_PARTY,
893
- text: `Error getting threads by resourceId ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
894
- details: { resourceId }
951
+ text: `Error listing threads: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
952
+ details: {
953
+ ...filter?.resourceId && { resourceId: filter.resourceId },
954
+ hasMetadataFilter: !!filter?.metadata
955
+ }
895
956
  },
896
957
  error$1
897
958
  );
@@ -2030,7 +2091,7 @@ var WorkflowsStorageD1 = class extends storage.WorkflowsStorage {
2030
2091
  };
2031
2092
 
2032
2093
  // src/storage/index.ts
2033
- var D1Store = class extends storage.MastraStorage {
2094
+ var D1Store = class extends storage.MastraCompositeStore {
2034
2095
  client;
2035
2096
  binding;
2036
2097
  tablePrefix;