@mastra/spanner 0.0.0 → 1.0.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +3 -9
  2. package/dist/docs/SKILL.md +22 -0
  3. package/dist/docs/assets/SOURCE_MAP.json +6 -0
  4. package/dist/docs/references/reference-storage-spanner.md +213 -0
  5. package/dist/index.cjs +9781 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +9765 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/storage/db/index.d.ts +344 -0
  12. package/dist/storage/db/index.d.ts.map +1 -0
  13. package/dist/storage/db/utils.d.ts +27 -0
  14. package/dist/storage/db/utils.d.ts.map +1 -0
  15. package/dist/storage/domains/agents/index.d.ts +44 -0
  16. package/dist/storage/domains/agents/index.d.ts.map +1 -0
  17. package/dist/storage/domains/background-tasks/index.d.ts +27 -0
  18. package/dist/storage/domains/background-tasks/index.d.ts.map +1 -0
  19. package/dist/storage/domains/blobs/index.d.ts +36 -0
  20. package/dist/storage/domains/blobs/index.d.ts.map +1 -0
  21. package/dist/storage/domains/mcp-clients/index.d.ts +64 -0
  22. package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -0
  23. package/dist/storage/domains/mcp-servers/index.d.ts +64 -0
  24. package/dist/storage/domains/mcp-servers/index.d.ts.map +1 -0
  25. package/dist/storage/domains/memory/index.d.ts +101 -0
  26. package/dist/storage/domains/memory/index.d.ts.map +1 -0
  27. package/dist/storage/domains/observability/index.d.ts +67 -0
  28. package/dist/storage/domains/observability/index.d.ts.map +1 -0
  29. package/dist/storage/domains/observability/metrics.d.ts +119 -0
  30. package/dist/storage/domains/observability/metrics.d.ts.map +1 -0
  31. package/dist/storage/domains/prompt-blocks/index.d.ts +65 -0
  32. package/dist/storage/domains/prompt-blocks/index.d.ts.map +1 -0
  33. package/dist/storage/domains/schedules/index.d.ts +55 -0
  34. package/dist/storage/domains/schedules/index.d.ts.map +1 -0
  35. package/dist/storage/domains/scorer-definitions/index.d.ts +64 -0
  36. package/dist/storage/domains/scorer-definitions/index.d.ts.map +1 -0
  37. package/dist/storage/domains/scores/index.d.ts +46 -0
  38. package/dist/storage/domains/scores/index.d.ts.map +1 -0
  39. package/dist/storage/domains/skills/index.d.ts +64 -0
  40. package/dist/storage/domains/skills/index.d.ts.map +1 -0
  41. package/dist/storage/domains/utils.d.ts +17 -0
  42. package/dist/storage/domains/utils.d.ts.map +1 -0
  43. package/dist/storage/domains/workflows/index.d.ts +97 -0
  44. package/dist/storage/domains/workflows/index.d.ts.map +1 -0
  45. package/dist/storage/index.d.ts +178 -0
  46. package/dist/storage/index.d.ts.map +1 -0
  47. package/package.json +2 -2
@@ -0,0 +1,64 @@
1
+ import { SkillsStorage } from '@mastra/core/storage';
2
+ import type { CreateIndexOptions, StorageSkillType, StorageCreateSkillInput, StorageListSkillsInput, StorageListSkillsOutput, StorageUpdateSkillInput } from '@mastra/core/storage';
3
+ import type { CreateSkillVersionInput, ListSkillVersionsInput, ListSkillVersionsOutput, SkillVersion } from '@mastra/core/storage/domains/skills';
4
+ import type { SpannerDomainConfig } from '../../db/index.js';
5
+ /**
6
+ * Spanner-backed storage for skills and their immutable versions.
7
+ * Mirrors the thin-record + versions pattern used by agents/prompt-blocks/scorer-definitions.
8
+ */
9
+ export declare class SkillsSpanner extends SkillsStorage {
10
+ private database;
11
+ private db;
12
+ private readonly skipDefaultIndexes?;
13
+ private readonly indexes?;
14
+ static readonly MANAGED_TABLES: readonly ["mastra_skills", "mastra_skill_versions"];
15
+ constructor(config: SpannerDomainConfig);
16
+ /** Creates the skill tables, indexes, and (when opted in) sweeps stale drafts. */
17
+ init(): Promise<void>;
18
+ /**
19
+ * Sweeps orphaned draft thin-rows whose paired version row was never written.
20
+ * Skipped under `initMode: 'validate'` (no destructive DML in validate mode).
21
+ */
22
+ private cleanupStaleDrafts;
23
+ /** Returns the default index set this domain creates during `init()`. */
24
+ getDefaultIndexDefinitions(): CreateIndexOptions[];
25
+ /** Creates the default indexes; no-op when `skipDefaultIndexes` was set. */
26
+ createDefaultIndexes(): Promise<void>;
27
+ /** Creates custom indexes routed to this domain's tables; no-op when none supplied. */
28
+ createCustomIndexes(): Promise<void>;
29
+ /** Removes every row from this domain's tables. Intended for tests. */
30
+ dangerouslyClearAll(): Promise<void>;
31
+ /** Decodes a raw Spanner thin-row into the public skill shape. */
32
+ private parseSkillRow;
33
+ /** Decodes a raw Spanner version row into the public version shape. */
34
+ private parseVersionRow;
35
+ /** Fetches the thin skill record by id, or `null` when absent. */
36
+ getById(id: string): Promise<StorageSkillType | null>;
37
+ /** Atomically inserts a draft thin row + version 1 in a single Spanner transaction. */
38
+ create(input: {
39
+ skill: StorageCreateSkillInput;
40
+ }): Promise<StorageSkillType>;
41
+ /** Updates thin-record fields (status, activeVersionId, authorId). */
42
+ update(input: StorageUpdateSkillInput): Promise<StorageSkillType>;
43
+ /** Removes a skill and all its versions atomically in a single transaction. */
44
+ delete(id: string): Promise<void>;
45
+ /** Paginated listing with optional authorId filter. */
46
+ list(args?: StorageListSkillsInput): Promise<StorageListSkillsOutput>;
47
+ /** Inserts a new immutable version row for an existing skill. */
48
+ createVersion(input: CreateSkillVersionInput): Promise<SkillVersion>;
49
+ /** Fetches a version row by its id, or `null` when absent. */
50
+ getVersion(id: string): Promise<SkillVersion | null>;
51
+ /** Fetches a specific version by `(skillId, versionNumber)`. */
52
+ getVersionByNumber(skillId: string, versionNumber: number): Promise<SkillVersion | null>;
53
+ /** Returns the highest-numbered version for a skill. */
54
+ getLatestVersion(skillId: string): Promise<SkillVersion | null>;
55
+ /** Paginated listing of versions for a single skill. */
56
+ listVersions(input: ListSkillVersionsInput): Promise<ListSkillVersionsOutput>;
57
+ /** Deletes a single version row by id. */
58
+ deleteVersion(id: string): Promise<void>;
59
+ /** Deletes every version row belonging to the given skill. */
60
+ deleteVersionsByParentId(entityId: string): Promise<void>;
61
+ /** Returns the total number of version rows for the given skill. */
62
+ countVersions(skillId: string): Promise<number>;
63
+ }
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/skills/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,aAAa,EAKd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,YAAY,EACb,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAIpD;;;GAGG;AACH,qBAAa,aAAc,SAAQ,aAAa;IAC9C,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,EAAE,CAAY;IACtB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAuB;IAEhD,MAAM,CAAC,QAAQ,CAAC,cAAc,sDAAiD;gBAEnE,MAAM,EAAE,mBAAmB;IAUvC,kFAAkF;IAC5E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B;;;OAGG;YACW,kBAAkB;IAmBhC,yEAAyE;IACzE,0BAA0B,IAAI,kBAAkB,EAAE;IAuBlD,4EAA4E;IACtE,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3C,uFAAuF;IACjF,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAK1C,uEAAuE;IACjE,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAK1C,kEAAkE;IAClE,OAAO,CAAC,aAAa;IAYrB,uEAAuE;IACvE,OAAO,CAAC,eAAe;IA0BvB,kEAAkE;IAC5D,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAuB3D,uFAAuF;IACjF,MAAM,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,uBAAuB,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAwFlF,sEAAsE;IAChE,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAgDvE,+EAA+E;IACzE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkCvC,uDAAuD;IACjD,IAAI,CAAC,IAAI,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAqE3E,iEAAiE;IAC3D,aAAa,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC;IAwC1E,8DAA8D;IACxD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAuB1D,gEAAgE;IAC1D,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA0B9F,wDAAwD;IAClD,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA0BrE,wDAAwD;IAClD,YAAY,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA8DnF,0CAA0C;IACpC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB9C,8DAA8D;IACxD,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB/D,oEAAoE;IAC9D,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAqBtD"}
@@ -0,0 +1,17 @@
1
+ import type { DateRange, TABLE_NAMES } from '@mastra/core/storage';
2
+ import { quoteIdent } from '../db/utils.js';
3
+ export { quoteIdent };
4
+ /**
5
+ * Build storage filter entries for a date range, using the operator suffixes
6
+ * understood by `SpannerDB.prepareWhereClause`.
7
+ */
8
+ export declare function buildDateRangeFilter(dateRange: DateRange | undefined, fieldName: string): Record<string, any>;
9
+ /**
10
+ * Convert a Spanner JSON-serialized row into the storage-layer expected shape.
11
+ * Mirrors the helper exported by other adapters so domain code can stay similar.
12
+ */
13
+ export declare function transformFromSpannerRow<T>({ tableName, row, }: {
14
+ tableName: TABLE_NAMES;
15
+ row: Record<string, any>;
16
+ }): T;
17
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/storage/domains/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAW7G;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,EACzC,SAAS,EACT,GAAG,GACJ,EAAE;IACD,SAAS,EAAE,WAAW,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC1B,GAAG,CAAC,CA6CJ"}
@@ -0,0 +1,97 @@
1
+ import { WorkflowsStorage } from '@mastra/core/storage';
2
+ import type { StorageListWorkflowRunsInput, WorkflowRun, WorkflowRuns, UpdateWorkflowStateOptions, CreateIndexOptions } from '@mastra/core/storage';
3
+ import type { StepResult, WorkflowRunState } from '@mastra/core/workflows';
4
+ import type { SpannerDomainConfig } from '../../db/index.js';
5
+ /**
6
+ * Spanner-backed storage for workflow run snapshots, including persistence,
7
+ * incremental updates, and listing of historical runs.
8
+ */
9
+ export declare class WorkflowsSpanner extends WorkflowsStorage {
10
+ private database;
11
+ private db;
12
+ private readonly skipDefaultIndexes?;
13
+ private readonly indexes?;
14
+ static readonly MANAGED_TABLES: readonly ["mastra_workflow_snapshot"];
15
+ constructor(config: SpannerDomainConfig);
16
+ /** Spanner serialises read-write transactions, so concurrent updates are safe. */
17
+ supportsConcurrentUpdates(): boolean;
18
+ /** Returns the default index set this domain creates during `init()`. */
19
+ getDefaultIndexDefinitions(): CreateIndexOptions[];
20
+ /**
21
+ * Creates the default indexes; no-op when `skipDefaultIndexes` was set.
22
+ * Filters out the snapshotStatus index when that generated column is absent
23
+ * (e.g. ensureStatusColumn() failed, or `initMode: 'validate'` skipped the
24
+ * DDL). Otherwise the createIndex call would fail on a missing column.
25
+ */
26
+ createDefaultIndexes(): Promise<void>;
27
+ /** Creates the workflow snapshot table, the snapshotStatus generated column, and indexes. */
28
+ init(): Promise<void>;
29
+ /**
30
+ * Spanner-specific optimization: add a STORED generated column that extracts
31
+ * `status` from the JSON snapshot, so the listWorkflowRuns status filter can
32
+ * use a regular secondary index instead of a full JSON_VALUE scan.
33
+ *
34
+ * The column is owned and maintained entirely by the Spanner adapter; the
35
+ * shared `@mastra/core` schema doesn't reference it. The DDL is idempotent
36
+ * (`ADD COLUMN IF NOT EXISTS`) and the schema operation is awaited; Spanner
37
+ * backfills existing rows asynchronously after the operation returns, while
38
+ * new rows pick up the value on every write.
39
+ */
40
+ private ensureStatusColumn;
41
+ /**
42
+ * Cached lookup for whether the `snapshotStatus` generated column exists.
43
+ * Resolves true after `ensureStatusColumn()` succeeds, otherwise falls back
44
+ * to an INFORMATION_SCHEMA probe (lets us still pick up the fast path on
45
+ * databases that already had the column from a prior deploy).
46
+ */
47
+ private statusColumnAvailable;
48
+ /** Returns true when the `snapshotStatus` generated column exists. */
49
+ private hasStatusColumn;
50
+ /** Creates custom indexes routed to this domain's tables; no-op when none supplied. */
51
+ createCustomIndexes(): Promise<void>;
52
+ /** Removes every workflow snapshot row. Intended for tests. */
53
+ dangerouslyClearAll(): Promise<void>;
54
+ /** Decodes a raw Spanner snapshot row into the public `WorkflowRun` shape. */
55
+ private parseWorkflowRun;
56
+ /** Upserts a workflow run snapshot, preserving the original `createdAt` on update. */
57
+ persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, }: {
58
+ workflowName: string;
59
+ runId: string;
60
+ resourceId?: string;
61
+ snapshot: WorkflowRunState;
62
+ createdAt?: Date;
63
+ updatedAt?: Date;
64
+ }): Promise<void>;
65
+ /** Loads the snapshot payload for a `(workflowName, runId)` pair, or `null` when absent. */
66
+ loadWorkflowSnapshot({ workflowName, runId, }: {
67
+ workflowName: string;
68
+ runId: string;
69
+ }): Promise<WorkflowRunState | null>;
70
+ /** Merges a step result and request-context delta into a snapshot inside an RW transaction. */
71
+ updateWorkflowResults({ workflowName, runId, stepId, result, requestContext, }: {
72
+ workflowName: string;
73
+ runId: string;
74
+ stepId: string;
75
+ result: StepResult<any, any, any, any>;
76
+ requestContext: Record<string, any>;
77
+ }): Promise<Record<string, StepResult<any, any, any, any>>>;
78
+ /** Applies a top-level snapshot patch (e.g. status, value) inside an RW transaction. */
79
+ updateWorkflowState({ workflowName, runId, opts, }: {
80
+ workflowName: string;
81
+ runId: string;
82
+ opts: UpdateWorkflowStateOptions;
83
+ }): Promise<WorkflowRunState | undefined>;
84
+ /** Fetches a single workflow run by `runId` (optionally narrowed by `workflowName`). */
85
+ getWorkflowRunById({ runId, workflowName, }: {
86
+ runId: string;
87
+ workflowName?: string;
88
+ }): Promise<WorkflowRun | null>;
89
+ /** Deletes the snapshot row for a `(workflowName, runId)` pair. */
90
+ deleteWorkflowRunById({ runId, workflowName }: {
91
+ runId: string;
92
+ workflowName: string;
93
+ }): Promise<void>;
94
+ /** Paginated listing with optional workflowName, status, resourceId, and date-range filters. */
95
+ listWorkflowRuns({ workflowName, fromDate, toDate, page, perPage, resourceId, status, }?: StorageListWorkflowRunsInput): Promise<WorkflowRuns>;
96
+ }
97
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/workflows/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ import { Spanner } from '@google-cloud/spanner';
2
+ import type { Database, Instance } from '@google-cloud/spanner';
3
+ import { MastraCompositeStore } from '@mastra/core/storage';
4
+ import type { StorageDomains, CreateIndexOptions } from '@mastra/core/storage';
5
+ import type { SpannerInitMode } from './db/index.js';
6
+ import { AgentsSpanner } from './domains/agents/index.js';
7
+ import { BackgroundTasksSpanner } from './domains/background-tasks/index.js';
8
+ import { BlobsSpanner } from './domains/blobs/index.js';
9
+ import { MCPClientsSpanner } from './domains/mcp-clients/index.js';
10
+ import { MCPServersSpanner } from './domains/mcp-servers/index.js';
11
+ import { MemorySpanner } from './domains/memory/index.js';
12
+ import { ObservabilitySpanner } from './domains/observability/index.js';
13
+ import { PromptBlocksSpanner } from './domains/prompt-blocks/index.js';
14
+ import { SchedulesSpanner } from './domains/schedules/index.js';
15
+ import { ScorerDefinitionsSpanner } from './domains/scorer-definitions/index.js';
16
+ import { ScoresSpanner } from './domains/scores/index.js';
17
+ import { SkillsSpanner } from './domains/skills/index.js';
18
+ import { WorkflowsSpanner } from './domains/workflows/index.js';
19
+ export { AgentsSpanner, BackgroundTasksSpanner, BlobsSpanner, MCPClientsSpanner, MCPServersSpanner, MemorySpanner, ObservabilitySpanner, PromptBlocksSpanner, SchedulesSpanner, ScorerDefinitionsSpanner, ScoresSpanner, SkillsSpanner, WorkflowsSpanner, };
20
+ export type { SpannerDomainConfig, SpannerInitMode } from './db/index.js';
21
+ /** Domain keys this adapter implements; the only valid values for `enabledDomains`. */
22
+ export declare const SPANNER_DOMAIN_KEYS: readonly ["scores", "workflows", "memory", "backgroundTasks", "agents", "mcpClients", "mcpServers", "skills", "blobs", "promptBlocks", "scorerDefinitions", "schedules", "observability"];
23
+ export type SpannerDomainKey = (typeof SPANNER_DOMAIN_KEYS)[number];
24
+ /**
25
+ * Cloud Spanner configuration accepted by `SpannerStore`.
26
+ *
27
+ * Supports either:
28
+ * - Pre-configured `database` (a `@google-cloud/spanner` Database handle), or
29
+ * - Connection details (`projectId`, `instanceId`, `databaseId`) from which the
30
+ * store creates a Spanner client internally.
31
+ */
32
+ export type SpannerConfigType = {
33
+ id: string;
34
+ /**
35
+ * When true, automatic initialization (table creation/migrations) is disabled.
36
+ *
37
+ * When `disableInit` is true, the store will not automatically create or alter
38
+ * tables on first use. You must call `storage.init()` explicitly during a
39
+ * separate deploy/migration step.
40
+ */
41
+ disableInit?: boolean;
42
+ /**
43
+ * When true, default indexes will not be created during initialization.
44
+ * @default false
45
+ */
46
+ skipDefaultIndexes?: boolean;
47
+ /**
48
+ * Custom indexes to create during initialization. Each index must specify the
49
+ * table it belongs to; the store routes indexes to the correct domain.
50
+ */
51
+ indexes?: CreateIndexOptions[];
52
+ /**
53
+ * Controls whether `init()` is allowed to apply schema changes.
54
+ *
55
+ * - `'sync'` (default): the adapter creates missing tables, columns, and
56
+ * indexes during `init()`. This is the historical behavior.
57
+ * - `'validate'`: the adapter applies no DDL during `init()` and instead
58
+ * verifies that every table, column, and default/custom index it would
59
+ * have created already exists. Missing schema elements throw a typed
60
+ * user error so the operator can reconcile the externally-managed
61
+ * schema with what the adapter expects.
62
+ *
63
+ * `'validate'` is intended for environments where another process
64
+ * (Terraform, Liquibase, a release pipeline, etc.) owns the schema.
65
+ * @default 'sync'
66
+ */
67
+ initMode?: SpannerInitMode;
68
+ /**
69
+ * When true, versioned domains (agents / skills / prompt-blocks /
70
+ * mcp-clients / mcp-servers / scorer-definitions) sweep orphaned draft
71
+ * thin-row records during `init()` i.e. drafts whose paired version
72
+ * row was never written. The transactional `create()` rewrite makes
73
+ * these orphans impossible going forward; this opt-in is for cleaning
74
+ * up legacy data left by older deployments or for environments where
75
+ * the small startup cost is acceptable.
76
+ * @default false
77
+ */
78
+ cleanupStaleDraftsOnStartup?: boolean;
79
+ /**
80
+ * Restricts which storage domains this adapter constructs and initializes.
81
+ *
82
+ * When omitted (the default), all domains the adapter implements are
83
+ * registered, matching historical behavior. When provided, only the listed
84
+ * domains are constructed and added to `this.stores`; `init()` will only
85
+ * touch those domains, and `getStore()` returns `undefined` for the rest.
86
+ *
87
+ * Useful when another store owns some domains in a composite, or when the
88
+ * deployment environment manages only a subset of the schema (e.g. a
89
+ * workflows-only Spanner database in `initMode: 'validate'`, where
90
+ * validating tables for unused domains would fail).
91
+ */
92
+ enabledDomains?: ReadonlyArray<SpannerDomainKey>;
93
+ /**
94
+ * Maximum acceptable staleness (in milliseconds) for the observability
95
+ * domain's read paths (metrics list / aggregates / breakdowns /
96
+ * time-series / percentiles / discovery). When set to a positive value,
97
+ * those queries run as bounded-staleness single-use reads, which Spanner
98
+ * can route to any replica that's at least that fresh. They stop
99
+ * competing with leader-region writes for CPU and can land on a closer
100
+ * replica.
101
+ *
102
+ * Default is `10000` (weak reads against the leader).
103
+ * @default 10000
104
+ */
105
+ dashboardStalenessMs?: number;
106
+ /**
107
+ * When true (the default), the observability domain's metric methods
108
+ * throw `*_NOT_IMPLEMENTED` and the metrics table is not created during
109
+ * `init()`. The `MastraStorageExporter` reads those errors and silently
110
+ * drops metric emissions.
111
+ *
112
+ * This is the recommended default because Spanner is row-oriented and
113
+ * OLTP-shaped — the metrics workload is write-heavy, scan-heavy, and
114
+ * benefits from columnar storage. Pair Spanner spans with a dedicated
115
+ * OLAP metrics store (DuckDB, ClickHouse) via a
116
+ * `MastraCompositeStore`-level wrapper that fans out by signal.
117
+ * @default true
118
+ */
119
+ disableMetrics?: boolean;
120
+ } & ({
121
+ /** Pre-configured Spanner Database handle. */
122
+ database: Database;
123
+ } | {
124
+ projectId: string;
125
+ instanceId: string;
126
+ databaseId: string;
127
+ /**
128
+ * Optional pass-through to the `@google-cloud/spanner` client constructor.
129
+ * Useful for credentials, custom service paths (e.g. against the emulator),
130
+ * or auth overrides.
131
+ */
132
+ spannerOptions?: ConstructorParameters<typeof Spanner>[0];
133
+ });
134
+ export type SpannerConfig = SpannerConfigType;
135
+ /**
136
+ * Google Cloud Spanner storage adapter for Mastra. Implements the GoogleSQL
137
+ * dialect of Cloud Spanner.
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * const storage = new SpannerStore({
142
+ * id: 'my-store',
143
+ * projectId: 'my-project',
144
+ * instanceId: 'my-instance',
145
+ * databaseId: 'mastra',
146
+ * });
147
+ *
148
+ * const memory = await storage.getStore('memory');
149
+ * await memory?.saveThread({ thread });
150
+ * ```
151
+ */
152
+ export declare class SpannerStore extends MastraCompositeStore {
153
+ database: Database;
154
+ spanner?: Spanner;
155
+ instance?: Instance;
156
+ private readonly ownsClient;
157
+ stores: StorageDomains;
158
+ constructor(config: SpannerConfigType);
159
+ /**
160
+ * Initializes the storage by running each domain's `init()` sequentially.
161
+ *
162
+ * Spanner does not allow concurrent schema changes against the same database,
163
+ * so the default `MastraCompositeStore.init()` (which fans out via
164
+ * `Promise.all`) cannot be used here.
165
+ *
166
+ * Concurrent callers all await the same in-flight promise: the first call
167
+ * installs a pending `hasInitialized` immediately, before any awaits, so a
168
+ * second caller landing on `init()` sees it and queues behind the same loop
169
+ * instead of starting its own.
170
+ */
171
+ init(): Promise<void>;
172
+ /**
173
+ * Closes the Spanner client and database handle if this store owns them.
174
+ * Pre-configured databases are left alone for the caller to manage.
175
+ */
176
+ close(): Promise<void>;
177
+ }
178
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/spanner",
3
- "version": "0.0.0",
3
+ "version": "1.0.0-alpha.0",
4
4
  "description": "Google Cloud Spanner provider for Mastra - db storage capabilities (GoogleSQL dialect)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -31,8 +31,8 @@
31
31
  "typescript": "^6.0.3",
32
32
  "vitest": "4.1.5",
33
33
  "@internal/lint": "0.0.97",
34
- "@mastra/core": "1.37.0-alpha.7",
35
34
  "@internal/storage-test-utils": "0.0.93",
35
+ "@mastra/core": "1.37.0-alpha.8",
36
36
  "@internal/types-builder": "0.0.72"
37
37
  },
38
38
  "peerDependencies": {