@mastra/cloudflare 1.0.0-beta.9 → 1.1.0-alpha.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/README.md CHANGED
@@ -11,7 +11,7 @@ npm install @mastra/cloudflare
11
11
  ## Prerequisites
12
12
 
13
13
  - Cloudflare account with KV namespaces set up
14
- - Node.js 16 or higher
14
+ - Node.js 22.13.0 or later
15
15
  - (Optional) Cloudflare Worker for Workers API mode
16
16
 
17
17
  ## Usage
@@ -0,0 +1,31 @@
1
+ # @mastra/cloudflare Documentation
2
+
3
+ > Embedded documentation for coding agents
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Read the skill overview
9
+ cat docs/SKILL.md
10
+
11
+ # Get the source map
12
+ cat docs/SOURCE_MAP.json
13
+
14
+ # Read topic documentation
15
+ cat docs/<topic>/01-overview.md
16
+ ```
17
+
18
+ ## Structure
19
+
20
+ ```
21
+ docs/
22
+ ├── SKILL.md # Entry point
23
+ ├── README.md # This file
24
+ ├── SOURCE_MAP.json # Export index
25
+ ├── storage/ (1 files)
26
+ ```
27
+
28
+ ## Version
29
+
30
+ Package: @mastra/cloudflare
31
+ Version: 1.1.0-alpha.0
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: mastra-cloudflare-docs
3
+ description: Documentation for @mastra/cloudflare. Includes links to type definitions and readable implementation code in dist/.
4
+ ---
5
+
6
+ # @mastra/cloudflare Documentation
7
+
8
+ > **Version**: 1.1.0-alpha.0
9
+ > **Package**: @mastra/cloudflare
10
+
11
+ ## Quick Navigation
12
+
13
+ Use SOURCE_MAP.json to find any export:
14
+
15
+ ```bash
16
+ cat docs/SOURCE_MAP.json
17
+ ```
18
+
19
+ Each export maps to:
20
+ - **types**: `.d.ts` file with JSDoc and API signatures
21
+ - **implementation**: `.js` chunk file with readable source
22
+ - **docs**: Conceptual documentation in `docs/`
23
+
24
+ ## Top Exports
25
+
26
+
27
+
28
+ See SOURCE_MAP.json for the complete list.
29
+
30
+ ## Available Topics
31
+
32
+ - [Storage](storage/) - 1 file(s)
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": "1.1.0-alpha.0",
3
+ "package": "@mastra/cloudflare",
4
+ "exports": {},
5
+ "modules": {}
6
+ }
@@ -0,0 +1,67 @@
1
+ # Storage API Reference
2
+
3
+ > API reference for storage - 1 entries
4
+
5
+
6
+ ---
7
+
8
+ ## Reference: Cloudflare Storage
9
+
10
+ > Documentation for the Cloudflare KV storage implementation in Mastra.
11
+
12
+ The Cloudflare KV storage implementation provides a globally distributed, serverless key-value store solution using Cloudflare Workers KV.
13
+
14
+ > **Observability Not Supported**
15
+ Cloudflare KV storage **does not support the observability domain**. Traces from the `DefaultExporter` cannot be persisted to KV, and Mastra Studio's observability features won't work with Cloudflare KV as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite#specialized-storage-for-observability) to route observability data to a supported provider like ClickHouse or PostgreSQL.
16
+
17
+ ## Installation
18
+
19
+ ```bash npm2yarn
20
+ npm install @mastra/cloudflare@latest
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ```typescript
26
+ import { CloudflareStore } from "@mastra/cloudflare";
27
+
28
+ // --- Example 1: Using Workers Binding ---
29
+ const storageWorkers = new CloudflareStore({
30
+ id: "cloudflare-workers-storage",
31
+ bindings: {
32
+ threads: THREADS_KV, // KVNamespace binding for threads table
33
+ messages: MESSAGES_KV, // KVNamespace binding for messages table
34
+ // Add other tables as needed
35
+ },
36
+ keyPrefix: "dev_", // Optional: isolate keys per environment
37
+ });
38
+
39
+ // --- Example 2: Using REST API ---
40
+ const storageRest = new CloudflareStore({
41
+ id: "cloudflare-rest-storage",
42
+ accountId: process.env.CLOUDFLARE_ACCOUNT_ID!, // Cloudflare Account ID
43
+ apiToken: process.env.CLOUDFLARE_API_TOKEN!, // Cloudflare API Token
44
+ namespacePrefix: "dev_", // Optional: isolate namespaces per environment
45
+ });
46
+ ```
47
+
48
+ ## Parameters
49
+
50
+ #### Additional Notes
51
+
52
+ ### Schema Management
53
+
54
+ The storage implementation handles schema creation and updates automatically. It creates the following tables:
55
+
56
+ - `threads`: Stores conversation threads
57
+ - `messages`: Stores individual messages
58
+ - `metadata`: Stores additional metadata for threads and messages
59
+
60
+ ### Consistency & Propagation
61
+
62
+ Cloudflare KV is an eventually consistent store, meaning that data may not be immediately available across all regions after a write.
63
+
64
+ ### Key Structure & Namespacing
65
+
66
+ Keys in Cloudflare KV are structured as a combination of a configurable prefix and a table-specific format (e.g., `threads:threadId`).
67
+ For Workers deployments, `keyPrefix` is used to isolate data within a namespace; for REST API deployments, `namespacePrefix` is used to isolate entire namespaces between environments or applications.
package/dist/index.cjs CHANGED
@@ -620,21 +620,23 @@ var MemoryStorageCloudflare = class extends storage.MemoryStorage {
620
620
  return null;
621
621
  }
622
622
  }
623
- async listThreadsByResourceId(args) {
623
+ async listThreads(args) {
624
+ const { page = 0, perPage: perPageInput, orderBy, filter } = args;
625
+ try {
626
+ this.validatePaginationInput(page, perPageInput ?? 100);
627
+ } catch (error$1) {
628
+ throw new error.MastraError(
629
+ {
630
+ id: storage.createStorageErrorId("CLOUDFLARE", "LIST_THREADS", "INVALID_PAGE"),
631
+ domain: error.ErrorDomain.STORAGE,
632
+ category: error.ErrorCategory.USER,
633
+ details: { page, ...perPageInput !== void 0 && { perPage: perPageInput } }
634
+ },
635
+ error$1 instanceof Error ? error$1 : new Error("Invalid pagination parameters")
636
+ );
637
+ }
638
+ const perPage = storage.normalizePerPage(perPageInput, 100);
624
639
  try {
625
- const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
626
- const perPage = storage.normalizePerPage(perPageInput, 100);
627
- if (page < 0) {
628
- throw new error.MastraError(
629
- {
630
- id: storage.createStorageErrorId("CLOUDFLARE", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
631
- domain: error.ErrorDomain.STORAGE,
632
- category: error.ErrorCategory.USER,
633
- details: { page }
634
- },
635
- new Error("page must be >= 0")
636
- );
637
- }
638
640
  const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
639
641
  const { field, direction } = this.parseOrderBy(orderBy);
640
642
  const prefix = this.#db.namespacePrefix ? `${this.#db.namespacePrefix}:` : "";
@@ -643,7 +645,15 @@ var MemoryStorageCloudflare = class extends storage.MemoryStorage {
643
645
  for (const { name: key } of keyObjs) {
644
646
  const data = await this.#db.getKV(storage.TABLE_THREADS, key);
645
647
  if (!data) continue;
646
- if (data.resourceId !== resourceId) continue;
648
+ if (filter?.resourceId && data.resourceId !== filter.resourceId) {
649
+ continue;
650
+ }
651
+ if (filter?.metadata && Object.keys(filter.metadata).length > 0) {
652
+ const metadata = this.ensureMetadata(data.metadata);
653
+ if (!metadata) continue;
654
+ const matches = Object.entries(filter.metadata).every(([key2, value]) => metadata[key2] === value);
655
+ if (!matches) continue;
656
+ }
647
657
  threads.push(data);
648
658
  }
649
659
  threads.sort((a, b) => {
@@ -663,10 +673,10 @@ var MemoryStorageCloudflare = class extends storage.MemoryStorage {
663
673
  } catch (error$1) {
664
674
  throw new error.MastraError(
665
675
  {
666
- id: storage.createStorageErrorId("CLOUDFLARE", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
676
+ id: storage.createStorageErrorId("CLOUDFLARE", "LIST_THREADS", "FAILED"),
667
677
  domain: error.ErrorDomain.STORAGE,
668
678
  category: error.ErrorCategory.THIRD_PARTY,
669
- text: "Failed to get threads by resource ID with pagination"
679
+ text: "Failed to list threads with filters"
670
680
  },
671
681
  error$1
672
682
  );
@@ -1200,15 +1210,11 @@ var MemoryStorageCloudflare = class extends storage.MemoryStorage {
1200
1210
  if (resourceId) {
1201
1211
  filteredThreadMessages = filteredThreadMessages.filter((msg) => msg.resourceId === resourceId);
1202
1212
  }
1203
- const dateRange = filter?.dateRange;
1204
- if (dateRange) {
1205
- filteredThreadMessages = filteredThreadMessages.filter((msg) => {
1206
- const messageDate = new Date(msg.createdAt);
1207
- if (dateRange.start && messageDate < new Date(dateRange.start)) return false;
1208
- if (dateRange.end && messageDate > new Date(dateRange.end)) return false;
1209
- return true;
1210
- });
1211
- }
1213
+ filteredThreadMessages = storage.filterByDateRange(
1214
+ filteredThreadMessages,
1215
+ (msg) => new Date(msg.createdAt),
1216
+ filter?.dateRange
1217
+ );
1212
1218
  const total = filteredThreadMessages.length;
1213
1219
  if (perPage === 0 && (!include || include.length === 0)) {
1214
1220
  return {
@@ -1989,7 +1995,7 @@ var WorkflowsStorageCloudflare = class extends storage.WorkflowsStorage {
1989
1995
  try {
1990
1996
  parsedSnapshot = JSON.parse(row.snapshot);
1991
1997
  } catch (e) {
1992
- console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
1998
+ this.logger.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
1993
1999
  }
1994
2000
  }
1995
2001
  return {
@@ -2163,7 +2169,7 @@ function isWorkersConfig(config) {
2163
2169
  }
2164
2170
 
2165
2171
  // src/storage/index.ts
2166
- var CloudflareStore = class extends storage.MastraStorage {
2172
+ var CloudflareStore = class extends storage.MastraCompositeStore {
2167
2173
  stores;
2168
2174
  client;
2169
2175
  accountId;