@simplysm/core-node 13.0.69 → 13.0.70
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 +17 -354
- package/dist/features/fs-watcher.d.ts +21 -21
- package/dist/features/fs-watcher.d.ts.map +1 -1
- package/dist/features/fs-watcher.js +9 -9
- package/dist/utils/fs.d.ts +96 -96
- package/dist/utils/path.d.ts +22 -22
- package/dist/utils/path.js +1 -1
- package/dist/utils/path.js.map +1 -1
- package/dist/worker/create-worker.d.ts +3 -3
- package/dist/worker/create-worker.js +3 -3
- package/dist/worker/create-worker.js.map +1 -1
- package/dist/worker/types.d.ts +14 -14
- package/dist/worker/worker.d.ts +5 -5
- package/dist/worker/worker.js +12 -12
- package/dist/worker/worker.js.map +1 -1
- package/package.json +6 -5
- package/src/features/fs-watcher.ts +38 -38
- package/src/utils/fs.ts +108 -108
- package/src/utils/path.ts +26 -26
- package/src/worker/create-worker.ts +10 -10
- package/src/worker/types.ts +14 -14
- package/src/worker/worker.ts +29 -29
- package/tests/utils/fs-watcher.spec.ts +339 -0
- package/tests/utils/fs.spec.ts +755 -0
- package/tests/utils/path.spec.ts +192 -0
- package/tests/worker/fixtures/test-worker.ts +35 -0
- package/tests/worker/sd-worker.spec.ts +189 -0
package/README.md
CHANGED
|
@@ -1,370 +1,33 @@
|
|
|
1
1
|
# @simplysm/core-node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Simplysm package - Core module (node)
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
```bash
|
|
8
|
-
npm install @simplysm/core-node
|
|
9
|
-
# or
|
|
10
7
|
pnpm add @simplysm/core-node
|
|
11
|
-
```
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
## Source Index
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
### Utils
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
| Source | Exports | Description | Test |
|
|
14
|
+
|--------|---------|-------------|------|
|
|
15
|
+
| `src/utils/fs.ts` | `fsExistsSync`, `fsExists`, `fsMkdirSync`, `fsMkdir`, `fsRmSync`, `fsRm`, `fsCopySync`, `fsCopy`, `fsReadSync`, `fsRead`, `fsReadBufferSync`, `fsReadBuffer`, `fsReadJsonSync`, `fsReadJson`, `fsWriteSync`, `fsWrite`, `fsWriteJsonSync`, `fsWriteJson`, `fsReaddirSync`, `fsReaddir`, `fsStatSync`, `fsStat`, `fsLstatSync`, `fsLstat`, `fsGlobSync`, `fsGlob`, `fsClearEmptyDirectory`, `fsFindAllParentChildPathsSync`, `fsFindAllParentChildPaths` | Comprehensive file system utilities (read, write, copy, delete, glob, stat) | `fs.spec.ts` |
|
|
16
|
+
| `src/utils/path.ts` | `NormPath`, `pathPosix`, `pathChangeFileDirectory`, `pathBasenameWithoutExt`, `pathIsChildPath`, `pathNorm`, `pathFilterByTargets` | Path normalization and manipulation utilities for posix-style paths | `path.spec.ts` |
|
|
18
17
|
|
|
19
|
-
###
|
|
18
|
+
### Features
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
| Source | Exports | Description | Test |
|
|
21
|
+
|--------|---------|-------------|------|
|
|
22
|
+
| `src/features/fs-watcher.ts` | `FsWatcherEvent`, `FsWatcherChangeInfo`, `FsWatcher` | File system watcher with debounced change detection and event filtering | `fs-watcher.spec.ts` |
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|---------------|-------------|
|
|
25
|
-
| `NormPath` | A branded type created by `pathNorm()`. Represents a normalized absolute path. |
|
|
26
|
-
| `pathPosix(...args)` | Converts to POSIX-style path (replaces backslashes with slashes). |
|
|
27
|
-
| `pathNorm(...paths)` | Normalizes paths and returns as `NormPath`. Converts to absolute path and normalizes with platform-specific separators. |
|
|
28
|
-
| `pathIsChildPath(childPath, parentPath)` | Checks if `childPath` is a child path of `parentPath`. Returns `false` for identical paths. Paths are normalized internally before comparison. |
|
|
29
|
-
| `pathChangeFileDirectory(filePath, fromDir, toDir)` | Changes the directory of a file path. Throws an error if the file is not within `fromDir`. |
|
|
30
|
-
| `pathBasenameWithoutExt(filePath)` | Returns the filename (basename) without extension. |
|
|
31
|
-
| `pathFilterByTargets(files, targets, cwd)` | Filters files based on target path list. `files` must be absolute paths under `cwd`. `targets` are POSIX-style paths relative to `cwd`. Returns `files` as-is if `targets` is an empty array. |
|
|
24
|
+
### Worker
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
pathChangeFileDirectory,
|
|
39
|
-
pathBasenameWithoutExt,
|
|
40
|
-
pathFilterByTargets,
|
|
41
|
-
} from "@simplysm/core-node";
|
|
42
|
-
|
|
43
|
-
// Convert to POSIX-style path
|
|
44
|
-
pathPosix("C:\\Users\\test"); // "C:/Users/test"
|
|
45
|
-
pathPosix("src", "index.ts"); // "src/index.ts"
|
|
46
|
-
|
|
47
|
-
// Normalize path (convert to absolute path)
|
|
48
|
-
const normPath = pathNorm("src", "index.ts"); // Returns NormPath type
|
|
49
|
-
|
|
50
|
-
// Check child path relationship
|
|
51
|
-
pathIsChildPath("/a/b/c", "/a/b"); // true
|
|
52
|
-
pathIsChildPath("/a/b", "/a/b/c"); // false
|
|
53
|
-
pathIsChildPath("/a/b", "/a/b"); // false (same path)
|
|
54
|
-
|
|
55
|
-
// Change file directory
|
|
56
|
-
pathChangeFileDirectory("/a/b/c.txt", "/a", "/x"); // "/x/b/c.txt"
|
|
57
|
-
|
|
58
|
-
// Return filename without extension
|
|
59
|
-
pathBasenameWithoutExt("file.txt"); // "file"
|
|
60
|
-
pathBasenameWithoutExt("/path/to/file.spec.ts"); // "file.spec"
|
|
61
|
-
|
|
62
|
-
// Filter files by target paths
|
|
63
|
-
const files = ["/proj/src/a.ts", "/proj/src/b.ts", "/proj/tests/c.ts"];
|
|
64
|
-
pathFilterByTargets(files, ["src"], "/proj");
|
|
65
|
-
// ["/proj/src/a.ts", "/proj/src/b.ts"]
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### File System Utilities (`utils/fs`)
|
|
69
|
-
|
|
70
|
-
Provides functions for reading, writing, deleting, copying, and searching files and directories. Most functions come in both async and sync (`Sync` suffix) versions.
|
|
71
|
-
|
|
72
|
-
#### Existence Check
|
|
73
|
-
|
|
74
|
-
| Function | Description |
|
|
75
|
-
|----------|-------------|
|
|
76
|
-
| `fsExists(targetPath)` | Asynchronously checks if a file or directory exists. |
|
|
77
|
-
| `fsExistsSync(targetPath)` | Synchronously checks if a file or directory exists. |
|
|
78
|
-
|
|
79
|
-
#### Directory Creation
|
|
80
|
-
|
|
81
|
-
| Function | Description |
|
|
82
|
-
|----------|-------------|
|
|
83
|
-
| `fsMkdir(targetPath)` | Asynchronously creates a directory (recursive). |
|
|
84
|
-
| `fsMkdirSync(targetPath)` | Synchronously creates a directory (recursive). |
|
|
85
|
-
|
|
86
|
-
#### Deletion
|
|
87
|
-
|
|
88
|
-
| Function | Description |
|
|
89
|
-
|----------|-------------|
|
|
90
|
-
| `fsRm(targetPath)` | Asynchronously deletes a file or directory. Retries up to 6 times (500ms intervals) for transient errors like file locks. |
|
|
91
|
-
| `fsRmSync(targetPath)` | Synchronously deletes a file or directory. Fails immediately without retries. |
|
|
92
|
-
|
|
93
|
-
#### Copy
|
|
94
|
-
|
|
95
|
-
| Function | Description |
|
|
96
|
-
|----------|-------------|
|
|
97
|
-
| `fsCopy(sourcePath, targetPath, filter?)` | Asynchronously copies a file or directory. Can filter copy targets with a `filter` function. Does nothing if `sourcePath` doesn't exist. |
|
|
98
|
-
| `fsCopySync(sourcePath, targetPath, filter?)` | Synchronously copies a file or directory. |
|
|
99
|
-
|
|
100
|
-
#### File Reading
|
|
101
|
-
|
|
102
|
-
| Function | Description |
|
|
103
|
-
|----------|-------------|
|
|
104
|
-
| `fsRead(targetPath)` | Asynchronously reads a file as a UTF-8 string. |
|
|
105
|
-
| `fsReadSync(targetPath)` | Synchronously reads a file as a UTF-8 string. |
|
|
106
|
-
| `fsReadBuffer(targetPath)` | Asynchronously reads a file as a Buffer. |
|
|
107
|
-
| `fsReadBufferSync(targetPath)` | Synchronously reads a file as a Buffer. |
|
|
108
|
-
| `fsReadJson<TData>(targetPath)` | Asynchronously reads a JSON file (uses `jsonParse`). |
|
|
109
|
-
| `fsReadJsonSync<TData>(targetPath)` | Synchronously reads a JSON file (uses `jsonParse`). |
|
|
110
|
-
|
|
111
|
-
#### File Writing
|
|
112
|
-
|
|
113
|
-
| Function | Description |
|
|
114
|
-
|----------|-------------|
|
|
115
|
-
| `fsWrite(targetPath, data)` | Asynchronously writes a file. Automatically creates parent directories if they don't exist. `data` is `string` or `Uint8Array`. |
|
|
116
|
-
| `fsWriteSync(targetPath, data)` | Synchronously writes a file. Automatically creates parent directories. |
|
|
117
|
-
| `fsWriteJson(targetPath, data, options?)` | Asynchronously writes a JSON file (uses `jsonStringify`). Can specify `replacer` and `space` in `options`. |
|
|
118
|
-
| `fsWriteJsonSync(targetPath, data, options?)` | Synchronously writes a JSON file. |
|
|
119
|
-
|
|
120
|
-
#### Directory Reading
|
|
121
|
-
|
|
122
|
-
| Function | Description |
|
|
123
|
-
|----------|-------------|
|
|
124
|
-
| `fsReaddir(targetPath)` | Asynchronously reads directory contents. Returns an array of entry names. |
|
|
125
|
-
| `fsReaddirSync(targetPath)` | Synchronously reads directory contents. Returns an array of entry names. |
|
|
126
|
-
|
|
127
|
-
#### File Information
|
|
128
|
-
|
|
129
|
-
| Function | Description |
|
|
130
|
-
|----------|-------------|
|
|
131
|
-
| `fsStat(targetPath)` | Asynchronously retrieves file/directory information (follows symbolic links). |
|
|
132
|
-
| `fsStatSync(targetPath)` | Synchronously retrieves file/directory information (follows symbolic links). |
|
|
133
|
-
| `fsLstat(targetPath)` | Asynchronously retrieves file/directory information (symbolic link itself, does not follow). |
|
|
134
|
-
| `fsLstatSync(targetPath)` | Synchronously retrieves file/directory information (symbolic link itself, does not follow). |
|
|
135
|
-
|
|
136
|
-
#### Glob Search
|
|
137
|
-
|
|
138
|
-
| Function | Description |
|
|
139
|
-
|----------|-------------|
|
|
140
|
-
| `fsGlob(pattern, options?)` | Asynchronously searches for files with a glob pattern. Returns an array of absolute paths of matched files. |
|
|
141
|
-
| `fsGlobSync(pattern, options?)` | Synchronously searches for files with a glob pattern. |
|
|
142
|
-
|
|
143
|
-
#### Other Utilities
|
|
144
|
-
|
|
145
|
-
| Function | Description |
|
|
146
|
-
|----------|-------------|
|
|
147
|
-
| `fsClearEmptyDirectory(dirPath)` | Recursively deletes empty directories under the specified directory. If all children of a directory are deleted, that directory is also deleted. |
|
|
148
|
-
| `fsFindAllParentChildPaths(childGlob, fromPath, rootPath?)` | Traverses parent directories from `fromPath` toward the root (or `rootPath`), asynchronously searching with a glob pattern at each level. Collects all matched paths. **Note**: `fromPath` must be a child of `rootPath`; otherwise, the search continues to the filesystem root. |
|
|
149
|
-
| `fsFindAllParentChildPathsSync(childGlob, fromPath, rootPath?)` | Synchronous version of `fsFindAllParentChildPaths`. Same parameters and behavior, but runs synchronously. |
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
import {
|
|
153
|
-
fsExists,
|
|
154
|
-
fsRead,
|
|
155
|
-
fsWrite,
|
|
156
|
-
fsReadJson,
|
|
157
|
-
fsWriteJson,
|
|
158
|
-
fsStat,
|
|
159
|
-
fsLstat,
|
|
160
|
-
fsReaddir,
|
|
161
|
-
fsGlob,
|
|
162
|
-
fsMkdir,
|
|
163
|
-
fsRm,
|
|
164
|
-
fsCopy,
|
|
165
|
-
fsClearEmptyDirectory,
|
|
166
|
-
fsFindAllParentChildPaths,
|
|
167
|
-
fsReadBuffer,
|
|
168
|
-
} from "@simplysm/core-node";
|
|
169
|
-
|
|
170
|
-
// Check existence
|
|
171
|
-
if (await fsExists("/path/to/file.txt")) {
|
|
172
|
-
// ...
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Read/write files
|
|
176
|
-
const content = await fsRead("/path/to/file.txt");
|
|
177
|
-
await fsWrite("/path/to/output.txt", "content"); // Automatically creates parent directories
|
|
178
|
-
|
|
179
|
-
// Read binary files
|
|
180
|
-
const buffer = await fsReadBuffer("/path/to/file.bin");
|
|
181
|
-
|
|
182
|
-
// Read/write JSON files (uses JsonConvert)
|
|
183
|
-
interface Config { port: number; host: string }
|
|
184
|
-
const config = await fsReadJson<Config>("/path/to/config.json");
|
|
185
|
-
await fsWriteJson("/path/to/output.json", data, { space: 2 });
|
|
186
|
-
|
|
187
|
-
// Retrieve file information
|
|
188
|
-
const stat = await fsStat("/path/to/file.txt"); // Follows symbolic links
|
|
189
|
-
const lstat = await fsLstat("/path/to/link"); // Symbolic link itself
|
|
190
|
-
|
|
191
|
-
// Read directory
|
|
192
|
-
const entries = await fsReaddir("/path/to/dir");
|
|
193
|
-
|
|
194
|
-
// Search files with glob pattern
|
|
195
|
-
const tsFiles = await fsGlob("**/*.ts");
|
|
196
|
-
|
|
197
|
-
// Create/delete directories
|
|
198
|
-
await fsMkdir("/path/to/dir"); // recursive
|
|
199
|
-
await fsRm("/path/to/target");
|
|
200
|
-
|
|
201
|
-
// Recursively delete empty directories
|
|
202
|
-
await fsClearEmptyDirectory("/path/to/dir");
|
|
203
|
-
|
|
204
|
-
// Copy files/directories (exclude node_modules with filter function)
|
|
205
|
-
await fsCopy("/src", "/dest", (path) => !path.includes("node_modules"));
|
|
206
|
-
|
|
207
|
-
// Traverse parent directories and glob search
|
|
208
|
-
const configs = await fsFindAllParentChildPaths(
|
|
209
|
-
"package.json",
|
|
210
|
-
"/proj/src/sub",
|
|
211
|
-
"/proj",
|
|
212
|
-
);
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
> It's recommended to use async functions except when async cannot be used (e.g., in constructors). Sync functions block the event loop and can cause performance degradation.
|
|
216
|
-
|
|
217
|
-
### FsWatcher (`features/fs-watcher`)
|
|
218
|
-
|
|
219
|
-
A chokidar-based file system change detection wrapper with glob pattern support. It merges events that occur within a short time and invokes callbacks.
|
|
220
|
-
|
|
221
|
-
| API | Description |
|
|
222
|
-
|-----|-------------|
|
|
223
|
-
| `FsWatcher.watch(paths, options?)` | Starts file watching (static, async). `paths` can be file paths or glob patterns (e.g., `"src/**/*.ts"`). Waits until chokidar's `ready` event and returns an `FsWatcher` instance. `options` accepts `chokidar.ChokidarOptions`. |
|
|
224
|
-
| `watcher.onChange(opt, cb)` | Registers a file change event handler. `opt` is `{ delay?: number }` (required object, `delay` is optional). Set event merge wait time (ms) with `opt.delay`. Supports chaining. |
|
|
225
|
-
| `watcher.close()` | Stops file watching. |
|
|
226
|
-
| `FsWatcherEvent` | Event type: `"add"` \| `"addDir"` \| `"change"` \| `"unlink"` \| `"unlinkDir"` |
|
|
227
|
-
| `FsWatcherChangeInfo` | Change information interface. Has `event: FsWatcherEvent` and `path: NormPath` fields. |
|
|
228
|
-
|
|
229
|
-
**Event Merge Strategy:**
|
|
230
|
-
|
|
231
|
-
When multiple events occur for the same file within a short time, only the final state is delivered.
|
|
232
|
-
|
|
233
|
-
| Previous Event | New Event | Result |
|
|
234
|
-
|----------------|-----------|--------|
|
|
235
|
-
| `add` | `change` | `add` (modification right after creation is treated as creation) |
|
|
236
|
-
| `add` | `unlink` | Deleted (immediate deletion after creation is treated as no change) |
|
|
237
|
-
| `addDir` | `unlinkDir` | Deleted (same as above, for directories) |
|
|
238
|
-
| `unlink` | `add` / `change` | `add` (recreation after deletion) |
|
|
239
|
-
| `unlinkDir` | `addDir` | `addDir` (directory recreation) |
|
|
240
|
-
| Others | - | Overwritten with the latest event |
|
|
241
|
-
|
|
242
|
-
```typescript
|
|
243
|
-
import { FsWatcher } from "@simplysm/core-node";
|
|
244
|
-
|
|
245
|
-
// Start file watching with glob patterns
|
|
246
|
-
const watcher = await FsWatcher.watch(["src/**/*.ts", "tests/**/*.spec.ts"]);
|
|
247
|
-
|
|
248
|
-
// Register change event handler (merge events within 300ms)
|
|
249
|
-
watcher.onChange({ delay: 300 }, (changes) => {
|
|
250
|
-
for (const { path, event } of changes) {
|
|
251
|
-
console.log(`${event}: ${path}`);
|
|
252
|
-
// event: "add" | "addDir" | "change" | "unlink" | "unlinkDir"
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
// Stop watching
|
|
257
|
-
await watcher.close();
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### Worker (`worker/`)
|
|
261
|
-
|
|
262
|
-
Provides a type-safe Worker wrapper based on Node.js `worker_threads`. Using Proxy, you can call worker methods as if calling them directly, and custom events are also supported.
|
|
263
|
-
|
|
264
|
-
| API | Description |
|
|
265
|
-
|-----|-------------|
|
|
266
|
-
| `Worker.create<TModule>(filePath, opt?)` | Creates a type-safe Worker Proxy. `filePath` is a `file://` URL or absolute path. `opt` accepts `Omit<WorkerOptions, "stdout" \| "stderr">` from `worker_threads`. |
|
|
267
|
-
| `createWorker<TMethods, TEvents>(methods)` | Worker factory used inside worker threads. Registers method objects and returns a sender object with a `send(event, data?)` method for emitting events to the main thread. |
|
|
268
|
-
| `WorkerModule` | Module type interface used for type inference in `Worker.create<typeof import("./worker")>()`. |
|
|
269
|
-
| `WorkerProxy<TModule>` | Proxy type returned by `Worker.create()`. Provides promisified methods, `on(event, listener)`, `off(event, listener)`, and `terminate()`. |
|
|
270
|
-
| `PromisifyMethods<TMethods>` | Utility type that wraps method return values in `Promise<Awaited<R>>`. Used internally by `WorkerProxy`. |
|
|
271
|
-
| `WorkerRequest` | Worker internal request message interface. Has `id`, `method`, and `params` fields. |
|
|
272
|
-
| `WorkerResponse` | Worker internal response message type. Union of `"return"`, `"error"`, `"event"`, and `"log"` response shapes. |
|
|
273
|
-
|
|
274
|
-
**Basic Usage (without events):**
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
// worker.ts - worker file
|
|
278
|
-
import { createWorker } from "@simplysm/core-node";
|
|
279
|
-
|
|
280
|
-
export default createWorker({
|
|
281
|
-
add: (a: number, b: number) => a + b,
|
|
282
|
-
multiply: (a: number, b: number) => a * b,
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
// main.ts - main thread
|
|
286
|
-
import { Worker } from "@simplysm/core-node";
|
|
287
|
-
import type * as MyWorker from "./worker";
|
|
288
|
-
import path from "path";
|
|
289
|
-
|
|
290
|
-
const worker = Worker.create<typeof MyWorker>(
|
|
291
|
-
path.resolve(import.meta.dirname, "./worker.ts"),
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
const sum = await worker.add(10, 20); // 30
|
|
295
|
-
const product = await worker.multiply(3, 4); // 12
|
|
296
|
-
|
|
297
|
-
await worker.terminate();
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
**Worker with Events:**
|
|
301
|
-
|
|
302
|
-
```typescript
|
|
303
|
-
// worker.ts
|
|
304
|
-
import { createWorker } from "@simplysm/core-node";
|
|
305
|
-
|
|
306
|
-
interface MyEvents {
|
|
307
|
-
progress: number;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// sender is defined below, but is referenced at function execution time due to closure
|
|
311
|
-
const methods = {
|
|
312
|
-
calculate: (a: number, b: number) => {
|
|
313
|
-
sender.send("progress", 50);
|
|
314
|
-
const result = a + b;
|
|
315
|
-
sender.send("progress", 100);
|
|
316
|
-
return result;
|
|
317
|
-
},
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
const sender = createWorker<typeof methods, MyEvents>(methods);
|
|
321
|
-
export default sender;
|
|
322
|
-
|
|
323
|
-
// main.ts
|
|
324
|
-
import { Worker } from "@simplysm/core-node";
|
|
325
|
-
import type * as MyWorker from "./worker";
|
|
326
|
-
import path from "path";
|
|
327
|
-
|
|
328
|
-
const worker = Worker.create<typeof MyWorker>(
|
|
329
|
-
path.resolve(import.meta.dirname, "./worker.ts"),
|
|
330
|
-
);
|
|
331
|
-
|
|
332
|
-
// Register event listener
|
|
333
|
-
worker.on("progress", (percent) => {
|
|
334
|
-
console.log(`Progress: ${percent}%`);
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
const result = await worker.calculate(10, 20); // 30
|
|
338
|
-
|
|
339
|
-
// Remove event listener
|
|
340
|
-
const listener = (percent: number) => { /* ... */ };
|
|
341
|
-
worker.on("progress", listener);
|
|
342
|
-
worker.off("progress", listener);
|
|
343
|
-
|
|
344
|
-
await worker.terminate();
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
## Caveats
|
|
348
|
-
|
|
349
|
-
- All functions throw errors wrapped in `SdError` to include path information.
|
|
350
|
-
- `fsRm` (async) retries up to 6 times (500ms intervals) for transient errors like file locks, but `fsRmSync` (sync) fails immediately without retries.
|
|
351
|
-
- In `fsCopy`/`fsCopySync`, the `filter` function is not applied to the top-level `sourcePath`, and returning `false` for a directory skips that directory and all its children.
|
|
352
|
-
- `FsWatcher` supports glob patterns (e.g., `"src/**/*.ts"`) by extracting the base directory and filtering matched files. The glob matching is performed using minimatch pattern matching.
|
|
353
|
-
- `FsWatcher` internally enforces `ignoreInitial: true`. If you pass `ignoreInitial: false`, the callback will be called with an empty array on the first `onChange` call, but the actual initial file list will not be included.
|
|
354
|
-
- `Worker` automatically runs TypeScript worker files through `tsx` in development environment (`.ts` files). In production environment (`.js`), it creates Workers directly.
|
|
355
|
-
- `Worker.create` forwards `stdout`/`stderr` from the worker thread to the main process automatically; these options cannot be overridden.
|
|
356
|
-
- This package depends on `@simplysm/core-common` and uses `jsonParse`/`jsonStringify` for JSON processing.
|
|
357
|
-
|
|
358
|
-
## Dependencies
|
|
359
|
-
|
|
360
|
-
| Package | Purpose |
|
|
361
|
-
|---------|---------|
|
|
362
|
-
| `@simplysm/core-common` | Common utilities (`SdError`, `jsonParse`, `jsonStringify`, `EventEmitter`, `DebounceQueue`, etc.) |
|
|
363
|
-
| `chokidar` | File system change detection (`FsWatcher`) |
|
|
364
|
-
| `consola` | Logging |
|
|
365
|
-
| `glob` | Glob pattern file search (`fsGlob`, `fsGlobSync`) |
|
|
366
|
-
| `minimatch` | Glob pattern matching for `FsWatcher` |
|
|
367
|
-
| `tsx` | Running TypeScript worker files in development environment |
|
|
26
|
+
| Source | Exports | Description | Test |
|
|
27
|
+
|--------|---------|-------------|------|
|
|
28
|
+
| `src/worker/types.ts` | `WorkerModule`, `PromisifyMethods`, `WorkerProxy`, `WorkerRequest`, `WorkerResponse` | Type definitions for worker thread message passing and proxy pattern | - |
|
|
29
|
+
| `src/worker/worker.ts` | `Worker` | Worker thread wrapper with method-based RPC and error forwarding | `sd-worker.spec.ts` |
|
|
30
|
+
| `src/worker/create-worker.ts` | `createWorker` | Factory to create a type-safe worker proxy from a module path | `sd-worker.spec.ts` |
|
|
368
31
|
|
|
369
32
|
## License
|
|
370
33
|
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import * as chokidar from "chokidar";
|
|
2
2
|
import { type NormPath } from "../utils/path";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* List of supported file change event types.
|
|
5
5
|
*/
|
|
6
6
|
declare const FS_WATCHER_EVENTS: readonly ["add", "addDir", "change", "unlink", "unlinkDir"];
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* File change event type.
|
|
9
9
|
*/
|
|
10
10
|
export type FsWatcherEvent = (typeof FS_WATCHER_EVENTS)[number];
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* File change information.
|
|
13
13
|
*/
|
|
14
14
|
export interface FsWatcherChangeInfo {
|
|
15
|
-
/**
|
|
15
|
+
/** Change event type */
|
|
16
16
|
event: FsWatcherEvent;
|
|
17
|
-
/**
|
|
17
|
+
/** Changed file/directory path (normalized) */
|
|
18
18
|
path: NormPath;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* Chokidar-based file system watcher wrapper.
|
|
22
|
+
* Merges events that occur within a short time and calls the callback once.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
* `options.ignoreInitial: false
|
|
26
|
-
*
|
|
27
|
-
*
|
|
24
|
+
* **Note**: The `ignoreInitial` option of chokidar is internally always set to `true`.
|
|
25
|
+
* If you pass `options.ignoreInitial: false`, the callback will be called with an empty array on the first `onChange` call,
|
|
26
|
+
* but the actual initial file list is not included.
|
|
27
|
+
* This is intentional behavior to prevent conflicts with the event merging logic.
|
|
28
28
|
*
|
|
29
29
|
* @example
|
|
30
30
|
* const watcher = await FsWatcher.watch(["src/**\/*.ts"]);
|
|
@@ -34,16 +34,16 @@ export interface FsWatcherChangeInfo {
|
|
|
34
34
|
* }
|
|
35
35
|
* });
|
|
36
36
|
*
|
|
37
|
-
* //
|
|
37
|
+
* // Close
|
|
38
38
|
* await watcher.close();
|
|
39
39
|
*/
|
|
40
40
|
export declare class FsWatcher {
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
* ready
|
|
42
|
+
* Starts watching files (asynchronous).
|
|
43
|
+
* Waits until the ready event is emitted.
|
|
44
44
|
*
|
|
45
|
-
* @param paths -
|
|
46
|
-
* @param options - chokidar
|
|
45
|
+
* @param paths - Array of file/directory paths or glob patterns to watch
|
|
46
|
+
* @param options - chokidar options
|
|
47
47
|
*/
|
|
48
48
|
static watch(paths: string[], options?: chokidar.ChokidarOptions): Promise<FsWatcher>;
|
|
49
49
|
private readonly _watcher;
|
|
@@ -53,17 +53,17 @@ export declare class FsWatcher {
|
|
|
53
53
|
private readonly _logger;
|
|
54
54
|
private constructor();
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
56
|
+
* Registers a file change event handler.
|
|
57
|
+
* Collects events for the specified delay time and calls the callback once.
|
|
58
58
|
*
|
|
59
|
-
* @param opt.delay -
|
|
60
|
-
* @param cb -
|
|
59
|
+
* @param opt.delay - Event merge wait time (ms)
|
|
60
|
+
* @param cb - Change event callback
|
|
61
61
|
*/
|
|
62
62
|
onChange(opt: {
|
|
63
63
|
delay?: number;
|
|
64
64
|
}, cb: (changeInfos: FsWatcherChangeInfo[]) => void | Promise<void>): this;
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
66
|
+
* Closes the file watcher.
|
|
67
67
|
*/
|
|
68
68
|
close(): Promise<void>;
|
|
69
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-watcher.d.ts","sourceRoot":"","sources":["..\\..\\src\\features\\fs-watcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAKrC,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,eAAe,CAAC;AAyBxD;;GAEG;AACH,QAAA,MAAM,iBAAiB,6DAA8D,CAAC;AAEtF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,
|
|
1
|
+
{"version":3,"file":"fs-watcher.d.ts","sourceRoot":"","sources":["..\\..\\src\\features\\fs-watcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAKrC,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,eAAe,CAAC;AAyBxD;;GAEG;AACH,QAAA,MAAM,iBAAiB,6DAA8D,CAAC;AAEtF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,KAAK,EAAE,cAAc,CAAC;IACtB,+CAA+C;IAC/C,IAAI,EAAE,QAAQ,CAAC;CAChB;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,SAAS;IACpB;;;;;;OAMG;WACU,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC;IAU3F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuB;IACvD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IAEjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAE5D,OAAO;IA6BP;;;;;;OAMG;IACH,QAAQ,CACN,GAAG,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EACvB,EAAE,EAAE,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC/D,IAAI;IA2EP;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|
|
@@ -17,11 +17,11 @@ function extractGlobBase(globPath) {
|
|
|
17
17
|
const FS_WATCHER_EVENTS = ["add", "addDir", "change", "unlink", "unlinkDir"];
|
|
18
18
|
class FsWatcher {
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
* ready
|
|
20
|
+
* Starts watching files (asynchronous).
|
|
21
|
+
* Waits until the ready event is emitted.
|
|
22
22
|
*
|
|
23
|
-
* @param paths -
|
|
24
|
-
* @param options - chokidar
|
|
23
|
+
* @param paths - Array of file/directory paths or glob patterns to watch
|
|
24
|
+
* @param options - chokidar options
|
|
25
25
|
*/
|
|
26
26
|
static async watch(paths, options) {
|
|
27
27
|
return new Promise((resolve, reject) => {
|
|
@@ -60,11 +60,11 @@ class FsWatcher {
|
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
63
|
+
* Registers a file change event handler.
|
|
64
|
+
* Collects events for the specified delay time and calls the callback once.
|
|
65
65
|
*
|
|
66
|
-
* @param opt.delay -
|
|
67
|
-
* @param cb -
|
|
66
|
+
* @param opt.delay - Event merge wait time (ms)
|
|
67
|
+
* @param cb - Change event callback
|
|
68
68
|
*/
|
|
69
69
|
onChange(opt, cb) {
|
|
70
70
|
const fnQ = new DebounceQueue(opt.delay);
|
|
@@ -112,7 +112,7 @@ class FsWatcher {
|
|
|
112
112
|
return this;
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
115
|
+
* Closes the file watcher.
|
|
116
116
|
*/
|
|
117
117
|
async close() {
|
|
118
118
|
for (const q of this._debounceQueues) {
|