@mastra/core
Version:
356 lines (355 loc) • 12 kB
JavaScript
const require_deep_equal = require("./deep-equal-BvQBG8wE.cjs");
const require_filesystem_versioned = require("./filesystem-versioned-8Ag_Np8l.cjs");
//#region src/storage/domains/workspaces/base.ts
var WorkspacesStorage = class extends require_filesystem_versioned.VersionedStorageDomain {
listKey = "workspaces";
versionMetadataFields = [
"id",
"workspaceId",
"versionNumber",
"changedFields",
"changeMessage",
"createdAt"
];
constructor() {
super({
component: "STORAGE",
name: "WORKSPACES"
});
}
};
//#endregion
//#region src/storage/domains/workspaces/inmemory.ts
var InMemoryWorkspacesStorage = class extends WorkspacesStorage {
db;
constructor({ db }) {
super();
this.db = db;
}
async dangerouslyClearAll() {
this.db.workspaces.clear();
this.db.workspaceVersions.clear();
}
async getById(id) {
const config = this.db.workspaces.get(id);
return config ? this.deepCopyConfig(config) : null;
}
async create(input) {
const { workspace } = input;
if (this.db.workspaces.has(workspace.id)) throw new Error(`Workspace with id ${workspace.id} already exists`);
const now = /* @__PURE__ */ new Date();
const newConfig = {
id: workspace.id,
status: "draft",
activeVersionId: void 0,
authorId: workspace.authorId,
metadata: workspace.metadata,
createdAt: now,
updatedAt: now
};
this.db.workspaces.set(workspace.id, newConfig);
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = workspace;
const versionId = crypto.randomUUID();
await this.createVersion({
id: versionId,
workspaceId: workspace.id,
versionNumber: 1,
...snapshotConfig,
changedFields: Object.keys(snapshotConfig),
changeMessage: "Initial version"
});
return this.deepCopyConfig(newConfig);
}
async update(input) {
const { id, ...updates } = input;
const existingConfig = this.db.workspaces.get(id);
if (!existingConfig) throw new Error(`Workspace with id ${id} not found`);
const { authorId, activeVersionId, metadata, status, ...rawConfigFields } = updates;
const configFields = {};
for (const [key, value] of Object.entries(rawConfigFields)) if (value !== void 0) configFields[key] = value;
const configFieldNames = [
"name",
"description",
"filesystem",
"sandbox",
"mounts",
"search",
"skills",
"tools",
"autoSync",
"operationTimeout"
];
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
const updatedConfig = {
...existingConfig,
...authorId !== void 0 && { authorId },
...activeVersionId !== void 0 && { activeVersionId },
...status !== void 0 && { status },
...metadata !== void 0 && { metadata: {
...existingConfig.metadata,
...metadata
} },
updatedAt: /* @__PURE__ */ new Date()
};
if (activeVersionId !== void 0 && status === void 0) updatedConfig.status = "published";
if (hasConfigUpdate) {
const latestVersion = await this.getLatestVersion(id);
if (!latestVersion) throw new Error(`No versions found for workspace ${id}`);
const { id: _versionId, workspaceId: _workspaceId, versionNumber: _versionNumber, changedFields: _changedFields, changeMessage: _changeMessage, createdAt: _createdAt, ...latestConfig } = latestVersion;
const newConfig = {
...latestConfig,
...configFields
};
const changedFields = configFieldNames.filter((field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field]));
if (changedFields.length > 0) {
const newVersionId = crypto.randomUUID();
const newVersionNumber = latestVersion.versionNumber + 1;
await this.createVersion({
id: newVersionId,
workspaceId: id,
versionNumber: newVersionNumber,
...newConfig,
changedFields,
changeMessage: `Updated ${changedFields.join(", ")}`
});
}
}
this.db.workspaces.set(id, updatedConfig);
return this.deepCopyConfig(updatedConfig);
}
async delete(id) {
this.db.workspaces.delete(id);
await this.deleteVersionsByParentId(id);
}
async list(args) {
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata } = args || {};
const { field, direction } = this.parseOrderBy(orderBy);
const perPage = require_filesystem_versioned.normalizePerPage(perPageInput, 100);
if (page < 0) throw new Error("page must be >= 0");
const maxOffset = Number.MAX_SAFE_INTEGER / 2;
if (page * perPage > maxOffset) throw new Error("page value too large");
let configs = Array.from(this.db.workspaces.values());
if (authorId !== void 0) configs = configs.filter((config) => config.authorId === authorId);
if (metadata && Object.keys(metadata).length > 0) configs = configs.filter((config) => {
if (!config.metadata) return false;
return Object.entries(metadata).every(([key, value]) => require_deep_equal.deepEqual(config.metadata[key], value));
});
const clonedConfigs = this.sortConfigs(configs, field, direction).map((config) => this.deepCopyConfig(config));
const { offset, perPage: perPageForResponse } = require_filesystem_versioned.calculatePagination(page, perPageInput, perPage);
return {
workspaces: clonedConfigs.slice(offset, offset + perPage),
total: clonedConfigs.length,
page,
perPage: perPageForResponse,
hasMore: offset + perPage < clonedConfigs.length
};
}
async createVersion(input) {
if (this.db.workspaceVersions.has(input.id)) throw new Error(`Version with id ${input.id} already exists`);
for (const version of this.db.workspaceVersions.values()) if (version.workspaceId === input.workspaceId && version.versionNumber === input.versionNumber) throw new Error(`Version number ${input.versionNumber} already exists for workspace ${input.workspaceId}`);
const version = {
...input,
createdAt: /* @__PURE__ */ new Date()
};
this.db.workspaceVersions.set(input.id, this.deepCopyVersion(version));
return this.deepCopyVersion(version);
}
async getVersion(id) {
const version = this.db.workspaceVersions.get(id);
return version ? this.deepCopyVersion(version) : null;
}
async getVersionByNumber(workspaceId, versionNumber) {
for (const version of this.db.workspaceVersions.values()) if (version.workspaceId === workspaceId && version.versionNumber === versionNumber) return this.deepCopyVersion(version);
return null;
}
async getLatestVersion(workspaceId) {
let latest = null;
for (const version of this.db.workspaceVersions.values()) if (version.workspaceId === workspaceId) {
if (!latest || version.versionNumber > latest.versionNumber) latest = version;
}
return latest ? this.deepCopyVersion(latest) : null;
}
async listVersions(input) {
const { workspaceId, page = 0, perPage: perPageInput, orderBy } = input;
const { field, direction } = this.parseVersionOrderBy(orderBy);
const perPage = require_filesystem_versioned.normalizePerPage(perPageInput, 20);
if (page < 0) throw new Error("page must be >= 0");
const maxOffset = Number.MAX_SAFE_INTEGER / 2;
if (page * perPage > maxOffset) throw new Error("page value too large");
let versions = Array.from(this.db.workspaceVersions.values()).filter((v) => v.workspaceId === workspaceId);
versions = this.sortVersions(versions, field, direction);
const clonedVersions = versions.map((v) => this.deepCopyVersion(v));
const total = clonedVersions.length;
const { offset, perPage: perPageForResponse } = require_filesystem_versioned.calculatePagination(page, perPageInput, perPage);
return {
versions: clonedVersions.slice(offset, offset + perPage),
total,
page,
perPage: perPageForResponse,
hasMore: offset + perPage < total
};
}
async deleteVersion(id) {
this.db.workspaceVersions.delete(id);
}
async deleteVersionsByParentId(entityId) {
const idsToDelete = [];
for (const [id, version] of this.db.workspaceVersions.entries()) if (version.workspaceId === entityId) idsToDelete.push(id);
for (const id of idsToDelete) this.db.workspaceVersions.delete(id);
}
async countVersions(workspaceId) {
let count = 0;
for (const version of this.db.workspaceVersions.values()) if (version.workspaceId === workspaceId) count++;
return count;
}
deepCopyConfig(config) {
return {
...config,
metadata: config.metadata ? { ...config.metadata } : config.metadata
};
}
deepCopyVersion(version) {
return structuredClone(version);
}
sortConfigs(configs, field, direction) {
return configs.sort((a, b) => {
const aValue = a[field].getTime();
const bValue = b[field].getTime();
return direction === "ASC" ? aValue - bValue : bValue - aValue;
});
}
sortVersions(versions, field, direction) {
return versions.sort((a, b) => {
let aVal;
let bVal;
if (field === "createdAt") {
aVal = a.createdAt.getTime();
bVal = b.createdAt.getTime();
} else {
aVal = a.versionNumber;
bVal = b.versionNumber;
}
return direction === "ASC" ? aVal - bVal : bVal - aVal;
});
}
};
//#endregion
//#region src/storage/domains/workspaces/filesystem.ts
var FilesystemWorkspacesStorage = class extends WorkspacesStorage {
helpers;
constructor({ db }) {
super();
this.helpers = new require_filesystem_versioned.FilesystemVersionedHelpers({
db,
entitiesFile: "workspaces.json",
parentIdField: "workspaceId",
name: "FilesystemWorkspacesStorage",
versionMetadataFields: [
"id",
"workspaceId",
"versionNumber",
"changedFields",
"changeMessage",
"createdAt"
]
});
}
async init() {
await this.helpers.db.init();
}
async dangerouslyClearAll() {
await this.helpers.dangerouslyClearAll();
}
async getById(id) {
return this.helpers.getById(id);
}
async create(input) {
const { workspace } = input;
const now = /* @__PURE__ */ new Date();
const entity = {
id: workspace.id,
status: "draft",
activeVersionId: void 0,
authorId: workspace.authorId,
metadata: workspace.metadata,
createdAt: now,
updatedAt: now
};
await this.helpers.createEntity(workspace.id, entity);
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = workspace;
const versionId = crypto.randomUUID();
await this.createVersion({
id: versionId,
workspaceId: workspace.id,
versionNumber: 1,
...snapshotConfig,
changedFields: Object.keys(snapshotConfig),
changeMessage: "Initial version"
});
return structuredClone(entity);
}
async update(input) {
const { id, ...updates } = input;
return this.helpers.updateEntity(id, updates);
}
async delete(id) {
await this.helpers.deleteEntity(id);
}
async list(args) {
const { page, perPage, orderBy, authorId, metadata } = args || {};
return await this.helpers.listEntities({
page,
perPage,
orderBy,
listKey: "workspaces",
filters: {
authorId,
metadata
}
});
}
async createVersion(input) {
return this.helpers.createVersion(input);
}
async getVersion(id) {
return this.helpers.getVersion(id);
}
async getVersionByNumber(workspaceId, versionNumber) {
return this.helpers.getVersionByNumber(workspaceId, versionNumber);
}
async getLatestVersion(workspaceId) {
return this.helpers.getLatestVersion(workspaceId);
}
async listVersions(input) {
return await this.helpers.listVersions(input, "workspaceId");
}
async deleteVersion(id) {
await this.helpers.deleteVersion(id);
}
async deleteVersionsByParentId(entityId) {
await this.helpers.deleteVersionsByParentId(entityId);
}
async countVersions(workspaceId) {
return this.helpers.countVersions(workspaceId);
}
};
//#endregion
Object.defineProperty(exports, "FilesystemWorkspacesStorage", {
enumerable: true,
get: function() {
return FilesystemWorkspacesStorage;
}
});
Object.defineProperty(exports, "InMemoryWorkspacesStorage", {
enumerable: true,
get: function() {
return InMemoryWorkspacesStorage;
}
});
Object.defineProperty(exports, "WorkspacesStorage", {
enumerable: true,
get: function() {
return WorkspacesStorage;
}
});
//# sourceMappingURL=filesystem-Buug7_j8.cjs.map