@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
1 lines • 12.8 kB
Source Map (JSON)
{"version":3,"sources":["../src/storage/domains/favorites/base.ts","../src/storage/domains/favorites/inmemory.ts"],"names":["MastraBase"],"mappings":"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","file":"chunk-RKHARY3D.cjs","sourcesContent":["import { MastraBase } from '../../../base';\nimport type {\n StorageDeleteFavoritesForEntityInput,\n StorageIsFavoritedBatchInput,\n StorageListFavoritesInput,\n StorageFavoriteEntityType,\n StorageFavoriteKey,\n} from '../../types';\n\n/**\n * Result of a favorite/unfavorite operation. `favorited` reflects the new state\n * for the caller; `favoriteCount` reflects the entity's denormalized counter\n * after the operation.\n */\nexport interface FavoriteToggleResult {\n favorited: boolean;\n favoriteCount: number;\n}\n\n/**\n * Abstract base class for favorites storage.\n *\n * The favorites domain is responsible for:\n * - persisting `(userId, entityType, entityId)` favorite rows,\n * - maintaining the denormalized `favoriteCount` on the parent entity record,\n * - answering batched lookups for list-response annotation.\n *\n * EE feature gating is the server-handler concern, not the storage domain.\n */\nexport abstract class FavoritesStorage extends MastraBase {\n constructor() {\n super({\n component: 'STORAGE',\n name: 'FAVORITES',\n });\n }\n\n /**\n * Initialize the favorites store (create tables, indexes, etc).\n */\n abstract init(): Promise<void>;\n\n /**\n * Favorite an entity for a user. Idempotent — re-favoriting an already-favorited\n * entity is a no-op and returns the current state.\n *\n * Implementations must atomically insert the favorite row and increment the\n * entity's `favoriteCount`. If the entity does not exist, throw.\n */\n abstract favorite(input: StorageFavoriteKey): Promise<FavoriteToggleResult>;\n\n /**\n * Unfavorite an entity for a user. Idempotent — unfavoriting a non-favorited\n * entity is a no-op and returns the current state.\n *\n * Implementations must atomically delete the favorite row and decrement the\n * entity's `favoriteCount` (clamped at 0). If the entity does not exist,\n * throw.\n */\n abstract unfavorite(input: StorageFavoriteKey): Promise<FavoriteToggleResult>;\n\n /**\n * Check whether a single entity is favorited by the given user.\n */\n abstract isFavorited(input: StorageFavoriteKey): Promise<boolean>;\n\n /**\n * Look up which entity IDs in a candidate set are favorited by the given user.\n * Used to annotate list responses.\n *\n * Returns a Set of favorited entity IDs. Order does not matter.\n */\n abstract isFavoritedBatch(input: StorageIsFavoritedBatchInput): Promise<Set<string>>;\n\n /**\n * List all entity IDs of the given type favorited by the user.\n * Used internally by the `?favoritedOnly=true` query handler to pre-filter\n * the candidate set for the existing list path.\n */\n abstract listFavoritedIds(input: StorageListFavoritesInput): Promise<string[]>;\n\n /**\n * Remove all favorite rows referencing the given entity. Called by\n * hard-delete handlers. Decrements no counters (the entity is being\n * removed).\n *\n * Returns the number of favorite rows removed.\n */\n abstract deleteFavoritesForEntity(input: StorageDeleteFavoritesForEntityInput): Promise<number>;\n\n /**\n * Delete all favorites. Used for testing.\n */\n abstract dangerouslyClearAll(): Promise<void>;\n}\n\nexport type { StorageFavoriteEntityType };\n","import type {\n StorageDeleteFavoritesForEntityInput,\n StorageIsFavoritedBatchInput,\n StorageListFavoritesInput,\n StorageFavoriteEntityType,\n StorageFavoriteKey,\n StorageFavoriteType,\n} from '../../types';\nimport type { InMemoryDB } from '../inmemory-db';\nimport type { FavoriteToggleResult } from './base';\nimport { FavoritesStorage } from './base';\n\n/**\n * Build the composite key used by the in-memory favorites Map.\n */\nfunction favoriteKey(userId: string, entityType: StorageFavoriteEntityType, entityId: string): string {\n return `${userId}\\u0000${entityType}\\u0000${entityId}`;\n}\n\n/**\n * In-memory implementation of FavoritesStorage. Mutates the shared InMemoryDB\n * Maps for favorites and the parent entity records (agents, skills) so that the\n * denormalized `favoriteCount` stays in sync.\n *\n * Atomicity is provided by the JavaScript single-threaded event loop: each\n * favorite/unfavorite runs to completion within one synchronous block.\n */\nexport class InMemoryFavoritesStorage extends FavoritesStorage {\n private db: InMemoryDB;\n\n constructor({ db }: { db: InMemoryDB }) {\n super();\n this.db = db;\n }\n\n async init(): Promise<void> {\n // No-op for in-memory store.\n }\n\n async dangerouslyClearAll(): Promise<void> {\n this.db.favorites.clear();\n // Keep denormalized counters in sync with the cleared favorites map.\n for (const agent of this.db.agents.values()) {\n if (agent.favoriteCount) agent.favoriteCount = 0;\n }\n for (const skill of this.db.skills.values()) {\n if (skill.favoriteCount) skill.favoriteCount = 0;\n }\n }\n\n async favorite({ userId, entityType, entityId }: StorageFavoriteKey): Promise<FavoriteToggleResult> {\n const entity = this.requireEntity(entityType, entityId);\n const key = favoriteKey(userId, entityType, entityId);\n\n if (this.db.favorites.has(key)) {\n return { favorited: true, favoriteCount: entity.favoriteCount ?? 0 };\n }\n\n const row: StorageFavoriteType = {\n userId,\n entityType,\n entityId,\n createdAt: new Date(),\n };\n this.db.favorites.set(key, row);\n\n const nextCount = (entity.favoriteCount ?? 0) + 1;\n entity.favoriteCount = nextCount;\n entity.updatedAt = new Date();\n\n return { favorited: true, favoriteCount: nextCount };\n }\n\n async unfavorite({ userId, entityType, entityId }: StorageFavoriteKey): Promise<FavoriteToggleResult> {\n const entity = this.requireEntity(entityType, entityId);\n const key = favoriteKey(userId, entityType, entityId);\n\n if (!this.db.favorites.has(key)) {\n return { favorited: false, favoriteCount: entity.favoriteCount ?? 0 };\n }\n\n this.db.favorites.delete(key);\n\n const nextCount = Math.max(0, (entity.favoriteCount ?? 0) - 1);\n entity.favoriteCount = nextCount;\n entity.updatedAt = new Date();\n\n return { favorited: false, favoriteCount: nextCount };\n }\n\n async isFavorited({ userId, entityType, entityId }: StorageFavoriteKey): Promise<boolean> {\n return this.db.favorites.has(favoriteKey(userId, entityType, entityId));\n }\n\n async isFavoritedBatch({ userId, entityType, entityIds }: StorageIsFavoritedBatchInput): Promise<Set<string>> {\n const result = new Set<string>();\n for (const entityId of entityIds) {\n if (this.db.favorites.has(favoriteKey(userId, entityType, entityId))) {\n result.add(entityId);\n }\n }\n return result;\n }\n\n async listFavoritedIds({ userId, entityType }: StorageListFavoritesInput): Promise<string[]> {\n const ids: string[] = [];\n for (const row of this.db.favorites.values()) {\n if (row.userId === userId && row.entityType === entityType) {\n ids.push(row.entityId);\n }\n }\n return ids;\n }\n\n async deleteFavoritesForEntity({ entityType, entityId }: StorageDeleteFavoritesForEntityInput): Promise<number> {\n let removed = 0;\n for (const [key, row] of this.db.favorites) {\n if (row.entityType === entityType && row.entityId === entityId) {\n this.db.favorites.delete(key);\n removed++;\n }\n }\n // Zero the parent's denormalized counter if the record still exists. The\n // cascade caller in the server typically deletes the entity first, in\n // which case this is a no-op — but callers that prune favorites for a still\n // existing entity (e.g. admin reset) need consistent counts.\n const map = entityType === 'agent' ? this.db.agents : this.db.skills;\n const entity = map.get(entityId);\n if (entity && entity.favoriteCount) {\n entity.favoriteCount = 0;\n }\n return removed;\n }\n\n /**\n * Look up the parent entity record for counter maintenance. Throws if the\n * entity does not exist — callers should validate existence (and access)\n * before invoking favorite/unfavorite.\n */\n private requireEntity(\n entityType: StorageFavoriteEntityType,\n entityId: string,\n ): { favoriteCount?: number; updatedAt: Date } {\n const map = entityType === 'agent' ? this.db.agents : this.db.skills;\n const entity = map.get(entityId);\n if (!entity) {\n throw new Error(`Cannot favorite: ${entityType} with id ${entityId} does not exist`);\n }\n return entity;\n }\n}\n"]}