@simplysm/core-common 13.0.96 → 13.0.98

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 CHANGED
@@ -1,113 +1,160 @@
1
1
  # @simplysm/core-common
2
2
 
3
- Simplysm 프레임워크의 기반 유틸리티 패키지. 플랫폼 중립적인 타입, 유틸리티 함수, 에러 클래스, 확장 메서드를 제공한다.
3
+ Core module (common) platform-neutral core utilities for the Simplysm framework.
4
4
 
5
- ## 설치
5
+ Provides error classes, immutable date/time types, prototype extensions, event handling, and utility namespaces that work in both browser and Node.js environments.
6
+
7
+ ## Installation
6
8
 
7
9
  ```bash
8
10
  npm install @simplysm/core-common
9
11
  ```
10
12
 
11
- ## 의존성
13
+ ## Side-Effect Imports
12
14
 
13
- - `@zip.js/zip.js` -- ZIP 파일 처리
14
- - `consola` -- 로깅
15
- - `fast-xml-parser` -- XML 파싱/직렬화
16
- - `yaml` -- YAML 직렬화 (ArgumentError 메시지용)
15
+ Importing the package entry point (`@simplysm/core-common`) automatically patches `Array`, `Map`, and `Set` prototypes with extension methods. These are declared as side effects in `package.json`:
17
16
 
18
- ## 문서
17
+ - `extensions/arr-ext` — Array prototype extensions
18
+ - `extensions/map-ext` — Map prototype extensions
19
+ - `extensions/set-ext` — Set prototype extensions
19
20
 
20
- | 카테고리 | 설명 |
21
- |---------|------|
22
- | [타입](docs/types.md) | DateTime, DateOnly, Time, Uuid, LazyGcMap 등 불변 타입 |
23
- | [유틸리티](docs/utilities.md) | obj, str, num, bytes, json, xml, zip 등 네임스페이스 유틸리티 |
24
- | [기능](docs/features.md) | EventEmitter, DebounceQueue, SerialQueue, 에러 클래스, 확장 메서드, env |
21
+ If you import only specific modules (e.g., `@simplysm/core-common/dist/types/date-time`), the prototype extensions are **not** applied unless you also import the entry point or the extension modules directly.
25
22
 
26
- ## 빠른 시작
23
+ ## API Overview
27
24
 
28
- ### 날짜/시간 타입
25
+ ### Errors
29
26
 
30
- ```typescript
31
- import { DateTime, DateOnly, Time } from "@simplysm/core-common";
27
+ | API | Type | Description |
28
+ |-----|------|-------------|
29
+ | `SdError` | class | Error with tree-structured cause chaining |
30
+ | `ArgumentError` | class | Invalid argument error with YAML-formatted details |
31
+ | `NotImplementedError` | class | Unimplemented feature error |
32
+ | `TimeoutError` | class | Waiting time exceeded error |
32
33
 
33
- const now = new DateTime();
34
- const tomorrow = now.addDays(1);
35
- const formatted = now.toFormatString("yyyy-MM-dd HH:mm:ss");
34
+ -> See [docs/errors.md](./docs/errors.md) for details.
36
35
 
37
- const today = new DateOnly();
38
- const weekInfo = today.getWeekSeqOfYear(); // { year, weekSeq }
36
+ ### Types
39
37
 
40
- const time = Time.parse("14:30:00");
41
- const later = time.addHours(2); // 24시간 래핑
42
- ```
38
+ | API | Type | Description |
39
+ |-----|------|-------------|
40
+ | `Uuid` | class | UUID v4 generation and parsing |
41
+ | `DateTime` | class | Immutable date+time (millisecond precision) |
42
+ | `DateOnly` | class | Immutable date without time |
43
+ | `Time` | class | Immutable time without date (24h wraparound) |
44
+ | `LazyGcMap` | class | Map with LRU-based automatic expiration |
45
+ | `Bytes` | type alias | `Uint8Array` (replaces `Buffer`) |
46
+ | `PrimitiveTypeMap` | type | Mapping of type name strings to types |
47
+ | `PrimitiveTypeStr` | type | `keyof PrimitiveTypeMap` |
48
+ | `PrimitiveType` | type | Union of all primitive types |
49
+ | `DeepPartial<T>` | type | Recursively makes all properties optional |
50
+ | `Type<T>` | interface | Constructor type for DI and factory patterns |
51
+ | `env` | const | Unified `DEV` / `VER` environment accessor |
43
52
 
44
- ### 유틸리티 함수
53
+ -> See [docs/types.md](./docs/types.md) for details.
45
54
 
46
- ```typescript
47
- import { obj, str, json, bytes } from "@simplysm/core-common";
55
+ ### Features
48
56
 
49
- // 객체 클론/비교/병합
50
- const cloned = obj.clone(source);
51
- const isEqual = obj.equal(a, b);
52
- const merged = obj.merge(source, target);
57
+ | API | Type | Description |
58
+ |-----|------|-------------|
59
+ | `EventEmitter` | class | Type-safe event emitter (EventTarget wrapper) |
60
+ | `DebounceQueue` | class | Async debounce — only the last call executes |
61
+ | `SerialQueue` | class | Async serial execution queue |
53
62
 
54
- // 문자열 변환
55
- str.toPascalCase("hello-world"); // "HelloWorld"
56
- str.toKebabCase("HelloWorld"); // "hello-world"
63
+ -> See [docs/features.md](./docs/features.md) for details.
57
64
 
58
- // JSON (커스텀 타입 지원)
59
- const serialized = json.stringify({ date: new DateTime() });
60
- const parsed = json.parse<{ date: DateTime }>(serialized);
65
+ ### Prototype Extensions (side-effect)
61
66
 
62
- // 바이너리
63
- const hex = bytes.toHex(data);
64
- const b64 = bytes.toBase64(data);
65
- ```
67
+ | API | Type | Description |
68
+ |-----|------|-------------|
69
+ | `Array` extensions | prototype | 34 methods — query, transform, diff, sort, mutate |
70
+ | `Map` extensions | prototype | `getOrCreate`, `update` |
71
+ | `Set` extensions | prototype | `adds`, `toggle` |
72
+
73
+ -> See [docs/extensions.md](./docs/extensions.md) for details.
74
+
75
+ ### Utilities
76
+
77
+ | API | Type | Description |
78
+ |-----|------|-------------|
79
+ | `obj` | namespace | clone, equal, merge, merge3, omit, pick, chain access |
80
+ | `str` | namespace | Korean particles, case conversion, full-width replacement |
81
+ | `num` | namespace | parseInt, parseFloat, format with separators |
82
+ | `bytes` | namespace | concat, hex, base64 conversion |
83
+ | `path` | namespace | POSIX-only join, basename, extname |
84
+ | `json` | namespace | Custom-type-aware JSON stringify/parse |
85
+ | `xml` | namespace | XML parse/stringify via fast-xml-parser |
86
+ | `wait` | namespace | `until` (polling) and `time` (delay) |
87
+ | `transfer` | namespace | Worker-safe encode/decode for custom types |
88
+ | `err` | namespace | Extract message from unknown error |
89
+ | `dt` | namespace | Date format, month normalization, 12h/24h conversion |
90
+ | `primitive` | namespace | Infer `PrimitiveTypeStr` from a value |
91
+ | `js`, `ts`, `html`, `tsql`, `mysql`, `pgsql` | function | Template tag functions for syntax highlighting |
92
+ | `ZipArchive` | class | ZIP read/write/compress with caching |
93
+
94
+ -> See [docs/utils.md](./docs/utils.md) for details.
95
+
96
+ ## Quick Usage Examples
66
97
 
67
- ### 이벤트 에미터
98
+ ### DateTime (immutable date/time)
68
99
 
69
100
  ```typescript
70
- import { EventEmitter } from "@simplysm/core-common";
101
+ import { DateTime, DateOnly } from "@simplysm/core-common";
71
102
 
72
- const emitter = new EventEmitter<{ change: string; error: Error }>();
73
- emitter.on("change", (data) => { /* ... */ });
74
- emitter.emit("change", "updated");
103
+ const now = new DateTime();
104
+ const tomorrow = now.addDays(1);
105
+ const formatted = now.toFormatString("yyyy-MM-dd HH:mm:ss");
106
+ const parsed = DateTime.parse("2025-01-15 10:30:00");
107
+
108
+ const today = new DateOnly();
109
+ const weekInfo = today.getWeekSeqOfYear(); // { year, weekSeq }
75
110
  ```
76
111
 
77
- ### 배열 확장 메서드
112
+ ### Object utilities
78
113
 
79
114
  ```typescript
80
- import "@simplysm/core-common"; // side-effect import
81
-
82
- const items = [1, 2, 3, 4, 5];
83
- items.first(); // 1
84
- items.last(); // 5
85
- items.distinct(); // 중복 제거
86
- items.orderBy((x) => x); // 정렬
87
- items.groupBy((x) => x % 2); // 그룹화
88
- items.sum(); // 15
115
+ import { obj, json } from "@simplysm/core-common";
116
+
117
+ const cloned = obj.clone(deepObject);
118
+ const isEqual = obj.equal(a, b, { ignoreArrayIndex: true });
119
+ const merged = obj.merge(base, override);
120
+ const value = obj.getChainValue(data, "a.b[0].c");
121
+
122
+ // Custom-type-aware JSON
123
+ const str = json.stringify({ date: new DateTime(), id: Uuid.generate() });
124
+ const restored = json.parse(str); // DateTime and Uuid instances restored
89
125
  ```
90
126
 
91
- ### ZIP 처리
127
+ ### Array extensions
92
128
 
93
129
  ```typescript
94
- import { ZipArchive } from "@simplysm/core-common";
130
+ import "@simplysm/core-common";
95
131
 
96
- await using zip = new ZipArchive(data);
97
- const content = await zip.get("file.txt");
98
- zip.write("new-file.txt", bytes);
99
- const compressed = await zip.compress();
132
+ const items = [3, 1, 4, 1, 5];
133
+ items.distinct(); // [3, 1, 4, 5]
134
+ items.orderBy(); // [1, 1, 3, 4, 5]
135
+ items.sum(); // 14
136
+ items.groupBy((x) => x % 2 === 0 ? "even" : "odd");
137
+
138
+ const users = [{ id: 1, name: "A" }, { id: 2, name: "B" }];
139
+ users.toMap((u) => u.id); // Map { 1 => {...}, 2 => {...} }
140
+ users.single((u) => u.id === 1); // { id: 1, name: "A" }
100
141
  ```
101
142
 
102
- ### 에러 클래스
143
+ ### EventEmitter
103
144
 
104
145
  ```typescript
105
- import { SdError, ArgumentError, TimeoutError } from "@simplysm/core-common";
146
+ import { EventEmitter } from "@simplysm/core-common";
106
147
 
107
- // 에러 체인 (=> 구분자로 조인)
108
- throw new SdError(originalError, "추가 컨텍스트");
109
- // 메시지: "추가 컨텍스트 => 원본 에러 메시지"
148
+ interface MyEvents { data: string; done: void }
110
149
 
111
- // 인자 에러 (YAML 형식)
112
- throw new ArgumentError({ userId: -1, name: "" });
150
+ class MyService extends EventEmitter<MyEvents> {}
151
+
152
+ const svc = new MyService();
153
+ svc.on("data", (msg) => console.log(msg));
154
+ svc.emit("data", "hello");
155
+ svc.emit("done");
113
156
  ```
157
+
158
+ ## License
159
+
160
+ Apache-2.0
package/dist/env.d.ts CHANGED
@@ -1,3 +1,8 @@
1
+ declare global {
2
+ interface ImportMeta {
3
+ env?: Record<string, unknown>;
4
+ }
5
+ }
1
6
  export declare const env: {
2
7
  DEV: boolean;
3
8
  VER?: string;
package/dist/env.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG,EAAE;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAKxB,CAAC"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B;CACF;AAMD,eAAO,MAAM,GAAG,EAAE;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAKxB,CAAC"}
package/dist/env.js CHANGED
@@ -1,7 +1,10 @@
1
+ const _metaEnv = import.meta.env ?? {};
2
+ const _processEnv = typeof process !== "undefined" ? process.env : {};
3
+ const _raw = { ..._metaEnv, ..._processEnv };
1
4
  const env = {
2
- ...process.env,
3
- DEV: JSON.parse(process.env.DEV != null && process.env.DEV !== "" ? process.env.DEV : "false"),
4
- VER: process.env.VER
5
+ ..._raw,
6
+ DEV: JSON.parse(String(_raw["DEV"] != null && String(_raw["DEV"]) !== "" ? _raw["DEV"] : false)),
7
+ VER: _raw["VER"]
5
8
  };
6
9
  export {
7
10
  env
package/dist/env.js.map CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/env.ts"],
4
- "mappings": "AAEO,MAAM,MAIT;AAAA,EACF,GAAG,QAAQ;AAAA,EACX,KAAK,KAAK,MAAM,QAAQ,IAAI,OAAO,QAAQ,QAAQ,IAAI,QAAQ,KAAK,QAAQ,IAAI,MAAM,OAAO;AAAA,EAC7F,KAAK,QAAQ,IAAI;AACnB;",
4
+ "mappings": "AAQA,MAAM,WAAoC,YAAY,OAAO,CAAC;AAC9D,MAAM,cAAuC,OAAO,YAAY,cAAc,QAAQ,MAAM,CAAC;AAC7F,MAAM,OAAgC,EAAE,GAAG,UAAU,GAAG,YAAY;AAE7D,MAAM,MAIT;AAAA,EACF,GAAG;AAAA,EACH,KAAK,KAAK,MAAM,OAAO,KAAK,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,CAAC,MAAM,KAAK,KAAK,KAAK,IAAI,KAAK,CAAC;AAAA,EAC/F,KAAK,KAAK,KAAK;AACjB;",
5
5
  "names": []
6
6
  }
package/docs/errors.md ADDED
@@ -0,0 +1,119 @@
1
+ # Errors
2
+
3
+ Error classes for the Simplysm framework. All classes extend `SdError`, which itself extends `Error`.
4
+
5
+ Source: `src/errors/*.ts`
6
+
7
+ ---
8
+
9
+ ## `SdError`
10
+
11
+ Error class supporting tree-structured cause chaining. Utilizes ES2024 `cause` property. Messages are joined in reverse order with ` => ` separator, and cause stack traces are appended.
12
+
13
+ ```typescript
14
+ export class SdError extends Error {
15
+ override cause?: Error;
16
+
17
+ /** Create by wrapping a cause error. Messages are joined in reverse order (upper message => lower message => cause message) */
18
+ constructor(cause: Error, ...messages: string[]);
19
+ /** Create with messages only. Messages are joined in reverse order (upper message => lower message) */
20
+ constructor(...messages: string[]);
21
+ }
22
+ ```
23
+
24
+ **Example:**
25
+
26
+ ```typescript
27
+ try {
28
+ await fetch(url);
29
+ } catch (err) {
30
+ throw new SdError(err, "API call failed", "User load failed");
31
+ }
32
+ // Result message: "User load failed => API call failed => original error message"
33
+
34
+ throw new SdError("invalid state", "processing not possible");
35
+ // Result message: "processing not possible => invalid state"
36
+ ```
37
+
38
+ ---
39
+
40
+ ## `ArgumentError`
41
+
42
+ An error thrown when invalid arguments are received. Includes the argument object in YAML format in the message to facilitate debugging. Extends `SdError`.
43
+
44
+ ```typescript
45
+ export class ArgumentError extends SdError {
46
+ /** Output argument object in YAML format with default message ("Invalid arguments.") */
47
+ constructor(argObj: Record<string, unknown>);
48
+ /** Output argument object in YAML format with a custom message */
49
+ constructor(message: string, argObj: Record<string, unknown>);
50
+ }
51
+ ```
52
+
53
+ **Example:**
54
+
55
+ ```typescript
56
+ throw new ArgumentError({ userId: 123, name: null });
57
+ // Result message: "Invalid arguments.\n\nuserId: 123\nname: null"
58
+
59
+ throw new ArgumentError("Invalid user", { userId: 123 });
60
+ // Result message: "Invalid user\n\nuserId: 123"
61
+ ```
62
+
63
+ ---
64
+
65
+ ## `NotImplementedError`
66
+
67
+ An error thrown when a feature that has not yet been implemented is called. Extends `SdError`.
68
+
69
+ ```typescript
70
+ export class NotImplementedError extends SdError {
71
+ /**
72
+ * @param message Additional description message
73
+ */
74
+ constructor(message?: string);
75
+ }
76
+ ```
77
+
78
+ **Example:**
79
+
80
+ ```typescript
81
+ class BaseService {
82
+ process(): void {
83
+ throw new NotImplementedError("Implementation required in subclass");
84
+ }
85
+ }
86
+
87
+ switch (type) {
88
+ case "A": return handleA();
89
+ case "B": throw new NotImplementedError(`Handling for type ${type}`);
90
+ }
91
+ ```
92
+
93
+ ---
94
+
95
+ ## `TimeoutError`
96
+
97
+ An error that occurs when the waiting time is exceeded. Automatically thrown when the maximum number of attempts is exceeded in `wait.until()`. Extends `SdError`.
98
+
99
+ ```typescript
100
+ export class TimeoutError extends SdError {
101
+ /**
102
+ * @param count Number of attempts
103
+ * @param message Additional message
104
+ */
105
+ constructor(count?: number, message?: string);
106
+ }
107
+ ```
108
+
109
+ **Example:**
110
+
111
+ ```typescript
112
+ try {
113
+ await wait.until(() => isReady, 100, 50);
114
+ } catch (err) {
115
+ if (err instanceof TimeoutError) {
116
+ // "Waiting time exceeded(50 attempts)"
117
+ }
118
+ }
119
+ ```