@mastra/mongodb 1.12.0-alpha.0 → 1.12.0-alpha.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/CHANGELOG.md +127 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +104 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +104 -31
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/datasets/index.d.ts +6 -7
- package/dist/storage/domains/datasets/index.d.ts.map +1 -1
- package/dist/storage/domains/experiments/index.d.ts +9 -5
- package/dist/storage/domains/experiments/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +9 -5
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/utils.d.ts +18 -0
- package/dist/storage/domains/utils.d.ts.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,132 @@
|
|
|
1
1
|
# @mastra/mongodb
|
|
2
2
|
|
|
3
|
+
## 1.12.0-alpha.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Added optional tenancy arguments to `getDataset`, `updateDataset`, and `deleteDataset`. ([#18750](https://github.com/mastra-ai/mastra/pull/18750))
|
|
8
|
+
|
|
9
|
+
You can now pass `organizationId` and `projectId` to scope dataset reads, updates, and deletes to a specific tenant. Reads and updates against a dataset in a different tenant throw `DATASET_NOT_FOUND` (surfaced as a 404 over HTTP). Deletes silently no-op on a tenancy mismatch — matching the existing "delete non-existent id is a no-op" semantics so cross-tenant existence is never leaked via error timing or status.
|
|
10
|
+
|
|
11
|
+
**Example**
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// Before
|
|
15
|
+
await client.getDataset('abc123');
|
|
16
|
+
await client.deleteDataset('abc123');
|
|
17
|
+
await client.updateDataset({ id: 'abc123', name: 'renamed' });
|
|
18
|
+
|
|
19
|
+
// After — scope to a tenant
|
|
20
|
+
await client.getDataset('abc123', { organizationId: 'org_a', projectId: 'proj_1' });
|
|
21
|
+
await client.deleteDataset('abc123', { organizationId: 'org_a' });
|
|
22
|
+
await client.updateDataset({ id: 'abc123', name: 'renamed', organizationId: 'org_a' });
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- Pushed remaining dataset read filters and pagination down to storage. ([#18710](https://github.com/mastra-ai/mastra/pull/18710))
|
|
26
|
+
|
|
27
|
+
`DatasetsManager.list({ filters })` now accepts `targetType`, `targetIds` (overlap/union semantics), and `name` (substring, case-insensitive) in addition to the existing tenancy and candidate filters. Filtering is pushed down to the storage layer so callers no longer have to post-filter results.
|
|
28
|
+
|
|
29
|
+
Storage adapters must also be upgraded to the versions listed below to honor the new filters. If a caller is on this version of `@mastra/core` but on an older storage adapter, the new `targetType`/`targetIds`/`name` filter keys are silently ignored by the adapter — no runtime error, but the filter has no effect and every dataset in the tenancy is returned.
|
|
30
|
+
|
|
31
|
+
`Dataset.listItems({ version, search, page, perPage })` now applies `search` and pagination at the storage layer when `version` is provided alongside any of those. Previously they were silently dropped whenever `version` was set. The return shape is unchanged: passing only `version` still returns a bare `DatasetItem[]` snapshot; passing `search`, `page`, or `perPage` (with or without `version`) returns the paginated `{ items, pagination }` shape. The bare-array branch is marked `@deprecated`; prefer passing `page` / `perPage` to always receive the paginated shape.
|
|
32
|
+
|
|
33
|
+
- Tenancy-scope experiments `getById` and `delete*` on `ExperimentsStorage`. ([#18770](https://github.com/mastra-ai/mastra/pull/18770))
|
|
34
|
+
|
|
35
|
+
`ExperimentsStorage.getExperimentById`, `getExperimentResultById`, `deleteExperiment`, and `deleteExperimentResults` used to key on the primary id alone, so any caller who knew the id could read or delete the row regardless of tenant. All four now accept an optional `filters: { organizationId?, projectId? }` argument that is enforced on every adapter (inmemory, libsql, pg, mysql, mongodb, spanner):
|
|
36
|
+
- On tenancy mismatch, `get*` returns `null` at the storage layer.
|
|
37
|
+
- On tenancy mismatch, `delete*` is a silent no-op.
|
|
38
|
+
- The tenancy predicate is folded into the destructive DML itself (scoped `WHERE` on the DELETE, an atomic gate + delete inside a transaction, or a scoped subquery for the results cascade). A concurrent tenant swap of the same id between a pre-check and the DELETE cannot let a scoped delete hit another tenant's row.
|
|
39
|
+
|
|
40
|
+
Both behaviors match how a missing id already responds, so existence does not leak through error timing or messages.
|
|
41
|
+
|
|
42
|
+
The same atomic-DML pattern is also applied to `DatasetsStorage.deleteDataset` across all 5 store adapters, closing a TOCTOU window between the pre-check and the parent DELETE that was introduced when tenancy filters were originally added.
|
|
43
|
+
|
|
44
|
+
`Dataset.getExperiment` and the shared experiment-ownership gate on `Dataset` now forward the dataset's tenancy scope to storage, so experiment reads and downstream mutations (list results, update result, delete experiment) reached through a dataset handle are automatically scoped to the owning tenant.
|
|
45
|
+
|
|
46
|
+
Legacy calls that omit `filters` are unchanged, so this is fully backwards-compatible.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
// Before: any caller who knew the id could read/delete across tenants.
|
|
50
|
+
await store.experiments.getExperimentById({ id: experimentId });
|
|
51
|
+
await store.experiments.deleteExperiment({ id: experimentId });
|
|
52
|
+
|
|
53
|
+
// After: pass the caller's scope; wrong tenant gets null / silent no-op.
|
|
54
|
+
await store.experiments.getExperimentById({
|
|
55
|
+
id: experimentId,
|
|
56
|
+
filters: { organizationId, projectId },
|
|
57
|
+
});
|
|
58
|
+
await store.experiments.deleteExperiment({
|
|
59
|
+
id: experimentId,
|
|
60
|
+
filters: { organizationId, projectId },
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- Fixed a cross-tenant data-access issue on datasets by scoping `DatasetsManager.get` and `DatasetsManager.delete` to tenancy filters. ([#18750](https://github.com/mastra-ai/mastra/pull/18750))
|
|
65
|
+
|
|
66
|
+
Previously `get({ id })` and `delete({ id })` looked up a dataset by its primary key alone. Any caller who knew a dataset id could read or delete it regardless of which `organizationId` / `projectId` it belonged to. This is now closed at the storage layer via a scoped SQL predicate (option (a) — no fetch-then-assert).
|
|
67
|
+
|
|
68
|
+
**What changed**
|
|
69
|
+
- `DatasetsManager.get` and `DatasetsManager.delete` accept optional `organizationId` and `projectId`.
|
|
70
|
+
- The tenancy is stashed on the returned `Dataset` handle and forwarded to every downstream storage call (`getDetails`, `update`, `addItem`, item batch ops, `startExperimentAsync`).
|
|
71
|
+
- The abstract storage contract (`getDatasetById`, `deleteDataset`) gained an optional `filters?: DatasetTenancyFilters` arg.
|
|
72
|
+
- Item-mutation inputs (`AddDatasetItemInput`, `UpdateDatasetItemInput`, `BatchInsertItemsInput`, `BatchDeleteItemsInput`) and `UpdateDatasetInput` accept optional `filters` for the internal existence check.
|
|
73
|
+
|
|
74
|
+
**Behavior**
|
|
75
|
+
- Omitting tenancy preserves the existing behavior (no predicate added) — fully backwards compatible.
|
|
76
|
+
- On tenancy mismatch, `get` throws NOT_FOUND (returns null at the storage layer) and `delete` is a silent no-op — matching how a missing id already behaves, so existence does not leak through error timing or messages.
|
|
77
|
+
|
|
78
|
+
**Example**
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
// Before
|
|
82
|
+
const ds = await mastra.datasets.get({ id });
|
|
83
|
+
await mastra.datasets.delete({ id });
|
|
84
|
+
|
|
85
|
+
// After — scope to a tenant
|
|
86
|
+
const ds = await mastra.datasets.get({ id, organizationId, projectId });
|
|
87
|
+
await mastra.datasets.delete({ id, organizationId, projectId });
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- Added optional `organizationId` and `projectId` fields to scores for multi-tenant isolation. Scores can now be saved with tenancy metadata and the `listScoresBy*` methods accept a `filters` option to scope results by organization and project. ([#18331](https://github.com/mastra-ai/mastra/pull/18331))
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
await storage.saveScore({ ...score, organizationId: 'org-a', projectId: 'proj-1' });
|
|
94
|
+
|
|
95
|
+
const result = await storage.listScoresByScorerId({
|
|
96
|
+
scorerId,
|
|
97
|
+
filters: { organizationId: 'org-a', projectId: 'proj-1' },
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`projectId` identifies the project scope, separate from `resourceId` which continues to mean the agent memory resource.
|
|
102
|
+
|
|
103
|
+
- Scoped `getDatasetById` and `deleteDataset` to tenancy filters when the caller passes `organizationId` / `projectId`. ([#18750](https://github.com/mastra-ai/mastra/pull/18750))
|
|
104
|
+
|
|
105
|
+
The adapters now push the tenancy predicate into the SQL/query when the new optional `filters` argument is present. Legacy calls that omit tenancy are unchanged. On mismatch, `getDatasetById` returns `null` and `deleteDataset` is a silent no-op — the cascade delete (dataset items and versions) is gated by a scoped parent pre-check, so cross-tenant data is never touched.
|
|
106
|
+
|
|
107
|
+
- Added optional `organizationId` and `projectId` query parameters to the dataset routes. ([#18750](https://github.com/mastra-ai/mastra/pull/18750))
|
|
108
|
+
|
|
109
|
+
`GET /datasets/:datasetId`, `PATCH /datasets/:datasetId`, and `DELETE /datasets/:datasetId` now accept optional tenancy query parameters. When provided, they are forwarded to `mastra.datasets.get` / `.delete` and the operation returns 404 if the dataset does not belong to the requested tenant. Requests that omit the query parameters keep their existing behavior.
|
|
110
|
+
|
|
111
|
+
**Example**
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
GET /datasets/abc123?organizationId=org_a&projectId=proj_1
|
|
115
|
+
DELETE /datasets/abc123?organizationId=org_a
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
- Updated dependencies [[`9250acd`](https://github.com/mastra-ai/mastra/commit/9250acd1357f0f1f33d0dcca16f9655084c58eca), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`c64c2a8`](https://github.com/mastra-ai/mastra/commit/c64c2a8503a50252f9ca6b8e8c54cadee31b92a2), [`06e2680`](https://github.com/mastra-ai/mastra/commit/06e26806b51d2cbd858afdc66daa2b86ff3ba64a), [`1240f05`](https://github.com/mastra-ai/mastra/commit/1240f051c8e5371f1c014448bf37b1a1b9a05e47), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748)]:
|
|
119
|
+
- @mastra/core@1.49.0-alpha.5
|
|
120
|
+
|
|
121
|
+
## 1.12.0-alpha.1
|
|
122
|
+
|
|
123
|
+
### Patch Changes
|
|
124
|
+
|
|
125
|
+
- Fixed `createExperiment` in the MongoDB store persisting `agentVersion` as `null` regardless of the input. `listExperiments` already accepts an `agentVersion` filter, but rows created by this backend would never match it. New experiments now round-trip `agentVersion` end-to-end. ([#18769](https://github.com/mastra-ai/mastra/pull/18769))
|
|
126
|
+
|
|
127
|
+
- Updated dependencies [[`6a61846`](https://github.com/mastra-ai/mastra/commit/6a61846eeda29fb714549b70f1bee2bf6b141c44)]:
|
|
128
|
+
- @mastra/core@1.49.0-alpha.4
|
|
129
|
+
|
|
3
130
|
## 1.12.0-alpha.0
|
|
4
131
|
|
|
5
132
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-mongodb
|
|
|
3
3
|
description: Documentation for @mastra/mongodb. Use when working with @mastra/mongodb APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/mongodb"
|
|
6
|
-
version: "1.12.0-alpha.
|
|
6
|
+
version: "1.12.0-alpha.2"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
package/dist/index.cjs
CHANGED
|
@@ -15,7 +15,7 @@ var skills = require('@mastra/core/storage/domains/skills');
|
|
|
15
15
|
|
|
16
16
|
// package.json
|
|
17
17
|
var package_default = {
|
|
18
|
-
version: "1.12.0-alpha.
|
|
18
|
+
version: "1.12.0-alpha.2"};
|
|
19
19
|
var MongoDBFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
20
20
|
getSupportedOperators() {
|
|
21
21
|
return {
|
|
@@ -2151,6 +2151,16 @@ var MongoDBBlobStore = class _MongoDBBlobStore extends storage.BlobStore {
|
|
|
2151
2151
|
};
|
|
2152
2152
|
}
|
|
2153
2153
|
};
|
|
2154
|
+
function formatDateForMongoDB(date) {
|
|
2155
|
+
return typeof date === "string" ? new Date(date) : date;
|
|
2156
|
+
}
|
|
2157
|
+
function applyTenancyFilter(filter, filters) {
|
|
2158
|
+
if (!filters) return;
|
|
2159
|
+
if (filters.organizationId !== void 0) filter.organizationId = filters.organizationId;
|
|
2160
|
+
if (filters.projectId !== void 0) filter.projectId = filters.projectId;
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
// src/storage/domains/datasets/index.ts
|
|
2154
2164
|
var MANAGED_COLLECTIONS = [storage.TABLE_DATASETS, storage.TABLE_DATASET_ITEMS, storage.TABLE_DATASET_VERSIONS];
|
|
2155
2165
|
var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
|
|
2156
2166
|
#connector;
|
|
@@ -2345,10 +2355,15 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
|
|
|
2345
2355
|
);
|
|
2346
2356
|
}
|
|
2347
2357
|
}
|
|
2348
|
-
async getDatasetById({
|
|
2358
|
+
async getDatasetById({
|
|
2359
|
+
id,
|
|
2360
|
+
filters
|
|
2361
|
+
}) {
|
|
2349
2362
|
try {
|
|
2350
2363
|
const collection = await this.getCollection(storage.TABLE_DATASETS);
|
|
2351
|
-
const
|
|
2364
|
+
const query = { id };
|
|
2365
|
+
applyTenancyFilter(query, filters);
|
|
2366
|
+
const row = await collection.findOne(query);
|
|
2352
2367
|
return row ? this.transformDatasetRow(row) : null;
|
|
2353
2368
|
} catch (error$1) {
|
|
2354
2369
|
throw new error.MastraError(
|
|
@@ -2363,7 +2378,7 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
|
|
|
2363
2378
|
}
|
|
2364
2379
|
async _doUpdateDataset(args) {
|
|
2365
2380
|
try {
|
|
2366
|
-
const existing = await this.getDatasetById({ id: args.id });
|
|
2381
|
+
const existing = await this.getDatasetById({ id: args.id, filters: args.filters });
|
|
2367
2382
|
if (!existing) {
|
|
2368
2383
|
throw new error.MastraError({
|
|
2369
2384
|
id: storage.createStorageErrorId("MONGODB", "UPDATE_DATASET", "NOT_FOUND"),
|
|
@@ -2400,8 +2415,13 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
|
|
|
2400
2415
|
);
|
|
2401
2416
|
}
|
|
2402
2417
|
}
|
|
2403
|
-
async deleteDataset({ id }) {
|
|
2418
|
+
async deleteDataset({ id, filters }) {
|
|
2404
2419
|
try {
|
|
2420
|
+
const datasetsCollectionForGate = await this.getCollection(storage.TABLE_DATASETS);
|
|
2421
|
+
const gateQuery = { id };
|
|
2422
|
+
applyTenancyFilter(gateQuery, filters);
|
|
2423
|
+
const gateHit = await datasetsCollectionForGate.findOne(gateQuery, { projection: { id: 1 } });
|
|
2424
|
+
if (!gateHit) return;
|
|
2405
2425
|
try {
|
|
2406
2426
|
const experimentsCollection = await this.getCollection(storage.TABLE_EXPERIMENTS);
|
|
2407
2427
|
const experimentIds = await experimentsCollection.find({ datasetId: id }, { projection: { id: 1 } }).toArray();
|
|
@@ -2421,7 +2441,9 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
|
|
|
2421
2441
|
const datasetsCollection = await this.getCollection(storage.TABLE_DATASETS);
|
|
2422
2442
|
await versionsCollection.deleteMany({ datasetId: id });
|
|
2423
2443
|
await itemsCollection.deleteMany({ datasetId: id });
|
|
2424
|
-
|
|
2444
|
+
const parentDeleteQuery = { id };
|
|
2445
|
+
applyTenancyFilter(parentDeleteQuery, filters);
|
|
2446
|
+
await datasetsCollection.deleteOne(parentDeleteQuery);
|
|
2425
2447
|
} catch (error$1) {
|
|
2426
2448
|
if (error$1 instanceof error.MastraError) throw error$1;
|
|
2427
2449
|
throw new error.MastraError(
|
|
@@ -2443,6 +2465,14 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
|
|
|
2443
2465
|
if (args.filters?.projectId !== void 0) filter.projectId = args.filters.projectId;
|
|
2444
2466
|
if (args.filters?.candidateKey !== void 0) filter.candidateKey = args.filters.candidateKey;
|
|
2445
2467
|
if (args.filters?.candidateId !== void 0) filter.candidateId = args.filters.candidateId;
|
|
2468
|
+
if (args.filters?.targetType !== void 0) filter.targetType = args.filters.targetType;
|
|
2469
|
+
if (args.filters?.targetIds !== void 0 && args.filters.targetIds.length > 0) {
|
|
2470
|
+
filter.targetIds = { $in: args.filters.targetIds };
|
|
2471
|
+
}
|
|
2472
|
+
if (args.filters?.name !== void 0 && args.filters.name.length > 0) {
|
|
2473
|
+
const escapedName = args.filters.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2474
|
+
filter.name = { $regex: escapedName, $options: "i" };
|
|
2475
|
+
}
|
|
2446
2476
|
const total = await collection.countDocuments(filter);
|
|
2447
2477
|
if (total === 0) {
|
|
2448
2478
|
return { datasets: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
|
|
@@ -3362,7 +3392,7 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
|
|
|
3362
3392
|
succeededCount: 0,
|
|
3363
3393
|
failedCount: 0,
|
|
3364
3394
|
skippedCount: 0,
|
|
3365
|
-
agentVersion: null,
|
|
3395
|
+
agentVersion: input.agentVersion ?? null,
|
|
3366
3396
|
startedAt: null,
|
|
3367
3397
|
completedAt: null,
|
|
3368
3398
|
createdAt: now,
|
|
@@ -3387,7 +3417,7 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
|
|
|
3387
3417
|
succeededCount: 0,
|
|
3388
3418
|
failedCount: 0,
|
|
3389
3419
|
skippedCount: 0,
|
|
3390
|
-
agentVersion: null,
|
|
3420
|
+
agentVersion: input.agentVersion ?? null,
|
|
3391
3421
|
startedAt: null,
|
|
3392
3422
|
completedAt: null,
|
|
3393
3423
|
createdAt: now,
|
|
@@ -3443,10 +3473,15 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
|
|
|
3443
3473
|
);
|
|
3444
3474
|
}
|
|
3445
3475
|
}
|
|
3446
|
-
async getExperimentById({
|
|
3476
|
+
async getExperimentById({
|
|
3477
|
+
id,
|
|
3478
|
+
filters
|
|
3479
|
+
}) {
|
|
3447
3480
|
try {
|
|
3448
3481
|
const collection = await this.getCollection(storage.TABLE_EXPERIMENTS);
|
|
3449
|
-
const
|
|
3482
|
+
const query = { id };
|
|
3483
|
+
applyTenancyFilter(query, filters);
|
|
3484
|
+
const doc = await collection.findOne(query);
|
|
3450
3485
|
if (!doc) return null;
|
|
3451
3486
|
return transformExperimentRow(doc);
|
|
3452
3487
|
} catch (error$1) {
|
|
@@ -3521,12 +3556,20 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
|
|
|
3521
3556
|
);
|
|
3522
3557
|
}
|
|
3523
3558
|
}
|
|
3524
|
-
async deleteExperiment({ id }) {
|
|
3559
|
+
async deleteExperiment({ id, filters }) {
|
|
3525
3560
|
try {
|
|
3526
|
-
const resultsCollection = await this.getCollection(storage.TABLE_EXPERIMENT_RESULTS);
|
|
3527
|
-
await resultsCollection.deleteMany({ experimentId: id });
|
|
3528
3561
|
const experimentsCollection = await this.getCollection(storage.TABLE_EXPERIMENTS);
|
|
3529
|
-
|
|
3562
|
+
const gateQuery = { id };
|
|
3563
|
+
applyTenancyFilter(gateQuery, filters);
|
|
3564
|
+
const existing = await experimentsCollection.findOne(gateQuery);
|
|
3565
|
+
if (!existing) return;
|
|
3566
|
+
const resultsCollection = await this.getCollection(storage.TABLE_EXPERIMENT_RESULTS);
|
|
3567
|
+
const resultsQuery = { experimentId: id };
|
|
3568
|
+
applyTenancyFilter(resultsQuery, filters);
|
|
3569
|
+
await resultsCollection.deleteMany(resultsQuery);
|
|
3570
|
+
const parentDeleteQuery = { id };
|
|
3571
|
+
applyTenancyFilter(parentDeleteQuery, filters);
|
|
3572
|
+
await experimentsCollection.deleteOne(parentDeleteQuery);
|
|
3530
3573
|
} catch (error$1) {
|
|
3531
3574
|
throw new error.MastraError(
|
|
3532
3575
|
{
|
|
@@ -3645,10 +3688,15 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
|
|
|
3645
3688
|
);
|
|
3646
3689
|
}
|
|
3647
3690
|
}
|
|
3648
|
-
async getExperimentResultById({
|
|
3691
|
+
async getExperimentResultById({
|
|
3692
|
+
id,
|
|
3693
|
+
filters
|
|
3694
|
+
}) {
|
|
3649
3695
|
try {
|
|
3650
3696
|
const collection = await this.getCollection(storage.TABLE_EXPERIMENT_RESULTS);
|
|
3651
|
-
const
|
|
3697
|
+
const query = { id };
|
|
3698
|
+
applyTenancyFilter(query, filters);
|
|
3699
|
+
const doc = await collection.findOne(query);
|
|
3652
3700
|
if (!doc) return null;
|
|
3653
3701
|
return transformExperimentResultRow(doc);
|
|
3654
3702
|
} catch (error$1) {
|
|
@@ -3715,10 +3763,22 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
|
|
|
3715
3763
|
);
|
|
3716
3764
|
}
|
|
3717
3765
|
}
|
|
3718
|
-
async deleteExperimentResults({
|
|
3766
|
+
async deleteExperimentResults({
|
|
3767
|
+
experimentId,
|
|
3768
|
+
filters
|
|
3769
|
+
}) {
|
|
3719
3770
|
try {
|
|
3771
|
+
if (filters?.organizationId !== void 0 || filters?.projectId !== void 0) {
|
|
3772
|
+
const experimentsCollection = await this.getCollection(storage.TABLE_EXPERIMENTS);
|
|
3773
|
+
const gateQuery = { id: experimentId };
|
|
3774
|
+
applyTenancyFilter(gateQuery, filters);
|
|
3775
|
+
const parent = await experimentsCollection.findOne(gateQuery);
|
|
3776
|
+
if (!parent) return;
|
|
3777
|
+
}
|
|
3720
3778
|
const collection = await this.getCollection(storage.TABLE_EXPERIMENT_RESULTS);
|
|
3721
|
-
|
|
3779
|
+
const deleteQuery = { experimentId };
|
|
3780
|
+
applyTenancyFilter(deleteQuery, filters);
|
|
3781
|
+
await collection.deleteMany(deleteQuery);
|
|
3722
3782
|
} catch (error$1) {
|
|
3723
3783
|
throw new error.MastraError(
|
|
3724
3784
|
{
|
|
@@ -4880,11 +4940,6 @@ var MongoDBMCPServersStorage = class _MongoDBMCPServersStorage extends storage.M
|
|
|
4880
4940
|
return result;
|
|
4881
4941
|
}
|
|
4882
4942
|
};
|
|
4883
|
-
function formatDateForMongoDB(date) {
|
|
4884
|
-
return typeof date === "string" ? new Date(date) : date;
|
|
4885
|
-
}
|
|
4886
|
-
|
|
4887
|
-
// src/storage/domains/memory/index.ts
|
|
4888
4943
|
var OM_TABLE = "mastra_observational_memory";
|
|
4889
4944
|
var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends storage.MemoryStorage {
|
|
4890
4945
|
supportsObservationalMemory = true;
|
|
@@ -9269,6 +9324,14 @@ function transformScoreRow(row) {
|
|
|
9269
9324
|
convertTimestamps: true
|
|
9270
9325
|
});
|
|
9271
9326
|
}
|
|
9327
|
+
function applyTenancyFilters(query, filters) {
|
|
9328
|
+
if (filters?.organizationId !== void 0) {
|
|
9329
|
+
query.organizationId = filters.organizationId;
|
|
9330
|
+
}
|
|
9331
|
+
if (filters?.projectId !== void 0) {
|
|
9332
|
+
query.projectId = filters.projectId;
|
|
9333
|
+
}
|
|
9334
|
+
}
|
|
9272
9335
|
var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends storage.ScoresStorage {
|
|
9273
9336
|
#connector;
|
|
9274
9337
|
#skipDefaultIndexes;
|
|
@@ -9437,7 +9500,8 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends storage.ScoresSto
|
|
|
9437
9500
|
pagination,
|
|
9438
9501
|
entityId,
|
|
9439
9502
|
entityType,
|
|
9440
|
-
source
|
|
9503
|
+
source,
|
|
9504
|
+
filters
|
|
9441
9505
|
}) {
|
|
9442
9506
|
try {
|
|
9443
9507
|
const { page, perPage: perPageInput } = pagination;
|
|
@@ -9453,6 +9517,7 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends storage.ScoresSto
|
|
|
9453
9517
|
if (source) {
|
|
9454
9518
|
query.source = source;
|
|
9455
9519
|
}
|
|
9520
|
+
applyTenancyFilters(query, filters);
|
|
9456
9521
|
const collection = await this.getCollection(storage.TABLE_SCORERS);
|
|
9457
9522
|
const total = await collection.countDocuments(query);
|
|
9458
9523
|
if (total === 0) {
|
|
@@ -9496,14 +9561,17 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends storage.ScoresSto
|
|
|
9496
9561
|
}
|
|
9497
9562
|
async listScoresByRunId({
|
|
9498
9563
|
runId,
|
|
9499
|
-
pagination
|
|
9564
|
+
pagination,
|
|
9565
|
+
filters
|
|
9500
9566
|
}) {
|
|
9501
9567
|
try {
|
|
9502
9568
|
const { page, perPage: perPageInput } = pagination;
|
|
9503
9569
|
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
9504
9570
|
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
9571
|
+
const query = { runId };
|
|
9572
|
+
applyTenancyFilters(query, filters);
|
|
9505
9573
|
const collection = await this.getCollection(storage.TABLE_SCORERS);
|
|
9506
|
-
const total = await collection.countDocuments(
|
|
9574
|
+
const total = await collection.countDocuments(query);
|
|
9507
9575
|
if (total === 0) {
|
|
9508
9576
|
return {
|
|
9509
9577
|
scores: [],
|
|
@@ -9516,7 +9584,7 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends storage.ScoresSto
|
|
|
9516
9584
|
};
|
|
9517
9585
|
}
|
|
9518
9586
|
const end = perPageInput === false ? total : start + perPage;
|
|
9519
|
-
let cursor = collection.find(
|
|
9587
|
+
let cursor = collection.find(query).sort({ createdAt: -1 }).skip(start);
|
|
9520
9588
|
if (perPageInput !== false) {
|
|
9521
9589
|
cursor = cursor.limit(perPage);
|
|
9522
9590
|
}
|
|
@@ -9546,14 +9614,17 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends storage.ScoresSto
|
|
|
9546
9614
|
async listScoresByEntityId({
|
|
9547
9615
|
entityId,
|
|
9548
9616
|
entityType,
|
|
9549
|
-
pagination
|
|
9617
|
+
pagination,
|
|
9618
|
+
filters
|
|
9550
9619
|
}) {
|
|
9551
9620
|
try {
|
|
9552
9621
|
const { page, perPage: perPageInput } = pagination;
|
|
9553
9622
|
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
9554
9623
|
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
9624
|
+
const query = { entityId, entityType };
|
|
9625
|
+
applyTenancyFilters(query, filters);
|
|
9555
9626
|
const collection = await this.getCollection(storage.TABLE_SCORERS);
|
|
9556
|
-
const total = await collection.countDocuments(
|
|
9627
|
+
const total = await collection.countDocuments(query);
|
|
9557
9628
|
if (total === 0) {
|
|
9558
9629
|
return {
|
|
9559
9630
|
scores: [],
|
|
@@ -9566,7 +9637,7 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends storage.ScoresSto
|
|
|
9566
9637
|
};
|
|
9567
9638
|
}
|
|
9568
9639
|
const end = perPageInput === false ? total : start + perPage;
|
|
9569
|
-
let cursor = collection.find(
|
|
9640
|
+
let cursor = collection.find(query).sort({ createdAt: -1 }).skip(start);
|
|
9570
9641
|
if (perPageInput !== false) {
|
|
9571
9642
|
cursor = cursor.limit(perPage);
|
|
9572
9643
|
}
|
|
@@ -9596,13 +9667,15 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends storage.ScoresSto
|
|
|
9596
9667
|
async listScoresBySpan({
|
|
9597
9668
|
traceId,
|
|
9598
9669
|
spanId,
|
|
9599
|
-
pagination
|
|
9670
|
+
pagination,
|
|
9671
|
+
filters
|
|
9600
9672
|
}) {
|
|
9601
9673
|
try {
|
|
9602
9674
|
const { page, perPage: perPageInput } = pagination;
|
|
9603
9675
|
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
9604
9676
|
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
9605
9677
|
const query = { traceId, spanId };
|
|
9678
|
+
applyTenancyFilters(query, filters);
|
|
9606
9679
|
const collection = await this.getCollection(storage.TABLE_SCORERS);
|
|
9607
9680
|
const total = await collection.countDocuments(query);
|
|
9608
9681
|
if (total === 0) {
|