path-treeify 1.0.0 → 1.1.0
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 +52 -39
- package/dist/index.cjs +159 -1
- package/dist/index.mjs +157 -1
- package/dist/types/index.d.ts +10 -3
- package/package.json +5 -7
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<img alt="node" src="https://img.shields.io/node/v/path-treeify">
|
|
16
16
|
</a>
|
|
17
17
|
<a href="https://github.com/isaaxite/path-treeify/blob/main/LICENSE">
|
|
18
|
-
<img alt="
|
|
18
|
+
<img alt="GitHub License" src="https://img.shields.io/github/license/isaaxite/path-treeify">
|
|
19
19
|
</a>
|
|
20
20
|
<a href="https://github.com/isaaxite/path-treeify">
|
|
21
21
|
<img alt="GitHub Created At" src="https://img.shields.io/github/created-at/isaaxite/path-treeify">
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
|
|
38
38
|
- 🌲 Builds a recursive tree from one or more directory paths
|
|
39
39
|
- 🔗 Each node carries a `parent` circular reference for upward traversal
|
|
40
|
+
- 📍 Each node exposes a `getPath()` method to retrieve its own paths directly
|
|
40
41
|
- 🔍 Optional `filter` callback to include/exclude directories during scanning
|
|
42
|
+
- ⚡ `build()` method scans the entire `base` directory with zero configuration
|
|
41
43
|
- 📦 Ships as both ESM (`index.mjs`) and CJS (`index.cjs`) with full TypeScript types
|
|
42
44
|
- 🚫 Zero runtime dependencies
|
|
43
45
|
|
|
@@ -68,18 +70,11 @@ import { PathTreeify } from 'path-treeify';
|
|
|
68
70
|
|
|
69
71
|
const treeify = new PathTreeify({ base: '/your/project/root' });
|
|
70
72
|
|
|
71
|
-
// Scan
|
|
72
|
-
const tree = treeify.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// parent: null,
|
|
77
|
-
// value: '',
|
|
78
|
-
// children: [
|
|
79
|
-
// { parent: [Circular], value: 'src', children: [...] },
|
|
80
|
-
// { parent: [Circular], value: 'tests', children: [...] }
|
|
81
|
-
// ]
|
|
82
|
-
// }
|
|
73
|
+
// Scan specific directories
|
|
74
|
+
const tree = treeify.buildByDirNames(['src', 'tests']);
|
|
75
|
+
|
|
76
|
+
// Or scan everything under base at once
|
|
77
|
+
const fullTree = treeify.build();
|
|
83
78
|
```
|
|
84
79
|
|
|
85
80
|
---
|
|
@@ -90,10 +85,10 @@ console.log(tree);
|
|
|
90
85
|
|
|
91
86
|
Creates a new instance.
|
|
92
87
|
|
|
93
|
-
| Option | Type | Required | Description
|
|
94
|
-
|
|
95
|
-
| `base` | `string` | ✅ | Absolute path to the root directory to scan from
|
|
96
|
-
| `filter` | `FilterFunction` (see below) | ❌ | Called for every directory found during traversal
|
|
88
|
+
| Option | Type | Required | Description |
|
|
89
|
+
|----------|-------------------------------|----------|----------------------------------------------------|
|
|
90
|
+
| `base` | `string` | ✅ | Absolute path to the root directory to scan from |
|
|
91
|
+
| `filter` | `FilterFunction` (see below) | ❌ | Called for every directory found during traversal |
|
|
97
92
|
|
|
98
93
|
`base` must exist and be a directory, otherwise the constructor throws.
|
|
99
94
|
|
|
@@ -121,15 +116,25 @@ const treeify = new PathTreeify({
|
|
|
121
116
|
|
|
122
117
|
---
|
|
123
118
|
|
|
124
|
-
### `
|
|
119
|
+
### `build(): PathTreeNode`
|
|
125
120
|
|
|
126
|
-
Scans
|
|
121
|
+
Scans **all** subdirectories directly under `base` and returns a synthetic root `PathTreeNode`. This is the zero-configuration alternative to `buildByDirNames`.
|
|
127
122
|
|
|
128
123
|
```ts
|
|
129
|
-
const
|
|
124
|
+
const tree = treeify.build();
|
|
130
125
|
```
|
|
131
126
|
|
|
132
|
-
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### `buildByDirNames(dirNames: string[]): PathTreeNode`
|
|
130
|
+
|
|
131
|
+
Scans the given relative directory names (resolved against `base`) and returns a synthetic root `PathTreeNode` whose `children` are the top-level nodes you requested.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
const root = treeify.buildByDirNames(['src', 'docs']);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- Each element must be a valid, accessible directory relative to `base`.
|
|
133
138
|
- Leading and trailing slashes are stripped automatically.
|
|
134
139
|
- Throws if any path does not exist or is not a directory.
|
|
135
140
|
|
|
@@ -137,7 +142,7 @@ const root = treeify.buildByDirPaths(['src', 'docs']);
|
|
|
137
142
|
|
|
138
143
|
### `getPathBy(node: PathTreeNode): { relative: string; absolute: string }`
|
|
139
144
|
|
|
140
|
-
Walks a node's `parent` chain to reconstruct its full path.
|
|
145
|
+
Walks a node's `parent` chain to reconstruct its full path. Equivalent to calling `node.getPath()` directly.
|
|
141
146
|
|
|
142
147
|
```ts
|
|
143
148
|
const srcNode = root.children[0];
|
|
@@ -150,49 +155,57 @@ const { relative, absolute } = treeify.getPathBy(srcNode);
|
|
|
150
155
|
|
|
151
156
|
### `PathTreeNode`
|
|
152
157
|
|
|
158
|
+
`PathTreeNode` is now a **class** with its own `getPath()` method, so you can retrieve a node's path without passing it back to the `PathTreeify` instance.
|
|
159
|
+
|
|
153
160
|
```ts
|
|
154
|
-
|
|
161
|
+
class PathTreeNode {
|
|
155
162
|
parent: PathTreeNode | null; // null only on the synthetic root
|
|
156
163
|
value: string; // directory name for this node
|
|
157
164
|
children: PathTreeNode[];
|
|
165
|
+
|
|
166
|
+
getPath(): { relative: string; absolute: string };
|
|
158
167
|
}
|
|
159
168
|
```
|
|
160
169
|
|
|
170
|
+
**`node.getPath()`** returns the same result as `treeify.getPathBy(node)` — both are available for convenience.
|
|
171
|
+
|
|
161
172
|
> ⚠️ **Circular references** — `parent` points back up the tree. Use `JSON.stringify` replacers or a library like `flatted` if you need to serialize the result.
|
|
162
173
|
|
|
163
174
|
---
|
|
164
175
|
|
|
165
176
|
## Examples
|
|
166
177
|
|
|
167
|
-
### Scan an entire directory
|
|
178
|
+
### Scan an entire base directory
|
|
168
179
|
|
|
169
180
|
```ts
|
|
170
181
|
import { PathTreeify } from 'path-treeify';
|
|
171
|
-
import { readdirSync } from 'fs';
|
|
172
182
|
|
|
173
|
-
const
|
|
174
|
-
|
|
183
|
+
const treeify = new PathTreeify({
|
|
184
|
+
base: '/your/project',
|
|
185
|
+
filter: ({ name }) => name !== 'node_modules' && !name.startsWith('.'),
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const tree = treeify.build();
|
|
189
|
+
```
|
|
175
190
|
|
|
176
|
-
|
|
177
|
-
const topLevel = readdirSync(base, { withFileTypes: true })
|
|
178
|
-
.filter(d => d.isDirectory())
|
|
179
|
-
.map(d => d.name);
|
|
191
|
+
### Scan specific directories
|
|
180
192
|
|
|
181
|
-
|
|
193
|
+
```ts
|
|
194
|
+
const tree = treeify.buildByDirNames(['src', 'tests', 'docs']);
|
|
182
195
|
```
|
|
183
196
|
|
|
184
|
-
### Retrieve
|
|
197
|
+
### Retrieve paths via `node.getPath()`
|
|
185
198
|
|
|
186
199
|
```ts
|
|
187
|
-
function printPaths(node
|
|
200
|
+
function printPaths(node) {
|
|
188
201
|
for (const child of node.children) {
|
|
189
|
-
const { absolute } =
|
|
202
|
+
const { absolute } = child.getPath();
|
|
190
203
|
console.log(absolute);
|
|
191
|
-
printPaths(child
|
|
204
|
+
printPaths(child);
|
|
192
205
|
}
|
|
193
206
|
}
|
|
194
207
|
|
|
195
|
-
printPaths(tree
|
|
208
|
+
printPaths(tree);
|
|
196
209
|
```
|
|
197
210
|
|
|
198
211
|
### CommonJS usage
|
|
@@ -201,11 +214,11 @@ printPaths(tree, treeify);
|
|
|
201
214
|
const { PathTreeify } = require('path-treeify');
|
|
202
215
|
|
|
203
216
|
const treeify = new PathTreeify({ base: __dirname });
|
|
204
|
-
const tree = treeify.
|
|
217
|
+
const tree = treeify.build();
|
|
205
218
|
```
|
|
206
219
|
|
|
207
220
|
---
|
|
208
221
|
|
|
209
222
|
## License
|
|
210
223
|
|
|
211
|
-
[MIT](https://github.com/isaaxite/path-treeify/blob/main
|
|
224
|
+
[MIT](https://github.com/isaaxite/path-treeify/blob/main/LICENSE) © [isaaxite](https://github.com/isaaxite)
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1,159 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
|
|
6
|
+
class PathValidator {
|
|
7
|
+
static isValid(path) {
|
|
8
|
+
try {
|
|
9
|
+
fs.accessSync(path, fs.constants.F_OK);
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
static isDirectory(path) {
|
|
17
|
+
try {
|
|
18
|
+
return fs.statSync(path).isDirectory();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
class PathTreeNode {
|
|
26
|
+
constructor(base) {
|
|
27
|
+
this.parent = null;
|
|
28
|
+
this.value = '';
|
|
29
|
+
this.children = [];
|
|
30
|
+
this.base = base;
|
|
31
|
+
}
|
|
32
|
+
getPath() {
|
|
33
|
+
let relative = '';
|
|
34
|
+
let current = this;
|
|
35
|
+
while (current.parent) {
|
|
36
|
+
relative = relative
|
|
37
|
+
? `${current.value}${path.sep}${relative}`
|
|
38
|
+
: current.value;
|
|
39
|
+
current = current.parent;
|
|
40
|
+
}
|
|
41
|
+
return { relative, absolute: path.resolve(this.base, relative) };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
class PathTreeify {
|
|
45
|
+
constructor({ filter, base }) {
|
|
46
|
+
if (typeof filter !== 'undefined') {
|
|
47
|
+
this.validateFilter(filter);
|
|
48
|
+
this.filter = filter;
|
|
49
|
+
}
|
|
50
|
+
if (!base || !PathValidator.isValid(base)) {
|
|
51
|
+
throw new Error(`${base} is not a valid path!`);
|
|
52
|
+
}
|
|
53
|
+
if (!PathValidator.isDirectory(base)) {
|
|
54
|
+
throw new Error(`${base} is not a dirPath!`);
|
|
55
|
+
}
|
|
56
|
+
this.base = base;
|
|
57
|
+
}
|
|
58
|
+
validateFilter(filter) {
|
|
59
|
+
if (typeof filter !== 'function') {
|
|
60
|
+
throw new TypeError('filter must be a function');
|
|
61
|
+
}
|
|
62
|
+
if (filter.length !== 1) {
|
|
63
|
+
throw new TypeError('filter must accept exactly one parameter');
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const testResult = filter({ name: 'test', postPath: '/test' });
|
|
67
|
+
if (typeof testResult !== 'boolean') {
|
|
68
|
+
throw new TypeError('filter must return a boolean');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
throw new TypeError('filter function threw an error during test: ' + error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
initNode(parent = null) {
|
|
76
|
+
const node = new PathTreeNode(this.base);
|
|
77
|
+
if (parent) {
|
|
78
|
+
node.parent = parent;
|
|
79
|
+
}
|
|
80
|
+
return node;
|
|
81
|
+
}
|
|
82
|
+
buildChildren(dirPath, parent) {
|
|
83
|
+
const names = fs.readdirSync(dirPath);
|
|
84
|
+
const children = [];
|
|
85
|
+
for (const name of names) {
|
|
86
|
+
const subPath = path.join(dirPath, name);
|
|
87
|
+
if (!fs.statSync(subPath).isDirectory()) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (this.filter && !this.filter({ dirPath, name })) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const node = this.initNode();
|
|
94
|
+
node.value = name;
|
|
95
|
+
node.parent = parent;
|
|
96
|
+
node.children = this.buildChildren(subPath, node);
|
|
97
|
+
children.push(node);
|
|
98
|
+
}
|
|
99
|
+
return children;
|
|
100
|
+
}
|
|
101
|
+
checkRelativePaths(relativeDirNames) {
|
|
102
|
+
if (!Array.isArray(relativeDirNames)) {
|
|
103
|
+
throw new Error(`Expected array, got ${typeof relativeDirNames}`);
|
|
104
|
+
}
|
|
105
|
+
for (let i = 0; i < relativeDirNames.length; i++) {
|
|
106
|
+
const it = relativeDirNames[i];
|
|
107
|
+
if (typeof it !== 'string') {
|
|
108
|
+
throw new Error(`Item at index ${i} is not a string, got ${typeof it}`);
|
|
109
|
+
}
|
|
110
|
+
const absPath = path.resolve(this.base, it);
|
|
111
|
+
if (!PathValidator.isValid(absPath)) {
|
|
112
|
+
throw new Error(`Path does not exist or is not accessible: ${absPath} (from relative path: ${it})`);
|
|
113
|
+
}
|
|
114
|
+
if (!PathValidator.isDirectory(absPath)) {
|
|
115
|
+
throw new Error(`Path is not a directory: ${absPath} (from relative path: ${it})`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
formatDirnames(dirNames) {
|
|
120
|
+
return dirNames.map(dir => {
|
|
121
|
+
// Remove leading and trailing slashes
|
|
122
|
+
return dir.replace(/^\/+|\/+$/g, '');
|
|
123
|
+
}).filter(dir => dir !== ''); // Optional: filter empty strings
|
|
124
|
+
}
|
|
125
|
+
getPathBy(node) {
|
|
126
|
+
let relative = '';
|
|
127
|
+
let current = node;
|
|
128
|
+
while (current.parent) {
|
|
129
|
+
relative = relative
|
|
130
|
+
? `${current.value}${path.sep}${relative}`
|
|
131
|
+
: current.value;
|
|
132
|
+
current = current.parent;
|
|
133
|
+
}
|
|
134
|
+
return { relative, absolute: path.resolve(this.base, relative) };
|
|
135
|
+
}
|
|
136
|
+
buildByDirNames(dirNames) {
|
|
137
|
+
const root = this.initNode();
|
|
138
|
+
this.checkRelativePaths(dirNames);
|
|
139
|
+
const dirNameArr = this.formatDirnames(dirNames);
|
|
140
|
+
for (const dirName of dirNameArr) {
|
|
141
|
+
const node = this.initNode();
|
|
142
|
+
node.value = dirName;
|
|
143
|
+
node.parent = root;
|
|
144
|
+
node.children = this.buildChildren(path.resolve(this.base, dirName), node);
|
|
145
|
+
root.children.push(node);
|
|
146
|
+
}
|
|
147
|
+
return root;
|
|
148
|
+
}
|
|
149
|
+
build() {
|
|
150
|
+
const dirNameArr = fs.readdirSync(this.base).filter(name => {
|
|
151
|
+
const abs = path.resolve(this.base, name);
|
|
152
|
+
return PathValidator.isDirectory(abs);
|
|
153
|
+
});
|
|
154
|
+
return this.buildByDirNames(dirNameArr);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
exports.PathTreeify = PathTreeify;
|
|
159
|
+
//# sourceMappingURL=index.cjs.map
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1,157 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { readdirSync, statSync, accessSync, constants } from 'fs';
|
|
2
|
+
import { join, resolve, sep } from 'path';
|
|
3
|
+
|
|
4
|
+
class PathValidator {
|
|
5
|
+
static isValid(path) {
|
|
6
|
+
try {
|
|
7
|
+
accessSync(path, constants.F_OK);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
static isDirectory(path) {
|
|
15
|
+
try {
|
|
16
|
+
return statSync(path).isDirectory();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
class PathTreeNode {
|
|
24
|
+
constructor(base) {
|
|
25
|
+
this.parent = null;
|
|
26
|
+
this.value = '';
|
|
27
|
+
this.children = [];
|
|
28
|
+
this.base = base;
|
|
29
|
+
}
|
|
30
|
+
getPath() {
|
|
31
|
+
let relative = '';
|
|
32
|
+
let current = this;
|
|
33
|
+
while (current.parent) {
|
|
34
|
+
relative = relative
|
|
35
|
+
? `${current.value}${sep}${relative}`
|
|
36
|
+
: current.value;
|
|
37
|
+
current = current.parent;
|
|
38
|
+
}
|
|
39
|
+
return { relative, absolute: resolve(this.base, relative) };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
class PathTreeify {
|
|
43
|
+
constructor({ filter, base }) {
|
|
44
|
+
if (typeof filter !== 'undefined') {
|
|
45
|
+
this.validateFilter(filter);
|
|
46
|
+
this.filter = filter;
|
|
47
|
+
}
|
|
48
|
+
if (!base || !PathValidator.isValid(base)) {
|
|
49
|
+
throw new Error(`${base} is not a valid path!`);
|
|
50
|
+
}
|
|
51
|
+
if (!PathValidator.isDirectory(base)) {
|
|
52
|
+
throw new Error(`${base} is not a dirPath!`);
|
|
53
|
+
}
|
|
54
|
+
this.base = base;
|
|
55
|
+
}
|
|
56
|
+
validateFilter(filter) {
|
|
57
|
+
if (typeof filter !== 'function') {
|
|
58
|
+
throw new TypeError('filter must be a function');
|
|
59
|
+
}
|
|
60
|
+
if (filter.length !== 1) {
|
|
61
|
+
throw new TypeError('filter must accept exactly one parameter');
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const testResult = filter({ name: 'test', postPath: '/test' });
|
|
65
|
+
if (typeof testResult !== 'boolean') {
|
|
66
|
+
throw new TypeError('filter must return a boolean');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
throw new TypeError('filter function threw an error during test: ' + error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
initNode(parent = null) {
|
|
74
|
+
const node = new PathTreeNode(this.base);
|
|
75
|
+
if (parent) {
|
|
76
|
+
node.parent = parent;
|
|
77
|
+
}
|
|
78
|
+
return node;
|
|
79
|
+
}
|
|
80
|
+
buildChildren(dirPath, parent) {
|
|
81
|
+
const names = readdirSync(dirPath);
|
|
82
|
+
const children = [];
|
|
83
|
+
for (const name of names) {
|
|
84
|
+
const subPath = join(dirPath, name);
|
|
85
|
+
if (!statSync(subPath).isDirectory()) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (this.filter && !this.filter({ dirPath, name })) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const node = this.initNode();
|
|
92
|
+
node.value = name;
|
|
93
|
+
node.parent = parent;
|
|
94
|
+
node.children = this.buildChildren(subPath, node);
|
|
95
|
+
children.push(node);
|
|
96
|
+
}
|
|
97
|
+
return children;
|
|
98
|
+
}
|
|
99
|
+
checkRelativePaths(relativeDirNames) {
|
|
100
|
+
if (!Array.isArray(relativeDirNames)) {
|
|
101
|
+
throw new Error(`Expected array, got ${typeof relativeDirNames}`);
|
|
102
|
+
}
|
|
103
|
+
for (let i = 0; i < relativeDirNames.length; i++) {
|
|
104
|
+
const it = relativeDirNames[i];
|
|
105
|
+
if (typeof it !== 'string') {
|
|
106
|
+
throw new Error(`Item at index ${i} is not a string, got ${typeof it}`);
|
|
107
|
+
}
|
|
108
|
+
const absPath = resolve(this.base, it);
|
|
109
|
+
if (!PathValidator.isValid(absPath)) {
|
|
110
|
+
throw new Error(`Path does not exist or is not accessible: ${absPath} (from relative path: ${it})`);
|
|
111
|
+
}
|
|
112
|
+
if (!PathValidator.isDirectory(absPath)) {
|
|
113
|
+
throw new Error(`Path is not a directory: ${absPath} (from relative path: ${it})`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
formatDirnames(dirNames) {
|
|
118
|
+
return dirNames.map(dir => {
|
|
119
|
+
// Remove leading and trailing slashes
|
|
120
|
+
return dir.replace(/^\/+|\/+$/g, '');
|
|
121
|
+
}).filter(dir => dir !== ''); // Optional: filter empty strings
|
|
122
|
+
}
|
|
123
|
+
getPathBy(node) {
|
|
124
|
+
let relative = '';
|
|
125
|
+
let current = node;
|
|
126
|
+
while (current.parent) {
|
|
127
|
+
relative = relative
|
|
128
|
+
? `${current.value}${sep}${relative}`
|
|
129
|
+
: current.value;
|
|
130
|
+
current = current.parent;
|
|
131
|
+
}
|
|
132
|
+
return { relative, absolute: resolve(this.base, relative) };
|
|
133
|
+
}
|
|
134
|
+
buildByDirNames(dirNames) {
|
|
135
|
+
const root = this.initNode();
|
|
136
|
+
this.checkRelativePaths(dirNames);
|
|
137
|
+
const dirNameArr = this.formatDirnames(dirNames);
|
|
138
|
+
for (const dirName of dirNameArr) {
|
|
139
|
+
const node = this.initNode();
|
|
140
|
+
node.value = dirName;
|
|
141
|
+
node.parent = root;
|
|
142
|
+
node.children = this.buildChildren(resolve(this.base, dirName), node);
|
|
143
|
+
root.children.push(node);
|
|
144
|
+
}
|
|
145
|
+
return root;
|
|
146
|
+
}
|
|
147
|
+
build() {
|
|
148
|
+
const dirNameArr = readdirSync(this.base).filter(name => {
|
|
149
|
+
const abs = resolve(this.base, name);
|
|
150
|
+
return PathValidator.isDirectory(abs);
|
|
151
|
+
});
|
|
152
|
+
return this.buildByDirNames(dirNameArr);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export { PathTreeify };
|
|
157
|
+
//# sourceMappingURL=index.mjs.map
|
package/dist/types/index.d.ts
CHANGED
|
@@ -6,10 +6,16 @@ interface PathTreeifyProps {
|
|
|
6
6
|
base: string;
|
|
7
7
|
filter?: FilterFunction;
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
declare class PathTreeNode {
|
|
10
|
+
private base;
|
|
10
11
|
parent: PathTreeNode | null;
|
|
11
12
|
value: string;
|
|
12
13
|
children: PathTreeNode[];
|
|
14
|
+
constructor(base: string);
|
|
15
|
+
getPath(): {
|
|
16
|
+
relative: string;
|
|
17
|
+
absolute: string;
|
|
18
|
+
};
|
|
13
19
|
}
|
|
14
20
|
export declare class PathTreeify {
|
|
15
21
|
private base;
|
|
@@ -18,12 +24,13 @@ export declare class PathTreeify {
|
|
|
18
24
|
private validateFilter;
|
|
19
25
|
private initNode;
|
|
20
26
|
private buildChildren;
|
|
21
|
-
private
|
|
27
|
+
private checkRelativePaths;
|
|
22
28
|
private formatDirnames;
|
|
23
29
|
getPathBy(node: PathTreeNode): {
|
|
24
30
|
relative: string;
|
|
25
31
|
absolute: string;
|
|
26
32
|
};
|
|
27
|
-
|
|
33
|
+
buildByDirNames(dirNames: string[]): PathTreeNode;
|
|
34
|
+
build(): PathTreeNode;
|
|
28
35
|
}
|
|
29
36
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "path-treeify",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
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",
|
|
@@ -21,10 +21,7 @@
|
|
|
21
21
|
"files": [
|
|
22
22
|
"dist/index.cjs",
|
|
23
23
|
"dist/index.mjs",
|
|
24
|
-
"dist/**/*.d.ts"
|
|
25
|
-
"README.md",
|
|
26
|
-
"!README.zh-CN.md",
|
|
27
|
-
"LICENSE"
|
|
24
|
+
"dist/**/*.d.ts"
|
|
28
25
|
],
|
|
29
26
|
"scripts": {
|
|
30
27
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -32,9 +29,10 @@
|
|
|
32
29
|
"build": "npm run clean && rollup -c",
|
|
33
30
|
"build:dev": "NODE_ENV=development npm run build",
|
|
34
31
|
"build:prod": "NODE_ENV=production npm run build",
|
|
35
|
-
"build:watch": "nodemon --watch
|
|
32
|
+
"build:watch": "nodemon --watch index.ts -e ts --exec \"npm run build:dev\"",
|
|
36
33
|
"check-publish": "npm pack --dry-run",
|
|
37
|
-
"publish": "npm publish"
|
|
34
|
+
"publish:beta": "npm publish --tag beta --access public",
|
|
35
|
+
"publish:latest": "npm publish --tag latest --access public"
|
|
38
36
|
},
|
|
39
37
|
"repository": {
|
|
40
38
|
"type": "git",
|