@rscc/common-core 0.1.2 → 0.2.0
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/dist/crypto.cjs +116 -0
- package/dist/crypto.d.cts +26 -0
- package/dist/crypto.d.ts +26 -0
- package/dist/crypto.js +89 -0
- package/dist/index.cjs +947 -4
- package/dist/index.d.cts +552 -1
- package/dist/index.d.ts +552 -1
- package/dist/index.js +912 -3
- package/package.json +12 -2
package/dist/index.d.cts
CHANGED
|
@@ -247,6 +247,22 @@ interface ApiClientConfig {
|
|
|
247
247
|
* - onUnauthorized 는 시도마다 발화될 수 있다 (기본 판정에선 401 비재시도라 1회).
|
|
248
248
|
*/
|
|
249
249
|
retry?: ApiClientRetryOptions;
|
|
250
|
+
/**
|
|
251
|
+
* 지정 시 대상 메서드 요청에 멱등성 키 헤더를 자동 부착한다 (contracts/idempotency.md).
|
|
252
|
+
* 미지정 = 미부착(현행 동작).
|
|
253
|
+
*
|
|
254
|
+
* - 키는 {@link generateIdempotencyKey} 로 **논리 호출당 1회** 생성된다 —
|
|
255
|
+
* sentTraceId 와 같은 위치(재시도 클로저 밖)라 재시도 전 시도에 동일 키가
|
|
256
|
+
* 부착된다 ("같은 논리 작업 = 같은 키" 계약의 자동화).
|
|
257
|
+
* - 호출자가 이미 같은 이름의 헤더를 실었으면 덮어쓰지 않는다 (호출자 우선).
|
|
258
|
+
* - 새 논리 호출(새 request)은 새 키를 생성한다.
|
|
259
|
+
*/
|
|
260
|
+
idempotency?: {
|
|
261
|
+
/** 멱등성 키 헤더명. 기본 "Idempotency-Key". */
|
|
262
|
+
header?: string;
|
|
263
|
+
/** 부착 대상 메서드(대문자). 기본 ["POST","PATCH"] — 비멱등 메서드만. */
|
|
264
|
+
methods?: string[];
|
|
265
|
+
};
|
|
250
266
|
/**
|
|
251
267
|
* true 면 성공(2xx) 응답의 본문이 유효한 JSON 이 아닐 때(본문 읽기 `text()` 실패 포함)
|
|
252
268
|
* 조용히 null 을 반환하지 않고 code "INVALID_JSON" 의 ApiError 를 throw 한다
|
|
@@ -756,4 +772,539 @@ declare function isValidBusinessNumber(value: string | null | undefined): boolea
|
|
|
756
772
|
*/
|
|
757
773
|
declare function isValidCorporateNumber(value: string | null | undefined): boolean;
|
|
758
774
|
|
|
759
|
-
|
|
775
|
+
/**
|
|
776
|
+
* 멱등성 키 생성 — contracts/idempotency.md (수동 동기화).
|
|
777
|
+
*
|
|
778
|
+
* 비멱등 메서드(POST/PATCH)의 실수 재전송이 부수효과를 중복 실행하지 않도록,
|
|
779
|
+
* 클라이언트가 논리 요청당 고유 키를 `Idempotency-Key` 헤더로 보낸다.
|
|
780
|
+
* 키 형식: `^[A-Za-z0-9_-]{1,128}$` — UUIDv4(36자, 하이픈 포함) 권장.
|
|
781
|
+
*
|
|
782
|
+
* "같은 논리 작업 = 같은 키, 새 작업 = 새 키" 가 핵심이다 — 재시도 루프
|
|
783
|
+
* **바깥에서 1회 생성**해 전 시도에 동일 부착해야 한다. apiClient 의
|
|
784
|
+
* `idempotency` 옵션은 이를 자동화한다 (키가 재시도 클로저 밖에서 생성됨).
|
|
785
|
+
*/
|
|
786
|
+
/**
|
|
787
|
+
* 멱등성 키 신규 생성 — `crypto.randomUUID()` 우선(UUIDv4), 부재 환경에서는
|
|
788
|
+
* Math.random 기반 8-4-4-4-12 hex 폴백 (generateTraceId 관용구 — 형식 동일).
|
|
789
|
+
* 두 경로 모두 계약 형식 `[A-Za-z0-9_-]{1,128}` 을 만족한다.
|
|
790
|
+
*/
|
|
791
|
+
declare function generateIdempotencyKey(): string;
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* 웹훅 서명 — HMAC-SHA256. contracts/webhook-signature.md (수동 동기화).
|
|
795
|
+
*
|
|
796
|
+
* Java `com.rscc.common.crypto.WebhookSignature` / Python `rscc_common.webhook`
|
|
797
|
+
* 과 동일 규칙 (3언어 공유 골든 벡터 WS-01~07).
|
|
798
|
+
*
|
|
799
|
+
* - 서명 대상: `"{t}.{rawBody}"` — 본문은 **원문 바이트 그대로**(재직렬화 금지).
|
|
800
|
+
* - 서명: HMAC-SHA256 의 lowercase hex 64자. secret 은 UTF-8 바이트.
|
|
801
|
+
* - 헤더 값: `t=<unix초>,v1=<hex>[,v1=<hex>...]` — 다중 v1 = 무중단 시크릿
|
|
802
|
+
* 로테이션(어느 하나라도 일치하면 유효). 미지 key(v0/v2 등)는 무시.
|
|
803
|
+
*
|
|
804
|
+
* [주의] 언어별 시그니처 비대칭 — 계약 문서 인용: "JS 구현은 async 다 —
|
|
805
|
+
* WebCrypto(`crypto.subtle.sign`)가 Promise 기반이라 signWebhook/verifyWebhook 은
|
|
806
|
+
* Promise<string>/Promise<boolean> 을 반환한다. Java/Python 은 동기다.
|
|
807
|
+
* 시맨틱(입력→판정)은 3언어 동일하며 반환 형태만 다르다."
|
|
808
|
+
*
|
|
809
|
+
* Node 전용 API(`timingSafeEqual` 등) 미사용 — 브라우저/Node 공용
|
|
810
|
+
* (`globalThis.crypto.subtle`, Node 18+ / 모던 브라우저).
|
|
811
|
+
*/
|
|
812
|
+
/** 웹훅 서명 헤더명 기본값 (contracts/webhook-signature.md). */
|
|
813
|
+
declare const WEBHOOK_SIGNATURE_HEADER = "X-Rscc-Signature";
|
|
814
|
+
/**
|
|
815
|
+
* 웹훅 서명 헤더 값을 생성한다 (발신측) — 반환값이 `X-Rscc-Signature` 헤더
|
|
816
|
+
* 값 전체(`t=<unix초>,v1=<hex>`)다.
|
|
817
|
+
*
|
|
818
|
+
* 시크릿 로테이션 기간에는 신·구 시크릿으로 각각 sign 한 뒤 `v1` 을 병기해
|
|
819
|
+
* 발송한다 (`t=...,v1=<신>,v1=<구>` — t 가 같으므로 두 번째 결과의 `v1=` 부분만
|
|
820
|
+
* 이어 붙이면 된다).
|
|
821
|
+
*
|
|
822
|
+
* @param secret 서명 시크릿 (UTF-8 인코딩 후 HMAC 키로 사용).
|
|
823
|
+
* @param payload 요청 본문 — **원문 그대로** (파싱·재직렬화 금지, 계약).
|
|
824
|
+
* @param timestampSeconds 발신 시각 unix 초.
|
|
825
|
+
*/
|
|
826
|
+
declare function signWebhook(secret: string, payload: string | Uint8Array, timestampSeconds: number): Promise<string>;
|
|
827
|
+
/**
|
|
828
|
+
* 웹훅 서명을 검증한다 (수신측) — 형식 오류·스큐 초과·전 후보 불일치 모두
|
|
829
|
+
* 예외 없이 **false** 를 반환한다 (호출부 분기 단순화, 계약).
|
|
830
|
+
*
|
|
831
|
+
* 판정 절차: 헤더 파싱(t 정확히 1개·정수, v1 1개 이상) → 시계 스큐
|
|
832
|
+
* `|now - t| ≤ toleranceSeconds`(경계 포함) → 보유 시크릿 각각 × 헤더의 각 v1
|
|
833
|
+
* 상수시간 대조, 하나라도 일치 → true.
|
|
834
|
+
*
|
|
835
|
+
* @param opts.header 수신한 `X-Rscc-Signature` 헤더 값 (부재 시 null → false).
|
|
836
|
+
* @param opts.payload 수신한 요청 본문 — raw 바이트/원문 문자열.
|
|
837
|
+
* @param opts.secrets 보유 시크릿 (단일 또는 배열 — 로테이션 기간 신·구 병행).
|
|
838
|
+
* @param opts.toleranceSeconds 허용 스큐(초). 기본 300.
|
|
839
|
+
* @param opts.nowSeconds 현재 시각 unix 초 주입 (테스트용). 기본 시스템 시계.
|
|
840
|
+
*/
|
|
841
|
+
declare function verifyWebhook(opts: {
|
|
842
|
+
header: string | null;
|
|
843
|
+
payload: string | Uint8Array;
|
|
844
|
+
secrets: string | string[];
|
|
845
|
+
toleranceSeconds?: number;
|
|
846
|
+
nowSeconds?: number;
|
|
847
|
+
}): Promise<boolean>;
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* 벌크/부분 실패 봉투 — BulkResult. contracts/bulk.md (수동 동기화).
|
|
851
|
+
*
|
|
852
|
+
* Java `com.rscc.common.response.BulkResult` / Python `rscc_common.bulk` 와
|
|
853
|
+
* 동일 와이어 계약 (3언어 공유 골든 벡터 BK-01~04).
|
|
854
|
+
*
|
|
855
|
+
* - 항상 `CommonResponse` 봉투의 `data` 자리에 실린다.
|
|
856
|
+
* - **항목 성공/실패 판정은 `code` 유무다** — code 있으면 실패, 없으면 성공.
|
|
857
|
+
* - 실패 항목은 items 에 전량 필수 기재, 성공 항목은 id 전달 필요 시만 기재.
|
|
858
|
+
* - 부분 실패여도 HTTP 200 + `success: true` (벌크 연산 자체는 수행됨).
|
|
859
|
+
* - `total == succeeded + failed` 불변식.
|
|
860
|
+
*/
|
|
861
|
+
/**
|
|
862
|
+
* 항목별 처리 상세 — `index` 는 **요청 배열에서의 0-기점 인덱스**(필수,
|
|
863
|
+
* 원본 항목과 대응시키는 유일 키). `code` 존재 = 실패 항목.
|
|
864
|
+
*/
|
|
865
|
+
interface BulkResultItem {
|
|
866
|
+
/** 요청 배열에서의 0-기점 인덱스 (필수). */
|
|
867
|
+
index: number;
|
|
868
|
+
/** 실패 사유 코드 — error-codes.yaml 코드 문자열 재사용. **존재 = 실패 항목**. */
|
|
869
|
+
code?: string;
|
|
870
|
+
/** 실패 사유 한국어 메시지 (실패 항목이면 기재). */
|
|
871
|
+
message?: string;
|
|
872
|
+
/** 성공 항목이 생성/영향을 준 리소스 식별자 (전달 필요 시만). */
|
|
873
|
+
id?: string;
|
|
874
|
+
}
|
|
875
|
+
/** 벌크 처리 결과 페이로드 — `total == succeeded + failed` 불변식. */
|
|
876
|
+
interface BulkResult {
|
|
877
|
+
/** 요청에 담긴 전체 항목 수. */
|
|
878
|
+
total: number;
|
|
879
|
+
/** 성공 항목 수. */
|
|
880
|
+
succeeded: number;
|
|
881
|
+
/** 실패 항목 수. */
|
|
882
|
+
failed: number;
|
|
883
|
+
/** 항목별 상세 — 실패 전량 필수, 성공은 선택. 전량 성공·id 없음이면 `[]`. */
|
|
884
|
+
items: BulkResultItem[];
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* 값이 BulkResult 와이어 형태인지 판별하는 타입 가드 — total/succeeded/failed 가
|
|
888
|
+
* number, items 가 배열이고 각 요소에 number `index` 가 있는지만 검사한다.
|
|
889
|
+
* 선택 키(code/message/id)·미지 키는 검사하지 않는다 (관용적 읽기 —
|
|
890
|
+
* isValidationErrorData 관용구, 새 선택 키 추가는 non-breaking).
|
|
891
|
+
*/
|
|
892
|
+
declare function isBulkResult(value: unknown): value is BulkResult;
|
|
893
|
+
/** 실패 항목만 추출한다 — 판정 기준은 `code` 유무 (계약 규칙 1). */
|
|
894
|
+
declare function bulkFailures(result: BulkResult): BulkResultItem[];
|
|
895
|
+
/** BulkResult 빌더 — success/failure 를 순서대로 기록하고 build 로 확정한다. */
|
|
896
|
+
interface BulkResultBuilder {
|
|
897
|
+
/** 성공 항목 기록 — `id` 를 준 경우에만 items 에 기재된다 (응답 크기 억제). */
|
|
898
|
+
success(index: number, id?: string): BulkResultBuilder;
|
|
899
|
+
/** 실패 항목 기록 — items 에 반드시 기재된다 (code·message 필수, 계약 규칙 1·2). */
|
|
900
|
+
failure(index: number, code: string, message: string): BulkResultBuilder;
|
|
901
|
+
/** total/succeeded/failed 자동 계산으로 BulkResult 를 확정한다. */
|
|
902
|
+
build(): BulkResult;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* BulkResult 빌더 생성 — 서버/BFF 측에서 항목별 처리 결과를 순서대로 기록한다.
|
|
906
|
+
*
|
|
907
|
+
* ```ts
|
|
908
|
+
* const result = createBulkResultBuilder()
|
|
909
|
+
* .success(0, "ord_001")
|
|
910
|
+
* .failure(1, "400", "수량은 1 이상이어야 합니다.")
|
|
911
|
+
* .success(2) // id 없음 — items 미기재
|
|
912
|
+
* .build(); // { total: 3, succeeded: 2, failed: 1, items: [...] }
|
|
913
|
+
* ```
|
|
914
|
+
*/
|
|
915
|
+
declare function createBulkResultBuilder(): BulkResultBuilder;
|
|
916
|
+
|
|
917
|
+
/**
|
|
918
|
+
* 파일 업로드 검증 — 크기·확장자·매직바이트. contracts/file-upload.md (수동 동기화).
|
|
919
|
+
*
|
|
920
|
+
* Java `com.rscc.common.util.FileSniffer` / Python `rscc_common.upload` 와
|
|
921
|
+
* 동일 계약 (3언어 공유 골든 벡터 MB-01~11).
|
|
922
|
+
*
|
|
923
|
+
* **브라우저 프리검증이다** — 업로드 전에 사용자에게 즉시 피드백을 주는 용도이며,
|
|
924
|
+
* 프리검증 통과가 서버 검증을 대체하지 않는다 (보안 경계는 항상 서버).
|
|
925
|
+
*
|
|
926
|
+
* - 판정은 **컨테이너 수준**: docx/hwpx 는 `zip`, hwp(5.0)/doc 는 `cfbf` 로
|
|
927
|
+
* 판정된다 (내부 구조 열람은 비범위).
|
|
928
|
+
* - 판정 우선순위는 계약 테이블 위→아래, 첫 일치 kind 반환.
|
|
929
|
+
*/
|
|
930
|
+
/** 매직바이트 판정 결과 kind — 3언어 공유 소문자 문자열 (계약 테이블 고정). */
|
|
931
|
+
type FileKind = "png" | "jpeg" | "gif" | "webp" | "pdf" | "zip" | "cfbf" | "hwp3";
|
|
932
|
+
/**
|
|
933
|
+
* 선두 바이트의 매직바이트를 대조해 파일 kind 를 판정한다 — 계약 테이블
|
|
934
|
+
* 위→아래 첫 일치, 전부 불일치·빈 입력·시그니처보다 짧은 head 는 null.
|
|
935
|
+
*
|
|
936
|
+
* @param head 파일 선두 바이트 (webp 판정에 최대 12바이트 필요 — File.slice
|
|
937
|
+
* 등으로 앞부분만 읽어 넘기면 된다).
|
|
938
|
+
*/
|
|
939
|
+
declare function sniffFile(head: ArrayBuffer | Uint8Array): FileKind | null;
|
|
940
|
+
/**
|
|
941
|
+
* 확장자가 허용하는 kind 집합 — 계약 매핑표 고정. 미지 확장자는 빈 집합.
|
|
942
|
+
* 대소문자 무시, 선행 `.` 은 허용(제거 후 비교).
|
|
943
|
+
*/
|
|
944
|
+
declare function kindsForExtension(ext: string): ReadonlySet<FileKind>;
|
|
945
|
+
/** validateUpload 결과 — ok:false 면 첫 위반 사유·계약 메시지를 담는다. */
|
|
946
|
+
type UploadValidationResult = {
|
|
947
|
+
ok: true;
|
|
948
|
+
} | {
|
|
949
|
+
ok: false;
|
|
950
|
+
reason: "size" | "extension" | "content-mismatch";
|
|
951
|
+
message: string;
|
|
952
|
+
};
|
|
953
|
+
/**
|
|
954
|
+
* 업로드 파일 3중 검증 (브라우저 프리검증) — 순서: (1) 크기 ≤ maxSizeBytes →
|
|
955
|
+
* (2) 확장자 ∈ allowedExtensions → (3) 매직바이트 kind ∈ 확장자 허용 kind.
|
|
956
|
+
* 첫 위반의 사유·메시지(계약 문구)를 결과 객체로 반환한다 (예외 없음).
|
|
957
|
+
*
|
|
958
|
+
* 계약 매핑표에 없는 확장자를 allowlist 에 넣으려면 `extraMappings` 로 확장자 →
|
|
959
|
+
* 허용 kind 배열을 주입해야 한다(주입 확장자는 기본 표를 대체 — Python
|
|
960
|
+
* `extra_mappings` / Java `extraMappings` 대응). 매핑이 없는 허용 확장자는 콘텐츠
|
|
961
|
+
* 대조가 불가능해 콘텐츠 불일치로 거부된다 (Python 과 동일 판정 — 조용한 통과 금지).
|
|
962
|
+
*
|
|
963
|
+
* @param input.fileName 파일명 (확장자는 마지막 `.` 뒤, 대소문자 무시).
|
|
964
|
+
* @param input.size 파일 크기 바이트 (File.size).
|
|
965
|
+
* @param input.head 파일 선두 바이트 (12바이트 이상 권장 — webp 최대 요구량).
|
|
966
|
+
* @param input.maxSizeBytes 크기 상한 (엔드포인트 정책).
|
|
967
|
+
* @param input.allowedExtensions 허용 확장자 allowlist (대소문자 무시).
|
|
968
|
+
* @param input.extraMappings 확장자 → 허용 kind 확장 주입 (선택). 키는 소문자·
|
|
969
|
+
* 선행 `.` 없는 확장자.
|
|
970
|
+
*/
|
|
971
|
+
declare function validateUpload(input: {
|
|
972
|
+
fileName: string;
|
|
973
|
+
size: number;
|
|
974
|
+
head: ArrayBuffer | Uint8Array;
|
|
975
|
+
maxSizeBytes: number;
|
|
976
|
+
allowedExtensions: readonly string[];
|
|
977
|
+
extraMappings?: Readonly<Record<string, readonly FileKind[]>>;
|
|
978
|
+
}): UploadValidationResult;
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* 목록 조회 쿼리 빌더 — page/size/sort. contracts/query-params.md (수동 동기화).
|
|
982
|
+
*
|
|
983
|
+
* 요청 **생성측** 빌더다 — 서버 파서(Java `SortWhitelist`/`PageParams`,
|
|
984
|
+
* Python `rscc_common.query`)와 왕복 일치하는 쿼리스트링을 만든다.
|
|
985
|
+
*
|
|
986
|
+
* - sort 문법: `sort=<field>[,<direction>]` — 같은 이름 반복으로 다중 정렬
|
|
987
|
+
* (선언 순서 = 정렬 우선순위). direction 생략 시 서버 기본 asc.
|
|
988
|
+
* - 예약 이름 `page`/`size`/`sort` 를 필터 이름으로 재사용하면 throw (계약).
|
|
989
|
+
*/
|
|
990
|
+
/** 정렬 지정 1건 — direction 생략 시 값에 방향을 싣지 않는다 (서버 기본 asc). */
|
|
991
|
+
interface SortParam {
|
|
992
|
+
/** 정렬 필드 — 서버 화이트리스트와 정확 일치해야 한다 (대소문자 구분). */
|
|
993
|
+
field: string;
|
|
994
|
+
/** 정렬 방향. 생략 시 asc (서버 기본). */
|
|
995
|
+
direction?: "asc" | "desc";
|
|
996
|
+
}
|
|
997
|
+
/** buildListQuery 입력 — 전 필드 선택 (지정한 것만 쿼리에 실린다). */
|
|
998
|
+
interface ListQueryOptions {
|
|
999
|
+
/** 페이지 번호 — 0-기점 (contracts/pagination.md 와 동일 기점). */
|
|
1000
|
+
page?: number;
|
|
1001
|
+
/** 페이지 크기. */
|
|
1002
|
+
size?: number;
|
|
1003
|
+
/** 다중 정렬 — 배열 순서 = 정렬 우선순위 (순서 보존). */
|
|
1004
|
+
sort?: readonly SortParam[];
|
|
1005
|
+
/**
|
|
1006
|
+
* 필터 파라미터 (엔드포인트 고유 스키마). 배열 값은 같은 이름으로 반복 기재,
|
|
1007
|
+
* null/undefined 값은 생략. 예약 이름 page/size/sort 는 금지 — RangeError.
|
|
1008
|
+
*/
|
|
1009
|
+
filters?: Record<string, string | number | boolean | readonly (string | number | boolean)[] | null | undefined>;
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* 목록 조회 쿼리스트링을 조립한다 — `URLSearchParams` 반환
|
|
1013
|
+
* (`toString()` 하면 서버 파서와 왕복 일치: `page=2&size=50&sort=name%2Cdesc`).
|
|
1014
|
+
*
|
|
1015
|
+
* @throws RangeError filters 키가 예약 이름(page/size/sort)인 경우.
|
|
1016
|
+
*/
|
|
1017
|
+
declare function buildListQuery(options: ListQueryOptions): URLSearchParams;
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* 피처 플래그 읽기 — boolean 파싱 통일. contracts/feature-flags.md (수동 동기화).
|
|
1021
|
+
*
|
|
1022
|
+
* Java `com.rscc.common.util.FeatureFlags` / Python `rscc_common.feature_flags`
|
|
1023
|
+
* 와 동일 파싱 규칙 (3언어 공유 골든 벡터 FF-01~06).
|
|
1024
|
+
*
|
|
1025
|
+
* - 참 집합은 **정확히 `{"true","1","on","yes"}`** — 대소문자 무시·trim.
|
|
1026
|
+
* 그 외 전부 false ("y"·"t"·"enabled" 불인정 — 오타는 기능 꺼짐, 안전한 쪽).
|
|
1027
|
+
* - **키 부재(→default)와 값 불인식(→false)은 다르다** — 잘못 쓴 설정 값이
|
|
1028
|
+
* default 뒤로 숨지 않게 한다.
|
|
1029
|
+
* - JS 는 주입된 소스 객체만 본다 — **env 폴백 없음** (브라우저엔 env 가 없다,
|
|
1030
|
+
* 계약 명시). 빌드타임 치환·서버 전달 설정 객체를 소스로 주입한다.
|
|
1031
|
+
*/
|
|
1032
|
+
/**
|
|
1033
|
+
* 플래그 값을 boolean 으로 파싱한다 — 문자열은 trim·소문자화 후 참 집합
|
|
1034
|
+
* `{"true","1","on","yes"}` 대조, boolean 은 그대로, null/undefined 는 false.
|
|
1035
|
+
*/
|
|
1036
|
+
declare function parseFlag(value: string | boolean | null | undefined): boolean;
|
|
1037
|
+
/** 피처 플래그 리더 — 주입된 소스 객체에서 boolean 플래그를 읽는다. */
|
|
1038
|
+
interface FeatureFlagReader {
|
|
1039
|
+
/**
|
|
1040
|
+
* 플래그 조회 — 키 부재 시 defaultValue(기본 false), 키 존재 시
|
|
1041
|
+
* {@link parseFlag} 판정 결과 (불인식 값 → false, default 미적용).
|
|
1042
|
+
*/
|
|
1043
|
+
isEnabled(key: string, defaultValue?: boolean): boolean;
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* 피처 플래그 리더 생성 — 소스 객체(빌드타임 치환·서버 전달 설정)를 주입한다.
|
|
1047
|
+
* 키는 논리 키 그대로 조회한다 (예: `"search.rerank"`).
|
|
1048
|
+
*
|
|
1049
|
+
* ```ts
|
|
1050
|
+
* const flags = createFeatureFlags({ "search.rerank": "on" });
|
|
1051
|
+
* flags.isEnabled("search.rerank"); // true
|
|
1052
|
+
* flags.isEnabled("upload.hwp-preview", true); // 키 부재 → default true
|
|
1053
|
+
* ```
|
|
1054
|
+
*/
|
|
1055
|
+
declare function createFeatureFlags(source: Record<string, string | boolean | undefined>): FeatureFlagReader;
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* 주민등록번호·외국인등록번호(13자리) 형식 검증.
|
|
1059
|
+
*
|
|
1060
|
+
* **[중요] 2020-10 이후 발급분은 뒷자리(성별코드 제외 6자리)가 임의번호라서
|
|
1061
|
+
* mod-11 체크섬이 성립하지 않는다** — 따라서 기본 검증({@link isValidRrn})은
|
|
1062
|
+
* 체크섬을 포함하지 않고, 레거시 체크섬은 {@link rrnChecksumOkLegacy} 로 분리한다.
|
|
1063
|
+
*
|
|
1064
|
+
* 원천: Java `RrnUtils` / Python `rrn.py` 와 동일 규칙 (수동 동기화).
|
|
1065
|
+
*
|
|
1066
|
+
* 검증 범위: 13자리 형식 + 성별코드(1~8) + 생년월일 실존(윤년 포함 실제 달력).
|
|
1067
|
+
* **미래 날짜 검증은 비범위** — 기준 시점이 없는 순수 함수이므로 하지 않는다.
|
|
1068
|
+
* 정규화는 하이픈·스페이스·탭만 제거(bizno 파리티), 숫자 판정은 ASCII `[0-9]` 만
|
|
1069
|
+
* (전각 숫자 무효).
|
|
1070
|
+
*
|
|
1071
|
+
* ⚠️ 수집 최소화: 주민등록번호는 법령상 처리 근거가 있을 때만 취급하고, 저장 시
|
|
1072
|
+
* 암호화 의무(개인정보보호법 제24조의2)가 있으며, 검증 목적 달성 즉시 파기를
|
|
1073
|
+
* 권장한다.
|
|
1074
|
+
*/
|
|
1075
|
+
/**
|
|
1076
|
+
* 주민등록번호 표기에서 하이픈(`-`)·스페이스(` `)·탭(`\t`)을 위치 불문 제거한다.
|
|
1077
|
+
* 그 외 문자는 보존한다(검증 단계에서 무효 처리).
|
|
1078
|
+
*/
|
|
1079
|
+
declare function normalizeRrn(value: string): string;
|
|
1080
|
+
/**
|
|
1081
|
+
* 기본 검증 = 13자리 형식 + 성별코드 1~8 + 생년월일 실존(윤년 포함 실제 달력).
|
|
1082
|
+
* **체크섬 미포함** — 2020-10 이후 발급분은 뒷자리가 임의번호라 mod-11 이 성립하지
|
|
1083
|
+
* 않는다. null/undefined·형식 위반은 false (예외 없음).
|
|
1084
|
+
*/
|
|
1085
|
+
declare function isValidRrn(value: string | null | undefined): boolean;
|
|
1086
|
+
/**
|
|
1087
|
+
* 외국인등록번호 여부 — {@link isValidRrn} 을 통과하고 성별코드가 5~8 이면 true.
|
|
1088
|
+
* 무효한 값은 false.
|
|
1089
|
+
*/
|
|
1090
|
+
declare function isForeignerRrn(value: string | null | undefined): boolean;
|
|
1091
|
+
/**
|
|
1092
|
+
* 레거시 mod-11 체크섬 검증 — **2020-10 이전 발급분 한정**. 이후 발급분은
|
|
1093
|
+
* 임의번호라서 유효한 번호도 false 가 나올 수 있으므로, 유효성 판정에 쓰지 말 것.
|
|
1094
|
+
*
|
|
1095
|
+
* 검증식: 가중치 `[2,3,4,5,6,7,8,9,2,3,4,5]`, `check = (11 − sum%11) % 10`,
|
|
1096
|
+
* **외국인(성별코드 5~8)은 `(check+2) % 10` 보정** 후 13번째 자리와 대조.
|
|
1097
|
+
* 기본 검증({@link isValidRrn}) 불통과 값은 false.
|
|
1098
|
+
*/
|
|
1099
|
+
declare function rrnChecksumOkLegacy(value: string | null | undefined): boolean;
|
|
1100
|
+
/**
|
|
1101
|
+
* 생년월일을 `"YYYY-MM-DD"` 문자열로 추출한다(타임존 함정 차단 — `Date` 미사용).
|
|
1102
|
+
* 세기는 성별코드로 판정. 무효한 번호는 null.
|
|
1103
|
+
*/
|
|
1104
|
+
declare function rrnBirthDate(value: string | null | undefined): string | null;
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* 한국어 조사 자동 선택 — 받침 유무에 따라 은/는·이/가 등을 고른다.
|
|
1108
|
+
*
|
|
1109
|
+
* 원천: Java `JosaUtils` / Python `text/josa.py` 와 동일 규칙 (수동 동기화).
|
|
1110
|
+
*
|
|
1111
|
+
* 판정 규칙:
|
|
1112
|
+
* - 끝 공백(스페이스·탭)을 스킵한 마지막 문자로 판정
|
|
1113
|
+
* - 한글 음절 → `jong = (c − 0xAC00) % 28` (0 = 받침 없음)
|
|
1114
|
+
* - 숫자(ASCII 0~9) → 독음 음절(`영일이삼사오육칠팔구`)로 치환 후 동일 판정
|
|
1115
|
+
* - 그 외(영문·기호·빈 문자열) → 병기형 `은(는)/이(가)/을(를)/과(와)/(으)로/아(야)`
|
|
1116
|
+
* - (으)로 특례: 받침 없음 또는 ㄹ 받침(jong==8) → "로", 그 외 받침 → "으로"
|
|
1117
|
+
*/
|
|
1118
|
+
/** 지원하는 조사 쌍 — 이 6종 외 값은 런타임에서도 RangeError. */
|
|
1119
|
+
type JosaPair = "은/는" | "이/가" | "을/를" | "과/와" | "(으)로" | "아/야";
|
|
1120
|
+
/**
|
|
1121
|
+
* 단어에 어울리는 조사를 고른다 (조사만 반환).
|
|
1122
|
+
* 판정 불가(영문·기호·빈 문자열)면 병기형(`은(는)` 등)을 반환한다.
|
|
1123
|
+
* 지원하지 않는 조사 쌍은 RangeError.
|
|
1124
|
+
*/
|
|
1125
|
+
declare function pickJosa(word: string, josa: JosaPair): string;
|
|
1126
|
+
/**
|
|
1127
|
+
* 단어 뒤에 어울리는 조사를 붙여 반환한다 (`attachJosa("사과", "은/는")` → `"사과는"`).
|
|
1128
|
+
* 판정에서 스킵한 끝 공백(스페이스·탭)은 출력에서도 제거한다
|
|
1129
|
+
* (`"필드 "` → `"필드는"` — 벡터 JO-12).
|
|
1130
|
+
*/
|
|
1131
|
+
declare function attachJosa(word: string, josa: JosaPair): string;
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* 한국식 나이 계산 3종 — 만 나이·연 나이·보험 나이.
|
|
1135
|
+
*
|
|
1136
|
+
* 원천: Java `KoreanAgeUtils` / Python `age.py` 와 동일 규칙 (수동 동기화).
|
|
1137
|
+
*
|
|
1138
|
+
* 입력은 **`"YYYY-MM-DD"` 문자열 고정** (`Date` 객체 금지 — JS Date 의 타임존
|
|
1139
|
+
* 함정 원천 차단). 형식 위반·실존하지 않는 날짜·`기준일 < 생일` 은 RangeError.
|
|
1140
|
+
*/
|
|
1141
|
+
/**
|
|
1142
|
+
* 만 나이 — 생일이 지나지 않았으면 1 을 뺀다 (민법 기준).
|
|
1143
|
+
* 2/29 생은 평년 3/1 에 증가한다(월·일 튜플 비교 — Java `Period` 시맨틱과 일치).
|
|
1144
|
+
*/
|
|
1145
|
+
declare function ageMan(birth: string, on: string): number;
|
|
1146
|
+
/** 연 나이 — 연도 차이만 계산한다 (청소년 보호법 등의 연 나이). */
|
|
1147
|
+
declare function ageByYear(birth: string, on: string): number;
|
|
1148
|
+
/**
|
|
1149
|
+
* 보험 나이 — 만 개월수 `m`(당월 일 미도달 시 −1) 기준 `⌊(m+6)/12⌋`.
|
|
1150
|
+
* 생후 6개월이 지난 시점(상령일)마다 한 살씩 올라간다.
|
|
1151
|
+
*/
|
|
1152
|
+
declare function ageInsurance(birth: string, on: string): number;
|
|
1153
|
+
|
|
1154
|
+
/**
|
|
1155
|
+
* 한국 전화번호 정규화·분류·포맷·E.164 변환.
|
|
1156
|
+
*
|
|
1157
|
+
* 원천: Java `PhoneNumberUtils` / Python `phone.py` 와 동일 규칙 (수동 동기화).
|
|
1158
|
+
*
|
|
1159
|
+
* 타입 문자열(`mobile|landline|voip|safe|m2m|unknown`)은 3언어 공유 소문자
|
|
1160
|
+
* 와이어 값이다.
|
|
1161
|
+
*
|
|
1162
|
+
* 로그·화면 노출 권장 경로: `formatPhoneNumber(normalizePhoneNumber(x))` →
|
|
1163
|
+
* `maskPhone`(masking.ts) 파이프라인. maskPhone 은 부분 문자열 단위로 매칭하므로
|
|
1164
|
+
* 형식이 보장되지 않은 원본을 직접 넣지 말고 이 경로로 정형화한 뒤 마스킹할 것.
|
|
1165
|
+
*/
|
|
1166
|
+
/** 전화번호 분류 — 3언어 공유 소문자 타입 문자열. */
|
|
1167
|
+
type PhoneType = "mobile" | "landline" | "voip" | "safe" | "m2m" | "unknown";
|
|
1168
|
+
/**
|
|
1169
|
+
* 구분자(하이픈·스페이스·탭·괄호·점)를 제거하고, `+82` 접두는 `0` 을 보충해
|
|
1170
|
+
* 국내 표기로 역변환한다 (`"+82 10-1234-5678"` → `"01012345678"`).
|
|
1171
|
+
* 이미 `0` 으로 시작하는 `+82 010…` 표기는 `0` 을 중복 보충하지 않는다
|
|
1172
|
+
* (Java/Python 동일 규칙). 그 외 문자는 보존한다(분류 단계에서 unknown 처리).
|
|
1173
|
+
*/
|
|
1174
|
+
declare function normalizePhoneNumber(value: string): string;
|
|
1175
|
+
/**
|
|
1176
|
+
* 정규화 후 번호를 분류한다. 표에 없는 패턴·비숫자 포함은 `"unknown"`.
|
|
1177
|
+
* - mobile: 010(11자리), 011/016/017/018/019(10~11자리)
|
|
1178
|
+
* - landline: 02(9~10자리), 지역번호 표(10~11자리)
|
|
1179
|
+
* - voip: 070(11자리) / safe: 050X(11~12자리) / m2m: 012(11~12자리)
|
|
1180
|
+
*/
|
|
1181
|
+
declare function classifyPhoneNumber(value: string): PhoneType;
|
|
1182
|
+
/**
|
|
1183
|
+
* 정규화 후 표준 하이픈 그룹핑으로 포맷한다. 그룹핑 불가(unknown·비표준 길이)면
|
|
1184
|
+
* **정규화 문자열을 그대로 반환**한다 (예외 없음).
|
|
1185
|
+
* - 02: 2-3-4(9자리) / 2-4-4(10자리)
|
|
1186
|
+
* - 3자리 식별번호(이동·지역·070·012 11자리): 3-3-4(10자리) / 3-4-4(11자리)
|
|
1187
|
+
* - 050X: 4-3-4(11자리) / 4-4-4(12자리)
|
|
1188
|
+
*/
|
|
1189
|
+
declare function formatPhoneNumber(value: string): string;
|
|
1190
|
+
/**
|
|
1191
|
+
* E.164(`+82…`) 표기로 변환한다 — 분류 성공 시 선행 `0` 을 떼고 `+82` 를 붙인다.
|
|
1192
|
+
* `"unknown"` 은 null. 역변환(`+82` → `0…`)은 {@link normalizePhoneNumber} 가 담당.
|
|
1193
|
+
*/
|
|
1194
|
+
declare function toE164(value: string): string | null;
|
|
1195
|
+
|
|
1196
|
+
/**
|
|
1197
|
+
* 금액 한글 표기 3종 — 한글 수사·공문서 갖은자 표기·UI 축약.
|
|
1198
|
+
*
|
|
1199
|
+
* 원천: Java `KoreanAmountUtils` / Python `money.py` 와 동일 규칙 (수동 동기화).
|
|
1200
|
+
*
|
|
1201
|
+
* 지원 범위: `|amount| < 10^20` (만·억·조·경). 입력은 `number`(안전 정수) 또는
|
|
1202
|
+
* `bigint` — 비정수·비안전 정수·범위 초과는 RangeError.
|
|
1203
|
+
* 축약은 **내림**을 채택한다(금액 과대 표시 방지).
|
|
1204
|
+
*/
|
|
1205
|
+
/**
|
|
1206
|
+
* 순수 한글 수사 표기 — `12345678` → `"천이백삼십사만오천육백칠십팔"`.
|
|
1207
|
+
* 그룹 내 1 은 십/백/천 앞에서 생략하고, 그룹값 1 은 "일만/일억" 으로 명시한다.
|
|
1208
|
+
* 0 은 `"영"`, 음수는 `"마이너스 "` 접두.
|
|
1209
|
+
*/
|
|
1210
|
+
declare function toKoreanWords(amount: number | bigint): string;
|
|
1211
|
+
/**
|
|
1212
|
+
* 공문서 위조방지 표기 — `"금" + 전자리 명시 수사(일십·일백·일천 포함) + "원整"`.
|
|
1213
|
+
* `12345678` → `"금일천이백삼십사만오천육백칠십팔원整"`, 0 → `"금영원整"`.
|
|
1214
|
+
* 음수는 RangeError (공문서 금액에 음수 없음).
|
|
1215
|
+
*/
|
|
1216
|
+
declare function toFormalNotation(amount: number | bigint): string;
|
|
1217
|
+
/**
|
|
1218
|
+
* UI 축약 표기 — 소수 1자리 **내림**(금액 과대 표시 방지), `.0` 생략, 정수부 콤마.
|
|
1219
|
+
* - ≥1조 → `"X.Y조"` / ≥1억 → `"X.Y억"` / ≥1만 → 만 단위 내림 콤마 `"N,NNN만"`
|
|
1220
|
+
* - <1만 → 콤마 숫자 그대로(단위·"원" 없음), 음수는 `-` 접두.
|
|
1221
|
+
*/
|
|
1222
|
+
declare function abbreviateAmount(amount: number | bigint): string;
|
|
1223
|
+
|
|
1224
|
+
/**
|
|
1225
|
+
* 영업일 계산기 — 공휴일 데이터 주입형.
|
|
1226
|
+
*
|
|
1227
|
+
* 원천: Java `BusinessDays` / Python `business_days.py` 와 동일 규칙 (수동 동기화).
|
|
1228
|
+
*
|
|
1229
|
+
* **내장 공휴일 테이블은 없다** — 한국 공휴일은 대체공휴일·임시공휴일 등으로
|
|
1230
|
+
* 매년 변하므로 라이브러리에 박제하지 않고 소비자가 주입한다.
|
|
1231
|
+
*
|
|
1232
|
+
* 날짜는 **`"YYYY-MM-DD"` 문자열 고정** (`Date` 객체 금지 — 타임존 함정 차단).
|
|
1233
|
+
* 형식 위반·실존하지 않는 날짜는 RangeError. 내부 요일·가감 연산은 UTC 기준
|
|
1234
|
+
* epoch day 산술이라 실행 환경 타임존의 영향을 받지 않는다.
|
|
1235
|
+
*/
|
|
1236
|
+
/** 영업일 계산기 — {@link createBusinessDays} 로 생성한다. */
|
|
1237
|
+
interface BusinessDays {
|
|
1238
|
+
/** 영업일 여부 — 주말(토·일) 또는 주입된 공휴일이면 false. */
|
|
1239
|
+
isBusinessDay(date: string): boolean;
|
|
1240
|
+
/**
|
|
1241
|
+
* 영업일 n일 가감(n 음수 허용). **n=0 은 입력 날짜 그대로 반환한다(스냅 없음)** —
|
|
1242
|
+
* 비영업일 입력도 그대로.
|
|
1243
|
+
*/
|
|
1244
|
+
addBusinessDays(date: string, n: number): string;
|
|
1245
|
+
/** 다음 영업일 (엄격 초과 — 입력이 영업일이어도 그다음을 찾는다). */
|
|
1246
|
+
nextBusinessDay(date: string): string;
|
|
1247
|
+
/** 이전 영업일 (엄격 미만). */
|
|
1248
|
+
previousBusinessDay(date: string): string;
|
|
1249
|
+
/** 반개구간 `[start, endExclusive)` 의 영업일 수. `start > end` 는 RangeError. */
|
|
1250
|
+
countBusinessDays(start: string, endExclusive: string): number;
|
|
1251
|
+
}
|
|
1252
|
+
interface BusinessDaysOptions {
|
|
1253
|
+
/** 공휴일 목록 — `"YYYY-MM-DD"` 문자열 (불변 복사). */
|
|
1254
|
+
holidays: Iterable<string>;
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* 공휴일을 주입해 영업일 계산기를 만든다.
|
|
1258
|
+
*
|
|
1259
|
+
* ```ts
|
|
1260
|
+
* const bd = createBusinessDays({ holidays: ["2026-01-01"] });
|
|
1261
|
+
* bd.addBusinessDays("2025-12-31", 1); // "2026-01-02" — 1/1 스킵
|
|
1262
|
+
* ```
|
|
1263
|
+
*/
|
|
1264
|
+
declare function createBusinessDays(options: BusinessDaysOptions): BusinessDays;
|
|
1265
|
+
|
|
1266
|
+
/**
|
|
1267
|
+
* 한글 자모 분해·결합 + 혼합 질의 전방일치 매처.
|
|
1268
|
+
*
|
|
1269
|
+
* 원천: Java `HangulUtils` / Python `text/jamo.py` 와 동일 규칙 (수동 동기화).
|
|
1270
|
+
* 초성만 뽑는 기존 `chosung.ts`(무변경·하위호환)와 별개 모듈이다.
|
|
1271
|
+
*
|
|
1272
|
+
* 분해 정책(확정): **두벌식 키보드 자모열** — 초성·중성·종성을 호환 자모
|
|
1273
|
+
* (U+3131~U+3163)로 펼치되,
|
|
1274
|
+
* - 복합 모음 분해: ㅘ→ㅗㅏ, ㅙ→ㅗㅐ, ㅚ→ㅗㅣ, ㅝ→ㅜㅓ, ㅞ→ㅜㅔ, ㅟ→ㅜㅣ, ㅢ→ㅡㅣ
|
|
1275
|
+
* - 겹받침 분해: ㄳ→ㄱㅅ, ㄵ→ㄴㅈ, ㄶ→ㄴㅎ, ㄺ→ㄹㄱ, ㄻ→ㄹㅁ, ㄼ→ㄹㅂ,
|
|
1276
|
+
* ㄽ→ㄹㅅ, ㄾ→ㄹㅌ, ㄿ→ㄹㅍ, ㅀ→ㄹㅎ, ㅄ→ㅂㅅ
|
|
1277
|
+
* - **쌍자음(ㄲㄸㅃㅆㅉ·종성 ㄲㅆ)은 분해하지 않는다**(시프트 입력 = 단일 타건)
|
|
1278
|
+
* - 완성 음절이 아닌 문자(비한글·단독 자모)는 그대로 통과 — 단독 복합 자모
|
|
1279
|
+
* (ㅘ·ㄳ 등)도 분해하지 않는다 (Java/Python 동일 정책)
|
|
1280
|
+
*
|
|
1281
|
+
* 결합은 역변환(왼쪽부터 탐욕) — 완성 음절 입력 기준 `compose(decompose(s)) == s`
|
|
1282
|
+
* 왕복이 보장된다. 음절을 이루지 못하는 자모는 그대로 출력한다.
|
|
1283
|
+
*/
|
|
1284
|
+
/**
|
|
1285
|
+
* 문자열을 두벌식 키보드 자모열로 분해한다 (`"값"` → `"ㄱㅏㅂㅅ"`).
|
|
1286
|
+
* 완성 음절은 초·중·종성으로, 복합 모음·겹받침은 구성 자모로 펼친다.
|
|
1287
|
+
* 쌍자음은 분해하지 않고, 완성 음절이 아닌 문자(비한글·단독 자모)는 그대로
|
|
1288
|
+
* 통과한다 (Java `HangulUtils.decompose` / Python `jamo.decompose` 동일 정책).
|
|
1289
|
+
*/
|
|
1290
|
+
declare function decomposeHangul(s: string): string;
|
|
1291
|
+
/**
|
|
1292
|
+
* 자모열을 완성 음절로 결합한다 — {@link decomposeHangul} 의 역변환(왼쪽부터 탐욕).
|
|
1293
|
+
* 초성→중성(다음 모음과 복합 결합 시도)→종성(다음 문자가 모음이면 초성으로 양보,
|
|
1294
|
+
* 겹받침 결합 후에도 다음이 모음이면 둘째를 양보) 순으로 채운다.
|
|
1295
|
+
* 음절을 이루지 못하는 자모·비한글 문자는 그대로 출력한다.
|
|
1296
|
+
*/
|
|
1297
|
+
declare function composeHangul(s: string): string;
|
|
1298
|
+
/**
|
|
1299
|
+
* 혼합 질의 전방일치 매처 — 완성 음절·단독 자음·진행 중 음절이 섞인 질의가
|
|
1300
|
+
* 대상의 접두인지 판정한다 (`matchesHangul("ㅎ길", "홍길동")` → true).
|
|
1301
|
+
*
|
|
1302
|
+
* - 마지막이 아닌 질의 문자: 완성 음절은 대상과 정확 일치, 단독 자음(ㄱ~ㅎ)은
|
|
1303
|
+
* 대상 음절의 초성 일치, 비한글은 소문자화 후 비교(toChosung 관례)
|
|
1304
|
+
* - 마지막 질의 문자: **자모열 전방일치** — `decompose(질의)` 가
|
|
1305
|
+
* `decompose(대상)` 의 접두면 매치 (`"셔"`→`"션"`, `"ㄷ"`→`"동"` 커버)
|
|
1306
|
+
* - 빈 질의는 true, 질의가 대상보다 길면 false
|
|
1307
|
+
*/
|
|
1308
|
+
declare function matchesHangul(query: string, target: string): boolean;
|
|
1309
|
+
|
|
1310
|
+
export { type ApiClient, type ApiClientConfig, type ApiClientRetryOptions, ApiError, type ApiErrorInfo, type ApiRequestInfo, type ApiResponseInfo, type ApiResult, type BulkResult, type BulkResultBuilder, type BulkResultItem, type Bulkhead, BulkheadFullError, type BulkheadOptions, type BusinessDays, type BusinessDaysOptions, type CircuitBreaker, type CircuitBreakerOptions, type CircuitState, type CommonResponse, type FeatureFlagReader, type FieldErrorDetail, type FileKind, type JosaPair, type ListQueryOptions, type PageResponse, type PhoneType, ResultCode, type RetryOptions, type SortParam, type SseCallbacks, type SseFrameEvent, type SseSource, type TokenBucket, type TokenBucketOptions, type TtlCache, type TtlCacheOptions, type UploadValidationResult, type ValidationErrorData, WEBHOOK_SIGNATURE_HEADER, abbreviateAmount, ageByYear, ageInsurance, ageMan, attachJosa, buildListQuery, bulkFailures, classifyPhoneNumber, composeHangul, createApiClient, createBulkResultBuilder, createBulkhead, createBusinessDays, createCircuitBreaker, createFeatureFlags, createTokenBucket, createTtlCache, decodeJwtPayload, decomposeHangul, formatPhoneNumber, generateIdempotencyKey, getTokenExpiry, isBulkResult, isChosungQuery, isForeignerRrn, isRetryableStatus, isTokenExpired, isValidBusinessNumber, isValidCorporateNumber, isValidRrn, isValidationErrorData, kindsForExtension, maskCardNumber, maskEmail, maskName, maskPhone, maskSecret, matchesHangul, normalizeBusinessNumber, normalizePhoneNumber, normalizeRrn, parseFlag, parseRetryAfterMs, parseSseFrame, parseWireDateTime, pickJosa, readSseStream, retry, rrnBirthDate, rrnChecksumOkLegacy, sanitizeLogValue, signWebhook, sniffFile, stripZone, toChosung, toE164, toFormalNotation, toKoreanWords, toWireDate, toWireDateTime, validateUpload, verifyWebhook };
|