| 159 | * batches all writes into a single flush. |
| 160 | */ |
| 161 | export class DurableObjectRawFileSystem implements FileSystem { |
| 162 | /** |
| 163 | * @param storage The Durable Object storage instance to persist files to. |
| 164 | * @param prefix An optional path prefix prepended to every key stored in KV. |
| 165 | * Defaults to `"bundle/"`, which namespaces bundle files away |
| 166 | * from any other keys the Durable Object may store. |
| 167 | */ |
| 168 | constructor( |
| 169 | private readonly storage: DurableObjectStorage, |
| 170 | private readonly prefix: string = "bundle/" |
| 171 | ) {} |
| 172 | |
| 173 | read(path: string): string | null { |
| 174 | return this.storage.kv.get<string>(this.formatPath(path)) ?? null; |
| 175 | } |
| 176 | |
| 177 | write(path: string, content: string): void { |
| 178 | this.storage.kv.put(this.formatPath(path), content); |
| 179 | } |
| 180 | |
| 181 | delete(path: string): void { |
| 182 | this.storage.kv.delete(this.formatPath(path)); |
| 183 | } |
| 184 | |
| 185 | list(prefix?: string): string[] { |
| 186 | const formattedPrefix = |
| 187 | prefix !== undefined ? this.formatPath(prefix) : this.prefix; |
| 188 | // kv.list() returns Iterable<[key, value]>. Strip the storage prefix from |
| 189 | // each key so callers always receive logical paths, consistent with |
| 190 | // InMemoryFileSystem.list(). |
| 191 | const result: string[] = []; |
| 192 | for (const [key] of this.storage.kv.list({ prefix: formattedPrefix })) { |
| 193 | result.push(key.slice(this.prefix.length)); |
| 194 | } |
| 195 | return result; |
| 196 | } |
| 197 | |
| 198 | flush(): Promise<void> { |
| 199 | return Promise.resolve(); |
| 200 | } |
| 201 | |
| 202 | private formatPath(path: string): string { |
| 203 | return `${this.prefix}${path}`; |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * A filesystem backed by Durable Object KV storage with a write-overlay. |
nothing calls this directly
no outgoing calls
no test coverage detected