@bevry/file
Advanced tools
Comparing version 1.5.0 to 2.0.0-next.1699869946.2d720214a93d871dd6b7247955ab67cbe62d199e
@@ -0,1 +1,5 @@ | ||
/// <reference types="node" /> | ||
import { RmOptions, MakeDirectoryOptions } from 'fs'; | ||
/** Make the directory structure */ | ||
export declare function mkdirp(path: string, opts?: MakeDirectoryOptions): Promise<void>; | ||
/** Check access of a file */ | ||
@@ -31,2 +35,6 @@ export declare function access(path: string, mode: number): Promise<void>; | ||
export declare function deleteFile(path: string): Promise<void>; | ||
/** Remove an entire directory (including nested contents) safely. */ | ||
export declare function deleteEntireDirectory(path: string, opts?: RmOptions): Promise<void>; | ||
/** Read an entire directory (including nested contents) safely. */ | ||
export declare function readEntireDirectory(path: string): Promise<Array<string>>; | ||
/** Read a directory */ | ||
@@ -33,0 +41,0 @@ export declare function readdir(path: string): Promise<Array<string>>; |
@@ -1,3 +0,44 @@ | ||
import { access as _access, readFile as _readFile, writeFile as _writeFile, unlink as _unlink, readdir as _readdir, constants, } from 'fs'; | ||
// builtin | ||
import { access as _access, readFile as _readFile, writeFile as _writeFile, unlink as _unlink, readdir as _readdir, mkdir as _mkdir, constants, | ||
// dynamically imported as not present on all node versions | ||
// rm as _rm, | ||
// rmdir as _rmdir, | ||
} from 'fs'; | ||
import { resolve as _resolve, dirname as _dirname } from 'path'; | ||
import { exec } from 'child_process'; | ||
import { versions } from 'process'; | ||
const nodeVersion = String(versions.node || '0'); | ||
// external | ||
import Errlop from 'errlop'; | ||
import versionCompare from 'version-compare'; | ||
/** Make the directory structure */ | ||
export async function mkdirp(path, opts = {}) { | ||
// if we already exist, nothing to do | ||
if (await isPresent(path)) { | ||
return; | ||
} | ||
// create according to node.js version | ||
if (versionCompare(nodeVersion, '14.14.0') >= 0) { | ||
return new Promise(function (resolve, reject) { | ||
_mkdir(path, Object.assign({ | ||
recursive: true, | ||
}, opts), function (err) { | ||
if (err) | ||
return reject(err); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
else { | ||
const dir = _dirname(path); | ||
await mkdirp(dir, opts); | ||
return new Promise(function (resolve, reject) { | ||
_mkdir(path, Object.assign({}, opts), function (err) { | ||
if (err) | ||
return reject(err); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
} | ||
/** Check access of a file */ | ||
@@ -15,3 +56,3 @@ export function access(path, mode) { | ||
export function exists(path) { | ||
return access(path, constants.F_OK); | ||
return access(path, constants?.F_OK ?? 0); // node 4 compat | ||
} | ||
@@ -26,3 +67,3 @@ /** Check the existence status of a file */ | ||
export function readable(path) { | ||
return access(path, constants.R_OK); | ||
return access(path, constants?.R_OK ?? 4); // node 4 compat | ||
} | ||
@@ -37,3 +78,3 @@ /** Check the readable status of a file */ | ||
export function writable(path) { | ||
return access(path, constants.W_OK); | ||
return access(path, constants?.W_OK ?? 2); // node 4 compat | ||
} | ||
@@ -48,3 +89,3 @@ /** Check the writable status of a file */ | ||
export function executable(path) { | ||
return access(path, constants.X_OK); | ||
return access(path, constants?.X_OK ?? 1); // node 4 compat | ||
} | ||
@@ -178,2 +219,101 @@ /** Check the executable status of a file */ | ||
} | ||
/** Remove an entire directory (including nested contents) safely. */ | ||
export async function deleteEntireDirectory(path, opts = {}) { | ||
// handle relative and absolute paths correctly | ||
path = _resolve(path); | ||
// check exists | ||
try { | ||
await exists(path); | ||
} | ||
catch (err) { | ||
// if it doesn't exist, then we don't care | ||
return; | ||
} | ||
// check writable | ||
try { | ||
await writable(path); | ||
} | ||
catch (err) { | ||
if (err.code === 'ENOENT') { | ||
// if it doesn't exist, then we don't care | ||
// this may not seem necessary, however it is | ||
// testen would fail on @bevry/json otherwise | ||
return; | ||
} | ||
throw new Errlop(`no write permission to delete the existing file: ${path}`, err); | ||
} | ||
// attempt delete | ||
return new Promise(function (resolve, reject) { | ||
function next(err) { | ||
if (err && err.code === 'ENOENT') | ||
return resolve(); | ||
if (err) | ||
return reject(err); | ||
return resolve(); | ||
} | ||
if (versionCompare(nodeVersion, '14.14.0') >= 0) { | ||
import('fs').then(function ({ rm: _rm }) { | ||
_rm(path, Object.assign({ recursive: true, force: true, maxRetries: 10 }, opts), next); | ||
}); | ||
} | ||
else if (versionCompare(nodeVersion, '12.16.0') >= 0 && | ||
versionCompare(nodeVersion, '16') < 0) { | ||
import('fs').then(function ({ rmdir: _rmdir }) { | ||
_rmdir(path, Object.assign({ recursive: true, maxRetries: 10 }, opts), next); | ||
}); | ||
} | ||
else if (versionCompare(nodeVersion, '12.10.0') >= 0 && | ||
versionCompare(nodeVersion, '12.16.0') < 0) { | ||
import('fs').then(function ({ rmdir: _rmdir }) { | ||
_rmdir(path, Object.assign({ recursive: true, maxBusyTries: 10 }, opts), next); | ||
}); | ||
} | ||
else { | ||
if (path === '' || path === '/') | ||
return next(new Error('will not delete root directory')); | ||
exec(`rm -rf ${JSON.stringify(path)}`, next); | ||
} | ||
}); | ||
} | ||
/** Read an entire directory (including nested contents) safely. */ | ||
export async function readEntireDirectory(path) { | ||
// handle relative and absolute paths correctly | ||
path = _resolve(path); | ||
// check exists | ||
try { | ||
await exists(path); | ||
} | ||
catch (err) { | ||
throw new Errlop(`unable to read the non-existent directory: ${path}`, err); | ||
} | ||
// check readable | ||
try { | ||
await readable(path); | ||
} | ||
catch (err) { | ||
throw new Errlop(`no read permission for the directory: ${path}`, err); | ||
} | ||
// attempt read | ||
return new Promise(function (resolve, reject) { | ||
if (versionCompare(nodeVersion, '18.17.0') >= 0) { | ||
_readdir(path, { encoding: null, recursive: true, withFileTypes: false }, function (err, files) { | ||
if (err) | ||
return reject(err); | ||
return resolve(files.sort()); | ||
}); | ||
} | ||
else { | ||
// find files and dirs, -f doesn't work on ubuntu | ||
exec('find .', { cwd: path }, function (err, stdout) { | ||
if (err) | ||
return reject(err); | ||
return resolve(stdout | ||
.split('\n') | ||
.map((p) => p.replace(/^[./\\]+/, '')) // trim . and ./ | ||
.filter(Boolean) | ||
.sort()); | ||
}); | ||
} | ||
}); | ||
} | ||
/** Read a directory */ | ||
@@ -180,0 +320,0 @@ export function readdir(path) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -6,5 +29,43 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.readDirectory = exports.readdir = exports.deleteFile = exports.unlink = exports.writeFile = exports.write = exports.readFile = exports.read = exports.isExecutable = exports.executable = exports.isWritable = exports.writable = exports.isReadable = exports.readable = exports.isPresent = exports.exists = exports.access = void 0; | ||
exports.readDirectory = exports.readdir = exports.readEntireDirectory = exports.deleteEntireDirectory = exports.deleteFile = exports.unlink = exports.writeFile = exports.write = exports.readFile = exports.read = exports.isExecutable = exports.executable = exports.isWritable = exports.writable = exports.isReadable = exports.readable = exports.isPresent = exports.exists = exports.access = exports.mkdirp = void 0; | ||
// builtin | ||
const fs_1 = require("fs"); | ||
const path_1 = require("path"); | ||
const child_process_1 = require("child_process"); | ||
const process_1 = require("process"); | ||
const nodeVersion = String(process_1.versions.node || '0'); | ||
// external | ||
const errlop_1 = __importDefault(require("errlop")); | ||
const version_compare_1 = __importDefault(require("version-compare")); | ||
/** Make the directory structure */ | ||
async function mkdirp(path, opts = {}) { | ||
// if we already exist, nothing to do | ||
if (await isPresent(path)) { | ||
return; | ||
} | ||
// create according to node.js version | ||
if ((0, version_compare_1.default)(nodeVersion, '14.14.0') >= 0) { | ||
return new Promise(function (resolve, reject) { | ||
(0, fs_1.mkdir)(path, Object.assign({ | ||
recursive: true, | ||
}, opts), function (err) { | ||
if (err) | ||
return reject(err); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
else { | ||
const dir = (0, path_1.dirname)(path); | ||
await mkdirp(dir, opts); | ||
return new Promise(function (resolve, reject) { | ||
(0, fs_1.mkdir)(path, Object.assign({}, opts), function (err) { | ||
if (err) | ||
return reject(err); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
} | ||
exports.mkdirp = mkdirp; | ||
/** Check access of a file */ | ||
@@ -23,3 +84,3 @@ function access(path, mode) { | ||
function exists(path) { | ||
return access(path, fs_1.constants.F_OK); | ||
return access(path, fs_1.constants?.F_OK ?? 0); // node 4 compat | ||
} | ||
@@ -36,3 +97,3 @@ exports.exists = exists; | ||
function readable(path) { | ||
return access(path, fs_1.constants.R_OK); | ||
return access(path, fs_1.constants?.R_OK ?? 4); // node 4 compat | ||
} | ||
@@ -49,3 +110,3 @@ exports.readable = readable; | ||
function writable(path) { | ||
return access(path, fs_1.constants.W_OK); | ||
return access(path, fs_1.constants?.W_OK ?? 2); // node 4 compat | ||
} | ||
@@ -62,3 +123,3 @@ exports.writable = writable; | ||
function executable(path) { | ||
return access(path, fs_1.constants.X_OK); | ||
return access(path, fs_1.constants?.X_OK ?? 1); // node 4 compat | ||
} | ||
@@ -200,2 +261,103 @@ exports.executable = executable; | ||
exports.deleteFile = deleteFile; | ||
/** Remove an entire directory (including nested contents) safely. */ | ||
async function deleteEntireDirectory(path, opts = {}) { | ||
// handle relative and absolute paths correctly | ||
path = (0, path_1.resolve)(path); | ||
// check exists | ||
try { | ||
await exists(path); | ||
} | ||
catch (err) { | ||
// if it doesn't exist, then we don't care | ||
return; | ||
} | ||
// check writable | ||
try { | ||
await writable(path); | ||
} | ||
catch (err) { | ||
if (err.code === 'ENOENT') { | ||
// if it doesn't exist, then we don't care | ||
// this may not seem necessary, however it is | ||
// testen would fail on @bevry/json otherwise | ||
return; | ||
} | ||
throw new errlop_1.default(`no write permission to delete the existing file: ${path}`, err); | ||
} | ||
// attempt delete | ||
return new Promise(function (resolve, reject) { | ||
function next(err) { | ||
if (err && err.code === 'ENOENT') | ||
return resolve(); | ||
if (err) | ||
return reject(err); | ||
return resolve(); | ||
} | ||
if ((0, version_compare_1.default)(nodeVersion, '14.14.0') >= 0) { | ||
Promise.resolve().then(() => __importStar(require('fs'))).then(function ({ rm: _rm }) { | ||
_rm(path, Object.assign({ recursive: true, force: true, maxRetries: 10 }, opts), next); | ||
}); | ||
} | ||
else if ((0, version_compare_1.default)(nodeVersion, '12.16.0') >= 0 && | ||
(0, version_compare_1.default)(nodeVersion, '16') < 0) { | ||
Promise.resolve().then(() => __importStar(require('fs'))).then(function ({ rmdir: _rmdir }) { | ||
_rmdir(path, Object.assign({ recursive: true, maxRetries: 10 }, opts), next); | ||
}); | ||
} | ||
else if ((0, version_compare_1.default)(nodeVersion, '12.10.0') >= 0 && | ||
(0, version_compare_1.default)(nodeVersion, '12.16.0') < 0) { | ||
Promise.resolve().then(() => __importStar(require('fs'))).then(function ({ rmdir: _rmdir }) { | ||
_rmdir(path, Object.assign({ recursive: true, maxBusyTries: 10 }, opts), next); | ||
}); | ||
} | ||
else { | ||
if (path === '' || path === '/') | ||
return next(new Error('will not delete root directory')); | ||
(0, child_process_1.exec)(`rm -rf ${JSON.stringify(path)}`, next); | ||
} | ||
}); | ||
} | ||
exports.deleteEntireDirectory = deleteEntireDirectory; | ||
/** Read an entire directory (including nested contents) safely. */ | ||
async function readEntireDirectory(path) { | ||
// handle relative and absolute paths correctly | ||
path = (0, path_1.resolve)(path); | ||
// check exists | ||
try { | ||
await exists(path); | ||
} | ||
catch (err) { | ||
throw new errlop_1.default(`unable to read the non-existent directory: ${path}`, err); | ||
} | ||
// check readable | ||
try { | ||
await readable(path); | ||
} | ||
catch (err) { | ||
throw new errlop_1.default(`no read permission for the directory: ${path}`, err); | ||
} | ||
// attempt read | ||
return new Promise(function (resolve, reject) { | ||
if ((0, version_compare_1.default)(nodeVersion, '18.17.0') >= 0) { | ||
(0, fs_1.readdir)(path, { encoding: null, recursive: true, withFileTypes: false }, function (err, files) { | ||
if (err) | ||
return reject(err); | ||
return resolve(files.sort()); | ||
}); | ||
} | ||
else { | ||
// find files and dirs, -f doesn't work on ubuntu | ||
(0, child_process_1.exec)('find .', { cwd: path }, function (err, stdout) { | ||
if (err) | ||
return reject(err); | ||
return resolve(stdout | ||
.split('\n') | ||
.map((p) => p.replace(/^[./\\]+/, '')) // trim . and ./ | ||
.filter(Boolean) | ||
.sort()); | ||
}); | ||
} | ||
}); | ||
} | ||
exports.readEntireDirectory = readEntireDirectory; | ||
/** Read a directory */ | ||
@@ -202,0 +364,0 @@ function readdir(path) { |
{ | ||
"name": "@bevry/file", | ||
"version": "1.5.0", | ||
"version": "2.0.0-next.1699869946.2d720214a93d871dd6b7247955ab67cbe62d199e", | ||
"description": "Helpers for reading, writing, deleting, and accessing a file.", | ||
@@ -12,3 +12,6 @@ "homepage": "https://github.com/bevry/file", | ||
"ecmascript", | ||
"es2016", | ||
"es2019", | ||
"es2022", | ||
"es5", | ||
"file", | ||
@@ -78,3 +81,3 @@ "from", | ||
"engines": { | ||
"node": ">=10" | ||
"node": ">=4" | ||
}, | ||
@@ -108,3 +111,3 @@ "editions": [ | ||
{ | ||
"description": "TypeScript compiled against ES2022 for Node.js 10 || 12 || 14 || 16 || 18 || 20 || 21 with Require for modules", | ||
"description": "TypeScript compiled against ES2022 for Node.js 14 || 16 || 18 || 20 || 21 with Require for modules", | ||
"directory": "edition-es2022", | ||
@@ -119,3 +122,3 @@ "entry": "index.js", | ||
"engines": { | ||
"node": "10 || 12 || 14 || 16 || 18 || 20 || 21", | ||
"node": "14 || 16 || 18 || 20 || 21", | ||
"browsers": false | ||
@@ -125,4 +128,4 @@ } | ||
{ | ||
"description": "TypeScript compiled against ES2022 for Node.js 12 || 14 || 16 || 18 || 20 || 21 with Import for modules", | ||
"directory": "edition-es2022-esm", | ||
"description": "TypeScript compiled against ES2019 for Node.js 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with Require for modules", | ||
"directory": "edition-es2019", | ||
"entry": "index.js", | ||
@@ -132,3 +135,48 @@ "tags": [ | ||
"javascript", | ||
"es2022", | ||
"es2019", | ||
"require" | ||
], | ||
"engines": { | ||
"node": "8 || 10 || 12 || 14 || 16 || 18 || 20 || 21", | ||
"browsers": false | ||
} | ||
}, | ||
{ | ||
"description": "TypeScript compiled against ES2016 for Node.js 6 || 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with Require for modules", | ||
"directory": "edition-es2016", | ||
"entry": "index.js", | ||
"tags": [ | ||
"compiled", | ||
"javascript", | ||
"es2016", | ||
"require" | ||
], | ||
"engines": { | ||
"node": "6 || 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21", | ||
"browsers": false | ||
} | ||
}, | ||
{ | ||
"description": "TypeScript compiled against ES5 for Node.js 4 || 6 || 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with Require for modules", | ||
"directory": "edition-es5", | ||
"entry": "index.js", | ||
"tags": [ | ||
"compiled", | ||
"javascript", | ||
"es5", | ||
"require" | ||
], | ||
"engines": { | ||
"node": "4 || 6 || 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21", | ||
"browsers": false | ||
} | ||
}, | ||
{ | ||
"description": "TypeScript compiled against ES2019 for Node.js 12 || 14 || 16 || 18 || 20 || 21 with Import for modules", | ||
"directory": "edition-es2019-esm", | ||
"entry": "index.js", | ||
"tags": [ | ||
"compiled", | ||
"javascript", | ||
"es2019", | ||
"import" | ||
@@ -144,6 +192,7 @@ ], | ||
"type": "module", | ||
"main": "edition-es2022/index.js", | ||
"main": "index.cjs", | ||
"exports": { | ||
"node": { | ||
"import": "./edition-es2022-esm/index.js", | ||
"import": "./edition-es2019-esm/index.js", | ||
"default": "./index.cjs", | ||
"require": "./edition-es2022/index.js" | ||
@@ -157,2 +206,6 @@ }, | ||
"module": "edition-browsers/index.js", | ||
"dependencies": { | ||
"editions": "^6.10.0", | ||
"version-compare": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
@@ -163,3 +216,3 @@ "@bevry/update-contributors": "^1.23.0", | ||
"@typescript-eslint/parser": "^6.10.0", | ||
"assert-helpers": "^10.1.0", | ||
"assert-helpers": "^11.1.0", | ||
"eslint": "^8.53.0", | ||
@@ -169,4 +222,4 @@ "eslint-config-bevry": "^3.29.0", | ||
"eslint-plugin-prettier": "^5.0.1", | ||
"kava": "3.2.0", | ||
"prettier": "^3.0.3", | ||
"kava": "^7.0.0", | ||
"prettier": "^3.1.0", | ||
"projectz": "^2.23.0", | ||
@@ -181,6 +234,9 @@ "surge": "^0.23.1", | ||
"our:clean": "rm -Rf ./docs ./edition* ./es2015 ./es5 ./out ./.next", | ||
"our:compile": "npm run our:compile:edition-browsers && npm run our:compile:edition-es2022 && npm run our:compile:edition-es2022-esm && npm run our:compile:types", | ||
"our:compile": "npm run our:compile:edition-browsers && npm run our:compile:edition-es2016 && npm run our:compile:edition-es2019 && npm run our:compile:edition-es2019-esm && npm run our:compile:edition-es2022 && npm run our:compile:edition-es5 && npm run our:compile:types", | ||
"our:compile:edition-browsers": "tsc --module ESNext --target ES2022 --outDir ./edition-browsers --project tsconfig.json && ( test ! -d edition-browsers/source || ( mv edition-browsers/source edition-temp && rm -Rf edition-browsers && mv edition-temp edition-browsers ) )", | ||
"our:compile:edition-es2016": "tsc --module commonjs --target ES2016 --outDir ./edition-es2016 --project tsconfig.json && ( test ! -d edition-es2016/source || ( mv edition-es2016/source edition-temp && rm -Rf edition-es2016 && mv edition-temp edition-es2016 ) ) && printf '%s' '{\"type\": \"commonjs\"}' > edition-es2016/package.json", | ||
"our:compile:edition-es2019": "tsc --module commonjs --target ES2019 --outDir ./edition-es2019 --project tsconfig.json && ( test ! -d edition-es2019/source || ( mv edition-es2019/source edition-temp && rm -Rf edition-es2019 && mv edition-temp edition-es2019 ) ) && printf '%s' '{\"type\": \"commonjs\"}' > edition-es2019/package.json", | ||
"our:compile:edition-es2019-esm": "tsc --module ESNext --target ES2019 --outDir ./edition-es2019-esm --project tsconfig.json && ( test ! -d edition-es2019-esm/source || ( mv edition-es2019-esm/source edition-temp && rm -Rf edition-es2019-esm && mv edition-temp edition-es2019-esm ) ) && printf '%s' '{\"type\": \"module\"}' > edition-es2019-esm/package.json", | ||
"our:compile:edition-es2022": "tsc --module commonjs --target ES2022 --outDir ./edition-es2022 --project tsconfig.json && ( test ! -d edition-es2022/source || ( mv edition-es2022/source edition-temp && rm -Rf edition-es2022 && mv edition-temp edition-es2022 ) ) && printf '%s' '{\"type\": \"commonjs\"}' > edition-es2022/package.json", | ||
"our:compile:edition-es2022-esm": "tsc --module ESNext --target ES2022 --outDir ./edition-es2022-esm --project tsconfig.json && ( test ! -d edition-es2022-esm/source || ( mv edition-es2022-esm/source edition-temp && rm -Rf edition-es2022-esm && mv edition-temp edition-es2022-esm ) ) && printf '%s' '{\"type\": \"module\"}' > edition-es2022-esm/package.json", | ||
"our:compile:edition-es5": "tsc --module commonjs --target ES5 --outDir ./edition-es5 --project tsconfig.json && ( test ! -d edition-es5/source || ( mv edition-es5/source edition-temp && rm -Rf edition-es5 && mv edition-temp edition-es5 ) ) && printf '%s' '{\"type\": \"commonjs\"}' > edition-es5/package.json", | ||
"our:compile:types": "tsc --project tsconfig.json --emitDeclarationOnly --declaration --declarationMap --declarationDir ./compiled-types && ( test ! -d compiled-types/source || ( mv compiled-types/source edition-temp && rm -Rf compiled-types && mv edition-temp compiled-types ) )", | ||
@@ -207,3 +263,3 @@ "our:deploy": "printf '%s\n' 'no need for this project'", | ||
"our:verify:prettier": "prettier --write .", | ||
"test": "node ./edition-es2022/test.js" | ||
"test": "node ./test.cjs" | ||
}, | ||
@@ -217,4 +273,5 @@ "eslintConfig": { | ||
"semi": false, | ||
"singleQuote": true | ||
"singleQuote": true, | ||
"trailingComma": "es5" | ||
} | ||
} | ||
} |
@@ -54,3 +54,3 @@ <!-- TITLE/ --> | ||
<script type="module"> | ||
import * as pkg from '//cdn.skypack.dev/@bevry/file@^1.5.0' | ||
import * as pkg from '//cdn.skypack.dev/@bevry/file@^2.0.0' | ||
</script> | ||
@@ -63,3 +63,3 @@ ``` | ||
<script type="module"> | ||
import * as pkg from '//unpkg.com/@bevry/file@^1.5.0' | ||
import * as pkg from '//unpkg.com/@bevry/file@^2.0.0' | ||
</script> | ||
@@ -72,3 +72,3 @@ ``` | ||
<script type="module"> | ||
import * as pkg from '//dev.jspm.io/@bevry/file@1.5.0' | ||
import * as pkg from '//dev.jspm.io/@bevry/file@2.0.0' | ||
</script> | ||
@@ -81,7 +81,10 @@ ``` | ||
<ul><li><code>@bevry/file/source/index.ts</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> source code with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<ul><li><code>@bevry/file</code> aliases <code>@bevry/file/index.cjs</code> which uses the <a href="https://github.com/bevry/editions" title="You can use the Editions Autoloader to autoload the appropriate edition for your consumers environment">Editions Autoloader</a> to automatically select the correct edition for the consumer's environment</li> | ||
<li><code>@bevry/file/source/index.ts</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> source code with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>@bevry/file/edition-browsers/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES2022 for web browsers with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>@bevry/file</code> aliases <code>@bevry/file/edition-es2022/index.js</code></li> | ||
<li><code>@bevry/file/edition-es2022/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES2022 for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 10 || 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>@bevry/file/edition-es2022-esm/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES2022 for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li></ul> | ||
<li><code>@bevry/file/edition-es2022/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES2022 for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 14 || 16 || 18 || 20 || 21 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>@bevry/file/edition-es2019/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_-_ECMAScript_2019" title="ECMAScript ES2019">ES2019</a> for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>@bevry/file/edition-es2016/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#7th_Edition_-_ECMAScript_2016" title="ECMAScript 2016">ES2016</a> for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 6 || 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>@bevry/file/edition-es5/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES5 for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 4 || 6 || 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>@bevry/file/edition-es2019-esm/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_-_ECMAScript_2019" title="ECMAScript ES2019">ES2019</a> for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li></ul> | ||
@@ -88,0 +91,0 @@ <!-- /INSTALL --> |
@@ -0,1 +1,2 @@ | ||
// builtin | ||
import { | ||
@@ -7,6 +8,58 @@ access as _access, | ||
readdir as _readdir, | ||
mkdir as _mkdir, | ||
constants, | ||
RmOptions, | ||
MakeDirectoryOptions, | ||
// dynamically imported as not present on all node versions | ||
// rm as _rm, | ||
// rmdir as _rmdir, | ||
} from 'fs' | ||
import { resolve as _resolve, dirname as _dirname } from 'path' | ||
import { exec } from 'child_process' | ||
import { versions } from 'process' | ||
const nodeVersion = String(versions.node || '0') | ||
// external | ||
import Errlop from 'errlop' | ||
import versionCompare from 'version-compare' | ||
/** Make the directory structure */ | ||
export async function mkdirp( | ||
path: string, | ||
opts: MakeDirectoryOptions = {} | ||
): Promise<void> { | ||
// if we already exist, nothing to do | ||
if (await isPresent(path)) { | ||
return | ||
} | ||
// create according to node.js version | ||
if (versionCompare(nodeVersion, '14.14.0') >= 0) { | ||
return new Promise(function (resolve, reject) { | ||
_mkdir( | ||
path, | ||
Object.assign( | ||
{ | ||
recursive: true, | ||
}, | ||
opts | ||
), | ||
function (err) { | ||
if (err) return reject(err) | ||
resolve() | ||
} | ||
) | ||
}) | ||
} else { | ||
const dir = _dirname(path) | ||
await mkdirp(dir, opts) | ||
return new Promise(function (resolve, reject) { | ||
_mkdir(path, Object.assign({}, opts), function (err) { | ||
if (err) return reject(err) | ||
resolve() | ||
}) | ||
}) | ||
} | ||
} | ||
/** Check access of a file */ | ||
@@ -24,3 +77,3 @@ export function access(path: string, mode: number): Promise<void> { | ||
export function exists(path: string): Promise<void> { | ||
return access(path, constants.F_OK) | ||
return access(path, constants?.F_OK ?? 0) // node 4 compat | ||
} | ||
@@ -37,3 +90,3 @@ | ||
export function readable(path: string): Promise<void> { | ||
return access(path, constants.R_OK) | ||
return access(path, constants?.R_OK ?? 4) // node 4 compat | ||
} | ||
@@ -50,3 +103,3 @@ | ||
export function writable(path: string): Promise<void> { | ||
return access(path, constants.W_OK) | ||
return access(path, constants?.W_OK ?? 2) // node 4 compat | ||
} | ||
@@ -63,3 +116,3 @@ | ||
export function executable(path: string): Promise<void> { | ||
return access(path, constants.X_OK) | ||
return access(path, constants?.X_OK ?? 1) // node 4 compat | ||
} | ||
@@ -106,3 +159,3 @@ | ||
`failed to read the existing and readable file: ${path}`, | ||
err, | ||
err | ||
) | ||
@@ -116,3 +169,3 @@ } | ||
contents: any, | ||
mode?: number, | ||
mode?: number | ||
): Promise<void> { | ||
@@ -132,3 +185,3 @@ return new Promise(function (resolve, reject) { | ||
contents: any, | ||
mode?: number, | ||
mode?: number | ||
): Promise<void> { | ||
@@ -160,3 +213,3 @@ // check exists | ||
`failed to write the existing and writable file: ${path}`, | ||
err, | ||
err | ||
) | ||
@@ -199,3 +252,3 @@ } | ||
`no write permission to delete the existing file: ${path}`, | ||
err, | ||
err | ||
) | ||
@@ -216,3 +269,3 @@ } | ||
`failed to delete the existing and writable file: ${path}`, | ||
err, | ||
err | ||
) | ||
@@ -222,2 +275,127 @@ } | ||
/** Remove an entire directory (including nested contents) safely. */ | ||
export async function deleteEntireDirectory( | ||
path: string, | ||
opts: RmOptions = {} | ||
): Promise<void> { | ||
// handle relative and absolute paths correctly | ||
path = _resolve(path) | ||
// check exists | ||
try { | ||
await exists(path) | ||
} catch (err: any) { | ||
// if it doesn't exist, then we don't care | ||
return | ||
} | ||
// check writable | ||
try { | ||
await writable(path) | ||
} catch (err: any) { | ||
if (err.code === 'ENOENT') { | ||
// if it doesn't exist, then we don't care | ||
// this may not seem necessary, however it is | ||
// testen would fail on @bevry/json otherwise | ||
return | ||
} | ||
throw new Errlop( | ||
`no write permission to delete the existing file: ${path}`, | ||
err | ||
) | ||
} | ||
// attempt delete | ||
return new Promise(function (resolve, reject) { | ||
function next(err: any) { | ||
if (err && err.code === 'ENOENT') return resolve() | ||
if (err) return reject(err) | ||
return resolve() | ||
} | ||
if (versionCompare(nodeVersion, '14.14.0') >= 0) { | ||
import('fs').then(function ({ rm: _rm }) { | ||
_rm( | ||
path, | ||
Object.assign({ recursive: true, force: true, maxRetries: 10 }, opts), | ||
next | ||
) | ||
}) | ||
} else if ( | ||
versionCompare(nodeVersion, '12.16.0') >= 0 && | ||
versionCompare(nodeVersion, '16') < 0 | ||
) { | ||
import('fs').then(function ({ rmdir: _rmdir }) { | ||
_rmdir( | ||
path, | ||
Object.assign({ recursive: true, maxRetries: 10 }, opts), | ||
next | ||
) | ||
}) | ||
} else if ( | ||
versionCompare(nodeVersion, '12.10.0') >= 0 && | ||
versionCompare(nodeVersion, '12.16.0') < 0 | ||
) { | ||
import('fs').then(function ({ rmdir: _rmdir }) { | ||
_rmdir( | ||
path, | ||
Object.assign({ recursive: true, maxBusyTries: 10 }, opts), | ||
next | ||
) | ||
}) | ||
} else { | ||
if (path === '' || path === '/') | ||
return next(new Error('will not delete root directory')) | ||
exec(`rm -rf ${JSON.stringify(path)}`, next) | ||
} | ||
}) | ||
} | ||
/** Read an entire directory (including nested contents) safely. */ | ||
export async function readEntireDirectory( | ||
path: string | ||
): Promise<Array<string>> { | ||
// handle relative and absolute paths correctly | ||
path = _resolve(path) | ||
// check exists | ||
try { | ||
await exists(path) | ||
} catch (err: any) { | ||
throw new Errlop(`unable to read the non-existent directory: ${path}`, err) | ||
} | ||
// check readable | ||
try { | ||
await readable(path) | ||
} catch (err: any) { | ||
throw new Errlop(`no read permission for the directory: ${path}`, err) | ||
} | ||
// attempt read | ||
return new Promise(function (resolve, reject) { | ||
if (versionCompare(nodeVersion, '18.17.0') >= 0) { | ||
_readdir( | ||
path, | ||
{ encoding: null, recursive: true, withFileTypes: false }, | ||
function (err, files) { | ||
if (err) return reject(err) | ||
return resolve(files.sort()) | ||
} | ||
) | ||
} else { | ||
// find files and dirs, -f doesn't work on ubuntu | ||
exec('find .', { cwd: path }, function (err, stdout: string) { | ||
if (err) return reject(err) | ||
return resolve( | ||
stdout | ||
.split('\n') | ||
.map((p) => p.replace(/^[./\\]+/, '')) // trim . and ./ | ||
.filter(Boolean) | ||
.sort() | ||
) | ||
}) | ||
} | ||
}) | ||
} | ||
/** Read a directory */ | ||
@@ -255,5 +433,5 @@ export function readdir(path: string): Promise<Array<string>> { | ||
`failed to read the existing and readable directory: ${path}`, | ||
err, | ||
err | ||
) | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
136637
20
2884
162
2
1
18
7
+ Addededitions@^6.10.0
+ Addedversion-compare@^3.0.0
+ Addededitions@6.21.0(transitive)
+ Addedversion-compare@3.11.0(transitive)
+ Addedversion-range@4.14.0(transitive)