path-treeify 1.4.0-beta.31d8864 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -215,9 +215,14 @@ An enum classifying each node's filesystem type.
215
215
 
216
216
  ```ts
217
217
  enum PathTreeNodeKind {
218
- Dir = 'dir',
219
- File = 'file',
220
- Unknown = 'unknown', // assigned before the type is resolved
218
+ Dir = 'dir',
219
+ File = 'file',
220
+ Unknown = 'unknown', // assigned before the type is resolved
221
+ BrokenSymlink = 'broken_symlink',
222
+ Other = 'other', // FIFO/socket etc.
223
+ NotFound = 'not_found',
224
+ PermissionDenied = 'permission_denied',
225
+ Error = 'error',
221
226
  }
222
227
  ```
223
228
 
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=require("fs"),r=require("path");function i(e,t){for(const r in t)Object.defineProperty(e,r,{value:t[r],writable:!1,configurable:!1,enumerable:!1})}function s(e){try{return function(e){try{const r=t.statSync(e);return r.isDirectory()?exports.PathTreeNodeKind.Dir:r.isFile()?exports.PathTreeNodeKind.File:exports.PathTreeNodeKind.Other}catch(e){if("ENOENT"!==e.code)throw e}try{return t.lstatSync(e).isSymbolicLink()?exports.PathTreeNodeKind.BrokenSymlink:exports.PathTreeNodeKind.Other}catch(e){if("ENOENT"!==e.code)throw e}return exports.PathTreeNodeKind.NotFound}(e)}catch(e){return exports.PathTreeNodeKind.Error}}exports.PathTreeNodeKind=void 0,(e=exports.PathTreeNodeKind||(exports.PathTreeNodeKind={})).Dir="dir",e.File="file",e.Unknown="unknown",e.BrokenSymlink="broken_symlink",e.Other="other",e.NotFound="not_found",e.Error="error";class n{static isValid(e){try{return t.accessSync(e,t.constants.F_OK),!0}catch{return!1}}static isDirectory(e){try{return t.statSync(e).isDirectory()}catch{return!1}}static isFile(e){try{return t.statSync(e).isFile()}catch{return!1}}}class o{constructor(e){this.depth=-1,this.parent=null,this.value="",this.children=[],this.type=exports.PathTreeNodeKind.Unknown,i(this,{_usePathCache:e.usePathCache})}getPath(){let e=this,t="";const s=()=>{let e="",i=this;for(;;){if(null===i.parent){t=i.value;break}e=e?`${i.value}${r.sep}${e}`:i.value,i=i.parent}return{relative:e,absolute:r.resolve(t,e)}};return e._usePathCache?(e._pathCache||i(this,{_pathCache:s()}),e._pathCache):s()}}exports.PathTreeify=class{constructor(e){this._base="",this._fileVisible=!1,this._usePathCache=!1;const{filter:t,base:r,fileVisible:s,usePathCache:o}=e;if(void 0!==t&&(this.validateFilter(t),i(this,{_userFilter:t})),!r||!n.isValid(r))throw new Error(`${r} is not a valid path!`);if(!n.isDirectory(r))throw new Error(`${r} is not a dirPath!`);i(this,{_usePathCache:Boolean(o),_base:r,_fileVisible:!("boolean"!=typeof s||!s)&&s})}applyFilter(e,t){return!(!this._fileVisible&&!n.isDirectory(e))&&(!this._userFilter||this._userFilter({name:t,dirPath:r.dirname(e)}))}validateFilter(e){if("function"!=typeof e)throw new TypeError("filter must be a function")}initNode(){return new o({usePathCache:this._usePathCache})}buildChildren(e,i,n){const o=[],a=i.depth+1,h=n||t.readdirSync(e);for(const t of h){const n=r.join(e,t);if(!this.applyFilter(n,t))continue;const h=s(n),l=this.initNode();l.depth=a,l.value=t,l.parent=i,o.push(l),this._fileVisible&&h===exports.PathTreeNodeKind.File?l.type=h:h===exports.PathTreeNodeKind.Dir?(l.type=h,l.children=this.buildChildren(n,l)):l.type=h}return o}checkRelativePaths(e){for(let t=0;t<e.length;t++){const i=e[t];if("string"!=typeof i)throw new Error(`Item at index ${t} is not a string, got ${typeof i}`);const s=r.resolve(this._base,i);if(!n.isValid(s))throw new Error(`Path does not exist or is not accessible: ${s} (from relative path: ${i})`);if(!(n.isDirectory(s)||this._fileVisible&&n.isFile(s)))throw new Error(`Path is not a directory: ${s} (from relative path: ${i})`)}}formatSegments(e){return e.map(e=>e.split(/[/\\]/).filter(Boolean).join(r.sep)).filter(Boolean)}getAllEntriesUnderBase(){return t.readdirSync(this._base).filter(e=>{const t=r.resolve(this._base,e);return this.applyFilter(t,e)})}buildBySegments(e){const t=this.initNode();return t.depth=0,t.value=this._base,t.type=exports.PathTreeNodeKind.Dir,t.children=this.buildChildren(this._base,t,e),t}buildByFilter(e){const t=this.getAllEntriesUnderBase();return this.buildBySegments(t.filter(e))}buildBy(e){if(Array.isArray(e)){const t=this.formatSegments(e);return this.checkRelativePaths(t),this.buildBySegments(t)}if("function"==typeof e)return this.buildByFilter(e);throw new TypeError("buildBy: expected an array of strings or a filter function, but received "+typeof e)}build(){const e=this.getAllEntriesUnderBase();return this.buildBySegments(e)}};
1
+ "use strict";var e,t=require("fs"),r=require("path");function i(e,t){for(const r in t)Object.defineProperty(e,r,{value:t[r],writable:!1,configurable:!1,enumerable:!1})}function n(e){try{return function(e){try{const r=t.statSync(e);if(r.isDirectory()){try{t.accessSync(e,t.constants.X_OK)}catch{return exports.PathTreeNodeKind.PermissionDenied}return exports.PathTreeNodeKind.Dir}return r.isFile()?exports.PathTreeNodeKind.File:exports.PathTreeNodeKind.Other}catch(e){const t=e.code;if("EACCES"===t)return exports.PathTreeNodeKind.PermissionDenied;if("ENOENT"!==t)throw e}try{return t.lstatSync(e).isSymbolicLink()?exports.PathTreeNodeKind.BrokenSymlink:exports.PathTreeNodeKind.Other}catch(e){const t=e.code;if("EACCES"===t)return exports.PathTreeNodeKind.PermissionDenied;if("ENOENT"!==t)throw e}return exports.PathTreeNodeKind.NotFound}(e)}catch(e){return exports.PathTreeNodeKind.Error}}exports.PathTreeNodeKind=void 0,(e=exports.PathTreeNodeKind||(exports.PathTreeNodeKind={})).Dir="dir",e.File="file",e.Unknown="unknown",e.BrokenSymlink="broken_symlink",e.Other="other",e.NotFound="not_found",e.PermissionDenied="permission_denied",e.Error="error";class s{constructor(e){this.depth=-1,this.parent=null,this.value="",this.children=[],this.type=exports.PathTreeNodeKind.Unknown,i(this,{_usePathCache:e.usePathCache})}getPath(){let e=this,t="";const n=()=>{let e="",i=this;for(;;){if(null===i.parent){t=i.value;break}e=e?`${i.value}${r.sep}${e}`:i.value,i=i.parent}return{relative:e,absolute:r.resolve(t,e)}};return e._usePathCache?(e._pathCache||i(this,{_pathCache:n()}),e._pathCache):n()}}exports.PathTreeify=class{constructor(e){this._base="",this._fileVisible=!1,this._usePathCache=!1;const{filter:t,base:r,fileVisible:s,usePathCache:o}=e,a=n(r||"");if(void 0!==t&&(this.validateFilter(t),i(this,{_userFilter:t})),a!==exports.PathTreeNodeKind.Dir)throw new Error(`${r} not a valid dirPath!`);i(this,{_usePathCache:Boolean(o),_base:r,_fileVisible:!("boolean"!=typeof s||!s)&&s})}applyFilter(e,t){return!(!this._fileVisible&&n(e)!==exports.PathTreeNodeKind.Dir)&&(!this._userFilter||this._userFilter({name:t,dirPath:r.dirname(e)}))}validateFilter(e){if("function"!=typeof e)throw new TypeError("filter must be a function")}initNode(){return new s({usePathCache:this._usePathCache})}buildChildren(e,i,s){const o=[],a=i.depth+1,h=s||t.readdirSync(e);for(const t of h){const s=r.join(e,t);if(!this.applyFilter(s,t))continue;const h=n(s),d=this.initNode();d.depth=a,d.value=t,d.parent=i,o.push(d),this._fileVisible&&h===exports.PathTreeNodeKind.File?d.type=h:h===exports.PathTreeNodeKind.Dir?(d.type=h,d.children=this.buildChildren(s,d)):d.type=h}return o}checkRelativePaths(e){for(let t=0;t<e.length;t++){const i=e[t];if("string"!=typeof i)throw new Error(`Item at index ${t} is not a string, got ${typeof i}`);const s=r.resolve(this._base,i),o=n(s);if([exports.PathTreeNodeKind.NotFound,exports.PathTreeNodeKind.PermissionDenied,exports.PathTreeNodeKind.Other,exports.PathTreeNodeKind.Error,exports.PathTreeNodeKind.BrokenSymlink].includes(o))throw new Error(`Path does not exist or is not accessible: ${s} (from relative path: ${i})`);if(o!==exports.PathTreeNodeKind.Dir&&(!this._fileVisible||o!==exports.PathTreeNodeKind.File))throw new Error(`Path is not a directory: ${s} (from relative path: ${i})`)}}formatSegments(e){return e.map(e=>e.split(/[/\\]/).filter(Boolean).join(r.sep)).filter(Boolean)}getAllEntriesUnderBase(){return t.readdirSync(this._base).filter(e=>{const t=r.resolve(this._base,e);return this.applyFilter(t,e)})}buildBySegments(e){const t=this.initNode();return t.depth=0,t.value=this._base,t.type=exports.PathTreeNodeKind.Dir,t.children=this.buildChildren(this._base,t,e),t}buildByFilter(e){const t=this.getAllEntriesUnderBase();return this.buildBySegments(t.filter(e))}buildBy(e){if(Array.isArray(e)){const t=this.formatSegments(e);return this.checkRelativePaths(t),this.buildBySegments(t)}if("function"==typeof e)return this.buildByFilter(e);throw new TypeError("buildBy: expected an array of strings or a filter function, but received "+typeof e)}build(){const e=this.getAllEntriesUnderBase();return this.buildBySegments(e)}};
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{accessSync as t,constants as e,statSync as i,lstatSync as r,readdirSync as s}from"fs";import{sep as n,resolve as o,dirname as a,join as l}from"path";var h;function c(t,e){for(const i in e)Object.defineProperty(t,i,{value:e[i],writable:!1,configurable:!1,enumerable:!1})}function u(t){try{return function(t){try{const e=i(t);return e.isDirectory()?h.Dir:e.isFile()?h.File:h.Other}catch(t){if("ENOENT"!==t.code)throw t}try{return r(t).isSymbolicLink()?h.BrokenSymlink:h.Other}catch(t){if("ENOENT"!==t.code)throw t}return h.NotFound}(t)}catch(t){return h.Error}}!function(t){t.Dir="dir",t.File="file",t.Unknown="unknown",t.BrokenSymlink="broken_symlink",t.Other="other",t.NotFound="not_found",t.Error="error"}(h||(h={}));class f{static isValid(i){try{return t(i,e.F_OK),!0}catch{return!1}}static isDirectory(t){try{return i(t).isDirectory()}catch{return!1}}static isFile(t){try{return i(t).isFile()}catch{return!1}}}class d{constructor(t){this.depth=-1,this.parent=null,this.value="",this.children=[],this.type=h.Unknown,c(this,{_usePathCache:t.usePathCache})}getPath(){let t=this,e="";const i=()=>{let t="",i=this;for(;;){if(null===i.parent){e=i.value;break}t=t?`${i.value}${n}${t}`:i.value,i=i.parent}return{relative:t,absolute:o(e,t)}};return t._usePathCache?(t._pathCache||c(this,{_pathCache:i()}),t._pathCache):i()}}class y{constructor(t){this._base="",this._fileVisible=!1,this._usePathCache=!1;const{filter:e,base:i,fileVisible:r,usePathCache:s}=t;if(void 0!==e&&(this.validateFilter(e),c(this,{_userFilter:e})),!i||!f.isValid(i))throw new Error(`${i} is not a valid path!`);if(!f.isDirectory(i))throw new Error(`${i} is not a dirPath!`);c(this,{_usePathCache:Boolean(s),_base:i,_fileVisible:!("boolean"!=typeof r||!r)&&r})}applyFilter(t,e){return!(!this._fileVisible&&!f.isDirectory(t))&&(!this._userFilter||this._userFilter({name:e,dirPath:a(t)}))}validateFilter(t){if("function"!=typeof t)throw new TypeError("filter must be a function")}initNode(){return new d({usePathCache:this._usePathCache})}buildChildren(t,e,i){const r=[],n=e.depth+1,o=i||s(t);for(const i of o){const s=l(t,i);if(!this.applyFilter(s,i))continue;const o=u(s),a=this.initNode();a.depth=n,a.value=i,a.parent=e,r.push(a),this._fileVisible&&o===h.File?a.type=o:o===h.Dir?(a.type=o,a.children=this.buildChildren(s,a)):a.type=o}return r}checkRelativePaths(t){for(let e=0;e<t.length;e++){const i=t[e];if("string"!=typeof i)throw new Error(`Item at index ${e} is not a string, got ${typeof i}`);const r=o(this._base,i);if(!f.isValid(r))throw new Error(`Path does not exist or is not accessible: ${r} (from relative path: ${i})`);if(!(f.isDirectory(r)||this._fileVisible&&f.isFile(r)))throw new Error(`Path is not a directory: ${r} (from relative path: ${i})`)}}formatSegments(t){return t.map(t=>t.split(/[/\\]/).filter(Boolean).join(n)).filter(Boolean)}getAllEntriesUnderBase(){return s(this._base).filter(t=>{const e=o(this._base,t);return this.applyFilter(e,t)})}buildBySegments(t){const e=this.initNode();return e.depth=0,e.value=this._base,e.type=h.Dir,e.children=this.buildChildren(this._base,e,t),e}buildByFilter(t){const e=this.getAllEntriesUnderBase();return this.buildBySegments(e.filter(t))}buildBy(t){if(Array.isArray(t)){const e=this.formatSegments(t);return this.checkRelativePaths(e),this.buildBySegments(e)}if("function"==typeof t)return this.buildByFilter(t);throw new TypeError("buildBy: expected an array of strings or a filter function, but received "+typeof t)}build(){const t=this.getAllEntriesUnderBase();return this.buildBySegments(t)}}export{h as PathTreeNodeKind,y as PathTreeify};
1
+ import{statSync as e,accessSync as t,constants as i,lstatSync as r,readdirSync as n}from"fs";import{sep as s,resolve as o,dirname as h,join as l}from"path";var a;function u(e,t){for(const i in t)Object.defineProperty(e,i,{value:t[i],writable:!1,configurable:!1,enumerable:!1})}function c(n){try{return function(n){try{const r=e(n);if(r.isDirectory()){try{t(n,i.X_OK)}catch{return a.PermissionDenied}return a.Dir}return r.isFile()?a.File:a.Other}catch(e){const t=e.code;if("EACCES"===t)return a.PermissionDenied;if("ENOENT"!==t)throw e}try{return r(n).isSymbolicLink()?a.BrokenSymlink:a.Other}catch(e){const t=e.code;if("EACCES"===t)return a.PermissionDenied;if("ENOENT"!==t)throw e}return a.NotFound}(n)}catch(e){return a.Error}}!function(e){e.Dir="dir",e.File="file",e.Unknown="unknown",e.BrokenSymlink="broken_symlink",e.Other="other",e.NotFound="not_found",e.PermissionDenied="permission_denied",e.Error="error"}(a||(a={}));class f{constructor(e){this.depth=-1,this.parent=null,this.value="",this.children=[],this.type=a.Unknown,u(this,{_usePathCache:e.usePathCache})}getPath(){let e=this,t="";const i=()=>{let e="",i=this;for(;;){if(null===i.parent){t=i.value;break}e=e?`${i.value}${s}${e}`:i.value,i=i.parent}return{relative:e,absolute:o(t,e)}};return e._usePathCache?(e._pathCache||u(this,{_pathCache:i()}),e._pathCache):i()}}class d{constructor(e){this._base="",this._fileVisible=!1,this._usePathCache=!1;const{filter:t,base:i,fileVisible:r,usePathCache:n}=e,s=c(i||"");if(void 0!==t&&(this.validateFilter(t),u(this,{_userFilter:t})),s!==a.Dir)throw new Error(`${i} not a valid dirPath!`);u(this,{_usePathCache:Boolean(n),_base:i,_fileVisible:!("boolean"!=typeof r||!r)&&r})}applyFilter(e,t){return!(!this._fileVisible&&c(e)!==a.Dir)&&(!this._userFilter||this._userFilter({name:t,dirPath:h(e)}))}validateFilter(e){if("function"!=typeof e)throw new TypeError("filter must be a function")}initNode(){return new f({usePathCache:this._usePathCache})}buildChildren(e,t,i){const r=[],s=t.depth+1,o=i||n(e);for(const i of o){const n=l(e,i);if(!this.applyFilter(n,i))continue;const o=c(n),h=this.initNode();h.depth=s,h.value=i,h.parent=t,r.push(h),this._fileVisible&&o===a.File?h.type=o:o===a.Dir?(h.type=o,h.children=this.buildChildren(n,h)):h.type=o}return r}checkRelativePaths(e){for(let t=0;t<e.length;t++){const i=e[t];if("string"!=typeof i)throw new Error(`Item at index ${t} is not a string, got ${typeof i}`);const r=o(this._base,i),n=c(r);if([a.NotFound,a.PermissionDenied,a.Other,a.Error,a.BrokenSymlink].includes(n))throw new Error(`Path does not exist or is not accessible: ${r} (from relative path: ${i})`);if(n!==a.Dir&&(!this._fileVisible||n!==a.File))throw new Error(`Path is not a directory: ${r} (from relative path: ${i})`)}}formatSegments(e){return e.map(e=>e.split(/[/\\]/).filter(Boolean).join(s)).filter(Boolean)}getAllEntriesUnderBase(){return n(this._base).filter(e=>{const t=o(this._base,e);return this.applyFilter(t,e)})}buildBySegments(e){const t=this.initNode();return t.depth=0,t.value=this._base,t.type=a.Dir,t.children=this.buildChildren(this._base,t,e),t}buildByFilter(e){const t=this.getAllEntriesUnderBase();return this.buildBySegments(t.filter(e))}buildBy(e){if(Array.isArray(e)){const t=this.formatSegments(e);return this.checkRelativePaths(t),this.buildBySegments(t)}if("function"==typeof e)return this.buildByFilter(e);throw new TypeError("buildBy: expected an array of strings or a filter function, but received "+typeof e)}build(){const e=this.getAllEntriesUnderBase();return this.buildBySegments(e)}}export{a as PathTreeNodeKind,d as PathTreeify};
@@ -28,6 +28,7 @@ export declare enum PathTreeNodeKind {
28
28
  BrokenSymlink = "broken_symlink",
29
29
  Other = "other",
30
30
  NotFound = "not_found",
31
+ PermissionDenied = "permission_denied",
31
32
  Error = "error"
32
33
  }
33
34
  /**
@@ -11,16 +11,9 @@ export declare function defineReadOnlyProps(obj: any, props: {
11
11
  * @returns A PathTreeNodeKind value indicating the type of the path
12
12
  */
13
13
  export declare function getPathType(p: string): PathTreeNodeKind;
14
+ /** A safer wrapper around getPathType that catches any unexpected errors and returns PathTreeNodeKind.Error instead. This is useful for scenarios where we want to classify inaccessible paths without crashing the entire process. */
14
15
  export declare function getSafePathType(p: string): PathTreeNodeKind;
15
- /** Utility class for validating file system paths */
16
- export declare class PathValidator {
17
- /** Returns true if the path exists and is accessible */
18
- static isValid(path: string): boolean;
19
- /** Returns true if the path points to a directory */
20
- static isDirectory(path: string): boolean;
21
- /** Returns true if the path points to a regular file */
22
- static isFile(path: string): boolean;
23
- }
16
+ /** Implementation of the PathTreeNode interface. This class is not exported; consumers receive nodes through the PathTreeify API as the PathTreeNode interface type. */
24
17
  export declare class PathTreeNodeImp implements PathTreeNode {
25
18
  depth: number;
26
19
  parent: PathTreeNode | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "path-treeify",
3
- "version": "1.4.0-beta.31d8864",
3
+ "version": "1.4.1",
4
4
  "description": "Convert a path or an array of paths into a tree-structured JavaScript object, where each node has a `parent` property that holds a circular reference to its parent node.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",