@simplysm/core-common 13.0.85 → 13.0.86
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/README.md +105 -27
- package/dist/utils/xml.js +1 -1
- package/dist/utils/xml.js.map +1 -1
- package/docs/features.md +300 -57
- package/docs/types.md +287 -188
- package/docs/utilities.md +359 -0
- package/package.json +2 -2
- package/src/utils/xml.ts +2 -2
- package/docs/byte-utilities.md +0 -55
- package/docs/date-format-utilities.md +0 -96
- package/docs/environment.md +0 -35
- package/docs/error-utilities.md +0 -35
- package/docs/errors.md +0 -79
- package/docs/extensions.md +0 -201
- package/docs/json-utilities.md +0 -57
- package/docs/number-utilities.md +0 -76
- package/docs/object-utilities.md +0 -165
- package/docs/path-utilities.md +0 -54
- package/docs/primitive-utilities.md +0 -40
- package/docs/string-utilities.md +0 -79
- package/docs/template-strings.md +0 -105
- package/docs/transfer-utilities.md +0 -53
- package/docs/wait-utilities.md +0 -50
- package/docs/xml-utilities.md +0 -48
- package/docs/zip-archive.md +0 -61
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# 유틸리티
|
|
2
|
+
|
|
3
|
+
네임스페이스로 그룹화된 유틸리티 함수들.
|
|
4
|
+
|
|
5
|
+
## obj -- 객체 유틸리티
|
|
6
|
+
|
|
7
|
+
### 클론/비교/병합
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { obj } from "@simplysm/core-common";
|
|
11
|
+
|
|
12
|
+
// 딥 클론 (순환 참조, 커스텀 타입 지원)
|
|
13
|
+
// 지원: DateTime, DateOnly, Time, Uuid, Uint8Array, Date, RegExp, Error, Map, Set, Array
|
|
14
|
+
// 함수/Symbol은 참조 유지, 프로토타입 체인 유지
|
|
15
|
+
const cloned = obj.clone(source);
|
|
16
|
+
|
|
17
|
+
// 딥 비교
|
|
18
|
+
obj.equal(a, b);
|
|
19
|
+
obj.equal(a, b, { shallow: true }); // 1단계만 비교
|
|
20
|
+
obj.equal(a, b, { ignoreArrayIndex: true }); // 배열 순서 무시 (O(n^2))
|
|
21
|
+
obj.equal(a, b, { topLevelIncludes: ["name", "age"] }); // 특정 키만 비교 (최상위만)
|
|
22
|
+
obj.equal(a, b, { topLevelExcludes: ["updatedAt"] }); // 특정 키 제외 (최상위만)
|
|
23
|
+
|
|
24
|
+
// 딥 병합
|
|
25
|
+
obj.merge(source, target);
|
|
26
|
+
obj.merge(source, target, { arrayProcess: "concat" }); // 배열 연결 (Set 기반 중복 제거)
|
|
27
|
+
obj.merge(source, target, { arrayProcess: "replace" }); // 배열 교체 (기본값)
|
|
28
|
+
obj.merge(source, target, { useDelTargetNull: true }); // target이 null이면 키 삭제
|
|
29
|
+
|
|
30
|
+
// 3-way 병합
|
|
31
|
+
const { conflict, result } = obj.merge3(source, origin, target);
|
|
32
|
+
// source와 origin 같고 target 다름 -> target 값 사용
|
|
33
|
+
// target과 origin 같고 source 다름 -> source 값 사용
|
|
34
|
+
// 세 값 모두 다름 -> conflict = true, origin 값 유지
|
|
35
|
+
|
|
36
|
+
// 키별 비교 옵션
|
|
37
|
+
obj.merge3(source, origin, target, {
|
|
38
|
+
name: { keys: ["first", "last"] },
|
|
39
|
+
tags: { ignoreArrayIndex: true },
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 객체 조작
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// pick/omit
|
|
47
|
+
obj.pick(item, ["name", "age"]); // { name, age }
|
|
48
|
+
obj.omit(item, ["password"]); // password 제외
|
|
49
|
+
obj.omitByFilter(item, (key) => key.startsWith("_")); // 조건부 제외
|
|
50
|
+
|
|
51
|
+
// 체인 접근 (점 표기법)
|
|
52
|
+
obj.getChainValue(data, "user.address[0].city");
|
|
53
|
+
obj.getChainValue(data, "user.name", true); // optional: 중간 경로 없으면 undefined
|
|
54
|
+
obj.setChainValue(data, "user.name", "new"); // 중간 경로 없으면 자동 생성
|
|
55
|
+
obj.deleteChainValue(data, "user.temp"); // 중간 경로 없으면 무시
|
|
56
|
+
|
|
57
|
+
// 깊이 기반 체인 접근
|
|
58
|
+
obj.getChainValueByDepth(data, "parent", 2); // data.parent.parent
|
|
59
|
+
obj.getChainValueByDepth(data, "parent", 2, true); // optional 모드
|
|
60
|
+
|
|
61
|
+
// 기타
|
|
62
|
+
obj.clearUndefined(data); // undefined 키 제거 (mutate)
|
|
63
|
+
obj.clear(data); // 모든 키 제거 (mutate)
|
|
64
|
+
obj.nullToUndefined(data); // null -> undefined (재귀, mutate, 순환 참조 안전)
|
|
65
|
+
obj.unflatten({ "a.b.c": 1 }); // { a: { b: { c: 1 } } }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 타입 유틸리티
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
obj.keys(myObj); // 타입 안전한 Object.keys
|
|
72
|
+
obj.entries(myObj); // 타입 안전한 Object.entries
|
|
73
|
+
obj.fromEntries(pairs); // 타입 안전한 Object.fromEntries
|
|
74
|
+
|
|
75
|
+
// 객체 엔트리 변환
|
|
76
|
+
obj.map(colors, (key, rgb) => [null, `rgb(${rgb})`]);
|
|
77
|
+
// key를 null로 반환하면 원래 key 유지, 새 key를 반환하면 key 변환
|
|
78
|
+
|
|
79
|
+
type A = obj.UndefToOptional<{ a: string | undefined }>; // { a?: string | undefined }
|
|
80
|
+
type B = obj.OptionalToUndef<{ a?: string }>; // { a: string | undefined }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## str -- 문자열 유틸리티
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { str } from "@simplysm/core-common";
|
|
89
|
+
|
|
90
|
+
str.toPascalCase("hello-world"); // "HelloWorld"
|
|
91
|
+
str.toCamelCase("hello-world"); // "helloWorld"
|
|
92
|
+
str.toKebabCase("HelloWorld"); // "hello-world"
|
|
93
|
+
str.toSnakeCase("HelloWorld"); // "hello_world"
|
|
94
|
+
|
|
95
|
+
str.isNullOrEmpty(value); // value is "" | undefined (타입 가드)
|
|
96
|
+
str.insert("abcde", 2, "XY"); // "abXYcde"
|
|
97
|
+
str.replaceFullWidth("ABC"); // "ABC" (전각 -> 반각)
|
|
98
|
+
|
|
99
|
+
// 한국어 조사
|
|
100
|
+
str.getKoreanSuffix("사과", "을"); // "를"
|
|
101
|
+
str.getKoreanSuffix("바나나", "을"); // "을"
|
|
102
|
+
str.getKoreanSuffix("칼", "로"); // "로" (ㄹ 종성 특수 처리)
|
|
103
|
+
// 지원 타입: "을"(을/를), "은"(은/는), "이"(이/가), "와"(과/와), "랑"(이랑/랑), "로"(으로/로), "라"(이라/라)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## num -- 숫자 유틸리티
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { num } from "@simplysm/core-common";
|
|
112
|
+
|
|
113
|
+
// 파싱 (비숫자 문자 자동 제거)
|
|
114
|
+
num.parseInt("1,234원"); // 1234
|
|
115
|
+
num.parseFloat("$1,234.56"); // 1234.56
|
|
116
|
+
num.parseRoundedInt("1.7"); // 2
|
|
117
|
+
|
|
118
|
+
num.isNullOrEmpty(value); // value is 0 | undefined (타입 가드)
|
|
119
|
+
|
|
120
|
+
// 포맷 (천 단위 구분자)
|
|
121
|
+
num.format(1234567); // "1,234,567"
|
|
122
|
+
num.format(1234.5678, { max: 2 }); // "1,234.57"
|
|
123
|
+
num.format(1234.5, { min: 2 }); // "1,234.50"
|
|
124
|
+
num.format(1234.5, { min: 2, max: 4 }); // "1,234.50"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## bytes -- 바이너리 유틸리티
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { bytes } from "@simplysm/core-common";
|
|
133
|
+
|
|
134
|
+
bytes.concat([arr1, arr2, arr3]); // Uint8Array 연결
|
|
135
|
+
bytes.toHex(data); // 소문자 hex 문자열
|
|
136
|
+
bytes.fromHex("48656c6c6f"); // Uint8Array
|
|
137
|
+
bytes.toBase64(data); // base64 인코딩
|
|
138
|
+
bytes.fromBase64(b64str); // base64 디코딩
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## json -- JSON 직렬화
|
|
144
|
+
|
|
145
|
+
커스텀 타입(DateTime, DateOnly, Time, Uuid, Set, Map, Error, Uint8Array, Date, RegExp 등)을 지원하는 JSON 직렬화/역직렬화.
|
|
146
|
+
|
|
147
|
+
내부적으로 `__type__`/`data` 형식의 태그 객체를 사용하여 타입 정보를 보존한다.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { json, DateTime } from "@simplysm/core-common";
|
|
151
|
+
|
|
152
|
+
// 직렬화 (커스텀 타입 자동 처리)
|
|
153
|
+
const str = json.stringify({
|
|
154
|
+
date: new DateTime(),
|
|
155
|
+
id: Uuid.generate(),
|
|
156
|
+
items: new Set([1, 2, 3]),
|
|
157
|
+
mapping: new Map([["a", 1]]),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// 역직렬화 (타입 자동 복원, null -> undefined 변환)
|
|
161
|
+
const data = json.parse<{ date: DateTime }>(str);
|
|
162
|
+
|
|
163
|
+
// 옵션
|
|
164
|
+
json.stringify(obj, { space: 2 }); // 들여쓰기
|
|
165
|
+
json.stringify(obj, { redactBytes: true }); // Uint8Array를 "__hidden__"로 대체 (로깅용)
|
|
166
|
+
json.stringify(obj, { replacer: (key, value) => value }); // 커스텀 replacer
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**주의사항:**
|
|
170
|
+
- `parse()`는 모든 JSON null을 undefined로 변환한다 (simplysm 프레임워크의 null-free 규칙)
|
|
171
|
+
- `redactBytes: true`로 직렬화한 결과는 `parse()`로 복원 불가 (SdError 발생)
|
|
172
|
+
- 순환 참조가 있으면 TypeError 발생
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## xml -- XML 처리
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { xml } from "@simplysm/core-common";
|
|
180
|
+
|
|
181
|
+
// 파싱 (속성은 $ 객체, 텍스트는 _ 키, 자식 요소는 배열)
|
|
182
|
+
const obj = xml.parse('<root attr="1"><child>text</child></root>');
|
|
183
|
+
// { root: { $: { attr: "1" }, child: [{ _: "text" }] } }
|
|
184
|
+
|
|
185
|
+
// 네임스페이스 접두사 제거
|
|
186
|
+
xml.parse(xmlStr, { stripTagPrefix: true });
|
|
187
|
+
|
|
188
|
+
// 직렬화
|
|
189
|
+
const xmlStr = xml.stringify(obj);
|
|
190
|
+
// fast-xml-parser의 XmlBuilderOptions를 두 번째 인자로 전달 가능
|
|
191
|
+
xml.stringify(obj, { format: true });
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## path -- 경로 유틸리티
|
|
197
|
+
|
|
198
|
+
POSIX 스타일 전용 경로 유틸리티. 브라우저 환경과 Capacitor 플러그인을 위해 설계되었다. Windows 백슬래시 경로는 지원하지 않는다.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { path } from "@simplysm/core-common";
|
|
202
|
+
|
|
203
|
+
path.join("a", "b", "c.txt"); // "a/b/c.txt"
|
|
204
|
+
path.basename("/a/b/file.ts"); // "file.ts"
|
|
205
|
+
path.basename("/a/b/file.ts", ".ts"); // "file"
|
|
206
|
+
path.extname("/a/b/file.ts"); // ".ts"
|
|
207
|
+
path.extname("/a/b/.gitignore"); // "" (숨김 파일은 빈 문자열)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## wait -- 비동기 대기
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { wait } from "@simplysm/core-common";
|
|
216
|
+
|
|
217
|
+
// 조건 충족까지 대기
|
|
218
|
+
await wait.until(() => isReady, 100, 50);
|
|
219
|
+
// 100ms 간격으로 체크, 최대 50회 (초과 시 TimeoutError)
|
|
220
|
+
// 첫 호출에서 true면 즉시 반환
|
|
221
|
+
|
|
222
|
+
// 시간 대기
|
|
223
|
+
await wait.time(1000); // 1초 대기
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## err -- 에러 처리
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { err } from "@simplysm/core-common";
|
|
232
|
+
|
|
233
|
+
try { /* ... */ } catch (e) {
|
|
234
|
+
const message = err.message(e); // unknown 타입에서 안전하게 메시지 추출
|
|
235
|
+
// Error 인스턴스면 .message, 아니면 String(e)
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## dt -- 날짜 포맷
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import { dt } from "@simplysm/core-common";
|
|
245
|
+
|
|
246
|
+
// 포맷 (DateTime/DateOnly/Time의 toFormatString이 내부적으로 사용)
|
|
247
|
+
dt.format("yyyy-MM-dd", { year: 2024, month: 1, day: 15 });
|
|
248
|
+
dt.format("HH:mm:ss", { hour: 14, minute: 30, second: 0 });
|
|
249
|
+
|
|
250
|
+
// 월 정규화
|
|
251
|
+
dt.normalizeMonth(2024, 13, 1); // { year: 2025, month: 1, day: 1 }
|
|
252
|
+
dt.normalizeMonth(2025, 2, 31); // { year: 2025, month: 2, day: 28 }
|
|
253
|
+
|
|
254
|
+
// 12시간 -> 24시간 변환
|
|
255
|
+
dt.convert12To24(12, false); // 0 (12 AM = 0시)
|
|
256
|
+
dt.convert12To24(12, true); // 12 (12 PM = 12시)
|
|
257
|
+
dt.convert12To24(2, true); // 14 (PM 2시 = 14시)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## primitive -- 프리미티브 타입 판별
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { primitive } from "@simplysm/core-common";
|
|
266
|
+
|
|
267
|
+
primitive.typeStr("hello"); // "string"
|
|
268
|
+
primitive.typeStr(123); // "number"
|
|
269
|
+
primitive.typeStr(true); // "boolean"
|
|
270
|
+
primitive.typeStr(new DateTime()); // "DateTime"
|
|
271
|
+
primitive.typeStr(new DateOnly()); // "DateOnly"
|
|
272
|
+
primitive.typeStr(new Time()); // "Time"
|
|
273
|
+
primitive.typeStr(new Uuid("...")); // "Uuid"
|
|
274
|
+
primitive.typeStr(new Uint8Array()); // "Bytes"
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## transfer -- Worker 데이터 전송
|
|
280
|
+
|
|
281
|
+
Worker `postMessage`용 직렬화/역직렬화. 순환 참조 감지(경로 포함 TypeError), 커스텀 타입 지원.
|
|
282
|
+
|
|
283
|
+
지원 타입: Date, DateTime, DateOnly, Time, Uuid, RegExp, Error(cause/code/detail 포함), Uint8Array, Array, Map, Set, plain object.
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import { transfer } from "@simplysm/core-common";
|
|
287
|
+
|
|
288
|
+
// Worker로 전송
|
|
289
|
+
const { result, transferList } = transfer.encode(data);
|
|
290
|
+
worker.postMessage(result, transferList);
|
|
291
|
+
// Uint8Array의 ArrayBuffer가 자동으로 transferList에 추가됨
|
|
292
|
+
// SharedArrayBuffer는 transferList에 포함되지 않음
|
|
293
|
+
|
|
294
|
+
// Worker에서 수신
|
|
295
|
+
const original = transfer.decode(event.data);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## 템플릿 문자열 태그
|
|
301
|
+
|
|
302
|
+
IDE 구문 강조를 위한 태그 함수. 들여쓰기 자동 정규화 (공통 들여쓰기 제거, 앞뒤 빈 줄 제거).
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
import { js, ts, html, tsql, mysql, pgsql } from "@simplysm/core-common";
|
|
306
|
+
|
|
307
|
+
const query = tsql`
|
|
308
|
+
SELECT *
|
|
309
|
+
FROM Users
|
|
310
|
+
WHERE id = ${userId}
|
|
311
|
+
`;
|
|
312
|
+
|
|
313
|
+
const markup = html`
|
|
314
|
+
<div class="container">
|
|
315
|
+
<h1>${title}</h1>
|
|
316
|
+
</div>
|
|
317
|
+
`;
|
|
318
|
+
|
|
319
|
+
// js, ts, mysql, pgsql도 동일하게 동작
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## ZipArchive -- ZIP 처리
|
|
325
|
+
|
|
326
|
+
`@zip.js/zip.js` 기반 ZIP 파일 처리. 내부 캐싱으로 동일 파일 중복 해제를 방지한다.
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
import { ZipArchive } from "@simplysm/core-common";
|
|
330
|
+
|
|
331
|
+
// ZIP 읽기 (await using 지원)
|
|
332
|
+
await using zip = new ZipArchive(blobOrBytes);
|
|
333
|
+
const fileData = await zip.get("path/to/file.txt");
|
|
334
|
+
const exists = await zip.exists("file.txt");
|
|
335
|
+
|
|
336
|
+
// 전체 파일 추출 (진행률 콜백)
|
|
337
|
+
const allFiles = await zip.extractAll((progress) => {
|
|
338
|
+
// progress: { fileName, totalSize, extractedSize }
|
|
339
|
+
});
|
|
340
|
+
// 반환: Map<string, Bytes | undefined>
|
|
341
|
+
|
|
342
|
+
// ZIP 생성
|
|
343
|
+
await using newZip = new ZipArchive();
|
|
344
|
+
newZip.write("file1.txt", data1);
|
|
345
|
+
newZip.write("dir/file2.txt", data2);
|
|
346
|
+
const compressed = await newZip.compress();
|
|
347
|
+
|
|
348
|
+
// 수동 정리 (await using을 사용하지 않는 경우)
|
|
349
|
+
await zip.close();
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
| 메서드 | 시그니처 | 설명 |
|
|
353
|
+
|--------|---------|------|
|
|
354
|
+
| `get` | `get(fileName: string): Promise<Bytes \| undefined>` | 파일 추출 (캐시 사용) |
|
|
355
|
+
| `exists` | `exists(fileName: string): Promise<boolean>` | 파일 존재 여부 |
|
|
356
|
+
| `extractAll` | `extractAll(cb?): Promise<Map<string, Bytes \| undefined>>` | 전체 추출 |
|
|
357
|
+
| `write` | `write(fileName: string, bytes: Bytes): void` | 파일 쓰기 (캐시에 저장) |
|
|
358
|
+
| `compress` | `compress(): Promise<Bytes>` | 캐시 내용을 ZIP으로 압축 |
|
|
359
|
+
| `close` | `close(): Promise<void>` | 리더 닫기 및 캐시 정리 |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/core-common",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.86",
|
|
4
4
|
"description": "Simplysm package - Core module (common)",
|
|
5
5
|
"author": "simplysm",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@zip.js/zip.js": "^2.8.23",
|
|
33
33
|
"consola": "^3.4.2",
|
|
34
|
-
"fast-xml-parser": "^5.5.
|
|
34
|
+
"fast-xml-parser": "^5.5.5",
|
|
35
35
|
"yaml": "^2.8.2"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/src/utils/xml.ts
CHANGED
|
@@ -28,8 +28,8 @@ export function parse(str: string, options?: { stripTagPrefix?: boolean }): unkn
|
|
|
28
28
|
parseTagValue: false,
|
|
29
29
|
textNodeName: "_",
|
|
30
30
|
htmlEntities: true,
|
|
31
|
-
isArray: (_tagName: string, jPath:
|
|
32
|
-
return !isAttribute && jPath.split(".").length > 1;
|
|
31
|
+
isArray: (_tagName: string, jPath: unknown, _isLeafNode: boolean, isAttribute: boolean) => {
|
|
32
|
+
return !isAttribute && typeof jPath === "string" && jPath.split(".").length > 1;
|
|
33
33
|
},
|
|
34
34
|
}).parse(str) as unknown;
|
|
35
35
|
return options?.stripTagPrefix ? stripTagPrefix(result) : result;
|
package/docs/byte-utilities.md
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# Byte Utilities
|
|
2
|
-
|
|
3
|
-
Imported as the `bytes` namespace. Provides `Uint8Array` manipulation utilities.
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
import { bytes } from "@simplysm/core-common";
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
## concat
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
function concat(arrays: Bytes[]): Bytes;
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Concatenates multiple `Uint8Array` instances into a single new array.
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## toHex / fromHex
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
function toHex(bytes: Bytes): string;
|
|
23
|
-
function fromHex(hex: string): Bytes;
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Converts between `Uint8Array` and lowercase hex strings. `fromHex` throws `ArgumentError` for odd-length strings or invalid hex characters.
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## toBase64 / fromBase64
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
function toBase64(bytes: Bytes): string;
|
|
34
|
-
function fromBase64(base64: string): Bytes;
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Converts between `Uint8Array` and base64 strings. `fromBase64` throws `ArgumentError` for invalid characters or length.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Usage Examples
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
import { bytes } from "@simplysm/core-common";
|
|
45
|
-
|
|
46
|
-
const a = new Uint8Array([1, 2]);
|
|
47
|
-
const b = new Uint8Array([3, 4]);
|
|
48
|
-
bytes.concat([a, b]); // Uint8Array [1, 2, 3, 4]
|
|
49
|
-
|
|
50
|
-
bytes.toHex(new Uint8Array([255, 0, 127])); // "ff007f"
|
|
51
|
-
bytes.fromHex("ff007f"); // Uint8Array [255, 0, 127]
|
|
52
|
-
|
|
53
|
-
bytes.toBase64(new Uint8Array([72, 101, 108, 108, 111])); // "SGVsbG8="
|
|
54
|
-
bytes.fromBase64("SGVsbG8="); // Uint8Array [72, 101, 108, 108, 111]
|
|
55
|
-
```
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# Date Format Utilities
|
|
2
|
-
|
|
3
|
-
Imported as the `dt` namespace. C#-style date/time formatting and month normalization.
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
import { dt } from "@simplysm/core-common";
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
## format
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
function format(formatString: string, args: {
|
|
13
|
-
year?: number;
|
|
14
|
-
month?: number;
|
|
15
|
-
day?: number;
|
|
16
|
-
hour?: number;
|
|
17
|
-
minute?: number;
|
|
18
|
-
second?: number;
|
|
19
|
-
millisecond?: number;
|
|
20
|
-
timezoneOffsetMinutes?: number;
|
|
21
|
-
}): string;
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Converts date/time components to a string using a C#-compatible format string.
|
|
25
|
-
|
|
26
|
-
| Format | Description | Example |
|
|
27
|
-
|--------|-------------|---------|
|
|
28
|
-
| `yyyy` | 4-digit year | 2024 |
|
|
29
|
-
| `yy` | 2-digit year | 24 |
|
|
30
|
-
| `MM` | Zero-padded month | 01-12 |
|
|
31
|
-
| `M` | Month | 1-12 |
|
|
32
|
-
| `ddd` | Day of week (Korean) | Sun, Mon, ... |
|
|
33
|
-
| `dd` | Zero-padded day | 01-31 |
|
|
34
|
-
| `d` | Day | 1-31 |
|
|
35
|
-
| `tt` | AM/PM | AM, PM |
|
|
36
|
-
| `hh` | Zero-padded 12-hour | 01-12 |
|
|
37
|
-
| `h` | 12-hour | 1-12 |
|
|
38
|
-
| `HH` | Zero-padded 24-hour | 00-23 |
|
|
39
|
-
| `H` | 24-hour | 0-23 |
|
|
40
|
-
| `mm` | Zero-padded minute | 00-59 |
|
|
41
|
-
| `m` | Minute | 0-59 |
|
|
42
|
-
| `ss` | Zero-padded second | 00-59 |
|
|
43
|
-
| `s` | Second | 0-59 |
|
|
44
|
-
| `fff` | Milliseconds (3 digits) | 000-999 |
|
|
45
|
-
| `ff` | Milliseconds (2 digits) | 00-99 |
|
|
46
|
-
| `f` | Milliseconds (1 digit) | 0-9 |
|
|
47
|
-
| `zzz` | Timezone offset | +09:00 |
|
|
48
|
-
| `zz` | Timezone offset | +09 |
|
|
49
|
-
| `z` | Timezone offset | +9 |
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## normalizeMonth
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
function normalizeMonth(year: number, month: number, day: number): {
|
|
57
|
-
year: number;
|
|
58
|
-
month: number;
|
|
59
|
-
day: number;
|
|
60
|
-
};
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Normalizes year/month/day when month is outside 1-12 range. Adjusts day to last day of month if needed (e.g., Jan 31 + setMonth(2) = Feb 28).
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
## convert12To24
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
function convert12To24(rawHour: number, isPM: boolean): number;
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
Converts 12-hour format to 24-hour format. `12 AM = 0`, `12 PM = 12`.
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## Usage Examples
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
import { dt } from "@simplysm/core-common";
|
|
81
|
-
|
|
82
|
-
dt.format("yyyy-MM-dd", { year: 2024, month: 3, day: 15 });
|
|
83
|
-
// "2024-03-15"
|
|
84
|
-
|
|
85
|
-
dt.format("tt h:mm:ss", { hour: 14, minute: 30, second: 45 });
|
|
86
|
-
// "PM 2:30:45"
|
|
87
|
-
|
|
88
|
-
dt.normalizeMonth(2025, 13, 15);
|
|
89
|
-
// { year: 2026, month: 1, day: 15 }
|
|
90
|
-
|
|
91
|
-
dt.normalizeMonth(2025, 2, 31);
|
|
92
|
-
// { year: 2025, month: 2, day: 28 }
|
|
93
|
-
|
|
94
|
-
dt.convert12To24(12, false); // 0 (12 AM)
|
|
95
|
-
dt.convert12To24(12, true); // 12 (12 PM)
|
|
96
|
-
```
|
package/docs/environment.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Environment
|
|
2
|
-
|
|
3
|
-
The `env` object exposes build-time environment variables.
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
import { env } from "@simplysm/core-common";
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
## env
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
const env: {
|
|
13
|
-
DEV: boolean;
|
|
14
|
-
VER?: string;
|
|
15
|
-
[key: string]: unknown;
|
|
16
|
-
};
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
- `DEV` - Whether running in development mode. Parsed from `process.env.DEV` (defaults to `false`).
|
|
20
|
-
- `VER` - Application version string from `process.env.VER`.
|
|
21
|
-
- Additional `process.env` properties are spread into the object.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Usage Examples
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { env } from "@simplysm/core-common";
|
|
29
|
-
|
|
30
|
-
if (env.DEV) {
|
|
31
|
-
// development-only logic
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
console.log(`Version: ${env.VER}`);
|
|
35
|
-
```
|
package/docs/error-utilities.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Error Utilities
|
|
2
|
-
|
|
3
|
-
Imported as the `err` namespace. Utilities for handling unknown error values.
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
import { err } from "@simplysm/core-common";
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
## message
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
function message(err: unknown): string;
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Extracts a message string from an unknown error value (typically from a `catch` block). Returns `err.message` for `Error` instances, otherwise returns `String(err)`.
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Usage Examples
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
import { err } from "@simplysm/core-common";
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
throw new Error("something failed");
|
|
26
|
-
} catch (e) {
|
|
27
|
-
const msg = err.message(e); // "something failed"
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
throw "raw string error";
|
|
32
|
-
} catch (e) {
|
|
33
|
-
const msg = err.message(e); // "raw string error"
|
|
34
|
-
}
|
|
35
|
-
```
|
package/docs/errors.md
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# Errors
|
|
2
|
-
|
|
3
|
-
Custom error class hierarchy with tree-structured cause chaining.
|
|
4
|
-
|
|
5
|
-
## SdError
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
class SdError extends Error {
|
|
9
|
-
cause?: Error;
|
|
10
|
-
|
|
11
|
-
constructor(cause: Error, ...messages: string[]);
|
|
12
|
-
constructor(...messages: string[]);
|
|
13
|
-
}
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Base error class supporting tree-structured cause chaining. Messages are joined in reverse order with ` => ` separator. The cause stack trace is appended to the current stack.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## ArgumentError
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
class ArgumentError extends SdError {
|
|
24
|
-
constructor(argObj: Record<string, unknown>);
|
|
25
|
-
constructor(message: string, argObj: Record<string, unknown>);
|
|
26
|
-
}
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Error for invalid arguments. Includes the argument object formatted as YAML in the message for easy debugging.
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## NotImplementedError
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
class NotImplementedError extends SdError {
|
|
37
|
-
constructor(message?: string);
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Error for features not yet implemented. Used for abstract method stubs and planned branches.
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## TimeoutError
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
class TimeoutError extends SdError {
|
|
49
|
-
constructor(count?: number, message?: string);
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Error thrown when waiting time is exceeded. Automatically thrown by `wait.until()` when the maximum number of attempts is reached.
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Usage Examples
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
import { SdError, ArgumentError, NotImplementedError, TimeoutError } from "@simplysm/core-common";
|
|
61
|
-
|
|
62
|
-
// Wrap a cause error
|
|
63
|
-
try {
|
|
64
|
-
await fetch(url);
|
|
65
|
-
} catch (err) {
|
|
66
|
-
throw new SdError(err, "API call failed", "User load failed");
|
|
67
|
-
// message: "User load failed => API call failed => original error message"
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// ArgumentError with YAML-formatted details
|
|
71
|
-
throw new ArgumentError("Invalid user", { userId: 123, name: null });
|
|
72
|
-
// message: "Invalid user\n\nuserId: 123\nname: null"
|
|
73
|
-
|
|
74
|
-
// NotImplementedError
|
|
75
|
-
throw new NotImplementedError("PDF export");
|
|
76
|
-
|
|
77
|
-
// TimeoutError
|
|
78
|
-
throw new TimeoutError(50, "Waiting for API response");
|
|
79
|
-
```
|