@zenfs/core 0.5.4 → 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
  }
@@ -434,18 +434,18 @@ export class AsyncStoreFS extends Async(FileSystem) {
434
434
  const parentDir = dirname(p), fname = basename(p), parentNode = await this.findINode(tx, parentDir), dirListing = await this.getDirListing(tx, parentNode, parentDir);
435
435
  //Check that the creater has correct access
436
436
  if (!parentNode.toStats().hasAccess(W_OK, cred)) {
437
- throw ApiError.EACCES(p);
437
+ throw ApiError.With('EACCES', p, 'commitNewFile');
438
438
  }
439
439
  // Invariant: The root always exists.
440
440
  // If we don't check this prior to taking steps below, we will create a
441
441
  // file with name '' in root should p == '/'.
442
442
  if (p === '/') {
443
- throw ApiError.EEXIST(p);
443
+ throw ApiError.With('EEXIST', p, 'commitNewFile');
444
444
  }
445
445
  // Check if file already exists.
446
446
  if (dirListing[fname]) {
447
447
  await tx.abort();
448
- throw ApiError.EEXIST(p);
448
+ throw ApiError.With('EEXIST', p, 'commitNewFile');
449
449
  }
450
450
  try {
451
451
  // Commit data.
@@ -484,21 +484,21 @@ export class AsyncStoreFS extends Async(FileSystem) {
484
484
  }
485
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);
486
486
  if (!parentListing[fileName]) {
487
- throw ApiError.ENOENT(p);
487
+ throw ApiError.With('ENOENT', p, 'removeEntry');
488
488
  }
489
489
  const fileIno = parentListing[fileName];
490
490
  // Get file inode.
491
491
  const fileNode = await this.getINode(tx, fileIno, p);
492
492
  if (!fileNode.toStats().hasAccess(W_OK, cred)) {
493
- throw ApiError.EACCES(p);
493
+ throw ApiError.With('EACCES', p, 'removeEntry');
494
494
  }
495
495
  // Remove from directory listing of parent.
496
496
  delete parentListing[fileName];
497
497
  if (!isDir && fileNode.toStats().isDirectory()) {
498
- throw ApiError.EISDIR(p);
498
+ throw ApiError.With('EISDIR', p, 'removeEntry');
499
499
  }
500
500
  if (isDir && !fileNode.toStats().isDirectory()) {
501
- throw ApiError.ENOTDIR(p);
501
+ throw ApiError.With('ENOTDIR', p, 'removeEntry');
502
502
  }
503
503
  try {
504
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);
@@ -134,10 +134,10 @@ export class SyncStoreFS extends Sync(FileSystem) {
134
134
  // Remove oldPath from parent's directory listing.
135
135
  oldDirNode = this.findINode(tx, oldParent), oldDirList = this.getDirListing(tx, oldDirNode, oldParent);
136
136
  if (!oldDirNode.toStats().hasAccess(W_OK, cred)) {
137
- throw ApiError.EACCES(oldPath);
137
+ throw ApiError.With('EACCES', oldPath, 'renameSync');
138
138
  }
139
139
  if (!oldDirList[oldName]) {
140
- throw ApiError.ENOENT(oldPath);
140
+ throw ApiError.With('ENOENT', oldPath, 'renameSync');
141
141
  }
142
142
  const ino = oldDirList[oldName];
143
143
  delete oldDirList[oldName];
@@ -175,7 +175,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
175
175
  }
176
176
  else {
177
177
  // If it's a directory, throw a permissions error.
178
- throw ApiError.EPERM(newPath);
178
+ throw ApiError.With('EPERM', newPath, 'renameSync');
179
179
  }
180
180
  }
181
181
  newDirList[newName] = ino;
@@ -194,7 +194,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
194
194
  // Get the inode to the item, convert it into a Stats object.
195
195
  const stats = this.findINode(this.store.beginTransaction(), p).toStats();
196
196
  if (!stats.hasAccess(R_OK, cred)) {
197
- throw ApiError.EACCES(p);
197
+ throw ApiError.With('EACCES', p, 'statSync');
198
198
  }
199
199
  return stats;
200
200
  }
@@ -205,10 +205,10 @@ export class SyncStoreFS extends Sync(FileSystem) {
205
205
  openFileSync(p, flag, cred) {
206
206
  const tx = this.store.beginTransaction(), node = this.findINode(tx, p), data = tx.get(node.ino);
207
207
  if (!node.toStats().hasAccess(flagToMode(flag), cred)) {
208
- throw ApiError.EACCES(p);
208
+ throw ApiError.With('EACCES', p, 'openFileSync');
209
209
  }
210
210
  if (data === null) {
211
- throw ApiError.ENOENT(p);
211
+ throw ApiError.With('ENOENT', p, 'openFileSync');
212
212
  }
213
213
  return new SyncStoreFile(this, p, flag, node.toStats(), data);
214
214
  }
@@ -218,7 +218,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
218
218
  rmdirSync(p, cred) {
219
219
  // Check first if directory is empty.
220
220
  if (this.readdirSync(p, cred).length > 0) {
221
- throw ApiError.ENOTEMPTY(p);
221
+ throw ApiError.With('ENOTEMPTY', p, 'rmdirSync');
222
222
  }
223
223
  else {
224
224
  this.removeEntry(p, true, cred);
@@ -231,7 +231,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
231
231
  const tx = this.store.beginTransaction();
232
232
  const node = this.findINode(tx, p);
233
233
  if (!node.toStats().hasAccess(R_OK, cred)) {
234
- throw ApiError.EACCES(p);
234
+ throw ApiError.With('EACCES', p, 'readdirSync');
235
235
  }
236
236
  return Object.keys(this.getDirListing(tx, node, p));
237
237
  }
@@ -258,16 +258,16 @@ export class SyncStoreFS extends Sync(FileSystem) {
258
258
  linkSync(existing, newpath, cred) {
259
259
  const tx = this.store.beginTransaction(), existingDir = dirname(existing), existingDirNode = this.findINode(tx, existingDir);
260
260
  if (!existingDirNode.toStats().hasAccess(R_OK, cred)) {
261
- throw ApiError.EACCES(existingDir);
261
+ throw ApiError.With('EACCES', existingDir, 'linkSync');
262
262
  }
263
263
  const newDir = dirname(newpath), newDirNode = this.findINode(tx, newDir), newListing = this.getDirListing(tx, newDirNode, newDir);
264
264
  if (!newDirNode.toStats().hasAccess(W_OK, cred)) {
265
- throw ApiError.EACCES(newDir);
265
+ throw ApiError.With('EACCES', newDir, 'linkSync');
266
266
  }
267
267
  const ino = this._findINode(tx, existingDir, basename(existing));
268
268
  const node = this.getINode(tx, ino, existing);
269
269
  if (!node.toStats().hasAccess(W_OK, cred)) {
270
- throw ApiError.EACCES(newpath);
270
+ throw ApiError.With('EACCES', newpath, 'linkSync');
271
271
  }
272
272
  node.nlink++;
273
273
  newListing[basename(newpath)] = ino;
@@ -314,7 +314,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
314
314
  const ino = this._findINode(tx, dirname(parent), basename(parent), visited);
315
315
  const dir = this.getDirListing(tx, this.getINode(tx, ino, parent + sep + filename), parent);
316
316
  if (!(filename in dir)) {
317
- throw ApiError.ENOENT(resolve(parent, filename));
317
+ throw ApiError.With('ENOENT', resolve(parent, filename), '_findINode');
318
318
  }
319
319
  return dir[filename];
320
320
  }
@@ -322,7 +322,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
322
322
  // Find the item in the root node.
323
323
  const dir = this.getDirListing(tx, this.getINode(tx, rootIno, parent), parent);
324
324
  if (!(filename in dir)) {
325
- throw ApiError.ENOENT(resolve(parent, filename));
325
+ throw ApiError.With('ENOENT', resolve(parent, filename), '_findINode');
326
326
  }
327
327
  return dir[filename];
328
328
  }
@@ -348,7 +348,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
348
348
  getINode(tx, id, p) {
349
349
  const data = tx.get(id);
350
350
  if (!data) {
351
- throw ApiError.ENOENT(p);
351
+ throw ApiError.With('ENOENT', p, 'getINode');
352
352
  }
353
353
  const inode = new Inode(data.buffer);
354
354
  return inode;
@@ -358,11 +358,11 @@ export class SyncStoreFS extends Sync(FileSystem) {
358
358
  */
359
359
  getDirListing(tx, inode, p) {
360
360
  if (!inode.toStats().isDirectory()) {
361
- throw ApiError.ENOTDIR(p);
361
+ throw ApiError.With('ENOTDIR', p, 'getDirListing');
362
362
  }
363
363
  const data = tx.get(inode.ino);
364
364
  if (!data) {
365
- throw ApiError.ENOENT(p);
365
+ throw ApiError.With('ENOENT', p, 'getDirListing');
366
366
  }
367
367
  return decodeDirListing(data);
368
368
  }
@@ -394,18 +394,18 @@ export class SyncStoreFS extends Sync(FileSystem) {
394
394
  const tx = this.store.beginTransaction(), parentDir = dirname(p), fname = basename(p), parentNode = this.findINode(tx, parentDir), dirListing = this.getDirListing(tx, parentNode, parentDir);
395
395
  //Check that the creater has correct access
396
396
  if (!parentNode.toStats().hasAccess(W_OK, cred)) {
397
- throw ApiError.EACCES(p);
397
+ throw ApiError.With('EACCES', p, 'commitNewFile');
398
398
  }
399
399
  /* Invariant: The root always exists.
400
400
  If we don't check this prior to taking steps below,
401
401
  we will create a file with name '' in root should p == '/'.
402
402
  */
403
403
  if (p === '/') {
404
- throw ApiError.EEXIST(p);
404
+ throw ApiError.With('EEXIST', p, 'commitNewFile');
405
405
  }
406
406
  // Check if file already exists.
407
407
  if (dirListing[fname]) {
408
- throw ApiError.EEXIST(p);
408
+ throw ApiError.With('EEXIST', p, 'commitNewFile');
409
409
  }
410
410
  const fileNode = new Inode();
411
411
  try {
@@ -435,20 +435,20 @@ export class SyncStoreFS extends Sync(FileSystem) {
435
435
  removeEntry(p, isDir, cred) {
436
436
  const tx = this.store.beginTransaction(), parent = dirname(p), parentNode = this.findINode(tx, parent), parentListing = this.getDirListing(tx, parentNode, parent), fileName = basename(p), fileIno = parentListing[fileName];
437
437
  if (!fileIno) {
438
- throw ApiError.ENOENT(p);
438
+ throw ApiError.With('ENOENT', p, 'removeEntry');
439
439
  }
440
440
  // Get file inode.
441
441
  const fileNode = this.getINode(tx, fileIno, p);
442
442
  if (!fileNode.toStats().hasAccess(W_OK, cred)) {
443
- throw ApiError.EACCES(p);
443
+ throw ApiError.With('EACCES', p, 'removeEntry');
444
444
  }
445
445
  // Remove from directory listing of parent.
446
446
  delete parentListing[fileName];
447
447
  if (!isDir && fileNode.toStats().isDirectory()) {
448
- throw ApiError.EISDIR(p);
448
+ throw ApiError.With('EISDIR', p, 'removeEntry');
449
449
  }
450
450
  if (isDir && !fileNode.toStats().isDirectory()) {
451
- throw ApiError.ENOTDIR(p);
451
+ throw ApiError.With('ENOTDIR', p, 'removeEntry');
452
452
  }
453
453
  try {
454
454
  // Update directory listing.