@effected/walker 0.20.1 → 0.22.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/Confine.js +19 -10
- package/ConfineReal.js +123 -0
- package/Descend.js +60 -126
- package/DescendSync.js +79 -0
- package/Walker.js +193 -38
- package/index.d.ts +591 -19
- package/index.js +4 -2
- package/internal/absolute.js +19 -0
- package/internal/descendMachine.js +282 -0
- package/internal/trimTrailing.js +13 -0
- package/internal/upwardDrivers.js +71 -0
- package/internal/upwardMachine.js +239 -0
- package/node-sync.d.ts +102 -0
- package/node-sync.js +61 -0
- package/package.json +7 -2
package/node-sync.d.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import "@effected/glob";
|
|
2
|
+
import "effect";
|
|
3
|
+
/**
|
|
4
|
+
* The stats {@link WalkerSyncFileSystem} answers — a structural subset of
|
|
5
|
+
* `node:fs` `Stats`, so `statSync` / `lstatSync` satisfy it verbatim.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
interface WalkerSyncStats {
|
|
10
|
+
/** Whether the entry is a regular file. */
|
|
11
|
+
isFile(): boolean;
|
|
12
|
+
/** Whether the entry is a directory. */
|
|
13
|
+
isDirectory(): boolean;
|
|
14
|
+
/** Whether the entry is a symbolic link (only ever true for `lstat`). */
|
|
15
|
+
isSymbolicLink(): boolean;
|
|
16
|
+
/** Modification time, epoch milliseconds. */
|
|
17
|
+
readonly mtimeMs: number;
|
|
18
|
+
/** Size in bytes. */
|
|
19
|
+
readonly size: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The synchronous file operations the sync walk needs, supplied by the
|
|
23
|
+
* consumer — `node:fs` satisfies it (`nodeWalkerFileSystem` from
|
|
24
|
+
* `@effected/walker/node-sync`).
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* Every member reports failure by throwing a node-shaped error. A `code` of
|
|
28
|
+
* `"ENOENT"` is the benign vanished-path race (empty, never recorded); any
|
|
29
|
+
* other throw from `readDirectory` or `realPath` is an unreadable directory,
|
|
30
|
+
* handled per `onUnreadable`. A throwing `stat` or `lstat` reads as "no
|
|
31
|
+
* entry", exactly as the `Effect` walk reads its failed `stat` and `lstat`.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
interface WalkerSyncFileSystem {
|
|
36
|
+
/** The entry names inside the directory at `path` (`readdirSync`). */
|
|
37
|
+
readonly readDirectory: (path: string) => ReadonlyArray<string>;
|
|
38
|
+
/** Stats of `path`, following links (`statSync`). */
|
|
39
|
+
readonly stat: (path: string) => WalkerSyncStats;
|
|
40
|
+
/** Stats of `path` itself, not following a final link (`lstatSync`). */
|
|
41
|
+
readonly lstat: (path: string) => WalkerSyncStats;
|
|
42
|
+
/** The real path of `path`, links resolved (`realpathSync`). */
|
|
43
|
+
readonly realPath: (path: string) => string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The synchronous path operations the sync forms need — a structural subset
|
|
47
|
+
* of `node:path`, so the module itself (or its `win32` / `posix` variant)
|
|
48
|
+
* satisfies it. It shapes only the absolute paths handed to the
|
|
49
|
+
* {@link WalkerSyncFileSystem}; matching is POSIX-relative by the glob
|
|
50
|
+
* contract.
|
|
51
|
+
*
|
|
52
|
+
* @remarks
|
|
53
|
+
* The members mirror core's `Path` service, so a sync form judges
|
|
54
|
+
* absoluteness, ascends and compares ceilings exactly as its `Effect` twin
|
|
55
|
+
* does under the `Path` layer of the same platform.
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
interface WalkerSyncPath {
|
|
60
|
+
/** The implementation's separator (`path.sep`). */
|
|
61
|
+
readonly sep: string;
|
|
62
|
+
/** Join segments with the implementation's separator (like `path.join`). */
|
|
63
|
+
readonly join: (...segments: ReadonlyArray<string>) => string;
|
|
64
|
+
/** The parent directory of a path (like `path.dirname`); a fixpoint at the root. */
|
|
65
|
+
readonly dirname: (path: string) => string;
|
|
66
|
+
/** Resolve segments to a normalized path (like `path.resolve`). */
|
|
67
|
+
readonly resolve: (...segments: ReadonlyArray<string>) => string;
|
|
68
|
+
/** Whether a path is absolute under this implementation (like `path.isAbsolute`). */
|
|
69
|
+
readonly isAbsolute: (path: string) => boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The platform half of every sync walk.
|
|
73
|
+
*
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
interface WalkerSyncOps {
|
|
77
|
+
/** File operations. */
|
|
78
|
+
readonly fileSystem: WalkerSyncFileSystem;
|
|
79
|
+
/** Path joining. */
|
|
80
|
+
readonly path: WalkerSyncPath;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* `WalkerSyncFileSystem` over `node:fs`: `readdirSync`, `statSync`,
|
|
84
|
+
* `lstatSync`, `realpathSync`.
|
|
85
|
+
*
|
|
86
|
+
* @public
|
|
87
|
+
*/
|
|
88
|
+
export declare const nodeWalkerFileSystem: WalkerSyncFileSystem;
|
|
89
|
+
/**
|
|
90
|
+
* `WalkerSyncPath` over `node:path` (the host platform's separator).
|
|
91
|
+
*
|
|
92
|
+
* @public
|
|
93
|
+
*/
|
|
94
|
+
export declare const nodeWalkerPath: WalkerSyncPath;
|
|
95
|
+
/**
|
|
96
|
+
* Both bindings, to spread into `descendSync` options.
|
|
97
|
+
*
|
|
98
|
+
* @public
|
|
99
|
+
*/
|
|
100
|
+
export declare const nodeWalkerSyncOps: WalkerSyncOps;
|
|
101
|
+
export type { WalkerSyncFileSystem, WalkerSyncOps, WalkerSyncPath, WalkerSyncStats };
|
|
102
|
+
//# sourceMappingURL=node-sync.d.ts.map
|
package/node-sync.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { lstatSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
// src/node-sync.ts
|
|
5
|
+
/**
|
|
6
|
+
* The Node.js binding for the synchronous walk — a ready-made
|
|
7
|
+
* `WalkerSyncFileSystem` over `node:fs` and `WalkerSyncPath` over `node:path`,
|
|
8
|
+
* so adopting `descendSync` is one import.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately a **separate subpath** (`@effected/walker/node-sync`), not part
|
|
11
|
+
* of the main entry: the main entry takes its platform through `R` (or, for the
|
|
12
|
+
* sync forms, from the caller) and imports nothing platform-shaped.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { GlobPattern } from "@effected/glob";
|
|
17
|
+
* import { descendSync } from "@effected/walker";
|
|
18
|
+
* import { nodeWalkerSyncOps } from "@effected/walker/node-sync";
|
|
19
|
+
* import { Result } from "effect";
|
|
20
|
+
*
|
|
21
|
+
* const pattern = Result.getOrThrow(GlobPattern.compileResult("src/**"));
|
|
22
|
+
* const files = descendSync(pattern, { cwd: process.cwd(), ...nodeWalkerSyncOps });
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @packageDocumentation
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* `WalkerSyncFileSystem` over `node:fs`: `readdirSync`, `statSync`,
|
|
29
|
+
* `lstatSync`, `realpathSync`.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
const nodeWalkerFileSystem = {
|
|
34
|
+
readDirectory: (p) => readdirSync(p),
|
|
35
|
+
stat: (p) => statSync(p),
|
|
36
|
+
lstat: (p) => lstatSync(p),
|
|
37
|
+
realPath: (p) => realpathSync(p)
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* `WalkerSyncPath` over `node:path` (the host platform's separator).
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
const nodeWalkerPath = {
|
|
45
|
+
sep: path.sep,
|
|
46
|
+
join: path.join,
|
|
47
|
+
dirname: path.dirname,
|
|
48
|
+
resolve: path.resolve,
|
|
49
|
+
isAbsolute: path.isAbsolute
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Both bindings, to spread into `descendSync` options.
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
const nodeWalkerSyncOps = {
|
|
57
|
+
fileSystem: nodeWalkerFileSystem,
|
|
58
|
+
path: nodeWalkerPath
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export { nodeWalkerFileSystem, nodeWalkerPath, nodeWalkerSyncOps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/walker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Path traversal as Effect primitives: ascend a directory chain to the first matching candidate, or descend a tree expanding a glob against the filesystem.",
|
|
6
6
|
"keywords": [
|
|
@@ -34,10 +34,15 @@
|
|
|
34
34
|
"import": "./index.js",
|
|
35
35
|
"default": "./index.js"
|
|
36
36
|
},
|
|
37
|
+
"./node-sync": {
|
|
38
|
+
"types": "./node-sync.d.ts",
|
|
39
|
+
"import": "./node-sync.js",
|
|
40
|
+
"default": "./node-sync.js"
|
|
41
|
+
},
|
|
37
42
|
"./package.json": "./package.json"
|
|
38
43
|
},
|
|
39
44
|
"peerDependencies": {
|
|
40
|
-
"@effected/glob": "^0.
|
|
45
|
+
"@effected/glob": "^0.16.0",
|
|
41
46
|
"effect": "^4.0.0"
|
|
42
47
|
},
|
|
43
48
|
"engines": {
|