@mastra/core
Version:
124 lines (123 loc) • 4.38 kB
JavaScript
import { t as MastraBase } from "./base-BeUQ6mLP.js";
//#region src/storage/domains/favorites/base.ts
/**
* Abstract base class for favorites storage.
*
* The favorites domain is responsible for:
* - persisting `(userId, entityType, entityId)` favorite rows,
* - maintaining the denormalized `favoriteCount` on the parent entity record,
* - answering batched lookups for list-response annotation.
*
* EE feature gating is the server-handler concern, not the storage domain.
*/
var FavoritesStorage = class extends MastraBase {
constructor() {
super({
component: "STORAGE",
name: "FAVORITES"
});
}
};
//#endregion
//#region src/storage/domains/favorites/inmemory.ts
/**
* Build the composite key used by the in-memory favorites Map.
*/
function favoriteKey(userId, entityType, entityId) {
return `${userId}\u0000${entityType}\u0000${entityId}`;
}
/**
* In-memory implementation of FavoritesStorage. Mutates the shared InMemoryDB
* Maps for favorites and the parent entity records (agents, skills) so that the
* denormalized `favoriteCount` stays in sync.
*
* Atomicity is provided by the JavaScript single-threaded event loop: each
* favorite/unfavorite runs to completion within one synchronous block.
*/
var InMemoryFavoritesStorage = class extends FavoritesStorage {
db;
constructor({ db }) {
super();
this.db = db;
}
async init() {}
async dangerouslyClearAll() {
this.db.favorites.clear();
for (const agent of this.db.agents.values()) if (agent.favoriteCount) agent.favoriteCount = 0;
for (const skill of this.db.skills.values()) if (skill.favoriteCount) skill.favoriteCount = 0;
}
async favorite({ userId, entityType, entityId }) {
const entity = this.requireEntity(entityType, entityId);
const key = favoriteKey(userId, entityType, entityId);
if (this.db.favorites.has(key)) return {
favorited: true,
favoriteCount: entity.favoriteCount ?? 0
};
const row = {
userId,
entityType,
entityId,
createdAt: /* @__PURE__ */ new Date()
};
this.db.favorites.set(key, row);
const nextCount = (entity.favoriteCount ?? 0) + 1;
entity.favoriteCount = nextCount;
entity.updatedAt = /* @__PURE__ */ new Date();
return {
favorited: true,
favoriteCount: nextCount
};
}
async unfavorite({ userId, entityType, entityId }) {
const entity = this.requireEntity(entityType, entityId);
const key = favoriteKey(userId, entityType, entityId);
if (!this.db.favorites.has(key)) return {
favorited: false,
favoriteCount: entity.favoriteCount ?? 0
};
this.db.favorites.delete(key);
const nextCount = Math.max(0, (entity.favoriteCount ?? 0) - 1);
entity.favoriteCount = nextCount;
entity.updatedAt = /* @__PURE__ */ new Date();
return {
favorited: false,
favoriteCount: nextCount
};
}
async isFavorited({ userId, entityType, entityId }) {
return this.db.favorites.has(favoriteKey(userId, entityType, entityId));
}
async isFavoritedBatch({ userId, entityType, entityIds }) {
const result = /* @__PURE__ */ new Set();
for (const entityId of entityIds) if (this.db.favorites.has(favoriteKey(userId, entityType, entityId))) result.add(entityId);
return result;
}
async listFavoritedIds({ userId, entityType }) {
const ids = [];
for (const row of this.db.favorites.values()) if (row.userId === userId && row.entityType === entityType) ids.push(row.entityId);
return ids;
}
async deleteFavoritesForEntity({ entityType, entityId }) {
let removed = 0;
for (const [key, row] of this.db.favorites) if (row.entityType === entityType && row.entityId === entityId) {
this.db.favorites.delete(key);
removed++;
}
const entity = (entityType === "agent" ? this.db.agents : this.db.skills).get(entityId);
if (entity && entity.favoriteCount) entity.favoriteCount = 0;
return removed;
}
/**
* Look up the parent entity record for counter maintenance. Throws if the
* entity does not exist — callers should validate existence (and access)
* before invoking favorite/unfavorite.
*/
requireEntity(entityType, entityId) {
const entity = (entityType === "agent" ? this.db.agents : this.db.skills).get(entityId);
if (!entity) throw new Error(`Cannot favorite: ${entityType} with id ${entityId} does not exist`);
return entity;
}
};
//#endregion
export { FavoritesStorage as n, InMemoryFavoritesStorage as t };
//# sourceMappingURL=inmemory-BRKxS_86.js.map