mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-05-30 23:40:40 +02:00
Fix:Include Watcher as lib with no dependencies and fix tiny-readdir bug #610
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
var signal_1 = require("./signal");
|
||||
/* ABORT CONTROLLER */
|
||||
var AbortController = /** @class */ (function () {
|
||||
function AbortController() {
|
||||
/* VARIABLES */
|
||||
this.signal = new signal_1.default();
|
||||
}
|
||||
/* API */
|
||||
AbortController.prototype.abort = function () {
|
||||
return this.signal.abort();
|
||||
};
|
||||
return AbortController;
|
||||
}());
|
||||
/* EXPORT */
|
||||
module.exports = AbortController;
|
||||
module.exports.default = AbortController;
|
||||
Object.defineProperty(module.exports, "__esModule", { value: true });
|
||||
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/* ABORT SIGNAL */
|
||||
var AbortSignal = /** @class */ (function () {
|
||||
function AbortSignal() {
|
||||
/* VARIABLES */
|
||||
this.aborted = false;
|
||||
this.listeners = {};
|
||||
}
|
||||
/* EVENTS API */
|
||||
AbortSignal.prototype.addEventListener = function (event, listener) {
|
||||
var listeners = this.listeners[event] || (this.listeners[event] = []);
|
||||
listeners.push(listener);
|
||||
};
|
||||
AbortSignal.prototype.removeEventListener = function (event, listener) {
|
||||
var listeners = this.listeners[event];
|
||||
if (!listeners)
|
||||
return;
|
||||
listeners.splice(listeners.indexOf(listener), 1);
|
||||
};
|
||||
AbortSignal.prototype.dispatchEvent = function (event) {
|
||||
var listeners = this.listeners[event];
|
||||
if (!listeners)
|
||||
return true;
|
||||
listeners.slice().forEach(function (listener) { return listener(); });
|
||||
return true;
|
||||
};
|
||||
/* API */
|
||||
AbortSignal.prototype.abort = function () {
|
||||
if (this.aborted)
|
||||
return;
|
||||
this.aborted = true;
|
||||
this.dispatchEvent('abort');
|
||||
};
|
||||
return AbortSignal;
|
||||
}());
|
||||
/* EXPORT */
|
||||
exports.default = AbortSignal;
|
||||
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
var isPrimitive = require("./is-primitive");
|
||||
/* ARE SHALLOW EQUAL */
|
||||
var isNaN = Number.isNaN;
|
||||
function areShallowEqual(x, y) {
|
||||
if (x === y)
|
||||
return true;
|
||||
if (isNaN(x))
|
||||
return isNaN(y);
|
||||
if (isPrimitive(x) || isPrimitive(y))
|
||||
return x === y;
|
||||
for (var i in x)
|
||||
if (!(i in y))
|
||||
return false;
|
||||
for (var i in y)
|
||||
if (x[i] !== y[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
/* EXPORT */
|
||||
module.exports = areShallowEqual;
|
||||
module.exports.default = areShallowEqual;
|
||||
Object.defineProperty(module.exports, "__esModule", { value: true });
|
||||
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
/* CONSTS */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NOOP = exports.LIMIT_FILES_DESCRIPTORS = exports.LIMIT_BASENAME_LENGTH = exports.IS_USER_ROOT = exports.IS_POSIX = exports.DEFAULT_TIMEOUT_SYNC = exports.DEFAULT_TIMEOUT_ASYNC = exports.DEFAULT_WRITE_OPTIONS = exports.DEFAULT_READ_OPTIONS = exports.DEFAULT_FOLDER_MODE = exports.DEFAULT_FILE_MODE = exports.DEFAULT_ENCODING = void 0;
|
||||
const DEFAULT_ENCODING = 'utf8';
|
||||
exports.DEFAULT_ENCODING = DEFAULT_ENCODING;
|
||||
const DEFAULT_FILE_MODE = 0o666;
|
||||
exports.DEFAULT_FILE_MODE = DEFAULT_FILE_MODE;
|
||||
const DEFAULT_FOLDER_MODE = 0o777;
|
||||
exports.DEFAULT_FOLDER_MODE = DEFAULT_FOLDER_MODE;
|
||||
const DEFAULT_READ_OPTIONS = {};
|
||||
exports.DEFAULT_READ_OPTIONS = DEFAULT_READ_OPTIONS;
|
||||
const DEFAULT_WRITE_OPTIONS = {};
|
||||
exports.DEFAULT_WRITE_OPTIONS = DEFAULT_WRITE_OPTIONS;
|
||||
const DEFAULT_TIMEOUT_ASYNC = 5000;
|
||||
exports.DEFAULT_TIMEOUT_ASYNC = DEFAULT_TIMEOUT_ASYNC;
|
||||
const DEFAULT_TIMEOUT_SYNC = 100;
|
||||
exports.DEFAULT_TIMEOUT_SYNC = DEFAULT_TIMEOUT_SYNC;
|
||||
const IS_POSIX = !!process.getuid;
|
||||
exports.IS_POSIX = IS_POSIX;
|
||||
const IS_USER_ROOT = process.getuid ? !process.getuid() : false;
|
||||
exports.IS_USER_ROOT = IS_USER_ROOT;
|
||||
const LIMIT_BASENAME_LENGTH = 128; //TODO: fetch the real limit from the filesystem //TODO: fetch the whole-path length limit too
|
||||
exports.LIMIT_BASENAME_LENGTH = LIMIT_BASENAME_LENGTH;
|
||||
const LIMIT_FILES_DESCRIPTORS = 10000; //TODO: fetch the real limit from the filesystem
|
||||
exports.LIMIT_FILES_DESCRIPTORS = LIMIT_FILES_DESCRIPTORS;
|
||||
const NOOP = () => { };
|
||||
exports.NOOP = NOOP;
|
||||
@@ -0,0 +1,177 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.writeFileSync = exports.writeFile = exports.readFileSync = exports.readFile = void 0;
|
||||
const path = require("path");
|
||||
const consts_1 = require("./consts");
|
||||
const fs_1 = require("./utils/fs");
|
||||
const lang_1 = require("./utils/lang");
|
||||
const scheduler_1 = require("./utils/scheduler");
|
||||
const temp_1 = require("./utils/temp");
|
||||
function readFile(filePath, options = consts_1.DEFAULT_READ_OPTIONS) {
|
||||
var _a;
|
||||
if (lang_1.default.isString(options))
|
||||
return readFile(filePath, { encoding: options });
|
||||
const timeout = Date.now() + ((_a = options.timeout) !== null && _a !== void 0 ? _a : consts_1.DEFAULT_TIMEOUT_ASYNC);
|
||||
return fs_1.default.readFileRetry(timeout)(filePath, options);
|
||||
}
|
||||
exports.readFile = readFile;
|
||||
;
|
||||
function readFileSync(filePath, options = consts_1.DEFAULT_READ_OPTIONS) {
|
||||
var _a;
|
||||
if (lang_1.default.isString(options))
|
||||
return readFileSync(filePath, { encoding: options });
|
||||
const timeout = Date.now() + ((_a = options.timeout) !== null && _a !== void 0 ? _a : consts_1.DEFAULT_TIMEOUT_SYNC);
|
||||
return fs_1.default.readFileSyncRetry(timeout)(filePath, options);
|
||||
}
|
||||
exports.readFileSync = readFileSync;
|
||||
;
|
||||
const writeFile = (filePath, data, options, callback) => {
|
||||
if (lang_1.default.isFunction(options))
|
||||
return writeFile(filePath, data, consts_1.DEFAULT_WRITE_OPTIONS, options);
|
||||
const promise = writeFileAsync(filePath, data, options);
|
||||
if (callback)
|
||||
promise.then(callback, callback);
|
||||
return promise;
|
||||
};
|
||||
exports.writeFile = writeFile;
|
||||
const writeFileAsync = async (filePath, data, options = consts_1.DEFAULT_WRITE_OPTIONS) => {
|
||||
var _a;
|
||||
if (lang_1.default.isString(options))
|
||||
return writeFileAsync(filePath, data, { encoding: options });
|
||||
const timeout = Date.now() + ((_a = options.timeout) !== null && _a !== void 0 ? _a : consts_1.DEFAULT_TIMEOUT_ASYNC);
|
||||
let schedulerCustomDisposer = null, schedulerDisposer = null, tempDisposer = null, tempPath = null, fd = null;
|
||||
try {
|
||||
if (options.schedule)
|
||||
schedulerCustomDisposer = await options.schedule(filePath);
|
||||
schedulerDisposer = await scheduler_1.default.schedule(filePath);
|
||||
filePath = await fs_1.default.realpathAttempt(filePath) || filePath;
|
||||
[tempPath, tempDisposer] = temp_1.default.get(filePath, options.tmpCreate || temp_1.default.create, !(options.tmpPurge === false));
|
||||
const useStatChown = consts_1.IS_POSIX && lang_1.default.isUndefined(options.chown), useStatMode = lang_1.default.isUndefined(options.mode);
|
||||
if (useStatChown || useStatMode) {
|
||||
const stat = await fs_1.default.statAttempt(filePath);
|
||||
if (stat) {
|
||||
options = { ...options };
|
||||
if (useStatChown)
|
||||
options.chown = { uid: stat.uid, gid: stat.gid };
|
||||
if (useStatMode)
|
||||
options.mode = stat.mode;
|
||||
}
|
||||
}
|
||||
const parentPath = path.dirname(filePath);
|
||||
await fs_1.default.mkdirAttempt(parentPath, {
|
||||
mode: consts_1.DEFAULT_FOLDER_MODE,
|
||||
recursive: true
|
||||
});
|
||||
fd = await fs_1.default.openRetry(timeout)(tempPath, 'w', options.mode || consts_1.DEFAULT_FILE_MODE);
|
||||
if (options.tmpCreated)
|
||||
options.tmpCreated(tempPath);
|
||||
if (lang_1.default.isString(data)) {
|
||||
await fs_1.default.writeRetry(timeout)(fd, data, 0, options.encoding || consts_1.DEFAULT_ENCODING);
|
||||
}
|
||||
else if (!lang_1.default.isUndefined(data)) {
|
||||
await fs_1.default.writeRetry(timeout)(fd, data, 0, data.length, 0);
|
||||
}
|
||||
if (options.fsync !== false) {
|
||||
if (options.fsyncWait !== false) {
|
||||
await fs_1.default.fsyncRetry(timeout)(fd);
|
||||
}
|
||||
else {
|
||||
fs_1.default.fsyncAttempt(fd);
|
||||
}
|
||||
}
|
||||
await fs_1.default.closeRetry(timeout)(fd);
|
||||
fd = null;
|
||||
if (options.chown)
|
||||
await fs_1.default.chownAttempt(tempPath, options.chown.uid, options.chown.gid);
|
||||
if (options.mode)
|
||||
await fs_1.default.chmodAttempt(tempPath, options.mode);
|
||||
try {
|
||||
await fs_1.default.renameRetry(timeout)(tempPath, filePath);
|
||||
}
|
||||
catch (error) {
|
||||
if (error.code !== 'ENAMETOOLONG')
|
||||
throw error;
|
||||
await fs_1.default.renameRetry(timeout)(tempPath, temp_1.default.truncate(filePath));
|
||||
}
|
||||
tempDisposer();
|
||||
tempPath = null;
|
||||
}
|
||||
finally {
|
||||
if (fd)
|
||||
await fs_1.default.closeAttempt(fd);
|
||||
if (tempPath)
|
||||
temp_1.default.purge(tempPath);
|
||||
if (schedulerCustomDisposer)
|
||||
schedulerCustomDisposer();
|
||||
if (schedulerDisposer)
|
||||
schedulerDisposer();
|
||||
}
|
||||
};
|
||||
const writeFileSync = (filePath, data, options = consts_1.DEFAULT_WRITE_OPTIONS) => {
|
||||
var _a;
|
||||
if (lang_1.default.isString(options))
|
||||
return writeFileSync(filePath, data, { encoding: options });
|
||||
const timeout = Date.now() + ((_a = options.timeout) !== null && _a !== void 0 ? _a : consts_1.DEFAULT_TIMEOUT_SYNC);
|
||||
let tempDisposer = null, tempPath = null, fd = null;
|
||||
try {
|
||||
filePath = fs_1.default.realpathSyncAttempt(filePath) || filePath;
|
||||
[tempPath, tempDisposer] = temp_1.default.get(filePath, options.tmpCreate || temp_1.default.create, !(options.tmpPurge === false));
|
||||
const useStatChown = consts_1.IS_POSIX && lang_1.default.isUndefined(options.chown), useStatMode = lang_1.default.isUndefined(options.mode);
|
||||
if (useStatChown || useStatMode) {
|
||||
const stat = fs_1.default.statSyncAttempt(filePath);
|
||||
if (stat) {
|
||||
options = { ...options };
|
||||
if (useStatChown)
|
||||
options.chown = { uid: stat.uid, gid: stat.gid };
|
||||
if (useStatMode)
|
||||
options.mode = stat.mode;
|
||||
}
|
||||
}
|
||||
const parentPath = path.dirname(filePath);
|
||||
fs_1.default.mkdirSyncAttempt(parentPath, {
|
||||
mode: consts_1.DEFAULT_FOLDER_MODE,
|
||||
recursive: true
|
||||
});
|
||||
fd = fs_1.default.openSyncRetry(timeout)(tempPath, 'w', options.mode || consts_1.DEFAULT_FILE_MODE);
|
||||
if (options.tmpCreated)
|
||||
options.tmpCreated(tempPath);
|
||||
if (lang_1.default.isString(data)) {
|
||||
fs_1.default.writeSyncRetry(timeout)(fd, data, 0, options.encoding || consts_1.DEFAULT_ENCODING);
|
||||
}
|
||||
else if (!lang_1.default.isUndefined(data)) {
|
||||
fs_1.default.writeSyncRetry(timeout)(fd, data, 0, data.length, 0);
|
||||
}
|
||||
if (options.fsync !== false) {
|
||||
if (options.fsyncWait !== false) {
|
||||
fs_1.default.fsyncSyncRetry(timeout)(fd);
|
||||
}
|
||||
else {
|
||||
fs_1.default.fsyncAttempt(fd);
|
||||
}
|
||||
}
|
||||
fs_1.default.closeSyncRetry(timeout)(fd);
|
||||
fd = null;
|
||||
if (options.chown)
|
||||
fs_1.default.chownSyncAttempt(tempPath, options.chown.uid, options.chown.gid);
|
||||
if (options.mode)
|
||||
fs_1.default.chmodSyncAttempt(tempPath, options.mode);
|
||||
try {
|
||||
fs_1.default.renameSyncRetry(timeout)(tempPath, filePath);
|
||||
}
|
||||
catch (error) {
|
||||
if (error.code !== 'ENAMETOOLONG')
|
||||
throw error;
|
||||
fs_1.default.renameSyncRetry(timeout)(tempPath, temp_1.default.truncate(filePath));
|
||||
}
|
||||
tempDisposer();
|
||||
tempPath = null;
|
||||
}
|
||||
finally {
|
||||
if (fd)
|
||||
fs_1.default.closeSyncAttempt(fd);
|
||||
if (tempPath)
|
||||
temp_1.default.purge(tempPath);
|
||||
}
|
||||
};
|
||||
exports.writeFileSync = writeFileSync;
|
||||
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.attemptifySync = exports.attemptifyAsync = void 0;
|
||||
const consts_1 = require("../consts");
|
||||
/* ATTEMPTIFY */
|
||||
//TODO: Maybe publish this as a standalone package
|
||||
//FIXME: The type castings here aren't exactly correct
|
||||
const attemptifyAsync = (fn, onError = consts_1.NOOP) => {
|
||||
return function () {
|
||||
return fn.apply(undefined, arguments).catch(onError);
|
||||
};
|
||||
};
|
||||
exports.attemptifyAsync = attemptifyAsync;
|
||||
const attemptifySync = (fn, onError = consts_1.NOOP) => {
|
||||
return function () {
|
||||
try {
|
||||
return fn.apply(undefined, arguments);
|
||||
}
|
||||
catch (error) {
|
||||
return onError(error);
|
||||
}
|
||||
};
|
||||
};
|
||||
exports.attemptifySync = attemptifySync;
|
||||
@@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs = require("fs");
|
||||
const util_1 = require("util");
|
||||
const attemptify_1 = require("./attemptify");
|
||||
const fs_handlers_1 = require("./fs_handlers");
|
||||
const retryify_1 = require("./retryify");
|
||||
/* FS */
|
||||
const FS = {
|
||||
chmodAttempt: attemptify_1.attemptifyAsync(util_1.promisify(fs.chmod), fs_handlers_1.default.onChangeError),
|
||||
chownAttempt: attemptify_1.attemptifyAsync(util_1.promisify(fs.chown), fs_handlers_1.default.onChangeError),
|
||||
closeAttempt: attemptify_1.attemptifyAsync(util_1.promisify(fs.close)),
|
||||
fsyncAttempt: attemptify_1.attemptifyAsync(util_1.promisify(fs.fsync)),
|
||||
mkdirAttempt: attemptify_1.attemptifyAsync(util_1.promisify(fs.mkdir)),
|
||||
realpathAttempt: attemptify_1.attemptifyAsync(util_1.promisify(fs.realpath)),
|
||||
statAttempt: attemptify_1.attemptifyAsync(util_1.promisify(fs.stat)),
|
||||
unlinkAttempt: attemptify_1.attemptifyAsync(util_1.promisify(fs.unlink)),
|
||||
closeRetry: retryify_1.retryifyAsync(util_1.promisify(fs.close), fs_handlers_1.default.isRetriableError),
|
||||
fsyncRetry: retryify_1.retryifyAsync(util_1.promisify(fs.fsync), fs_handlers_1.default.isRetriableError),
|
||||
openRetry: retryify_1.retryifyAsync(util_1.promisify(fs.open), fs_handlers_1.default.isRetriableError),
|
||||
readFileRetry: retryify_1.retryifyAsync(util_1.promisify(fs.readFile), fs_handlers_1.default.isRetriableError),
|
||||
renameRetry: retryify_1.retryifyAsync(util_1.promisify(fs.rename), fs_handlers_1.default.isRetriableError),
|
||||
statRetry: retryify_1.retryifyAsync(util_1.promisify(fs.stat), fs_handlers_1.default.isRetriableError),
|
||||
writeRetry: retryify_1.retryifyAsync(util_1.promisify(fs.write), fs_handlers_1.default.isRetriableError),
|
||||
chmodSyncAttempt: attemptify_1.attemptifySync(fs.chmodSync, fs_handlers_1.default.onChangeError),
|
||||
chownSyncAttempt: attemptify_1.attemptifySync(fs.chownSync, fs_handlers_1.default.onChangeError),
|
||||
closeSyncAttempt: attemptify_1.attemptifySync(fs.closeSync),
|
||||
mkdirSyncAttempt: attemptify_1.attemptifySync(fs.mkdirSync),
|
||||
realpathSyncAttempt: attemptify_1.attemptifySync(fs.realpathSync),
|
||||
statSyncAttempt: attemptify_1.attemptifySync(fs.statSync),
|
||||
unlinkSyncAttempt: attemptify_1.attemptifySync(fs.unlinkSync),
|
||||
closeSyncRetry: retryify_1.retryifySync(fs.closeSync, fs_handlers_1.default.isRetriableError),
|
||||
fsyncSyncRetry: retryify_1.retryifySync(fs.fsyncSync, fs_handlers_1.default.isRetriableError),
|
||||
openSyncRetry: retryify_1.retryifySync(fs.openSync, fs_handlers_1.default.isRetriableError),
|
||||
readFileSyncRetry: retryify_1.retryifySync(fs.readFileSync, fs_handlers_1.default.isRetriableError),
|
||||
renameSyncRetry: retryify_1.retryifySync(fs.renameSync, fs_handlers_1.default.isRetriableError),
|
||||
statSyncRetry: retryify_1.retryifySync(fs.statSync, fs_handlers_1.default.isRetriableError),
|
||||
writeSyncRetry: retryify_1.retryifySync(fs.writeSync, fs_handlers_1.default.isRetriableError)
|
||||
};
|
||||
/* EXPORT */
|
||||
exports.default = FS;
|
||||
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const consts_1 = require("../consts");
|
||||
/* FS HANDLERS */
|
||||
const Handlers = {
|
||||
isChangeErrorOk: (error) => {
|
||||
const { code } = error;
|
||||
if (code === 'ENOSYS')
|
||||
return true;
|
||||
if (!consts_1.IS_USER_ROOT && (code === 'EINVAL' || code === 'EPERM'))
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
isRetriableError: (error) => {
|
||||
const { code } = error;
|
||||
if (code === 'EMFILE' || code === 'ENFILE' || code === 'EAGAIN' || code === 'EBUSY' || code === 'EACCESS' || code === 'EACCS' || code === 'EPERM')
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
onChangeError: (error) => {
|
||||
if (Handlers.isChangeErrorOk(error))
|
||||
return;
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
/* EXPORT */
|
||||
exports.default = Handlers;
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
/* LANG */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Lang = {
|
||||
isFunction: (x) => {
|
||||
return typeof x === 'function';
|
||||
},
|
||||
isString: (x) => {
|
||||
return typeof x === 'string';
|
||||
},
|
||||
isUndefined: (x) => {
|
||||
return typeof x === 'undefined';
|
||||
}
|
||||
};
|
||||
/* EXPORT */
|
||||
exports.default = Lang;
|
||||
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.retryifySync = exports.retryifyAsync = void 0;
|
||||
const retryify_queue_1 = require("./retryify_queue");
|
||||
/* RETRYIFY */
|
||||
const retryifyAsync = (fn, isRetriableError) => {
|
||||
return function (timestamp) {
|
||||
return function attempt() {
|
||||
return retryify_queue_1.default.schedule().then(cleanup => {
|
||||
return fn.apply(undefined, arguments).then(result => {
|
||||
cleanup();
|
||||
return result;
|
||||
}, error => {
|
||||
cleanup();
|
||||
if (Date.now() >= timestamp)
|
||||
throw error;
|
||||
if (isRetriableError(error)) {
|
||||
const delay = Math.round(100 + (400 * Math.random())), delayPromise = new Promise(resolve => setTimeout(resolve, delay));
|
||||
return delayPromise.then(() => attempt.apply(undefined, arguments));
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
exports.retryifyAsync = retryifyAsync;
|
||||
const retryifySync = (fn, isRetriableError) => {
|
||||
return function (timestamp) {
|
||||
return function attempt() {
|
||||
try {
|
||||
return fn.apply(undefined, arguments);
|
||||
}
|
||||
catch (error) {
|
||||
if (Date.now() > timestamp)
|
||||
throw error;
|
||||
if (isRetriableError(error))
|
||||
return attempt.apply(undefined, arguments);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
exports.retryifySync = retryifySync;
|
||||
@@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const consts_1 = require("../consts");
|
||||
/* RETRYIFY QUEUE */
|
||||
const RetryfyQueue = {
|
||||
interval: 25,
|
||||
intervalId: undefined,
|
||||
limit: consts_1.LIMIT_FILES_DESCRIPTORS,
|
||||
queueActive: new Set(),
|
||||
queueWaiting: new Set(),
|
||||
init: () => {
|
||||
if (RetryfyQueue.intervalId)
|
||||
return;
|
||||
RetryfyQueue.intervalId = setInterval(RetryfyQueue.tick, RetryfyQueue.interval);
|
||||
},
|
||||
reset: () => {
|
||||
if (!RetryfyQueue.intervalId)
|
||||
return;
|
||||
clearInterval(RetryfyQueue.intervalId);
|
||||
delete RetryfyQueue.intervalId;
|
||||
},
|
||||
add: (fn) => {
|
||||
RetryfyQueue.queueWaiting.add(fn);
|
||||
if (RetryfyQueue.queueActive.size < (RetryfyQueue.limit / 2)) { // Active queue not under preassure, executing immediately
|
||||
RetryfyQueue.tick();
|
||||
}
|
||||
else {
|
||||
RetryfyQueue.init();
|
||||
}
|
||||
},
|
||||
remove: (fn) => {
|
||||
RetryfyQueue.queueWaiting.delete(fn);
|
||||
RetryfyQueue.queueActive.delete(fn);
|
||||
},
|
||||
schedule: () => {
|
||||
return new Promise(resolve => {
|
||||
const cleanup = () => RetryfyQueue.remove(resolver);
|
||||
const resolver = () => resolve(cleanup);
|
||||
RetryfyQueue.add(resolver);
|
||||
});
|
||||
},
|
||||
tick: () => {
|
||||
if (RetryfyQueue.queueActive.size >= RetryfyQueue.limit)
|
||||
return;
|
||||
if (!RetryfyQueue.queueWaiting.size)
|
||||
return RetryfyQueue.reset();
|
||||
for (const fn of RetryfyQueue.queueWaiting) {
|
||||
if (RetryfyQueue.queueActive.size >= RetryfyQueue.limit)
|
||||
break;
|
||||
RetryfyQueue.queueWaiting.delete(fn);
|
||||
RetryfyQueue.queueActive.add(fn);
|
||||
fn();
|
||||
}
|
||||
}
|
||||
};
|
||||
/* EXPORT */
|
||||
exports.default = RetryfyQueue;
|
||||
@@ -0,0 +1,35 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/* VARIABLES */
|
||||
const Queues = {};
|
||||
/* SCHEDULER */
|
||||
//TODO: Maybe publish this as a standalone package
|
||||
const Scheduler = {
|
||||
next: (id) => {
|
||||
const queue = Queues[id];
|
||||
if (!queue)
|
||||
return;
|
||||
queue.shift();
|
||||
const job = queue[0];
|
||||
if (job) {
|
||||
job(() => Scheduler.next(id));
|
||||
}
|
||||
else {
|
||||
delete Queues[id];
|
||||
}
|
||||
},
|
||||
schedule: (id) => {
|
||||
return new Promise(resolve => {
|
||||
let queue = Queues[id];
|
||||
if (!queue)
|
||||
queue = Queues[id] = [];
|
||||
queue.push(resolve);
|
||||
if (queue.length > 1)
|
||||
return;
|
||||
resolve(() => Scheduler.next(id));
|
||||
});
|
||||
}
|
||||
};
|
||||
/* EXPORT */
|
||||
exports.default = Scheduler;
|
||||
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const path = require("path");
|
||||
const consts_1 = require("../consts");
|
||||
const fs_1 = require("./fs");
|
||||
/* TEMP */
|
||||
//TODO: Maybe publish this as a standalone package
|
||||
const Temp = {
|
||||
store: {},
|
||||
create: (filePath) => {
|
||||
const randomness = `000000${Math.floor(Math.random() * 16777215).toString(16)}`.slice(-6), // 6 random-enough hex characters
|
||||
timestamp = Date.now().toString().slice(-10), // 10 precise timestamp digits
|
||||
prefix = 'tmp-', suffix = `.${prefix}${timestamp}${randomness}`, tempPath = `${filePath}${suffix}`;
|
||||
return tempPath;
|
||||
},
|
||||
get: (filePath, creator, purge = true) => {
|
||||
const tempPath = Temp.truncate(creator(filePath));
|
||||
if (tempPath in Temp.store)
|
||||
return Temp.get(filePath, creator, purge); // Collision found, try again
|
||||
Temp.store[tempPath] = purge;
|
||||
const disposer = () => delete Temp.store[tempPath];
|
||||
return [tempPath, disposer];
|
||||
},
|
||||
purge: (filePath) => {
|
||||
if (!Temp.store[filePath])
|
||||
return;
|
||||
delete Temp.store[filePath];
|
||||
fs_1.default.unlinkAttempt(filePath);
|
||||
},
|
||||
purgeSync: (filePath) => {
|
||||
if (!Temp.store[filePath])
|
||||
return;
|
||||
delete Temp.store[filePath];
|
||||
fs_1.default.unlinkSyncAttempt(filePath);
|
||||
},
|
||||
purgeSyncAll: () => {
|
||||
for (const filePath in Temp.store) {
|
||||
Temp.purgeSync(filePath);
|
||||
}
|
||||
},
|
||||
truncate: (filePath) => {
|
||||
const basename = path.basename(filePath);
|
||||
if (basename.length <= consts_1.LIMIT_BASENAME_LENGTH)
|
||||
return filePath; //FIXME: Rough and quick attempt at detecting ok lengths
|
||||
const truncable = /^(\.?)(.*?)((?:\.[^.]+)?(?:\.tmp-\d{10}[a-f0-9]{6})?)$/.exec(basename);
|
||||
if (!truncable)
|
||||
return filePath; //FIXME: No truncable part detected, can't really do much without also changing the parent path, which is unsafe, hoping for the best here
|
||||
const truncationLength = basename.length - consts_1.LIMIT_BASENAME_LENGTH;
|
||||
return `${filePath.slice(0, -basename.length)}${truncable[1]}${truncable[2].slice(0, -truncationLength)}${truncable[3]}`; //FIXME: The truncable part might be shorter than needed here
|
||||
}
|
||||
};
|
||||
/* INIT */
|
||||
process.on('exit', Temp.purgeSyncAll); // Ensuring purgeable temp files are purged on exit
|
||||
/* EXPORT */
|
||||
exports.default = Temp;
|
||||
@@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RENAME_TIMEOUT = exports.POLLING_TIMEOUT = exports.POLLING_INTERVAL = exports.PLATFORM = exports.IS_WINDOWS = exports.IS_MAC = exports.IS_LINUX = exports.HAS_NATIVE_RECURSION = exports.DEPTH = exports.DEBOUNCE = void 0;
|
||||
const os_1 = __importDefault(require("os"));
|
||||
/* CONSTANTS */
|
||||
const DEBOUNCE = 300;
|
||||
exports.DEBOUNCE = DEBOUNCE;
|
||||
const DEPTH = 20;
|
||||
exports.DEPTH = DEPTH;
|
||||
const PLATFORM = os_1.default.platform();
|
||||
exports.PLATFORM = PLATFORM;
|
||||
const IS_LINUX = (PLATFORM === 'linux');
|
||||
exports.IS_LINUX = IS_LINUX;
|
||||
const IS_MAC = (PLATFORM === 'darwin');
|
||||
exports.IS_MAC = IS_MAC;
|
||||
const IS_WINDOWS = (PLATFORM === 'win32');
|
||||
exports.IS_WINDOWS = IS_WINDOWS;
|
||||
const HAS_NATIVE_RECURSION = IS_MAC || IS_WINDOWS;
|
||||
exports.HAS_NATIVE_RECURSION = HAS_NATIVE_RECURSION;
|
||||
const POLLING_INTERVAL = 3000;
|
||||
exports.POLLING_INTERVAL = POLLING_INTERVAL;
|
||||
const POLLING_TIMEOUT = 20000;
|
||||
exports.POLLING_TIMEOUT = POLLING_TIMEOUT;
|
||||
const RENAME_TIMEOUT = 1250;
|
||||
exports.RENAME_TIMEOUT = RENAME_TIMEOUT;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0EsWUFBWTs7Ozs7O0FBRVosNENBQW9CO0FBRXBCLGVBQWU7QUFFZixNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUM7QUFzQmIsNEJBQVE7QUFwQmhCLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQztBQW9CQyxzQkFBSztBQWxCdkIsTUFBTSxRQUFRLEdBQUcsWUFBRSxDQUFDLFFBQVEsRUFBRyxDQUFDO0FBa0I2Qyw0QkFBUTtBQWhCckYsTUFBTSxRQUFRLEdBQUcsQ0FBRSxRQUFRLEtBQUssT0FBTyxDQUFFLENBQUM7QUFnQkssNEJBQVE7QUFkdkQsTUFBTSxNQUFNLEdBQUcsQ0FBRSxRQUFRLEtBQUssUUFBUSxDQUFFLENBQUM7QUFjZ0Isd0JBQU07QUFaL0QsTUFBTSxVQUFVLEdBQUcsQ0FBRSxRQUFRLEtBQUssT0FBTyxDQUFFLENBQUM7QUFZcUIsZ0NBQVU7QUFWM0UsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLElBQUksVUFBVSxDQUFDO0FBVXpCLG9EQUFvQjtBQVI3QyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQztBQVF5RCw0Q0FBZ0I7QUFOdkcsTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDO0FBTTJFLDBDQUFlO0FBSnhILE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQztBQUk4Rix3Q0FBYyJ9
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Returns a function, that, as long as it continues to be invoked, will not
|
||||
* be triggered. The function will be called after it stops being called for
|
||||
* N milliseconds. If `immediate` is passed, trigger the function on the
|
||||
* leading edge, instead of the trailing. The function also has a property 'clear'
|
||||
* that is a function which will clear the timer to prevent previously scheduled executions.
|
||||
*
|
||||
* @source underscore.js
|
||||
* @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
|
||||
* @param {Function} function to wrap
|
||||
* @param {Number} timeout in ms (`100`)
|
||||
* @param {Boolean} whether to execute at the beginning (`false`)
|
||||
* @api public
|
||||
*/
|
||||
function debounce(func, wait, immediate) {
|
||||
var timeout, args, context, timestamp, result;
|
||||
if (null == wait) wait = 100;
|
||||
|
||||
function later() {
|
||||
var last = Date.now() - timestamp;
|
||||
|
||||
if (last < wait && last >= 0) {
|
||||
timeout = setTimeout(later, wait - last);
|
||||
} else {
|
||||
timeout = null;
|
||||
if (!immediate) {
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var debounced = function () {
|
||||
context = this;
|
||||
args = arguments;
|
||||
timestamp = Date.now();
|
||||
var callNow = immediate && !timeout;
|
||||
if (!timeout) timeout = setTimeout(later, wait);
|
||||
if (callNow) {
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
debounced.clear = function () {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
};
|
||||
|
||||
debounced.flush = function () {
|
||||
if (timeout) {
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
};
|
||||
|
||||
return debounced;
|
||||
};
|
||||
|
||||
// Adds compatibility for ES modules
|
||||
debounce.debounce = debounce;
|
||||
|
||||
module.exports = debounce;
|
||||
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
/* ENUMS */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW51bXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZW51bXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLFdBQVcifQ==
|
||||
@@ -0,0 +1,15 @@
|
||||
/*!
|
||||
* is-primitive <https://github.com/jonschlinkert/is-primitive>
|
||||
*
|
||||
* Copyright (c) 2014-present, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function isPrimitive(val) {
|
||||
if (typeof val === 'object') {
|
||||
return val === null;
|
||||
}
|
||||
return typeof val !== 'function';
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
/* PROMISE CONCURRENCY LIMITER */
|
||||
class Limiter {
|
||||
/* CONSTRUCTOR */
|
||||
constructor(options) {
|
||||
this.concurrency = options.concurrency;
|
||||
this.count = 0;
|
||||
this.queue = new Set();
|
||||
}
|
||||
/* API */
|
||||
add(fn) {
|
||||
if (this.count < this.concurrency)
|
||||
return this.run(fn);
|
||||
return new Promise(resolve => {
|
||||
const callback = () => resolve(this.run(fn));
|
||||
this.queue.add(callback);
|
||||
});
|
||||
}
|
||||
flush() {
|
||||
for (const callback of this.queue) {
|
||||
if (this.count >= this.concurrency)
|
||||
break;
|
||||
this.queue.delete(callback);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
run(fn) {
|
||||
this.count += 1;
|
||||
const promise = fn();
|
||||
const cleanup = () => {
|
||||
this.count -= 1;
|
||||
this.flush();
|
||||
};
|
||||
promise.then(cleanup, cleanup);
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
module.exports = Limiter;
|
||||
module.exports.default = Limiter;
|
||||
Object.defineProperty(module.exports, "__esModule", { value: true });
|
||||
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
/* CONSTS */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.S_IFSOCK = exports.S_IFREG = exports.S_IFMT = exports.S_IFLNK = exports.S_IFIFO = exports.S_IFDIR = exports.S_IFCHR = exports.S_IFBLK = exports.RETRY_TIMEOUT = exports.MAX_SAFE_INTEGER = exports.IS_WINDOWS = void 0;
|
||||
const IS_WINDOWS = (process.platform === 'win32');
|
||||
exports.IS_WINDOWS = IS_WINDOWS;
|
||||
const { MAX_SAFE_INTEGER } = Number;
|
||||
exports.MAX_SAFE_INTEGER = MAX_SAFE_INTEGER;
|
||||
const RETRY_TIMEOUT = 5000;
|
||||
exports.RETRY_TIMEOUT = RETRY_TIMEOUT;
|
||||
const { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK } = process['binding']('constants').fs;
|
||||
exports.S_IFBLK = S_IFBLK;
|
||||
exports.S_IFCHR = S_IFCHR;
|
||||
exports.S_IFDIR = S_IFDIR;
|
||||
exports.S_IFIFO = S_IFIFO;
|
||||
exports.S_IFLNK = S_IFLNK;
|
||||
exports.S_IFMT = S_IFMT;
|
||||
exports.S_IFREG = S_IFREG;
|
||||
exports.S_IFSOCK = S_IFSOCK;
|
||||
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Stats = void 0;
|
||||
const fs_1 = require("../atomically/utils/fs");
|
||||
const path_1 = require("path");
|
||||
const consts_1 = require("./consts");
|
||||
const stats_1 = require("./stats");
|
||||
exports.Stats = stats_1.default;
|
||||
/* HELPERS */
|
||||
const { stat, FSReqCallback } = process['binding']('fs');
|
||||
/* RIPSTAT */
|
||||
const ripstat = (filePath, timeout) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = new FSReqCallback(true);
|
||||
req.oncomplete = (error, statsdata) => {
|
||||
if (error) {
|
||||
const { code } = error;
|
||||
if (code === 'EMFILE' || code === 'ENFILE' || code === 'EAGAIN' || code === 'EBUSY' || code === 'EACCESS' || code === 'EACCS' || code === 'EPERM') { // Retriable error
|
||||
fs_1.default.statRetry(timeout || consts_1.RETRY_TIMEOUT)(filePath, { bigint: true }).then(nstats => {
|
||||
const statsdata = [nstats.dev, nstats.mode, nstats.nlink, nstats.uid, nstats.gid, nstats.rdev, nstats.blksize, nstats.ino, nstats.size, nstats.blocks, 0n, nstats.atimeNs, 0n, nstats.mtimeNs, 0n, nstats.ctimeNs, 0n, nstats.birthtimeNs];
|
||||
const stats = new stats_1.default(statsdata);
|
||||
resolve(stats);
|
||||
}, reject);
|
||||
}
|
||||
else {
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const stats = new stats_1.default(statsdata);
|
||||
resolve(stats);
|
||||
}
|
||||
};
|
||||
stat(path_1.toNamespacedPath(filePath), true, req);
|
||||
});
|
||||
};
|
||||
/* EXPORT */
|
||||
exports.default = ripstat;
|
||||
@@ -0,0 +1,55 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const consts_1 = require("./consts");
|
||||
/* HELPERS */
|
||||
const { floor } = Math;
|
||||
const toNumber = Number;
|
||||
/* STATS */
|
||||
class Stats {
|
||||
/* CONSTRUCTOR */
|
||||
constructor(stats) {
|
||||
this.dev = toNumber(stats[0]);
|
||||
this.mode = toNumber(stats[1]);
|
||||
this.nlink = toNumber(stats[2]);
|
||||
this.uid = toNumber(stats[3]);
|
||||
this.gid = toNumber(stats[4]);
|
||||
this.rdev = toNumber(stats[5]);
|
||||
this.blksize = toNumber(stats[6]);
|
||||
this.ino = (stats[7] <= consts_1.MAX_SAFE_INTEGER) ? toNumber(stats[7]) : stats[7];
|
||||
this.size = toNumber(stats[8]);
|
||||
this.blocks = toNumber(stats[9]);
|
||||
this.atimeMs = (toNumber(stats[10]) * 1000) + floor(toNumber(stats[11]) / 1000000);
|
||||
this.mtimeMs = (toNumber(stats[12]) * 1000) + floor(toNumber(stats[13]) / 1000000);
|
||||
this.ctimeMs = (toNumber(stats[14]) * 1000) + floor(toNumber(stats[15]) / 1000000);
|
||||
this.birthtimeMs = (toNumber(stats[16]) * 1000) + floor(toNumber(stats[17]) / 1000000);
|
||||
}
|
||||
/* HELPERS */
|
||||
_isMode(mode) {
|
||||
return (this.mode & consts_1.S_IFMT) === mode;
|
||||
}
|
||||
/* API */
|
||||
isDirectory() {
|
||||
return this._isMode(consts_1.S_IFDIR);
|
||||
}
|
||||
isFile() {
|
||||
return this._isMode(consts_1.S_IFREG);
|
||||
}
|
||||
isBlockDevice() {
|
||||
return !consts_1.IS_WINDOWS && this._isMode(consts_1.S_IFBLK);
|
||||
}
|
||||
isCharacterDevice() {
|
||||
return this._isMode(consts_1.S_IFCHR);
|
||||
}
|
||||
isSymbolicLink() {
|
||||
return this._isMode(consts_1.S_IFLNK);
|
||||
}
|
||||
isFIFO() {
|
||||
return !consts_1.IS_WINDOWS && this._isMode(consts_1.S_IFIFO);
|
||||
}
|
||||
isSocket() {
|
||||
return !consts_1.IS_WINDOWS && this._isMode(consts_1.S_IFSOCK);
|
||||
}
|
||||
}
|
||||
/* EXPORT */
|
||||
exports.default = Stats;
|
||||
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
/* STRING INDEXES */
|
||||
function indexes(str, substr) {
|
||||
var indexes = [], rangeLength = substr.length;
|
||||
var indexFrom = 0;
|
||||
while (true) {
|
||||
var index = str.indexOf(substr, indexFrom);
|
||||
if (index === -1)
|
||||
return indexes;
|
||||
indexes.push(index);
|
||||
indexFrom = index + rangeLength;
|
||||
}
|
||||
}
|
||||
/* EXPORT */
|
||||
module.exports = indexes;
|
||||
module.exports.default = indexes;
|
||||
Object.defineProperty(module.exports, "__esModule", { value: true });
|
||||
@@ -0,0 +1,104 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const promise_concurrency_limiter_1 = require("./promise-concurrency-limiter");
|
||||
/* HELPERS */
|
||||
const limiter = new promise_concurrency_limiter_1.default({ concurrency: 500 });
|
||||
/* TINY READDIR */
|
||||
const readdir = (rootPath, options) => {
|
||||
var _a, _b, _c, _d;
|
||||
const followSymlinks = (_a = options === null || options === void 0 ? void 0 : options.followSymlinks) !== null && _a !== void 0 ? _a : false, maxDepth = (_b = options === null || options === void 0 ? void 0 : options.depth) !== null && _b !== void 0 ? _b : Infinity, isIgnored = (_c = options === null || options === void 0 ? void 0 : options.ignore) !== null && _c !== void 0 ? _c : (() => false), signal = (_d = options === null || options === void 0 ? void 0 : options.signal) !== null && _d !== void 0 ? _d : { aborted: false }, directories = [], files = [], symlinks = [], map = {}, resultEmpty = { directories: [], files: [], symlinks: [], map: {} }, result = { directories, files, symlinks, map };
|
||||
const handleDirectory = (dirmap, subPath, depth) => {
|
||||
dirmap.directories.push(subPath);
|
||||
directories.push(subPath);
|
||||
if (depth >= maxDepth)
|
||||
return;
|
||||
|
||||
// if depth > 1 and the limiter is full, then we cannot queue this function or the current promise will never return
|
||||
if (depth > 1 && limiter.count >= limiter.concurrency) return populateResultFromPath(subPath, depth + 1)
|
||||
|
||||
return limiter.add(() => populateResultFromPath(subPath, depth + 1));
|
||||
};
|
||||
const handleFile = (dirmap, subPath) => {
|
||||
dirmap.files.push(subPath);
|
||||
files.push(subPath);
|
||||
};
|
||||
const handleSymlink = (dirmap, subPath, depth) => {
|
||||
dirmap.symlinks.push(subPath);
|
||||
symlinks.push(subPath);
|
||||
if (!followSymlinks)
|
||||
return;
|
||||
if (depth >= maxDepth)
|
||||
return;
|
||||
return limiter.add(() => populateResultFromSymlink(subPath, depth + 1));
|
||||
};
|
||||
const handleStat = (dirmap, rootPath, stat, depth) => {
|
||||
if (signal.aborted)
|
||||
return;
|
||||
if (isIgnored(rootPath))
|
||||
return;
|
||||
if (stat.isDirectory()) {
|
||||
return handleDirectory(dirmap, rootPath, depth);
|
||||
}
|
||||
else if (stat.isFile()) {
|
||||
return handleFile(dirmap, rootPath);
|
||||
}
|
||||
else if (stat.isSymbolicLink()) {
|
||||
return handleSymlink(dirmap, rootPath, depth);
|
||||
}
|
||||
};
|
||||
const handleDirent = (dirmap, rootPath, dirent, depth) => {
|
||||
if (signal.aborted)
|
||||
return;
|
||||
const subPath = `${rootPath}${path.sep}${dirent.name}`;
|
||||
if (isIgnored(subPath))
|
||||
return;
|
||||
if (dirent.isDirectory()) {
|
||||
return handleDirectory(dirmap, subPath, depth);
|
||||
}
|
||||
else if (dirent.isFile()) {
|
||||
return handleFile(dirmap, subPath);
|
||||
}
|
||||
else if (dirent.isSymbolicLink()) {
|
||||
return handleSymlink(dirmap, subPath, depth);
|
||||
}
|
||||
};
|
||||
const handleDirents = (dirmap, rootPath, dirents, depth) => {
|
||||
return Promise.all(dirents.map((dirent) => {
|
||||
return handleDirent(dirmap, rootPath, dirent, depth);
|
||||
}));
|
||||
};
|
||||
const populateResultFromPath = async (rootPath, depth) => {
|
||||
if (signal.aborted)
|
||||
return;
|
||||
if (depth > maxDepth)
|
||||
return;
|
||||
const dirents = await fs.promises.readdir(rootPath, { withFileTypes: true }).catch(() => []);
|
||||
if (signal.aborted)
|
||||
return;
|
||||
const dirmap = map[rootPath] = { directories: [], files: [], symlinks: [] };
|
||||
if (!dirents.length)
|
||||
return;
|
||||
await handleDirents(dirmap, rootPath, dirents, depth);
|
||||
};
|
||||
const populateResultFromSymlink = async (rootPath, depth) => {
|
||||
try {
|
||||
const realPath = await fs.promises.realpath(rootPath), stat = await fs.promises.stat(realPath), dirmap = map[rootPath] = { directories: [], files: [], symlinks: [] };
|
||||
await handleStat(dirmap, realPath, stat, depth);
|
||||
}
|
||||
catch (_a) { }
|
||||
};
|
||||
const getResult = async (rootPath, depth = 1) => {
|
||||
rootPath = path.normalize(rootPath);
|
||||
await populateResultFromPath(rootPath, depth);
|
||||
if (signal.aborted)
|
||||
return resultEmpty;
|
||||
return result;
|
||||
};
|
||||
return getResult(rootPath);
|
||||
};
|
||||
/* EXPORT */
|
||||
module.exports = readdir;
|
||||
module.exports.default = readdir;
|
||||
Object.defineProperty(module.exports, "__esModule", { value: true });
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WatcherStats = exports.Stats = void 0;
|
||||
const ripstat_1 = require("ripstat");
|
||||
Object.defineProperty(exports, "Stats", { enumerable: true, get: function () { return ripstat_1.Stats; } });
|
||||
const watcher_stats_1 = __importDefault(require("./watcher_stats"));
|
||||
exports.WatcherStats = watcher_stats_1.default;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLFlBQVk7Ozs7OztBQUdaLHFDQUE4QjtBQWlGbUUsc0ZBakZ6RixlQUFLLE9BaUZ5RjtBQTlFdEcsb0VBQTJDO0FBOEUwSyx1QkE5RTlNLHVCQUFZLENBOEU4TSJ9
|
||||
@@ -0,0 +1,88 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const are_shallow_equal_1 = __importDefault(require("./are-shallow-equal"));
|
||||
const debounce_1 = __importDefault(require("./debounce"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const ripstat_1 = __importDefault(require("./ripstat"));
|
||||
const tiny_readdir_1 = __importDefault(require("./tiny-readdir"));
|
||||
const constants_1 = require("./constants");
|
||||
/* UTILS */
|
||||
const Utils = {
|
||||
lang: {
|
||||
areShallowEqual: //TODO: Import all these utilities from "nanodash" instead
|
||||
are_shallow_equal_1.default,
|
||||
debounce: debounce_1.default,
|
||||
attempt: (fn) => {
|
||||
try {
|
||||
return fn();
|
||||
}
|
||||
catch (error) {
|
||||
return Utils.lang.castError(error);
|
||||
}
|
||||
},
|
||||
castArray: (x) => {
|
||||
return Utils.lang.isArray(x) ? x : [x];
|
||||
},
|
||||
castError(exception) {
|
||||
if (Utils.lang.isError(exception))
|
||||
return exception;
|
||||
if (Utils.lang.isString(exception))
|
||||
return new Error(exception);
|
||||
return new Error('Unknown error');
|
||||
},
|
||||
defer: (callback) => {
|
||||
return setTimeout(callback, 0);
|
||||
},
|
||||
isArray: (x) => {
|
||||
return Array.isArray(x);
|
||||
},
|
||||
isError(x) {
|
||||
return x instanceof Error;
|
||||
},
|
||||
isFunction: (x) => {
|
||||
return typeof x === 'function';
|
||||
},
|
||||
isNumber: (x) => {
|
||||
return typeof x === 'number';
|
||||
},
|
||||
isString: (x) => {
|
||||
return typeof x === 'string';
|
||||
},
|
||||
isUndefined: (x) => {
|
||||
return x === undefined;
|
||||
},
|
||||
noop: () => {
|
||||
return;
|
||||
},
|
||||
uniq: (arr) => {
|
||||
if (arr.length < 2)
|
||||
return arr;
|
||||
return Array.from(new Set(arr));
|
||||
}
|
||||
},
|
||||
fs: {
|
||||
isSubPath: (targetPath, subPath) => {
|
||||
return (subPath.startsWith(targetPath) && subPath[targetPath.length] === path_1.default.sep && (subPath.length - targetPath.length) > path_1.default.sep.length);
|
||||
},
|
||||
poll: (targetPath, timeout = constants_1.POLLING_TIMEOUT) => {
|
||||
return ripstat_1.default(targetPath, timeout).catch(Utils.lang.noop);
|
||||
},
|
||||
readdir: async (rootPath, ignore, depth = Infinity, signal, readdirMap) => {
|
||||
if (readdirMap && depth === 1 && rootPath in readdirMap) { // Reusing cached data
|
||||
const result = readdirMap[rootPath];
|
||||
return [result.directories, result.files];
|
||||
}
|
||||
else { // Retrieving fresh data
|
||||
const result = await tiny_readdir_1.default(rootPath, { depth, ignore, signal });
|
||||
return [result.directories, result.files];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
/* EXPORT */
|
||||
exports.default = Utils;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLFlBQVk7Ozs7O0FBRVosMEVBQWdEO0FBQ2hELHdEQUFnQztBQUNoQyxnREFBd0I7QUFDeEIsc0RBQThCO0FBQzlCLGdFQUFtQztBQUNuQywyQ0FBNEM7QUFHNUMsV0FBVztBQUVYLE1BQU0sS0FBSyxHQUFHO0lBRVosSUFBSSxFQUFFO1FBRUosZUFBZSxFQUZULDBEQUEwRDtRQUVoRSwyQkFBZTtRQUVmLFFBQVEsRUFBUixrQkFBUTtRQUVSLE9BQU8sRUFBRSxDQUFNLEVBQVcsRUFBYyxFQUFFO1lBRXhDLElBQUk7Z0JBRUYsT0FBTyxFQUFFLEVBQUcsQ0FBQzthQUVkO1lBQUMsT0FBUSxLQUFjLEVBQUc7Z0JBRXpCLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUcsS0FBSyxDQUFFLENBQUM7YUFFdkM7UUFFSCxDQUFDO1FBRUQsU0FBUyxFQUFFLENBQU0sQ0FBVSxFQUFRLEVBQUU7WUFFbkMsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBRyxDQUFDLENBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRTVDLENBQUM7UUFFRCxTQUFTLENBQUcsU0FBa0I7WUFFNUIsSUFBSyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBRyxTQUFTLENBQUU7Z0JBQUcsT0FBTyxTQUFTLENBQUM7WUFFekQsSUFBSyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBRyxTQUFTLENBQUU7Z0JBQUcsT0FBTyxJQUFJLEtBQUssQ0FBRyxTQUFTLENBQUUsQ0FBQztZQUV4RSxPQUFPLElBQUksS0FBSyxDQUFHLGVBQWUsQ0FBRSxDQUFDO1FBRXZDLENBQUM7UUFFRCxLQUFLLEVBQUUsQ0FBRSxRQUFrQixFQUFtQixFQUFFO1lBRTlDLE9BQU8s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
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
/* WATCHER LOCKS RESOLVER */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// Registering a single interval scales much better than registering N timeouts
|
||||
// Timeouts are respected within the interval margin
|
||||
const WatcherLocksResolver = {
|
||||
/* VARIABLES */
|
||||
interval: 100,
|
||||
intervalId: undefined,
|
||||
fns: new Map(),
|
||||
/* LIFECYCLE */
|
||||
init: () => {
|
||||
if (WatcherLocksResolver.intervalId)
|
||||
return;
|
||||
WatcherLocksResolver.intervalId = setInterval(WatcherLocksResolver.resolve, WatcherLocksResolver.interval);
|
||||
},
|
||||
reset: () => {
|
||||
if (!WatcherLocksResolver.intervalId)
|
||||
return;
|
||||
clearInterval(WatcherLocksResolver.intervalId);
|
||||
delete WatcherLocksResolver.intervalId;
|
||||
},
|
||||
/* API */
|
||||
add: (fn, timeout) => {
|
||||
WatcherLocksResolver.fns.set(fn, Date.now() + timeout);
|
||||
WatcherLocksResolver.init();
|
||||
},
|
||||
remove: (fn) => {
|
||||
WatcherLocksResolver.fns.delete(fn);
|
||||
},
|
||||
resolve: () => {
|
||||
if (!WatcherLocksResolver.fns.size)
|
||||
return WatcherLocksResolver.reset();
|
||||
const now = Date.now();
|
||||
for (const [fn, timestamp] of WatcherLocksResolver.fns) {
|
||||
if (timestamp >= now)
|
||||
continue; // We should still wait some more for this
|
||||
WatcherLocksResolver.remove(fn);
|
||||
fn();
|
||||
}
|
||||
}
|
||||
};
|
||||
/* EXPORT */
|
||||
exports.default = WatcherLocksResolver;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0Y2hlcl9sb2Nrc19yZXNvbHZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93YXRjaGVyX2xvY2tzX3Jlc29sdmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSw0QkFBNEI7O0FBRTVCLCtFQUErRTtBQUMvRSxvREFBb0Q7QUFFcEQsTUFBTSxvQkFBb0IsR0FBRztJQUUzQixlQUFlO0lBRWYsUUFBUSxFQUFFLEdBQUc7SUFDYixVQUFVLEVBQUUsU0FBdUM7SUFDbkQsR0FBRyxFQUFFLElBQUksR0FBRyxFQUFxQjtJQUVqQyxlQUFlO0lBRWYsSUFBSSxFQUFFLEdBQVMsRUFBRTtRQUVmLElBQUssb0JBQW9CLENBQUMsVUFBVTtZQUFHLE9BQU87UUFFOUMsb0JBQW9CLENBQUMsVUFBVSxHQUFHLFdBQVcsQ0FBRyxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsb0JBQW9CLENBQUMsUUFBUSxDQUFFLENBQUM7SUFFaEgsQ0FBQztJQUVELEtBQUssRUFBRSxHQUFTLEVBQUU7UUFFaEIsSUFBSyxDQUFDLG9CQUFvQixDQUFDLFVBQVU7WUFBRyxPQUFPO1FBRS9DLGFBQWEsQ0FBRyxvQkFBb0IsQ0FBQyxVQUFVLENBQUUsQ0FBQztRQUVsRCxPQUFPLG9CQUFvQixDQUFDLFVBQVUsQ0FBQztJQUV6QyxDQUFDO0lBRUQsU0FBUztJQUVULEdBQUcsRUFBRSxDQUFFLEVBQVksRUFBRSxPQUFlLEVBQVMsRUFBRTtRQUU3QyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFHLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFHLEdBQUcsT0FBTyxDQUFFLENBQUM7UUFFM0Qsb0JBQW9CLENBQUMsSUFBSSxFQUFHLENBQUM7SUFFL0IsQ0FBQztJQUVELE1BQU0sRUFBRSxDQUFFLEVBQVksRUFBUyxFQUFFO1FBRS9CLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUcsRUFBRSxDQUFFLENBQUM7SUFFekMsQ0FBQztJQUVELE9BQU8sRUFBRSxHQUFTLEVBQUU7UUFFbEIsSUFBSyxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxJQUFJO1lBQUcsT0FBTyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUcsQ0FBQztRQUUzRSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFHLENBQUM7UUFFeEIsS0FBTSxNQUFNLENBQUMsRUFBRSxFQUFFLFNBQVMsQ0FBQyxJQUFJLG9CQUFvQixDQUFDLEdBQUcsRUFBRztZQUV4RCxJQUFLLFNBQVMsSUFBSSxHQUFHO2dCQUFHLFNBQVMsQ0FBQywwQ0FBMEM7WUFFNUUsb0JBQW9CLENBQUMsTUFBTSxDQUFHLEVBQUUsQ0FBRSxDQUFDO1lBRW5DLEVBQUUsRUFBRyxDQUFDO1NBRVA7SUFFSCxDQUFDO0NBRUYsQ0FBQztBQUVGLFlBQVk7QUFFWixrQkFBZSxvQkFBb0IsQ0FBQyJ9
|
||||
@@ -0,0 +1,113 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = __importDefault(require("./utils"));
|
||||
const watcher_stats_1 = __importDefault(require("./watcher_stats"));
|
||||
/* WATCHER POLLER */
|
||||
class WatcherPoller {
|
||||
constructor() {
|
||||
/* VARIABLES */
|
||||
this.inos = {};
|
||||
this.stats = new Map();
|
||||
}
|
||||
/* API */
|
||||
getIno(targetPath, event, type) {
|
||||
const inos = this.inos[event];
|
||||
if (!inos)
|
||||
return;
|
||||
const ino = inos[targetPath];
|
||||
if (!ino)
|
||||
return;
|
||||
if (type && ino[1] !== type)
|
||||
return;
|
||||
return ino[0];
|
||||
}
|
||||
getStats(targetPath) {
|
||||
return this.stats.get(targetPath);
|
||||
}
|
||||
async poll(targetPath, timeout) {
|
||||
const stats = await utils_1.default.fs.poll(targetPath, timeout);
|
||||
if (!stats)
|
||||
return;
|
||||
const isSupported = stats.isFile() || stats.isDirectory();
|
||||
if (!isSupported)
|
||||
return;
|
||||
return new watcher_stats_1.default(stats);
|
||||
}
|
||||
reset() {
|
||||
this.inos = {};
|
||||
this.stats = new Map();
|
||||
}
|
||||
async update(targetPath, timeout) {
|
||||
const prev = this.getStats(targetPath), next = await this.poll(targetPath, timeout);
|
||||
this.updateStats(targetPath, next);
|
||||
if (!prev && next) {
|
||||
if (next.isFile()) {
|
||||
this.updateIno(targetPath, "add" /* ADD */, next);
|
||||
return ["add" /* ADD */];
|
||||
}
|
||||
if (next.isDirectory()) {
|
||||
this.updateIno(targetPath, "addDir" /* ADD_DIR */, next);
|
||||
return ["addDir" /* ADD_DIR */];
|
||||
}
|
||||
}
|
||||
else if (prev && !next) {
|
||||
if (prev.isFile()) {
|
||||
this.updateIno(targetPath, "unlink" /* UNLINK */, prev);
|
||||
return ["unlink" /* UNLINK */];
|
||||
}
|
||||
if (prev.isDirectory()) {
|
||||
this.updateIno(targetPath, "unlinkDir" /* UNLINK_DIR */, prev);
|
||||
return ["unlinkDir" /* UNLINK_DIR */];
|
||||
}
|
||||
}
|
||||
else if (prev && next) {
|
||||
if (prev.isFile()) {
|
||||
if (next.isFile()) {
|
||||
if (prev.ino === next.ino && !prev.size && !next.size)
|
||||
return []; // Same path, same content and same file, nothing actually changed
|
||||
this.updateIno(targetPath, "change" /* CHANGE */, next);
|
||||
return ["change" /* CHANGE */];
|
||||
}
|
||||
if (next.isDirectory()) {
|
||||
this.updateIno(targetPath, "unlink" /* UNLINK */, prev);
|
||||
this.updateIno(targetPath, "addDir" /* ADD_DIR */, next);
|
||||
return ["unlink" /* UNLINK */, "addDir" /* ADD_DIR */];
|
||||
}
|
||||
}
|
||||
else if (prev.isDirectory()) {
|
||||
if (next.isFile()) {
|
||||
this.updateIno(targetPath, "unlinkDir" /* UNLINK_DIR */, prev);
|
||||
this.updateIno(targetPath, "add" /* ADD */, next);
|
||||
return ["unlinkDir" /* UNLINK_DIR */, "add" /* ADD */];
|
||||
}
|
||||
if (next.isDirectory()) {
|
||||
if (prev.ino === next.ino)
|
||||
return []; // Same path and same directory, nothing actually changed
|
||||
this.updateIno(targetPath, "unlinkDir" /* UNLINK_DIR */, prev);
|
||||
this.updateIno(targetPath, "addDir" /* ADD_DIR */, next);
|
||||
return ["unlinkDir" /* UNLINK_DIR */, "addDir" /* ADD_DIR */];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
updateIno(targetPath, event, stats) {
|
||||
const inos = this.inos[event] = this.inos[event] || (this.inos[event] = {}), type = stats.isFile() ? 2 /* FILE */ : 1 /* DIR */;
|
||||
inos[targetPath] = [stats.ino, type];
|
||||
}
|
||||
updateStats(targetPath, stats) {
|
||||
if (stats) {
|
||||
this.stats.set(targetPath, stats);
|
||||
}
|
||||
else {
|
||||
this.stats.delete(targetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* EXPORT */
|
||||
exports.default = WatcherPoller;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0Y2hlcl9wb2xsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd2F0Y2hlcl9wb2xsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLFlBQVk7Ozs7O0FBR1osb0RBQTRCO0FBQzVCLG9FQUEyQztBQUczQyxvQkFBb0I7QUFFcEIsTUFBTSxhQUFhO0lBQW5CO1FBRUUsZUFBZTtRQUVmLFNBQUksR0FBZ0UsRUFBRSxDQUFDO1FBQ3ZFLFVBQUssR0FBNEIsSUFBSSxHQUFHLEVBQUcsQ0FBQztJQXNLOUMsQ0FBQztJQXBLQyxTQUFTO0lBRVQsTUFBTSxDQUFHLFVBQWdCLEVBQUUsS0FBa0IsRUFBRSxJQUFlO1FBRTVELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFOUIsSUFBSyxDQUFDLElBQUk7WUFBRyxPQUFPO1FBRXBCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUU3QixJQUFLLENBQUMsR0FBRztZQUFHLE9BQU87UUFFbkIsSUFBSyxJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUk7WUFBRyxPQUFPO1FBRXRDLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRWhCLENBQUM7SUFFRCxRQUFRLENBQUcsVUFBZ0I7UUFFekIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBRyxVQUFVLENBQUUsQ0FBQztJQUV2QyxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUksQ0FBRyxVQUFnQixFQUFFLE9BQWdCO1FBRTdDLE1BQU0sS0FBSyxHQUFHLE1BQU0sZUFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUcsVUFBVSxFQUFFLE9BQU8sQ0FBRSxDQUFDO1FBRTFELElBQUssQ0FBQyxLQUFLO1lBQUcsT0FBTztRQUVyQixNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFHLElBQUksS0FBSyxDQUFD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
|
||||
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
/* IMPORT */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/* WATCHER STATS */
|
||||
// An even more memory-efficient representation of the useful subset of stats objects
|
||||
class WatcherStats {
|
||||
/* CONSTRUCTOR */
|
||||
constructor(stats) {
|
||||
this.ino = stats.ino;
|
||||
this.size = stats.size;
|
||||
this.atimeMs = stats.atimeMs;
|
||||
this.mtimeMs = stats.mtimeMs;
|
||||
this.ctimeMs = stats.ctimeMs;
|
||||
this.birthtimeMs = stats.birthtimeMs;
|
||||
this._isFile = stats.isFile();
|
||||
this._isDirectory = stats.isDirectory();
|
||||
this._isSymbolicLink = stats.isSymbolicLink();
|
||||
}
|
||||
/* API */
|
||||
isFile() {
|
||||
return this._isFile;
|
||||
}
|
||||
isDirectory() {
|
||||
return this._isDirectory;
|
||||
}
|
||||
isSymbolicLink() {
|
||||
return this._isSymbolicLink;
|
||||
}
|
||||
}
|
||||
/* EXPORT */
|
||||
exports.default = WatcherStats;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0Y2hlcl9zdGF0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93YXRjaGVyX3N0YXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSxZQUFZOztBQUlaLG1CQUFtQjtBQUVuQixxRkFBcUY7QUFFckYsTUFBTSxZQUFZO0lBY2hCLGlCQUFpQjtJQUVqQixZQUFjLEtBQVk7UUFFeEIsSUFBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDO1FBQ3JCLElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQztRQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDN0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDO1FBQzdCLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7UUFDckMsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFHLENBQUM7UUFDL0IsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUMsV0FBVyxFQUFHLENBQUM7UUFDekMsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFHLENBQUM7SUFFakQsQ0FBQztJQUVELFNBQVM7SUFFVCxNQUFNO1FBRUosT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBRXRCLENBQUM7SUFFRCxXQUFXO1FBRVQsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBRTNCLENBQUM7SUFFRCxjQUFjO1FBRVosT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDO0lBRTlCLENBQUM7Q0FFRjtBQUVELFlBQVk7QUFFWixrQkFBZSxZQUFZLENBQUMifQ==
|
||||
Reference in New Issue
Block a user