UNPKG

5.39 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.CachedFileSystem = exports.FileKind = void 0;
4const tslib_1 = require("tslib");
5const inversify_1 = require("inversify");
6const ymir_1 = require("@fimbul/ymir");
7const bind_decorator_1 = require("bind-decorator");
8const utils_1 = require("../utils");
9const path = require("path");
10var FileKind;
11(function (FileKind) {
12 FileKind[FileKind["NonExistent"] = 0] = "NonExistent";
13 FileKind[FileKind["File"] = 1] = "File";
14 FileKind[FileKind["Directory"] = 2] = "Directory";
15 FileKind[FileKind["Other"] = 3] = "Other";
16})(FileKind = exports.FileKind || (exports.FileKind = {}));
17let CachedFileSystem = class CachedFileSystem {
18 constructor(fs, cache) {
19 this.fs = fs;
20 this.realpath = this.fs.realpath === undefined ? undefined : (file) => {
21 return utils_1.resolveCachedResult(this.realpathCache, this.fs.normalizePath(file), () => this.fs.realpath(file));
22 };
23 this.fileKindCache = cache.create();
24 this.realpathCache = cache.create();
25 this.direntCache = cache.create();
26 }
27 isFile(file) {
28 return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(file), this.doGetKind) === 1 /* File */;
29 }
30 isDirectory(dir) {
31 return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(dir), this.doGetKind) === 2 /* Directory */;
32 }
33 getKind(file) {
34 return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(file), this.doGetKind);
35 }
36 doGetKind(file) {
37 try {
38 return statsToKind(this.fs.stat(file));
39 }
40 catch {
41 return 0 /* NonExistent */;
42 }
43 }
44 readDirectory(dir) {
45 dir = this.fs.normalizePath(dir);
46 let cachedResult = this.direntCache.get(dir);
47 if (cachedResult !== undefined)
48 return cachedResult.map((entry) => ({ kind: this.fileKindCache.get(this.fs.normalizePath(path.join(dir, entry))), name: entry }));
49 cachedResult = [];
50 const result = [];
51 for (const entry of this.fs.readDirectory(dir)) {
52 if (typeof entry === 'string') {
53 cachedResult.push(entry);
54 result.push({ kind: this.getKind(path.join(dir, entry)), name: entry });
55 }
56 else {
57 cachedResult.push(entry.name);
58 const filePath = path.join(dir, entry.name);
59 let kind;
60 if (entry.isSymbolicLink()) {
61 kind = this.getKind(filePath);
62 }
63 else {
64 kind = statsToKind(entry);
65 this.fileKindCache.set(this.fs.normalizePath(filePath), kind);
66 }
67 result.push({ kind, name: entry.name });
68 }
69 }
70 this.direntCache.set(dir, cachedResult);
71 return result;
72 }
73 readFile(file) {
74 return this.fs.readFile(this.fs.normalizePath(file));
75 }
76 writeFile(file, content) {
77 file = this.fs.normalizePath(file);
78 this.fs.writeFile(file, content);
79 this.updateCache(file, 1 /* File */);
80 }
81 remove(file) {
82 file = this.fs.normalizePath(file);
83 this.fs.deleteFile(file);
84 this.updateCache(file, 0 /* NonExistent */);
85 }
86 createDirectory(dir) {
87 dir = this.fs.normalizePath(dir);
88 if (this.fileKindCache.get(dir) === 2 /* Directory */)
89 return;
90 return this.doCreateDirectory(dir);
91 }
92 doCreateDirectory(dir) {
93 try {
94 this.fs.createDirectory(dir);
95 }
96 catch (e) {
97 try {
98 const stat = this.fs.stat(dir);
99 if (!stat.isDirectory())
100 throw e;
101 }
102 catch {
103 const parent = this.fs.normalizePath(path.dirname(dir));
104 if (parent === dir)
105 throw e;
106 this.doCreateDirectory(parent);
107 this.fs.createDirectory(dir);
108 }
109 }
110 this.updateCache(dir, 2 /* Directory */);
111 }
112 updateCache(file, kind) {
113 // this currently doesn't handle directory removal as there is no API for that
114 if (this.fileKindCache.get(file) === kind)
115 return;
116 this.fileKindCache.set(file, kind);
117 if (kind === 0 /* NonExistent */)
118 this.realpathCache.delete(file); // only invalidate realpath cache on file removal
119 // invalidate direntCache unconditionally as the new file's name might differ in case from the one we have here
120 this.direntCache.delete(this.fs.normalizePath(path.dirname(file)));
121 }
122};
123tslib_1.__decorate([
124 bind_decorator_1.default,
125 tslib_1.__metadata("design:type", Function),
126 tslib_1.__metadata("design:paramtypes", [String]),
127 tslib_1.__metadata("design:returntype", Number)
128], CachedFileSystem.prototype, "doGetKind", null);
129CachedFileSystem = tslib_1.__decorate([
130 inversify_1.injectable(),
131 tslib_1.__metadata("design:paramtypes", [ymir_1.FileSystem, ymir_1.CacheFactory])
132], CachedFileSystem);
133exports.CachedFileSystem = CachedFileSystem;
134function statsToKind(stats) {
135 return stats.isFile() ? 1 /* File */ : stats.isDirectory() ? 2 /* Directory */ : 3 /* Other */;
136}
137//# sourceMappingURL=cached-file-system.js.map
\No newline at end of file