instrumentality 0.0.13 → 0.0.15
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.
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +2 -2
- package/dist/road.d.ts +66 -47
- package/dist/road.d.ts.map +1 -1
- package/dist/road.js +169 -91
- package/package.json +1 -1
- package/src/dom.ts +2 -2
- package/src/road.ts +132 -89
package/dist/road.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import * as cr from "node:crypto";
|
|
2
3
|
import * as fs from "node:fs";
|
|
3
4
|
import { constants as fsc } from "node:fs";
|
|
@@ -57,22 +58,6 @@ export function resolveDirent(dirent) {
|
|
|
57
58
|
throw new Err(`Unknown dirent type for ${dirent.name}`);
|
|
58
59
|
}
|
|
59
60
|
export { resolveDirent as resDirent };
|
|
60
|
-
/**
|
|
61
|
-
* Creates the appropriate subclass of {@link Road} based on the file mode of the specified path.
|
|
62
|
-
*
|
|
63
|
-
* @param path_ The path to follow.
|
|
64
|
-
* @returns A new instance of {@link Road}.
|
|
65
|
-
* @throws If {@link fp.lstat}/{@link fs.lstatSync} fails to retrieved the status of {@link path_}.
|
|
66
|
-
*/
|
|
67
|
-
export async function factory(path_) {
|
|
68
|
-
return new (resolveStat((await fp.lstat(path_)).mode))(path_, false);
|
|
69
|
-
}
|
|
70
|
-
export { factory as fac, factory as mk };
|
|
71
|
-
/** Sync version of {@link factory}. */
|
|
72
|
-
export function factorySync(path_) {
|
|
73
|
-
return new (resolveStat(fs.lstatSync(path_).mode))(path_, false);
|
|
74
|
-
}
|
|
75
|
-
export { factorySync as facSync, factorySync as mkSync };
|
|
76
61
|
/**
|
|
77
62
|
* A map that keeps track of locked roads to prevent concurrent modifications.
|
|
78
63
|
*
|
|
@@ -91,18 +76,32 @@ export let lockedRoads = null;
|
|
|
91
76
|
* It is more like a memory representation, similar to a pointer in low-level programming languages; other processes might mess with the underlying entry. There are methods to check for consistency, but they are not guaranteed to be foolproof.
|
|
92
77
|
*/
|
|
93
78
|
export class Road {
|
|
94
|
-
/** The absolute path to the
|
|
79
|
+
/** The absolute path to the entry that this Road instance represents.
|
|
95
80
|
* @remarks Intentionally made protected to prevent external modification, as changing this value could lead to inconsistencies and unexpected behavior. */
|
|
96
81
|
pointsTo;
|
|
97
|
-
/** Indicates
|
|
82
|
+
/** Indicates which operations are allowed on the entry represented by this Road instance.
|
|
98
83
|
* Changing this value does not affect the actual file system permissions, but rather serves as a safeguard within the application to prevent accidental modifications. */
|
|
99
|
-
|
|
84
|
+
writable = true;
|
|
85
|
+
moveable = true;
|
|
86
|
+
deletable = true;
|
|
87
|
+
copyable = true;
|
|
88
|
+
renameable = true;
|
|
89
|
+
assertWrite() { if (!this.writable)
|
|
90
|
+
throw new Err(`Road to '${this.isAt}' isn't writable.`); }
|
|
91
|
+
assertMove() { if (!this.moveable)
|
|
92
|
+
throw new Err(`Road to '${this.isAt}' isn't moveable.`); }
|
|
93
|
+
assertDelete() { if (!this.deletable)
|
|
94
|
+
throw new Err(`Road to '${this.isAt}' isn't deletable.`); }
|
|
95
|
+
assertCopy() { if (!this.copyable)
|
|
96
|
+
throw new Err(`Road to '${this.isAt}' isn't copyable.`); }
|
|
97
|
+
assertRename() { if (!this.renameable)
|
|
98
|
+
throw new Err(`Road to '${this.isAt}' isn't renameable.`); }
|
|
100
99
|
// Quick accessors
|
|
101
100
|
/** Copy of the absolute path. */
|
|
102
101
|
get isAt() { return this.pointsTo; }
|
|
103
102
|
/** Name of the road without the path (including extensions). */
|
|
104
103
|
get name() { return this.isAt.slice(this.isAt.lastIndexOf(ph.sep) + 1); }
|
|
105
|
-
/** The amount of path segments in the absolute path to the
|
|
104
|
+
/** The amount of path segments in the absolute path to the entry represented by this Road instance, minus one (i.e., the depth of the path in the file system hierarchy). */
|
|
106
105
|
get depth() { return this.isAt.split(ph.sep).length - 1; }
|
|
107
106
|
/** Same as {@link isAt} but for compatibility with external APIs. */
|
|
108
107
|
toString() { return this.isAt; }
|
|
@@ -116,7 +115,7 @@ export class Road {
|
|
|
116
115
|
*/
|
|
117
116
|
constructor(path_, typeCheck_) {
|
|
118
117
|
this.pointsTo = ph.resolve(path_);
|
|
119
|
-
if (typeCheck_ && !this.checkSync())
|
|
118
|
+
if (typeCheck_ && !this.checkSync(true))
|
|
120
119
|
throw new Err(`Type mismatch: '${this.isAt}'`);
|
|
121
120
|
}
|
|
122
121
|
/** @returns An instance of {@link Folder} representing the parent directory of the current road. */
|
|
@@ -138,8 +137,6 @@ export class Road {
|
|
|
138
137
|
/** @returns An array of {@link Folder} instances representing the ancestors of the current road. */
|
|
139
138
|
ancestors() { return [...this.ancestorsIt()]; }
|
|
140
139
|
reserveLock(allowConcurrent) {
|
|
141
|
-
if (!this.mutable)
|
|
142
|
-
throw new Err(`Road to '${this.isAt}' is immutable.`);
|
|
143
140
|
lockedRoads ??= new Map();
|
|
144
141
|
const { promise, resolve } = Promise.withResolvers();
|
|
145
142
|
const isAt = this.isAt;
|
|
@@ -161,7 +158,9 @@ export class Road {
|
|
|
161
158
|
try {
|
|
162
159
|
await l.previous;
|
|
163
160
|
}
|
|
164
|
-
catch {
|
|
161
|
+
catch {
|
|
162
|
+
null;
|
|
163
|
+
}
|
|
165
164
|
return l;
|
|
166
165
|
}
|
|
167
166
|
lockSync() {
|
|
@@ -180,7 +179,7 @@ export class Road {
|
|
|
180
179
|
async untilAccessible(abs, expectMode = fsc.F_OK, cb_) {
|
|
181
180
|
const watcher = fs.watch(this.isAt);
|
|
182
181
|
try {
|
|
183
|
-
for await (
|
|
182
|
+
for await (const _ of on(watcher, 'change', { signal: abs })) {
|
|
184
183
|
try {
|
|
185
184
|
await fp.access(this.isAt, expectMode);
|
|
186
185
|
return;
|
|
@@ -207,7 +206,7 @@ export class Road {
|
|
|
207
206
|
async onChange(abs_, cb_) {
|
|
208
207
|
const watcher = fs.watch(this.isAt);
|
|
209
208
|
try {
|
|
210
|
-
for await (
|
|
209
|
+
for await (const _ of on(watcher, 'change', { signal: abs_ }))
|
|
211
210
|
return await cb_?.() ?? null;
|
|
212
211
|
return null;
|
|
213
212
|
}
|
|
@@ -224,43 +223,51 @@ export class Road {
|
|
|
224
223
|
lstatSync() { return fs.lstatSync(this.isAt); }
|
|
225
224
|
/** Wrapper around {@link fp.rm} with locking. */
|
|
226
225
|
async delete() {
|
|
226
|
+
this.assertDelete();
|
|
227
227
|
using _ = await this.lock();
|
|
228
228
|
await fp.rm(this.isAt, { recursive: true, force: true });
|
|
229
229
|
}
|
|
230
230
|
/** Wrapper around {@link fs.rmSync} with locking. */
|
|
231
231
|
deleteSync() {
|
|
232
|
+
this.assertDelete();
|
|
232
233
|
using _ = this.lockSync();
|
|
233
234
|
fs.rmSync(this.isAt, { recursive: true, force: true });
|
|
234
235
|
}
|
|
235
236
|
async copy(into_) {
|
|
237
|
+
this.assertCopy();
|
|
236
238
|
const newPath = into_.join(this.name);
|
|
237
239
|
await fp.cp(this.isAt, newPath, { recursive: true, force: true });
|
|
238
240
|
return new this.constructor(newPath, false);
|
|
239
241
|
}
|
|
240
242
|
copySync(into_) {
|
|
243
|
+
this.assertCopy();
|
|
241
244
|
const newPath = into_.join(this.name);
|
|
242
245
|
fs.cpSync(this.isAt, newPath, { recursive: true, force: true });
|
|
243
246
|
return new this.constructor(newPath, false);
|
|
244
247
|
}
|
|
245
248
|
async move(into_) {
|
|
249
|
+
this.assertMove();
|
|
246
250
|
using _ = await this.lock();
|
|
247
251
|
const newPath = into_.join(this.name);
|
|
248
252
|
await fp.rename(this.isAt, newPath);
|
|
249
253
|
this.pointsTo = newPath;
|
|
250
254
|
}
|
|
251
255
|
moveSync(into_) {
|
|
256
|
+
this.assertMove();
|
|
252
257
|
using _ = this.lockSync();
|
|
253
258
|
const newPath = into_.join(this.name);
|
|
254
259
|
fs.renameSync(this.isAt, newPath);
|
|
255
260
|
this.pointsTo = newPath;
|
|
256
261
|
}
|
|
257
262
|
async rename(newName_) {
|
|
263
|
+
this.assertRename();
|
|
258
264
|
using _ = await this.lock();
|
|
259
265
|
const newPath = this.parent().join(newName_);
|
|
260
266
|
await fp.rename(this.isAt, newPath);
|
|
261
267
|
this.pointsTo = newPath;
|
|
262
268
|
}
|
|
263
269
|
renameSync(newName_) {
|
|
270
|
+
this.assertRename();
|
|
264
271
|
using _ = this.lockSync();
|
|
265
272
|
const newPath = this.parent().join(newName_);
|
|
266
273
|
fs.renameSync(this.isAt, newPath);
|
|
@@ -289,6 +296,18 @@ export class Road {
|
|
|
289
296
|
/** Type narrowing for {@link Socket} (similar to `instanceof` without unnecessary runtime checks). */
|
|
290
297
|
isSocket() { return false; }
|
|
291
298
|
}
|
|
299
|
+
/**
|
|
300
|
+
* Creates the appropriate subclass of {@link Road} based on the file mode of the specified path.
|
|
301
|
+
*
|
|
302
|
+
* @param path_ The path to follow.
|
|
303
|
+
* @returns A new instance of {@link Road}.
|
|
304
|
+
* @throws If {@link fp.lstat}/{@link fs.lstatSync} fails to retrieved the status of {@link path_}.
|
|
305
|
+
*/
|
|
306
|
+
export async function road(path_) { return new (resolveStat((await fp.lstat(path_)).mode))(path_, false); }
|
|
307
|
+
export { road as fac, road as mk, road as factory };
|
|
308
|
+
/** Sync version of {@link road}. */
|
|
309
|
+
export function roadSync(path_) { return new (resolveStat((fs.lstatSync(path_).mode)))(path_, false); }
|
|
310
|
+
export { roadSync as facSync, roadSync as mkSync, roadSync as factorySync };
|
|
292
311
|
/** Subclass of {@link Road} that represents a file. */
|
|
293
312
|
export class File extends Road {
|
|
294
313
|
/**
|
|
@@ -326,7 +345,7 @@ export class File extends Road {
|
|
|
326
345
|
/** The file name without its extension. */
|
|
327
346
|
get noExt() { return ph.basename(this.isAt, this.ext); }
|
|
328
347
|
async read(options_) {
|
|
329
|
-
return fp.readFile(this.isAt, options_);
|
|
348
|
+
return await fp.readFile(this.isAt, options_);
|
|
330
349
|
}
|
|
331
350
|
readSync(options_) {
|
|
332
351
|
return fs.readFileSync(this.isAt, options_);
|
|
@@ -408,11 +427,15 @@ export class File extends Road {
|
|
|
408
427
|
try {
|
|
409
428
|
iter1.return?.(undefined);
|
|
410
429
|
}
|
|
411
|
-
catch {
|
|
430
|
+
catch {
|
|
431
|
+
null;
|
|
432
|
+
}
|
|
412
433
|
try {
|
|
413
434
|
iter2.return?.(undefined);
|
|
414
435
|
}
|
|
415
|
-
catch {
|
|
436
|
+
catch {
|
|
437
|
+
null;
|
|
438
|
+
}
|
|
416
439
|
}
|
|
417
440
|
}
|
|
418
441
|
async hash(algorithm_ = "sha256", options_, encoding_) {
|
|
@@ -430,30 +453,37 @@ export class File extends Road {
|
|
|
430
453
|
async size() { return (await this.lstat()).size; }
|
|
431
454
|
sizeSync() { return this.lstatSync().size; }
|
|
432
455
|
async writeAtomic(data_, options_) {
|
|
456
|
+
this.assertWrite();
|
|
433
457
|
using _ = await this.lock();
|
|
434
458
|
await this.parent().borrow(File, async (tmp) => {
|
|
459
|
+
tmp.assertWrite();
|
|
435
460
|
using _ = await tmp.lock();
|
|
436
461
|
await fp.writeFile(tmp.isAt, data_, options_);
|
|
437
462
|
await fp.rename(tmp.isAt, this.isAt);
|
|
438
463
|
});
|
|
439
464
|
}
|
|
440
465
|
writeAtomicSync(data_, options_) {
|
|
466
|
+
this.assertWrite();
|
|
441
467
|
using _ = this.lockSync();
|
|
442
468
|
this.parent().borrowSync(File, tmp => {
|
|
469
|
+
tmp.assertWrite();
|
|
443
470
|
using _ = tmp.lockSync();
|
|
444
471
|
fs.writeFileSync(tmp.isAt, data_, options_);
|
|
445
472
|
fs.renameSync(tmp.isAt, this.isAt);
|
|
446
473
|
});
|
|
447
474
|
}
|
|
448
475
|
async write(data_, options_) {
|
|
476
|
+
this.assertWrite();
|
|
449
477
|
using _ = await this.lock();
|
|
450
478
|
await fp.writeFile(this.isAt, data_, options_);
|
|
451
479
|
}
|
|
452
480
|
writeSync(data_, options_) {
|
|
481
|
+
this.assertWrite();
|
|
453
482
|
using _ = this.lockSync();
|
|
454
483
|
fs.writeFileSync(this.isAt, data_, options_);
|
|
455
484
|
}
|
|
456
485
|
async writePast(offset_, data_) {
|
|
486
|
+
this.assertWrite();
|
|
457
487
|
using _ = await this.lock();
|
|
458
488
|
const fd = await fp.open(this.isAt, 'r+');
|
|
459
489
|
try {
|
|
@@ -465,6 +495,7 @@ export class File extends Road {
|
|
|
465
495
|
}
|
|
466
496
|
}
|
|
467
497
|
writePastSync(offset_, data_) {
|
|
498
|
+
this.assertWrite();
|
|
468
499
|
using _ = this.lockSync();
|
|
469
500
|
const fd = fs.openSync(this.isAt, 'r+');
|
|
470
501
|
try {
|
|
@@ -476,6 +507,7 @@ export class File extends Road {
|
|
|
476
507
|
}
|
|
477
508
|
}
|
|
478
509
|
async truncWritePast(offset_, data_) {
|
|
510
|
+
this.assertWrite();
|
|
479
511
|
using _ = await this.lock();
|
|
480
512
|
const fd = await fp.open(this.isAt, 'r+');
|
|
481
513
|
try {
|
|
@@ -488,6 +520,7 @@ export class File extends Road {
|
|
|
488
520
|
}
|
|
489
521
|
}
|
|
490
522
|
truncWritePastSync(offset_, data_) {
|
|
523
|
+
this.assertWrite();
|
|
491
524
|
using _ = this.lockSync();
|
|
492
525
|
const fd = fs.openSync(this.isAt, 'r+');
|
|
493
526
|
try {
|
|
@@ -500,23 +533,29 @@ export class File extends Road {
|
|
|
500
533
|
}
|
|
501
534
|
}
|
|
502
535
|
async append(data_, options_) {
|
|
536
|
+
this.assertWrite();
|
|
503
537
|
using _ = await this.lock();
|
|
504
538
|
await fp.appendFile(this.isAt, data_, options_);
|
|
505
539
|
}
|
|
506
540
|
appendSync(data_, options_) {
|
|
541
|
+
this.assertWrite();
|
|
507
542
|
using _ = this.lockSync();
|
|
508
543
|
fs.appendFileSync(this.isAt, data_, options_);
|
|
509
544
|
}
|
|
510
|
-
async check() { try {
|
|
545
|
+
async check(throwOnError_) { try {
|
|
511
546
|
return (await fp.lstat(this.isAt)).isFile();
|
|
512
547
|
}
|
|
513
|
-
catch {
|
|
548
|
+
catch (e) {
|
|
549
|
+
if (throwOnError_)
|
|
550
|
+
throw e;
|
|
514
551
|
return false;
|
|
515
552
|
} }
|
|
516
|
-
checkSync() { try {
|
|
553
|
+
checkSync(throwOnError_) { try {
|
|
517
554
|
return fs.lstatSync(this.isAt).isFile();
|
|
518
555
|
}
|
|
519
|
-
catch {
|
|
556
|
+
catch (e) {
|
|
557
|
+
if (throwOnError_)
|
|
558
|
+
throw e;
|
|
520
559
|
return false;
|
|
521
560
|
} }
|
|
522
561
|
isFile() { return true; }
|
|
@@ -584,12 +623,10 @@ export class Folder extends Road {
|
|
|
584
623
|
yield* entry.walkSync(filter_);
|
|
585
624
|
}
|
|
586
625
|
}
|
|
587
|
-
async find(name_,
|
|
626
|
+
async find(name_, filter_) {
|
|
588
627
|
try {
|
|
589
|
-
const found = await
|
|
590
|
-
if (!
|
|
591
|
-
return found;
|
|
592
|
-
if (found instanceof expect_)
|
|
628
|
+
const found = await road(this.join(name_));
|
|
629
|
+
if (!filter_ || filter_(found))
|
|
593
630
|
return found;
|
|
594
631
|
return null;
|
|
595
632
|
}
|
|
@@ -597,45 +634,45 @@ export class Folder extends Road {
|
|
|
597
634
|
return null;
|
|
598
635
|
}
|
|
599
636
|
}
|
|
600
|
-
findSync(name_,
|
|
637
|
+
findSync(name_, filter_) {
|
|
601
638
|
try {
|
|
602
|
-
const found =
|
|
603
|
-
if (!
|
|
604
|
-
return found;
|
|
605
|
-
if (found instanceof expect_)
|
|
639
|
+
const found = roadSync(this.join(name_));
|
|
640
|
+
if (!filter_ || filter_(found))
|
|
606
641
|
return found;
|
|
607
642
|
return null;
|
|
608
643
|
}
|
|
609
|
-
catch
|
|
644
|
+
catch {
|
|
610
645
|
return null;
|
|
611
646
|
}
|
|
612
647
|
}
|
|
613
648
|
async add(name_, createable_) {
|
|
649
|
+
this.assertWrite();
|
|
614
650
|
const newPath = this.join(name_);
|
|
615
651
|
await createable_.mk(newPath);
|
|
616
|
-
return (await
|
|
652
|
+
return (await road(newPath));
|
|
617
653
|
}
|
|
618
654
|
addSync(name_, createable_) {
|
|
655
|
+
this.assertWrite();
|
|
619
656
|
const newPath = this.join(name_);
|
|
620
657
|
createable_.mkSync(newPath);
|
|
621
|
-
return
|
|
658
|
+
return roadSync(newPath);
|
|
622
659
|
}
|
|
623
660
|
async borrow(createable_, cb_) {
|
|
624
|
-
const
|
|
661
|
+
const created = await createable_.mk(this.join(`instrumentality@${crypto.randomUUID()}`));
|
|
625
662
|
try {
|
|
626
|
-
await cb_(
|
|
663
|
+
await cb_(created);
|
|
627
664
|
}
|
|
628
665
|
finally {
|
|
629
|
-
await fp.rm(
|
|
666
|
+
await fp.rm(created.isAt, { recursive: true, force: true });
|
|
630
667
|
}
|
|
631
668
|
}
|
|
632
669
|
borrowSync(createable_, cb_) {
|
|
633
|
-
const
|
|
670
|
+
const created = createable_.mkSync(this.join(`instrumentality@${crypto.randomUUID()}`));
|
|
634
671
|
try {
|
|
635
|
-
cb_(
|
|
672
|
+
cb_(created);
|
|
636
673
|
}
|
|
637
674
|
finally {
|
|
638
|
-
fs.rmSync(
|
|
675
|
+
fs.rmSync(created.isAt, { recursive: true, force: true });
|
|
639
676
|
}
|
|
640
677
|
}
|
|
641
678
|
async size() {
|
|
@@ -650,16 +687,20 @@ export class Folder extends Road {
|
|
|
650
687
|
size += entry.sizeSync();
|
|
651
688
|
return size;
|
|
652
689
|
}
|
|
653
|
-
async check() { try {
|
|
690
|
+
async check(throwOnError_) { try {
|
|
654
691
|
return (await fp.lstat(this.isAt)).isDirectory();
|
|
655
692
|
}
|
|
656
|
-
catch {
|
|
693
|
+
catch (e) {
|
|
694
|
+
if (throwOnError_)
|
|
695
|
+
throw e;
|
|
657
696
|
return false;
|
|
658
697
|
} }
|
|
659
|
-
checkSync() { try {
|
|
698
|
+
checkSync(throwOnError_) { try {
|
|
660
699
|
return fs.lstatSync(this.isAt).isDirectory();
|
|
661
700
|
}
|
|
662
|
-
catch {
|
|
701
|
+
catch (e) {
|
|
702
|
+
if (throwOnError_)
|
|
703
|
+
throw e;
|
|
663
704
|
return false;
|
|
664
705
|
} }
|
|
665
706
|
isFolder() { return true; }
|
|
@@ -668,11 +709,12 @@ export class Folder extends Road {
|
|
|
668
709
|
}
|
|
669
710
|
export function folder(...args) { return new Folder(...args); }
|
|
670
711
|
export function dir(...args) { return new Folder(...args); }
|
|
712
|
+
export function directory(...args) { return new Folder(...args); }
|
|
671
713
|
export function sysRoot() { return new Folder(ph.parse(process.cwd()).root, false); }
|
|
672
714
|
export function home() { return new Folder(os.homedir(), false); }
|
|
673
715
|
export function tmp() { return new Folder(os.tmpdir(), false); }
|
|
674
716
|
export function here() { return new Folder(process.cwd(), false); }
|
|
675
|
-
export { Folder as Dir, Folder as Directory
|
|
717
|
+
export { Folder as Dir, Folder as Directory };
|
|
676
718
|
export class SymbolicLink extends Road {
|
|
677
719
|
static async create(at_, target_) {
|
|
678
720
|
try {
|
|
@@ -695,17 +737,21 @@ export class SymbolicLink extends Road {
|
|
|
695
737
|
}
|
|
696
738
|
static mkSync = SymbolicLink.createSync;
|
|
697
739
|
async target() {
|
|
698
|
-
return
|
|
740
|
+
return await road(ph.resolve(ph.dirname(this.isAt), await fp.readlink(this.isAt)));
|
|
699
741
|
}
|
|
700
742
|
targetSync() {
|
|
701
|
-
return
|
|
743
|
+
return roadSync(ph.resolve(ph.dirname(this.isAt), fs.readlinkSync(this.isAt)));
|
|
702
744
|
}
|
|
703
745
|
async retarget(to_) {
|
|
746
|
+
this.assertDelete();
|
|
747
|
+
this.assertWrite();
|
|
704
748
|
using _ = await this.lock();
|
|
705
749
|
await fp.unlink(this.isAt);
|
|
706
750
|
await fp.symlink(to_.isAt, this.isAt);
|
|
707
751
|
}
|
|
708
752
|
retargetSync(to_) {
|
|
753
|
+
this.assertDelete();
|
|
754
|
+
this.assertWrite();
|
|
709
755
|
using _ = this.lockSync();
|
|
710
756
|
fs.unlinkSync(this.isAt);
|
|
711
757
|
fs.symlinkSync(to_.isAt, this.isAt);
|
|
@@ -713,23 +759,29 @@ export class SymbolicLink extends Road {
|
|
|
713
759
|
async size() { return (await this.lstat()).size; }
|
|
714
760
|
sizeSync() { return this.lstatSync().size; }
|
|
715
761
|
async delete() {
|
|
762
|
+
this.assertDelete();
|
|
716
763
|
using _ = await this.lock();
|
|
717
764
|
await fp.unlink(this.isAt);
|
|
718
765
|
}
|
|
719
766
|
deleteSync() {
|
|
767
|
+
this.assertDelete();
|
|
720
768
|
using _ = this.lockSync();
|
|
721
769
|
fs.unlinkSync(this.isAt);
|
|
722
770
|
}
|
|
723
|
-
async check() { try {
|
|
771
|
+
async check(throwOnError_) { try {
|
|
724
772
|
return (await fp.lstat(this.isAt)).isSymbolicLink();
|
|
725
773
|
}
|
|
726
|
-
catch {
|
|
774
|
+
catch (e) {
|
|
775
|
+
if (throwOnError_)
|
|
776
|
+
throw e;
|
|
727
777
|
return false;
|
|
728
778
|
} }
|
|
729
|
-
checkSync() { try {
|
|
779
|
+
checkSync(throwOnError_) { try {
|
|
730
780
|
return fs.lstatSync(this.isAt).isSymbolicLink();
|
|
731
781
|
}
|
|
732
|
-
catch {
|
|
782
|
+
catch (e) {
|
|
783
|
+
if (throwOnError_)
|
|
784
|
+
throw e;
|
|
733
785
|
return false;
|
|
734
786
|
} }
|
|
735
787
|
isSymlink() { return true; }
|
|
@@ -737,92 +789,118 @@ export class SymbolicLink extends Road {
|
|
|
737
789
|
}
|
|
738
790
|
export { SymbolicLink as Symlink };
|
|
739
791
|
export function symlink(...args) { return new SymbolicLink(...args); }
|
|
792
|
+
/**
|
|
793
|
+
* Represents a system-level resource that is not subject to modification.
|
|
794
|
+
* All modification operations will throw an error.
|
|
795
|
+
*
|
|
796
|
+
* One could say 'this road truly is *unusable*.' hehe
|
|
797
|
+
*/
|
|
740
798
|
export class UnusableRoad extends Road {
|
|
741
|
-
|
|
742
|
-
|
|
799
|
+
// Modification will cause system issues (e.g. deleting a device file)
|
|
800
|
+
writable = false;
|
|
801
|
+
moveable = false;
|
|
802
|
+
deletable = false;
|
|
803
|
+
copyable = false;
|
|
804
|
+
size() { return Promise.resolve(0); }
|
|
743
805
|
sizeSync() { return 0; }
|
|
744
806
|
error() { throw new Err(`${this.constructor.name} at '${this.isAt}' is a system-level resource thus not subject to modification.`); }
|
|
745
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be locked */
|
|
807
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be locked */
|
|
746
808
|
lock() { return this.error(); }
|
|
747
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be locked */
|
|
809
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be locked */
|
|
748
810
|
lockSync() { return this.error(); }
|
|
749
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be deleted */
|
|
811
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be deleted */
|
|
750
812
|
delete() { return this.error(); }
|
|
751
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be deleted */
|
|
813
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be deleted */
|
|
752
814
|
deleteSync() { return this.error(); }
|
|
753
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be moved */
|
|
815
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be moved */
|
|
754
816
|
move() { return this.error(); }
|
|
755
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be moved */
|
|
817
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be moved */
|
|
756
818
|
moveSync() { return this.error(); }
|
|
757
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be copied */
|
|
819
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be copied */
|
|
758
820
|
copy() { return this.error(); }
|
|
759
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be copied */
|
|
821
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be copied */
|
|
760
822
|
copySync() { return this.error(); }
|
|
761
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be renamed */
|
|
823
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be renamed */
|
|
762
824
|
rename() { return this.error(); }
|
|
763
|
-
/** @deprecated System-level resources (UnusableRoad) can't/shouldn't be renamed */
|
|
825
|
+
/** @deprecated System-level resources ({@link UnusableRoad}) can't/shouldn't be renamed */
|
|
764
826
|
renameSync() { return this.error(); }
|
|
765
827
|
isUnusable() { return true; }
|
|
766
828
|
}
|
|
767
829
|
export class BlockDevice extends UnusableRoad {
|
|
768
|
-
async check() { try {
|
|
830
|
+
async check(throwOnError_) { try {
|
|
769
831
|
return (await fp.lstat(this.isAt)).isBlockDevice();
|
|
770
832
|
}
|
|
771
|
-
catch {
|
|
833
|
+
catch (e) {
|
|
834
|
+
if (throwOnError_)
|
|
835
|
+
throw e;
|
|
772
836
|
return false;
|
|
773
837
|
} }
|
|
774
|
-
checkSync() { try {
|
|
838
|
+
checkSync(throwOnError_) { try {
|
|
775
839
|
return fs.lstatSync(this.isAt).isBlockDevice();
|
|
776
840
|
}
|
|
777
|
-
catch {
|
|
841
|
+
catch (e) {
|
|
842
|
+
if (throwOnError_)
|
|
843
|
+
throw e;
|
|
778
844
|
return false;
|
|
779
845
|
} }
|
|
780
846
|
isBlockDevice() { return true; }
|
|
781
847
|
}
|
|
782
848
|
export function blockDevice(...args) { return new BlockDevice(...args); }
|
|
783
849
|
export class CharacterDevice extends UnusableRoad {
|
|
784
|
-
async check() { try {
|
|
850
|
+
async check(throwOnError_) { try {
|
|
785
851
|
return (await fp.lstat(this.isAt)).isCharacterDevice();
|
|
786
852
|
}
|
|
787
|
-
catch {
|
|
853
|
+
catch (e) {
|
|
854
|
+
if (throwOnError_)
|
|
855
|
+
throw e;
|
|
788
856
|
return false;
|
|
789
857
|
} }
|
|
790
|
-
checkSync() { try {
|
|
858
|
+
checkSync(throwOnError_) { try {
|
|
791
859
|
return fs.lstatSync(this.isAt).isCharacterDevice();
|
|
792
860
|
}
|
|
793
|
-
catch {
|
|
861
|
+
catch (e) {
|
|
862
|
+
if (throwOnError_)
|
|
863
|
+
throw e;
|
|
794
864
|
return false;
|
|
795
865
|
} }
|
|
796
866
|
isCharacterDevice() { return true; }
|
|
797
867
|
}
|
|
798
868
|
export function characterDevice(...args) { return new CharacterDevice(...args); }
|
|
799
869
|
export class Fifo extends UnusableRoad {
|
|
800
|
-
async check() { try {
|
|
870
|
+
async check(throwOnError_) { try {
|
|
801
871
|
return (await fp.lstat(this.isAt)).isFIFO();
|
|
802
872
|
}
|
|
803
|
-
catch {
|
|
873
|
+
catch (e) {
|
|
874
|
+
if (throwOnError_)
|
|
875
|
+
throw e;
|
|
804
876
|
return false;
|
|
805
877
|
} }
|
|
806
|
-
checkSync() { try {
|
|
878
|
+
checkSync(throwOnError_) { try {
|
|
807
879
|
return fs.lstatSync(this.isAt).isFIFO();
|
|
808
880
|
}
|
|
809
|
-
catch {
|
|
881
|
+
catch (e) {
|
|
882
|
+
if (throwOnError_)
|
|
883
|
+
throw e;
|
|
810
884
|
return false;
|
|
811
885
|
} }
|
|
812
886
|
isFifo() { return true; }
|
|
813
887
|
}
|
|
814
888
|
export function fifo(...args) { return new Fifo(...args); }
|
|
815
889
|
export class Socket extends UnusableRoad {
|
|
816
|
-
async check() { try {
|
|
890
|
+
async check(throwOnError_) { try {
|
|
817
891
|
return (await fp.lstat(this.isAt)).isSocket();
|
|
818
892
|
}
|
|
819
|
-
catch {
|
|
893
|
+
catch (e) {
|
|
894
|
+
if (throwOnError_)
|
|
895
|
+
throw e;
|
|
820
896
|
return false;
|
|
821
897
|
} }
|
|
822
|
-
checkSync() { try {
|
|
898
|
+
checkSync(throwOnError_) { try {
|
|
823
899
|
return fs.lstatSync(this.isAt).isSocket();
|
|
824
900
|
}
|
|
825
|
-
catch {
|
|
901
|
+
catch (e) {
|
|
902
|
+
if (throwOnError_)
|
|
903
|
+
throw e;
|
|
826
904
|
return false;
|
|
827
905
|
} }
|
|
828
906
|
isSocket() { return true; }
|
package/package.json
CHANGED
package/src/dom.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolves on `DOMContentLoaded` or immediately if the document is already ready.
|
|
3
3
|
*/
|
|
4
|
-
export
|
|
4
|
+
export function onceReady(): Promise<void> {
|
|
5
5
|
if (document.readyState === "complete" || document.readyState === "interactive")
|
|
6
|
-
return
|
|
6
|
+
return Promise.resolve()
|
|
7
7
|
return new Promise(r => document.addEventListener("DOMContentLoaded", () => r(), { once: true }))
|
|
8
8
|
}
|
|
9
9
|
|