()
| 20 | } |
| 21 | |
| 22 | export function makeMemoryFs(): Fs { |
| 23 | const files = new Map<string, Uint8Array>(); |
| 24 | const dirs = new Set<string>(["/"]); |
| 25 | const textEncoder = new TextEncoder(); |
| 26 | const textDecoder = new TextDecoder(); |
| 27 | |
| 28 | function joinPath(dir: string, name: string) { |
| 29 | return dir === "/" ? `/${name}` : `${dir}/${name}`; |
| 30 | } |
| 31 | |
| 32 | function addParents(filePath: string) { |
| 33 | let dir = dirname(filePath); |
| 34 | while (dir !== "." && dir !== "/") { |
| 35 | dirs.add(dir); |
| 36 | dir = dirname(dir); |
| 37 | } |
| 38 | if (dir === "/") dirs.add(dir); |
| 39 | } |
| 40 | |
| 41 | return { |
| 42 | async mkdir(path, opts) { |
| 43 | if (!opts?.recursive) { |
| 44 | const parent = dirname(path); |
| 45 | if (parent !== "/" && !dirs.has(parent)) throwNoEntError(path, "mkdir"); |
| 46 | } |
| 47 | dirs.add(path); |
| 48 | if (opts?.recursive) addParents(path); |
| 49 | }, |
| 50 | async pathExists(path) { |
| 51 | return files.has(path) || dirs.has(path); |
| 52 | }, |
| 53 | async readFile(path: string) { |
| 54 | const data = files.get(path); |
| 55 | if (data === undefined) throwNoEntError(path, "open"); |
| 56 | return textDecoder.decode(data); |
| 57 | }, |
| 58 | async rm(path, opts) { |
| 59 | if (files.has(path)) { |
| 60 | files.delete(path); |
| 61 | return; |
| 62 | } |
| 63 | if (dirs.has(path)) { |
| 64 | if (opts?.recursive) { |
| 65 | const prefix = path + "/"; |
| 66 | for (const k of files.keys()) { |
| 67 | if (k.startsWith(prefix)) { |
| 68 | files.delete(k); |
| 69 | } |
| 70 | } |
| 71 | for (const k of Array.from(dirs)) { |
| 72 | if (k === path || k.startsWith(prefix)) { |
| 73 | dirs.delete(k); |
| 74 | } |
| 75 | } |
| 76 | } else { |
| 77 | const prefix = path + "/"; |
| 78 | const hasChildren = |
| 79 | [...files.keys()].some((k) => k.startsWith(prefix)) || |
no outgoing calls