@simplysm/sd-claude 14.0.89 → 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 +52 -30
- package/claude/references/sd-simplysm14/apis/angular/controls.md +200 -38
- package/claude/references/sd-simplysm14/apis/angular/crud.md +41 -53
- package/claude/references/sd-simplysm14/apis/angular/directives.md +66 -22
- package/claude/references/sd-simplysm14/apis/angular/features.md +127 -40
- package/claude/references/sd-simplysm14/apis/angular/infra.md +60 -43
- package/claude/references/sd-simplysm14/apis/angular/layout.md +56 -20
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +74 -74
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +50 -40
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +55 -15
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +59 -42
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +77 -62
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +8 -7
- 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 +22 -14
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +19 -19
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +17 -17
- package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +28 -28
- package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +37 -37
- package/claude/references/sd-simplysm14/apis/core-common/README.md +87 -219
- package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +54 -98
- package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +57 -99
- package/claude/references/sd-simplysm14/apis/core-common/datetime.md +60 -103
- package/claude/references/sd-simplysm14/apis/core-common/errors.md +42 -47
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +42 -88
- package/claude/references/sd-simplysm14/apis/core-common/serialization.md +55 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +6 -7
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +17 -12
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +14 -13
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +9 -8
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +14 -13
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +4 -8
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +14 -12
- package/claude/references/sd-simplysm14/apis/excel/README.md +22 -22
- 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/orm-common/README.md +6 -8
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +118 -67
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +83 -86
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +102 -93
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +138 -81
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +49 -44
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +42 -42
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +44 -33
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +11 -10
- package/claude/references/sd-simplysm14/apis/service-client/README.md +56 -52
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +33 -28
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +23 -21
- package/claude/references/sd-simplysm14/apis/service-common/README.md +83 -48
- 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 +69 -81
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +46 -43
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +63 -37
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +40 -30
- package/claude/references/sd-simplysm14/apis/storage/README.md +17 -17
- 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-demo/SKILL.md +0 -6
- package/claude/skills/sd-docs/SKILL.md +58 -0
- package/claude/{workflows/sd-docs.rules.md → skills/sd-docs/references/subagent-prompt.md} +103 -103
- package/claude/skills/sd-impl/SKILL.md +7 -4
- package/claude/skills/sd-spec/SKILL.md +842 -15
- 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 -53
- package/claude/skills/sd-spec/references/spec-authoring.md +0 -519
- package/claude/workflows/sd-docs.js +0 -84
|
@@ -1,262 +1,130 @@
|
|
|
1
1
|
# @simplysm/core-common
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
브라우저·Node 공용 유틸리티 패키지. 날짜/시간 값 타입, 에러 클래스, 배열/객체 조작, 직렬화, 비동기 큐, 로거, 환경변수 접근을 제공. 워크스페이스 거의 모든 패키지의 기반.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- **에러 클래스** (`SdError`/`ArgumentError`/`NotImplementedError`/`TimeoutError`) — 원인 체인을 가진 에러를 throw 하거나 `instanceof` 로 분기할 때. 자세히: [errors.md](./errors.md)
|
|
8
|
-
- **날짜/시간 값 타입** (`DateTime`/`DateOnly`/`Time`, `dt` 네임스페이스) — 불변 날짜·시간 값을 만들고 파싱·산술·포맷할 때. 자세히: [datetime.md](./datetime.md)
|
|
9
|
-
- **Array 확장 메서드** (`Array.prototype` 전역 확장) — `single`/`groupBy`/`distinct`/`orderBy`/`diffs`/`toTree` 등 컬렉션 가공이 필요할 때. 자세히: [array-ext.md](./array-ext.md)
|
|
10
|
-
- **객체 유틸** (`obj` 네임스페이스, `DeepPartial`/`Type`) — 깊은 복사·동등성·병합·체인 경로 접근·타입 안전 키 순회가 필요할 때. 자세히: [obj.md](./obj.md)
|
|
11
|
-
- **JSON/Worker 직렬화** (`json`/`transfer` 네임스페이스) — 커스텀 타입(날짜·UUID·Map·Set·Error)을 보존하며 JSON 또는 Worker 메시지로 직렬화할 때. 자세히: [json-transfer.md](./json-transfer.md)
|
|
12
|
-
- **비동기 런타임** (`DebounceQueue`/`SerialQueue`/`EventEmitter`/`LazyGcMap`/`createLogger`) — 디바운스·직렬 실행·타입 안전 이벤트·자동 만료 캐시·태그 로거가 필요할 때. 자세히: [async-runtime.md](./async-runtime.md)
|
|
13
|
-
- **`Uuid`** — UUID v4 생성·검증·바이트 변환이 필요할 때. (아래 인라인 "값 타입 보조 — Uuid")
|
|
14
|
-
- **환경변수** (`env`/`parseBoolEnv`) — process.env / import.meta.env 를 런타임 무관하게 읽고 쓸 때. (아래 인라인 "환경변수")
|
|
15
|
-
- **Set/Map 확장** (`Set.prototype.adds`/`toggle`, `Map.prototype.getOrCreate`/`update`) — Set/Map 을 체이닝으로 다룰 때. (아래 인라인 "Set/Map 확장")
|
|
16
|
-
- **문자열 유틸** (`str` 네임스페이스) — 한국어 조사·케이스 변환·전각 변환·빈 문자열 가드가 필요할 때. (아래 인라인 "str")
|
|
17
|
-
- **숫자 유틸** (`num` 네임스페이스) — 느슨한 정수/실수 파싱·천단위 포맷이 필요할 때. (아래 인라인 "num")
|
|
18
|
-
- **바이트 유틸** (`bytes` 네임스페이스) — Uint8Array hex/base64/concat 변환이 필요할 때. (아래 인라인 "bytes")
|
|
19
|
-
- **경로 유틸** (`path` 네임스페이스) — 브라우저에서 POSIX 경로 join/basename/extname 이 필요할 때. (아래 인라인 "path")
|
|
20
|
-
- **XML 유틸** (`xml` 네임스페이스) — XML 파싱/직렬화가 필요할 때. (아래 인라인 "xml")
|
|
21
|
-
- **대기 유틸** (`wait` 네임스페이스) — 조건 폴링·지연이 필요할 때. (아래 인라인 "wait")
|
|
22
|
-
- **에러 메시지 추출** (`err` 네임스페이스) — catch 의 `unknown` 에서 메시지 문자열을 뽑을 때. (아래 인라인 "err")
|
|
23
|
-
- **원시 타입 추론** (`primitive` 네임스페이스, `PrimitiveType*`/`Bytes`) — 런타임 값에서 ORM 원시 타입 문자열을 얻을 때. (아래 인라인 "primitive / 공통 타입")
|
|
24
|
-
- **코드 템플릿 태그** (`js`/`ts`/`html`/`tsql`/`mysql`/`pgsql`) — IDE 하이라이팅 + 들여쓰기 정규화가 필요할 때. (아래 인라인 "템플릿 태그")
|
|
25
|
-
- **`ZipArchive`** — ZIP 읽기/쓰기/압축/해제가 필요할 때. (아래 인라인 "ZipArchive")
|
|
26
|
-
|
|
27
|
-
## 값 타입 보조 — Uuid
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
class Uuid {
|
|
31
|
-
static generate(): Uuid; // crypto.getRandomValues 기반 v4 생성
|
|
32
|
-
static fromBytes(bytes: Bytes): Uuid; // 16바이트 Uint8Array → Uuid (16바이트 아니면 ArgumentError)
|
|
33
|
-
constructor(uuid: string); // 형식 검증 후 보관 (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, 위반 시 ArgumentError)
|
|
34
|
-
toString(): string; // UUID 문자열 반환
|
|
35
|
-
toBytes(): Bytes; // 16바이트 Uint8Array 반환
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
- `generate()` — 새 랜덤 UUID 가 필요할 때(엔티티 PK 등). 암호학적으로 안전한 난수 사용.
|
|
40
|
-
- `fromBytes(bytes)` / `toBytes()` — 바이너리 저장/전송과 문자열 표현 사이를 오갈 때. 입력 바이트 길이가 16 이 아니면 `ArgumentError` throw.
|
|
41
|
-
- `new Uuid(str)` — 외부에서 받은 문자열을 검증해 값으로 승격할 때. 형식 불일치 시 `ArgumentError` throw.
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
const id = Uuid.generate();
|
|
45
|
-
const restored = new Uuid(id.toString());
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## 환경변수 — env / parseBoolEnv
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
function env(key: string): string | undefined; // 읽기: process.env 우선, 없으면 import.meta.env
|
|
52
|
-
function env(key: string, value: string): void; // 쓰기: process.env[key] = value (process 존재 시)
|
|
53
|
-
function parseBoolEnv(value: unknown): boolean; // "true"/"1"/"yes"/"on"(대소문자 무시) → true, 그 외 false
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
- `env(key)` — 단일 인자. Node 면 `process.env`, 브라우저(Vite) 면 `import.meta.env` 에서 조회. 둘 다 없으면 `undefined`. "값 없음"을 빈 문자열로 치환하지 않음.
|
|
57
|
-
- `env(key, value)` — 2번째 인자 전달 시 쓰기 모드. `process` 가 없는 환경(순수 브라우저)에서는 아무 동작 안 함.
|
|
58
|
-
- `parseBoolEnv(value)` — boolean 플래그용 환경변수를 해석할 때. 위 4개 리터럴만 true.
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
if (parseBoolEnv(env("DEV"))) { /* 개발 모드 */ }
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Set/Map 확장
|
|
65
|
-
|
|
66
|
-
전역 `Set.prototype` / `Map.prototype` 에 메서드를 추가(import 시 자동 적용, `enumerable: false`).
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
interface Set<T> {
|
|
70
|
-
adds(...values: T[]): this; // 여러 값 일괄 추가, this 반환(체이닝)
|
|
71
|
-
toggle(value: T, addOrDel?: "add" | "del"): this; // 토글: 인자 생략 시 있으면 제거/없으면 추가
|
|
72
|
-
}
|
|
73
|
-
interface Map<K, V> {
|
|
74
|
-
getOrCreate(key: K, newValue: V): V; // 값 직접 지정 (key 없을 때만 set)
|
|
75
|
-
getOrCreate(key: K, newValueFn: () => V): V; // 팩토리 지연 생성 (비싼 연산용)
|
|
76
|
-
update(key: K, updateFn: (v: V | undefined) => V): void; // 현재 값(없으면 undefined) → 새 값으로 갱신
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
- `Set.toggle(value, addOrDel)` — `addOrDel` 생략 시 존재 여부로 자동 토글, `"add"` 면 강제 추가, `"del"` 면 강제 제거. 조건부 선택 상태(`isOn ? "add" : "del"`) 표현에 사용.
|
|
81
|
-
- `Map.getOrCreate` — 2번째 인자가 함수면 팩토리로 인식되어 호출됨. 함수 자체를 값으로 저장하려면 `() => myFn` 처럼 한 번 더 감싼다.
|
|
82
|
-
- `Map.update` — key 가 없어도 `updateFn(undefined)` 가 호출되어 새 값이 set 됨. 카운터 증가(`(v) => (v ?? 0) + 1`)·배열 누적에 사용.
|
|
5
|
+
> 부수효과 주의: 이 패키지를 import 하면 `Array.prototype`·`Set.prototype`·`Map.prototype` 에 확장 메서드가 설치됨(전역 prototype 변경). 확장 메서드는 `array.toMap(...)` 처럼 메서드로 직접 호출.
|
|
83
6
|
|
|
84
|
-
|
|
85
|
-
new Set([1, 2]).adds(3, 4).toggle(2); // {1, 3, 4}
|
|
86
|
-
countMap.update("k", (v) => (v ?? 0) + 1);
|
|
87
|
-
```
|
|
7
|
+
## 사용 트리거 인덱스
|
|
88
8
|
|
|
89
|
-
|
|
9
|
+
- **에러 클래스** — `throw` 할 때, 에러 원인 체인을 만들 때, catch 에서 분기할 때. SdError/ArgumentError/NotImplementedError/TimeoutError. 자세히: [errors.md](./errors.md)
|
|
10
|
+
- **날짜/시간 값 타입** — 날짜·시간을 불변 값으로 다루거나 파싱·포맷·산술할 때. DateTime/DateOnly/Time + `dt` 포맷 네임스페이스. 자세히: [datetime.md](./datetime.md)
|
|
11
|
+
- **배열 확장 메서드** — 배열을 그룹화·정렬·중복제거·Map변환·트리화·diff/merge 할 때. `Array.prototype` 확장. 자세히: [array-ext.md](./array-ext.md)
|
|
12
|
+
- **객체 유틸 (`obj` 네임스페이스)** — 깊은 복사/비교/병합, 체인 경로 접근, key 변환을 할 때. 자세히: [obj.md](./obj.md)
|
|
13
|
+
- **직렬화/Worker 전송** — 커스텀 타입(DateTime·Uuid·Map·Set·Error 등) 포함 데이터를 JSON·XML·바이트·Worker 메시지로 주고받을 때. `json`/`xml`/`bytes`/`transfer` 네임스페이스. 자세히: [serialization.md](./serialization.md)
|
|
14
|
+
- **비동기 큐·이벤트·대기** — 디바운스/직렬 실행, 타입 안전 이벤트, 조건 대기, 자동 만료 Map 이 필요할 때. DebounceQueue/SerialQueue/EventEmitter/wait/LazyGcMap. 자세히: [async-runtime.md](./async-runtime.md)
|
|
15
|
+
- **로거** — 모듈 어디서든 로그를 찍을 때 (아래 인라인).
|
|
16
|
+
- **환경변수** — 환경변수를 읽고/쓰고/boolean 파싱할 때 (아래 인라인).
|
|
17
|
+
- **문자열/숫자/경로 유틸** — 한국어 조사, 케이스 변환, 숫자 파싱·포맷, POSIX 경로 조작 (아래 인라인).
|
|
18
|
+
- **UUID·ZIP·템플릿 태그·Set/Map 확장·공용 타입** — 그 외 단발성 유틸 (아래 인라인).
|
|
90
19
|
|
|
91
|
-
|
|
20
|
+
## 로거
|
|
92
21
|
|
|
93
|
-
|
|
94
|
-
str.getKoreanSuffix(text: string, type: "을"|"은"|"이"|"와"|"랑"|"로"|"라"): string;
|
|
95
|
-
str.replaceFullWidth(str: string): string;
|
|
96
|
-
str.toPascalCase(str: string): string;
|
|
97
|
-
str.toCamelCase(str: string): string;
|
|
98
|
-
str.toKebabCase(str: string): string;
|
|
99
|
-
str.toSnakeCase(str: string): string;
|
|
100
|
-
str.isNullOrEmpty(str: string | undefined): str is "" | undefined;
|
|
101
|
-
str.insert(str: string, index: number, insertString: string): string;
|
|
102
|
-
```
|
|
22
|
+
`createLogger(tag)` — consola 기반 lazy logger 인스턴스 생성. 모듈 레벨에서 호출해도 안전(첫 메서드 접근 시점까지 `consola.withTag` 생성을 지연하므로 이후 `setupConsola()` 의 level/reporters 변경이 반영됨).
|
|
103
23
|
|
|
104
|
-
-
|
|
105
|
-
- `replaceFullWidth(str)` — 전각 영문/숫자/공백/괄호를 반각으로. 스캔된 바코드·일본어 입력 정규화에 사용.
|
|
106
|
-
- `toPascalCase`/`toCamelCase`/`toKebabCase`/`toSnakeCase` — `-` `_` `.` 구분자 또는 대문자 경계 기준 케이스 변환. kebab/snake 는 연속 대문자를 각각 분리(`XMLParser`→`x-m-l-parser`)하고 기존 구분자는 보존.
|
|
107
|
-
- `isNullOrEmpty(str)` — 타입 가드. true 면 `"" | undefined`, false 면 비어있지 않은 `string` 으로 좁혀짐.
|
|
108
|
-
- `insert(str, index, insertString)` — 지정 위치에 삽입한 새 문자열 반환(원본 불변).
|
|
24
|
+
- tag: string — 로그 prefix 로 표시되는 태그. 형식은 `<도메인>:<역할>` 또는 단일 토큰 권장. 메시지 본문에 `[패키지명]` 수동 prefix 를 넣지 말 것 — 그 역할은 tag 가 담당.
|
|
109
25
|
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
|
|
26
|
+
```ts
|
|
27
|
+
import { createLogger } from "@simplysm/core-common";
|
|
28
|
+
const logger = createLogger("capacitor:auto-update");
|
|
29
|
+
logger.info("최신 버전 확인 중");
|
|
30
|
+
logger.error("checkPermissions 실패", err);
|
|
113
31
|
```
|
|
114
32
|
|
|
115
|
-
|
|
33
|
+
`console.*` 직접 호출·`consola.withTag()` 직접 호출 금지 — 항상 `createLogger` 사용.
|
|
116
34
|
|
|
117
|
-
|
|
118
|
-
num.parseInt(text: unknown): number | undefined; // 비숫자 제거 후 정수 (소수점 이하 버림)
|
|
119
|
-
num.parseFloat(text: unknown): number | undefined; // 비숫자 제거 후 실수
|
|
120
|
-
num.parseRoundedInt(text: unknown): number | undefined; // parseFloat 후 반올림
|
|
121
|
-
num.isNullOrEmpty(val: number | undefined): val is 0 | undefined;
|
|
122
|
-
num.format(val: number, digit?: { max?: number; min?: number }): string;
|
|
123
|
-
```
|
|
35
|
+
## 환경변수
|
|
124
36
|
|
|
125
|
-
- `
|
|
126
|
-
- `
|
|
127
|
-
- `
|
|
128
|
-
- `format(val, digit)` — `toLocaleString` 기반 천단위 구분. `digit.max` 최대 소수 자릿수, `digit.min` 최소(부족분 0 채움). `val` 이 결측이면 결과도 `undefined`(오버로드).
|
|
37
|
+
- `env(key)`: → `string | undefined` — 환경변수 읽기. `process.env[key]` 우선, 없으면 `import.meta.env[key]` fallback. Node·브라우저(Vite) 양쪽에서 동작.
|
|
38
|
+
- `env(key, value)`: → `void` — `process.env[key]` 에 값 쓰기 (Node 환경에서만 적용, 브라우저에선 무동작).
|
|
39
|
+
- `parseBoolEnv(value)`: → `boolean` — 환경변수 문자열을 boolean 으로 해석. `"true"|"1"|"yes"|"on"` (대소문자 무시) 이면 true, 그 외(빈 값·undefined 포함) false. 플래그성 env 판정에 사용.
|
|
129
40
|
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
|
|
41
|
+
```ts
|
|
42
|
+
import { env, parseBoolEnv } from "@simplysm/core-common";
|
|
43
|
+
if (parseBoolEnv(env("DEV"))) { /* 개발 모드 분기 */ }
|
|
133
44
|
```
|
|
134
45
|
|
|
135
|
-
##
|
|
46
|
+
## 문자열 유틸 (`str` 네임스페이스)
|
|
136
47
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
bytes.fromBase64(base64: string): Bytes; // 비base64 문자/잘못된 길이 → ArgumentError
|
|
143
|
-
```
|
|
48
|
+
- `str.getKoreanSuffix(text, type)`: → string — 받침 유무로 한국어 조사 선택. type: `"을"`(을/를)·`"은"`(은/는)·`"이"`(이/가)·`"와"`(과/와)·`"랑"`(이랑/랑)·`"로"`(으로/로, 받침 ㄹ 은 "로")·`"라"`(이라/라). 빈 문자열·한글 아님이면 받침 없음 조사 반환. 동적 메시지 조립에 사용.
|
|
49
|
+
- `str.replaceFullWidth(s)`: → string — 전각 영문/숫자/공백/괄호를 반각으로 변환. OCR·외부 입력 정규화에 사용.
|
|
50
|
+
- `str.toPascalCase(s)` / `toCamelCase(s)` / `toKebabCase(s)` / `toSnakeCase(s)`: → string — 케이스 변환. `-`·`_`·`.` 구분자와 대문자 경계를 인식. 코드 생성·식별자 정규화에 사용.
|
|
51
|
+
- `str.isNullOrEmpty(s)`: → `s is "" | undefined` — null/undefined/빈 문자열 판정(타입 가드). false 분기에서 non-empty string 으로 좁혀짐.
|
|
52
|
+
- `str.insert(s, index, insertString)`: → string — index 위치에 문자열 삽입한 새 문자열.
|
|
144
53
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
## path
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
path.join(...segments: string[]): string; // POSIX(슬래시) join, 중복 슬래시 정리
|
|
153
|
-
path.basename(filePath: string, ext?: string): string; // 마지막 세그먼트, ext 일치 시 제거
|
|
154
|
-
path.extname(filePath: string): string; // 확장자(점 포함), 숨김파일은 ""
|
|
54
|
+
```ts
|
|
55
|
+
import { str } from "@simplysm/core-common";
|
|
56
|
+
`${name}${str.getKoreanSuffix(name, "을")} 저장했습니다`;
|
|
155
57
|
```
|
|
156
58
|
|
|
157
|
-
|
|
158
|
-
- `basename(p, ext)` — `ext` 가 끝과 일치하면 그만큼 잘라 확장자 없는 이름 반환.
|
|
159
|
-
- `extname` — `.gitignore` 같은 선행 점 파일은 빈 문자열(`""`).
|
|
59
|
+
## 숫자 유틸 (`num` 네임스페이스)
|
|
160
60
|
|
|
161
|
-
|
|
61
|
+
- `num.parseInt(text)`: → `number | undefined` — 비숫자 문자 제거 후 정수 파싱. 소수점은 버림(`"12.34"`→12). 선행 `-` 만 음수 부호로 유지, 중간 `-` 제거(`"010-1234"`→101234). 파싱 불가면 undefined.
|
|
62
|
+
- `num.parseFloat(text)`: → `number | undefined` — 위와 동일 규칙으로 실수 파싱.
|
|
63
|
+
- `num.parseRoundedInt(text)`: → `number | undefined` — float 파싱 후 반올림한 정수. 소수 입력을 반올림 정수로 받을 때.
|
|
64
|
+
- `num.isNullOrEmpty(val)`: → `val is 0 | undefined` — null/undefined/0 판정(타입 가드). false 분기에서 0 아닌 숫자로 좁혀짐.
|
|
65
|
+
- `num.format(val, digit?)`: → string(또는 입력이 undefined 면 undefined) — 천 단위 구분자 포함 포맷. `digit.max`=최대 소수 자릿수, `digit.min`=최소 소수 자릿수(부족분 0 채움). `format(1234.567, { max: 2 })`→`"1,234.57"`.
|
|
162
66
|
|
|
163
|
-
|
|
164
|
-
xml.parse(str: string, options?: { stripTagPrefix?: boolean }): unknown;
|
|
165
|
-
xml.stringify(obj: unknown, options?: XmlBuilderOptions): string;
|
|
166
|
-
```
|
|
67
|
+
## 경로 유틸 (`path` 네임스페이스)
|
|
167
68
|
|
|
168
|
-
|
|
169
|
-
- `stringify` — `$`(속성)·`_`(텍스트) 규약으로 XML 문자열 생성. `options` 로 fast-xml-parser 빌더 옵션 덮어쓰기.
|
|
69
|
+
POSIX 스타일(슬래시 `/`)만 지원. 브라우저·Capacitor 환경용. Windows 백슬래시 경로 미지원.
|
|
170
70
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
```
|
|
71
|
+
- `path.join(...segments)`: → string — 세그먼트를 `/` 로 결합. 중간 중복 슬래시·빈 세그먼트 정리.
|
|
72
|
+
- `path.basename(filePath, ext?)`: → string — 파일명 추출. ext 가 주어지고 끝나면 그 확장자 제거.
|
|
73
|
+
- `path.extname(filePath)`: → string — 확장자 추출(`.` 포함). 숨김 파일(`.gitignore`)은 빈 문자열(Node 와 동일).
|
|
175
74
|
|
|
176
|
-
##
|
|
75
|
+
## UUID (`Uuid` 클래스)
|
|
177
76
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
77
|
+
- `Uuid.generate()`: → Uuid — `crypto.getRandomValues` 기반 암호학적 안전 UUID v4 생성.
|
|
78
|
+
- `new Uuid(uuidStr)` — 문자열로 생성. 형식 불일치면 ArgumentError throw.
|
|
79
|
+
- `Uuid.fromBytes(bytes)`: → Uuid — 16바이트 Uint8Array 로 생성. 길이≠16 이면 ArgumentError.
|
|
80
|
+
- 인스턴스: `toString()` → 문자열, `toBytes()` → 16바이트 Uint8Array.
|
|
182
81
|
|
|
183
|
-
|
|
184
|
-
- `time(ms)` — `setTimeout` 기반 지연 Promise.
|
|
82
|
+
## ZIP (`ZipArchive` 클래스)
|
|
185
83
|
|
|
186
|
-
|
|
187
|
-
await wait.until(() => ready, 100, 50); // 최대 50회(5초) 폴링
|
|
188
|
-
await wait.time(300);
|
|
189
|
-
```
|
|
84
|
+
ZIP 읽기/쓰기/압축/해제. 동일 파일 중복 해제 방지용 내부 캐시 사용. 사용 후 `close()` 필수.
|
|
190
85
|
|
|
191
|
-
|
|
86
|
+
- `new ZipArchive(data?)` — data(`Blob | Uint8Array`) 주면 읽기용, 생략하면 새 아카이브.
|
|
87
|
+
- `extractAll(progressCallback?)`: → `Promise<Map<string, Bytes | undefined>>` — 모든 파일 추출. 콜백은 `{ fileName, totalSize, extractedSize }` 진행률 수신.
|
|
88
|
+
- `get(fileName)`: → `Promise<Bytes | undefined>` — 단일 파일 추출(없으면 undefined).
|
|
89
|
+
- `exists(fileName)`: → `Promise<boolean>` — 파일 존재 여부.
|
|
90
|
+
- `write(fileName, bytes)`: → void — 파일을 캐시에 등록(아직 압축 전).
|
|
91
|
+
- `compress()`: → `Promise<Bytes>` — 캐시된 전체 파일을 ZIP 바이트로 압축. 내부적으로 `extractAll()` 호출(대용량 시 메모리 주의).
|
|
92
|
+
- `close()`: → `Promise<void>` — 리더 닫고 캐시 비움.
|
|
192
93
|
|
|
193
|
-
|
|
194
|
-
err.message(error: unknown): string; // Error 면 .message, 아니면 String(error)
|
|
195
|
-
```
|
|
94
|
+
## 템플릿 태그 (코드 하이라이팅용)
|
|
196
95
|
|
|
197
|
-
|
|
96
|
+
`js` / `ts` / `html` / `tsql` / `mysql` / `pgsql` — 모두 동일 동작: 템플릿 리터럴을 문자열로 결합하고 공통 들여쓰기를 제거(앞뒤 빈 줄 제거). IDE 하이라이팅·가독성 목적이며 SQL 이스케이프 등 기능 차이는 없음.
|
|
198
97
|
|
|
199
|
-
```
|
|
200
|
-
|
|
98
|
+
```ts
|
|
99
|
+
import { ts } from "@simplysm/core-common";
|
|
100
|
+
const code = ts`
|
|
101
|
+
interface User { name: string; }
|
|
102
|
+
`; // 들여쓰기 정규화된 문자열
|
|
201
103
|
```
|
|
202
104
|
|
|
203
|
-
##
|
|
105
|
+
## Set 확장 메서드 (`Set.prototype`)
|
|
204
106
|
|
|
205
|
-
|
|
206
|
-
|
|
107
|
+
- `set.adds(...values)`: → this — 여러 값을 한 번에 add. 체이닝 가능.
|
|
108
|
+
- `set.toggle(value, addOrDel?)`: → this — 값 토글. `addOrDel` 생략 시 있으면 제거/없으면 추가, `"add"`=강제 추가, `"del"`=강제 제거. 조건부 추가/제거를 한 줄로.
|
|
207
109
|
|
|
208
|
-
|
|
209
|
-
type PrimitiveTypeMap = { string; number; boolean; DateTime; DateOnly; Time; Uuid; Bytes };
|
|
210
|
-
type PrimitiveTypeStr = keyof PrimitiveTypeMap;
|
|
211
|
-
type PrimitiveType = PrimitiveTypeMap[PrimitiveTypeStr] | undefined;
|
|
212
|
-
```
|
|
110
|
+
## Map 확장 메서드 (`Map.prototype`)
|
|
213
111
|
|
|
214
|
-
- `
|
|
215
|
-
- `
|
|
216
|
-
- `PrimitiveType` — 원시 타입 union + `undefined`. 결측 보존을 위해 `undefined` 포함.
|
|
217
|
-
- `DeepPartial<T>` / `Type<T>` 타입 유틸은 [obj.md](./obj.md) 의 "타입 유틸리티" 참조.
|
|
112
|
+
- `map.getOrCreate(key, newValue)` / `getOrCreate(key, newValueFn)`: → V — key 없으면 값(또는 팩토리 호출 결과) 설정 후 반환, 있으면 기존 값. 주의: V 가 함수 타입이면 두 번째 인자 함수가 팩토리로 인식되어 호출됨 — 함수를 값으로 저장하려면 `() => myFn` 으로 감쌀 것.
|
|
113
|
+
- `map.update(key, updateFn)`: → void — `updateFn(현재값 | undefined)` 결과로 값 설정. key 가 없어도 호출됨. 카운터 증가·배열 누적에 사용. 예: `m.update(k, v => (v ?? 0) + 1)`.
|
|
218
114
|
|
|
219
|
-
##
|
|
115
|
+
## 공용 타입 (`common.types`)
|
|
220
116
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
117
|
+
- `Bytes` = `Uint8Array` — 바이너리 데이터 별칭. Buffer 대신 사용.
|
|
118
|
+
- `PrimitiveTypeMap` — 원시 타입 문자열 → 실제 타입 매핑(`string`/`number`/`boolean`/`DateTime`/`DateOnly`/`Time`/`Uuid`/`Bytes`). orm-common 과 공유.
|
|
119
|
+
- `PrimitiveTypeStr` = `keyof PrimitiveTypeMap` — 원시 타입 문자열 key union.
|
|
120
|
+
- `PrimitiveType` — 모든 원시 타입 값의 union(+ undefined).
|
|
121
|
+
- `DeepPartial<T>` — 모든 속성을 재귀적으로 optional 화. 원시/날짜 타입은 그대로 두고 object/array 만 재귀.
|
|
122
|
+
- `Type<TInstance>` — 클래스 생성자 타입(`new (...args) => TInstance`). DI·팩토리·instanceof 체크에 사용.
|
|
224
123
|
|
|
225
|
-
|
|
124
|
+
## 원시 타입 추론 (`primitive` 네임스페이스)
|
|
226
125
|
|
|
227
|
-
|
|
228
|
-
const sql = mysql`
|
|
229
|
-
SELECT *
|
|
230
|
-
FROM users
|
|
231
|
-
`; // 공통 들여쓰기가 제거된 두 줄
|
|
232
|
-
```
|
|
126
|
+
- `primitive.typeStr(value)`: → PrimitiveTypeStr — 런타임 값에서 원시 타입 문자열 추론(`"hello"`→`"string"`, `new DateTime()`→`"DateTime"`, `Uint8Array`→`"Bytes"`). 지원 안 되는 타입이면 ArgumentError. ORM 컬럼 타입 판정 등에 사용.
|
|
233
127
|
|
|
234
|
-
##
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
class ZipArchive {
|
|
238
|
-
constructor(data?: Blob | Bytes); // 데이터 생략 시 새(쓰기용) 아카이브
|
|
239
|
-
extractAll(progressCallback?: (p: { fileName: string; totalSize: number; extractedSize: number }) => void): Promise<Map<string, Bytes | undefined>>;
|
|
240
|
-
get(fileName: string): Promise<Bytes | undefined>;
|
|
241
|
-
exists(fileName: string): Promise<boolean>;
|
|
242
|
-
write(fileName: string, bytes: Bytes): void; // 캐시에만 기록
|
|
243
|
-
compress(): Promise<Bytes>;
|
|
244
|
-
close(): Promise<void>;
|
|
245
|
-
}
|
|
246
|
-
```
|
|
128
|
+
## 에러 메시지 추출 (`err` 네임스페이스)
|
|
247
129
|
|
|
248
|
-
- `
|
|
249
|
-
- `get`/`exists` — 단일 파일 추출/존재 확인. 결과는 내부 캐시에 보관해 재추출 방지.
|
|
250
|
-
- `extractAll(cb)` — 전체 추출. `cb` 는 파일별 진행(`fileName`, 전체 바이트 `totalSize`, 누적 추출 `extractedSize`)을 보고.
|
|
251
|
-
- `write(name, bytes)` — 캐시에만 기록. 실제 압축 산출은 `compress()` 호출 시.
|
|
252
|
-
- `compress()` — 캐시(필요 시 `extractAll`)의 모든 파일을 ZIP 바이트로. 대용량은 전부 메모리 로드되므로 주의.
|
|
253
|
-
- `close()` — 리더 닫고 캐시 비움. `try/finally` 에서 호출 권장.
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
const archive = new ZipArchive(zipBytes);
|
|
257
|
-
try {
|
|
258
|
-
const content = await archive.get("file.txt");
|
|
259
|
-
} finally {
|
|
260
|
-
await archive.close();
|
|
261
|
-
}
|
|
262
|
-
```
|
|
130
|
+
- `err.message(e)`: → string — `unknown` 에러에서 메시지 추출. Error 면 `.message`, 아니면 `String(e)`. catch 블록의 `unknown` 을 안전하게 문자열화할 때.
|
|
@@ -1,121 +1,77 @@
|
|
|
1
|
-
# @simplysm/core-common —
|
|
1
|
+
# @simplysm/core-common — 배열 확장 메서드
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@simplysm/core-common` import 시 `Array.prototype` 에 설치되는 확장 메서드. 배열을 조회·그룹화·정렬·중복제거·Map/객체/트리 변환·diff/merge·집계할 때 함께 읽힘. 모두 `array.method(...)` 로 직접 호출. enumerable=false 로 설치되어 `for...in`·`Object.keys` 에 노출되지 않음.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
표기: **읽기 전용**(원본 불변, 새 배열/값 반환) vs **@mutates**(원본 직접 수정). 정렬/중복제거는 두 버전(예: `orderBy` vs `orderByThis`)이 있음.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
single(predicate?): TItem | undefined; // 조건 일치 1건. 2건 이상이면 ArgumentError
|
|
9
|
-
first(predicate?): TItem | undefined; // 첫 일치(없으면 undefined)
|
|
10
|
-
last(predicate?): TItem | undefined; // 마지막 일치
|
|
11
|
-
filterExists(): NonNullable<TItem>[]; // null/undefined 제거
|
|
12
|
-
ofType(type: PrimitiveTypeStr | Type<T>): T[]; // 타입별 필터
|
|
13
|
-
filterAsync(predicate: (item, i) => Promise<boolean>): Promise<TItem[]>; // 순차 비동기 필터
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
- `single(predicate)` — "정확히 1건" 보장이 필요할 때. 조건 일치가 2건 이상이면 `ArgumentError` throw, 0건이면 `undefined`. predicate 생략 시 배열 전체 대상.
|
|
17
|
-
- `first`/`last` — predicate 생략 시 각각 `[0]`/마지막 요소.
|
|
18
|
-
- `ofType(type)` — `"string"|"number"|"boolean"|"DateTime"|"DateOnly"|"Time"|"Uuid"|"Bytes"` 문자열이면 해당 원시 타입으로, 생성자(`Type<N>`)면 `instanceof`/constructor 일치로 필터. 혼합 배열에서 특정 타입만 뽑을 때.
|
|
19
|
-
- `filterAsync` — predicate 가 Promise 인 경우. 병렬이 아니라 **순차** 실행(부수효과 순서 보장).
|
|
7
|
+
## 조회 / 필터
|
|
20
8
|
|
|
21
|
-
|
|
9
|
+
- `single(predicate?)`: → `T | undefined` — 조건에 맞는 단 하나 반환. **2개 이상이면 ArgumentError throw**. 0개면 undefined. "유일해야 한다"는 불변식 검증에 사용.
|
|
10
|
+
- `first(predicate?)`: → `T | undefined` — 첫 요소(predicate 있으면 첫 매칭). 없으면 undefined.
|
|
11
|
+
- `last(predicate?)`: → `T | undefined` — 마지막 요소(predicate 있으면 뒤에서 첫 매칭).
|
|
12
|
+
- `filterExists()`: → `NonNullable<T>[]` — null/undefined 제거(타입도 좁혀짐).
|
|
13
|
+
- `ofType(type)`: → 좁혀진 배열 — PrimitiveTypeStr(`"string"`·`"number"`·`"boolean"`·`"DateTime"`·`"DateOnly"`·`"Time"`·`"Uuid"`·`"Bytes"`) 또는 생성자(`Type<N>`)로 필터. 문자열이면 typeof/instanceof, 생성자면 `instanceof` 또는 `constructor` 일치. 혼합 배열에서 특정 타입만 뽑을 때.
|
|
14
|
+
- `filterAsync(predicate)`: → `Promise<T[]>` — 비동기 조건 필터(**순차** 실행).
|
|
22
15
|
|
|
23
|
-
|
|
24
|
-
mapAsync(selector: (item, i) => Promise<R>): Promise<R[]>; // 순차
|
|
25
|
-
parallelAsync(fn: (item, i) => Promise<R>): Promise<R[]>; // Promise.all 병렬
|
|
26
|
-
mapMany(): U[]; // 중첩 배열 1단 평탄화
|
|
27
|
-
mapMany(selector: (item, i) => R[]): R[]; // 매핑 후 평탄화
|
|
28
|
-
mapManyAsync(selector: (item, i) => Promise<R[]>): Promise<R[]>; // 순차 매핑 후 평탄화
|
|
29
|
-
```
|
|
16
|
+
## 비동기 매핑
|
|
30
17
|
|
|
31
|
-
- `mapAsync
|
|
32
|
-
- `
|
|
18
|
+
- `mapAsync(selector)`: → `Promise<R[]>` — 비동기 매핑(**순차** 실행, 순서 보존).
|
|
19
|
+
- `parallelAsync(fn)`: → `Promise<R[]>` — `Promise.all` 기반 **병렬** 실행. 하나라도 reject 면 전체 reject. 독립 IO 를 동시에 돌릴 때.
|
|
20
|
+
- `mapMany(selector?)`: → 평탄화 배열 — selector 매핑 후 1단계 flat + `filterExists`. selector 없으면 자신을 flat. 중첩 배열 펼칠 때.
|
|
21
|
+
- `mapManyAsync(selector?)`: → `Promise<...>` — 비동기 매핑 후 평탄화(순차).
|
|
33
22
|
|
|
34
|
-
##
|
|
23
|
+
## 그룹화 / Map·객체 변환
|
|
35
24
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
toObject(keySelector: (item, i) => string, valueSelector?): Record<string, V>;
|
|
44
|
-
```
|
|
25
|
+
- `groupBy(keySelector, valueSelector?)`: → `{ key, values }[]` — key 별 그룹. 원시 key 는 O(n), 객체 key 는 깊은 비교 O(n²). 객체 key 가 불필요하면 `toArrayMap` 권장.
|
|
26
|
+
- `toMap(keySelector, valueSelector?)`: → `Map<K, V|T>` — key→단일값. **중복 key 면 ArgumentError**. 1:1 인덱싱에 사용.
|
|
27
|
+
- `toMapAsync(keySelector, valueSelector?)`: → `Promise<Map>` — 위의 비동기(순차) 버전(selector 가 Promise 반환 허용).
|
|
28
|
+
- `toArrayMap(keySelector, valueSelector?)`: → `Map<K, (V|T)[]>` — key→값 배열(중복 허용). O(n) 그룹화의 기본 선택지.
|
|
29
|
+
- `toSetMap(keySelector, valueSelector?)`: → `Map<K, Set<V|T>>` — key→Set(중복 자동 제거).
|
|
30
|
+
- `toMapValues(keySelector, valueSelector)`: → `Map<K, V>` — key 별로 모은 **항목 배열 전체**를 valueSelector(items)→집계값으로 변환. 그룹별 합계 등.
|
|
31
|
+
- `toObject(keySelector, valueSelector?)`: → `Record<string, V|T>` — key(string)→값 객체. 중복 key(둘 다 non-null)면 ArgumentError.
|
|
45
32
|
|
|
46
|
-
|
|
47
|
-
- `toMap` — key→단일 값. key 중복 시 뒤 값이 덮어씀. `toArrayMap`/`toSetMap` — key→배열/Set(다대일 집계).
|
|
48
|
-
- `toMapValues(keySelector, valueSelector)` — 같은 key 의 항목 배열을 받아 단일 값으로 집계(`(items) => items.sum(...)` 등).
|
|
49
|
-
- `toObject` — key 가 반드시 string. `valueSelector` 생략 시 값은 원소 자체.
|
|
33
|
+
## 트리화
|
|
50
34
|
|
|
51
|
-
|
|
35
|
+
- `toTree(keyProp, parentKey)`: → `TreeArray<T>[]` — 평면 배열을 트리로. `parentKey` 값이 null/undefined 인 항목이 루트, 각 노드에 `children` 추가(항목은 clone 됨). 내부 `toArrayMap` 으로 O(n). `TreeArray<T> = T & { children: TreeArray<T>[] }`.
|
|
52
36
|
|
|
53
|
-
```
|
|
54
|
-
toTree(
|
|
55
|
-
|
|
56
|
-
orderBy(selector?): TItem[];
|
|
57
|
-
orderByDesc(selector?): TItem[];
|
|
37
|
+
```ts
|
|
38
|
+
items.toTree("id", "parentId");
|
|
39
|
+
// [{ id: 1, name: "root", children: [{ id: 2, ..., children: [] }] }]
|
|
58
40
|
```
|
|
59
41
|
|
|
60
|
-
|
|
61
|
-
- `distinct(options)` — 중복 제거. `true`/`{matchAddress:true}` 면 참조(Set) 비교, `keyFn` 지정 시 key 기준 O(n). 객체 배열을 옵션 없이 쓰면 깊은 비교 O(n²)(대량 데이터엔 `keyFn` 권장).
|
|
62
|
-
- `orderBy`/`orderByDesc(selector)` — selector 반환 타입은 `string|number|DateOnly|DateTime|Time|undefined`. 새 배열 반환. 결측은 비교에서 그대로 처리.
|
|
42
|
+
## 정렬 / 중복제거
|
|
63
43
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
44
|
+
- `orderBy(selector?)` / `orderByDesc(selector?)`: → `T[]` (새 배열) — selector 가 반환한 string/number/boolean/DateTime/DateOnly/Time/undefined 로 정렬. null/undefined 는 오름차순 앞·내림차순 뒤. 날짜타입은 tick 비교, 문자열은 `localeCompare`. selector 없으면 요소 자체.
|
|
45
|
+
- `orderByThis(selector?)` / `orderByDescThis(selector?)`: → `T[]` @mutates — 원본을 in-place 정렬.
|
|
46
|
+
- `distinct(options?)`: → `T[]` (새 배열) — 중복 제거. options: `true`/`{ matchAddress: true }`=참조 비교 O(n), `{ keyFn }`=커스텀 key O(n), 미지정=원시는 값·객체는 깊은 비교 O(n²). 대량 객체 배열엔 `keyFn` 권장.
|
|
47
|
+
- `distinctThis(options?)`: → `T[]` @mutates — 원본에서 중복 제거(첫 등장만 유지).
|
|
68
48
|
|
|
69
|
-
## diff
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
type ArrayDiffsResult<O, T> =
|
|
73
|
-
| { source: undefined; target: T } // INSERT
|
|
74
|
-
| { source: O; target: undefined } // DELETE
|
|
75
|
-
| { source: O; target: T }; // UPDATE
|
|
76
|
-
type ArrayOneWayDiffResult<T> =
|
|
77
|
-
| { type: "create"; item: T; orgItem: undefined }
|
|
78
|
-
| { type: "update"; item: T; orgItem: T }
|
|
79
|
-
| { type: "same"; item: T; orgItem: T };
|
|
80
|
-
|
|
81
|
-
diffs(target, options?): ArrayDiffsResult<TItem, TOther>[];
|
|
82
|
-
oneWayDiffs(orgItems, keyPropNameOrGetValFn, options?): ArrayOneWayDiffResult<TItem>[];
|
|
83
|
-
merge(target, options?): (TItem | TOther | (TItem & TOther))[];
|
|
84
|
-
```
|
|
49
|
+
## diff / merge
|
|
85
50
|
|
|
86
|
-
- `diffs(target, options)` — 두
|
|
87
|
-
- `oneWayDiffs(orgItems, keyPropNameOrGetValFn, options)` — 현재
|
|
88
|
-
- `merge(target, options)` —
|
|
51
|
+
- `diffs(target, options?)`: → `ArrayDiffsResult<T,P>[]` — 두 배열 비교. 결과 항목은 `{ source: undefined, target }`(INSERT) / `{ source, target: undefined }`(DELETE) / `{ source, target }`(UPDATE). options: `keys`=동일성 판정 key(없으면 전체 깊은 비교), `excludes`=비교 제외 속성. target 에 중복 key 면 첫 매칭만.
|
|
52
|
+
- `oneWayDiffs(orgItems, keyPropNameOrGetValFn, options?)`: → `ArrayOneWayDiffResult<T>[]` — 현재 배열을 원본(배열 또는 `Map<key, item>`) 대비 분류. 결과 type: `"create"`(key 값 없거나 원본에 없음)·`"update"`(값 다름)·`"same"`(같음, `includeSame: true` 일 때만 포함). keyPropNameOrGetValFn 은 key 속성명 또는 `(item)=>키값` 함수. options.excludes/includes 로 비교 범위 조정. 저장 시 INSERT/UPDATE 판정에 사용.
|
|
53
|
+
- `merge(target, options?)`: → `(T|P|(T&P))[]` (새 배열) — `diffs` 결과로 source 를 기준 삼아 병합. UPDATE 는 `obj.merge` 로 깊은 병합, INSERT 는 추가, DELETE 는 유지(원본 보존). options 는 `diffs` 와 동일.
|
|
54
|
+
|
|
55
|
+
`ArrayDiffsResult`·`ArrayOneWayDiffResult`·`TreeArray`·`ComparableType`(=`string | number | boolean | DateTime | DateOnly | Time | undefined`) 타입이 함께 export 됨.
|
|
89
56
|
|
|
90
57
|
## 집계
|
|
91
58
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
min(selector?): TProp | undefined;
|
|
95
|
-
max(selector?): TProp | undefined;
|
|
96
|
-
shuffle(): TItem[];
|
|
97
|
-
```
|
|
59
|
+
- `sum(selector?)`: → number — 합계(빈 배열 0). 숫자 아닌 값이면 ArgumentError.
|
|
60
|
+
- `min(selector?)` / `max(selector?)`: → `string | number | undefined` — 최소/최대. 숫자·문자열만 허용(아니면 ArgumentError). 빈 배열 undefined.
|
|
98
61
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
- `
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
orderByThis(selector?): TItem[]; // 오름차순 in-place
|
|
108
|
-
orderByDescThis(selector?): TItem[]; // 내림차순 in-place
|
|
109
|
-
insert(index: number, ...items: TItem[]): this;
|
|
110
|
-
remove(item: TItem): this;
|
|
111
|
-
remove(selector: (item, i) => boolean): this;
|
|
112
|
-
toggle(item: TItem): this; // 있으면 제거, 없으면 추가
|
|
113
|
-
clear(): this; // 비우기
|
|
114
|
-
```
|
|
62
|
+
## 그 외 @mutates
|
|
63
|
+
|
|
64
|
+
- `insert(index, ...items)`: → this — index 위치에 삽입.
|
|
65
|
+
- `remove(item)` / `remove(selector)`: → this — 일치 항목(또는 조건 매칭) 모두 제거(역순 순회 O(n)).
|
|
66
|
+
- `toggle(item)`: → this — 있으면 제거·없으면 push.
|
|
67
|
+
- `clear()`: → this — 전체 비움.
|
|
68
|
+
|
|
69
|
+
## shuffle
|
|
115
70
|
|
|
116
|
-
-
|
|
117
|
-
- `remove` — 값 또는 조건 함수 오버로드. `toggle` — 멤버십 토글로 선택 상태 관리에 사용.
|
|
71
|
+
- `shuffle()`: → `T[]` (새 배열) — Fisher–Yates 무작위 섞기. 원본 불변.
|
|
118
72
|
|
|
119
|
-
```
|
|
120
|
-
|
|
73
|
+
```ts
|
|
74
|
+
const grouped = users.toArrayMap((u) => u.teamId); // Map<teamId, User[]>
|
|
75
|
+
const sorted = items.orderBy((x) => x.createdAt); // DateTime 기준 오름차순
|
|
76
|
+
const diff = next.oneWayDiffs(prev, "id"); // create/update/same 분류
|
|
121
77
|
```
|