@simplysm/core-node 13.0.100 → 14.0.1
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/dist/features/fs-watcher.d.ts +21 -21
- package/dist/features/fs-watcher.d.ts.map +1 -1
- package/dist/features/fs-watcher.js +176 -114
- package/dist/features/fs-watcher.js.map +1 -6
- package/dist/index.js +6 -7
- package/dist/index.js.map +1 -6
- package/dist/utils/fs.d.ts +96 -96
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +437 -272
- package/dist/utils/fs.js.map +1 -6
- package/dist/utils/path.d.ts +22 -22
- package/dist/utils/path.js +103 -45
- package/dist/utils/path.js.map +1 -6
- package/dist/worker/create-worker.d.ts +3 -3
- package/dist/worker/create-worker.js +106 -81
- package/dist/worker/create-worker.js.map +1 -6
- package/dist/worker/types.d.ts +14 -14
- package/dist/worker/types.js +4 -1
- package/dist/worker/types.js.map +1 -6
- package/dist/worker/worker.d.ts +5 -5
- package/dist/worker/worker.js +168 -132
- package/dist/worker/worker.js.map +1 -6
- package/lib/worker-dev-proxy.js +15 -0
- package/package.json +8 -6
- package/src/features/fs-watcher.ts +53 -42
- package/src/index.ts +3 -3
- package/src/utils/fs.ts +111 -120
- 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/README.md +0 -112
- package/docs/features.md +0 -91
- package/docs/fs.md +0 -309
- package/docs/path.md +0 -120
- package/docs/worker.md +0 -168
- package/tests/utils/fs-watcher.spec.ts +0 -286
- package/tests/utils/fs.spec.ts +0 -705
- package/tests/utils/path.spec.ts +0 -179
- package/tests/worker/fixtures/test-worker.ts +0 -35
- package/tests/worker/sd-worker.spec.ts +0 -174
|
@@ -5,15 +5,15 @@ import type { WorkerRequest, WorkerResponse } from "./types";
|
|
|
5
5
|
//#region createWorker
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Worker
|
|
8
|
+
* Worker thread에서 사용하기 위한 워커 팩토리.
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
|
-
* //
|
|
11
|
+
* // 이벤트 없는 워커
|
|
12
12
|
* export default createWorker({
|
|
13
13
|
* add: (a: number, b: number) => a + b,
|
|
14
14
|
* });
|
|
15
15
|
*
|
|
16
|
-
* //
|
|
16
|
+
* // 이벤트가 있는 워커
|
|
17
17
|
* interface MyEvents { progress: number; }
|
|
18
18
|
* const methods = {
|
|
19
19
|
* calc: (x: number) => { sender.send("progress", 50); return x * 2; },
|
|
@@ -32,13 +32,13 @@ export function createWorker<
|
|
|
32
32
|
__events: TEvents;
|
|
33
33
|
} {
|
|
34
34
|
if (parentPort === null) {
|
|
35
|
-
throw new SdError("
|
|
35
|
+
throw new SdError("이 스크립트는 worker thread에서 실행되어야 합니다 (parentPort 필요).");
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const port = parentPort;
|
|
39
39
|
|
|
40
|
-
// Worker thread
|
|
41
|
-
//
|
|
40
|
+
// Worker thread의 stdout은 메인 스레드로 자동 전달되지 않음
|
|
41
|
+
// stdout.write를 가로채서 메시지 프로토콜을 통해 메인 스레드로 전달
|
|
42
42
|
process.stdout.write = (
|
|
43
43
|
chunk: string | Uint8Array,
|
|
44
44
|
encodingOrCallback?: BufferEncoding | ((err?: Error) => void),
|
|
@@ -50,7 +50,7 @@ export function createWorker<
|
|
|
50
50
|
port.postMessage(serialized.result, serialized.transferList);
|
|
51
51
|
|
|
52
52
|
const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
|
|
53
|
-
if (cb) {
|
|
53
|
+
if (cb != null) {
|
|
54
54
|
queueMicrotask(() => cb());
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -60,7 +60,7 @@ export function createWorker<
|
|
|
60
60
|
port.on("message", async (serializedRequest: unknown) => {
|
|
61
61
|
const decoded = transfer.decode(serializedRequest);
|
|
62
62
|
|
|
63
|
-
//
|
|
63
|
+
// 요청 구조 검증
|
|
64
64
|
if (
|
|
65
65
|
decoded == null ||
|
|
66
66
|
typeof decoded !== "object" ||
|
|
@@ -77,7 +77,7 @@ export function createWorker<
|
|
|
77
77
|
const errorResponse: WorkerResponse = {
|
|
78
78
|
type: "error",
|
|
79
79
|
request: { id: "unknown", method: "unknown", params: [] },
|
|
80
|
-
body: new SdError(
|
|
80
|
+
body: new SdError(`잘못된 워커 요청 형식: ${decodedStr}`),
|
|
81
81
|
};
|
|
82
82
|
const serialized = transfer.encode(errorResponse);
|
|
83
83
|
port.postMessage(serialized.result, serialized.transferList);
|
|
@@ -91,7 +91,7 @@ export function createWorker<
|
|
|
91
91
|
const response: WorkerResponse = {
|
|
92
92
|
request,
|
|
93
93
|
type: "error",
|
|
94
|
-
body: new SdError(
|
|
94
|
+
body: new SdError(`알 수 없는 메서드: ${request.method}`),
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
const serialized = transfer.encode(response);
|
package/src/worker/types.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
//#region Types
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* `createWorker()`가 반환하는 워커 모듈의 타입 구조.
|
|
5
|
+
* `Worker.create<typeof import("./worker")>()`에서 타입 추론에 사용된다.
|
|
6
6
|
*
|
|
7
|
-
* @see createWorker -
|
|
8
|
-
* @see Worker.create -
|
|
7
|
+
* @see createWorker - 워커 모듈 생성
|
|
8
|
+
* @see Worker.create - 워커 프록시 생성
|
|
9
9
|
*/
|
|
10
10
|
export interface WorkerModule {
|
|
11
11
|
default: {
|
|
@@ -15,9 +15,9 @@ export interface WorkerModule {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* 메서드 반환값을 Promise로 감싸는 매핑 타입.
|
|
19
|
+
* 워커 메서드는 postMessage 기반으로 동작하여 항상 비동기이므로,
|
|
20
|
+
* 동기 메서드 타입도 `Promise<Awaited<R>>`로 변환된다.
|
|
21
21
|
*/
|
|
22
22
|
export type PromisifyMethods<TMethods> = {
|
|
23
23
|
[K in keyof TMethods]: TMethods[K] extends (...args: infer P) => infer R
|
|
@@ -26,14 +26,14 @@ export type PromisifyMethods<TMethods> = {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* Worker.create()가 반환하는 프록시 타입.
|
|
30
|
+
* Promise화된 메서드 + on() + terminate()을 제공한다.
|
|
31
31
|
*/
|
|
32
32
|
export type WorkerProxy<TModule extends WorkerModule> = PromisifyMethods<
|
|
33
33
|
TModule["default"]["__methods"]
|
|
34
34
|
> & {
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* 워커 이벤트 리스너를 등록한다.
|
|
37
37
|
*/
|
|
38
38
|
on<TEventName extends keyof TModule["default"]["__events"] & string>(
|
|
39
39
|
event: TEventName,
|
|
@@ -41,7 +41,7 @@ export type WorkerProxy<TModule extends WorkerModule> = PromisifyMethods<
|
|
|
41
41
|
): void;
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
44
|
+
* 워커 이벤트 리스너를 해제한다.
|
|
45
45
|
*/
|
|
46
46
|
off<TEventName extends keyof TModule["default"]["__events"] & string>(
|
|
47
47
|
event: TEventName,
|
|
@@ -49,13 +49,13 @@ export type WorkerProxy<TModule extends WorkerModule> = PromisifyMethods<
|
|
|
49
49
|
): void;
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
*
|
|
52
|
+
* 워커를 종료한다.
|
|
53
53
|
*/
|
|
54
54
|
terminate(): Promise<void>;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
58
|
+
* 내부 워커 요청 메시지.
|
|
59
59
|
*/
|
|
60
60
|
export interface WorkerRequest {
|
|
61
61
|
id: string;
|
|
@@ -64,7 +64,7 @@ export interface WorkerRequest {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
67
|
+
* 내부 워커 응답 메시지.
|
|
68
68
|
*/
|
|
69
69
|
export type WorkerResponse =
|
|
70
70
|
| {
|
package/src/worker/worker.ts
CHANGED
|
@@ -11,11 +11,11 @@ const logger = consola.withTag("sd-worker");
|
|
|
11
11
|
//#region WorkerInternal
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Worker의 내부 구현 클래스.
|
|
15
|
+
* Proxy를 통해 외부에 노출된다.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* 개발 환경(.ts 파일)에서는 TypeScript 워커 파일을 tsx를 통해 실행한다.
|
|
18
|
+
* 프로덕션 환경(.js 파일)에서는 Worker를 직접 생성한다.
|
|
19
19
|
*/
|
|
20
20
|
class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
21
21
|
private readonly _worker: WorkerRaw;
|
|
@@ -30,13 +30,13 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
|
30
30
|
|
|
31
31
|
const ext = path.extname(import.meta.filename);
|
|
32
32
|
|
|
33
|
-
//
|
|
33
|
+
// 타입 가드를 통해 env 객체 추출
|
|
34
34
|
const envObj = opt?.env != null && typeof opt.env === "object" ? opt.env : {};
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
// worker-dev-proxy.js:
|
|
36
|
+
// 개발 환경(.ts 파일)에서는 tsx를 통해 실행
|
|
37
|
+
// worker-dev-proxy.js: tsx를 통해 TypeScript 워커 파일을 동적으로 로드하는 프록시
|
|
38
38
|
if (ext === ".ts") {
|
|
39
|
-
//
|
|
39
|
+
// file:// URL이면 절대 경로로 변환 (worker-dev-proxy.js가 다시 pathToFileURL을 적용)
|
|
40
40
|
const workerPath = filePath.startsWith("file://") ? fileURLToPath(filePath) : filePath;
|
|
41
41
|
this._worker = new WorkerRaw(
|
|
42
42
|
path.resolve(import.meta.dirname, "../../lib/worker-dev-proxy.js"),
|
|
@@ -52,8 +52,8 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
|
52
52
|
},
|
|
53
53
|
);
|
|
54
54
|
} else {
|
|
55
|
-
//
|
|
56
|
-
//
|
|
55
|
+
// 프로덕션 환경 (.js 파일)
|
|
56
|
+
// file:// URL이면 변환; 그렇지 않으면 절대 경로를 그대로 사용
|
|
57
57
|
const workerPath = filePath.startsWith("file://") ? fileURLToPath(filePath) : filePath;
|
|
58
58
|
this._worker = new WorkerRaw(workerPath, {
|
|
59
59
|
stdout: true,
|
|
@@ -66,30 +66,30 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
//
|
|
69
|
+
// 워커의 stdout/stderr를 메인 프로세스로 파이프
|
|
70
70
|
this._worker.stdout.pipe(process.stdout);
|
|
71
71
|
this._worker.stderr.pipe(process.stderr);
|
|
72
72
|
|
|
73
73
|
this._worker.on("exit", (code) => {
|
|
74
74
|
if (!this._isTerminated && code !== 0) {
|
|
75
|
-
logger.error(
|
|
76
|
-
//
|
|
77
|
-
this._rejectAllPending(new Error(
|
|
75
|
+
logger.error(`워커가 비정상 종료되었습니다 (코드: ${code})`);
|
|
76
|
+
// 비정상 종료 시 대기 중인 모든 요청을 거부
|
|
77
|
+
this._rejectAllPending(new Error(`워커가 비정상 종료되었습니다 (코드: ${code})`));
|
|
78
78
|
}
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
this._worker.on("error", (err) => {
|
|
82
|
-
logger.error("
|
|
83
|
-
//
|
|
82
|
+
logger.error("워커 오류:", err);
|
|
83
|
+
// 워커 오류 시 대기 중인 모든 요청을 거부
|
|
84
84
|
this._rejectAllPending(err);
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
this._worker.on("message", (serializedResponse: unknown) => {
|
|
88
88
|
const decoded = transfer.decode(serializedResponse);
|
|
89
89
|
|
|
90
|
-
//
|
|
90
|
+
// 응답 구조 검증
|
|
91
91
|
if (decoded == null || typeof decoded !== "object" || !("type" in decoded)) {
|
|
92
|
-
logger.warn("
|
|
92
|
+
logger.warn("워커로부터 잘못된 응답 형식:", decoded);
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
const response = decoded as WorkerResponse;
|
|
@@ -116,7 +116,7 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
*
|
|
119
|
+
* 대기 중인 모든 요청을 거부한다.
|
|
120
120
|
*/
|
|
121
121
|
private _rejectAllPending(err: Error): void {
|
|
122
122
|
for (const [_id, { method, reject }] of this._pendingRequests) {
|
|
@@ -126,7 +126,7 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
*
|
|
129
|
+
* 워커 메서드를 호출한다.
|
|
130
130
|
*/
|
|
131
131
|
call(method: string, params: unknown[]): Promise<unknown> {
|
|
132
132
|
return new Promise((resolve, reject) => {
|
|
@@ -144,11 +144,11 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
/**
|
|
147
|
-
*
|
|
147
|
+
* 워커를 종료한다.
|
|
148
148
|
*/
|
|
149
149
|
async terminate(): Promise<void> {
|
|
150
150
|
this._isTerminated = true;
|
|
151
|
-
this._rejectAllPending(new Error("
|
|
151
|
+
this._rejectAllPending(new Error("워커가 종료되었습니다"));
|
|
152
152
|
await this._worker.terminate();
|
|
153
153
|
}
|
|
154
154
|
}
|
|
@@ -158,7 +158,7 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
|
158
158
|
//#region Worker
|
|
159
159
|
|
|
160
160
|
/**
|
|
161
|
-
*
|
|
161
|
+
* 타입 안전한 Worker 래퍼.
|
|
162
162
|
*
|
|
163
163
|
* @example
|
|
164
164
|
* // worker.ts
|
|
@@ -173,11 +173,11 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
|
|
|
173
173
|
*/
|
|
174
174
|
export const Worker = {
|
|
175
175
|
/**
|
|
176
|
-
*
|
|
176
|
+
* 타입 안전한 Worker Proxy를 생성한다.
|
|
177
177
|
*
|
|
178
|
-
* @param filePath -
|
|
179
|
-
* @param opt -
|
|
180
|
-
* @returns Proxy
|
|
178
|
+
* @param filePath - 워커 파일 경로 (file:// URL 또는 절대 경로)
|
|
179
|
+
* @param opt - 워커 옵션
|
|
180
|
+
* @returns Proxy 객체 (메서드 직접 호출, on(), terminate() 지원)
|
|
181
181
|
*/
|
|
182
182
|
create<TModule extends WorkerModule>(
|
|
183
183
|
filePath: string,
|
|
@@ -187,7 +187,7 @@ export const Worker = {
|
|
|
187
187
|
|
|
188
188
|
return new Proxy({} as WorkerProxy<TModule>, {
|
|
189
189
|
get(_target, prop: string) {
|
|
190
|
-
//
|
|
190
|
+
// 예약된 메서드: on, off, terminate
|
|
191
191
|
if (prop === "on") {
|
|
192
192
|
return (event: string, listener: (data: unknown) => void) => {
|
|
193
193
|
internal.on(event, listener);
|
|
@@ -202,7 +202,7 @@ export const Worker = {
|
|
|
202
202
|
return () => internal.terminate();
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
//
|
|
205
|
+
// 그 외의 경우 워커 메서드로 처리
|
|
206
206
|
return (...args: unknown[]) => internal.call(prop, args);
|
|
207
207
|
},
|
|
208
208
|
});
|
package/README.md
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# @simplysm/core-node
|
|
2
|
-
|
|
3
|
-
Simplysm package - Core module (node). Node.js utilities for file system operations, path manipulation, file watching, and type-safe worker threads.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @simplysm/core-node
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## API Overview
|
|
12
|
-
|
|
13
|
-
### File System Utils (`fsx` namespace)
|
|
14
|
-
|
|
15
|
-
| API | Type | Description |
|
|
16
|
-
|-----|------|-------------|
|
|
17
|
-
| `existsSync` | function | Check if a file or directory exists (sync) |
|
|
18
|
-
| `exists` | function | Check if a file or directory exists (async) |
|
|
19
|
-
| `mkdirSync` | function | Create a directory recursively (sync) |
|
|
20
|
-
| `mkdir` | function | Create a directory recursively (async) |
|
|
21
|
-
| `rmSync` | function | Delete a file or directory (sync) |
|
|
22
|
-
| `rm` | function | Delete a file or directory with retries (async) |
|
|
23
|
-
| `copySync` | function | Copy a file or directory with optional filter (sync) |
|
|
24
|
-
| `copy` | function | Copy a file or directory with optional filter (async) |
|
|
25
|
-
| `readSync` | function | Read a file as UTF-8 string (sync) |
|
|
26
|
-
| `read` | function | Read a file as UTF-8 string (async) |
|
|
27
|
-
| `readBufferSync` | function | Read a file as Buffer (sync) |
|
|
28
|
-
| `readBuffer` | function | Read a file as Buffer (async) |
|
|
29
|
-
| `readJsonSync` | function | Read a JSON file using JsonConvert (sync) |
|
|
30
|
-
| `readJson` | function | Read a JSON file using JsonConvert (async) |
|
|
31
|
-
| `writeSync` | function | Write data to a file, auto-creates parent dirs (sync) |
|
|
32
|
-
| `write` | function | Write data to a file, auto-creates parent dirs (async) |
|
|
33
|
-
| `writeJsonSync` | function | Write data to a JSON file (sync) |
|
|
34
|
-
| `writeJson` | function | Write data to a JSON file (async) |
|
|
35
|
-
| `readdirSync` | function | Read directory contents (sync) |
|
|
36
|
-
| `readdir` | function | Read directory contents (async) |
|
|
37
|
-
| `statSync` | function | Get file info, follows symlinks (sync) |
|
|
38
|
-
| `stat` | function | Get file info, follows symlinks (async) |
|
|
39
|
-
| `lstatSync` | function | Get file info, no symlink follow (sync) |
|
|
40
|
-
| `lstat` | function | Get file info, no symlink follow (async) |
|
|
41
|
-
| `globSync` | function | Search files by glob pattern (sync) |
|
|
42
|
-
| `glob` | function | Search files by glob pattern (async) |
|
|
43
|
-
| `clearEmptyDirectory` | function | Recursively delete empty directories |
|
|
44
|
-
| `findAllParentChildPathsSync` | function | Search for glob matches traversing parent dirs (sync) |
|
|
45
|
-
| `findAllParentChildPaths` | function | Search for glob matches traversing parent dirs (async) |
|
|
46
|
-
|
|
47
|
-
-> See [docs/fs.md](./docs/fs.md) for details.
|
|
48
|
-
|
|
49
|
-
### Path Utils (`pathx` namespace)
|
|
50
|
-
|
|
51
|
-
| API | Type | Description |
|
|
52
|
-
|-----|------|-------------|
|
|
53
|
-
| `NormPath` | type | Brand type for normalized path |
|
|
54
|
-
| `posix` | function | Convert to POSIX-style path (backslash to forward slash) |
|
|
55
|
-
| `changeFileDirectory` | function | Change the directory of a file path |
|
|
56
|
-
| `basenameWithoutExt` | function | Get filename without extension |
|
|
57
|
-
| `isChildPath` | function | Check if a path is a child of another path |
|
|
58
|
-
| `norm` | function | Normalize path to absolute NormPath |
|
|
59
|
-
| `filterByTargets` | function | Filter files by target path list |
|
|
60
|
-
|
|
61
|
-
-> See [docs/path.md](./docs/path.md) for details.
|
|
62
|
-
|
|
63
|
-
### Features
|
|
64
|
-
|
|
65
|
-
| API | Type | Description |
|
|
66
|
-
|-----|------|-------------|
|
|
67
|
-
| `FsWatcherEvent` | type | File change event type (`add`, `addDir`, `change`, `unlink`, `unlinkDir`) |
|
|
68
|
-
| `FsWatcherChangeInfo` | interface | File change information (`event`, `path`) |
|
|
69
|
-
| `FsWatcher` | class | Chokidar-based file watcher with event merging |
|
|
70
|
-
|
|
71
|
-
-> See [docs/features.md](./docs/features.md) for details.
|
|
72
|
-
|
|
73
|
-
### Worker System
|
|
74
|
-
|
|
75
|
-
| API | Type | Description |
|
|
76
|
-
|-----|------|-------------|
|
|
77
|
-
| `WorkerModule` | interface | Worker module type structure for type inference |
|
|
78
|
-
| `PromisifyMethods` | type | Maps method return values to Promise |
|
|
79
|
-
| `WorkerProxy` | type | Proxy type with promisified methods + on/off/terminate |
|
|
80
|
-
| `WorkerRequest` | interface | Internal worker request message |
|
|
81
|
-
| `WorkerResponse` | type | Internal worker response message |
|
|
82
|
-
| `Worker` | object | Type-safe Worker wrapper with `create()` factory |
|
|
83
|
-
| `createWorker` | function | Worker factory for use in worker threads |
|
|
84
|
-
|
|
85
|
-
-> See [docs/worker.md](./docs/worker.md) for details.
|
|
86
|
-
|
|
87
|
-
## Usage Examples
|
|
88
|
-
|
|
89
|
-
```typescript
|
|
90
|
-
import { fsx, pathx, FsWatcher, Worker, createWorker } from "@simplysm/core-node";
|
|
91
|
-
|
|
92
|
-
// File system
|
|
93
|
-
const content = await fsx.read("/path/to/file.txt");
|
|
94
|
-
await fsx.write("/path/to/output.txt", content);
|
|
95
|
-
|
|
96
|
-
// Path utilities
|
|
97
|
-
const normalized = pathx.norm("/some/path");
|
|
98
|
-
const posixPath = pathx.posix("C:\\Users\\test");
|
|
99
|
-
|
|
100
|
-
// File watching
|
|
101
|
-
const watcher = await FsWatcher.watch(["src/**/*.ts"]);
|
|
102
|
-
watcher.onChange({ delay: 300 }, (changes) => {
|
|
103
|
-
for (const { path, event } of changes) {
|
|
104
|
-
// handle changes
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Workers
|
|
109
|
-
const worker = Worker.create<typeof import("./worker")>("./worker.ts");
|
|
110
|
-
const result = await worker.add(10, 20);
|
|
111
|
-
await worker.terminate();
|
|
112
|
-
```
|
package/docs/features.md
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# Features
|
|
2
|
-
|
|
3
|
-
## FsWatcher
|
|
4
|
-
|
|
5
|
-
Chokidar-based file system watcher wrapper. Merges events that occur within a short time and calls the callback once.
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
import { FsWatcher } from "@simplysm/core-node";
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
### Types
|
|
12
|
-
|
|
13
|
-
#### `FsWatcherEvent`
|
|
14
|
-
|
|
15
|
-
File change event type.
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
type FsWatcherEvent = "add" | "addDir" | "change" | "unlink" | "unlinkDir";
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
#### `FsWatcherChangeInfo`
|
|
22
|
-
|
|
23
|
-
File change information.
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
interface FsWatcherChangeInfo {
|
|
27
|
-
/** Change event type */
|
|
28
|
-
event: FsWatcherEvent;
|
|
29
|
-
/** Changed file/directory path (normalized) */
|
|
30
|
-
path: NormPath;
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Class: `FsWatcher`
|
|
35
|
-
|
|
36
|
-
The `ignoreInitial` option of chokidar is internally always set to `true`. If you pass `options.ignoreInitial: false`, the callback will be called with an empty array on the first `onChange` call, but the actual initial file list is not included. This is intentional behavior to prevent conflicts with the event merging logic.
|
|
37
|
-
|
|
38
|
-
#### `FsWatcher.watch`
|
|
39
|
-
|
|
40
|
-
Starts watching files (asynchronous). Waits until the ready event is emitted.
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
static async watch(paths: string[], options?: chokidar.ChokidarOptions): Promise<FsWatcher>;
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Parameters:**
|
|
47
|
-
- `paths` -- Array of file/directory paths or glob patterns to watch
|
|
48
|
-
- `options` -- chokidar options
|
|
49
|
-
|
|
50
|
-
#### `onChange`
|
|
51
|
-
|
|
52
|
-
Registers a file change event handler. Collects events for the specified delay time and calls the callback once.
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
onChange(
|
|
56
|
-
opt: { delay?: number },
|
|
57
|
-
cb: (changeInfos: FsWatcherChangeInfo[]) => void | Promise<void>,
|
|
58
|
-
): this;
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**Parameters:**
|
|
62
|
-
- `opt.delay` -- Event merge wait time (ms)
|
|
63
|
-
- `cb` -- Change event callback
|
|
64
|
-
|
|
65
|
-
Event merging strategy:
|
|
66
|
-
- `add` + `change` -> `add` (modification immediately after creation is considered as creation)
|
|
67
|
-
- `add` + `unlink` -> no change (immediate deletion after creation is considered as no change)
|
|
68
|
-
- `unlink` + `add` -> `add` (recreation after deletion is considered as creation)
|
|
69
|
-
- Otherwise -> overwrite with latest event
|
|
70
|
-
|
|
71
|
-
#### `close`
|
|
72
|
-
|
|
73
|
-
Closes the file watcher.
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
async close(): Promise<void>;
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Example
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
const watcher = await FsWatcher.watch(["src/**/*.ts"]);
|
|
83
|
-
watcher.onChange({ delay: 300 }, (changes) => {
|
|
84
|
-
for (const { path, event } of changes) {
|
|
85
|
-
console.log(`${event}: ${path}`);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Close
|
|
90
|
-
await watcher.close();
|
|
91
|
-
```
|