@simplysm/sd-claude 14.0.88 → 14.0.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/references/sd-simplysm14/README.md +16 -17
- package/claude/references/sd-simplysm14/apis/angular/README.md +39 -43
- package/claude/references/sd-simplysm14/apis/angular/controls.md +174 -80
- package/claude/references/sd-simplysm14/apis/angular/crud.md +41 -50
- package/claude/references/sd-simplysm14/apis/angular/directives.md +60 -26
- package/claude/references/sd-simplysm14/apis/angular/features.md +109 -37
- package/claude/references/sd-simplysm14/apis/angular/infra.md +61 -44
- package/claude/references/sd-simplysm14/apis/angular/layout.md +39 -31
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +73 -85
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +54 -39
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +55 -30
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +71 -67
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +82 -72
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +35 -36
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +71 -43
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +38 -30
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +45 -50
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +42 -55
- package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +62 -0
- package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +39 -38
- package/claude/references/sd-simplysm14/apis/core-common/README.md +95 -103
- package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +59 -54
- package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +86 -0
- package/claude/references/sd-simplysm14/apis/core-common/datetime.md +57 -66
- package/claude/references/sd-simplysm14/apis/core-common/errors.md +86 -0
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +60 -42
- package/claude/references/sd-simplysm14/apis/core-common/serialization.md +55 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +10 -8
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +29 -32
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +34 -22
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +29 -25
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +40 -53
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +22 -29
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +31 -31
- package/claude/references/sd-simplysm14/apis/excel/README.md +26 -26
- package/claude/references/sd-simplysm14/apis/excel/cell.md +37 -29
- package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +29 -15
- package/claude/references/sd-simplysm14/apis/excel/style.md +33 -27
- package/claude/references/sd-simplysm14/apis/excel/utils.md +29 -19
- package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +78 -55
- package/claude/references/sd-simplysm14/apis/excel/wrapper.md +42 -45
- package/claude/references/sd-simplysm14/apis/lint/README.md +27 -21
- package/claude/references/sd-simplysm14/apis/lint/rules.md +89 -49
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +6 -62
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +149 -67
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +111 -99
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +115 -72
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +134 -92
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +67 -52
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +63 -26
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +51 -40
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +10 -12
- package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +92 -45
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +226 -108
- package/claude/references/sd-simplysm14/apis/service-client/README.md +90 -88
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +37 -29
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +45 -20
- package/claude/references/sd-simplysm14/apis/service-common/README.md +89 -40
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +126 -34
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +109 -54
- package/claude/references/sd-simplysm14/apis/service-server/README.md +70 -66
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +47 -47
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +71 -34
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +31 -32
- package/claude/references/sd-simplysm14/apis/storage/README.md +34 -28
- package/claude/references/sd-simplysm14/manuals/client-app-structure.md +142 -140
- package/claude/references/sd-simplysm14/manuals/client-orm.md +1 -1
- package/claude/references/sd-simplysm14/manuals/client-service.md +19 -7
- package/claude/references/sd-simplysm14/manuals/client-shared-data.md +2 -2
- package/claude/references/sd-simplysm14/manuals/client-system-log.md +11 -3
- package/claude/references/sd-simplysm14/manuals/data-log.md +0 -1
- package/claude/references/sd-simplysm14/manuals/orm.md +16 -0
- package/claude/rules/sd-design-rules.md +10 -0
- package/claude/skills/sd-docs/SKILL.md +58 -46
- package/claude/skills/sd-docs/references/{doc-rules.md → subagent-prompt.md} +103 -103
- package/claude/skills/sd-impl/SKILL.md +1 -1
- package/claude/skills/sd-spec/SKILL.md +858 -858
- package/claude/skills/sd-spec/references/example-spec.md +26 -36
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +0 -47
- package/claude/references/sd-simplysm14/apis/orm-common/query-builder.md +0 -29
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/.specs/inventory/spec.md +0 -99
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/package.json +0 -12
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/index.ts +0 -3
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inbound/inbound.list.ts +0 -150
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inventory/inventory-master.list.ts +0 -143
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/outbound/outbound.list.ts +0 -150
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/pnpm-workspace.yaml +0 -2
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/sd.config.ts +0 -12
- package/claude/skills/sd-demo/evals/golden.jsonl +0 -1
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/package.json +0 -8
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/src/.gitkeep +0 -0
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tests/.gitkeep +0 -0
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tsconfig.json +0 -10
- package/claude/skills/sd-dev/evals/golden.jsonl +0 -1
- package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +0 -7
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +0 -3
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +0 -6
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +0 -1
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +0 -8
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +0 -7
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +0 -3
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +0 -3
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +0 -6
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +0 -1
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +0 -8
- package/claude/skills/sd-docs/evals/golden.jsonl +0 -2
- package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/packages/app/src/screens/box-register/box-register.view.ts +0 -46
- package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +0 -89
- package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/golden.jsonl +0 -4
- package/claude/skills/sd-manual/evals/fixtures/new-manual/src/notification.ts +0 -25
- package/claude/skills/sd-manual/evals/fixtures/update-manual/.claude/references/sd-simplysm14/manuals/notification.md +0 -14
- package/claude/skills/sd-manual/evals/fixtures/update-manual/src/notification.ts +0 -37
- package/claude/skills/sd-manual/evals/golden.jsonl +0 -2
- package/claude/skills/sd-review/evals/fixtures/code-review/src/foo.ts +0 -7
- package/claude/skills/sd-review/evals/fixtures/doc-review/docs/foo.md +0 -4
- package/claude/skills/sd-review/evals/golden.jsonl +0 -2
- package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +0 -14
- package/claude/skills/sd-skill/evals/fixtures/new-skill/.gitkeep +0 -0
- package/claude/skills/sd-skill/evals/golden.jsonl +0 -2
- package/claude/skills/sd-spec/evals/fixtures/case-a-split//355/232/214/354/235/230/353/241/235.md +0 -20
- package/claude/skills/sd-spec/evals/fixtures/case-b-detail/.specs/260513120000_warehouse/spec.md +0 -95
- package/claude/skills/sd-spec/evals/golden.jsonl +0 -2
- package/claude/skills/sd-unpack/evals/fixtures/eml-with-text-attachment/meeting.eml +0 -21
- package/claude/skills/sd-unpack/evals/fixtures/simple-eml/meeting.eml +0 -10
- package/claude/skills/sd-unpack/evals/golden.jsonl +0 -2
- package/claude/skills/sd-use/evals/fixtures/empty/.gitkeep +0 -0
- package/claude/skills/sd-use/evals/golden.jsonl +0 -6
|
@@ -1,95 +1,86 @@
|
|
|
1
|
-
# @simplysm/core-common — 날짜·시간
|
|
1
|
+
# @simplysm/core-common — 날짜·시간 값 타입
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
날짜·시간을 **불변(immutable)** 값으로 다룰 때 함께 읽히는 묶음. JS `Date` 대신 사용. `set*`·`add*` 메서드는 모두 새 인스턴스를 반환하고 원본을 바꾸지 않음. 모두 로컬 타임존 기준으로 동작. ORM 컬럼 타입(`DateTime`/`DateOnly`/`Time`)·JSON/Worker 직렬화에서 1급 지원됨.
|
|
4
|
+
|
|
5
|
+
세 클래스 공통:
|
|
6
|
+
- `parse(str)` 정적 메서드로 문자열 파싱(미지원 형식이면 ArgumentError).
|
|
7
|
+
- `tick` getter — 내부 밀리초 값. `equal`·정렬·복제의 동등성 기준.
|
|
8
|
+
- `isValid` getter — 유효 값 여부.
|
|
9
|
+
- `toFormatString(formatStr)` / `toString()` — 포맷 문자열 변환(아래 `dt` 네임스페이스의 포맷 토큰 사용).
|
|
4
10
|
|
|
5
11
|
## DateTime
|
|
6
12
|
|
|
7
|
-
날짜+시간(밀리초 정밀도) 불변 클래스.
|
|
13
|
+
날짜+시간(밀리초 정밀도) 불변 클래스.
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
생성자 오버로드:
|
|
10
16
|
- `new DateTime()` — 현재 시각.
|
|
11
|
-
- `new DateTime(year, month, day, hour?, minute?, second?, millisecond?)` —
|
|
12
|
-
- `new DateTime(tick
|
|
13
|
-
- `new DateTime(date
|
|
14
|
-
|
|
15
|
-
- `DateTime.parse(str)
|
|
16
|
-
|
|
17
|
-
읽기 전용
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
산술 메서드(새 인스턴스 반환):
|
|
29
|
-
- `addYears/addMonths(n)` — `setYear/setMonth` 경유라 말일 보정 규칙을 따름.
|
|
30
|
-
- `addDays/addHours/addMinutes/addSeconds/addMilliseconds(n)` — 음수 가능. 시 이하는 tick 기반 가산이라 DST 경계를 그대로 통과.
|
|
31
|
-
|
|
32
|
-
포맷:
|
|
33
|
-
- `toFormatString(formatStr): string` — 포맷 문자열로 변환(아래 `dt.format` 토큰 참조).
|
|
34
|
-
- `toString(): string` — `yyyy-MM-ddTHH:mm:ss.fffzzz` 형식.
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
const d = DateTime.parse("2025-01-15 10:30:00");
|
|
38
|
-
d.addDays(1).toFormatString("yyyy-MM-dd (ddd)"); // "2025-01-16 (목)"
|
|
17
|
+
- `new DateTime(year, month, day, hour?, minute?, second?, millisecond?)` — month 는 1~12(내부에서 0-base 변환). 시·분·초·밀리초 생략 시 0.
|
|
18
|
+
- `new DateTime(tick)` — 밀리초 tick.
|
|
19
|
+
- `new DateTime(date)` — JS Date 복제.
|
|
20
|
+
|
|
21
|
+
- `DateTime.parse(str)`: → DateTime — 지원 형식: `yyyy-MM-dd HH:mm:ss[.fff]`, `yyyyMMddHHmmss`, `yyyy-MM-dd AM/PM HH:mm:ss`, 한국어 `yyyy-MM-dd 오전/오후 HH:mm:ss`, ISO 8601.
|
|
22
|
+
|
|
23
|
+
getter: `year`·`month`(1~12)·`day`·`hour`·`minute`·`second`·`millisecond`·`tick`·`dayOfWeek`(일~토=0~6)·`timezoneOffsetMinutes`(UTC 대비 분, KST=+540)·`isValid`·`date`(내부 Date, 읽기 전용).
|
|
24
|
+
|
|
25
|
+
불변 변환(새 인스턴스): `setYear`·`setMonth`·`setDay`·`setHour`·`setMinute`·`setSecond`·`setMillisecond`. 산술(새 인스턴스): `addYears`·`addMonths`·`addDays`·`addHours`·`addMinutes`·`addSeconds`·`addMilliseconds`.
|
|
26
|
+
|
|
27
|
+
- `setMonth(month)` / `addMonths` — 대상 월의 일수가 현재 일보다 적으면 그 달 마지막 일로 보정(1/31 → setMonth(2) → 2/28|29). 범위 밖 월은 연도로 캐리.
|
|
28
|
+
- `setDay(day)` — 범위 밖 일은 JS Date 규칙대로 다음/이전 월로 넘어감.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { DateTime } from "@simplysm/core-common";
|
|
32
|
+
const at = DateTime.parse("2025-01-15 10:30:00");
|
|
33
|
+
at.addDays(3).toFormatString("yyyy-MM-dd HH:mm"); // "2025-01-18 10:30"
|
|
39
34
|
```
|
|
40
35
|
|
|
41
36
|
## DateOnly
|
|
42
37
|
|
|
43
|
-
시간
|
|
44
|
-
|
|
45
|
-
생성자: `new DateOnly()`(오늘) / `(year, month, day)` / `(tick)` / `(date)` — 모두 시간 부분을 버리고 자정으로 정규화.
|
|
38
|
+
시간 없는 날짜(yyyy-MM-dd) 불변 클래스.
|
|
46
39
|
|
|
47
|
-
|
|
40
|
+
생성자: `new DateOnly()`(오늘) / `(year, month, day)` / `(tick)` / `(date)`.
|
|
48
41
|
|
|
49
|
-
|
|
42
|
+
- `DateOnly.parse(str)`: → DateOnly — `yyyy-MM-dd`·`yyyyMMdd`(타임존 무관, 문자열에서 직접 추출)·ISO 8601(UTC 해석 후 로컬 변환). 서버/클라 타임존이 다르면 `yyyy-MM-dd` 형식 권장.
|
|
50
43
|
|
|
51
|
-
|
|
44
|
+
getter: `year`·`month`·`day`·`tick`·`dayOfWeek`·`isValid`·`date`. 불변 변환: `setYear`·`setMonth`·`setDay`(DateTime 과 동일한 월말/캐리 보정). 산술: `addYears`·`addMonths`·`addDays`.
|
|
52
45
|
|
|
53
|
-
주차 계산
|
|
54
|
-
- `
|
|
55
|
-
- `
|
|
56
|
-
- `
|
|
57
|
-
- `
|
|
58
|
-
- `DateOnly.getDateByYearWeekSeq(arg, weekStartDay?, minDaysInFirstWeek?)
|
|
46
|
+
주차 계산(ISO 8601 기본: weekStartDay=1 월요일, minDaysInFirstWeek=4):
|
|
47
|
+
- `getWeekSeqOfYear(weekStartDay?, minDaysInFirstWeek?)`: → `{ year, weekSeq }` — 해당 연도 내 주차 번호.
|
|
48
|
+
- `getWeekSeqOfMonth(weekStartDay?, minDaysInFirstWeek?)`: → `{ year, monthSeq, weekSeq }` — 해당 월 내 주차 번호.
|
|
49
|
+
- `getWeekSeqStartDate(weekStartDay?, minDaysInFirstWeek?)`: → DateOnly — 이 날짜가 속한 주의 시작일.
|
|
50
|
+
- `getBaseYearMonthSeqForWeekSeq(weekStartDay?, minDaysInFirstWeek?)`: → `{ year, monthSeq }` — 주차 귀속 기준 연·월(주가 걸친 경우 어느 달로 셈할지).
|
|
51
|
+
- `DateOnly.getDateByYearWeekSeq(arg, weekStartDay?, minDaysInFirstWeek?)`: → DateOnly — `arg = { year, month?, weekSeq }` 로 그 주의 시작일을 역산.
|
|
59
52
|
|
|
60
|
-
|
|
53
|
+
옵션 풀이:
|
|
54
|
+
- weekStartDay: 0~6 — 주 시작 요일. 0=일요일(미국식), 1=월요일(ISO, 기본). 달력 표시 기준에 맞춤.
|
|
55
|
+
- minDaysInFirstWeek: 1~7 — 첫 주로 인정할 최소 일수. 4=ISO(주의 과반), 1=시작일 포함 즉시 1주차(미국식).
|
|
61
56
|
|
|
62
|
-
```
|
|
63
|
-
|
|
57
|
+
```ts
|
|
58
|
+
import { DateOnly } from "@simplysm/core-common";
|
|
59
|
+
new DateOnly(2025, 1, 6).getWeekSeqOfYear(); // { year: 2025, weekSeq: 2 }
|
|
64
60
|
```
|
|
65
61
|
|
|
66
62
|
## Time
|
|
67
63
|
|
|
68
|
-
날짜
|
|
69
|
-
|
|
70
|
-
생성자: `new Time()`(현재 시각의 시간부) / `(hour, minute, second?, millisecond?)` / `(tick)`(하루 내 밀리초) / `(date)`(Date 의 시간부만).
|
|
71
|
-
|
|
72
|
-
- `Time.parse(str): Time` — `HH:mm:ss(.fff)`, `AM/PM HH:mm:ss`, ISO 8601(시간부만 추출) 지원. 실패 시 `ArgumentError`.
|
|
64
|
+
날짜 없는 시간(HH:mm:ss.fff) 불변 클래스. 24시간 초과·음수 tick 은 자동으로 0~24h 범위로 순환 정규화됨.
|
|
73
65
|
|
|
74
|
-
|
|
66
|
+
생성자: `new Time()`(현재 시각) / `(hour, minute, second?, millisecond?)` / `(tick)` / `(date)`(Date 의 시간부만).
|
|
75
67
|
|
|
76
|
-
|
|
77
|
-
산술: `addHours/addMinutes/addSeconds/addMilliseconds(n)` — 24시간 순환(23:30 + 1h → 00:30).
|
|
68
|
+
- `Time.parse(str)`: → Time — `HH:mm:ss[.fff]`·`AM/PM HH:mm:ss`·ISO 8601(시간부만 추출).
|
|
78
69
|
|
|
79
|
-
|
|
70
|
+
getter: `hour`·`minute`·`second`·`millisecond`·`tick`·`isValid`. 불변 변환: `setHour`·`setMinute`·`setSecond`·`setMillisecond`. 산술: `addHours`·`addMinutes`·`addSeconds`·`addMilliseconds` (모두 24시간 순환 — 23:30 에 +1h → 00:30).
|
|
80
71
|
|
|
81
|
-
## dt (
|
|
72
|
+
## dt 네임스페이스 (날짜/시간 포맷)
|
|
82
73
|
|
|
83
|
-
`
|
|
74
|
+
`toFormatString` 이 내부적으로 쓰는 포맷 토큰 정의. 직접 호출도 가능.
|
|
84
75
|
|
|
85
|
-
- `dt.format(formatString, args)
|
|
86
|
-
- `dt.normalizeMonth(year, month, day)
|
|
87
|
-
- `dt.convert12To24(rawHour, isPM)
|
|
88
|
-
- 타입 `dt.DtNormalizedMonth = { year
|
|
76
|
+
- `dt.format(formatString, args)`: → string — `args = { year?, month?, day?, hour?, minute?, second?, millisecond?, timezoneOffsetMinutes? }` 중 주어진 구성요소만 치환. C# 스타일 토큰 사용.
|
|
77
|
+
- `dt.normalizeMonth(year, month, day)`: → `{ year, month, day }` — 범위 밖 월을 연도로 캐리하고 일을 월말로 보정. `set*Month` 구현 기반.
|
|
78
|
+
- `dt.convert12To24(rawHour, isPM)`: → number — 12시간제(1~12)+오전/오후 → 24시간제(0~23). 12 AM=0, 12 PM=12.
|
|
79
|
+
- 타입 `dt.DtNormalizedMonth` = `{ year; month; day }`.
|
|
89
80
|
|
|
90
|
-
포맷
|
|
81
|
+
포맷 토큰: `yyyy`/`yy`(연), `MM`/`M`(월), `ddd`(요일 일~토)/`dd`/`d`(일), `tt`(AM/PM), `hh`/`h`(12시간), `HH`/`H`(24시간), `mm`/`m`(분), `ss`/`s`(초), `fff`/`ff`/`f`(밀리초), `zzz`(±HH:mm)/`zz`(±HH)/`z`(±H, 타임존 오프셋).
|
|
91
82
|
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
// "2024-03-15
|
|
83
|
+
```ts
|
|
84
|
+
import { dt } from "@simplysm/core-common";
|
|
85
|
+
dt.format("yyyy-MM-dd (ddd)", { year: 2024, month: 3, day: 15 }); // "2024-03-15 (금)"
|
|
95
86
|
```
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @simplysm/core-common — 에러 클래스
|
|
2
|
+
|
|
3
|
+
`throw` 를 던지거나, 에러 원인을 체인으로 감싸거나, catch 에서 `instanceof` 로 분기할 때 함께 읽히는 묶음. 모두 `SdError` 를 상속하므로 `instanceof SdError` 로 한꺼번에 잡을 수 있음.
|
|
4
|
+
|
|
5
|
+
## SdError
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
class SdError extends Error {
|
|
9
|
+
override cause?: Error;
|
|
10
|
+
constructor(cause: Error, ...messages: string[]); // 원인 에러를 감싸기
|
|
11
|
+
constructor(...messages: string[]); // 메시지만으로 생성
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
ES2024 `cause` 를 활용한 트리형 에러. 메시지는 **역순으로** `" => "` 로 결합됨(상위 메시지가 앞).
|
|
16
|
+
|
|
17
|
+
- cause: Error — 첫 인자가 Error 면 원인 에러로 보존(`this.cause`). 원인 에러의 stack 이 현재 stack 뒤에 `---- cause stack ----` 로 이어 붙음. 하위 호출에서 받은 에러를 상위 문맥으로 감쌀 때.
|
|
18
|
+
- ...messages: string[] — 문맥 메시지들. `new SdError(err, "API 호출 실패", "사용자 로드 실패")` → `"사용자 로드 실패 => API 호출 실패 => 원본 메시지"`. null/undefined 메시지는 제외됨.
|
|
19
|
+
- `name` 은 `"SdError"`. V8(Node·Chrome)에서 `captureStackTrace` 로 생성자 프레임 제거.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { SdError } from "@simplysm/core-common";
|
|
23
|
+
try {
|
|
24
|
+
await fetch(url);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
throw new SdError(err, "API 호출 실패", "사용자 로드 실패");
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
주의: 첫 인자가 Error 가 아니면(문자열·기타) cause 없이 메시지로만 취급됨. `new SdError("잘못된 상태", "처리 불가")` → `"처리 불가 => 잘못된 상태"`.
|
|
31
|
+
|
|
32
|
+
## ArgumentError
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
class ArgumentError extends SdError {
|
|
36
|
+
constructor(argObj: Record<string, unknown>);
|
|
37
|
+
constructor(message: string, argObj: Record<string, unknown>);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
유효하지 않은 인자를 받았을 때 던지는 에러. 디버깅을 위해 인자 객체를 **YAML 형식**으로 메시지에 붙임. `name` 은 `"ArgumentError"`.
|
|
42
|
+
|
|
43
|
+
- argObj: Record<string, unknown> — 메시지에 YAML 로 직렬화해 포함할 인자값들. 어떤 입력이 문제였는지 드러낼 때.
|
|
44
|
+
- message: string — 커스텀 머리말. 생략 시 `"잘못된 인자입니다."` 사용.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { ArgumentError } from "@simplysm/core-common";
|
|
48
|
+
throw new ArgumentError("유효하지 않은 UUID 형식입니다.", { uuid });
|
|
49
|
+
// 메시지: "유효하지 않은 UUID 형식입니다.\n\nuuid: ..."
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
이 패키지 내부 검증(Uuid·bytes·obj 체인 등)에서 이미 광범위하게 throw 하므로, 유효성 위반은 직접 처리하지 말고 그대로 전파하는 편이 일관적.
|
|
53
|
+
|
|
54
|
+
## NotImplementedError
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
class NotImplementedError extends SdError {
|
|
58
|
+
constructor(message?: string);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
아직 구현되지 않은 기능이 호출됐을 때. 메시지는 `"미구현"` 또는 `"미구현: <message>"`. `name` 은 `"NotImplementedError"`. 추상 메서드 스텁, 미구현 분기에 사용.
|
|
63
|
+
|
|
64
|
+
- message?: string — 무엇이 미구현인지 추가 설명. 예: `throw new NotImplementedError(\`타입 ${type} 처리\`)`.
|
|
65
|
+
|
|
66
|
+
## TimeoutError
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
class TimeoutError extends SdError {
|
|
70
|
+
constructor(count?: number, message?: string);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
대기 시간 초과 에러. 메시지는 `"대기 시간 초과"` + (count 있으면 `(N회 시도)`) + (message 있으면 `: <message>`). `name` 은 `"TimeoutError"`.
|
|
75
|
+
|
|
76
|
+
- count?: number — 시도 횟수. `wait.until(...)` 이 최대 시도 초과 시 자동으로 이 에러를 throw(시도 횟수를 넣어).
|
|
77
|
+
- message?: string — 무엇을 기다리다 초과했는지 추가 설명.
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { TimeoutError, wait } from "@simplysm/core-common";
|
|
81
|
+
try {
|
|
82
|
+
await wait.until(() => isReady, 100, 50);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
if (err instanceof TimeoutError) { /* 타임아웃 처리 */ }
|
|
85
|
+
}
|
|
86
|
+
```
|
|
@@ -1,53 +1,71 @@
|
|
|
1
1
|
# @simplysm/core-common — obj 네임스페이스
|
|
2
2
|
|
|
3
|
-
`import { obj } from "@simplysm/core-common"
|
|
4
|
-
|
|
5
|
-
## clone
|
|
6
|
-
|
|
7
|
-
- `obj.clone(source)
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- `obj.
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- `obj.
|
|
27
|
-
|
|
28
|
-
|
|
3
|
+
`import { obj } from "@simplysm/core-common"` 로 접근하는 객체 조작 유틸. 깊은 복사/비교/병합, 체인 경로 접근, key 변환을 할 때 함께 읽힘. 깊은 연산은 커스텀 값 타입(DateTime·DateOnly·Time·Uuid·Uint8Array)·Date·RegExp·Map·Set·Error 를 인지하고 순환 참조를 처리함.
|
|
4
|
+
|
|
5
|
+
## clone
|
|
6
|
+
|
|
7
|
+
- `obj.clone(source)`: → 동일 타입 — 깊은 복사. 순환 참조 지원. Date/DateTime/DateOnly/Time/Uuid/Uint8Array/RegExp/Array/Map/Set/Error(cause·커스텀 속성 포함) 및 일반 객체(프로토타입 체인 유지)를 복제.
|
|
8
|
+
- 주의: 함수·Symbol 은 복사 안 되고 참조 유지. WeakMap/WeakSet 미지원(빈 객체화). getter/setter 는 현재 값으로 평가되어 복사(접근자 자체는 복사 안 됨).
|
|
9
|
+
|
|
10
|
+
## equal
|
|
11
|
+
|
|
12
|
+
- `obj.equal(source, target, options?)`: → boolean — 깊은 동등성 비교. Date/날짜타입(tick)/Uuid(문자열)/RegExp/Array/Map/Set/일반 객체를 인지. null/undefined 인 속성은 비교에서 제외(없는 것으로 취급).
|
|
13
|
+
|
|
14
|
+
옵션(`EqualOptions`):
|
|
15
|
+
- topLevelIncludes?: string[] — 비교할 key 화이트리스트(최상위 객체 속성에만 적용). 일부 필드만 같으면 OK 로 볼 때.
|
|
16
|
+
- topLevelExcludes?: string[] — 비교에서 뺄 key(최상위만). `updatedAt` 같은 변동 필드 무시할 때.
|
|
17
|
+
- ignoreArrayIndex?: boolean — true 면 배열 순서 무시(같은 다중집합인지). O(n²). `[1,2,3]==[3,2,1]`.
|
|
18
|
+
- shallow?: boolean — true 면 1단계만 참조 비교. 대용량에서 성능 우선일 때.
|
|
19
|
+
- 주의: include/exclude 는 객체 속성 key 에만 적용. Map 의 key 는 항상 전부 비교됨.
|
|
20
|
+
|
|
21
|
+
## merge / merge3
|
|
22
|
+
|
|
23
|
+
- `obj.merge(source, target, opt?)`: → `Source & Target` — 깊은 병합(원본 불변, 새 객체 반환). target 값으로 source 를 덮어쓰되 객체/Map 은 재귀 병합. 날짜타입·Uuid·Uint8Array 는 통째로 교체.
|
|
24
|
+
- opt.arrayProcess?: `"replace" | "concat"` — 배열 처리. `"replace"`(기본)=target 배열로 교체, `"concat"`=합치고 Set 으로 중복 제거(객체는 참조 비교).
|
|
25
|
+
- opt.useDelTargetNull?: boolean — true 면 target 값이 null 일 때 해당 key 를 결과에서 삭제. 패치에서 "필드 제거"를 표현할 때.
|
|
26
|
+
- `obj.merge3(source, origin, target, optionsObj?)`: → `{ conflict, result }` — 3-way 병합(공통 조상 origin 기준). source 만 바뀌면 source, target 만 바뀌면 target, 둘 다 같으면 그 값, 셋 다 다르면 conflict=true(origin 유지). optionsObj 는 key 별 비교 옵션(`Merge3KeyOptions`: keys/excludes/ignoreArrayIndex). 동시 편집 충돌 감지에 사용.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { obj } from "@simplysm/core-common";
|
|
30
|
+
const merged = obj.merge(base, patch, { arrayProcess: "concat", useDelTargetNull: true });
|
|
31
|
+
const { conflict, result } = obj.merge3(mine, origin, theirs);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## omit / pick
|
|
35
|
+
|
|
36
|
+
- `obj.omit(item, omitKeys)`: → `Omit<T,K>` — 지정 key 제외한 새 객체.
|
|
37
|
+
- `obj.omitByFilter(item, omitKeyFn)`: → T — `omitKeyFn(key)` 가 true 인 key 제외(예: `_` 로 시작하는 내부 속성).
|
|
38
|
+
- `obj.pick(item, pickKeys)`: → `Pick<T,K>` — 지정 key 만 남긴 새 객체.
|
|
29
39
|
|
|
30
40
|
## 체인 경로 접근
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
- `obj.getChainValueByDepth(target, key, depth, optional?)` — 같은 key 로 `depth` 단계 하강(예: `parent` 로 2단계). `depth<1` 이면 `ArgumentError`.
|
|
34
|
-
- `obj.setChainValue(target, chain, value)` — 경로로 값 설정(중간 객체 자동 생성). 빈 chain 이면 `ArgumentError`.
|
|
35
|
-
- `obj.deleteChainValue(target, chain)` — 경로로 값 삭제. 중간 경로가 없으면 조용히 반환.
|
|
42
|
+
문자열 경로(`"a.b[0].c"`)로 중첩 값 접근. `?`·`!`·따옴표는 무시됨.
|
|
36
43
|
|
|
37
|
-
|
|
44
|
+
- `obj.getChainValue(o, chain)` / `getChainValue(o, chain, true)`: → unknown — 경로 값 조회. 세 번째 `true` 면 중간 null/undefined 를 만나도 에러 없이 undefined.
|
|
45
|
+
- `obj.getChainValueByDepth(o, key, depth, optional?)`: → 값 — 같은 key 로 depth 단계 하강(예: `parent` 를 2번). depth<1 이면 ArgumentError. optional 처리는 위와 동일.
|
|
46
|
+
- `obj.setChainValue(o, chain, value)`: → void — 경로에 값 설정(중간 객체 자동 생성). 빈 chain 이면 ArgumentError.
|
|
47
|
+
- `obj.deleteChainValue(o, chain)`: → void — 경로 값 삭제(중간 경로 없으면 조용히 반환).
|
|
38
48
|
|
|
39
|
-
|
|
40
|
-
- `obj.clear(target)` — 모든 key 삭제(원본 수정).
|
|
41
|
-
- `obj.nullToUndefined(target)` — `null` → `undefined` 재귀 변환(원본 수정, 순환 참조 안전). 커스텀 날짜/Uuid 타입은 그대로 둠. simplysm 의 null-free 규칙용.
|
|
42
|
-
- `obj.unflatten(flatObj)` — `{ "a.b.c": 1 }` → `{ a: { b: { c: 1 } } }`.
|
|
49
|
+
## 정리 유틸 (@mutates)
|
|
43
50
|
|
|
44
|
-
|
|
51
|
+
- `obj.clearUndefined(o)`: → T — null/undefined 값 key 를 원본에서 삭제.
|
|
52
|
+
- `obj.clear(o)`: → 빈 객체 — 모든 key 삭제.
|
|
53
|
+
- `obj.nullToUndefined(o)`: → `T | undefined` — null 을 undefined 로 재귀 변환(순환 안전). 날짜타입·Uuid 는 통과. simplysm 의 null-free 규칙 적용에 사용.
|
|
54
|
+
- `obj.unflatten(flatObj)`: → 중첩 객체 — `{ "a.b.c": 1 }` → `{ a: { b: { c: 1 } } }`.
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
- `obj.OptionalToUndef<T>` — optional 속성을 `필수 + undefined` 유니온으로(역변환).
|
|
56
|
+
## 타입 안전 Object.* 와 변환
|
|
48
57
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
- `obj.keys(o)`: → `(keyof T)[]` — 타입 안전 `Object.keys`.
|
|
59
|
+
- `obj.entries(o)`: → `Entries<T>` — 타입 안전 `Object.entries`(튜플 타입 보존).
|
|
60
|
+
- `obj.fromEntries(entryPairs)`: → 객체 — 타입 안전 `Object.fromEntries`.
|
|
61
|
+
- `obj.map(o, fn)`: → 새 객체 — 각 엔트리를 `fn(key, value) => [newKey | null, newValue]` 로 변환. newKey 가 null 이면 기존 key 유지(값만 변환). key+값 동시 변환 가능.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
obj.map(colors, (key, rgb) => [`${key}Light`, `rgb(${rgb})`]);
|
|
53
65
|
```
|
|
66
|
+
|
|
67
|
+
## 함께 export 되는 타입 유틸
|
|
68
|
+
|
|
69
|
+
- `UndefToOptional<T>` — `undefined` 를 포함한 속성을 optional(`?`)로 변환.
|
|
70
|
+
- `OptionalToUndef<T>` — optional 속성을 `필수 + undefined` union 으로 변환.
|
|
71
|
+
- 옵션 타입: `EqualOptions`·`MergeOptions`·`Merge3KeyOptions`.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @simplysm/core-common — 직렬화 / Worker 전송
|
|
2
|
+
|
|
3
|
+
커스텀 타입(DateTime·DateOnly·Time·Uuid·Map·Set·Error·Uint8Array 등)을 포함한 데이터를 JSON·XML·바이트·Worker 메시지로 주고받을 때 함께 읽히는 묶음. JSON·transfer 는 `__type__` 태그 방식으로 표준 직렬화가 잃어버리는 타입을 복원함.
|
|
4
|
+
|
|
5
|
+
## json 네임스페이스
|
|
6
|
+
|
|
7
|
+
- `json.stringify(obj, options?)`: → string — 커스텀 타입 보존 JSON 직렬화. Date/DateTime/DateOnly/Time/Uuid/Set/Map/Error/Uint8Array 를 `{ __type__, data }` 형태로 변환. 전역 프로토타입을 건드리지 않아 Worker 환경에서도 안전. 순환 참조면 TypeError.
|
|
8
|
+
- options.space?: `string | number` — 들여쓰기(숫자=공백 수, 문자열=들여쓰기 문자).
|
|
9
|
+
- options.replacer?: `(key, value) => unknown` — 기본 타입 변환 **전에** 호출되는 커스텀 변환.
|
|
10
|
+
- options.redactBytes?: boolean — true 면 Uint8Array 내용을 `"__hidden__"` 로 대체(로깅용). 이 결과는 `json.parse` 로 복원 불가.
|
|
11
|
+
- `json.parse<T>(json)`: → T — `json.stringify` 결과 역직렬화. `__type__` 태그를 보고 원래 타입 복원. **모든 JSON null 은 undefined 로 변환**됨(null-free 규칙). `redactBytes` 로 가려진 Uint8Array 를 만나면 SdError. 파싱 실패 시 SdError(개발 모드 `env("DEV")` 이면 전체 JSON, 운영이면 길이만 메시지에 포함).
|
|
12
|
+
- 주의: 사용자 데이터에 `{ __type__: "Date"|..., data: ... }` 형태가 우연히 들어 있으면 의도치 않게 타입으로 변환될 수 있음.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { json } from "@simplysm/core-common";
|
|
16
|
+
const text = json.stringify({ at: new DateTime(), ids: new Set([1, 2]) });
|
|
17
|
+
const back = json.parse<{ at: DateTime; ids: Set<number> }>(text); // 타입 복원
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## transfer 네임스페이스 (Worker 전송)
|
|
21
|
+
|
|
22
|
+
`structuredClone` 이 못 다루는 커스텀 타입을 Worker 로 보내기 위한 인코딩/디코딩. `postMessage` 의 transferList(zero-copy)와 연동.
|
|
23
|
+
|
|
24
|
+
- `transfer.encode(obj)`: → `{ result, transferList }` — 직렬화 가능한 형태로 변환. Uint8Array 의 ArrayBuffer 를 transferList 에 모아 zero-copy 전송 준비(SharedArrayBuffer 는 제외). Date/DateTime/DateOnly/Time/Uuid/RegExp/Error(cause·code·detail 포함)는 `__type__` 태그로 변환, Array/Map/Set/일반 객체는 재귀. 같은 객체 재참조는 캐시 재사용. **순환 참조면 TypeError(경로 포함)**.
|
|
25
|
+
- `transfer.decode(obj)`: → unknown — Worker 수신 데이터를 커스텀 타입으로 복원(encode 의 역).
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { transfer } from "@simplysm/core-common";
|
|
29
|
+
const { result, transferList } = transfer.encode(data);
|
|
30
|
+
worker.postMessage(result, transferList);
|
|
31
|
+
// worker 측: const decoded = transfer.decode(event.data);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
json 과의 차이: transfer 는 날짜를 tick(숫자)로 인코딩하고 RegExp 를 지원하며 Uint8Array 를 변환 없이 transferList 로 넘김(메모리 효율). 문자열 산출물이 필요하면 json, Worker 간 객체 전송이면 transfer.
|
|
35
|
+
|
|
36
|
+
## bytes 네임스페이스 (Uint8Array 인코딩)
|
|
37
|
+
|
|
38
|
+
- `bytes.concat(arrays)`: → Bytes — 여러 Uint8Array 결합.
|
|
39
|
+
- `bytes.toHex(b)`: → string — 소문자 hex 문자열.
|
|
40
|
+
- `bytes.fromHex(hex)`: → Bytes — hex(대소문자 허용)→바이트. 홀수 길이·비 hex 문자면 ArgumentError.
|
|
41
|
+
- `bytes.toBase64(b)`: → string — Base64 인코딩(표준 패딩 `=`).
|
|
42
|
+
- `bytes.fromBase64(b64)`: → Bytes — Base64 디코딩. 공백·패딩 정규화 후 비 base64 문자·잘못된 길이면 ArgumentError.
|
|
43
|
+
|
|
44
|
+
## xml 네임스페이스
|
|
45
|
+
|
|
46
|
+
`fast-xml-parser` 래퍼. 속성은 `$` 객체, 텍스트 노드는 `_` key, 자식 요소는 배열로 표현.
|
|
47
|
+
|
|
48
|
+
- `xml.parse(str, options?)`: → unknown — XML→객체. `options.stripTagPrefix?: boolean` true 면 태그의 네임스페이스 접두사(`ns:tag`→`tag`) 제거(속성 접두사는 유지).
|
|
49
|
+
- `xml.stringify(obj, options?)`: → string — 객체→XML. options 는 `fast-xml-parser` 의 `XmlBuilderOptions`(선택).
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { xml } from "@simplysm/core-common";
|
|
53
|
+
xml.parse('<root id="1"><item>hello</item></root>');
|
|
54
|
+
// { root: { $: { id: "1" }, item: [{ _: "hello" }] } }
|
|
55
|
+
```
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# @simplysm/core-node
|
|
2
2
|
|
|
3
|
-
Node.js
|
|
3
|
+
Node.js 런타임 전용 유틸·기능 모음. `@simplysm/core-common` 위에 Node API(`fs`/`path`/`child_process`/`worker_threads`/`chokidar`/`consola`)를 얹은 계층이므로 브라우저에서는 사용 불가.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`cpx`/`fsx`/`pathx` 는 `export * as` 네임스페이스로 노출되므로 항상 접두사로 호출한다 (`import { fsx } from "@simplysm/core-node"` → `fsx.read(...)`). 나머지(FsWatcher, consola 셋업, worker)는 named export.
|
|
6
6
|
|
|
7
7
|
## 사용 트리거 인덱스
|
|
8
8
|
|
|
9
|
-
- **fsx** — 파일/디렉토리 존재
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **FsWatcher** —
|
|
13
|
-
- **
|
|
14
|
-
- **Worker / createWorker** — worker_threads 를 타입 안전한 메서드
|
|
9
|
+
- **fsx** — 파일/디렉토리 존재 확인·생성·삭제·복사·읽기/쓰기(텍스트·바이너리·JSON)·stat·glob·부모 탐색을 동기/비동기 쌍으로 다룰 때. 모든 오류를 `SdError(원인, 경로)` 로 감싸 throw. 자세히: [fsx.md](./fsx.md)
|
|
10
|
+
- **pathx** — 경로를 POSIX(슬래시)로 정규화하거나, 하위경로 판정·디렉토리 치환·확장자 제거 basename·타겟 필터링 같은 경로 문자열 가공이 필요할 때. 자세히: [pathx.md](./pathx.md)
|
|
11
|
+
- **cpx** — 외부 명령을 실행해 stdout/stderr 를 OS 인코딩으로 디코딩해 받을 때(`spawn`/`spawnSync`), 또는 OS 코드페이지 인코딩 감지가 필요할 때. exitCode≠0 자동 throw. 자세히: [cpx.md](./cpx.md)
|
|
12
|
+
- **FsWatcher / FsWatcherEvent / FsWatcherChangeInfo** — glob 경로를 chokidar 로 감시하며 짧은 시간 내 이벤트를 병합해 콜백 한 번으로 받을 때(watch 빌드 등). 자세히: [fs-watcher.md](./fs-watcher.md)
|
|
13
|
+
- **setupConsola / PrettyReporter / createFileReporter / FileReporterOptions / SetupConsolaOptions / withMaxLevel** — Node 진입점(서버·CLI)에서 consola 전역 로거의 콘솔/파일 출력 형식을 환경별로 1회 셋업하거나 reporter 를 커스텀할 때. 자세히: [consola.md](./consola.md)
|
|
14
|
+
- **Worker / createWorker / WorkerProxy / WorkerModule / PromisifyMethods / WorkerRequest / WorkerResponse** — worker_threads 를 타입 안전한 메서드 호출·이벤트·로그 전달 프록시로 쓸 때. 자세히: [worker.md](./worker.md)
|
|
15
|
+
|
|
16
|
+
위 6개 군은 사용 시점·컨텍스트가 분리되어 각각 별도 `.md` 로 분할됨. README 인라인 군 없음.
|
|
@@ -1,51 +1,48 @@
|
|
|
1
1
|
# @simplysm/core-node — consola 로깅 설정
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`consola` 글로벌 로거의 reporter 를 환경별로 구성하는 셋업과 reporter 구현 (`packages/core-node/src/features/consola/*`). 로그 출력 자체는 `@simplysm/core-common` 의 `createLogger(tag)` 로 하고(직접 `console.*`·`consola.withTag` 금지), 출력 채널·형식만 여기서 셋업한다. 콘솔용 `PrettyReporter`(색·아이콘·tag·날짜·에러 스택·box)와 일자별 rotate 되는 `createFileReporter` 를 조합한다.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Node 진입점(서버·CLI) 에서 1회 `setupConsola()` 호출** 이 일반 사용. Browser·Capacitor 진입점에서는 호출 금지(Node 전용 API) — 그쪽은 consola 기본 reporter 가 브라우저 콘솔로 출력한다.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- `opts.cli?: boolean` — true 면 CLI 모드로 취급해 dev 분기를 사용(prod 파일 전용 분기를 건너뜀).
|
|
9
|
-
- `SetupConsolaOptions` — `{ cli?: boolean }`.
|
|
7
|
+
## setupConsola
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
9
|
+
- `setupConsola(opts?: SetupConsolaOptions): void` — 환경 변수(`DEV`, `SD_DEBUG`)에 따라 `consola.level` 과 `reporters` 를 설정. 모든 분기에서 level 은 `debug` 까지 포함.
|
|
10
|
+
- `opts.cli?: boolean` — CLI 모드 여부. true 면 prod 분기를 건너뛰고 항상 콘솔 출력 경로로 감.
|
|
11
|
+
- 분기:
|
|
12
|
+
- `cli` 아니고 `DEV` 아님(prod) → 파일 reporter 만(`createFileReporter()`). 콘솔 출력 없음, debug 까지 파일 기록.
|
|
13
|
+
- `SD_DEBUG` 참(dev+디버그) → `PrettyReporter` 만, debug 까지 콘솔 출력.
|
|
14
|
+
- 그 외(dev / cli) → 파일 reporter + `info` 까지만 콘솔 출력하는 PrettyReporter(`withMaxLevel(..., LogLevels.info)`). 파일에는 debug 전부, 콘솔에는 info 이하만.
|
|
15
|
+
- `DEV`/`SD_DEBUG` 는 `parseBoolEnv` 로 해석되는 boolean 환경값(`@simplysm/core-common`).
|
|
15
16
|
|
|
16
17
|
```ts
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
consola.info("started");
|
|
18
|
+
import { setupConsola } from "@simplysm/core-node";
|
|
19
|
+
setupConsola({ cli: true }); // 진입점에서 1회
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## withMaxLevel
|
|
23
23
|
|
|
24
|
-
- `
|
|
25
|
-
- level < 2(error/warn)는 stderr, 그 외는 stdout 으로 출력.
|
|
26
|
-
- 컬러 지원은 `NO_COLOR`(있으면 끔) → `FORCE_COLOR`(있으면 켬) → TTY → Windows 순으로 자동 판정.
|
|
27
|
-
- Error 인자는 메시지 + 정리된 스택(cwd 접두 제거, `file://` 제거)으로 출력하고, `cause` 체인을 들여쓰기로 재귀 출력.
|
|
28
|
-
- `box`/`trace` 타입 로그는 별도 포맷(box 는 ` > ` 접두, trace 는 스택 부착).
|
|
29
|
-
- `formatPlain(logObj, formatOptions?): string` — 색·날짜·뱃지 여백 없이 한 엔트리를 평문(멀티라인 가능)으로 포맷. 파일 리포터 등에서 콘솔과 동일한 표현(아이콘·tag·객체 inspect·스택)을 재사용하기 위한 진입점. `formatOptions` 에 `ctx.options.formatOptions` 를 넘기면 객체 펼침(`compact`) 등이 콘솔과 일치.
|
|
24
|
+
- `withMaxLevel(reporter: ConsolaReporter, maxLevel: number): ConsolaReporter` — reporter 를 감싸 `logObj.level > maxLevel` 인 로그를 버리는 필터 래퍼. "콘솔에는 정보성만, 파일에는 전부" 같은 분리에 사용. consola `LogLevels` 숫자 기준(작을수록 심각: error 0, warn 1, info 3 등) — maxLevel 보다 큰(=덜 심각한) 로그가 잘림.
|
|
30
25
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
- `createFileReporter(options?: FileReporterOptions): ConsolaReporter` — `<cwd>/.logs/app.<YYYY-MM-DD>.log` 에 평문 라인으로 기록하는 리포터 생성. 일자 변경·크기 초과 시 회전(`app.<date>.<seq>.log`).
|
|
34
|
-
- `options.maxSize?: number` — 파일 회전 임계 바이트. 기본 20MB(`20 * 1024 * 1024`).
|
|
35
|
-
- `options.maxDays?: number` — 로그 보존 일수. 초과 일자 파일은 일자가 바뀔 때 정리됨. 기본 14.
|
|
36
|
-
- `FileReporterOptions` — `{ maxSize?: number; maxDays?: number }`.
|
|
26
|
+
## PrettyReporter
|
|
37
27
|
|
|
38
|
-
|
|
28
|
+
- `class PrettyReporter implements ConsolaReporter` — 색·아이콘·tag·날짜·에러 스택·box 를 직접 포맷하는 콘솔 reporter. level<2(error/warn)는 stderr, 그 외 stdout 으로 출력. 색 지원은 `NO_COLOR`(끔)/`FORCE_COLOR`(켬)/TTY/win32 순으로 자동 감지.
|
|
29
|
+
- `log(logObj, ctx): void` — consola 가 호출하는 reporter 인터페이스. 한 줄(또는 멀티라인) 포맷 후 스트림에 기록. error 의 `cause` 체인을 들여쓰기로 펼치고, 스택에서 cwd/`file://` 접두를 제거.
|
|
30
|
+
- `formatPlain(logObj, formatOptions?): string` — 색·날짜·뱃지 여백 **없이** 평문으로 포맷(trim). 아이콘·tag·객체 inspect·스택 표현은 콘솔과 동일하게 재사용. 파일 reporter 등이 콘솔과 같은 본문을 얻기 위한 진입점.
|
|
31
|
+
- `formatOptions?: Partial<FormatOpts>` — 콘솔과 동일한 `ctx.options.formatOptions`(예: 객체 펼침 `compact`)를 넘기면 출력이 콘솔과 일치.
|
|
39
32
|
|
|
40
|
-
##
|
|
33
|
+
## createFileReporter
|
|
41
34
|
|
|
42
|
-
- `
|
|
35
|
+
- `createFileReporter(options?: FileReporterOptions): ConsolaReporter` — `<cwd>/.logs/app.<YYYY-MM-DD>.log` 에 기록하는 reporter 생성. 본문은 `PrettyReporter.formatPlain` 으로 콘솔과 동일하게, 앞에 `타임스탬프 [TYPE]` 접두를 붙임. 날짜 변경 또는 크기 초과 시 rotate, 일자가 바뀌는 첫 기록 시 오래된 파일 정리.
|
|
36
|
+
- `options.maxSize?: number` — 파일 1개 최대 바이트. 초과 시 `app.<date>.<seq>.log` 로 분할. 기본 20MB(`20 * 1024 * 1024`).
|
|
37
|
+
- `options.maxDays?: number` — 보관 일수. cutoff(오늘 − maxDays) 이전 날짜 파일 삭제. 기본 14.
|
|
43
38
|
|
|
44
39
|
```ts
|
|
45
|
-
|
|
40
|
+
import { createFileReporter } from "@simplysm/core-node";
|
|
41
|
+
import consola from "consola";
|
|
42
|
+
consola.options.reporters = [createFileReporter({ maxSize: 5 * 1024 * 1024, maxDays: 7 })];
|
|
46
43
|
```
|
|
47
44
|
|
|
48
|
-
##
|
|
45
|
+
## FileReporterOptions / SetupConsolaOptions
|
|
49
46
|
|
|
50
|
-
-
|
|
51
|
-
-
|
|
47
|
+
- `interface FileReporterOptions { maxSize?: number; maxDays?: number }` — 위 createFileReporter 옵션 타입.
|
|
48
|
+
- `interface SetupConsolaOptions { cli?: boolean }` — 위 setupConsola 옵션 타입.
|