import { MemoryStorage, WorkspaceJournal } from "../workspace/journal.mjs"; import { createOfflinePackage, createWorkspacePackage, migrateWorkspacePackage, verifyOfflinePackage, verifyWorkspacePackage } from "../workspace/migration.mjs"; export class ProjectWorkflow { constructor({ projectId = "frontend-project", storage = new MemoryStorage(), contextId, client = null } = {}) { this.projectId = projectId; this.contextId = contextId; this.storage = storage; this.journal = new WorkspaceJournal(storage, { projectId }); this.client = client; this.files = {}; this.lastRecovery = null; } importFiles(files) { if (!Array.isArray(files) || files.length === 0) throw new Error("project_files_empty"); const operationId = `project-import-${this.journal.nextSequence()}`; this.journal.prepare(operationId, files); this.journal.commit(operationId); const recovery = this.journal.recover(); this.lastRecovery = recovery; if (recovery.status !== "recovered") throw new Error("project_import_blocked"); this.files = recovery.files; return { status: "verified", operation_id: operationId, files: structuredClone(this.files), state_hash: recovery.state_hash }; } recover() { const recovery = this.journal.recover(); this.lastRecovery = recovery; if (recovery.status === "recovered") this.files = recovery.files; return recovery; } exportFiles() { return Object.entries(this.files).sort(([left], [right]) => left.localeCompare(right)).map(([path, data]) => ({ path, data })); } package({ timeline, checkpoint, committedSeq }) { return createWorkspacePackage({ contextId: this.contextId, timeline, checkpoint, journal: this.journal.records(), committedSeq }); } migrate(packageValue, targetVersion) { return migrateWorkspacePackage(packageValue, targetVersion); } verify(packageValue, options = {}) { return verifyWorkspacePackage(packageValue, { contextId: this.contextId, ...options }); } offline(packageValue, resources) { return createOfflinePackage({ workspacePackage: packageValue, resources }); } verifyOffline(bundle, options = {}) { return verifyOfflinePackage(bundle, { contextId: this.contextId, ...options }); } }