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

fs-inspect

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fs-inspect - npm Package Compare versions

Comparing version 1.0.3 to 1.0.4

279

cjs/index.js

@@ -13,22 +13,38 @@ 'use strict';

async function makeFileInfo(root, relative) {
const absolute = path__default['default'].join(root, relative);
const { base, name, ext } = path__default['default'].parse(absolute);
const info = await fs__default['default'].promises.stat(absolute);
const { size, birthtimeMs: created, mtimeMs: modified } = info;
const isDirectory = info.isDirectory();
return {
isDirectory,
hidden: name.startsWith('.'),
relative,
absolute,
size: isDirectory ? 0 : size,
base,
name,
ext,
created,
modified,
};
function isDictionary(obj) {
return obj !== null && typeof obj === 'object' && Array.isArray(obj) === false;
}
isDictionary.TYPE_NAME = 'Dictionary';
function isFunction(obj) {
return typeof obj === 'function';
}
isFunction.TYPE_NAME = 'UnknownFunction';
function isBoolean(obj) {
return typeof obj === 'boolean';
}
isBoolean.TYPE_NAME = 'boolean';
function isString(obj) {
return typeof obj === 'string';
}
isString.TYPE_NAME = 'string';
function isNumber(obj) {
return typeof obj === 'number';
}
isNumber.TYPE_NAME = 'number';
function isIndex(obj) {
return typeof obj === 'number' || typeof obj === 'string';
}
isIndex.TYPE_NAME = 'Index';
function isPrimitive(obj) {
return typeof obj === 'number' || typeof obj === 'string' || typeof obj === 'boolean';
}
isPrimitive.TYPE_NAME = 'Primitive';
function isIndexable(obj) {
return obj !== null && typeof obj === 'object';
}
isIndexable.TYPE_NAME = 'Indexable';
function isArray(obj) {
return Array.isArray(obj);
}
isArray.TYPE_NAME = 'unknown[]';
function isNullish(obj) {

@@ -43,2 +59,66 @@ return obj === null || typeof obj === 'undefined';

function isJSONValue(val) {
switch (typeof val) {
case 'string':
case 'number':
case 'boolean':
return true;
case 'object': {
if (val === null) {
return true;
}
if (Array.isArray(val)) {
return val.every(isJSONValue);
}
return Object.values(val).every(isJSONValue);
}
}
return false;
}
isJSONValue.TYPE_NAME = 'JSONValue';
function isJSONArray(val) {
return Array.isArray(val);
}
isJSONArray.TYPE_NAME = 'JSONArray';
function isJSONObject(val) {
return val !== null && typeof val === 'object' && !Array.isArray(val);
}
isJSONObject.TYPE_NAME = 'JSONObject';
function stringifyDefinition(value) {
if (typeof value === 'string') {
return value;
}
const elements = Object.entries(value);
if (elements.length === 0) {
return '{}';
}
return `{ ${elements.map(([k, v]) => `${k}: ${stringifyDefinition(v)}`).join(', ')} }`;
}
function inspectType(value, opts = {}) {
const { maxDepth = 3 } = opts;
if (typeof value !== 'object') {
return typeof value;
}
if (value === null) {
return 'null';
}
if (Array.isArray(value)) {
return 'Array';
}
if (value.constructor.name !== 'Object') {
return value.constructor.name;
}
if (maxDepth <= 0) {
return 'Dictionary';
}
const result = {};
const nestedOptions = { ...opts, maxDepth: maxDepth - 1 };
for (const [k, v] of Object.entries(value)) {
result[k] = inspectType(v, nestedOptions);
}
return stringifyDefinition(result);
}
function asDefined(obj, fallback) {

@@ -51,42 +131,5 @@ if (isDefined(obj)) {

}
throw new Error("Unable to cast " + typeof obj + " to NonNullable<unknown>");
throw new Error(`Unable to cast ${inspectType(obj)} to NonNullable<unknown>`);
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
((function (_super) {
__extends(TypeAssertion, _super);
function TypeAssertion() {
return _super !== null && _super.apply(this, arguments) || this;
}
return TypeAssertion;
})(Error));
function deferred() {

@@ -110,5 +153,5 @@ let resolve;

while (pending.length > 0) {
const next = asDefined(pending.shift());
const [info, depth] = asDefined(pending.shift());
try {
await fn(next);
await fn(info, depth);
}

@@ -120,3 +163,3 @@ catch (e) {

try {
await recover(e, next[0]);
await recover(e, info.relative);
recovered = true;

@@ -142,9 +185,9 @@ }

return {
add(location, depth) {
add(info, depth) {
if (stopped) {
return;
}
pending.push([location, depth]);
pending.push([info, depth]);
if (running < concurrency) {
runThread();
void runThread();
}

@@ -160,4 +203,38 @@ },

async function makeFileInfo(root, relative) {
const absolute = path__default["default"].join(root, relative);
const { base, name, ext } = path__default["default"].parse(absolute);
const info = await fs__default["default"].promises.stat(absolute);
const { size, birthtimeMs: created, mtimeMs: modified } = info;
const isDirectory = info.isDirectory();
return {
isDirectory,
hidden: name.startsWith('.'),
relative,
absolute,
size: isDirectory ? 0 : size,
base,
name,
ext,
created,
modified,
};
}
async function extendFileInfo(entry) {
const { base, name, ext } = path__default["default"].parse(entry.absolute);
const info = await fs__default["default"].promises.stat(entry.absolute);
const { size, birthtimeMs: created, mtimeMs: modified } = info;
return {
...entry,
size: entry.isDirectory ? 0 : size,
base,
name,
ext,
created,
modified,
};
}
function createInspector(options = {}) {
const { exclude, filter, map, concurrency = 8, maxDepth = Infinity, catch: recover, includeFolders = false, includeHidden = false } = options;
const { exclude, filter, map, concurrency = 8, maxDepth = Infinity, minDepth = 0, catch: recover, type, includeFolders, includeHidden = false } = options;
if (!isValidCount(concurrency)) {

@@ -169,35 +246,75 @@ throw new Error(`Invalid concurrency value ${concurrency}. Expected either a positive non-zero integer, or Infinity.`);

}
if (isDefined(type) && isDefined(includeFolders)) {
throw new Error('Clashing arguments "type" and "includeFolder" specified. Use "type: all" to include files and folders in your output.');
}
let includeTypes = type ?? 'files';
if (includeFolders) {
includeTypes = 'all';
}
if (minDepth !== 0 && !isValidCount(minDepth)) {
throw new Error(`Invalid minDepth value ${minDepth}. Expected either a positive integer, or Infinity.`);
}
if (minDepth > maxDepth) {
throw new Error('Invalid depth range. Expected minDepth to be less than or equal to maxDepth.');
}
return {
async search(location) {
const results = [];
const root = path__default['default'].resolve(location);
const processEntry = async ([relative, depth]) => {
const info = await makeFileInfo(root, relative);
if (info.hidden && !includeHidden) {
const processEntry = async (basicInfo, depth) => {
let fullInfo = null;
if (basicInfo.hidden && !includeHidden) {
return;
}
if (info.isDirectory) {
if (depth < maxDepth) {
if (exclude && await exclude(info)) {
if (basicInfo.isDirectory) {
if (exclude) {
fullInfo = await extendFileInfo(basicInfo);
if (await exclude(fullInfo)) {
return;
}
for (const entry of await fs__default['default'].promises.readdir(info.absolute)) {
add(path__default['default'].join(relative, entry), depth + 1);
}
if (depth < maxDepth) {
for (const entry of await fs__default["default"].promises.readdir(basicInfo.absolute, { withFileTypes: true })) {
const child = {
isDirectory: entry.isDirectory(),
hidden: entry.name.startsWith('.'),
relative: path__default["default"].join(basicInfo.relative, entry.name),
absolute: path__default["default"].join(basicInfo.absolute, entry.name),
};
add(child, depth + 1);
}
}
if (!includeFolders) {
if (includeTypes === 'files') {
return;
}
}
if (!filter || await filter(info)) {
if (map) {
results.push(await map(info));
else if (includeTypes === 'folders') {
return;
}
if (depth < minDepth) {
return;
}
if (fullInfo === null) {
fullInfo = await extendFileInfo(basicInfo);
}
if (filter) {
if (!await filter(fullInfo)) {
return;
}
else {
results.push(info);
}
}
const output = map ? await map(fullInfo) : fullInfo;
results.push(output);
};
const { add, complete } = queue({ concurrency, fn: processEntry, recover });
add('', 0);
let rootEntry;
try {
rootEntry = await makeFileInfo(path__default["default"].resolve(location), '');
}
catch (e) {
if (recover) {
await recover(e, '');
return [];
}
throw e;
}
add(rootEntry, 0);
await complete;

@@ -204,0 +321,0 @@ return results;

{
"name": "fs-inspect",
"version": "1.0.3",
"version": "1.0.4",
"description": "directory tree scanner for Node.js",

@@ -9,17 +9,17 @@ "main": "cjs/index.js",

"devDependencies": {
"@rollup/plugin-node-resolve": "^11.2.0",
"@types/jest": "^26.0.14",
"@typescript-eslint/eslint-plugin": "^4.3.0",
"@typescript-eslint/parser": "^4.3.0",
"eslint": "^7.10.0",
"jest": "^26.5.0",
"rollup": "^2.32.0",
"rollup-plugin-typescript2": "^0.28.0",
"ts-jest": "^26.4.1",
"ts-runtime-typecheck": "^2.2.0",
"typescript": "^4.1.2"
"@rollup/plugin-node-resolve": "^13.3.0",
"@types/jest": "^28.1.1",
"@typescript-eslint/eslint-plugin": "^5.28.0",
"@typescript-eslint/parser": "^5.28.0",
"eslint": "^8.17.0",
"jest": "^28.1.1",
"rollup": "^2.75.6",
"rollup-plugin-typescript2": "^0.32.1",
"ts-jest": "^28.0.5",
"ts-runtime-typecheck": "^2.6.0",
"typescript": "^4.7.3"
},
"scripts": {
"test": "jest --verbose --coverage",
"lint": "eslint",
"lint": "eslint src",
"build": "rollup -c && cp ./package.json ./dist/package.json && cp ./README.md ./dist/README.md"

@@ -26,0 +26,0 @@ },

@@ -39,3 +39,3 @@ # fs-inspect

Before each item is added to the results it can optionally be omitted using a 'filter' function. If 'includeFolders' is true then folders will be passed to the filter function, but the filter will not prevent the children of the folder from being visited.
Before each item is added to the results it can optionally be omitted using a 'filter' function. If folders are included in the output then they will be passed to the filter function, but the filter will not prevent the children of the folder from being visited.

@@ -59,3 +59,3 @@ ```typescript

When a folder is visited an optional 'exclude' function can be used to indicate that the children of the folder should be skipped, which has obvious performance advantages if you wish to skip large parts of the file tree. If 'includeFolders' is true then excluded folders will not be included in the results, so you will not have to use 'filter' to skip them.
When a folder is visited an optional 'exclude' function can be used to indicate that the children of the folder should be skipped, which has obvious performance advantages if you wish to skip large parts of the file tree. If folders are included in the output then excluded folders will not be included in the results, so you will not have to use 'filter' to skip them.

@@ -124,4 +124,6 @@ ```typescript

If you have a very deep file tree and you are only interested in the top couple of levels you can specify a depth limit with the `maxDepth` option. By default there is no limit (Infinity). The minimum value is 1, which is _just_ the direct children of the target folder.
If you have a very deep file tree and you are only interested in the top couple of levels you can specify a depth limit with the `maxDepth` option. By default there is no limit (Infinity). The minimum value is 1, which is *just* the direct children of the target folder.
Additionally if you are only interested in the results inside a subfolder then `minDepth` can be used to filter out results from the top levels. It defaults to 0 which indicates the inclusion of the root entry.
## Hidden files/folders

@@ -133,7 +135,7 @@

Folders are not added to the output by default, you can include them using the `includeFolders` option.
Folders are not added to the output by default, you can include them by setting the `type` option to `all` or `folders`. These include files and folders, or just folders respectively.
## Root entry
If the target location for the search is a file, then only that file will be included in the output. Providing that it passes any filters you have specified. If it's a folder and `includeFolders` is set then it will be included in the output. In both cases the relative path will be an empty string, indicating that it is the root of the tree.
If the target location for the search is a file, then only that file will be included in the output. Providing that it passes any filters you have specified. If it's a folder and are included in the output normally then it will be included in the output. In both cases the relative path will be an empty string, indicating that it is the root of the tree.

@@ -181,6 +183,10 @@ ## Error recovery

- ### InspectorOptions.includeFolders
- ### InspectorOptions.type
An optional boolean flag that causes folders to be included in the output. Default value is false.
An optional string which indicates if `'files'`, `'folders'` or `'all'` should be included in the output. Default value is `'files'`.
- ### InspectorOptions.includeFolders
**Depreciated** optional boolean flag that indicates that folders should be included in the output. Use `type: 'all'` instead.
- ### InspectorOptions.concurrency

@@ -194,2 +200,6 @@

- ### InspectorOptions.minDepth
An optional positive integer which specified the minimum search depth through the folder tree. Infinity indicates no limit. 0 indicates all entries should be included. Default value is 0.
- ### InspectorOptions.exclude

@@ -196,0 +206,0 @@

Sorry, the diff of this file is not supported yet

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