@simplysm/sd-claude 14.0.81 → 14.0.83

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 (87) hide show
  1. package/claude/references/sd-requirement-source-handling.md +20 -20
  2. package/claude/references/sd-simplysm14/README.md +13 -13
  3. package/claude/references/sd-simplysm14/manuals/client-component.md +92 -92
  4. package/claude/references/sd-simplysm14/manuals/client-crud.md +11 -11
  5. package/claude/references/sd-simplysm14/manuals/client-demo.md +28 -28
  6. package/claude/references/sd-simplysm14/manuals/client-rules.md +1 -1
  7. package/claude/references/sd-simplysm14/manuals/client-setup.md +21 -21
  8. package/claude/references/sd-simplysm14/manuals/client-tab.md +3 -3
  9. package/claude/references/sd-simplysm14/manuals/logging.md +15 -15
  10. package/claude/references/sd-simplysm14/manuals/orm-union.md +6 -6
  11. package/claude/references/sd-simplysm14/manuals/orm.md +19 -19
  12. package/claude/references/sd-simplysm14/manuals/test.md +33 -33
  13. package/claude/rules/sd-base-rules.md +44 -43
  14. package/claude/rules/sd-design-rules.md +18 -18
  15. package/claude/skills/sd-commit/SKILL.md +10 -10
  16. package/claude/skills/sd-config/SKILL.md +2 -2
  17. package/claude/skills/sd-demo/SKILL.md +45 -45
  18. package/claude/skills/sd-dev/SKILL.md +15 -15
  19. package/claude/skills/sd-docs/SKILL.md +7 -7
  20. package/claude/skills/sd-docs/references/subagent-prompt.md +33 -33
  21. package/claude/skills/sd-impl/SKILL.md +60 -60
  22. package/claude/skills/sd-review/SKILL.md +9 -9
  23. package/claude/skills/sd-skill/SKILL.md +74 -74
  24. package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +1 -1
  25. package/claude/skills/sd-spec/SKILL.md +355 -319
  26. package/claude/skills/sd-spec/references/example-spec.md +104 -104
  27. package/claude/skills/sd-unpack/SKILL.md +34 -34
  28. package/claude/skills/sd-use/SKILL.md +4 -4
  29. package/package.json +1 -1
  30. package/claude/references/sd-simplysm14/apis/angular/README.md +0 -37
  31. package/claude/references/sd-simplysm14/apis/angular/app-structure.md +0 -92
  32. package/claude/references/sd-simplysm14/apis/angular/buttons.md +0 -88
  33. package/claude/references/sd-simplysm14/apis/angular/crud.md +0 -100
  34. package/claude/references/sd-simplysm14/apis/angular/forms.md +0 -200
  35. package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +0 -231
  36. package/claude/references/sd-simplysm14/apis/angular/kanban.md +0 -80
  37. package/claude/references/sd-simplysm14/apis/angular/layout.md +0 -92
  38. package/claude/references/sd-simplysm14/apis/angular/modal.md +0 -115
  39. package/claude/references/sd-simplysm14/apis/angular/routing.md +0 -107
  40. package/claude/references/sd-simplysm14/apis/angular/select-dropdown.md +0 -35
  41. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +0 -82
  42. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +0 -134
  43. package/claude/references/sd-simplysm14/apis/angular/sheet.md +0 -127
  44. package/claude/references/sd-simplysm14/apis/angular/toast.md +0 -97
  45. package/claude/references/sd-simplysm14/apis/angular/visual.md +0 -167
  46. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +0 -79
  47. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +0 -83
  48. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +0 -91
  49. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +0 -49
  50. package/claude/references/sd-simplysm14/apis/core-browser/README.md +0 -143
  51. package/claude/references/sd-simplysm14/apis/core-common/README.md +0 -58
  52. package/claude/references/sd-simplysm14/apis/core-common/extensions.md +0 -88
  53. package/claude/references/sd-simplysm14/apis/core-common/features.md +0 -51
  54. package/claude/references/sd-simplysm14/apis/core-common/types.md +0 -88
  55. package/claude/references/sd-simplysm14/apis/core-common/utils.md +0 -189
  56. package/claude/references/sd-simplysm14/apis/core-node/README.md +0 -12
  57. package/claude/references/sd-simplysm14/apis/core-node/consola.md +0 -59
  58. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +0 -44
  59. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +0 -42
  60. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +0 -53
  61. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +0 -24
  62. package/claude/references/sd-simplysm14/apis/core-node/worker.md +0 -65
  63. package/claude/references/sd-simplysm14/apis/excel/README.md +0 -193
  64. package/claude/references/sd-simplysm14/apis/lint/README.md +0 -94
  65. package/claude/references/sd-simplysm14/apis/orm-common/README.md +0 -58
  66. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +0 -77
  67. package/claude/references/sd-simplysm14/apis/orm-common/executable.md +0 -20
  68. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +0 -92
  69. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +0 -98
  70. package/claude/references/sd-simplysm14/apis/orm-common/schema-builders.md +0 -128
  71. package/claude/references/sd-simplysm14/apis/orm-node/README.md +0 -69
  72. package/claude/references/sd-simplysm14/apis/sd-claude/README.md +0 -32
  73. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +0 -80
  74. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config.md +0 -155
  75. package/claude/references/sd-simplysm14/apis/service-client/README.md +0 -131
  76. package/claude/references/sd-simplysm14/apis/service-common/README.md +0 -29
  77. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +0 -63
  78. package/claude/references/sd-simplysm14/apis/service-common/messages.md +0 -56
  79. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +0 -64
  80. package/claude/references/sd-simplysm14/apis/service-common/service-types.md +0 -43
  81. package/claude/references/sd-simplysm14/apis/service-server/README.md +0 -13
  82. package/claude/references/sd-simplysm14/apis/service-server/auth.md +0 -39
  83. package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +0 -71
  84. package/claude/references/sd-simplysm14/apis/service-server/define-service.md +0 -55
  85. package/claude/references/sd-simplysm14/apis/service-server/internals.md +0 -82
  86. package/claude/references/sd-simplysm14/apis/service-server/server.md +0 -57
  87. package/claude/references/sd-simplysm14/apis/storage/README.md +0 -71
@@ -1,143 +0,0 @@
1
- # @simplysm/core-browser
2
-
3
- 브라우저 전용 보강 — `Element`/`HTMLElement` 프로토타입 확장(import 사이드 이펙트) + DOM/파일/네트워크/IndexedDB 헬퍼.
4
-
5
- > 이 패키지를 import 만 해도 `Element`/`HTMLElement` 프로토타입이 확장된다. SSR 환경에서는 import 자체를 피한다.
6
-
7
- ## 사용 트리거 인덱스
8
-
9
- DOM 탐색/가시성 — `Element` 확장:
10
-
11
- - **`findAll`** — `el` 하위에서 선택자 일치 요소 전부 배열로 받을 때.
12
- - **`findFirst`** — `el` 하위에서 선택자 일치 첫 요소만 받을 때 (`querySelector` 의 `null` 대신 `undefined`).
13
- - **`prependChild`** — 자식 목록의 맨 앞으로 삽입할 때.
14
- - **`getParents`** — 가까운 부모부터 위로 거슬러 올라가는 조상 배열이 필요할 때.
15
- - **`isOffsetElement`** — 어떤 요소가 자식 absolute 의 기준이 되는지(`position: relative/absolute/fixed/sticky`) 판정할 때.
16
- - **`isVisible`** — 화면에 실제로 보이는지(클라이언트 영역 + `visibility` + `opacity`) 판정할 때.
17
-
18
- 포커스/탭 이동 — `Element` 확장:
19
-
20
- - **`findTabbableParent`** — 현재 요소를 감싸는 가장 가까운 tabbable 부모를 찾을 때 (모달·툴팁의 포커스 트랩 호스트 추적).
21
- - **`findFirstTabbableChild`** — 컨테이너에 진입했을 때 처음 포커스할 자식을 찾을 때.
22
-
23
- 레이아웃/스크롤 — `HTMLElement` 확장:
24
-
25
- - **`repaint`** — 스타일 변경 후 즉시 동기 reflow 가 필요할 때.
26
- - **`getRelativeOffset`** — 드롭다운/팝업을 부모 기준 absolute 좌표로 띄울 때 (스크롤·border·transform 보정 포함).
27
- - **`scrollIntoViewIfNeeded`** — 고정 헤더/컬럼에 가려진 셀을 위/왼쪽으로만 보정 스크롤할 때.
28
-
29
- 클립보드/측정 헬퍼:
30
-
31
- - **`copyElement`** — `<el @copy>` 이벤트 핸들러로 내부 첫 input/textarea 값을 클립보드로 보낼 때.
32
- - **`pasteToElement`** — `<el @paste>` 이벤트 핸들러로 클립보드 값을 내부 첫 input/textarea 에 전체 교체할 때.
33
- - **`getBounds`** / **`ElementBounds`** — 다수 요소의 뷰포트 경계를 `IntersectionObserver` 로 한 번에 측정할 때 (입력 순서 유지·타임아웃 보장).
34
-
35
- 파일 다이얼로그/다운로드:
36
-
37
- - **`openFileDialog`** — 사용자에게 파일 선택 UI 를 띄워 `File[]` 을 받을 때 (취소·빈 선택은 `undefined`).
38
- - **`downloadBlob`** — 메모리 상의 `Blob` 을 사용자 다운로드로 흘려보낼 때 (파일명 sanitize).
39
-
40
- 진행률 fetch:
41
-
42
- - **`fetchUrlBytes`** / **`DownloadProgress`** — 큰 바이너리를 `Uint8Array` 로 받으며 진행률 콜백을 받을 때.
43
-
44
- IndexedDB:
45
-
46
- - **`IndexedDbStore`** / **`StoreConfig`** — 브라우저 영속 키/값 저장소가 필요할 때 (트랜잭션·재진입 안전 `open`).
47
- - **`IndexedDbVirtualFs`** / **`VirtualFsEntry`** — 위 저장소 위에 경로(`/a/b/c`) 기반 파일/디렉토리 트리를 올릴 때.
48
-
49
- ## DOM 탐색/가시성 — `Element` 확장
50
-
51
- ```ts
52
- el.findAll<T extends Element = Element>(selector: string): T[] // 빈 선택자 → []
53
- el.findFirst<T extends Element = Element>(selector: string): T | undefined // 빈 선택자 → undefined
54
- el.prependChild<T extends Element>(child: T): T // 첫 자식으로 삽입
55
- el.getParents(): Element[] // 가까운 순서
56
- el.isOffsetElement(): boolean // position: relative/absolute/fixed/sticky
57
- el.isVisible(): boolean // clientRects 존재 + visibility != hidden + opacity != "0"
58
- ```
59
-
60
- ## 포커스/탭 이동 — `Element` 확장
61
-
62
- ```ts
63
- el.findTabbableParent(): HTMLElement | undefined // tabbable 라이브러리 사용
64
- el.findFirstTabbableChild(): HTMLElement | undefined // TreeWalker로 첫 매치
65
- ```
66
-
67
- ## 레이아웃/스크롤 — `HTMLElement` 확장
68
-
69
- ```ts
70
- el.repaint(): void // offsetHeight 접근으로 강제 reflow
71
- el.getRelativeOffset(parent: HTMLElement | string): { top; left } // CSS top/left 즉시 사용 가능. transform/border/스크롤 보정. 못 찾으면 ArgumentError
72
- el.scrollIntoViewIfNeeded(target: { top; left }, offset?): void // 상단/좌측 가림만 보정. 하단/우측은 브라우저 기본
73
- ```
74
-
75
- `getRelativeOffset` 은 드롭다운/팝업의 absolute 위치 지정 표준 경로. `parent` 는 가장 가까운 offset parent 또는 selector.
76
-
77
- ## 클립보드/측정 헬퍼
78
-
79
- ```ts
80
- function copyElement(event: ClipboardEvent): void // 대상 내 첫 input/textarea.value → clipboard
81
- function pasteToElement(event: ClipboardEvent): void // clipboard → 첫 input/textarea.value 교체 + input 이벤트 dispatch
82
- function getBounds(els: Element[], timeout = 5000): Promise<ElementBounds[]> // IntersectionObserver 기반. 입력 순서 유지. timeout 초과 시 TimeoutError
83
-
84
- interface ElementBounds { target: Element; top: number; left: number; width: number; height: number; }
85
- ```
86
-
87
- `copyElement`/`pasteToElement` 는 `<element @copy=... @paste=...>` 이벤트 핸들러로 직결. 커서/선택 영역은 무시하고 전체 값 교체.
88
-
89
- ## 파일 다이얼로그/다운로드
90
-
91
- ```ts
92
- function openFileDialog(options?: { accept?: string; multiple?: boolean }): Promise<File[] | undefined>
93
- // 취소 시 undefined, 빈 선택 시 undefined.
94
- function downloadBlob(blob: Blob, fileName: string): void
95
- // 파일명: sanitize-filename + 대괄호 제거. 빈 결과는 "download". ObjectURL 1초 후 해제.
96
- ```
97
-
98
- ## 진행률 fetch
99
-
100
- ```ts
101
- interface DownloadProgress { receivedLength: number; contentLength: number; }
102
- function fetchUrlBytes(url: string, options?: { onProgress?: (p: DownloadProgress) => void }): Promise<Uint8Array>
103
- ```
104
-
105
- `Content-Length` 가 있으면 사전 할당(메모리 효율) + 초과/부족 검출, 없으면 청크 수집 후 `bytes.concat`. HTTP 오류·본문 없음·길이 불일치는 모두 throw.
106
-
107
- ## IndexedDB 저장소 — `IndexedDbStore`
108
-
109
- ```ts
110
- interface StoreConfig { name: string; keyPath: string; }
111
-
112
- class IndexedDbStore {
113
- constructor(dbName: string, dbVersion: number, storeConfigs: StoreConfig[]);
114
- open(): Promise<IDBDatabase>; // versionchange/close 시 자동 무효화
115
- withStore<R>(name, mode: IDBTransactionMode, fn: (s: IDBObjectStore) => Promise<R>): Promise<R>; // fn throw 시 tx.abort
116
- get<T>(name, key: IDBValidKey): Promise<T | undefined>;
117
- put(name, value): Promise<void>;
118
- delete(name, key: IDBValidKey): Promise<void>;
119
- getAll<T>(name): Promise<T[]>;
120
- close(): void;
121
- }
122
- ```
123
-
124
- `open()` 은 중복 호출 안전(병행 호출 단일화). `withStore` 의 `fn` 내부 에러는 트랜잭션 abort 후 원본 에러로 reject.
125
-
126
- ## IndexedDB 가상 파일시스템 — `IndexedDbVirtualFs`
127
-
128
- `IndexedDbStore` 위에 경로 키(`/a/b/c`) 기반 파일/디렉토리 모델. 데이터는 base64 문자열로 저장.
129
-
130
- ```ts
131
- interface VirtualFsEntry { kind: "file" | "dir"; dataBase64?: string; }
132
-
133
- class IndexedDbVirtualFs {
134
- constructor(db: IndexedDbStore, storeName: string, keyField: string);
135
- getEntry(fullKey: string): Promise<VirtualFsEntry | undefined>;
136
- putEntry(fullKey: string, kind: "file" | "dir", dataBase64?: string): Promise<void>;
137
- deleteByPrefix(keyPrefix: string): Promise<boolean>; // 자기 자신 + "/" 하위 재귀 삭제
138
- listChildren(prefix: string): Promise<{ name: string; isDirectory: boolean }[]>; // 직속 자식만, 중간 경로도 dir 로 노출
139
- ensureDir(fullKeyBuilder: (path: string) => string, dirPath: string): Promise<void>; // 중간 디렉토리 모두 생성
140
- }
141
- ```
142
-
143
- `fullKey`/`keyField`/`fullKeyBuilder` 분리로 멀티 테넌트(예: 사용자별 prefix) 키 스킴을 호출 측에서 결정.
@@ -1,58 +0,0 @@
1
- # @simplysm/core-common
2
- 브라우저·Node 공통 유틸·타입·에러·확장 메서드 패키지. import 시 Array/Map/Set 프로토타입 확장이 자동 적용됨.
3
-
4
- ## 사용 트리거 인덱스
5
- - **`env`, `parseBoolEnv`, `__DEV__`** — 환경변수 읽기/쓰기 또는 빌드 시점 dev 플래그 분기. (인라인)
6
- - **에러 클래스 (`SdError`, `ArgumentError`, `NotImplementedError`, `TimeoutError`)** — 도메인별 에러 throw 또는 instanceof 분기. (인라인)
7
- - **공통 타입 유틸 (`Bytes`, `Type<T>`, `DeepPartial<T>`, `PrimitiveType*`)** — 타입 시그니처 작성, 생성자/원시타입 타입화. (인라인)
8
- - **날짜·시간·UUID·LazyGcMap 클래스** — 도메인 값 객체 생성/파싱/연산. 자세히: [types.md](./types.md)
9
- - **이벤트·큐 클래스 (`EventEmitter`, `DebounceQueue`, `SerialQueue`)** — 입력 디바운싱, 작업 직렬화, 타입 안전 이벤트 발행. 자세히: [features.md](./features.md)
10
- - **Array/Map/Set 확장 메서드** — `single`/`first`/`groupBy`/`toMap`/`distinct`/`orderBy`/`diffs`/`merge`/`toTree`, `Map.getOrCreate`/`update`, `Set.adds`/`toggle` 등. 자세히: [extensions.md](./extensions.md)
11
- - **`obj`/`str`/`num`/`bytes`/`path`/`json`/`xml`/`wait`/`transfer`/`err`/`dt`/`primitive` 네임스페이스 + `js`/`ts`/`html`/`tsql`/`mysql`/`pgsql` 태그, `ZipArchive`** — 객체 복제·동등성·병합, 문자열 파싱·casing, JSON/XML 직렬화, Worker 전송, 날짜 포맷팅 등. 자세히: [utils.md](./utils.md)
12
-
13
- ## env
14
-
15
- ```ts
16
- env(key: string): string | undefined
17
- env(key: string, value: string): void // process.env에 set
18
- parseBoolEnv(value: unknown): boolean // "true"|"1"|"yes"|"on" (대소문자 무시) → true
19
- declare const __DEV__: boolean // 빌드 시 define으로 치환 (라이브러리 빌드에선 미치환)
20
- ```
21
- - `env(key)`: `process.env[key]` 우선, 없으면 `import.meta.env[key]`. 둘 다 없으면 `undefined`. Node/브라우저 양쪽 안전.
22
-
23
- ## 에러 클래스
24
-
25
- 모두 `SdError` 상속. ES2024 `cause` 사용. V8에서 `captureStackTrace` + cause stack 결합.
26
-
27
- ```ts
28
- new SdError(cause: Error, ...messages: string[]) // "상위msg => ... => cause.message"
29
- new SdError(...messages: string[]) // 메시지 가변 인자, 역순 " => " join
30
- new ArgumentError(argObj) // "잘못된 인자입니다.\n\n<YAML>"
31
- new ArgumentError(message, argObj) // message + YAML 첨부
32
- new NotImplementedError(message?) // "미구현[: message]"
33
- new TimeoutError(count?, message?) // "대기 시간 초과[(N회 시도)][: message]"
34
- ```
35
- - `cause`: 원인 Error. 메시지·stack이 결합되어 디버깅 가능.
36
- - `messages`: 가변 인자, **역순으로** ` => ` join (상위 컨텍스트가 앞).
37
- - `ArgumentError.argObj`: 검사 실패한 인자 객체. `yaml` 라이브러리로 YAML 렌더되어 메시지 끝에 첨부.
38
-
39
- ## 공통 타입 유틸 (`common.types.ts`)
40
-
41
- ```ts
42
- type Bytes = Uint8Array // 바이너리 표준 타입 (Buffer 대체)
43
- interface Type<T> extends Function { new (...args: unknown[]): T } // 클래스 생성자 타입
44
- type DeepPartial<T> // 재귀 Partial (원시타입은 그대로)
45
-
46
- type PrimitiveTypeMap = { // 원시 타입 ↔ 문자열 키 매핑
47
- string, number, boolean, DateTime, DateOnly, Time, Uuid, Bytes
48
- }
49
- type PrimitiveTypeStr = keyof PrimitiveTypeMap // "string"|"number"|...
50
- type PrimitiveType = PrimitiveTypeMap[PrimitiveTypeStr] | undefined // 값 union
51
- ```
52
- - `Type<T>`: DI/팩토리/instanceof 체크용. `new ctor()` 호출 가능.
53
- - `DeepPartial<T>`: 객체·array는 재귀 Partial. 원시·`DateTime`/`DateOnly`/`Time`/`Uuid`/`Bytes`는 leaf로 유지.
54
- - `PrimitiveType*`: `@simplysm/orm-common`과 공유. `primitive.typeStr(value)` 런타임 추론과 한 쌍.
55
-
56
- ## 부수 효과 (import 시 자동 적용)
57
-
58
- `@simplysm/core-common`을 한 번이라도 import하면 `Array.prototype`·`Map.prototype`·`Set.prototype`에 확장 메서드가 enumerable=false로 추가됨. 글로벌 인터페이스(`Array<T>`, `ReadonlyArray<T>`, `Map<K,V>`, `Set<T>`)도 ambient declare됨.
@@ -1,88 +0,0 @@
1
- # @simplysm/core-common — extensions
2
-
3
- `@simplysm/core-common` import 시 자동 적용. 글로벌 `Array`/`ReadonlyArray`/`Map`/`Set` 인터페이스에 ambient declare.
4
-
5
- ## ReadonlyArray<T> (비파괴)
6
-
7
- ```ts
8
- single(predicate?): T | undefined // 0~1개만 통과. 2개+ → ArgumentError
9
- first(predicate?): T | undefined // 첫 요소 (predicate 시 find와 동일)
10
- last(predicate?): T | undefined // 마지막 요소
11
- filterAsync(predicate: async): Promise<T[]> // 비동기 필터 (순차)
12
- filterExists(): NonNullable<T>[] // null/undefined 제거 + 타입 좁힘
13
- ofType(type: PrimitiveTypeStr | Type<N>): N[] // 원시 타입명 또는 생성자로 필터
14
- mapAsync(selector: async): Promise<R[]> // 비동기 매핑 (순차)
15
- mapMany(selector?): R[] // flat + filterExists
16
- mapManyAsync(selector?: async): Promise<R[]>
17
- parallelAsync(fn: async): Promise<R[]> // Promise.all (하나 reject 시 전체 reject)
18
-
19
- groupBy(keySelector, valueSelector?): { key, values }[]
20
- // 원시 key: O(n) Map 최적화. 객체 key: equal() 비교로 O(n²)
21
- toMap(keySelector, valueSelector?): Map<K, V> // 중복 key → ArgumentError
22
- toMapAsync(keySelector: async, valueSelector?: async): Promise<Map>
23
- toArrayMap(keySelector, valueSelector?): Map<K, V[]> // 중복 허용, array로 누적 (O(n))
24
- toSetMap(keySelector, valueSelector?): Map<K, Set<V>>
25
- toMapValues(keySelector, valueSelector(items)): Map<K, V> // value는 그룹 전체로 계산
26
- toObject(keySelector: → string, valueSelector?): Record<string, V>
27
- toTree(keyProp, parentKey): TreeArray<T>[] // 평면 → 트리 (parentKey null이면 root)
28
-
29
- distinct(options?: bool | { matchAddress?, keyFn? }): T[]
30
- // matchAddress=true: Set 참조 비교. keyFn: 커스텀 키 O(n). 둘 다 없이 객체: O(n²) equal
31
- orderBy(selector?): T[] // 오름차순 (불변, 새 array)
32
- orderByDesc(selector?): T[]
33
-
34
- diffs(target, options?: { keys?, excludes? }): ArrayDiffsResult<T, P>[]
35
- // 전체 일치 우선, 없으면 keys 일치(update 후보). 결과: INSERT|DELETE|UPDATE
36
- oneWayDiffs(orgItems: T[] | Map<TKey, T>, keyPropNameOrGetValFn, options?):
37
- ArrayOneWayDiffResult<T>[] // type: 'create'|'update'|'same'
38
- merge(target, options?): (T | P | T&P)[] // diffs 후 update는 obj.merge, insert는 append
39
-
40
- sum(selector?): number // 숫자 아니면 ArgumentError
41
- min(selector?): number | string | undefined // 숫자/문자열만
42
- max(selector?): number | string | undefined
43
- shuffle(): T[] // Fisher-Yates, 새 array
44
- ```
45
-
46
- ## Array<T> (파괴, @mutates)
47
-
48
- ```ts
49
- distinctThis(options?) // distinct를 in-place로
50
- orderByThis(selector?) // Array.prototype.sort 위임 (in-place)
51
- orderByDescThis(selector?)
52
- insert(index, ...items) // splice 삽입, this 반환
53
- remove(item | selector) // 역순 순회 splice 제거
54
- toggle(item) // 있으면 remove, 없으면 push
55
- clear() // 전체 비우기
56
- ```
57
-
58
- ## 익스포트 타입
59
-
60
- ```ts
61
- type ArrayDiffsResult<TOrig, TOther> =
62
- | { source: undefined; target: TOther } // INSERT
63
- | { source: TOrig; target: undefined } // DELETE
64
- | { source: TOrig; target: TOther } // UPDATE
65
- type ArrayOneWayDiffResult<T> =
66
- | { type: 'create'; item: T; orgItem: undefined }
67
- | { type: 'update'; item: T; orgItem: T }
68
- | { type: 'same'; item: T; orgItem: T }
69
- type TreeArray<TNode> = TNode & { children: TreeArray<TNode>[] }
70
- type ComparableType = string | number | boolean | DateTime | DateOnly | Time | undefined
71
- ```
72
-
73
- ## Map<K, V>
74
-
75
- ```ts
76
- getOrCreate(key, newValue: V): V
77
- getOrCreate(key, newValueFn: () => V): V // 함수면 팩토리로 호출하여 lazy 생성
78
- update(key, updateFn: (v: V | undefined) => V): void // key 없어도 fn 호출
79
- ```
80
- - **주의**: `Map<K, () => void>` 같이 V가 함수 타입이면 두 번째 인자가 팩토리로 인식됨. 함수 값을 저장하려면 `getOrCreate(k, () => myFn)`.
81
-
82
- ## Set<T>
83
-
84
- ```ts
85
- adds(...values: T[]): this // 다중 add
86
- toggle(value, addOrDel?: "add" | "del"): this
87
- // 인자 없으면 자동 토글, "add"=강제 추가, "del"=강제 삭제
88
- ```
@@ -1,51 +0,0 @@
1
- # @simplysm/core-common — features
2
-
3
- ## EventEmitter<TEvents>
4
-
5
- EventTarget 기반의 타입 안전 이벤트 이미터. 브라우저·Node 공통.
6
-
7
- ```ts
8
- class EventEmitter<TEvents extends { [K in keyof TEvents]: unknown } = Record<string, unknown>> {
9
- on<E extends keyof TEvents & string>(type: E, listener: (data: TEvents[E]) => void): void
10
- off<E>(type: E, listener: ...): void
11
- emit<E>(type: E, ...args: TEvents[E] extends void ? [] : [data: TEvents[E]]): void
12
- listenerCount(type): number
13
- dispose(): void // 모든 리스너 제거
14
- }
15
- ```
16
- - `TEvents`: `{ eventName: dataType }` 맵. `void` 타입이면 `emit("done")` 인자 생략.
17
- - 같은 `(type, listener)` 쌍 중복 등록 시 무시.
18
- - 내부적으로 `CustomEvent.detail`로 데이터 전송. listener는 wrapper로 감싸져 등록되며, listenerMap이 원본 ↔ wrapper 매핑 보관.
19
-
20
- ```ts
21
- interface MyEvents { data: string; done: void }
22
- class M extends EventEmitter<MyEvents> {}
23
- const m = new M();
24
- m.on("data", s => ...);
25
- m.emit("data", "hi");
26
- m.emit("done");
27
- ```
28
-
29
- ## DebounceQueue extends EventEmitter<{ error: SdError }>
30
-
31
- 마지막 요청만 실행. 짧은 시간 내 다중 호출 → 마지막 1건만 처리.
32
-
33
- ```ts
34
- new DebounceQueue(delay?: number) // ms. 생략 시 다음 이벤트 루프 (setTimeout(_, undefined))
35
- run(fn: () => void | Promise<void>): void
36
- dispose(): void // 타이머·pending 정리
37
- ```
38
- - `delay` ms 지난 뒤 가장 최근 `fn` 실행. 실행 중 도착한 추가 `run()`은 디바운스 지연 없이 현재 실행 직후 즉시 처리 (요청 누락 방지).
39
- - fn throw 시 `SdError`로 감싸 `"error"` 이벤트 발행. 리스너 없으면 `consola` 로그.
40
-
41
- ## SerialQueue extends EventEmitter<{ error: SdError }>
42
-
43
- 큐에 추가된 함수들을 순차 실행.
44
-
45
- ```ts
46
- new SerialQueue(gap: number = 0) // 각 작업 사이 ms 간격
47
- run(fn: () => void | Promise<void>): void
48
- dispose(): void // 대기 큐 비우기 (실행 중은 완료됨)
49
- ```
50
- - 하나 완료 후 다음 시작. 에러 발생해도 후속 작업 계속 실행. throw는 `SdError` 감싸서 `"error"` 이벤트 (리스너 없으면 `consola.error`).
51
- - `gap>0` 이면 작업 간 `wait.time(gap)` 대기.
@@ -1,88 +0,0 @@
1
- # @simplysm/core-common — types
2
-
3
- ## Uuid
4
-
5
- ```ts
6
- class Uuid {
7
- static generate(): Uuid // crypto.getRandomValues 기반 UUID v4
8
- static fromBytes(bytes: Bytes): Uuid // 16바이트 Uint8Array → Uuid (길이≠16이면 ArgumentError)
9
- constructor(uuid: string) // 형식 검증 (실패 시 ArgumentError)
10
- toString(): string
11
- toBytes(): Bytes
12
- }
13
- ```
14
- - 정규식 `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i` 로 검증.
15
- - v4 비트: byte[6]은 0x40 마스크, byte[8]은 0x80 마스크 적용.
16
-
17
- ## DateTime (불변, 로컬 타임존, ms 정밀도)
18
-
19
- ```ts
20
- new DateTime() // 현재
21
- new DateTime(year, month, day, h?, m?, s?, ms?)
22
- new DateTime(tick: number)
23
- new DateTime(date: Date)
24
- static parse(str): DateTime // 'yyyy-MM-dd HH:mm:ss[.fff]', 'yyyyMMddHHmmss',
25
- // 'yyyy-MM-dd AM/PM HH:mm:ss', '오전/오후', ISO 8601
26
- ```
27
- - 읽기 getter: `year`, `month` (1-12), `day`, `hour`, `minute`, `second`, `millisecond`, `tick`, `dayOfWeek` (0=일~6=토), `timezoneOffsetMinutes`, `isValid`, `date` (내부 Date 복사 X — readonly 참조).
28
- - 변환: `setYear/Month/Day/Hour/Minute/Second/Millisecond(n)` → 새 인스턴스. `setMonth`는 일수 초과 시 해당 월 말일로 보정 (예: 1월 31일 → 2월 28/29일).
29
- - 산술: `addYears/Months/Days` (캘린더 기반), `addHours/Minutes/Seconds/Milliseconds` (tick 가산).
30
- - 포맷: `toFormatString(fmt)` — `dt.format` 형식 문자열. `toString()` = `"yyyy-MM-ddTHH:mm:ss.fffzzz"`.
31
- - 파싱 실패 시 `ArgumentError`.
32
-
33
- ## DateOnly (불변, 시간 제외)
34
-
35
- ```ts
36
- new DateOnly() | new DateOnly(y,m,d) | new DateOnly(tick) | new DateOnly(date)
37
- static parse(str): DateOnly // 'yyyy-MM-dd', 'yyyyMMdd' (타임존 무관),
38
- // ISO 8601 (UTC→로컬 변환)
39
- static getDateByYearWeekSeq(
40
- { year, month?, weekSeq },
41
- weekStartDay = 1, minDaysInFirstWeek = 4,
42
- ): DateOnly // 지정 주차의 시작 날짜
43
- ```
44
- - getter: `year`, `month`, `day`, `tick`, `dayOfWeek`, `isValid`.
45
- - `setYear/Month/Day`, `addYears/Months/Days` 동일 패턴 (월 보정 동일).
46
- - 주차 API (인스턴스):
47
- - `getBaseYearMonthSeqForWeekSeq(weekStartDay=1, minDaysInFirstWeek=4)`: 이 날짜가 속한 주의 기준 연/월.
48
- - `getWeekSeqStartDate(...)`: 이 날짜가 속한 주의 시작 날짜.
49
- - `getWeekSeqOfYear(...)`: `{ year, weekSeq }`.
50
- - `getWeekSeqOfMonth(...)`: `{ year, monthSeq, weekSeq }`.
51
- - `weekStartDay`: 주 시작 요일 (0=일~6=토). 기본 1=월.
52
- - `minDaysInFirstWeek`: 첫 주 최소 일수 (1~7). 4=ISO 8601, 1=미국식.
53
- - `toFormatString(fmt)` / `toString()` = `"yyyy-MM-dd"`.
54
-
55
- ## Time (불변, 24시간 순환)
56
-
57
- ```ts
58
- new Time() | new Time(h, m, s?, ms?) | new Time(tick) | new Time(date)
59
- static parse(str): Time // 'HH:mm:ss[.fff]', 'AM/PM HH:mm:ss', ISO 8601
60
- ```
61
- - 24시간을 초과/음수인 tick 입력은 자동으로 `% MS_PER_DAY` 정규화.
62
- - getter: `hour`, `minute`, `second`, `millisecond`, `tick`, `isValid`.
63
- - `setHour/Minute/Second/Millisecond`, `addHours/Minutes/Seconds/Milliseconds` (24시간 순환).
64
- - `toFormatString(fmt)` / `toString()` = `"HH:mm:ss.fff"`.
65
-
66
- ## LazyGcMap<TKey, TValue>
67
-
68
- LRU 접근 시간 갱신 + 주기 GC 로 자동 만료되는 `Map`.
69
-
70
- ```ts
71
- new LazyGcMap({
72
- expireTime: number, // 만료 ms (필수). 마지막 접근부터 경과 시 삭제
73
- gcInterval?: number, // GC 주기 ms. 기본 = max(expireTime/10, 1000)
74
- onExpire?: (key, value) => void|Promise<void>, // 만료 시 콜백. 비동기 가능, throw하면 로그만
75
- })
76
-
77
- has(key) // 접근 시간 갱신 X
78
- get(key) // 접근 시간 갱신 O
79
- set(key, val) // GC 타이머 시작
80
- delete(key) // 비면 GC 중지
81
- clear() // 전체 삭제 + GC 중지 (인스턴스 재사용 가능)
82
- dispose() // 영구 정리 (이후 모든 작업 no-op, getOrCreate만 throw)
83
- getOrCreate(key, factory)
84
- size, keys(), values(), entries()
85
- ```
86
- - **반드시 `dispose()` 호출 필요** — 안 하면 GC 타이머 leak.
87
- - GC 중복 실행 방지(`_isGcRunning`). `onExpire` 실행 도중 같은 key로 `set()`되면 새 값은 보존(참조 동일성 비교).
88
- - 비어있으면 자동 GC 중지 → 재 `set()` 시 자동 재시작.
@@ -1,189 +0,0 @@
1
- # @simplysm/core-common — utils
2
-
3
- `utils/` 네임스페이스 일괄 export. import는 `import { obj, str, ..., js, ZipArchive } from "@simplysm/core-common"`.
4
-
5
- ## `obj` — 객체 조작
6
-
7
- ```ts
8
- obj.clone<T>(source): T
9
- // 깊은 복사. 순환 참조 지원. Date/DateTime/DateOnly/Time/Uuid/RegExp/Error/Uint8Array/Array/Map/Set 모두 별도 처리.
10
- // 프로토타입 체인 유지(Object.setPrototypeOf). 함수·Symbol은 참조 유지. WeakMap/WeakSet 미지원. getter/setter는 현재 값으로 평가.
11
-
12
- obj.equal(source, target, options?: EqualOptions): boolean
13
- interface EqualOptions {
14
- topLevelIncludes?: string[] // 지정한 key만 비교 (최상위만, 객체 속성에만 적용)
15
- topLevelExcludes?: string[] // 지정한 key 제외 (최상위만)
16
- ignoreArrayIndex?: boolean // array 순서 무시. true면 O(n²) (permutation 매칭)
17
- shallow?: boolean // 1단계 참조 비교
18
- }
19
- // null != null 분기, custom 타입은 tick/toString 기반 비교.
20
-
21
- obj.merge<S, T>(source, target, opt?: MergeOptions): S & T
22
- interface MergeOptions {
23
- arrayProcess?: "replace" | "concat" // 기본 "replace"(target으로 교체). "concat"=합집합(Set 중복 제거)
24
- useDelTargetNull?: boolean // target이 null이면 결과 key 삭제
25
- }
26
- // 불변 (새 객체 반환). 타입 다르면 target으로 덮어씀. Map은 재귀 머지.
27
-
28
- obj.merge3(source, origin, target, optionsObj?: Record<key, Merge3KeyOptions>):
29
- { conflict: boolean; result: O & S & T }
30
- // 3-way merge. source==origin → target 채택, target==origin → source 채택,
31
- // source==target → 채택, 셋 다 다름 → conflict=true + origin 유지
32
- interface Merge3KeyOptions { keys?; excludes?; ignoreArrayIndex? } // equal과 동일
33
-
34
- obj.omit(item, omitKeys[]): Omit<T, K>
35
- obj.omitByFilter(item, (key) => boolean): T // @internal
36
- obj.pick(item, keys[]): Pick<T, K>
37
-
38
- obj.getChainValue(o, "a.b[0].c", optional?: true): unknown
39
- obj.getChainValueByDepth(o, key, depth, optional?): T[K] // 같은 key로 depth회 하강
40
- obj.setChainValue(o, chain, value): void
41
- obj.deleteChainValue(o, chain): void
42
-
43
- obj.clearUndefined(o): T // @mutates null/undefined key 삭제
44
- obj.clear(o): {} // @mutates 전체 비우기
45
- obj.nullToUndefined(o): T // @mutates null→undefined (재귀, 순환 안전)
46
- obj.unflatten({ "a.b.c": 1 }): { a: { b: { c: 1 } } } // @internal
47
-
48
- obj.keys(o): (keyof T)[] // 타입 안전 Object.keys
49
- obj.entries(o): [K, V][] // 타입 안전 Object.entries
50
- obj.fromEntries(pairs): Record
51
- obj.map(o, (key, value) => [newKey | null, newValue]): Record
52
- // null newKey → 기존 key 유지. key/value 동시 변환
53
-
54
- type UndefToOptional<T> // { a, b: T|undefined } → { a, b?: T }
55
- type OptionalToUndef<T> // { a, b? } → { a, b: T|undefined }
56
- ```
57
-
58
- ## `str` — 문자열
59
-
60
- ```ts
61
- str.getKoreanSuffix(text, type: "을"|"은"|"이"|"와"|"랑"|"로"|"라"): string
62
- // 받침 유무로 조사 자동. "로"는 ㄹ 받침 예외(받침 있어도 "로"). 한글 외 문자→무받침 취급.
63
- str.replaceFullWidth(str): string // 전각 영숫자/공백/괄호 → 반각
64
- str.toPascalCase(s) / toCamelCase / toKebabCase / toSnakeCase
65
- // PascalCase: 하이픈/언더/점 + 소문자 → 대문자. 첫글자 대문자화.
66
- // kebab/snake: 대문자/대문자그룹 분리. 기존 구분자는 유지 (혼합 시 "hello-_world").
67
- str.isNullOrEmpty(s): s is "" | undefined // 타입 가드
68
- str.insert(s, index, insertString): string
69
- ```
70
-
71
- ## `num` — 숫자
72
-
73
- ```ts
74
- num.parseInt(text): number | undefined // 숫자 외 문자 제거. 선행 - 만 음수, 중간 - 제거. "010-1234-5678"→1012345678
75
- num.parseFloat(text): number | undefined
76
- num.parseRoundedInt(text): number | undefined // parseFloat 후 Math.round
77
- num.isNullOrEmpty(n): n is 0 | undefined // 타입 가드 (0/null/undefined)
78
- num.format(val, digit?: { max?, min? }): string // toLocaleString. min 부족분은 0 패딩
79
- ```
80
-
81
- ## `bytes` — Uint8Array
82
-
83
- ```ts
84
- bytes.concat(arrs: Bytes[]): Bytes
85
- bytes.toHex(b): string // 소문자
86
- bytes.fromHex(hex): Bytes // 홀수 길이/무효 문자 → ArgumentError
87
- bytes.toBase64(b): string
88
- bytes.fromBase64(s): Bytes // 공백·패딩 정규화. 무효 문자/길이 → ArgumentError
89
- ```
90
-
91
- ## `path` — POSIX 경로 (브라우저용, `/` 만 지원)
92
-
93
- ```ts
94
- path.join(...segments): string // 슬래시 정규화
95
- path.basename(filePath, ext?): string // ext 제거 옵션
96
- path.extname(filePath): string // 숨김파일(.gitignore)은 "" (Node 동일)
97
- ```
98
-
99
- ## `json` — 커스텀 타입 지원 JSON
100
-
101
- ```ts
102
- json.stringify(obj, options?: {
103
- space?: number | string,
104
- replacer?: (key, value) => unknown,
105
- redactBytes?: boolean, // Uint8Array → "__hidden__" (로깅용, parse 시 throw)
106
- }): string
107
- json.parse<T>(str): T
108
- ```
109
- - 사전 변환으로 `{ __type__, data }` 태그 객체 생성: Date/DateTime/DateOnly/Time/Uuid/Set/Map/Error(cause·code·detail 포함)/Uint8Array(hex). `Date.prototype.toJSON` 미수정 → Worker 안전.
110
- - 순환 참조 → `TypeError`.
111
- - `parse`는 `nullToUndefined` 적용 (모든 JSON `null` → `undefined`, simplysm null-free 규칙).
112
- - 파싱 실패 시 `__DEV__` 환경에서는 메시지에 전체 JSON 포함, 아니면 길이만.
113
-
114
- ## `xml` — XML (fast-xml-parser 래퍼)
115
-
116
- ```ts
117
- xml.parse(str, options?: { stripTagPrefix?: boolean }): unknown
118
- xml.stringify(obj, options?: XmlBuilderOptions): string
119
- ```
120
- - 속성은 `$` 그룹, 텍스트 노드는 `_` key. 1단계 깊이 미만은 단일 객체, 이상은 array.
121
- - `stripTagPrefix`: `"ns:tag"`에서 접두사 제거 (속성은 유지).
122
-
123
- ## `wait` — 타이밍
124
-
125
- ```ts
126
- wait.time(ms): Promise<void> // setTimeout Promise화
127
- wait.until(forwarder, ms = 100, maxCount?): Promise<void>
128
- // forwarder가 true 반환할 때까지 ms 간격 폴링. maxCount 초과 시 TimeoutError(count)
129
- ```
130
-
131
- ## `transfer` — Worker 직렬화
132
-
133
- ```ts
134
- transfer.encode(obj): { result: unknown; transferList: ArrayBuffer[] }
135
- transfer.decode(obj): unknown
136
- ```
137
- - `worker.postMessage(result, transferList)` 패턴. Uint8Array는 zero-copy 전송, SharedArrayBuffer는 transferList 제외.
138
- - 지원: Date/DateTime/DateOnly/Time/Uuid/RegExp, Error(cause·code·detail), Array/Map/Set/일반 객체. 그 외 TypedArray는 일반 객체로 처리됨.
139
- - 순환 참조 → `TypeError("순환 참조 감지됨: <path>")`. 같은 객체 다중 참조는 캐시 재사용.
140
-
141
- ## `err` — 에러 메시지
142
-
143
- ```ts
144
- err.message(err: unknown): string // Error.message 또는 String(err)
145
- ```
146
-
147
- ## `dt` — 날짜·시간 포맷 내부 헬퍼
148
-
149
- ```ts
150
- dt.format(formatStr, args: { year?, month?, day?, hour?, minute?, second?, millisecond?, timezoneOffsetMinutes? }): string
151
- dt.normalizeMonth(year, month, day): { year, month, day } // 월 오버플로 + 일수 보정
152
- dt.convert12To24(rawHour, isPM): number // 12 AM=0, 12 PM=12
153
- ```
154
- - format 토큰: `yyyy yy`, `MM M`, `ddd`(요일 한글), `dd d`, `tt`(AM/PM), `hh h`(12시간), `HH H`(24시간), `mm m`, `ss s`, `fff ff f`(밀리초), `zzz zz z`(타임존 ±HH:mm/±HH/±H). 긴 토큰 우선.
155
-
156
- ## `primitive` — PrimitiveType 런타임
157
-
158
- ```ts
159
- primitive.typeStr(value): PrimitiveTypeStr // 값 → "string"|"number"|"boolean"|"DateTime"|"DateOnly"|"Time"|"Uuid"|"Bytes"
160
- ```
161
- - 미지원 타입 → `ArgumentError`.
162
-
163
- ## 직접 export — 템플릿 태그
164
-
165
- `js`, `ts`, `html`, `tsql`, `mysql`, `pgsql` — 모두 같은 동작 (IDE 코드 하이라이팅용). 들여쓰기 정규화: 앞뒤 빈 줄 제거 + 모든 줄에서 공통 최소 들여쓰기만큼 dedent.
166
-
167
- ```ts
168
- const sql = mysql`
169
- SELECT * FROM users
170
- LIMIT 10
171
- `;
172
- ```
173
-
174
- ## 직접 export — `ZipArchive` (`@zip.js/zip.js` 래퍼)
175
-
176
- ```ts
177
- class ZipArchive {
178
- constructor(data?: Blob | Bytes) // 없으면 새 아카이브
179
- extractAll(progressCb?: (p: { fileName, totalSize, extractedSize }) => void): Promise<Map<string, Bytes>>
180
- get(fileName): Promise<Bytes | undefined> // 캐싱됨
181
- exists(fileName): Promise<boolean>
182
- write(fileName, bytes): void // 캐시에만 저장
183
- compress(): Promise<Bytes> // 캐시된 모든 파일을 ZIP으로 (extractAll 호출 → 전체 메모리 적재)
184
- close(): Promise<void> // reader 닫고 캐시 비움
185
- }
186
- interface ZipArchiveProgress { fileName, totalSize, extractedSize }
187
- ```
188
- - 같은 파일 재추출 방지를 위해 내부 `_cache: Map<filename, Bytes>` 사용.
189
- - 대용량 ZIP 의 `compress()` 는 메모리 주의 (스트리밍 X).
@@ -1,12 +0,0 @@
1
- ## @simplysm/core-node
2
-
3
- Node.js 환경 전용 파일시스템·자식 프로세스·경로·파일감시·로깅·Worker 유틸 묶음.
4
-
5
- ## 사용 트리거 인덱스
6
-
7
- - **`fsx`** — 파일/디렉토리 존재확인·생성·복사·삭제·읽기/쓰기(텍스트/바이너리/JSON)·glob·부모 디렉토리 탐색이 필요할 때. 자세히: [fsx.md](./fsx.md)
8
- - **`pathx`** — POSIX 슬래시 경로 변환, 부모-자식 경로 판정, cwd 기준 타겟 필터링이 필요할 때. 자세히: [pathx.md](./pathx.md)
9
- - **`cpx`** — 자식 프로세스 spawn(비동기/동기), 시스템 인코딩 자동 디코딩, 실패 시 reject 옵션. 자세히: [cpx.md](./cpx.md)
10
- - **`FsWatcher`** — 디렉토리/glob 변경 감시 + 디바운싱 + 이벤트 병합 + EPERM 자동 재시작. 자세히: [fs-watcher.md](./fs-watcher.md)
11
- - **`setupConsola` / `PrettyReporter` / `createFileReporter`** — CLI/서버 로깅 일괄 설정, 컬러 콘솔 + JSONL 파일 회전. 자세히: [consola.md](./consola.md)
12
- - **`Worker` / `createWorker`** — 타입 안전 worker_threads 래퍼. 메인에서 `Worker.create()`, 워커에서 `createWorker()`. 자세히: [worker.md](./worker.md)