mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
fix: harden persistence tiers and opfs durability
This commit is contained in:
107
tests/helpers/memory-opfs.mjs
Normal file
107
tests/helpers/memory-opfs.mjs
Normal file
@@ -0,0 +1,107 @@
|
||||
export function createNotFoundError(message) {
|
||||
const error = new Error(String(message || "Not found"));
|
||||
error.name = "NotFoundError";
|
||||
return error;
|
||||
}
|
||||
|
||||
export class MemoryOpfsFileHandle {
|
||||
constructor(parent, name) {
|
||||
this.parent = parent;
|
||||
this.name = String(name || "");
|
||||
}
|
||||
|
||||
async getFile() {
|
||||
const parent = this.parent;
|
||||
const name = this.name;
|
||||
return {
|
||||
async text() {
|
||||
return String(parent.files.get(name) ?? "");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async createWritable() {
|
||||
const parent = this.parent;
|
||||
const name = this.name;
|
||||
let buffer = String(parent.files.get(name) ?? "");
|
||||
return {
|
||||
async write(chunk) {
|
||||
if (typeof chunk === "string") {
|
||||
buffer = chunk;
|
||||
return;
|
||||
}
|
||||
if (chunk == null) {
|
||||
buffer = "";
|
||||
return;
|
||||
}
|
||||
buffer = String(chunk);
|
||||
},
|
||||
async close() {
|
||||
if (Number(parent.writeDelayMs) > 0) {
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, Number(parent.writeDelayMs)),
|
||||
);
|
||||
}
|
||||
parent.files.set(name, buffer);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class MemoryOpfsDirectoryHandle {
|
||||
constructor(name = "", { writeDelayMs = 0 } = {}) {
|
||||
this.name = String(name || "");
|
||||
this.directories = new Map();
|
||||
this.files = new Map();
|
||||
this.writeDelayMs = Number(writeDelayMs) || 0;
|
||||
}
|
||||
|
||||
async getDirectoryHandle(name, options = {}) {
|
||||
const normalizedName = String(name || "");
|
||||
let directory = this.directories.get(normalizedName) || null;
|
||||
if (!directory) {
|
||||
if (!options.create) {
|
||||
throw createNotFoundError(`Directory not found: ${normalizedName}`);
|
||||
}
|
||||
directory = new MemoryOpfsDirectoryHandle(normalizedName, {
|
||||
writeDelayMs: this.writeDelayMs,
|
||||
});
|
||||
this.directories.set(normalizedName, directory);
|
||||
}
|
||||
return directory;
|
||||
}
|
||||
|
||||
async getFileHandle(name, options = {}) {
|
||||
const normalizedName = String(name || "");
|
||||
if (!this.files.has(normalizedName)) {
|
||||
if (!options.create) {
|
||||
throw createNotFoundError(`File not found: ${normalizedName}`);
|
||||
}
|
||||
this.files.set(normalizedName, "");
|
||||
}
|
||||
return new MemoryOpfsFileHandle(this, normalizedName);
|
||||
}
|
||||
|
||||
async removeEntry(name, options = {}) {
|
||||
const normalizedName = String(name || "");
|
||||
if (this.files.delete(normalizedName)) {
|
||||
return;
|
||||
}
|
||||
const directory = this.directories.get(normalizedName) || null;
|
||||
if (directory) {
|
||||
const canDelete =
|
||||
options.recursive === true ||
|
||||
(directory.files.size === 0 && directory.directories.size === 0);
|
||||
if (!canDelete) {
|
||||
throw new Error(`Directory not empty: ${normalizedName}`);
|
||||
}
|
||||
this.directories.delete(normalizedName);
|
||||
return;
|
||||
}
|
||||
throw createNotFoundError(`Entry not found: ${normalizedName}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function createMemoryOpfsRoot(options = {}) {
|
||||
return new MemoryOpfsDirectoryHandle("root", options);
|
||||
}
|
||||
Reference in New Issue
Block a user