@simplysm/core-node 13.0.69 → 13.0.71
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/dist/worker/worker.js
CHANGED
|
@@ -43,18 +43,18 @@ class WorkerInternal extends EventEmitter {
|
|
|
43
43
|
this._worker.stderr.pipe(process.stderr);
|
|
44
44
|
this._worker.on("exit", (code) => {
|
|
45
45
|
if (!this._isTerminated && code !== 0) {
|
|
46
|
-
logger.error(
|
|
47
|
-
this._rejectAllPending(new Error(
|
|
46
|
+
logger.error(`Worker crashed (code: ${code})`);
|
|
47
|
+
this._rejectAllPending(new Error(`Worker crashed (code: ${code})`));
|
|
48
48
|
}
|
|
49
49
|
});
|
|
50
50
|
this._worker.on("error", (err) => {
|
|
51
|
-
logger.error("
|
|
51
|
+
logger.error("Worker error:", err);
|
|
52
52
|
this._rejectAllPending(err);
|
|
53
53
|
});
|
|
54
54
|
this._worker.on("message", (serializedResponse) => {
|
|
55
55
|
const decoded = transferableDecode(serializedResponse);
|
|
56
56
|
if (decoded == null || typeof decoded !== "object" || !("type" in decoded)) {
|
|
57
|
-
logger.warn("
|
|
57
|
+
logger.warn("Invalid response format from worker:", decoded);
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
60
|
const response = decoded;
|
|
@@ -78,7 +78,7 @@ class WorkerInternal extends EventEmitter {
|
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
81
|
+
* Rejects all pending requests.
|
|
82
82
|
*/
|
|
83
83
|
_rejectAllPending(err) {
|
|
84
84
|
for (const [_id, { method, reject }] of this._pendingRequests) {
|
|
@@ -87,7 +87,7 @@ class WorkerInternal extends EventEmitter {
|
|
|
87
87
|
this._pendingRequests.clear();
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
|
-
*
|
|
90
|
+
* Calls a worker method.
|
|
91
91
|
*/
|
|
92
92
|
call(method, params) {
|
|
93
93
|
return new Promise((resolve, reject) => {
|
|
@@ -102,21 +102,21 @@ class WorkerInternal extends EventEmitter {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
|
-
*
|
|
105
|
+
* Terminates the worker.
|
|
106
106
|
*/
|
|
107
107
|
async terminate() {
|
|
108
108
|
this._isTerminated = true;
|
|
109
|
-
this._rejectAllPending(new Error("
|
|
109
|
+
this._rejectAllPending(new Error("Worker terminated"));
|
|
110
110
|
await this._worker.terminate();
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
const Worker = {
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
115
|
+
* Creates a type-safe Worker Proxy.
|
|
116
116
|
*
|
|
117
|
-
* @param filePath -
|
|
118
|
-
* @param opt - Worker
|
|
119
|
-
* @returns Proxy
|
|
117
|
+
* @param filePath - Worker file path (file:// URL or absolute path)
|
|
118
|
+
* @param opt - Worker options
|
|
119
|
+
* @returns Proxy object (supports direct method calls, on(), and terminate())
|
|
120
120
|
*/
|
|
121
121
|
create(filePath, opt) {
|
|
122
122
|
const internal = new WorkerInternal(filePath, opt);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/worker/worker.ts"],
|
|
4
|
-
"mappings": "AAAA,SAAS,cAAc,oBAAoB,oBAAoB,YAAY;AAC3E,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,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/core-node",
|
|
3
|
-
"version": "13.0.
|
|
4
|
-
"description": "
|
|
5
|
-
"author": "
|
|
3
|
+
"version": "13.0.71",
|
|
4
|
+
"description": "Simplysm package - Core module (node)",
|
|
5
|
+
"author": "simplysm",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
-
"src"
|
|
17
|
+
"src",
|
|
18
|
+
"tests"
|
|
18
19
|
],
|
|
19
20
|
"sideEffects": false,
|
|
20
21
|
"dependencies": {
|
|
@@ -23,6 +24,6 @@
|
|
|
23
24
|
"glob": "^13.0.6",
|
|
24
25
|
"minimatch": "^10.2.2",
|
|
25
26
|
"tsx": "^4.21.0",
|
|
26
|
-
"@simplysm/core-common": "13.0.
|
|
27
|
+
"@simplysm/core-common": "13.0.71"
|
|
27
28
|
}
|
|
28
29
|
}
|
|
@@ -8,11 +8,11 @@ import { type NormPath, pathNorm } from "../utils/path";
|
|
|
8
8
|
|
|
9
9
|
//#region Helpers
|
|
10
10
|
|
|
11
|
-
/**
|
|
11
|
+
/** Glob metacharacter pattern */
|
|
12
12
|
const GLOB_CHARS_RE = /[*?{[\]]/;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Extracts the base directory from a glob pattern.
|
|
16
16
|
* @example extractGlobBase("/home/user/src/**\/*.ts") → "/home/user/src"
|
|
17
17
|
*/
|
|
18
18
|
function extractGlobBase(globPath: string): string {
|
|
@@ -30,22 +30,22 @@ function extractGlobBase(globPath: string): string {
|
|
|
30
30
|
//#region Types
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* List of supported file change event types.
|
|
34
34
|
*/
|
|
35
35
|
const FS_WATCHER_EVENTS = ["add", "addDir", "change", "unlink", "unlinkDir"] as const;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* File change event type.
|
|
39
39
|
*/
|
|
40
40
|
export type FsWatcherEvent = (typeof FS_WATCHER_EVENTS)[number];
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
43
|
+
* File change information.
|
|
44
44
|
*/
|
|
45
45
|
export interface FsWatcherChangeInfo {
|
|
46
|
-
/**
|
|
46
|
+
/** Change event type */
|
|
47
47
|
event: FsWatcherEvent;
|
|
48
|
-
/**
|
|
48
|
+
/** Changed file/directory path (normalized) */
|
|
49
49
|
path: NormPath;
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -54,13 +54,13 @@ export interface FsWatcherChangeInfo {
|
|
|
54
54
|
//#region FsWatcher
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
57
|
+
* Chokidar-based file system watcher wrapper.
|
|
58
|
+
* Merges events that occur within a short time and calls the callback once.
|
|
59
59
|
*
|
|
60
|
-
*
|
|
61
|
-
* `options.ignoreInitial: false
|
|
62
|
-
*
|
|
63
|
-
*
|
|
60
|
+
* **Note**: The `ignoreInitial` option of chokidar is internally always set to `true`.
|
|
61
|
+
* If you pass `options.ignoreInitial: false`, the callback will be called with an empty array on the first `onChange` call,
|
|
62
|
+
* but the actual initial file list is not included.
|
|
63
|
+
* This is intentional behavior to prevent conflicts with the event merging logic.
|
|
64
64
|
*
|
|
65
65
|
* @example
|
|
66
66
|
* const watcher = await FsWatcher.watch(["src/**\/*.ts"]);
|
|
@@ -70,16 +70,16 @@ export interface FsWatcherChangeInfo {
|
|
|
70
70
|
* }
|
|
71
71
|
* });
|
|
72
72
|
*
|
|
73
|
-
* //
|
|
73
|
+
* // Close
|
|
74
74
|
* await watcher.close();
|
|
75
75
|
*/
|
|
76
76
|
export class FsWatcher {
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
79
|
-
* ready
|
|
78
|
+
* Starts watching files (asynchronous).
|
|
79
|
+
* Waits until the ready event is emitted.
|
|
80
80
|
*
|
|
81
|
-
* @param paths -
|
|
82
|
-
* @param options - chokidar
|
|
81
|
+
* @param paths - Array of file/directory paths or glob patterns to watch
|
|
82
|
+
* @param options - chokidar options
|
|
83
83
|
*/
|
|
84
84
|
static async watch(paths: string[], options?: chokidar.ChokidarOptions): Promise<FsWatcher> {
|
|
85
85
|
return new Promise<FsWatcher>((resolve, reject) => {
|
|
@@ -111,7 +111,7 @@ export class FsWatcher {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
//
|
|
114
|
+
// Remove duplicate paths
|
|
115
115
|
const uniquePaths = [...new Set(watchPaths)];
|
|
116
116
|
|
|
117
117
|
this._watcher = chokidar.watch(uniquePaths, {
|
|
@@ -121,18 +121,18 @@ export class FsWatcher {
|
|
|
121
121
|
});
|
|
122
122
|
this._ignoreInitial = options?.ignoreInitial ?? this._ignoreInitial;
|
|
123
123
|
|
|
124
|
-
//
|
|
124
|
+
// Log errors that occur during watching
|
|
125
125
|
this._watcher.on("error", (err) => {
|
|
126
126
|
this._logger.error("FsWatcher error:", err);
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
131
|
+
* Registers a file change event handler.
|
|
132
|
+
* Collects events for the specified delay time and calls the callback once.
|
|
133
133
|
*
|
|
134
|
-
* @param opt.delay -
|
|
135
|
-
* @param cb -
|
|
134
|
+
* @param opt.delay - Event merge wait time (ms)
|
|
135
|
+
* @param cb - Change event callback
|
|
136
136
|
*/
|
|
137
137
|
onChange(
|
|
138
138
|
opt: { delay?: number },
|
|
@@ -143,7 +143,7 @@ export class FsWatcher {
|
|
|
143
143
|
|
|
144
144
|
let changeInfoMap = new Map<string, EventName>();
|
|
145
145
|
|
|
146
|
-
// ignoreInitial
|
|
146
|
+
// If ignoreInitial is false, call callback with empty array initially
|
|
147
147
|
if (!this._ignoreInitial) {
|
|
148
148
|
fnQ.run(async () => {
|
|
149
149
|
await cb([]);
|
|
@@ -151,22 +151,22 @@ export class FsWatcher {
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
this._watcher.on("all", (event, filePath) => {
|
|
154
|
-
//
|
|
154
|
+
// Only process supported events
|
|
155
155
|
if (!FS_WATCHER_EVENTS.includes(event as FsWatcherEvent)) return;
|
|
156
156
|
|
|
157
|
-
// glob
|
|
157
|
+
// If glob matchers exist, apply pattern filtering
|
|
158
158
|
if (this._globMatchers.length > 0) {
|
|
159
159
|
const posixFilePath = filePath.replace(/\\/g, "/");
|
|
160
160
|
if (!this._globMatchers.some((m) => m.match(posixFilePath))) return;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
/*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* - add + change → add (
|
|
167
|
-
* - add + unlink →
|
|
168
|
-
* - unlink + add → add (
|
|
169
|
-
* -
|
|
164
|
+
* Event merging strategy:
|
|
165
|
+
* If multiple events occur for the same file within a short time, only the final state is passed.
|
|
166
|
+
* - add + change → add (modification immediately after creation is considered as creation)
|
|
167
|
+
* - add + unlink → no change (immediate deletion after creation is considered as no change)
|
|
168
|
+
* - unlink + add → add (recreation after deletion is considered as creation)
|
|
169
|
+
* - otherwise → overwrite with latest event
|
|
170
170
|
*/
|
|
171
171
|
if (!changeInfoMap.has(filePath)) {
|
|
172
172
|
changeInfoMap.set(filePath, event);
|
|
@@ -174,19 +174,19 @@ export class FsWatcher {
|
|
|
174
174
|
const prevEvent = changeInfoMap.get(filePath)!;
|
|
175
175
|
|
|
176
176
|
if (prevEvent === "add" && event === "change") {
|
|
177
|
-
// add
|
|
177
|
+
// add followed by change → keep add
|
|
178
178
|
changeInfoMap.set(filePath, "add");
|
|
179
179
|
} else if (
|
|
180
180
|
(prevEvent === "add" && event === "unlink") ||
|
|
181
181
|
(prevEvent === "addDir" && event === "unlinkDir")
|
|
182
182
|
) {
|
|
183
|
-
// add
|
|
183
|
+
// add followed by unlink → no change (deletion)
|
|
184
184
|
changeInfoMap.delete(filePath);
|
|
185
185
|
} else if (prevEvent === "unlink" && (event === "add" || event === "change")) {
|
|
186
|
-
// unlink
|
|
186
|
+
// unlink followed by add/change → add (file recreation)
|
|
187
187
|
changeInfoMap.set(filePath, "add");
|
|
188
188
|
} else if (prevEvent === "unlinkDir" && event === "addDir") {
|
|
189
|
-
// unlinkDir
|
|
189
|
+
// unlinkDir followed by addDir → addDir (directory recreation)
|
|
190
190
|
changeInfoMap.set(filePath, "addDir");
|
|
191
191
|
} else {
|
|
192
192
|
changeInfoMap.set(filePath, event);
|
|
@@ -213,7 +213,7 @@ export class FsWatcher {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
/**
|
|
216
|
-
*
|
|
216
|
+
* Closes the file watcher.
|
|
217
217
|
*/
|
|
218
218
|
async close(): Promise<void> {
|
|
219
219
|
for (const q of this._debounceQueues) {
|