@simplysm/core-node 13.0.100 → 14.0.4
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 +93 -79
- 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/docs/fs-watcher.md +107 -0
- package/docs/fsx.md +287 -0
- package/docs/pathx.md +115 -0
- package/docs/worker.md +117 -62
- package/lib/worker-dev-proxy.js +15 -0
- package/package.json +9 -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/docs/features.md +0 -91
- package/docs/fs.md +0 -309
- package/docs/path.md +0 -120
- 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
package/dist/worker/worker.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { WorkerOptions as WorkerRawOptions } from "worker_threads";
|
|
2
2
|
import type { WorkerModule, WorkerProxy } from "./types";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* 타입 안전한 Worker 래퍼.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* // worker.ts
|
|
@@ -16,11 +16,11 @@ import type { WorkerModule, WorkerProxy } from "./types";
|
|
|
16
16
|
*/
|
|
17
17
|
export declare const Worker: {
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* 타입 안전한 Worker Proxy를 생성한다.
|
|
20
20
|
*
|
|
21
|
-
* @param filePath -
|
|
22
|
-
* @param opt -
|
|
23
|
-
* @returns Proxy
|
|
21
|
+
* @param filePath - 워커 파일 경로 (file:// URL 또는 절대 경로)
|
|
22
|
+
* @param opt - 워커 옵션
|
|
23
|
+
* @returns Proxy 객체 (메서드 직접 호출, on(), terminate() 지원)
|
|
24
24
|
*/
|
|
25
25
|
create<TModule extends WorkerModule>(filePath: string, opt?: Omit<WorkerRawOptions, "stdout" | "stderr">): WorkerProxy<TModule>;
|
|
26
26
|
};
|
package/dist/worker/worker.js
CHANGED
|
@@ -4,143 +4,179 @@ import path from "path";
|
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { Worker as WorkerRaw } from "worker_threads";
|
|
6
6
|
const logger = consola.withTag("sd-worker");
|
|
7
|
+
//#region WorkerInternal
|
|
8
|
+
/**
|
|
9
|
+
* Worker의 내부 구현 클래스.
|
|
10
|
+
* Proxy를 통해 외부에 노출된다.
|
|
11
|
+
*
|
|
12
|
+
* 개발 환경(.ts 파일)에서는 TypeScript 워커 파일을 tsx를 통해 실행한다.
|
|
13
|
+
* 프로덕션 환경(.js 파일)에서는 Worker를 직접 생성한다.
|
|
14
|
+
*/
|
|
7
15
|
class WorkerInternal extends EventEmitter {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
_worker;
|
|
17
|
+
_isTerminated = false;
|
|
18
|
+
_pendingRequests = new Map();
|
|
19
|
+
constructor(filePath, opt) {
|
|
20
|
+
super();
|
|
21
|
+
const ext = path.extname(import.meta.filename);
|
|
22
|
+
// 타입 가드를 통해 env 객체 추출
|
|
23
|
+
const envObj = opt?.env != null && typeof opt.env === "object" ? opt.env : {};
|
|
24
|
+
// 개발 환경(.ts 파일)에서는 tsx를 통해 실행
|
|
25
|
+
// worker-dev-proxy.js: tsx를 통해 TypeScript 워커 파일을 동적으로 로드하는 프록시
|
|
26
|
+
if (ext === ".ts") {
|
|
27
|
+
// file:// URL이면 절대 경로로 변환 (worker-dev-proxy.js가 다시 pathToFileURL을 적용)
|
|
28
|
+
const workerPath = filePath.startsWith("file://") ? fileURLToPath(filePath) : filePath;
|
|
29
|
+
this._worker = new WorkerRaw(path.resolve(import.meta.dirname, "../../lib/worker-dev-proxy.js"), {
|
|
30
|
+
stdout: true,
|
|
31
|
+
stderr: true,
|
|
32
|
+
...opt,
|
|
33
|
+
env: {
|
|
34
|
+
...process.env,
|
|
35
|
+
...envObj,
|
|
36
|
+
},
|
|
37
|
+
argv: [workerPath, ...(opt?.argv ?? [])],
|
|
38
|
+
});
|
|
28
39
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
else {
|
|
41
|
+
// 프로덕션 환경 (.js 파일)
|
|
42
|
+
// file:// URL이면 변환; 그렇지 않으면 절대 경로를 그대로 사용
|
|
43
|
+
const workerPath = filePath.startsWith("file://") ? fileURLToPath(filePath) : filePath;
|
|
44
|
+
this._worker = new WorkerRaw(workerPath, {
|
|
45
|
+
stdout: true,
|
|
46
|
+
stderr: true,
|
|
47
|
+
...opt,
|
|
48
|
+
env: {
|
|
49
|
+
...process.env,
|
|
50
|
+
...envObj,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
39
53
|
}
|
|
40
|
-
|
|
54
|
+
// 워커의 stdout/stderr를 메인 프로세스로 파이프
|
|
55
|
+
this._worker.stdout.pipe(process.stdout);
|
|
56
|
+
this._worker.stderr.pipe(process.stderr);
|
|
57
|
+
this._worker.on("exit", (code) => {
|
|
58
|
+
if (!this._isTerminated && code !== 0) {
|
|
59
|
+
logger.error(`워커가 비정상 종료되었습니다 (코드: ${code})`);
|
|
60
|
+
// 비정상 종료 시 대기 중인 모든 요청을 거부
|
|
61
|
+
this._rejectAllPending(new Error(`워커가 비정상 종료되었습니다 (코드: ${code})`));
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
this._worker.on("error", (err) => {
|
|
65
|
+
logger.error("워커 오류:", err);
|
|
66
|
+
// 워커 오류 시 대기 중인 모든 요청을 거부
|
|
67
|
+
this._rejectAllPending(err);
|
|
68
|
+
});
|
|
69
|
+
this._worker.on("message", (serializedResponse) => {
|
|
70
|
+
const decoded = transfer.decode(serializedResponse);
|
|
71
|
+
// 응답 구조 검증
|
|
72
|
+
if (decoded == null || typeof decoded !== "object" || !("type" in decoded)) {
|
|
73
|
+
logger.warn("워커로부터 잘못된 응답 형식:", decoded);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const response = decoded;
|
|
77
|
+
if (response.type === "event") {
|
|
78
|
+
this.emit(response.event, response.body);
|
|
79
|
+
}
|
|
80
|
+
else if (response.type === "log") {
|
|
81
|
+
process.stdout.write(response.body);
|
|
82
|
+
}
|
|
83
|
+
else if (response.type === "return") {
|
|
84
|
+
const pending = this._pendingRequests.get(response.request.id);
|
|
85
|
+
if (pending) {
|
|
86
|
+
this._pendingRequests.delete(response.request.id);
|
|
87
|
+
pending.resolve(response.body);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// response.type === "error"
|
|
92
|
+
const pending = this._pendingRequests.get(response.request.id);
|
|
93
|
+
if (pending) {
|
|
94
|
+
this._pendingRequests.delete(response.request.id);
|
|
95
|
+
pending.reject(response.body);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
41
99
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
this._worker.on("error", (err) => {
|
|
51
|
-
logger.error("Worker error:", err);
|
|
52
|
-
this._rejectAllPending(err);
|
|
53
|
-
});
|
|
54
|
-
this._worker.on("message", (serializedResponse) => {
|
|
55
|
-
const decoded = transfer.decode(serializedResponse);
|
|
56
|
-
if (decoded == null || typeof decoded !== "object" || !("type" in decoded)) {
|
|
57
|
-
logger.warn("Invalid response format from worker:", decoded);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const response = decoded;
|
|
61
|
-
if (response.type === "event") {
|
|
62
|
-
this.emit(response.event, response.body);
|
|
63
|
-
} else if (response.type === "log") {
|
|
64
|
-
process.stdout.write(response.body);
|
|
65
|
-
} else if (response.type === "return") {
|
|
66
|
-
const pending = this._pendingRequests.get(response.request.id);
|
|
67
|
-
if (pending) {
|
|
68
|
-
this._pendingRequests.delete(response.request.id);
|
|
69
|
-
pending.resolve(response.body);
|
|
100
|
+
/**
|
|
101
|
+
* 대기 중인 모든 요청을 거부한다.
|
|
102
|
+
*/
|
|
103
|
+
_rejectAllPending(err) {
|
|
104
|
+
for (const [_id, { method, reject }] of this._pendingRequests) {
|
|
105
|
+
reject(new Error(`${err.message} (method: ${method})`));
|
|
70
106
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
107
|
+
this._pendingRequests.clear();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 워커 메서드를 호출한다.
|
|
111
|
+
*/
|
|
112
|
+
call(method, params) {
|
|
113
|
+
return new Promise((resolve, reject) => {
|
|
114
|
+
const request = {
|
|
115
|
+
id: Uuid.generate().toString(),
|
|
116
|
+
method,
|
|
117
|
+
params,
|
|
118
|
+
};
|
|
119
|
+
this._pendingRequests.set(request.id, { method, resolve, reject });
|
|
120
|
+
const serialized = transfer.encode(request);
|
|
121
|
+
this._worker.postMessage(serialized.result, serialized.transferList);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 워커를 종료한다.
|
|
126
|
+
*/
|
|
127
|
+
async terminate() {
|
|
128
|
+
this._isTerminated = true;
|
|
129
|
+
this._rejectAllPending(new Error("워커가 종료되었습니다"));
|
|
130
|
+
await this._worker.terminate();
|
|
86
131
|
}
|
|
87
|
-
this._pendingRequests.clear();
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Calls a worker method.
|
|
91
|
-
*/
|
|
92
|
-
call(method, params) {
|
|
93
|
-
return new Promise((resolve, reject) => {
|
|
94
|
-
const request = {
|
|
95
|
-
id: Uuid.generate().toString(),
|
|
96
|
-
method,
|
|
97
|
-
params
|
|
98
|
-
};
|
|
99
|
-
this._pendingRequests.set(request.id, { method, resolve, reject });
|
|
100
|
-
const serialized = transfer.encode(request);
|
|
101
|
-
this._worker.postMessage(serialized.result, serialized.transferList);
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Terminates the worker.
|
|
106
|
-
*/
|
|
107
|
-
async terminate() {
|
|
108
|
-
this._isTerminated = true;
|
|
109
|
-
this._rejectAllPending(new Error("Worker terminated"));
|
|
110
|
-
await this._worker.terminate();
|
|
111
|
-
}
|
|
112
132
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region Worker
|
|
135
|
+
/**
|
|
136
|
+
* 타입 안전한 Worker 래퍼.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* // worker.ts
|
|
140
|
+
* export default createWorker({
|
|
141
|
+
* add: (a: number, b: number) => a + b,
|
|
142
|
+
* });
|
|
143
|
+
*
|
|
144
|
+
* // main.ts
|
|
145
|
+
* const worker = Worker.create<typeof import("./worker.js")>("./worker.ts");
|
|
146
|
+
* const result = await worker.add(10, 20); // 30
|
|
147
|
+
* await worker.terminate();
|
|
148
|
+
*/
|
|
149
|
+
export const Worker = {
|
|
150
|
+
/**
|
|
151
|
+
* 타입 안전한 Worker Proxy를 생성한다.
|
|
152
|
+
*
|
|
153
|
+
* @param filePath - 워커 파일 경로 (file:// URL 또는 절대 경로)
|
|
154
|
+
* @param opt - 워커 옵션
|
|
155
|
+
* @returns Proxy 객체 (메서드 직접 호출, on(), terminate() 지원)
|
|
156
|
+
*/
|
|
157
|
+
create(filePath, opt) {
|
|
158
|
+
const internal = new WorkerInternal(filePath, opt);
|
|
159
|
+
return new Proxy({}, {
|
|
160
|
+
get(_target, prop) {
|
|
161
|
+
// 예약된 메서드: on, off, terminate
|
|
162
|
+
if (prop === "on") {
|
|
163
|
+
return (event, listener) => {
|
|
164
|
+
internal.on(event, listener);
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (prop === "off") {
|
|
168
|
+
return (event, listener) => {
|
|
169
|
+
internal.off(event, listener);
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (prop === "terminate") {
|
|
173
|
+
return () => internal.terminate();
|
|
174
|
+
}
|
|
175
|
+
// 그 외의 경우 워커 메서드로 처리
|
|
176
|
+
return (...args) => internal.call(prop, args);
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
},
|
|
145
180
|
};
|
|
146
|
-
//#
|
|
181
|
+
//#endregion
|
|
182
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/worker/worker.ts"],
|
|
4
|
-
"mappings": "AAAA,SAAS,cAAc,UAAU,YAAY;AAC7C,OAAO,aAAa;AACpB,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAE9B,SAAS,UAAU,iBAAiB;AAGpC,MAAM,SAAS,QAAQ,QAAQ,WAAW;AAW1C,MAAM,uBAAuB,aAAsC;AAAA,EAChD;AAAA,EACT,gBAAgB;AAAA,EACP,mBAAmB,oBAAI,IAGtC;AAAA,EAEF,YAAY,UAAkB,KAAmD;AAC/E,UAAM;AAEN,UAAM,MAAM,KAAK,QAAQ,YAAY,QAAQ;AAG7C,UAAM,SAAS,KAAK,OAAO,QAAQ,OAAO,IAAI,QAAQ,WAAW,IAAI,MAAM,CAAC;AAI5E,QAAI,QAAQ,OAAO;AAEjB,YAAM,aAAa,SAAS,WAAW,SAAS,IAAI,cAAc,QAAQ,IAAI;AAC9E,WAAK,UAAU,IAAI;AAAA,QACjB,KAAK,QAAQ,YAAY,SAAS,+BAA+B;AAAA,QACjE;AAAA,UACE,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,GAAG;AAAA,UACH,KAAK;AAAA,YACH,GAAG,QAAQ;AAAA,YACX,GAAG;AAAA,UACL;AAAA,UACA,MAAM,CAAC,YAAY,GAAI,KAAK,QAAQ,CAAC,CAAE;AAAA,QACzC;AAAA,MACF;AAAA,IACF,OAAO;AAGL,YAAM,aAAa,SAAS,WAAW,SAAS,IAAI,cAAc,QAAQ,IAAI;AAC9E,WAAK,UAAU,IAAI,UAAU,YAAY;AAAA,QACvC,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,GAAG;AAAA,QACH,KAAK;AAAA,UACH,GAAG,QAAQ;AAAA,UACX,GAAG;AAAA,QACL;AAAA,MACF,CAAC;AAAA,IACH;AAGA,SAAK,QAAQ,OAAO,KAAK,QAAQ,MAAM;AACvC,SAAK,QAAQ,OAAO,KAAK,QAAQ,MAAM;AAEvC,SAAK,QAAQ,GAAG,QAAQ,CAAC,SAAS;AAChC,UAAI,CAAC,KAAK,iBAAiB,SAAS,GAAG;AACrC,eAAO,MAAM,yBAAyB,IAAI,GAAG;AAE7C,aAAK,kBAAkB,IAAI,MAAM,yBAAyB,IAAI,GAAG,CAAC;AAAA,MACpE;AAAA,IACF,CAAC;AAED,SAAK,QAAQ,GAAG,SAAS,CAAC,QAAQ;AAChC,aAAO,MAAM,iBAAiB,GAAG;AAEjC,WAAK,kBAAkB,GAAG;AAAA,IAC5B,CAAC;AAED,SAAK,QAAQ,GAAG,WAAW,CAAC,uBAAgC;AAC1D,YAAM,UAAU,SAAS,OAAO,kBAAkB;AAGlD,UAAI,WAAW,QAAQ,OAAO,YAAY,YAAY,EAAE,UAAU,UAAU;AAC1E,eAAO,KAAK,wCAAwC,OAAO;AAC3D;AAAA,MACF;AACA,YAAM,WAAW;AAEjB,UAAI,SAAS,SAAS,SAAS;AAC7B,aAAK,KAAK,SAAS,OAAO,SAAS,IAAI;AAAA,MACzC,WAAW,SAAS,SAAS,OAAO;AAClC,gBAAQ,OAAO,MAAM,SAAS,IAAI;AAAA,MACpC,WAAW,SAAS,SAAS,UAAU;AACrC,cAAM,UAAU,KAAK,iBAAiB,IAAI,SAAS,QAAQ,EAAE;AAC7D,YAAI,SAAS;AACX,eAAK,iBAAiB,OAAO,SAAS,QAAQ,EAAE;AAChD,kBAAQ,QAAQ,SAAS,IAAI;AAAA,QAC/B;AAAA,MACF,OAAO;AAEL,cAAM,UAAU,KAAK,iBAAiB,IAAI,SAAS,QAAQ,EAAE;AAC7D,YAAI,SAAS;AACX,eAAK,iBAAiB,OAAO,SAAS,QAAQ,EAAE;AAChD,kBAAQ,OAAO,SAAS,IAAI;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,KAAkB;AAC1C,eAAW,CAAC,KAAK,EAAE,QAAQ,OAAO,CAAC,KAAK,KAAK,kBAAkB;AAC7D,aAAO,IAAI,MAAM,GAAG,IAAI,OAAO,aAAa,MAAM,GAAG,CAAC;AAAA,IACxD;AACA,SAAK,iBAAiB,MAAM;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,QAAgB,QAAqC;AACxD,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,UAAyB;AAAA,QAC7B,IAAI,KAAK,SAAS,EAAE,SAAS;AAAA,QAC7B;AAAA,QACA;AAAA,MACF;AAEA,WAAK,iBAAiB,IAAI,QAAQ,IAAI,EAAE,QAAQ,SAAS,OAAO,CAAC;AAEjE,YAAM,aAAa,SAAS,OAAO,OAAO;AAC1C,WAAK,QAAQ,YAAY,WAAW,QAAQ,WAAW,YAAY;AAAA,IACrE,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAA2B;AAC/B,SAAK,gBAAgB;AACrB,SAAK,kBAAkB,IAAI,MAAM,mBAAmB,CAAC;AACrD,UAAM,KAAK,QAAQ,UAAU;AAAA,EAC/B;AACF;AAoBO,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpB,OACE,UACA,KACsB;AACtB,UAAM,WAAW,IAAI,eAAe,UAAU,GAAG;AAEjD,WAAO,IAAI,MAAM,CAAC,GAA2B;AAAA,MAC3C,IAAI,SAAS,MAAc;AAEzB,YAAI,SAAS,MAAM;AACjB,iBAAO,CAAC,OAAe,aAAsC;AAC3D,qBAAS,GAAG,OAAO,QAAQ;AAAA,UAC7B;AAAA,QACF;AACA,YAAI,SAAS,OAAO;AAClB,iBAAO,CAAC,OAAe,aAAsC;AAC3D,qBAAS,IAAI,OAAO,QAAQ;AAAA,UAC9B;AAAA,QACF;AACA,YAAI,SAAS,aAAa;AACxB,iBAAO,MAAM,SAAS,UAAU;AAAA,QAClC;AAGA,eAAO,IAAI,SAAoB,SAAS,KAAK,MAAM,IAAI;AAAA,MACzD;AAAA,IACF,CAAC;AAAA,EACH;AACF;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["..\\..\\src\\worker\\worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# FsWatcher -- File System Watcher
|
|
2
|
+
|
|
3
|
+
Chokidar-based file system watcher with debounced event delivery and glob filtering.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { FsWatcher } from "@simplysm/core-node";
|
|
7
|
+
import type { FsWatcherEvent, FsWatcherChangeInfo } from "@simplysm/core-node";
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Types
|
|
11
|
+
|
|
12
|
+
### FsWatcherEvent
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type FsWatcherEvent = "add" | "addDir" | "change" | "unlink" | "unlinkDir"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Supported file change event types.
|
|
19
|
+
|
|
20
|
+
### FsWatcherChangeInfo (interface)
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
interface FsWatcherChangeInfo {
|
|
24
|
+
event: FsWatcherEvent;
|
|
25
|
+
path: NormPath;
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Field | Type | Description |
|
|
30
|
+
|-------|------|-------------|
|
|
31
|
+
| `event` | `FsWatcherEvent` | The type of change event |
|
|
32
|
+
| `path` | `NormPath` | Normalized absolute path of the changed file/directory |
|
|
33
|
+
|
|
34
|
+
## FsWatcher (class)
|
|
35
|
+
|
|
36
|
+
Wraps chokidar to provide debounced file change notifications. Multiple events occurring within a short window are merged and delivered as a single batch.
|
|
37
|
+
|
|
38
|
+
Event merging strategy:
|
|
39
|
+
- `add` + `change` --> `add` (modification right after creation is treated as creation)
|
|
40
|
+
- `add` + `unlink` --> removed (creation then deletion cancels out)
|
|
41
|
+
- `unlink` + `add` --> `add` (deletion then recreation is treated as creation)
|
|
42
|
+
- Other combinations --> latest event wins
|
|
43
|
+
|
|
44
|
+
**Note:** `ignoreInitial` is always set to `true` internally. Passing `ignoreInitial: false` triggers an initial callback with an empty array, but does not include the initial file listing.
|
|
45
|
+
|
|
46
|
+
### Static Methods
|
|
47
|
+
|
|
48
|
+
#### FsWatcher.watch
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
static async watch(
|
|
52
|
+
paths: string[],
|
|
53
|
+
options?: chokidar.ChokidarOptions,
|
|
54
|
+
): Promise<FsWatcher>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Start watching files/directories. Resolves when the watcher is ready.
|
|
58
|
+
|
|
59
|
+
| Parameter | Type | Description |
|
|
60
|
+
|-----------|------|-------------|
|
|
61
|
+
| `paths` | `string[]` | File paths, directory paths, or glob patterns to watch |
|
|
62
|
+
| `options` | `chokidar.ChokidarOptions?` | Chokidar configuration options |
|
|
63
|
+
|
|
64
|
+
Glob patterns in `paths` are automatically decomposed: the base directory is watched, and events are filtered by the glob pattern using minimatch.
|
|
65
|
+
|
|
66
|
+
### Instance Methods
|
|
67
|
+
|
|
68
|
+
#### onChange
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
onChange(
|
|
72
|
+
opt: { delay?: number },
|
|
73
|
+
cb: (changeInfos: FsWatcherChangeInfo[]) => void | Promise<void>,
|
|
74
|
+
): this
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Register a change event handler. Events are collected for the specified delay duration and delivered as a single batch.
|
|
78
|
+
|
|
79
|
+
| Parameter | Type | Description |
|
|
80
|
+
|-----------|------|-------------|
|
|
81
|
+
| `opt.delay` | `number?` | Debounce delay in milliseconds |
|
|
82
|
+
| `cb` | `(changeInfos: FsWatcherChangeInfo[]) => void \| Promise<void>` | Callback receiving batched change events |
|
|
83
|
+
|
|
84
|
+
Returns `this` for chaining.
|
|
85
|
+
|
|
86
|
+
#### close
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
async close(): Promise<void>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Stop watching and clean up all debounce queues.
|
|
93
|
+
|
|
94
|
+
## Usage
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
const watcher = await FsWatcher.watch(["src/**/*.ts"], { depth: 3 });
|
|
98
|
+
|
|
99
|
+
watcher.onChange({ delay: 300 }, (changes) => {
|
|
100
|
+
for (const { path, event } of changes) {
|
|
101
|
+
console.log(`${event}: ${path}`);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Later: stop watching
|
|
106
|
+
await watcher.close();
|
|
107
|
+
```
|