@zenfs/core 0.5.3 → 0.5.5

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.
@@ -80,9 +80,10 @@ export declare const ErrorStrings: {
80
80
  interface ApiErrorJSON {
81
81
  errno: ErrorCode;
82
82
  message: string;
83
- path: string;
83
+ path?: string;
84
84
  code: string;
85
85
  stack: string;
86
+ syscall: string;
86
87
  }
87
88
  /**
88
89
  * Represents a ZenFS error. Passed back to applications after a failed
@@ -91,18 +92,10 @@ interface ApiErrorJSON {
91
92
  export declare class ApiError extends Error implements NodeJS.ErrnoException {
92
93
  errno: ErrorCode;
93
94
  path?: string;
95
+ syscall: string;
94
96
  static fromJSON(json: ApiErrorJSON): ApiError;
95
- static OnPath(code: ErrorCode, path: string): ApiError;
96
- static EACCES(path: string): ApiError;
97
- static ENOENT(path: string): ApiError;
98
- static EEXIST(path: string): ApiError;
99
- static EISDIR(path: string): ApiError;
100
- static ENOTDIR(path: string): ApiError;
101
- static EPERM(path: string): ApiError;
102
- static ENOTEMPTY(path: string): ApiError;
97
+ static With(code: string, path: string, syscall?: string): ApiError;
103
98
  code: string;
104
- syscall: string;
105
- stack?: string;
106
99
  /**
107
100
  * Represents a ZenFS error. Passed back to applications after a failed
108
101
  * call to the ZenFS API.
@@ -113,7 +106,7 @@ export declare class ApiError extends Error implements NodeJS.ErrnoException {
113
106
  * @param type The type of the error.
114
107
  * @param message A descriptive error message.
115
108
  */
116
- constructor(errno: ErrorCode, message?: string, path?: string);
109
+ constructor(errno: ErrorCode, message?: string, path?: string, syscall?: string);
117
110
  /**
118
111
  * @return A friendly error message.
119
112
  */
package/dist/ApiError.js CHANGED
@@ -98,34 +98,13 @@ export const ErrorStrings = {
98
98
  */
99
99
  export class ApiError extends Error {
100
100
  static fromJSON(json) {
101
- const err = new ApiError(json.errno, json.message, json.path);
101
+ const err = new ApiError(json.errno, json.message, json.path, json.syscall);
102
102
  err.code = json.code;
103
103
  err.stack = json.stack;
104
104
  return err;
105
105
  }
106
- static OnPath(code, path) {
107
- return new ApiError(code, ErrorStrings[code], path);
108
- }
109
- static EACCES(path) {
110
- return this.OnPath(ErrorCode.EACCES, path);
111
- }
112
- static ENOENT(path) {
113
- return this.OnPath(ErrorCode.ENOENT, path);
114
- }
115
- static EEXIST(path) {
116
- return this.OnPath(ErrorCode.EEXIST, path);
117
- }
118
- static EISDIR(path) {
119
- return this.OnPath(ErrorCode.EISDIR, path);
120
- }
121
- static ENOTDIR(path) {
122
- return this.OnPath(ErrorCode.ENOTDIR, path);
123
- }
124
- static EPERM(path) {
125
- return this.OnPath(ErrorCode.EPERM, path);
126
- }
127
- static ENOTEMPTY(path) {
128
- return this.OnPath(ErrorCode.ENOTEMPTY, path);
106
+ static With(code, path, syscall) {
107
+ return new ApiError(ErrorCode[code], ErrorStrings[ErrorCode[code]], path, syscall);
129
108
  }
130
109
  /**
131
110
  * Represents a ZenFS error. Passed back to applications after a failed
@@ -137,12 +116,11 @@ export class ApiError extends Error {
137
116
  * @param type The type of the error.
138
117
  * @param message A descriptive error message.
139
118
  */
140
- constructor(errno, message = ErrorStrings[errno], path) {
119
+ constructor(errno, message = ErrorStrings[errno], path, syscall = '') {
141
120
  super(message);
142
121
  this.errno = errno;
143
122
  this.path = path;
144
- // Unsupported.
145
- this.syscall = '';
123
+ this.syscall = syscall;
146
124
  this.code = ErrorCode[errno];
147
125
  this.message = `${this.code}: ${message}${this.path ? `, '${this.path}'` : ''}`;
148
126
  }
@@ -159,6 +137,7 @@ export class ApiError extends Error {
159
137
  path: this.path,
160
138
  stack: this.stack,
161
139
  message: this.message,
140
+ syscall: this.syscall,
162
141
  };
163
142
  }
164
143
  /**
package/dist/FileIndex.js CHANGED
@@ -306,7 +306,7 @@ export class FileIndexFS extends Readonly(FileSystem) {
306
306
  async stat(path) {
307
307
  const inode = this._index.get(path);
308
308
  if (!inode) {
309
- throw ApiError.ENOENT(path);
309
+ throw ApiError.With('ENOENT', path, 'stat');
310
310
  }
311
311
  if (inode.isDirectory()) {
312
312
  return inode.stats;
@@ -319,7 +319,7 @@ export class FileIndexFS extends Readonly(FileSystem) {
319
319
  statSync(path) {
320
320
  const inode = this._index.get(path);
321
321
  if (!inode) {
322
- throw ApiError.ENOENT(path);
322
+ throw ApiError.With('ENOENT', path, 'statSync');
323
323
  }
324
324
  if (inode.isDirectory()) {
325
325
  return inode.stats;
@@ -337,10 +337,10 @@ export class FileIndexFS extends Readonly(FileSystem) {
337
337
  // Check if the path exists, and is a file.
338
338
  const inode = this._index.get(path);
339
339
  if (!inode) {
340
- throw ApiError.ENOENT(path);
340
+ throw ApiError.With('ENOENT', path, 'openFile');
341
341
  }
342
342
  if (!inode.toStats().hasAccess(flagToMode(flag), cred)) {
343
- throw ApiError.EACCES(path);
343
+ throw ApiError.With('EACCESS', path, 'openFile');
344
344
  }
345
345
  if (inode.isDirectory()) {
346
346
  const stats = inode.stats;
@@ -356,10 +356,10 @@ export class FileIndexFS extends Readonly(FileSystem) {
356
356
  // Check if the path exists, and is a file.
357
357
  const inode = this._index.get(path);
358
358
  if (!inode) {
359
- throw ApiError.ENOENT(path);
359
+ throw ApiError.With('ENOENT', path, 'openFileSync');
360
360
  }
361
361
  if (!inode.toStats().hasAccess(flagToMode(flag), cred)) {
362
- throw ApiError.EACCES(path);
362
+ throw ApiError.With('EACCES', path, 'openFileSync');
363
363
  }
364
364
  if (inode.isDirectory()) {
365
365
  const stats = inode.stats;
@@ -371,23 +371,23 @@ export class FileIndexFS extends Readonly(FileSystem) {
371
371
  // Check if it exists.
372
372
  const inode = this._index.get(path);
373
373
  if (!inode) {
374
- throw ApiError.ENOENT(path);
374
+ throw ApiError.With('ENOENT', path, 'readdir');
375
375
  }
376
376
  if (inode.isDirectory()) {
377
377
  return inode.listing;
378
378
  }
379
- throw ApiError.ENOTDIR(path);
379
+ throw ApiError.With('ENOTDIR', path, 'readdir');
380
380
  }
381
381
  readdirSync(path) {
382
382
  // Check if it exists.
383
383
  const inode = this._index.get(path);
384
384
  if (!inode) {
385
- throw ApiError.ENOENT(path);
385
+ throw ApiError.With('ENOENT', path, 'readdirSync');
386
386
  }
387
387
  if (inode.isDirectory()) {
388
388
  return inode.listing;
389
389
  }
390
- throw ApiError.ENOTDIR(path);
390
+ throw ApiError.With('ENOTDIR', path, 'readdirSync');
391
391
  }
392
392
  }
393
393
  export class SyncFileIndexFS extends Sync((FileIndexFS)) {
@@ -127,10 +127,10 @@ export class AsyncStoreFS extends Async(FileSystem) {
127
127
  // Remove oldPath from parent's directory listing.
128
128
  oldDirNode = await this.findINode(tx, oldParent), oldDirList = await this.getDirListing(tx, oldDirNode, oldParent);
129
129
  if (!oldDirNode.toStats().hasAccess(W_OK, cred)) {
130
- throw ApiError.EACCES(oldPath);
130
+ throw ApiError.With('EACCES', oldPath, 'rename');
131
131
  }
132
132
  if (!oldDirList[oldName]) {
133
- throw ApiError.ENOENT(oldPath);
133
+ throw ApiError.With('ENOENT', oldPath, 'rename');
134
134
  }
135
135
  const nodeId = oldDirList[oldName];
136
136
  delete oldDirList[oldName];
@@ -168,7 +168,7 @@ export class AsyncStoreFS extends Async(FileSystem) {
168
168
  }
169
169
  else {
170
170
  // If it's a directory, throw a permissions error.
171
- throw ApiError.EPERM(newPath);
171
+ throw ApiError.With('EPERM', newPath, 'rename');
172
172
  }
173
173
  }
174
174
  newDirList[newName] = nodeId;
@@ -193,11 +193,11 @@ export class AsyncStoreFS extends Async(FileSystem) {
193
193
  const tx = this.store.beginTransaction();
194
194
  const inode = await this.findINode(tx, p);
195
195
  if (!inode) {
196
- throw ApiError.ENOENT(p);
196
+ throw ApiError.With('ENOENT', p, 'stat');
197
197
  }
198
198
  const stats = inode.toStats();
199
199
  if (!stats.hasAccess(R_OK, cred)) {
200
- throw ApiError.EACCES(p);
200
+ throw ApiError.With('EACCES', p, 'stat');
201
201
  }
202
202
  return stats;
203
203
  }
@@ -209,10 +209,10 @@ export class AsyncStoreFS extends Async(FileSystem) {
209
209
  async openFile(p, flag, cred) {
210
210
  const tx = this.store.beginTransaction(), node = await this.findINode(tx, p), data = await tx.get(node.ino);
211
211
  if (!node.toStats().hasAccess(flagToMode(flag), cred)) {
212
- throw ApiError.EACCES(p);
212
+ throw ApiError.With('EACCES', p, 'openFile');
213
213
  }
214
214
  if (!data) {
215
- throw ApiError.ENOENT(p);
215
+ throw ApiError.With('ENOENT', p, 'openFile');
216
216
  }
217
217
  return new AsyncFile(this, p, flag, node.toStats(), data);
218
218
  }
@@ -223,7 +223,7 @@ export class AsyncStoreFS extends Async(FileSystem) {
223
223
  // Check first if directory is empty.
224
224
  const list = await this.readdir(p, cred);
225
225
  if (list.length > 0) {
226
- throw ApiError.ENOTEMPTY(p);
226
+ throw ApiError.With('ENOTEMPTY', p, 'rmdir');
227
227
  }
228
228
  await this.removeEntry(p, true, cred);
229
229
  }
@@ -235,7 +235,7 @@ export class AsyncStoreFS extends Async(FileSystem) {
235
235
  const tx = this.store.beginTransaction();
236
236
  const node = await this.findINode(tx, p);
237
237
  if (!node.toStats().hasAccess(R_OK, cred)) {
238
- throw ApiError.EACCES(p);
238
+ throw ApiError.With('EACCES', p, 'readdur');
239
239
  }
240
240
  return Object.keys(await this.getDirListing(tx, node, p));
241
241
  }
@@ -264,16 +264,16 @@ export class AsyncStoreFS extends Async(FileSystem) {
264
264
  async link(existing, newpath, cred) {
265
265
  const tx = this.store.beginTransaction(), existingDir = dirname(existing), existingDirNode = await this.findINode(tx, existingDir);
266
266
  if (!existingDirNode.toStats().hasAccess(R_OK, cred)) {
267
- throw ApiError.EACCES(existingDir);
267
+ throw ApiError.With('EACCES', existingDir, 'link');
268
268
  }
269
269
  const newDir = dirname(newpath), newDirNode = await this.findINode(tx, newDir), newListing = await this.getDirListing(tx, newDirNode, newDir);
270
270
  if (!newDirNode.toStats().hasAccess(W_OK, cred)) {
271
- throw ApiError.EACCES(newDir);
271
+ throw ApiError.With('EACCES', newDir, 'link');
272
272
  }
273
273
  const ino = await this._findINode(tx, existingDir, basename(existing));
274
274
  const node = await this.getINode(tx, ino, existing);
275
275
  if (!node.toStats().hasAccess(W_OK, cred)) {
276
- throw ApiError.EACCES(newpath);
276
+ throw ApiError.With('EACCES', newpath, 'link');
277
277
  }
278
278
  node.nlink++;
279
279
  newListing[basename(newpath)] = ino;
@@ -341,7 +341,7 @@ export class AsyncStoreFS extends Async(FileSystem) {
341
341
  return id;
342
342
  }
343
343
  else {
344
- throw ApiError.ENOENT(resolve(parent, filename));
344
+ throw ApiError.With('ENOENT', resolve(parent, filename), '_findINode');
345
345
  }
346
346
  }
347
347
  }
@@ -358,7 +358,7 @@ export class AsyncStoreFS extends Async(FileSystem) {
358
358
  return id;
359
359
  }
360
360
  else {
361
- throw ApiError.ENOENT(resolve(parent, filename));
361
+ throw ApiError.With('ENOENT', resolve(parent, filename), '_findINode');
362
362
  }
363
363
  }
364
364
  }
@@ -380,7 +380,7 @@ export class AsyncStoreFS extends Async(FileSystem) {
380
380
  async getINode(tx, id, p) {
381
381
  const data = await tx.get(id);
382
382
  if (!data) {
383
- throw ApiError.ENOENT(p);
383
+ throw ApiError.With('ENOENT', p, 'getINode');
384
384
  }
385
385
  return new Inode(data.buffer);
386
386
  }
@@ -390,7 +390,7 @@ export class AsyncStoreFS extends Async(FileSystem) {
390
390
  */
391
391
  async getDirListing(tx, inode, p) {
392
392
  if (!inode.toStats().isDirectory()) {
393
- throw ApiError.ENOTDIR(p);
393
+ throw ApiError.With('ENOTDIR', p, 'getDirListing');
394
394
  }
395
395
  const data = await tx.get(inode.ino);
396
396
  if (!data) {
@@ -399,7 +399,7 @@ export class AsyncStoreFS extends Async(FileSystem) {
399
399
  than a directory listing. The latter should never occur unless
400
400
  the file system is corrupted.
401
401
  */
402
- throw ApiError.ENOENT(p);
402
+ throw ApiError.With('ENOENT', p, 'getDirListing');
403
403
  }
404
404
  return decodeDirListing(data);
405
405
  }
@@ -407,26 +407,18 @@ export class AsyncStoreFS extends Async(FileSystem) {
407
407
  * Adds a new node under a random ID. Retries 5 times before giving up in
408
408
  * the exceedingly unlikely chance that we try to reuse a random ino.
409
409
  */
410
- async addNewNode(tx, data) {
411
- let retries = 0;
412
- const reroll = async () => {
413
- if (++retries === 5) {
414
- // Max retries hit. Return with an error.
415
- throw new ApiError(ErrorCode.EIO, 'Unable to commit data to key-value store.');
416
- }
417
- else {
418
- // Try again.
419
- const ino = randomIno();
420
- const committed = await tx.put(ino, data, false);
421
- if (!committed) {
422
- return reroll();
423
- }
424
- else {
425
- return ino;
426
- }
427
- }
428
- };
429
- return reroll();
410
+ async addNewNode(tx, data, _maxAttempts = 5) {
411
+ if (_maxAttempts <= 0) {
412
+ // Max retries hit. Return with an error.
413
+ throw new ApiError(ErrorCode.EIO, 'Unable to commit data to key-value store.');
414
+ }
415
+ // Make an attempt
416
+ const ino = randomIno();
417
+ const isCommited = await tx.put(ino, data, false);
418
+ if (!isCommited) {
419
+ return await this.addNewNode(tx, data, --_maxAttempts);
420
+ }
421
+ return ino;
430
422
  }
431
423
  /**
432
424
  * Commits a new file (well, a FILE or a DIRECTORY) to the file system with
@@ -442,18 +434,18 @@ export class AsyncStoreFS extends Async(FileSystem) {
442
434
  const parentDir = dirname(p), fname = basename(p), parentNode = await this.findINode(tx, parentDir), dirListing = await this.getDirListing(tx, parentNode, parentDir);
443
435
  //Check that the creater has correct access
444
436
  if (!parentNode.toStats().hasAccess(W_OK, cred)) {
445
- throw ApiError.EACCES(p);
437
+ throw ApiError.With('EACCES', p, 'commitNewFile');
446
438
  }
447
439
  // Invariant: The root always exists.
448
440
  // If we don't check this prior to taking steps below, we will create a
449
441
  // file with name '' in root should p == '/'.
450
442
  if (p === '/') {
451
- throw ApiError.EEXIST(p);
443
+ throw ApiError.With('EEXIST', p, 'commitNewFile');
452
444
  }
453
445
  // Check if file already exists.
454
446
  if (dirListing[fname]) {
455
447
  await tx.abort();
456
- throw ApiError.EEXIST(p);
448
+ throw ApiError.With('EEXIST', p, 'commitNewFile');
457
449
  }
458
450
  try {
459
451
  // Commit data.
@@ -492,21 +484,21 @@ export class AsyncStoreFS extends Async(FileSystem) {
492
484
  }
493
485
  const tx = this.store.beginTransaction(), parent = dirname(p), parentNode = await this.findINode(tx, parent), parentListing = await this.getDirListing(tx, parentNode, parent), fileName = basename(p);
494
486
  if (!parentListing[fileName]) {
495
- throw ApiError.ENOENT(p);
487
+ throw ApiError.With('ENOENT', p, 'removeEntry');
496
488
  }
497
489
  const fileIno = parentListing[fileName];
498
490
  // Get file inode.
499
491
  const fileNode = await this.getINode(tx, fileIno, p);
500
492
  if (!fileNode.toStats().hasAccess(W_OK, cred)) {
501
- throw ApiError.EACCES(p);
493
+ throw ApiError.With('EACCES', p, 'removeEntry');
502
494
  }
503
495
  // Remove from directory listing of parent.
504
496
  delete parentListing[fileName];
505
497
  if (!isDir && fileNode.toStats().isDirectory()) {
506
- throw ApiError.EISDIR(p);
498
+ throw ApiError.With('EISDIR', p, 'removeEntry');
507
499
  }
508
500
  if (isDir && !fileNode.toStats().isDirectory()) {
509
- throw ApiError.ENOTDIR(p);
501
+ throw ApiError.With('ENOTDIR', p, 'removeEntry');
510
502
  }
511
503
  try {
512
504
  await tx.put(parentNode.ino, encodeDirListing(parentListing), true);
@@ -134,7 +134,7 @@ export class UnlockedOverlayFS extends FileSystem {
134
134
  }
135
135
  catch (e) {
136
136
  if (this._deletedFiles.has(oldPath)) {
137
- throw ApiError.ENOENT(oldPath);
137
+ throw ApiError.With('ENOENT', oldPath, 'rename');
138
138
  }
139
139
  }
140
140
  }
@@ -147,7 +147,7 @@ export class UnlockedOverlayFS extends FileSystem {
147
147
  }
148
148
  catch (e) {
149
149
  if (this._deletedFiles.has(oldPath)) {
150
- throw ApiError.ENOENT(oldPath);
150
+ throw ApiError.With('ENOENT', oldPath, 'renameSync');
151
151
  }
152
152
  }
153
153
  }
@@ -158,7 +158,7 @@ export class UnlockedOverlayFS extends FileSystem {
158
158
  }
159
159
  catch (e) {
160
160
  if (this._deletedFiles.has(p)) {
161
- throw ApiError.ENOENT(p);
161
+ throw ApiError.With('ENOENT', p, 'stat');
162
162
  }
163
163
  const oldStat = new Stats(await this._readable.stat(p, cred));
164
164
  // Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type
@@ -173,7 +173,7 @@ export class UnlockedOverlayFS extends FileSystem {
173
173
  }
174
174
  catch (e) {
175
175
  if (this._deletedFiles.has(p)) {
176
- throw ApiError.ENOENT(p);
176
+ throw ApiError.With('ENOENT', p, 'statSync');
177
177
  }
178
178
  const oldStat = new Stats(this._readable.statSync(p, cred));
179
179
  // Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type.
@@ -224,7 +224,7 @@ export class UnlockedOverlayFS extends FileSystem {
224
224
  this.checkInitialized();
225
225
  this.checkPath(p);
226
226
  if (!(await this.exists(p, cred))) {
227
- throw ApiError.ENOENT(p);
227
+ throw ApiError.With('ENOENT', p, 'unlink');
228
228
  }
229
229
  if (await this._writable.exists(p, cred)) {
230
230
  await this._writable.unlink(p, cred);
@@ -238,7 +238,7 @@ export class UnlockedOverlayFS extends FileSystem {
238
238
  this.checkInitialized();
239
239
  this.checkPath(p);
240
240
  if (!this.existsSync(p, cred)) {
241
- throw ApiError.ENOENT(p);
241
+ throw ApiError.With('ENOENT', p, 'unlinkSync');
242
242
  }
243
243
  if (this._writable.existsSync(p, cred)) {
244
244
  this._writable.unlinkSync(p, cred);
@@ -251,7 +251,7 @@ export class UnlockedOverlayFS extends FileSystem {
251
251
  async rmdir(p, cred) {
252
252
  this.checkInitialized();
253
253
  if (!(await this.exists(p, cred))) {
254
- throw ApiError.ENOENT(p);
254
+ throw ApiError.With('ENOENT', p, 'rmdir');
255
255
  }
256
256
  if (await this._writable.exists(p, cred)) {
257
257
  await this._writable.rmdir(p, cred);
@@ -259,7 +259,7 @@ export class UnlockedOverlayFS extends FileSystem {
259
259
  if (await this.exists(p, cred)) {
260
260
  // Check if directory is empty.
261
261
  if ((await this.readdir(p, cred)).length > 0) {
262
- throw ApiError.ENOTEMPTY(p);
262
+ throw ApiError.With('ENOTEMPTY', p, 'rmdir');
263
263
  }
264
264
  else {
265
265
  this.deletePath(p, cred);
@@ -269,7 +269,7 @@ export class UnlockedOverlayFS extends FileSystem {
269
269
  rmdirSync(p, cred) {
270
270
  this.checkInitialized();
271
271
  if (!this.existsSync(p, cred)) {
272
- throw ApiError.ENOENT(p);
272
+ throw ApiError.With('ENOENT', p, 'rmdirSync');
273
273
  }
274
274
  if (this._writable.existsSync(p, cred)) {
275
275
  this._writable.rmdirSync(p, cred);
@@ -277,7 +277,7 @@ export class UnlockedOverlayFS extends FileSystem {
277
277
  if (this.existsSync(p, cred)) {
278
278
  // Check if directory is empty.
279
279
  if (this.readdirSync(p, cred).length > 0) {
280
- throw ApiError.ENOTEMPTY(p);
280
+ throw ApiError.With('ENOTEMPTY', p, 'rmdirSync');
281
281
  }
282
282
  else {
283
283
  this.deletePath(p, cred);
@@ -287,7 +287,7 @@ export class UnlockedOverlayFS extends FileSystem {
287
287
  async mkdir(p, mode, cred) {
288
288
  this.checkInitialized();
289
289
  if (await this.exists(p, cred)) {
290
- throw ApiError.EEXIST(p);
290
+ throw ApiError.With('EEXIST', p, 'mkdir');
291
291
  }
292
292
  // The below will throw should any of the parent directories fail to exist on _writable.
293
293
  await this.createParentDirectories(p, cred);
@@ -296,7 +296,7 @@ export class UnlockedOverlayFS extends FileSystem {
296
296
  mkdirSync(p, mode, cred) {
297
297
  this.checkInitialized();
298
298
  if (this.existsSync(p, cred)) {
299
- throw ApiError.EEXIST(p);
299
+ throw ApiError.With('EEXIST', p, 'mkdirSync');
300
300
  }
301
301
  // The below will throw should any of the parent directories fail to exist on _writable.
302
302
  this.createParentDirectoriesSync(p, cred);
@@ -306,7 +306,7 @@ export class UnlockedOverlayFS extends FileSystem {
306
306
  this.checkInitialized();
307
307
  const dirStats = await this.stat(p, cred);
308
308
  if (!dirStats.isDirectory()) {
309
- throw ApiError.ENOTDIR(p);
309
+ throw ApiError.With('ENOTDIR', p, 'readdir');
310
310
  }
311
311
  // Readdir in both, check delete log on RO file system's listing, merge, return.
312
312
  const contents = [];
@@ -333,7 +333,7 @@ export class UnlockedOverlayFS extends FileSystem {
333
333
  this.checkInitialized();
334
334
  const dirStats = this.statSync(p, cred);
335
335
  if (!dirStats.isDirectory()) {
336
- throw ApiError.ENOTDIR(p);
336
+ throw ApiError.With('ENOTDIR', p, 'readdirSync');
337
337
  }
338
338
  // Readdir in both, check delete log on RO file system's listing, merge, return.
339
339
  let contents = [];
@@ -405,7 +405,7 @@ export class UnlockedOverlayFS extends FileSystem {
405
405
  }
406
406
  checkPath(path) {
407
407
  if (path == deletionLogPath) {
408
- throw ApiError.EPERM(path);
408
+ throw ApiError.With('EPERM', path, 'checkPath');
409
409
  }
410
410
  }
411
411
  /**
@@ -442,7 +442,7 @@ export class UnlockedOverlayFS extends FileSystem {
442
442
  */
443
443
  operateOnWritable(p, cred) {
444
444
  if (!this.existsSync(p, cred)) {
445
- throw ApiError.ENOENT(p);
445
+ throw ApiError.With('ENOENT', p, 'operateOnWriteable');
446
446
  }
447
447
  if (!this._writable.existsSync(p, cred)) {
448
448
  // File is on readable storage. Copy to writable storage before
@@ -452,7 +452,7 @@ export class UnlockedOverlayFS extends FileSystem {
452
452
  }
453
453
  async operateOnWritableAsync(p, cred) {
454
454
  if (!(await this.exists(p, cred))) {
455
- throw ApiError.ENOENT(p);
455
+ throw ApiError.With('ENOENT', p, 'operateOnWritableAsync');
456
456
  }
457
457
  if (!(await this._writable.exists(p, cred))) {
458
458
  return this.copyToWritable(p, cred);
@@ -202,7 +202,7 @@ export declare class SyncStoreFS extends SyncStoreFS_base {
202
202
  * the exceedingly unlikely chance that we try to reuse a random GUID.
203
203
  * @return The GUID that the data was stored under.
204
204
  */
205
- protected addNewNode(tx: SyncTransaction, data: Uint8Array): Ino;
205
+ protected addNewNode(tx: SyncTransaction, data: Uint8Array, _maxAttempts?: number): Ino;
206
206
  /**
207
207
  * Commits a new file (well, a FILE or a DIRECTORY) to the file system with the given mode.
208
208
  * Note: This will commit the transaction.