@simplysm/core-node 13.0.96 → 13.0.97

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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/README.md +0 -315
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/core-node",
3
- "version": "13.0.96",
3
+ "version": "13.0.97",
4
4
  "description": "Simplysm package - Core module (node)",
5
5
  "author": "simplysm",
6
6
  "license": "Apache-2.0",
@@ -25,6 +25,6 @@
25
25
  "glob": "^13.0.6",
26
26
  "minimatch": "^10.2.4",
27
27
  "tsx": "^4.21.0",
28
- "@simplysm/core-common": "13.0.96"
28
+ "@simplysm/core-common": "13.0.97"
29
29
  }
30
30
  }
package/README.md DELETED
@@ -1,315 +0,0 @@
1
- # @simplysm/core-node
2
-
3
- Node.js 환경 전용 유틸리티. 파일시스템, 경로, 파일 감시, Worker 스레드를 제공한다.
4
-
5
- ## 설치
6
-
7
- ```bash
8
- npm install @simplysm/core-node
9
- ```
10
-
11
- **의존성:** `@simplysm/core-common`, `chokidar`, `consola`, `glob`, `minimatch`, `tsx`
12
-
13
- ## 모듈 구조
14
-
15
- ```
16
- @simplysm/core-node
17
- ├── fsx # 파일시스템 유틸리티 (namespace)
18
- ├── pathx # 경로 유틸리티 (namespace)
19
- ├── FsWatcher # 파일 감시 (class)
20
- ├── Worker # 타입 안전한 Worker 스레드 (object)
21
- ├── createWorker # Worker 팩토리 (function)
22
- └── types # NormPath, WorkerModule, WorkerProxy, ...
23
- ```
24
-
25
- ---
26
-
27
- ## 주요 사용법
28
-
29
- ### fsx -- 파일시스템 유틸리티
30
-
31
- 모든 함수는 async/sync 쌍으로 제공된다 (예: `read` / `readSync`).
32
-
33
- ```typescript
34
- import { fsx } from "@simplysm/core-node";
35
-
36
- // 존재 확인
37
- await fsx.exists("/path/to/file");
38
- fsx.existsSync("/path/to/file");
39
-
40
- // 디렉토리 생성 (재귀)
41
- await fsx.mkdir("/path/to/dir");
42
- fsx.mkdirSync("/path/to/dir");
43
-
44
- // 삭제
45
- // async: 6회 재시도, 500ms 간격 (파일 잠금 등 일시적 오류 대응)
46
- // sync: 재시도 없이 즉시 실패
47
- await fsx.rm("/path/to/target");
48
- fsx.rmSync("/path/to/target");
49
-
50
- // 복사 (필터 지원)
51
- // 필터는 자식 경로에만 적용, 최상위 sourcePath는 필터링 대상이 아님
52
- // 디렉토리에 false를 반환하면 해당 디렉토리와 모든 하위 내용을 건너뜀
53
- // sourcePath가 존재하지 않으면 아무 동작 없이 반환
54
- await fsx.copy(src, dst, (absPath) => !absPath.includes("node_modules"));
55
- fsx.copySync(src, dst);
56
-
57
- // 읽기
58
- const text = await fsx.read("/path/to/file.txt"); // UTF-8 문자열
59
- const buf = await fsx.readBuffer("/path/to/file.bin"); // Buffer
60
- const config = await fsx.readJson<Config>("/path/config.json"); // JSON 파싱 (core-common의 json.parse 사용)
61
-
62
- // 쓰기 (부모 디렉토리 자동 생성)
63
- await fsx.write("/path/to/file.txt", content); // string | Uint8Array
64
- await fsx.writeJson("/path/to/config.json", data, { space: 2 });
65
- // writeJson의 options: { replacer?, space? }
66
-
67
- // 디렉토리 읽기
68
- const entries = await fsx.readdir("/path/to/dir"); // string[]
69
-
70
- // 파일 정보
71
- const stats = await fsx.stat("/path/to/file"); // 심볼릭 링크 따라감
72
- const lstats = await fsx.lstat("/path/to/symlink"); // 심볼릭 링크 자체 정보
73
-
74
- // Glob 패턴 검색 (절대 경로 반환)
75
- const files = await fsx.glob("**/*.ts", { cwd: "/project" });
76
- const filesSync = fsx.globSync("**/*.ts", { cwd: "/project" });
77
-
78
- // 빈 디렉토리 정리 (재귀적으로 빈 디렉토리 삭제)
79
- await fsx.clearEmptyDirectory("/path/to/dir");
80
-
81
- // 상위 디렉토리 탐색
82
- // fromPath에서 루트까지 각 디렉토리에서 childGlob 패턴에 매칭되는 파일 검색
83
- const paths = await fsx.findAllParentChildPaths("package.json", "/project/src/deep");
84
- const pathsSync = fsx.findAllParentChildPathsSync("package.json", "/project/src/deep", "/project"); // rootPath 지정 가능
85
- ```
86
-
87
- ### pathx -- 경로 유틸리티
88
-
89
- ```typescript
90
- import { pathx } from "@simplysm/core-node";
91
- import type { NormPath } from "@simplysm/core-node";
92
-
93
- // POSIX 변환 (여러 인자를 path.join 후 변환)
94
- pathx.posix("C:\\Users\\test"); // "C:/Users/test"
95
- pathx.posix("src", "index.ts"); // "src/index.ts"
96
-
97
- // 정규화 (절대 경로, 브랜드 타입 NormPath 반환)
98
- const norm: NormPath = pathx.norm("relative/path");
99
- const norm2: NormPath = pathx.norm("base", "relative"); // 여러 경로 조합 가능
100
-
101
- // 디렉토리 변경
102
- pathx.changeFileDirectory("/a/b/c.txt", "/a", "/x"); // "/x/b/c.txt"
103
- // filePath가 fromDirectory 하위가 아니면 ArgumentError 발생
104
-
105
- // 확장자 없는 파일명
106
- pathx.basenameWithoutExt("/path/file.spec.ts"); // "file.spec"
107
-
108
- // 자식 경로 확인
109
- pathx.isChildPath("/a/b/c", "/a/b"); // true
110
- pathx.isChildPath("/a/b", "/a/b"); // false (동일 경로)
111
-
112
- // 대상 경로 필터링
113
- pathx.filterByTargets(
114
- ["/proj/src/a.ts", "/proj/tests/c.ts"],
115
- ["src"],
116
- "/proj"
117
- );
118
- // ["/proj/src/a.ts"]
119
- // targets가 빈 배열이면 files를 그대로 반환
120
- ```
121
-
122
- ### FsWatcher -- 파일 감시
123
-
124
- Chokidar 기반, 이벤트 디바운싱 및 glob 패턴 지원.
125
-
126
- ```typescript
127
- import { FsWatcher } from "@simplysm/core-node";
128
- import type { FsWatcherEvent, FsWatcherChangeInfo } from "@simplysm/core-node";
129
-
130
- // 감시 시작 (ready 이벤트까지 대기)
131
- // 경로 또는 glob 패턴 모두 사용 가능
132
- const watcher = await FsWatcher.watch([
133
- "/project/src", // 디렉토리 경로
134
- "/project/lib/**/*.js", // glob 패턴
135
- ]);
136
-
137
- // chokidar 옵션 전달 가능 (ignoreInitial은 내부적으로 항상 true로 설정됨)
138
- const watcher2 = await FsWatcher.watch(["/project/src"], {
139
- depth: 2,
140
- ignored: /node_modules/,
141
- });
142
-
143
- // 변경 이벤트 핸들러 등록
144
- // delay ms 동안 이벤트를 모아 한 번에 콜백 호출
145
- watcher.onChange({ delay: 300 }, (changes: FsWatcherChangeInfo[]) => {
146
- for (const { event, path } of changes) {
147
- // event: "add" | "addDir" | "change" | "unlink" | "unlinkDir"
148
- // path: NormPath (정규화된 절대 경로)
149
- }
150
- });
151
-
152
- // 종료
153
- await watcher.close();
154
- ```
155
-
156
- **이벤트 병합 전략** (같은 파일에 대해 짧은 시간 내 여러 이벤트 발생 시):
157
- - `add` + `change` -> `add` (생성 직후 수정은 생성으로 처리)
158
- - `add` + `unlink` -> 제거 (생성 후 즉시 삭제는 무변경)
159
- - `unlink` + `add` -> `add` (삭제 후 재생성은 생성으로 처리)
160
- - `unlink` + `change` -> `add` (삭제 후 변경은 생성으로 처리)
161
- - `unlinkDir` + `addDir` -> `addDir`
162
- - 그 외 -> 마지막 이벤트로 덮어쓰기
163
-
164
- ### Worker -- 타입 안전한 Worker 스레드
165
-
166
- #### Worker 파일 작성 (worker.ts)
167
-
168
- ```typescript
169
- import { createWorker } from "@simplysm/core-node";
170
-
171
- // 이벤트 없는 Worker
172
- export default createWorker({
173
- add: (a: number, b: number) => a + b,
174
- });
175
-
176
- // 이벤트가 있는 Worker
177
- interface MyEvents {
178
- progress: number;
179
- }
180
-
181
- const methods = {
182
- processFile: async (path: string) => {
183
- sender.send("progress", 50);
184
- // ... 처리 ...
185
- sender.send("progress", 100);
186
- return "done";
187
- },
188
- };
189
-
190
- const sender = createWorker<typeof methods, MyEvents>(methods);
191
- export default sender;
192
- ```
193
-
194
- #### 메인 스레드에서 사용
195
-
196
- ```typescript
197
- import { Worker } from "@simplysm/core-node";
198
-
199
- // Worker 생성 (타입 추론을 위해 typeof import 사용)
200
- const worker = Worker.create<typeof import("./worker")>("./worker.ts");
201
-
202
- // 옵션 전달 (WorkerOptions에서 stdout/stderr 제외)
203
- const worker2 = Worker.create<typeof import("./worker")>("./worker.ts", {
204
- env: { NODE_ENV: "production" },
205
- argv: ["--verbose"],
206
- });
207
-
208
- // 메서드 호출 (자동 Promise 래핑)
209
- const result = await worker.add(10, 20); // 30
210
-
211
- // 이벤트 수신
212
- const handler = (value: number) => { /* ... */ };
213
- worker.on("progress", handler);
214
- worker.off("progress", handler); // 이벤트 해제
215
-
216
- // 종료
217
- await worker.terminate();
218
- ```
219
-
220
- **특징:**
221
- - `.ts` 파일은 tsx를 통해 자동 실행 (개발 환경), `.js` 파일은 직접 Worker 생성 (프로덕션)
222
- - UUID 기반 요청 추적으로 동시 요청 지원
223
- - Worker 크래시 시 대기 중인 모든 요청 자동 reject
224
- - Worker 내 `process.stdout.write`는 메인 스레드로 자동 전달
225
- - `@simplysm/core-common`의 `transfer`를 사용하여 메시지 직렬화
226
- - `file://` URL 경로와 절대 경로 모두 지원
227
-
228
- ---
229
-
230
- ## API 레퍼런스
231
-
232
- ### fsx (namespace)
233
-
234
- | 함수 | 시그니처 | 설명 |
235
- |------|----------|------|
236
- | `exists` | `(targetPath: string) => Promise<boolean>` | 파일/디렉토리 존재 확인 |
237
- | `existsSync` | `(targetPath: string) => boolean` | 동기 버전 |
238
- | `mkdir` | `(targetPath: string) => Promise<void>` | 디렉토리 재귀 생성 |
239
- | `mkdirSync` | `(targetPath: string) => void` | 동기 버전 |
240
- | `rm` | `(targetPath: string) => Promise<void>` | 삭제 (6회 재시도, 500ms 간격) |
241
- | `rmSync` | `(targetPath: string) => void` | 동기 버전 (재시도 없음) |
242
- | `copy` | `(src, dst, filter?) => Promise<void>` | 파일/디렉토리 복사 (async 시 병렬 처리) |
243
- | `copySync` | `(src, dst, filter?) => void` | 동기 버전 |
244
- | `read` | `(targetPath: string) => Promise<string>` | UTF-8 텍스트 읽기 |
245
- | `readSync` | `(targetPath: string) => string` | 동기 버전 |
246
- | `readBuffer` | `(targetPath: string) => Promise<Buffer>` | 바이너리 읽기 |
247
- | `readBufferSync` | `(targetPath: string) => Buffer` | 동기 버전 |
248
- | `readJson` | `<T>(targetPath: string) => Promise<T>` | JSON 파일 읽기 |
249
- | `readJsonSync` | `<T>(targetPath: string) => T` | 동기 버전 |
250
- | `write` | `(targetPath, data: string \| Uint8Array) => Promise<void>` | 파일 쓰기 (부모 디렉토리 자동 생성) |
251
- | `writeSync` | `(targetPath, data: string \| Uint8Array) => void` | 동기 버전 |
252
- | `writeJson` | `(targetPath, data, options?) => Promise<void>` | JSON 파일 쓰기 |
253
- | `writeJsonSync` | `(targetPath, data, options?) => void` | 동기 버전 |
254
- | `readdir` | `(targetPath: string) => Promise<string[]>` | 디렉토리 내용 읽기 |
255
- | `readdirSync` | `(targetPath: string) => string[]` | 동기 버전 |
256
- | `stat` | `(targetPath: string) => Promise<fs.Stats>` | 파일 정보 (심링크 따라감) |
257
- | `statSync` | `(targetPath: string) => fs.Stats` | 동기 버전 |
258
- | `lstat` | `(targetPath: string) => Promise<fs.Stats>` | 파일 정보 (심링크 자체) |
259
- | `lstatSync` | `(targetPath: string) => fs.Stats` | 동기 버전 |
260
- | `glob` | `(pattern, options?: GlobOptions) => Promise<string[]>` | Glob 패턴 검색 (절대 경로 반환) |
261
- | `globSync` | `(pattern, options?: GlobOptions) => string[]` | 동기 버전 |
262
- | `clearEmptyDirectory` | `(dirPath: string) => Promise<void>` | 빈 디렉토리 재귀 삭제 |
263
- | `findAllParentChildPaths` | `(childGlob, fromPath, rootPath?) => Promise<string[]>` | 상위 디렉토리 탐색 |
264
- | `findAllParentChildPathsSync` | `(childGlob, fromPath, rootPath?) => string[]` | 동기 버전 |
265
-
266
- ### pathx (namespace)
267
-
268
- | 함수 | 시그니처 | 설명 |
269
- |------|----------|------|
270
- | `posix` | `(...args: string[]) => string` | POSIX 경로 변환 (path.join 후 `\` -> `/`) |
271
- | `norm` | `(...paths: string[]) => NormPath` | 절대 경로 정규화 (브랜드 타입) |
272
- | `changeFileDirectory` | `(filePath, fromDir, toDir) => string` | 파일의 기준 디렉토리 변경 |
273
- | `basenameWithoutExt` | `(filePath: string) => string` | 확장자 제외한 파일명 |
274
- | `isChildPath` | `(childPath, parentPath) => boolean` | 자식 경로 여부 확인 |
275
- | `filterByTargets` | `(files, targets, cwd) => string[]` | 대상 경로 기준 파일 필터링 |
276
-
277
- ### FsWatcher (class)
278
-
279
- | 멤버 | 시그니처 | 설명 |
280
- |------|----------|------|
281
- | `static watch` | `(paths: string[], options?: ChokidarOptions) => Promise<FsWatcher>` | 감시 시작 (ready까지 대기) |
282
- | `onChange` | `(opt: { delay?: number }, cb) => this` | 변경 이벤트 핸들러 등록 (체이닝 가능) |
283
- | `close` | `() => Promise<void>` | 감시 종료 |
284
-
285
- ### Worker (object)
286
-
287
- | 멤버 | 시그니처 | 설명 |
288
- |------|----------|------|
289
- | `create` | `<TModule>(filePath, opt?) => WorkerProxy<TModule>` | 타입 안전한 Worker 프록시 생성 |
290
-
291
- ### createWorker (function)
292
-
293
- ```typescript
294
- function createWorker<
295
- TMethods extends Record<string, (...args: any[]) => unknown>,
296
- TEvents extends Record<string, unknown> = Record<string, never>,
297
- >(methods: TMethods): {
298
- send<K extends keyof TEvents & string>(event: K, data?: TEvents[K]): void;
299
- __methods: TMethods;
300
- __events: TEvents;
301
- }
302
- ```
303
-
304
- ### 타입
305
-
306
- | 타입 | 설명 |
307
- |------|------|
308
- | `NormPath` | 정규화된 경로 브랜드 타입 (`string & { [NORM]: never }`) |
309
- | `FsWatcherEvent` | `"add" \| "addDir" \| "change" \| "unlink" \| "unlinkDir"` |
310
- | `FsWatcherChangeInfo` | `{ event: FsWatcherEvent; path: NormPath }` |
311
- | `WorkerModule` | Worker 모듈 타입 구조 (타입 추론용) |
312
- | `WorkerProxy<TModule>` | Worker 프록시 타입 (메서드 + `on`/`off`/`terminate`) |
313
- | `PromisifyMethods<T>` | 메서드 반환값을 Promise로 래핑하는 매핑 타입 |
314
- | `WorkerRequest` | 내부 Worker 요청 메시지 타입 |
315
- | `WorkerResponse` | 내부 Worker 응답 메시지 타입 (return/error/event/log) |