@mastra/spanner 0.0.0-a-b-demo-20260526202724

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/LICENSE.md +30 -0
  3. package/README.md +108 -0
  4. package/dist/docs/SKILL.md +22 -0
  5. package/dist/docs/assets/SOURCE_MAP.json +6 -0
  6. package/dist/docs/references/reference-storage-spanner.md +213 -0
  7. package/dist/index.cjs +9781 -0
  8. package/dist/index.cjs.map +1 -0
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +9765 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/storage/db/index.d.ts +344 -0
  14. package/dist/storage/db/index.d.ts.map +1 -0
  15. package/dist/storage/db/utils.d.ts +27 -0
  16. package/dist/storage/db/utils.d.ts.map +1 -0
  17. package/dist/storage/domains/agents/index.d.ts +44 -0
  18. package/dist/storage/domains/agents/index.d.ts.map +1 -0
  19. package/dist/storage/domains/background-tasks/index.d.ts +27 -0
  20. package/dist/storage/domains/background-tasks/index.d.ts.map +1 -0
  21. package/dist/storage/domains/blobs/index.d.ts +36 -0
  22. package/dist/storage/domains/blobs/index.d.ts.map +1 -0
  23. package/dist/storage/domains/mcp-clients/index.d.ts +64 -0
  24. package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -0
  25. package/dist/storage/domains/mcp-servers/index.d.ts +64 -0
  26. package/dist/storage/domains/mcp-servers/index.d.ts.map +1 -0
  27. package/dist/storage/domains/memory/index.d.ts +101 -0
  28. package/dist/storage/domains/memory/index.d.ts.map +1 -0
  29. package/dist/storage/domains/observability/index.d.ts +67 -0
  30. package/dist/storage/domains/observability/index.d.ts.map +1 -0
  31. package/dist/storage/domains/observability/metrics.d.ts +119 -0
  32. package/dist/storage/domains/observability/metrics.d.ts.map +1 -0
  33. package/dist/storage/domains/prompt-blocks/index.d.ts +65 -0
  34. package/dist/storage/domains/prompt-blocks/index.d.ts.map +1 -0
  35. package/dist/storage/domains/schedules/index.d.ts +55 -0
  36. package/dist/storage/domains/schedules/index.d.ts.map +1 -0
  37. package/dist/storage/domains/scorer-definitions/index.d.ts +64 -0
  38. package/dist/storage/domains/scorer-definitions/index.d.ts.map +1 -0
  39. package/dist/storage/domains/scores/index.d.ts +46 -0
  40. package/dist/storage/domains/scores/index.d.ts.map +1 -0
  41. package/dist/storage/domains/skills/index.d.ts +64 -0
  42. package/dist/storage/domains/skills/index.d.ts.map +1 -0
  43. package/dist/storage/domains/utils.d.ts +17 -0
  44. package/dist/storage/domains/utils.d.ts.map +1 -0
  45. package/dist/storage/domains/workflows/index.d.ts +97 -0
  46. package/dist/storage/domains/workflows/index.d.ts.map +1 -0
  47. package/dist/storage/index.d.ts +178 -0
  48. package/dist/storage/index.d.ts.map +1 -0
  49. package/package.json +68 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,51 @@
1
+ # @mastra/spanner
2
+
3
+ ## 0.0.0-a-b-demo-20260526202724
4
+
5
+ ### Major Changes
6
+
7
+ - Added a Google Cloud Spanner storage adapter (`@mastra/spanner`) targeting the GoogleSQL dialect. The adapter implements the `memory`, `workflows`, `scores`, `backgroundTasks`, `agents`, `mcpClients`, `mcpServers`, `skills`, `blobs`, `promptBlocks`, `scorerDefinitions`, `schedules`, and `observability` storage domains and works with both managed Cloud Spanner instances and the local Spanner emulator. The `schedules` domain plugs into Mastra's built-in `WorkflowScheduler` for cron-driven workflow triggers, and the `observability` domain persists AI tracing spans in `mastra_ai_spans` to power the Studio traces UI (JSON containment filters compile to per-key `JSON_VALUE` equality and `EXISTS` over `JSON_QUERY_ARRAY` since Spanner has no `@>` operator). ([#15955](https://github.com/mastra-ai/mastra/pull/15955))
8
+
9
+ ```typescript
10
+ import { SpannerStore } from '@mastra/spanner';
11
+
12
+ const storage = new SpannerStore({
13
+ id: 'spanner-storage',
14
+ projectId: process.env.SPANNER_PROJECT_ID!,
15
+ instanceId: process.env.SPANNER_INSTANCE_ID!,
16
+ databaseId: process.env.SPANNER_DATABASE_ID!,
17
+ });
18
+ ```
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies [[`cfa2e3a`](https://github.com/mastra-ai/mastra/commit/cfa2e3a5292322f48bb28b4d257d631da7f9d3cc), [`0cbece9`](https://github.com/mastra-ai/mastra/commit/0cbece9d832cb134a74cdbf3682d390a058215a4), [`2f5f58a`](https://github.com/mastra-ai/mastra/commit/2f5f58a9a8bb13bcdc6789db221eef7c9bf1ff02), [`7dfe1bc`](https://github.com/mastra-ai/mastra/commit/7dfe1bcfe71d261a6fd6bbf29b1dec49d78fb98f), [`ac442a4`](https://github.com/mastra-ai/mastra/commit/ac442a42fda0354ac2bcea772bf6691cb3e9dbb3), [`b7286f4`](https://github.com/mastra-ai/mastra/commit/b7286f4308267f5fd70e6bfee10dba9472640906), [`6096445`](https://github.com/mastra-ai/mastra/commit/60964459733f0ab384584d95e19c36607ffdf7b0), [`a481027`](https://github.com/mastra-ai/mastra/commit/a481027b549ba1018414990c8f045eaee7b9f413), [`1e5c067`](https://github.com/mastra-ai/mastra/commit/1e5c067d2e20a781af670578180d1ee249806d41), [`168fa09`](https://github.com/mastra-ai/mastra/commit/168fa09d6b39114cb8c13bd06f1dccb9bc81c6cd), [`df1947a`](https://github.com/mastra-ai/mastra/commit/df1947affa40f742067542251fac7ca759492ef4), [`ee59b74`](https://github.com/mastra-ai/mastra/commit/ee59b743ce73ad11784b4d9c6fbba8568edee1c8), [`a97b1a0`](https://github.com/mastra-ai/mastra/commit/a97b1a0abaed83946c3519d1e0f680d0815b8a67), [`008baaf`](https://github.com/mastra-ai/mastra/commit/008baafd8d851f831407045aebead5a2e3342eff), [`801baa0`](https://github.com/mastra-ai/mastra/commit/801baa07cccdbaec1d00942a92bdc831111744a2), [`8116436`](https://github.com/mastra-ai/mastra/commit/81164363eb225d774e41ff27da6a5ea611406688), [`c27c4b9`](https://github.com/mastra-ai/mastra/commit/c27c4b9f137df5414fca4e45896aceccff6b0ed5), [`08b3b59`](https://github.com/mastra-ai/mastra/commit/08b3b590dd960dee6c9a6e39272f8927d803db6e), [`9365eb3`](https://github.com/mastra-ai/mastra/commit/9365eb3773e9d44134ed097fa477b6430baf4245), [`b3c3b18`](https://github.com/mastra-ai/mastra/commit/b3c3b189121489a3a51a8fd8204b569be9a89fe5), [`b9d33b4`](https://github.com/mastra-ai/mastra/commit/b9d33b45c2f62bad0d3e1384ac2b11622c9fef58), [`70cb714`](https://github.com/mastra-ai/mastra/commit/70cb7149c8f16f478e15b58498254a53181750a4), [`91cf0e0`](https://github.com/mastra-ai/mastra/commit/91cf0e027e511b871481a8576b56b7af83b15afd), [`7f9da22`](https://github.com/mastra-ai/mastra/commit/7f9da22efd5aa595e138a31de55a5f0f2f28b33d), [`b9d33b4`](https://github.com/mastra-ai/mastra/commit/b9d33b45c2f62bad0d3e1384ac2b11622c9fef58)]:
23
+ - @mastra/core@0.0.0-a-b-demo-20260526202724
24
+
25
+ ## 2.0.0-alpha.0
26
+
27
+ ### Major Changes
28
+
29
+ - Added a Google Cloud Spanner storage adapter (`@mastra/spanner`) targeting the GoogleSQL dialect. The adapter implements the `memory`, `workflows`, `scores`, `backgroundTasks`, `agents`, `mcpClients`, `mcpServers`, `skills`, `blobs`, `promptBlocks`, `scorerDefinitions`, `schedules`, and `observability` storage domains and works with both managed Cloud Spanner instances and the local Spanner emulator. The `schedules` domain plugs into Mastra's built-in `WorkflowScheduler` for cron-driven workflow triggers, and the `observability` domain persists AI tracing spans in `mastra_ai_spans` to power the Studio traces UI (JSON containment filters compile to per-key `JSON_VALUE` equality and `EXISTS` over `JSON_QUERY_ARRAY` since Spanner has no `@>` operator). ([#15955](https://github.com/mastra-ai/mastra/pull/15955))
30
+
31
+ ```typescript
32
+ import { SpannerStore } from '@mastra/spanner';
33
+
34
+ const storage = new SpannerStore({
35
+ id: 'spanner-storage',
36
+ projectId: process.env.SPANNER_PROJECT_ID!,
37
+ instanceId: process.env.SPANNER_INSTANCE_ID!,
38
+ databaseId: process.env.SPANNER_DATABASE_ID!,
39
+ });
40
+ ```
41
+
42
+ ### Patch Changes
43
+
44
+ - Updated dependencies [[`0cbece9`](https://github.com/mastra-ai/mastra/commit/0cbece9d832cb134a74cdbf3682d390a058215a4), [`7dfe1bc`](https://github.com/mastra-ai/mastra/commit/7dfe1bcfe71d261a6fd6bbf29b1dec49d78fb98f), [`70cb714`](https://github.com/mastra-ai/mastra/commit/70cb7149c8f16f478e15b58498254a53181750a4), [`7f9da22`](https://github.com/mastra-ai/mastra/commit/7f9da22efd5aa595e138a31de55a5f0f2f28b33d)]:
45
+ - @mastra/core@1.37.0-alpha.6
46
+
47
+ ## 1.0.0
48
+
49
+ ### Major Changes
50
+
51
+ - Initial stable release of the Google Cloud Spanner storage adapter for Mastra. Supports the GoogleSQL dialect with full storage-domain parity: `memory`, `workflows`, `scores`, `backgroundTasks`, `agents`, `mcpClients`, `mcpServers`, `skills`, `blobs`, `promptBlocks`, `scorerDefinitions`, `schedules` (cron-driven workflow triggers consumed by `WorkflowScheduler`), and `observability` (AI tracing spans persisted in `mastra_ai_spans` with the full trace read/write surface). Works against managed Spanner instances and the local Spanner emulator.
package/LICENSE.md ADDED
@@ -0,0 +1,30 @@
1
+ Portions of this software are licensed as follows:
2
+
3
+ - All content that resides under any directory named "ee/" within this
4
+ repository, including but not limited to:
5
+ - `packages/core/src/auth/ee/`
6
+ - `packages/server/src/server/auth/ee/`
7
+ is licensed under the license defined in `ee/LICENSE`.
8
+
9
+ - All third-party components incorporated into the Mastra Software are
10
+ licensed under the original license provided by the owner of the
11
+ applicable component.
12
+
13
+ - Content outside of the above-mentioned directories or restrictions is
14
+ available under the "Apache License 2.0" as defined below.
15
+
16
+ # Apache License 2.0
17
+
18
+ Copyright (c) 2025 Kepler Software, Inc.
19
+
20
+ Licensed under the Apache License, Version 2.0 (the "License");
21
+ you may not use this file except in compliance with the License.
22
+ You may obtain a copy of the License at
23
+
24
+ http://www.apache.org/licenses/LICENSE-2.0
25
+
26
+ Unless required by applicable law or agreed to in writing, software
27
+ distributed under the License is distributed on an "AS IS" BASIS,
28
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29
+ See the License for the specific language governing permissions and
30
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # @mastra/spanner
2
+
3
+ Google Cloud Spanner storage adapter for Mastra. Implements the GoogleSQL dialect.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @mastra/spanner
9
+ ```
10
+
11
+ ## Prerequisites
12
+
13
+ - A Cloud Spanner instance and database created with the GoogleSQL dialect.
14
+ - Application credentials available to the Node.js client (Application Default Credentials, service account JSON, or `GOOGLE_APPLICATION_CREDENTIALS`).
15
+ - For local development, the [Spanner emulator](https://cloud.google.com/spanner/docs/emulator) running on `localhost:9010`.
16
+
17
+ ## Usage
18
+
19
+ ### Connecting to a managed Cloud Spanner database
20
+
21
+ ```typescript
22
+ import { SpannerStore } from '@mastra/spanner';
23
+
24
+ const store = new SpannerStore({
25
+ id: 'spanner-storage',
26
+ projectId: 'my-gcp-project',
27
+ instanceId: 'my-instance',
28
+ databaseId: 'mastra',
29
+ });
30
+ ```
31
+
32
+ ### Connecting to the Spanner emulator
33
+
34
+ ```typescript
35
+ process.env.SPANNER_EMULATOR_HOST = 'localhost:9010';
36
+
37
+ const store = new SpannerStore({
38
+ id: 'spanner-storage',
39
+ projectId: 'test-project',
40
+ instanceId: 'test-instance',
41
+ databaseId: 'test-db',
42
+ // Skip auth checks when talking to the emulator
43
+ spannerOptions: { servicePath: 'localhost', port: 9010, sslCreds: undefined },
44
+ });
45
+ ```
46
+
47
+ The store automatically detects the `SPANNER_EMULATOR_HOST` env var and uses
48
+ unauthenticated channels when set. You can also create the instance/database
49
+ through the emulator using the standard `gcloud` CLI.
50
+
51
+ ### Pre-configured client or database
52
+
53
+ If you already manage a Spanner client elsewhere, pass the database directly:
54
+
55
+ ```typescript
56
+ import { Spanner } from '@google-cloud/spanner';
57
+ import { SpannerStore } from '@mastra/spanner';
58
+
59
+ const spanner = new Spanner({ projectId: 'my-project' });
60
+ const database = spanner.instance('my-instance').database('mastra');
61
+
62
+ const store = new SpannerStore({
63
+ id: 'spanner-storage',
64
+ database,
65
+ });
66
+ ```
67
+
68
+ ## Notes on the GoogleSQL dialect
69
+
70
+ - Tables are created with the GoogleSQL dialect using `STRING(MAX)` for text/JSON
71
+ payloads, `INT64`, `FLOAT64`, `BOOL` and `TIMESTAMP`.
72
+ - DDL is applied through `database.updateSchema(...)` (long-running operation).
73
+ - Upserts use `INSERT OR UPDATE`. Deletes use `DELETE WHERE TRUE` (Spanner has no
74
+ `TRUNCATE`).
75
+ - Identifiers are quoted with backticks.
76
+ - The adapter does not use named schemas. Use a dedicated database for isolation.
77
+
78
+ ## Storage domains
79
+
80
+ The adapter implements the following storage domains:
81
+
82
+ - `memory`: threads, messages, resources
83
+ - `workflows`: workflow snapshots and run state
84
+ - `scores`: evaluation scores
85
+ - `backgroundTasks`: background tool execution state
86
+ - `agents`: thin agent records and versioned config snapshots
87
+ - `mcpClients`: MCP client configurations with version history
88
+ - `mcpServers`: MCP server configurations with version history
89
+ - `skills`: skill records and versioned skill snapshots
90
+ - `blobs`: content-addressable blob store (used by the skills domain)
91
+ - `promptBlocks`: prompt block records and versioned template/rules snapshots
92
+ - `scorerDefinitions`: scorer definition records and versioned scoring-config snapshots
93
+ - `schedules`: cron-driven workflow schedules and trigger history (consumed by `WorkflowScheduler`)
94
+ - `observability`: AI tracing spans (per-trace and per-span records) used by the Studio traces UI
95
+
96
+ ## Testing locally with the emulator
97
+
98
+ Start the emulator:
99
+
100
+ ```bash
101
+ docker compose up -d
102
+ ```
103
+
104
+ Then run the tests:
105
+
106
+ ```bash
107
+ ENABLE_TESTS=true pnpm test
108
+ ```
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: mastra-spanner
3
+ description: Documentation for @mastra/spanner. Use when working with @mastra/spanner APIs, configuration, or implementation.
4
+ metadata:
5
+ package: "@mastra/spanner"
6
+ version: "0.0.0-a-b-demo-20260526202724"
7
+ ---
8
+
9
+ ## When to use
10
+
11
+ Use this skill whenever you are working with @mastra/spanner to obtain the domain-specific knowledge.
12
+
13
+ ## How to use
14
+
15
+ Read the individual reference documents for detailed explanations and code examples.
16
+
17
+ ### Reference
18
+
19
+ - [Reference: Google Cloud Spanner storage](references/reference-storage-spanner.md) - Documentation for the Google Cloud Spanner storage implementation in Mastra.
20
+
21
+
22
+ Read [assets/SOURCE_MAP.json](assets/SOURCE_MAP.json) for source code references.
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": "0.0.0-a-b-demo-20260526202724",
3
+ "package": "@mastra/spanner",
4
+ "exports": {},
5
+ "modules": {}
6
+ }
@@ -0,0 +1,213 @@
1
+ # Google Cloud Spanner storage
2
+
3
+ The Google Cloud Spanner storage implementation provides a horizontally scalable, strongly consistent storage backend for Mastra. It targets the GoogleSQL dialect of Cloud Spanner.
4
+
5
+ ## Installation
6
+
7
+ **npm**:
8
+
9
+ ```bash
10
+ npm install @mastra/spanner@latest
11
+ ```
12
+
13
+ **pnpm**:
14
+
15
+ ```bash
16
+ pnpm add @mastra/spanner@latest
17
+ ```
18
+
19
+ **Yarn**:
20
+
21
+ ```bash
22
+ yarn add @mastra/spanner@latest
23
+ ```
24
+
25
+ **Bun**:
26
+
27
+ ```bash
28
+ bun add @mastra/spanner@latest
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ```typescript
34
+ import { SpannerStore } from '@mastra/spanner'
35
+
36
+ const storage = new SpannerStore({
37
+ id: 'spanner-storage',
38
+ projectId: process.env.SPANNER_PROJECT_ID!,
39
+ instanceId: process.env.SPANNER_INSTANCE_ID!,
40
+ databaseId: process.env.SPANNER_DATABASE_ID!,
41
+ })
42
+ ```
43
+
44
+ The instance and database must already exist. The adapter creates the required tables on first use, so the credentials provided to the Spanner client need permission to run schema changes (or run `storage.init()` once during a deploy step with elevated credentials).
45
+
46
+ ## Parameters
47
+
48
+ **id** (`string`): Unique identifier for this storage instance.
49
+
50
+ **projectId** (`string`): Google Cloud project ID. Required unless \`database\` is provided.
51
+
52
+ **instanceId** (`string`): Cloud Spanner instance ID. Required unless \`database\` is provided.
53
+
54
+ **databaseId** (`string`): Cloud Spanner database ID. Required unless \`database\` is provided.
55
+
56
+ **database** (`@google-cloud/spanner Database`): Pre-configured Spanner Database handle. Use this when you manage the Spanner client elsewhere (for example, to share auth or connection options across services).
57
+
58
+ **spannerOptions** (`object`): Options forwarded to the \`@google-cloud/spanner\` client constructor. Use this to set credentials, custom endpoints, or to point at the local emulator.
59
+
60
+ **disableInit** (`boolean`): When true, skip automatic table creation on first use. You must call \`storage.init()\` explicitly during a separate deploy step. (Default: `false`)
61
+
62
+ **skipDefaultIndexes** (`boolean`): When true, skip creation of default indexes during initialization. (Default: `false`)
63
+
64
+ **indexes** (`CreateIndexOptions[]`): Custom secondary indexes to create. Each index must specify the table it belongs to. Indexes are routed to the appropriate domain based on the table name.
65
+
66
+ **initMode** (`'sync' | 'validate'`): Controls schema-initialization behavior. \`'sync'\` creates missing tables, columns, and indexes during \`init()\` (the historical behavior). \`'validate'\` issues no DDL and instead verifies that every expected table, column, and default/custom index already exists, throwing a typed user error if anything is missing — useful when an external process (Terraform, Liquibase, a release pipeline, etc.) owns the schema and Mastra should only verify it. (Default: `'sync'`)
67
+
68
+ ## Constructor examples
69
+
70
+ You can instantiate `SpannerStore` in several ways:
71
+
72
+ ```typescript
73
+ import { Spanner } from '@google-cloud/spanner'
74
+ import { SpannerStore } from '@mastra/spanner'
75
+
76
+ // Using projectId / instanceId / databaseId
77
+ const store1 = new SpannerStore({
78
+ id: 'spanner-storage-1',
79
+ projectId: 'my-gcp-project',
80
+ instanceId: 'my-instance',
81
+ databaseId: 'mastra',
82
+ })
83
+
84
+ // Reusing an existing Spanner Database handle
85
+ const spanner = new Spanner({ projectId: 'my-gcp-project' })
86
+ const database = spanner.instance('my-instance').database('mastra')
87
+
88
+ const store2 = new SpannerStore({
89
+ id: 'spanner-storage-2',
90
+ database,
91
+ })
92
+
93
+ // Using the local Spanner emulator (set the SPANNER_EMULATOR_HOST env var)
94
+ process.env.SPANNER_EMULATOR_HOST = 'localhost:9010'
95
+ const store3 = new SpannerStore({
96
+ id: 'spanner-storage-emulator',
97
+ projectId: 'test-project',
98
+ instanceId: 'test-instance',
99
+ databaseId: 'test-db',
100
+ spannerOptions: { servicePath: 'localhost', port: 9010, sslCreds: undefined },
101
+ })
102
+ ```
103
+
104
+ ## Additional notes
105
+
106
+ ### Schema management
107
+
108
+ The storage adapter creates the following tables, all using the GoogleSQL dialect:
109
+
110
+ - `mastra_workflow_snapshot`: workflow state and execution data
111
+ - `mastra_threads`: conversation threads
112
+ - `mastra_messages`: individual messages
113
+ - `mastra_resources`: resource working memory
114
+ - `mastra_scorers`: evaluation scores
115
+ - `mastra_background_tasks`: background tool execution state
116
+ - `mastra_agents`: thin agent records (id, status, active version)
117
+ - `mastra_agent_versions`: versioned agent configuration snapshots
118
+ - `mastra_mcp_clients` / `mastra_mcp_client_versions`: MCP client configurations and their version history
119
+ - `mastra_mcp_servers` / `mastra_mcp_server_versions`: MCP server configurations and their version history
120
+ - `mastra_skills` / `mastra_skill_versions`: skill records and versioned skill snapshots (instructions, references, scripts, assets, content tree)
121
+ - `mastra_skill_blobs`: content-addressable blob store keyed by SHA-256 hash, used for skill version contents
122
+ - `mastra_prompt_blocks` / `mastra_prompt_block_versions`: prompt block records and versioned content snapshots (template content, rules, request-context schema)
123
+ - `mastra_scorer_definitions` / `mastra_scorer_definition_versions`: scorer definition records and versioned config snapshots (judge instructions, model, score range, preset config, default sampling)
124
+ - `mastra_schedules` / `mastra_schedule_triggers`: cron-driven workflow schedules and trigger history, consumed by Mastra's built-in `WorkflowScheduler`
125
+ - `mastra_ai_spans`: AI tracing spans for observability (per-trace and per-span records, used to power the Studio traces UI)
126
+
127
+ Tables are created with `STRING(MAX)` for text and JSON payloads, `INT64`, `FLOAT64`, `BOOL`, and `TIMESTAMP`.
128
+
129
+ Two tables also carry Spanner-specific `STORED` generated columns that the adapter populates from JSON payloads so common filters can use a regular secondary index instead of a `JSON_VALUE` scan:
130
+
131
+ - `mastra_workflow_snapshot.snapshotStatus` — extracts `$.status` from `snapshot`; backs `listWorkflowRuns({ status })`.
132
+ - `mastra_schedules.target_workflow_id` — extracts `$.workflowId` from `target`; backs `listSchedules({ workflowId })`.
133
+
134
+ Both are added via `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` during `init()` and skipped under `initMode: 'validate'` (where the schema is owned externally). When the column is absent, the adapter falls back to a `JSON_VALUE` filter at runtime.
135
+
136
+ The adapter does not create or use named schemas; use a dedicated database for isolation.
137
+
138
+ ### Initialization
139
+
140
+ When you pass storage to the `Mastra` class, `init()` is called automatically before any storage operation:
141
+
142
+ ```typescript
143
+ import { Mastra } from '@mastra/core'
144
+ import { SpannerStore } from '@mastra/spanner'
145
+
146
+ const storage = new SpannerStore({
147
+ id: 'spanner-storage',
148
+ projectId: process.env.SPANNER_PROJECT_ID!,
149
+ instanceId: process.env.SPANNER_INSTANCE_ID!,
150
+ databaseId: process.env.SPANNER_DATABASE_ID!,
151
+ })
152
+
153
+ const mastra = new Mastra({
154
+ storage, // init() is called automatically
155
+ })
156
+ ```
157
+
158
+ If you use storage directly, call `init()` once before the first operation. Spanner does not allow concurrent schema changes, so `SpannerStore.init()` runs each domain's setup sequentially.
159
+
160
+ ```typescript
161
+ const storage = new SpannerStore({
162
+ id: 'spanner-storage',
163
+ projectId: process.env.SPANNER_PROJECT_ID!,
164
+ instanceId: process.env.SPANNER_INSTANCE_ID!,
165
+ databaseId: process.env.SPANNER_DATABASE_ID!,
166
+ })
167
+
168
+ await storage.init()
169
+ const memory = await storage.getStore('memory')
170
+ const thread = await memory?.getThreadById({ threadId: '...' })
171
+ ```
172
+
173
+ > **Warning:** If `init()` is not called and `disableInit` is true, the required tables will not exist and storage operations will fail.
174
+
175
+ ### GoogleSQL specifics
176
+
177
+ A few behaviors differ from other relational adapters:
178
+
179
+ - Upserts use `INSERT OR UPDATE`. Spanner does not provide a `RETURNING` clause for upserts, so callers needing the post-write state must read it back.
180
+ - There is no `TRUNCATE`; `dangerouslyClearAll()` issues `DELETE WHERE TRUE`.
181
+ - Identifiers are quoted with backticks.
182
+ - DDL is applied through `database.updateSchema(...)`, which is asynchronous (long-running operation).
183
+ - `NULLS FIRST/LAST` is not supported. Ordering with NULL handling is emulated through an `IS NULL` ordering key.
184
+ - JSON containment is not supported natively. `listTraces` `metadata` and `scope` filters compile to per-key `JSON_VALUE(...) = @v` equality checks, and `tags` filters compile to `EXISTS` over `JSON_QUERY_ARRAY(...)`. This differs from Postgres' `@>` containment operator (which can match nested structure in a single index scan) — most one-shot lookups still work but deeply nested structural matches are not expressible.
185
+
186
+ ### Direct database access
187
+
188
+ `SpannerStore` exposes the underlying Spanner client objects:
189
+
190
+ ```typescript
191
+ store.database // @google-cloud/spanner Database
192
+ store.instance // @google-cloud/spanner Instance (when created internally)
193
+ store.spanner // @google-cloud/spanner Spanner client (when created internally)
194
+ ```
195
+
196
+ These are intended for advanced scenarios such as bespoke transactions or schema introspection. When you reuse the database directly, you bypass the adapter's validation and JSON conversion logic.
197
+
198
+ ### Local development with the emulator
199
+
200
+ Run the Cloud Spanner emulator locally with Docker:
201
+
202
+ ```bash
203
+ docker run -p 9010:9010 -p 9020:9020 gcr.io/cloud-spanner-emulator/emulator
204
+ ```
205
+
206
+ Set `SPANNER_EMULATOR_HOST=localhost:9010` and create the instance and database before running your app:
207
+
208
+ ```bash
209
+ gcloud spanner instances create test-instance --config=emulator-config --nodes=1
210
+ gcloud spanner databases create test-db --instance=test-instance
211
+ ```
212
+
213
+ Then connect with the same env var set in your Node.js process; the `@google-cloud/spanner` client detects the emulator automatically.