toolcraft 0.0.771 → 0.0.772

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 (61) hide show
  1. package/composition.json +13 -3
  2. package/dist/composition.json +13 -3
  3. package/node_modules/@poe-code/safe-fs/dist/contracts/filesystem.d.ts +8 -1
  4. package/node_modules/@poe-code/safe-fs/dist/core.d.ts +1 -1
  5. package/node_modules/@poe-code/safe-fs/dist/core.js +1 -1
  6. package/node_modules/@poe-code/safe-fs/dist/fs/capabilities.js +4 -2
  7. package/node_modules/@poe-code/safe-fs/dist/fs/devices/index.d.ts +2 -2
  8. package/node_modules/@poe-code/safe-fs/dist/fs/devices/index.js +9 -6
  9. package/node_modules/@poe-code/safe-fs/dist/fs/memory/index.d.ts +2 -2
  10. package/node_modules/@poe-code/safe-fs/dist/fs/memory/index.js +4 -3
  11. package/node_modules/@poe-code/safe-fs/dist/fs/mount/index.d.ts +2 -2
  12. package/node_modules/@poe-code/safe-fs/dist/fs/mount/index.js +12 -7
  13. package/node_modules/@poe-code/safe-fs/dist/fs/overlay/index.d.ts +1 -0
  14. package/node_modules/@poe-code/safe-fs/dist/fs/overlay/index.js +10 -0
  15. package/node_modules/@poe-code/safe-fs/dist/fs/overlay/memory-publication.js +18 -0
  16. package/node_modules/@poe-code/safe-fs/dist/fs/scoped.js +1 -1
  17. package/node_modules/@poe-code/safe-fs/dist/storage.d.ts +1 -1
  18. package/node_modules/@poe-code/safe-fs/dist/storage.js +21 -3
  19. package/node_modules/@poe-code/xml-ast/README.md +10 -1
  20. package/node_modules/@poe-code/xml-ast/dist/errors.d.ts +4 -0
  21. package/node_modules/@poe-code/xml-ast/dist/errors.js +7 -0
  22. package/node_modules/@poe-code/xml-ast/dist/index.d.ts +2 -4
  23. package/node_modules/@poe-code/xml-ast/dist/index.js +3 -7
  24. package/node_modules/@poe-code/xml-ast/dist/stream.d.ts +16 -0
  25. package/node_modules/@poe-code/xml-ast/dist/stream.js +163 -0
  26. package/node_modules/saxes/README.md +323 -0
  27. package/node_modules/saxes/package.json +71 -0
  28. package/node_modules/saxes/saxes.d.ts +635 -0
  29. package/node_modules/saxes/saxes.js +2053 -0
  30. package/node_modules/saxes/saxes.js.map +1 -0
  31. package/node_modules/tiny-http-mcp-server/dist/composition.json +11 -1
  32. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/README.md +6 -2
  33. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/register-client.d.ts +9 -3
  34. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/register-client.js +22 -7
  35. package/node_modules/tiny-http-mcp-server/package.json +4 -4
  36. package/node_modules/tiny-mcp-client/README.md +11 -2
  37. package/node_modules/tiny-mcp-client/dist/index.browser.d.ts +17 -4
  38. package/node_modules/tiny-mcp-client/dist/index.browser.js +92 -40
  39. package/node_modules/tiny-mcp-client/dist/index.d.ts +17 -4
  40. package/node_modules/tiny-mcp-client/dist/index.js +114 -47
  41. package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
  42. package/node_modules/toolcraft-schema/package.json +1 -1
  43. package/node_modules/xmlchars/LICENSE +18 -0
  44. package/node_modules/xmlchars/README.md +33 -0
  45. package/node_modules/xmlchars/package.json +51 -0
  46. package/node_modules/xmlchars/xml/1.0/ed4.d.ts +31 -0
  47. package/node_modules/xmlchars/xml/1.0/ed4.js +44 -0
  48. package/node_modules/xmlchars/xml/1.0/ed4.js.map +1 -0
  49. package/node_modules/xmlchars/xml/1.0/ed5.d.ts +51 -0
  50. package/node_modules/xmlchars/xml/1.0/ed5.js +105 -0
  51. package/node_modules/xmlchars/xml/1.0/ed5.js.map +1 -0
  52. package/node_modules/xmlchars/xml/1.1/ed2.d.ts +73 -0
  53. package/node_modules/xmlchars/xml/1.1/ed2.js +145 -0
  54. package/node_modules/xmlchars/xml/1.1/ed2.js.map +1 -0
  55. package/node_modules/xmlchars/xmlchars.d.ts +170 -0
  56. package/node_modules/xmlchars/xmlchars.js +191 -0
  57. package/node_modules/xmlchars/xmlchars.js.map +1 -0
  58. package/node_modules/xmlchars/xmlns/1.0/ed3.d.ts +28 -0
  59. package/node_modules/xmlchars/xmlns/1.0/ed3.js +65 -0
  60. package/node_modules/xmlchars/xmlns/1.0/ed3.js.map +1 -0
  61. package/package.json +8 -6
package/composition.json CHANGED
@@ -106,6 +106,11 @@
106
106
  "version": "0.1.0",
107
107
  "license": "MIT"
108
108
  },
109
+ {
110
+ "name": "saxes",
111
+ "version": "6.0.0",
112
+ "license": "ISC"
113
+ },
109
114
  {
110
115
  "name": "sisteransi",
111
116
  "version": "1.0.5",
@@ -118,7 +123,7 @@
118
123
  },
119
124
  {
120
125
  "name": "tiny-http-mcp-server",
121
- "version": "0.1.124",
126
+ "version": "0.1.129",
122
127
  "license": "MIT"
123
128
  },
124
129
  {
@@ -133,7 +138,7 @@
133
138
  },
134
139
  {
135
140
  "name": "toolcraft",
136
- "version": "0.0.771",
141
+ "version": "0.0.772",
137
142
  "license": "MIT"
138
143
  },
139
144
  {
@@ -143,7 +148,12 @@
143
148
  },
144
149
  {
145
150
  "name": "toolcraft-schema",
146
- "version": "0.0.771",
151
+ "version": "0.0.772",
152
+ "license": "MIT"
153
+ },
154
+ {
155
+ "name": "xmlchars",
156
+ "version": "2.2.0",
147
157
  "license": "MIT"
148
158
  },
149
159
  {
@@ -106,6 +106,11 @@
106
106
  "version": "0.1.0",
107
107
  "license": "MIT"
108
108
  },
109
+ {
110
+ "name": "saxes",
111
+ "version": "6.0.0",
112
+ "license": "ISC"
113
+ },
109
114
  {
110
115
  "name": "sisteransi",
111
116
  "version": "1.0.5",
@@ -118,7 +123,7 @@
118
123
  },
119
124
  {
120
125
  "name": "tiny-http-mcp-server",
121
- "version": "0.1.124",
126
+ "version": "0.1.129",
122
127
  "license": "MIT"
123
128
  },
124
129
  {
@@ -133,7 +138,7 @@
133
138
  },
134
139
  {
135
140
  "name": "toolcraft",
136
- "version": "0.0.771",
141
+ "version": "0.0.772",
137
142
  "license": "MIT"
138
143
  },
139
144
  {
@@ -143,7 +148,12 @@
143
148
  },
144
149
  {
145
150
  "name": "toolcraft-schema",
146
- "version": "0.0.771",
151
+ "version": "0.0.772",
152
+ "license": "MIT"
153
+ },
154
+ {
155
+ "name": "xmlchars",
156
+ "version": "2.2.0",
147
157
  "license": "MIT"
148
158
  },
149
159
  {
@@ -87,6 +87,8 @@ export interface FileSystemCapabilities {
87
87
  readonly synchronousDirectoryValidation?: boolean;
88
88
  /** Captures a followed destination path with a synchronous commit validator. */
89
89
  readonly synchronousStagingResolution?: boolean;
90
+ /** Also binds the final symlink and its target in the synchronous validator. */
91
+ readonly synchronousFollowedStagingResolution?: boolean;
90
92
  /** Invokes commitGuard in the same synchronous section as staged replacement. */
91
93
  readonly guardedStagingPublication?: boolean;
92
94
  readonly atomicFilePublication?: boolean;
@@ -129,6 +131,7 @@ export interface CapabilityQueryOptions extends OpenReadFileOptions {
129
131
  * Omission retains the ordinary per-target query and its acquisition intent. */
130
132
  readonly stagingAncestry?: boolean;
131
133
  readonly stagingResolution?: boolean;
134
+ readonly followFinalSymlink?: boolean;
132
135
  readonly create?: boolean;
133
136
  readonly creation?: OpenFileOptions["creation"];
134
137
  }
@@ -233,6 +236,10 @@ export interface FileStagingEntry {
233
236
  export interface FileResolutionStep extends FileStagingEntry {
234
237
  readonly linkTarget?: string;
235
238
  }
239
+ export interface PrepareStagingResolutionOptions extends FsOptions {
240
+ /** Requires synchronousFollowedStagingResolution; omission preserves final-entry resolution. */
241
+ readonly followFinalSymlink?: boolean;
242
+ }
236
243
  export interface FileStagingResolution {
237
244
  readonly path: string;
238
245
  readonly parent: FileStat;
@@ -344,7 +351,7 @@ export interface FileSystem {
344
351
  * The returned guard checks current identities/search access synchronously;
345
352
  * preparation is not validation, and the guard's result is not an async lease. */
346
353
  prepareDirectoryAncestry?(ancestors: readonly FileStagingEntry[], options?: FsOptions): Promise<() => true>;
347
- prepareStagingResolution?(path: string, options?: FsOptions): Promise<FileStagingResolution>;
354
+ prepareStagingResolution?(path: string, options?: PrepareStagingResolutionOptions): Promise<FileStagingResolution>;
348
355
  removeStagedFile?(staging: FileStaging, options?: FsOptions): Promise<void>;
349
356
  openReadFile?(path: string, options?: OpenReadFileOptions): Promise<FileReadHandle>;
350
357
  openResizeFile?(path: string, options?: OpenResizeFileOptions): Promise<FileResizeHandle>;
@@ -8,7 +8,7 @@ export * from "./fs/object-publication/index.js";
8
8
  export * from "./fs/webdav/index.js";
9
9
  export * from "./bridge/index.js";
10
10
  export * from "./python/index.js";
11
- export { parseXml, parseXmlSteps, XmlLimitError } from "./xml.js";
11
+ export { parseXml, parseXmlSteps, parseXmlStream, XmlLimitError } from "./xml.js";
12
12
  export type { XmlName, XmlAttribute, XmlContent, XmlElement, XmlLimits } from "./xml.js";
13
13
  export * from "./contracts/object.js";
14
14
  export { ObjectAuthority } from "./fs/object-authority.js";
@@ -8,7 +8,7 @@ export * from "./fs/object-publication/index.js";
8
8
  export * from "./fs/webdav/index.js";
9
9
  export * from "./bridge/index.js";
10
10
  export * from "./python/index.js";
11
- export { parseXml, parseXmlSteps, XmlLimitError } from "./xml.js";
11
+ export { parseXml, parseXmlSteps, parseXmlStream, XmlLimitError } from "./xml.js";
12
12
  export * from "./contracts/object.js";
13
13
  export { ObjectAuthority } from "./fs/object-authority.js";
14
14
  export * from "./fs/s3/index.js";
@@ -132,7 +132,7 @@ export function readOnlyCapabilities(capabilities) {
132
132
  ].filter(name => capabilities[name] !== undefined).map(name => [name, capabilities[name]]));
133
133
  return Object.freeze({
134
134
  ...inspection, retainedStagingCleanup: false, retainedStagingWrite: false, readOnly: true, write: false, append: false, exclusiveCreate: false,
135
- synchronousStagingResolution: false,
135
+ synchronousStagingResolution: false, synchronousFollowedStagingResolution: false,
136
136
  mkdir: false, recursiveMkdir: false, remove: false, removeDirectory: false, recursiveRemove: false,
137
137
  rename: false, copy: false, exclusiveCopy: false, truncate: false, streamingAppend: false,
138
138
  randomAccessWrite: false, hardlinks: false, permissions: false, conditionalChmod: false, timestamps: false,
@@ -144,7 +144,7 @@ export function quotaCapabilities(capabilities) {
144
144
  const streamingWrite = requireCapabilities(capabilities.write, capabilities.append, capabilities.streamingAppend, !capabilities.readOnly);
145
145
  const streamingAppend = requireCapabilities(capabilities.append, capabilities.streamingAppend, !capabilities.readOnly);
146
146
  const { streamingWrite: ignoredWrite, streamingAppend: ignoredAppend, ...rest } = capabilities;
147
- return Object.freeze({ ...rest, synchronousStagingResolution: false, retainedStagingCleanup: false, retainedStagingWrite: false, atomicStagingAncestry: false, synchronousDirectoryValidation: false, guardedStagingPublication: false, atomicFilePublication: false, descriptorWriteStream: false, atomicResize: false, atomicFileMutation: false, atomicEntryRemoval: false, atomicEntryRemovalReceipt: false, atomicStagedFileMutation: false, atomicFileStaging: false, atomicDirectoryMetadata: false, trustedOwnedStaging: false,
147
+ return Object.freeze({ ...rest, synchronousStagingResolution: false, synchronousFollowedStagingResolution: false, retainedStagingCleanup: false, retainedStagingWrite: false, atomicStagingAncestry: false, synchronousDirectoryValidation: false, guardedStagingPublication: false, atomicFilePublication: false, descriptorWriteStream: false, atomicResize: false, atomicFileMutation: false, atomicEntryRemoval: false, atomicEntryRemovalReceipt: false, atomicStagedFileMutation: false, atomicFileStaging: false, atomicDirectoryMetadata: false, trustedOwnedStaging: false,
148
148
  ...(streamingWrite === undefined ? {} : { streamingWrite }),
149
149
  ...(streamingAppend === undefined ? {} : { streamingAppend }),
150
150
  });
@@ -179,6 +179,8 @@ export function ownedMutationCapabilities(filesystem, capabilities = filesystem.
179
179
  (unavailable ??= {}).synchronousDirectoryValidation = false;
180
180
  if (capabilities.synchronousStagingResolution === true && (capabilities.readOnly === true || typeof filesystem.prepareStagingResolution !== "function"))
181
181
  (unavailable ??= {}).synchronousStagingResolution = false;
182
+ if (capabilities.synchronousFollowedStagingResolution === true && (capabilities.synchronousStagingResolution !== true || unavailable?.synchronousStagingResolution === false))
183
+ (unavailable ??= {}).synchronousFollowedStagingResolution = false;
182
184
  if (capabilities.guardedStagingPublication === true && (capabilities.atomicFileStaging !== true || unavailable?.atomicFileStaging === false))
183
185
  (unavailable ??= {}).guardedStagingPublication = false;
184
186
  if (capabilities.atomicDirectoryMetadata === true && (capabilities.readOnly === true || typeof filesystem.prepareDirectory !== "function"))
@@ -1,5 +1,5 @@
1
1
  import type { FileDescriptor, OpenFileOptions } from "../../contracts/descriptor.js";
2
- import type { AppendFileOptions, CapabilityQueryOptions, CopyFileOptions, DirectoryEntry, FileReadHandle, FileResizeHandle, FileResizeOperation, FileResizeOptions, FileStat, FileSystem, OpenReadFileOptions, OpenResizeFileOptions, FileSystemCapabilities, FsOptions, RenameOptions, MkdirOptions, ReadDirectoryOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions, ConditionalFilePublicationOptions, ConditionalWriteFileOptions, ConditionalRemoveFileOptions, ConditionalRemoveEntryOptions, ConditionalRemoveEntryReceiptOptions, CreateStagedFileOptions, FileStaging, FileStagingEntry, FileStagingResolution, PublishStagedFileOptions, PublishStagedFileSetOptions, PrepareDirectoryOptions, StagedFileContent } from "../../contracts/filesystem.js";
2
+ import type { AppendFileOptions, CapabilityQueryOptions, CopyFileOptions, DirectoryEntry, FileReadHandle, FileResizeHandle, FileResizeOperation, FileResizeOptions, FileStat, FileSystem, OpenReadFileOptions, OpenResizeFileOptions, FileSystemCapabilities, FsOptions, RenameOptions, MkdirOptions, ReadDirectoryOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions, ConditionalFilePublicationOptions, ConditionalWriteFileOptions, ConditionalRemoveFileOptions, ConditionalRemoveEntryOptions, ConditionalRemoveEntryReceiptOptions, CreateStagedFileOptions, FileStaging, FileStagingEntry, FileStagingResolution, PrepareStagingResolutionOptions, PublishStagedFileOptions, PublishStagedFileSetOptions, PrepareDirectoryOptions, StagedFileContent } from "../../contracts/filesystem.js";
3
3
  import type { ByteSource } from "../../contracts/io.js";
4
4
  import { type EntryLocation } from "../mount/comparison.js";
5
5
  import { pathNamespace } from "../path-namespace.js";
@@ -43,7 +43,7 @@ export declare class DeviceFileSystem implements FileSystem {
43
43
  publishStagedFile(staging: FileStaging, destination: string, options: PublishStagedFileOptions): Promise<void>;
44
44
  publishStagedFileSet(receipt: FileStaging, destination: string, supplied: PublishStagedFileSetOptions): Promise<FileStat>;
45
45
  prepareDirectoryAncestry(ancestors: readonly FileStagingEntry[], options?: FsOptions): Promise<() => true>;
46
- prepareStagingResolution(path: string, options?: FsOptions): Promise<FileStagingResolution>;
46
+ prepareStagingResolution(path: string, options?: PrepareStagingResolutionOptions): Promise<FileStagingResolution>;
47
47
  removeStagedFile(staging: FileStaging, options?: FsOptions): Promise<void>;
48
48
  prepareDirectory(path: string, options: PrepareDirectoryOptions): Promise<FileStat>;
49
49
  rename(source: string, destination: string, options?: RenameOptions): Promise<void>;
@@ -13,7 +13,7 @@ import { openFileDescriptor } from "../descriptor.js";
13
13
  import { normalizePath } from "../../contracts/virtual-path.js";
14
14
  const views = new WeakMap();
15
15
  const deviceCapabilities = Object.freeze({
16
- synchronousStagingResolution: false,
16
+ synchronousStagingResolution: false, synchronousFollowedStagingResolution: false,
17
17
  readOnly: false, read: true, stat: true, realpath: true, access: true, readdir: false,
18
18
  write: true, append: true, exclusiveCreate: true, streamingRead: true, retainedRead: true,
19
19
  streamingWrite: true, streamingAppend: true, independentWriteStreams: true, copy: true, exclusiveCopy: true,
@@ -179,7 +179,7 @@ export class DeviceFileSystem {
179
179
  let selected;
180
180
  const traversal = options.stagingResolution === true ? { virtual: false } : undefined;
181
181
  try {
182
- resolved = await this.#resolve(path, options, options.stagingResolution !== true && (options.create !== undefined || options.creation !== "exclusive"), options.create, traversal);
182
+ resolved = await this.#resolve(path, options, options.stagingResolution === true ? options.followFinalSymlink === true : options.create !== undefined || options.creation !== "exclusive", options.create, traversal);
183
183
  }
184
184
  catch (error) {
185
185
  options.signal?.throwIfAborted();
@@ -210,7 +210,7 @@ export class DeviceFileSystem {
210
210
  // This intent cannot bind virtual traversal. Do not infer other path
211
211
  // capabilities by resolving the shadowed entry in the backing filesystem.
212
212
  if (traversal?.virtual)
213
- return Object.freeze({ synchronousStagingResolution: false });
213
+ return Object.freeze({ synchronousStagingResolution: false, synchronousFollowedStagingResolution: false });
214
214
  if (selected === undefined) {
215
215
  const query = this.#filesystem.capabilitiesFor;
216
216
  options.signal?.throwIfAborted();
@@ -229,6 +229,7 @@ export class DeviceFileSystem {
229
229
  throw new FsError("EAGAIN", { path });
230
230
  if ([resolution.path, ...resolution.traversed.map(entry => entry.path)].some(entry => entry === deviceDirectory || entry.startsWith(`${deviceDirectory}/`))) {
231
231
  (unavailable ??= {}).synchronousStagingResolution = false;
232
+ unavailable.synchronousFollowedStagingResolution = false;
232
233
  }
233
234
  runStagingGuard(resolution.validate);
234
235
  }
@@ -237,6 +238,7 @@ export class DeviceFileSystem {
237
238
  if (!isFsError(error, "ENOTSUP"))
238
239
  throw error;
239
240
  (unavailable ??= {}).synchronousStagingResolution = false;
241
+ unavailable.synchronousFollowedStagingResolution = false;
240
242
  }
241
243
  }
242
244
  if (resolved.startsWith(`${deviceDirectory}/`)) {
@@ -244,6 +246,7 @@ export class DeviceFileSystem {
244
246
  u.atomicStagingAncestry = false;
245
247
  u.synchronousDirectoryValidation = false;
246
248
  u.synchronousStagingResolution = false;
249
+ u.synchronousFollowedStagingResolution = false;
247
250
  }
248
251
  if (typeof this.#filesystem.open !== "function" && capabilities.open !== false)
249
252
  (unavailable ??= {}).open = false;
@@ -753,19 +756,19 @@ export class DeviceFileSystem {
753
756
  }
754
757
  }
755
758
  async prepareStagingResolution(path, options = {}) {
756
- const controls = options.signal === undefined ? {} : { signal: options.signal };
759
+ const controls = { ...(options.signal === undefined ? {} : { signal: options.signal }), ...(options.followFinalSymlink === true ? { followFinalSymlink: true } : {}) };
757
760
  controls.signal?.throwIfAborted();
758
761
  if (normalizePath(path) !== path || !path.startsWith("/"))
759
762
  throw new FsError("EINVAL", { path });
760
763
  try {
761
764
  const traversal = { virtual: false };
762
- const resolved = await this.#resolve(path, controls, false, undefined, traversal);
765
+ const resolved = await this.#resolve(path, controls, controls.followFinalSymlink === true, undefined, traversal);
763
766
  controls.signal?.throwIfAborted();
764
767
  if (traversal.virtual)
765
768
  throw new FsError("ENOTSUP", { path });
766
769
  const declared = ownedMutationCapabilities(this.#filesystem, await this.#filesystem.capabilitiesFor?.(path, { ...controls, stagingResolution: true }) ?? this.#filesystem.capabilities);
767
770
  controls.signal?.throwIfAborted();
768
- if (declared.synchronousStagingResolution !== true || !this.#filesystem.prepareStagingResolution)
771
+ if (declared.synchronousStagingResolution !== true || controls.followFinalSymlink === true && declared.synchronousFollowedStagingResolution !== true || !this.#filesystem.prepareStagingResolution)
769
772
  throw new FsError("ENOTSUP", { path });
770
773
  const receipt = snapshotStagingResolution(await this.#filesystem.prepareStagingResolution(path, controls));
771
774
  controls.signal?.throwIfAborted();
@@ -1,4 +1,4 @@
1
- import type { AppendFileOptions, CopyFileOptions, DirectoryEntry, EntryComparison, FileReadHandle, FileResizeHandle, FileStat, FileSystem, FileSystemCapabilities, FsOptions, ChmodOptions, RenameOptions, MkdirOptions, ReadDirectoryOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, FileDescriptor, OpenFileOptions, OpenReadFileOptions, OpenResizeFileOptions, WriteFileOptions, ConditionalWriteFileOptions, ConditionalRemoveFileOptions, ConditionalRemoveEntryOptions, ConditionalRemoveEntryReceiptOptions, CreateStagedFileOptions, FileStaging, FileStagingEntry, FileStagingResolution, PublishStagedFileOptions, PublishStagedFileSetOptions, PrepareDirectoryOptions, StagedFileContent } from "../../contracts/filesystem.js";
1
+ import type { AppendFileOptions, CopyFileOptions, DirectoryEntry, EntryComparison, FileReadHandle, FileResizeHandle, FileStat, FileSystem, FileSystemCapabilities, FsOptions, ChmodOptions, RenameOptions, MkdirOptions, ReadDirectoryOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, FileDescriptor, OpenFileOptions, OpenReadFileOptions, OpenResizeFileOptions, WriteFileOptions, ConditionalWriteFileOptions, ConditionalRemoveFileOptions, ConditionalRemoveEntryOptions, ConditionalRemoveEntryReceiptOptions, CreateStagedFileOptions, FileStaging, FileStagingEntry, FileStagingResolution, PrepareStagingResolutionOptions, PublishStagedFileOptions, PublishStagedFileSetOptions, PrepareDirectoryOptions, StagedFileContent } from "../../contracts/filesystem.js";
2
2
  import type { ByteSource } from "../../contracts/io.js";
3
3
  import { type MemoryAtomicView } from "./atomic-view.js";
4
4
  import { MemoryAllocation, MemoryLedger } from "./ledger.js";
@@ -116,7 +116,7 @@ export declare class MemoryFileSystem implements FileSystem {
116
116
  createStagedFile(directoryPath: string, name: string, content: StagedFileContent, options: CreateStagedFileOptions): Promise<FileStaging>;
117
117
  private retainStagingCleanup;
118
118
  prepareDirectoryAncestry(ancestors: readonly FileStagingEntry[], options?: FsOptions): Promise<() => true>;
119
- prepareStagingResolution(path: string, options?: FsOptions): Promise<FileStagingResolution>;
119
+ prepareStagingResolution(path: string, options?: PrepareStagingResolutionOptions): Promise<FileStagingResolution>;
120
120
  private verifyDirectoryAncestry;
121
121
  publishStagedFile(receipt: FileStaging, destination: string, options: PublishStagedFileOptions): Promise<void>;
122
122
  publishStagedFileSet(receipt: FileStaging, destination: string, options: PublishStagedFileSetOptions): Promise<FileStat>;
@@ -585,7 +585,7 @@ const SHARED_STOCK_MEMORY_CAPABILITIES = Object.freeze({
585
585
  timestamps: true,
586
586
  atomicRename: true,
587
587
  atomicStagedFileMutation: true, atomicFileStaging: true, retainedStagingCleanup: true, retainedStagingWrite: true, atomicStagingAncestry: true, atomicFileMutation: true, atomicEntryRemoval: true, atomicEntryRemovalReceipt: true, atomicTreeRemoval: true,
588
- synchronousDirectoryValidation: true, synchronousStagingResolution: true, guardedStagingPublication: true,
588
+ synchronousDirectoryValidation: true, synchronousStagingResolution: true, synchronousFollowedStagingResolution: true, guardedStagingPublication: true,
589
589
  atomicDirectoryMetadata: true,
590
590
  streamingRead: true,
591
591
  retainedRead: true,
@@ -2186,13 +2186,14 @@ export class MemoryFileSystem {
2186
2186
  return () => this.verifyDirectoryAncestry(entries, controls);
2187
2187
  }
2188
2188
  async prepareStagingResolution(path, options = {}) {
2189
+ const followFinal = options.followFinalSymlink === true;
2189
2190
  const controls = options.signal === undefined ? {} : { signal: options.signal };
2190
2191
  controls.signal?.throwIfAborted();
2191
2192
  this.validatePath(path, "prepareStagingResolution");
2192
2193
  if (!path.startsWith("/") || normalizePath(path) !== path)
2193
2194
  this.fail("EINVAL", "prepareStagingResolution", path);
2194
2195
  const traversed = [];
2195
- const location = this.resolve(path, "prepareStagingResolution", { followFinal: false, allowMissing: true, resolutionSteps: traversed });
2196
+ const location = this.resolve(path, "prepareStagingResolution", { followFinal, allowMissing: true, resolutionSteps: traversed });
2196
2197
  if (location.node && location.node.type !== "file")
2197
2198
  this.fail("ENOTSUP", "prepareStagingResolution", path);
2198
2199
  const parentPath = location.path.slice(0, location.path.lastIndexOf("/")) || "/";
@@ -2207,7 +2208,7 @@ export class MemoryFileSystem {
2207
2208
  const currentSteps = [];
2208
2209
  let current;
2209
2210
  try {
2210
- current = this.resolve(path, "verifyStagingResolution", { followFinal: false, allowMissing: true, resolutionSteps: currentSteps });
2211
+ current = this.resolve(path, "verifyStagingResolution", { followFinal, allowMissing: true, resolutionSteps: currentSteps });
2211
2212
  }
2212
2213
  catch (error) {
2213
2214
  if (error instanceof FsError && ["ENOENT", "ENOTDIR", "ELOOP"].includes(error.code))
@@ -1,4 +1,4 @@
1
- import type { AppendFileOptions, CapabilityQueryOptions, CopyFileOptions, DirectoryEntry, FileReadHandle, FileResizeHandle, FileResizeOperation, FileResizeOptions, FileStat, FileSystem, OpenReadFileOptions, OpenResizeFileOptions, FileSystemCapabilities, FsOptions, ChmodOptions, RenameOptions, MkdirOptions, ReadDirectoryOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions, ConditionalFilePublicationOptions, ConditionalWriteFileOptions, ConditionalRemoveFileOptions, ConditionalRemoveEntryOptions, ConditionalRemoveEntryReceiptOptions, CreateStagedFileOptions, FileStaging, FileStagingEntry, FileStagingResolution, PublishStagedFileOptions, PublishStagedFileSetOptions, PrepareDirectoryOptions, StagedFileContent } from "../../contracts/filesystem.js";
1
+ import type { AppendFileOptions, CapabilityQueryOptions, CopyFileOptions, DirectoryEntry, FileReadHandle, FileResizeHandle, FileResizeOperation, FileResizeOptions, FileStat, FileSystem, OpenReadFileOptions, OpenResizeFileOptions, FileSystemCapabilities, FsOptions, ChmodOptions, RenameOptions, MkdirOptions, ReadDirectoryOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions, ConditionalFilePublicationOptions, ConditionalWriteFileOptions, ConditionalRemoveFileOptions, ConditionalRemoveEntryOptions, ConditionalRemoveEntryReceiptOptions, CreateStagedFileOptions, FileStaging, FileStagingEntry, FileStagingResolution, PrepareStagingResolutionOptions, PublishStagedFileOptions, PublishStagedFileSetOptions, PrepareDirectoryOptions, StagedFileContent } from "../../contracts/filesystem.js";
2
2
  import type { ByteSource } from "../../contracts/io.js";
3
3
  import type { FileDescriptor, OpenFileOptions } from "../../contracts/descriptor.js";
4
4
  export interface MountFileSystemOptions {
@@ -18,7 +18,7 @@ export declare class MountFileSystem implements FileSystem {
18
18
  private supportsStagingAncestry;
19
19
  private supportsDirectoryValidation;
20
20
  prepareDirectoryAncestry(ancestors: readonly FileStagingEntry[], options?: FsOptions): Promise<() => true>;
21
- prepareStagingResolution(path: string, options?: FsOptions): Promise<FileStagingResolution>;
21
+ prepareStagingResolution(path: string, options?: PrepareStagingResolutionOptions): Promise<FileStagingResolution>;
22
22
  private prepareAncestry;
23
23
  private protected;
24
24
  openReadFile(path: string, options?: OpenReadFileOptions): Promise<FileReadHandle>;
@@ -191,7 +191,8 @@ export class MountFileSystem {
191
191
  fail("EINVAL");
192
192
  const location = await this.resolve(path, options, {
193
193
  allowMissing: options.create ?? true,
194
- followFinal: options.stagingResolution !== true && (options.create !== undefined || options.creation !== "exclusive"),
194
+ retainedResolution: options.stagingResolution === true && options.followFinalSymlink === true,
195
+ followFinal: options.stagingResolution === true ? options.followFinalSymlink === true : options.create !== undefined || options.creation !== "exclusive",
195
196
  ...(options.create === undefined ? {} : { resizeCreate: options.create }),
196
197
  });
197
198
  const observed = ownedMutationCapabilities(location.mount.backend, await location.mount.backend.capabilitiesFor?.(location.local, options)
@@ -212,15 +213,15 @@ export class MountFileSystem {
212
213
  const input = location.mount.path === "/" ? path : path.slice(location.mount.path.length) || "/";
213
214
  const declared = input === location.local ? resize : ownedMutationCapabilities(location.mount.backend, await location.mount.backend.capabilitiesFor?.(input, options) ?? location.mount.backend.capabilities);
214
215
  options.signal?.throwIfAborted();
215
- resolution = declared.synchronousStagingResolution === true && await this.supportsStagingAncestry(location, resize, options);
216
+ resolution = declared.synchronousStagingResolution === true && (options.followFinalSymlink !== true || declared.synchronousFollowedStagingResolution === true) && await this.supportsStagingAncestry(location, resize, options);
216
217
  }
217
218
  }
218
219
  const conditionalChmod = options.conditionalChmod === true
219
220
  ? resize.conditionalChmod === true && typeof location.mount.backend.chmod === "function"
220
221
  && await this.supportsDirectoryValidation(location.path.slice(0, location.path.lastIndexOf("/")) || "/", options, true)
221
222
  : this.capabilities.conditionalChmod;
222
- const { synchronousDirectoryValidation: ignoredValidation, synchronousStagingResolution: ignoredResolution, ...ordinary } = resize;
223
- const withOpen = { ...ordinary, ...(conditionalChmod === undefined ? {} : { conditionalChmod }), ...(resolution === undefined ? {} : { synchronousStagingResolution: resolution }), ...(validation === undefined ? {} : { synchronousDirectoryValidation: validation }), atomicStagingAncestry: ancestry, ...(typeof location.mount.backend.open === "function" ? {} : { open: false }) };
223
+ const { synchronousDirectoryValidation: ignoredValidation, synchronousStagingResolution: ignoredResolution, synchronousFollowedStagingResolution: ignoredFollowedResolution, ...ordinary } = resize;
224
+ const withOpen = { ...ordinary, ...(conditionalChmod === undefined ? {} : { conditionalChmod }), ...(resolution === undefined ? {} : { synchronousStagingResolution: resolution, ...(options.followFinalSymlink === true ? { synchronousFollowedStagingResolution: resolution } : {}) }), ...(validation === undefined ? {} : { synchronousDirectoryValidation: validation }), atomicStagingAncestry: ancestry, ...(typeof location.mount.backend.open === "function" ? {} : { open: false }) };
224
225
  const capabilities = location.synthetic ? { ...withOpen, open: false, retainedRead: false }
225
226
  : retainedResizeCapabilities(location.mount.backend, retainedReadCapabilities(location.mount.backend, withOpen));
226
227
  if (location.synthetic)
@@ -264,19 +265,19 @@ export class MountFileSystem {
264
265
  return this.operation("prepareDirectoryAncestry", ancestors.at(-1)?.path ?? "/", options, () => this.prepareAncestry(ancestors, options));
265
266
  }
266
267
  prepareStagingResolution(path, options = {}) {
267
- const controls = options.signal === undefined ? {} : { signal: options.signal };
268
+ const controls = { ...(options.signal === undefined ? {} : { signal: options.signal }), ...(options.followFinalSymlink === true ? { followFinalSymlink: true } : {}) };
268
269
  return this.operation("prepareStagingResolution", path, controls, async () => {
269
270
  if (normalizePath(globalPath(path)) !== path)
270
271
  fail("EINVAL");
271
272
  const observed = [];
272
- const location = await this.resolve(path, controls, { followFinal: false, allowMissing: true, resolutionSteps: observed });
273
+ const location = await this.resolve(path, controls, { followFinal: controls.followFinalSymlink === true, retainedResolution: controls.followFinalSymlink === true, allowMissing: true, resolutionSteps: observed });
273
274
  if (location.synthetic || !within(location.mount.path, path))
274
275
  fail("ENOTSUP");
275
276
  const backend = location.mount.backend;
276
277
  const input = location.mount.path === "/" ? path : path.slice(location.mount.path.length) || "/";
277
278
  const declared = ownedMutationCapabilities(backend, await backend.capabilitiesFor?.(input, { ...controls, stagingResolution: true }) ?? backend.capabilities);
278
279
  controls.signal?.throwIfAborted();
279
- if (declared.synchronousStagingResolution !== true || !backend.prepareStagingResolution)
280
+ if (declared.synchronousStagingResolution !== true || controls.followFinalSymlink === true && declared.synchronousFollowedStagingResolution !== true || !backend.prepareStagingResolution)
280
281
  fail("ENOTSUP");
281
282
  const prefix = directoryAncestryPaths(location.mount.path).map(ancestor => {
282
283
  const entry = observed.find(step => step.path === ancestor);
@@ -546,6 +547,10 @@ export class MountFileSystem {
546
547
  let followedFinalLink = false;
547
548
  const verified = async (location) => {
548
549
  let inspection = !location.stat && settings.resizeCreate === true ? creationVerification : verification;
550
+ // A guarded resolution binds the original link chain and missing target
551
+ // through the authoritative backend receipt; realpath cannot name absence.
552
+ if (settings.retainedResolution && !location.stat && followedFinalLink)
553
+ inspection = undefined;
549
554
  // A missing entry has no realpath. Verify its existing parent while
550
555
  // leaving dangling final symlinks on the ordinary following path.
551
556
  if (inspection && !location.stat && settings.allowMissing && !followedFinalLink && inspection.finalName === undefined) {
@@ -43,6 +43,7 @@ export declare class OverlayFileSystem implements FileSystem {
43
43
  private bytes;
44
44
  private cleanGarbage;
45
45
  cleanup(options?: FsOptions): Promise<void>;
46
+ private stagingOptions;
46
47
  private staged;
47
48
  private preserve;
48
49
  private clone;
@@ -554,7 +554,12 @@ export class OverlayFileSystem {
554
554
  async cleanup(options = {}) {
555
555
  return this.run(options, () => this.cleanGarbage(true));
556
556
  }
557
+ // Receipts describe overlay paths and identities, never backing-layer staging paths.
558
+ stagingOptions({ signal }) {
559
+ return signal === undefined ? {} : { signal };
560
+ }
557
561
  async staged(options, operation) {
562
+ options = this.stagingOptions(options);
558
563
  const root = `/.virtual-bash-overlay-${platform.randomUUID()}`;
559
564
  if (await this.maybeStat(this.#upper, root, options) || await this.maybeStat(this.#lower, root, options))
560
565
  fail("EEXIST", root);
@@ -570,6 +575,7 @@ export class OverlayFileSystem {
570
575
  }
571
576
  }
572
577
  async preserve(path, stat, options) {
578
+ options = this.stagingOptions(options);
573
579
  if (this.#upper.chmod)
574
580
  await this.#upper.chmod(path, stat.mode & 0o7777, options);
575
581
  else if (((await this.#upper.lstat(path, options)).mode & 0o7777) !== (stat.mode & 0o7777))
@@ -579,6 +585,7 @@ export class OverlayFileSystem {
579
585
  await this.#upper.utimes(path, stat.atimeMs, stat.mtimeMs, options);
580
586
  }
581
587
  async clone(entry, destination, options) {
588
+ options = this.stagingOptions(options);
582
589
  if (entry.stat.type !== "directory" && ((entry.stat.nlink ?? 1) > 1
583
590
  || (entry.backend.capabilities.hardlinks === true && entry.stat.nlink === undefined))) {
584
591
  fail("ENOTSUP", entry.path, "copy-up cannot preserve hardlink identity");
@@ -608,6 +615,7 @@ export class OverlayFileSystem {
608
615
  }
609
616
  }
610
617
  async ensureDirectory(path, options) {
618
+ options = this.stagingOptions(options);
611
619
  const entry = await this.lookup(path, options);
612
620
  if (!entry)
613
621
  fail("ENOENT", path);
@@ -618,6 +626,7 @@ export class OverlayFileSystem {
618
626
  await this.copyUp(entry, options);
619
627
  }
620
628
  async copyUp(entry, options) {
629
+ options = this.stagingOptions(options);
621
630
  if (entry.backend === this.#upper)
622
631
  return;
623
632
  if (entry.path === "/")
@@ -640,6 +649,7 @@ export class OverlayFileSystem {
640
649
  });
641
650
  }
642
651
  async parent(path, options) {
652
+ options = this.stagingOptions(options);
643
653
  const parent = await this.lookup(dirname(path), options);
644
654
  if (!parent)
645
655
  fail("ENOENT", dirname(path));
@@ -376,6 +376,24 @@ export class OverlayMemoryPublication {
376
376
  const owned = await this.upper.createStagedFile(directory, name, content, { ...options, parent });
377
377
  const staging = Object.freeze({
378
378
  parent: owned.parent, directory: owned.directory, file: owned.file,
379
+ ...(owned.writer ? { writer: Object.freeze({
380
+ write: async (bytes, controls = {}) => {
381
+ controls.signal?.throwIfAborted();
382
+ this.stores();
383
+ guard?.();
384
+ this.check(ancestors);
385
+ await owned.writer.write(bytes, controls);
386
+ },
387
+ finish: async (controls = {}) => {
388
+ controls.signal?.throwIfAborted();
389
+ this.stores();
390
+ guard?.();
391
+ this.check(ancestors);
392
+ const stat = await owned.writer.finish(controls);
393
+ this.stages.set(staging.directory, { ...owned, file: { ...owned.file, stat } });
394
+ return stat;
395
+ },
396
+ }) } : {}),
379
397
  ...(owned.cleanup ? { cleanup: createStagingCleanup(directory, controls => this.cleanup(staging, controls, true), () => owned.cleanup.close()) } : {}),
380
398
  });
381
399
  this.stages.set(staging.directory, owned);
@@ -459,7 +459,7 @@ export function scopeFileSystem(filesystem, charge, signal, cleanupCharge = char
459
459
  try {
460
460
  const declared = ownedMutationCapabilities(original, await original.capabilitiesFor?.(path, { ...controls, stagingResolution: true }) ?? original.capabilities);
461
461
  controls.signal?.throwIfAborted();
462
- if (declared.synchronousStagingResolution !== true)
462
+ if (declared.synchronousStagingResolution !== true || controls.followFinalSymlink === true && declared.synchronousFollowedStagingResolution !== true)
463
463
  throw new FsError("ENOTSUP", { path });
464
464
  const resolution = snapshotStagingResolution(await Reflect.apply(method, original, [path, controls]));
465
465
  controls.signal?.throwIfAborted();
@@ -49,7 +49,7 @@ export declare class IntegerTable {
49
49
  /** Ordered replay with a fixed 16-level radix stack (at most 2 KiB of
50
50
  * owned node bytes) and 128 output records. Batches avoid alternating sparse
51
51
  * index reads with consumer writes on every record. Mutation is not permitted. */
52
- entries(): AsyncGenerator<readonly [bigint, bigint]>;
52
+ entries(start?: bigint, end?: bigint): AsyncGenerator<readonly [bigint, bigint]>;
53
53
  /** Hot radix paths must not evict dirty leaf pages in a one-page backend. */
54
54
  private branch;
55
55
  private lookup;
@@ -103,14 +103,20 @@ export class PagedStorage {
103
103
  this.pages.set(number, cached);
104
104
  return cached;
105
105
  }
106
+ let reusable;
106
107
  if (this.pages.size === this.maxPages) {
107
108
  if (!this.descriptor)
108
109
  await this.spill();
109
110
  const [oldNumber, oldPage] = this.pages.entries().next().value;
110
111
  await this.flush(oldNumber, oldPage);
111
112
  this.pages.delete(oldNumber);
113
+ reusable = oldPage;
112
114
  }
113
- const page = { bytes: new Uint8Array(pageBytes), dirty: false };
115
+ // Flush owns the bytes until its awaited write completes. Reuse only then;
116
+ // zero new/unwritten ranges so the previous page cannot leak into them.
117
+ const page = reusable ?? { bytes: new Uint8Array(pageBytes), dirty: false };
118
+ if (reusable)
119
+ page.bytes.fill(0);
114
120
  if (number * pageBytes < this.diskLength) {
115
121
  let offset = 0;
116
122
  while (offset < pageBytes) {
@@ -204,8 +210,14 @@ export class IntegerTable {
204
210
  async retain(key, value, dirty) {
205
211
  if (this.cache.size === this.maxEntries && !this.cache.has(key)) {
206
212
  const [oldKey, old] = this.cache.entries().next().value;
213
+ // Flush the bounded dirty window together, before the caller touches other
214
+ // stored data. One dirty leaf per insertion otherwise thrashes a page cache.
207
215
  if (old.dirty)
208
- await this.persist(oldKey, old.value);
216
+ for (const [key, entry] of this.cache)
217
+ if (entry.dirty) {
218
+ await this.persist(key, entry.value);
219
+ entry.dirty = false;
220
+ }
209
221
  this.cache.delete(oldKey);
210
222
  }
211
223
  this.cache.delete(key);
@@ -232,7 +244,11 @@ export class IntegerTable {
232
244
  /** Ordered replay with a fixed 16-level radix stack (at most 2 KiB of
233
245
  * owned node bytes) and 128 output records. Batches avoid alternating sparse
234
246
  * index reads with consumer writes on every record. Mutation is not permitted. */
235
- async *entries() {
247
+ async *entries(start = 0n, end = 0x10000000000000000n) {
248
+ if (start < 0n || start > end || end > 0x10000000000000000n)
249
+ throw new RangeError("Invalid integer table range");
250
+ if (start === end)
251
+ return;
236
252
  const revision = this.revision;
237
253
  const check = () => { if (revision !== this.revision)
238
254
  throw new Error("Integer table changed during iteration"); };
@@ -259,6 +275,8 @@ export class IntegerTable {
259
275
  if (!value)
260
276
  continue;
261
277
  const key = prefix | BigInt(slot) << shift;
278
+ if (key >= end || key + (1n << shift) <= start)
279
+ continue;
262
280
  if (shift === 0n)
263
281
  yield [key, value - 1n];
264
282
  else
@@ -16,9 +16,10 @@ console.log(document.children[0].text); // A & B
16
16
  | API | Use |
17
17
  | --- | --- |
18
18
  | `parseXml(source, limits?)` | Parse a string into an `XmlElement`. |
19
+ | `parseXmlStream(chunks, limits?, checkpoint?)` | Consume synchronous or asynchronous string chunks into an `XmlElement`. |
19
20
  | `parseXmlSteps(source, limits?)` | Advance a parser through work checkpoints; the generator returns the completed element. |
20
21
  | `XmlLimitError` | Inspect which configured resource limit was exceeded through its `limit` property. |
21
- | `XmlElement`, `XmlContent`, `XmlAttribute`, `XmlName`, `XmlLimits` | Describe and consume the XML tree without Node.js types. |
22
+ | `XmlElement`, `XmlContent`, `XmlAttribute`, `XmlName`, `XmlLimits`, `XmlStreamLimits` | Describe and consume the XML tree without Node.js types. |
22
23
 
23
24
  Pass positive integer limits for depth, element and content counts, attributes, namespaces, and text. Omitted limits are unlimited. `retainContent` preserves ordered mixed content; `onElement` observes element names, parents, and depths during parsing. `expectedEncoding` checks an XML declaration against the caller's decoded input.
24
25
 
@@ -26,3 +27,11 @@ Pass positive integer limits for depth, element and content counts, attributes,
26
27
  Pass `recover: message => report(message)` to repair truncated elements,
27
28
  mismatched closing tags, and undeclared entities. Each repair calls the callback.
28
29
  Resource limits and the prohibition on DTDs remain in force.
30
+
31
+ `parseXmlStream` consumes each chunk before requesting the next and calls the optional asynchronous checkpoint with at most 512 UTF-16 units. It preserves the buffered parser’s tree shape, namespaces and retained content. The source is closed on parsing or checkpoint failure. Decode byte sources incrementally before passing their strings. This avoids a full source string; the resulting tree and individual XML tokens still reside in memory. Recovery remains available through the buffered parser.
32
+
33
+ For validation or root-name detection, pass `retainTree: false` to `parseXmlStream`. It validates the complete document and enforces the same limits, but returns a root element with empty data fields. Only open element frames, namespace scopes and current parser tokens remain resident; completed descendants, text, attributes and document content are not retained. `onElement` still observes each element.
34
+
35
+ Use `streamElements: { matches, consume }` to process selected complete subtrees asynchronously. Matching non-root elements are detached from their parent; nested matches remain inside the selected ancestor. `consume(element, parent, before?)` runs in source order and is awaited before the next 512-unit parse window. The producer closes on consumer failure. This mode requires normal tree/content retention and retains each selected subtree until consumption; individual large subtrees and XML tokens still need their own storage strategy.
36
+
37
+ Set `streamElements.captureBefore: true` to detach preceding sibling content when each subtree is selected and receive it as `before`. This preserves text, CDATA, comments and sibling order even when multiple subtrees share one parse window. The remaining trailing content stays in the parent. Store both `before` and the subtree when you need to reconstruct the original mixed content.
@@ -0,0 +1,4 @@
1
+ export declare class XmlLimitError extends SyntaxError {
2
+ readonly limit: string;
3
+ constructor(limit: string, message: string);
4
+ }
@@ -0,0 +1,7 @@
1
+ export class XmlLimitError extends SyntaxError {
2
+ limit;
3
+ constructor(limit, message) {
4
+ super(message);
5
+ this.limit = limit;
6
+ }
7
+ }
@@ -1,3 +1,4 @@
1
+ export { XmlLimitError } from "./errors.js";
1
2
  export interface XmlName {
2
3
  readonly name: string;
3
4
  readonly namespace: string;
@@ -39,9 +40,6 @@ export interface XmlLimits {
39
40
  readonly maxTextLength?: number;
40
41
  readonly onElement?: (element: XmlName, parent: XmlName | undefined, depth: number) => void;
41
42
  }
42
- export declare class XmlLimitError extends SyntaxError {
43
- readonly limit: string;
44
- constructor(limit: string, message: string);
45
- }
46
43
  export declare function parseXmlSteps(input: string, limits?: XmlLimits): Generator<number, XmlElement, void>;
47
44
  export declare function parseXml(input: string, limits?: XmlLimits): XmlElement;
45
+ export { parseXmlStream, type XmlStreamLimits } from "./stream.js";