@mastra/spanner 1.2.1-alpha.0 → 1.2.1

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/dist/index.js CHANGED
@@ -2967,6 +2967,10 @@ function rowToDataset(row) {
2967
2967
  targetIds: t.targetIds ?? null,
2968
2968
  scorerIds: t.scorerIds ?? null,
2969
2969
  version: Number(t.version ?? 0),
2970
+ organizationId: t.organizationId ?? null,
2971
+ projectId: t.projectId ?? null,
2972
+ candidateKey: t.candidateKey ?? null,
2973
+ candidateId: t.candidateId ?? null,
2970
2974
  createdAt: toDate(t.createdAt),
2971
2975
  updatedAt: toDate(t.updatedAt)
2972
2976
  };
@@ -2977,6 +2981,8 @@ function rowToItem(row) {
2977
2981
  id: String(t.id),
2978
2982
  datasetId: String(t.datasetId),
2979
2983
  datasetVersion: Number(t.datasetVersion),
2984
+ organizationId: t.organizationId ?? null,
2985
+ projectId: t.projectId ?? null,
2980
2986
  input: t.input,
2981
2987
  groundTruth: t.groundTruth ?? void 0,
2982
2988
  expectedTrajectory: t.expectedTrajectory ?? void 0,
@@ -3023,6 +3029,16 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3023
3029
  await this.db.createTable({ tableName: TABLE_DATASETS, schema: TABLE_SCHEMAS[TABLE_DATASETS] });
3024
3030
  await this.db.createTable({ tableName: TABLE_DATASET_ITEMS, schema: TABLE_SCHEMAS[TABLE_DATASET_ITEMS] });
3025
3031
  await this.db.createTable({ tableName: TABLE_DATASET_VERSIONS, schema: TABLE_SCHEMAS[TABLE_DATASET_VERSIONS] });
3032
+ await this.db.alterTable({
3033
+ tableName: TABLE_DATASETS,
3034
+ schema: TABLE_SCHEMAS[TABLE_DATASETS],
3035
+ ifNotExists: ["organizationId", "projectId", "candidateKey", "candidateId"]
3036
+ });
3037
+ await this.db.alterTable({
3038
+ tableName: TABLE_DATASET_ITEMS,
3039
+ schema: TABLE_SCHEMAS[TABLE_DATASET_ITEMS],
3040
+ ifNotExists: ["organizationId", "projectId"]
3041
+ });
3026
3042
  await this.createDefaultIndexes();
3027
3043
  await this.createCustomIndexes();
3028
3044
  }
@@ -3083,6 +3099,10 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3083
3099
  targetIds: input.targetIds ?? null,
3084
3100
  scorerIds: input.scorerIds ?? null,
3085
3101
  version: 0,
3102
+ organizationId: input.organizationId ?? null,
3103
+ projectId: input.projectId ?? null,
3104
+ candidateKey: input.candidateKey ?? null,
3105
+ candidateId: input.candidateId ?? null,
3086
3106
  createdAt: now,
3087
3107
  updatedAt: now
3088
3108
  };
@@ -3101,6 +3121,10 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3101
3121
  targetIds: record.targetIds,
3102
3122
  scorerIds: record.scorerIds,
3103
3123
  version: 0,
3124
+ organizationId: record.organizationId,
3125
+ projectId: record.projectId,
3126
+ candidateKey: record.candidateKey,
3127
+ candidateId: record.candidateId,
3104
3128
  createdAt: now,
3105
3129
  updatedAt: now
3106
3130
  }
@@ -3230,8 +3254,28 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3230
3254
  const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
3231
3255
  try {
3232
3256
  const tableName = quoteIdent(TABLE_DATASETS, "table name");
3257
+ const filterConditions = [];
3258
+ const filterParams = {};
3259
+ if (args.filters?.organizationId !== void 0) {
3260
+ filterConditions.push(`${quoteIdent("organizationId", "column name")} = @organizationId`);
3261
+ filterParams.organizationId = args.filters.organizationId;
3262
+ }
3263
+ if (args.filters?.projectId !== void 0) {
3264
+ filterConditions.push(`${quoteIdent("projectId", "column name")} = @projectId`);
3265
+ filterParams.projectId = args.filters.projectId;
3266
+ }
3267
+ if (args.filters?.candidateKey !== void 0) {
3268
+ filterConditions.push(`${quoteIdent("candidateKey", "column name")} = @candidateKey`);
3269
+ filterParams.candidateKey = args.filters.candidateKey;
3270
+ }
3271
+ if (args.filters?.candidateId !== void 0) {
3272
+ filterConditions.push(`${quoteIdent("candidateId", "column name")} = @candidateId`);
3273
+ filterParams.candidateId = args.filters.candidateId;
3274
+ }
3275
+ const whereClause = filterConditions.length > 0 ? `WHERE ${filterConditions.join(" AND ")}` : "";
3233
3276
  const [countRows] = await this.database.run({
3234
- sql: `SELECT COUNT(*) AS count FROM ${tableName}`,
3277
+ sql: `SELECT COUNT(*) AS count FROM ${tableName} ${whereClause}`,
3278
+ params: filterParams,
3235
3279
  json: true
3236
3280
  });
3237
3281
  const total = Number(countRows[0]?.count ?? 0);
@@ -3240,10 +3284,10 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3240
3284
  }
3241
3285
  const limit = perPageInput === false ? total : perPage;
3242
3286
  const [rows] = await this.database.run({
3243
- sql: `SELECT * FROM ${tableName}
3287
+ sql: `SELECT * FROM ${tableName} ${whereClause}
3244
3288
  ORDER BY ${quoteIdent("createdAt", "column name")} DESC, ${quoteIdent("id", "column name")} ASC
3245
3289
  LIMIT @limit OFFSET @offset`,
3246
- params: { limit, offset },
3290
+ params: { ...filterParams, limit, offset },
3247
3291
  json: true
3248
3292
  });
3249
3293
  const datasets = rows.map(rowToDataset);
@@ -3270,10 +3314,13 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3270
3314
  // ==========================================================================
3271
3315
  // SCD-2 helpers
3272
3316
  // ==========================================================================
3273
- /** Reads and increments the dataset version inside `tx`; throws if missing. */
3317
+ /** Reads and increments the dataset version inside `tx`; throws if missing. Also returns parent tenancy. */
3274
3318
  async bumpVersion(tx, datasetId, now) {
3275
3319
  const [rows] = await tx.run({
3276
- sql: `SELECT ${quoteIdent("version", "column name")} AS version FROM ${quoteIdent(TABLE_DATASETS, "table name")}
3320
+ sql: `SELECT ${quoteIdent("version", "column name")} AS version,
3321
+ ${quoteIdent("organizationId", "column name")} AS organizationId,
3322
+ ${quoteIdent("projectId", "column name")} AS projectId
3323
+ FROM ${quoteIdent(TABLE_DATASETS, "table name")}
3277
3324
  WHERE ${quoteIdent("id", "column name")} = @id LIMIT 1`,
3278
3325
  params: { id: datasetId },
3279
3326
  json: true
@@ -3297,7 +3344,7 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3297
3344
  params: { newVersion, now: now.toISOString(), id: datasetId },
3298
3345
  types: { now: "timestamp" }
3299
3346
  });
3300
- return newVersion;
3347
+ return { version: newVersion, organizationId: row.organizationId ?? null, projectId: row.projectId ?? null };
3301
3348
  }
3302
3349
  /** Inserts a dataset version snapshot row inside `tx`. */
3303
3350
  async insertVersionRow(tx, datasetId, version, now) {
@@ -3342,13 +3389,15 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3342
3389
  await this.db.runWithAbortRetry(
3343
3390
  () => this.database.runTransactionAsync(async (tx) => {
3344
3391
  try {
3345
- const newVersion = await this.bumpVersion(tx, args.datasetId, now);
3392
+ const { version: newVersion, organizationId, projectId } = await this.bumpVersion(tx, args.datasetId, now);
3346
3393
  await this.db.insert({
3347
3394
  tableName: TABLE_DATASET_ITEMS,
3348
3395
  record: {
3349
3396
  id: itemId,
3350
3397
  datasetId: args.datasetId,
3351
3398
  datasetVersion: newVersion,
3399
+ organizationId,
3400
+ projectId,
3352
3401
  validTo: null,
3353
3402
  isDeleted: false,
3354
3403
  input: args.input,
@@ -3369,6 +3418,8 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3369
3418
  id: itemId,
3370
3419
  datasetId: args.datasetId,
3371
3420
  datasetVersion: newVersion,
3421
+ organizationId,
3422
+ projectId,
3372
3423
  input: args.input,
3373
3424
  groundTruth: args.groundTruth,
3374
3425
  expectedTrajectory: args.expectedTrajectory,
@@ -3435,7 +3486,7 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3435
3486
  await this.db.runWithAbortRetry(
3436
3487
  () => this.database.runTransactionAsync(async (tx) => {
3437
3488
  try {
3438
- const newVersion = await this.bumpVersion(tx, args.datasetId, now);
3489
+ const { version: newVersion, organizationId, projectId } = await this.bumpVersion(tx, args.datasetId, now);
3439
3490
  await this.closeCurrentRow(tx, args.id, newVersion);
3440
3491
  await this.db.insert({
3441
3492
  tableName: TABLE_DATASET_ITEMS,
@@ -3443,6 +3494,8 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3443
3494
  id: args.id,
3444
3495
  datasetId: args.datasetId,
3445
3496
  datasetVersion: newVersion,
3497
+ organizationId,
3498
+ projectId,
3446
3499
  validTo: null,
3447
3500
  isDeleted: false,
3448
3501
  input: merged.input,
@@ -3463,6 +3516,8 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3463
3516
  id: args.id,
3464
3517
  datasetId: args.datasetId,
3465
3518
  datasetVersion: newVersion,
3519
+ organizationId,
3520
+ projectId,
3466
3521
  input: merged.input,
3467
3522
  groundTruth: merged.groundTruth,
3468
3523
  expectedTrajectory: merged.expectedTrajectory,
@@ -3511,7 +3566,7 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3511
3566
  await this.db.runWithAbortRetry(
3512
3567
  () => this.database.runTransactionAsync(async (tx) => {
3513
3568
  try {
3514
- const newVersion = await this.bumpVersion(tx, args.datasetId, now);
3569
+ const { version: newVersion, organizationId, projectId } = await this.bumpVersion(tx, args.datasetId, now);
3515
3570
  await this.closeCurrentRow(tx, args.id, newVersion);
3516
3571
  await this.db.insert({
3517
3572
  tableName: TABLE_DATASET_ITEMS,
@@ -3519,6 +3574,8 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3519
3574
  id: args.id,
3520
3575
  datasetId: args.datasetId,
3521
3576
  datasetVersion: newVersion,
3577
+ organizationId,
3578
+ projectId,
3522
3579
  validTo: null,
3523
3580
  isDeleted: true,
3524
3581
  input: existing.input,
@@ -3562,6 +3619,14 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3562
3619
  try {
3563
3620
  const conditions = [`${quoteIdent("datasetId", "column name")} = @datasetId`];
3564
3621
  const params = { datasetId: args.datasetId };
3622
+ if (args.filters?.organizationId !== void 0) {
3623
+ conditions.push(`${quoteIdent("organizationId", "column name")} = @organizationId`);
3624
+ params.organizationId = args.filters.organizationId;
3625
+ }
3626
+ if (args.filters?.projectId !== void 0) {
3627
+ conditions.push(`${quoteIdent("projectId", "column name")} = @projectId`);
3628
+ params.projectId = args.filters.projectId;
3629
+ }
3565
3630
  if (args.version !== void 0) {
3566
3631
  conditions.push(`${quoteIdent("datasetVersion", "column name")} <= @version`);
3567
3632
  conditions.push(
@@ -3783,7 +3848,7 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3783
3848
  await this.db.runWithAbortRetry(
3784
3849
  () => this.database.runTransactionAsync(async (tx) => {
3785
3850
  try {
3786
- const newVersion = await this.bumpVersion(tx, input.datasetId, now);
3851
+ const { version: newVersion, organizationId, projectId } = await this.bumpVersion(tx, input.datasetId, now);
3787
3852
  for (const { id, item } of prepared) {
3788
3853
  await this.db.insert({
3789
3854
  tableName: TABLE_DATASET_ITEMS,
@@ -3791,6 +3856,8 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3791
3856
  id,
3792
3857
  datasetId: input.datasetId,
3793
3858
  datasetVersion: newVersion,
3859
+ organizationId,
3860
+ projectId,
3794
3861
  validTo: null,
3795
3862
  isDeleted: false,
3796
3863
  input: item.input,
@@ -3812,6 +3879,8 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3812
3879
  id,
3813
3880
  datasetId: input.datasetId,
3814
3881
  datasetVersion: newVersion,
3882
+ organizationId,
3883
+ projectId,
3815
3884
  input: item.input,
3816
3885
  groundTruth: item.groundTruth,
3817
3886
  expectedTrajectory: item.expectedTrajectory,
@@ -3855,7 +3924,7 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3855
3924
  await this.db.runWithAbortRetry(
3856
3925
  () => this.database.runTransactionAsync(async (tx) => {
3857
3926
  try {
3858
- const newVersion = await this.bumpVersion(tx, input.datasetId, now);
3927
+ const { version: newVersion, organizationId, projectId } = await this.bumpVersion(tx, input.datasetId, now);
3859
3928
  for (const existing of current) {
3860
3929
  await this.closeCurrentRow(tx, existing.id, newVersion);
3861
3930
  await this.db.insert({
@@ -3864,6 +3933,8 @@ var DatasetsSpanner = class _DatasetsSpanner extends DatasetsStorage {
3864
3933
  id: existing.id,
3865
3934
  datasetId: input.datasetId,
3866
3935
  datasetVersion: newVersion,
3936
+ organizationId,
3937
+ projectId,
3867
3938
  validTo: null,
3868
3939
  isDeleted: true,
3869
3940
  input: existing.input,
@@ -3914,6 +3985,8 @@ function rowToExperiment(row) {
3914
3985
  metadata: t.metadata ?? void 0,
3915
3986
  datasetId: t.datasetId ?? null,
3916
3987
  datasetVersion: t.datasetVersion == null ? null : Number(t.datasetVersion),
3988
+ organizationId: t.organizationId ?? null,
3989
+ projectId: t.projectId ?? null,
3917
3990
  targetType: t.targetType,
3918
3991
  targetId: String(t.targetId),
3919
3992
  status: t.status,
@@ -3935,6 +4008,8 @@ function rowToExperimentResult(row) {
3935
4008
  experimentId: String(t.experimentId),
3936
4009
  itemId: String(t.itemId),
3937
4010
  itemDatasetVersion: t.itemDatasetVersion == null ? null : Number(t.itemDatasetVersion),
4011
+ organizationId: t.organizationId ?? null,
4012
+ projectId: t.projectId ?? null,
3938
4013
  input: t.input ?? null,
3939
4014
  output: t.output ?? null,
3940
4015
  groundTruth: t.groundTruth ?? null,
@@ -3966,6 +4041,16 @@ var ExperimentsSpanner = class _ExperimentsSpanner extends ExperimentsStorage {
3966
4041
  async init() {
3967
4042
  await this.db.createTable({ tableName: TABLE_EXPERIMENTS, schema: TABLE_SCHEMAS[TABLE_EXPERIMENTS] });
3968
4043
  await this.db.createTable({ tableName: TABLE_EXPERIMENT_RESULTS, schema: TABLE_SCHEMAS[TABLE_EXPERIMENT_RESULTS] });
4044
+ await this.db.alterTable({
4045
+ tableName: TABLE_EXPERIMENTS,
4046
+ schema: TABLE_SCHEMAS[TABLE_EXPERIMENTS],
4047
+ ifNotExists: ["organizationId", "projectId"]
4048
+ });
4049
+ await this.db.alterTable({
4050
+ tableName: TABLE_EXPERIMENT_RESULTS,
4051
+ schema: TABLE_SCHEMAS[TABLE_EXPERIMENT_RESULTS],
4052
+ ifNotExists: ["organizationId", "projectId"]
4053
+ });
3969
4054
  await this.createDefaultIndexes();
3970
4055
  await this.createCustomIndexes();
3971
4056
  }
@@ -3987,6 +4072,17 @@ var ExperimentsSpanner = class _ExperimentsSpanner extends ExperimentsStorage {
3987
4072
  table: TABLE_EXPERIMENT_RESULTS,
3988
4073
  columns: ["experimentId", "itemId"],
3989
4074
  unique: true
4075
+ },
4076
+ // Tenancy: leading-tenant indexes for multi-tenant scans (parity with datasets domain).
4077
+ {
4078
+ name: "mastra_experiments_org_project_idx",
4079
+ table: TABLE_EXPERIMENTS,
4080
+ columns: ["organizationId", "projectId"]
4081
+ },
4082
+ {
4083
+ name: "mastra_experiment_results_org_project_idx",
4084
+ table: TABLE_EXPERIMENT_RESULTS,
4085
+ columns: ["organizationId", "projectId"]
3990
4086
  }
3991
4087
  ];
3992
4088
  }
@@ -4013,6 +4109,8 @@ var ExperimentsSpanner = class _ExperimentsSpanner extends ExperimentsStorage {
4013
4109
  metadata: input.metadata ?? void 0,
4014
4110
  datasetId: input.datasetId ?? null,
4015
4111
  datasetVersion: input.datasetVersion ?? null,
4112
+ organizationId: input.organizationId ?? null,
4113
+ projectId: input.projectId ?? null,
4016
4114
  targetType: input.targetType,
4017
4115
  targetId: input.targetId,
4018
4116
  status: "pending",
@@ -4035,6 +4133,8 @@ var ExperimentsSpanner = class _ExperimentsSpanner extends ExperimentsStorage {
4035
4133
  metadata: experiment.metadata ?? null,
4036
4134
  datasetId: experiment.datasetId,
4037
4135
  datasetVersion: experiment.datasetVersion,
4136
+ organizationId: experiment.organizationId,
4137
+ projectId: experiment.projectId,
4038
4138
  targetType: experiment.targetType,
4039
4139
  targetId: experiment.targetId,
4040
4140
  status: experiment.status,
@@ -4153,6 +4253,17 @@ var ExperimentsSpanner = class _ExperimentsSpanner extends ExperimentsStorage {
4153
4253
  conditions.push(`${quoteIdent("status", "column name")} = @status`);
4154
4254
  params.status = args.status;
4155
4255
  }
4256
+ if (args.filters) {
4257
+ const { organizationId, projectId } = args.filters;
4258
+ if (organizationId !== void 0) {
4259
+ conditions.push(`${quoteIdent("organizationId", "column name")} = @organizationId`);
4260
+ params.organizationId = organizationId;
4261
+ }
4262
+ if (projectId !== void 0) {
4263
+ conditions.push(`${quoteIdent("projectId", "column name")} = @projectId`);
4264
+ params.projectId = projectId;
4265
+ }
4266
+ }
4156
4267
  const whereSql = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
4157
4268
  const tableName = quoteIdent(TABLE_EXPERIMENTS, "table name");
4158
4269
  const [countRows] = await this.database.run({
@@ -4237,6 +4348,8 @@ var ExperimentsSpanner = class _ExperimentsSpanner extends ExperimentsStorage {
4237
4348
  experimentId: input.experimentId,
4238
4349
  itemId: input.itemId,
4239
4350
  itemDatasetVersion: input.itemDatasetVersion ?? null,
4351
+ organizationId: input.organizationId ?? null,
4352
+ projectId: input.projectId ?? null,
4240
4353
  input: input.input ?? null,
4241
4354
  output: input.output ?? null,
4242
4355
  groundTruth: input.groundTruth ?? null,
@@ -4257,6 +4370,8 @@ var ExperimentsSpanner = class _ExperimentsSpanner extends ExperimentsStorage {
4257
4370
  experimentId: result.experimentId,
4258
4371
  itemId: result.itemId,
4259
4372
  itemDatasetVersion: result.itemDatasetVersion,
4373
+ organizationId: result.organizationId,
4374
+ projectId: result.projectId,
4260
4375
  input: result.input,
4261
4376
  output: result.output,
4262
4377
  groundTruth: result.groundTruth,
@@ -4390,6 +4505,17 @@ var ExperimentsSpanner = class _ExperimentsSpanner extends ExperimentsStorage {
4390
4505
  conditions.push(`${quoteIdent("status", "column name")} = @status`);
4391
4506
  params.status = args.status;
4392
4507
  }
4508
+ if (args.filters) {
4509
+ const { organizationId, projectId } = args.filters;
4510
+ if (organizationId !== void 0) {
4511
+ conditions.push(`${quoteIdent("organizationId", "column name")} = @organizationId`);
4512
+ params.organizationId = organizationId;
4513
+ }
4514
+ if (projectId !== void 0) {
4515
+ conditions.push(`${quoteIdent("projectId", "column name")} = @projectId`);
4516
+ params.projectId = projectId;
4517
+ }
4518
+ }
4393
4519
  const whereSql = `WHERE ${conditions.join(" AND ")}`;
4394
4520
  const tableName = quoteIdent(TABLE_EXPERIMENT_RESULTS, "table name");
4395
4521
  const [countRows] = await this.database.run({