@mastra/pg 1.15.1 → 1.16.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
2
- import { BRANCH_SPAN_TYPES, createVectorErrorId, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, TABLE_SCHEMAS, createStorageErrorId, normalizePerPage, calculatePagination, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS, BlobStore, TABLE_SKILL_BLOBS, ChannelsStorage, TABLE_CHANNEL_INSTALLATIONS, TABLE_CHANNEL_CONFIG, DatasetsStorage, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, DATASETS_SCHEMA, TABLE_CONFIGS, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, ensureDate, safelyParseJSON, ExperimentsStorage, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, FavoritesStorage, TABLE_FAVORITES, MCPClientsStorage, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, MCPServersStorage, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, MemoryStorage, TABLE_THREADS, TABLE_RESOURCES, TABLE_MESSAGES, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, NotificationsStorage, TABLE_NOTIFICATIONS, ObservabilityStorage, TABLE_SPANS, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, SchedulesStorage, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, ScorerDefinitionsStorage, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, ScoresStorage, TABLE_SCORERS, SkillsStorage, TABLE_SKILLS, TABLE_SKILL_VERSIONS, ToolProviderConnectionsStorage, TABLE_TOOL_PROVIDER_CONNECTIONS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, mergeWorkflowStepResult, WorkspacesStorage, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, MastraCompositeStore, TraceStatus, getDefaultValue, parseDuration, listBranchesArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listFeedbackArgsSchema, normalizeScheduleTarget, transformScoreRow as transformScoreRow$1, getSqlType, EntityType, METRIC_DISTINCT_COLUMNS } from '@mastra/core/storage';
2
+ import { BRANCH_SPAN_TYPES, createVectorErrorId, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, TABLE_SCHEMAS, createStorageErrorId, normalizePerPage, calculatePagination, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS, BlobStore, TABLE_SKILL_BLOBS, ChannelsStorage, TABLE_CHANNEL_INSTALLATIONS, TABLE_CHANNEL_CONFIG, DatasetsStorage, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, DATASETS_SCHEMA, TABLE_CONFIGS, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, ensureDate, safelyParseJSON, hasErrorCode, ExperimentsStorage, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, FavoritesStorage, TABLE_FAVORITES, MCPClientsStorage, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, MCPServersStorage, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, MemoryStorage, TABLE_THREADS, TABLE_RESOURCES, TABLE_MESSAGES, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, NotificationsStorage, TABLE_NOTIFICATIONS, ObservabilityStorage, TABLE_SPANS, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, SchedulesStorage, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, ScorerDefinitionsStorage, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, ScoresStorage, TABLE_SCORERS, SkillsStorage, TABLE_SKILLS, TABLE_SKILL_VERSIONS, ToolProviderConnectionsStorage, TABLE_TOOL_PROVIDER_CONNECTIONS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, mergeWorkflowStepResult, WorkspacesStorage, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, MastraCompositeStore, TraceStatus, getDefaultValue, parseDuration, listBranchesArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listFeedbackArgsSchema, normalizeScheduleTarget, transformScoreRow as transformScoreRow$1, getSqlType, EntityType, METRIC_DISTINCT_COLUMNS } from '@mastra/core/storage';
3
3
  import { parseSqlIdentifier, parseFieldKey } from '@mastra/core/utils';
4
4
  import { MastraVector, validateTopK, validateUpsertInput } from '@mastra/core/vector';
5
5
  import { Mutex } from 'async-mutex';
@@ -5428,6 +5428,7 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
5428
5428
  await this.#addColumnIfNotExists(TABLE_DATASET_ITEMS, "organizationId", "TEXT");
5429
5429
  await this.#addColumnIfNotExists(TABLE_DATASET_ITEMS, "projectId", "TEXT");
5430
5430
  await this.#addColumnIfNotExists(TABLE_DATASET_ITEMS, "toolMocks", "JSONB");
5431
+ await this.#addColumnIfNotExists(TABLE_DATASET_ITEMS, "externalId", "TEXT");
5431
5432
  await this.createDefaultIndexes();
5432
5433
  await this.createCustomIndexes();
5433
5434
  }
@@ -5446,6 +5447,11 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
5446
5447
  table: TABLE_DATASET_ITEMS,
5447
5448
  columns: ["datasetId", "datasetVersion"]
5448
5449
  },
5450
+ {
5451
+ name: "idx_dataset_items_external_id_history",
5452
+ table: TABLE_DATASET_ITEMS,
5453
+ columns: ["datasetId", "externalId", "datasetVersion"]
5454
+ },
5449
5455
  {
5450
5456
  name: "idx_dataset_items_dataset_validto_deleted",
5451
5457
  table: TABLE_DATASET_ITEMS,
@@ -5528,6 +5534,7 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
5528
5534
  id: row.id,
5529
5535
  datasetId: row.datasetId,
5530
5536
  datasetVersion: row.datasetVersion,
5537
+ externalId: row.externalId ?? null,
5531
5538
  organizationId: row.organizationId ?? null,
5532
5539
  projectId: row.projectId ?? null,
5533
5540
  input: safelyParseJSON(row.input),
@@ -5546,6 +5553,7 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
5546
5553
  id: row.id,
5547
5554
  datasetId: row.datasetId,
5548
5555
  datasetVersion: row.datasetVersion,
5556
+ externalId: row.externalId ?? null,
5549
5557
  organizationId: row.organizationId ?? null,
5550
5558
  projectId: row.projectId ?? null,
5551
5559
  validTo: row.validTo,
@@ -5572,7 +5580,8 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
5572
5580
  // --- Dataset CRUD ---
5573
5581
  async createDataset(input) {
5574
5582
  try {
5575
- const id = crypto.randomUUID();
5583
+ const id = input.id ?? crypto.randomUUID();
5584
+ if (input.id !== void 0) this.validateCallerDefinedDatasetId(input.id);
5576
5585
  const now = /* @__PURE__ */ new Date();
5577
5586
  const nowIso = now.toISOString();
5578
5587
  await this.#db.insert({
@@ -5617,6 +5626,11 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
5617
5626
  updatedAt: now
5618
5627
  };
5619
5628
  } catch (error) {
5629
+ if (input.id !== void 0 && hasErrorCode(error, /* @__PURE__ */ new Set(["23505"]))) {
5630
+ const existing = await this.getDatasetById({ id: input.id });
5631
+ if (existing) return this.resolveExistingDataset(existing, { ...input, id: input.id });
5632
+ }
5633
+ if (error instanceof MastraError) throw error;
5620
5634
  throw new MastraError(
5621
5635
  {
5622
5636
  id: createStorageErrorId("PG", "CREATE_DATASET", "FAILED"),
@@ -5889,11 +5903,12 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
5889
5903
  parentOrganizationId = row.organizationId ?? null;
5890
5904
  parentProjectId = row.projectId ?? null;
5891
5905
  await t.none(
5892
- `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,NULL,false,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16)`,
5906
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`,
5893
5907
  [
5894
5908
  id,
5895
5909
  args.datasetId,
5896
5910
  newVersion,
5911
+ args.externalId ?? null,
5897
5912
  parentOrganizationId,
5898
5913
  parentProjectId,
5899
5914
  JSON.stringify(args.input),
@@ -5993,11 +6008,12 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
5993
6008
  [newVersion, args.id]
5994
6009
  );
5995
6010
  await t.none(
5996
- `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,NULL,false,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16)`,
6011
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`,
5997
6012
  [
5998
6013
  args.id,
5999
6014
  args.datasetId,
6000
6015
  newVersion,
6016
+ existing.externalId ?? null,
6001
6017
  parentOrganizationId,
6002
6018
  parentProjectId,
6003
6019
  JSON.stringify(mergedInput),
@@ -6077,11 +6093,12 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
6077
6093
  [newVersion, id]
6078
6094
  );
6079
6095
  await t.none(
6080
- `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,NULL,true,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16)`,
6096
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,true,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`,
6081
6097
  [
6082
6098
  id,
6083
6099
  datasetId,
6084
6100
  newVersion,
6101
+ existing.externalId ?? null,
6085
6102
  parentOrganizationId,
6086
6103
  parentProjectId,
6087
6104
  JSON.stringify(existing.input),
@@ -6116,78 +6133,93 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
6116
6133
  }
6117
6134
  async _doBatchInsertItems(input) {
6118
6135
  try {
6119
- const dataset = await this.getDatasetById({ id: input.datasetId });
6120
- if (!dataset) {
6121
- throw new MastraError({
6122
- id: createStorageErrorId("PG", "BULK_ADD_ITEMS", "DATASET_NOT_FOUND"),
6123
- domain: ErrorDomain.STORAGE,
6124
- category: ErrorCategory.USER,
6125
- details: { datasetId: input.datasetId }
6126
- });
6127
- }
6136
+ if (input.items.length === 0) return [];
6128
6137
  const datasetsTable = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
6129
6138
  const itemsTable = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
6130
6139
  const versionsTable = getTableName2({
6131
6140
  indexName: TABLE_DATASET_VERSIONS,
6132
6141
  schemaName: getSchemaName2(this.#schema)
6133
6142
  });
6134
- const now = /* @__PURE__ */ new Date();
6135
- const nowIso = now.toISOString();
6136
- const versionId = crypto.randomUUID();
6137
- const itemsWithIds = input.items.map((itemInput) => ({ id: crypto.randomUUID(), input: itemInput }));
6138
- const parentOrganizationId = dataset.organizationId ?? null;
6139
- const parentProjectId = dataset.projectId ?? null;
6140
- let newVersion;
6143
+ let results = [];
6141
6144
  await this.#db.client.tx(async (t) => {
6142
- const row = await t.one(
6143
- `UPDATE ${datasetsTable} SET "version" = "version" + 1 WHERE "id" = $1 RETURNING "version"`,
6145
+ const dataset = await t.oneOrNone(
6146
+ `SELECT "version", "organizationId", "projectId" FROM ${datasetsTable} WHERE "id" = $1 FOR UPDATE`,
6144
6147
  [input.datasetId]
6145
6148
  );
6146
- newVersion = row.version;
6147
- for (const { id, input: itemInput } of itemsWithIds) {
6148
- await t.none(
6149
- `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,NULL,false,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16)`,
6150
- [
6149
+ if (!dataset)
6150
+ throw new MastraError({
6151
+ id: createStorageErrorId("PG", "BULK_ADD_ITEMS", "DATASET_NOT_FOUND"),
6152
+ domain: ErrorDomain.STORAGE,
6153
+ category: ErrorCategory.USER,
6154
+ details: { datasetId: input.datasetId }
6155
+ });
6156
+ const externalIds = [...new Set(input.items.flatMap((item) => item.externalId ? [item.externalId] : []))];
6157
+ const historyRows = externalIds.length ? await t.manyOrNone(
6158
+ `SELECT * FROM ${itemsTable} WHERE "datasetId" = $1 AND "externalId" = ANY($2::text[]) ORDER BY "datasetVersion"`,
6159
+ [input.datasetId, externalIds]
6160
+ ) : [];
6161
+ const plan = this.planDatasetItemBatch(
6162
+ input.items,
6163
+ historyRows.map((row) => this.transformItemRowFull(row)),
6164
+ () => crypto.randomUUID()
6165
+ );
6166
+ const resolved = new Map(
6167
+ [...plan.existingCurrentItems].map(([id, row]) => [id, this.datasetItemFromRow(row)])
6168
+ );
6169
+ if (plan.inserts.length > 0) {
6170
+ const newVersion = Number(dataset.version) + 1;
6171
+ const now = /* @__PURE__ */ new Date();
6172
+ const nowIso = now.toISOString();
6173
+ await t.none(`UPDATE ${datasetsTable} SET "version" = $2 WHERE "id" = $1`, [input.datasetId, newVersion]);
6174
+ for (const { id, item } of plan.inserts) {
6175
+ await t.none(
6176
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`,
6177
+ [
6178
+ id,
6179
+ input.datasetId,
6180
+ newVersion,
6181
+ item.externalId ?? null,
6182
+ dataset.organizationId ?? null,
6183
+ dataset.projectId ?? null,
6184
+ JSON.stringify(item.input),
6185
+ jsonbArg(item.groundTruth),
6186
+ jsonbArg(item.expectedTrajectory),
6187
+ jsonbArg(item.toolMocks),
6188
+ jsonbArg(item.requestContext),
6189
+ jsonbArg(item.metadata),
6190
+ jsonbArg(item.source),
6191
+ nowIso,
6192
+ nowIso,
6193
+ nowIso,
6194
+ nowIso
6195
+ ]
6196
+ );
6197
+ resolved.set(id, {
6151
6198
  id,
6152
- input.datasetId,
6153
- newVersion,
6154
- parentOrganizationId,
6155
- parentProjectId,
6156
- JSON.stringify(itemInput.input),
6157
- jsonbArg(itemInput.groundTruth),
6158
- jsonbArg(itemInput.expectedTrajectory),
6159
- jsonbArg(itemInput.toolMocks),
6160
- jsonbArg(itemInput.requestContext),
6161
- jsonbArg(itemInput.metadata),
6162
- jsonbArg(itemInput.source),
6163
- nowIso,
6164
- nowIso,
6165
- nowIso,
6166
- nowIso
6167
- ]
6199
+ datasetId: input.datasetId,
6200
+ datasetVersion: newVersion,
6201
+ externalId: item.externalId ?? null,
6202
+ organizationId: dataset.organizationId ?? null,
6203
+ projectId: dataset.projectId ?? null,
6204
+ input: item.input,
6205
+ groundTruth: item.groundTruth,
6206
+ expectedTrajectory: item.expectedTrajectory,
6207
+ toolMocks: item.toolMocks,
6208
+ requestContext: item.requestContext,
6209
+ metadata: item.metadata,
6210
+ source: item.source,
6211
+ createdAt: now,
6212
+ updatedAt: now
6213
+ });
6214
+ }
6215
+ await t.none(
6216
+ `INSERT INTO ${versionsTable} ("id","datasetId","version","createdAt","createdAtZ") VALUES ($1,$2,$3,$4,$5)`,
6217
+ [crypto.randomUUID(), input.datasetId, newVersion, nowIso, nowIso]
6168
6218
  );
6169
6219
  }
6170
- await t.none(
6171
- `INSERT INTO ${versionsTable} ("id","datasetId","version","createdAt","createdAtZ") VALUES ($1,$2,$3,$4,$5)`,
6172
- [versionId, input.datasetId, newVersion, nowIso, nowIso]
6173
- );
6220
+ results = plan.resolvedIds.map((id) => resolved.get(id));
6174
6221
  });
6175
- return itemsWithIds.map(({ id, input: itemInput }) => ({
6176
- id,
6177
- datasetId: input.datasetId,
6178
- datasetVersion: newVersion,
6179
- organizationId: parentOrganizationId,
6180
- projectId: parentProjectId,
6181
- input: itemInput.input,
6182
- groundTruth: itemInput.groundTruth,
6183
- expectedTrajectory: itemInput.expectedTrajectory,
6184
- toolMocks: itemInput.toolMocks,
6185
- requestContext: itemInput.requestContext,
6186
- metadata: itemInput.metadata,
6187
- source: itemInput.source,
6188
- createdAt: now,
6189
- updatedAt: now
6190
- }));
6222
+ return results;
6191
6223
  } catch (error) {
6192
6224
  if (error instanceof MastraError) throw error;
6193
6225
  throw new MastraError(
@@ -6241,11 +6273,12 @@ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
6241
6273
  [newVersion, item.id]
6242
6274
  );
6243
6275
  await t.none(
6244
- `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,NULL,true,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16)`,
6276
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,true,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`,
6245
6277
  [
6246
6278
  item.id,
6247
6279
  input.datasetId,
6248
6280
  newVersion,
6281
+ item.externalId ?? null,
6249
6282
  parentOrganizationId,
6250
6283
  parentProjectId,
6251
6284
  JSON.stringify(item.input),