@simplysm/sd-claude 14.0.41 → 14.0.43

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 (67) hide show
  1. package/claude/references/sd-simplysm14/angular/docs/directives.md +74 -3
  2. package/claude/references/sd-simplysm14/angular/docs/features.md +64 -14
  3. package/claude/references/sd-simplysm14/angular/docs/plugins.md +2 -90
  4. package/claude/references/sd-simplysm14/angular/docs/providers.md +2 -2
  5. package/claude/references/sd-simplysm14/angular/docs/type-utilities.md +1 -2
  6. package/claude/references/sd-simplysm14/angular/docs/ui-data.md +103 -23
  7. package/claude/references/sd-simplysm14/angular/docs/ui-form.md +173 -28
  8. package/claude/references/sd-simplysm14/angular/docs/ui-layout.md +19 -4
  9. package/claude/references/sd-simplysm14/angular/docs/ui-navigation.md +20 -2
  10. package/claude/references/sd-simplysm14/angular/docs/ui-overlay.md +23 -14
  11. package/claude/references/sd-simplysm14/angular/docs/ui-visual.md +15 -7
  12. package/claude/references/sd-simplysm14/angular/docs/utils.md +1 -1
  13. package/claude/references/sd-simplysm14/angular/usage.md +16 -15
  14. package/claude/references/sd-simplysm14/capacitor-plugin-auto-update/usage.md +1 -1
  15. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/file-operations.md +154 -0
  16. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/permissions.md +84 -0
  17. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/storage-paths.md +107 -0
  18. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/types.md +83 -0
  19. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/usage.md +83 -128
  20. package/claude/references/sd-simplysm14/capacitor-plugin-usb-storage/usage.md +99 -1
  21. package/claude/references/sd-simplysm14/core-node/docs/child-process.md +182 -0
  22. package/claude/references/sd-simplysm14/core-node/docs/features.md +1 -1
  23. package/claude/references/sd-simplysm14/core-node/docs/file-system.md +509 -0
  24. package/claude/references/sd-simplysm14/core-node/docs/file-watching.md +139 -0
  25. package/claude/references/sd-simplysm14/core-node/docs/logging.md +180 -0
  26. package/claude/references/sd-simplysm14/core-node/docs/path.md +176 -0
  27. package/claude/references/sd-simplysm14/core-node/docs/worker-threads.md +334 -0
  28. package/claude/references/sd-simplysm14/core-node/usage.md +192 -96
  29. package/claude/references/sd-simplysm14/excel/docs/core-classes.md +33 -14
  30. package/claude/references/sd-simplysm14/excel/usage.md +47 -45
  31. package/claude/references/sd-simplysm14/lint/usage.md +3 -2
  32. package/claude/references/sd-simplysm14/orm-common/docs/queryable-executable.md +30 -35
  33. package/claude/references/sd-simplysm14/orm-common/usage.md +9 -8
  34. package/claude/references/sd-simplysm14/sd-claude/docs/assets.md +43 -34
  35. package/claude/references/sd-simplysm14/sd-claude/docs/cli.md +1 -1
  36. package/claude/references/sd-simplysm14/sd-claude/docs/hooks.md +20 -2
  37. package/claude/references/sd-simplysm14/sd-claude/docs/scripts.md +5 -18
  38. package/claude/references/sd-simplysm14/sd-claude/usage.md +6 -5
  39. package/claude/references/sd-simplysm14/sd-cli/usage.md +176 -1
  40. package/claude/references/sd-simplysm14/service-client/usage.md +126 -61
  41. package/claude/references/sd-simplysm14/service-common/usage.md +28 -28
  42. package/claude/references/sd-simplysm14/storage/usage.md +123 -30
  43. package/claude/references/sd-testing.md +100 -4
  44. package/claude/rules/sd-claude-rules.md +19 -4
  45. package/claude/sd-check-write.py +1 -1
  46. package/claude/skills/sd-check/SKILL.md +7 -4
  47. package/claude/skills/sd-claude-docs/SKILL.md +7 -4
  48. package/claude/skills/sd-claude-docs/references/package-doc-gen.md +30 -7
  49. package/claude/skills/sd-commit/SKILL.md +2 -0
  50. package/claude/skills/sd-debug/SKILL.md +1 -1
  51. package/claude/skills/sd-deliverable/SKILL.md +2 -0
  52. package/claude/skills/sd-dev/SKILL.md +1 -1
  53. package/claude/skills/sd-doc-extract/SKILL.md +2 -0
  54. package/claude/{references/sd-debug.md → skills/sd-inner-debug/SKILL.md} +16 -20
  55. package/claude/{references/sd-review.md → skills/sd-inner-review/SKILL.md} +9 -4
  56. package/claude/skills/sd-issue/SKILL.md +2 -0
  57. package/claude/skills/sd-outlook/SKILL.md +2 -0
  58. package/claude/skills/sd-plan/SKILL.md +1 -1
  59. package/claude/skills/sd-prompt/SKILL.md +2 -2
  60. package/claude/skills/sd-refactor/SKILL.md +2 -2
  61. package/claude/skills/sd-review/SKILL.md +1 -1
  62. package/claude/skills/sd-tdd/SKILL.md +7 -7
  63. package/claude/skills/sd-use/SKILL.md +2 -0
  64. package/claude/skills/sd-wbs/SKILL.md +41 -18
  65. package/package.json +1 -1
  66. /package/claude/{rules → references}/sd-simplysm14.md +0 -0
  67. /package/claude/{references → rules}/sd-clarify.md +0 -0
@@ -10,154 +10,250 @@ npm install @simplysm/core-node
10
10
 
11
11
  ## API Overview
12
12
 
13
- ### Utilities (fsx)
13
+ ### File System (fsx)
14
14
 
15
- 파일 시스템 유틸리티. `import { fsx } from "@simplysm/core-node"` 형태로 사용한다.
15
+ 파일 시스템 작업을 위한 유틸리티 네임스페이스. 모든 함수는 동기/비동기 쌍으로 제공된다.
16
16
 
17
17
  | API | Type | Description |
18
18
  |-----|------|-------------|
19
- | `fsx.exists` | function | 파일/디렉토리 존재 여부 확인 (비동기) |
20
- | `fsx.existsSync` | function | 파일/디렉토리 존재 여부 확인 (동기) |
21
- | `fsx.mkdir` | function | 디렉토리 재귀 생성 (비동기) |
22
- | `fsx.mkdirSync` | function | 디렉토리 재귀 생성 (동기) |
23
- | `fsx.rm` | function | 파일/디렉토리 삭제, 최대 6회 재시도 (비동기) |
24
- | `fsx.rmSync` | function | 파일/디렉토리 삭제, 재시도 없음 (동기) |
25
- | `fsx.copy` | function | 파일/디렉토리 복사, filter 옵션 지원 (비동기) |
26
- | `fsx.copySync` | function | 파일/디렉토리 복사, filter 옵션 지원 (동기) |
27
- | `fsx.read` | function | 파일을 UTF-8 문자열로 읽기 (비동기) |
28
- | `fsx.readSync` | function | 파일을 UTF-8 문자열로 읽기 (동기) |
29
- | `fsx.readBytes` | function | 파일을 Uint8Array로 읽기 (비동기) |
30
- | `fsx.readBytesSync` | function | 파일을 Uint8Array로 읽기 (동기) |
31
- | `fsx.readJson` | function | JSON 파일 읽기 (비동기) |
32
- | `fsx.readJsonSync` | function | JSON 파일 읽기 (동기) |
33
- | `fsx.write` | function | 파일 쓰기, 상위 디렉토리 자동 생성 (비동기) |
34
- | `fsx.writeSync` | function | 파일 쓰기, 상위 디렉토리 자동 생성 (동기) |
35
- | `fsx.writeJson` | function | JSON 파일 쓰기 (비동기) |
36
- | `fsx.writeJsonSync` | function | JSON 파일 쓰기 (동기) |
37
- | `fsx.readdir` | function | 디렉토리 내용 읽기 (비동기) |
38
- | `fsx.readdirSync` | function | 디렉토리 내용 읽기 (동기) |
39
- | `fsx.stat` | function | 파일 정보 조회, 심볼릭 링크 따라감 (비동기) |
40
- | `fsx.statSync` | function | 파일 정보 조회, 심볼릭 링크 따라감 (동기) |
41
- | `fsx.lstat` | function | 파일 정보 조회, 심볼릭 링크 따라가지 않음 (비동기) |
42
- | `fsx.lstatSync` | function | 파일 정보 조회, 심볼릭 링크 따라가지 않음 (동기) |
43
- | `fsx.glob` | function | glob 패턴으로 파일 검색, 절대 경로 반환 (비동기) |
44
- | `fsx.globSync` | function | glob 패턴으로 파일 검색, 절대 경로 반환 (동기) |
45
- | `fsx.clearEmptyDirectory` | function | 빈 디렉토리 재귀 삭제 (비동기) |
46
- | `fsx.findAllParentChildPaths` | function | 부모 디렉토리 순회하며 glob 매칭 경로 수집 (비동기) |
47
- | `fsx.findAllParentChildPathsSync` | function | 부모 디렉토리 순회하며 glob 매칭 경로 수집 (동기) |
48
-
49
- → See [docs/utilities-fsx.md](./docs/utilities-fsx.md) for details.
50
-
51
- ### Utilities (cpx)
52
-
53
- 자식 프로세스 실행 유틸리티. `import { cpx } from "@simplysm/core-node"` 형태로 사용한다.
19
+ | `exists` | function | 파일 또는 디렉토리가 존재하는지 확인 (비동기) |
20
+ | `existsSync` | function | 파일 또는 디렉토리가 존재하는지 확인 (동기) |
21
+ | `mkdir` | function | 디렉토리를 생성 (재귀적, 비동기) |
22
+ | `mkdirSync` | function | 디렉토리를 생성 (재귀적, 동기) |
23
+ | `rm` | function | 파일/디렉토리 삭제, 파일 잠금 시 최대 6회 재시도 (비동기) |
24
+ | `rmSync` | function | 파일/디렉토리 삭제 (동기, 재시도 없음) |
25
+ | `copy` | function | 파일/디렉토리 복사, 필터 옵션 지원 (비동기) |
26
+ | `copySync` | function | 파일/디렉토리 복사, 필터 옵션 지원 (동기) |
27
+ | `read` | function | 파일을 UTF-8 문자열로 읽음 (비동기) |
28
+ | `readSync` | function | 파일을 UTF-8 문자열로 읽음 (동기) |
29
+ | `readBytes` | function | 파일을 Uint8Array로 읽음 (비동기) |
30
+ | `readBytesSync` | function | 파일을 Uint8Array로 읽음 (동기) |
31
+ | `readJson` | function | JSON 파일 읽음 (비동기) |
32
+ | `readJsonSync` | function | JSON 파일 읽음 (동기) |
33
+ | `write` | function | 파일에 데이터 쓰기, 상위 디렉토리 자동 생성 (비동기) |
34
+ | `writeSync` | function | 파일에 데이터 쓰기, 상위 디렉토리 자동 생성 (동기) |
35
+ | `writeJson` | function | JSON 파일에 데이터 쓰기 (비동기) |
36
+ | `writeJsonSync` | function | JSON 파일에 데이터 쓰기 (동기) |
37
+ | `readdir` | function | 디렉토리 내용 읽기 (비동기) |
38
+ | `readdirSync` | function | 디렉토리 내용 읽기 (동기) |
39
+ | `stat` | function | 파일/디렉토리 정보 조회, 심볼릭 링크 따라감 (비동기) |
40
+ | `statSync` | function | 파일/디렉토리 정보 조회, 심볼릭 링크 따라감 (동기) |
41
+ | `lstat` | function | 파일/디렉토리 정보 조회, 심볼릭 링크 따라가지 않음 (비동기) |
42
+ | `lstatSync` | function | 파일/디렉토리 정보 조회, 심볼릭 링크 따라가지 않음 (동기) |
43
+ | `glob` | function | Glob 패턴으로 파일 검색 (비동기) |
44
+ | `globSync` | function | Glob 패턴으로 파일 검색 (동기) |
45
+ | `clearEmptyDirectory` | function | 빈 디렉토리 재귀적 삭제 |
46
+ | `findAllParentChildPathsSync` | function | 부모 디렉토리에서 특정 파일 검색 (동기) |
47
+ | `findAllParentChildPaths` | function | 부모 디렉토리에서 특정 파일 검색 (비동기) |
48
+
49
+ → See [docs/file-system.md](./docs/file-system.md) for details.
50
+
51
+ ### Child Process (cpx)
52
+
53
+ 자식 프로세스 실행 인코딩 감지.
54
54
 
55
55
  | API | Type | Description |
56
56
  |-----|------|-------------|
57
- | `cpx.spawn` | function | 비동기 자식 프로세스 실행, SpawnProcess 반환 |
58
- | `cpx.spawnSync` | function | 동기 자식 프로세스 실행, SpawnResult 반환 |
59
- | `cpx.SpawnProcess` | class | spawn()의 반환 타입. PromiseLike + kill() 지원 |
60
- | `cpx.SpawnResult` | interface | 프로세스 실행 결과 (stdout, stderr, exitCode) |
61
- | `cpx.getSystemEncoding` | function | 시스템 인코딩 감지 (Windows: chcp, Linux: LANG 환경변수) |
62
- | `cpx.codePageToEncoding` | function | Windows 코드 페이지 번호를 인코딩 이름으로 변환 |
63
- | `cpx.resetEncodingCache` | function | 캐시된 시스템 인코딩 초기화 |
64
- | `cpx.decodeBytes` | function | Uint8Array를 시스템 인코딩으로 디코딩 |
65
- | `cpx.resolveStdioPipe` | function | stdio 옵션에서 stdout/stderr pipe 여부 추출 |
57
+ | `spawn` | function | 자식 프로세스 실행, Promise 기반, 실시간 제어 가능 |
58
+ | `spawnSync` | function | 자식 프로세스 동기 실행 |
59
+ | `getSystemEncoding` | function | 시스템 기본 인코딩 감지 |
60
+ | `codePageToEncoding` | function | Windows 코드 페이지를 인코딩명으로 변환 |
61
+ | `decodeBytes` | function | Uint8Array를 문자열로 디코딩 |
62
+ | `resolveStdioPipe` | function | stdio 옵션에서 pipe 여부 판단 |
63
+ | `resetEncodingCache` | function | 인코딩 캐시 초기화 |
64
+ | `SpawnProcess` | class | spawn() 반환 타입, PromiseLike 구현 |
65
+ | `SpawnResult` | interface | spawn/spawnSync 결과 타입 |
66
66
 
67
- → See [docs/utilities-cpx.md](./docs/utilities-cpx.md) for details.
67
+ → See [docs/child-process.md](./docs/child-process.md) for details.
68
68
 
69
- ### Utilities (pathx)
69
+ ### Path (pathx)
70
70
 
71
- 경로 유틸리티. `import { pathx } from "@simplysm/core-node"` 형태로 사용한다.
71
+ 경로 처리 PosixPath 브랜드 타입.
72
72
 
73
73
  | API | Type | Description |
74
74
  |-----|------|-------------|
75
- | `pathx.PosixPath` | type | POSIX 슬래시 경로임을 타입 수준에서 보장하는 브랜드 타입 |
76
- | `pathx.posix` | function | 백슬래시를 슬래시로 변환하여 PosixPath 반환 |
77
- | `pathx.posixResolve` | function | 절대 경로 resolve 후 POSIX 스타일로 변환 |
78
- | `pathx.changeFileDirectory` | function | 파일 경로의 디렉토리 부분을 변경 |
79
- | `pathx.basenameWithoutExt` | function | 확장자를 제외한 파일명 반환 |
80
- | `pathx.isChildPath` | function | childPath가 parentPath의 하위 경로인지 확인 |
81
- | `pathx.filterByTargets` | function | 대상 경로 목록으로 파일 목록 필터링 |
75
+ | `posix` | function | 경로를 POSIX 스타일(슬래시)로 변환 |
76
+ | `posixResolve` | function | 경로를 절대 경로로 resolve한 POSIX 스타일로 변환 |
77
+ | `changeFileDirectory` | function | 파일의 디렉토리를 변경 |
78
+ | `basenameWithoutExt` | function | 확장자를 제외한 파일명 반환 |
79
+ | `isChildPath` | function | 자식 경로 여부 확인 |
80
+ | `filterByTargets` | function | 대상 경로 목록에 기반한 파일 필터링 |
81
+ | `PosixPath` | type | POSIX 스타일 경로 브랜드 타입 |
82
82
 
83
- → See [docs/utilities-pathx.md](./docs/utilities-pathx.md) for details.
83
+ → See [docs/path.md](./docs/path.md) for details.
84
84
 
85
- ### Features
85
+ ### File Watching (FsWatcher)
86
+
87
+ Chokidar 기반 파일 시스템 감시 클래스.
86
88
 
87
89
  | API | Type | Description |
88
90
  |-----|------|-------------|
89
- | `FsWatcher` | class | Chokidar 기반 파일 시스템 감시 래퍼. 이벤트 병합, EPERM 자동 복구 |
90
- | `FsWatcherEvent` | type | 파일 변경 이벤트 타입 (`"add" \| "addDir" \| "change" \| "unlink" \| "unlinkDir"`) |
91
+ | `FsWatcher` | class | 파일 시스템 감시, 이벤트 병합, 자동 복구 |
92
+ | `FsWatcherEvent` | type | 감시 이벤트 타입: "add" \| "addDir" \| "change" \| "unlink" \| "unlinkDir" |
91
93
  | `FsWatcherChangeInfo` | interface | 파일 변경 정보 (event + path) |
92
- | `PrettyReporter` | class | 터미널 출력용 consola reporter (아이콘, 색상, 에러 스택 포맷팅) |
93
- | `createFileReporter` | function | 파일 기반 consola reporter 생성 (JSON 라인, 날짜별 로테이션, 크기 제한) |
94
- | `FileReporterOptions` | interface | createFileReporter 옵션 (maxSize, maxDays) |
95
- | `withMaxLevel` | function | consola reporter를 지정된 로그 레벨 이하로 제한하는 래퍼 |
96
- | `setupConsola` | function | 환경에 따라 consola reporter를 자동 구성 |
97
- | `SetupConsolaOptions` | interface | setupConsola 옵션 (cli 모드 여부) |
98
94
 
99
- → See [docs/features.md](./docs/features.md) for details.
95
+ → See [docs/file-watching.md](./docs/file-watching.md) for details.
96
+
97
+ ### Logging (consola)
98
+
99
+ Consola 로깅 설정 및 reporter.
100
+
101
+ | API | Type | Description |
102
+ |-----|------|-------------|
103
+ | `setupConsola` | function | 환경별 자동 consola 구성 |
104
+ | `withMaxLevel` | function | 로그 레벨 상한선을 설정한 reporter 래퍼 |
105
+ | `PrettyReporter` | class | 터미널 출력용 consola reporter |
106
+ | `createFileReporter` | function | 파일 기반 consola reporter 생성 |
107
+
108
+ → See [docs/logging.md](./docs/logging.md) for details.
109
+
110
+ ### Worker Threads
100
111
 
101
- ### Worker
112
+ 타입 안전한 Worker thread 래퍼.
102
113
 
103
114
  | API | Type | Description |
104
115
  |-----|------|-------------|
105
- | `Worker` | const (object) | 타입 안전한 Worker Proxy 생성 팩토리 (`Worker.create()`) |
106
- | `createWorker` | function | Worker thread 측에서 메서드와 이벤트를 등록하는 팩토리 |
107
- | `WorkerModule` | interface | createWorker가 반환하는 워커 모듈의 타입 구조 |
108
- | `PromisifyMethods` | type | 메서드 반환값을 Promise로 감싸는 매핑 타입 |
109
- | `WorkerProxy` | type | Worker.create()가 반환하는 프록시 타입 (메서드 + on/off + terminate) |
110
- | `WorkerRequest` | interface | 내부 워커 요청 메시지 |
111
- | `WorkerResponse` | type | 내부 워커 응답 메시지 (discriminated union: return \| error \| event \| log) |
116
+ | `Worker` | class | Worker thread 프록시 생성 메서드 호출 |
117
+ | `createWorker` | function | 워커 측에서 호출하는 워커 모듈 생성 함수 |
118
+ | `WorkerModule` | interface | 워커 모듈의 타입 구조 |
119
+ | `WorkerProxy` | type | Worker.create() 반환 프록시 타입 |
120
+ | `WorkerRequest` | interface | 워커 요청 메시지 타입 |
121
+ | `WorkerResponse` | type | 워커 응답 메시지 타입 |
122
+ | `PromisifyMethods` | type | 메서드를 Promise 버전으로 변환하는 매핑 타입 |
112
123
 
113
- → See [docs/worker.md](./docs/worker.md) for details.
124
+ → See [docs/worker-threads.md](./docs/worker-threads.md) for details.
114
125
 
115
126
  ## Usage Examples
116
127
 
117
- ### 파일 시스템 조작
128
+ ### File System Operations
118
129
 
119
130
  ```typescript
120
131
  import { fsx } from "@simplysm/core-node";
121
132
 
133
+ // 파일 존재 확인
134
+ const exists = await fsx.exists("/path/to/file.txt");
135
+
122
136
  // 파일 읽기/쓰기
123
- await fsx.write("/path/to/file.txt", "content");
124
- const text = await fsx.read("/path/to/file.txt");
137
+ const content = await fsx.read("/path/to/file.txt");
138
+ await fsx.write("/path/to/new-file.txt", "Hello, World!");
139
+
140
+ // JSON 파일 읽기/쓰기
141
+ const data = await fsx.readJson<{ name: string }>("/path/to/config.json");
142
+ await fsx.writeJson("/path/to/config.json", { name: "test" });
125
143
 
126
- // JSON 읽기/쓰기
127
- await fsx.writeJson("/path/to/config.json", { key: "value" }, { space: 2 });
128
- const config = await fsx.readJson<{ key: string }>("/path/to/config.json");
144
+ // 파일 복사 (필터 적용)
145
+ await fsx.copy("/src/dir", "/dst/dir", (filePath) => {
146
+ return !filePath.includes("node_modules");
147
+ });
129
148
 
130
- // glob 검색
131
- const tsFiles = await fsx.glob("/project/src/**/*.ts");
149
+ // Glob 검색
150
+ const tsFiles = await fsx.glob("src/**/*.ts");
132
151
  ```
133
152
 
134
- ### 자식 프로세스 실행
153
+ ### Child Process Execution
135
154
 
136
155
  ```typescript
137
156
  import { cpx } from "@simplysm/core-node";
138
157
 
139
- const result = await cpx.spawn("git", ["status"], { cwd: "/project" });
140
- // result: { stdout: string, stderr: string, exitCode: number }
158
+ // 기본 실행
159
+ const result = await cpx.spawn("npm", ["list"], { cwd: "/project" });
160
+ console.log(result.stdout);
161
+
162
+ // 실시간 출력
163
+ await cpx.spawn("npm", ["run", "build"], { stdio: "inherit" });
164
+
165
+ // 오류 무시
166
+ const result = await cpx.spawn("cmd", ["nonexistent"], { reject: false });
167
+ // result.exitCode가 0이 아니어도 throw되지 않음
168
+
169
+ // 동기 실행
170
+ const syncResult = cpx.spawnSync("node", ["--version"]);
171
+ console.log(syncResult.stdout);
172
+ ```
173
+
174
+ ### Path Utilities
175
+
176
+ ```typescript
177
+ import { pathx } from "@simplysm/core-node";
178
+
179
+ // POSIX 경로 변환
180
+ const posixPath = pathx.posix("C:\\Users\\test");
181
+ console.log(posixPath); // "C:/Users/test"
182
+
183
+ // 절대 경로 resolve + POSIX
184
+ const absPath = pathx.posixResolve("./relative", "path");
141
185
 
142
- // 실행 종료 가능
143
- const proc = cpx.spawn("long-running-cmd", []);
144
- proc.kill();
186
+ // 자식 경로 확인
187
+ const isChild = pathx.isChildPath("/a/b/c", "/a/b"); // true
188
+
189
+ // 경로 필터링
190
+ const filtered = pathx.filterByTargets(
191
+ ["/proj/src/a.ts", "/proj/tests/b.ts"],
192
+ ["src"],
193
+ "/proj"
194
+ );
195
+ // ["/proj/src/a.ts"]
196
+ ```
197
+
198
+ ### File Watching
199
+
200
+ ```typescript
201
+ import { FsWatcher } from "@simplysm/core-node";
202
+
203
+ const watcher = await FsWatcher.watch(["src/**/*.ts"]);
204
+
205
+ watcher.onChange({ delay: 300 }, (changes) => {
206
+ for (const { event, path } of changes) {
207
+ console.log(`${event}: ${path}`);
208
+ }
209
+ });
210
+
211
+ // 파일 감시 종료
212
+ await watcher.close();
145
213
  ```
146
214
 
147
- ### Worker thread
215
+ ### Logging Setup
148
216
 
149
217
  ```typescript
150
- // worker.ts
218
+ import { setupConsola } from "@simplysm/core-node";
219
+
220
+ // 환경별 자동 구성
221
+ setupConsola();
222
+
223
+ // CLI 모드 (프로덕션에서도 file + pretty reporter 사용)
224
+ setupConsola({ cli: true });
225
+ ```
226
+
227
+ ### Worker Threads
228
+
229
+ ```typescript
230
+ // worker.ts (워커 파일)
151
231
  import { createWorker } from "@simplysm/core-node";
152
232
 
153
- const methods = { add: (a: number, b: number) => a + b };
154
- export default createWorker(methods);
233
+ interface MyEvents {
234
+ progress: number;
235
+ }
236
+
237
+ const methods = {
238
+ add: (a: number, b: number) => a + b,
239
+ multiply: (a: number, b: number) => a * b,
240
+ };
155
241
 
156
- // main.ts
242
+ const sender = createWorker<typeof methods, MyEvents>(methods);
243
+ export default sender;
244
+
245
+ // main.ts (메인 파일)
157
246
  import { Worker } from "@simplysm/core-node";
158
247
  import type * as MyWorker from "./worker";
159
248
 
160
249
  const worker = Worker.create<typeof MyWorker>("./worker.ts");
161
- const result = await worker.add(10, 20); // 30
250
+
251
+ const sum = await worker.add(10, 20); // 30
252
+ const product = await worker.multiply(5, 6); // 30
253
+
254
+ worker.on("progress", (value) => {
255
+ console.log(`Progress: ${value}%`);
256
+ });
257
+
162
258
  await worker.terminate();
163
259
  ```
@@ -63,7 +63,7 @@ ZIP 리더와 내부 캐시를 정리한다. 이미 닫힌 워크북에 대해
63
63
 
64
64
  ## `ExcelWorksheet`
65
65
 
66
- Excel 워크시트를 나타내는 클래스. 셀 접근, 행/열 복사, 데이터 테이블 처리, 이미지 삽입 기능을 제공한다.
66
+ Excel 워크시트를 나타내는 클래스. 셀 접근, 행/열 복사, 데이터 테이블 처리, 이미지 삽입, 뷰 설정 기능을 제공한다.
67
67
 
68
68
  ```typescript
69
69
  export class ExcelWorksheet {
@@ -90,7 +90,11 @@ export class ExcelWorksheet {
90
90
  async getCells(): Promise<ExcelCell[][]>;
91
91
 
92
92
  // Data
93
- async getDataTable(opt?: { ... }): Promise<Record<string, ExcelValueType>[]>;
93
+ async getDataTable(opt?: {
94
+ headerRowIndex?: number;
95
+ checkEndColIndex?: number;
96
+ usableHeaderNameFn?: (headerName: string) => boolean;
97
+ }): Promise<Record<string, ExcelValueType>[]>;
94
98
  async setDataMatrix(matrix: ExcelValueType[][]): Promise<void>;
95
99
  async setRecords(records: Record<string, ExcelValueType>[]): Promise<void>;
96
100
 
@@ -99,7 +103,12 @@ export class ExcelWorksheet {
99
103
  async freezeAt(point: { r?: number; c?: number }): Promise<void>;
100
104
 
101
105
  // Image
102
- async addImage(opts: { ... }): Promise<void>;
106
+ async addImage(opts: {
107
+ bytes: Bytes;
108
+ ext: string;
109
+ from: { r: number; c: number; rOff?: number | string; cOff?: number | string };
110
+ to?: { r: number; c: number; rOff?: number | string; cOff?: number | string };
111
+ }): Promise<void>;
103
112
  }
104
113
  ```
105
114
 
@@ -193,6 +202,10 @@ export class ExcelWorksheet {
193
202
  | `srcR` | `number` | 복사할 원본 행 인덱스 (0 기반) |
194
203
  | `targetR` | `number` | 삽입할 대상 행 인덱스 (0 기반) |
195
204
 
205
+ **병합 셀 처리:**
206
+ - 삽입 지점을 관통하는 다중행 병합은 자동으로 1행 확장됨
207
+ - 원본 행의 단일행 병합만 대상 행에 복사됨
208
+
196
209
  ### Range Methods
197
210
 
198
211
  #### `getRange()`
@@ -207,25 +220,27 @@ export class ExcelWorksheet {
207
220
 
208
221
  #### `getDataTable(opt?)`
209
222
 
210
- 워크시트 데이터를 테이블(레코드 배열)로 반환한다. 첫 번째 행(또는 `headerRowIndex`)을 헤더로 사용한다.
223
+ 워크시트 데이터를 테이블(레코드 배열)로 반환한다. 지정된 헤더 행(기본값: 첫 번째 행)을 기준으로 이하의 데이터를 읽는다.
211
224
 
212
225
  | Parameter | Type | Description |
213
226
  |-----------|------|-------------|
214
- | `opt.headerRowIndex` | `number \| undefined` | 헤더 행 인덱스 (기본값: 번째 행) |
215
- | `opt.checkEndColIndex` | `number \| undefined` | 데이터 끝을 판단할 열 인덱스. 이 열이 비어있으면 데이터가 끝난 것으로 판단한다 |
216
- | `opt.usableHeaderNameFn` | `(headerName: string) => boolean \| undefined` | 사용 가능한 헤더를 필터링하는 함수 |
227
+ | `opt.headerRowIndex` | `number \| undefined` | 헤더 행 인덱스 (기본값: 데이터 범위의 시작 행) |
228
+ | `opt.checkEndColIndex` | `number \| undefined` | 데이터 끝을 판단할 열 인덱스. 이 열이 비어있는 행을 만나면 데이터가 끝난 것으로 판단한다 |
229
+ | `opt.usableHeaderNameFn` | `(headerName: string) => boolean \| undefined` | 사용 가능한 헤더를 필터링하는 함수. 반환값이 `false`인 헤더는 제외된다 |
230
+
231
+ **반환값:** `Record<string, ExcelValueType>[]` - 헤더를 키로 하는 레코드 배열
217
232
 
218
233
  #### `setDataMatrix(matrix)`
219
234
 
220
- 2차원 배열 데이터를 워크시트에 쓴다.
235
+ 2차원 배열 데이터를 워크시트에 쓴다. (0, 0) 위치부터 시작하여 데이터를 기록한다.
221
236
 
222
237
  | Parameter | Type | Description |
223
238
  |-----------|------|-------------|
224
- | `matrix` | `ExcelValueType[][]` | 2차원 배열 데이터 (행 우선, 인덱스 0 첫 번째 행) |
239
+ | `matrix` | `ExcelValueType[][]` | 2차원 배열 데이터 (행 우선, `matrix[0]`이 첫 번째 행) |
225
240
 
226
241
  #### `setRecords(records)`
227
242
 
228
- 레코드 배열을 워크시트에 쓴다. 첫 번째 행에 헤더가 자동 생성되고, 이후 행에 데이터가 기록된다.
243
+ 레코드 배열을 워크시트에 쓴다. 첫 번째 행(r=0)에 헤더가 자동 생성되고, 이후 행(r=1...)에 데이터가 기록된다. 모든 레코드의 필드를 수집하여 헤더로 사용한다.
229
244
 
230
245
  | Parameter | Type | Description |
231
246
  |-----------|------|-------------|
@@ -254,14 +269,18 @@ export class ExcelWorksheet {
254
269
 
255
270
  #### `addImage(opts)`
256
271
 
257
- 워크시트에 이미지를 삽입한다.
272
+ 워크시트에 이미지를 삽입한다. 같은 시트의 첫 이미지 호출 시 `drawing1.xml` 생성, 이후 이미지는 동일 drawing에 추가된다.
258
273
 
259
274
  | Parameter | Type | Description |
260
275
  |-----------|------|-------------|
261
276
  | `opts.bytes` | `Bytes` | 이미지 바이너리 데이터 |
262
- | `opts.ext` | `string` | 이미지 확장자 (png, jpg ) |
263
- | `opts.from` | `{ r: number; c: number; rOff?: number \| string; cOff?: number \| string }` | 이미지 시작 위치 (0 기반 행/열 인덱스, rOff/cOff EMU 오프셋) |
264
- | `opts.to` | `{ r: number; c: number; rOff?: number \| string; cOff?: number \| string } \| undefined` | 이미지 끝 위치 (생략 시 from 위치에서 1행x1열 크기) |
277
+ | `opts.ext` | `string` | 이미지 확장자 (예: `"png"`, `"jpg"`, `"gif"`) |
278
+ | `opts.from` | `{ r: number; c: number; rOff?: number \| string; cOff?: number \| string }` | 이미지 시작 위치. `r`/`c`는 0 기반 행/열 인덱스, `rOff`/`cOff`는 선택적 EMU 오프셋 |
279
+ | `opts.to` | `{ r: number; c: number; rOff?: number \| string; cOff?: number \| string } \| undefined` | 이미지 끝 위치. 생략 시 기본값은 `{ r: from.r + 1, c: from.c + 1 }`이다 |
280
+
281
+ **이미지 파일 관리:**
282
+ - 이미지는 `xl/media/image1.ext`, `xl/media/image2.ext` 등으로 자동 관리됨
283
+ - 기존 파일명과 중복되지 않도록 인덱스 자동 증가
265
284
 
266
285
  ---
267
286
 
@@ -1,6 +1,6 @@
1
1
  # @simplysm/excel
2
2
 
3
- 심플리즘 패키지 - xlsx 파일 읽기/쓰기 라이브러리. DOM-independent (neutral) 환경에서 동작한다.
3
+ Excel 워크북(xlsx) 읽기/쓰기 라이브러리. DOM 의존성이 없어 Node.js와 브라우저 양쪽에서 동작하는 neutral 패키지다. Lazy Loading 아키텍처로 대용량 파일도 메모리 효율적으로 처리한다.
4
4
 
5
5
  ## Installation
6
6
 
@@ -14,65 +14,50 @@ npm install @simplysm/excel
14
14
 
15
15
  | API | Type | Description |
16
16
  |-----|------|-------------|
17
- | `ExcelWorkbook` | class | Excel 워크북 처리 클래스. ZIP 리소스를 관리하며, 워크시트 생성/조회/내보내기를 제공한다 |
18
- | `ExcelWorksheet` | class | Excel 워크시트. 셀/행/열 접근, 복사, 데이터 테이블, 이미지 삽입 기능을 제공한다 |
19
- | `ExcelCell` | class | Excel 셀. 읽기/쓰기, 수식, 스타일, 셀 병합 기능을 제공한다 |
20
- | `ExcelRow` | class | Excel 행. 셀 접근 기능을 제공한다 |
21
- | `ExcelCol` | class | Excel 열. 셀 접근 열 너비 설정 기능을 제공한다 |
17
+ | `ExcelWorkbook` | class | Excel 워크북 진입점. 워크시트 생성/조회, 바이트 내보내기, ZIP 리소스 관리 |
18
+ | `ExcelWorksheet` | class | 워크시트. 셀/행/열 접근, 행/셀 복사, 데이터 테이블 읽기, 이미지 삽입, 시트명 변경 |
19
+ | `ExcelCell` | class | 개별 셀. 값/수식 읽기/쓰기, 스타일 설정, 셀 병합 |
20
+ | `ExcelRow` | class | 워크시트 행. 셀 접근, 전체 셀 조회 |
21
+ | `ExcelCol` | class | 워크시트 열. 셀 접근, 열 너비 설정 |
22
22
 
23
- -> See [docs/core-classes.md](./docs/core-classes.md) for details.
23
+ See [docs/core-classes.md](./docs/core-classes.md) for details.
24
24
 
25
25
  ### Wrapper
26
26
 
27
27
  | API | Type | Description |
28
28
  |-----|------|-------------|
29
- | `ExcelWrapper` | class | Zod 스키마 기반 타입 안전한 Excel 읽기/쓰기 래퍼 |
29
+ | `ExcelWrapper` | class | Zod 스키마 기반 타입 안전한 Excel 읽기/쓰기. 헤더 자동 생성, 유효성 검사, 필수 필드 강조 |
30
30
 
31
- -> See [docs/wrapper.md](./docs/wrapper.md) for details.
31
+ See [docs/wrapper.md](./docs/wrapper.md) for details.
32
32
 
33
33
  ### Utilities
34
34
 
35
35
  | API | Type | Description |
36
36
  |-----|------|-------------|
37
- | `ExcelUtils` | class | 셀 주소 변환, 날짜/숫자 변환, 숫자 형식 처리 정적 메서드 모음 |
37
+ | `ExcelUtils` | class | 셀 주소 변환 (좌표↔문자열), 날짜↔숫자 변환, 숫자 형식 매핑 (정적 메서드) |
38
38
 
39
- -> See [docs/utilities.md](./docs/utilities.md) for details.
39
+ See [docs/utilities.md](./docs/utilities.md) for details.
40
40
 
41
41
  ### Types
42
42
 
43
43
  | API | Type | Description |
44
44
  |-----|------|-------------|
45
- | `ExcelValueType` | type | 셀 값 타입 (`number \| string \| DateOnly \| DateTime \| Time \| boolean \| undefined`) |
46
- | `ExcelNumberFormat` | type | 숫자 형식 이름 (`"number" \| "string" \| "DateOnly" \| "DateTime" \| "Time"`) |
47
- | `ExcelCellType` | type | Excel 타입 (`"s" \| "b" \| "str" \| "n" \| "inlineStr" \| "e"`) |
45
+ | `ExcelValueType` | type | 셀 값 타입: number, string, DateOnly, DateTime, Time, boolean, undefined |
46
+ | `ExcelNumberFormat` | type | 숫자 형식 이름: "number", "string", "DateOnly", "DateTime", "Time" |
47
+ | `ExcelCellType` | type | 셀 타입: "s"(공유문자열), "b"(boolean), "str"(수식문자열), "n"(숫자), "inlineStr", "e"(에러) |
48
48
  | `ExcelAddressPoint` | interface | 셀 좌표 (0 기반 r, c) |
49
- | `ExcelAddressRangePoint` | interface | 셀 범위 좌표 (s, e) |
49
+ | `ExcelAddressRangePoint` | interface | 셀 범위 좌표 (시작점 s, 끝점 e) |
50
50
  | `ExcelStyleOptions` | interface | 셀 스타일 옵션 (배경색, 테두리, 정렬, 숫자 형식) |
51
- | `ExcelBorderPosition` | type | 테두리 위치 (`"left" \| "right" \| "top" \| "bottom"`) |
52
- | `ExcelHorizontalAlign` | type | 가로 정렬 (`"center" \| "left" \| "right"`) |
53
- | `ExcelVerticalAlign` | type | 세로 정렬 (`"center" \| "top" \| "bottom"`) |
51
+ | `ExcelBorderPosition` | type | 테두리 위치: "left", "right", "top", "bottom" |
52
+ | `ExcelHorizontalAlign` | type | 가로 정렬: "left", "center", "right" |
53
+ | `ExcelVerticalAlign` | type | 세로 정렬: "top", "center", "bottom" |
54
54
  | `ExcelXml` | interface | XML 처리 클래스가 구현하는 인터페이스 (내부용) |
55
- | `ExcelXmlContentTypeData` | interface | `[Content_Types].xml` 데이터 구조 (내부용) |
56
- | `ExcelXmlRelationshipData` | interface | `*.rels` 데이터 구조 (내부용) |
57
- | `ExcelRelationshipData` | interface | 개별 Relationship 엔트리 데이터 (내부용) |
58
- | `ExcelXmlWorkbookData` | interface | `workbook.xml` 데이터 구조 (내부용) |
59
- | `ExcelXmlWorksheetData` | interface | `worksheet*.xml` 데이터 구조 (내부용) |
60
- | `ExcelRowData` | interface | 행 XML 데이터 (내부용) |
61
- | `ExcelCellData` | interface | 셀 XML 데이터 (내부용) |
62
- | `ExcelXmlDrawingData` | interface | `drawing*.xml` 데이터 구조 (내부용) |
63
- | `ExcelXmlSharedStringData` | interface | `sharedStrings.xml` 데이터 구조 (내부용) |
64
- | `ExcelXmlSharedStringDataSi` | type | SharedString 개별 항목 union 타입 (내부용) |
65
- | `ExcelXmlSharedStringDataText` | type | SharedString 텍스트 데이터 (내부용) |
66
- | `ExcelXmlStyleData` | interface | `styles.xml` 데이터 구조 (내부용) |
67
- | `ExcelXmlStyleDataXf` | interface | 셀 서식(xf) 데이터 (내부용) |
68
- | `ExcelXmlStyleDataFill` | interface | 채우기 스타일 데이터 (내부용) |
69
- | `ExcelXmlStyleDataBorder` | interface | 테두리 스타일 데이터 (내부용) |
70
-
71
- -> See [docs/types.md](./docs/types.md) for details.
55
+
56
+ See [docs/types.md](./docs/types.md) for details.
72
57
 
73
58
  ## Usage Examples
74
59
 
75
- ### 워크북 생성 및 셀 값 쓰기
60
+ ### Excel 파일 생성 및 저장
76
61
 
77
62
  ```typescript
78
63
  import { ExcelWorkbook } from "@simplysm/excel";
@@ -80,32 +65,44 @@ import { ExcelWorkbook } from "@simplysm/excel";
80
65
  const wb = new ExcelWorkbook();
81
66
  try {
82
67
  const ws = await wb.addWorksheet("Sheet1");
68
+
69
+ // 헤더 행
83
70
  await ws.cell(0, 0).setValue("이름");
84
71
  await ws.cell(0, 1).setValue("나이");
85
- await ws.cell(1, 0).setValue("홍길동");
72
+
73
+ // 데이터 행
74
+ await ws.cell(1, 0).setValue("김철수");
86
75
  await ws.cell(1, 1).setValue(30);
76
+
87
77
  const bytes = await wb.toBytes();
78
+ // 파일 저장 또는 전송
88
79
  } finally {
89
80
  await wb.close();
90
81
  }
91
82
  ```
92
83
 
93
- ### 기존 파일 읽기
84
+ ### 기존 Excel 파일 읽기
94
85
 
95
86
  ```typescript
96
87
  import { ExcelWorkbook } from "@simplysm/excel";
97
88
 
98
- const wb = new ExcelWorkbook(fileBytes);
89
+ const bytes = /* 파일 바이트 배열 */;
90
+ const wb = new ExcelWorkbook(bytes);
99
91
  try {
92
+ // 시트명 또는 인덱스(0 기반)로 조회
100
93
  const ws = await wb.getWorksheet(0);
94
+
95
+ // 개별 셀 읽기
101
96
  const value = await ws.cell(0, 0).getValue();
102
- const dataTable = await ws.getDataTable();
97
+
98
+ // 전체 데이터 테이블 읽기 (첫 행이 헤더)
99
+ const table = await ws.getDataTable();
103
100
  } finally {
104
101
  await wb.close();
105
102
  }
106
103
  ```
107
104
 
108
- ### Zod 스키마 기반 래퍼 사용
105
+ ### Zod 스키마 기반 타입 안전한 작업
109
106
 
110
107
  ```typescript
111
108
  import { ExcelWrapper } from "@simplysm/excel";
@@ -119,14 +116,19 @@ const schema = z.object({
119
116
 
120
117
  const wrapper = new ExcelWrapper(schema);
121
118
 
122
- // 쓰기
123
- const wb = await wrapper.write("Sheet1", records);
119
+ // 레코드 배열을 Excel로 쓰기
120
+ const records = [
121
+ { name: "김철수", age: 30, email: "kim@example.com" },
122
+ { name: "이영희", age: 28 },
123
+ ];
124
+ const wb = await wrapper.write("사람", records);
124
125
  try {
125
126
  const bytes = await wb.toBytes();
126
127
  } finally {
127
128
  await wb.close();
128
129
  }
129
130
 
130
- // 읽기
131
- const records = await wrapper.read(fileBytes, "Sheet1");
131
+ // Excel 파일을 레코드 배열로 읽기 (유효성 검사 포함)
132
+ const bytes = /* 파일 바이트 배열 */;
133
+ const data = await wrapper.read(bytes, "사람");
132
134
  ```