Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@yarnpkg/fslib

Package Overview
Dependencies
Maintainers
5
Versions
131
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@yarnpkg/fslib - npm Package Compare versions

Comparing version 2.0.0-rc.14 to 2.0.0-rc.15

lib/algorithms/copyPromise.d.ts

193

lib/algorithms/copyPromise.js
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.copyPromise = copyPromise;
var _fs = _interopRequireDefault(require("fs"));
var _path = require("../path");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = require("../path");
async function copyPromise(destinationFs, destination, sourceFs, source, opts) {
const normalizedDestination = destinationFs.pathUtils.normalize(destination);
const normalizedSource = sourceFs.pathUtils.normalize(source);
const operations = [];
const utimes = [];
await destinationFs.mkdirpPromise(destination);
await copyImpl(operations, utimes, destinationFs, normalizedDestination, sourceFs, normalizedSource, opts);
for (const operation of operations) await operation();
for (const [p, atime, mtime] of utimes) {
await destinationFs.utimesPromise(p, atime, mtime);
}
const normalizedDestination = destinationFs.pathUtils.normalize(destination);
const normalizedSource = sourceFs.pathUtils.normalize(source);
const operations = [];
const utimes = [];
await destinationFs.mkdirpPromise(destination);
await copyImpl(operations, utimes, destinationFs, normalizedDestination, sourceFs, normalizedSource, opts);
for (const operation of operations)
await operation();
for (const [p, atime, mtime] of utimes) {
await destinationFs.utimesPromise(p, atime, mtime);
}
}
exports.copyPromise = copyPromise;
async function copyImpl(operations, utimes, destinationFs, destination, sourceFs, source, opts) {
const destinationStat = await maybeLStat(destinationFs, destination);
const sourceStat = await sourceFs.lstatPromise(source);
utimes.push([destination, sourceStat.atime, sourceStat.mtime]);
switch (true) {
case sourceStat.isDirectory():
{
await copyFolder(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
}
break;
case sourceStat.isFile():
{
await copyFile(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
}
break;
case sourceStat.isSymbolicLink():
{
await copySymlink(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
}
break;
default:
{
throw new Error(`Unsupported file type (${sourceStat.mode})`);
}
break;
}
operations.push(async () => destinationFs.chmodPromise(destination, sourceStat.mode & 0o777));
const destinationStat = await maybeLStat(destinationFs, destination);
const sourceStat = await sourceFs.lstatPromise(source);
utimes.push([destination, sourceStat.atime, sourceStat.mtime]);
switch (true) {
case sourceStat.isDirectory():
{
await copyFolder(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
}
break;
case sourceStat.isFile():
{
await copyFile(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
}
break;
case sourceStat.isSymbolicLink():
{
await copySymlink(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
}
break;
default:
{
throw new Error(`Unsupported file type (${sourceStat.mode})`);
}
break;
}
operations.push(async () => destinationFs.chmodPromise(destination, sourceStat.mode & 0o777));
}
async function maybeLStat(baseFs, p) {
try {
return await baseFs.lstatPromise(p);
} catch (e) {
return null;
}
try {
return await baseFs.lstatPromise(p);
}
catch (e) {
return null;
}
}
async function copyFolder(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) {
if (destinationStat !== null && !destinationStat.isDirectory()) {
if (opts.overwrite) {
operations.push(async () => destinationFs.removePromise(destination));
destinationStat = null;
} else {
return;
if (destinationStat !== null && !destinationStat.isDirectory()) {
if (opts.overwrite) {
operations.push(async () => destinationFs.removePromise(destination));
destinationStat = null;
}
else {
return;
}
}
}
if (destinationStat === null) operations.push(async () => destinationFs.mkdirPromise(destination, {
mode: sourceStat.mode
}));
const entries = await sourceFs.readdirPromise(source);
await Promise.all(entries.map(async entry => {
await copyImpl(operations, utimes, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), opts);
}));
if (destinationStat === null)
operations.push(async () => destinationFs.mkdirPromise(destination, { mode: sourceStat.mode }));
const entries = await sourceFs.readdirPromise(source);
await Promise.all(entries.map(async (entry) => {
await copyImpl(operations, utimes, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), opts);
}));
}
async function copyFile(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) {
if (destinationStat !== null) {
if (opts.overwrite) {
operations.push(async () => destinationFs.removePromise(destination));
destinationStat = null;
} else {
return;
if (destinationStat !== null) {
if (opts.overwrite) {
operations.push(async () => destinationFs.removePromise(destination));
destinationStat = null;
}
else {
return;
}
}
}
if (destinationFs === sourceFs) {
operations.push(async () => destinationFs.copyFilePromise(source, destination, _fs.default.constants.COPYFILE_FICLONE));
} else {
operations.push(async () => destinationFs.writeFilePromise(destination, (await sourceFs.readFilePromise(source))));
}
if (destinationFs === sourceFs) {
operations.push(async () => destinationFs.copyFilePromise(source, destination, fs_1.default.constants.COPYFILE_FICLONE));
}
else {
operations.push(async () => destinationFs.writeFilePromise(destination, await sourceFs.readFilePromise(source)));
}
}
async function copySymlink(operations, utimes, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) {
if (destinationStat !== null) {
if (opts.overwrite) {
operations.push(async () => destinationFs.removePromise(destination));
destinationStat = null;
} else {
return;
if (destinationStat !== null) {
if (opts.overwrite) {
operations.push(async () => destinationFs.removePromise(destination));
destinationStat = null;
}
else {
return;
}
}
}
const target = await sourceFs.readlinkPromise(source);
operations.push(async () => destinationFs.symlinkPromise((0, _path.convertPath)(destinationFs.pathUtils, target), destination));
}
const target = await sourceFs.readlinkPromise(source);
operations.push(async () => destinationFs.symlinkPromise(path_1.convertPath(destinationFs.pathUtils, target), destination));
}
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AliasFS = void 0;
var _ProxiedFS = require("./ProxiedFS");
class AliasFS extends _ProxiedFS.ProxiedFS {
constructor(target, {
baseFs,
pathUtils
}) {
super(pathUtils);
this.target = void 0;
this.baseFs = void 0;
this.target = target;
this.baseFs = baseFs;
}
getRealPath() {
return this.target;
}
getBaseFs() {
return this.baseFs;
}
mapFromBase(p) {
return p;
}
mapToBase(p) {
return p;
}
Object.defineProperty(exports, "__esModule", { value: true });
const ProxiedFS_1 = require("./ProxiedFS");
class AliasFS extends ProxiedFS_1.ProxiedFS {
constructor(target, { baseFs, pathUtils }) {
super(pathUtils);
this.target = target;
this.baseFs = baseFs;
}
getRealPath() {
return this.target;
}
getBaseFs() {
return this.baseFs;
}
mapFromBase(p) {
return p;
}
mapToBase(p) {
return p;
}
}
exports.AliasFS = AliasFS;
exports.AliasFS = AliasFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CwdFS = void 0;
var _NodeFS = require("./NodeFS");
var _ProxiedFS = require("./ProxiedFS");
var _path = require("./path");
class CwdFS extends _ProxiedFS.ProxiedFS {
constructor(target, {
baseFs = new _NodeFS.NodeFS()
} = {}) {
super(_path.ppath);
this.target = void 0;
this.baseFs = void 0;
this.target = target;
this.baseFs = baseFs;
}
getRealPath() {
return this.pathUtils.resolve(this.baseFs.getRealPath(), this.target);
}
mapFromBase(path) {
return this.pathUtils.relative(this.getRealPath(), path);
}
mapToBase(path) {
return this.pathUtils.resolve(this.getRealPath(), path);
}
Object.defineProperty(exports, "__esModule", { value: true });
const NodeFS_1 = require("./NodeFS");
const ProxiedFS_1 = require("./ProxiedFS");
const path_1 = require("./path");
class CwdFS extends ProxiedFS_1.ProxiedFS {
constructor(target, { baseFs = new NodeFS_1.NodeFS() } = {}) {
super(path_1.ppath);
this.target = target;
this.baseFs = baseFs;
}
getRealPath() {
return this.pathUtils.resolve(this.baseFs.getRealPath(), this.target);
}
mapFromBase(path) {
return this.pathUtils.relative(this.getRealPath(), path);
}
mapToBase(path) {
return this.pathUtils.resolve(this.getRealPath(), path);
}
}
exports.CwdFS = CwdFS;
exports.CwdFS = CwdFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.EBUSY = EBUSY;
exports.ENOSYS = ENOSYS;
exports.EINVAL = EINVAL;
exports.EBADF = EBADF;
exports.ENOENT = ENOENT;
exports.ENOTDIR = ENOTDIR;
exports.EISDIR = EISDIR;
exports.EEXIST = EEXIST;
exports.EROFS = EROFS;
Object.defineProperty(exports, "__esModule", { value: true });
function makeError(code, message) {
return Object.assign(new Error(`${code}: ${message}`), {
code
});
return Object.assign(new Error(`${code}: ${message}`), { code });
}
function EBUSY(message) {
return makeError(`EBUSY`, message);
return makeError(`EBUSY`, message);
}
exports.EBUSY = EBUSY;
function ENOSYS(message, reason) {
return makeError(`ENOSYS`, `${message}, ${reason}`);
return makeError(`ENOSYS`, `${message}, ${reason}`);
}
exports.ENOSYS = ENOSYS;
function EINVAL(reason) {
return makeError(`EINVAL`, `invalid argument, ${reason}`);
return makeError(`EINVAL`, `invalid argument, ${reason}`);
}
exports.EINVAL = EINVAL;
function EBADF(reason) {
return makeError(`EBADF`, `bad file descriptor, ${reason}`);
return makeError(`EBADF`, `bad file descriptor, ${reason}`);
}
exports.EBADF = EBADF;
function ENOENT(reason) {
return makeError(`ENOENT`, `no such file or directory, ${reason}`);
return makeError(`ENOENT`, `no such file or directory, ${reason}`);
}
exports.ENOENT = ENOENT;
function ENOTDIR(reason) {
return makeError(`ENOTDIR`, `not a directory, ${reason}`);
return makeError(`ENOTDIR`, `not a directory, ${reason}`);
}
exports.ENOTDIR = ENOTDIR;
function EISDIR(reason) {
return makeError(`EISDIR`, `illegal operation on a directory, ${reason}`);
return makeError(`EISDIR`, `illegal operation on a directory, ${reason}`);
}
exports.EISDIR = EISDIR;
function EEXIST(reason) {
return makeError(`EEXIST`, `file already exists, ${reason}`);
return makeError(`EEXIST`, `file already exists, ${reason}`);
}
exports.EEXIST = EEXIST;
function EROFS(reason) {
return makeError(`EROFS`, `read-only filesystem, ${reason}`);
}
return makeError(`EROFS`, `read-only filesystem, ${reason}`);
}
exports.EROFS = EROFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.normalizeLineEndings = normalizeLineEndings;
exports.BasePortableFakeFS = exports.FakeFS = void 0;
var _os = require("os");
var _copyPromise = require("./algorithms/copyPromise");
var _path = require("./path");
Object.defineProperty(exports, "__esModule", { value: true });
const os_1 = require("os");
const copyPromise_1 = require("./algorithms/copyPromise");
const path_1 = require("./path");
const path_2 = require("./path");
class FakeFS {
constructor(pathUtils) {
this.pathUtils = void 0;
this.pathUtils = pathUtils;
}
async removePromise(p) {
let stat;
try {
stat = await this.lstatPromise(p);
} catch (error) {
if (error.code === `ENOENT`) {
return;
} else {
throw error;
}
constructor(pathUtils) {
this.pathUtils = pathUtils;
}
if (stat.isDirectory()) {
for (const entry of await this.readdirPromise(p)) await this.removePromise(this.pathUtils.resolve(p, entry)); // 5 gives 1s worth of retries at worst
for (let t = 0; t < 5; ++t) {
async removePromise(p) {
let stat;
try {
await this.rmdirPromise(p);
break;
} catch (error) {
if (error.code === `EBUSY` || error.code === `ENOTEMPTY`) {
await new Promise(resolve => setTimeout(resolve, t * 100));
continue;
} else {
throw error;
}
stat = await this.lstatPromise(p);
}
}
} else {
await this.unlinkPromise(p);
catch (error) {
if (error.code === `ENOENT`) {
return;
}
else {
throw error;
}
}
if (stat.isDirectory()) {
for (const entry of await this.readdirPromise(p))
await this.removePromise(this.pathUtils.resolve(p, entry));
// 5 gives 1s worth of retries at worst
for (let t = 0; t < 5; ++t) {
try {
await this.rmdirPromise(p);
break;
}
catch (error) {
if (error.code === `EBUSY` || error.code === `ENOTEMPTY`) {
await new Promise(resolve => setTimeout(resolve, t * 100));
continue;
}
else {
throw error;
}
}
}
}
else {
await this.unlinkPromise(p);
}
}
}
removeSync(p) {
let stat;
try {
stat = this.lstatSync(p);
} catch (error) {
if (error.code === `ENOENT`) {
return;
} else {
throw error;
}
removeSync(p) {
let stat;
try {
stat = this.lstatSync(p);
}
catch (error) {
if (error.code === `ENOENT`) {
return;
}
else {
throw error;
}
}
if (stat.isDirectory()) {
for (const entry of this.readdirSync(p))
this.removeSync(this.pathUtils.resolve(p, entry));
this.rmdirSync(p);
}
else {
this.unlinkSync(p);
}
}
if (stat.isDirectory()) {
for (const entry of this.readdirSync(p)) this.removeSync(this.pathUtils.resolve(p, entry));
this.rmdirSync(p);
} else {
this.unlinkSync(p);
async mkdirpPromise(p, { chmod, utimes } = {}) {
p = this.resolve(p);
if (p === this.pathUtils.dirname(p))
return;
const parts = p.split(this.pathUtils.sep);
for (let u = 2; u <= parts.length; ++u) {
const subPath = parts.slice(0, u).join(this.pathUtils.sep);
if (!this.existsSync(subPath)) {
try {
await this.mkdirPromise(subPath);
}
catch (error) {
if (error.code === `EEXIST`) {
continue;
}
else {
throw error;
}
}
if (chmod != null)
await this.chmodPromise(subPath, chmod);
if (utimes != null) {
await this.utimesPromise(subPath, utimes[0], utimes[1]);
}
else {
const parentStat = await this.statPromise(this.pathUtils.dirname(subPath));
await this.utimesPromise(subPath, parentStat.atime, parentStat.mtime);
}
}
}
}
}
async mkdirpPromise(p, {
chmod,
utimes
} = {}) {
p = this.resolve(p);
if (p === this.pathUtils.dirname(p)) return;
const parts = p.split(this.pathUtils.sep);
for (let u = 2; u <= parts.length; ++u) {
const subPath = parts.slice(0, u).join(this.pathUtils.sep);
if (!this.existsSync(subPath)) {
mkdirpSync(p, { chmod, utimes } = {}) {
p = this.resolve(p);
if (p === this.pathUtils.dirname(p))
return;
const parts = p.split(this.pathUtils.sep);
for (let u = 2; u <= parts.length; ++u) {
const subPath = parts.slice(0, u).join(this.pathUtils.sep);
if (!this.existsSync(subPath)) {
try {
this.mkdirSync(subPath);
}
catch (error) {
if (error.code === `EEXIST`) {
continue;
}
else {
throw error;
}
}
if (chmod != null)
this.chmodSync(subPath, chmod);
if (utimes != null) {
this.utimesSync(subPath, utimes[0], utimes[1]);
}
else {
const parentStat = this.statSync(this.pathUtils.dirname(subPath));
this.utimesSync(subPath, parentStat.atime, parentStat.mtime);
}
}
}
}
async copyPromise(destination, source, { baseFs = this, overwrite = true } = {}) {
return await copyPromise_1.copyPromise(this, destination, baseFs, source, { overwrite });
}
copySync(destination, source, { baseFs = this, overwrite = true } = {}) {
const stat = baseFs.lstatSync(source);
const exists = this.existsSync(destination);
if (stat.isDirectory()) {
this.mkdirpSync(destination);
const directoryListing = baseFs.readdirSync(source);
for (const entry of directoryListing) {
this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), { baseFs, overwrite });
}
}
else if (stat.isFile()) {
if (!exists || overwrite) {
if (exists)
this.removeSync(destination);
const content = baseFs.readFileSync(source);
this.writeFileSync(destination, content);
}
}
else if (stat.isSymbolicLink()) {
if (!exists || overwrite) {
if (exists)
this.removeSync(destination);
const target = baseFs.readlinkSync(source);
this.symlinkSync(path_2.convertPath(this.pathUtils, target), destination);
}
}
else {
throw new Error(`Unsupported file type (file: ${source}, mode: 0o${stat.mode.toString(8).padStart(6, `0`)})`);
}
const mode = stat.mode & 0o777;
this.chmodSync(destination, mode);
}
async changeFilePromise(p, content, { automaticNewlines } = {}) {
let current = '';
try {
await this.mkdirPromise(subPath);
} catch (error) {
if (error.code === `EEXIST`) {
continue;
} else {
throw error;
}
current = await this.readFilePromise(p, `utf8`);
}
if (chmod != null) await this.chmodPromise(subPath, chmod);
if (utimes != null) {
await this.utimesPromise(subPath, utimes[0], utimes[1]);
} else {
const parentStat = await this.statPromise(this.pathUtils.dirname(subPath));
await this.utimesPromise(subPath, parentStat.atime, parentStat.mtime);
catch (error) {
// ignore errors, no big deal
}
}
const normalizedContent = automaticNewlines
? normalizeLineEndings(current, content)
: content;
if (current === normalizedContent)
return;
await this.writeFilePromise(p, normalizedContent);
}
}
mkdirpSync(p, {
chmod,
utimes
} = {}) {
p = this.resolve(p);
if (p === this.pathUtils.dirname(p)) return;
const parts = p.split(this.pathUtils.sep);
for (let u = 2; u <= parts.length; ++u) {
const subPath = parts.slice(0, u).join(this.pathUtils.sep);
if (!this.existsSync(subPath)) {
changeFileSync(p, content, { automaticNewlines = false } = {}) {
let current = '';
try {
this.mkdirSync(subPath);
} catch (error) {
if (error.code === `EEXIST`) {
continue;
} else {
throw error;
}
current = this.readFileSync(p, `utf8`);
}
if (chmod != null) this.chmodSync(subPath, chmod);
if (utimes != null) {
this.utimesSync(subPath, utimes[0], utimes[1]);
} else {
const parentStat = this.statSync(this.pathUtils.dirname(subPath));
this.utimesSync(subPath, parentStat.atime, parentStat.mtime);
catch (error) {
// ignore errors, no big deal
}
}
const normalizedContent = automaticNewlines
? normalizeLineEndings(current, content)
: content;
if (current === normalizedContent)
return;
this.writeFileSync(p, normalizedContent);
}
}
async copyPromise(destination, source, {
baseFs = this,
overwrite = true
} = {}) {
return await (0, _copyPromise.copyPromise)(this, destination, baseFs, source, {
overwrite
});
}
copySync(destination, source, {
baseFs = this,
overwrite = true
} = {}) {
const stat = baseFs.lstatSync(source);
const exists = this.existsSync(destination);
if (stat.isDirectory()) {
this.mkdirpSync(destination);
const directoryListing = baseFs.readdirSync(source);
for (const entry of directoryListing) {
this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), {
baseFs,
overwrite
});
}
} else if (stat.isFile()) {
if (!exists || overwrite) {
if (exists) this.removeSync(destination);
const content = baseFs.readFileSync(source);
this.writeFileSync(destination, content);
}
} else if (stat.isSymbolicLink()) {
if (!exists || overwrite) {
if (exists) this.removeSync(destination);
const target = baseFs.readlinkSync(source);
this.symlinkSync((0, _path.convertPath)(this.pathUtils, target), destination);
}
} else {
throw new Error(`Unsupported file type (file: ${source}, mode: 0o${stat.mode.toString(8).padStart(6, `0`)})`);
async movePromise(fromP, toP) {
try {
await this.renamePromise(fromP, toP);
}
catch (error) {
if (error.code === `EXDEV`) {
await this.copyPromise(toP, fromP);
await this.removePromise(fromP);
}
else {
throw error;
}
}
}
const mode = stat.mode & 0o777;
this.chmodSync(destination, mode);
}
async changeFilePromise(p, content, {
automaticNewlines
} = {}) {
let current = '';
try {
current = await this.readFilePromise(p, `utf8`);
} catch (error) {// ignore errors, no big deal
moveSync(fromP, toP) {
try {
this.renameSync(fromP, toP);
}
catch (error) {
if (error.code === `EXDEV`) {
this.copySync(toP, fromP);
this.removeSync(fromP);
}
else {
throw error;
}
}
}
const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content;
if (current === normalizedContent) return;
await this.writeFilePromise(p, normalizedContent);
}
changeFileSync(p, content, {
automaticNewlines = false
} = {}) {
let current = '';
try {
current = this.readFileSync(p, `utf8`);
} catch (error) {// ignore errors, no big deal
}
const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content;
if (current === normalizedContent) return;
this.writeFileSync(p, normalizedContent);
}
async movePromise(fromP, toP) {
try {
await this.renamePromise(fromP, toP);
} catch (error) {
if (error.code === `EXDEV`) {
await this.copyPromise(toP, fromP);
await this.removePromise(fromP);
} else {
throw error;
}
}
}
moveSync(fromP, toP) {
try {
this.renameSync(fromP, toP);
} catch (error) {
if (error.code === `EXDEV`) {
this.copySync(toP, fromP);
this.removeSync(fromP);
} else {
throw error;
}
}
}
async lockPromise(affectedPath, callback) {
const lockPath = `${affectedPath}.flock`;
const interval = 1000 / 60;
const startTime = Date.now();
let fd = null; // Even when we detect that a lock file exists, we still look inside to see
// whether the pid that created it is still alive. It's not foolproof
// (there are false positive), but there are no false negative and that's
// all that matters in 99% of the cases.
const isAlive = async () => {
let pid;
try {
[pid] = await this.readJsonPromise(lockPath);
} catch (error) {
// If we can't read the file repeatedly, we assume the process was
// aborted before even writing finishing writing the payload.
return Date.now() - startTime < 500;
}
try {
// "As a special case, a signal of 0 can be used to test for the
// existence of a process" - so we check whether it's alive.
process.kill(pid, 0);
return true;
} catch (error) {
return false;
}
};
while (fd === null) {
try {
fd = await this.openPromise(lockPath, `wx`);
} catch (error) {
if (error.code === `EEXIST`) {
if (!(await isAlive())) {
async lockPromise(affectedPath, callback) {
const lockPath = `${affectedPath}.flock`;
const interval = 1000 / 60;
const startTime = Date.now();
let fd = null;
// Even when we detect that a lock file exists, we still look inside to see
// whether the pid that created it is still alive. It's not foolproof
// (there are false positive), but there are no false negative and that's
// all that matters in 99% of the cases.
const isAlive = async () => {
let pid;
try {
await this.unlinkPromise(lockPath);
continue;
} catch (error) {// No big deal if we can't remove it. Just fallback to wait for
// it to be eventually released by its owner.
([pid] = await this.readJsonPromise(lockPath));
}
}
if (Date.now() - startTime < 60 * 1000) {
await new Promise(resolve => setTimeout(resolve, interval));
} else {
throw new Error(`Couldn't acquire a lock in a reasonable time (via ${lockPath})`);
}
} else {
throw error;
catch (error) {
// If we can't read the file repeatedly, we assume the process was
// aborted before even writing finishing writing the payload.
return Date.now() - startTime < 500;
}
try {
// "As a special case, a signal of 0 can be used to test for the
// existence of a process" - so we check whether it's alive.
process.kill(pid, 0);
return true;
}
catch (error) {
return false;
}
};
while (fd === null) {
try {
fd = await this.openPromise(lockPath, `wx`);
}
catch (error) {
if (error.code === `EEXIST`) {
if (!await isAlive()) {
try {
await this.unlinkPromise(lockPath);
continue;
}
catch (error) {
// No big deal if we can't remove it. Just fallback to wait for
// it to be eventually released by its owner.
}
}
if (Date.now() - startTime < 60 * 1000) {
await new Promise(resolve => setTimeout(resolve, interval));
}
else {
throw new Error(`Couldn't acquire a lock in a reasonable time (via ${lockPath})`);
}
}
else {
throw error;
}
}
}
}
await this.writePromise(fd, JSON.stringify([process.pid]));
try {
return await callback();
}
finally {
await this.closePromise(fd);
await this.unlinkPromise(lockPath);
}
}
await this.writePromise(fd, JSON.stringify([process.pid]));
try {
return await callback();
} finally {
await this.closePromise(fd);
await this.unlinkPromise(lockPath);
async readJsonPromise(p) {
const content = await this.readFilePromise(p, `utf8`);
try {
return JSON.parse(content);
}
catch (error) {
error.message += ` (in ${p})`;
throw error;
}
}
}
async readJsonPromise(p) {
const content = await this.readFilePromise(p, `utf8`);
try {
return JSON.parse(content);
} catch (error) {
error.message += ` (in ${p})`;
throw error;
async readJsonSync(p) {
const content = this.readFileSync(p, `utf8`);
try {
return JSON.parse(content);
}
catch (error) {
error.message += ` (in ${p})`;
throw error;
}
}
}
async readJsonSync(p) {
const content = this.readFileSync(p, `utf8`);
try {
return JSON.parse(content);
} catch (error) {
error.message += ` (in ${p})`;
throw error;
async writeJsonPromise(p, data) {
return await this.writeFilePromise(p, `${JSON.stringify(data, null, 2)}\n`);
}
}
async writeJsonPromise(p, data) {
return await this.writeFilePromise(p, `${JSON.stringify(data, null, 2)}\n`);
}
writeJsonSync(p, data) {
return this.writeFileSync(p, `${JSON.stringify(data, null, 2)}\n`);
}
async preserveTimePromise(p, cb) {
const stat = await this.lstatPromise(p);
const result = await cb();
if (typeof result !== `undefined`) p = result;
if (this.lutimesPromise) {
await this.lutimesPromise(p, stat.atime, stat.mtime);
} else if (!stat.isSymbolicLink()) {
await this.utimesPromise(p, stat.atime, stat.mtime);
writeJsonSync(p, data) {
return this.writeFileSync(p, `${JSON.stringify(data, null, 2)}\n`);
}
}
async preserveTimeSync(p, cb) {
const stat = this.lstatSync(p);
const result = cb();
if (typeof result !== `undefined`) p = result;
if (this.lutimesSync) {
this.lutimesSync(p, stat.atime, stat.mtime);
} else if (!stat.isSymbolicLink()) {
this.utimesSync(p, stat.atime, stat.mtime);
async preserveTimePromise(p, cb) {
const stat = await this.lstatPromise(p);
const result = await cb();
if (typeof result !== `undefined`)
p = result;
if (this.lutimesPromise) {
await this.lutimesPromise(p, stat.atime, stat.mtime);
}
else if (!stat.isSymbolicLink()) {
await this.utimesPromise(p, stat.atime, stat.mtime);
}
}
}
async preserveTimeSync(p, cb) {
const stat = this.lstatSync(p);
const result = cb();
if (typeof result !== `undefined`)
p = result;
if (this.lutimesSync) {
this.lutimesSync(p, stat.atime, stat.mtime);
}
else if (!stat.isSymbolicLink()) {
this.utimesSync(p, stat.atime, stat.mtime);
}
}
}
exports.FakeFS = FakeFS;
FakeFS.DEFAULT_TIME = 315532800;
;
class BasePortableFakeFS extends FakeFS {
constructor() {
super(_path.ppath);
}
resolve(p) {
return this.pathUtils.resolve(_path.PortablePath.root, p);
}
constructor() {
super(path_2.ppath);
}
resolve(p) {
return this.pathUtils.resolve(path_1.PortablePath.root, p);
}
}
exports.BasePortableFakeFS = BasePortableFakeFS;
function getEndOfLine(content) {
const matches = content.match(/\r?\n/g);
if (matches === null) return _os.EOL;
const crlf = matches.filter(nl => nl === `\r\n`).length;
const lf = matches.length - crlf;
return crlf > lf ? `\r\n` : `\n`;
const matches = content.match(/\r?\n/g);
if (matches === null)
return os_1.EOL;
const crlf = matches.filter(nl => nl === `\r\n`).length;
const lf = matches.length - crlf;
return crlf > lf ? `\r\n` : `\n`;
}
function normalizeLineEndings(originalContent, newContent) {
return newContent.replace(/\r?\n/g, getEndOfLine(originalContent));
}
return newContent.replace(/\r?\n/g, getEndOfLine(originalContent));
}
exports.normalizeLineEndings = normalizeLineEndings;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.patchFs = patchFs;
exports.extendFs = extendFs;
Object.defineProperty(exports, "CreateReadStreamOptions", {
enumerable: true,
get: function () {
return _FakeFS.CreateReadStreamOptions;
}
});
Object.defineProperty(exports, "CreateWriteStreamOptions", {
enumerable: true,
get: function () {
return _FakeFS.CreateWriteStreamOptions;
}
});
Object.defineProperty(exports, "MkdirOptions", {
enumerable: true,
get: function () {
return _FakeFS.MkdirOptions;
}
});
Object.defineProperty(exports, "WatchOptions", {
enumerable: true,
get: function () {
return _FakeFS.WatchOptions;
}
});
Object.defineProperty(exports, "WatchCallback", {
enumerable: true,
get: function () {
return _FakeFS.WatchCallback;
}
});
Object.defineProperty(exports, "Watcher", {
enumerable: true,
get: function () {
return _FakeFS.Watcher;
}
});
Object.defineProperty(exports, "WriteFileOptions", {
enumerable: true,
get: function () {
return _FakeFS.WriteFileOptions;
}
});
Object.defineProperty(exports, "normalizeLineEndings", {
enumerable: true,
get: function () {
return _FakeFS.normalizeLineEndings;
}
});
Object.defineProperty(exports, "FakeFS", {
enumerable: true,
get: function () {
return _FakeFS.FakeFS;
}
});
Object.defineProperty(exports, "NodeFS", {
enumerable: true,
get: function () {
return _NodeFS.NodeFS;
}
});
Object.defineProperty(exports, "FSPath", {
enumerable: true,
get: function () {
return _path.FSPath;
}
});
Object.defineProperty(exports, "Path", {
enumerable: true,
get: function () {
return _path.Path;
}
});
Object.defineProperty(exports, "PortablePath", {
enumerable: true,
get: function () {
return _path.PortablePath;
}
});
Object.defineProperty(exports, "NativePath", {
enumerable: true,
get: function () {
return _path.NativePath;
}
});
Object.defineProperty(exports, "Filename", {
enumerable: true,
get: function () {
return _path.Filename;
}
});
Object.defineProperty(exports, "ParsedPath", {
enumerable: true,
get: function () {
return _path.ParsedPath;
}
});
Object.defineProperty(exports, "PathUtils", {
enumerable: true,
get: function () {
return _path.PathUtils;
}
});
Object.defineProperty(exports, "FormatInputPathObject", {
enumerable: true,
get: function () {
return _path.FormatInputPathObject;
}
});
Object.defineProperty(exports, "npath", {
enumerable: true,
get: function () {
return _path.npath;
}
});
Object.defineProperty(exports, "ppath", {
enumerable: true,
get: function () {
return _path.ppath;
}
});
Object.defineProperty(exports, "toFilename", {
enumerable: true,
get: function () {
return _path.toFilename;
}
});
Object.defineProperty(exports, "AliasFS", {
enumerable: true,
get: function () {
return _AliasFS.AliasFS;
}
});
Object.defineProperty(exports, "CwdFS", {
enumerable: true,
get: function () {
return _CwdFS.CwdFS;
}
});
Object.defineProperty(exports, "JailFS", {
enumerable: true,
get: function () {
return _JailFS.JailFS;
}
});
Object.defineProperty(exports, "LazyFS", {
enumerable: true,
get: function () {
return _LazyFS.LazyFS;
}
});
Object.defineProperty(exports, "NoFS", {
enumerable: true,
get: function () {
return _NoFS.NoFS;
}
});
Object.defineProperty(exports, "PosixFS", {
enumerable: true,
get: function () {
return _PosixFS.PosixFS;
}
});
Object.defineProperty(exports, "ProxiedFS", {
enumerable: true,
get: function () {
return _ProxiedFS.ProxiedFS;
}
});
Object.defineProperty(exports, "VirtualFS", {
enumerable: true,
get: function () {
return _VirtualFS.VirtualFS;
}
});
Object.defineProperty(exports, "ZipFS", {
enumerable: true,
get: function () {
return _ZipFS.ZipFS;
}
});
Object.defineProperty(exports, "ZipOpenFS", {
enumerable: true,
get: function () {
return _ZipOpenFS.ZipOpenFS;
}
});
exports.xfs = void 0;
var _FakeFS = require("./FakeFS");
var _NodeFS = require("./NodeFS");
var _path = require("./path");
var _AliasFS = require("./AliasFS");
var _CwdFS = require("./CwdFS");
var _JailFS = require("./JailFS");
var _LazyFS = require("./LazyFS");
var _NoFS = require("./NoFS");
var _PosixFS = require("./PosixFS");
var _ProxiedFS = require("./ProxiedFS");
var _VirtualFS = require("./VirtualFS");
var _ZipFS = require("./ZipFS");
var _ZipOpenFS = require("./ZipOpenFS");
Object.defineProperty(exports, "__esModule", { value: true });
const NodeFS_1 = require("./NodeFS");
const path_1 = require("./path");
var FakeFS_1 = require("./FakeFS");
exports.normalizeLineEndings = FakeFS_1.normalizeLineEndings;
var path_2 = require("./path");
exports.PortablePath = path_2.PortablePath;
var path_3 = require("./path");
exports.npath = path_3.npath;
exports.ppath = path_3.ppath;
exports.toFilename = path_3.toFilename;
var AliasFS_1 = require("./AliasFS");
exports.AliasFS = AliasFS_1.AliasFS;
var FakeFS_2 = require("./FakeFS");
exports.FakeFS = FakeFS_2.FakeFS;
var CwdFS_1 = require("./CwdFS");
exports.CwdFS = CwdFS_1.CwdFS;
var JailFS_1 = require("./JailFS");
exports.JailFS = JailFS_1.JailFS;
var LazyFS_1 = require("./LazyFS");
exports.LazyFS = LazyFS_1.LazyFS;
var NoFS_1 = require("./NoFS");
exports.NoFS = NoFS_1.NoFS;
var NodeFS_2 = require("./NodeFS");
exports.NodeFS = NodeFS_2.NodeFS;
var PosixFS_1 = require("./PosixFS");
exports.PosixFS = PosixFS_1.PosixFS;
var ProxiedFS_1 = require("./ProxiedFS");
exports.ProxiedFS = ProxiedFS_1.ProxiedFS;
var VirtualFS_1 = require("./VirtualFS");
exports.VirtualFS = VirtualFS_1.VirtualFS;
var ZipFS_1 = require("./ZipFS");
exports.ZipFS = ZipFS_1.ZipFS;
var ZipOpenFS_1 = require("./ZipOpenFS");
exports.ZipOpenFS = ZipOpenFS_1.ZipOpenFS;
function patchFs(patchedFs, fakeFs) {
const SYNC_IMPLEMENTATIONS = new Set([`accessSync`, `appendFileSync`, `createReadStream`, `chmodSync`, `closeSync`, `copyFileSync`, `lstatSync`, `mkdirSync`, `openSync`, `readSync`, `readlinkSync`, `readFileSync`, `readdirSync`, `readlinkSync`, `realpathSync`, `renameSync`, `rmdirSync`, `statSync`, `symlinkSync`, `unlinkSync`, `utimesSync`, `watch`, `writeFileSync`, `writeSync`]);
const ASYNC_IMPLEMENTATIONS = new Set([`accessPromise`, `appendFilePromise`, `chmodPromise`, `closePromise`, `copyFilePromise`, `lstatPromise`, `mkdirPromise`, `openPromise`, `readdirPromise`, `realpathPromise`, `readFilePromise`, `readdirPromise`, `readlinkPromise`, `renamePromise`, `rmdirPromise`, `statPromise`, `symlinkPromise`, `unlinkPromise`, `utimesPromise`, `writeFilePromise`, `writeSync`]);
patchedFs.existsSync = p => {
try {
return fakeFs.existsSync(p);
} catch (error) {
return false;
}
};
patchedFs.exists = (p, ...args) => {
const hasCallback = typeof args[args.length - 1] === `function`;
const callback = hasCallback ? args.pop() : () => {};
process.nextTick(() => {
fakeFs.existsPromise(p).then(exists => {
callback(exists);
}, () => {
callback(false);
});
});
};
patchedFs.read = (p, buffer, ...args) => {
const hasCallback = typeof args[args.length - 1] === `function`;
const callback = hasCallback ? args.pop() : () => {};
process.nextTick(() => {
fakeFs.readPromise(p, buffer, ...args).then(bytesRead => {
callback(null, bytesRead, buffer);
}, error => {
callback(error);
});
});
};
for (const fnName of ASYNC_IMPLEMENTATIONS) {
const fakeImpl = fakeFs[fnName].bind(fakeFs);
const origName = fnName.replace(/Promise$/, ``);
patchedFs[origName] = (...args) => {
const hasCallback = typeof args[args.length - 1] === `function`;
const callback = hasCallback ? args.pop() : () => {};
process.nextTick(() => {
fakeImpl(...args).then(result => {
callback(null, result);
}, error => {
callback(error);
const SYNC_IMPLEMENTATIONS = new Set([
`accessSync`,
`appendFileSync`,
`createReadStream`,
`chmodSync`,
`closeSync`,
`copyFileSync`,
`lstatSync`,
`mkdirSync`,
`openSync`,
`readSync`,
`readlinkSync`,
`readFileSync`,
`readdirSync`,
`readlinkSync`,
`realpathSync`,
`renameSync`,
`rmdirSync`,
`statSync`,
`symlinkSync`,
`unlinkSync`,
`utimesSync`,
`watch`,
`writeFileSync`,
`writeSync`,
]);
const ASYNC_IMPLEMENTATIONS = new Set([
`accessPromise`,
`appendFilePromise`,
`chmodPromise`,
`closePromise`,
`copyFilePromise`,
`lstatPromise`,
`mkdirPromise`,
`openPromise`,
`readdirPromise`,
`realpathPromise`,
`readFilePromise`,
`readdirPromise`,
`readlinkPromise`,
`renamePromise`,
`rmdirPromise`,
`statPromise`,
`symlinkPromise`,
`unlinkPromise`,
`utimesPromise`,
`writeFilePromise`,
`writeSync`,
]);
patchedFs.existsSync = (p) => {
try {
return fakeFs.existsSync(p);
}
catch (error) {
return false;
}
};
patchedFs.exists = (p, ...args) => {
const hasCallback = typeof args[args.length - 1] === `function`;
const callback = hasCallback ? args.pop() : () => { };
process.nextTick(() => {
fakeFs.existsPromise(p).then(exists => {
callback(exists);
}, () => {
callback(false);
});
});
});
};
}
for (const fnName of SYNC_IMPLEMENTATIONS) {
const fakeImpl = fakeFs[fnName].bind(fakeFs);
const origName = fnName;
patchedFs[origName] = fakeImpl;
}
patchedFs.realpathSync.native = patchedFs.realpathSync;
patchedFs.realpath.native = patchedFs.realpath;
patchedFs.read = (p, buffer, ...args) => {
const hasCallback = typeof args[args.length - 1] === `function`;
const callback = hasCallback ? args.pop() : () => { };
process.nextTick(() => {
fakeFs.readPromise(p, buffer, ...args).then(bytesRead => {
callback(null, bytesRead, buffer);
}, error => {
callback(error);
});
});
};
for (const fnName of ASYNC_IMPLEMENTATIONS) {
const fakeImpl = fakeFs[fnName].bind(fakeFs);
const origName = fnName.replace(/Promise$/, ``);
patchedFs[origName] = (...args) => {
const hasCallback = typeof args[args.length - 1] === `function`;
const callback = hasCallback ? args.pop() : () => { };
process.nextTick(() => {
fakeImpl(...args).then((result) => {
callback(null, result);
}, (error) => {
callback(error);
});
});
};
}
for (const fnName of SYNC_IMPLEMENTATIONS) {
const fakeImpl = fakeFs[fnName].bind(fakeFs);
const origName = fnName;
patchedFs[origName] = fakeImpl;
}
patchedFs.realpathSync.native = patchedFs.realpathSync;
patchedFs.realpath.native = patchedFs.realpath;
}
exports.patchFs = patchFs;
function extendFs(realFs, fakeFs) {
const patchedFs = Object.create(realFs);
patchFs(patchedFs, fakeFs);
return patchedFs;
const patchedFs = Object.create(realFs);
patchFs(patchedFs, fakeFs);
return patchedFs;
}
const xfs = Object.assign(new _NodeFS.NodeFS(), {
mktempSync(cb) {
// We lazily load `tmp` because it injects itself into the `process`
// events (to clean the folders at exit time), and it may lead to
// large memory leaks. Better avoid loading it until we can't do
// otherwise (ideally the fix would be for `tmp` itself to only
// attach cleaners after the first call).
const tmp = require(`tmp`);
const {
name,
removeCallback
} = tmp.dirSync({
unsafeCleanup: true
});
if (typeof cb === `undefined`) {
return _path.npath.toPortablePath(name);
} else {
try {
return cb(_path.npath.toPortablePath(name));
} finally {
removeCallback();
}
}
},
mktempPromise(cb) {
// We lazily load `tmp` because it injects itself into the `process`
// events (to clean the folders at exit time), and it may lead to
// large memory leaks. Better avoid loading it until we can't do
// otherwise (ideally the fix would be for `tmp` itself to only
// attach cleaners after the first call).
const tmp = require(`tmp`);
if (typeof cb === `undefined`) {
return new Promise((resolve, reject) => {
tmp.dir({
unsafeCleanup: true
}, (err, path) => {
if (err) {
reject(err);
} else {
resolve(_path.npath.toPortablePath(path));
}
});
});
} else {
return new Promise((resolve, reject) => {
tmp.dir({
unsafeCleanup: true
}, (err, path, cleanup) => {
if (err) {
reject(err);
} else {
Promise.resolve(_path.npath.toPortablePath(path)).then(cb).then(result => {
cleanup();
resolve(result);
}, error => {
cleanup();
reject(error);
exports.extendFs = extendFs;
exports.xfs = Object.assign(new NodeFS_1.NodeFS(), {
mktempSync(cb) {
// We lazily load `tmp` because it injects itself into the `process`
// events (to clean the folders at exit time), and it may lead to
// large memory leaks. Better avoid loading it until we can't do
// otherwise (ideally the fix would be for `tmp` itself to only
// attach cleaners after the first call).
const tmp = require(`tmp`);
const { name, removeCallback } = tmp.dirSync({ unsafeCleanup: true });
if (typeof cb === `undefined`) {
return path_1.npath.toPortablePath(name);
}
else {
try {
return cb(path_1.npath.toPortablePath(name));
}
finally {
removeCallback();
}
}
},
mktempPromise(cb) {
// We lazily load `tmp` because it injects itself into the `process`
// events (to clean the folders at exit time), and it may lead to
// large memory leaks. Better avoid loading it until we can't do
// otherwise (ideally the fix would be for `tmp` itself to only
// attach cleaners after the first call).
const tmp = require(`tmp`);
if (typeof cb === `undefined`) {
return new Promise((resolve, reject) => {
tmp.dir({ unsafeCleanup: true }, (err, path) => {
if (err) {
reject(err);
}
else {
resolve(path_1.npath.toPortablePath(path));
}
});
});
}
});
});
}
}
}
else {
return new Promise((resolve, reject) => {
tmp.dir({ unsafeCleanup: true }, (err, path, cleanup) => {
if (err) {
reject(err);
}
else {
Promise.resolve(path_1.npath.toPortablePath(path)).then(cb).then(result => {
cleanup();
resolve(result);
}, error => {
cleanup();
reject(error);
});
}
});
});
}
},
});
exports.xfs = xfs;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.JailFS = void 0;
var _NodeFS = require("./NodeFS");
var _ProxiedFS = require("./ProxiedFS");
var _path = require("./path");
const JAIL_ROOT = _path.PortablePath.root;
class JailFS extends _ProxiedFS.ProxiedFS {
constructor(target, {
baseFs = new _NodeFS.NodeFS()
} = {}) {
super(_path.ppath);
this.target = void 0;
this.baseFs = void 0;
this.target = this.pathUtils.resolve(_path.PortablePath.root, target);
this.baseFs = baseFs;
}
getRealPath() {
return this.pathUtils.resolve(this.baseFs.getRealPath(), this.pathUtils.relative(_path.PortablePath.root, this.target));
}
getTarget() {
return this.target;
}
getBaseFs() {
return this.baseFs;
}
mapToBase(p) {
const normalized = this.pathUtils.normalize(p);
if (this.pathUtils.isAbsolute(p)) return this.pathUtils.resolve(this.target, this.pathUtils.relative(JAIL_ROOT, p));
if (normalized.match(/^\.\.\//)) throw new Error(`Resolving this path (${p}) would escape the jail`);
return this.pathUtils.resolve(this.target, p);
}
mapFromBase(p) {
return this.pathUtils.resolve(JAIL_ROOT, this.pathUtils.relative(this.target, p));
}
Object.defineProperty(exports, "__esModule", { value: true });
const NodeFS_1 = require("./NodeFS");
const ProxiedFS_1 = require("./ProxiedFS");
const path_1 = require("./path");
const JAIL_ROOT = path_1.PortablePath.root;
class JailFS extends ProxiedFS_1.ProxiedFS {
constructor(target, { baseFs = new NodeFS_1.NodeFS() } = {}) {
super(path_1.ppath);
this.target = this.pathUtils.resolve(path_1.PortablePath.root, target);
this.baseFs = baseFs;
}
getRealPath() {
return this.pathUtils.resolve(this.baseFs.getRealPath(), this.pathUtils.relative(path_1.PortablePath.root, this.target));
}
getTarget() {
return this.target;
}
getBaseFs() {
return this.baseFs;
}
mapToBase(p) {
const normalized = this.pathUtils.normalize(p);
if (this.pathUtils.isAbsolute(p))
return this.pathUtils.resolve(this.target, this.pathUtils.relative(JAIL_ROOT, p));
if (normalized.match(/^\.\.\//))
throw new Error(`Resolving this path (${p}) would escape the jail`);
return this.pathUtils.resolve(this.target, p);
}
mapFromBase(p) {
return this.pathUtils.resolve(JAIL_ROOT, this.pathUtils.relative(this.target, p));
}
}
exports.JailFS = JailFS;
exports.JailFS = JailFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.LazyFS = void 0;
var _ProxiedFS = require("./ProxiedFS");
class LazyFS extends _ProxiedFS.ProxiedFS {
constructor(factory, pathUtils) {
super(pathUtils);
this.factory = void 0;
this.instance = null;
this.factory = factory;
}
get baseFs() {
if (!this.instance) this.instance = this.factory();
return this.instance;
}
set baseFs(value) {
this.instance = value;
}
mapFromBase(p) {
return p;
}
mapToBase(p) {
return p;
}
Object.defineProperty(exports, "__esModule", { value: true });
const ProxiedFS_1 = require("./ProxiedFS");
class LazyFS extends ProxiedFS_1.ProxiedFS {
constructor(factory, pathUtils) {
super(pathUtils);
this.instance = null;
this.factory = factory;
}
get baseFs() {
if (!this.instance)
this.instance = this.factory();
return this.instance;
}
set baseFs(value) {
this.instance = value;
}
mapFromBase(p) {
return p;
}
mapToBase(p) {
return p;
}
}
exports.LazyFS = LazyFS;
exports.LazyFS = LazyFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.NodeFS = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _FakeFS = require("./FakeFS");
var _path = require("./path");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class NodeFS extends _FakeFS.BasePortableFakeFS {
constructor(realFs = _fs.default) {
super();
this.realFs = void 0;
this.realFs = realFs;
}
getRealPath() {
return _path.PortablePath.root;
}
async openPromise(p, flags, mode) {
return await new Promise((resolve, reject) => {
this.realFs.open(_path.npath.fromPortablePath(p), flags, mode, this.makeCallback(resolve, reject));
});
}
openSync(p, flags, mode) {
return this.realFs.openSync(_path.npath.fromPortablePath(p), flags, mode);
}
async readPromise(fd, buffer, offset = 0, length = 0, position = -1) {
return await new Promise((resolve, reject) => {
this.realFs.read(fd, buffer, offset, length, position, (error, bytesRead) => {
if (error) {
reject(error);
} else {
resolve(bytesRead);
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const FakeFS_1 = require("./FakeFS");
const path_1 = require("./path");
class NodeFS extends FakeFS_1.BasePortableFakeFS {
constructor(realFs = fs_1.default) {
super();
this.realFs = realFs;
}
getRealPath() {
return path_1.PortablePath.root;
}
async openPromise(p, flags, mode) {
return await new Promise((resolve, reject) => {
this.realFs.open(path_1.npath.fromPortablePath(p), flags, mode, this.makeCallback(resolve, reject));
});
}
openSync(p, flags, mode) {
return this.realFs.openSync(path_1.npath.fromPortablePath(p), flags, mode);
}
async readPromise(fd, buffer, offset = 0, length = 0, position = -1) {
return await new Promise((resolve, reject) => {
this.realFs.read(fd, buffer, offset, length, position, (error, bytesRead) => {
if (error) {
reject(error);
}
else {
resolve(bytesRead);
}
});
});
}
readSync(fd, buffer, offset, length, position) {
return this.realFs.readSync(fd, buffer, offset, length, position);
}
async writePromise(fd, buffer, offset, length, position) {
return await new Promise((resolve, reject) => {
if (typeof buffer === `string`) {
return this.realFs.write(fd, buffer, offset, this.makeCallback(resolve, reject));
}
else {
return this.realFs.write(fd, buffer, offset, length, position, this.makeCallback(resolve, reject));
}
});
}
writeSync(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return this.realFs.writeSync(fd, buffer, offset);
}
});
});
}
readSync(fd, buffer, offset, length, position) {
return this.realFs.readSync(fd, buffer, offset, length, position);
}
async writePromise(fd, buffer, offset, length, position) {
return await new Promise((resolve, reject) => {
if (typeof buffer === `string`) {
return this.realFs.write(fd, buffer, offset, this.makeCallback(resolve, reject));
} else {
return this.realFs.write(fd, buffer, offset, length, position, this.makeCallback(resolve, reject));
}
});
}
writeSync(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return this.realFs.writeSync(fd, buffer, offset);
} else {
return this.realFs.writeSync(fd, buffer, offset, length, position);
else {
return this.realFs.writeSync(fd, buffer, offset, length, position);
}
}
}
async closePromise(fd) {
await new Promise((resolve, reject) => {
this.realFs.close(fd, this.makeCallback(resolve, reject));
});
}
closeSync(fd) {
this.realFs.closeSync(fd);
}
createReadStream(p, opts) {
const realPath = p !== null ? _path.npath.fromPortablePath(p) : p;
return this.realFs.createReadStream(realPath, opts);
}
createWriteStream(p, opts) {
const realPath = p !== null ? _path.npath.fromPortablePath(p) : p;
return this.realFs.createWriteStream(realPath, opts);
}
async realpathPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.realpath(_path.npath.fromPortablePath(p), {}, this.makeCallback(resolve, reject));
}).then(path => {
return _path.npath.toPortablePath(path);
});
}
realpathSync(p) {
return _path.npath.toPortablePath(this.realFs.realpathSync(_path.npath.fromPortablePath(p), {}));
}
async existsPromise(p) {
return await new Promise(resolve => {
this.realFs.exists(_path.npath.fromPortablePath(p), resolve);
});
}
accessSync(p, mode) {
return this.realFs.accessSync(_path.npath.fromPortablePath(p), mode);
}
async accessPromise(p, mode) {
return await new Promise((resolve, reject) => {
this.realFs.access(_path.npath.fromPortablePath(p), mode, this.makeCallback(resolve, reject));
});
}
existsSync(p) {
return this.realFs.existsSync(_path.npath.fromPortablePath(p));
}
async statPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.stat(_path.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
});
}
statSync(p) {
return this.realFs.statSync(_path.npath.fromPortablePath(p));
}
async lstatPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.lstat(_path.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
});
}
lstatSync(p) {
return this.realFs.lstatSync(_path.npath.fromPortablePath(p));
}
async chmodPromise(p, mask) {
return await new Promise((resolve, reject) => {
this.realFs.chmod(_path.npath.fromPortablePath(p), mask, this.makeCallback(resolve, reject));
});
}
chmodSync(p, mask) {
return this.realFs.chmodSync(_path.npath.fromPortablePath(p), mask);
}
async renamePromise(oldP, newP) {
return await new Promise((resolve, reject) => {
this.realFs.rename(_path.npath.fromPortablePath(oldP), _path.npath.fromPortablePath(newP), this.makeCallback(resolve, reject));
});
}
renameSync(oldP, newP) {
return this.realFs.renameSync(_path.npath.fromPortablePath(oldP), _path.npath.fromPortablePath(newP));
}
async copyFilePromise(sourceP, destP, flags = 0) {
return await new Promise((resolve, reject) => {
this.realFs.copyFile(_path.npath.fromPortablePath(sourceP), _path.npath.fromPortablePath(destP), flags, this.makeCallback(resolve, reject));
});
}
copyFileSync(sourceP, destP, flags = 0) {
return this.realFs.copyFileSync(_path.npath.fromPortablePath(sourceP), _path.npath.fromPortablePath(destP), flags);
}
async appendFilePromise(p, content, opts) {
return await new Promise((resolve, reject) => {
const fsNativePath = typeof p === `string` ? _path.npath.fromPortablePath(p) : p;
if (opts) {
this.realFs.appendFile(fsNativePath, content, opts, this.makeCallback(resolve, reject));
} else {
this.realFs.appendFile(fsNativePath, content, this.makeCallback(resolve, reject));
}
});
}
appendFileSync(p, content, opts) {
const fsNativePath = typeof p === `string` ? _path.npath.fromPortablePath(p) : p;
if (opts) {
this.realFs.appendFileSync(fsNativePath, content, opts);
} else {
this.realFs.appendFileSync(fsNativePath, content);
async closePromise(fd) {
await new Promise((resolve, reject) => {
this.realFs.close(fd, this.makeCallback(resolve, reject));
});
}
}
async writeFilePromise(p, content, opts) {
return await new Promise((resolve, reject) => {
const fsNativePath = typeof p === `string` ? _path.npath.fromPortablePath(p) : p;
if (opts) {
this.realFs.writeFile(fsNativePath, content, opts, this.makeCallback(resolve, reject));
} else {
this.realFs.writeFile(fsNativePath, content, this.makeCallback(resolve, reject));
}
});
}
writeFileSync(p, content, opts) {
const fsNativePath = typeof p === `string` ? _path.npath.fromPortablePath(p) : p;
if (opts) {
this.realFs.writeFileSync(fsNativePath, content, opts);
} else {
this.realFs.writeFileSync(fsNativePath, content);
closeSync(fd) {
this.realFs.closeSync(fd);
}
}
async unlinkPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.unlink(_path.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
});
}
unlinkSync(p) {
return this.realFs.unlinkSync(_path.npath.fromPortablePath(p));
}
async utimesPromise(p, atime, mtime) {
return await new Promise((resolve, reject) => {
this.realFs.utimes(_path.npath.fromPortablePath(p), atime, mtime, this.makeCallback(resolve, reject));
});
}
utimesSync(p, atime, mtime) {
this.realFs.utimesSync(_path.npath.fromPortablePath(p), atime, mtime);
}
async mkdirPromise(p, opts) {
return await new Promise((resolve, reject) => {
this.realFs.mkdir(_path.npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject));
});
}
mkdirSync(p, opts) {
return this.realFs.mkdirSync(_path.npath.fromPortablePath(p), opts);
}
async rmdirPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.rmdir(_path.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
});
}
rmdirSync(p) {
return this.realFs.rmdirSync(_path.npath.fromPortablePath(p));
}
async symlinkPromise(target, p) {
const type = target.endsWith(`/`) ? `dir` : `file`;
return await new Promise((resolve, reject) => {
this.realFs.symlink(_path.npath.fromPortablePath(target.replace(/\/+$/, ``)), _path.npath.fromPortablePath(p), type, this.makeCallback(resolve, reject));
});
}
symlinkSync(target, p) {
const type = target.endsWith(`/`) ? `dir` : `file`;
return this.realFs.symlinkSync(_path.npath.fromPortablePath(target.replace(/\/+$/, ``)), _path.npath.fromPortablePath(p), type);
}
async readFilePromise(p, encoding) {
return await new Promise((resolve, reject) => {
const fsNativePath = typeof p === `string` ? _path.npath.fromPortablePath(p) : p;
this.realFs.readFile(fsNativePath, encoding, this.makeCallback(resolve, reject));
});
}
readFileSync(p, encoding) {
const fsNativePath = typeof p === `string` ? _path.npath.fromPortablePath(p) : p;
return this.realFs.readFileSync(fsNativePath, encoding);
}
async readdirPromise(p, {
withFileTypes
} = {}) {
return await new Promise((resolve, reject) => {
if (withFileTypes) {
this.realFs.readdir(_path.npath.fromPortablePath(p), {
withFileTypes: true
}, this.makeCallback(resolve, reject));
} else {
this.realFs.readdir(_path.npath.fromPortablePath(p), this.makeCallback(value => resolve(value), reject));
}
});
}
readdirSync(p, {
withFileTypes
} = {}) {
if (withFileTypes) {
return this.realFs.readdirSync(_path.npath.fromPortablePath(p), {
withFileTypes: true
});
} else {
return this.realFs.readdirSync(_path.npath.fromPortablePath(p));
createReadStream(p, opts) {
const realPath = (p !== null ? path_1.npath.fromPortablePath(p) : p);
return this.realFs.createReadStream(realPath, opts);
}
}
async readlinkPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.readlink(_path.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
}).then(path => {
return _path.npath.toPortablePath(path);
});
}
readlinkSync(p) {
return _path.npath.toPortablePath(this.realFs.readlinkSync(_path.npath.fromPortablePath(p)));
}
watch(p, a, b) {
return this.realFs.watch(_path.npath.fromPortablePath(p), // @ts-ignore
a, b);
}
makeCallback(resolve, reject) {
return (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
};
}
createWriteStream(p, opts) {
const realPath = (p !== null ? path_1.npath.fromPortablePath(p) : p);
return this.realFs.createWriteStream(realPath, opts);
}
async realpathPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.realpath(path_1.npath.fromPortablePath(p), {}, this.makeCallback(resolve, reject));
}).then(path => {
return path_1.npath.toPortablePath(path);
});
}
realpathSync(p) {
return path_1.npath.toPortablePath(this.realFs.realpathSync(path_1.npath.fromPortablePath(p), {}));
}
async existsPromise(p) {
return await new Promise(resolve => {
this.realFs.exists(path_1.npath.fromPortablePath(p), resolve);
});
}
accessSync(p, mode) {
return this.realFs.accessSync(path_1.npath.fromPortablePath(p), mode);
}
async accessPromise(p, mode) {
return await new Promise((resolve, reject) => {
this.realFs.access(path_1.npath.fromPortablePath(p), mode, this.makeCallback(resolve, reject));
});
}
existsSync(p) {
return this.realFs.existsSync(path_1.npath.fromPortablePath(p));
}
async statPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.stat(path_1.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
});
}
statSync(p) {
return this.realFs.statSync(path_1.npath.fromPortablePath(p));
}
async lstatPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.lstat(path_1.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
});
}
lstatSync(p) {
return this.realFs.lstatSync(path_1.npath.fromPortablePath(p));
}
async chmodPromise(p, mask) {
return await new Promise((resolve, reject) => {
this.realFs.chmod(path_1.npath.fromPortablePath(p), mask, this.makeCallback(resolve, reject));
});
}
chmodSync(p, mask) {
return this.realFs.chmodSync(path_1.npath.fromPortablePath(p), mask);
}
async renamePromise(oldP, newP) {
return await new Promise((resolve, reject) => {
this.realFs.rename(path_1.npath.fromPortablePath(oldP), path_1.npath.fromPortablePath(newP), this.makeCallback(resolve, reject));
});
}
renameSync(oldP, newP) {
return this.realFs.renameSync(path_1.npath.fromPortablePath(oldP), path_1.npath.fromPortablePath(newP));
}
async copyFilePromise(sourceP, destP, flags = 0) {
return await new Promise((resolve, reject) => {
this.realFs.copyFile(path_1.npath.fromPortablePath(sourceP), path_1.npath.fromPortablePath(destP), flags, this.makeCallback(resolve, reject));
});
}
copyFileSync(sourceP, destP, flags = 0) {
return this.realFs.copyFileSync(path_1.npath.fromPortablePath(sourceP), path_1.npath.fromPortablePath(destP), flags);
}
async appendFilePromise(p, content, opts) {
return await new Promise((resolve, reject) => {
const fsNativePath = typeof p === `string` ? path_1.npath.fromPortablePath(p) : p;
if (opts) {
this.realFs.appendFile(fsNativePath, content, opts, this.makeCallback(resolve, reject));
}
else {
this.realFs.appendFile(fsNativePath, content, this.makeCallback(resolve, reject));
}
});
}
appendFileSync(p, content, opts) {
const fsNativePath = typeof p === `string` ? path_1.npath.fromPortablePath(p) : p;
if (opts) {
this.realFs.appendFileSync(fsNativePath, content, opts);
}
else {
this.realFs.appendFileSync(fsNativePath, content);
}
}
async writeFilePromise(p, content, opts) {
return await new Promise((resolve, reject) => {
const fsNativePath = typeof p === `string` ? path_1.npath.fromPortablePath(p) : p;
if (opts) {
this.realFs.writeFile(fsNativePath, content, opts, this.makeCallback(resolve, reject));
}
else {
this.realFs.writeFile(fsNativePath, content, this.makeCallback(resolve, reject));
}
});
}
writeFileSync(p, content, opts) {
const fsNativePath = typeof p === `string` ? path_1.npath.fromPortablePath(p) : p;
if (opts) {
this.realFs.writeFileSync(fsNativePath, content, opts);
}
else {
this.realFs.writeFileSync(fsNativePath, content);
}
}
async unlinkPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.unlink(path_1.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
});
}
unlinkSync(p) {
return this.realFs.unlinkSync(path_1.npath.fromPortablePath(p));
}
async utimesPromise(p, atime, mtime) {
return await new Promise((resolve, reject) => {
this.realFs.utimes(path_1.npath.fromPortablePath(p), atime, mtime, this.makeCallback(resolve, reject));
});
}
utimesSync(p, atime, mtime) {
this.realFs.utimesSync(path_1.npath.fromPortablePath(p), atime, mtime);
}
async mkdirPromise(p, opts) {
return await new Promise((resolve, reject) => {
this.realFs.mkdir(path_1.npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject));
});
}
mkdirSync(p, opts) {
return this.realFs.mkdirSync(path_1.npath.fromPortablePath(p), opts);
}
async rmdirPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.rmdir(path_1.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
});
}
rmdirSync(p) {
return this.realFs.rmdirSync(path_1.npath.fromPortablePath(p));
}
async symlinkPromise(target, p) {
const type = target.endsWith(`/`) ? `dir` : `file`;
return await new Promise((resolve, reject) => {
this.realFs.symlink(path_1.npath.fromPortablePath(target.replace(/\/+$/, ``)), path_1.npath.fromPortablePath(p), type, this.makeCallback(resolve, reject));
});
}
symlinkSync(target, p) {
const type = target.endsWith(`/`) ? `dir` : `file`;
return this.realFs.symlinkSync(path_1.npath.fromPortablePath(target.replace(/\/+$/, ``)), path_1.npath.fromPortablePath(p), type);
}
async readFilePromise(p, encoding) {
return await new Promise((resolve, reject) => {
const fsNativePath = typeof p === `string` ? path_1.npath.fromPortablePath(p) : p;
this.realFs.readFile(fsNativePath, encoding, this.makeCallback(resolve, reject));
});
}
readFileSync(p, encoding) {
const fsNativePath = typeof p === `string` ? path_1.npath.fromPortablePath(p) : p;
return this.realFs.readFileSync(fsNativePath, encoding);
}
async readdirPromise(p, { withFileTypes } = {}) {
return await new Promise((resolve, reject) => {
if (withFileTypes) {
this.realFs.readdir(path_1.npath.fromPortablePath(p), { withFileTypes: true }, this.makeCallback(resolve, reject));
}
else {
this.realFs.readdir(path_1.npath.fromPortablePath(p), this.makeCallback(value => resolve(value), reject));
}
});
}
readdirSync(p, { withFileTypes } = {}) {
if (withFileTypes) {
return this.realFs.readdirSync(path_1.npath.fromPortablePath(p), { withFileTypes: true });
}
else {
return this.realFs.readdirSync(path_1.npath.fromPortablePath(p));
}
}
async readlinkPromise(p) {
return await new Promise((resolve, reject) => {
this.realFs.readlink(path_1.npath.fromPortablePath(p), this.makeCallback(resolve, reject));
}).then(path => {
return path_1.npath.toPortablePath(path);
});
}
readlinkSync(p) {
return path_1.npath.toPortablePath(this.realFs.readlinkSync(path_1.npath.fromPortablePath(p)));
}
watch(p, a, b) {
return this.realFs.watch(path_1.npath.fromPortablePath(p),
// @ts-ignore
a, b);
}
makeCallback(resolve, reject) {
return (err, result) => {
if (err) {
reject(err);
}
else {
resolve(result);
}
};
}
}
exports.NodeFS = NodeFS;
exports.NodeFS = NodeFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.NoFS = void 0;
var _FakeFS = require("./FakeFS");
var _path = require("./path");
const makeError = () => Object.assign(new Error(`ENOSYS: unsupported filesystem access`), {
code: `ENOSYS`
});
class NoFS extends _FakeFS.FakeFS {
constructor() {
super(_path.ppath);
}
getRealPath() {
throw makeError();
}
resolve() {
throw makeError();
}
async openPromise() {
throw makeError();
}
openSync() {
throw makeError();
}
async readPromise() {
throw makeError();
}
readSync() {
throw makeError();
}
async writePromise() {
throw makeError();
}
writeSync() {
throw makeError();
}
async closePromise() {
throw makeError();
}
closeSync() {
throw makeError();
}
createWriteStream() {
throw makeError();
}
createReadStream() {
throw makeError();
}
async realpathPromise() {
throw makeError();
}
realpathSync() {
throw makeError();
}
async readdirPromise() {
throw makeError();
}
readdirSync() {
throw makeError();
}
async existsPromise(p) {
throw makeError();
}
existsSync(p) {
throw makeError();
}
async accessPromise() {
throw makeError();
}
accessSync() {
throw makeError();
}
async statPromise() {
throw makeError();
}
statSync() {
throw makeError();
}
async lstatPromise(p) {
throw makeError();
}
lstatSync(p) {
throw makeError();
}
async chmodPromise() {
throw makeError();
}
chmodSync() {
throw makeError();
}
async mkdirPromise() {
throw makeError();
}
mkdirSync() {
throw makeError();
}
async rmdirPromise() {
throw makeError();
}
rmdirSync() {
throw makeError();
}
async symlinkPromise() {
throw makeError();
}
symlinkSync() {
throw makeError();
}
async renamePromise() {
throw makeError();
}
renameSync() {
throw makeError();
}
async copyFilePromise() {
throw makeError();
}
copyFileSync() {
throw makeError();
}
async appendFilePromise() {
throw makeError();
}
appendFileSync() {
throw makeError();
}
async writeFilePromise() {
throw makeError();
}
writeFileSync() {
throw makeError();
}
async unlinkPromise() {
throw makeError();
}
unlinkSync() {
throw makeError();
}
async utimesPromise() {
throw makeError();
}
utimesSync() {
throw makeError();
}
async readFilePromise() {
throw makeError();
}
readFileSync() {
throw makeError();
}
async readlinkPromise() {
throw makeError();
}
readlinkSync() {
throw makeError();
}
watch() {
throw makeError();
}
Object.defineProperty(exports, "__esModule", { value: true });
const FakeFS_1 = require("./FakeFS");
const path_1 = require("./path");
const makeError = () => Object.assign(new Error(`ENOSYS: unsupported filesystem access`), { code: `ENOSYS` });
class NoFS extends FakeFS_1.FakeFS {
constructor() {
super(path_1.ppath);
}
getRealPath() {
throw makeError();
}
resolve() {
throw makeError();
}
async openPromise() {
throw makeError();
}
openSync() {
throw makeError();
}
async readPromise() {
throw makeError();
}
readSync() {
throw makeError();
}
async writePromise() {
throw makeError();
}
writeSync() {
throw makeError();
}
async closePromise() {
throw makeError();
}
closeSync() {
throw makeError();
}
createWriteStream() {
throw makeError();
}
createReadStream() {
throw makeError();
}
async realpathPromise() {
throw makeError();
}
realpathSync() {
throw makeError();
}
async readdirPromise() {
throw makeError();
}
readdirSync() {
throw makeError();
}
async existsPromise(p) {
throw makeError();
}
existsSync(p) {
throw makeError();
}
async accessPromise() {
throw makeError();
}
accessSync() {
throw makeError();
}
async statPromise() {
throw makeError();
}
statSync() {
throw makeError();
}
async lstatPromise(p) {
throw makeError();
}
lstatSync(p) {
throw makeError();
}
async chmodPromise() {
throw makeError();
}
chmodSync() {
throw makeError();
}
async mkdirPromise() {
throw makeError();
}
mkdirSync() {
throw makeError();
}
async rmdirPromise() {
throw makeError();
}
rmdirSync() {
throw makeError();
}
async symlinkPromise() {
throw makeError();
}
symlinkSync() {
throw makeError();
}
async renamePromise() {
throw makeError();
}
renameSync() {
throw makeError();
}
async copyFilePromise() {
throw makeError();
}
copyFileSync() {
throw makeError();
}
async appendFilePromise() {
throw makeError();
}
appendFileSync() {
throw makeError();
}
async writeFilePromise() {
throw makeError();
}
writeFileSync() {
throw makeError();
}
async unlinkPromise() {
throw makeError();
}
unlinkSync() {
throw makeError();
}
async utimesPromise() {
throw makeError();
}
utimesSync() {
throw makeError();
}
async readFilePromise() {
throw makeError();
}
readFileSync() {
throw makeError();
}
async readlinkPromise() {
throw makeError();
}
readlinkSync() {
throw makeError();
}
watch() {
throw makeError();
}
}
exports.NoFS = NoFS;
NoFS.instance = new NoFS();
NoFS.instance = new NoFS();
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.convertPath = convertPath;
exports.toFilename = toFilename;
exports.ppath = exports.npath = exports.PortablePath = void 0;
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const PortablePath = {
root: `/`,
dot: `.`
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.PortablePath = PortablePath;
const npath = Object.create(_path.default);
exports.npath = npath;
const ppath = Object.create(_path.default.posix);
exports.ppath = ppath;
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
exports.PortablePath = {
root: `/`,
dot: `.`,
};
exports.npath = Object.create(path_1.default);
exports.ppath = Object.create(path_1.default.posix);
const contains = function (pathUtils, from, to) {
from = pathUtils.normalize(from);
to = pathUtils.normalize(to);
if (from === to) return `.`;
if (!from.endsWith(pathUtils.sep)) from = from + pathUtils.sep;
if (to.startsWith(from)) {
return to.slice(from.length);
} else {
return null;
}
from = pathUtils.normalize(from);
to = pathUtils.normalize(to);
if (from === to)
return `.`;
if (!from.endsWith(pathUtils.sep))
from = (from + pathUtils.sep);
if (to.startsWith(from)) {
return to.slice(from.length);
}
else {
return null;
}
};
npath.fromPortablePath = fromPortablePath;
npath.toPortablePath = toPortablePath;
npath.contains = (from, to) => contains(npath, from, to);
ppath.contains = (from, to) => contains(ppath, from, to);
exports.npath.fromPortablePath = fromPortablePath;
exports.npath.toPortablePath = toPortablePath;
exports.npath.contains = (from, to) => contains(exports.npath, from, to);
exports.ppath.contains = (from, to) => contains(exports.ppath, from, to);
const WINDOWS_PATH_REGEXP = /^[a-zA-Z]:.*$/;
const PORTABLE_PATH_REGEXP = /^\/[a-zA-Z]:.*$/; // Path should look like "/N:/berry/scripts/plugin-pack.js"
const PORTABLE_PATH_REGEXP = /^\/[a-zA-Z]:.*$/;
// Path should look like "/N:/berry/scripts/plugin-pack.js"
// And transform to "N:\berry\scripts\plugin-pack.js"
function fromPortablePath(p) {
if (process.platform !== 'win32') return p;
return p.match(PORTABLE_PATH_REGEXP) ? p.substring(1).replace(/\//g, `\\`) : p;
} // Path should look like "N:/berry/scripts/plugin-pack.js"
if (process.platform !== 'win32')
return p;
return p.match(PORTABLE_PATH_REGEXP) ? p.substring(1).replace(/\//g, `\\`) : p;
}
// Path should look like "N:/berry/scripts/plugin-pack.js"
// And transform to "/N:/berry/scripts/plugin-pack.js"
function toPortablePath(p) {
if (process.platform !== 'win32') return p;
return (p.match(WINDOWS_PATH_REGEXP) ? `/${p}` : p).replace(/\\/g, `/`);
if (process.platform !== 'win32')
return p;
return (p.match(WINDOWS_PATH_REGEXP) ? `/${p}` : p).replace(/\\/g, `/`);
}
function convertPath(targetPathUtils, sourcePath) {
return targetPathUtils === npath ? fromPortablePath(sourcePath) : toPortablePath(sourcePath);
return (targetPathUtils === exports.npath ? fromPortablePath(sourcePath) : toPortablePath(sourcePath));
}
exports.convertPath = convertPath;
function toFilename(filename) {
if (npath.parse(filename).dir !== '' || ppath.parse(filename).dir !== '') throw new Error(`Invalid filename: "${filename}"`);
return filename;
}
if (exports.npath.parse(filename).dir !== '' || exports.ppath.parse(filename).dir !== '')
throw new Error(`Invalid filename: "${filename}"`);
return filename;
}
exports.toFilename = toFilename;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.PosixFS = void 0;
var _ProxiedFS = require("./ProxiedFS");
var _path = require("./path");
class PosixFS extends _ProxiedFS.ProxiedFS {
constructor(baseFs) {
super(_path.npath);
this.baseFs = void 0;
this.baseFs = baseFs;
}
mapFromBase(path) {
return _path.npath.fromPortablePath(path);
}
mapToBase(path) {
return _path.npath.toPortablePath(path);
}
Object.defineProperty(exports, "__esModule", { value: true });
const ProxiedFS_1 = require("./ProxiedFS");
const path_1 = require("./path");
class PosixFS extends ProxiedFS_1.ProxiedFS {
constructor(baseFs) {
super(path_1.npath);
this.baseFs = baseFs;
}
mapFromBase(path) {
return path_1.npath.fromPortablePath(path);
}
mapToBase(path) {
return path_1.npath.toPortablePath(path);
}
}
exports.PosixFS = PosixFS;
exports.PosixFS = PosixFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ProxiedFS = void 0;
var _FakeFS = require("./FakeFS");
class ProxiedFS extends _FakeFS.FakeFS {
constructor(...args) {
super(...args);
this.baseFs = void 0;
}
resolve(path) {
return this.mapFromBase(this.baseFs.resolve(this.mapToBase(path)));
}
getRealPath() {
return this.mapFromBase(this.baseFs.getRealPath());
}
openPromise(p, flags, mode) {
return this.baseFs.openPromise(this.mapToBase(p), flags, mode);
}
openSync(p, flags, mode) {
return this.baseFs.openSync(this.mapToBase(p), flags, mode);
}
async readPromise(fd, buffer, offset, length, position) {
return await this.baseFs.readPromise(fd, buffer, offset, length, position);
}
readSync(fd, buffer, offset, length, position) {
return this.baseFs.readSync(fd, buffer, offset, length, position);
}
async writePromise(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return await this.baseFs.writePromise(fd, buffer, offset);
} else {
return await this.baseFs.writePromise(fd, buffer, offset, length, position);
Object.defineProperty(exports, "__esModule", { value: true });
const FakeFS_1 = require("./FakeFS");
class ProxiedFS extends FakeFS_1.FakeFS {
resolve(path) {
return this.mapFromBase(this.baseFs.resolve(this.mapToBase(path)));
}
}
writeSync(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return this.baseFs.writeSync(fd, buffer, offset);
} else {
return this.baseFs.writeSync(fd, buffer, offset, length, position);
getRealPath() {
return this.mapFromBase(this.baseFs.getRealPath());
}
}
closePromise(fd) {
return this.baseFs.closePromise(fd);
}
closeSync(fd) {
this.baseFs.closeSync(fd);
}
createReadStream(p, opts) {
return this.baseFs.createReadStream(p !== null ? this.mapToBase(p) : p, opts);
}
createWriteStream(p, opts) {
return this.baseFs.createWriteStream(p !== null ? this.mapToBase(p) : p, opts);
}
async realpathPromise(p) {
return this.mapFromBase((await this.baseFs.realpathPromise(this.mapToBase(p))));
}
realpathSync(p) {
return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(p)));
}
existsPromise(p) {
return this.baseFs.existsPromise(this.mapToBase(p));
}
existsSync(p) {
return this.baseFs.existsSync(this.mapToBase(p));
}
accessSync(p, mode) {
return this.baseFs.accessSync(this.mapToBase(p), mode);
}
accessPromise(p, mode) {
return this.baseFs.accessPromise(this.mapToBase(p), mode);
}
statPromise(p) {
return this.baseFs.statPromise(this.mapToBase(p));
}
statSync(p) {
return this.baseFs.statSync(this.mapToBase(p));
}
lstatPromise(p) {
return this.baseFs.lstatPromise(this.mapToBase(p));
}
lstatSync(p) {
return this.baseFs.lstatSync(this.mapToBase(p));
}
chmodPromise(p, mask) {
return this.baseFs.chmodPromise(this.mapToBase(p), mask);
}
chmodSync(p, mask) {
return this.baseFs.chmodSync(this.mapToBase(p), mask);
}
renamePromise(oldP, newP) {
return this.baseFs.renamePromise(this.mapToBase(oldP), this.mapToBase(newP));
}
renameSync(oldP, newP) {
return this.baseFs.renameSync(this.mapToBase(oldP), this.mapToBase(newP));
}
copyFilePromise(sourceP, destP, flags = 0) {
return this.baseFs.copyFilePromise(this.mapToBase(sourceP), this.mapToBase(destP), flags);
}
copyFileSync(sourceP, destP, flags = 0) {
return this.baseFs.copyFileSync(this.mapToBase(sourceP), this.mapToBase(destP), flags);
}
appendFilePromise(p, content, opts) {
return this.baseFs.appendFilePromise(this.fsMapToBase(p), content, opts);
}
appendFileSync(p, content, opts) {
return this.baseFs.appendFileSync(this.fsMapToBase(p), content, opts);
}
writeFilePromise(p, content, opts) {
return this.baseFs.writeFilePromise(this.fsMapToBase(p), content, opts);
}
writeFileSync(p, content, opts) {
return this.baseFs.writeFileSync(this.fsMapToBase(p), content, opts);
}
unlinkPromise(p) {
return this.baseFs.unlinkPromise(this.mapToBase(p));
}
unlinkSync(p) {
return this.baseFs.unlinkSync(this.mapToBase(p));
}
utimesPromise(p, atime, mtime) {
return this.baseFs.utimesPromise(this.mapToBase(p), atime, mtime);
}
utimesSync(p, atime, mtime) {
return this.baseFs.utimesSync(this.mapToBase(p), atime, mtime);
}
mkdirPromise(p, opts) {
return this.baseFs.mkdirPromise(this.mapToBase(p), opts);
}
mkdirSync(p, opts) {
return this.baseFs.mkdirSync(this.mapToBase(p), opts);
}
rmdirPromise(p) {
return this.baseFs.rmdirPromise(this.mapToBase(p));
}
rmdirSync(p) {
return this.baseFs.rmdirSync(this.mapToBase(p));
}
symlinkPromise(target, p) {
return this.baseFs.symlinkPromise(this.mapToBase(target), this.mapToBase(p));
}
symlinkSync(target, p) {
return this.baseFs.symlinkSync(this.mapToBase(target), this.mapToBase(p));
}
readFilePromise(p, encoding) {
// This weird condition is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
if (encoding === 'utf8') {
return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding);
} else {
return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding);
openPromise(p, flags, mode) {
return this.baseFs.openPromise(this.mapToBase(p), flags, mode);
}
}
readFileSync(p, encoding) {
// This weird condition is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
if (encoding === 'utf8') {
return this.baseFs.readFileSync(this.fsMapToBase(p), encoding);
} else {
return this.baseFs.readFileSync(this.fsMapToBase(p), encoding);
openSync(p, flags, mode) {
return this.baseFs.openSync(this.mapToBase(p), flags, mode);
}
}
async readdirPromise(p, {
withFileTypes
} = {}) {
return this.baseFs.readdirPromise(this.mapToBase(p), {
withFileTypes: withFileTypes
});
}
readdirSync(p, {
withFileTypes
} = {}) {
return this.baseFs.readdirSync(this.mapToBase(p), {
withFileTypes: withFileTypes
});
}
async readlinkPromise(p) {
return this.mapFromBase((await this.baseFs.readlinkPromise(this.mapToBase(p))));
}
readlinkSync(p) {
return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(p)));
}
watch(p, a, b) {
return this.baseFs.watch(this.mapToBase(p), // @ts-ignore
a, b);
}
fsMapToBase(p) {
if (typeof p === `number`) {
return p;
} else {
return this.mapToBase(p);
async readPromise(fd, buffer, offset, length, position) {
return await this.baseFs.readPromise(fd, buffer, offset, length, position);
}
}
readSync(fd, buffer, offset, length, position) {
return this.baseFs.readSync(fd, buffer, offset, length, position);
}
async writePromise(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return await this.baseFs.writePromise(fd, buffer, offset);
}
else {
return await this.baseFs.writePromise(fd, buffer, offset, length, position);
}
}
writeSync(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return this.baseFs.writeSync(fd, buffer, offset);
}
else {
return this.baseFs.writeSync(fd, buffer, offset, length, position);
}
}
closePromise(fd) {
return this.baseFs.closePromise(fd);
}
closeSync(fd) {
this.baseFs.closeSync(fd);
}
createReadStream(p, opts) {
return this.baseFs.createReadStream(p !== null ? this.mapToBase(p) : p, opts);
}
createWriteStream(p, opts) {
return this.baseFs.createWriteStream(p !== null ? this.mapToBase(p) : p, opts);
}
async realpathPromise(p) {
return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(p)));
}
realpathSync(p) {
return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(p)));
}
existsPromise(p) {
return this.baseFs.existsPromise(this.mapToBase(p));
}
existsSync(p) {
return this.baseFs.existsSync(this.mapToBase(p));
}
accessSync(p, mode) {
return this.baseFs.accessSync(this.mapToBase(p), mode);
}
accessPromise(p, mode) {
return this.baseFs.accessPromise(this.mapToBase(p), mode);
}
statPromise(p) {
return this.baseFs.statPromise(this.mapToBase(p));
}
statSync(p) {
return this.baseFs.statSync(this.mapToBase(p));
}
lstatPromise(p) {
return this.baseFs.lstatPromise(this.mapToBase(p));
}
lstatSync(p) {
return this.baseFs.lstatSync(this.mapToBase(p));
}
chmodPromise(p, mask) {
return this.baseFs.chmodPromise(this.mapToBase(p), mask);
}
chmodSync(p, mask) {
return this.baseFs.chmodSync(this.mapToBase(p), mask);
}
renamePromise(oldP, newP) {
return this.baseFs.renamePromise(this.mapToBase(oldP), this.mapToBase(newP));
}
renameSync(oldP, newP) {
return this.baseFs.renameSync(this.mapToBase(oldP), this.mapToBase(newP));
}
copyFilePromise(sourceP, destP, flags = 0) {
return this.baseFs.copyFilePromise(this.mapToBase(sourceP), this.mapToBase(destP), flags);
}
copyFileSync(sourceP, destP, flags = 0) {
return this.baseFs.copyFileSync(this.mapToBase(sourceP), this.mapToBase(destP), flags);
}
appendFilePromise(p, content, opts) {
return this.baseFs.appendFilePromise(this.fsMapToBase(p), content, opts);
}
appendFileSync(p, content, opts) {
return this.baseFs.appendFileSync(this.fsMapToBase(p), content, opts);
}
writeFilePromise(p, content, opts) {
return this.baseFs.writeFilePromise(this.fsMapToBase(p), content, opts);
}
writeFileSync(p, content, opts) {
return this.baseFs.writeFileSync(this.fsMapToBase(p), content, opts);
}
unlinkPromise(p) {
return this.baseFs.unlinkPromise(this.mapToBase(p));
}
unlinkSync(p) {
return this.baseFs.unlinkSync(this.mapToBase(p));
}
utimesPromise(p, atime, mtime) {
return this.baseFs.utimesPromise(this.mapToBase(p), atime, mtime);
}
utimesSync(p, atime, mtime) {
return this.baseFs.utimesSync(this.mapToBase(p), atime, mtime);
}
mkdirPromise(p, opts) {
return this.baseFs.mkdirPromise(this.mapToBase(p), opts);
}
mkdirSync(p, opts) {
return this.baseFs.mkdirSync(this.mapToBase(p), opts);
}
rmdirPromise(p) {
return this.baseFs.rmdirPromise(this.mapToBase(p));
}
rmdirSync(p) {
return this.baseFs.rmdirSync(this.mapToBase(p));
}
symlinkPromise(target, p) {
return this.baseFs.symlinkPromise(this.mapToBase(target), this.mapToBase(p));
}
symlinkSync(target, p) {
return this.baseFs.symlinkSync(this.mapToBase(target), this.mapToBase(p));
}
readFilePromise(p, encoding) {
// This weird condition is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
if (encoding === 'utf8') {
return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding);
}
else {
return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding);
}
}
readFileSync(p, encoding) {
// This weird condition is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
if (encoding === 'utf8') {
return this.baseFs.readFileSync(this.fsMapToBase(p), encoding);
}
else {
return this.baseFs.readFileSync(this.fsMapToBase(p), encoding);
}
}
async readdirPromise(p, { withFileTypes } = {}) {
return this.baseFs.readdirPromise(this.mapToBase(p), { withFileTypes: withFileTypes });
}
readdirSync(p, { withFileTypes } = {}) {
return this.baseFs.readdirSync(this.mapToBase(p), { withFileTypes: withFileTypes });
}
async readlinkPromise(p) {
return this.mapFromBase(await this.baseFs.readlinkPromise(this.mapToBase(p)));
}
readlinkSync(p) {
return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(p)));
}
watch(p, a, b) {
return this.baseFs.watch(this.mapToBase(p),
// @ts-ignore
a, b);
}
fsMapToBase(p) {
if (typeof p === `number`) {
return p;
}
else {
return this.mapToBase(p);
}
}
}
exports.ProxiedFS = ProxiedFS;
exports.ProxiedFS = ProxiedFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.VirtualFS = void 0;
var _NodeFS = require("./NodeFS");
var _ProxiedFS = require("./ProxiedFS");
var _path = require("./path");
const NUMBER_REGEXP = /^[0-9]+$/; // $0: full path
Object.defineProperty(exports, "__esModule", { value: true });
const NodeFS_1 = require("./NodeFS");
const ProxiedFS_1 = require("./ProxiedFS");
const path_1 = require("./path");
const NUMBER_REGEXP = /^[0-9]+$/;
// $0: full path
// $1: virtual folder

@@ -20,77 +13,65 @@ // $2: virtual segment

// $5: subpath
const VIRTUAL_REGEXP = /^(\/(?:[^\/]+\/)*?\$\$virtual)((?:\/([^\/]+)(?:\/([^\/]+))?)?((?:\/.*)?))$/;
class VirtualFS extends _ProxiedFS.ProxiedFS {
static makeVirtualPath(base, component, to) {
if (_path.ppath.basename(base) !== `$$virtual`) throw new Error(`Assertion failed: Virtual folders must be named "$$virtual"`); // Obtains the relative distance between the virtual path and its actual target
const target = _path.ppath.relative(_path.ppath.dirname(base), to);
const segments = target.split(`/`); // Counts how many levels we need to go back to start applying the rest of the path
let depth = 0;
while (depth < segments.length && segments[depth] === `..`) depth += 1;
const finalSegments = segments.slice(depth);
const fullVirtualPath = _path.ppath.join(base, component, String(depth), ...finalSegments);
return fullVirtualPath;
}
static resolveVirtual(p) {
const match = p.match(VIRTUAL_REGEXP);
if (!match) return p;
const target = _path.ppath.dirname(match[1]);
if (!match[3] || !match[4]) return target;
const isnum = NUMBER_REGEXP.test(match[4]);
if (!isnum) return p;
const depth = Number(match[4]);
const backstep = `../`.repeat(depth);
const subpath = match[5] || `.`;
return VirtualFS.resolveVirtual(_path.ppath.join(target, backstep, subpath));
}
constructor({
baseFs = new _NodeFS.NodeFS()
} = {}) {
super(_path.ppath);
this.baseFs = void 0;
this.baseFs = baseFs;
}
getRealPath() {
return this.baseFs.getRealPath();
}
realpathSync(p) {
const match = p.match(VIRTUAL_REGEXP);
if (!match) return this.baseFs.realpathSync(p);
if (!match[5]) return p;
const realpath = this.baseFs.realpathSync(this.mapToBase(p));
return VirtualFS.makeVirtualPath(match[1], match[3], realpath);
}
async realpathPromise(p) {
const match = p.match(VIRTUAL_REGEXP);
if (!match) return await this.baseFs.realpathPromise(p);
if (!match[5]) return p;
const realpath = await this.baseFs.realpathPromise(this.mapToBase(p));
return VirtualFS.makeVirtualPath(match[1], match[3], realpath);
}
mapToBase(p) {
return VirtualFS.resolveVirtual(p);
}
mapFromBase(p) {
return p;
}
class VirtualFS extends ProxiedFS_1.ProxiedFS {
constructor({ baseFs = new NodeFS_1.NodeFS() } = {}) {
super(path_1.ppath);
this.baseFs = baseFs;
}
static makeVirtualPath(base, component, to) {
if (path_1.ppath.basename(base) !== `$$virtual`)
throw new Error(`Assertion failed: Virtual folders must be named "$$virtual"`);
// Obtains the relative distance between the virtual path and its actual target
const target = path_1.ppath.relative(path_1.ppath.dirname(base), to);
const segments = target.split(`/`);
// Counts how many levels we need to go back to start applying the rest of the path
let depth = 0;
while (depth < segments.length && segments[depth] === `..`)
depth += 1;
const finalSegments = segments.slice(depth);
const fullVirtualPath = path_1.ppath.join(base, component, String(depth), ...finalSegments);
return fullVirtualPath;
}
static resolveVirtual(p) {
const match = p.match(VIRTUAL_REGEXP);
if (!match)
return p;
const target = path_1.ppath.dirname(match[1]);
if (!match[3] || !match[4])
return target;
const isnum = NUMBER_REGEXP.test(match[4]);
if (!isnum)
return p;
const depth = Number(match[4]);
const backstep = `../`.repeat(depth);
const subpath = (match[5] || `.`);
return VirtualFS.resolveVirtual(path_1.ppath.join(target, backstep, subpath));
}
getRealPath() {
return this.baseFs.getRealPath();
}
realpathSync(p) {
const match = p.match(VIRTUAL_REGEXP);
if (!match)
return this.baseFs.realpathSync(p);
if (!match[5])
return p;
const realpath = this.baseFs.realpathSync(this.mapToBase(p));
return VirtualFS.makeVirtualPath(match[1], match[3], realpath);
}
async realpathPromise(p) {
const match = p.match(VIRTUAL_REGEXP);
if (!match)
return await this.baseFs.realpathPromise(p);
if (!match[5])
return p;
const realpath = await this.baseFs.realpathPromise(this.mapToBase(p));
return VirtualFS.makeVirtualPath(match[1], match[3], realpath);
}
mapToBase(p) {
return VirtualFS.resolveVirtual(p);
}
mapFromBase(p) {
return p;
}
}
exports.VirtualFS = VirtualFS;
exports.VirtualFS = VirtualFS;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ZipFS = void 0;
var _libzip = _interopRequireDefault(require("@yarnpkg/libzip"));
var _fs = require("fs");
var _stream = require("stream");
var _util = require("util");
var _FakeFS = require("./FakeFS");
var _NodeFS = require("./NodeFS");
var errors = _interopRequireWildcard(require("./errors"));
var _path = require("./path");
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const stream_1 = require("stream");
const util_1 = require("util");
const FakeFS_1 = require("./FakeFS");
const NodeFS_1 = require("./NodeFS");
const errors = __importStar(require("./errors"));
const path_1 = require("./path");
const S_IFMT = 0o170000;

@@ -34,948 +21,826 @@ const S_IFDIR = 0o040000;

const S_IFLNK = 0o120000;
class DirEntry {
constructor() {
this.name = ``;
this.mode = 0;
}
isBlockDevice() {
return false;
}
isCharacterDevice() {
return false;
}
isDirectory() {
return (this.mode & S_IFMT) === S_IFDIR;
}
isFIFO() {
return false;
}
isFile() {
return (this.mode & S_IFMT) === S_IFREG;
}
isSocket() {
return false;
}
isSymbolicLink() {
return (this.mode & S_IFMT) === S_IFLNK;
}
constructor() {
this.name = ``;
this.mode = 0;
}
isBlockDevice() {
return false;
}
isCharacterDevice() {
return false;
}
isDirectory() {
return (this.mode & S_IFMT) === S_IFDIR;
}
isFIFO() {
return false;
}
isFile() {
return (this.mode & S_IFMT) === S_IFREG;
}
isSocket() {
return false;
}
isSymbolicLink() {
return (this.mode & S_IFMT) === S_IFLNK;
}
}
class StatEntry {
constructor() {
this.dev = 0;
this.ino = 0;
this.mode = 0;
this.nlink = 1;
this.rdev = 0;
this.blocks = 1;
}
isBlockDevice() {
return false;
}
isCharacterDevice() {
return false;
}
isDirectory() {
return (this.mode & S_IFMT) === S_IFDIR;
}
isFIFO() {
return false;
}
isFile() {
return (this.mode & S_IFMT) === S_IFREG;
}
isSocket() {
return false;
}
isSymbolicLink() {
return (this.mode & S_IFMT) === S_IFLNK;
}
constructor() {
this.dev = 0;
this.ino = 0;
this.mode = 0;
this.nlink = 1;
this.rdev = 0;
this.blocks = 1;
}
isBlockDevice() {
return false;
}
isCharacterDevice() {
return false;
}
isDirectory() {
return (this.mode & S_IFMT) === S_IFDIR;
}
isFIFO() {
return false;
}
isFile() {
return (this.mode & S_IFMT) === S_IFREG;
}
isSocket() {
return false;
}
isSymbolicLink() {
return (this.mode & S_IFMT) === S_IFLNK;
}
}
function makeDefaultStats() {
return Object.assign(new StatEntry(), {
uid: 0,
gid: 0,
size: 0,
blksize: 0,
atimeMs: 0,
mtimeMs: 0,
ctimeMs: 0,
birthtimeMs: 0,
atime: new Date(0),
mtime: new Date(0),
ctime: new Date(0),
birthtime: new Date(0),
mode: S_IFREG | 0o644
});
return Object.assign(new StatEntry(), {
uid: 0,
gid: 0,
size: 0,
blksize: 0,
atimeMs: 0,
mtimeMs: 0,
ctimeMs: 0,
birthtimeMs: 0,
atime: new Date(0),
mtime: new Date(0),
ctime: new Date(0),
birthtime: new Date(0),
mode: S_IFREG | 0o644,
});
}
function toUnixTimestamp(time) {
if (typeof time === 'string' && String(+time) === time) return +time; // @ts-ignore
if (Number.isFinite(time)) {
if (time < 0) {
return Date.now() / 1000;
} else {
return time;
if (typeof time === 'string' && String(+time) === time)
return +time;
// @ts-ignore
if (Number.isFinite(time)) {
if (time < 0) {
return Date.now() / 1000;
}
else {
return time;
}
}
} // convert to 123.456 UNIX timestamp
if ((0, _util.isDate)(time)) return time.getTime() / 1000;
throw new Error(`Invalid time`);
// convert to 123.456 UNIX timestamp
if (util_1.isDate(time))
return time.getTime() / 1000;
throw new Error(`Invalid time`);
}
class ZipFS extends _FakeFS.BasePortableFakeFS {
constructor(source, opts = {}) {
super();
this.baseFs = void 0;
this.path = void 0;
this.stats = void 0;
this.zip = void 0;
this.listings = new Map();
this.entries = new Map();
this.fds = new Map();
this.nextFd = 0;
this.ready = false;
this.readOnly = false;
const pathOptions = opts;
if (typeof source === `string`) {
const {
baseFs = new _NodeFS.NodeFS()
} = pathOptions;
this.baseFs = baseFs;
this.path = source;
} else {
this.path = null;
this.baseFs = null;
class ZipFS extends FakeFS_1.BasePortableFakeFS {
constructor(source, opts) {
super();
this.listings = new Map();
this.entries = new Map();
this.fds = new Map();
this.nextFd = 0;
this.ready = false;
this.readOnly = false;
this.libzip = opts.libzip;
const pathOptions = opts;
if (typeof source === `string`) {
const { baseFs = new NodeFS_1.NodeFS() } = pathOptions;
this.baseFs = baseFs;
this.path = source;
}
else {
this.path = null;
this.baseFs = null;
}
if (opts.stats) {
this.stats = opts.stats;
}
else {
if (typeof source === `string`) {
try {
this.stats = this.baseFs.statSync(source);
}
catch (error) {
if (error.code === `ENOENT` && pathOptions.create) {
this.stats = makeDefaultStats();
}
else {
throw error;
}
}
}
else {
this.stats = makeDefaultStats();
}
}
const errPtr = this.libzip.malloc(4);
try {
let flags = 0;
if (typeof source === `string` && pathOptions.create)
flags |= this.libzip.ZIP_CREATE | this.libzip.ZIP_TRUNCATE;
if (opts.readOnly) {
flags |= this.libzip.ZIP_RDONLY;
this.readOnly = true;
}
if (typeof source === `string`) {
this.zip = this.libzip.open(path_1.npath.fromPortablePath(source), flags, errPtr);
}
else {
const lzSource = this.allocateUnattachedSource(source);
try {
this.zip = this.libzip.openFromSource(lzSource, flags, errPtr);
}
catch (error) {
this.libzip.source.free(lzSource);
throw error;
}
}
if (this.zip === 0) {
const error = this.libzip.struct.errorS();
this.libzip.error.initWithCode(error, this.libzip.getValue(errPtr, `i32`));
throw new Error(this.libzip.error.strerror(error));
}
}
finally {
this.libzip.free(errPtr);
}
this.listings.set(path_1.PortablePath.root, new Set());
const entryCount = this.libzip.getNumEntries(this.zip, 0);
for (let t = 0; t < entryCount; ++t) {
const raw = this.libzip.getName(this.zip, t, 0);
if (path_1.ppath.isAbsolute(raw))
continue;
const p = path_1.ppath.resolve(path_1.PortablePath.root, raw);
this.registerEntry(p, t);
// If the raw path is a directory, register it
// to prevent empty folder being skipped
if (raw.endsWith('/')) {
this.registerListing(p);
}
}
this.ready = true;
}
if (opts.stats) {
this.stats = opts.stats;
} else {
if (typeof source === `string`) {
getAllFiles() {
return Array.from(this.entries.keys());
}
getRealPath() {
if (!this.path)
throw new Error(`ZipFS don't have real paths when loaded from a buffer`);
return this.path;
}
saveAndClose() {
if (!this.path || !this.baseFs)
throw new Error(`ZipFS cannot be saved and must be discarded when loaded from a buffer`);
if (!this.ready)
throw errors.EBUSY(`archive closed, close`);
if (this.readOnly)
return this.discardAndClose();
const previousMod = this.baseFs.existsSync(this.path)
? this.baseFs.statSync(this.path).mode & 0o777
: null;
const rc = this.libzip.close(this.zip);
if (rc === -1)
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
// this.libzip overrides the chmod when writing the archive, which is a weird
// behavior I don't totally understand (plus the umask seems bogus in some
// weird cases - maybe related to emscripten?)
//
// See also https://github.com/nih-at/libzip/issues/77
if (previousMod === null)
this.baseFs.chmodSync(this.path, this.stats.mode);
else if (previousMod !== (this.baseFs.statSync(this.path).mode & 0o777))
this.baseFs.chmodSync(this.path, previousMod);
this.ready = false;
}
discardAndClose() {
if (!this.ready)
throw errors.EBUSY(`archive closed, close`);
this.libzip.discard(this.zip);
this.ready = false;
}
async openPromise(p, flags, mode) {
return this.openSync(p, flags, mode);
}
openSync(p, flags, mode) {
const fd = this.nextFd++;
this.fds.set(fd, { cursor: 0, p });
return fd;
}
async readPromise(fd, buffer, offset, length, position) {
return this.readSync(fd, buffer, offset, length, position);
}
readSync(fd, buffer, offset = 0, length = 0, position = -1) {
const entry = this.fds.get(fd);
if (typeof entry === `undefined`)
throw errors.EBADF(`read`);
let realPosition;
if (position === -1 || position === null)
realPosition = entry.cursor;
else
realPosition = position;
const source = this.readFileSync(entry.p);
source.copy(buffer, offset, realPosition, realPosition + length);
const bytesRead = Math.max(0, Math.min(source.length - realPosition, length));
if (position === -1)
entry.cursor += bytesRead;
return bytesRead;
}
async writePromise(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return this.writeSync(fd, buffer, position);
}
else {
return this.writeSync(fd, buffer, offset, length, position);
}
}
writeSync(fd, buffer, offset, length, position) {
const entry = this.fds.get(fd);
if (typeof entry === `undefined`)
throw errors.EBADF(`read`);
throw new Error(`Unimplemented`);
}
async closePromise(fd) {
return this.closeSync(fd);
}
closeSync(fd) {
const entry = this.fds.get(fd);
if (typeof entry === `undefined`)
throw errors.EBADF(`read`);
this.fds.delete(fd);
}
createReadStream(p, { encoding } = {}) {
if (p === null)
throw new Error(`Unimplemented`);
const stream = Object.assign(new stream_1.PassThrough(), {
bytesRead: 0,
path: p,
close: () => {
clearImmediate(immediate);
},
});
const immediate = setImmediate(() => {
try {
const data = this.readFileSync(p, encoding);
stream.bytesRead = data.length;
stream.write(data);
stream.end();
}
catch (error) {
stream.emit(`error`, error);
stream.end();
}
});
return stream;
}
createWriteStream(p, { encoding } = {}) {
if (this.readOnly)
throw errors.EROFS(`open '${p}'`);
if (p === null)
throw new Error(`Unimplemented`);
const stream = Object.assign(new stream_1.PassThrough(), {
bytesWritten: 0,
path: p,
close: () => {
stream.end();
},
});
const chunks = [];
stream.on(`data`, chunk => {
const chunkBuffer = Buffer.from(chunk);
stream.bytesWritten += chunkBuffer.length;
chunks.push(chunkBuffer);
});
stream.on(`end`, () => {
this.writeFileSync(p, Buffer.concat(chunks), encoding);
});
return stream;
}
async realpathPromise(p) {
return this.realpathSync(p);
}
realpathSync(p) {
const resolvedP = this.resolveFilename(`lstat '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP))
throw errors.ENOENT(`lstat '${p}'`);
return resolvedP;
}
async existsPromise(p) {
return this.existsSync(p);
}
existsSync(p) {
let resolvedP;
try {
this.stats = this.baseFs.statSync(source);
} catch (error) {
if (error.code === `ENOENT` && pathOptions.create) {
this.stats = makeDefaultStats();
} else {
resolvedP = this.resolveFilename(`stat '${p}'`, p);
}
catch (error) {
return false;
}
return this.entries.has(resolvedP) || this.listings.has(resolvedP);
}
async accessPromise(p, mode) {
return this.accessSync(p, mode);
}
accessSync(p, mode = fs_1.constants.F_OK) {
const resolvedP = this.resolveFilename(`access '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP))
throw errors.ENOENT(`access '${p}'`);
if (this.readOnly && (mode & fs_1.constants.W_OK)) {
throw errors.EROFS(`access '${p}'`);
}
}
async statPromise(p) {
return this.statSync(p);
}
statSync(p) {
const resolvedP = this.resolveFilename(`stat '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP))
throw errors.ENOENT(`stat '${p}'`);
if (p[p.length - 1] === `/` && !this.listings.has(resolvedP))
throw errors.ENOTDIR(`stat '${p}'`);
return this.statImpl(`stat '${p}'`, resolvedP);
}
async lstatPromise(p) {
return this.lstatSync(p);
}
lstatSync(p) {
const resolvedP = this.resolveFilename(`lstat '${p}'`, p, false);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP))
throw errors.ENOENT(`lstat '${p}'`);
if (p[p.length - 1] === `/` && !this.listings.has(resolvedP))
throw errors.ENOTDIR(`lstat '${p}'`);
return this.statImpl(`lstat '${p}'`, resolvedP);
}
statImpl(reason, p) {
const entry = this.entries.get(p);
// File, or explicit directory
if (typeof entry !== `undefined`) {
const stat = this.libzip.struct.statS();
const rc = this.libzip.statIndex(this.zip, entry, 0, 0, stat);
if (rc === -1)
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
const uid = this.stats.uid;
const gid = this.stats.gid;
const size = (this.libzip.struct.statSize(stat) >>> 0);
const blksize = 512;
const blocks = Math.ceil(size / blksize);
const mtimeMs = (this.libzip.struct.statMtime(stat) >>> 0) * 1000;
const atimeMs = mtimeMs;
const birthtimeMs = mtimeMs;
const ctimeMs = mtimeMs;
const atime = new Date(atimeMs);
const birthtime = new Date(birthtimeMs);
const ctime = new Date(ctimeMs);
const mtime = new Date(mtimeMs);
const type = this.listings.has(p)
? S_IFDIR
: S_IFREG;
const defaultMode = type === S_IFDIR
? 0o755
: 0o644;
const mode = type | (this.getUnixMode(entry, defaultMode) & 0o777);
return Object.assign(new StatEntry(), { uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode });
}
// Implicit directory
if (this.listings.has(p)) {
const uid = this.stats.uid;
const gid = this.stats.gid;
const size = 0;
const blksize = 512;
const blocks = 0;
const atimeMs = this.stats.mtimeMs;
const birthtimeMs = this.stats.mtimeMs;
const ctimeMs = this.stats.mtimeMs;
const mtimeMs = this.stats.mtimeMs;
const atime = new Date(atimeMs);
const birthtime = new Date(birthtimeMs);
const ctime = new Date(ctimeMs);
const mtime = new Date(mtimeMs);
const mode = S_IFDIR | 0o755;
return Object.assign(new StatEntry(), { uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode });
}
throw new Error(`Unreachable`);
}
getUnixMode(index, defaultMode) {
const rc = this.libzip.file.getExternalAttributes(this.zip, index, 0, 0, this.libzip.uint08S, this.libzip.uint32S);
if (rc === -1)
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
const opsys = this.libzip.getValue(this.libzip.uint08S, `i8`) >>> 0;
if (opsys !== this.libzip.ZIP_OPSYS_UNIX)
return defaultMode;
return this.libzip.getValue(this.libzip.uint32S, `i32`) >>> 16;
}
registerListing(p) {
let listing = this.listings.get(p);
if (listing)
return listing;
const parentListing = this.registerListing(path_1.ppath.dirname(p));
listing = new Set();
parentListing.add(path_1.ppath.basename(p));
this.listings.set(p, listing);
return listing;
}
registerEntry(p, index) {
const parentListing = this.registerListing(path_1.ppath.dirname(p));
parentListing.add(path_1.ppath.basename(p));
this.entries.set(p, index);
}
resolveFilename(reason, p, resolveLastComponent = true) {
if (!this.ready)
throw errors.EBUSY(`archive closed, ${reason}`);
let resolvedP = path_1.ppath.resolve(path_1.PortablePath.root, p);
if (resolvedP === `/`)
return path_1.PortablePath.root;
while (true) {
const parentP = this.resolveFilename(reason, path_1.ppath.dirname(resolvedP), true);
const isDir = this.listings.has(parentP);
const doesExist = this.entries.has(parentP);
if (!isDir && !doesExist)
throw errors.ENOENT(reason);
if (!isDir)
throw errors.ENOTDIR(reason);
resolvedP = path_1.ppath.resolve(parentP, path_1.ppath.basename(resolvedP));
if (!resolveLastComponent)
break;
const index = this.libzip.name.locate(this.zip, resolvedP);
if (index === -1)
break;
if (this.isSymbolicLink(index)) {
const target = this.getFileSource(index).toString();
resolvedP = path_1.ppath.resolve(path_1.ppath.dirname(resolvedP), target);
}
else {
break;
}
}
return resolvedP;
}
allocateBuffer(content) {
if (!Buffer.isBuffer(content))
content = Buffer.from(content);
const buffer = this.libzip.malloc(content.byteLength);
if (!buffer)
throw new Error(`Couldn't allocate enough memory`);
// Copy the file into the Emscripten heap
const heap = new Uint8Array(this.libzip.HEAPU8.buffer, buffer, content.byteLength);
heap.set(content);
return { buffer, byteLength: content.byteLength };
}
allocateUnattachedSource(content) {
const error = this.libzip.struct.errorS();
const { buffer, byteLength } = this.allocateBuffer(content);
const source = this.libzip.source.fromUnattachedBuffer(buffer, byteLength, 0, true, error);
if (source === 0) {
this.libzip.free(error);
throw new Error(this.libzip.error.strerror(error));
}
return source;
}
allocateSource(content) {
const { buffer, byteLength } = this.allocateBuffer(content);
const source = this.libzip.source.fromBuffer(this.zip, buffer, byteLength, 0, true);
if (source === 0) {
this.libzip.free(buffer);
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
}
return source;
}
setFileSource(p, content) {
const target = path_1.ppath.relative(path_1.PortablePath.root, p);
const lzSource = this.allocateSource(content);
try {
return this.libzip.file.add(this.zip, target, lzSource, this.libzip.ZIP_FL_OVERWRITE);
}
catch (error) {
this.libzip.source.free(lzSource);
throw error;
}
}
} else {
this.stats = makeDefaultStats();
}
}
const errPtr = _libzip.default.malloc(4);
try {
let flags = 0;
if (typeof source === `string` && pathOptions.create) flags |= _libzip.default.ZIP_CREATE | _libzip.default.ZIP_TRUNCATE;
if (opts.readOnly) {
flags |= _libzip.default.ZIP_RDONLY;
this.readOnly = true;
}
if (typeof source === `string`) {
this.zip = _libzip.default.open(_path.npath.fromPortablePath(source), flags, errPtr);
} else {
const lzSource = this.allocateUnattachedSource(source);
isSymbolicLink(index) {
const attrs = this.libzip.file.getExternalAttributes(this.zip, index, 0, 0, this.libzip.uint08S, this.libzip.uint32S);
if (attrs === -1)
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
const opsys = this.libzip.getValue(this.libzip.uint08S, `i8`) >>> 0;
if (opsys !== this.libzip.ZIP_OPSYS_UNIX)
return false;
const attributes = this.libzip.getValue(this.libzip.uint32S, `i32`) >>> 16;
return (attributes & S_IFMT) === S_IFLNK;
}
getFileSource(index) {
const stat = this.libzip.struct.statS();
const rc = this.libzip.statIndex(this.zip, index, 0, 0, stat);
if (rc === -1)
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
const size = this.libzip.struct.statSize(stat);
const buffer = this.libzip.malloc(size);
try {
this.zip = _libzip.default.openFromSource(lzSource, flags, errPtr);
} catch (error) {
_libzip.default.source.free(lzSource);
throw error;
const file = this.libzip.fopenIndex(this.zip, index, 0, 0);
if (file === 0)
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
try {
const rc = this.libzip.fread(file, buffer, size, 0);
if (rc === -1)
throw new Error(this.libzip.error.strerror(this.libzip.file.getError(file)));
else if (rc < size)
throw new Error(`Incomplete read`);
else if (rc > size)
throw new Error(`Overread`);
const memory = this.libzip.HEAPU8.subarray(buffer, buffer + size);
const data = Buffer.from(memory);
return data;
}
finally {
this.libzip.fclose(file);
}
}
}
if (this.zip === 0) {
const error = _libzip.default.struct.errorS();
_libzip.default.error.initWithCode(error, _libzip.default.getValue(errPtr, `i32`));
throw new Error(_libzip.default.error.strerror(error));
}
} finally {
_libzip.default.free(errPtr);
finally {
this.libzip.free(buffer);
}
}
this.listings.set(_path.PortablePath.root, new Set());
const entryCount = _libzip.default.getNumEntries(this.zip, 0);
for (let t = 0; t < entryCount; ++t) {
const raw = _libzip.default.getName(this.zip, t, 0);
if (_path.ppath.isAbsolute(raw)) continue;
const p = _path.ppath.resolve(_path.PortablePath.root, raw);
this.registerEntry(p, t); // If the raw path is a directory, register it
// to prevent empty folder being skipped
if (raw.endsWith('/')) {
this.registerListing(p);
}
async chmodPromise(p, mask) {
return this.chmodSync(p, mask);
}
this.ready = true;
}
getAllFiles() {
return Array.from(this.entries.keys());
}
getRealPath() {
if (!this.path) throw new Error(`ZipFS don't have real paths when loaded from a buffer`);
return this.path;
}
saveAndClose() {
if (!this.path || !this.baseFs) throw new Error(`ZipFS cannot be saved and must be discarded when loaded from a buffer`);
if (!this.ready) throw errors.EBUSY(`archive closed, close`);
if (this.readOnly) return this.discardAndClose();
const previousMod = this.baseFs.existsSync(this.path) ? this.baseFs.statSync(this.path).mode & 0o777 : null;
const rc = _libzip.default.close(this.zip);
if (rc === -1) throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip))); // Libzip overrides the chmod when writing the archive, which is a weird
// behavior I don't totally understand (plus the umask seems bogus in some
// weird cases - maybe related to emscripten?)
//
// See also https://github.com/nih-at/libzip/issues/77
if (previousMod === null) this.baseFs.chmodSync(this.path, this.stats.mode);else if (previousMod !== (this.baseFs.statSync(this.path).mode & 0o777)) this.baseFs.chmodSync(this.path, previousMod);
this.ready = false;
}
discardAndClose() {
if (!this.ready) throw errors.EBUSY(`archive closed, close`);
_libzip.default.discard(this.zip);
this.ready = false;
}
async openPromise(p, flags, mode) {
return this.openSync(p, flags, mode);
}
openSync(p, flags, mode) {
const fd = this.nextFd++;
this.fds.set(fd, {
cursor: 0,
p
});
return fd;
}
async readPromise(fd, buffer, offset, length, position) {
return this.readSync(fd, buffer, offset, length, position);
}
readSync(fd, buffer, offset = 0, length = 0, position = -1) {
const entry = this.fds.get(fd);
if (typeof entry === `undefined`) throw errors.EBADF(`read`);
let realPosition;
if (position === -1 || position === null) realPosition = entry.cursor;else realPosition = position;
const source = this.readFileSync(entry.p);
source.copy(buffer, offset, realPosition, realPosition + length);
const bytesRead = Math.max(0, Math.min(source.length - realPosition, length));
if (position === -1) entry.cursor += bytesRead;
return bytesRead;
}
async writePromise(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return this.writeSync(fd, buffer, position);
} else {
return this.writeSync(fd, buffer, offset, length, position);
chmodSync(p, mask) {
if (this.readOnly)
throw errors.EROFS(`chmod '${p}'`);
const resolvedP = this.resolveFilename(`chmod '${p}'`, p, false);
// We silently ignore chmod requests for directories
if (this.listings.has(resolvedP))
return;
const entry = this.entries.get(resolvedP);
if (typeof entry === `undefined`)
throw new Error(`Assertion failed: The entry should have been registered (${resolvedP})`);
const oldMod = this.getUnixMode(entry, S_IFREG | 0o000);
const newMod = oldMod & (~0o777) | mask;
const rc = this.libzip.file.setExternalAttributes(this.zip, entry, 0, 0, this.libzip.ZIP_OPSYS_UNIX, newMod << 16);
if (rc === -1) {
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
}
}
}
writeSync(fd, buffer, offset, length, position) {
const entry = this.fds.get(fd);
if (typeof entry === `undefined`) throw errors.EBADF(`read`);
throw new Error(`Unimplemented`);
}
async closePromise(fd) {
return this.closeSync(fd);
}
closeSync(fd) {
const entry = this.fds.get(fd);
if (typeof entry === `undefined`) throw errors.EBADF(`read`);
this.fds.delete(fd);
}
createReadStream(p, {
encoding
} = {}) {
if (p === null) throw new Error(`Unimplemented`);
const stream = Object.assign(new _stream.PassThrough(), {
bytesRead: 0,
path: p,
close: () => {
clearImmediate(immediate);
}
});
const immediate = setImmediate(() => {
try {
const data = this.readFileSync(p, encoding);
stream.bytesRead = data.length;
stream.write(data);
stream.end();
} catch (error) {
stream.emit(`error`, error);
stream.end();
}
});
return stream;
}
createWriteStream(p, {
encoding
} = {}) {
if (this.readOnly) throw errors.EROFS(`open '${p}'`);
if (p === null) throw new Error(`Unimplemented`);
const stream = Object.assign(new _stream.PassThrough(), {
bytesWritten: 0,
path: p,
close: () => {
stream.end();
}
});
const chunks = [];
stream.on(`data`, chunk => {
const chunkBuffer = Buffer.from(chunk);
stream.bytesWritten += chunkBuffer.length;
chunks.push(chunkBuffer);
});
stream.on(`end`, () => {
this.writeFileSync(p, Buffer.concat(chunks), encoding);
});
return stream;
}
async realpathPromise(p) {
return this.realpathSync(p);
}
realpathSync(p) {
const resolvedP = this.resolveFilename(`lstat '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw errors.ENOENT(`lstat '${p}'`);
return resolvedP;
}
async existsPromise(p) {
return this.existsSync(p);
}
existsSync(p) {
let resolvedP;
try {
resolvedP = this.resolveFilename(`stat '${p}'`, p);
} catch (error) {
return false;
async renamePromise(oldP, newP) {
return this.renameSync(oldP, newP);
}
return this.entries.has(resolvedP) || this.listings.has(resolvedP);
}
async accessPromise(p, mode) {
return this.accessSync(p, mode);
}
accessSync(p, mode = _fs.constants.F_OK) {
const resolvedP = this.resolveFilename(`access '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw errors.ENOENT(`access '${p}'`);
if (this.readOnly && mode & _fs.constants.W_OK) {
throw errors.EROFS(`access '${p}'`);
renameSync(oldP, newP) {
throw new Error(`Unimplemented`);
}
}
async statPromise(p) {
return this.statSync(p);
}
statSync(p) {
const resolvedP = this.resolveFilename(`stat '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw errors.ENOENT(`stat '${p}'`);
if (p[p.length - 1] === `/` && !this.listings.has(resolvedP)) throw errors.ENOTDIR(`stat '${p}'`);
return this.statImpl(`stat '${p}'`, resolvedP);
}
async lstatPromise(p) {
return this.lstatSync(p);
}
lstatSync(p) {
const resolvedP = this.resolveFilename(`lstat '${p}'`, p, false);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw errors.ENOENT(`lstat '${p}'`);
if (p[p.length - 1] === `/` && !this.listings.has(resolvedP)) throw errors.ENOTDIR(`lstat '${p}'`);
return this.statImpl(`lstat '${p}'`, resolvedP);
}
statImpl(reason, p) {
const entry = this.entries.get(p); // File, or explicit directory
if (typeof entry !== `undefined`) {
const stat = _libzip.default.struct.statS();
const rc = _libzip.default.statIndex(this.zip, entry, 0, 0, stat);
if (rc === -1) throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
const uid = this.stats.uid;
const gid = this.stats.gid;
const size = _libzip.default.struct.statSize(stat) >>> 0;
const blksize = 512;
const blocks = Math.ceil(size / blksize);
const mtimeMs = (_libzip.default.struct.statMtime(stat) >>> 0) * 1000;
const atimeMs = mtimeMs;
const birthtimeMs = mtimeMs;
const ctimeMs = mtimeMs;
const atime = new Date(atimeMs);
const birthtime = new Date(birthtimeMs);
const ctime = new Date(ctimeMs);
const mtime = new Date(mtimeMs);
const type = this.listings.has(p) ? S_IFDIR : S_IFREG;
const defaultMode = type === S_IFDIR ? 0o755 : 0o644;
const mode = type | this.getUnixMode(entry, defaultMode) & 0o777;
return Object.assign(new StatEntry(), {
uid,
gid,
size,
blksize,
blocks,
atime,
birthtime,
ctime,
mtime,
atimeMs,
birthtimeMs,
ctimeMs,
mtimeMs,
mode
});
} // Implicit directory
if (this.listings.has(p)) {
const uid = this.stats.uid;
const gid = this.stats.gid;
const size = 0;
const blksize = 512;
const blocks = 0;
const atimeMs = this.stats.mtimeMs;
const birthtimeMs = this.stats.mtimeMs;
const ctimeMs = this.stats.mtimeMs;
const mtimeMs = this.stats.mtimeMs;
const atime = new Date(atimeMs);
const birthtime = new Date(birthtimeMs);
const ctime = new Date(ctimeMs);
const mtime = new Date(mtimeMs);
const mode = S_IFDIR | 0o755;
return Object.assign(new StatEntry(), {
uid,
gid,
size,
blksize,
blocks,
atime,
birthtime,
ctime,
mtime,
atimeMs,
birthtimeMs,
ctimeMs,
mtimeMs,
mode
});
async copyFilePromise(sourceP, destP, flags) {
return this.copyFileSync(sourceP, destP, flags);
}
throw new Error(`Unreachable`);
}
getUnixMode(index, defaultMode) {
const rc = _libzip.default.file.getExternalAttributes(this.zip, index, 0, 0, _libzip.default.uint08S, _libzip.default.uint32S);
if (rc === -1) throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
const opsys = _libzip.default.getValue(_libzip.default.uint08S, `i8`) >>> 0;
if (opsys !== _libzip.default.ZIP_OPSYS_UNIX) return defaultMode;
return _libzip.default.getValue(_libzip.default.uint32S, `i32`) >>> 16;
}
registerListing(p) {
let listing = this.listings.get(p);
if (listing) return listing;
const parentListing = this.registerListing(_path.ppath.dirname(p));
listing = new Set();
parentListing.add(_path.ppath.basename(p));
this.listings.set(p, listing);
return listing;
}
registerEntry(p, index) {
const parentListing = this.registerListing(_path.ppath.dirname(p));
parentListing.add(_path.ppath.basename(p));
this.entries.set(p, index);
}
resolveFilename(reason, p, resolveLastComponent = true) {
if (!this.ready) throw errors.EBUSY(`archive closed, ${reason}`);
let resolvedP = _path.ppath.resolve(_path.PortablePath.root, p);
if (resolvedP === `/`) return _path.PortablePath.root;
while (true) {
const parentP = this.resolveFilename(reason, _path.ppath.dirname(resolvedP), true);
const isDir = this.listings.has(parentP);
const doesExist = this.entries.has(parentP);
if (!isDir && !doesExist) throw errors.ENOENT(reason);
if (!isDir) throw errors.ENOTDIR(reason);
resolvedP = _path.ppath.resolve(parentP, _path.ppath.basename(resolvedP));
if (!resolveLastComponent) break;
const index = _libzip.default.name.locate(this.zip, resolvedP);
if (index === -1) break;
if (this.isSymbolicLink(index)) {
const target = this.getFileSource(index).toString();
resolvedP = _path.ppath.resolve(_path.ppath.dirname(resolvedP), target);
} else {
break;
}
copyFileSync(sourceP, destP, flags = 0) {
if (this.readOnly)
throw errors.EROFS(`copyfile '${sourceP} -> '${destP}'`);
if ((flags & fs_1.constants.COPYFILE_FICLONE_FORCE) !== 0)
throw errors.ENOSYS(`unsupported clone operation`, `copyfile '${sourceP}' -> ${destP}'`);
const resolvedSourceP = this.resolveFilename(`copyfile '${sourceP} -> ${destP}'`, sourceP);
const indexSource = this.entries.get(resolvedSourceP);
if (typeof indexSource === `undefined`)
throw errors.EINVAL(`copyfile '${sourceP}' -> '${destP}'`);
const resolvedDestP = this.resolveFilename(`copyfile '${sourceP}' -> ${destP}'`, destP);
const indexDest = this.entries.get(resolvedDestP);
if ((flags & (fs_1.constants.COPYFILE_EXCL | fs_1.constants.COPYFILE_FICLONE_FORCE)) !== 0 && typeof indexDest !== `undefined`)
throw errors.EEXIST(`copyfile '${sourceP}' -> '${destP}'`);
const source = this.getFileSource(indexSource);
const newIndex = this.setFileSource(resolvedDestP, source);
if (newIndex !== indexDest) {
this.registerEntry(resolvedDestP, newIndex);
}
}
return resolvedP;
}
allocateBuffer(content) {
if (!Buffer.isBuffer(content)) content = Buffer.from(content);
const buffer = _libzip.default.malloc(content.byteLength);
if (!buffer) throw new Error(`Couldn't allocate enough memory`); // Copy the file into the Emscripten heap
const heap = new Uint8Array(_libzip.default.HEAPU8.buffer, buffer, content.byteLength);
heap.set(content);
return {
buffer,
byteLength: content.byteLength
};
}
allocateUnattachedSource(content) {
const error = _libzip.default.struct.errorS();
const {
buffer,
byteLength
} = this.allocateBuffer(content);
const source = _libzip.default.source.fromUnattachedBuffer(buffer, byteLength, 0, true, error);
if (source === 0) {
_libzip.default.free(error);
throw new Error(_libzip.default.error.strerror(error));
async appendFilePromise(p, content, opts) {
return this.appendFileSync(p, content, opts);
}
return source;
}
allocateSource(content) {
const {
buffer,
byteLength
} = this.allocateBuffer(content);
const source = _libzip.default.source.fromBuffer(this.zip, buffer, byteLength, 0, true);
if (source === 0) {
_libzip.default.free(buffer);
throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
appendFileSync(p, content, opts = {}) {
if (this.readOnly)
throw errors.EROFS(`open '${p}'`);
if (typeof opts === `undefined`)
opts = { flag: `a` };
else if (typeof opts === `string`)
opts = { flag: `a`, encoding: opts };
else if (typeof opts.flag === `undefined`)
opts = Object.assign({ flag: `a` }, opts);
return this.writeFileSync(p, content, opts);
}
return source;
}
setFileSource(p, content) {
const target = _path.ppath.relative(_path.PortablePath.root, p);
const lzSource = this.allocateSource(content);
try {
return _libzip.default.file.add(this.zip, target, lzSource, _libzip.default.ZIP_FL_OVERWRITE);
} catch (error) {
_libzip.default.source.free(lzSource);
throw error;
async writeFilePromise(p, content, opts) {
return this.writeFileSync(p, content, opts);
}
}
isSymbolicLink(index) {
const attrs = _libzip.default.file.getExternalAttributes(this.zip, index, 0, 0, _libzip.default.uint08S, _libzip.default.uint32S);
if (attrs === -1) throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
const opsys = _libzip.default.getValue(_libzip.default.uint08S, `i8`) >>> 0;
if (opsys !== _libzip.default.ZIP_OPSYS_UNIX) return false;
const attributes = _libzip.default.getValue(_libzip.default.uint32S, `i32`) >>> 16;
return (attributes & S_IFMT) === S_IFLNK;
}
getFileSource(index) {
const stat = _libzip.default.struct.statS();
const rc = _libzip.default.statIndex(this.zip, index, 0, 0, stat);
if (rc === -1) throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
const size = _libzip.default.struct.statSize(stat);
const buffer = _libzip.default.malloc(size);
try {
const file = _libzip.default.fopenIndex(this.zip, index, 0, 0);
if (file === 0) throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
try {
const rc = _libzip.default.fread(file, buffer, size, 0);
if (rc === -1) throw new Error(_libzip.default.error.strerror(_libzip.default.file.getError(file)));else if (rc < size) throw new Error(`Incomplete read`);else if (rc > size) throw new Error(`Overread`);
const memory = _libzip.default.HEAPU8.subarray(buffer, buffer + size);
const data = Buffer.from(memory);
return data;
} finally {
_libzip.default.fclose(file);
}
} finally {
_libzip.default.free(buffer);
writeFileSync(p, content, opts) {
if (typeof p !== `string`)
throw errors.EBADF(`read`);
if (this.readOnly)
throw errors.EROFS(`open '${p}'`);
const resolvedP = this.resolveFilename(`open '${p}'`, p);
if (this.listings.has(resolvedP))
throw errors.EISDIR(`open '${p}'`);
const index = this.entries.get(resolvedP);
if (index !== undefined && typeof opts === `object` && opts.flag && opts.flag.includes(`a`))
content = Buffer.concat([this.getFileSource(index), Buffer.from(content)]);
let encoding = null;
if (typeof opts === `string`)
encoding = opts;
else if (typeof opts === `object` && opts.encoding)
encoding = opts.encoding;
if (encoding !== null)
content = content.toString(encoding);
const newIndex = this.setFileSource(resolvedP, content);
if (newIndex !== index) {
this.registerEntry(resolvedP, newIndex);
}
}
}
async chmodPromise(p, mask) {
return this.chmodSync(p, mask);
}
chmodSync(p, mask) {
if (this.readOnly) throw errors.EROFS(`chmod '${p}'`);
const resolvedP = this.resolveFilename(`chmod '${p}'`, p, false); // We silently ignore chmod requests for directories
if (this.listings.has(resolvedP)) return;
const entry = this.entries.get(resolvedP);
if (typeof entry === `undefined`) throw new Error(`Assertion failed: The entry should have been registered (${resolvedP})`);
const oldMod = this.getUnixMode(entry, S_IFREG | 0o000);
const newMod = oldMod & ~0o777 | mask;
const rc = _libzip.default.file.setExternalAttributes(this.zip, entry, 0, 0, _libzip.default.ZIP_OPSYS_UNIX, newMod << 16);
if (rc === -1) {
throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
async unlinkPromise(p) {
return this.unlinkSync(p);
}
}
async renamePromise(oldP, newP) {
return this.renameSync(oldP, newP);
}
renameSync(oldP, newP) {
throw new Error(`Unimplemented`);
}
async copyFilePromise(sourceP, destP, flags) {
return this.copyFileSync(sourceP, destP, flags);
}
copyFileSync(sourceP, destP, flags = 0) {
if (this.readOnly) throw errors.EROFS(`copyfile '${sourceP} -> '${destP}'`);
if ((flags & _fs.constants.COPYFILE_FICLONE_FORCE) !== 0) throw errors.ENOSYS(`unsupported clone operation`, `copyfile '${sourceP}' -> ${destP}'`);
const resolvedSourceP = this.resolveFilename(`copyfile '${sourceP} -> ${destP}'`, sourceP);
const indexSource = this.entries.get(resolvedSourceP);
if (typeof indexSource === `undefined`) throw errors.EINVAL(`copyfile '${sourceP}' -> '${destP}'`);
const resolvedDestP = this.resolveFilename(`copyfile '${sourceP}' -> ${destP}'`, destP);
const indexDest = this.entries.get(resolvedDestP);
if ((flags & (_fs.constants.COPYFILE_EXCL | _fs.constants.COPYFILE_FICLONE_FORCE)) !== 0 && typeof indexDest !== `undefined`) throw errors.EEXIST(`copyfile '${sourceP}' -> '${destP}'`);
const source = this.getFileSource(indexSource);
const newIndex = this.setFileSource(resolvedDestP, source);
if (newIndex !== indexDest) {
this.registerEntry(resolvedDestP, newIndex);
unlinkSync(p) {
throw new Error(`Unimplemented`);
}
}
async appendFilePromise(p, content, opts) {
return this.appendFileSync(p, content, opts);
}
appendFileSync(p, content, opts = {}) {
if (this.readOnly) throw errors.EROFS(`open '${p}'`);
if (typeof opts === `undefined`) opts = {
flag: `a`
};else if (typeof opts === `string`) opts = {
flag: `a`,
encoding: opts
};else if (typeof opts.flag === `undefined`) opts = {
flag: `a`,
...opts
};
return this.writeFileSync(p, content, opts);
}
async writeFilePromise(p, content, opts) {
return this.writeFileSync(p, content, opts);
}
writeFileSync(p, content, opts) {
if (typeof p !== `string`) throw errors.EBADF(`read`);
if (this.readOnly) throw errors.EROFS(`open '${p}'`);
const resolvedP = this.resolveFilename(`open '${p}'`, p);
if (this.listings.has(resolvedP)) throw errors.EISDIR(`open '${p}'`);
const index = this.entries.get(resolvedP);
if (index !== undefined && typeof opts === `object` && opts.flag && opts.flag.includes(`a`)) content = Buffer.concat([this.getFileSource(index), Buffer.from(content)]);
let encoding = null;
if (typeof opts === `string`) encoding = opts;else if (typeof opts === `object` && opts.encoding) encoding = opts.encoding;
if (encoding !== null) content = content.toString(encoding);
const newIndex = this.setFileSource(resolvedP, content);
if (newIndex !== index) {
this.registerEntry(resolvedP, newIndex);
async utimesPromise(p, atime, mtime) {
return this.utimesSync(p, atime, mtime);
}
}
async unlinkPromise(p) {
return this.unlinkSync(p);
}
unlinkSync(p) {
throw new Error(`Unimplemented`);
}
async utimesPromise(p, atime, mtime) {
return this.utimesSync(p, atime, mtime);
}
utimesSync(p, atime, mtime) {
if (this.readOnly) throw errors.EROFS(`utimes '${p}'`);
const resolvedP = this.resolveFilename(`utimes '${p}'`, p);
this.utimesImpl(resolvedP, mtime);
}
async lutimesPromise(p, atime, mtime) {
return this.lutimesSync(p, atime, mtime);
}
lutimesSync(p, atime, mtime) {
if (this.readOnly) throw errors.EROFS(`lutimes '${p}'`);
const resolvedP = this.resolveFilename(`utimes '${p}'`, p, false);
this.utimesImpl(resolvedP, mtime);
}
utimesImpl(resolvedP, mtime) {
if (this.listings.has(resolvedP)) if (!this.entries.has(resolvedP)) this.hydrateDirectory(resolvedP);
const entry = this.entries.get(resolvedP);
if (entry === undefined) throw new Error(`Unreachable`);
const rc = _libzip.default.file.setMtime(this.zip, entry, 0, toUnixTimestamp(mtime), 0);
if (rc === -1) {
throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
utimesSync(p, atime, mtime) {
if (this.readOnly)
throw errors.EROFS(`utimes '${p}'`);
const resolvedP = this.resolveFilename(`utimes '${p}'`, p);
this.utimesImpl(resolvedP, mtime);
}
}
async mkdirPromise(p, opts) {
return this.mkdirSync(p, opts);
}
mkdirSync(p, opts) {
if (opts && opts.recursive) return this.mkdirpSync(p, {
chmod: opts.mode
});
if (this.readOnly) throw errors.EROFS(`mkdir '${p}'`);
const resolvedP = this.resolveFilename(`mkdir '${p}'`, p);
if (this.entries.has(resolvedP) || this.listings.has(resolvedP)) throw errors.EEXIST(`mkdir '${p}'`);
this.hydrateDirectory(resolvedP);
}
async rmdirPromise(p) {
return this.rmdirSync(p);
}
rmdirSync(p) {
throw new Error(`Unimplemented`);
}
hydrateDirectory(resolvedP) {
const index = _libzip.default.dir.add(this.zip, _path.ppath.relative(_path.PortablePath.root, resolvedP));
if (index === -1) throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
this.registerListing(resolvedP);
this.registerEntry(resolvedP, index);
return index;
}
async symlinkPromise(target, p) {
return this.symlinkSync(target, p);
}
symlinkSync(target, p) {
if (this.readOnly) throw errors.EROFS(`symlink '${target}' -> '${p}'`);
const resolvedP = this.resolveFilename(`symlink '${target}' -> '${p}'`, p);
if (this.listings.has(resolvedP)) throw errors.EISDIR(`symlink '${target}' -> '${p}'`);
if (this.entries.has(resolvedP)) throw errors.EEXIST(`symlink '${target}' -> '${p}'`);
const index = this.setFileSource(resolvedP, target);
this.registerEntry(resolvedP, index);
const rc = _libzip.default.file.setExternalAttributes(this.zip, index, 0, 0, _libzip.default.ZIP_OPSYS_UNIX, (0o120000 | 0o777) << 16);
if (rc === -1) {
throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
async lutimesPromise(p, atime, mtime) {
return this.lutimesSync(p, atime, mtime);
}
}
async readFilePromise(p, encoding) {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return this.readFileSync(p, encoding);
default:
return this.readFileSync(p, encoding);
lutimesSync(p, atime, mtime) {
if (this.readOnly)
throw errors.EROFS(`lutimes '${p}'`);
const resolvedP = this.resolveFilename(`utimes '${p}'`, p, false);
this.utimesImpl(resolvedP, mtime);
}
}
readFileSync(p, encoding) {
if (typeof p !== `string`) throw errors.EBADF(`read`); // This is messed up regarding the TS signatures
if (typeof encoding === `object`) // @ts-ignore
encoding = encoding ? encoding.encoding : undefined;
const resolvedP = this.resolveFilename(`open '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw errors.ENOENT(`open '${p}'`); // Ensures that the last component is a directory, if the user said so (even if it is we'll throw right after with EISDIR anyway)
if (p[p.length - 1] === `/` && !this.listings.has(resolvedP)) throw errors.ENOTDIR(`open '${p}'`);
if (this.listings.has(resolvedP)) throw errors.EISDIR(`read`);
const entry = this.entries.get(resolvedP);
if (entry === undefined) throw new Error(`Unreachable`);
const data = this.getFileSource(entry);
return encoding ? data.toString(encoding) : data;
}
async readdirPromise(p, {
withFileTypes
} = {}) {
return this.readdirSync(p, {
withFileTypes: withFileTypes
});
}
readdirSync(p, {
withFileTypes
} = {}) {
const resolvedP = this.resolveFilename(`scandir '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw errors.ENOENT(`scandir '${p}'`);
const directoryListing = this.listings.get(resolvedP);
if (!directoryListing) throw errors.ENOTDIR(`scandir '${p}'`);
const entries = [...directoryListing];
if (!withFileTypes) return entries;
return entries.map(name => {
return Object.assign(this.statImpl(`lstat`, _path.ppath.join(p, name)), {
name
});
});
}
async readlinkPromise(p) {
return this.readlinkSync(p);
}
readlinkSync(p) {
const resolvedP = this.resolveFilename(`readlink '${p}'`, p, false);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw errors.ENOENT(`readlink '${p}'`); // Ensure that the last component is a directory (if it is we'll throw right after with EISDIR anyway)
if (p[p.length - 1] === `/` && !this.listings.has(resolvedP)) throw errors.ENOTDIR(`open '${p}'`);
if (this.listings.has(resolvedP)) throw errors.EINVAL(`readlink '${p}'`);
const entry = this.entries.get(resolvedP);
if (entry === undefined) throw new Error(`Unreachable`);
const rc = _libzip.default.file.getExternalAttributes(this.zip, entry, 0, 0, _libzip.default.uint08S, _libzip.default.uint32S);
if (rc === -1) throw new Error(_libzip.default.error.strerror(_libzip.default.getError(this.zip)));
const opsys = _libzip.default.getValue(_libzip.default.uint08S, `i8`) >>> 0;
if (opsys !== _libzip.default.ZIP_OPSYS_UNIX) throw errors.EINVAL(`readlink '${p}'`);
const attributes = _libzip.default.getValue(_libzip.default.uint32S, `i32`) >>> 16;
if ((attributes & 0o170000) !== 0o120000) throw errors.EINVAL(`readlink '${p}'`);
return this.getFileSource(entry).toString();
}
watch(p, a, b) {
let persistent;
switch (typeof a) {
case `function`:
case `string`:
case `undefined`:
{
persistent = true;
utimesImpl(resolvedP, mtime) {
if (this.listings.has(resolvedP))
if (!this.entries.has(resolvedP))
this.hydrateDirectory(resolvedP);
const entry = this.entries.get(resolvedP);
if (entry === undefined)
throw new Error(`Unreachable`);
const rc = this.libzip.file.setMtime(this.zip, entry, 0, toUnixTimestamp(mtime), 0);
if (rc === -1) {
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
}
break;
default:
{
// @ts-ignore
({
persistent = true
} = a);
}
async mkdirPromise(p, opts) {
return this.mkdirSync(p, opts);
}
mkdirSync(p, opts) {
if (opts && opts.recursive)
return this.mkdirpSync(p, { chmod: opts.mode });
if (this.readOnly)
throw errors.EROFS(`mkdir '${p}'`);
const resolvedP = this.resolveFilename(`mkdir '${p}'`, p);
if (this.entries.has(resolvedP) || this.listings.has(resolvedP))
throw errors.EEXIST(`mkdir '${p}'`);
this.hydrateDirectory(resolvedP);
}
async rmdirPromise(p) {
return this.rmdirSync(p);
}
rmdirSync(p) {
throw new Error(`Unimplemented`);
}
hydrateDirectory(resolvedP) {
const index = this.libzip.dir.add(this.zip, path_1.ppath.relative(path_1.PortablePath.root, resolvedP));
if (index === -1)
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
this.registerListing(resolvedP);
this.registerEntry(resolvedP, index);
return index;
}
async symlinkPromise(target, p) {
return this.symlinkSync(target, p);
}
symlinkSync(target, p) {
if (this.readOnly)
throw errors.EROFS(`symlink '${target}' -> '${p}'`);
const resolvedP = this.resolveFilename(`symlink '${target}' -> '${p}'`, p);
if (this.listings.has(resolvedP))
throw errors.EISDIR(`symlink '${target}' -> '${p}'`);
if (this.entries.has(resolvedP))
throw errors.EEXIST(`symlink '${target}' -> '${p}'`);
const index = this.setFileSource(resolvedP, target);
this.registerEntry(resolvedP, index);
const rc = this.libzip.file.setExternalAttributes(this.zip, index, 0, 0, this.libzip.ZIP_OPSYS_UNIX, (0o120000 | 0o777) << 16);
if (rc === -1) {
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
}
break;
}
if (!persistent) return {
on: () => {},
close: () => {}
};
const interval = setInterval(() => {}, 24 * 60 * 60 * 1000);
return {
on: () => {},
close: () => {
clearInterval(interval);
}
};
}
async readFilePromise(p, encoding) {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return this.readFileSync(p, encoding);
default:
return this.readFileSync(p, encoding);
}
}
readFileSync(p, encoding) {
if (typeof p !== `string`)
throw errors.EBADF(`read`);
// This is messed up regarding the TS signatures
if (typeof encoding === `object`)
// @ts-ignore
encoding = encoding ? encoding.encoding : undefined;
const resolvedP = this.resolveFilename(`open '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP))
throw errors.ENOENT(`open '${p}'`);
// Ensures that the last component is a directory, if the user said so (even if it is we'll throw right after with EISDIR anyway)
if (p[p.length - 1] === `/` && !this.listings.has(resolvedP))
throw errors.ENOTDIR(`open '${p}'`);
if (this.listings.has(resolvedP))
throw errors.EISDIR(`read`);
const entry = this.entries.get(resolvedP);
if (entry === undefined)
throw new Error(`Unreachable`);
const data = this.getFileSource(entry);
return encoding ? data.toString(encoding) : data;
}
async readdirPromise(p, { withFileTypes } = {}) {
return this.readdirSync(p, { withFileTypes: withFileTypes });
}
readdirSync(p, { withFileTypes } = {}) {
const resolvedP = this.resolveFilename(`scandir '${p}'`, p);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP))
throw errors.ENOENT(`scandir '${p}'`);
const directoryListing = this.listings.get(resolvedP);
if (!directoryListing)
throw errors.ENOTDIR(`scandir '${p}'`);
const entries = [...directoryListing];
if (!withFileTypes)
return entries;
return entries.map(name => {
return Object.assign(this.statImpl(`lstat`, path_1.ppath.join(p, name)), {
name,
});
});
}
async readlinkPromise(p) {
return this.readlinkSync(p);
}
readlinkSync(p) {
const resolvedP = this.resolveFilename(`readlink '${p}'`, p, false);
if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP))
throw errors.ENOENT(`readlink '${p}'`);
// Ensure that the last component is a directory (if it is we'll throw right after with EISDIR anyway)
if (p[p.length - 1] === `/` && !this.listings.has(resolvedP))
throw errors.ENOTDIR(`open '${p}'`);
if (this.listings.has(resolvedP))
throw errors.EINVAL(`readlink '${p}'`);
const entry = this.entries.get(resolvedP);
if (entry === undefined)
throw new Error(`Unreachable`);
const rc = this.libzip.file.getExternalAttributes(this.zip, entry, 0, 0, this.libzip.uint08S, this.libzip.uint32S);
if (rc === -1)
throw new Error(this.libzip.error.strerror(this.libzip.getError(this.zip)));
const opsys = this.libzip.getValue(this.libzip.uint08S, `i8`) >>> 0;
if (opsys !== this.libzip.ZIP_OPSYS_UNIX)
throw errors.EINVAL(`readlink '${p}'`);
const attributes = this.libzip.getValue(this.libzip.uint32S, `i32`) >>> 16;
if ((attributes & 0o170000) !== 0o120000)
throw errors.EINVAL(`readlink '${p}'`);
return this.getFileSource(entry).toString();
}
watch(p, a, b) {
let persistent;
switch (typeof a) {
case `function`:
case `string`:
case `undefined`:
{
persistent = true;
}
break;
default:
{
// @ts-ignore
({ persistent = true } = a);
}
break;
}
if (!persistent)
return { on: () => { }, close: () => { } };
const interval = setInterval(() => { }, 24 * 60 * 60 * 1000);
return { on: () => { }, close: () => { clearInterval(interval); } };
}
}
exports.ZipFS = ZipFS;
;
;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ZipOpenFS = void 0;
var _fs = require("fs");
var _FakeFS = require("./FakeFS");
var _NodeFS = require("./NodeFS");
var _ZipFS = require("./ZipFS");
var _path = require("./path");
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const FakeFS_1 = require("./FakeFS");
const NodeFS_1 = require("./NodeFS");
const ZipFS_1 = require("./ZipFS");
const path_1 = require("./path");
const ZIP_FD = 0x80000000;
class ZipOpenFS extends _FakeFS.BasePortableFakeFS {
static open(fn) {
const zipOpenFs = new ZipOpenFS();
try {
return fn(zipOpenFs);
} finally {
zipOpenFs.saveAndClose();
class ZipOpenFS extends FakeFS_1.BasePortableFakeFS {
constructor({ libzip, baseFs = new NodeFS_1.NodeFS(), filter = null, maxOpenFiles = Infinity, readOnlyArchives = false, useCache = true }) {
super();
this.fdMap = new Map();
this.nextFd = 3;
this.isZip = new Set();
this.notZip = new Set();
this.libzip = libzip;
this.baseFs = baseFs;
this.zipInstances = useCache ? new Map() : null;
this.filter = filter;
this.maxOpenFiles = maxOpenFiles;
this.readOnlyArchives = readOnlyArchives;
this.isZip = new Set();
this.notZip = new Set();
}
}
static async openPromise(fn) {
const zipOpenFs = new ZipOpenFS();
try {
return await fn(zipOpenFs);
} finally {
zipOpenFs.saveAndClose();
static async openPromise(fn, opts) {
const zipOpenFs = new ZipOpenFS(opts);
try {
return await fn(zipOpenFs);
}
finally {
zipOpenFs.saveAndClose();
}
}
}
constructor({
baseFs = new _NodeFS.NodeFS(),
filter = null,
maxOpenFiles = Infinity,
readOnlyArchives = false,
useCache = true
} = {}) {
super();
this.baseFs = void 0;
this.zipInstances = void 0;
this.fdMap = new Map();
this.nextFd = 3;
this.filter = void 0;
this.maxOpenFiles = void 0;
this.readOnlyArchives = void 0;
this.isZip = new Set();
this.notZip = new Set();
this.baseFs = baseFs;
this.zipInstances = useCache ? new Map() : null;
this.filter = filter;
this.maxOpenFiles = maxOpenFiles;
this.readOnlyArchives = readOnlyArchives;
this.isZip = new Set();
this.notZip = new Set();
}
getRealPath() {
return this.baseFs.getRealPath();
}
saveAndClose() {
if (this.zipInstances) {
for (const [path, zipFs] of this.zipInstances.entries()) {
zipFs.saveAndClose();
this.zipInstances.delete(path);
}
getRealPath() {
return this.baseFs.getRealPath();
}
}
discardAndClose() {
if (this.zipInstances) {
for (const [path, zipFs] of this.zipInstances.entries()) {
zipFs.discardAndClose();
this.zipInstances.delete(path);
}
saveAndClose() {
if (this.zipInstances) {
for (const [path, zipFs] of this.zipInstances.entries()) {
zipFs.saveAndClose();
this.zipInstances.delete(path);
}
}
}
}
remapFd(zipFs, fd) {
const remappedFd = this.nextFd++ | ZIP_FD;
this.fdMap.set(remappedFd, [zipFs, fd]);
return remappedFd;
}
async openPromise(p, flags, mode) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.openPromise(p, flags, mode);
}, async (zipFs, {
subPath
}) => {
return this.remapFd(zipFs, (await zipFs.openPromise(subPath, flags, mode)));
});
}
openSync(p, flags, mode) {
return this.makeCallSync(p, () => {
return this.baseFs.openSync(p, flags, mode);
}, (zipFs, {
subPath
}) => {
return this.remapFd(zipFs, zipFs.openSync(subPath, flags, mode));
});
}
async readPromise(fd, buffer, offset, length, position) {
if ((fd & ZIP_FD) === 0) return await this.baseFs.readPromise(fd, buffer, offset, length, position);
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`) throw Object.assign(new Error(`EBADF: bad file descriptor, read`), {
code: `EBADF`
});
const [zipFs, realFd] = entry;
return await zipFs.readPromise(realFd, buffer, offset, length, position);
}
readSync(fd, buffer, offset, length, position) {
if ((fd & ZIP_FD) === 0) return this.baseFs.readSync(fd, buffer, offset, length, position);
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`) throw Object.assign(new Error(`EBADF: bad file descriptor, read`), {
code: `EBADF`
});
const [zipFs, realFd] = entry;
return zipFs.readSync(realFd, buffer, offset, length, position);
}
async writePromise(fd, buffer, offset, length, position) {
if ((fd & ZIP_FD) === 0) {
if (typeof buffer === `string`) {
return await this.baseFs.writePromise(fd, buffer, offset);
} else {
return await this.baseFs.writePromise(fd, buffer, offset, length, position);
}
discardAndClose() {
if (this.zipInstances) {
for (const [path, zipFs] of this.zipInstances.entries()) {
zipFs.discardAndClose();
this.zipInstances.delete(path);
}
}
}
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`) throw Object.assign(new Error(`EBADF: bad file descriptor, write`), {
code: `EBADF`
});
const [zipFs, realFd] = entry;
if (typeof buffer === `string`) {
return await zipFs.writePromise(realFd, buffer, offset);
} else {
return await zipFs.writePromise(realFd, buffer, offset, length, position);
remapFd(zipFs, fd) {
const remappedFd = this.nextFd++ | ZIP_FD;
this.fdMap.set(remappedFd, [zipFs, fd]);
return remappedFd;
}
}
writeSync(fd, buffer, offset, length, position) {
if ((fd & ZIP_FD) === 0) {
if (typeof buffer === `string`) {
return this.baseFs.writeSync(fd, buffer, offset);
} else {
return this.baseFs.writeSync(fd, buffer, offset, length, position);
}
async openPromise(p, flags, mode) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.openPromise(p, flags, mode);
}, async (zipFs, { subPath }) => {
return this.remapFd(zipFs, await zipFs.openPromise(subPath, flags, mode));
});
}
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`) throw Object.assign(new Error(`EBADF: bad file descriptor, write`), {
code: `EBADF`
});
const [zipFs, realFd] = entry;
if (typeof buffer === `string`) {
return zipFs.writeSync(realFd, buffer, offset);
} else {
return zipFs.writeSync(realFd, buffer, offset, length, position);
openSync(p, flags, mode) {
return this.makeCallSync(p, () => {
return this.baseFs.openSync(p, flags, mode);
}, (zipFs, { subPath }) => {
return this.remapFd(zipFs, zipFs.openSync(subPath, flags, mode));
});
}
}
async closePromise(fd) {
if ((fd & ZIP_FD) === 0) return await this.baseFs.closePromise(fd);
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`) throw Object.assign(new Error(`EBADF: bad file descriptor, close`), {
code: `EBADF`
});
this.fdMap.delete(fd);
const [zipFs, realFd] = entry;
return await zipFs.closePromise(realFd);
}
closeSync(fd) {
if ((fd & ZIP_FD) === 0) return this.baseFs.closeSync(fd);
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`) throw Object.assign(new Error(`EBADF: bad file descriptor, close`), {
code: `EBADF`
});
this.fdMap.delete(fd);
const [zipFs, realFd] = entry;
return zipFs.closeSync(realFd);
}
createReadStream(p, opts) {
if (p === null) return this.baseFs.createReadStream(p, opts);
return this.makeCallSync(p, () => {
return this.baseFs.createReadStream(p, opts);
}, (zipFs, {
subPath
}) => {
return zipFs.createReadStream(subPath, opts);
});
}
createWriteStream(p, opts) {
if (p === null) return this.baseFs.createWriteStream(p, opts);
return this.makeCallSync(p, () => {
return this.baseFs.createWriteStream(p, opts);
}, (zipFs, {
subPath
}) => {
return zipFs.createWriteStream(subPath, opts);
});
}
async realpathPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.realpathPromise(p);
}, async (zipFs, {
archivePath,
subPath
}) => {
return this.pathUtils.resolve((await this.baseFs.realpathPromise(archivePath)), this.pathUtils.relative(_path.PortablePath.root, (await zipFs.realpathPromise(subPath))));
});
}
realpathSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.realpathSync(p);
}, (zipFs, {
archivePath,
subPath
}) => {
return this.pathUtils.resolve(this.baseFs.realpathSync(archivePath), this.pathUtils.relative(_path.PortablePath.root, zipFs.realpathSync(subPath)));
});
}
async existsPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.existsPromise(p);
}, async (zipFs, {
subPath
}) => {
return await zipFs.existsPromise(subPath);
});
}
existsSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.existsSync(p);
}, (zipFs, {
subPath
}) => {
return zipFs.existsSync(subPath);
});
}
async accessPromise(p, mode) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.accessPromise(p, mode);
}, async (zipFs, {
subPath
}) => {
return await zipFs.accessPromise(subPath, mode);
});
}
accessSync(p, mode) {
return this.makeCallSync(p, () => {
return this.baseFs.accessSync(p, mode);
}, (zipFs, {
subPath
}) => {
return zipFs.accessSync(subPath, mode);
});
}
async statPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.statPromise(p);
}, async (zipFs, {
subPath
}) => {
return await zipFs.statPromise(subPath);
});
}
statSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.statSync(p);
}, (zipFs, {
subPath
}) => {
return zipFs.statSync(subPath);
});
}
async lstatPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.lstatPromise(p);
}, async (zipFs, {
subPath
}) => {
return await zipFs.lstatPromise(subPath);
});
}
lstatSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.lstatSync(p);
}, (zipFs, {
subPath
}) => {
return zipFs.lstatSync(subPath);
});
}
async chmodPromise(p, mask) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.chmodPromise(p, mask);
}, async (zipFs, {
subPath
}) => {
return await zipFs.chmodPromise(subPath, mask);
});
}
chmodSync(p, mask) {
return this.makeCallSync(p, () => {
return this.baseFs.chmodSync(p, mask);
}, (zipFs, {
subPath
}) => {
return zipFs.chmodSync(subPath, mask);
});
}
async renamePromise(oldP, newP) {
return await this.makeCallPromise(oldP, async () => {
return await this.makeCallPromise(newP, async () => {
return await this.baseFs.renamePromise(oldP, newP);
}, async () => {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {
code: `EEXDEV`
async readPromise(fd, buffer, offset, length, position) {
if ((fd & ZIP_FD) === 0)
return await this.baseFs.readPromise(fd, buffer, offset, length, position);
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`)
throw Object.assign(new Error(`EBADF: bad file descriptor, read`), { code: `EBADF` });
const [zipFs, realFd] = entry;
return await zipFs.readPromise(realFd, buffer, offset, length, position);
}
readSync(fd, buffer, offset, length, position) {
if ((fd & ZIP_FD) === 0)
return this.baseFs.readSync(fd, buffer, offset, length, position);
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`)
throw Object.assign(new Error(`EBADF: bad file descriptor, read`), { code: `EBADF` });
const [zipFs, realFd] = entry;
return zipFs.readSync(realFd, buffer, offset, length, position);
}
async writePromise(fd, buffer, offset, length, position) {
if ((fd & ZIP_FD) === 0) {
if (typeof buffer === `string`) {
return await this.baseFs.writePromise(fd, buffer, offset);
}
else {
return await this.baseFs.writePromise(fd, buffer, offset, length, position);
}
}
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`)
throw Object.assign(new Error(`EBADF: bad file descriptor, write`), { code: `EBADF` });
const [zipFs, realFd] = entry;
if (typeof buffer === `string`) {
return await zipFs.writePromise(realFd, buffer, offset);
}
else {
return await zipFs.writePromise(realFd, buffer, offset, length, position);
}
}
writeSync(fd, buffer, offset, length, position) {
if ((fd & ZIP_FD) === 0) {
if (typeof buffer === `string`) {
return this.baseFs.writeSync(fd, buffer, offset);
}
else {
return this.baseFs.writeSync(fd, buffer, offset, length, position);
}
}
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`)
throw Object.assign(new Error(`EBADF: bad file descriptor, write`), { code: `EBADF` });
const [zipFs, realFd] = entry;
if (typeof buffer === `string`) {
return zipFs.writeSync(realFd, buffer, offset);
}
else {
return zipFs.writeSync(realFd, buffer, offset, length, position);
}
}
async closePromise(fd) {
if ((fd & ZIP_FD) === 0)
return await this.baseFs.closePromise(fd);
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`)
throw Object.assign(new Error(`EBADF: bad file descriptor, close`), { code: `EBADF` });
this.fdMap.delete(fd);
const [zipFs, realFd] = entry;
return await zipFs.closePromise(realFd);
}
closeSync(fd) {
if ((fd & ZIP_FD) === 0)
return this.baseFs.closeSync(fd);
const entry = this.fdMap.get(fd);
if (typeof entry === `undefined`)
throw Object.assign(new Error(`EBADF: bad file descriptor, close`), { code: `EBADF` });
this.fdMap.delete(fd);
const [zipFs, realFd] = entry;
return zipFs.closeSync(realFd);
}
createReadStream(p, opts) {
if (p === null)
return this.baseFs.createReadStream(p, opts);
return this.makeCallSync(p, () => {
return this.baseFs.createReadStream(p, opts);
}, (zipFs, { subPath }) => {
return zipFs.createReadStream(subPath, opts);
});
});
}, async (zipFsO, {
subPath: subPathO
}) => {
return await this.makeCallPromise(newP, async () => {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {
code: `EEXDEV`
}
createWriteStream(p, opts) {
if (p === null)
return this.baseFs.createWriteStream(p, opts);
return this.makeCallSync(p, () => {
return this.baseFs.createWriteStream(p, opts);
}, (zipFs, { subPath }) => {
return zipFs.createWriteStream(subPath, opts);
});
}, async (zipFsN, {
subPath: subPathN
}) => {
if (zipFsO !== zipFsN) {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {
code: `EEXDEV`
});
} else {
return await zipFsO.renamePromise(subPathO, subPathN);
}
});
});
}
renameSync(oldP, newP) {
return this.makeCallSync(oldP, () => {
return this.makeCallSync(newP, () => {
return this.baseFs.renameSync(oldP, newP);
}, async () => {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {
code: `EEXDEV`
}
async realpathPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.realpathPromise(p);
}, async (zipFs, { archivePath, subPath }) => {
return this.pathUtils.resolve(await this.baseFs.realpathPromise(archivePath), this.pathUtils.relative(path_1.PortablePath.root, await zipFs.realpathPromise(subPath)));
});
});
}, (zipFsO, {
subPath: subPathO
}) => {
return this.makeCallSync(newP, () => {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {
code: `EEXDEV`
}
realpathSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.realpathSync(p);
}, (zipFs, { archivePath, subPath }) => {
return this.pathUtils.resolve(this.baseFs.realpathSync(archivePath), this.pathUtils.relative(path_1.PortablePath.root, zipFs.realpathSync(subPath)));
});
}, (zipFsN, {
subPath: subPathN
}) => {
if (zipFsO !== zipFsN) {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {
code: `EEXDEV`
});
} else {
return zipFsO.renameSync(subPathO, subPathN);
}
});
});
}
async copyFilePromise(sourceP, destP, flags = 0) {
const fallback = async (sourceFs, sourceP, destFs, destP) => {
if ((flags & _fs.constants.COPYFILE_FICLONE_FORCE) !== 0) throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'`), {
code: `EXDEV`
});
if (flags & _fs.constants.COPYFILE_EXCL && (await this.existsPromise(sourceP))) throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'`), {
code: `EEXIST`
});
let content;
try {
content = await sourceFs.readFilePromise(sourceP);
} catch (error) {
throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'`), {
code: `EINVAL`
}
async existsPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.existsPromise(p);
}, async (zipFs, { subPath }) => {
return await zipFs.existsPromise(subPath);
});
}
await destFs.writeFilePromise(destP, content);
};
return await this.makeCallPromise(sourceP, async () => {
return await this.makeCallPromise(destP, async () => {
return await this.baseFs.copyFilePromise(sourceP, destP, flags);
}, async (zipFsD, {
subPath: subPathD
}) => {
return await fallback(this.baseFs, sourceP, zipFsD, subPathD);
});
}, async (zipFsS, {
subPath: subPathS
}) => {
return await this.makeCallPromise(destP, async () => {
return await fallback(zipFsS, subPathS, this.baseFs, destP);
}, async (zipFsD, {
subPath: subPathD
}) => {
if (zipFsS !== zipFsD) {
return await fallback(zipFsS, subPathS, zipFsD, subPathD);
} else {
return await zipFsS.copyFilePromise(subPathS, subPathD, flags);
}
existsSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.existsSync(p);
}, (zipFs, { subPath }) => {
return zipFs.existsSync(subPath);
});
}
async accessPromise(p, mode) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.accessPromise(p, mode);
}, async (zipFs, { subPath }) => {
return await zipFs.accessPromise(subPath, mode);
});
}
accessSync(p, mode) {
return this.makeCallSync(p, () => {
return this.baseFs.accessSync(p, mode);
}, (zipFs, { subPath }) => {
return zipFs.accessSync(subPath, mode);
});
}
async statPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.statPromise(p);
}, async (zipFs, { subPath }) => {
return await zipFs.statPromise(subPath);
});
}
statSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.statSync(p);
}, (zipFs, { subPath }) => {
return zipFs.statSync(subPath);
});
}
async lstatPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.lstatPromise(p);
}, async (zipFs, { subPath }) => {
return await zipFs.lstatPromise(subPath);
});
}
lstatSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.lstatSync(p);
}, (zipFs, { subPath }) => {
return zipFs.lstatSync(subPath);
});
}
async chmodPromise(p, mask) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.chmodPromise(p, mask);
}, async (zipFs, { subPath }) => {
return await zipFs.chmodPromise(subPath, mask);
});
}
chmodSync(p, mask) {
return this.makeCallSync(p, () => {
return this.baseFs.chmodSync(p, mask);
}, (zipFs, { subPath }) => {
return zipFs.chmodSync(subPath, mask);
});
}
async renamePromise(oldP, newP) {
return await this.makeCallPromise(oldP, async () => {
return await this.makeCallPromise(newP, async () => {
return await this.baseFs.renamePromise(oldP, newP);
}, async () => {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` });
});
}, async (zipFsO, { subPath: subPathO }) => {
return await this.makeCallPromise(newP, async () => {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` });
}, async (zipFsN, { subPath: subPathN }) => {
if (zipFsO !== zipFsN) {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` });
}
else {
return await zipFsO.renamePromise(subPathO, subPathN);
}
});
});
}
renameSync(oldP, newP) {
return this.makeCallSync(oldP, () => {
return this.makeCallSync(newP, () => {
return this.baseFs.renameSync(oldP, newP);
}, async () => {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` });
});
}, (zipFsO, { subPath: subPathO }) => {
return this.makeCallSync(newP, () => {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` });
}, (zipFsN, { subPath: subPathN }) => {
if (zipFsO !== zipFsN) {
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` });
}
else {
return zipFsO.renameSync(subPathO, subPathN);
}
});
});
}
async copyFilePromise(sourceP, destP, flags = 0) {
const fallback = async (sourceFs, sourceP, destFs, destP) => {
if ((flags & fs_1.constants.COPYFILE_FICLONE_FORCE) !== 0)
throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'`), { code: `EXDEV` });
if ((flags & fs_1.constants.COPYFILE_EXCL) && await this.existsPromise(sourceP))
throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'`), { code: `EEXIST` });
let content;
try {
content = await sourceFs.readFilePromise(sourceP);
}
catch (error) {
throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'`), { code: `EINVAL` });
}
await destFs.writeFilePromise(destP, content);
};
return await this.makeCallPromise(sourceP, async () => {
return await this.makeCallPromise(destP, async () => {
return await this.baseFs.copyFilePromise(sourceP, destP, flags);
}, async (zipFsD, { subPath: subPathD }) => {
return await fallback(this.baseFs, sourceP, zipFsD, subPathD);
});
}, async (zipFsS, { subPath: subPathS }) => {
return await this.makeCallPromise(destP, async () => {
return await fallback(zipFsS, subPathS, this.baseFs, destP);
}, async (zipFsD, { subPath: subPathD }) => {
if (zipFsS !== zipFsD) {
return await fallback(zipFsS, subPathS, zipFsD, subPathD);
}
else {
return await zipFsS.copyFilePromise(subPathS, subPathD, flags);
}
});
});
}
copyFileSync(sourceP, destP, flags = 0) {
const fallback = (sourceFs, sourceP, destFs, destP) => {
if ((flags & fs_1.constants.COPYFILE_FICLONE_FORCE) !== 0)
throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'`), { code: `EXDEV` });
if ((flags & fs_1.constants.COPYFILE_EXCL) && this.existsSync(sourceP))
throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'`), { code: `EEXIST` });
let content;
try {
content = sourceFs.readFileSync(sourceP);
}
catch (error) {
throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'`), { code: `EINVAL` });
}
destFs.writeFileSync(destP, content);
};
return this.makeCallSync(sourceP, () => {
return this.makeCallSync(destP, () => {
return this.baseFs.copyFileSync(sourceP, destP, flags);
}, (zipFsD, { subPath: subPathD }) => {
return fallback(this.baseFs, sourceP, zipFsD, subPathD);
});
}, (zipFsS, { subPath: subPathS }) => {
return this.makeCallSync(destP, () => {
return fallback(zipFsS, subPathS, this.baseFs, destP);
}, (zipFsD, { subPath: subPathD }) => {
if (zipFsS !== zipFsD) {
return fallback(zipFsS, subPathS, zipFsD, subPathD);
}
else {
return zipFsS.copyFileSync(subPathS, subPathD, flags);
}
});
});
}
async appendFilePromise(p, content, opts) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.appendFilePromise(p, content, opts);
}, async (zipFs, { subPath }) => {
return await zipFs.appendFilePromise(subPath, content, opts);
});
}
appendFileSync(p, content, opts) {
return this.makeCallSync(p, () => {
return this.baseFs.appendFileSync(p, content, opts);
}, (zipFs, { subPath }) => {
return zipFs.appendFileSync(subPath, content, opts);
});
}
async writeFilePromise(p, content, opts) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.writeFilePromise(p, content, opts);
}, async (zipFs, { subPath }) => {
return await zipFs.writeFilePromise(subPath, content, opts);
});
}
writeFileSync(p, content, opts) {
return this.makeCallSync(p, () => {
return this.baseFs.writeFileSync(p, content, opts);
}, (zipFs, { subPath }) => {
return zipFs.writeFileSync(subPath, content, opts);
});
}
async unlinkPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.unlinkPromise(p);
}, async (zipFs, { subPath }) => {
return await zipFs.unlinkPromise(subPath);
});
}
unlinkSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.unlinkSync(p);
}, (zipFs, { subPath }) => {
return zipFs.unlinkSync(subPath);
});
}
async utimesPromise(p, atime, mtime) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.utimesPromise(p, atime, mtime);
}, async (zipFs, { subPath }) => {
return await zipFs.utimesPromise(subPath, atime, mtime);
});
}
utimesSync(p, atime, mtime) {
return this.makeCallSync(p, () => {
return this.baseFs.utimesSync(p, atime, mtime);
}, (zipFs, { subPath }) => {
return zipFs.utimesSync(subPath, atime, mtime);
});
}
async mkdirPromise(p, opts) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.mkdirPromise(p, opts);
}, async (zipFs, { subPath }) => {
return await zipFs.mkdirPromise(subPath, opts);
});
}
mkdirSync(p, opts) {
return this.makeCallSync(p, () => {
return this.baseFs.mkdirSync(p, opts);
}, (zipFs, { subPath }) => {
return zipFs.mkdirSync(subPath, opts);
});
}
async rmdirPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.rmdirPromise(p);
}, async (zipFs, { subPath }) => {
return await zipFs.rmdirPromise(subPath);
});
}
rmdirSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.rmdirSync(p);
}, (zipFs, { subPath }) => {
return zipFs.rmdirSync(subPath);
});
}
async symlinkPromise(target, p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.symlinkPromise(target, p);
}, async (zipFs, { subPath }) => {
return await zipFs.symlinkPromise(target, subPath);
});
}
symlinkSync(target, p) {
return this.makeCallSync(p, () => {
return this.baseFs.symlinkSync(target, p);
}, (zipFs, { subPath }) => {
return zipFs.symlinkSync(target, subPath);
});
}
async readFilePromise(p, encoding) {
return this.makeCallPromise(p, async () => {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return await this.baseFs.readFilePromise(p, encoding);
default:
return await this.baseFs.readFilePromise(p, encoding);
}
}, async (zipFs, { subPath }) => {
return await zipFs.readFilePromise(subPath, encoding);
});
}
readFileSync(p, encoding) {
return this.makeCallSync(p, () => {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return this.baseFs.readFileSync(p, encoding);
default:
return this.baseFs.readFileSync(p, encoding);
}
}, (zipFs, { subPath }) => {
return zipFs.readFileSync(subPath, encoding);
});
}
async readdirPromise(p, { withFileTypes } = {}) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.readdirPromise(p, { withFileTypes: withFileTypes });
}, async (zipFs, { subPath }) => {
return await zipFs.readdirPromise(subPath, { withFileTypes: withFileTypes });
}, {
requireSubpath: false,
});
}
readdirSync(p, { withFileTypes } = {}) {
return this.makeCallSync(p, () => {
return this.baseFs.readdirSync(p, { withFileTypes: withFileTypes });
}, (zipFs, { subPath }) => {
return zipFs.readdirSync(subPath, { withFileTypes: withFileTypes });
}, {
requireSubpath: false,
});
}
async readlinkPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.readlinkPromise(p);
}, async (zipFs, { subPath }) => {
return await zipFs.readlinkPromise(subPath);
});
}
readlinkSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.readlinkSync(p);
}, (zipFs, { subPath }) => {
return zipFs.readlinkSync(subPath);
});
}
watch(p, a, b) {
return this.makeCallSync(p, () => {
return this.baseFs.watch(p,
// @ts-ignore
a, b);
}, (zipFs, { subPath }) => {
return zipFs.watch(subPath,
// @ts-ignore
a, b);
});
}
async makeCallPromise(p, discard, accept, { requireSubpath = true } = {}) {
if (typeof p !== `string`)
return await discard();
const normalizedP = this.pathUtils.normalize(this.pathUtils.resolve(path_1.PortablePath.root, p));
const zipInfo = this.findZip(normalizedP);
if (!zipInfo)
return await discard();
if (requireSubpath && zipInfo.subPath === `/`)
return await discard();
return await this.getZipPromise(zipInfo.archivePath, async (zipFs) => await accept(zipFs, zipInfo));
}
makeCallSync(p, discard, accept, { requireSubpath = true } = {}) {
if (typeof p !== `string`)
return discard();
const normalizedP = this.pathUtils.normalize(this.pathUtils.resolve(path_1.PortablePath.root, p));
const zipInfo = this.findZip(normalizedP);
if (!zipInfo)
return discard();
if (requireSubpath && zipInfo.subPath === `/`)
return discard();
return this.getZipSync(zipInfo.archivePath, zipFs => accept(zipFs, zipInfo));
}
findZip(p) {
if (this.filter && !this.filter.test(p))
return null;
const parts = p.split(/\//g);
for (let t = 2; t <= parts.length; ++t) {
const archivePath = parts.slice(0, t).join(`/`);
if (this.notZip.has(archivePath))
continue;
if (this.isZip.has(archivePath))
return { archivePath, subPath: this.pathUtils.resolve(path_1.PortablePath.root, parts.slice(t).join(`/`)) };
let realArchivePath = archivePath;
let stat;
while (true) {
try {
stat = this.baseFs.lstatSync(realArchivePath);
}
catch (error) {
return null;
}
if (stat.isSymbolicLink()) {
realArchivePath = this.pathUtils.resolve(this.pathUtils.dirname(realArchivePath), this.baseFs.readlinkSync(realArchivePath));
}
else {
break;
}
}
const isZip = stat.isFile() && this.pathUtils.extname(realArchivePath) === `.zip`;
if (isZip) {
this.isZip.add(archivePath);
return { archivePath, subPath: this.pathUtils.resolve(path_1.PortablePath.root, parts.slice(t).join(`/`)) };
}
else {
this.notZip.add(archivePath);
if (stat.isFile()) {
return null;
}
}
}
});
});
}
copyFileSync(sourceP, destP, flags = 0) {
const fallback = (sourceFs, sourceP, destFs, destP) => {
if ((flags & _fs.constants.COPYFILE_FICLONE_FORCE) !== 0) throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'`), {
code: `EXDEV`
});
if (flags & _fs.constants.COPYFILE_EXCL && this.existsSync(sourceP)) throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'`), {
code: `EEXIST`
});
let content;
try {
content = sourceFs.readFileSync(sourceP);
} catch (error) {
throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'`), {
code: `EINVAL`
return null;
}
limitOpenFiles(max) {
if (this.zipInstances === null)
return;
let closeCount = this.zipInstances.size - max;
for (const [path, zipFs] of this.zipInstances.entries()) {
if (closeCount <= 0)
break;
zipFs.saveAndClose();
this.zipInstances.delete(path);
closeCount -= 1;
}
}
async getZipPromise(p, accept) {
const getZipOptions = async () => ({
baseFs: this.baseFs,
libzip: this.libzip,
readOnly: this.readOnlyArchives,
stats: await this.baseFs.statPromise(p),
});
}
destFs.writeFileSync(destP, content);
};
return this.makeCallSync(sourceP, () => {
return this.makeCallSync(destP, () => {
return this.baseFs.copyFileSync(sourceP, destP, flags);
}, (zipFsD, {
subPath: subPathD
}) => {
return fallback(this.baseFs, sourceP, zipFsD, subPathD);
});
}, (zipFsS, {
subPath: subPathS
}) => {
return this.makeCallSync(destP, () => {
return fallback(zipFsS, subPathS, this.baseFs, destP);
}, (zipFsD, {
subPath: subPathD
}) => {
if (zipFsS !== zipFsD) {
return fallback(zipFsS, subPathS, zipFsD, subPathD);
} else {
return zipFsS.copyFileSync(subPathS, subPathD, flags);
if (this.zipInstances) {
let zipFs = this.zipInstances.get(p);
if (!zipFs)
zipFs = new ZipFS_1.ZipFS(p, await getZipOptions());
// Removing then re-adding the field allows us to easily implement
// a basic LRU garbage collection strategy
this.zipInstances.delete(p);
this.zipInstances.set(p, zipFs);
this.limitOpenFiles(this.maxOpenFiles);
return await accept(zipFs);
}
});
});
}
async appendFilePromise(p, content, opts) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.appendFilePromise(p, content, opts);
}, async (zipFs, {
subPath
}) => {
return await zipFs.appendFilePromise(subPath, content, opts);
});
}
appendFileSync(p, content, opts) {
return this.makeCallSync(p, () => {
return this.baseFs.appendFileSync(p, content, opts);
}, (zipFs, {
subPath
}) => {
return zipFs.appendFileSync(subPath, content, opts);
});
}
async writeFilePromise(p, content, opts) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.writeFilePromise(p, content, opts);
}, async (zipFs, {
subPath
}) => {
return await zipFs.writeFilePromise(subPath, content, opts);
});
}
writeFileSync(p, content, opts) {
return this.makeCallSync(p, () => {
return this.baseFs.writeFileSync(p, content, opts);
}, (zipFs, {
subPath
}) => {
return zipFs.writeFileSync(subPath, content, opts);
});
}
async unlinkPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.unlinkPromise(p);
}, async (zipFs, {
subPath
}) => {
return await zipFs.unlinkPromise(subPath);
});
}
unlinkSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.unlinkSync(p);
}, (zipFs, {
subPath
}) => {
return zipFs.unlinkSync(subPath);
});
}
async utimesPromise(p, atime, mtime) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.utimesPromise(p, atime, mtime);
}, async (zipFs, {
subPath
}) => {
return await zipFs.utimesPromise(subPath, atime, mtime);
});
}
utimesSync(p, atime, mtime) {
return this.makeCallSync(p, () => {
return this.baseFs.utimesSync(p, atime, mtime);
}, (zipFs, {
subPath
}) => {
return zipFs.utimesSync(subPath, atime, mtime);
});
}
async mkdirPromise(p, opts) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.mkdirPromise(p, opts);
}, async (zipFs, {
subPath
}) => {
return await zipFs.mkdirPromise(subPath, opts);
});
}
mkdirSync(p, opts) {
return this.makeCallSync(p, () => {
return this.baseFs.mkdirSync(p, opts);
}, (zipFs, {
subPath
}) => {
return zipFs.mkdirSync(subPath, opts);
});
}
async rmdirPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.rmdirPromise(p);
}, async (zipFs, {
subPath
}) => {
return await zipFs.rmdirPromise(subPath);
});
}
rmdirSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.rmdirSync(p);
}, (zipFs, {
subPath
}) => {
return zipFs.rmdirSync(subPath);
});
}
async symlinkPromise(target, p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.symlinkPromise(target, p);
}, async (zipFs, {
subPath
}) => {
return await zipFs.symlinkPromise(target, subPath);
});
}
symlinkSync(target, p) {
return this.makeCallSync(p, () => {
return this.baseFs.symlinkSync(target, p);
}, (zipFs, {
subPath
}) => {
return zipFs.symlinkSync(target, subPath);
});
}
async readFilePromise(p, encoding) {
return this.makeCallPromise(p, async () => {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return await this.baseFs.readFilePromise(p, encoding);
default:
return await this.baseFs.readFilePromise(p, encoding);
}
}, async (zipFs, {
subPath
}) => {
return await zipFs.readFilePromise(subPath, encoding);
});
}
readFileSync(p, encoding) {
return this.makeCallSync(p, () => {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return this.baseFs.readFileSync(p, encoding);
default:
return this.baseFs.readFileSync(p, encoding);
}
}, (zipFs, {
subPath
}) => {
return zipFs.readFileSync(subPath, encoding);
});
}
async readdirPromise(p, {
withFileTypes
} = {}) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.readdirPromise(p, {
withFileTypes: withFileTypes
});
}, async (zipFs, {
subPath
}) => {
return await zipFs.readdirPromise(subPath, {
withFileTypes: withFileTypes
});
}, {
requireSubpath: false
});
}
readdirSync(p, {
withFileTypes
} = {}) {
return this.makeCallSync(p, () => {
return this.baseFs.readdirSync(p, {
withFileTypes: withFileTypes
});
}, (zipFs, {
subPath
}) => {
return zipFs.readdirSync(subPath, {
withFileTypes: withFileTypes
});
}, {
requireSubpath: false
});
}
async readlinkPromise(p) {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.readlinkPromise(p);
}, async (zipFs, {
subPath
}) => {
return await zipFs.readlinkPromise(subPath);
});
}
readlinkSync(p) {
return this.makeCallSync(p, () => {
return this.baseFs.readlinkSync(p);
}, (zipFs, {
subPath
}) => {
return zipFs.readlinkSync(subPath);
});
}
watch(p, a, b) {
return this.makeCallSync(p, () => {
return this.baseFs.watch(p, // @ts-ignore
a, b);
}, (zipFs, {
subPath
}) => {
return zipFs.watch(subPath, // @ts-ignore
a, b);
});
}
async makeCallPromise(p, discard, accept, {
requireSubpath = true
} = {}) {
if (typeof p !== `string`) return await discard();
const normalizedP = this.pathUtils.normalize(this.pathUtils.resolve(_path.PortablePath.root, p));
const zipInfo = this.findZip(normalizedP);
if (!zipInfo) return await discard();
if (requireSubpath && zipInfo.subPath === `/`) return await discard();
return await this.getZipPromise(zipInfo.archivePath, async zipFs => await accept(zipFs, zipInfo));
}
makeCallSync(p, discard, accept, {
requireSubpath = true
} = {}) {
if (typeof p !== `string`) return discard();
const normalizedP = this.pathUtils.normalize(this.pathUtils.resolve(_path.PortablePath.root, p));
const zipInfo = this.findZip(normalizedP);
if (!zipInfo) return discard();
if (requireSubpath && zipInfo.subPath === `/`) return discard();
return this.getZipSync(zipInfo.archivePath, zipFs => accept(zipFs, zipInfo));
}
findZip(p) {
if (this.filter && !this.filter.test(p)) return null;
const parts = p.split(/\//g);
for (let t = 2; t <= parts.length; ++t) {
const archivePath = parts.slice(0, t).join(`/`);
if (this.notZip.has(archivePath)) continue;
if (this.isZip.has(archivePath)) return {
archivePath,
subPath: this.pathUtils.resolve(_path.PortablePath.root, parts.slice(t).join(`/`))
};
let realArchivePath = archivePath;
let stat;
while (true) {
try {
stat = this.baseFs.lstatSync(realArchivePath);
} catch (error) {
return null;
else {
const zipFs = new ZipFS_1.ZipFS(p, await getZipOptions());
try {
return await accept(zipFs);
}
finally {
zipFs.saveAndClose();
}
}
if (stat.isSymbolicLink()) {
realArchivePath = this.pathUtils.resolve(this.pathUtils.dirname(realArchivePath), this.baseFs.readlinkSync(realArchivePath));
} else {
break;
}
getZipSync(p, accept) {
const getZipOptions = () => ({
baseFs: this.baseFs,
libzip: this.libzip,
readOnly: this.readOnlyArchives,
stats: this.baseFs.statSync(p),
});
if (this.zipInstances) {
let zipFs = this.zipInstances.get(p);
if (!zipFs)
this.zipInstances.set(p, zipFs = new ZipFS_1.ZipFS(p, getZipOptions()));
return accept(zipFs);
}
}
const isZip = stat.isFile() && this.pathUtils.extname(realArchivePath) === `.zip`;
if (isZip) {
this.isZip.add(archivePath);
return {
archivePath,
subPath: this.pathUtils.resolve(_path.PortablePath.root, parts.slice(t).join(`/`))
};
} else {
this.notZip.add(archivePath);
if (stat.isFile()) {
return null;
else {
const zipFs = new ZipFS_1.ZipFS(p, getZipOptions());
try {
return accept(zipFs);
}
finally {
zipFs.saveAndClose();
}
}
}
}
return null;
}
limitOpenFiles(max) {
if (this.zipInstances === null) return;
let closeCount = this.zipInstances.size - max;
for (const [path, zipFs] of this.zipInstances.entries()) {
if (closeCount <= 0) break;
zipFs.saveAndClose();
this.zipInstances.delete(path);
closeCount -= 1;
}
}
async getZipPromise(p, accept) {
const getZipOptions = async () => ({
baseFs: this.baseFs,
readOnly: this.readOnlyArchives,
stats: await this.baseFs.statPromise(p)
});
if (this.zipInstances) {
let zipFs = this.zipInstances.get(p);
if (!zipFs) zipFs = new _ZipFS.ZipFS(p, (await getZipOptions())); // Removing then re-adding the field allows us to easily implement
// a basic LRU garbage collection strategy
this.zipInstances.delete(p);
this.zipInstances.set(p, zipFs);
this.limitOpenFiles(this.maxOpenFiles);
return await accept(zipFs);
} else {
const zipFs = new _ZipFS.ZipFS(p, (await getZipOptions()));
try {
return await accept(zipFs);
} finally {
zipFs.saveAndClose();
}
}
}
getZipSync(p, accept) {
const getZipOptions = () => ({
baseFs: this.baseFs,
readOnly: this.readOnlyArchives,
stats: this.baseFs.statSync(p)
});
if (this.zipInstances) {
let zipFs = this.zipInstances.get(p);
if (!zipFs) this.zipInstances.set(p, zipFs = new _ZipFS.ZipFS(p, getZipOptions()));
return accept(zipFs);
} else {
const zipFs = new _ZipFS.ZipFS(p, getZipOptions());
try {
return accept(zipFs);
} finally {
zipFs.saveAndClose();
}
}
}
}
exports.ZipOpenFS = ZipOpenFS;
exports.ZipOpenFS = ZipOpenFS;
{
"name": "@yarnpkg/fslib",
"version": "2.0.0-rc.14",
"version": "2.0.0-rc.15",
"main": "./lib/index.js",
"sideEffects": false,
"dependencies": {
"@yarnpkg/libzip": "^2.0.0-rc.5",
"@yarnpkg/libzip": "^2.0.0-rc.8",
"tmp": "^0.1.0"

@@ -9,0 +9,0 @@ },

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc