@rscc/common-core 0.1.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jeonghyeon-Ryu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # @rscc/common-core
2
+
3
+ RSCC 공통 코어 — `CommonResponse` 봉투 타입, API 클라이언트 팩토리(traceId 발신/에코), SSE 프레임 파서, JWT 디코더, 시크릿 마스킹 유틸. **프레임워크 무관, 런타임 의존성 0.**
4
+
5
+ ## 설치
6
+
7
+ ```bash
8
+ npm i @rscc/common-core
9
+ ```
10
+
11
+ - **Node >= 18** (전역 `fetch` / `Headers` / `ReadableStream` 전제)
12
+ - ESM + CJS 듀얼 빌드, 타입 선언(`.d.ts` / `.d.cts`) 동봉, `sideEffects: false`
13
+
14
+ ## 공개 API
15
+
16
+ | 모듈 | 공개 API | 설명 |
17
+ |---|---|---|
18
+ | types | `CommonResponse<T>` · `PageResponse<T>` · `ResultCode` | 응답 봉투·페이지네이션(page 0 시작)·결과 코드(값은 문자열) |
19
+ | apiClient | `createApiClient(config)` · `ApiError` · `ApiClient` · `ApiClientConfig` · `ApiResult<T>` | 봉투 언랩 · 401 콜백 · `X-Trace-Id` 발신/에코 |
20
+ | sse | `parseSseFrame` · `readSseStream` · `SseFrameEvent` · `SseSource` · `SseCallbacks` | SSE 프레임 파싱 — 청크/멀티바이트 경계 안전, 모르는 키는 skip |
21
+ | jwt | `decodeJwtPayload` · `getTokenExpiry` · `isTokenExpired` | base64url 디코드만 — **서명 미검증**, 만료 판단은 fail-closed |
22
+ | masking | `maskSecret` | 앞4+뒤4 노출, 8자 이하 전량 마스킹 (java `MaskingUtils` 와 동일 규칙) |
23
+
24
+ ## 사용 예시
25
+
26
+ ### createApiClient — CommonResponse 언랩 + traceId
27
+
28
+ ```ts
29
+ import { createApiClient, ApiError } from "@rscc/common-core";
30
+
31
+ const api = createApiClient({
32
+ baseUrl: "https://api.example.com", // 끝 슬래시 없이
33
+ getToken: () => localStorage.getItem("token"), // 선택 — Authorization: Bearer 부착
34
+ onUnauthorized: () => { /* 로그아웃/리다이렉트 정책은 소비자가 결정 */ },
35
+ });
36
+
37
+ // 성공 봉투 → data 언랩
38
+ const user = await api.request<UserInfo>("/api/v1/users/me");
39
+
40
+ // 실패 봉투/HTTP 에러 → ApiError { code, message, status, traceId }
41
+ try {
42
+ await api.request("/api/v1/things/999");
43
+ } catch (e) {
44
+ if (e instanceof ApiError) console.error(`[${e.traceId}] ${e.code}: ${e.message}`);
45
+ }
46
+ ```
47
+
48
+ ### SSE 스트림 소비
49
+
50
+ ```ts
51
+ import { readSseStream } from "@rscc/common-core";
52
+
53
+ const res = await fetch(streamUrl, { method: "POST", body, signal });
54
+ await readSseStream(res, {
55
+ onDelta: (chunk) => { /* 텍스트 증분 */ },
56
+ onSources: (sources) => { /* RAG 근거 */ },
57
+ onError: (message) => { /* in-band 오류 */ },
58
+ onDone: () => { /* data: [DONE] */ },
59
+ });
60
+ ```
61
+
62
+ ## 알려진 제약
63
+
64
+ - SSE 파서는 프레임 구분자 **LF(`\n\n`) 고정** — CRLF 로 정규화하는 프록시 뒤에서는 프레임이 분리되지 않는다.
65
+ - `baseUrl` 은 **끝 슬래시 없이** 지정할 것 — path 와 단순 연결하며 정규화하지 않는다.
66
+ - `requestWithMeta` 의 `ApiResult.response` 는 body 가 이미 소비된 상태 — headers/status 조회용.
67
+ - 2xx 응답인데 본문이 JSON 이 아니면 `data` 는 조용히 null 이 된다.
68
+ - JWT 디코더는 **서명을 검증하지 않는다** — 표시·만료 판단 전용. 인가 판단은 반드시 서버에서.
69
+
70
+ ## 문서 / 저장소
71
+
72
+ - 상세 문서: [js/README.md](https://github.com/Jeonghyeon-Ryu/r-common/blob/master/js/README.md)
73
+ - 와이어 계약(단일 소스): [contracts/](https://github.com/Jeonghyeon-Ryu/r-common/tree/master/contracts)
74
+ - React 훅: [@rscc/common-react](https://www.npmjs.com/package/@rscc/common-react)
75
+ - 저장소: [Jeonghyeon-Ryu/r-common](https://github.com/Jeonghyeon-Ryu/r-common) · MIT