@poe-platform/safe-bash 0.1.545 → 0.1.547

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 (71) hide show
  1. package/dist/safe-bash/chunks/{chunk-FAA2WXKH.js → chunk-4JW32W4B.js} +163 -105
  2. package/dist/safe-bash/chunks/{chunk-FAA2WXKH.js.map → chunk-4JW32W4B.js.map} +3 -3
  3. package/dist/safe-bash/chunks/{chunk-XWCSJDGK.js → chunk-4V3NGZAG.js} +2 -2
  4. package/dist/safe-bash/chunks/{chunk-ASCV3OWE.js → chunk-AWP6Z3RR.js} +3 -3
  5. package/dist/safe-bash/chunks/{chunk-2YHZYNLC.js → chunk-DKT746UJ.js} +2 -2
  6. package/dist/safe-bash/chunks/{chunk-C7Z2SSTY.js → chunk-EUNOVYVT.js} +16 -3
  7. package/dist/safe-bash/chunks/chunk-EUNOVYVT.js.map +7 -0
  8. package/dist/safe-bash/chunks/{chunk-6E3FCEJ5.js → chunk-F5AOPLRZ.js} +2 -2
  9. package/dist/safe-bash/chunks/{chunk-GA43CRT3.js → chunk-FIY2BMTU.js} +2 -2
  10. package/dist/safe-bash/chunks/{chunk-EGLBB57T.js → chunk-IDJQT32M.js} +2 -2
  11. package/dist/safe-bash/chunks/{chunk-25GUOTPE.js → chunk-QX2X5EC5.js} +2 -2
  12. package/dist/safe-bash/chunks/{chunk-CTE3HGYS.js → chunk-VY5N6O6I.js} +3 -3
  13. package/dist/safe-bash/chunks/{chunk-K4RQ7ASH.js → chunk-WJWYJDQE.js} +2 -2
  14. package/dist/safe-bash/chunks/{chunk-R4HP2LEO.js → chunk-WXUZXY35.js} +2 -2
  15. package/dist/safe-bash/chunks/{chunk-IVJ5JGXZ.js → chunk-YFFFBLBC.js} +2 -2
  16. package/dist/safe-bash/commands/archive/unzip/safety.d.ts +3 -2
  17. package/dist/safe-bash/commands/archive/unzip/safety.d.ts.map +1 -1
  18. package/dist/safe-bash/commands/archive/unzip/safety.js +57 -62
  19. package/dist/safe-bash/commands/archive/unzip/safety.js.map +1 -1
  20. package/dist/safe-bash/commands/archive/unzip.d.ts.map +1 -1
  21. package/dist/safe-bash/commands/archive/unzip.js +12 -9
  22. package/dist/safe-bash/commands/archive/unzip.js.map +1 -1
  23. package/dist/safe-bash/commands/archive/zip/safety.d.ts +1 -0
  24. package/dist/safe-bash/commands/archive/zip/safety.d.ts.map +1 -1
  25. package/dist/safe-bash/commands/archive/zip/safety.js +19 -87
  26. package/dist/safe-bash/commands/archive/zip/safety.js.map +1 -1
  27. package/dist/safe-bash/commands/archive/zip.d.ts.map +1 -1
  28. package/dist/safe-bash/commands/archive/zip.js +2 -1
  29. package/dist/safe-bash/commands/archive/zip.js.map +1 -1
  30. package/dist/safe-bash/commands/csplit/command.d.ts.map +1 -1
  31. package/dist/safe-bash/commands/csplit/command.js +3 -1
  32. package/dist/safe-bash/commands/csplit/command.js.map +1 -1
  33. package/dist/safe-bash/commands/csplit/index.browser.js +3 -3
  34. package/dist/safe-bash/commands/csplit/internal.d.ts +2 -0
  35. package/dist/safe-bash/commands/csplit/internal.d.ts.map +1 -1
  36. package/dist/safe-bash/commands/csplit/internal.js +12 -0
  37. package/dist/safe-bash/commands/csplit/internal.js.map +1 -1
  38. package/dist/safe-bash/commands/csplit/io.d.ts +4 -2
  39. package/dist/safe-bash/commands/csplit/io.d.ts.map +1 -1
  40. package/dist/safe-bash/commands/csplit/io.js +98 -58
  41. package/dist/safe-bash/commands/csplit/io.js.map +1 -1
  42. package/dist/safe-bash/commands/factor/index.browser.js +2 -2
  43. package/dist/safe-bash/commands/getopt/index.browser.js +2 -2
  44. package/dist/safe-bash/commands/hexdump/index.browser.js +2 -2
  45. package/dist/safe-bash/commands/iconv/index.browser.js +2 -2
  46. package/dist/safe-bash/commands/line-endings/index.browser.js +3 -3
  47. package/dist/safe-bash/commands/llm/index.browser.js +2 -2
  48. package/dist/safe-bash/commands/network/index.browser.js +3 -3
  49. package/dist/safe-bash/commands/pr/index.browser.js +2 -2
  50. package/dist/safe-bash/commands/tsort/index.browser.js +2 -2
  51. package/dist/safe-bash/commands/yq/index.browser.js +2 -2
  52. package/dist/safe-bash/contracts/filesystem.d.ts +1 -1
  53. package/dist/safe-bash/contracts/filesystem.d.ts.map +1 -1
  54. package/dist/safe-bash/contracts/output.d.ts.map +1 -1
  55. package/dist/safe-bash/contracts/output.js +12 -2
  56. package/dist/safe-bash/contracts/output.js.map +1 -1
  57. package/dist/safe-bash/core.browser.js +255 -141
  58. package/dist/safe-bash/core.browser.js.map +3 -3
  59. package/package.json +2 -2
  60. package/dist/safe-bash/chunks/chunk-C7Z2SSTY.js.map +0 -7
  61. /package/dist/safe-bash/chunks/{chunk-XWCSJDGK.js.map → chunk-4V3NGZAG.js.map} +0 -0
  62. /package/dist/safe-bash/chunks/{chunk-ASCV3OWE.js.map → chunk-AWP6Z3RR.js.map} +0 -0
  63. /package/dist/safe-bash/chunks/{chunk-2YHZYNLC.js.map → chunk-DKT746UJ.js.map} +0 -0
  64. /package/dist/safe-bash/chunks/{chunk-6E3FCEJ5.js.map → chunk-F5AOPLRZ.js.map} +0 -0
  65. /package/dist/safe-bash/chunks/{chunk-GA43CRT3.js.map → chunk-FIY2BMTU.js.map} +0 -0
  66. /package/dist/safe-bash/chunks/{chunk-EGLBB57T.js.map → chunk-IDJQT32M.js.map} +0 -0
  67. /package/dist/safe-bash/chunks/{chunk-25GUOTPE.js.map → chunk-QX2X5EC5.js.map} +0 -0
  68. /package/dist/safe-bash/chunks/{chunk-CTE3HGYS.js.map → chunk-VY5N6O6I.js.map} +0 -0
  69. /package/dist/safe-bash/chunks/{chunk-K4RQ7ASH.js.map → chunk-WJWYJDQE.js.map} +0 -0
  70. /package/dist/safe-bash/chunks/{chunk-R4HP2LEO.js.map → chunk-WXUZXY35.js.map} +0 -0
  71. /package/dist/safe-bash/chunks/{chunk-IVJ5JGXZ.js.map → chunk-YFFFBLBC.js.map} +0 -0
@@ -2,39 +2,39 @@ import {
2
2
  createTsortCommand,
3
3
  createTsortCommands,
4
4
  tsortCommands
5
- } from "./chunks/chunk-IVJ5JGXZ.js";
5
+ } from "./chunks/chunk-YFFFBLBC.js";
6
6
  import {
7
7
  createFactorCommand,
8
8
  createFactorCommands,
9
9
  factorCommands
10
- } from "./chunks/chunk-XWCSJDGK.js";
10
+ } from "./chunks/chunk-4V3NGZAG.js";
11
11
  import {
12
12
  createGetoptCommand,
13
13
  createGetoptCommands,
14
14
  getoptCommands
15
- } from "./chunks/chunk-2YHZYNLC.js";
15
+ } from "./chunks/chunk-DKT746UJ.js";
16
16
  import {
17
17
  createHdCommand,
18
18
  createHexdumpCommand,
19
19
  createHexdumpCommands,
20
20
  hexdumpCommands
21
- } from "./chunks/chunk-EGLBB57T.js";
21
+ } from "./chunks/chunk-IDJQT32M.js";
22
22
  import {
23
23
  createIconvCommand,
24
24
  createIconvCommands,
25
25
  iconvCommands
26
- } from "./chunks/chunk-K4RQ7ASH.js";
26
+ } from "./chunks/chunk-WJWYJDQE.js";
27
27
  import {
28
28
  createDos2unixCommand,
29
29
  createLineEndingCommands,
30
30
  createUnix2dosCommand,
31
31
  lineEndingCommands
32
- } from "./chunks/chunk-ASCV3OWE.js";
32
+ } from "./chunks/chunk-AWP6Z3RR.js";
33
33
  import {
34
34
  classify,
35
35
  createLlmCommands,
36
36
  llmCommands
37
- } from "./chunks/chunk-6E3FCEJ5.js";
37
+ } from "./chunks/chunk-F5AOPLRZ.js";
38
38
  import {
39
39
  createElevenLabsProvider,
40
40
  createOpenAiProvider
@@ -54,7 +54,7 @@ import {
54
54
  rawValues,
55
55
  stringify,
56
56
  yqCommands
57
- } from "./chunks/chunk-GA43CRT3.js";
57
+ } from "./chunks/chunk-FIY2BMTU.js";
58
58
  import {
59
59
  Budget,
60
60
  JqError,
@@ -77,7 +77,7 @@ import {
77
77
  createWgetCommand,
78
78
  curlCommands,
79
79
  networkCommands
80
- } from "./chunks/chunk-CTE3HGYS.js";
80
+ } from "./chunks/chunk-VY5N6O6I.js";
81
81
  import {
82
82
  CurlError,
83
83
  cloudflareWorkerNetworkLimits,
@@ -136,20 +136,20 @@ import {
136
136
  exprMatchCeilings,
137
137
  matchEre,
138
138
  withRegexSession
139
- } from "./chunks/chunk-FAA2WXKH.js";
139
+ } from "./chunks/chunk-4JW32W4B.js";
140
140
  import {
141
141
  bindFileOutputBudget,
142
142
  openFileOutput,
143
143
  writeFileOutput
144
- } from "./chunks/chunk-R4HP2LEO.js";
144
+ } from "./chunks/chunk-WXUZXY35.js";
145
145
  import {
146
146
  createPrCommand,
147
147
  createPrCommands,
148
148
  prCommands
149
- } from "./chunks/chunk-25GUOTPE.js";
149
+ } from "./chunks/chunk-QX2X5EC5.js";
150
150
  import {
151
151
  createOutputOperation
152
- } from "./chunks/chunk-C7Z2SSTY.js";
152
+ } from "./chunks/chunk-EUNOVYVT.js";
153
153
  import {
154
154
  PublicDiagnostic,
155
155
  publicDiagnosticMessage
@@ -27147,47 +27147,29 @@ var ZipScope = class {
27147
27147
  };
27148
27148
  async function publishZip(scope, prepared) {
27149
27149
  const { fs, signal } = scope.context;
27150
- const capabilities = await scope.operation(() => fs.capabilitiesFor?.(prepared.output, { signal }) ?? fs.capabilities);
27151
- if (capabilities.atomicRename !== true || capabilities.exclusiveCreate !== true || capabilities.explicitDirectories !== true || capabilities.permissions !== true || !fs.rmdir || (prepared.existing ? !fs.chmod : capabilities.atomicRenameNoReplace !== true)) fail("ZIP publication requires atomic rename, exclusive creation, private directories and mode preservation");
27152
- let directory2;
27153
- let temporary = "";
27154
- let identity2;
27155
- let published = false;
27156
- let collision = false;
27150
+ const capabilities = await scope.operation(() => fs.capabilitiesFor?.(prepared.output, { signal, create: true }) ?? fs.capabilities);
27151
+ if (capabilities.atomicFileStaging !== true || !fs.createStagedFile || !fs.publishStagedFile || !fs.removeStagedFile) fail("ZIP publication requires atomic owned file staging");
27152
+ let staging;
27157
27153
  let failure;
27158
- const checkOwner = async () => {
27159
- const parent = await scope.operation(() => fs.realpath(prepared.parentName, { signal }));
27160
- const owner = directory2 && await scope.stat(directory2.path);
27161
- if (parent !== prepared.parent || !owner || owner.type !== "directory" || !sameIdentity2(owner, directory2.stat)) fail("ZIP temporary ownership changed before mutation");
27162
- };
27163
27154
  const close = retainFileSystemCleanup2(fs, async (cleanup) => {
27164
- if (!directory2 || !hasIdentity(directory2.stat)) return;
27165
- const parent = await cleanup.realpath(prepared.parentName);
27166
- const owner = await cleanup.lstat(directory2.path);
27167
- if (parent !== prepared.parent || owner.type !== "directory" || !sameIdentity2(owner, directory2.stat)) fail("ZIP temporary ownership changed before cleanup");
27168
- if (temporary && !published && !collision) {
27169
- let current;
27170
- try {
27171
- current = await cleanup.lstat(temporary);
27172
- } catch (error) {
27173
- if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") throw error;
27174
- }
27175
- if (current) {
27176
- if (!identity2 || !sameIdentity2(current, identity2) || current.type !== "file" || current.nlink !== 1) fail("ZIP temporary file changed before cleanup");
27177
- await cleanup.rm(temporary);
27178
- }
27155
+ if (staging) {
27156
+ if (!cleanup.removeStagedFile) fail("ZIP atomic cleanup unavailable");
27157
+ await cleanup.removeStagedFile(staging);
27179
27158
  }
27180
- await cleanup.rmdir(directory2.path);
27181
27159
  }, { maxOperations: 16 });
27182
27160
  try {
27183
27161
  for (let attempt = 0; attempt < Math.min(64, scope.limits.maxMembers); attempt++) {
27184
27162
  const path = `${prepared.parent === "/" ? "" : prepared.parent}/.zip-${attempt + 1}`;
27185
27163
  checkPath(path, scope.limits);
27164
+ checkPath(`${path}/archive.zip`, scope.limits);
27186
27165
  if (path === prepared.output) continue;
27187
27166
  try {
27188
27167
  await scope.operation(async () => {
27189
- await fs.mkdir(path, { signal, mode: 448 });
27190
- directory2 = { path, stat: await fs.lstat(path) };
27168
+ staging = await fs.createStagedFile(path, "archive.zip", { type: "file", data: prepared.bytes }, {
27169
+ signal,
27170
+ parent: prepared.parentStat,
27171
+ ...prepared.existing ? { mode: prepared.existing.mode & 4095 } : {}
27172
+ });
27191
27173
  });
27192
27174
  break;
27193
27175
  } catch (error) {
@@ -27195,44 +27177,14 @@ async function publishZip(scope, prepared) {
27195
27177
  if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "EEXIST") throw error;
27196
27178
  }
27197
27179
  }
27198
- if (!directory2) fail("ZIP temporary directory attempt limit exceeded");
27199
- if (directory2.stat.type !== "directory" || !hasIdentity(directory2.stat) || (directory2.stat.mode & 511) !== 448) fail("ZIP temporary directory ownership unavailable");
27200
- temporary = `${directory2.path}/archive.zip`;
27201
- checkPath(temporary, scope.limits);
27202
- await checkOwner();
27203
- await scope.operation(async () => {
27204
- let writeFailure;
27205
- try {
27206
- await fs.writeFile(temporary, prepared.bytes, { signal, flag: "wx", ...prepared.existing ? { mode: prepared.existing.mode & 4095 } : {} });
27207
- } catch (error) {
27208
- collision = typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
27209
- writeFailure = { reason: error };
27210
- }
27211
- if (!collision) {
27212
- await checkOwner();
27213
- try {
27214
- identity2 = await fs.lstat(temporary);
27215
- } catch (error) {
27216
- if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") throw error;
27217
- }
27218
- }
27219
- if (writeFailure) throw writeFailure.reason;
27220
- });
27221
- if (!identity2 || !hasIdentity(identity2) || identity2.type !== "file" || identity2.nlink !== 1 || identity2.size !== prepared.bytes.length) fail("ZIP staged archive identity or size changed");
27222
- if (prepared.existing) {
27223
- await checkOwner();
27224
- await scope.operation(() => fs.chmod(temporary, prepared.existing.mode & 4095, { signal }));
27225
- }
27180
+ if (!staging) fail("ZIP temporary directory attempt limit exceeded");
27226
27181
  const parent = await scope.operation(() => fs.realpath(prepared.parentName, { signal }));
27227
- const current = await scope.stat(prepared.output);
27228
- if (parent !== prepared.parent || (prepared.existing ? !current || !sameIdentity2(prepared.existing, current) || current.type !== "file" || current.nlink !== 1 || current.size !== prepared.existing.size || current.mode !== prepared.existing.mode || current.mtimeMs !== prepared.existing.mtimeMs || current.ctimeMs !== prepared.existing.ctimeMs : current !== void 0)) fail("archive backing entry changed before publication");
27229
- const staging = await scope.stat(temporary);
27230
- const owner = await scope.stat(directory2.path);
27231
- if (!staging || !sameIdentity2(staging, identity2) || staging.type !== "file" || staging.nlink !== 1 || staging.size !== prepared.bytes.length || !owner || !sameIdentity2(owner, directory2.stat) || owner.type !== "directory") fail("ZIP temporary ownership changed before publication");
27232
- await scope.operation(async () => {
27233
- await fs.rename(temporary, prepared.output, { signal, ...!prepared.existing ? { noReplace: true } : {} });
27234
- published = true;
27235
- });
27182
+ if (parent !== prepared.parent) fail("archive parent changed before publication");
27183
+ await scope.operation(() => fs.publishStagedFile(staging, prepared.output, {
27184
+ signal,
27185
+ parent: prepared.parentStat,
27186
+ destination: prepared.existing ?? null
27187
+ }));
27236
27188
  } catch (error) {
27237
27189
  failure = { reason: error };
27238
27190
  }
@@ -27318,6 +27270,7 @@ async function prepare(scope, parsed, budget) {
27318
27270
  const outputName = vfsPath(context2.cwd, parsed.archive);
27319
27271
  const parentName = dirname(outputName);
27320
27272
  const parent = await scope.operation(() => context2.fs.realpath(parentName, { signal: context2.signal }));
27273
+ const parentStat = await scope.operation(() => context2.fs.lstat(parent, { signal: context2.signal }));
27321
27274
  const output2 = `${parent === "/" ? "" : parent}/${outputName.slice(outputName.lastIndexOf("/") + 1)}`;
27322
27275
  checkPath(output2, limits);
27323
27276
  const existing2 = await scope.stat(output2);
@@ -27443,7 +27396,7 @@ async function prepare(scope, parsed, budget) {
27443
27396
  append(entry, false);
27444
27397
  }
27445
27398
  const bytes3 = await writeZipArchive({ entries: entries2, comment: archive.comment }, limits, context2.signal);
27446
- return { output: output2, parentName, parent, existing: existing2, bytes: bytes3, progress };
27399
+ return { output: output2, parentName, parent, parentStat, existing: existing2, bytes: bytes3, progress };
27447
27400
  }
27448
27401
  function createZipCommand(options2 = {}) {
27449
27402
  const limits = settings2(options2);
@@ -27758,13 +27711,25 @@ var Extraction = class {
27758
27711
  const { fs, signal } = this.context;
27759
27712
  for (const component of raw.split("/")) {
27760
27713
  if (!component || component === ".") continue;
27714
+ const parent = await this.operation(() => fs.lstat(current, { signal }));
27761
27715
  current = resolvePath(current, component);
27762
27716
  const stat = await this.stat(current);
27763
- if (!stat && create) await this.operation(() => fs.mkdir(current, { signal, mode: 493 }));
27717
+ if (!stat && create) await this.createDirectory(current, parent);
27764
27718
  else if (!stat || stat.type !== "directory") fail(`unsafe non-directory or symlink ancestor: ${display(current)}`);
27765
27719
  }
27766
27720
  return current;
27767
27721
  }
27722
+ async createDirectory(path, parent) {
27723
+ const { fs, signal } = this.context;
27724
+ const capabilities = await this.operation(async () => await fs.capabilitiesFor?.(path, { signal, create: true }) ?? fs.capabilities);
27725
+ if (capabilities.atomicDirectoryMetadata !== true || !fs.prepareDirectory) fail("extraction requires atomic directory creation");
27726
+ return this.operation(() => fs.prepareDirectory(path, {
27727
+ signal,
27728
+ parent,
27729
+ expected: null,
27730
+ ...capabilities.permissions === false ? {} : { mode: 493 }
27731
+ }));
27732
+ }
27768
27733
  async parents(root, path, create) {
27769
27734
  if (!isPathWithin(root, path)) fail("extraction path escapes root");
27770
27735
  await this.directory(dirname(path), create);
@@ -27828,74 +27793,65 @@ var Extraction = class {
27828
27793
  const current = await this.stat(path);
27829
27794
  if (!current || current.type !== expected.type || !sameIdentity2(current, expected)) fail("extraction entry changed before mutation");
27830
27795
  }
27831
- async metadata(root, path, identity2, mode, modified) {
27796
+ async metadata(root, path, identity2, parent, mode, modified) {
27832
27797
  const { fs, signal } = this.context;
27833
- if (fs.chmod && fs.capabilities.permissions !== false) {
27834
- await this.checked(root, path, identity2);
27835
- await this.operation(() => fs.chmod(path, mode & 511, { signal }));
27836
- }
27837
- if (fs.utimes && fs.capabilities.timestamps !== false) {
27838
- await this.checked(root, path, identity2);
27839
- await this.operation(() => fs.utimes(path, modified.getTime(), modified.getTime(), { signal }));
27840
- }
27798
+ await this.parents(root, path, false);
27799
+ const capabilities = await this.operation(async () => await fs.capabilitiesFor?.(path, { signal }) ?? fs.capabilities);
27800
+ if (capabilities.permissions === false && capabilities.timestamps === false) return;
27801
+ if (capabilities.atomicDirectoryMetadata !== true || !fs.prepareDirectory) fail("extraction metadata requires atomic entry conditions");
27802
+ await this.operation(() => fs.prepareDirectory(path, {
27803
+ signal,
27804
+ expected: identity2,
27805
+ parent,
27806
+ ...capabilities.permissions === false ? {} : { mode: mode & 511 },
27807
+ ...capabilities.timestamps === false ? {} : { atimeMs: modified.getTime(), mtimeMs: modified.getTime() }
27808
+ }));
27841
27809
  }
27842
- publish(root, path, chunks, expected, mode, modified, target) {
27843
- const publication = this.stage(root, path, chunks, expected, mode, modified, target);
27810
+ publish(root, path, chunks, expected, parent, mode, modified, target) {
27811
+ const publication = this.stage(root, path, chunks, expected, parent, mode, modified, target);
27844
27812
  this.publications.add(publication);
27845
27813
  return publication.finally(() => {
27846
27814
  this.publications.delete(publication);
27847
27815
  });
27848
27816
  }
27849
- async stage(root, path, chunks, expected, mode, modified, target) {
27817
+ async stage(root, path, chunks, expected, parent, mode, modified, target) {
27850
27818
  const { fs, signal } = this.context;
27851
- let temporary = "";
27852
- let identity2;
27853
- let created = false;
27819
+ const capabilities = await this.operation(async () => await fs.capabilitiesFor?.(path, { signal, create: true }) ?? fs.capabilities);
27820
+ if (capabilities.atomicFileStaging !== true || !fs.createStagedFile || !fs.publishStagedFile || !fs.removeStagedFile) fail("extraction requires atomic owned file staging");
27821
+ let staging;
27854
27822
  let failure;
27855
27823
  const cleanup = retainFileSystemCleanup3(fs, async (view) => {
27856
- if (!created || !identity2) return;
27857
- try {
27858
- let parent = "/";
27859
- for (const component of dirname(temporary).split("/").filter(Boolean)) {
27860
- parent = resolvePath(parent, component);
27861
- if ((await view.lstat(parent)).type !== "directory") return;
27862
- }
27863
- const current = await view.lstat(temporary);
27864
- if (current.type === identity2.type && sameIdentity2(current, identity2)) await view.rm(temporary);
27865
- } catch (error) {
27866
- if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") throw error;
27824
+ if (staging) {
27825
+ if (!view.removeStagedFile) fail("extraction atomic cleanup unavailable");
27826
+ await view.removeStagedFile(staging);
27867
27827
  }
27868
27828
  }, { maxOperations: Math.min(4096, this.limits.maxDepth + 3) });
27869
27829
  try {
27870
- await this.parents(root, path, true);
27830
+ await this.parents(root, path, false);
27831
+ const content = target === void 0 ? { type: "file", data: import_buffer.Buffer.concat(chunks) } : { type: "symlink", target };
27871
27832
  for (let attempt = 0; attempt < this.limits.maxMembers; attempt++) {
27872
- temporary = resolvePath(dirname(path), `.unzip-${++this.serial}`);
27833
+ const temporary = resolvePath(dirname(path), `.unzip-${++this.serial}`);
27873
27834
  checkPath(temporary, this.limits);
27874
- if (temporary === path || await this.stat(temporary)) continue;
27875
- await this.operation(async () => {
27876
- if (target === void 0) await fs.writeFile(temporary, new Uint8Array(), { signal, flag: "wx", mode: 384 });
27877
- else await fs.symlink(target, temporary, { signal });
27878
- created = true;
27879
- identity2 = await fs.lstat(temporary);
27880
- });
27881
- if (!identity2 || !hasIdentity(identity2)) fail("temporary file backing identity unavailable");
27882
- break;
27883
- }
27884
- if (!created) fail("temporary file attempt limit exceeded");
27885
- if (target === void 0) {
27886
- for (const chunk of chunks) {
27887
- await this.checked(root, temporary, identity2);
27888
- await this.operation(() => fs.appendFile(temporary, chunk, { signal }));
27835
+ checkPath(`${temporary}/entry`, this.limits);
27836
+ if (temporary === path) continue;
27837
+ try {
27838
+ await this.operation(async () => {
27839
+ staging = await fs.createStagedFile(temporary, "entry", content, {
27840
+ signal,
27841
+ parent,
27842
+ ...target !== void 0 || capabilities.permissions === false ? {} : { mode: mode & 511 },
27843
+ ...target !== void 0 || capabilities.timestamps === false ? {} : { atimeMs: modified.getTime(), mtimeMs: modified.getTime() }
27844
+ });
27845
+ });
27846
+ break;
27847
+ } catch (error) {
27848
+ signal.throwIfAborted();
27849
+ if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "EEXIST") throw error;
27889
27850
  }
27890
- await this.metadata(root, temporary, identity2, mode, modified);
27891
27851
  }
27852
+ if (!staging) fail("temporary file attempt limit exceeded");
27892
27853
  await this.parents(root, path, false);
27893
- const current = await this.stat(path);
27894
- if (current ? !expected || !sameIdentity2(current, expected) || current.type !== "file" : expected !== void 0) fail("destination changed before publication");
27895
- const staging = await this.stat(temporary);
27896
- if (!staging || !identity2 || !sameIdentity2(staging, identity2) || staging.type !== (target === void 0 ? "file" : "symlink")) fail("temporary file changed before publication");
27897
- await this.operation(() => fs.rename(temporary, path, { signal }));
27898
- created = false;
27854
+ await this.operation(() => fs.publishStagedFile(staging, path, { signal, parent, destination: expected ?? null }));
27899
27855
  } catch (error) {
27900
27856
  failure = { reason: error };
27901
27857
  }
@@ -28032,18 +27988,20 @@ function createUnzipCommand(options2 = {}) {
28032
27988
  if (chunk.length) fail("directory has nonempty payload");
28033
27989
  });
28034
27990
  }
27991
+ const parent2 = await extraction.operation(() => context2.fs.lstat(dirname(path), { signal: context2.signal }));
28035
27992
  const existing3 = await extraction.stat(path);
27993
+ let identity2 = existing3;
28036
27994
  if (existing3 && existing3.type !== "directory") fail("directory destination is not a directory");
28037
27995
  if (!existing3) {
28038
- await extraction.operation(() => context2.fs.mkdir(path, { signal: context2.signal, mode: 493 }));
27996
+ identity2 = await extraction.createDirectory(path, parent2);
28039
27997
  await budget.output(` creating: ${filtered(shown)}
28040
27998
  `);
28041
27999
  }
28042
- const identity2 = await extraction.stat(path);
28043
28000
  if (!identity2 || identity2.type !== "directory") fail("directory changed during creation");
28044
- directories.push({ path, entry, identity: identity2 });
28001
+ directories.push({ path, entry, identity: identity2, parent: parent2 });
28045
28002
  continue;
28046
28003
  }
28004
+ let parent = await extraction.operation(() => context2.fs.lstat(dirname(path), { signal: context2.signal }));
28047
28005
  let existing2 = await extraction.destination(path, archivePath, archiveStat);
28048
28006
  let skip = false;
28049
28007
  let prompting = 0;
@@ -28084,6 +28042,7 @@ function createUnzipCommand(options2 = {}) {
28084
28042
  path = extraction.member(root, renamed);
28085
28043
  shown = parsed.destination === void 0 ? renamed : `${parsed.destination.endsWith("/") ? parsed.destination : `${parsed.destination}/`}${renamed}`;
28086
28044
  await extraction.parents(root, path, true);
28045
+ parent = await extraction.operation(() => context2.fs.lstat(dirname(path), { signal: context2.signal }));
28087
28046
  existing2 = await extraction.destination(path, archivePath, archiveStat);
28088
28047
  continue;
28089
28048
  }
@@ -28107,11 +28066,11 @@ function createUnzipCommand(options2 = {}) {
28107
28066
  const target = text2(import_buffer.Buffer.concat(chunks));
28108
28067
  await extraction.target(root, path, target);
28109
28068
  if (!context2.fs.symlink || context2.fs.capabilities.symlinks === false) fail("filesystem does not support symlinks");
28110
- links.push({ path, shown, target, existing: existing2, entry });
28069
+ links.push({ path, shown, target, existing: existing2, parent, entry });
28111
28070
  await budget.output(` linking: ${padded(filtered(shown))} -> ${filtered(target)}
28112
28071
  `);
28113
28072
  } else {
28114
- await extraction.publish(root, path, chunks, existing2, entry.mode, entry.modified);
28073
+ await extraction.publish(root, path, chunks, existing2, parent, entry.mode, entry.modified);
28115
28074
  await budget.output(`${entry.method === 0 ? " extracting" : " inflating"}: ${padded(filtered(shown))}
28116
28075
  `);
28117
28076
  }
@@ -28125,12 +28084,12 @@ ${String(total).padStart(9)} ${selected} file${selected ===
28125
28084
  await extraction.parents(root, link.path, false);
28126
28085
  await extraction.target(root, link.path, link.target);
28127
28086
  await extraction.destination(link.path, archivePath, archiveStat);
28128
- await extraction.publish(root, link.path, [], link.existing, link.entry.mode, link.entry.modified, link.target);
28087
+ await extraction.publish(root, link.path, [], link.existing, link.parent, link.entry.mode, link.entry.modified, link.target);
28129
28088
  await budget.output(` ${padded(filtered(link.shown))} -> ${filtered(link.target)}
28130
28089
  `);
28131
28090
  }
28132
- for (const { path, entry, identity: identity2 } of directories.reverse()) {
28133
- await extraction.metadata(root, path, identity2, entry.mode, entry.modified);
28091
+ for (const { path, entry, identity: identity2, parent } of directories.reverse()) {
28092
+ await extraction.metadata(root, path, identity2, parent, entry.mode, entry.modified);
28134
28093
  }
28135
28094
  for (let index = 0; index < parsed.patterns.length; index++) if (!selection.matched.has(index)) {
28136
28095
  await budget.output(`caution: filename not matched: ${filtered(parsed.patterns[index])}
@@ -49342,7 +49301,7 @@ init_platform();
49342
49301
  // packages/safe-js/dist/browser/safe-fs.js
49343
49302
  init_platform();
49344
49303
 
49345
- // packages/safe-js/dist/browser/chunks/chunk-BAO3TSWI.js
49304
+ // packages/safe-js/dist/browser/chunks/chunk-SB2GDI2R.js
49346
49305
  init_platform();
49347
49306
  var platform = Object.freeze({
49348
49307
  errno(_code) {
@@ -50015,6 +49974,9 @@ var MemoryFileSystem = class _MemoryFileSystem {
50015
49974
  permissions: true,
50016
49975
  timestamps: true,
50017
49976
  atomicRename: true,
49977
+ atomicFileStaging: true,
49978
+ atomicFileMutation: true,
49979
+ atomicDirectoryMetadata: true,
50018
49980
  streamingRead: true,
50019
49981
  retainedRead: true,
50020
49982
  get retainedResize() {
@@ -50067,6 +50029,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50067
50029
  ino: this.nextInode++,
50068
50030
  nlink: 1,
50069
50031
  references: 0,
50032
+ revision: 0,
50070
50033
  atimeMs: now,
50071
50034
  mtimeMs: now,
50072
50035
  ctimeMs: now,
@@ -50124,6 +50087,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50124
50087
  if (!Number.isSafeInteger(value2) || value2 < 0) this.fail("EINVAL", syscall, path);
50125
50088
  }
50126
50089
  changed(node) {
50090
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50127
50091
  node.mtimeMs = node.ctimeMs = Date.now();
50128
50092
  }
50129
50093
  resolve(path, syscall, options2 = {}) {
@@ -50192,6 +50156,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50192
50156
  snapshot(node) {
50193
50157
  return {
50194
50158
  type: node.type,
50159
+ ...Number.isSafeInteger(node.revision) ? { revision: node.revision } : {},
50195
50160
  preferredIoBlockSize: 4096,
50196
50161
  size: node.type === "file" ? node.data.byteLength : node.type === "symlink" ? new TextEncoder().encode(node.target).byteLength : 0,
50197
50162
  mode: node.mode,
@@ -50333,6 +50298,145 @@ var MemoryFileSystem = class _MemoryFileSystem {
50333
50298
  node.atimeMs = Date.now();
50334
50299
  return new Uint8Array(node.data);
50335
50300
  }
50301
+ expectEntry(node, expected, path, unchanged5 = true) {
50302
+ if (expected === null) {
50303
+ if (node) this.fail("EAGAIN", "fileStaging", path);
50304
+ return;
50305
+ }
50306
+ if (!node) this.fail("EAGAIN", "fileStaging", path);
50307
+ const current = this.snapshot(node);
50308
+ if (!expected.identityScope || expected.identityScope !== current.identityScope || !Number.isSafeInteger(expected.ino) || !Number.isSafeInteger(expected.dev)) this.fail("ENOTSUP", "fileStaging", path);
50309
+ if (current.ino !== expected.ino || current.dev !== expected.dev || current.type !== expected.type) this.fail("EAGAIN", "fileStaging", path);
50310
+ if (unchanged5) {
50311
+ if (!Number.isSafeInteger(expected.revision) || !Number.isSafeInteger(current.revision)) this.fail("ENOTSUP", "fileStaging", path);
50312
+ if (current.revision !== expected.revision || current.size !== expected.size || current.mode !== expected.mode || current.nlink !== expected.nlink || current.mtimeMs !== expected.mtimeMs || current.ctimeMs !== expected.ctimeMs) this.fail("EAGAIN", "fileStaging", path);
50313
+ }
50314
+ }
50315
+ stagingLocations(staging) {
50316
+ const parent = this.entry(staging.parent.path, "fileStaging");
50317
+ this.expectEntry(parent.node, staging.parent.stat, staging.parent.path, false);
50318
+ if (parent.node.type !== "directory") this.fail("ENOTDIR", "fileStaging", staging.parent.path);
50319
+ const directory2 = this.entry(staging.directory.path, "fileStaging");
50320
+ this.expectEntry(directory2.node, staging.directory.stat, staging.directory.path, false);
50321
+ if (directory2.parent !== parent.node || directory2.node.type !== "directory" || (directory2.node.mode & 511) !== 448) this.fail("EAGAIN", "fileStaging", staging.directory.path);
50322
+ const file = this.entry(staging.file.path, "fileStaging", true);
50323
+ if (file.parent !== directory2.node || !["file", "symlink"].includes(staging.file.stat.type)) this.fail("EAGAIN", "fileStaging", staging.file.path);
50324
+ return { directory: directory2, file };
50325
+ }
50326
+ async createStagedFile(directoryPath, name2, content, options2) {
50327
+ options2.signal?.throwIfAborted();
50328
+ if (!name2 || name2 === "." || name2 === ".." || name2.includes("/") || name2.includes("\0")) this.fail("EINVAL", "createStagedFile", directoryPath);
50329
+ const location = this.entry(directoryPath, "createStagedFile", true);
50330
+ if (location.node) this.fail("EEXIST", "createStagedFile", directoryPath);
50331
+ this.expectEntry(location.parent, options2.parent, directoryPath, false);
50332
+ this.permission(location.parent, 3, "createStagedFile", directoryPath);
50333
+ const mode2 = this.mode(options2.mode, content.type === "file" ? 438 : 511, "createStagedFile", directoryPath);
50334
+ for (const time of [options2.atimeMs, options2.mtimeMs]) if (time !== void 0 && !Number.isFinite(time)) this.fail("EINVAL", "createStagedFile", directoryPath);
50335
+ if (content.type === "file" && !(content.data instanceof Uint8Array)) throw new TypeError("Staged files require Uint8Array data");
50336
+ if (content.type === "symlink") this.validatePath(content.target, "createStagedFile");
50337
+ const retained = (location.name.length + name2.length) * 2 + (content.type === "symlink" ? content.target.length * 2 : 0);
50338
+ this.ledger.reserve(retained, 4, "createStagedFile", directoryPath);
50339
+ let allocation;
50340
+ let directory2;
50341
+ let file;
50342
+ try {
50343
+ if (content.type === "file") allocation = this.bytes(content.data, "createStagedFile", directoryPath);
50344
+ directory2 = this.directory(448);
50345
+ file = content.type === "file" ? { ...this.metadata(typeModes.file | mode2), type: "file", data: allocation.data, allocation } : { ...this.metadata(typeModes.symlink | mode2), type: "symlink", target: content.target };
50346
+ if (options2.atimeMs !== void 0) file.atimeMs = options2.atimeMs;
50347
+ if (options2.mtimeMs !== void 0) file.mtimeMs = options2.mtimeMs;
50348
+ directory2.entries.set(name2, file);
50349
+ location.parent.entries.set(location.name, directory2);
50350
+ } catch (error) {
50351
+ allocation?.release();
50352
+ this.ledger.release(retained, 4);
50353
+ throw error;
50354
+ }
50355
+ this.changed(location.parent);
50356
+ const parentPath = location.path.slice(0, location.path.lastIndexOf("/")) || "/";
50357
+ const receipt = (path, node) => Object.freeze({ path, stat: Object.freeze(this.snapshot(node)) });
50358
+ return Object.freeze({ parent: receipt(parentPath, location.parent), directory: receipt(location.path, directory2), file: receipt(`${location.path}/${name2}`, file) });
50359
+ }
50360
+ async publishStagedFile(staging, destination2, options2) {
50361
+ options2.signal?.throwIfAborted();
50362
+ const { directory: directory2, file } = this.stagingLocations(staging);
50363
+ this.expectEntry(file.node, staging.file.stat, staging.file.path);
50364
+ const target = this.entry(destination2, "publishStagedFile", true);
50365
+ this.expectEntry(target.parent, options2.parent, destination2, false);
50366
+ this.expectEntry(target.node, options2.destination, destination2);
50367
+ if (target.parent === directory2.node || target.node === directory2.node || target.node === file.node) this.fail("EINVAL", "publishStagedFile", destination2);
50368
+ if (target.node && (target.node.type !== "file" || target.node.nlink !== 1)) this.fail("EAGAIN", "publishStagedFile", destination2);
50369
+ return _MemoryFileSystem.prototype.rename.call(this, staging.file.path, destination2, { ...options2, noReplace: options2.destination === null });
50370
+ }
50371
+ async removeStagedFile(staging, options2 = {}) {
50372
+ options2.signal?.throwIfAborted();
50373
+ const { directory: directory2, file } = this.stagingLocations(staging);
50374
+ if (file.node) this.expectEntry(file.node, staging.file.stat, staging.file.path);
50375
+ const node = directory2.node;
50376
+ if (node.entries.size !== (file.node ? 1 : 0)) this.fail("ENOTEMPTY", "removeStagedFile", staging.directory.path);
50377
+ this.permission(directory2.parent, 3, "removeStagedFile", staging.directory.path);
50378
+ this.permission(node, 3, "removeStagedFile", staging.file.path);
50379
+ directory2.parent.entries.delete(directory2.name);
50380
+ if (file.node) {
50381
+ node.entries.delete(file.name);
50382
+ this.ledger.release(file.name.length * 2, 1);
50383
+ file.node.nlink--;
50384
+ file.node.ctimeMs = Date.now();
50385
+ file.node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, file.node.revision + 1);
50386
+ this.releaseNode(file.node);
50387
+ }
50388
+ this.ledger.release(directory2.name.length * 2, 1);
50389
+ node.nlink = 0;
50390
+ node.ctimeMs = Date.now();
50391
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50392
+ this.releaseNode(node);
50393
+ this.changed(directory2.parent);
50394
+ }
50395
+ async prepareDirectory(path, options2) {
50396
+ options2.signal?.throwIfAborted();
50397
+ const location = this.entry(path, "prepareDirectory", true);
50398
+ this.expectEntry(location.parent, options2.parent, path, false);
50399
+ this.expectEntry(location.node, options2.expected, path, false);
50400
+ const mode2 = options2.mode === void 0 ? void 0 : this.mode(options2.mode, 0, "prepareDirectory", path);
50401
+ for (const time of [options2.atimeMs, options2.mtimeMs]) if (time !== void 0 && !Number.isFinite(time)) this.fail("EINVAL", "prepareDirectory", path);
50402
+ let node = location.node;
50403
+ if (!node) {
50404
+ this.permission(location.parent, 3, "prepareDirectory", path);
50405
+ node = this.addNode(location.parent, location.name, () => this.directory(mode2 ?? 511), "prepareDirectory", path);
50406
+ }
50407
+ if (node.type !== "directory") this.fail("ENOTDIR", "prepareDirectory", path);
50408
+ if (mode2 !== void 0) node.mode = typeModes.directory | mode2;
50409
+ if (options2.atimeMs !== void 0) node.atimeMs = options2.atimeMs;
50410
+ if (options2.mtimeMs !== void 0) node.mtimeMs = options2.mtimeMs;
50411
+ node.ctimeMs = Date.now();
50412
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50413
+ return Object.freeze(this.snapshot(node));
50414
+ }
50415
+ async writeFileConditional(path, data2, options2) {
50416
+ options2.signal?.throwIfAborted();
50417
+ const location = this.entry(path, "writeFileConditional", true);
50418
+ this.expectEntry(location.parent, options2.parent, path, false);
50419
+ this.expectEntry(location.node, options2.expected, path);
50420
+ if (location.node && location.node.type !== "file") this.fail("EINVAL", "writeFileConditional", path);
50421
+ this.writeData(path, data2, { ...options2.mode === void 0 ? {} : { mode: options2.mode }, flag: options2.append ? "a" : "w" }, "writeFileConditional");
50422
+ return Object.freeze(this.snapshot(location.parent.entries.get(location.name)));
50423
+ }
50424
+ async removeFileConditional(path, options2) {
50425
+ options2.signal?.throwIfAborted();
50426
+ const location = this.entry(path, "removeFileConditional", true);
50427
+ this.expectEntry(location.parent, options2.parent, path, false);
50428
+ this.expectEntry(location.node, options2.expected, path);
50429
+ const node = location.node;
50430
+ if (node.type !== "file") this.fail("EINVAL", "removeFileConditional", path);
50431
+ this.permission(location.parent, 3, "removeFileConditional", path);
50432
+ location.parent.entries.delete(location.name);
50433
+ this.ledger.release(location.name.length * 2, 1);
50434
+ node.nlink--;
50435
+ node.ctimeMs = Date.now();
50436
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50437
+ this.releaseNode(node);
50438
+ this.changed(location.parent);
50439
+ }
50336
50440
  async writeFile(path, data2, options2 = {}) {
50337
50441
  options2.signal?.throwIfAborted();
50338
50442
  this.writeData(path, data2, options2, "writeFile");
@@ -50387,6 +50491,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50387
50491
  this.ledger.release(location.name.length * 2, 1);
50388
50492
  node.nlink = 0;
50389
50493
  node.ctimeMs = Date.now();
50494
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50390
50495
  this.releaseNode(node);
50391
50496
  this.changed(location.parent);
50392
50497
  }
@@ -50421,6 +50526,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50421
50526
  }
50422
50527
  entry.nlink--;
50423
50528
  entry.ctimeMs = Date.now();
50529
+ entry.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, entry.revision + 1);
50424
50530
  this.releaseNode(entry);
50425
50531
  }
50426
50532
  this.changed(location.parent);
@@ -50457,11 +50563,13 @@ var MemoryFileSystem = class _MemoryFileSystem {
50457
50563
  this.ledger.release(origin.name.length * 2, 1);
50458
50564
  target.node.nlink--;
50459
50565
  target.node.ctimeMs = Date.now();
50566
+ target.node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, target.node.revision + 1);
50460
50567
  this.releaseNode(target.node);
50461
50568
  } else if (nameGrowth < 0) this.ledger.release(-nameGrowth, 0);
50462
50569
  this.changed(origin.parent);
50463
50570
  this.changed(target.parent);
50464
50571
  node.ctimeMs = Date.now();
50572
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50465
50573
  } catch (error) {
50466
50574
  if (error instanceof FsError2) throw new FsError2(error.code, { syscall: "rename", path: source2, dest: destination2, cause: error });
50467
50575
  throw error;
@@ -50527,6 +50635,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50527
50635
  }
50528
50636
  node.nlink++;
50529
50637
  node.ctimeMs = Date.now();
50638
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50530
50639
  this.changed(target.parent);
50531
50640
  }
50532
50641
  async chmod(path, mode2, options2 = {}) {
@@ -50535,6 +50644,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50535
50644
  const node = this.resolve(path, "chmod").node;
50536
50645
  node.mode = typeModes[node.type] | permissions;
50537
50646
  node.ctimeMs = Date.now();
50647
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50538
50648
  }
50539
50649
  async utimes(path, atimeMs, mtimeMs, options2 = {}) {
50540
50650
  options2.signal?.throwIfAborted();
@@ -50543,6 +50653,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50543
50653
  node.atimeMs = atimeMs;
50544
50654
  node.mtimeMs = mtimeMs;
50545
50655
  node.ctimeMs = Date.now();
50656
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50546
50657
  }
50547
50658
  async truncate(path, length = 0, options2 = {}) {
50548
50659
  options2.signal?.throwIfAborted();
@@ -50831,6 +50942,9 @@ var deviceCapabilities = Object.freeze({
50831
50942
  timestamps: false,
50832
50943
  truncate: false,
50833
50944
  randomAccessWrite: false,
50945
+ atomicFileMutation: false,
50946
+ atomicFileStaging: false,
50947
+ atomicDirectoryMetadata: false,
50834
50948
  atomicRename: false,
50835
50949
  atomicRenameNoReplace: false,
50836
50950
  descriptorWriteStream: true,