@poe-platform/safe-fs 0.1.727 → 0.1.729

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +15 -8
  2. package/dist/safe-fs/contracts/errors.js +8 -1
  3. package/dist/safe-fs/contracts/filesystem.d.ts +68 -2
  4. package/dist/safe-fs/contracts/io.js +210 -28
  5. package/dist/safe-fs/contracts/virtual-path.d.ts +3 -1
  6. package/dist/safe-fs/contracts/virtual-path.js +20 -1
  7. package/dist/safe-fs/core.d.ts +1 -0
  8. package/dist/safe-fs/core.js +1 -0
  9. package/dist/safe-fs/fs/capabilities.d.ts +1 -1
  10. package/dist/safe-fs/fs/capabilities.js +59 -21
  11. package/dist/safe-fs/fs/conditional-chmod.d.ts +7 -0
  12. package/dist/safe-fs/fs/conditional-chmod.js +19 -0
  13. package/dist/safe-fs/fs/descriptor.js +51 -25
  14. package/dist/safe-fs/fs/devices/index.d.ts +7 -2
  15. package/dist/safe-fs/fs/devices/index.js +210 -29
  16. package/dist/safe-fs/fs/devices/path.d.ts +3 -1
  17. package/dist/safe-fs/fs/devices/path.js +70 -12
  18. package/dist/safe-fs/fs/memory/index.d.ts +70 -48
  19. package/dist/safe-fs/fs/memory/index.js +1595 -244
  20. package/dist/safe-fs/fs/memory/ledger.d.ts +8 -1
  21. package/dist/safe-fs/fs/memory/ledger.js +46 -6
  22. package/dist/safe-fs/fs/memory/missing-target.js +21 -1
  23. package/dist/safe-fs/fs/mount/index.d.ts +11 -3
  24. package/dist/safe-fs/fs/mount/index.js +326 -15
  25. package/dist/safe-fs/fs/object-publication/index.js +79 -3
  26. package/dist/safe-fs/fs/overlay/index.d.ts +2 -2
  27. package/dist/safe-fs/fs/overlay/index.js +27 -5
  28. package/dist/safe-fs/fs/overlay/memory-publication.d.ts +2 -1
  29. package/dist/safe-fs/fs/overlay/memory-publication.js +39 -2
  30. package/dist/safe-fs/fs/quota/index.js +5 -5
  31. package/dist/safe-fs/fs/readonly/index.d.ts +1 -0
  32. package/dist/safe-fs/fs/readonly/index.js +13 -0
  33. package/dist/safe-fs/fs/real/index.d.ts +6 -2
  34. package/dist/safe-fs/fs/real/index.js +78 -8
  35. package/dist/safe-fs/fs/s3/filesystem.d.ts +3 -0
  36. package/dist/safe-fs/fs/s3/filesystem.js +57 -25
  37. package/dist/safe-fs/fs/s3/http/transport.js +20 -3
  38. package/dist/safe-fs/fs/s3/mock.js +19 -2
  39. package/dist/safe-fs/fs/s3/namespace.js +8 -2
  40. package/dist/safe-fs/fs/s3/registry.js +2 -0
  41. package/dist/safe-fs/fs/scoped.d.ts +1 -0
  42. package/dist/safe-fs/fs/scoped.js +261 -74
  43. package/dist/safe-fs/fs/staging-ancestry.d.ts +8 -0
  44. package/dist/safe-fs/fs/staging-ancestry.js +115 -0
  45. package/dist/safe-fs/fs/staging-cleanup.d.ts +5 -0
  46. package/dist/safe-fs/fs/staging-cleanup.js +63 -0
  47. package/dist/safe-fs/fs/webdav/webdav.js +7 -5
  48. package/dist/safe-fs/platform/browser.d.ts +5 -0
  49. package/dist/safe-fs/platform/browser.js +17 -0
  50. package/dist/safe-fs/platform/node.d.ts +5 -0
  51. package/dist/safe-fs/platform/node.js +28 -0
  52. package/dist/safe-fs/platform/transport-budget.d.ts +7 -0
  53. package/dist/safe-fs/platform/transport-budget.js +4 -0
  54. package/dist/safe-fs/testing/object-io-metrics.d.ts +3 -0
  55. package/dist/safe-fs/testing/object-io-metrics.js +29 -0
  56. package/dist/safe-fs/testing/object-publication.d.ts +3 -1
  57. package/dist/safe-fs/testing/object-publication.js +2 -2
  58. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
- import { FsError } from "../contracts/errors.js";
1
+ import { FsError, toFsError } from "../contracts/errors.js";
2
2
  import { finishCleanup } from "../contracts/cleanup.js";
3
+ import { inspectStagingBindings } from "./staging-ancestry.js";
3
4
  export function retainedReadCapabilities(filesystem, capabilities = filesystem.capabilities) {
4
5
  return typeof filesystem.openReadFile === "function" ? capabilities : { ...capabilities, retainedRead: false };
5
6
  }
@@ -104,11 +105,12 @@ export function readOnlyCapabilities(capabilities) {
104
105
  "symlinks", "streamingRead", "open", "retainedRead", "versionedDescriptors",
105
106
  ].filter(name => capabilities[name] !== undefined).map(name => [name, capabilities[name]]));
106
107
  return Object.freeze({
107
- ...inspection, readOnly: true, write: false, append: false, exclusiveCreate: false,
108
+ ...inspection, retainedStagingCleanup: false, readOnly: true, write: false, append: false, exclusiveCreate: false,
109
+ synchronousStagingResolution: false,
108
110
  mkdir: false, recursiveMkdir: false, remove: false, removeDirectory: false, recursiveRemove: false,
109
111
  rename: false, copy: false, exclusiveCopy: false, truncate: false, streamingAppend: false,
110
- randomAccessWrite: false, hardlinks: false, permissions: false, timestamps: false,
111
- descriptorWriteStream: false, atomicResize: false, retainedResize: false, atomicFileMutation: false, atomicEntryRemoval: false, atomicTreeRemoval: false, atomicFileStaging: false, atomicDirectoryMetadata: false, trustedOwnedStaging: false,
112
+ randomAccessWrite: false, hardlinks: false, permissions: false, conditionalChmod: false, timestamps: false,
113
+ descriptorWriteStream: false, atomicResize: false, retainedResize: false, atomicFileMutation: false, atomicEntryRemoval: false, atomicEntryRemovalReceipt: false, atomicTreeRemoval: false, atomicFileStaging: false, atomicDirectoryMetadata: false, trustedOwnedStaging: false,
112
114
  atomicFilePublication: false, atomicRename: false, atomicRenameNoReplace: false, streamingWrite: false,
113
115
  });
114
116
  }
@@ -116,35 +118,71 @@ export function quotaCapabilities(capabilities) {
116
118
  const streamingWrite = requireCapabilities(capabilities.write, capabilities.append, !capabilities.readOnly);
117
119
  const streamingAppend = requireCapabilities(capabilities.append, !capabilities.readOnly);
118
120
  const { streamingWrite: ignoredWrite, streamingAppend: ignoredAppend, ...rest } = capabilities;
119
- return Object.freeze({ ...rest, atomicFilePublication: false, descriptorWriteStream: false, atomicResize: false, atomicFileMutation: false, atomicEntryRemoval: false, atomicFileStaging: false, atomicDirectoryMetadata: false, trustedOwnedStaging: false,
121
+ return Object.freeze({ ...rest, synchronousStagingResolution: false, retainedStagingCleanup: false, atomicStagingAncestry: false, synchronousDirectoryValidation: false, guardedStagingPublication: false, atomicFilePublication: false, descriptorWriteStream: false, atomicResize: false, atomicFileMutation: false, atomicEntryRemoval: false, atomicEntryRemovalReceipt: false, atomicFileStaging: false, atomicDirectoryMetadata: false, trustedOwnedStaging: false,
120
122
  ...(streamingWrite === undefined ? {} : { streamingWrite }),
121
123
  ...(streamingAppend === undefined ? {} : { streamingAppend }),
122
124
  });
123
125
  }
126
+ const TRUSTED_OWNED_STAGING_METHODS = [
127
+ "createStagedFile", "publishStagedFile", "removeStagedFile", "writeFileConditional", "removeFileConditional", "prepareDirectory",
128
+ ];
124
129
  export function ownedMutationCapabilities(filesystem, capabilities = filesystem.capabilities) {
125
- const unavailable = {};
130
+ let unavailable;
126
131
  if (capabilities.atomicFilePublication === true && (capabilities.readOnly === true || typeof filesystem.publishFileConditional !== "function"))
127
- unavailable.atomicFilePublication = false;
132
+ (unavailable ??= {}).atomicFilePublication = false;
128
133
  if (capabilities.atomicEntryRemoval === true && (capabilities.readOnly === true || typeof filesystem.removeEntryConditional !== "function"))
129
- unavailable.atomicEntryRemoval = false;
134
+ (unavailable ??= {}).atomicEntryRemoval = false;
135
+ if (capabilities.atomicEntryRemovalReceipt === true && (capabilities.atomicEntryRemoval !== true || unavailable?.atomicEntryRemoval === false))
136
+ (unavailable ??= {}).atomicEntryRemovalReceipt = false;
130
137
  if (capabilities.atomicTreeRemoval === true && (capabilities.readOnly === true || typeof filesystem.removeTreeConditional !== "function"))
131
- unavailable.atomicTreeRemoval = false;
138
+ (unavailable ??= {}).atomicTreeRemoval = false;
132
139
  if (capabilities.atomicFileMutation === true && (capabilities.readOnly === true || typeof filesystem.writeFileConditional !== "function" || typeof filesystem.removeFileConditional !== "function"))
133
- unavailable.atomicFileMutation = false;
140
+ (unavailable ??= {}).atomicFileMutation = false;
134
141
  if (capabilities.atomicFileStaging === true && (capabilities.readOnly === true
135
142
  || typeof filesystem.createStagedFile !== "function" || typeof filesystem.publishStagedFile !== "function" || typeof filesystem.removeStagedFile !== "function"))
136
- unavailable.atomicFileStaging = false;
143
+ (unavailable ??= {}).atomicFileStaging = false;
144
+ if (capabilities.retainedStagingCleanup === true && (capabilities.atomicFileStaging !== true || unavailable?.atomicFileStaging === false))
145
+ (unavailable ??= {}).retainedStagingCleanup = false;
146
+ if (capabilities.atomicStagingAncestry === true && (capabilities.atomicFileStaging !== true || unavailable?.atomicFileStaging === false))
147
+ (unavailable ??= {}).atomicStagingAncestry = false;
148
+ if (capabilities.synchronousDirectoryValidation === true && typeof filesystem.prepareDirectoryAncestry !== "function")
149
+ (unavailable ??= {}).synchronousDirectoryValidation = false;
150
+ if (capabilities.synchronousStagingResolution === true && (capabilities.readOnly === true || typeof filesystem.prepareStagingResolution !== "function"))
151
+ (unavailable ??= {}).synchronousStagingResolution = false;
152
+ if (capabilities.guardedStagingPublication === true && (capabilities.atomicFileStaging !== true || unavailable?.atomicFileStaging === false))
153
+ (unavailable ??= {}).guardedStagingPublication = false;
137
154
  if (capabilities.atomicDirectoryMetadata === true && (capabilities.readOnly === true || typeof filesystem.prepareDirectory !== "function"))
138
- unavailable.atomicDirectoryMetadata = false;
139
- if (capabilities.trustedOwnedStaging === true && (capabilities.readOnly === true
140
- || ["createStagedFile", "publishStagedFile", "removeStagedFile", "writeFileConditional", "removeFileConditional", "prepareDirectory"].some(method => typeof filesystem[method] !== "function")))
141
- unavailable.trustedOwnedStaging = false;
142
- return Object.keys(unavailable).length ? { ...capabilities, ...unavailable } : capabilities;
155
+ (unavailable ??= {}).atomicDirectoryMetadata = false;
156
+ if (capabilities.trustedOwnedStaging === true) {
157
+ let missing = capabilities.readOnly === true;
158
+ if (!missing) {
159
+ for (let i = 0; i < TRUSTED_OWNED_STAGING_METHODS.length; i++) {
160
+ if (typeof filesystem[TRUSTED_OWNED_STAGING_METHODS[i]] !== "function") {
161
+ missing = true;
162
+ break;
163
+ }
164
+ }
165
+ }
166
+ if (missing)
167
+ (unavailable ??= {}).trustedOwnedStaging = false;
168
+ }
169
+ return unavailable ? { ...capabilities, ...unavailable } : capabilities;
143
170
  }
144
171
  export async function requireOwnedMutation(filesystem, path, capability, options, create = false) {
145
- options.signal?.throwIfAborted();
146
- const capabilities = ownedMutationCapabilities(filesystem, await filesystem.capabilitiesFor?.(path, create ? { ...options, create: true } : options) ?? filesystem.capabilities);
147
- options.signal?.throwIfAborted();
148
- if (capabilities[capability] !== true && !(capabilities.trustedOwnedStaging === true && ["atomicFileStaging", "atomicFileMutation", "atomicDirectoryMetadata"].includes(capability)))
149
- throw new FsError("ENOTSUP", { path, syscall: capability });
172
+ try {
173
+ options.signal?.throwIfAborted();
174
+ const query = create ? { ...options, create: true } : options;
175
+ const capabilities = ownedMutationCapabilities(filesystem, await filesystem.capabilitiesFor?.(path, capability === "atomicStagingAncestry" ? { ...query, stagingAncestry: true } : query) ?? filesystem.capabilities);
176
+ options.signal?.throwIfAborted();
177
+ if (capabilities[capability] !== true && !(capabilities.trustedOwnedStaging === true && ["atomicFileStaging", "atomicFileMutation", "atomicDirectoryMetadata"].includes(capability)))
178
+ throw new FsError("ENOTSUP", { path, syscall: capability });
179
+ }
180
+ catch (error) {
181
+ options.signal?.throwIfAborted();
182
+ if (capability === "atomicStagingAncestry" && "ancestors" in options && options.ancestors !== undefined
183
+ && "destination" in options && ["ENOTSUP", "ENOENT", "ENOTDIR", "ELOOP"].includes(toFsError(error).code)) {
184
+ await inspectStagingBindings(entry => filesystem.lstat(entry, options), path, options);
185
+ }
186
+ throw error;
187
+ }
150
188
  }
@@ -0,0 +1,7 @@
1
+ import type { ChmodOptions, FileStagingEntry, FileStat } from "../contracts/filesystem.js";
2
+ export interface ConditionalChmodOptions extends ChmodOptions {
3
+ readonly parent: FileStat;
4
+ readonly expected: FileStat;
5
+ readonly ancestors: readonly FileStagingEntry[];
6
+ }
7
+ export declare function snapshotConditionalChmod(path: string, options: ChmodOptions): ConditionalChmodOptions | undefined;
@@ -0,0 +1,19 @@
1
+ import { FsError } from "../contracts/errors.js";
2
+ import { dirname } from "../contracts/virtual-path.js";
3
+ import { snapshotDirectoryAncestry } from "./staging-ancestry.js";
4
+ export function snapshotConditionalChmod(path, options) {
5
+ const { signal, parent, expected, ancestors, commitGuard } = options;
6
+ signal?.throwIfAborted();
7
+ if (parent === undefined && expected === undefined && ancestors === undefined && commitGuard === undefined)
8
+ return undefined;
9
+ if (parent === undefined || expected === undefined || ancestors === undefined) {
10
+ throw new FsError("EINVAL", { syscall: "chmod", path, message: "complete conditional chmod receipt is required" });
11
+ }
12
+ if (commitGuard !== undefined && typeof commitGuard !== "function")
13
+ throw new FsError("EINVAL", { syscall: "chmod", path });
14
+ const entries = snapshotDirectoryAncestry(ancestors);
15
+ if (entries.at(-1)?.path !== dirname(path))
16
+ throw new FsError("EINVAL", { syscall: "chmod", path });
17
+ return { ...(signal === undefined ? {} : { signal }), parent: { ...parent }, expected: { ...expected }, ancestors: entries,
18
+ ...(commitGuard === undefined ? {} : { commitGuard }) };
19
+ }
@@ -45,6 +45,37 @@ function integer(value, syscall, path) {
45
45
  if (!Number.isSafeInteger(value) || value < 0)
46
46
  throw new FsError("EINVAL", { syscall, path });
47
47
  }
48
+ const OPEN_FILE_OPTION_KEYS = new Set(["access", "creation", "truncate", "append", "mode", "exactMode", "noFollow", "synchronization", "signal"]);
49
+ const managedCapabilitiesCache = new WeakMap();
50
+ function getManagedCapabilities(capabilities, access, append) {
51
+ let byKey = managedCapabilitiesCache.get(capabilities);
52
+ const key = `${access}:${append ? 1 : 0}`;
53
+ if (byKey) {
54
+ const cached = byKey.get(key);
55
+ if (cached)
56
+ return cached;
57
+ }
58
+ else {
59
+ byKey = new Map();
60
+ managedCapabilitiesCache.set(capabilities, byKey);
61
+ }
62
+ const positionedAppendWrite = capabilities.positionedAppendWrite === true && capabilities.positionedWrite && access !== "read";
63
+ const frozen = Object.freeze({
64
+ ...(capabilities.noFollow === undefined ? {} : { noFollow: capabilities.noFollow }),
65
+ ...(capabilities.publication === undefined ? {} : { publication: capabilities.publication }),
66
+ ...(capabilities.position === undefined ? {} : { position: capabilities.position }),
67
+ ...(capabilities.readObservation === undefined ? {} : { readObservation: capabilities.readObservation }),
68
+ ...(capabilities.openTruncate === undefined ? {} : { openTruncate: capabilities.openTruncate }),
69
+ positionedRead: capabilities.positionedRead && access !== "write",
70
+ positionedWrite: capabilities.positionedWrite && access !== "read" && (!append || positionedAppendWrite),
71
+ ...(capabilities.positionedAppendWrite === undefined ? {} : { positionedAppendWrite }),
72
+ ...(capabilities.delegateZeroLengthWrite === undefined ? {} : { delegateZeroLengthWrite: capabilities.delegateZeroLengthWrite && access !== "read" }),
73
+ truncate: capabilities.truncate && access !== "read",
74
+ synchronization: capabilities.synchronization,
75
+ });
76
+ byKey.set(key, frozen);
77
+ return frozen;
78
+ }
48
79
  class ManagedFileDescriptor {
49
80
  capabilities;
50
81
  #path;
@@ -62,26 +93,13 @@ class ManagedFileDescriptor {
62
93
  const getPosition = capabilities.position === true ? backend.getPosition : undefined;
63
94
  if (capabilities.position === true && typeof getPosition !== "function")
64
95
  throw new FsError("ENOTSUP", { syscall: "getPosition", path });
65
- this.#getPosition = getPosition?.bind(backend);
96
+ this.#getPosition = getPosition;
66
97
  const probeRead = capabilities.readObservation === true ? backend.probeRead : undefined;
67
98
  if (capabilities.readObservation === true && typeof probeRead !== "function")
68
99
  throw new FsError("ENOTSUP", { syscall: "probeRead", path });
69
- this.#probeRead = probeRead?.bind(backend);
100
+ this.#probeRead = probeRead;
70
101
  this.#backend = backend;
71
- const positionedAppendWrite = capabilities.positionedAppendWrite === true && capabilities.positionedWrite && options.access !== "read";
72
- this.capabilities = Object.freeze({
73
- ...(capabilities.noFollow === undefined ? {} : { noFollow: capabilities.noFollow }),
74
- ...(capabilities.publication === undefined ? {} : { publication: capabilities.publication }),
75
- ...(capabilities.position === undefined ? {} : { position: capabilities.position }),
76
- ...(capabilities.readObservation === undefined ? {} : { readObservation: capabilities.readObservation }),
77
- ...(capabilities.openTruncate === undefined ? {} : { openTruncate: capabilities.openTruncate }),
78
- positionedRead: capabilities.positionedRead && options.access !== "write",
79
- positionedWrite: capabilities.positionedWrite && options.access !== "read" && (!options.append || positionedAppendWrite),
80
- ...(capabilities.positionedAppendWrite === undefined ? {} : { positionedAppendWrite }),
81
- ...(capabilities.delegateZeroLengthWrite === undefined ? {} : { delegateZeroLengthWrite: capabilities.delegateZeroLengthWrite && options.access !== "read" }),
82
- truncate: capabilities.truncate && options.access !== "read",
83
- synchronization: capabilities.synchronization,
84
- });
102
+ this.capabilities = getManagedCapabilities(capabilities, options.access, options.append);
85
103
  }
86
104
  #run(syscall, options, action) {
87
105
  const signal = options.signal;
@@ -128,7 +146,7 @@ class ManagedFileDescriptor {
128
146
  return this.#run("getPosition", options, async (backend, forwarded) => {
129
147
  if (!this.capabilities.position || !this.#getPosition)
130
148
  throw new FsError("ENOTSUP", { syscall: "getPosition", path: this.#path });
131
- const position = await this.#getPosition(backend.resource, forwarded);
149
+ const position = await this.#getPosition.call(backend, backend.resource, forwarded);
132
150
  if (!Number.isSafeInteger(position) || position < 0)
133
151
  throw new FsError("EIO", { syscall: "getPosition", path: this.#path });
134
152
  return position;
@@ -138,7 +156,7 @@ class ManagedFileDescriptor {
138
156
  return this.#run("probeRead", options, async (backend, forwarded) => {
139
157
  if (!this.capabilities.readObservation || !this.#probeRead)
140
158
  throw new FsError("ENOTSUP", { syscall: "probeRead", path: this.#path });
141
- const readiness = await this.#probeRead(backend.resource, forwarded);
159
+ const readiness = await this.#probeRead.call(backend, backend.resource, forwarded);
142
160
  if (readiness !== "ready" && readiness !== "blocked" && readiness !== "unknown")
143
161
  throw new FsError("EIO", { syscall: "probeRead", path: this.#path });
144
162
  return readiness;
@@ -209,11 +227,17 @@ export async function openFileDescriptor(path, options, capabilities, acquire) {
209
227
  throw new FsError("EINVAL", { syscall: "open", path });
210
228
  const signal = options.signal;
211
229
  signal?.throwIfAborted();
212
- const keys = ["access", "creation", "truncate", "append", "mode", "exactMode", "noFollow", "synchronization", "signal"];
213
230
  const { access, creation = "never", truncate = false, append = false, mode = 0o666, synchronization } = options;
214
- if (Object.keys(options).some(key => !keys.includes(key))
215
- || !["read", "write", "readwrite"].includes(access)
216
- || !["never", "ifMissing", "exclusive"].includes(creation)
231
+ let invalidKey = false;
232
+ for (const key in options) {
233
+ if (Object.prototype.hasOwnProperty.call(options, key) && !OPEN_FILE_OPTION_KEYS.has(key)) {
234
+ invalidKey = true;
235
+ break;
236
+ }
237
+ }
238
+ if (invalidKey
239
+ || (access !== "read" && access !== "write" && access !== "readwrite")
240
+ || (creation !== "never" && creation !== "ifMissing" && creation !== "exclusive")
217
241
  || options.noFollow !== undefined && typeof options.noFollow !== "boolean"
218
242
  || options.exactMode !== undefined && typeof options.exactMode !== "boolean"
219
243
  || typeof truncate !== "boolean" || typeof append !== "boolean"
@@ -226,7 +250,7 @@ export async function openFileDescriptor(path, options, capabilities, acquire) {
226
250
  ...(options.noFollow === undefined ? {} : { noFollow: options.noFollow }),
227
251
  ...(options.exactMode === undefined ? {} : { exactMode: options.exactMode }),
228
252
  ...(signal === undefined ? {} : { signal }), ...(synchronization === undefined ? {} : { synchronization }) });
229
- const admittedCapabilities = Object.freeze({ ...capabilities });
253
+ const admittedCapabilities = Object.isFrozen(capabilities) ? capabilities : Object.freeze({ ...capabilities });
230
254
  admitCapabilities(path, admitted, admittedCapabilities);
231
255
  let backend;
232
256
  try {
@@ -238,9 +262,11 @@ export async function openFileDescriptor(path, options, capabilities, acquire) {
238
262
  }
239
263
  try {
240
264
  signal?.throwIfAborted();
241
- const selected = Object.freeze({ ...(backend.capabilities ?? admittedCapabilities) });
265
+ const rawBackendCapabilities = backend.capabilities;
266
+ const selected = rawBackendCapabilities ? Object.freeze({ ...rawBackendCapabilities }) : admittedCapabilities;
242
267
  signal?.throwIfAborted();
243
- admitCapabilities(path, admitted, selected);
268
+ if (rawBackendCapabilities)
269
+ admitCapabilities(path, admitted, selected);
244
270
  const descriptor = new ManagedFileDescriptor(path, admitted, selected, backend);
245
271
  signal?.throwIfAborted();
246
272
  return descriptor;
@@ -1,5 +1,5 @@
1
1
  import type { FileDescriptor, OpenFileOptions } from "../../contracts/descriptor.js";
2
- import type { AppendFileOptions, CapabilityQueryOptions, CopyFileOptions, DirectoryEntry, FileReadHandle, FileResizeHandle, FileResizeOperation, FileResizeOptions, FileStat, FileSystem, OpenReadFileOptions, OpenResizeFileOptions, FileSystemCapabilities, FsOptions, RenameOptions, MkdirOptions, ReadDirectoryOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions, ConditionalFilePublicationOptions, ConditionalWriteFileOptions, ConditionalRemoveFileOptions, ConditionalRemoveEntryOptions, CreateStagedFileOptions, FileStaging, PublishStagedFileOptions, PrepareDirectoryOptions, StagedFileContent } from "../../contracts/filesystem.js";
2
+ import type { AppendFileOptions, CapabilityQueryOptions, CopyFileOptions, DirectoryEntry, FileReadHandle, FileResizeHandle, FileResizeOperation, FileResizeOptions, FileStat, FileSystem, OpenReadFileOptions, OpenResizeFileOptions, FileSystemCapabilities, FsOptions, RenameOptions, MkdirOptions, ReadDirectoryOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions, ConditionalFilePublicationOptions, ConditionalWriteFileOptions, ConditionalRemoveFileOptions, ConditionalRemoveEntryOptions, ConditionalRemoveEntryReceiptOptions, CreateStagedFileOptions, FileStaging, FileStagingEntry, FileStagingResolution, PublishStagedFileOptions, PrepareDirectoryOptions, StagedFileContent } from "../../contracts/filesystem.js";
3
3
  import type { ByteSource } from "../../contracts/io.js";
4
4
  export declare class DeviceFileSystem implements FileSystem {
5
5
  #private;
@@ -27,11 +27,16 @@ export declare class DeviceFileSystem implements FileSystem {
27
27
  rmdir(path: string, options?: FsOptions): Promise<void>;
28
28
  publishFileConditional(path: string, source: ByteSource, options: ConditionalFilePublicationOptions): Promise<FileStat>;
29
29
  writeFileConditional(path: string, data: Uint8Array, options: ConditionalWriteFileOptions): Promise<FileStat>;
30
- removeEntryConditional(path: string, options: ConditionalRemoveEntryOptions): Promise<void>;
30
+ removeEntryConditional(path: string, options: ConditionalRemoveEntryOptions & {
31
+ readonly returnRemainingStat?: false | undefined;
32
+ }): Promise<void>;
33
+ removeEntryConditional(path: string, options: ConditionalRemoveEntryReceiptOptions): Promise<void | FileStat>;
31
34
  removeFileConditional(path: string, options: ConditionalRemoveFileOptions): Promise<void>;
32
35
  removeTreeConditional(path: string, options: ConditionalRemoveEntryOptions): Promise<void>;
33
36
  createStagedFile(path: string, name: string, content: StagedFileContent, options: CreateStagedFileOptions): Promise<FileStaging>;
34
37
  publishStagedFile(staging: FileStaging, destination: string, options: PublishStagedFileOptions): Promise<void>;
38
+ prepareDirectoryAncestry(ancestors: readonly FileStagingEntry[], options?: FsOptions): Promise<() => true>;
39
+ prepareStagingResolution(path: string, options?: FsOptions): Promise<FileStagingResolution>;
35
40
  removeStagedFile(staging: FileStaging, options?: FsOptions): Promise<void>;
36
41
  prepareDirectory(path: string, options: PrepareDirectoryOptions): Promise<FileStat>;
37
42
  rename(source: string, destination: string, options?: RenameOptions): Promise<void>;