path-treeify 1.4.0 → 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 +9 -4
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/types/index.d.ts +8 -66
- package/dist/types/src/types.d.ts +60 -0
- package/dist/types/src/utils.d.ts +31 -0
- package/package.json +5 -5
- package/dist/types/dev/index.d.ts +0 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<img alt="GitHub Created At" src="https://img.shields.io/github/created-at/isaaxite/path-treeify">
|
|
28
28
|
</a>
|
|
29
29
|
<a href="https://github.com/isaaxite/path-treeify">
|
|
30
|
-
<img alt="
|
|
30
|
+
<img alt="NPM Unpacked Size" src="https://img.shields.io/npm/unpacked-size/path-treeify">
|
|
31
31
|
</a>
|
|
32
32
|
<a href="https://github.com/isaaxite/path-treeify/commits/main/">
|
|
33
33
|
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/isaaxite/path-treeify">
|
|
@@ -215,9 +215,14 @@ An enum classifying each node's filesystem type.
|
|
|
215
215
|
|
|
216
216
|
```ts
|
|
217
217
|
enum PathTreeNodeKind {
|
|
218
|
-
Dir
|
|
219
|
-
File
|
|
220
|
-
Unknown
|
|
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"),
|
|
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{
|
|
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};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,75 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
name: string;
|
|
4
|
-
dirPath: string;
|
|
5
|
-
}) => boolean;
|
|
6
|
-
/** Constructor options for PathTreeify */
|
|
7
|
-
interface PathTreeifyProps {
|
|
8
|
-
/** The root directory to scan */
|
|
9
|
-
base: string;
|
|
10
|
-
/** Optional filter applied to every entry during recursive traversal */
|
|
11
|
-
filter?: FilterFunction;
|
|
12
|
-
/** When true, files are included as leaf nodes alongside directories. Defaults to false */
|
|
13
|
-
fileVisible?: boolean;
|
|
14
|
-
/**
|
|
15
|
-
* When true, the result of {@link PathTreeNode.getPath} is memoised on each node
|
|
16
|
-
* after the first call. Subsequent calls return the same object reference without
|
|
17
|
-
* re-walking the parent chain. Useful when nodes are accessed repeatedly.
|
|
18
|
-
* Defaults to false.
|
|
19
|
-
*/
|
|
20
|
-
usePathCache?: boolean;
|
|
21
|
-
}
|
|
22
|
-
/** Classification of a node in the path tree */
|
|
23
|
-
export declare enum PathTreeNodeKind {
|
|
24
|
-
Dir = "dir",
|
|
25
|
-
File = "file",
|
|
26
|
-
/** Assigned before the node's type has been resolved */
|
|
27
|
-
Unknown = "unknown"
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Public interface for a node in the path tree.
|
|
31
|
-
* Consumers receive this type; the internal implementation class is not exported.
|
|
32
|
-
*/
|
|
33
|
-
export interface PathTreeNode {
|
|
34
|
-
/** Distance from the root node; root itself is 0, its direct children are 1, and so on */
|
|
35
|
-
depth: number;
|
|
36
|
-
/** Reference to the parent node; null for the root node */
|
|
37
|
-
parent: PathTreeNode | null;
|
|
38
|
-
/** The entry name of this node (not a full path) */
|
|
39
|
-
value: string;
|
|
40
|
-
/** Child nodes; non-empty only for directory nodes */
|
|
41
|
-
children: PathTreeNode[];
|
|
42
|
-
/** Whether this node is a directory, a file, or not yet resolved */
|
|
43
|
-
type: PathTreeNodeKind;
|
|
44
|
-
/**
|
|
45
|
-
* Walks up the parent chain to compute this node's relative and absolute paths.
|
|
46
|
-
* When the owning {@link PathTreeify} instance was created with `usePathCache: true`,
|
|
47
|
-
* the result is memoised after the first call and the same object is returned on
|
|
48
|
-
* every subsequent call.
|
|
49
|
-
* @returns `relative` — path from the tree root; `absolute` — fully resolved path on disk
|
|
50
|
-
*/
|
|
51
|
-
getPath(): {
|
|
52
|
-
relative: string;
|
|
53
|
-
absolute: string;
|
|
54
|
-
};
|
|
55
|
-
}
|
|
1
|
+
import { PathTreeifyProps, PathTreeNode } from './src/types';
|
|
2
|
+
export { PathTreeifyProps, PathTreeNodeKind, PathTreeNode } from './src/types';
|
|
56
3
|
/** Builds a tree of {@link PathTreeNode} entries rooted at a given base path */
|
|
57
4
|
export declare class PathTreeify {
|
|
58
5
|
/** The root directory to scan */
|
|
59
|
-
private
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*/
|
|
65
|
-
private pathTreeNodeShared;
|
|
6
|
+
private _base;
|
|
7
|
+
/** When true, files are included as leaf nodes during traversal. Defaults to false */
|
|
8
|
+
private _fileVisible;
|
|
9
|
+
/** When true, absolute paths are cached on each node after the first retrieval to speed up subsequent `getPath` calls at the cost of higher memory usage. Defaults to false */
|
|
10
|
+
private _usePathCache;
|
|
66
11
|
/**
|
|
67
12
|
* Optional user-supplied filter. When set, every entry must pass this predicate
|
|
68
13
|
* in addition to the built-in visibility check.
|
|
69
14
|
*/
|
|
70
|
-
private
|
|
71
|
-
/** When true, files are included as leaf nodes during traversal. Defaults to false */
|
|
72
|
-
private fileVisible;
|
|
15
|
+
private _userFilter?;
|
|
73
16
|
constructor(props: Partial<PathTreeifyProps>);
|
|
74
17
|
/**
|
|
75
18
|
* Determines whether a given entry should be included in the tree.
|
|
@@ -148,4 +91,3 @@ export declare class PathTreeify {
|
|
|
148
91
|
/** Builds a full tree from all immediate entries under the base path */
|
|
149
92
|
build(): PathTreeNode;
|
|
150
93
|
}
|
|
151
|
-
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** A filter function that determines whether an entry should be included in the tree */
|
|
2
|
+
export type FilterFunction = (params: {
|
|
3
|
+
name: string;
|
|
4
|
+
dirPath: string;
|
|
5
|
+
}) => boolean;
|
|
6
|
+
/** Constructor options for PathTreeify */
|
|
7
|
+
export interface PathTreeifyProps {
|
|
8
|
+
/** The root directory to scan */
|
|
9
|
+
base: string;
|
|
10
|
+
/** Optional filter applied to every entry during recursive traversal */
|
|
11
|
+
filter?: FilterFunction;
|
|
12
|
+
/** When true, files are included as leaf nodes alongside directories. Defaults to false */
|
|
13
|
+
fileVisible?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* When true, the result of {@link PathTreeNode.getPath} is memoised on each node
|
|
16
|
+
* after the first call. Subsequent calls return the same object reference without
|
|
17
|
+
* re-walking the parent chain. Useful when nodes are accessed repeatedly.
|
|
18
|
+
* Defaults to false.
|
|
19
|
+
*/
|
|
20
|
+
usePathCache?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Classification of a node in the path tree */
|
|
23
|
+
export declare enum PathTreeNodeKind {
|
|
24
|
+
Dir = "dir",
|
|
25
|
+
File = "file",
|
|
26
|
+
/** Assigned before the node's type has been resolved */
|
|
27
|
+
Unknown = "unknown",
|
|
28
|
+
BrokenSymlink = "broken_symlink",
|
|
29
|
+
Other = "other",
|
|
30
|
+
NotFound = "not_found",
|
|
31
|
+
PermissionDenied = "permission_denied",
|
|
32
|
+
Error = "error"
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Public interface for a node in the path tree.
|
|
36
|
+
* Consumers receive this type; the internal implementation class is not exported.
|
|
37
|
+
*/
|
|
38
|
+
export interface PathTreeNode {
|
|
39
|
+
/** Distance from the root node; root itself is 0, its direct children are 1, and so on */
|
|
40
|
+
depth: number;
|
|
41
|
+
/** Reference to the parent node; null for the root node */
|
|
42
|
+
parent: PathTreeNode | null;
|
|
43
|
+
/** The entry name of this node (not a full path) */
|
|
44
|
+
value: string;
|
|
45
|
+
/** Child nodes; non-empty only for directory nodes */
|
|
46
|
+
children: PathTreeNode[];
|
|
47
|
+
/** Whether this node is a directory, a file, or not yet resolved */
|
|
48
|
+
type: PathTreeNodeKind;
|
|
49
|
+
/**
|
|
50
|
+
* Walks up the parent chain to compute this node's relative and absolute paths.
|
|
51
|
+
* When the owning {@link PathTreeify} instance was created with `usePathCache: true`,
|
|
52
|
+
* the result is memoised after the first call and the same object is returned on
|
|
53
|
+
* every subsequent call.
|
|
54
|
+
* @returns `relative` — path from the tree root; `absolute` — fully resolved path on disk
|
|
55
|
+
*/
|
|
56
|
+
getPath(): {
|
|
57
|
+
relative: string;
|
|
58
|
+
absolute: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { PathTreeNode, PathTreeNodeKind } from "./types";
|
|
2
|
+
/** Defines read-only properties on an object. Each property is set to the corresponding value in the props object, and is non-writable, non-configurable, and non-enumerable.
|
|
3
|
+
* @param obj - The target object on which to define the properties
|
|
4
|
+
* @param props - An object where keys are property names and values are the corresponding property values to set
|
|
5
|
+
*/
|
|
6
|
+
export declare function defineReadOnlyProps(obj: any, props: {
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}): void;
|
|
9
|
+
/** Determines the type of a given path, classifying it as a directory, file, symbolic link, or other. If the path does not exist, it is classified as NotFound. If any unexpected error occurs during the stat/lstat operations, it will be thrown to the caller.
|
|
10
|
+
* @param p - The path to classify
|
|
11
|
+
* @returns A PathTreeNodeKind value indicating the type of the path
|
|
12
|
+
*/
|
|
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. */
|
|
15
|
+
export declare function getSafePathType(p: string): PathTreeNodeKind;
|
|
16
|
+
/** Implementation of the PathTreeNode interface. This class is not exported; consumers receive nodes through the PathTreeify API as the PathTreeNode interface type. */
|
|
17
|
+
export declare class PathTreeNodeImp implements PathTreeNode {
|
|
18
|
+
depth: number;
|
|
19
|
+
parent: PathTreeNode | null;
|
|
20
|
+
value: string;
|
|
21
|
+
children: PathTreeNode[];
|
|
22
|
+
type: PathTreeNodeKind;
|
|
23
|
+
constructor(props: {
|
|
24
|
+
usePathCache: boolean;
|
|
25
|
+
});
|
|
26
|
+
/** Retrieves the absolute and relative path represented by this node. If path caching is enabled, the result will be cached after the first retrieval to optimize subsequent calls. */
|
|
27
|
+
getPath(): {
|
|
28
|
+
relative: string;
|
|
29
|
+
absolute: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "path-treeify",
|
|
3
|
-
"version": "1.4.
|
|
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",
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"scripts": {
|
|
27
27
|
"test": "ava",
|
|
28
28
|
"test:coverage": "c8 ava",
|
|
29
|
-
"test:
|
|
30
|
-
"test:report": "rimraf reports && npm run test:coverage && npm run test:
|
|
29
|
+
"test:md": "mkdir -p reports && ava --tap | tap-json | node ./.github/scripts/generate-report.js --title \"${npm_config_title:-AVA Test Results}\" > reports/ava-test.md",
|
|
30
|
+
"test:report": "rimraf reports && npm run test:coverage && npm run test:md",
|
|
31
31
|
"clean": "rimraf dist",
|
|
32
32
|
"build": "npm run clean && rollup -c",
|
|
33
33
|
"build:dev": "NODE_ENV=development npm run build",
|
|
34
34
|
"build:prod": "NODE_ENV=production npm run build",
|
|
35
|
-
"
|
|
35
|
+
"dev": "nodemon --watch index.ts -e ts --exec \"npm run build:dev\"",
|
|
36
36
|
"check-publish": "npm pack --dry-run",
|
|
37
37
|
"publish:beta": "npm publish --tag beta --access public",
|
|
38
38
|
"publish:latest": "npm publish --tag latest --access public"
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"nodemon": "^3.1.14",
|
|
94
94
|
"rimraf": "^6.1.3",
|
|
95
95
|
"rollup": "^4.59.0",
|
|
96
|
-
"tap-
|
|
96
|
+
"tap-json": "^1.0.0",
|
|
97
97
|
"tslib": "^2.8.1",
|
|
98
98
|
"tsx": "^4.21.0",
|
|
99
99
|
"typescript": "^5.9.3"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|