@poe-platform/safe-bash 0.1.546 → 0.1.548

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 (141) hide show
  1. package/README.md +1 -1
  2. package/dist/safe-bash/chunks/{chunk-UO33SQJU.js → chunk-2PQ3XOCQ.js} +239 -2
  3. package/dist/safe-bash/chunks/chunk-2PQ3XOCQ.js.map +7 -0
  4. package/dist/safe-bash/chunks/{chunk-WISNTI7E.js → chunk-3Y5PKSHX.js} +7 -11
  5. package/dist/safe-bash/chunks/{chunk-WISNTI7E.js.map → chunk-3Y5PKSHX.js.map} +1 -1
  6. package/dist/safe-bash/chunks/{chunk-VY5N6O6I.js → chunk-BXVGCJXW.js} +108 -21
  7. package/dist/safe-bash/chunks/chunk-BXVGCJXW.js.map +7 -0
  8. package/dist/safe-bash/chunks/chunk-C7QNJ3D4.js +13 -0
  9. package/dist/safe-bash/chunks/chunk-C7QNJ3D4.js.map +7 -0
  10. package/dist/safe-bash/chunks/{chunk-AWP6Z3RR.js → chunk-E3NZKSTA.js} +8 -12
  11. package/dist/safe-bash/chunks/{chunk-AWP6Z3RR.js.map → chunk-E3NZKSTA.js.map} +1 -1
  12. package/dist/safe-bash/chunks/{chunk-WXUZXY35.js → chunk-FMTBJ7SG.js} +3 -3
  13. package/dist/safe-bash/chunks/{chunk-QX2X5EC5.js → chunk-H6E6F5KJ.js} +7 -11
  14. package/dist/safe-bash/chunks/{chunk-QX2X5EC5.js.map → chunk-H6E6F5KJ.js.map} +1 -1
  15. package/dist/safe-bash/chunks/{chunk-IDJQT32M.js → chunk-HQCBEAFK.js} +7 -11
  16. package/dist/safe-bash/chunks/{chunk-IDJQT32M.js.map → chunk-HQCBEAFK.js.map} +1 -1
  17. package/dist/safe-bash/chunks/{chunk-4V3NGZAG.js → chunk-IYFB6VED.js} +6 -10
  18. package/dist/safe-bash/chunks/{chunk-4V3NGZAG.js.map → chunk-IYFB6VED.js.map} +1 -1
  19. package/dist/safe-bash/chunks/chunk-KJYVSFGF.js +284 -0
  20. package/dist/safe-bash/chunks/chunk-KJYVSFGF.js.map +7 -0
  21. package/dist/safe-bash/chunks/{chunk-O7BRWSKX.js → chunk-LHKAA57T.js} +60 -17
  22. package/dist/safe-bash/chunks/chunk-LHKAA57T.js.map +7 -0
  23. package/dist/safe-bash/chunks/chunk-LR32SJ3D.js +915 -0
  24. package/dist/safe-bash/chunks/chunk-LR32SJ3D.js.map +7 -0
  25. package/dist/safe-bash/chunks/{chunk-EUNOVYVT.js → chunk-OECKXHVJ.js} +2 -2
  26. package/dist/safe-bash/chunks/{chunk-DKT746UJ.js → chunk-PE5NZIA2.js} +5 -9
  27. package/dist/safe-bash/chunks/{chunk-DKT746UJ.js.map → chunk-PE5NZIA2.js.map} +1 -1
  28. package/dist/safe-bash/chunks/{chunk-X7C3PN2T.js → chunk-PMBBUNNN.js} +168 -114
  29. package/dist/safe-bash/chunks/{chunk-X7C3PN2T.js.map → chunk-PMBBUNNN.js.map} +3 -3
  30. package/dist/safe-bash/chunks/{chunk-YFFFBLBC.js → chunk-TJVKGNKA.js} +6 -10
  31. package/dist/safe-bash/chunks/{chunk-YFFFBLBC.js.map → chunk-TJVKGNKA.js.map} +1 -1
  32. package/dist/safe-bash/chunks/{chunk-FIY2BMTU.js → chunk-W3TLNFDB.js} +8 -12
  33. package/dist/safe-bash/chunks/{chunk-FIY2BMTU.js.map → chunk-W3TLNFDB.js.map} +1 -1
  34. package/dist/safe-bash/chunks/{chunk-PPFWG34Y.js → chunk-XBLVOMEJ.js} +2 -2
  35. package/dist/safe-bash/chunks/{chunk-WJWYJDQE.js → chunk-XYVCXUGM.js} +7 -11
  36. package/dist/safe-bash/chunks/{chunk-WJWYJDQE.js.map → chunk-XYVCXUGM.js.map} +1 -1
  37. package/dist/safe-bash/commands/archive/unzip/safety.d.ts +3 -2
  38. package/dist/safe-bash/commands/archive/unzip/safety.d.ts.map +1 -1
  39. package/dist/safe-bash/commands/archive/unzip/safety.js +57 -62
  40. package/dist/safe-bash/commands/archive/unzip/safety.js.map +1 -1
  41. package/dist/safe-bash/commands/archive/unzip.d.ts.map +1 -1
  42. package/dist/safe-bash/commands/archive/unzip.js +12 -9
  43. package/dist/safe-bash/commands/archive/unzip.js.map +1 -1
  44. package/dist/safe-bash/commands/archive/zip/safety.d.ts +1 -0
  45. package/dist/safe-bash/commands/archive/zip/safety.d.ts.map +1 -1
  46. package/dist/safe-bash/commands/archive/zip/safety.js +19 -87
  47. package/dist/safe-bash/commands/archive/zip/safety.js.map +1 -1
  48. package/dist/safe-bash/commands/archive/zip.d.ts.map +1 -1
  49. package/dist/safe-bash/commands/archive/zip.js +2 -1
  50. package/dist/safe-bash/commands/archive/zip.js.map +1 -1
  51. package/dist/safe-bash/commands/csplit/command.d.ts.map +1 -1
  52. package/dist/safe-bash/commands/csplit/command.js +3 -1
  53. package/dist/safe-bash/commands/csplit/command.js.map +1 -1
  54. package/dist/safe-bash/commands/csplit/index.browser.js +4 -6
  55. package/dist/safe-bash/commands/csplit/internal.d.ts +2 -0
  56. package/dist/safe-bash/commands/csplit/internal.d.ts.map +1 -1
  57. package/dist/safe-bash/commands/csplit/internal.js +12 -0
  58. package/dist/safe-bash/commands/csplit/internal.js.map +1 -1
  59. package/dist/safe-bash/commands/csplit/io.d.ts +4 -2
  60. package/dist/safe-bash/commands/csplit/io.d.ts.map +1 -1
  61. package/dist/safe-bash/commands/csplit/io.js +98 -58
  62. package/dist/safe-bash/commands/csplit/io.js.map +1 -1
  63. package/dist/safe-bash/commands/factor/index.browser.js +3 -5
  64. package/dist/safe-bash/commands/getopt/index.browser.js +3 -5
  65. package/dist/safe-bash/commands/hexdump/index.browser.js +3 -5
  66. package/dist/safe-bash/commands/iconv/index.browser.js +3 -5
  67. package/dist/safe-bash/commands/line-endings/index.browser.js +4 -6
  68. package/dist/safe-bash/commands/llm/command.d.ts +3 -2
  69. package/dist/safe-bash/commands/llm/command.d.ts.map +1 -1
  70. package/dist/safe-bash/commands/llm/command.js +260 -181
  71. package/dist/safe-bash/commands/llm/command.js.map +1 -1
  72. package/dist/safe-bash/commands/llm/elevenlabs-stream.d.ts +3 -0
  73. package/dist/safe-bash/commands/llm/elevenlabs-stream.d.ts.map +1 -0
  74. package/dist/safe-bash/commands/llm/elevenlabs-stream.js +118 -0
  75. package/dist/safe-bash/commands/llm/elevenlabs-stream.js.map +1 -0
  76. package/dist/safe-bash/commands/llm/elevenlabs.d.ts +16 -0
  77. package/dist/safe-bash/commands/llm/elevenlabs.d.ts.map +1 -0
  78. package/dist/safe-bash/commands/llm/elevenlabs.js +120 -0
  79. package/dist/safe-bash/commands/llm/elevenlabs.js.map +1 -0
  80. package/dist/safe-bash/commands/llm/index.browser.js +10 -4
  81. package/dist/safe-bash/commands/llm/index.d.ts +5 -5
  82. package/dist/safe-bash/commands/llm/index.d.ts.map +1 -1
  83. package/dist/safe-bash/commands/llm/index.js +3 -11
  84. package/dist/safe-bash/commands/llm/index.js.map +1 -1
  85. package/dist/safe-bash/commands/llm/mime.d.ts +2 -1
  86. package/dist/safe-bash/commands/llm/mime.d.ts.map +1 -1
  87. package/dist/safe-bash/commands/llm/mime.js +125 -21
  88. package/dist/safe-bash/commands/llm/mime.js.map +1 -1
  89. package/dist/safe-bash/commands/llm/openai-http.d.ts +9 -0
  90. package/dist/safe-bash/commands/llm/openai-http.d.ts.map +1 -0
  91. package/dist/safe-bash/commands/llm/openai-http.js +144 -0
  92. package/dist/safe-bash/commands/llm/openai-http.js.map +1 -0
  93. package/dist/safe-bash/commands/llm/openai-sse.d.ts +3 -0
  94. package/dist/safe-bash/commands/llm/openai-sse.d.ts.map +1 -0
  95. package/dist/safe-bash/commands/llm/openai-sse.js +67 -0
  96. package/dist/safe-bash/commands/llm/openai-sse.js.map +1 -0
  97. package/dist/safe-bash/commands/llm/openai.d.ts +15 -0
  98. package/dist/safe-bash/commands/llm/openai.d.ts.map +1 -0
  99. package/dist/safe-bash/commands/llm/openai.js +203 -0
  100. package/dist/safe-bash/commands/llm/openai.js.map +1 -0
  101. package/dist/safe-bash/commands/llm/providers/elevenlabs.d.ts +1 -15
  102. package/dist/safe-bash/commands/llm/providers/elevenlabs.d.ts.map +1 -1
  103. package/dist/safe-bash/commands/llm/providers/elevenlabs.js +1 -50
  104. package/dist/safe-bash/commands/llm/providers/elevenlabs.js.map +1 -1
  105. package/dist/safe-bash/commands/llm/providers/index.browser.js +2 -4
  106. package/dist/safe-bash/commands/llm/providers/openai.d.ts +1 -14
  107. package/dist/safe-bash/commands/llm/providers/openai.d.ts.map +1 -1
  108. package/dist/safe-bash/commands/llm/providers/openai.js +1 -77
  109. package/dist/safe-bash/commands/llm/providers/openai.js.map +1 -1
  110. package/dist/safe-bash/commands/llm/providers/shared.d.ts +4 -14
  111. package/dist/safe-bash/commands/llm/providers/shared.d.ts.map +1 -1
  112. package/dist/safe-bash/commands/llm/providers/shared.js +3 -156
  113. package/dist/safe-bash/commands/llm/providers/shared.js.map +1 -1
  114. package/dist/safe-bash/commands/network/index.browser.js +8 -13
  115. package/dist/safe-bash/commands/pr/index.browser.js +3 -5
  116. package/dist/safe-bash/commands/tsort/index.browser.js +3 -5
  117. package/dist/safe-bash/commands/xml/index.browser.js +4 -7
  118. package/dist/safe-bash/commands/yq/index.browser.js +5 -8
  119. package/dist/safe-bash/contracts/filesystem.d.ts +1 -1
  120. package/dist/safe-bash/contracts/filesystem.d.ts.map +1 -1
  121. package/dist/safe-bash/core.browser.js +278 -171
  122. package/dist/safe-bash/core.browser.js.map +3 -3
  123. package/package.json +2 -2
  124. package/dist/safe-bash/chunks/chunk-BZUQJTOZ.js +0 -322
  125. package/dist/safe-bash/chunks/chunk-BZUQJTOZ.js.map +0 -7
  126. package/dist/safe-bash/chunks/chunk-EUTSYRNM.js +0 -111
  127. package/dist/safe-bash/chunks/chunk-EUTSYRNM.js.map +0 -7
  128. package/dist/safe-bash/chunks/chunk-F5AOPLRZ.js +0 -355
  129. package/dist/safe-bash/chunks/chunk-F5AOPLRZ.js.map +0 -7
  130. package/dist/safe-bash/chunks/chunk-FDGESHPB.js +0 -224
  131. package/dist/safe-bash/chunks/chunk-FDGESHPB.js.map +0 -7
  132. package/dist/safe-bash/chunks/chunk-KYU6MXVK.js +0 -58
  133. package/dist/safe-bash/chunks/chunk-KYU6MXVK.js.map +0 -7
  134. package/dist/safe-bash/chunks/chunk-O7BRWSKX.js.map +0 -7
  135. package/dist/safe-bash/chunks/chunk-TTTOMUAY.js +0 -33
  136. package/dist/safe-bash/chunks/chunk-TTTOMUAY.js.map +0 -7
  137. package/dist/safe-bash/chunks/chunk-UO33SQJU.js.map +0 -7
  138. package/dist/safe-bash/chunks/chunk-VY5N6O6I.js.map +0 -7
  139. /package/dist/safe-bash/chunks/{chunk-WXUZXY35.js.map → chunk-FMTBJ7SG.js.map} +0 -0
  140. /package/dist/safe-bash/chunks/{chunk-EUNOVYVT.js.map → chunk-OECKXHVJ.js.map} +0 -0
  141. /package/dist/safe-bash/chunks/{chunk-PPFWG34Y.js.map → chunk-XBLVOMEJ.js.map} +0 -0
@@ -2,48 +2,49 @@ import {
2
2
  createTsortCommand,
3
3
  createTsortCommands,
4
4
  tsortCommands
5
- } from "./chunks/chunk-YFFFBLBC.js";
5
+ } from "./chunks/chunk-TJVKGNKA.js";
6
6
  import {
7
7
  createFactorCommand,
8
8
  createFactorCommands,
9
9
  factorCommands
10
- } from "./chunks/chunk-4V3NGZAG.js";
10
+ } from "./chunks/chunk-IYFB6VED.js";
11
11
  import {
12
12
  createGetoptCommand,
13
13
  createGetoptCommands,
14
14
  getoptCommands
15
- } from "./chunks/chunk-DKT746UJ.js";
15
+ } from "./chunks/chunk-PE5NZIA2.js";
16
16
  import {
17
17
  createHdCommand,
18
18
  createHexdumpCommand,
19
19
  createHexdumpCommands,
20
20
  hexdumpCommands
21
- } from "./chunks/chunk-IDJQT32M.js";
21
+ } from "./chunks/chunk-HQCBEAFK.js";
22
22
  import {
23
23
  createIconvCommand,
24
24
  createIconvCommands,
25
25
  iconvCommands
26
- } from "./chunks/chunk-WJWYJDQE.js";
26
+ } from "./chunks/chunk-XYVCXUGM.js";
27
27
  import {
28
28
  createDos2unixCommand,
29
29
  createLineEndingCommands,
30
30
  createUnix2dosCommand,
31
31
  lineEndingCommands
32
- } from "./chunks/chunk-AWP6Z3RR.js";
32
+ } from "./chunks/chunk-E3NZKSTA.js";
33
33
  import {
34
- classify,
35
34
  createLlmCommands,
36
35
  llmCommands
37
- } from "./chunks/chunk-F5AOPLRZ.js";
36
+ } from "./chunks/chunk-KJYVSFGF.js";
37
+ import "./chunks/chunk-C7QNJ3D4.js";
38
38
  import {
39
+ classify,
39
40
  createElevenLabsProvider,
40
41
  createOpenAiProvider
41
- } from "./chunks/chunk-BZUQJTOZ.js";
42
+ } from "./chunks/chunk-LR32SJ3D.js";
42
43
  import {
43
44
  createXmlCommands,
44
45
  defaultXmlQueryLimits,
45
46
  xmlCommands
46
- } from "./chunks/chunk-WISNTI7E.js";
47
+ } from "./chunks/chunk-3Y5PKSHX.js";
47
48
  import {
48
49
  Interpreter,
49
50
  createYqCommand,
@@ -54,7 +55,7 @@ import {
54
55
  rawValues,
55
56
  stringify,
56
57
  yqCommands
57
- } from "./chunks/chunk-FIY2BMTU.js";
58
+ } from "./chunks/chunk-W3TLNFDB.js";
58
59
  import {
59
60
  Budget,
60
61
  JqError,
@@ -67,8 +68,10 @@ import {
67
68
  resolveJqLimits,
68
69
  truth,
69
70
  wellFormed
70
- } from "./chunks/chunk-PPFWG34Y.js";
71
+ } from "./chunks/chunk-XBLVOMEJ.js";
71
72
  import {
73
+ CurlError,
74
+ cloudflareWorkerNetworkLimits,
72
75
  createCurlCommand,
73
76
  createCurlCommands,
74
77
  createFetchTransport,
@@ -76,13 +79,9 @@ import {
76
79
  createOriginAuthorizer,
77
80
  createWgetCommand,
78
81
  curlCommands,
82
+ defaultNetworkLimits,
79
83
  networkCommands
80
- } from "./chunks/chunk-VY5N6O6I.js";
81
- import {
82
- CurlError,
83
- cloudflareWorkerNetworkLimits,
84
- defaultNetworkLimits
85
- } from "./chunks/chunk-EUTSYRNM.js";
84
+ } from "./chunks/chunk-BXVGCJXW.js";
86
85
  import {
87
86
  RecordBuffer,
88
87
  UsageError,
@@ -98,6 +97,7 @@ import {
98
97
  emptyInput,
99
98
  encoder,
100
99
  escapeBytes,
100
+ escapeText,
101
101
  evaluateCommandSupport,
102
102
  input,
103
103
  inputRequirements,
@@ -111,12 +111,9 @@ import {
111
111
  replaceArgument,
112
112
  requireOperands,
113
113
  textOutputRequirements,
114
- value
115
- } from "./chunks/chunk-O7BRWSKX.js";
116
- import {
117
- escapeText,
114
+ value,
118
115
  writeDiagnostic
119
- } from "./chunks/chunk-KYU6MXVK.js";
116
+ } from "./chunks/chunk-LHKAA57T.js";
120
117
  import {
121
118
  AvailableRecords,
122
119
  EreLedger,
@@ -136,24 +133,20 @@ import {
136
133
  exprMatchCeilings,
137
134
  matchEre,
138
135
  withRegexSession
139
- } from "./chunks/chunk-X7C3PN2T.js";
136
+ } from "./chunks/chunk-PMBBUNNN.js";
140
137
  import {
141
138
  bindFileOutputBudget,
142
139
  openFileOutput,
143
140
  writeFileOutput
144
- } from "./chunks/chunk-WXUZXY35.js";
141
+ } from "./chunks/chunk-FMTBJ7SG.js";
145
142
  import {
146
143
  createPrCommand,
147
144
  createPrCommands,
148
145
  prCommands
149
- } from "./chunks/chunk-QX2X5EC5.js";
146
+ } from "./chunks/chunk-H6E6F5KJ.js";
150
147
  import {
151
148
  createOutputOperation
152
- } from "./chunks/chunk-EUNOVYVT.js";
153
- import {
154
- PublicDiagnostic,
155
- publicDiagnosticMessage
156
- } from "./chunks/chunk-TTTOMUAY.js";
149
+ } from "./chunks/chunk-OECKXHVJ.js";
157
150
  import {
158
151
  basename,
159
152
  dirname,
@@ -167,37 +160,37 @@ import {
167
160
  import {
168
161
  CommandArgumentIdentityError,
169
162
  CommandRegistry,
170
- concatShellValues,
171
- createCommandArguments,
172
- getCommandArguments,
173
- shellValueByteLength,
174
- shellValueBytes,
175
- shellValueFromBytes,
176
- shellValueRetainedBytes,
177
- shellValueText,
178
- validateExitCode
179
- } from "./chunks/chunk-UO33SQJU.js";
180
- import {
181
163
  FsError,
164
+ PublicDiagnostic,
182
165
  cancelTurn,
183
166
  collectBytes,
184
167
  collectText,
168
+ concatShellValues,
185
169
  createBytePipe,
170
+ createCommandArguments,
171
+ getCommandArguments,
186
172
  inheritYieldCheckpoint,
187
173
  isErrnoCode,
188
174
  isFsError,
189
175
  monotonicNow,
190
176
  outputFailure,
191
177
  pipeBytes,
178
+ publicDiagnosticMessage,
192
179
  readBytes,
193
180
  registerYieldCheckpoint,
194
181
  scheduleTurn,
182
+ shellValueByteLength,
183
+ shellValueBytes,
184
+ shellValueFromBytes,
185
+ shellValueRetainedBytes,
186
+ shellValueText,
195
187
  toByteSource,
196
188
  toFsError,
189
+ validateExitCode,
197
190
  writeBytes,
198
191
  writeText,
199
192
  yieldTurn
200
- } from "./chunks/chunk-FDGESHPB.js";
193
+ } from "./chunks/chunk-2PQ3XOCQ.js";
201
194
  import {
202
195
  import_buffer,
203
196
  init_platform
@@ -27147,47 +27140,29 @@ var ZipScope = class {
27147
27140
  };
27148
27141
  async function publishZip(scope, prepared) {
27149
27142
  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;
27143
+ const capabilities = await scope.operation(() => fs.capabilitiesFor?.(prepared.output, { signal, create: true }) ?? fs.capabilities);
27144
+ if (capabilities.atomicFileStaging !== true || !fs.createStagedFile || !fs.publishStagedFile || !fs.removeStagedFile) fail("ZIP publication requires atomic owned file staging");
27145
+ let staging;
27157
27146
  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
27147
  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
- }
27148
+ if (staging) {
27149
+ if (!cleanup.removeStagedFile) fail("ZIP atomic cleanup unavailable");
27150
+ await cleanup.removeStagedFile(staging);
27179
27151
  }
27180
- await cleanup.rmdir(directory2.path);
27181
27152
  }, { maxOperations: 16 });
27182
27153
  try {
27183
27154
  for (let attempt = 0; attempt < Math.min(64, scope.limits.maxMembers); attempt++) {
27184
27155
  const path = `${prepared.parent === "/" ? "" : prepared.parent}/.zip-${attempt + 1}`;
27185
27156
  checkPath(path, scope.limits);
27157
+ checkPath(`${path}/archive.zip`, scope.limits);
27186
27158
  if (path === prepared.output) continue;
27187
27159
  try {
27188
27160
  await scope.operation(async () => {
27189
- await fs.mkdir(path, { signal, mode: 448 });
27190
- directory2 = { path, stat: await fs.lstat(path) };
27161
+ staging = await fs.createStagedFile(path, "archive.zip", { type: "file", data: prepared.bytes }, {
27162
+ signal,
27163
+ parent: prepared.parentStat,
27164
+ ...prepared.existing ? { mode: prepared.existing.mode & 4095 } : {}
27165
+ });
27191
27166
  });
27192
27167
  break;
27193
27168
  } catch (error) {
@@ -27195,44 +27170,14 @@ async function publishZip(scope, prepared) {
27195
27170
  if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "EEXIST") throw error;
27196
27171
  }
27197
27172
  }
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
- }
27173
+ if (!staging) fail("ZIP temporary directory attempt limit exceeded");
27226
27174
  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
- });
27175
+ if (parent !== prepared.parent) fail("archive parent changed before publication");
27176
+ await scope.operation(() => fs.publishStagedFile(staging, prepared.output, {
27177
+ signal,
27178
+ parent: prepared.parentStat,
27179
+ destination: prepared.existing ?? null
27180
+ }));
27236
27181
  } catch (error) {
27237
27182
  failure = { reason: error };
27238
27183
  }
@@ -27318,6 +27263,7 @@ async function prepare(scope, parsed, budget) {
27318
27263
  const outputName = vfsPath(context2.cwd, parsed.archive);
27319
27264
  const parentName = dirname(outputName);
27320
27265
  const parent = await scope.operation(() => context2.fs.realpath(parentName, { signal: context2.signal }));
27266
+ const parentStat = await scope.operation(() => context2.fs.lstat(parent, { signal: context2.signal }));
27321
27267
  const output2 = `${parent === "/" ? "" : parent}/${outputName.slice(outputName.lastIndexOf("/") + 1)}`;
27322
27268
  checkPath(output2, limits);
27323
27269
  const existing2 = await scope.stat(output2);
@@ -27443,7 +27389,7 @@ async function prepare(scope, parsed, budget) {
27443
27389
  append(entry, false);
27444
27390
  }
27445
27391
  const bytes3 = await writeZipArchive({ entries: entries2, comment: archive.comment }, limits, context2.signal);
27446
- return { output: output2, parentName, parent, existing: existing2, bytes: bytes3, progress };
27392
+ return { output: output2, parentName, parent, parentStat, existing: existing2, bytes: bytes3, progress };
27447
27393
  }
27448
27394
  function createZipCommand(options2 = {}) {
27449
27395
  const limits = settings2(options2);
@@ -27758,13 +27704,25 @@ var Extraction = class {
27758
27704
  const { fs, signal } = this.context;
27759
27705
  for (const component of raw.split("/")) {
27760
27706
  if (!component || component === ".") continue;
27707
+ const parent = await this.operation(() => fs.lstat(current, { signal }));
27761
27708
  current = resolvePath(current, component);
27762
27709
  const stat = await this.stat(current);
27763
- if (!stat && create) await this.operation(() => fs.mkdir(current, { signal, mode: 493 }));
27710
+ if (!stat && create) await this.createDirectory(current, parent);
27764
27711
  else if (!stat || stat.type !== "directory") fail(`unsafe non-directory or symlink ancestor: ${display(current)}`);
27765
27712
  }
27766
27713
  return current;
27767
27714
  }
27715
+ async createDirectory(path, parent) {
27716
+ const { fs, signal } = this.context;
27717
+ const capabilities = await this.operation(async () => await fs.capabilitiesFor?.(path, { signal, create: true }) ?? fs.capabilities);
27718
+ if (capabilities.atomicDirectoryMetadata !== true || !fs.prepareDirectory) fail("extraction requires atomic directory creation");
27719
+ return this.operation(() => fs.prepareDirectory(path, {
27720
+ signal,
27721
+ parent,
27722
+ expected: null,
27723
+ ...capabilities.permissions === false ? {} : { mode: 493 }
27724
+ }));
27725
+ }
27768
27726
  async parents(root, path, create) {
27769
27727
  if (!isPathWithin(root, path)) fail("extraction path escapes root");
27770
27728
  await this.directory(dirname(path), create);
@@ -27828,74 +27786,65 @@ var Extraction = class {
27828
27786
  const current = await this.stat(path);
27829
27787
  if (!current || current.type !== expected.type || !sameIdentity2(current, expected)) fail("extraction entry changed before mutation");
27830
27788
  }
27831
- async metadata(root, path, identity2, mode, modified) {
27789
+ async metadata(root, path, identity2, parent, mode, modified) {
27832
27790
  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
- }
27791
+ await this.parents(root, path, false);
27792
+ const capabilities = await this.operation(async () => await fs.capabilitiesFor?.(path, { signal }) ?? fs.capabilities);
27793
+ if (capabilities.permissions === false && capabilities.timestamps === false) return;
27794
+ if (capabilities.atomicDirectoryMetadata !== true || !fs.prepareDirectory) fail("extraction metadata requires atomic entry conditions");
27795
+ await this.operation(() => fs.prepareDirectory(path, {
27796
+ signal,
27797
+ expected: identity2,
27798
+ parent,
27799
+ ...capabilities.permissions === false ? {} : { mode: mode & 511 },
27800
+ ...capabilities.timestamps === false ? {} : { atimeMs: modified.getTime(), mtimeMs: modified.getTime() }
27801
+ }));
27841
27802
  }
27842
- publish(root, path, chunks, expected, mode, modified, target) {
27843
- const publication = this.stage(root, path, chunks, expected, mode, modified, target);
27803
+ publish(root, path, chunks, expected, parent, mode, modified, target) {
27804
+ const publication = this.stage(root, path, chunks, expected, parent, mode, modified, target);
27844
27805
  this.publications.add(publication);
27845
27806
  return publication.finally(() => {
27846
27807
  this.publications.delete(publication);
27847
27808
  });
27848
27809
  }
27849
- async stage(root, path, chunks, expected, mode, modified, target) {
27810
+ async stage(root, path, chunks, expected, parent, mode, modified, target) {
27850
27811
  const { fs, signal } = this.context;
27851
- let temporary = "";
27852
- let identity2;
27853
- let created = false;
27812
+ const capabilities = await this.operation(async () => await fs.capabilitiesFor?.(path, { signal, create: true }) ?? fs.capabilities);
27813
+ if (capabilities.atomicFileStaging !== true || !fs.createStagedFile || !fs.publishStagedFile || !fs.removeStagedFile) fail("extraction requires atomic owned file staging");
27814
+ let staging;
27854
27815
  let failure;
27855
27816
  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;
27817
+ if (staging) {
27818
+ if (!view.removeStagedFile) fail("extraction atomic cleanup unavailable");
27819
+ await view.removeStagedFile(staging);
27867
27820
  }
27868
27821
  }, { maxOperations: Math.min(4096, this.limits.maxDepth + 3) });
27869
27822
  try {
27870
- await this.parents(root, path, true);
27823
+ await this.parents(root, path, false);
27824
+ const content = target === void 0 ? { type: "file", data: import_buffer.Buffer.concat(chunks) } : { type: "symlink", target };
27871
27825
  for (let attempt = 0; attempt < this.limits.maxMembers; attempt++) {
27872
- temporary = resolvePath(dirname(path), `.unzip-${++this.serial}`);
27826
+ const temporary = resolvePath(dirname(path), `.unzip-${++this.serial}`);
27873
27827
  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 }));
27828
+ checkPath(`${temporary}/entry`, this.limits);
27829
+ if (temporary === path) continue;
27830
+ try {
27831
+ await this.operation(async () => {
27832
+ staging = await fs.createStagedFile(temporary, "entry", content, {
27833
+ signal,
27834
+ parent,
27835
+ ...target !== void 0 || capabilities.permissions === false ? {} : { mode: mode & 511 },
27836
+ ...target !== void 0 || capabilities.timestamps === false ? {} : { atimeMs: modified.getTime(), mtimeMs: modified.getTime() }
27837
+ });
27838
+ });
27839
+ break;
27840
+ } catch (error) {
27841
+ signal.throwIfAborted();
27842
+ if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "EEXIST") throw error;
27889
27843
  }
27890
- await this.metadata(root, temporary, identity2, mode, modified);
27891
27844
  }
27845
+ if (!staging) fail("temporary file attempt limit exceeded");
27892
27846
  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;
27847
+ await this.operation(() => fs.publishStagedFile(staging, path, { signal, parent, destination: expected ?? null }));
27899
27848
  } catch (error) {
27900
27849
  failure = { reason: error };
27901
27850
  }
@@ -28032,18 +27981,20 @@ function createUnzipCommand(options2 = {}) {
28032
27981
  if (chunk.length) fail("directory has nonempty payload");
28033
27982
  });
28034
27983
  }
27984
+ const parent2 = await extraction.operation(() => context2.fs.lstat(dirname(path), { signal: context2.signal }));
28035
27985
  const existing3 = await extraction.stat(path);
27986
+ let identity2 = existing3;
28036
27987
  if (existing3 && existing3.type !== "directory") fail("directory destination is not a directory");
28037
27988
  if (!existing3) {
28038
- await extraction.operation(() => context2.fs.mkdir(path, { signal: context2.signal, mode: 493 }));
27989
+ identity2 = await extraction.createDirectory(path, parent2);
28039
27990
  await budget.output(` creating: ${filtered(shown)}
28040
27991
  `);
28041
27992
  }
28042
- const identity2 = await extraction.stat(path);
28043
27993
  if (!identity2 || identity2.type !== "directory") fail("directory changed during creation");
28044
- directories.push({ path, entry, identity: identity2 });
27994
+ directories.push({ path, entry, identity: identity2, parent: parent2 });
28045
27995
  continue;
28046
27996
  }
27997
+ let parent = await extraction.operation(() => context2.fs.lstat(dirname(path), { signal: context2.signal }));
28047
27998
  let existing2 = await extraction.destination(path, archivePath, archiveStat);
28048
27999
  let skip = false;
28049
28000
  let prompting = 0;
@@ -28084,6 +28035,7 @@ function createUnzipCommand(options2 = {}) {
28084
28035
  path = extraction.member(root, renamed);
28085
28036
  shown = parsed.destination === void 0 ? renamed : `${parsed.destination.endsWith("/") ? parsed.destination : `${parsed.destination}/`}${renamed}`;
28086
28037
  await extraction.parents(root, path, true);
28038
+ parent = await extraction.operation(() => context2.fs.lstat(dirname(path), { signal: context2.signal }));
28087
28039
  existing2 = await extraction.destination(path, archivePath, archiveStat);
28088
28040
  continue;
28089
28041
  }
@@ -28107,11 +28059,11 @@ function createUnzipCommand(options2 = {}) {
28107
28059
  const target = text2(import_buffer.Buffer.concat(chunks));
28108
28060
  await extraction.target(root, path, target);
28109
28061
  if (!context2.fs.symlink || context2.fs.capabilities.symlinks === false) fail("filesystem does not support symlinks");
28110
- links.push({ path, shown, target, existing: existing2, entry });
28062
+ links.push({ path, shown, target, existing: existing2, parent, entry });
28111
28063
  await budget.output(` linking: ${padded(filtered(shown))} -> ${filtered(target)}
28112
28064
  `);
28113
28065
  } else {
28114
- await extraction.publish(root, path, chunks, existing2, entry.mode, entry.modified);
28066
+ await extraction.publish(root, path, chunks, existing2, parent, entry.mode, entry.modified);
28115
28067
  await budget.output(`${entry.method === 0 ? " extracting" : " inflating"}: ${padded(filtered(shown))}
28116
28068
  `);
28117
28069
  }
@@ -28125,12 +28077,12 @@ ${String(total).padStart(9)} ${selected} file${selected ===
28125
28077
  await extraction.parents(root, link.path, false);
28126
28078
  await extraction.target(root, link.path, link.target);
28127
28079
  await extraction.destination(link.path, archivePath, archiveStat);
28128
- await extraction.publish(root, link.path, [], link.existing, link.entry.mode, link.entry.modified, link.target);
28080
+ await extraction.publish(root, link.path, [], link.existing, link.parent, link.entry.mode, link.entry.modified, link.target);
28129
28081
  await budget.output(` ${padded(filtered(link.shown))} -> ${filtered(link.target)}
28130
28082
  `);
28131
28083
  }
28132
- for (const { path, entry, identity: identity2 } of directories.reverse()) {
28133
- await extraction.metadata(root, path, identity2, entry.mode, entry.modified);
28084
+ for (const { path, entry, identity: identity2, parent } of directories.reverse()) {
28085
+ await extraction.metadata(root, path, identity2, parent, entry.mode, entry.modified);
28134
28086
  }
28135
28087
  for (let index = 0; index < parsed.patterns.length; index++) if (!selection.matched.has(index)) {
28136
28088
  await budget.output(`caution: filename not matched: ${filtered(parsed.patterns[index])}
@@ -49342,7 +49294,7 @@ init_platform();
49342
49294
  // packages/safe-js/dist/browser/safe-fs.js
49343
49295
  init_platform();
49344
49296
 
49345
- // packages/safe-js/dist/browser/chunks/chunk-BAO3TSWI.js
49297
+ // packages/safe-js/dist/browser/chunks/chunk-SB2GDI2R.js
49346
49298
  init_platform();
49347
49299
  var platform = Object.freeze({
49348
49300
  errno(_code) {
@@ -50015,6 +49967,9 @@ var MemoryFileSystem = class _MemoryFileSystem {
50015
49967
  permissions: true,
50016
49968
  timestamps: true,
50017
49969
  atomicRename: true,
49970
+ atomicFileStaging: true,
49971
+ atomicFileMutation: true,
49972
+ atomicDirectoryMetadata: true,
50018
49973
  streamingRead: true,
50019
49974
  retainedRead: true,
50020
49975
  get retainedResize() {
@@ -50067,6 +50022,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50067
50022
  ino: this.nextInode++,
50068
50023
  nlink: 1,
50069
50024
  references: 0,
50025
+ revision: 0,
50070
50026
  atimeMs: now,
50071
50027
  mtimeMs: now,
50072
50028
  ctimeMs: now,
@@ -50124,6 +50080,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50124
50080
  if (!Number.isSafeInteger(value2) || value2 < 0) this.fail("EINVAL", syscall, path);
50125
50081
  }
50126
50082
  changed(node) {
50083
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50127
50084
  node.mtimeMs = node.ctimeMs = Date.now();
50128
50085
  }
50129
50086
  resolve(path, syscall, options2 = {}) {
@@ -50192,6 +50149,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50192
50149
  snapshot(node) {
50193
50150
  return {
50194
50151
  type: node.type,
50152
+ ...Number.isSafeInteger(node.revision) ? { revision: node.revision } : {},
50195
50153
  preferredIoBlockSize: 4096,
50196
50154
  size: node.type === "file" ? node.data.byteLength : node.type === "symlink" ? new TextEncoder().encode(node.target).byteLength : 0,
50197
50155
  mode: node.mode,
@@ -50333,6 +50291,145 @@ var MemoryFileSystem = class _MemoryFileSystem {
50333
50291
  node.atimeMs = Date.now();
50334
50292
  return new Uint8Array(node.data);
50335
50293
  }
50294
+ expectEntry(node, expected, path, unchanged5 = true) {
50295
+ if (expected === null) {
50296
+ if (node) this.fail("EAGAIN", "fileStaging", path);
50297
+ return;
50298
+ }
50299
+ if (!node) this.fail("EAGAIN", "fileStaging", path);
50300
+ const current = this.snapshot(node);
50301
+ if (!expected.identityScope || expected.identityScope !== current.identityScope || !Number.isSafeInteger(expected.ino) || !Number.isSafeInteger(expected.dev)) this.fail("ENOTSUP", "fileStaging", path);
50302
+ if (current.ino !== expected.ino || current.dev !== expected.dev || current.type !== expected.type) this.fail("EAGAIN", "fileStaging", path);
50303
+ if (unchanged5) {
50304
+ if (!Number.isSafeInteger(expected.revision) || !Number.isSafeInteger(current.revision)) this.fail("ENOTSUP", "fileStaging", path);
50305
+ 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);
50306
+ }
50307
+ }
50308
+ stagingLocations(staging) {
50309
+ const parent = this.entry(staging.parent.path, "fileStaging");
50310
+ this.expectEntry(parent.node, staging.parent.stat, staging.parent.path, false);
50311
+ if (parent.node.type !== "directory") this.fail("ENOTDIR", "fileStaging", staging.parent.path);
50312
+ const directory2 = this.entry(staging.directory.path, "fileStaging");
50313
+ this.expectEntry(directory2.node, staging.directory.stat, staging.directory.path, false);
50314
+ if (directory2.parent !== parent.node || directory2.node.type !== "directory" || (directory2.node.mode & 511) !== 448) this.fail("EAGAIN", "fileStaging", staging.directory.path);
50315
+ const file = this.entry(staging.file.path, "fileStaging", true);
50316
+ if (file.parent !== directory2.node || !["file", "symlink"].includes(staging.file.stat.type)) this.fail("EAGAIN", "fileStaging", staging.file.path);
50317
+ return { directory: directory2, file };
50318
+ }
50319
+ async createStagedFile(directoryPath, name2, content, options2) {
50320
+ options2.signal?.throwIfAborted();
50321
+ if (!name2 || name2 === "." || name2 === ".." || name2.includes("/") || name2.includes("\0")) this.fail("EINVAL", "createStagedFile", directoryPath);
50322
+ const location = this.entry(directoryPath, "createStagedFile", true);
50323
+ if (location.node) this.fail("EEXIST", "createStagedFile", directoryPath);
50324
+ this.expectEntry(location.parent, options2.parent, directoryPath, false);
50325
+ this.permission(location.parent, 3, "createStagedFile", directoryPath);
50326
+ const mode2 = this.mode(options2.mode, content.type === "file" ? 438 : 511, "createStagedFile", directoryPath);
50327
+ for (const time of [options2.atimeMs, options2.mtimeMs]) if (time !== void 0 && !Number.isFinite(time)) this.fail("EINVAL", "createStagedFile", directoryPath);
50328
+ if (content.type === "file" && !(content.data instanceof Uint8Array)) throw new TypeError("Staged files require Uint8Array data");
50329
+ if (content.type === "symlink") this.validatePath(content.target, "createStagedFile");
50330
+ const retained = (location.name.length + name2.length) * 2 + (content.type === "symlink" ? content.target.length * 2 : 0);
50331
+ this.ledger.reserve(retained, 4, "createStagedFile", directoryPath);
50332
+ let allocation;
50333
+ let directory2;
50334
+ let file;
50335
+ try {
50336
+ if (content.type === "file") allocation = this.bytes(content.data, "createStagedFile", directoryPath);
50337
+ directory2 = this.directory(448);
50338
+ 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 };
50339
+ if (options2.atimeMs !== void 0) file.atimeMs = options2.atimeMs;
50340
+ if (options2.mtimeMs !== void 0) file.mtimeMs = options2.mtimeMs;
50341
+ directory2.entries.set(name2, file);
50342
+ location.parent.entries.set(location.name, directory2);
50343
+ } catch (error) {
50344
+ allocation?.release();
50345
+ this.ledger.release(retained, 4);
50346
+ throw error;
50347
+ }
50348
+ this.changed(location.parent);
50349
+ const parentPath = location.path.slice(0, location.path.lastIndexOf("/")) || "/";
50350
+ const receipt = (path, node) => Object.freeze({ path, stat: Object.freeze(this.snapshot(node)) });
50351
+ return Object.freeze({ parent: receipt(parentPath, location.parent), directory: receipt(location.path, directory2), file: receipt(`${location.path}/${name2}`, file) });
50352
+ }
50353
+ async publishStagedFile(staging, destination2, options2) {
50354
+ options2.signal?.throwIfAborted();
50355
+ const { directory: directory2, file } = this.stagingLocations(staging);
50356
+ this.expectEntry(file.node, staging.file.stat, staging.file.path);
50357
+ const target = this.entry(destination2, "publishStagedFile", true);
50358
+ this.expectEntry(target.parent, options2.parent, destination2, false);
50359
+ this.expectEntry(target.node, options2.destination, destination2);
50360
+ if (target.parent === directory2.node || target.node === directory2.node || target.node === file.node) this.fail("EINVAL", "publishStagedFile", destination2);
50361
+ if (target.node && (target.node.type !== "file" || target.node.nlink !== 1)) this.fail("EAGAIN", "publishStagedFile", destination2);
50362
+ return _MemoryFileSystem.prototype.rename.call(this, staging.file.path, destination2, { ...options2, noReplace: options2.destination === null });
50363
+ }
50364
+ async removeStagedFile(staging, options2 = {}) {
50365
+ options2.signal?.throwIfAborted();
50366
+ const { directory: directory2, file } = this.stagingLocations(staging);
50367
+ if (file.node) this.expectEntry(file.node, staging.file.stat, staging.file.path);
50368
+ const node = directory2.node;
50369
+ if (node.entries.size !== (file.node ? 1 : 0)) this.fail("ENOTEMPTY", "removeStagedFile", staging.directory.path);
50370
+ this.permission(directory2.parent, 3, "removeStagedFile", staging.directory.path);
50371
+ this.permission(node, 3, "removeStagedFile", staging.file.path);
50372
+ directory2.parent.entries.delete(directory2.name);
50373
+ if (file.node) {
50374
+ node.entries.delete(file.name);
50375
+ this.ledger.release(file.name.length * 2, 1);
50376
+ file.node.nlink--;
50377
+ file.node.ctimeMs = Date.now();
50378
+ file.node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, file.node.revision + 1);
50379
+ this.releaseNode(file.node);
50380
+ }
50381
+ this.ledger.release(directory2.name.length * 2, 1);
50382
+ node.nlink = 0;
50383
+ node.ctimeMs = Date.now();
50384
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50385
+ this.releaseNode(node);
50386
+ this.changed(directory2.parent);
50387
+ }
50388
+ async prepareDirectory(path, options2) {
50389
+ options2.signal?.throwIfAborted();
50390
+ const location = this.entry(path, "prepareDirectory", true);
50391
+ this.expectEntry(location.parent, options2.parent, path, false);
50392
+ this.expectEntry(location.node, options2.expected, path, false);
50393
+ const mode2 = options2.mode === void 0 ? void 0 : this.mode(options2.mode, 0, "prepareDirectory", path);
50394
+ for (const time of [options2.atimeMs, options2.mtimeMs]) if (time !== void 0 && !Number.isFinite(time)) this.fail("EINVAL", "prepareDirectory", path);
50395
+ let node = location.node;
50396
+ if (!node) {
50397
+ this.permission(location.parent, 3, "prepareDirectory", path);
50398
+ node = this.addNode(location.parent, location.name, () => this.directory(mode2 ?? 511), "prepareDirectory", path);
50399
+ }
50400
+ if (node.type !== "directory") this.fail("ENOTDIR", "prepareDirectory", path);
50401
+ if (mode2 !== void 0) node.mode = typeModes.directory | mode2;
50402
+ if (options2.atimeMs !== void 0) node.atimeMs = options2.atimeMs;
50403
+ if (options2.mtimeMs !== void 0) node.mtimeMs = options2.mtimeMs;
50404
+ node.ctimeMs = Date.now();
50405
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50406
+ return Object.freeze(this.snapshot(node));
50407
+ }
50408
+ async writeFileConditional(path, data2, options2) {
50409
+ options2.signal?.throwIfAborted();
50410
+ const location = this.entry(path, "writeFileConditional", true);
50411
+ this.expectEntry(location.parent, options2.parent, path, false);
50412
+ this.expectEntry(location.node, options2.expected, path);
50413
+ if (location.node && location.node.type !== "file") this.fail("EINVAL", "writeFileConditional", path);
50414
+ this.writeData(path, data2, { ...options2.mode === void 0 ? {} : { mode: options2.mode }, flag: options2.append ? "a" : "w" }, "writeFileConditional");
50415
+ return Object.freeze(this.snapshot(location.parent.entries.get(location.name)));
50416
+ }
50417
+ async removeFileConditional(path, options2) {
50418
+ options2.signal?.throwIfAborted();
50419
+ const location = this.entry(path, "removeFileConditional", true);
50420
+ this.expectEntry(location.parent, options2.parent, path, false);
50421
+ this.expectEntry(location.node, options2.expected, path);
50422
+ const node = location.node;
50423
+ if (node.type !== "file") this.fail("EINVAL", "removeFileConditional", path);
50424
+ this.permission(location.parent, 3, "removeFileConditional", path);
50425
+ location.parent.entries.delete(location.name);
50426
+ this.ledger.release(location.name.length * 2, 1);
50427
+ node.nlink--;
50428
+ node.ctimeMs = Date.now();
50429
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50430
+ this.releaseNode(node);
50431
+ this.changed(location.parent);
50432
+ }
50336
50433
  async writeFile(path, data2, options2 = {}) {
50337
50434
  options2.signal?.throwIfAborted();
50338
50435
  this.writeData(path, data2, options2, "writeFile");
@@ -50387,6 +50484,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50387
50484
  this.ledger.release(location.name.length * 2, 1);
50388
50485
  node.nlink = 0;
50389
50486
  node.ctimeMs = Date.now();
50487
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50390
50488
  this.releaseNode(node);
50391
50489
  this.changed(location.parent);
50392
50490
  }
@@ -50421,6 +50519,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50421
50519
  }
50422
50520
  entry.nlink--;
50423
50521
  entry.ctimeMs = Date.now();
50522
+ entry.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, entry.revision + 1);
50424
50523
  this.releaseNode(entry);
50425
50524
  }
50426
50525
  this.changed(location.parent);
@@ -50457,11 +50556,13 @@ var MemoryFileSystem = class _MemoryFileSystem {
50457
50556
  this.ledger.release(origin.name.length * 2, 1);
50458
50557
  target.node.nlink--;
50459
50558
  target.node.ctimeMs = Date.now();
50559
+ target.node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, target.node.revision + 1);
50460
50560
  this.releaseNode(target.node);
50461
50561
  } else if (nameGrowth < 0) this.ledger.release(-nameGrowth, 0);
50462
50562
  this.changed(origin.parent);
50463
50563
  this.changed(target.parent);
50464
50564
  node.ctimeMs = Date.now();
50565
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50465
50566
  } catch (error) {
50466
50567
  if (error instanceof FsError2) throw new FsError2(error.code, { syscall: "rename", path: source2, dest: destination2, cause: error });
50467
50568
  throw error;
@@ -50527,6 +50628,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50527
50628
  }
50528
50629
  node.nlink++;
50529
50630
  node.ctimeMs = Date.now();
50631
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50530
50632
  this.changed(target.parent);
50531
50633
  }
50532
50634
  async chmod(path, mode2, options2 = {}) {
@@ -50535,6 +50637,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50535
50637
  const node = this.resolve(path, "chmod").node;
50536
50638
  node.mode = typeModes[node.type] | permissions;
50537
50639
  node.ctimeMs = Date.now();
50640
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50538
50641
  }
50539
50642
  async utimes(path, atimeMs, mtimeMs, options2 = {}) {
50540
50643
  options2.signal?.throwIfAborted();
@@ -50543,6 +50646,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
50543
50646
  node.atimeMs = atimeMs;
50544
50647
  node.mtimeMs = mtimeMs;
50545
50648
  node.ctimeMs = Date.now();
50649
+ node.revision = Math.min(Number.MAX_SAFE_INTEGER + 1, node.revision + 1);
50546
50650
  }
50547
50651
  async truncate(path, length = 0, options2 = {}) {
50548
50652
  options2.signal?.throwIfAborted();
@@ -50831,6 +50935,9 @@ var deviceCapabilities = Object.freeze({
50831
50935
  timestamps: false,
50832
50936
  truncate: false,
50833
50937
  randomAccessWrite: false,
50938
+ atomicFileMutation: false,
50939
+ atomicFileStaging: false,
50940
+ atomicDirectoryMetadata: false,
50834
50941
  atomicRename: false,
50835
50942
  atomicRenameNoReplace: false,
50836
50943
  descriptorWriteStream: true,