@procedures/fs 0.0.0-stage → 0.2.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/CHANGELOG.md +25 -0
- package/LICENSE +21 -0
- package/README.md +895 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/module.d.ts +22 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +203 -0
- package/dist/module.js.map +1 -0
- package/dist/procedures/fs/copy.d.ts +11 -0
- package/dist/procedures/fs/copy.d.ts.map +1 -0
- package/dist/procedures/fs/copy.js +21 -0
- package/dist/procedures/fs/copy.js.map +1 -0
- package/dist/procedures/fs/exists.d.ts +11 -0
- package/dist/procedures/fs/exists.d.ts.map +1 -0
- package/dist/procedures/fs/exists.js +20 -0
- package/dist/procedures/fs/exists.js.map +1 -0
- package/dist/procedures/fs/glob.d.ts +17 -0
- package/dist/procedures/fs/glob.d.ts.map +1 -0
- package/dist/procedures/fs/glob.js +85 -0
- package/dist/procedures/fs/glob.js.map +1 -0
- package/dist/procedures/fs/index.d.ts +12 -0
- package/dist/procedures/fs/index.d.ts.map +1 -0
- package/dist/procedures/fs/index.js +12 -0
- package/dist/procedures/fs/index.js.map +1 -0
- package/dist/procedures/fs/json.d.ts +11 -0
- package/dist/procedures/fs/json.d.ts.map +1 -0
- package/dist/procedures/fs/json.js +16 -0
- package/dist/procedures/fs/json.js.map +1 -0
- package/dist/procedures/fs/mkdir.d.ts +11 -0
- package/dist/procedures/fs/mkdir.d.ts.map +1 -0
- package/dist/procedures/fs/mkdir.js +39 -0
- package/dist/procedures/fs/mkdir.js.map +1 -0
- package/dist/procedures/fs/move.d.ts +11 -0
- package/dist/procedures/fs/move.d.ts.map +1 -0
- package/dist/procedures/fs/move.js +46 -0
- package/dist/procedures/fs/move.js.map +1 -0
- package/dist/procedures/fs/read.d.ts +11 -0
- package/dist/procedures/fs/read.d.ts.map +1 -0
- package/dist/procedures/fs/read.js +21 -0
- package/dist/procedures/fs/read.js.map +1 -0
- package/dist/procedures/fs/readdir.d.ts +11 -0
- package/dist/procedures/fs/readdir.d.ts.map +1 -0
- package/dist/procedures/fs/readdir.js +38 -0
- package/dist/procedures/fs/readdir.js.map +1 -0
- package/dist/procedures/fs/rm.d.ts +11 -0
- package/dist/procedures/fs/rm.d.ts.map +1 -0
- package/dist/procedures/fs/rm.js +30 -0
- package/dist/procedures/fs/rm.js.map +1 -0
- package/dist/procedures/fs/stat.d.ts +11 -0
- package/dist/procedures/fs/stat.d.ts.map +1 -0
- package/dist/procedures/fs/stat.js +29 -0
- package/dist/procedures/fs/stat.js.map +1 -0
- package/dist/procedures/fs/write.d.ts +11 -0
- package/dist/procedures/fs/write.d.ts.map +1 -0
- package/dist/procedures/fs/write.js +24 -0
- package/dist/procedures/fs/write.js.map +1 -0
- package/dist/procedures/fs.d.ts +5 -0
- package/dist/procedures/fs.d.ts.map +1 -0
- package/dist/procedures/fs.js +5 -0
- package/dist/procedures/fs.js.map +1 -0
- package/dist/register.d.ts +7 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +9 -0
- package/dist/register.js.map +1 -0
- package/dist/types.d.ts +187 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +197 -0
- package/dist/types.js.map +1 -0
- package/package.json +77 -3
- package/src/index.ts +17 -0
- package/src/module.ts +265 -0
- package/src/procedures/fs/copy.ts +24 -0
- package/src/procedures/fs/exists.ts +20 -0
- package/src/procedures/fs/glob.ts +92 -0
- package/src/procedures/fs/index.ts +11 -0
- package/src/procedures/fs/json.ts +21 -0
- package/src/procedures/fs/mkdir.ts +43 -0
- package/src/procedures/fs/move.ts +47 -0
- package/src/procedures/fs/read.ts +23 -0
- package/src/procedures/fs/readdir.ts +44 -0
- package/src/procedures/fs/rm.ts +31 -0
- package/src/procedures/fs/stat.ts +30 -0
- package/src/procedures/fs/write.ts +27 -0
- package/src/procedures/fs.ts +5 -0
- package/src/register.ts +11 -0
- package/src/types.ts +407 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* glob procedure
|
|
3
|
+
*
|
|
4
|
+
* Find files matching glob pattern
|
|
5
|
+
*
|
|
6
|
+
* The matches are relative to `cwd` (or absolute with `absolute: true`), with "/" separators.
|
|
7
|
+
* `ignore` removes the matches of its patterns and does not enter the folders that they match.
|
|
8
|
+
*
|
|
9
|
+
* Before, `ignore` was stripped by the input schema, and `absolute` and `dot` had no effect:
|
|
10
|
+
* `node:fs` glob has no such options (deep dive DATA-7).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { glob as nodeGlob, readdir } from "node:fs/promises";
|
|
14
|
+
import { posix, resolve } from "node:path";
|
|
15
|
+
import type { GlobInput, GlobOutput } from "../../types.js";
|
|
16
|
+
|
|
17
|
+
// A character that a file name cannot hold. It takes the place of a leading "." of a name, so
|
|
18
|
+
// that "*" and "**" match dot entries when `dot` is true.
|
|
19
|
+
const DOT = "\u0001";
|
|
20
|
+
|
|
21
|
+
/** "a\\b" (Windows) becomes "a/b". */
|
|
22
|
+
function toPosix(path: string): string {
|
|
23
|
+
return path.split("\\").join("/");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Each name of the path that starts with "." starts with DOT instead. */
|
|
27
|
+
function hideDots(path: string): string {
|
|
28
|
+
return path
|
|
29
|
+
.split("/")
|
|
30
|
+
.map((name) => (name.startsWith(".") && name !== "." && name !== ".." ? DOT + name.slice(1) : name))
|
|
31
|
+
.join("/");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function ignored(path: string, ignore: readonly string[]): boolean {
|
|
35
|
+
return ignore.some((pattern) => posix.matchesGlob(path, pattern));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A folder is not entered when each path inside it is ignored. */
|
|
39
|
+
function folderIgnored(path: string, ignore: readonly string[]): boolean {
|
|
40
|
+
return ignored(`${path}/${DOT}`, ignore) || ignored(path, ignore);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** All the matches of `pattern` under `root`, dot entries included. */
|
|
44
|
+
async function walkWithDots(root: string, pattern: string, ignore: readonly string[]): Promise<string[]> {
|
|
45
|
+
const hiddenPattern = hideDots(pattern);
|
|
46
|
+
const hiddenIgnore = ignore.map(hideDots);
|
|
47
|
+
const matches: string[] = [];
|
|
48
|
+
|
|
49
|
+
async function visit(relative: string): Promise<void> {
|
|
50
|
+
const entries = await readdir(relative ? resolve(root, relative) : root, { withFileTypes: true });
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
const path = relative ? `${relative}/${entry.name}` : entry.name;
|
|
53
|
+
const hidden = hideDots(path);
|
|
54
|
+
if (entry.isDirectory()) {
|
|
55
|
+
if (folderIgnored(hidden, hiddenIgnore)) continue;
|
|
56
|
+
if (posix.matchesGlob(hidden, hiddenPattern)) matches.push(path);
|
|
57
|
+
await visit(path);
|
|
58
|
+
} else if (posix.matchesGlob(hidden, hiddenPattern) && !ignored(hidden, hiddenIgnore)) {
|
|
59
|
+
matches.push(path);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await visit("");
|
|
65
|
+
return matches;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Find files matching glob pattern
|
|
70
|
+
*/
|
|
71
|
+
export async function glob(input: GlobInput): Promise<GlobOutput> {
|
|
72
|
+
const { pattern, absolute, dot } = input;
|
|
73
|
+
const ignore = input.ignore ?? [];
|
|
74
|
+
const root = resolve(input.cwd ?? process.cwd());
|
|
75
|
+
|
|
76
|
+
let relative: string[];
|
|
77
|
+
if (dot) {
|
|
78
|
+
relative = await walkWithDots(root, toPosix(pattern), ignore);
|
|
79
|
+
} else {
|
|
80
|
+
relative = [];
|
|
81
|
+
for await (const match of nodeGlob(pattern, { cwd: root, exclude: [...ignore] })) {
|
|
82
|
+
const path = toPosix(match);
|
|
83
|
+
// The exclude list of node:fs prunes folders. This check also covers the Node versions
|
|
84
|
+
// that ignore it.
|
|
85
|
+
if (!ignored(path, ignore)) relative.push(path);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
relative.sort();
|
|
90
|
+
const matches = absolute ? relative.map((path) => resolve(root, path)) : relative;
|
|
91
|
+
return { pattern, matches };
|
|
92
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { read } from "./read.js";
|
|
2
|
+
export { write } from "./write.js";
|
|
3
|
+
export { exists } from "./exists.js";
|
|
4
|
+
export { mkdir } from "./mkdir.js";
|
|
5
|
+
export { rm } from "./rm.js";
|
|
6
|
+
export { readdir } from "./readdir.js";
|
|
7
|
+
export { stat } from "./stat.js";
|
|
8
|
+
export { copy } from "./copy.js";
|
|
9
|
+
export { move } from "./move.js";
|
|
10
|
+
export { glob } from "./glob.js";
|
|
11
|
+
export { readJson } from "./json.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read.json procedure
|
|
3
|
+
*
|
|
4
|
+
* Read and parse JSON file
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ReadJsonInput, ReadJsonOutput } from "../../types.js";
|
|
8
|
+
import { read } from "./read.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Read and parse JSON file
|
|
12
|
+
*/
|
|
13
|
+
export async function readJson(input: ReadJsonInput): Promise<ReadJsonOutput> {
|
|
14
|
+
const { path } = input;
|
|
15
|
+
const {
|
|
16
|
+
content,
|
|
17
|
+
stats
|
|
18
|
+
} = await read({path, encoding : 'utf8'})
|
|
19
|
+
const data = JSON.parse(content);
|
|
20
|
+
return { path, data, stats };
|
|
21
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mkdir procedure
|
|
3
|
+
*
|
|
4
|
+
* Create directory
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { mkdir as fsMkdir } from "node:fs/promises";
|
|
8
|
+
import { FileType, type MkdirInput, type MkdirOutput, type StatOutput } from "../../types.js";
|
|
9
|
+
import { stat } from "./stat.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create directory
|
|
13
|
+
*/
|
|
14
|
+
export async function mkdir(input: MkdirInput): Promise<MkdirOutput> {
|
|
15
|
+
const { path, recursive } = input;
|
|
16
|
+
|
|
17
|
+
// Probe the existing path. Only a genuine "not found" (ENOENT) means we
|
|
18
|
+
// should proceed to create it; any other stat error (e.g. EACCES) must
|
|
19
|
+
// propagate rather than being masked by an mkdir attempt.
|
|
20
|
+
let existing: StatOutput | undefined;
|
|
21
|
+
try {
|
|
22
|
+
existing = await stat(input);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (existing) {
|
|
28
|
+
// The path already exists. It's only a no-op success if it's a directory;
|
|
29
|
+
// an existing file (or other non-directory) is a real conflict, not a
|
|
30
|
+
// silently-"already created" directory.
|
|
31
|
+
if (existing.type === FileType.Directory) {
|
|
32
|
+
return { path, created: false };
|
|
33
|
+
}
|
|
34
|
+
const conflict = new Error(
|
|
35
|
+
`Cannot create directory: path already exists and is not a directory: ${path}`,
|
|
36
|
+
) as NodeJS.ErrnoException;
|
|
37
|
+
conflict.code = "EEXIST";
|
|
38
|
+
throw conflict;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await fsMkdir(path, { recursive });
|
|
42
|
+
return { path, created: true };
|
|
43
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* move procedure
|
|
3
|
+
*
|
|
4
|
+
* Move or rename file/directory
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { cp, rename } from "node:fs/promises";
|
|
8
|
+
import type { MoveInput, MoveOutput } from "../../types.js";
|
|
9
|
+
import { stat } from "./stat.js";
|
|
10
|
+
import { rm } from "./rm.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Move or rename file/directory
|
|
14
|
+
*/
|
|
15
|
+
export async function move(input: MoveInput): Promise<MoveOutput> {
|
|
16
|
+
const { src, dest, overwrite } = input;
|
|
17
|
+
|
|
18
|
+
if (!overwrite) {
|
|
19
|
+
try {
|
|
20
|
+
await stat({path : dest});
|
|
21
|
+
throw new Error(`Destination already exists: ${dest}`);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
await rename(src, dest);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
if ((err as NodeJS.ErrnoException).code === "EXDEV") {
|
|
31
|
+
// Cross-device move: copy then delete the source. When not overwriting,
|
|
32
|
+
// use errorOnExist so an already-present destination throws instead of
|
|
33
|
+
// being silently skipped by `cp` — otherwise the subsequent removal of
|
|
34
|
+
// `src` would lose the files that were never copied over.
|
|
35
|
+
await cp(src, dest, {
|
|
36
|
+
recursive: true,
|
|
37
|
+
force: overwrite,
|
|
38
|
+
errorOnExist: !overwrite,
|
|
39
|
+
});
|
|
40
|
+
await rm({ path: src, recursive: true, force: false });
|
|
41
|
+
} else {
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { src, dest };
|
|
47
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read procedure
|
|
3
|
+
*
|
|
4
|
+
* Read file contents
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFile } from "node:fs/promises";
|
|
8
|
+
import type { ReadInput, ReadOutput } from "../../types.js";
|
|
9
|
+
import { stat } from "./stat.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Read file contents
|
|
13
|
+
*/
|
|
14
|
+
export async function read(input: ReadInput): Promise<ReadOutput> {
|
|
15
|
+
const { path, encoding } = input;
|
|
16
|
+
const content = await readFile(path, { encoding: encoding as BufferEncoding });
|
|
17
|
+
const stats = await stat({path});
|
|
18
|
+
return {
|
|
19
|
+
content,
|
|
20
|
+
path,
|
|
21
|
+
stats
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* readdir procedure
|
|
3
|
+
*
|
|
4
|
+
* Read directory contents
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readdir as fsReaddir } from "node:fs/promises";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { type ReaddirInput, type ReaddirOutput, type ReaddirEntry, FileType } from "../../types.js";
|
|
10
|
+
import { stat } from "./stat.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Read directory contents
|
|
14
|
+
*/
|
|
15
|
+
export async function readdir(input: ReaddirInput): Promise<ReaddirOutput> {
|
|
16
|
+
const { path, recursive, includeStats } = input;
|
|
17
|
+
const entries: ReaddirEntry[] = [];
|
|
18
|
+
|
|
19
|
+
async function readDir(dir: string): Promise<void> {
|
|
20
|
+
const items = await fsReaddir(dir, { withFileTypes: true });
|
|
21
|
+
for (const item of items) {
|
|
22
|
+
const fullPath = join(dir, item.name);
|
|
23
|
+
|
|
24
|
+
let type: FileType = FileType.Other;
|
|
25
|
+
if (item.isFile()) type = FileType.File;
|
|
26
|
+
else if (item.isDirectory()) type = FileType.Directory;
|
|
27
|
+
|
|
28
|
+
const entry: ReaddirEntry = { name: item.name, path: fullPath, type };
|
|
29
|
+
|
|
30
|
+
if (includeStats) {
|
|
31
|
+
entry.stats = await stat({path : fullPath});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
entries.push(entry);
|
|
35
|
+
|
|
36
|
+
if (recursive && item.isDirectory()) {
|
|
37
|
+
await readDir(fullPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await readDir(path);
|
|
43
|
+
return { path, entries };
|
|
44
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rm procedure
|
|
3
|
+
*
|
|
4
|
+
* Remove file or directory
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { rm as fsRm } from "node:fs/promises";
|
|
8
|
+
import type { RmInput, RmOutput } from "../../types.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Remove file or directory
|
|
12
|
+
*/
|
|
13
|
+
export async function rm(input: RmInput): Promise<RmOutput> {
|
|
14
|
+
const { path, recursive, force } = input;
|
|
15
|
+
// Always call with force:false so Node reports a missing path via ENOENT
|
|
16
|
+
// (letting us distinguish "removed" from "didn't exist"). Node's `force`
|
|
17
|
+
// option only suppresses ENOENT anyway, so replicating it here keeps the
|
|
18
|
+
// exact same behavior while still surfacing EPERM/ENOTEMPTY/EBUSY/etc.
|
|
19
|
+
try {
|
|
20
|
+
await fsRm(path, { recursive, force: false });
|
|
21
|
+
return { path, removed: true };
|
|
22
|
+
} catch (err) {
|
|
23
|
+
// With force:true a non-existent path is not an error — report it as
|
|
24
|
+
// "nothing removed". Every other error (permissions, non-empty, busy) must
|
|
25
|
+
// propagate rather than being silently swallowed.
|
|
26
|
+
if (force && (err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
27
|
+
return { path, removed: false };
|
|
28
|
+
}
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stat procedure
|
|
3
|
+
*
|
|
4
|
+
* Get file or directory stats
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { stat as fsStat } from "node:fs/promises";
|
|
8
|
+
import { FileType, type StatInput, type StatOutput } from "../../types.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get file or directory stats
|
|
12
|
+
*/
|
|
13
|
+
export async function stat(input: StatInput): Promise<StatOutput> {
|
|
14
|
+
const { path } = input;
|
|
15
|
+
const stats = await fsStat(path);
|
|
16
|
+
|
|
17
|
+
let type: FileType = FileType.Other;
|
|
18
|
+
if (stats.isFile()) type = FileType.File;
|
|
19
|
+
else if (stats.isDirectory()) type = FileType.Directory;
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
path,
|
|
23
|
+
type,
|
|
24
|
+
size: stats.size,
|
|
25
|
+
mtime: stats.mtime.toISOString(),
|
|
26
|
+
ctime: stats.ctime.toISOString(),
|
|
27
|
+
atime: stats.atime.toISOString(),
|
|
28
|
+
mode: stats.mode,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* write procedure
|
|
3
|
+
*
|
|
4
|
+
* Write content to file
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { writeFile, appendFile } from "node:fs/promises";
|
|
8
|
+
import type { WriteInput, WriteOutput } from "../../types.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Write content to file
|
|
12
|
+
*/
|
|
13
|
+
export async function write(input: WriteInput): Promise<WriteOutput> {
|
|
14
|
+
const { path, content, encoding, mode } = input;
|
|
15
|
+
const writeOptions = { encoding: encoding as BufferEncoding };
|
|
16
|
+
|
|
17
|
+
if (mode === "append") {
|
|
18
|
+
await appendFile(path, content, writeOptions);
|
|
19
|
+
} else {
|
|
20
|
+
await writeFile(path, content, writeOptions);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
path,
|
|
25
|
+
bytesWritten: Buffer.byteLength(content, encoding as BufferEncoding),
|
|
26
|
+
};
|
|
27
|
+
}
|
package/src/register.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Importing this file registers the procedures of @procedures/fs, and of the modules that it
|
|
3
|
+
* requires, in the global registry: `import "@procedures/fs/register"`. The package root and the
|
|
4
|
+
* `./module` entry register nothing (ARCHITECTURE-PROPOSALS-2026-10, P9).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { registerFsProcedures } from "./module.js";
|
|
8
|
+
|
|
9
|
+
export * from "./module.js";
|
|
10
|
+
|
|
11
|
+
registerFsProcedures();
|