mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
178 lines
7.6 KiB
JavaScript
178 lines
7.6 KiB
JavaScript
|
"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;
|