bolt.diy/app/lib/stores/files.ts

77 lines
2.1 KiB
TypeScript

import { map, type MapStore } from 'nanostores';
import { computeFileModifications } from '~/utils/diff';
import { createScopedLogger } from '~/utils/logger';
import { unreachable } from '~/utils/unreachable';
import type { ProtocolFile } from '../replay/SimulationPrompt';
const logger = createScopedLogger('FilesStore');
export type FileMap = Record<string, ProtocolFile | undefined>;
export class FilesStore {
/**
* Tracks the number of files without folders.
*/
#size = 0;
/**
* @note Keeps track all modified files with their original content since the last user message.
* Needs to be reset when the user sends another message and all changes have to be submitted
* for the model to be aware of the changes.
*/
#modifiedFiles: Map<string, string> = import.meta.hot?.data.modifiedFiles ?? new Map();
/**
* Map of files that matches the state of WebContainer.
*/
files: MapStore<FileMap> = import.meta.hot?.data.files ?? map({});
get filesCount() {
return this.#size;
}
constructor() {
if (import.meta.hot) {
import.meta.hot.data.files = this.files;
import.meta.hot.data.modifiedFiles = this.#modifiedFiles;
}
}
getFile(filePath: string) {
const dirent = this.files.get()[filePath];
return dirent;
}
getFileModifications() {
return computeFileModifications(this.files.get(), this.#modifiedFiles);
}
resetFileModifications() {
this.#modifiedFiles.clear();
}
async saveFile(filePath: string, content: string) {
try {
const oldContent = this.getFile(filePath)?.content;
if (!oldContent) {
console.log('CurrentFiles', JSON.stringify(Object.keys(this.files.get())));
unreachable(`Cannot save unknown file ${filePath}`);
}
if (!this.#modifiedFiles.has(filePath)) {
this.#modifiedFiles.set(filePath, oldContent);
}
// we immediately update the file and don't rely on the `change` event coming from the watcher
this.files.setKey(filePath, { path: filePath, content });
logger.info('File updated');
} catch (error) {
logger.error('Failed to update file content\n\n', error);
throw error;
}
}
}