@simplysm/core-node 13.0.75 → 13.0.77
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 +353 -44
- package/dist/features/fs-watcher.d.ts.map +1 -1
- package/dist/features/fs-watcher.js +2 -2
- package/dist/features/fs-watcher.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/utils/fs.d.ts +30 -30
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +101 -99
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/path.d.ts +19 -19
- package/dist/utils/path.d.ts.map +1 -1
- package/dist/utils/path.js +17 -17
- package/dist/utils/path.js.map +1 -1
- package/dist/worker/create-worker.d.ts +1 -1
- package/dist/worker/create-worker.d.ts.map +1 -1
- package/dist/worker/create-worker.js +8 -8
- package/dist/worker/create-worker.js.map +1 -1
- package/dist/worker/types.d.ts +2 -2
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker.js +4 -4
- package/dist/worker/worker.js.map +1 -1
- package/package.json +2 -2
- package/src/features/fs-watcher.ts +2 -2
- package/src/index.ts +2 -2
- package/src/utils/fs.ts +570 -562
- package/src/utils/path.ts +24 -24
- package/src/worker/create-worker.ts +9 -9
- package/src/worker/types.ts +6 -6
- package/src/worker/worker.ts +4 -4
- package/tests/utils/fs-watcher.spec.ts +0 -53
- package/tests/utils/fs.spec.ts +123 -173
- package/tests/utils/path.spec.ts +55 -68
- package/tests/worker/sd-worker.spec.ts +0 -15
package/README.md
CHANGED
|
@@ -23,73 +23,382 @@ pnpm add @simplysm/core-node
|
|
|
23
23
|
|
|
24
24
|
## Filesystem Utilities
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
|
37
|
-
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
Import as a namespace:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { fsx } from "@simplysm/core-node";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Wraps the built-in `fs` module with recursive directory creation, retry logic, glob support, and consistent error wrapping via `SdError`. Both synchronous (`Sync` suffix) and asynchronous variants are provided for most operations.
|
|
33
|
+
|
|
34
|
+
### Existence Check
|
|
35
|
+
|
|
36
|
+
| Function | Signature | Description |
|
|
37
|
+
|----------|-----------|-------------|
|
|
38
|
+
| `fsx.existsSync` | `(targetPath: string) => boolean` | Check if a path exists (synchronous) |
|
|
39
|
+
| `fsx.exists` | `(targetPath: string) => Promise<boolean>` | Check if a path exists (asynchronous) |
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
if (await fsx.exists("/some/file.txt")) { /* ... */ }
|
|
43
|
+
if (fsx.existsSync("/some/file.txt")) { /* ... */ }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Create Directory
|
|
47
|
+
|
|
48
|
+
| Function | Signature | Description |
|
|
49
|
+
|----------|-----------|-------------|
|
|
50
|
+
| `fsx.mkdirSync` | `(targetPath: string) => void` | Create directory recursively (synchronous) |
|
|
51
|
+
| `fsx.mkdir` | `(targetPath: string) => Promise<void>` | Create directory recursively (asynchronous) |
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
await fsx.mkdir("/some/deep/dir");
|
|
55
|
+
fsx.mkdirSync("/some/deep/dir");
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Delete
|
|
59
|
+
|
|
60
|
+
| Function | Signature | Description |
|
|
61
|
+
|----------|-----------|-------------|
|
|
62
|
+
| `fsx.rmSync` | `(targetPath: string) => void` | Delete file or directory recursively (synchronous, no retry) |
|
|
63
|
+
| `fsx.rm` | `(targetPath: string) => Promise<void>` | Delete file or directory recursively (asynchronous, retries up to 6 times at 500ms intervals on transient errors) |
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
await fsx.rm("/some/dir");
|
|
67
|
+
fsx.rmSync("/some/file.txt");
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Copy
|
|
71
|
+
|
|
72
|
+
| Function | Signature | Description |
|
|
73
|
+
|----------|-----------|-------------|
|
|
74
|
+
| `fsx.copySync` | `(sourcePath: string, targetPath: string, filter?: (absolutePath: string) => boolean) => void` | Copy file or directory (synchronous) |
|
|
75
|
+
| `fsx.copy` | `(sourcePath: string, targetPath: string, filter?: (absolutePath: string) => boolean) => Promise<void>` | Copy file or directory (asynchronous) |
|
|
76
|
+
|
|
77
|
+
If `sourcePath` does not exist, the function returns without error. The `filter` callback receives the absolute path of each child item; returning `false` excludes that item and its descendants. The top-level `sourcePath` is never filtered.
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
await fsx.copy("/src", "/dest", (p) => !p.includes("node_modules"));
|
|
81
|
+
fsx.copySync("/src", "/dest");
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Read File
|
|
85
|
+
|
|
86
|
+
| Function | Signature | Description |
|
|
87
|
+
|----------|-----------|-------------|
|
|
88
|
+
| `fsx.readSync` | `(targetPath: string) => string` | Read file as UTF-8 string (synchronous) |
|
|
89
|
+
| `fsx.read` | `(targetPath: string) => Promise<string>` | Read file as UTF-8 string (asynchronous) |
|
|
90
|
+
| `fsx.readBufferSync` | `(targetPath: string) => Buffer` | Read file as `Buffer` (synchronous) |
|
|
91
|
+
| `fsx.readBuffer` | `(targetPath: string) => Promise<Buffer>` | Read file as `Buffer` (asynchronous) |
|
|
92
|
+
| `fsx.readJsonSync` | `<TData = unknown>(targetPath: string) => TData` | Read and parse a JSON file (synchronous) |
|
|
93
|
+
| `fsx.readJson` | `<TData = unknown>(targetPath: string) => Promise<TData>` | Read and parse a JSON file (asynchronous) |
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
const text = await fsx.read("/config.txt");
|
|
97
|
+
const buf = fsx.readBufferSync("/image.png");
|
|
98
|
+
const config = await fsx.readJson<Config>("/config.json");
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Write File
|
|
102
|
+
|
|
103
|
+
| Function | Signature | Description |
|
|
104
|
+
|----------|-----------|-------------|
|
|
105
|
+
| `fsx.writeSync` | `(targetPath: string, data: string \| Uint8Array) => void` | Write to file, auto-creating parent directories (synchronous) |
|
|
106
|
+
| `fsx.write` | `(targetPath: string, data: string \| Uint8Array) => Promise<void>` | Write to file, auto-creating parent directories (asynchronous) |
|
|
107
|
+
| `fsx.writeJsonSync` | `(targetPath: string, data: unknown, options?: { replacer?: ..., space?: string \| number }) => void` | Serialize and write JSON to file (synchronous) |
|
|
108
|
+
| `fsx.writeJson` | `(targetPath: string, data: unknown, options?: { replacer?: ..., space?: string \| number }) => Promise<void>` | Serialize and write JSON to file (asynchronous) |
|
|
109
|
+
|
|
110
|
+
The `writeJsonSync`/`writeJson` `options` parameter:
|
|
111
|
+
- `replacer?: (this: unknown, key: string | undefined, value: unknown) => unknown` — custom JSON replacer function
|
|
112
|
+
- `space?: string | number` — indentation (passed to `JSON.stringify`)
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
await fsx.write("/output.txt", "hello");
|
|
116
|
+
fsx.writeSync("/output.bin", new Uint8Array([1, 2, 3]));
|
|
117
|
+
await fsx.writeJson("/config.json", { key: "value" }, { space: 2 });
|
|
118
|
+
fsx.writeJsonSync("/config.json", { key: "value" });
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Read Directory
|
|
122
|
+
|
|
123
|
+
| Function | Signature | Description |
|
|
124
|
+
|----------|-----------|-------------|
|
|
125
|
+
| `fsx.readdirSync` | `(targetPath: string) => string[]` | List directory entries (synchronous) |
|
|
126
|
+
| `fsx.readdir` | `(targetPath: string) => Promise<string[]>` | List directory entries (asynchronous) |
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
const entries = await fsx.readdir("/some/dir");
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### File Information
|
|
133
|
+
|
|
134
|
+
| Function | Signature | Description |
|
|
135
|
+
|----------|-----------|-------------|
|
|
136
|
+
| `fsx.statSync` | `(targetPath: string) => fs.Stats` | Get `fs.Stats` following symlinks (synchronous) |
|
|
137
|
+
| `fsx.stat` | `(targetPath: string) => Promise<fs.Stats>` | Get `fs.Stats` following symlinks (asynchronous) |
|
|
138
|
+
| `fsx.lstatSync` | `(targetPath: string) => fs.Stats` | Get `fs.Stats` without following symlinks (synchronous) |
|
|
139
|
+
| `fsx.lstat` | `(targetPath: string) => Promise<fs.Stats>` | Get `fs.Stats` without following symlinks (asynchronous) |
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
const stats = await fsx.stat("/some/file.txt");
|
|
143
|
+
console.log(stats.size);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Glob
|
|
147
|
+
|
|
148
|
+
| Function | Signature | Description |
|
|
149
|
+
|----------|-----------|-------------|
|
|
150
|
+
| `fsx.globSync` | `(pattern: string, options?: GlobOptions) => string[]` | Find files by glob pattern, returns absolute paths (synchronous) |
|
|
151
|
+
| `fsx.glob` | `(pattern: string, options?: GlobOptions) => Promise<string[]>` | Find files by glob pattern, returns absolute paths (asynchronous) |
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const files = await fsx.glob("src/**/*.ts");
|
|
155
|
+
const configs = fsx.globSync("**/tsconfig.json", { dot: true });
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Utilities
|
|
159
|
+
|
|
160
|
+
| Function | Signature | Description |
|
|
161
|
+
|----------|-----------|-------------|
|
|
162
|
+
| `fsx.clearEmptyDirectory` | `(dirPath: string) => Promise<void>` | Recursively delete all empty directories under `dirPath`; if all children of a parent are removed, the parent is also deleted |
|
|
163
|
+
| `fsx.findAllParentChildPathsSync` | `(childGlob: string, fromPath: string, rootPath?: string) => string[]` | Find matching paths by traversing parent directories toward the root (synchronous) |
|
|
164
|
+
| `fsx.findAllParentChildPaths` | `(childGlob: string, fromPath: string, rootPath?: string) => Promise<string[]>` | Find matching paths by traversing parent directories toward the root (asynchronous) |
|
|
165
|
+
|
|
166
|
+
`findAllParentChildPathsSync` / `findAllParentChildPaths` walk from `fromPath` up to `rootPath` (or the filesystem root if omitted), collecting all paths that match `childGlob` in each directory. `fromPath` must be a child of `rootPath`; otherwise the search goes to the filesystem root.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
await fsx.clearEmptyDirectory("/build");
|
|
170
|
+
|
|
171
|
+
const configs = fsx.findAllParentChildPathsSync("tsconfig.json", "/project/src", "/project");
|
|
172
|
+
// → ["/project/src/tsconfig.json", "/project/tsconfig.json"]
|
|
173
|
+
|
|
174
|
+
const pkgFiles = await fsx.findAllParentChildPaths("package.json", process.cwd());
|
|
175
|
+
```
|
|
47
176
|
|
|
48
177
|
---
|
|
49
178
|
|
|
50
179
|
## Path Utilities
|
|
51
180
|
|
|
52
|
-
|
|
181
|
+
Import as a namespace:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { pathx } from "@simplysm/core-node";
|
|
185
|
+
```
|
|
53
186
|
|
|
54
187
|
Complements the built-in `path` module with normalization, POSIX conversion, and filtering helpers.
|
|
55
188
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
|
59
|
-
|
|
60
|
-
| `
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
|
189
|
+
### Types
|
|
190
|
+
|
|
191
|
+
| Type | Description |
|
|
192
|
+
|------|-------------|
|
|
193
|
+
| `pathx.NormPath` | Branded `string` type for normalized absolute paths. Can only be produced by `pathx.norm()`. |
|
|
194
|
+
|
|
195
|
+
### Functions
|
|
196
|
+
|
|
197
|
+
| Function | Signature | Description |
|
|
198
|
+
|----------|-----------|-------------|
|
|
199
|
+
| `pathx.norm` | `(...paths: string[]) => NormPath` | Resolve segments to an absolute `NormPath` using `path.resolve` |
|
|
200
|
+
| `pathx.posix` | `(...args: string[]) => string` | Join segments and convert backslashes to forward slashes |
|
|
201
|
+
| `pathx.changeFileDirectory` | `(filePath: string, fromDirectory: string, toDirectory: string) => string` | Re-root a file path to a different base directory; throws if `filePath` is not inside `fromDirectory` |
|
|
202
|
+
| `pathx.basenameWithoutExt` | `(filePath: string) => string` | Get filename without its last extension |
|
|
203
|
+
| `pathx.isChildPath` | `(childPath: string, parentPath: string) => boolean` | Return `true` if `childPath` is strictly inside `parentPath` (same path returns `false`) |
|
|
204
|
+
| `pathx.filterByTargets` | `(files: string[], targets: string[], cwd: string) => string[]` | Filter absolute paths to only those matching or under any entry in `targets` (relative to `cwd`); returns `files` unchanged when `targets` is empty |
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import { pathx } from "@simplysm/core-node";
|
|
208
|
+
|
|
209
|
+
// norm
|
|
210
|
+
const abs: pathx.NormPath = pathx.norm("relative", "path");
|
|
211
|
+
|
|
212
|
+
// posix
|
|
213
|
+
pathx.posix("C:\\Users\\test"); // "C:/Users/test"
|
|
214
|
+
pathx.posix("src", "index.ts"); // "src/index.ts"
|
|
215
|
+
|
|
216
|
+
// changeFileDirectory
|
|
217
|
+
pathx.changeFileDirectory("/a/b/c.txt", "/a", "/x"); // "/x/b/c.txt"
|
|
218
|
+
|
|
219
|
+
// basenameWithoutExt
|
|
220
|
+
pathx.basenameWithoutExt("file.spec.ts"); // "file.spec"
|
|
221
|
+
|
|
222
|
+
// isChildPath
|
|
223
|
+
pathx.isChildPath("/a/b/c", "/a/b"); // true
|
|
224
|
+
pathx.isChildPath("/a/b", "/a/b"); // false
|
|
225
|
+
|
|
226
|
+
// filterByTargets
|
|
227
|
+
const files = ["/proj/src/a.ts", "/proj/src/b.ts", "/proj/tests/c.ts"];
|
|
228
|
+
pathx.filterByTargets(files, ["src"], "/proj");
|
|
229
|
+
// → ["/proj/src/a.ts", "/proj/src/b.ts"]
|
|
230
|
+
```
|
|
65
231
|
|
|
66
232
|
---
|
|
67
233
|
|
|
68
234
|
## File System Watcher
|
|
69
235
|
|
|
70
|
-
|
|
236
|
+
```ts
|
|
237
|
+
import { FsWatcher } from "@simplysm/core-node";
|
|
238
|
+
import type { FsWatcherEvent, FsWatcherChangeInfo } from "@simplysm/core-node";
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
A chokidar-based watcher that debounces rapid events and delivers them as a single batched array to a callback. Glob patterns are supported in the `paths` array and are matched using minimatch.
|
|
242
|
+
|
|
243
|
+
**Note:** `ignoreInitial` is always set to `true` internally. If you pass `options.ignoreInitial: false`, the callback is invoked once with an empty array on the first `onChange` call, but the actual initial file list is not included.
|
|
71
244
|
|
|
72
|
-
|
|
245
|
+
### API
|
|
73
246
|
|
|
74
247
|
| API | Description |
|
|
75
248
|
|-----|-------------|
|
|
76
|
-
| `FsWatcher.watch(paths, options?)` | Start watching
|
|
77
|
-
| `watcher.onChange(opt, cb)` | Register a debounced batch-change handler |
|
|
78
|
-
| `watcher.close()` | Stop watching and dispose resources |
|
|
249
|
+
| `FsWatcher.watch(paths, options?)` | Static method. Start watching and wait until the watcher is ready. Returns `Promise<FsWatcher>`. |
|
|
250
|
+
| `watcher.onChange(opt, cb)` | Register a debounced batch-change handler. `opt.delay` sets the debounce window in ms. Returns `this` for chaining. |
|
|
251
|
+
| `watcher.close()` | Stop watching and dispose all resources. Returns `Promise<void>`. |
|
|
79
252
|
|
|
80
|
-
|
|
253
|
+
**`FsWatcher.watch` parameters:**
|
|
254
|
+
- `paths: string[]` — file/directory paths or glob patterns to watch
|
|
255
|
+
- `options?: ChokidarOptions` — passed to chokidar (except `ignoreInitial`, which is always overridden to `true`)
|
|
256
|
+
|
|
257
|
+
**`onChange` parameters:**
|
|
258
|
+
- `opt: { delay?: number }` — debounce delay in milliseconds
|
|
259
|
+
- `cb: (changeInfos: FsWatcherChangeInfo[]) => void | Promise<void>` — called with the merged batch of changes
|
|
260
|
+
|
|
261
|
+
**Event merging rules applied within a debounce window:**
|
|
262
|
+
- `add` then `change` → `add`
|
|
263
|
+
- `add` then `unlink` → removed (no change emitted)
|
|
264
|
+
- `unlink` then `add` or `change` → `add`
|
|
265
|
+
- `unlinkDir` then `addDir` → `addDir`
|
|
266
|
+
- Otherwise the latest event wins.
|
|
267
|
+
|
|
268
|
+
### Types
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
type FsWatcherEvent = "add" | "addDir" | "change" | "unlink" | "unlinkDir";
|
|
272
|
+
|
|
273
|
+
interface FsWatcherChangeInfo {
|
|
274
|
+
event: FsWatcherEvent;
|
|
275
|
+
path: NormPath; // normalized absolute path
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Example
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
import { FsWatcher } from "@simplysm/core-node";
|
|
283
|
+
|
|
284
|
+
const watcher = await FsWatcher.watch(["src/**/*.ts", "public"]);
|
|
285
|
+
|
|
286
|
+
watcher.onChange({ delay: 300 }, async (changes) => {
|
|
287
|
+
for (const { event, path } of changes) {
|
|
288
|
+
console.log(`${event}: ${path}`);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// Later:
|
|
293
|
+
await watcher.close();
|
|
294
|
+
```
|
|
81
295
|
|
|
82
296
|
---
|
|
83
297
|
|
|
84
298
|
## Worker Thread Abstraction
|
|
85
299
|
|
|
86
|
-
|
|
300
|
+
```ts
|
|
301
|
+
import { createWorker, Worker } from "@simplysm/core-node";
|
|
302
|
+
import type {
|
|
303
|
+
WorkerModule,
|
|
304
|
+
WorkerProxy,
|
|
305
|
+
PromisifyMethods,
|
|
306
|
+
WorkerRequest,
|
|
307
|
+
WorkerResponse,
|
|
308
|
+
} from "@simplysm/core-node";
|
|
309
|
+
```
|
|
87
310
|
|
|
88
|
-
Type-safe RPC bridge over Node.js `worker_threads`. Define methods in a worker file and call them from the main thread with full TypeScript inference.
|
|
311
|
+
Type-safe RPC bridge over Node.js `worker_threads`. Define methods in a worker file and call them from the main thread with full TypeScript inference. In development (`.ts` files), workers are executed via `tsx`; in production (`.js` files), workers are executed directly.
|
|
89
312
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
313
|
+
### `createWorker`
|
|
314
|
+
|
|
315
|
+
Used inside a worker file to register RPC methods and optionally declare typed events.
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
function createWorker<
|
|
319
|
+
TMethods extends Record<string, (...args: any[]) => unknown>,
|
|
320
|
+
TEvents extends Record<string, unknown> = Record<string, never>,
|
|
321
|
+
>(
|
|
322
|
+
methods: TMethods,
|
|
323
|
+
): {
|
|
324
|
+
send<TEventName extends keyof TEvents & string>(event: TEventName, data?: TEvents[TEventName]): void;
|
|
325
|
+
__methods: TMethods;
|
|
326
|
+
__events: TEvents;
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
- `methods` — object mapping method names to their implementations
|
|
331
|
+
- Returns an object with a `send(event, data?)` method for emitting typed events to the main thread
|
|
332
|
+
- The `__methods` and `__events` fields carry type information used by `Worker.create`
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
// worker.ts
|
|
336
|
+
import { createWorker } from "@simplysm/core-node";
|
|
337
|
+
|
|
338
|
+
interface MyEvents { progress: number; }
|
|
339
|
+
|
|
340
|
+
const methods = {
|
|
341
|
+
add: (a: number, b: number) => a + b,
|
|
342
|
+
calc: (x: number) => {
|
|
343
|
+
sender.send("progress", 50);
|
|
344
|
+
return x * 2;
|
|
345
|
+
},
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
const sender = createWorker<typeof methods, MyEvents>(methods);
|
|
349
|
+
export default sender;
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### `Worker.create`
|
|
353
|
+
|
|
354
|
+
Used in the main thread to create a typed proxy to a worker file.
|
|
94
355
|
|
|
95
|
-
|
|
356
|
+
```ts
|
|
357
|
+
Worker.create<TModule extends WorkerModule>(
|
|
358
|
+
filePath: string,
|
|
359
|
+
opt?: Omit<WorkerOptions, "stdout" | "stderr">,
|
|
360
|
+
): WorkerProxy<TModule>
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
- `filePath` — absolute path or `file://` URL to the worker file (`.ts` in development, `.js` in production)
|
|
364
|
+
- `opt` — standard `worker_threads` `WorkerOptions` (excluding `stdout`/`stderr`, which are always piped)
|
|
365
|
+
- Returns a `WorkerProxy` with all worker methods promisified, plus `on()`, `off()`, and `terminate()`
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
// main.ts
|
|
369
|
+
import { Worker } from "@simplysm/core-node";
|
|
370
|
+
|
|
371
|
+
const worker = Worker.create<typeof import("./worker")>("./worker.ts");
|
|
372
|
+
|
|
373
|
+
worker.on("progress", (value) => console.log("progress:", value));
|
|
374
|
+
|
|
375
|
+
const result = await worker.add(10, 20); // 30
|
|
376
|
+
await worker.terminate();
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Types
|
|
380
|
+
|
|
381
|
+
| Type | Description |
|
|
382
|
+
|------|-------------|
|
|
383
|
+
| `WorkerModule` | Shape constraint for the module returned by `createWorker()`. Used as the type parameter of `Worker.create`. |
|
|
384
|
+
| `WorkerProxy<TModule>` | Proxy type returned by `Worker.create()`. Provides promisified methods plus `on(event, listener)`, `off(event, listener)`, and `terminate()`. |
|
|
385
|
+
| `PromisifyMethods<TMethods>` | Maps each method's return type to `Promise<Awaited<R>>`. |
|
|
386
|
+
| `WorkerRequest` | Internal RPC request message shape: `{ id: string, method: string, params: unknown[] }`. |
|
|
387
|
+
| `WorkerResponse` | Internal RPC response message — a discriminated union of `"return"`, `"error"`, `"event"`, and `"log"` variants. |
|
|
388
|
+
|
|
389
|
+
### `WorkerProxy` interface detail
|
|
390
|
+
|
|
391
|
+
```ts
|
|
392
|
+
type WorkerProxy<TModule extends WorkerModule> =
|
|
393
|
+
PromisifyMethods<TModule["default"]["__methods"]> & {
|
|
394
|
+
on<TEventName extends keyof TModule["default"]["__events"] & string>(
|
|
395
|
+
event: TEventName,
|
|
396
|
+
listener: (data: TModule["default"]["__events"][TEventName]) => void,
|
|
397
|
+
): void;
|
|
398
|
+
off<TEventName extends keyof TModule["default"]["__events"] & string>(
|
|
399
|
+
event: TEventName,
|
|
400
|
+
listener: (data: TModule["default"]["__events"][TEventName]) => void,
|
|
401
|
+
): void;
|
|
402
|
+
terminate(): Promise<void>;
|
|
403
|
+
};
|
|
404
|
+
```
|
|
@@ -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,
|
|
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,EAAQ,MAAM,eAAe,CAAC;AAyBpD;;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"}
|
|
@@ -3,7 +3,7 @@ import * as chokidar from "chokidar";
|
|
|
3
3
|
import consola from "consola";
|
|
4
4
|
import { Minimatch } from "minimatch";
|
|
5
5
|
import path from "path";
|
|
6
|
-
import {
|
|
6
|
+
import { norm } from "../utils/path.js";
|
|
7
7
|
const GLOB_CHARS_RE = /[*?{[\]]/;
|
|
8
8
|
function extractGlobBase(globPath) {
|
|
9
9
|
const segments = globPath.split(/[/\\]/);
|
|
@@ -102,7 +102,7 @@ class FsWatcher {
|
|
|
102
102
|
changeInfoMap = /* @__PURE__ */ new Map();
|
|
103
103
|
const changeInfos = Array.from(currChangeInfoMap.entries()).map(
|
|
104
104
|
([changedPath, evt]) => ({
|
|
105
|
-
path:
|
|
105
|
+
path: norm(changedPath),
|
|
106
106
|
event: evt
|
|
107
107
|
})
|
|
108
108
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/features/fs-watcher.ts"],
|
|
4
|
-
"mappings": "AAAA,SAAS,qBAAqB;AAC9B,YAAY,cAAc;AAC1B,OAAO,aAAa;AAEpB,SAAS,iBAAiB;AAC1B,OAAO,UAAU;AACjB,SAAwB,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["..\\src\\index.ts"],"names":[],"mappings":"AACA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["..\\src\\index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as fsx from "./utils/fs.js";
|
|
2
|
+
import * as pathx from "./utils/path.js";
|
|
3
3
|
export * from "./features/fs-watcher.js";
|
|
4
4
|
export * from "./worker/types.js";
|
|
5
5
|
export * from "./worker/worker.js";
|
|
6
6
|
export * from "./worker/create-worker.js";
|
|
7
|
+
export {
|
|
8
|
+
fsx,
|
|
9
|
+
pathx
|
|
10
|
+
};
|
|
7
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED