@effectionx/fs 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/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # FS
2
+
3
+ File system operations for Effection programs. This package wraps Node.js
4
+ `fs/promises` APIs as Effection Operations with structured concurrency support.
5
+
6
+ ---
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @effectionx/fs
12
+ ```
13
+
14
+ ## Basic Usage
15
+
16
+ ```typescript
17
+ import { main } from "effection";
18
+ import { exists, readTextFile, writeTextFile } from "@effectionx/fs";
19
+
20
+ await main(function* () {
21
+ if (yield* exists("./config.json")) {
22
+ const config = yield* readTextFile("./config.json");
23
+ console.log(JSON.parse(config));
24
+ } else {
25
+ yield* writeTextFile("./config.json", JSON.stringify({ version: 1 }));
26
+ }
27
+ });
28
+ ```
29
+
30
+ ## File Operations
31
+
32
+ ### stat()
33
+
34
+ Get file or directory stats.
35
+
36
+ ```typescript
37
+ import { stat } from "@effectionx/fs";
38
+
39
+ const stats = yield* stat("./file.txt");
40
+ console.log(stats.isFile()); // true
41
+ console.log(stats.size); // file size in bytes
42
+ ```
43
+
44
+ ### lstat()
45
+
46
+ Get file or directory stats without following symlinks.
47
+
48
+ ```typescript
49
+ import { lstat } from "@effectionx/fs";
50
+
51
+ const stats = yield* lstat("./symlink");
52
+ console.log(stats.isSymbolicLink()); // true
53
+ ```
54
+
55
+ ### exists()
56
+
57
+ Check if a file or directory exists.
58
+
59
+ ```typescript
60
+ import { exists } from "@effectionx/fs";
61
+
62
+ if (yield* exists("./config.json")) {
63
+ console.log("Config file found");
64
+ }
65
+ ```
66
+
67
+ ### readTextFile()
68
+
69
+ Read a file as text.
70
+
71
+ ```typescript
72
+ import { readTextFile } from "@effectionx/fs";
73
+
74
+ const content = yield* readTextFile("./README.md");
75
+ ```
76
+
77
+ ### writeTextFile()
78
+
79
+ Write text to a file.
80
+
81
+ ```typescript
82
+ import { writeTextFile } from "@effectionx/fs";
83
+
84
+ yield* writeTextFile("./output.txt", "Hello, World!");
85
+ ```
86
+
87
+ ### ensureFile()
88
+
89
+ Ensure a file exists, creating parent directories and the file if needed.
90
+
91
+ ```typescript
92
+ import { ensureFile } from "@effectionx/fs";
93
+
94
+ yield* ensureFile("./data/logs/app.log");
95
+ ```
96
+
97
+ ### copyFile()
98
+
99
+ Copy a file.
100
+
101
+ ```typescript
102
+ import { copyFile } from "@effectionx/fs";
103
+
104
+ yield* copyFile("./source.txt", "./backup.txt");
105
+ ```
106
+
107
+ ### rm()
108
+
109
+ Remove a file or directory.
110
+
111
+ ```typescript
112
+ import { rm } from "@effectionx/fs";
113
+
114
+ // Remove a file
115
+ yield* rm("./temp.txt");
116
+
117
+ // Remove a directory recursively
118
+ yield* rm("./temp", { recursive: true });
119
+
120
+ // Force remove (no error if doesn't exist)
121
+ yield* rm("./maybe-exists", { force: true });
122
+ ```
123
+
124
+ ## Directory Operations
125
+
126
+ ### ensureDir()
127
+
128
+ Ensure a directory exists, creating it recursively if needed.
129
+
130
+ ```typescript
131
+ import { ensureDir } from "@effectionx/fs";
132
+
133
+ yield* ensureDir("./data/cache/images");
134
+ ```
135
+
136
+ ### readdir()
137
+
138
+ Read the contents of a directory.
139
+
140
+ ```typescript
141
+ import { readdir } from "@effectionx/fs";
142
+
143
+ const entries = yield* readdir("./src");
144
+ console.log(entries); // ["index.ts", "utils.ts", ...]
145
+ ```
146
+
147
+ ### emptyDir()
148
+
149
+ Empty a directory by removing all its contents. Creates the directory if it
150
+ doesn't exist.
151
+
152
+ ```typescript
153
+ import { emptyDir } from "@effectionx/fs";
154
+
155
+ yield* emptyDir("./dist");
156
+ ```
157
+
158
+ ### walk()
159
+
160
+ Walk a directory tree and yield entries as a Stream.
161
+
162
+ ```typescript
163
+ import { walk } from "@effectionx/fs";
164
+ import { each } from "effection";
165
+
166
+ for (const entry of yield* each(walk("./src"))) {
167
+ if (entry.isFile && entry.name.endsWith(".ts")) {
168
+ console.log(entry.path);
169
+ }
170
+ yield* each.next();
171
+ }
172
+ ```
173
+
174
+ Each entry includes:
175
+ - `path` - Full path to the entry
176
+ - `name` - Basename of the entry
177
+ - `isFile` - Whether it's a file
178
+ - `isDirectory` - Whether it's a directory
179
+ - `isSymlink` - Whether it's a symbolic link
180
+
181
+ #### Walk Options
182
+
183
+ ```typescript
184
+ walk("./src", {
185
+ includeDirs: true, // Include directories (default: true)
186
+ includeFiles: true, // Include files (default: true)
187
+ includeSymlinks: true, // Include symlinks (default: true)
188
+ match: [/\.ts$/], // Only include matching paths
189
+ skip: [/node_modules/], // Exclude matching paths
190
+ maxDepth: 3, // Maximum traversal depth
191
+ followSymlinks: false, // Follow symbolic links (default: false)
192
+ });
193
+ ```
194
+
195
+ ### expandGlob()
196
+
197
+ Expand glob patterns and yield matching paths as a Stream.
198
+
199
+ ```typescript
200
+ import { expandGlob } from "@effectionx/fs";
201
+ import { each } from "effection";
202
+
203
+ for (const entry of yield* each(expandGlob("./src/**/*.ts"))) {
204
+ console.log(entry.path);
205
+ yield* each.next();
206
+ }
207
+ ```
208
+
209
+ #### Glob Options
210
+
211
+ ```typescript
212
+ expandGlob("**/*.ts", {
213
+ root: "./src", // Root directory (default: ".")
214
+ exclude: ["**/*.test.ts"], // Patterns to exclude
215
+ includeDirs: false, // Include directories (default: true)
216
+ followSymlinks: false, // Follow symbolic links (default: false)
217
+ });
218
+ ```
219
+
220
+ ## Utilities
221
+
222
+ ### toPath()
223
+
224
+ Convert a path or URL to a file path string.
225
+
226
+ ```typescript
227
+ import { toPath } from "@effectionx/fs";
228
+
229
+ toPath("./file.txt"); // "./file.txt"
230
+ toPath(new URL("file:///tmp")); // "/tmp"
231
+ ```
232
+
233
+ ### globToRegExp()
234
+
235
+ Convert a glob pattern to a RegExp.
236
+
237
+ ```typescript
238
+ import { globToRegExp } from "@effectionx/fs";
239
+
240
+ const regex = globToRegExp("*.ts");
241
+ regex.test("file.ts"); // true
242
+ regex.test("file.js"); // false
243
+
244
+ // Supports extended glob syntax
245
+ globToRegExp("**/*.{ts,js}"); // Match .ts or .js files recursively
246
+ globToRegExp("file[0-9].txt"); // Character classes
247
+ globToRegExp("src/**/test?.ts"); // ? matches single character
248
+ ```
249
+
250
+ ### URL Conversion
251
+
252
+ Re-exported from `node:url` for convenience:
253
+
254
+ ```typescript
255
+ import { fromFileUrl, toFileUrl } from "@effectionx/fs";
256
+
257
+ fromFileUrl(new URL("file:///tmp/file.txt")); // "/tmp/file.txt"
258
+ toFileUrl("/tmp/file.txt"); // URL { href: "file:///tmp/file.txt" }
259
+ ```
260
+
261
+ ## Path and URL Support
262
+
263
+ All file operations accept either a string path or a `URL` object:
264
+
265
+ ```typescript
266
+ import { readTextFile } from "@effectionx/fs";
267
+
268
+ // String path
269
+ yield* readTextFile("./config.json");
270
+
271
+ // URL object
272
+ yield* readTextFile(new URL("file:///etc/config.json"));
273
+
274
+ // import.meta.url based paths
275
+ yield* readTextFile(new URL("./data.json", import.meta.url));
276
+ ```
package/dist/mod.d.ts ADDED
@@ -0,0 +1,223 @@
1
+ import type { Stats } from "node:fs";
2
+ import { type Operation, type Stream } from "effection";
3
+ /**
4
+ * Convert a path or URL to a file path string
5
+ */
6
+ export declare function toPath(pathOrUrl: string | URL): string;
7
+ /**
8
+ * Get file or directory stats
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { stat } from "@effectionx/fs";
13
+ *
14
+ * const stats = yield* stat("./file.txt");
15
+ * console.log(stats.isFile());
16
+ * ```
17
+ */
18
+ export declare function stat(pathOrUrl: string | URL): Operation<Stats>;
19
+ /**
20
+ * Get file or directory stats without following symlinks
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { lstat } from "@effectionx/fs";
25
+ *
26
+ * const stats = yield* lstat("./symlink");
27
+ * console.log(stats.isSymbolicLink());
28
+ * ```
29
+ */
30
+ export declare function lstat(pathOrUrl: string | URL): Operation<Stats>;
31
+ /**
32
+ * Check if a file or directory exists
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * import { exists } from "@effectionx/fs";
37
+ *
38
+ * if (yield* exists("./config.json")) {
39
+ * console.log("Config file found");
40
+ * }
41
+ * ```
42
+ */
43
+ export declare function exists(pathOrUrl: string | URL): Operation<boolean>;
44
+ /**
45
+ * Ensure a directory exists, creating it recursively if needed
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * import { ensureDir } from "@effectionx/fs";
50
+ *
51
+ * yield* ensureDir("./data/cache");
52
+ * ```
53
+ */
54
+ export declare function ensureDir(pathOrUrl: string | URL): Operation<void>;
55
+ /**
56
+ * Ensure a file exists, creating parent directories and the file if needed
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * import { ensureFile } from "@effectionx/fs";
61
+ *
62
+ * yield* ensureFile("./data/config.json");
63
+ * ```
64
+ */
65
+ export declare function ensureFile(pathOrUrl: string | URL): Operation<void>;
66
+ /**
67
+ * Read the contents of a directory
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * import { readdir } from "@effectionx/fs";
72
+ *
73
+ * const entries = yield* readdir("./src");
74
+ * ```
75
+ */
76
+ export declare function readdir(pathOrUrl: string | URL): Operation<string[]>;
77
+ /**
78
+ * Empty a directory by removing all its contents.
79
+ * Creates the directory if it doesn't exist.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * import { emptyDir } from "@effectionx/fs";
84
+ *
85
+ * yield* emptyDir("./dist");
86
+ * ```
87
+ */
88
+ export declare function emptyDir(pathOrUrl: string | URL): Operation<void>;
89
+ /**
90
+ * Remove a file or directory
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * import { rm } from "@effectionx/fs";
95
+ *
96
+ * yield* rm("./temp", { recursive: true });
97
+ * ```
98
+ */
99
+ export declare function rm(pathOrUrl: string | URL, options?: {
100
+ recursive?: boolean;
101
+ force?: boolean;
102
+ }): Operation<void>;
103
+ /**
104
+ * Copy a file
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * import { copyFile } from "@effectionx/fs";
109
+ *
110
+ * yield* copyFile("./source.txt", "./dest.txt");
111
+ * ```
112
+ */
113
+ export declare function copyFile(src: string | URL, dest: string | URL): Operation<void>;
114
+ /**
115
+ * Read a file as text
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * import { readTextFile } from "@effectionx/fs";
120
+ *
121
+ * const content = yield* readTextFile("./config.json");
122
+ * ```
123
+ */
124
+ export declare function readTextFile(pathOrUrl: string | URL): Operation<string>;
125
+ /**
126
+ * Write text to a file
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * import { writeTextFile } from "@effectionx/fs";
131
+ *
132
+ * yield* writeTextFile("./output.txt", "Hello, World!");
133
+ * ```
134
+ */
135
+ export declare function writeTextFile(pathOrUrl: string | URL, content: string): Operation<void>;
136
+ /**
137
+ * Entry returned by walk()
138
+ */
139
+ export interface WalkEntry {
140
+ /** Full path to the entry */
141
+ path: string;
142
+ /** Name of the entry (basename) */
143
+ name: string;
144
+ /** Whether the entry is a file */
145
+ isFile: boolean;
146
+ /** Whether the entry is a directory */
147
+ isDirectory: boolean;
148
+ /** Whether the entry is a symbolic link */
149
+ isSymlink: boolean;
150
+ }
151
+ /**
152
+ * Options for walk()
153
+ */
154
+ export interface WalkOptions {
155
+ /** Include directories in results (default: true) */
156
+ includeDirs?: boolean;
157
+ /** Include files in results (default: true) */
158
+ includeFiles?: boolean;
159
+ /** Include symbolic links in results (default: true) */
160
+ includeSymlinks?: boolean;
161
+ /** Only include entries matching these patterns */
162
+ match?: RegExp[];
163
+ /** Exclude entries matching these patterns */
164
+ skip?: RegExp[];
165
+ /** Maximum depth to traverse (default: Infinity) */
166
+ maxDepth?: number;
167
+ /** Follow symbolic links (default: false) */
168
+ followSymlinks?: boolean;
169
+ }
170
+ /**
171
+ * Walk a directory tree and yield entries as a Stream
172
+ *
173
+ * @example
174
+ * ```ts
175
+ * import { walk } from "@effectionx/fs";
176
+ * import { each } from "effection";
177
+ *
178
+ * for (const entry of yield* each(walk("./src"))) {
179
+ * if (entry.isFile && entry.name.endsWith(".ts")) {
180
+ * console.log(entry.path);
181
+ * }
182
+ * yield* each.next();
183
+ * }
184
+ * ```
185
+ */
186
+ export declare function walk(root: string | URL, options?: WalkOptions): Stream<WalkEntry, void>;
187
+ /**
188
+ * Expand glob patterns and yield matching paths as a Stream
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * import { expandGlob } from "@effectionx/fs";
193
+ * import { each } from "effection";
194
+ *
195
+ * for (const entry of yield* each(expandGlob("./src/*.ts"))) {
196
+ * console.log(entry.path);
197
+ * yield* each.next();
198
+ * }
199
+ * ```
200
+ */
201
+ export declare function expandGlob(glob: string, options?: {
202
+ root?: string;
203
+ exclude?: string[];
204
+ includeDirs?: boolean;
205
+ followSymlinks?: boolean;
206
+ }): Stream<WalkEntry, void>;
207
+ /**
208
+ * Convert a glob pattern to a RegExp
209
+ *
210
+ * @example
211
+ * ```ts
212
+ * import { globToRegExp } from "@effectionx/fs";
213
+ *
214
+ * const regex = globToRegExp("*.ts");
215
+ * console.log(regex.test("file.ts")); // true
216
+ * ```
217
+ */
218
+ export declare function globToRegExp(glob: string, options?: {
219
+ extended?: boolean;
220
+ globstar?: boolean;
221
+ }): RegExp;
222
+ export { fileURLToPath as fromFileUrl, pathToFileURL as toFileUrl, } from "node:url";
223
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../mod.ts"],"names":[],"mappings":"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"}