@simplysm/sd-claude 14.0.82 → 14.0.84
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-requirement-source-handling.md +20 -20
- package/claude/references/sd-simplysm14/README.md +13 -13
- package/claude/references/sd-simplysm14/manuals/client-component.md +92 -92
- package/claude/references/sd-simplysm14/manuals/client-crud.md +11 -11
- package/claude/references/sd-simplysm14/manuals/client-demo.md +28 -28
- package/claude/references/sd-simplysm14/manuals/client-rules.md +1 -1
- package/claude/references/sd-simplysm14/manuals/client-setup.md +21 -21
- package/claude/references/sd-simplysm14/manuals/client-tab.md +3 -3
- package/claude/references/sd-simplysm14/manuals/logging.md +15 -15
- package/claude/references/sd-simplysm14/manuals/orm-union.md +6 -6
- package/claude/references/sd-simplysm14/manuals/orm.md +19 -19
- package/claude/references/sd-simplysm14/manuals/test.md +33 -33
- package/claude/rules/sd-design-rules.md +18 -18
- package/claude/sd-system-prompt.md +369 -0
- package/claude/skills/sd-commit/SKILL.md +10 -10
- package/claude/skills/sd-config/SKILL.md +2 -2
- package/claude/skills/sd-demo/SKILL.md +45 -45
- package/claude/skills/sd-dev/SKILL.md +15 -15
- package/claude/skills/sd-docs/SKILL.md +7 -7
- package/claude/skills/sd-docs/references/subagent-prompt.md +33 -33
- package/claude/skills/sd-impl/SKILL.md +60 -60
- package/claude/skills/sd-review/SKILL.md +9 -9
- package/claude/skills/sd-skill/SKILL.md +74 -74
- package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +1 -1
- package/claude/skills/sd-spec/SKILL.md +354 -319
- package/claude/skills/sd-spec/references/example-spec.md +104 -104
- package/claude/skills/sd-unpack/SKILL.md +34 -34
- package/claude/skills/sd-unpack/scripts/handlers/__pycache__/office_com.cpython-314.pyc +0 -0
- package/claude/skills/sd-unpack/scripts/handlers/office_com.py +234 -159
- package/claude/skills/sd-use/SKILL.md +4 -4
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/apis/angular/README.md +0 -37
- package/claude/references/sd-simplysm14/apis/angular/app-structure.md +0 -92
- package/claude/references/sd-simplysm14/apis/angular/buttons.md +0 -88
- package/claude/references/sd-simplysm14/apis/angular/crud.md +0 -100
- package/claude/references/sd-simplysm14/apis/angular/forms.md +0 -200
- package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +0 -231
- package/claude/references/sd-simplysm14/apis/angular/kanban.md +0 -80
- package/claude/references/sd-simplysm14/apis/angular/layout.md +0 -92
- package/claude/references/sd-simplysm14/apis/angular/modal.md +0 -115
- package/claude/references/sd-simplysm14/apis/angular/routing.md +0 -107
- package/claude/references/sd-simplysm14/apis/angular/select-dropdown.md +0 -35
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +0 -82
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +0 -134
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +0 -127
- package/claude/references/sd-simplysm14/apis/angular/toast.md +0 -97
- package/claude/references/sd-simplysm14/apis/angular/visual.md +0 -167
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +0 -79
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +0 -83
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +0 -91
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +0 -49
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +0 -143
- package/claude/references/sd-simplysm14/apis/core-common/README.md +0 -58
- package/claude/references/sd-simplysm14/apis/core-common/extensions.md +0 -88
- package/claude/references/sd-simplysm14/apis/core-common/features.md +0 -51
- package/claude/references/sd-simplysm14/apis/core-common/types.md +0 -88
- package/claude/references/sd-simplysm14/apis/core-common/utils.md +0 -189
- package/claude/references/sd-simplysm14/apis/core-node/README.md +0 -12
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +0 -59
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +0 -44
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +0 -42
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +0 -53
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +0 -24
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +0 -65
- package/claude/references/sd-simplysm14/apis/excel/README.md +0 -193
- package/claude/references/sd-simplysm14/apis/lint/README.md +0 -94
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +0 -58
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +0 -77
- package/claude/references/sd-simplysm14/apis/orm-common/executable.md +0 -20
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +0 -92
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +0 -98
- package/claude/references/sd-simplysm14/apis/orm-common/schema-builders.md +0 -128
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +0 -69
- package/claude/references/sd-simplysm14/apis/sd-claude/README.md +0 -32
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +0 -80
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config.md +0 -155
- package/claude/references/sd-simplysm14/apis/service-client/README.md +0 -131
- package/claude/references/sd-simplysm14/apis/service-common/README.md +0 -29
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +0 -63
- package/claude/references/sd-simplysm14/apis/service-common/messages.md +0 -56
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +0 -64
- package/claude/references/sd-simplysm14/apis/service-common/service-types.md +0 -43
- package/claude/references/sd-simplysm14/apis/service-server/README.md +0 -13
- package/claude/references/sd-simplysm14/apis/service-server/auth.md +0 -39
- package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +0 -71
- package/claude/references/sd-simplysm14/apis/service-server/define-service.md +0 -55
- package/claude/references/sd-simplysm14/apis/service-server/internals.md +0 -82
- package/claude/references/sd-simplysm14/apis/service-server/server.md +0 -57
- package/claude/references/sd-simplysm14/apis/storage/README.md +0 -71
- package/claude/rules/sd-base-rules.md +0 -306
|
@@ -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)
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
## @simplysm/core-node — consola 설정
|
|
2
|
-
|
|
3
|
-
전역 `consola` 인스턴스에 reporter 를 일괄 부착하는 헬퍼와 reporter 구현체.
|
|
4
|
-
|
|
5
|
-
### setupConsola
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
setupConsola(opts?: { cli?: boolean }): void
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
전역 `consola.level = LogLevels.debug` 로 설정 후 환경에 따라 reporter 구성:
|
|
12
|
-
|
|
13
|
-
- `opts.cli !== true` && `env("DEV")` falsy → **프로덕션**: `createFileReporter()` 만 (JSONL 파일, 콘솔 X).
|
|
14
|
-
- 그 외 → **개발**:
|
|
15
|
-
- `env("SD_DEBUG")` truthy → `PrettyReporter()` 만 (debug 포함 콘솔).
|
|
16
|
-
- 그 외 → `createFileReporter()`(debug 포함 파일) + `PrettyReporter()`(info 이상만 콘솔, `withMaxLevel` 적용).
|
|
17
|
-
|
|
18
|
-
`opts.cli`: CLI 프로세스(`sd-cli` 등) 여부. true 면 파일 출력 없이 콘솔만 사용하도록 분기.
|
|
19
|
-
|
|
20
|
-
### withMaxLevel
|
|
21
|
-
|
|
22
|
-
```ts
|
|
23
|
-
withMaxLevel(reporter: ConsolaReporter, maxLevel: number): ConsolaReporter
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
기존 reporter 를 감싸 `logObj.level > maxLevel` 인 항목을 버린다. consola `LogLevels` 는 낮을수록 심각(0=fatal/error, 1=warn, 2=log, 3=info, 4=debug, 5=trace).
|
|
27
|
-
|
|
28
|
-
### PrettyReporter
|
|
29
|
-
|
|
30
|
-
`class PrettyReporter implements ConsolaReporter` — ANSI 컬러 콘솔 출력.
|
|
31
|
-
|
|
32
|
-
- 색상 활성화: `env("NO_COLOR")` 있으면 비활성, `env("FORCE_COLOR")` 있으면 강제, TTY 또는 win32 면 활성.
|
|
33
|
-
- level<2 (fatal/error/warn) → `stderr`, 그 외 → `stdout`.
|
|
34
|
-
- `type === "box"` → 박스 포맷, `type === "trace"` → 스택 첨부, level<2 또는 `badge: true` → 위아래 빈 줄.
|
|
35
|
-
- `Error` args → message + cwd prefix 제거된 스택 + `cause` 재귀 indent.
|
|
36
|
-
- `ctx.options.formatOptions.date: true` → 시각 `HH:mm:ss.SSS` 부착.
|
|
37
|
-
|
|
38
|
-
### createFileReporter
|
|
39
|
-
|
|
40
|
-
```ts
|
|
41
|
-
createFileReporter(options?: { maxSize?: number; maxDays?: number }): ConsolaReporter
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
- `maxSize` (기본 20MB): 파일 1개 최대 크기. 초과 시 `app.<YYYY-MM-DD>.<seq>.log` 시퀀스로 회전.
|
|
45
|
-
- `maxDays` (기본 14): cutoff 일자 이전 로그 파일 자동 삭제. 매일 첫 로그 시 1회 실행.
|
|
46
|
-
- 출력 위치: `${process.cwd()}/.logs/app.<YYYY-MM-DD>.log` (필요시 `.<seq>` 부착).
|
|
47
|
-
- 라인 형식: `{ time, level, tag?, err?: {message,stack}, msg? }` JSONL. `Error` arg 는 `err` 필드로 분리, 나머지는 `msg` 로 공백 연결.
|
|
48
|
-
- 날짜 바뀌면 자동 로테이트. `.logs` 디렉토리는 첫 쓰기 시 생성.
|
|
49
|
-
|
|
50
|
-
### 예
|
|
51
|
-
|
|
52
|
-
```ts
|
|
53
|
-
import { setupConsola, PrettyReporter, createFileReporter } from "@simplysm/core-node";
|
|
54
|
-
import consola from "consola";
|
|
55
|
-
setupConsola({ cli: true });
|
|
56
|
-
|
|
57
|
-
// 커스텀
|
|
58
|
-
consola.options.reporters = [new PrettyReporter(), createFileReporter({ maxDays: 30 })];
|
|
59
|
-
```
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
## @simplysm/core-node — cpx
|
|
2
|
-
|
|
3
|
-
`import { cpx } from "@simplysm/core-node"`. 자식 프로세스 spawn 래퍼. stdout/stderr 를 시스템 인코딩으로 자동 디코딩, 실패 시 stderr 포함 에러 throw.
|
|
4
|
-
|
|
5
|
-
### 인코딩 감지
|
|
6
|
-
|
|
7
|
-
- `getSystemEncoding(): string` — Windows 는 `chcp` 결과 코드 페이지를, POSIX 는 `LANG`/`LC_ALL` 의 `.<enc>` 부분을 파싱. 실패 시 `"utf-8"`. **결과는 모듈 캐시**.
|
|
8
|
-
- `resetEncodingCache(): void` — 캐시 초기화. 환경 변경 후 강제 재감지 시.
|
|
9
|
-
- `codePageToEncoding(codePage): string` — Windows 코드 페이지 번호→IANA 인코딩명(65001/949/932/936/950/1252/1251/1250/874 지원, 그 외 `"utf-8"`).
|
|
10
|
-
- `decodeBytes(raw: Uint8Array, systemEncoding?: string): string` — UTF-8 fatal decode 시도 → 실패 시 지정 인코딩으로 fallback.
|
|
11
|
-
|
|
12
|
-
### spawn
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
spawn(cmd, args, options?): SpawnProcess
|
|
16
|
-
spawnSync(cmd, args, options?): SpawnResult
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
- `options`: Node `SpawnOptions`/`SpawnSyncOptions` + `reject?: boolean`.
|
|
20
|
-
- `stdio` 기본 `"pipe"`. pipe 인 스트림만 캡처되며 비-pipe 스트림은 결과 문자열이 빈 문자열.
|
|
21
|
-
- `env`: `process.env` 와 병합되어 자식에 전달.
|
|
22
|
-
- `reject` (기본 `true`): exitCode≠0 일 때 `false` 면 결과 객체 반환, `true` 면 throw. 에러 메시지는 `Command failed (exit N): <cmd> <args>` + stderr/stdout 마지막 4000자.
|
|
23
|
-
- `SpawnResult`: `{ stdout: string; stderr: string; exitCode: number }`. 종료 코드가 없고 시그널만 있으면 exitCode=1.
|
|
24
|
-
|
|
25
|
-
### SpawnProcess
|
|
26
|
-
|
|
27
|
-
`spawn()` 반환값. `PromiseLike<SpawnResult>`.
|
|
28
|
-
|
|
29
|
-
- `pid: number | undefined` — 자식 PID.
|
|
30
|
-
- `then / catch` — `SpawnResult` resolve 또는 에러 reject.
|
|
31
|
-
- `kill(signal?): boolean` — 자식 프로세스에 시그널 전송.
|
|
32
|
-
|
|
33
|
-
### resolveStdioPipe
|
|
34
|
-
|
|
35
|
-
- `resolveStdioPipe(stdio): { stdout: boolean; stderr: boolean }` — `SpawnOptions["stdio"]` 가 각 스트림에 대해 pipe 인지 판정. 배열·`"pipe"`·`undefined` 모두 처리.
|
|
36
|
-
|
|
37
|
-
### 예
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
import { cpx } from "@simplysm/core-node";
|
|
41
|
-
const { stdout } = await cpx.spawn("git", ["rev-parse", "HEAD"]);
|
|
42
|
-
const proc = cpx.spawn("node", ["server.js"], { reject: false });
|
|
43
|
-
proc.kill("SIGTERM");
|
|
44
|
-
```
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
## @simplysm/core-node — FsWatcher
|
|
2
|
-
|
|
3
|
-
Chokidar 기반 디렉토리/글로브 변경 감시. 짧은 시간 내 이벤트를 병합하여 콜백 1회로 묶고, Windows EPERM 시 자동 재시작.
|
|
4
|
-
|
|
5
|
-
### 타입
|
|
6
|
-
|
|
7
|
-
- `FsWatcherEvent = "add" | "addDir" | "change" | "unlink" | "unlinkDir"` — chokidar 원본 이벤트 그대로. 디렉토리/파일 add·unlink 구분.
|
|
8
|
-
- `FsWatcherChangeInfo = { event: FsWatcherEvent; path: PosixPath }` — 콜백 인자 1건. `path` 는 POSIX 슬래시 정규화.
|
|
9
|
-
|
|
10
|
-
### 생성
|
|
11
|
-
|
|
12
|
-
```ts
|
|
13
|
-
FsWatcher.watch(paths: string[], options?: ChokidarOptions): Promise<FsWatcher>
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
- `paths`: 감시 대상. 디렉토리 절대 경로 또는 glob 패턴 혼용 가능. glob 메타문자 이전까지를 실제 감시 base 로 추출 후 chokidar 에 전달.
|
|
17
|
-
- `options`: chokidar `ChokidarOptions`. `ignoreInitial` 은 내부적으로 항상 `true` 로 override 되지만, 사용자가 `false` 로 명시한 경우 첫 `onChange` 콜백을 **빈 배열**로 1회 호출(초기 트리거 신호용, 실제 초기 목록은 X).
|
|
18
|
-
- `ready` 대기 후 resolve. 초기화 에러 시 close 후 reject.
|
|
19
|
-
|
|
20
|
-
### 메서드
|
|
21
|
-
|
|
22
|
-
- `onChange(opt: { delay?: number }, cb: (changes: FsWatcherChangeInfo[]) => void | Promise<void>): this`
|
|
23
|
-
- `opt.delay`: 디바운스 ms. 마지막 이벤트로부터 이 시간 후 콜백 1회.
|
|
24
|
-
- 같은 파일에 대한 연속 이벤트 자동 병합: `add+change=add`, `add+unlink`=상쇄(제외), `addDir+unlinkDir`=상쇄, `unlink+add=add`, `unlink+change=change`, `unlinkDir+addDir=addDir`. 룩업 미스는 현재 이벤트로 덮어쓰기.
|
|
25
|
-
- 콜백은 감시 base 가 아닌 **`paths` 원본 glob 에 매칭되는 경로만** 통과 (minimatch, dot 포함).
|
|
26
|
-
- 다중 호출 가능. 각 호출마다 독립 debounce 큐 + handler 등록.
|
|
27
|
-
- `close(): Promise<void>` — debounce 큐 dispose + chokidar close.
|
|
28
|
-
|
|
29
|
-
### 자동 복구
|
|
30
|
-
|
|
31
|
-
- 감시 디렉토리 소실로 EPERM 발생 시 최대 3회 / 1초 간격으로 watcher 재생성·핸들러 재등록. 성공 시 retry count 리셋, 초과 시 중단(error 로그).
|
|
32
|
-
- native `fs.FSWatcher.prototype.emit` 를 모듈 로드 시 1회 패치: listener 0 + `error` 이벤트는 swallow (orphan error 로 인한 프로세스 종료 방지).
|
|
33
|
-
|
|
34
|
-
### 예
|
|
35
|
-
|
|
36
|
-
```ts
|
|
37
|
-
const w = await FsWatcher.watch(["src/**/*.ts"]);
|
|
38
|
-
w.onChange({ delay: 300 }, async (changes) => {
|
|
39
|
-
for (const { path, event } of changes) console.log(event, path);
|
|
40
|
-
});
|
|
41
|
-
// await w.close();
|
|
42
|
-
```
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
## @simplysm/core-node — fsx
|
|
2
|
-
|
|
3
|
-
`import { fsx } from "@simplysm/core-node"`. 모든 함수는 동기(`*Sync`) + 비동기 쌍 제공. 실패 시 경로 정보를 포함한 `SdError` throw.
|
|
4
|
-
|
|
5
|
-
### 존재 확인 / 디렉토리
|
|
6
|
-
|
|
7
|
-
- `existsSync(p) / exists(p): boolean | Promise<boolean>` — 파일·디렉토리 존재 여부.
|
|
8
|
-
- `mkdirSync(p) / mkdir(p): void | Promise<void>` — 재귀 생성. 이미 있으면 무시.
|
|
9
|
-
- `readdirSync(p) / readdir(p): string[]` — 자식 이름 배열(절대 경로 아님).
|
|
10
|
-
|
|
11
|
-
### 삭제
|
|
12
|
-
|
|
13
|
-
- `rmSync(p)` — 재귀+force. **재시도 없음**, 파일 잠금 시 즉시 실패.
|
|
14
|
-
- `rm(p)` — 재귀+force, **최대 6회 / 500ms 간격 재시도**. 일시적 잠금 회피용.
|
|
15
|
-
|
|
16
|
-
### 복사
|
|
17
|
-
|
|
18
|
-
- `copySync(src, dst, filter?) / copy(src, dst, filter?)` — 재귀 복사.
|
|
19
|
-
- `src`: 원본 경로. 존재하지 않으면 no-op.
|
|
20
|
-
- `dst`: 대상 경로. 상위 디렉토리 자동 생성.
|
|
21
|
-
- `filter(absolutePath): boolean`: 하위 항목 1개에 대한 포함 여부. true=포함, false=제외. **최상위 src 는 적용 대상 아님**. 디렉토리에 false 반환 시 그 하위 전체 스킵.
|
|
22
|
-
- 파일 복사 실패 시 최대 6회 / 500ms 재시도.
|
|
23
|
-
|
|
24
|
-
### 읽기 / 쓰기
|
|
25
|
-
|
|
26
|
-
- `readSync(p) / read(p): string` — UTF-8 텍스트.
|
|
27
|
-
- `readBytesSync(p) / readBytes(p): Uint8Array` — 바이너리.
|
|
28
|
-
- `readJsonSync<T>(p) / readJson<T>(p): T` — `@simplysm/core-common` 의 `json.parse` 사용. 파싱 실패 시 본문 앞 500자 미리보기 포함 에러.
|
|
29
|
-
- `writeSync(p, data) / write(p, data)` — `data: string | Uint8Array`. 상위 디렉토리 자동 생성, `flush: true`.
|
|
30
|
-
- `writeJsonSync(p, data, opts?) / writeJson(p, data, opts?)` — `opts.replacer`: JSON.stringify 와 동일한 replacer. `opts.space`: 들여쓰기(숫자=스페이스 수, 문자열=리터럴).
|
|
31
|
-
|
|
32
|
-
### Stats
|
|
33
|
-
|
|
34
|
-
- `statSync / stat` — `fs.Stats`. 심볼릭 링크 따라감.
|
|
35
|
-
- `lstatSync / lstat` — `fs.Stats`. 심볼릭 링크 안 따라감 (링크 자체 정보).
|
|
36
|
-
|
|
37
|
-
### Glob
|
|
38
|
-
|
|
39
|
-
- `globSync(pattern, options?) / glob(pattern, options?): string[]` — `glob` 패키지 래핑. 패턴 내 백슬래시는 슬래시로 치환 후 호출. 결과는 **항상 절대 경로**로 정규화.
|
|
40
|
-
- `options`: `glob` 패키지의 `GlobOptions`(예: `dot: true` 로 dotfile 포함).
|
|
41
|
-
|
|
42
|
-
### 트리 유틸
|
|
43
|
-
|
|
44
|
-
- `clearEmptyDirectory(dirPath)` — 하위까지 재귀 순회, 파일이 없는 디렉토리만 삭제. 파일이 하나라도 있으면 보존.
|
|
45
|
-
- `findAllParentChildPathsSync(childGlob, fromPath, rootPath?) / findAllParentChildPaths(...)` — `fromPath` 부터 루트 방향으로 부모 디렉토리를 따라가며 각 디렉토리에서 `childGlob` 패턴 매칭 파일을 수집. `rootPath` 도달 시 종료(지정 없으면 FS 루트까지). 모노레포 루트 탐색 등에 사용.
|
|
46
|
-
|
|
47
|
-
### 예
|
|
48
|
-
|
|
49
|
-
```ts
|
|
50
|
-
import { fsx } from "@simplysm/core-node";
|
|
51
|
-
await fsx.copy("src", "dist", (p) => !p.includes("node_modules"));
|
|
52
|
-
const cfg = await fsx.readJson<{ name: string }>("package.json");
|
|
53
|
-
```
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
## @simplysm/core-node — pathx
|
|
2
|
-
|
|
3
|
-
`import { pathx } from "@simplysm/core-node"`. POSIX 슬래시 경로 정규화·비교·필터링.
|
|
4
|
-
|
|
5
|
-
### 타입
|
|
6
|
-
|
|
7
|
-
- `PosixPath` — `string & { [POSIX]: never }` 브랜드 타입. `posix()` / `posixResolve()` 만 생성 가능. 글로브·minimatch·URL 호환 경로 표현용.
|
|
8
|
-
|
|
9
|
-
### 함수
|
|
10
|
-
|
|
11
|
-
- `posix(p): PosixPath` — 백슬래시→슬래시 치환만. resolve 안 함.
|
|
12
|
-
- `posixResolve(...args): PosixPath` — `path.resolve(...args)` 후 슬래시 치환. 절대 경로 보장.
|
|
13
|
-
- `changeFileDirectory(filePath, fromDirectory, toDirectory): string` — `filePath` 의 디렉토리 prefix 를 `fromDirectory`→`toDirectory` 로 갈아끼움. `filePath === fromDirectory` 면 `toDirectory` 반환. `filePath` 가 `fromDirectory` 하위가 아니면 `ArgumentError` throw.
|
|
14
|
-
- `basenameWithoutExt(filePath): string` — 마지막 확장자 1개 제거한 basename. `"a.spec.ts"` → `"a.spec"`.
|
|
15
|
-
- `isChildPath(childPath, parentPath): boolean` — `child` 가 `parent` **엄격 하위**인지 (동일 경로면 false). 내부적으로 `posixResolve` 정규화 후 `parent + "/"` prefix 매칭.
|
|
16
|
-
- `filterByTargets(files, targets, cwd): string[]` — `files`(cwd 하위 절대 경로 배열)에서 `targets`(cwd 기준 상대 POSIX 경로) 와 일치 또는 하위 항목만 통과. `targets` 가 빈 배열이면 `files` 그대로 반환. sd-cli 의 `-t` 옵션 처리에 사용.
|
|
17
|
-
|
|
18
|
-
### 예
|
|
19
|
-
|
|
20
|
-
```ts
|
|
21
|
-
import { pathx } from "@simplysm/core-node";
|
|
22
|
-
const out = pathx.changeFileDirectory("/proj/src/a.ts", "/proj/src", "/proj/dist"); // /proj/dist/a.ts
|
|
23
|
-
pathx.isChildPath("/a/b/c", "/a/b"); // true
|
|
24
|
-
```
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
## @simplysm/core-node — Worker
|
|
2
|
-
|
|
3
|
-
타입 안전한 `worker_threads` 래퍼. 메인에서는 `Worker.create()` 로 프록시 호출, 워커에서는 `createWorker()` 로 메서드·이벤트 노출.
|
|
4
|
-
|
|
5
|
-
### 워커 스크립트 — `createWorker`
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
createWorker<TMethods, TEvents = Record<string, never>>(methods: TMethods): {
|
|
9
|
-
send<K extends keyof TEvents & string>(event: K, data?: TEvents[K]): void;
|
|
10
|
-
__methods: TMethods;
|
|
11
|
-
__events: TEvents;
|
|
12
|
-
}
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
- `methods`: 워커가 제공할 메서드 맵. 각 값은 동기/비동기 함수. 동기 반환도 메인에서는 Promise 로 받음.
|
|
16
|
-
- `TEvents`: 메인으로 발행할 이벤트 시그니처(`{ eventName: payloadType }`).
|
|
17
|
-
- 반환 객체의 `send(event, data?)` 로 메인에 이벤트 push. `__methods`/`__events` 는 타입 추론 전용(런타임 미사용).
|
|
18
|
-
- `parentPort` 없으면 throw (반드시 worker thread 에서 import).
|
|
19
|
-
- `process.stdout.write` 를 가로채 메인의 stdout 으로 전달(worker thread 의 stdout 미전달 한계 우회).
|
|
20
|
-
- 메서드 처리 중 throw → `Error` 직렬화되어 메인 호출 Promise reject.
|
|
21
|
-
|
|
22
|
-
워커 파일은 반드시 `export default createWorker(...)` 형태로 export.
|
|
23
|
-
|
|
24
|
-
### 메인 — `Worker.create`
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
Worker.create<TModule extends WorkerModule>(
|
|
28
|
-
filePath: string,
|
|
29
|
-
opt?: Omit<WorkerOptions, "stdout" | "stderr">,
|
|
30
|
-
): WorkerProxy<TModule>
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
- `TModule`: 워커 파일의 `typeof import("./worker")`. 메서드 시그니처·이벤트 타입 추론 소스.
|
|
34
|
-
- `filePath`: 워커 파일 경로. `file://` URL 또는 절대 경로 모두 허용.
|
|
35
|
-
- `opt`: Node `WorkerOptions` 중 `stdout/stderr` 제외(고정 `true`). `env` 는 `process.env` 와 병합. `argv` 는 dev 모드에서 워커 경로 뒤에 추가.
|
|
36
|
-
- 개발(`import.meta.filename` 이 `.ts`) → 내부 `worker-dev-proxy.js` 를 워커로 띄우고 tsx 로 사용자 워커 동적 로드. 프로덕션(`.js`) → 사용자 파일 직접 실행.
|
|
37
|
-
- 워커 stdout/stderr 는 메인 프로세스로 파이프.
|
|
38
|
-
|
|
39
|
-
### 반환 프록시 — `WorkerProxy<TModule>`
|
|
40
|
-
|
|
41
|
-
- `methods` (스프레드된 키): 각 메서드 → `(...args) => Promise<Awaited<R>>`. 매 호출마다 UUID 부여, `@simplysm/core-common` 의 `transfer.encode` 로 직렬화하여 `postMessage`.
|
|
42
|
-
- `on(event, listener)` / `off(event, listener)` — 워커가 `send()` 로 발행한 이벤트 구독/해제.
|
|
43
|
-
- `terminate(): Promise<void>` — 대기 중인 모든 요청을 reject 후 워커 종료.
|
|
44
|
-
|
|
45
|
-
### 비정상 종료
|
|
46
|
-
|
|
47
|
-
- 워커 `exit` (코드≠0, 사용자 terminate 아님) 또는 `error` 발생 시 대기 중인 모든 호출이 `Error("워커가 비정상 종료되었습니다 (코드: N) (method: X)")` 등으로 reject.
|
|
48
|
-
|
|
49
|
-
### 예
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
// worker.ts
|
|
53
|
-
import { createWorker } from "@simplysm/core-node";
|
|
54
|
-
interface E { progress: number }
|
|
55
|
-
const methods = { calc: (n: number) => n * 2 };
|
|
56
|
-
const sender = createWorker<typeof methods, E>(methods);
|
|
57
|
-
export default sender;
|
|
58
|
-
|
|
59
|
-
// main.ts
|
|
60
|
-
import { Worker } from "@simplysm/core-node";
|
|
61
|
-
const w = Worker.create<typeof import("./worker")>("./worker.ts");
|
|
62
|
-
w.on("progress", (p) => console.log(p));
|
|
63
|
-
console.log(await w.calc(21)); // 42
|
|
64
|
-
await w.terminate();
|
|
65
|
-
```
|