@simplysm/sd-claude 14.0.42 → 14.0.44
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/claude/references/sd-simplysm14/angular/docs/directives.md +74 -3
- package/claude/references/sd-simplysm14/angular/docs/features.md +64 -14
- package/claude/references/sd-simplysm14/angular/docs/plugins.md +2 -90
- package/claude/references/sd-simplysm14/angular/docs/providers.md +2 -2
- package/claude/references/sd-simplysm14/angular/docs/type-utilities.md +1 -2
- package/claude/references/sd-simplysm14/angular/docs/ui-data.md +103 -23
- package/claude/references/sd-simplysm14/angular/docs/ui-form.md +173 -28
- package/claude/references/sd-simplysm14/angular/docs/ui-layout.md +19 -4
- package/claude/references/sd-simplysm14/angular/docs/ui-navigation.md +20 -2
- package/claude/references/sd-simplysm14/angular/docs/ui-overlay.md +23 -14
- package/claude/references/sd-simplysm14/angular/docs/ui-visual.md +15 -7
- package/claude/references/sd-simplysm14/angular/docs/utils.md +1 -1
- package/claude/references/sd-simplysm14/angular/usage.md +59 -15
- package/claude/references/sd-simplysm14/capacitor-plugin-auto-update/usage.md +1 -1
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/file-operations.md +154 -0
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/permissions.md +84 -0
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/storage-paths.md +107 -0
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/types.md +83 -0
- package/claude/references/sd-simplysm14/capacitor-plugin-file-system/usage.md +83 -128
- package/claude/references/sd-simplysm14/capacitor-plugin-usb-storage/usage.md +99 -1
- package/claude/references/sd-simplysm14/core-node/docs/child-process.md +182 -0
- package/claude/references/sd-simplysm14/core-node/docs/features.md +1 -1
- package/claude/references/sd-simplysm14/core-node/docs/file-system.md +509 -0
- package/claude/references/sd-simplysm14/core-node/docs/file-watching.md +139 -0
- package/claude/references/sd-simplysm14/core-node/docs/logging.md +180 -0
- package/claude/references/sd-simplysm14/core-node/docs/path.md +176 -0
- package/claude/references/sd-simplysm14/core-node/docs/worker-threads.md +334 -0
- package/claude/references/sd-simplysm14/core-node/usage.md +192 -96
- package/claude/references/sd-simplysm14/excel/docs/core-classes.md +33 -14
- package/claude/references/sd-simplysm14/excel/usage.md +47 -45
- package/claude/references/sd-simplysm14/lint/usage.md +3 -2
- package/claude/references/sd-simplysm14/orm-common/docs/queryable-executable.md +30 -35
- package/claude/references/sd-simplysm14/orm-common/usage.md +9 -8
- package/claude/references/sd-simplysm14/sd-claude/docs/assets.md +43 -34
- package/claude/references/sd-simplysm14/sd-claude/docs/cli.md +1 -1
- package/claude/references/sd-simplysm14/sd-claude/docs/hooks.md +20 -2
- package/claude/references/sd-simplysm14/sd-claude/docs/scripts.md +5 -18
- package/claude/references/sd-simplysm14/sd-claude/usage.md +6 -5
- package/claude/references/sd-simplysm14/sd-cli/usage.md +176 -1
- package/claude/references/sd-simplysm14/service-client/usage.md +126 -61
- package/claude/references/sd-simplysm14/service-common/usage.md +28 -28
- package/claude/references/sd-simplysm14/storage/usage.md +123 -30
- package/claude/{rules → references}/sd-simplysm14.md +1 -1
- package/claude/references/sd-testing.md +100 -4
- package/claude/rules/sd-claude-rules.md +21 -5
- package/claude/sd-check-write.py +1 -1
- package/claude/skills/sd-check/SKILL.md +7 -4
- package/claude/skills/sd-claude-docs/SKILL.md +7 -4
- package/claude/skills/sd-claude-docs/references/package-doc-gen.md +30 -7
- package/claude/skills/sd-commit/SKILL.md +2 -0
- package/claude/skills/sd-debug/SKILL.md +1 -1
- package/claude/skills/sd-deliverable/SKILL.md +2 -0
- package/claude/skills/sd-dev/SKILL.md +1 -1
- package/claude/skills/sd-doc-extract/SKILL.md +2 -0
- package/claude/{references/sd-debug.md → skills/sd-inner-debug/SKILL.md} +16 -20
- package/claude/{references/sd-review.md → skills/sd-inner-review/SKILL.md} +9 -4
- package/claude/skills/sd-issue/SKILL.md +2 -0
- package/claude/skills/sd-outlook/SKILL.md +2 -0
- package/claude/skills/sd-plan/SKILL.md +1 -1
- package/claude/skills/sd-prompt/SKILL.md +2 -2
- package/claude/skills/sd-refactor/SKILL.md +2 -2
- package/claude/skills/sd-review/SKILL.md +1 -1
- package/claude/skills/sd-tdd/SKILL.md +7 -7
- package/claude/skills/sd-use/SKILL.md +2 -0
- package/claude/skills/sd-wbs/SKILL.md +41 -18
- package/package.json +1 -1
- /package/claude/{references → rules}/sd-clarify.md +0 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Logging (consola)
|
|
2
|
+
|
|
3
|
+
## `setupConsola`
|
|
4
|
+
|
|
5
|
+
환경에 따라 consola의 reporter를 자동으로 구성한다.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
export function setupConsola(opts?: SetupConsolaOptions): void
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
| Parameter | Type | Description |
|
|
12
|
+
|-----------|------|-------------|
|
|
13
|
+
| `opts` | SetupConsolaOptions (optional) | 옵션 객체 |
|
|
14
|
+
|
|
15
|
+
### SetupConsolaOptions
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
export interface SetupConsolaOptions {
|
|
19
|
+
cli?: boolean;
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
| Field | Type | Description |
|
|
24
|
+
|-------|------|-------------|
|
|
25
|
+
| `cli` | boolean (optional) | CLI 모드 여부. true이면 프로덕션에서도 PrettyReporter 사용 (기본값: false) |
|
|
26
|
+
|
|
27
|
+
### Behavior by Environment
|
|
28
|
+
|
|
29
|
+
| Condition | Reporters | Debug Level |
|
|
30
|
+
|-----------|-----------|------------|
|
|
31
|
+
| Production (not DEV, not cli) | FileReporter | debug 레벨 포함 |
|
|
32
|
+
| Development or cli + SD_DEBUG | PrettyReporter | debug 레벨 포함 |
|
|
33
|
+
| Development or cli (일반) | FileReporter + PrettyReporter (info 이하) | debug는 파일에만 기록 |
|
|
34
|
+
|
|
35
|
+
**Note**:
|
|
36
|
+
- `DEV` 환경변수 또는 `SD_DEBUG` 환경변수의 값을 `parseBoolEnv()`로 파싱한다.
|
|
37
|
+
- `env("...")`는 @simplysm/core-common의 함수를 사용한다.
|
|
38
|
+
|
|
39
|
+
**Example**:
|
|
40
|
+
```typescript
|
|
41
|
+
// 환경별 자동 구성
|
|
42
|
+
setupConsola();
|
|
43
|
+
|
|
44
|
+
// CLI 모드
|
|
45
|
+
setupConsola({ cli: true });
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## `withMaxLevel`
|
|
51
|
+
|
|
52
|
+
Consola reporter를 지정된 로그 레벨 이하로 제한하는 래퍼.
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
export function withMaxLevel(reporter: ConsolaReporter, maxLevel: number): ConsolaReporter
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
| Parameter | Type | Description |
|
|
59
|
+
|-----------|------|-------------|
|
|
60
|
+
| `reporter` | ConsolaReporter | 원본 reporter |
|
|
61
|
+
| `maxLevel` | number | 최대 로그 레벨 (LogLevels 상수 참고) |
|
|
62
|
+
|
|
63
|
+
**Return**: 제한된 reporter
|
|
64
|
+
|
|
65
|
+
**Consola LogLevels**:
|
|
66
|
+
```
|
|
67
|
+
0: fatal
|
|
68
|
+
1: error
|
|
69
|
+
2: warn
|
|
70
|
+
3: info
|
|
71
|
+
4: success
|
|
72
|
+
5: log
|
|
73
|
+
6: debug
|
|
74
|
+
7: trace
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Example**:
|
|
78
|
+
```typescript
|
|
79
|
+
import { withMaxLevel, PrettyReporter, LogLevels } from "@simplysm/core-node";
|
|
80
|
+
|
|
81
|
+
// info 레벨 이하만 출력
|
|
82
|
+
const limitedReporter = withMaxLevel(new PrettyReporter(), LogLevels.info);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## `PrettyReporter`
|
|
88
|
+
|
|
89
|
+
터미널 출력용 consola reporter.
|
|
90
|
+
|
|
91
|
+
아이콘, 색상, 에러 스택 포맷팅을 지원한다.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
export class PrettyReporter implements ConsolaReporter {
|
|
95
|
+
log(logObj: LogObject, ctx: { options: ConsolaOptions }): void
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Features**:
|
|
100
|
+
- 로그 레벨별 아이콘 표시
|
|
101
|
+
- 컬러 출력
|
|
102
|
+
- 에러 객체의 스택 포맷팅
|
|
103
|
+
- 타임스탐프 표시 (선택적)
|
|
104
|
+
|
|
105
|
+
**Example**:
|
|
106
|
+
```typescript
|
|
107
|
+
import { PrettyReporter } from "@simplysm/core-node";
|
|
108
|
+
import consola from "consola";
|
|
109
|
+
|
|
110
|
+
consola.options.reporters = [new PrettyReporter()];
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## `createFileReporter`
|
|
116
|
+
|
|
117
|
+
파일 기반 consola reporter를 생성한다.
|
|
118
|
+
|
|
119
|
+
JSON 라인 형식으로 로그를 기록하며, 날짜별 로테이션과 크기 제한을 지원한다.
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
export function createFileReporter(options?: FileReporterOptions): ConsolaReporter
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
| Parameter | Type | Description |
|
|
126
|
+
|-----------|------|-------------|
|
|
127
|
+
| `options` | FileReporterOptions (optional) | 옵션 객체 |
|
|
128
|
+
|
|
129
|
+
### FileReporterOptions
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
export interface FileReporterOptions {
|
|
133
|
+
maxSize?: number; // 로그 파일 최대 크기 (바이트, 기본값: 20MB)
|
|
134
|
+
maxDays?: number; // 로그 보관 기간 (일, 기본값: 14일)
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
| Field | Type | Description |
|
|
139
|
+
|-------|------|-------------|
|
|
140
|
+
| `maxSize` | number (optional) | 단일 로그 파일의 최대 크기 (바이트). 초과 시 롤오버됨 (기본값: 20MB = 20 * 1024 * 1024) |
|
|
141
|
+
| `maxDays` | number (optional) | 로그 파일 보관 기간 (일). 이 기간이 지난 로그는 자동 삭제됨 (기본값: 14) |
|
|
142
|
+
|
|
143
|
+
### Log File Format
|
|
144
|
+
|
|
145
|
+
- 디렉토리: `.logs/`
|
|
146
|
+
- 파일명 형식: `app.YYYY-MM-DD.log`
|
|
147
|
+
- 내용: JSON 라인 (각 로그는 하나의 JSON 객체)
|
|
148
|
+
|
|
149
|
+
**Example**:
|
|
150
|
+
```typescript
|
|
151
|
+
import { createFileReporter } from "@simplysm/core-node";
|
|
152
|
+
import consola from "consola";
|
|
153
|
+
|
|
154
|
+
const fileReporter = createFileReporter({
|
|
155
|
+
maxSize: 10 * 1024 * 1024, // 10MB
|
|
156
|
+
maxDays: 7, // 7일 보관
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
consola.options.reporters = [fileReporter];
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Integration with setupConsola
|
|
165
|
+
|
|
166
|
+
setupConsola()는 내부적으로 PrettyReporter와 createFileReporter()를 사용하여 환경에 맞게 reporters를 구성한다.
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { setupConsola } from "@simplysm/core-node";
|
|
170
|
+
import consola from "consola";
|
|
171
|
+
|
|
172
|
+
// 자동 구성
|
|
173
|
+
setupConsola();
|
|
174
|
+
|
|
175
|
+
// 이후 consola를 정상적으로 사용 가능
|
|
176
|
+
consola.info("Application started");
|
|
177
|
+
consola.debug("Debug information");
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**주의**: consola는 프로젝트 루트의 `console.*` 금지 규칙을 대체하는 표준 로깅 수단이다.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Path (pathx)
|
|
2
|
+
|
|
3
|
+
## `PosixPath`
|
|
4
|
+
|
|
5
|
+
POSIX 스타일(슬래시) 경로임을 타입 수준에서 보장하는 브랜드 타입.
|
|
6
|
+
|
|
7
|
+
posix() 또는 posixResolve()를 통해서만 생성할 수 있다.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
export type PosixPath = string & {
|
|
11
|
+
[POSIX]: never;
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Note**: 일반 문자열을 강제로 PosixPath로 캐스팅할 수 없다. posix() 또는 posixResolve()를 반드시 사용해야 한다.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## `posix`
|
|
20
|
+
|
|
21
|
+
경로를 POSIX 스타일(슬래시)로 변환한다.
|
|
22
|
+
|
|
23
|
+
경로 결합이나 resolve는 수행하지 않으며, 단순히 백슬래시를 슬래시로 바꾼다.
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
export function posix(p: string): PosixPath
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Parameter | Type | Description |
|
|
30
|
+
|-----------|------|-------------|
|
|
31
|
+
| `p` | string | 변환할 경로 |
|
|
32
|
+
|
|
33
|
+
**Return**: PosixPath (슬래시로 정규화된 경로)
|
|
34
|
+
|
|
35
|
+
**Example**:
|
|
36
|
+
```typescript
|
|
37
|
+
posix("C:\\Users\\test"); // "C:/Users/test"
|
|
38
|
+
posix("./relative/path"); // "./relative/path"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## `posixResolve`
|
|
44
|
+
|
|
45
|
+
절대 경로로 resolve한 뒤 POSIX 스타일로 변환한다.
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
export function posixResolve(...args: string[]): PosixPath
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Parameter | Type | Description |
|
|
52
|
+
|-----------|------|-------------|
|
|
53
|
+
| `...args` | string[] | resolve할 경로 세그먼트 (node:path.resolve와 동일) |
|
|
54
|
+
|
|
55
|
+
**Return**: PosixPath (절대 경로, 슬래시로 정규화)
|
|
56
|
+
|
|
57
|
+
**Example**:
|
|
58
|
+
```typescript
|
|
59
|
+
posixResolve("/base", "sub", "file.txt"); // "/base/sub/file.txt" (Unix 환경)
|
|
60
|
+
posixResolve("relative/path"); // "/home/user/relative/path" (절대 경로로 resolve됨)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## `changeFileDirectory`
|
|
66
|
+
|
|
67
|
+
파일 경로의 디렉토리를 변경한다.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
export function changeFileDirectory(
|
|
71
|
+
filePath: string,
|
|
72
|
+
fromDirectory: string,
|
|
73
|
+
toDirectory: string,
|
|
74
|
+
): string
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
| Parameter | Type | Description |
|
|
78
|
+
|-----------|------|-------------|
|
|
79
|
+
| `filePath` | string | 파일 경로 |
|
|
80
|
+
| `fromDirectory` | string | 현재 디렉토리 |
|
|
81
|
+
| `toDirectory` | string | 새 디렉토리 |
|
|
82
|
+
|
|
83
|
+
**Return**: 새 디렉토리로 변경된 파일 경로
|
|
84
|
+
|
|
85
|
+
**Throws**: filePath가 fromDirectory 내부에 없는 경우 ArgumentError 발생
|
|
86
|
+
|
|
87
|
+
**Example**:
|
|
88
|
+
```typescript
|
|
89
|
+
changeFileDirectory("/a/b/c.txt", "/a/b", "/x");
|
|
90
|
+
// → "/x/c.txt"
|
|
91
|
+
|
|
92
|
+
changeFileDirectory("/a/b/sub/c.txt", "/a/b", "/x");
|
|
93
|
+
// → "/x/sub/c.txt"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## `basenameWithoutExt`
|
|
99
|
+
|
|
100
|
+
확장자를 제외한 파일명(basename)을 반환한다.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
export function basenameWithoutExt(filePath: string): string
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| Parameter | Type | Description |
|
|
107
|
+
|-----------|------|-------------|
|
|
108
|
+
| `filePath` | string | 파일 경로 |
|
|
109
|
+
|
|
110
|
+
**Return**: 확장자를 제외한 파일명
|
|
111
|
+
|
|
112
|
+
**Example**:
|
|
113
|
+
```typescript
|
|
114
|
+
basenameWithoutExt("file.txt"); // "file"
|
|
115
|
+
basenameWithoutExt("/path/to/file.spec.ts"); // "file.spec"
|
|
116
|
+
basenameWithoutExt("/path/to/file"); // "file"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## `isChildPath`
|
|
122
|
+
|
|
123
|
+
childPath가 parentPath의 하위 경로인지 확인한다.
|
|
124
|
+
|
|
125
|
+
동일한 경로이면 false를 반환한다.
|
|
126
|
+
|
|
127
|
+
경로는 내부적으로 posixResolve()를 사용하여 정규화되며, POSIX 슬래시(/)를 구분자로 사용하여 비교한다.
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
export function isChildPath(childPath: string, parentPath: string): boolean
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
| Parameter | Type | Description |
|
|
134
|
+
|-----------|------|-------------|
|
|
135
|
+
| `childPath` | string | 자식으로 확인할 경로 |
|
|
136
|
+
| `parentPath` | string | 부모로 확인할 경로 |
|
|
137
|
+
|
|
138
|
+
**Return**: childPath가 parentPath의 하위 경로이면 true, 동일하거나 상위 경로이면 false
|
|
139
|
+
|
|
140
|
+
**Example**:
|
|
141
|
+
```typescript
|
|
142
|
+
isChildPath("/a/b/c", "/a/b"); // true
|
|
143
|
+
isChildPath("/a/b", "/a/b/c"); // false
|
|
144
|
+
isChildPath("/a/b", "/a/b"); // false (동일 경로)
|
|
145
|
+
isChildPath("/a/bc", "/a/b"); // false (접두사 매칭이 아님)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## `filterByTargets`
|
|
151
|
+
|
|
152
|
+
대상 경로 목록을 기반으로 파일을 필터링한다.
|
|
153
|
+
|
|
154
|
+
대상 경로와 일치하거나 하위에 있는 파일을 포함한다.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
export function filterByTargets(files: string[], targets: string[], cwd: string): string[]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
| Parameter | Type | Description |
|
|
161
|
+
|-----------|------|-------------|
|
|
162
|
+
| `files` | string[] | 필터링할 파일 경로 배열. 주의: cwd 하위의 절대 경로여야 한다. cwd 외부의 경로는 상대 경로(../)로 변환되어 처리된다. |
|
|
163
|
+
| `targets` | string[] | 대상 경로 (cwd 기준 상대 경로, POSIX 스타일 권장) |
|
|
164
|
+
| `cwd` | string | 현재 작업 디렉토리 (절대 경로) |
|
|
165
|
+
|
|
166
|
+
**Return**: targets가 비어있으면 files를 그대로 반환; 그렇지 않으면 대상 경로 하위의 파일만 반환
|
|
167
|
+
|
|
168
|
+
**Example**:
|
|
169
|
+
```typescript
|
|
170
|
+
const files = ["/proj/src/a.ts", "/proj/src/b.ts", "/proj/tests/c.ts"];
|
|
171
|
+
filterByTargets(files, ["src"], "/proj");
|
|
172
|
+
// → ["/proj/src/a.ts", "/proj/src/b.ts"]
|
|
173
|
+
|
|
174
|
+
filterByTargets(files, [], "/proj");
|
|
175
|
+
// → ["/proj/src/a.ts", "/proj/src/b.ts", "/proj/tests/c.ts"] (targets가 비어있음)
|
|
176
|
+
```
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# Worker Threads
|
|
2
|
+
|
|
3
|
+
## `Worker`
|
|
4
|
+
|
|
5
|
+
Worker thread 프록시를 생성하는 팩토리 객체.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
export const Worker: {
|
|
9
|
+
create<TModule extends WorkerModule>(
|
|
10
|
+
workerPath: string,
|
|
11
|
+
options?: Omit<WorkerRawOptions, "stdout" | "stderr">,
|
|
12
|
+
): WorkerProxy<TModule>
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Static Method
|
|
17
|
+
|
|
18
|
+
#### `create`
|
|
19
|
+
|
|
20
|
+
워커 파일을 로드하고 타입 안전한 프록시를 생성한다.
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
static create<TModule extends WorkerModule>(
|
|
24
|
+
workerPath: string,
|
|
25
|
+
options?: Omit<WorkerRawOptions, "stdout" | "stderr">,
|
|
26
|
+
): WorkerProxy<TModule>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Parameter | Type | Description |
|
|
30
|
+
|-----------|------|-------------|
|
|
31
|
+
| `workerPath` | string | 워커 파일 경로 (.ts 또는 .js). 개발 환경에서는 .ts를 권장하며, 내부적으로 tsx를 통해 실행된다. |
|
|
32
|
+
| `options` | WorkerRawOptions (optional) | Worker thread 옵션. stdout/stderr는 자동으로 메인 프로세스로 파이프된다. |
|
|
33
|
+
|
|
34
|
+
**Return**: WorkerProxy<TModule> - 타입 안전한 워커 프록시
|
|
35
|
+
|
|
36
|
+
**Development vs Production**:
|
|
37
|
+
- **.ts 파일**: `lib/worker-dev-proxy.js`를 통해 tsx로 실행됨
|
|
38
|
+
- **.js 파일**: 직접 Worker로 로드됨
|
|
39
|
+
|
|
40
|
+
**Example**:
|
|
41
|
+
```typescript
|
|
42
|
+
import { Worker } from "@simplysm/core-node";
|
|
43
|
+
import type * as MyWorker from "./worker";
|
|
44
|
+
|
|
45
|
+
const worker = Worker.create<typeof MyWorker>("./worker.ts");
|
|
46
|
+
|
|
47
|
+
// 메서드 호출 (타입 안전)
|
|
48
|
+
const result = await worker.add(10, 20);
|
|
49
|
+
|
|
50
|
+
// 이벤트 수신 (타입 안전)
|
|
51
|
+
worker.on("progress", (value) => {
|
|
52
|
+
console.log(`Progress: ${value}%`);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
await worker.terminate();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## `createWorker`
|
|
61
|
+
|
|
62
|
+
워커 측에서 호출하여 메서드와 이벤트를 등록하는 팩토리 함수.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
export function createWorker<
|
|
66
|
+
TMethods extends Record<string, (...args: any[]) => unknown>,
|
|
67
|
+
TEvents extends Record<string, unknown> = Record<string, never>,
|
|
68
|
+
>(
|
|
69
|
+
methods: TMethods,
|
|
70
|
+
): {
|
|
71
|
+
send<TEventName extends keyof TEvents & string>(event: TEventName, data?: TEvents[TEventName]): void;
|
|
72
|
+
__methods: TMethods;
|
|
73
|
+
__events: TEvents;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
| Parameter | Type | Description |
|
|
78
|
+
|-----------|------|-------------|
|
|
79
|
+
| `methods` | Record<string, function> | 워커가 제공할 메서드 객체 |
|
|
80
|
+
|
|
81
|
+
**Type Parameters**:
|
|
82
|
+
- `TMethods`: 메서드 타입
|
|
83
|
+
- `TEvents`: 이벤트 타입 (기본값: 빈 객체)
|
|
84
|
+
|
|
85
|
+
**Return**: sender 객체. `send()` 메서드로 이벤트를 발송하고, export default로 내보낸다.
|
|
86
|
+
|
|
87
|
+
**Example**:
|
|
88
|
+
```typescript
|
|
89
|
+
// worker.ts
|
|
90
|
+
import { createWorker } from "@simplysm/core-node";
|
|
91
|
+
|
|
92
|
+
interface MyEvents {
|
|
93
|
+
progress: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const methods = {
|
|
97
|
+
add: (a: number, b: number) => a + b,
|
|
98
|
+
multiply: (a: number, b: number) => a * b,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const sender = createWorker<typeof methods, MyEvents>(methods);
|
|
102
|
+
|
|
103
|
+
export default sender;
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## `WorkerProxy`
|
|
109
|
+
|
|
110
|
+
Worker.create()가 반환하는 프록시 타입.
|
|
111
|
+
|
|
112
|
+
Promise화된 메서드 + 이벤트 리스너 + 종료 메서드를 제공한다.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
export type WorkerProxy<TModule extends WorkerModule> = PromisifyMethods<
|
|
116
|
+
TModule["default"]["__methods"]
|
|
117
|
+
> & {
|
|
118
|
+
on<TEventName extends keyof TModule["default"]["__events"] & string>(
|
|
119
|
+
event: TEventName,
|
|
120
|
+
listener: (data: TModule["default"]["__events"][TEventName]) => void,
|
|
121
|
+
): void;
|
|
122
|
+
|
|
123
|
+
off<TEventName extends keyof TModule["default"]["__events"] & string>(
|
|
124
|
+
event: TEventName,
|
|
125
|
+
listener: (data: TModule["default"]["__events"][TEventName]) => void,
|
|
126
|
+
): void;
|
|
127
|
+
|
|
128
|
+
terminate(): Promise<void>;
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Methods
|
|
133
|
+
|
|
134
|
+
| Name | Signature | Description |
|
|
135
|
+
|------|-----------|-------------|
|
|
136
|
+
| `[메서드명]` | `(...args): Promise<R>` | 워커의 메서드. 비동기로 Promise를 반환한다. |
|
|
137
|
+
| `on` | `<E extends EventName>(event, listener): void` | 워커 이벤트 리스너를 등록한다. |
|
|
138
|
+
| `off` | `<E extends EventName>(event, listener): void` | 워커 이벤트 리스너를 해제한다. |
|
|
139
|
+
| `terminate` | `(): Promise<void>` | 워커를 종료한다. |
|
|
140
|
+
|
|
141
|
+
**Example**:
|
|
142
|
+
```typescript
|
|
143
|
+
const worker = Worker.create<typeof MyWorker>("./worker.ts");
|
|
144
|
+
|
|
145
|
+
// 메서드 호출
|
|
146
|
+
const sum = await worker.add(10, 20); // 30
|
|
147
|
+
const product = await worker.multiply(5, 6); // 30
|
|
148
|
+
|
|
149
|
+
// 이벤트 리스너 등록
|
|
150
|
+
worker.on("progress", (value) => {
|
|
151
|
+
console.log(`Progress: ${value}%`);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// 이벤트 리스너 제거
|
|
155
|
+
worker.off("progress", handler);
|
|
156
|
+
|
|
157
|
+
// 워커 종료
|
|
158
|
+
await worker.terminate();
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## `PromisifyMethods`
|
|
164
|
+
|
|
165
|
+
메서드의 반환값을 Promise로 감싸는 매핑 타입.
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
export type PromisifyMethods<TMethods> = {
|
|
169
|
+
[K in keyof TMethods]: TMethods[K] extends (...args: infer P) => infer R
|
|
170
|
+
? (...args: P) => Promise<Awaited<R>>
|
|
171
|
+
: never;
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Note**: 워커 메서드는 postMessage 기반으로 동작하여 항상 비동기이므로, 동기 메서드 타입도 `Promise<Awaited<R>>`로 변환된다.
|
|
176
|
+
|
|
177
|
+
**Example**:
|
|
178
|
+
```typescript
|
|
179
|
+
// 원본
|
|
180
|
+
interface Methods {
|
|
181
|
+
add: (a: number, b: number) => number;
|
|
182
|
+
process: (data: string) => Promise<Result>;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// PromisifyMethods 적용 후
|
|
186
|
+
type ProxiedMethods = {
|
|
187
|
+
add: (a: number, b: number) => Promise<number>;
|
|
188
|
+
process: (data: string) => Promise<Result>;
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## `WorkerModule`
|
|
195
|
+
|
|
196
|
+
createWorker()가 반환하는 워커 모듈의 타입 구조.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
export interface WorkerModule {
|
|
200
|
+
default: {
|
|
201
|
+
__methods: Record<string, (...args: any[]) => unknown>;
|
|
202
|
+
__events: Record<string, unknown>;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Usage**:
|
|
208
|
+
```typescript
|
|
209
|
+
import type * as MyWorker from "./worker";
|
|
210
|
+
|
|
211
|
+
const worker = Worker.create<typeof MyWorker>("./worker.ts");
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## `WorkerRequest`
|
|
217
|
+
|
|
218
|
+
메인 프로세스에서 워커로 보내는 요청 메시지.
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
export interface WorkerRequest {
|
|
222
|
+
id: string;
|
|
223
|
+
method: string;
|
|
224
|
+
params: unknown[];
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Field | Type | Description |
|
|
229
|
+
|-------|------|-------------|
|
|
230
|
+
| `id` | string | 요청의 고유 ID (응답과 매칭하는 데 사용) |
|
|
231
|
+
| `method` | string | 호출할 메서드명 |
|
|
232
|
+
| `params` | unknown[] | 메서드 인자 배열 |
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## `WorkerResponse`
|
|
237
|
+
|
|
238
|
+
워커에서 메인 프로세스로 보내는 응답 메시지.
|
|
239
|
+
|
|
240
|
+
Discriminated union 타입으로, 다음 중 하나의 형태를 가진다:
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
export type WorkerResponse =
|
|
244
|
+
| {
|
|
245
|
+
request: WorkerRequest;
|
|
246
|
+
type: "return";
|
|
247
|
+
body?: unknown;
|
|
248
|
+
}
|
|
249
|
+
| {
|
|
250
|
+
request: WorkerRequest;
|
|
251
|
+
type: "error";
|
|
252
|
+
body: Error;
|
|
253
|
+
}
|
|
254
|
+
| {
|
|
255
|
+
type: "event";
|
|
256
|
+
event: string;
|
|
257
|
+
body?: unknown;
|
|
258
|
+
}
|
|
259
|
+
| {
|
|
260
|
+
type: "log";
|
|
261
|
+
body: string;
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
| Variant | Description |
|
|
266
|
+
|---------|-------------|
|
|
267
|
+
| `return` | 메서드 실행 성공 결과 |
|
|
268
|
+
| `error` | 메서드 실행 중 에러 발생 |
|
|
269
|
+
| `event` | 워커에서 발송한 이벤트 (request 없음, event 이름과 body 포함) |
|
|
270
|
+
| `log` | 워커의 stdout.write 출력 (string body) |
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Complete Example
|
|
275
|
+
|
|
276
|
+
### worker.ts (워커 파일)
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import { createWorker } from "@simplysm/core-node";
|
|
280
|
+
|
|
281
|
+
interface MyEvents {
|
|
282
|
+
progress: number;
|
|
283
|
+
done: { result: number };
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const methods = {
|
|
287
|
+
compute: async (n: number) => {
|
|
288
|
+
const sender = createWorker<typeof methods, MyEvents>(methods);
|
|
289
|
+
|
|
290
|
+
let result = 0;
|
|
291
|
+
for (let i = 0; i <= n; i++) {
|
|
292
|
+
result += i;
|
|
293
|
+
// 진행률 보고
|
|
294
|
+
sender.send("progress", (i / n) * 100);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
sender.send("done", { result });
|
|
298
|
+
return result;
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
const sender = createWorker<typeof methods, MyEvents>(methods);
|
|
303
|
+
export default sender;
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### main.ts (메인 파일)
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
import { Worker } from "@simplysm/core-node";
|
|
310
|
+
import type * as MyWorker from "./worker";
|
|
311
|
+
|
|
312
|
+
async function main() {
|
|
313
|
+
const worker = Worker.create<typeof MyWorker>("./worker.ts");
|
|
314
|
+
|
|
315
|
+
// 진행률 수신
|
|
316
|
+
worker.on("progress", (value) => {
|
|
317
|
+
console.log(`Progress: ${value.toFixed(1)}%`);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// 완료 신호 수신
|
|
321
|
+
worker.on("done", ({ result }) => {
|
|
322
|
+
console.log(`Done! Result: ${result}`);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// 메서드 호출
|
|
326
|
+
const result = await worker.compute(100);
|
|
327
|
+
console.log(`Final result: ${result}`);
|
|
328
|
+
|
|
329
|
+
// 워커 종료
|
|
330
|
+
await worker.terminate();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
main().catch(console.error);
|
|
334
|
+
```
|