@ddunigma/node 6.0.1 → 6.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +64 -2
  2. package/CONTRIBUTING.md +137 -0
  3. package/README.md +54 -39
  4. package/ROADMAP.md +12 -11
  5. package/dist/BrowserAdapter-FJYE5LZO.js +1 -0
  6. package/dist/BrowserAdapter-NXLXZCJX.cjs +1 -0
  7. package/dist/{ObfuscationLayer-DTlA723P.d.ts → ObfuscationLayer-C5TQHpYX.d.cts} +9 -11
  8. package/dist/{ObfuscationLayer-4rCOCRWH.d.cts → ObfuscationLayer-DmlvbjTB.d.ts} +9 -11
  9. package/dist/{WebStreams-C16QV2Dz.d.ts → WebStreams-DY1ovJBp.d.cts} +5 -9
  10. package/dist/{WebStreams-CY9E19f5.d.cts → WebStreams-DynLi09H.d.ts} +5 -9
  11. package/dist/browser.cjs +1 -1
  12. package/dist/browser.d.cts +12 -21
  13. package/dist/browser.d.ts +12 -21
  14. package/dist/browser.js +1 -1
  15. package/dist/chunk-B4QRMN45.js +9 -0
  16. package/dist/chunk-BUR4IORD.cjs +1 -0
  17. package/dist/chunk-C2AT5XRJ.js +1 -0
  18. package/dist/chunk-DAHLP6QA.cjs +1 -0
  19. package/dist/chunk-GR2WPLDK.js +1 -0
  20. package/dist/chunk-JATMOMX5.cjs +9 -0
  21. package/dist/chunk-XVV2OPRV.js +1 -0
  22. package/dist/chunk-ZMNWFYGY.cjs +1 -0
  23. package/dist/{core-BsIwjJK-.d.cts → core-DCeItMgU.d.cts} +35 -53
  24. package/dist/{core-BsIwjJK-.d.ts → core-DCeItMgU.d.ts} +35 -53
  25. package/dist/core.cjs +1 -1
  26. package/dist/core.d.cts +1 -1
  27. package/dist/core.d.ts +1 -1
  28. package/dist/core.js +1 -1
  29. package/dist/index.cjs +1 -1
  30. package/dist/index.d.cts +21 -26
  31. package/dist/index.d.ts +21 -26
  32. package/dist/index.js +1 -1
  33. package/dist/secure.browser.cjs +1 -1
  34. package/dist/secure.browser.d.cts +4 -4
  35. package/dist/secure.browser.d.ts +4 -4
  36. package/dist/secure.browser.js +1 -1
  37. package/dist/secure.cjs +1 -1
  38. package/dist/secure.d.cts +9 -9
  39. package/dist/secure.d.ts +9 -9
  40. package/dist/secure.js +1 -1
  41. package/docs/REFERENCE.md +45 -32
  42. package/package.json +22 -16
  43. package/dist/BrowserAdapter-A6RBN4N3.js +0 -1
  44. package/dist/BrowserAdapter-NWASGV3D.cjs +0 -1
  45. package/dist/chunk-6N7QYPEJ.js +0 -1
  46. package/dist/chunk-6ZYMNHFT.js +0 -1
  47. package/dist/chunk-7KUEHTG2.js +0 -1
  48. package/dist/chunk-BDP7E7K3.cjs +0 -1
  49. package/dist/chunk-HUUB5BUS.cjs +0 -1
  50. package/dist/chunk-JBUTKSCC.cjs +0 -9
  51. package/dist/chunk-LCOYWJWO.cjs +0 -1
  52. package/dist/chunk-VW2SZR2Z.js +0 -9
package/CHANGELOG.md CHANGED
@@ -2,6 +2,68 @@
2
2
 
3
3
  이 프로젝트의 주요 변경 사항을 기록합니다.
4
4
 
5
+ ## Unreleased
6
+
7
+ ## 6.1.1 - 2026-09-02
8
+
9
+ ### 정확성·안전성
10
+
11
+ - `throwOnError:false` fallback에서 padding 충돌 제거 후 charset이 1개가 되면 비트 패킹이
12
+ 종료되지 않던 문제를 수정했습니다. 변형된 charset을 다시 검증하고 유효한 preset으로
13
+ fallback합니다.
14
+ - 빈 custom charset·빈 padding·빈 coda, 유효 범위 밖 bit length, 잘못된 factory 타입을
15
+ 명시적으로 거부합니다. 생성자 옵션과 호출 옵션을 합친 뒤의 chunk 설정도 다시 검증합니다.
16
+ - `getStats`/`getStatsAsync`와 progress callback의 일반 오류를 공개 `Ddu64Error` 계약에 맞게
17
+ 래핑합니다.
18
+ - BrowserAdapter가 압축과 압축 해제 지원 여부를 각각 감지·캐시하도록 수정했습니다. 한쪽 Web
19
+ API만 제공하는 런타임에서도 지원되는 방향은 정상 동작합니다.
20
+
21
+ ### 기본 진입점 adapter 통합
22
+
23
+ - `@ddunigma/node`와 `@ddunigma/node/browser`의 비동기 secure 경로가 별도 secure 인스턴스를
24
+ 만들지 않고 현재 core에 adapter만 동적 import·주입합니다. 첫 동시 호출은 하나의 Promise를
25
+ 공유하며, charset·KDF salt 등 생성자 상태는 생성 시점 snapshot을 유지합니다.
26
+ - 압축된 입력은 wire metadata로 판별하므로 `decodeAsync`에 `compress:true`를 반복하지 않아도
27
+ lazy adapter가 로드됩니다. 명시적 `adapter`/`adapterFactory`는 자동 adapter보다 우선합니다.
28
+ - root와 browser 진입점이 실제 메서드에서 받는 `DduOptions`/`DduConstructorOptions` 및 adapter·
29
+ KDF 타입을 동일하게 export합니다. 동기 압축·암호화는 계속 `/secure` 진입점을 사용합니다.
30
+
31
+ ### 유지보수·배포
32
+
33
+ - 사용되지 않는 sync crypto 중계 모듈, 중복 테스트, 단일 호출 전달 helper와 오래된 작업 주석을
34
+ 제거하고 현재 구조를 기준으로 `CONTRIBUTING.md`, README, API reference를 정비했습니다.
35
+ - format check, production `any` 금지, benchmark lint/typecheck, packed ESM/CJS/browser secure smoke,
36
+ 패키지 크기 상한, Node 22/24/26 및 Bun/Deno smoke를 릴리스 게이트에 추가했습니다.
37
+ - npm OIDC trusted publishing workflow를 추가하고 이미 배포된 `6.1.0`과 충돌하지 않도록 패치
38
+ 버전을 `6.1.1`로 올렸습니다.
39
+
40
+ ## 6.1.0 - 2026-07-09
41
+
42
+ ### 기본 진입점에 lazy secure 추가 (편의성 개선)
43
+
44
+ 기본 진입점(`@ddunigma/node`, `@ddunigma/node/browser`)에서 secure 옵션(`compress`,
45
+ `encryptionKey`)이 감지된 **비동기** 호출은 이제 secure 래퍼(`Ddu64Secure`/`Ddu64SecureBrowser`)를
46
+ `import()`로 지연 로드해 그대로 처리합니다. lean 정적 import 그래프는 유지되며(어댑터는 동적
47
+ 청크에만 포함), 순수 인코딩/난독화 경로는 종전대로 어댑터를 로드하지 않습니다.
48
+
49
+ - 대상 async 메서드: `encodeAsync`/`decodeAsync`/`decodeToUint8ArrayAsync`/`decodeToBufferAsync`,
50
+ 그리고 압축 통계용 `getStatsAsync`(Node·브라우저 대칭).
51
+ - 동기 secure(예: `encode({ compress: true })`)는 여전히 지원하지 않으며, `encode`/`decode`/
52
+ `decodeToUint8Array`/`getStats`가 대칭적으로 `Ddu64AdapterError`를 던져 `encodeAsync`/
53
+ `decodeAsync`/`getStatsAsync` 또는 `@ddunigma/node/secure`를 안내합니다.
54
+ - **타입 표면 변경(주의):** 기본 진입점의 공개 옵션 타입이 `DduBaseOptions` → `DduOptions`
55
+ (secure 전체)로 넓어졌습니다. 이에 따라 6.0의 **컴파일 단계 차단**(`encode(x, { compress: true })`가
56
+ 타입 에러)이 **런타임 가드**로 전환됩니다. 동기 메서드에 secure 옵션을 넘기면 컴파일은
57
+ 통과하고 호출 시 위 `Ddu64AdapterError`가 발생합니다.
58
+ - 명시 `adapter`를 기본 진입점 생성자에 주입하면 base 코어가 sync/async secure를 직접 처리하며
59
+ lazy 우회 및 동기 가드가 비활성화됩니다.
60
+ - 성능: adapter 판정을 생성 시점 boolean 캐시로 옮겨, async hot-path에서 호출마다 발생하던
61
+ `getCharSetInfo()` 할당(charset 배열 복사 + 정보 객체)을 제거했습니다.
62
+
63
+ ## 6.0.1 - 2026-07-09
64
+
65
+ - npm package version metadata를 `6.0.1`로 갱신했습니다.
66
+
5
67
  ## 6.0.0
6
68
 
7
69
  이전 published 버전(5.0.0) 대비 호환성에 영향을 주는 변경이 포함되어 메이저로 올립니다.
@@ -133,8 +195,8 @@ payload를 거부**합니다(`requireEncryption` 기본값이 키 보유 시 `tr
133
195
 
134
196
  - 디코드 입력(인코딩 문자열) 길이 상한 `maxEncodedChars` 옵션 추가. 청크/개행 제거 등
135
197
  전처리 **이전에** 선검사하여, 개행만 가득한 거대한 입력이 출력 한도(`maxDecodedBytes`)를
136
- 우회하면서 대량 문자열 복사를 유발하던 문제를 차단합니다. 기본값은 `maxDecodedBytes`에
137
- 비례(`max(256MiB, maxDecodedBytes×4)` 문자)하여 정상 입력을 깨지 않습니다.
198
+ 우회하면서 대량 문자열 복사를 유발하던 문제를 차단합니다. 자동값은
199
+ `maxDecodedBytes×4+1024` 문자이며 호출 단위로 출력 한도를 낮추면 함께 낮아집니다.
138
200
 
139
201
  ### 기타 변경
140
202
 
@@ -0,0 +1,137 @@
1
+ # Contributing to ddunigma-node
2
+
3
+ 이 문서는 `@ddunigma/node`의 코드, 테스트, 문서, 패키지 진입점을 변경할 때 따라야 할
4
+ 프로젝트 컨벤션입니다. 현재 구조와 공개 API 호환성을 우선하며, 규칙이 충돌하면
5
+ 정확성, 와이어 호환성, 경량성, 가독성 순으로 판단합니다.
6
+
7
+ ## 핵심 원칙
8
+
9
+ - 코어는 커스텀 charset codec와 가역 난독화에 집중합니다.
10
+ - 압축·암호화는 플랫폼 어댑터를 통한 선택 기능입니다.
11
+ - runtime dependency 0개를 기본 제약으로 유지합니다.
12
+ - 공개 진입점·타입·실행 동작은 항상 같이 변경합니다.
13
+ - 출력 형식, charset 순서, footer, KDF 기본값 변경은 와이어 호환성 변경으로 취급합니다.
14
+ - 추상화는 실제 복잡도나 중복을 줄일 때만 추가합니다.
15
+
16
+ ## 진입점 역할
17
+
18
+ | 진입점 | 역할 | 정적 import 제약 |
19
+ | ------------------------ | -------------------------------------------------------------------------- | ------------------------------------------------- |
20
+ | `@ddunigma/node` | Node 기본 API. 동기 codec/checksum/난독화, 비동기 secure adapter lazy load | `node:crypto`, `node:zlib`, `NodeAdapter` 금지 |
21
+ | `@ddunigma/node/browser` | 브라우저 기본 API. 비동기 secure adapter lazy load | Node 내장 모듈, `BrowserAdapter` 정적 import 금지 |
22
+ | `@ddunigma/node/core` | 플랫폼 독립 core. 필요한 구현은 사용자가 주입 | 구체 adapter와 난독화 구현 import 금지 |
23
+ | `@ddunigma/node/secure` | adapter, Web Streams, 동기 Node secure API를 포함한 전체 표면 | 조건부 export의 Node/browser 경계 유지 |
24
+
25
+ `package.json#exports`는 공개 API 계약입니다. 진입점을 추가하거나 제거할 때는 ESM, CJS,
26
+ browser, worker, types 조건과 pack smoke를 함께 갱신합니다. 조건은 구체적인 항목에서
27
+ `default`로 배치합니다.
28
+
29
+ ## TypeScript·모듈
30
+
31
+ - strict TypeScript와 ES2022 번들 타겟을 유지합니다.
32
+ - 소스 import는 번들 후 경로와 맞도록 `.js` 확장자를 사용합니다.
33
+ - 공개 메서드가 받는 정확한 옵션 타입은 해당 진입점에서 다시 export합니다.
34
+ - production 코드의 `any`는 금지합니다. 외부 경계는 `unknown`으로 받고 검증합니다.
35
+ - 입력으로 받은 배열, typed array, 설정 객체를 지연 사용하면 생성 시점에 snapshot을 만듭니다.
36
+ - 공개 API 변경 시 `src/index.ts`, `src/browser.ts`, `src/core.ts`, secure 진입점과 `.d.ts`
37
+ pack 검증을 모두 확인합니다.
38
+
39
+ ## 함수 분리 기준
40
+
41
+ 다음 내용은 별도 헬퍼로 빼지 않고 호출 함수 내에 동기적으로 작성합니다.
42
+
43
+ - 한 곳에서만 사용하는 단순 조건 판정, 필드 할당, 객체 구성
44
+ - 즉시 다음 줄의 메서드를 호출하는 단순 전달 함수
45
+ - 부수효과가 없고 5-10줄 내에서 자연스럽게 읽히는 변환
46
+ - 이름이 있어도 도메인 경계나 재사용 가치가 생기지 않는 코드
47
+
48
+ 다음 경우에만 함수나 모듈로 분리합니다.
49
+
50
+ - 동기·비동기 파이프라인 등 두 곳 이상에서 실제로 공유
51
+ - 복잡한 불변식, wire parser, checksum, lookup table처럼 독립 테스트 가치가 있음
52
+ - 플랫폼 경계나 에러 분류 경계를 명확히 표현
53
+ - 반복 코드를 제거하면서도 인자 수와 제어 흐름이 더 단순해짐
54
+
55
+ 헬퍼를 추가할 때는 이름만으로 역할이 드러나야 하며, 미사용 인자를 `_`로 숨겨
56
+ 두지 않습니다. 인자가 필요 없으면 시그니처와 호출부에서 제거합니다.
57
+
58
+ ## 옵션·상태 규칙
59
+
60
+ - `undefined`는 미지정, `""`·`[]`·`0`·`false`는 사용자가 명시한 값입니다. truthy 검사로
61
+ 둘을 합치지 않습니다.
62
+ - 기본값 합성은 우선 `??`를 사용하고, boolean override는 명시적으로 처리합니다.
63
+ - 생성자 기본값과 호출별 옵션을 합성한 후 조합 불변식을 다시 검증합니다.
64
+ - 필터링, 중복 제거, padding 제거 등으로 데이터가 변하면 길이·bitLength·충돌을 재검증합니다.
65
+ - `throwOnError:false`는 무효한 상태를 인코더에 남기는 옵션이 아니라 유효한 preset으로
66
+ fallback하는 옵션입니다.
67
+ - 비트 패킹, 버퍼 할당, 반복문 경계에는 생성자 검증과 별개의 방어 검증을 둡니다.
68
+
69
+ ## Lazy adapter 규칙
70
+
71
+ - root의 평문 codec, checksum, 난독화 호출은 adapter chunk를 불러오지 않습니다.
72
+ - 비동기 압축·암복호화 파이프라인이 해당 단계에 도달했을 때만 adapter를 import합니다.
73
+ - lazy 활성화는 별도 core 인스턴스를 만들지 않고 현재 인스턴스에 adapter만 주입합니다.
74
+ - 첫 동시 호출은 Promise를 캐시해 import와 adapter 생성을 한 번만 수행합니다.
75
+ - 디코딩은 호출 옵션보다 wire metadata를 권위 있는 정보로 사용합니다.
76
+ - 사용자가 `adapter` 또는 `adapterFactory`를 주입하면 자동 adapter보다 우선합니다.
77
+
78
+ ## 에러 계약
79
+
80
+ - 모든 공개 API는 실패 시 `Ddu64Error` 하위 타입만 throw/reject합니다.
81
+ - 내부 모듈은 가능하면 발생 지점에서 charset, encode, decode, adapter, limit 에러를 분류합니다.
82
+ - 사용자 callback과 플랫폼 API의 plain `Error`는 공개 경계에서 원인을 보존해 래핑합니다.
83
+ - 이미 `Ddu64Error`인 오류는 중복 래핑하지 않습니다.
84
+ - 에러 문구에는 작업과 해결 경로를 포함하고 비밀키·평문·전체 payload를 포함하지 않습니다.
85
+
86
+ ## 주석·문서
87
+
88
+ - 주석은 코드가 보여주지 못하는 불변식, wire 호환성, 보안 경계, 성능 근거를 설명합니다.
89
+ - 코드를 그대로 반복하는 주석, 완료된 Task/요구사항 번호, 리팩터링 과정 기록은 남기지 않습니다.
90
+ - 난독화를 암호화, 무작위화, 자연어 생성으로 표현하지 않습니다.
91
+ - README는 첫 사용과 안전한 기본 경로, REFERENCE는 전체 계약, CHANGELOG는 사용자 관점의
92
+ 변경을 담당합니다.
93
+ - 구현이 바뀌면 같은 변경에서 JSDoc, README, REFERENCE, CHANGELOG을 갱신합니다.
94
+
95
+ ## 테스트
96
+
97
+ - 모든 테스트와 fixture는 각각 `test/`, `test/fixtures/`에 둡니다. `src/`에는 배포 대상
98
+ 소스만 유지합니다.
99
+ - 결함 수정은 수정 전에 실패하는 최소 회귀 테스트를 포함합니다.
100
+ - 단순 라운드트립을 파일별로 반복하지 않고 경계값, 불변식, 호환 벡터를 우선합니다.
101
+ - 사용자 입력 공간이 넓은 codec은 property test로 라운드트립·길이·에러 타입을 검증합니다.
102
+ - 와이어 호환성은 fixture/vector를 유지하고 이유 없이 재생성하지 않습니다.
103
+ - 진입점 변경은 소스 테스트와 packed ESM/CJS/browser smoke를 모두 추가합니다.
104
+ - 비정상 종료 위험은 유효한 상태로 진입하지 못하게 테스트하고, 필요하면 자식 프로세스
105
+ timeout으로 검증합니다.
106
+ - 테스트 제목과 주석은 현재 구현 용어를 사용하고 제거된 API의 부재를 계속 테스트하지 않습니다.
107
+
108
+ ## 성능·크기·안전성
109
+
110
+ - hot path에서 전체 크기 임시 배열, 불필요한 문자열 복사, 반복 lookup 객체 생성을 피합니다.
111
+ - 최적화는 benchmark 수치와 동치성 테스트를 함께 제공해야 합니다.
112
+ - 모든 디코딩·압축 해제·스트림 버퍼는 명시적 크기 상한을 유지합니다.
113
+ - 크기 제한은 각 진입점의 최소 사용 경로와 adapter 활성화 경로를 따로 검증합니다.
114
+ - 새 runtime dependency는 표준 API로 해결할 수 없고 크기·유지보수·공급망 비용을 정량화한 경우에만
115
+ 추가합니다.
116
+ - 난독화는 보안 경계가 아닙니다. 기밀성이 필요하면 AES-GCM과 충분한 entropy의 키를 사용합니다.
117
+ - 비밀번호를 키로 사용하면 PBKDF2, application-specific salt, 명시적 iteration을 사용합니다.
118
+
119
+ ## 호환성·릴리스
120
+
121
+ - 기능 제거, 출력 변경, 기본 KDF 변경, export 제거는 major 버전에서만 수행합니다.
122
+ - 미사용 공개 API는 즉시 삭제하지 않고 `@deprecated`와 대체 경로를 먼저 제공합니다.
123
+ - 배포 전 `pnpm verify`, `pnpm bench:guard`, 패키지 버전과 tag 일치를 확인합니다.
124
+ - `pnpm verify`는 typecheck, lint, format, dead-code, build, coverage, size, pack, runtime smoke를 모두 포함합니다.
125
+ - npm 배포는 긴 수명의 write token 대신 GitHub Actions OIDC trusted publishing을 사용합니다.
126
+ - CHANGELOG의 `Unreleased`는 다음 배포 변경만 포함하고, 태그된 변경은 버전·날짜 섹션으로 이동합니다.
127
+
128
+ npm package 설정의 Trusted Publisher는 GitHub 저장소 `parkjh2568/ddunigma-node`, workflow
129
+ `publish.yml`, environment `npm`, 허용 작업 `npm publish`와 정확히 일치시킵니다. GitHub Release
130
+ tag는 `v${package.json.version}` 형식이어야 하며 workflow가 불일치 배포를 차단합니다.
131
+
132
+ ## 참고
133
+
134
+ - [Node.js package exports and conditional exports](https://nodejs.org/api/packages.html)
135
+ - [TypeScript modules reference](https://www.typescriptlang.org/docs/handbook/modules/reference)
136
+ - [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/)
137
+ - [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)
package/README.md CHANGED
@@ -2,22 +2,17 @@
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/@ddunigma%2Fnode.svg)](https://www.npmjs.com/package/@ddunigma/node)
4
4
 
5
- 커스텀 charset 사용하는 Base64 스타일 인코더/디코더 라이브러리입니다.
5
+ Zero-dependency 커스텀 charset codec입니다. 한글 종성 조합 charset, 가역 난독화,
6
+ 선택적 압축·AES-256-GCM 암호화·CRC32 checksum을 Node.js와 브라우저에서 제공합니다.
6
7
 
7
- V2 추가사항
8
+ > 난독화와 CRC32는 기밀성이나 인증을 제공하지 않습니다. 보호가 필요한 데이터는
9
+ > 충분한 entropy의 키와 AES-GCM을 사용하세요.
8
10
 
9
- - 이제 한글 종성 결합 시스템을 활용하여 8개 기본 문자 × 8개 종성으로 64가지 조합을 만들어, 6비트를 한 글자로 표현합니다.
10
-
11
- ## Credits
12
-
13
- - Origin implementation by:
14
- - [@i3ls](https://github.com/i3l3)
15
- - [@gunu3371](https://github.com/gunu3371)
16
- - Original Repository: [ddunigma](https://github.com/i3l3/ddunigma)
17
-
18
- ## Requirements
11
+ ## 지원 환경
19
12
 
20
13
  - Node.js >= 22.0.0
14
+ - 브라우저 압축·암호화는 WebCrypto와 해당 `CompressionStream`/
15
+ `DecompressionStream` 형식을 지원하는 런타임
21
16
 
22
17
  ## Install
23
18
 
@@ -30,32 +25,27 @@ npm install @ddunigma/node
30
25
  ```typescript
31
26
  import { Ddu64, DduSetSymbol } from "@ddunigma/node";
32
27
 
33
- // V2 (기본, 한글 종성 결합 64개)
34
28
  const ddu = new Ddu64();
35
- ddu.encode("안녕하세요"); // "뎯땩잇땨뎪뎨잇잉뎯욱잇우뎯땨읶뎨뎯땩듂잊"
36
- ddu.decode("뎯땩잇땨뎪뎨잇잉뎯욱잇우뎯땨읶뎨뎯땩듂잊"); // "안녕하세요"
29
+ const encoded = ddu.encode("안녕하세요");
30
+ ddu.decode(encoded); // "안녕하세요"
37
31
 
38
- // V1 (구버전 호환, 8문자 쌍 방식)
39
- const dduV1 = new Ddu64({ dduSetSymbol: DduSetSymbol.DDU_V1 });
40
- dduV1.encode("안녕하세요"); // ".우땨땨이?땨뜌.이.뜌이?이!.우우땨이?우뜌.우땨뜌이이.뜌.우땨땨!이이야"
41
- dduV1.decode(".우땨땨이?땨뜌.이.뜌이?이!.우우땨이?우뜌.우땨뜌이이.뜌.우땨땨!이이야"); // "안녕하세요"
32
+ // 구버전 8문자 쌍 형식 호환
33
+ const legacy = new Ddu64({ dduSetSymbol: DduSetSymbol.DDU_V1 });
34
+ legacy.decode(legacy.encode("legacy"));
42
35
  ```
43
36
 
44
37
  ## 진입점
45
38
 
46
- | 진입점 | 기능 | 용도 |
47
- | ------------------------ | --------------------------------------- | --------------------- |
48
- | `@ddunigma/node` | 인코딩 + 한글 난독화 | Node 기본 lean |
49
- | `@ddunigma/node/browser` | 인코딩 + 한글 난독화 | 브라우저/Workers lean |
50
- | `@ddunigma/node/secure` | 압축/암호화/체크섬/Web Streams + 난독화 | 배터리 필요할 |
51
- | `@ddunigma/node/core` | 순수 인코딩/디코딩 | 최소 번들 |
39
+ | 진입점 | 기능 | 권장 용도 |
40
+ | ------------------------ | ----------------------------------------------------------- | ----------------------- |
41
+ | `@ddunigma/node` | Node codec/checksum/난독화 + async secure adapter lazy load | 기본 선택 |
42
+ | `@ddunigma/node/browser` | 브라우저 codec/checksum/난독화 + async adapter lazy load | 브라우저/Workers |
43
+ | `@ddunigma/node/secure` | sync/async adapter, Web Streams, adapter export | Node 동기 secure·스트림 |
44
+ | `@ddunigma/node/core` | 플랫폼 독립 codec/checksum | 최소 번들·직접 주입 |
52
45
 
53
- ```typescript
54
- import { Ddu64 as NodeDdu64 } from "@ddunigma/node";
55
- import { Ddu64 as BrowserDdu64 } from "@ddunigma/node/browser";
56
- import { Ddu64 as SecureDdu64 } from "@ddunigma/node/secure";
57
- import { Ddu64 as CoreDdu64 } from "@ddunigma/node/core";
58
- ```
46
+ Root 진입점은 평문 codec 경로에서 adapter를 불러오지 않습니다. 비동기 압축·
47
+ 암복호화가 실제로 실행될 때만 해당 런타임 adapter를 동적 import해 같은 core
48
+ 인스턴스에 주입합니다.
59
49
 
60
50
  ## 한글 난독화
61
51
 
@@ -67,27 +57,52 @@ const encoded = ddu.encode("재미있는 난독화");
67
57
  const decoded = ddu.decode(encoded);
68
58
  ```
69
59
 
70
- ## 압축, 암호화, 체크섬
60
+ 난독화는 charset 문자를 한글 음절로 바꾸는 결정론적 1:1 가역 변환입니다. 빈도 분포를
61
+ 숨기거나 암호화하지 않습니다. Checksum을 함께 사용하면 checksum marker는 한글 난독화
62
+ 밖의 ASCII suffix로 남습니다.
63
+
64
+ ## 압축·암호화·Checksum
71
65
 
72
66
  ```typescript
73
- import { Ddu64 } from "@ddunigma/node/secure";
67
+ import { Ddu64 } from "@ddunigma/node";
74
68
 
75
69
  const ddu = new Ddu64({
76
70
  compress: true,
77
71
  encryptionKey: "my-secret-key",
78
72
  keyDerivation: {
79
73
  algorithm: "pbkdf2",
80
- salt: "my-application-salt",
74
+ salt: "my-application-and-user-specific-salt",
81
75
  iterations: 600_000,
82
76
  },
83
77
  checksum: true,
84
78
  });
85
79
 
86
- const encoded = ddu.encode("보호할 데이터");
87
- const decoded = ddu.decode(encoded);
80
+ const encoded = await ddu.encodeAsync("보호할 데이터");
81
+ const decoded = await ddu.decodeAsync(encoded);
88
82
  ```
89
83
 
90
- ## Reference
84
+ 압축 여부는 wire metadata에서 판별하므로 decode에 `compress:true`를 반복할 필요가 없습니다.
85
+ 동기 압축·암호화가 필요하면 `@ddunigma/node/secure`를 import하세요.
86
+
87
+ ### 키 파생 주의사항
88
+
89
+ - 사람이 입력하는 비밀번호는 `pbkdf2`와 충분한 iteration을 사용하세요.
90
+ - `salt`는 애플리케이션·사용자별로 고유하게 관리하고 복호화 시 동일한 값을 제공하세요.
91
+ - 기본 PBKDF2 210,000회와 고정 fallback salt는 기존 wire 호환성을 위한 값입니다. 보안이
92
+ 중요한 새 데이터에서는 명시적 설정에 의존하세요.
93
+ - `sha256`은 구버전 호환 또는 충분한 entropy의 키에만 사용하세요.
94
+ - KDF 설정은 wire format에 기록되지 않으므로 데이터와 함께 버전 관리하세요.
95
+
96
+ OWASP의 현재 PBKDF2-HMAC-SHA256 권고와 애플리케이션 위협 모델을 함께 검토하세요.
97
+ [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)
98
+
99
+ ## 상세 문서
100
+
101
+ - [API Reference](docs/REFERENCE.md)
102
+ - [범위·설계 결정](ROADMAP.md)
103
+ - [개발·릴리스 컨벤션](CONTRIBUTING.md)
104
+
105
+ ## Credits
91
106
 
92
- 전체 옵션, 커스텀 charset, URL-Safe, Web Streams, `/core` 고급 사용법은
93
- [docs/REFERENCE.md](docs/REFERENCE.md)를 보세요.
107
+ - Origin implementation: [@i3ls](https://github.com/i3l3), [@gunu3371](https://github.com/gunu3371)
108
+ - Original repository: [ddunigma](https://github.com/i3l3/ddunigma)
package/ROADMAP.md CHANGED
@@ -7,7 +7,7 @@ envelope, ⑤ 프레임드 스트리밍 `DDS2`) 모두 검토·시제 구현 후
7
7
 
8
8
  ---
9
9
 
10
- ## ④ 암호화 KDF envelope v5 (self-describing KDF) 제외 (범위 밖)
10
+ ## ④ 암호화 KDF envelope v5 (self-describing KDF) - 제외 (범위 밖)
11
11
 
12
12
  > 결정: **구현하지 않음.** opt-in(`encryptionVersion: 5`)으로 한 차례 구현했다가 되돌렸다.
13
13
  > 이유: 자기기술 KDF envelope는 **인코딩 유틸리티의 정체성과 미스매치**다. 새로운 영구
@@ -22,7 +22,7 @@ envelope, ⑤ 프레임드 스트리밍 `DDS2`) 모두 검토·시제 구현 후
22
22
 
23
23
  ---
24
24
 
25
- ## ⑤ 진짜 스트리밍 (프레임드 와이어 포맷 `DDS2`) 제외 (범위 밖, 제거됨)
25
+ ## ⑤ 진짜 스트리밍 (프레임드 와이어 포맷 `DDS2`) - 제외 (범위 밖, 제거됨)
26
26
 
27
27
  > 결정: **구현하지 않음(제거 완료).** opt-in(`createFramedEncodeStream`/`createFramedDecodeStream`,
28
28
  > `src/streams/FramedStreams.ts`)으로 한 차례 구현했다가 ④ v5 KDF와 같은 이유로 되돌렸다.
@@ -58,18 +58,20 @@ envelope, ⑤ 프레임드 스트리밍 `DDS2`) 모두 검토·시제 구현 후
58
58
  > 영구 포맷을 늘리지 않는다(V4 페이로드/DDS1 스트림 헤더 불변). 따라서 분리·폐기 없이 전부
59
59
  > 유지한다.
60
60
  >
61
- > 진입점 구성은 4종으로 고정한다: 기본(`@ddunigma/node`, lean = 인코딩+난독화),
62
- > `@ddunigma/node/browser`(lean), `@ddunigma/node/secure`(배터리 풀세트),
63
- > `@ddunigma/node/core`(순수 인코딩). lean 진입점은 어댑터(zlib/crypto)를 정적 import하지 않아
64
- > 트리셰이킹되고, secure 진입점에만 배터리가 포함된다. 분리로 "경량 기본 + 필요 시 배터리"를
65
- > 동시에 만족한다.
61
+ > 진입점 구성은 4종으로 고정한다. 기본 `@ddunigma/node`와 `/browser`는 codec·체크섬·난독화를
62
+ > 동기로 처리하고, 비동기 압축·암복호화가 실제 실행될 때만 현재 core에 플랫폼 adapter를 동적
63
+ > import·주입한다. `/secure`는 adapter를 정적으로 포함해 Node 동기 secure API와 Web Streams,
64
+ > adapter export를 제공한다. `/core`는 구체 adapter와 난독화 구현을 포함하지 않는 직접 주입용
65
+ > 표면이다. 이 구조는 단일 root API의 편의성과 미사용 adapter의 정적 번들 비용 회피를 함께
66
+ > 유지한다.
66
67
  >
67
- > 비고: lean 진입점 번들 여유가 빠듯하므로(size-limit 예산 근접) **신규 기능은 secure/core
68
- > 쪽에 싣고 lean 경로는 가볍게 유지**한다.
68
+ > 비고: root의 lazy adapter는 별도 secure 인스턴스를 만들지 않으며 동시 import Promise를
69
+ > 공유한다. 동기 압축·암호화는 동적 import와 양립할 수 없으므로 `/secure`의 명시적 역할로 둔다.
70
+ > 신규 기능은 wire format·정적 import 그래프·size-limit에 미치는 영향을 함께 검토한다.
69
71
 
70
72
  ---
71
73
 
72
- ## 인코딩 성능 최적화 완료 (출력 불변)
74
+ ## 인코딩 성능 최적화 - 완료 (출력 불변)
73
75
 
74
76
  > `encoding-perf-optimization` 스펙으로 한글/커스텀 charset hot path를 최적화했다. `bitLength 6/8`
75
77
  > 직접 매핑 언롤 융합으로 인코드 `packPow2ToString` ~40→~183 MB/s(약 4.5x), 디코드
@@ -89,4 +91,3 @@ envelope, ⑤ 프레임드 스트리밍 `DDS2`) 모두 검토·시제 구현 후
89
91
  - 경량 인코더 정체성에 부합하지 않는 대형 기능은 애플리케이션 레벨/전용 라이브러리로 위임한다.
90
92
  - secure 진입점의 현행 배터리(압축/암호화/체크섬/Web Streams)는 전부 유지한다(신규 영구 포맷을
91
93
  늘리지 않으므로 ④⑤ 제외 논리와 충돌하지 않음).
92
- - 제거된 기능(⑤ DDS2)의 스펙 아티팩트(`.kiro/specs/dds2-true-streaming/`)는 정리했다.
@@ -0,0 +1 @@
1
+ export{a as BrowserAdapter}from'./chunk-C2AT5XRJ.js';import'./chunk-IZK7KCU7.js';import'./chunk-Q6SCBUV2.js';import'./chunk-EI7MMDWY.js';
@@ -0,0 +1 @@
1
+ 'use strict';var chunkZMNWFYGY_cjs=require('./chunk-ZMNWFYGY.cjs');require('./chunk-ZTGECGM2.cjs'),require('./chunk-JY2ZPBJK.cjs'),require('./chunk-BCUBYE76.cjs');Object.defineProperty(exports,"BrowserAdapter",{enumerable:true,get:function(){return chunkZMNWFYGY_cjs.a}});
@@ -1,4 +1,4 @@
1
- import { O as ObfuscationLayer } from './core-BsIwjJK-.js';
1
+ import { O as ObfuscationLayer } from './core-DCeItMgU.cjs';
2
2
 
3
3
  /**
4
4
  * Runtime detection helpers with no platform-specific imports.
@@ -17,11 +17,11 @@ declare function detectRuntime(): RuntimeId;
17
17
  /**
18
18
  * 한글 음절 난독화 레이어 구현.
19
19
  *
20
- * 암호화된 charset 인코딩 문자열을 결정론적 전단사 매핑을 사용하여
21
- * 자연스러운 한국어 음절 블록으로 변환합니다. 매핑은 다음을 보장합니다:
20
+ * charset 인코딩 문자열을 결정론적·가역적으로 한글 음절 블록으로 변환합니다.
21
+ * 매핑은 다음을 보장합니다:
22
22
  * - 모든 출력 문자가 유효한 한국어 음절 블록 (U+AC00–U+D7A3)
23
- * - 단일 문자 빈도가 기대 균등 빈도의 3배를 초과하지 않음
24
- * - 출력 길이 <= 입력 길이의 1.5배 (실제로는 1:1 매핑)
23
+ * - 출력 길이가 입력과 동일한 1:1 매핑
24
+ * 입력 문자 빈도는 보존되므로 보안적 무작위성이나 기밀성을 제공하지 않습니다.
25
25
  *
26
26
  * 플랫폼 독립적: Node.js 임포트 없음.
27
27
  *
@@ -33,8 +33,7 @@ declare function detectRuntime(): RuntimeId;
33
33
  *
34
34
  * 입력 알파벳(인코더가 사용하는 charset 문자)이 주어지면,
35
35
  * 이 레이어는 각 문자를 결정론적으로 한글 음절에 매핑합니다.
36
- * 매핑은 전단사(가역적)이며 위치에 따라 각 문자의 할당된 음절 범위를
37
- * 순환하여 출력 빈도를 균등하게 분배합니다.
36
+ * 위치에 따라 각 문자의 할당된 음절 범위를 순환하며 원본 문자로 복원할 수 있습니다.
38
37
  */
39
38
  declare class HangulObfuscationLayer implements ObfuscationLayer {
40
39
  private readonly config;
@@ -46,13 +45,12 @@ declare class HangulObfuscationLayer implements ObfuscationLayer {
46
45
  */
47
46
  constructor(alphabet: string[]);
48
47
  /**
49
- * 암호화된 charset 인코딩 문자열을 한글 음절로 변환합니다.
48
+ * charset 인코딩 문자열을 한글 음절로 변환합니다.
50
49
  *
51
50
  * 각 입력 문자는 할당된 범위의 한글 음절에 매핑됩니다.
52
- * 문자열 내 위치가 범위 내 어떤 음절을 사용할지 결정하여
53
- * 균등한 빈도 분포를 보장합니다.
51
+ * 문자열 내 위치가 범위 내 어떤 음절을 사용할지 결정합니다.
54
52
  *
55
- * @param input - 암호화된 charset 인코딩 문자열
53
+ * @param input - charset 인코딩 문자열
56
54
  * @returns 한글 음절 블록 문자열 (U+AC00–U+D7A3)
57
55
  * @throws 입력에 알파벳에 없는 문자가 포함된 경우 에러
58
56
  */
@@ -1,4 +1,4 @@
1
- import { O as ObfuscationLayer } from './core-BsIwjJK-.cjs';
1
+ import { O as ObfuscationLayer } from './core-DCeItMgU.js';
2
2
 
3
3
  /**
4
4
  * Runtime detection helpers with no platform-specific imports.
@@ -17,11 +17,11 @@ declare function detectRuntime(): RuntimeId;
17
17
  /**
18
18
  * 한글 음절 난독화 레이어 구현.
19
19
  *
20
- * 암호화된 charset 인코딩 문자열을 결정론적 전단사 매핑을 사용하여
21
- * 자연스러운 한국어 음절 블록으로 변환합니다. 매핑은 다음을 보장합니다:
20
+ * charset 인코딩 문자열을 결정론적·가역적으로 한글 음절 블록으로 변환합니다.
21
+ * 매핑은 다음을 보장합니다:
22
22
  * - 모든 출력 문자가 유효한 한국어 음절 블록 (U+AC00–U+D7A3)
23
- * - 단일 문자 빈도가 기대 균등 빈도의 3배를 초과하지 않음
24
- * - 출력 길이 <= 입력 길이의 1.5배 (실제로는 1:1 매핑)
23
+ * - 출력 길이가 입력과 동일한 1:1 매핑
24
+ * 입력 문자 빈도는 보존되므로 보안적 무작위성이나 기밀성을 제공하지 않습니다.
25
25
  *
26
26
  * 플랫폼 독립적: Node.js 임포트 없음.
27
27
  *
@@ -33,8 +33,7 @@ declare function detectRuntime(): RuntimeId;
33
33
  *
34
34
  * 입력 알파벳(인코더가 사용하는 charset 문자)이 주어지면,
35
35
  * 이 레이어는 각 문자를 결정론적으로 한글 음절에 매핑합니다.
36
- * 매핑은 전단사(가역적)이며 위치에 따라 각 문자의 할당된 음절 범위를
37
- * 순환하여 출력 빈도를 균등하게 분배합니다.
36
+ * 위치에 따라 각 문자의 할당된 음절 범위를 순환하며 원본 문자로 복원할 수 있습니다.
38
37
  */
39
38
  declare class HangulObfuscationLayer implements ObfuscationLayer {
40
39
  private readonly config;
@@ -46,13 +45,12 @@ declare class HangulObfuscationLayer implements ObfuscationLayer {
46
45
  */
47
46
  constructor(alphabet: string[]);
48
47
  /**
49
- * 암호화된 charset 인코딩 문자열을 한글 음절로 변환합니다.
48
+ * charset 인코딩 문자열을 한글 음절로 변환합니다.
50
49
  *
51
50
  * 각 입력 문자는 할당된 범위의 한글 음절에 매핑됩니다.
52
- * 문자열 내 위치가 범위 내 어떤 음절을 사용할지 결정하여
53
- * 균등한 빈도 분포를 보장합니다.
51
+ * 문자열 내 위치가 범위 내 어떤 음절을 사용할지 결정합니다.
54
52
  *
55
- * @param input - 암호화된 charset 인코딩 문자열
53
+ * @param input - charset 인코딩 문자열
56
54
  * @returns 한글 음절 블록 문자열 (U+AC00–U+D7A3)
57
55
  * @throws 입력에 알파벳에 없는 문자가 포함된 경우 에러
58
56
  */
@@ -1,4 +1,4 @@
1
- import { P as PlatformAdapter, I as KeyDerivationOptions, D as Ddu64Core, F as DduSecureConstructorOptions, H as DduStreamOptions } from './core-BsIwjJK-.js';
1
+ import { P as PlatformAdapter, G as KeyDerivationOptions, D as Ddu64Core, a as DduSecureConstructorOptions, I as DduStreamOptions } from './core-DCeItMgU.cjs';
2
2
 
3
3
  /**
4
4
  * 브라우저 플랫폼 어댑터 구현.
@@ -64,11 +64,6 @@ declare class BrowserAdapter implements PlatformAdapter {
64
64
  * DecompressionStream을 통해 Brotli 데이터를 압축 해제합니다.
65
65
  */
66
66
  brotliDecompress(data: Uint8Array, maxBytes?: number): Promise<Uint8Array>;
67
- /**
68
- * CompressionStream에 적합한 deflate 형식을 결정합니다.
69
- * Node.js zlib.deflateRaw와의 상호운용성을 위해 'deflate-raw'만 사용합니다.
70
- */
71
- private getDeflateFormat;
72
67
  private writeAndReadStream;
73
68
  private readAllChunks;
74
69
  }
@@ -77,11 +72,11 @@ declare class BrowserAdapter implements PlatformAdapter {
77
72
  * Browser 전용 secure Ddu64 래퍼.
78
73
  *
79
74
  * Ddu64Core를 확장하여 압축/암호화/체크섬(배터리 포함)을 지원합니다:
80
- * - BrowserAdapter 자동 주입 (WebCrypto/CompressionStream) → 비동기 압축/암호화/체크섬
75
+ * - BrowserAdapter 자동 주입 (WebCrypto/CompressionStream) → 비동기 압축/암호화
81
76
  * - HangulObfuscationLayer 자동 주입 → 한글 난독화 사용 가능
82
77
  *
83
78
  * Node.js 내장 모듈을 정적으로 import하지 않으므로 브라우저 번들에 crypto/zlib가
84
- * 끌려오지 않습니다. 구 `Ddu64Browser`의 배터리 동작을 계승합니다.
79
+ * 끌려오지 않습니다.
85
80
  *
86
81
  * @module Ddu64SecureBrowser
87
82
  */
@@ -90,7 +85,8 @@ declare class BrowserAdapter implements PlatformAdapter {
90
85
  * Browser 전용 secure Ddu64 인코더/디코더.
91
86
  *
92
87
  * Ddu64Core를 래핑하여 자동 BrowserAdapter 주입(WebCrypto/CompressionStream 기반
93
- * 압축/암호화/체크섬)을 제공합니다. 동기 압축/암호화 메서드는 지원하지 않으며
88
+ * 압축/암호화)을 제공합니다. 체크섬은 코어의 순수 JavaScript CRC32 경로를 사용합니다.
89
+ * 동기 압축/암호화 메서드는 지원하지 않으며
94
90
  * `encodeAsync`/`decodeAsync` 계열을 사용해야 합니다.
95
91
  *
96
92
  * @example
@@ -1,4 +1,4 @@
1
- import { P as PlatformAdapter, I as KeyDerivationOptions, D as Ddu64Core, F as DduSecureConstructorOptions, H as DduStreamOptions } from './core-BsIwjJK-.cjs';
1
+ import { P as PlatformAdapter, G as KeyDerivationOptions, D as Ddu64Core, a as DduSecureConstructorOptions, I as DduStreamOptions } from './core-DCeItMgU.js';
2
2
 
3
3
  /**
4
4
  * 브라우저 플랫폼 어댑터 구현.
@@ -64,11 +64,6 @@ declare class BrowserAdapter implements PlatformAdapter {
64
64
  * DecompressionStream을 통해 Brotli 데이터를 압축 해제합니다.
65
65
  */
66
66
  brotliDecompress(data: Uint8Array, maxBytes?: number): Promise<Uint8Array>;
67
- /**
68
- * CompressionStream에 적합한 deflate 형식을 결정합니다.
69
- * Node.js zlib.deflateRaw와의 상호운용성을 위해 'deflate-raw'만 사용합니다.
70
- */
71
- private getDeflateFormat;
72
67
  private writeAndReadStream;
73
68
  private readAllChunks;
74
69
  }
@@ -77,11 +72,11 @@ declare class BrowserAdapter implements PlatformAdapter {
77
72
  * Browser 전용 secure Ddu64 래퍼.
78
73
  *
79
74
  * Ddu64Core를 확장하여 압축/암호화/체크섬(배터리 포함)을 지원합니다:
80
- * - BrowserAdapter 자동 주입 (WebCrypto/CompressionStream) → 비동기 압축/암호화/체크섬
75
+ * - BrowserAdapter 자동 주입 (WebCrypto/CompressionStream) → 비동기 압축/암호화
81
76
  * - HangulObfuscationLayer 자동 주입 → 한글 난독화 사용 가능
82
77
  *
83
78
  * Node.js 내장 모듈을 정적으로 import하지 않으므로 브라우저 번들에 crypto/zlib가
84
- * 끌려오지 않습니다. 구 `Ddu64Browser`의 배터리 동작을 계승합니다.
79
+ * 끌려오지 않습니다.
85
80
  *
86
81
  * @module Ddu64SecureBrowser
87
82
  */
@@ -90,7 +85,8 @@ declare class BrowserAdapter implements PlatformAdapter {
90
85
  * Browser 전용 secure Ddu64 인코더/디코더.
91
86
  *
92
87
  * Ddu64Core를 래핑하여 자동 BrowserAdapter 주입(WebCrypto/CompressionStream 기반
93
- * 압축/암호화/체크섬)을 제공합니다. 동기 압축/암호화 메서드는 지원하지 않으며
88
+ * 압축/암호화)을 제공합니다. 체크섬은 코어의 순수 JavaScript CRC32 경로를 사용합니다.
89
+ * 동기 압축/암호화 메서드는 지원하지 않으며
94
90
  * `encodeAsync`/`decodeAsync` 계열을 사용해야 합니다.
95
91
  *
96
92
  * @example
package/dist/browser.cjs CHANGED
@@ -1 +1 @@
1
- 'use strict';var chunkBDP7E7K3_cjs=require('./chunk-BDP7E7K3.cjs'),chunkJBUTKSCC_cjs=require('./chunk-JBUTKSCC.cjs'),chunkZTGECGM2_cjs=require('./chunk-ZTGECGM2.cjs'),chunkBCUBYE76_cjs=require('./chunk-BCUBYE76.cjs');var t=class extends chunkJBUTKSCC_cjs.i{static{chunkBCUBYE76_cjs.a(this,"Ddu64Browser");}constructor(r,o,i){let e=chunkJBUTKSCC_cjs.b(r,o,i),a={...e.dduOptions,...e.dduChar!==void 0?{dduChar:e.dduChar}:{},...e.paddingChar!==void 0?{paddingChar:e.paddingChar}:{},obfuscationLayerFactory:e.dduOptions?.obfuscationLayerFactory??(p=>new chunkBDP7E7K3_cjs.a(p))};super(a);}encode(r,o){return super.encode(r,o)}encodeAsync(r,o){return super.encodeAsync(r,o)}decode(r,o){return super.decode(r,o)}decodeAsync(r,o){return super.decodeAsync(r,o)}decodeToUint8Array(r,o){return super.decodeToUint8Array(r,o)}decodeToUint8ArrayAsync(r,o){return super.decodeToUint8ArrayAsync(r,o)}getStats(r,o){return super.getStats(r,o)}getStatsAsync(r,o){return super.getStatsAsync(r,o)}};Object.defineProperty(exports,"HangulObfuscationLayer",{enumerable:true,get:function(){return chunkBDP7E7K3_cjs.a}});Object.defineProperty(exports,"createEncoderObfuscationLayer",{enumerable:true,get:function(){return chunkBDP7E7K3_cjs.b}});Object.defineProperty(exports,"detectRuntime",{enumerable:true,get:function(){return chunkBDP7E7K3_cjs.c}});Object.defineProperty(exports,"CharsetBuilder",{enumerable:true,get:function(){return chunkJBUTKSCC_cjs.j}});Object.defineProperty(exports,"Ddu64Core",{enumerable:true,get:function(){return chunkJBUTKSCC_cjs.i}});Object.defineProperty(exports,"DduSetSymbol",{enumerable:true,get:function(){return chunkJBUTKSCC_cjs.a}});Object.defineProperty(exports,"Ddu64AdapterError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.m}});Object.defineProperty(exports,"Ddu64CharsetError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.j}});Object.defineProperty(exports,"Ddu64ChecksumError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.i}});Object.defineProperty(exports,"Ddu64CompressionError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.e}});Object.defineProperty(exports,"Ddu64DecodeError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.d}});Object.defineProperty(exports,"Ddu64DecompressionError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.f}});Object.defineProperty(exports,"Ddu64DecryptionError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.h}});Object.defineProperty(exports,"Ddu64EncodeError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.c}});Object.defineProperty(exports,"Ddu64EncryptionError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.g}});Object.defineProperty(exports,"Ddu64Error",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.b}});Object.defineProperty(exports,"Ddu64ErrorCode",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.a}});Object.defineProperty(exports,"Ddu64InvalidInputError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.k}});Object.defineProperty(exports,"Ddu64LimitError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.l}});Object.defineProperty(exports,"Ddu64ObfuscationError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.n}});Object.defineProperty(exports,"Ddu64StreamError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.o}});Object.defineProperty(exports,"isDdu64Error",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.p}});exports.Ddu64=t;exports.Ddu64Browser=t;
1
+ 'use strict';var chunkBUR4IORD_cjs=require('./chunk-BUR4IORD.cjs'),chunkJATMOMX5_cjs=require('./chunk-JATMOMX5.cjs'),chunkZTGECGM2_cjs=require('./chunk-ZTGECGM2.cjs'),chunkBCUBYE76_cjs=require('./chunk-BCUBYE76.cjs');var t=class extends chunkJATMOMX5_cjs.i{static{chunkBCUBYE76_cjs.a(this,"Ddu64Browser");}#o;#e;#t;constructor(o,r,d){let e=chunkJATMOMX5_cjs.b(o,r,d),p=e.dduOptions?.adapter!==void 0||e.dduOptions?.adapterFactory!==void 0,n={...e.dduOptions,...e.dduChar!==void 0?{dduChar:e.dduChar}:{},...e.paddingChar!==void 0?{paddingChar:e.paddingChar}:{},asyncAdapterFactory:e.dduOptions?.asyncAdapterFactory??(p?void 0:()=>import('./BrowserAdapter-NXLXZCJX.cjs').then(({BrowserAdapter:s})=>new s)),obfuscationLayerFactory:e.dduOptions?.obfuscationLayerFactory??(s=>new chunkBUR4IORD_cjs.a(s))};super(n),this.#o=n.compress===true,this.#e=n.encryptionKey!==void 0,this.#t=p;}encode(o,r){return this.#r("encode",r),super.encode(o,r)}decodeToUint8Array(o,r){return this.#r("decode",r),super.decodeToUint8Array(o,r)}getStats(o,r){return this.#r("encode",r,false),super.getStats(o,r)}#r(o,r,d=true){if(!this.#t&&((r?.compress??this.#o)===true||d&&this.#e))throw new chunkZTGECGM2_cjs.m("@ddunigma/node/browser: use encodeAsync/decodeAsync/getStatsAsync, or @ddunigma/node/secure for secure options.",o)}};Object.defineProperty(exports,"HangulObfuscationLayer",{enumerable:true,get:function(){return chunkBUR4IORD_cjs.a}});Object.defineProperty(exports,"createEncoderObfuscationLayer",{enumerable:true,get:function(){return chunkBUR4IORD_cjs.b}});Object.defineProperty(exports,"detectRuntime",{enumerable:true,get:function(){return chunkBUR4IORD_cjs.c}});Object.defineProperty(exports,"CharsetBuilder",{enumerable:true,get:function(){return chunkJATMOMX5_cjs.j}});Object.defineProperty(exports,"Ddu64Core",{enumerable:true,get:function(){return chunkJATMOMX5_cjs.i}});Object.defineProperty(exports,"DduSetSymbol",{enumerable:true,get:function(){return chunkJATMOMX5_cjs.a}});Object.defineProperty(exports,"Ddu64AdapterError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.m}});Object.defineProperty(exports,"Ddu64CharsetError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.j}});Object.defineProperty(exports,"Ddu64ChecksumError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.i}});Object.defineProperty(exports,"Ddu64CompressionError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.e}});Object.defineProperty(exports,"Ddu64DecodeError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.d}});Object.defineProperty(exports,"Ddu64DecompressionError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.f}});Object.defineProperty(exports,"Ddu64DecryptionError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.h}});Object.defineProperty(exports,"Ddu64EncodeError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.c}});Object.defineProperty(exports,"Ddu64EncryptionError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.g}});Object.defineProperty(exports,"Ddu64Error",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.b}});Object.defineProperty(exports,"Ddu64ErrorCode",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.a}});Object.defineProperty(exports,"Ddu64InvalidInputError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.k}});Object.defineProperty(exports,"Ddu64LimitError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.l}});Object.defineProperty(exports,"Ddu64ObfuscationError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.n}});Object.defineProperty(exports,"Ddu64StreamError",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.o}});Object.defineProperty(exports,"isDdu64Error",{enumerable:true,get:function(){return chunkZTGECGM2_cjs.p}});exports.Ddu64=t;exports.Ddu64Browser=t;