@ddunigma/node 3.0.1 → 3.0.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/README.md CHANGED
@@ -43,305 +43,317 @@ dduV1.decode(".우땨땨이?땨뜌.이.뜌이?이!.우우땨이?우뜌.우땨뜌
43
43
 
44
44
  ---
45
45
 
46
- ## 기본 사용법
47
-
48
- ### 인코딩/디코딩
46
+ ## Binary Data
49
47
 
50
48
  ```typescript
51
- import { Ddu64 } from "@ddunigma/node";
52
-
53
- const encoder = new Ddu64();
49
+ const ddu = new Ddu64();
50
+ const input = new Uint8Array([0, 1, 127, 128, 255]);
54
51
 
55
- const encoded = encoder.encode("Hello World!");
56
- const decoded = encoder.decode(encoded);
52
+ const encoded = ddu.encode(input);
53
+ const bytes = ddu.decodeToUint8Array(encoded);
54
+ const buffer = ddu.decodeToBuffer(encoded); // Node.js Buffer
57
55
  ```
58
56
 
59
- ### 커스텀 charset
57
+ ## Presets
60
58
 
61
59
  ```typescript
62
- // 문자열 또는 배열로 charset 지정
63
- const encoder = new Ddu64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "=");
60
+ import { Ddu64, DduSetSymbol } from "@ddunigma/node";
64
61
 
65
- // 종성 결합 커스텀 charset (dduChar × codaChar 동적 생성)
66
- const encoder2 = new Ddu64(["가", "나", "다", "라"], "뭐", {
67
- codaChar: ["", "ㄱ", "ㄲ", "ㄷ"], // 4×4 = 16개 조합
68
- });
62
+ // 기본값 - 한글 종성 결합 64문자
63
+ new Ddu64();
64
+
65
+ // 구버전 호환 8문자
66
+ new Ddu64(undefined, undefined, { dduSetSymbol: DduSetSymbol.DDU_V1 });
67
+
68
+ // 영문+숫자 64문자
69
+ new Ddu64(undefined, undefined, { dduSetSymbol: DduSetSymbol.ONECHARSET });
69
70
  ```
70
71
 
71
- ### 프리셋
72
+ | Symbol | 문자 수 | 설명 |
73
+ | ------------ | ------: | ---------------------------------- |
74
+ | `DDU` | 64 | 한글 기본 문자 8개 × 종성 8개 조합 |
75
+ | `DDU_V1` | 8 | 기존 8문자 쌍 방식 (하위 호환) |
76
+ | `ONECHARSET` | 64 | 영문, 숫자, 일부 특수문자 |
72
77
 
73
- | Symbol | 문자 수 | 비트 | 설명 |
74
- | ------------ | ------- | ---- | ------------------------------------ |
75
- | `DDU` | 64 | 6 | 한글 종성 결합 (8 기본문자 × 8 종성) |
76
- | `DDU_V1` | 8 | 3 | 구버전 호환 (뜌땨이우야!?.) |
77
- | `ONECHARSET` | 64 | 6 | 영문 + 숫자 + 특수문자 |
78
+ ## Custom Charset
78
79
 
79
80
  ```typescript
80
- import { Ddu64, DduSetSymbol } from "@ddunigma/node";
81
-
82
- const encoder = new Ddu64(undefined, undefined, {
83
- dduSetSymbol: DduSetSymbol.ONECHARSET,
81
+ // 문자열로 직접 지정
82
+ const base64Like = new Ddu64(
83
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
84
+ "=",
85
+ );
86
+
87
+ // 한글 종성 조합으로 커스텀 charset 생성
88
+ const hangulCoda = new Ddu64(["가", "나", "다", "라"], "뭐", {
89
+ codaChar: ["", "ㄱ", "ㄲ", "ㄷ"],
84
90
  });
91
+ // → 가, 각, 갂, 갇, 나, 낙, 낚, 낟, 다, 닥, 닦, 닫, 라, 락, 랔, 랗 (16문자)
85
92
  ```
86
93
 
87
- ---
94
+ ## CharsetBuilder
88
95
 
89
- ## 고급 기능
96
+ ```typescript
97
+ import { CharsetBuilder, Ddu64 } from "@ddunigma/node";
90
98
 
91
- ### 압축
99
+ // Base64에서 혼동 문자 제거 후 2의 제곱수로 맞추기
100
+ const { charset, padding } = CharsetBuilder.base64()
101
+ .excludeConfusing()
102
+ .limitToPowerOfTwo()
103
+ .buildWithPadding();
92
104
 
93
- deflate(기본) 또는 brotli 압축을 지원합니다. 디코딩 시 자동으로 압축 여부를 감지합니다.
105
+ const ddu = new Ddu64(charset, padding);
94
106
 
95
- ```typescript
96
- const encoder = new Ddu64();
107
+ // 유니코드 범위에서 생성
108
+ const chars = CharsetBuilder.fromUnicodeRange(0x4e00, 0x4e3f)
109
+ .shuffle(12345)
110
+ .limitToPowerOfTwo()
111
+ .build();
112
+ ```
97
113
 
98
- // 호출 시 옵션으로 지정
99
- const encoded = encoder.encode(longText, { compress: true });
100
- const decoded = encoder.decode(encoded);
114
+ ## Compression
101
115
 
102
- // 생성자에서 기본 활성화
103
- const compressEncoder = new Ddu64(undefined, undefined, {
104
- compress: true,
105
- compressionAlgorithm: "brotli",
106
- compressionLevel: 6,
116
+ ```typescript
117
+ const ddu = new Ddu64(undefined, undefined, {
118
+ compress: true, // 압축 활성화
119
+ compressionAlgorithm: "deflate", // "deflate" | "brotli"
120
+ compressionLevel: 6, // deflate: 0-9, brotli: 0-11
107
121
  });
122
+
123
+ const encoded = ddu.encode("A".repeat(1000)); // 압축되어 짧아짐
124
+ const decoded = ddu.decode(encoded);
108
125
  ```
109
126
 
110
- ### 암호화
127
+ 압축은 원본보다 작아질 때만 적용됩니다. 압축 결과가 더 크면 비압축으로 저장됩니다.
111
128
 
112
- AES-256-GCM 암호화를 내장합니다. 동일한 키로 생성된 인코더만 복호화할 수 있습니다.
129
+ ## Encryption
113
130
 
114
131
  ```typescript
115
- const encoder = new Ddu64(undefined, undefined, {
132
+ // SHA-256 파생 (기본)
133
+ const ddu = new Ddu64(undefined, undefined, {
116
134
  encryptionKey: "my-secret-key",
117
135
  });
118
136
 
119
- const encoded = encoder.encode("비밀 메시지");
120
- const decoded = encoder.decode(encoded);
137
+ const encoded = ddu.encode("secret message");
138
+ const decoded = ddu.decode(encoded); // 같은 키로만 복호화 가능
139
+
140
+ // PBKDF2 키 파생
141
+ const dduPbkdf2 = new Ddu64(undefined, undefined, {
142
+ encryptionKey: "user password",
143
+ keyDerivation: {
144
+ algorithm: "pbkdf2",
145
+ salt: "app-specific-salt",
146
+ iterations: 210_000,
147
+ hash: "SHA-256",
148
+ },
149
+ });
121
150
  ```
122
151
 
123
- ### 체크섬
124
-
125
- CRC32 체크섬으로 데이터 무결성을 검증합니다.
152
+ ## Checksum
126
153
 
127
154
  ```typescript
128
- const encoder = new Ddu64();
155
+ const ddu = new Ddu64(undefined, undefined, { checksum: true });
129
156
 
130
- const encoded = encoder.encode(data, { checksum: true });
131
- const decoded = encoder.decode(encoded, { checksum: true });
132
- // 데이터 변조 시 에러 발생
157
+ const encoded = ddu.encode("data"); // CRC32 체크섬 포함
158
+ const decoded = ddu.decode(encoded); // 무결성 검증 후 반환
133
159
  ```
134
160
 
135
- ### URL-Safe
136
-
137
- `+`, `/`, `=` 를 URL 안전 문자(`-`, `_`, `.`)로 변환합니다.
161
+ ## URL-Safe
138
162
 
139
163
  ```typescript
140
- const encoder = new Ddu64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "=", {
164
+ const ddu = new Ddu64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "=", {
141
165
  urlSafe: true,
142
166
  });
143
- ```
144
167
 
145
- > charset/padding에 `-`, `_`, `.` 포함되면 urlSafe를 활성화할 수 없습니다.
168
+ // +→- /→_ =→. 자동 변환
169
+ const encoded = ddu.encode("URL safe text");
170
+ ```
146
171
 
147
- ### 청크 분할
172
+ ## Chunking
148
173
 
149
174
  ```typescript
150
- const encoder = new Ddu64();
151
-
152
- const encoded = encoder.encode(data, {
175
+ const ddu = new Ddu64(undefined, undefined, {
153
176
  chunkSize: 76,
154
177
  chunkSeparator: "\n",
155
178
  });
156
- // 디코딩 시 구분자 자동 제거
157
- ```
158
179
 
159
- ### 비동기 처리
160
-
161
- 대용량 데이터에서 이벤트 루프 블로킹을 방지합니다.
162
-
163
- ```typescript
164
- const encoded = await encoder.encodeAsync(largeBuffer);
165
- const decoded = await encoder.decodeAsync(encoded);
166
- const buffer = await encoder.decodeToBufferAsync(encoded);
180
+ const encoded = ddu.encode("long data ".repeat(100));
181
+ // 76자마다 줄바꿈 삽입
167
182
  ```
168
183
 
169
- ### 진행률 콜백
184
+ ## Obfuscation (한글 난독화)
170
185
 
171
186
  ```typescript
172
- encoder.encode(data, {
173
- onProgress: ({ percent, stage }) => {
174
- console.log(`${percent}% (${stage})`);
175
- },
187
+ const ddu = new Ddu64(undefined, undefined, {
188
+ encryptionKey: "secret",
189
+ obfuscate: true, // 암호화 필수
176
190
  });
191
+
192
+ const encoded = ddu.encode("hello");
193
+ // 출력이 한글 음절 블록(U+AC00–U+D7A3)으로 변환됨
177
194
  ```
178
195
 
179
- ### 통계
196
+ ## Async (브라우저 호환)
180
197
 
181
198
  ```typescript
182
- const stats = encoder.getStats(data, { compress: true });
183
- // { originalSize, encodedSize, compressedSize, compressionRatio, expansionRatio, charsetSize, bitLength }
199
+ // 브라우저에서는 async 메서드 사용
200
+ import { Ddu64 } from "@ddunigma/node/browser";
201
+
202
+ const ddu = new Ddu64();
203
+ const encoded = await ddu.encodeAsync("browser text");
204
+ const decoded = await ddu.decodeAsync(encoded);
184
205
  ```
185
206
 
186
- ### Zip Bomb 방어
207
+ Node.js에서도 async 메서드를 사용할 수 있습니다. 브라우저 진입점(`@ddunigma/node/browser`)은 Node.js 내장 모듈을 임포트하지 않습니다.
208
+
209
+ ## Web Streams
187
210
 
188
211
  ```typescript
189
- const encoder = new Ddu64(undefined, undefined, {
190
- maxDecodedBytes: 10 * 1024 * 1024, // 10MB
191
- maxDecompressedBytes: 50 * 1024 * 1024, // 50MB
212
+ import { Ddu64, createReadableEncodeStream, createReadableDecodeStream } from "@ddunigma/node";
213
+
214
+ const ddu = new Ddu64(undefined, undefined, {
215
+ compress: true,
216
+ encryptionKey: "stream-key",
192
217
  });
193
- ```
194
218
 
195
- ---
219
+ const encodedStream = readableByteStream.pipeThrough(
220
+ createReadableEncodeStream(ddu, { compress: true }),
221
+ );
196
222
 
197
- ## CharsetBuilder
223
+ const decodedStream = encodedStream.pipeThrough(createReadableDecodeStream(ddu));
224
+ ```
198
225
 
199
- 커스텀 charset을 빌더 패턴으로 생성합니다.
226
+ ## WASM Acceleration
200
227
 
201
228
  ```typescript
202
- import { CharsetBuilder } from "@ddunigma/node";
229
+ import { Ddu64, preloadWasm } from "@ddunigma/node";
203
230
 
204
- // 유니코드 범위
205
- CharsetBuilder.fromUnicodeRange(0x4e00, 0x4e3f).build();
231
+ await preloadWasm(); // 선택적 사전 로드
206
232
 
207
- // Base64에서 혼동 문자 제외
208
- CharsetBuilder.base64().excludeConfusing().build();
209
-
210
- // 2의 제곱수로 제한 + 시드 셔플
211
- CharsetBuilder.fromString("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
212
- .limitToPowerOfTwo()
213
- .shuffle(12345)
214
- .build();
233
+ const ddu = new Ddu64(undefined, undefined, {
234
+ wasmThreshold: 4096, // 이 크기 이상일 때 WASM 사용
235
+ });
215
236
 
216
- // 패딩 문자 자동 선택
217
- const { charset, padding } = CharsetBuilder.base64().buildWithPadding();
237
+ const encoded = ddu.encode(new Uint8Array(1024 * 1024));
218
238
  ```
219
239
 
220
- ---
221
-
222
- ## DduPipeline
240
+ WASM을 사용할 수 없으면 JavaScript로 자동 폴백됩니다.
223
241
 
224
- 압축 암호화 → 인코딩을 체이닝하고, `reverse()`로 역순 복원합니다.
242
+ ## Progress Callback
225
243
 
226
244
  ```typescript
227
- import { DduPipeline, Ddu64 } from "@ddunigma/node";
245
+ const ddu = new Ddu64(undefined, undefined, { compress: true });
228
246
 
229
- const pipeline = new DduPipeline().compress(6, "brotli").encrypt("secret-key").encode(new Ddu64());
230
-
231
- const encoded = pipeline.processToString("Hello");
232
- const decoded = pipeline.reverse().processToString(encoded);
247
+ ddu.encode("data", {
248
+ onProgress: ({ percent, stage }) => {
249
+ console.log(`${stage}: ${percent}%`);
250
+ // stage: start → compress → encrypt → encode → done
251
+ },
252
+ });
233
253
  ```
234
254
 
235
- ---
236
-
237
- ## 스트림
238
-
239
- 대용량 파일을 메모리 효율적으로 처리합니다. 스트림 헤더로 압축/암호화를 자동 감지합니다.
255
+ ## Stats
240
256
 
241
257
  ```typescript
242
- import { Ddu64, createEncodeStream, createDecodeStream } from "@ddunigma/node";
243
- import fs from "fs";
258
+ const ddu = new Ddu64(undefined, undefined, { compress: true });
259
+ const stats = ddu.getStats("A".repeat(1000));
244
260
 
245
- const encoder = new Ddu64(undefined, undefined, {
246
- compress: true,
247
- encryptionKey: "stream-key",
248
- });
261
+ // { originalSize, encodedSize, compressedSize, compressionRatio, expansionRatio, charsetSize, bitLength }
262
+ ```
249
263
 
250
- fs.createReadStream("input.bin")
251
- .pipe(createEncodeStream(encoder))
252
- .pipe(fs.createWriteStream("output.ddu"));
264
+ ## Size Limits
253
265
 
254
- fs.createReadStream("output.ddu")
255
- .pipe(createDecodeStream(encoder))
256
- .pipe(fs.createWriteStream("restored.bin"));
266
+ ```typescript
267
+ const ddu = new Ddu64(undefined, undefined, {
268
+ maxDecodedBytes: 10 * 1024 * 1024, // 디코딩 최대 크기 (기본 64MB)
269
+ maxDecompressedBytes: 50 * 1024 * 1024, // 압축해제 최대 크기 (기본 64MB)
270
+ });
257
271
  ```
258
272
 
259
273
  ---
260
274
 
261
- ## API Reference
262
-
263
- ### `new Ddu64(dduChar?, paddingChar?, options?)`
264
-
265
- | Parameter | Type | Description |
266
- | ------------- | ----------------------- | ------------------------ |
267
- | `dduChar` | `string \| string[]` | charset 문자열 또는 배열 |
268
- | `paddingChar` | `string` | 패딩 문자 |
269
- | `options` | `DduConstructorOptions` | 옵션 객체 |
270
-
271
- **생성자 옵션:**
272
-
273
- | Option | Type | Default | Description |
274
- | ---------------------- | ----------------------- | ----------- | ----------------------------- |
275
- | `dduSetSymbol` | `DduSetSymbol` | `DDU` | 프리셋 심볼 |
276
- | `codaChar` | `string[]` | — | 종성 배열 (동적 charset 생성) |
277
- | `encoding` | `BufferEncoding` | `'utf-8'` | 문자열 인코딩 |
278
- | `compress` | `boolean` | `false` | 기본 압축 활성화 |
279
- | `compressionAlgorithm` | `"deflate" \| "brotli"` | `'deflate'` | 압축 알고리즘 |
280
- | `compressionLevel` | `number` | `6` | 압축 레벨 |
281
- | `urlSafe` | `boolean` | `false` | URL-Safe 모드 |
282
- | `encryptionKey` | `string` | — | AES-256-GCM 암호화 키 |
283
- | `checksum` | `boolean` | `false` | CRC32 체크섬 |
284
- | `chunkSize` | `number` | — | 청크 분할 크기 |
285
- | `chunkSeparator` | `string` | `'\n'` | 청크 구분자 |
286
- | `maxDecodedBytes` | `number` | `67108864` | 최대 디코딩 바이트 (64MB) |
287
- | `maxDecompressedBytes` | `number` | `67108864` | 최대 압축해제 바이트 (64MB) |
288
- | `throwOnError` | `boolean` | `false` | 초기화 오류 시 throw |
289
- | `useRepeatPadding` | `boolean` | `false` | 패딩 문자 반복 방식 |
290
- | `usePowerOfTwo` | `boolean` | `true` | 2의 제곱수 charset 강제 |
291
-
292
- **메서드:**
293
-
294
- | Method | Return | Description |
295
- | ---------------------------------------- | ----------------- | -------------------- |
296
- | `encode(data, options?)` | `string` | 인코딩 |
297
- | `decode(encoded, options?)` | `string` | 디코딩 |
298
- | `decodeToBuffer(encoded, options?)` | `Buffer` | Buffer로 디코딩 |
299
- | `encodeAsync(data, options?)` | `Promise<string>` | 비동기 인코딩 |
300
- | `decodeAsync(encoded, options?)` | `Promise<string>` | 비동기 디코딩 |
301
- | `decodeToBufferAsync(encoded, options?)` | `Promise<Buffer>` | 비동기 Buffer 디코딩 |
302
- | `getStats(data, options?)` | `DduEncodeStats` | 인코딩 통계 |
303
- | `getCharSetInfo()` | `CharSetInfo` | charset 정보 |
304
-
305
- **encode/decode 옵션 (DduOptions):**
306
-
307
- | Option | Type | Description |
308
- | ---------------------- | ----------------------- | -------------------- |
309
- | `compress` | `boolean` | 압축 사용 |
310
- | `compressionAlgorithm` | `"deflate" \| "brotli"` | 압축 알고리즘 |
311
- | `compressionLevel` | `number` | 압축 레벨 |
312
- | `checksum` | `boolean` | 체크섬 추가/검증 |
313
- | `chunkSize` | `number` | 청크 분할 크기 |
314
- | `chunkSeparator` | `string` | 청크 구분자 |
315
- | `maxDecodedBytes` | `number` | 최대 디코딩 바이트 |
316
- | `maxDecompressedBytes` | `number` | 최대 압축해제 바이트 |
317
- | `onProgress` | `function` | 진행률 콜백 |
275
+ ## API
318
276
 
319
- ---
277
+ ```typescript
278
+ class Ddu64 {
279
+ encode(data: string | Uint8Array, options?: DduOptions): string;
280
+ decode(encoded: string, options?: DduOptions): string;
281
+ decodeToUint8Array(encoded: string, options?: DduOptions): Uint8Array;
282
+ decodeToBuffer(encoded: string, options?: DduOptions): Buffer;
283
+
284
+ encodeAsync(data: string | Uint8Array, options?: DduOptions): Promise<string>;
285
+ decodeAsync(encoded: string, options?: DduOptions): Promise<string>;
286
+ decodeToUint8ArrayAsync(encoded: string, options?: DduOptions): Promise<Uint8Array>;
287
+ decodeToBufferAsync(encoded: string, options?: DduOptions): Promise<Buffer>;
288
+
289
+ getStats(data: string | Uint8Array, options?: DduOptions): DduEncodeStats;
290
+ getCharSetInfo(): CharSetInfo;
291
+
292
+ static setWorkerPoolSize(n: number): void;
293
+ }
294
+ ```
320
295
 
321
- ## Testing
296
+ ## Constructor Options
322
297
 
323
- ```bash
324
- pnpm test # 전체 테스트
325
- pnpm test:watch # 워치 모드
326
- pnpm test:coverage # 커버리지
298
+ ```typescript
299
+ new Ddu64(dduChar?, paddingChar?, options?);
327
300
  ```
328
301
 
329
- ## Build & Verify
302
+ | Option | Type | Default | 설명 |
303
+ | ---------------------- | ----------------------- | ----------- | --------------------- |
304
+ | `dduSetSymbol` | `DduSetSymbol` | `DDU` | 프리셋 선택 |
305
+ | `dduChar` | `string \| string[]` | - | 커스텀 charset |
306
+ | `paddingChar` | `string` | - | 패딩 문자 |
307
+ | `codaChar` | `string[]` | - | 종성 조합 문자 |
308
+ | `compress` | `boolean` | `false` | 압축 활성화 |
309
+ | `compressionAlgorithm` | `"deflate" \| "brotli"` | `"deflate"` | 압축 알고리즘 |
310
+ | `compressionLevel` | `number` | `6` | 압축 레벨 |
311
+ | `encryptionKey` | `string` | - | AES-256-GCM 암호화 키 |
312
+ | `keyDerivation` | `KeyDerivationOptions` | `sha256` | 키 파생 방식 |
313
+ | `checksum` | `boolean` | `false` | CRC32 체크섬 |
314
+ | `urlSafe` | `boolean` | `false` | URL-Safe 변환 |
315
+ | `obfuscate` | `boolean` | `false` | 한글 난독화 |
316
+ | `chunkSize` | `number` | - | 청크 분할 크기 |
317
+ | `chunkSeparator` | `string` | `"\n"` | 청크 구분자 |
318
+ | `maxDecodedBytes` | `number` | `67108864` | 디코딩 크기 제한 |
319
+ | `maxDecompressedBytes` | `number` | `67108864` | 압축해제 크기 제한 |
320
+ | `wasmThreshold` | `number` | `4096` | WASM 사용 임계값 |
321
+ | `throwOnError` | `boolean` | `false` | 초기화 에러 시 throw |
322
+
323
+ ## Per-Call Options
324
+
325
+ `encode`, `decode`, `encodeAsync`, `decodeAsync` 등에서 호출별로 오버라이드 가능:
326
+
327
+ | Option | Type | 설명 |
328
+ | ---------------------- | ----------------------- | ------------------ |
329
+ | `compress` | `boolean` | 압축 사용 여부 |
330
+ | `compressionAlgorithm` | `"deflate" \| "brotli"` | 압축 알고리즘 |
331
+ | `compressionLevel` | `number` | 압축 레벨 |
332
+ | `encrypt` | `boolean` | 암호화 사용 여부 |
333
+ | `checksum` | `boolean` | 체크섬 사용 여부 |
334
+ | `obfuscate` | `boolean` | 난독화 사용 여부 |
335
+ | `chunkSize` | `number` | 청크 크기 |
336
+ | `maxDecodedBytes` | `number` | 디코딩 크기 제한 |
337
+ | `maxDecompressedBytes` | `number` | 압축해제 크기 제한 |
338
+ | `onProgress` | `(info) => void` | 진행률 콜백 |
339
+
340
+ ## Entry Points
341
+
342
+ | Import Path | 용도 |
343
+ | ------------------------ | ------------------------------------- |
344
+ | `@ddunigma/node` | Node.js 전체 기능 (동기+비동기) |
345
+ | `@ddunigma/node/browser` | 브라우저 최적화 (Node.js 모듈 미포함) |
346
+ | `@ddunigma/node/core` | 최소 코어 (인코딩/디코딩만) |
347
+
348
+ ## Build & Test
330
349
 
331
350
  ```bash
351
+ pnpm test
332
352
  pnpm build
333
353
  pnpm lint
334
354
  pnpm bench
335
- pnpm pack:check
336
355
  ```
337
356
 
338
- ---
339
-
340
- ## Credits
341
-
342
- - Original: [@i3ls](https://github.com/i3l3), [@gunu3371](https://github.com/gunu3371)
343
- - Repository: [ddunigma](https://github.com/i3l3/ddunigma)
344
-
345
357
  ## License
346
358
 
347
359
  BSD-2-Clause
@@ -0,0 +1,7 @@
1
+ 'use strict';var crypto$1=require('crypto'),zlib=require('zlib'),util=require('util');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;var Ne=Object.defineProperty;var Ke=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var O=(n,e)=>()=>(n&&(e=n(n=0)),e);var N=(n,e)=>{for(var t in e)Ne(n,t,{get:e[t],enumerable:true});};var xe={};N(xe,{NodeAdapter:()=>Q});function ke(n){return (n??"SHA-256").toLowerCase().replace("-","")}function ve(n){return n===void 0||!Number.isFinite(n)||n<=0?Ue:Math.max(Bt,Math.floor(n))}function Le(n){return n===void 0?Buffer.from(Pt,"utf-8"):typeof n=="string"?Buffer.from(n,"utf-8"):Buffer.from(n.buffer,n.byteOffset,n.byteLength)}var At,Pe,Ct,De,Et,Ue,Bt,Pt,Q,Te=O(()=>{At=util.promisify(zlib.deflateRaw),Pe=util.promisify(zlib.inflateRaw),Ct=util.promisify(zlib.brotliCompress),De=util.promisify(zlib.brotliDecompress),Et=util.promisify(crypto$1.pbkdf2),Ue=21e4,Bt=1e4,Pt="ddunigma:pbkdf2:v1";Q=class{supportsSyncCrypto=true;supportsSyncCompression=true;supportsBrotli=true;runtime="node";async deriveKey(e,t){if(t?.algorithm==="pbkdf2"){let r=await Et(e,Le(t.salt),ve(t.iterations),32,ke(t.hash));return new Uint8Array(r)}return this.deriveKeySync(e,t)}deriveKeySync(e,t){return t?.algorithm==="pbkdf2"?new Uint8Array(crypto$1.pbkdf2Sync(e,Le(t.salt),ve(t.iterations),32,ke(t.hash))):new Uint8Array(crypto$1.createHash("sha256").update(e).digest())}async encrypt(e,t){return this.encryptSync(e,t)}encryptSync(e,t){let r=crypto$1.randomBytes(12),o=crypto$1.createCipheriv("aes-256-gcm",t,r),s=Buffer.concat([o.update(e),o.final()]),i=o.getAuthTag(),a=new Uint8Array(28+s.length);return a.set(r,0),a.set(i,12),a.set(s,28),a}async decrypt(e,t){return this.decryptSync(e,t)}decryptSync(e,t){if(e.length<28)throw new Error("[Ddu64 decrypt] Invalid encrypted data: too short");let r=e.subarray(0,12),o=e.subarray(12,28),s=e.subarray(28),i=crypto$1.createDecipheriv("aes-256-gcm",t,r);i.setAuthTag(o);let a=Buffer.concat([i.update(s),i.final()]);return new Uint8Array(a)}randomBytes(e){return new Uint8Array(crypto$1.randomBytes(e))}async deflate(e,t){let r={};t!==void 0&&(r.level=t);let o=await At(Buffer.from(e),r);return new Uint8Array(o)}deflateSync(e,t){let r={};return t!==void 0&&(r.level=t),new Uint8Array(zlib.deflateRawSync(Buffer.from(e),r))}async inflate(e,t){if(t===void 0||t===Number.POSITIVE_INFINITY){let o=await Pe(Buffer.from(e));return new Uint8Array(o)}let r={maxOutputLength:t};try{let o=await Pe(Buffer.from(e),r);return new Uint8Array(o)}catch(o){let s=o,i=String(s?.message??"").toLowerCase();throw String(s?.code??"")==="ERR_BUFFER_TOO_LARGE"||i.includes("output length")||i.includes("buffer too large")?new Error(`[Ddu64 inflate] Decompressed data exceeds limit. Limit: ${t} bytes`,{cause:o}):o}}inflateSync(e,t){if(t===void 0||t===Number.POSITIVE_INFINITY)return new Uint8Array(zlib.inflateRawSync(Buffer.from(e)));try{return new Uint8Array(zlib.inflateRawSync(Buffer.from(e),{maxOutputLength:t}))}catch(r){let o=r,s=String(o?.message??"").toLowerCase();throw String(o?.code??"")==="ERR_BUFFER_TOO_LARGE"||s.includes("output length")||s.includes("buffer too large")?new Error(`[Ddu64 inflate] Decompressed data exceeds limit. Limit: ${t} bytes`,{cause:r}):r}}async brotliCompress(e,t){let r={};t!==void 0&&(r.params={[zlib.constants.BROTLI_PARAM_QUALITY]:Math.max(0,Math.min(11,t))});let o=await Ct(Buffer.from(e),r);return new Uint8Array(o)}brotliCompressSync(e,t){let r={};return t!==void 0&&(r.params={[zlib.constants.BROTLI_PARAM_QUALITY]:Math.max(0,Math.min(11,t))}),new Uint8Array(zlib.brotliCompressSync(Buffer.from(e),r))}async brotliDecompress(e,t){if(t===void 0||t===Number.POSITIVE_INFINITY){let r=await De(Buffer.from(e));return new Uint8Array(r)}try{let r=await De(Buffer.from(e),{maxOutputLength:t});return new Uint8Array(r)}catch(r){let o=r,s=String(o?.message??"").toLowerCase();throw String(o?.code??"")==="ERR_BUFFER_TOO_LARGE"||s.includes("output length")||s.includes("buffer too large")||s.includes("cannot create a buffer larger")?new Error(`[Ddu64 brotli] Decompressed data exceeds limit. Limit: ${t} bytes`,{cause:r}):r}}brotliDecompressSync(e,t){if(t===void 0||t===Number.POSITIVE_INFINITY)return new Uint8Array(zlib.brotliDecompressSync(Buffer.from(e)));try{return new Uint8Array(zlib.brotliDecompressSync(Buffer.from(e),{maxOutputLength:t}))}catch(r){let o=r,s=String(o?.message??"").toLowerCase();throw String(o?.code??"")==="ERR_BUFFER_TOO_LARGE"||s.includes("output length")||s.includes("buffer too large")||s.includes("cannot create a buffer larger")?new Error(`[Ddu64 brotli] Decompressed data exceeds limit. Limit: ${t} bytes`,{cause:r}):r}}};});var Re={};N(Re,{BrowserAdapter:()=>exports.BrowserAdapter});function Ut(n){return n===void 0||!Number.isFinite(n)||n<=0?21e4:Math.max(1e4,Math.floor(n))}function kt(n){return n===void 0?new TextEncoder().encode(Dt):typeof n=="string"?new TextEncoder().encode(n):n}var Dt;exports.BrowserAdapter=void 0;var J=O(()=>{Dt="ddunigma:pbkdf2:v1";exports.BrowserAdapter=class{supportsSyncCrypto=false;supportsSyncCompression=false;supportsBrotli=false;runtime="browser";async deriveKey(e,t){let o=new TextEncoder().encode(e);if(t?.algorithm==="pbkdf2"){let i=await crypto.subtle.importKey("raw",o,"PBKDF2",false,["deriveBits"]),a=await crypto.subtle.deriveBits({name:"PBKDF2",salt:kt(t.salt),iterations:Ut(t.iterations),hash:t.hash??"SHA-256"},i,256);return new Uint8Array(a)}let s=await crypto.subtle.digest("SHA-256",o);return new Uint8Array(s)}async encrypt(e,t){let r=crypto.getRandomValues(new Uint8Array(12)),o=await crypto.subtle.importKey("raw",t,{name:"AES-GCM"},false,["encrypt"]),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:r,tagLength:128},o,e),i=new Uint8Array(s),a=i.slice(0,i.length-16),c=i.slice(i.length-16),d=new Uint8Array(28+a.length);return d.set(r,0),d.set(c,12),d.set(a,28),d}async decrypt(e,t){if(e.length<28)throw new Error("[Ddu64 decrypt] Encrypted data is invalid. Payload must be at least 28 bytes (12 IV + 16 authTag + ciphertext).");let r=e.slice(0,12),o=e.slice(12,28),s=e.slice(28),i=new Uint8Array(s.length+16);i.set(s,0),i.set(o,s.length);let a=await crypto.subtle.importKey("raw",t,{name:"AES-GCM"},false,["decrypt"]);try{let c=await crypto.subtle.decrypt({name:"AES-GCM",iv:r,tagLength:128},a,i);return new Uint8Array(c)}catch{throw new Error("[Ddu64 decrypt] Decryption failed: data tampering or incorrect key.")}}randomBytes(e){return crypto.getRandomValues(new Uint8Array(e))}async deflate(e,t){if(typeof CompressionStream>"u")throw new Error("[Ddu64 compress] Deflate compression is unsupported in the current runtime. CompressionStream API is not available.");let r=this.getDeflateFormat(),o=new CompressionStream(r),s=o.writable.getWriter(),i=o.readable.getReader();s.write(e),s.close();let a=[],c=0;for(;;){let{done:h,value:f}=await i.read();if(h)break;a.push(f),c+=f.length;}let d=new Uint8Array(c),l=0;for(let h of a)d.set(h,l),l+=h.length;return d}async inflate(e,t){if(typeof DecompressionStream>"u")throw new Error("[Ddu64 decompress] Deflate decompression is unsupported in the current runtime. DecompressionStream API is not available.");let r=this.getDeflateFormat(),o=new DecompressionStream(r),s=o.writable.getWriter(),i=o.readable.getReader();s.write(e),s.close();let a=[],c=0;for(;;){let{done:h,value:f}=await i.read();if(h)break;if(c+=f.length,t!==void 0&&c>t)throw new Error(`[Ddu64 decompress] Decompressed size exceeds limit. Estimated ${c}+ bytes exceeds maximum of ${t} bytes.`);a.push(f);}let d=new Uint8Array(c),l=0;for(let h of a)d.set(h,l),l+=h.length;return d}getDeflateFormat(){return "deflate-raw"}};});var Ie={};N(Ie,{detectRuntime:()=>ee,getAdapter:()=>_e});function ee(){if(typeof globalThis.process<"u"&&globalThis.process?.versions?.node)return "node";if(globalThis.Deno?.version?.deno)return "deno";if(globalThis.Bun?.version)return "bun";if(typeof globalThis.crypto<"u"&&globalThis.crypto?.subtle)return "browser";throw new Error("[ddunigma] No suitable crypto provider found. Detected runtime lacks both Node.js crypto module and Web Crypto API (SubtleCrypto).")}async function _e(){switch(ee()){case "node":{let{NodeAdapter:e}=await Promise.resolve().then(()=>(Te(),xe));return new e}case "deno":case "bun":case "browser":case "edge":{let{BrowserAdapter:e}=await Promise.resolve().then(()=>(J(),Re));return new e}default:throw new Error("[ddunigma] No suitable crypto provider found. Detected runtime lacks both Node.js crypto module and Web Crypto API (SubtleCrypto).")}}var te=O(()=>{});function oe(n,e){let{bitLength:t,usePowerOfTwo:r,charsetSize:o}=e,s=n.length;if(s===0)return {indices:[],paddingBits:0};let i=s*8,a=Math.ceil(i/t),c=r?a:a*2,d=new Array(c),l=0,h=0,f=0;if(r){let m=(1<<t)-1;for(let g=0;g<s;g++)for(h=h<<8|n[g],f+=8;f>=t;)f-=t,d[l++]=h>>f&m,h&=(1<<f)-1;}else for(let m=0;m<s;m++)for(h=h<<8|n[m],f+=8;f>=t;){f-=t;let g=h>>f,p=g/o|0;d[l++]=p,d[l++]=g-p*o,h&=(1<<f)-1;}let u=0;if(f>0){u=t-f;let m=h<<u;if(r)d[l++]=m;else {let g=m/o|0;d[l++]=g,d[l++]=m-g*o;}}return d.length=l,{indices:d,paddingBits:u}}function se(n,e,t){let{bitLength:r,usePowerOfTwo:o,charsetSize:s}=t,i=n.length;if(i===0)return new Uint8Array(0);let a=o?1:2,c=Math.ceil(i/a),d=r<31?1<<r:Math.pow(2,r),l=Math.ceil((c*r-e)/8),h=new Uint8Array(l+1),f=0,u=0,m=0;if(o)for(let g=0;g<i;g+=a){let p=n[g];if(p<0||p>=s)throw new Error(`[BitPack decode] Invalid index ${p} at position ${g}`);for(u=u<<r|p,m+=r,g+a>=i&&e>0&&(u>>=e,m-=e);m>=8;)m-=8,h[f++]=u>>m&255,u&=(1<<m)-1;}else for(let g=0;g<i;g+=a){let p=n[g],y=n[g+1];if(p<0||p>=s)throw new Error(`[BitPack decode] Invalid index ${p} at position ${g}`);if(y===void 0||y<0||y>=s)throw new Error(`[BitPack decode] Invalid index ${y} at position ${g+1}`);let b=p*s+y;if(b>=d)throw new Error(`[BitPack decode] Value ${b} exceeds range at position ${g}`);for(u=u<<r|b,m+=r,g+a>=i&&e>0&&(u>>=e,m-=e);m>=8;)m-=8,h[f++]=u>>m&255,u&=(1<<m)-1;}return h.subarray(0,f)}function We(n,e){return n<=1?0:e?Math.floor(Math.log2(n)):Math.ceil(Math.log2(n))}function He(n){return n>0&&(n&n-1)===0}function ie(n){let e=He(n);return {bitLength:We(n,e),usePowerOfTwo:e,charsetSize:n}}var A="DDS1",B="ELYSIA",P="GRISEO";function K(n,e,t){let r=n.length,o=e.length,s={cleanedInput:n,paddingBits:0,isEncrypted:false,pipelineVersion:2};if(r<o)return s;let a=Math.max(0,t-1).toString().length;for(let c=Math.min(a,r);c>=1;c--){let d=r-c,l=true;for(let b=d;b<r;b++){let k=n.charCodeAt(b);if(k<48||k>57){l=false;break}}if(!l)continue;let h=n.substring(d),f=parseInt(h,10);if(Number.isNaN(f)||f<0||f>=t||h!==f.toString())continue;let u=d,m=false,g,p=2;u>=2&&n.substring(u-2,u)==="V3"&&(p=3,u-=2),u>=3&&n.substring(u-3,u)==="ENC"&&(m=true,u-=3),u>=B.length&&n.substring(u-B.length,u)===B?(g="deflate",u-=B.length):u>=P.length&&n.substring(u-P.length,u)===P&&(g="brotli",u-=P.length);let y=u-o;if(y>=0&&n.substring(y,u)===e)return {cleanedInput:n.substring(0,y),paddingBits:f,compressionAlgorithm:g,isEncrypted:m,pipelineVersion:p}}if(n.endsWith(e)){let c=0,d=r;for(;d>=o&&n.substring(d-o,d)===e;)c++,d-=o;if(c>0){let l=c*2;if(l<t)return {cleanedInput:n.substring(0,d),paddingBits:l,isEncrypted:false,pipelineVersion:2}}}return s}function W(n){let e=n.lastIndexOf("CHK");if(e===-1)return {data:n,checksum:null};let t=n.slice(e+3);return t.length!==8||!/^[0-9a-f]+$/i.test(t)?{data:n,checksum:null}:{data:n.slice(0,e),checksum:t.toLowerCase()}}function H(n){return n.length*2+A.length+2}function v(n,e){let t=e.compressionAlgorithm==="brotli"?"B":e.compressionAlgorithm==="deflate"?"D":"N",r=e.encrypted?"1":"0";return `${n}${A}${t}${r}${n}`}function ae(n,e){let t=H(e);if(n.length<t||!n.startsWith(e))return null;let r=e.length;if(n.slice(r,r+A.length)!==A)throw new Error("[wireFormat] Invalid stream header magic");let s=n[r+A.length],i=n[r+A.length+1];if(n.slice(t-e.length,t)!==e)throw new Error("[wireFormat] Invalid stream header terminator");let c=s==="B"?"brotli":s==="D"?"deflate":s==="N"?void 0:null;if(c===null)throw new Error("[wireFormat] Invalid stream header compression flag");if(i!=="0"&&i!=="1")throw new Error("[wireFormat] Invalid stream header encryption flag");return {compressionAlgorithm:c,encrypted:i==="1"}}function ce(n){let{paddingBits:e,compressionAlgorithm:t,isEncrypted:r,paddingChar:o,useRepeatPadding:s,pipelineVersion:i=2}=n;if(e===0&&!t&&!r&&i===2)return "";if(s&&!t&&!r&&i===2&&e>0&&e%2===0){let c=e>>1;return o.repeat(c)}return o+(t==="deflate"?B:t==="brotli"?P:"")+(r?"ENC":"")+(i===3?"V3":"")+e.toString()}var ze=(()=>{let n=new Uint32Array(256);for(let e=0;e<256;e++){let t=e;for(let r=0;r<8;r++)t=t>>>1^(t&1?3988292384:0);n[e]=t;}return n})();function D(n){let e=4294967295;for(let t=0;t<n.length;t++)e=e>>>8^ze[(e^n[t])&255];return ((e^4294967295)>>>0).toString(16).padStart(8,"0")}function de(n){return n.length===0?n:n.replaceAll("+","-").replaceAll("/","_").replaceAll("=",".")}function z(n){return n.length===0?n:n.replaceAll("-","+").replaceAll("_","/").replaceAll(".","=")}function le(n,e,t){if(e<=0||n.length<=e)return n;let r=Math.ceil(n.length/e),o=new Array(r*2-1),s=0;for(let i=0;i<n.length;i+=e)o[s++]=n.slice(i,i+e),i+e<n.length&&(o[s++]=t);return o.join("")}function F(n,e){if(n.length===0)return n;let t=n.replace(/[\r\n]/g,""),r=e&&e!==`
2
+ `&&e!==`\r
3
+ `&&e!=="\r"?e:"";return r.length>0&&t.includes(r)&&(t=t.replaceAll(r,"")),t}var Fe={"":0,\u3131:1,\u3132:2,\u3133:3,\u3134:4,\u3135:5,\u3136:6,\u3137:7,\u3139:8,\u313A:9,\u313B:10,\u313C:11,\u313D:12,\u313E:13,\u313F:14,\u3140:15,\u3141:16,\u3142:17,\u3144:18,\u3145:19,\u3146:20,\u3147:21,\u3148:22,\u314A:23,\u314B:24,\u314C:25,\u314D:26,\u314E:27};function $e(n,e){let t=n.charCodeAt(0);if(t<44032||t>55203)return n;let r=t-(t-44032)%28,o=Fe[e]??0;return String.fromCharCode(r+o)}function L(n,e){let t=new Array(n.length*e.length),r=0;for(let o of n)for(let s of e)t[r++]=$e(o,s);return t}function x(n,e){let r=n===void 0||!Number.isFinite(n)?6:Math.floor(n);return Math.min(e==="brotli"?11:9,Math.max(0,r))}var qe=new TextEncoder,Ye=new TextDecoder;function T(n){return qe.encode(n)}function $(n){return Ye.decode(n)}var q=(r=>(r.DDU="ddu",r.DDU_V1="ddu_v1",r.ONECHARSET="oneCharSet",r))(q||{}),Y={dduSetSymbol:"ddu",usePowerOfTwo:true,requiredLength:64,bitLength:6};var Ve={symbol:"ddu",charSet:["\uB70C","\uB568","\uC774","\uC6B0","\uC57C","\uB4C0","\uB31C","\uB3A8"],codaChar:["","\u3131","\u3132","\u3137","\u3148","\u3147","\u3145","\u3146"],maxRequiredLength:64,bitLength:6,paddingChar:"\uBB50",useRepeatPadding:true},je={symbol:"ddu_v1",charSet:["\uB70C","\uB568","\uC774","\uC6B0","\uC57C","!","?","."],maxRequiredLength:8,bitLength:3,paddingChar:"\uBB50",useRepeatPadding:true},Ge={symbol:"oneCharSet",charSet:["A","s","q","r","0","z","3","t","y","1","5","2","4","E","B","C","Q","F","R","T","U","W","V","X","Y","Z","b","a","c","d","D","G","L","H","I","-","J","K","M","O","N","f","e","h","g","P","i","S","k","l","m","u","j","v","n","o","p","9","w","6","7","8","x","_"],paddingChar:"=",maxRequiredLength:64,bitLength:6};function R(n){switch(n){case "ddu":return Ve;case "ddu_v1":return je;case "oneCharSet":return Ge;default:return}}var Ze=65536,Xe=["-","_","."];function ue(n,e,t,r){let o=(s,i,a,c,d)=>{if(Qe(a,t?.usePowerOfTwo)&&a>0){let f=Math.floor(Math.log2(a)),u=1<<f;return {charSet:s.length===u?s:s.slice(0,u),padding:i,requiredLength:u,bitLength:f,isPredefined:c,useRepeatPadding:d}}return {charSet:s.length===a?s:s.slice(0,a),padding:i,requiredLength:a,bitLength:a>0?Math.ceil(Math.log2(a)):0,isPredefined:c,useRepeatPadding:d}};try{let s=n??t?.dduChar,i=e??t?.paddingChar;if(s){if(!i)throw new Error("[Ddu64 Constructor] paddingChar is required when dduChar is provided.");let l=typeof s=="string"?[...s]:[...s],h=t?.codaChar,f=h?!0:t?.useRepeatPadding??!1;if(h&&h.length>0&&(l=L(l,h)),r&&new Set(l).size!==l.length){let g=l.filter((p,y)=>l.indexOf(p)!==y);throw new Error(`[Ddu64 Constructor] Character set contains duplicate characters: [${[...new Set(g)].join(", ")}]`)}let u=t?.requiredLength??l.length;if(l.length<u)throw new Error("[Ddu64 Constructor] Insufficient characters.");return o(l,i,u,!1,f)}let a=t?.dduSetSymbol??Y.dduSetSymbol??"ddu",c=Je(a),d=c.codaChar?L(c.charSet,c.codaChar):c.charSet;return o(d,c.paddingChar,c.maxRequiredLength,!0,c.useRepeatPadding)}catch(s){if(r)throw s;return V(t)}}function he(n,e,t){let r=[n,null];for(let s of r){let i=s?{...s}:V(t);try{let a=i.charSet,c=i.requiredLength,d=Array.from(new Set(a));if(d.length!==a.length){if(e){let f=a.filter((u,m)=>a.indexOf(u)!==m);throw new Error(`[Ddu64 normalizeCharSet] Character set contains duplicate characters: [${[...new Set(f)].join(", ")}]`)}a=d,i.isPredefined||(c=a.length);}if(a.length<c)throw new Error(`[Ddu64 normalizeCharSet] Insufficient characters. Required: ${c}, Has: ${a.length}`);if(c<2)throw new Error("[Ddu64 normalizeCharSet] At least 2 unique characters required.");if(a.length===0)throw new Error("[Ddu64 normalizeCharSet] Empty charset.");if(a.find(f=>f.length!==1)){if(e)throw new Error("[Ddu64 normalizeCharSet] Multi-character symbols are not supported.");continue}if(a.length>Ze){if(e)throw new Error("[Ddu64 normalizeCharSet] Charset size exceeds maximum supported size of 65536.");continue}if(i.padding.length!==1)throw new Error(`[Ddu64 normalizeCharSet] Padding length mismatch. Expected 1, got ${i.padding.length}`);if(a.includes(i.padding)){if(e)throw new Error(`[Ddu64 normalizeCharSet] Padding character "${i.padding}" conflicts with charset.`);a=a.filter(f=>f!==i.padding);}for(let f of a)if(f.includes(`
4
+ `)||f.includes("\r"))throw new Error("[Ddu64 normalizeCharSet] Newline and carriage return characters are reserved.");if(i.padding.includes(`
5
+ `)||i.padding.includes("\r"))throw new Error("[Ddu64 normalizeCharSet] Newline and carriage return characters are reserved.");return {charSet:a.length===c?a:a.slice(0,c),padding:i.padding,isPredefined:i.isPredefined}}catch(a){if(e)throw a}}let o=V(t);return {charSet:o.charSet.slice(0,o.requiredLength),padding:o.padding,isPredefined:true}}function fe(n,e,t){for(let r of Xe){for(let o of n)if(o.includes(r)){let s=`[Ddu64 Constructor] URL-Safe mode conflict: charset character "${o}" contains "${r}".`;if(t)throw new Error(s);return false}if(e.includes(r)){let o=`[Ddu64 Constructor] URL-Safe mode conflict: padding character "${e}" contains "${r}".`;if(t)throw new Error(o);return false}}return true}function me(n,e,t){if(t>256)return;let r=Math.min(n.length,t),o=n.slice(0,r),s=new Set;for(let a=0;a<o.length;a++)s.add(o[a]);s.add(e);for(let a=0;a<o.length;a++){let c=o[a];for(let h=0;h<o.length;h++){let f=c+o[h];if(s.has(f))throw new Error(`Combination conflict: "${c}" + "${o[h]}"`);s.add(f);}let d=c+e;if(s.has(d))throw new Error(`Combination conflict: "${c}" + padding`);s.add(d);let l=e+c;if(s.has(l))throw new Error(`Combination conflict: padding + "${c}"`);s.add(l);}let i=e+e;if(s.has(i))throw new Error("Combination conflict: double padding");s.add(i);}function Qe(n,e){return e!==void 0?e?n>0:false:n>0&&(n&n-1)===0}function Je(n){let e=R(n);if(!e)throw new Error(`CharSet with symbol ${n} not found`);return e}function V(n){let e=n?.dduSetSymbol??Y.dduSetSymbol??"oneCharSet",t=R(e)??R("oneCharSet");if(!t)throw new Error("Critical: No fallback CharSet available");return {charSet:t.codaChar?L(t.charSet,t.codaChar):t.charSet,padding:t.paddingChar,requiredLength:t.maxRequiredLength,bitLength:t.bitLength,isPredefined:true,useRepeatPadding:t.useRepeatPadding}}function et(){let n=1;return typeof globalThis.navigator<"u"&&globalThis.navigator.hardwareConcurrency?n=globalThis.navigator.hardwareConcurrency:typeof globalThis.process<"u"&&globalThis.process.versions?.node&&(typeof globalThis.process.availableParallelism=="function"?n=globalThis.process.availableParallelism():n=4),Math.max(1,Math.min(64,n-1))}function tt(){try{let{Worker:n}=Ke("worker_threads"),e=new URL("./nodeWorker.js",(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href))).pathname,t=new n(e);return {postMessage(r){t.postMessage(r);},async terminate(){await t.terminate();},onMessage(r){t.on("message",r);},onError(r){t.on("error",r);}}}catch{return null}}function rt(){try{if(typeof globalThis.Worker>"u")return null;let n=new URL("./webWorker.js",(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href))),e=new globalThis.Worker(n,{type:"module"});return {postMessage(t){e.postMessage(t);},async terminate(){e.terminate();},onMessage(t){e.addEventListener("message",r=>{t(r.data);});},onError(t){e.addEventListener("error",r=>{t(new Error(r.message||"Worker error"));});}}}catch{return null}}var G=class{poolSize;workers=[];pendingTasks=new Map;nextTaskId=0;roundRobinIndex=0;initialized=false;terminated=false;constructor(e){this.poolSize=e??et();}async encode(e,t){return await this.dispatch("encode",e,t)}async decode(e,t){return await this.dispatch("decode",e,t)}setPoolSize(e){if(!Number.isInteger(e))throw new Error(`[WorkerPool] Pool size must be an integer. Got: ${e}. Valid range: [1, 64]`);if(e<1||e>64)throw new Error(`[WorkerPool] Pool size must be between 1 and 64. Got: ${e}`);let t=this.poolSize;this.poolSize=e,this.initialized&&t!==e&&(this.terminateWorkers(),this.initialized=false);}async terminate(){this.terminated=true,await this.terminateWorkers();for(let[,e]of this.pendingTasks)e.reject(new Error("[WorkerPool] Pool terminated"));this.pendingTasks.clear();}async dispatch(e,t,r){if(this.terminated)throw new Error("[WorkerPool] Pool has been terminated");if(this.ensureInitialized(),this.workers.length===0)throw new Error("[WorkerPool] No workers available. Workers may not be supported in this runtime.");let o=this.nextTaskId++,s=this.roundRobinIndex%this.workers.length;this.roundRobinIndex=(this.roundRobinIndex+1)%this.workers.length;let i=this.workers[s];return new Promise((a,c)=>{this.pendingTasks.set(o,{resolve:a,reject:c});let d={id:o,type:e,data:t,config:r};i.postMessage(d);})}ensureInitialized(){if(this.initialized)return;let e=typeof globalThis.process<"u"&&!!globalThis.process.versions?.node;for(let t=0;t<this.poolSize;t++){let r=e?tt():rt();if(!r)break;r.onMessage(o=>{let s=this.pendingTasks.get(o.id);s&&(this.pendingTasks.delete(o.id),o.type==="error"?s.reject(new Error(o.error??"Worker error")):s.resolve(o.result));}),r.onError(o=>{console.error("[WorkerPool] Worker error:",o.message);}),this.workers.push(r);}this.initialized=true;}async terminateWorkers(){let e=this.workers.map(t=>t.terminate());await Promise.all(e),this.workers=[];}},j=null;function nt(){return j||(j=new G),j}function pe(n){nt().setPoolSize(n);}function ye(n){if(n.length===0)throw new Error("[Ddu64 obfuscation] Alphabet must not be empty.");if(n.length>11172)throw new Error(`[Ddu64 obfuscation] Alphabet size (${n.length}) exceeds available Hangul syllables (11172).`);let e=Math.floor(11172/n.length),t=new Map;for(let r=0;r<n.length;r++)t.set(n[r],r);return {alphabet:n,syllablesPerChar:e,charToIndex:t}}function ge(n,e,t){let r=44032+n*t.syllablesPerChar,o=e%t.syllablesPerChar;return r+o}function be(n,e){if(n<44032||n>55203)return -1;let t=n-44032,r=Math.floor(t/e.syllablesPerChar);return r>=e.alphabet.length?-1:r}var C=class{config;constructor(e){this.config=ye(e);}obfuscate(e){if(e.length===0)return "";let t=new Array(e.length);for(let r=0;r<e.length;r++){let o=e[r],s=this.config.charToIndex.get(o);if(s===void 0)throw new Error(`[Ddu64 obfuscation] Character "${o}" (U+${o.charCodeAt(0).toString(16).padStart(4,"0").toUpperCase()}) not found in obfuscation alphabet.`);let i=ge(s,r,this.config);t[r]=String.fromCharCode(i);}return t.join("")}deobfuscate(e){if(e.length===0)return "";let t=new Array(e.length);for(let r=0;r<e.length;r++){let o=e.charCodeAt(r),s=be(o,this.config);if(s===-1)throw new Error(`[Ddu64 obfuscation] Invalid syllable at position ${r}: U+${o.toString(16).padStart(4,"0").toUpperCase()} is not in the mapped range.`);t[r]=this.config.alphabet[s];}return t.join("")}};function ot(n,e){let t=new Set(n);t.add(e);let r=[...t];return new C(r)}var E=null,Z=false,S=false,w=null,X=class{exports;_ready=true;constructor(e){this.exports=e;}get ready(){return this._ready}encode(e,t){let{exports:r}=this;if(e.length===0)return {indices:new Uint16Array(0),paddingBits:0};let o=r.alloc(e.length);new Uint8Array(r.memory.buffer).set(e,o);let i=1<<t,a=1;try{let c=r.encode(o,e.length,t,i,a),d=r.get_result_ptr(),l=new Uint16Array(r.memory.buffer,d,c),h=new Uint16Array(c);return h.set(l),{indices:h,paddingBits:r.get_padding_bits()}}finally{r.dealloc(o,e.length);}}decode(e,t,r){let{exports:o}=this;if(e.length===0)return new Uint8Array(0);let s=e.length*2,i=o.alloc(s);new Uint16Array(o.memory.buffer,i,e.length).set(e);let c=1<<t,d=1;try{let l=o.decode(i,e.length,t,c,d,r);if(l===4294967295)throw new Error("[WasmCodec decode] Invalid index in input");let h=o.get_result_ptr(),f=new Uint8Array(o.memory.buffer,h,l),u=new Uint8Array(l);return u.set(f),u}finally{o.dealloc(i,s);}}};async function st(){try{if(typeof globalThis.process<"u"&&globalThis.process.versions?.node){let{readFile:n}=await import('fs/promises'),{fileURLToPath:e}=await import('url'),{dirname:t,join:r}=await import('path'),o=t(e((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href)))),s=r(o,"wasm","codec.wasm");try{let i=await n(s);return i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength)}catch{let i=r(o,"codec.wasm");try{let a=await n(i);return a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength)}catch{let a=r(o,"..","wasm","codec.wasm");try{let c=await n(a);return c.buffer.slice(c.byteOffset,c.byteOffset+c.byteLength)}catch{return null}}}}if(typeof fetch=="function"){let n=await fetch(new URL("./wasm/codec.wasm",(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href))));return n.ok?await n.arrayBuffer():null}return null}catch{return null}}async function it(n){try{if(n.byteLength<16)return null;let e=new Uint8Array(n,0,4);if(e[0]!==0||e[1]!==97||e[2]!==115||e[3]!==109)return null;let t;try{t=await WebAssembly.compile(n);}catch{return null}let o=(await WebAssembly.instantiate(t,{})).exports;return typeof o.alloc!="function"||typeof o.dealloc!="function"||typeof o.encode!="function"||typeof o.decode!="function"||typeof o.get_result_ptr!="function"||typeof o.get_result_len!="function"||typeof o.get_padding_bits!="function"||!o.memory?null:o}catch{return null}}async function we(){try{if(E)return !0;if(S)return !1;let n=await st();if(!n)return S=!0,!1;let e=await it(n);return e?(E=new X(e),!0):(S=!0,!1)}catch{return S=true,false}}function at(n,e){let t;return {promise:new Promise((s,i)=>{t=setTimeout(()=>i(new Error(e)),n);}),clear:()=>clearTimeout(t)}}async function ct(){if(E)return;if(w)return w;let n=at(1e4,"[Ddu64 wasm] WASM initialization timed out (10s)"),e=async()=>{try{if(!await we())throw new Error("[Ddu64 wasm] WASM initialization failed")}finally{n.clear();}};return w=Promise.race([e(),n.promise]).finally(()=>{w=null,Z=true;}),w}function dt(){if(E)return E;if(S)return null;if(!Z&&!w){Z=true;let n;w=new Promise(e=>{n=setTimeout(()=>{S=true,e();},5e3),we().then(t=>{t||(S=true);}).catch(()=>{S=true;}).finally(()=>{n!==void 0&&clearTimeout(n),e();});}).finally(()=>{w=null;});}return null}function _(){return E}function Se(n){if(!Number.isFinite(n))throw new Error(`[Ddu64 config] wasmThreshold must be a finite number, got ${n}`);return Math.max(1024,Math.min(1048576,Math.round(n)))}var Lt=8,xt=64*1024*1024,Tt=64*1024*1024,re="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Me="=",Rt=Object.fromEntries([...re].map((n,e)=>[n,e])),M=class{dduChar;paddingChar;bitLength;usePowerOfTwo;effectiveBitLength;dduBinaryLookup=new Map;isPredefinedCharSet;defaultCompress;defaultMaxDecodedBytes;defaultMaxDecompressedBytes;urlSafe;encryptionKey;keyDerivation;encryptionKeyHash;defaultChecksum;defaultChunkSize;defaultChunkSeparator;defaultCompressionLevel;defaultCompressionAlgorithm;useRepeatPadding;bitPackConfig;wasmThreshold;canUseNativeBase64;nativeDecodeMap;adapter;defaultObfuscate;_obfuscationLayer;constructor(e,t,r){let o=r?.throwOnError??r?.useBuildErrorReturn??false;r?.adapter?this.adapter=r.adapter:this.adapter=void 0;let s=ue(e,t,r,o),i=he(s,o,r);this.dduChar=i.charSet,this.paddingChar=i.padding,this.isPredefinedCharSet=i.isPredefined,this.defaultCompress=r?.compress??false,this.defaultMaxDecodedBytes=this.normalizeLimit(r?.maxDecodedBytes,xt,o,"maxDecodedBytes"),this.defaultMaxDecompressedBytes=this.normalizeLimit(r?.maxDecompressedBytes,Tt,o,"maxDecompressedBytes");let a=this.dduChar.length;this.usePowerOfTwo=a>0&&(a&a-1)===0;let c=Math.ceil(Math.log2(a));this.bitLength=this.usePowerOfTwo?Math.floor(Math.log2(a)):c,this.effectiveBitLength=this.usePowerOfTwo?this.bitLength:c;for(let l=0;l<a;l++)this.dduBinaryLookup.set(this.dduChar[l],l);this.isPredefinedCharSet||me(this.dduChar,this.paddingChar,a);let d=r?.urlSafe??false;if(this.urlSafe=d?fe(this.dduChar,this.paddingChar,o):false,this.encryptionKey=r?.encryptionKey,this.keyDerivation=r?.keyDerivation,this.encryptionKey&&this.adapter?.deriveKeySync&&(this.encryptionKeyHash=this.adapter.deriveKeySync(this.encryptionKey,this.keyDerivation)),this.defaultChecksum=r?.checksum??false,this.defaultChunkSize=r?.chunkSize,this.defaultChunkSeparator=r?.chunkSeparator??`
6
+ `,this.defaultCompressionAlgorithm=r?.compressionAlgorithm??"deflate",this.defaultCompressionLevel=x(r?.compressionLevel,this.defaultCompressionAlgorithm),this.useRepeatPadding=r?.useRepeatPadding??s.useRepeatPadding??false,this.defaultObfuscate=r?.obfuscate??false,this.defaultObfuscate&&!this.encryptionKey)throw new Error("[Ddu64 obfuscation] Obfuscation requires encryption to be enabled.");if(this.bitPackConfig=ie(a),this.wasmThreshold=Se(r?.wasmThreshold??4096),this.canUseNativeBase64=this.usePowerOfTwo&&this.dduChar.length===64,this.canUseNativeBase64){this.nativeDecodeMap=new Map;for(let l=0;l<re.length;l++){let h=this.dduChar[l];this.nativeDecodeMap.set(h,re[l]);}}}encode(e,t){return this.encodeInternal(e,t).encoded}decode(e,t){let r=this.decodeToUint8Array(e,t);return $(r)}decodeToUint8Array(e,t){let r=t?.checksum??this.defaultChecksum,o=t?.compress!==false,s=t?.encrypt!==false,i=e;this.reportProgress(t,{processedBytes:0,totalBytes:e.length,percent:0,stage:"start"});let a=t?.chunkSeparator??this.defaultChunkSeparator;i=F(i,a),this.urlSafe&&(i=z(i));let c=null;if(r){let y=W(i);c=y.checksum,i=y.data;}this.shouldObfuscate(t)&&(i=this.getObfuscationLayer().deobfuscate(i));let{cleanedInput:d,paddingBits:l,compressionAlgorithm:h,isEncrypted:f,pipelineVersion:u}=K(i,this.paddingChar,this.effectiveBitLength);if(f&&s&&!this.encryptionKey)throw new Error("[Ddu64 decode] Encrypted payload requires an encryptionKey");this.assertEncodedInputAligned(d);let m=this.normalizeLimit(t?.maxDecodedBytes,this.defaultMaxDecodedBytes,true,"maxDecodedBytes"),g=this.estimateDecodedBytes(d.length,l);if(g>m)throw new Error(`[Ddu64 decode] Decoded output exceeds limit. Estimated: ${g} bytes, Limit: ${m} bytes`);this.reportProgress(t,{processedBytes:d.length,totalBytes:e.length,percent:30,stage:"decode"});let p=this.decodeChars(d,l);if(u===3&&f&&this.encryptionKey&&s&&(this.reportProgress(t,{processedBytes:p.length,totalBytes:p.length,percent:55,stage:"decrypt"}),p=this.decryptSync(p)),h&&o&&(u===2||!f||s)){let y=this.normalizeLimit(t?.maxDecompressedBytes,this.defaultMaxDecompressedBytes,true,"maxDecompressedBytes");this.reportProgress(t,{processedBytes:p.length,totalBytes:p.length,percent:70,stage:"decompress"}),p=this.decompressSync(p,h,y);}if(c&&(u===2||!f||s)){this.reportProgress(t,{processedBytes:p.length,totalBytes:p.length,percent:85,stage:"checksum"});let y=D(p);if(y!==c)throw new Error(`[Ddu64 decode] Checksum mismatch. Expected: ${c}, Got: ${y}`)}return u===2&&f&&this.encryptionKey&&s&&(this.reportProgress(t,{processedBytes:p.length,totalBytes:p.length,percent:90,stage:"decrypt"}),p=this.decryptSync(p)),this.reportProgress(t,{processedBytes:p.length,totalBytes:p.length,percent:100,stage:"done"}),p}async encodeAsync(e,t){let r=await this.getAdapterAsync(),o=t?.compress??this.defaultCompress,s=t?.checksum??this.defaultChecksum,i=(t?.encrypt??true)&&!!this.encryptionKey,a=t?.chunkSize??this.defaultChunkSize,c=t?.chunkSeparator??this.defaultChunkSeparator,d=typeof e=="string"?T(e):e;this.reportProgress(t,{processedBytes:0,totalBytes:d.length,percent:0,stage:"start"});let l="";s&&(l=D(d));let h;if(o){let m=t?.compressionAlgorithm??this.defaultCompressionAlgorithm,g=x(t?.compressionLevel??this.defaultCompressionLevel,m);this.reportProgress(t,{processedBytes:d.length,totalBytes:d.length,percent:20,stage:"compress"});let p;if(m==="brotli"){if(!r.brotliCompress)throw new Error("[Ddu64 compress] Brotli compression is unavailable in the current runtime.");p=await r.brotliCompress(d,g);}else p=await r.deflate(d,g);p.length<d.length&&(d=p,h=m);}let f=false;if(i){let m=await this.getKeyHashAsync(r);this.reportProgress(t,{processedBytes:d.length,totalBytes:d.length,percent:45,stage:"encrypt"}),d=await r.encrypt(d,m),f=true;}this.reportProgress(t,{processedBytes:d.length,totalBytes:d.length,percent:70,stage:"encode"});let u=this.encodeBytes(d,h,f,t);return u=this.applyPostEncoding(u,t,l,s,a,c),this.reportProgress(t,{processedBytes:d.length,totalBytes:d.length,percent:100,stage:"done"}),u}async decodeAsync(e,t){let r=await this.decodeToUint8ArrayAsync(e,t);return $(r)}async decodeToUint8ArrayAsync(e,t){let r=await this.getAdapterAsync(),o=t?.checksum??this.defaultChecksum,s=t?.compress!==false,i=t?.encrypt!==false,a=e;this.reportProgress(t,{processedBytes:0,totalBytes:e.length,percent:0,stage:"start"});let c=t?.chunkSeparator??this.defaultChunkSeparator;a=F(a,c),this.urlSafe&&(a=z(a));let d=null;if(o){let b=W(a);d=b.checksum,a=b.data;}this.shouldObfuscate(t)&&(a=this.getObfuscationLayer().deobfuscate(a));let{cleanedInput:l,paddingBits:h,compressionAlgorithm:f,isEncrypted:u,pipelineVersion:m}=K(a,this.paddingChar,this.effectiveBitLength);if(u&&i&&!this.encryptionKey)throw new Error("[Ddu64 decode] Encrypted payload requires an encryptionKey");this.assertEncodedInputAligned(l);let g=this.normalizeLimit(t?.maxDecodedBytes,this.defaultMaxDecodedBytes,true,"maxDecodedBytes"),p=this.estimateDecodedBytes(l.length,h);if(p>g)throw new Error(`[Ddu64 decode] Decoded output exceeds limit. Estimated: ${p} bytes, Limit: ${g} bytes`);this.reportProgress(t,{processedBytes:l.length,totalBytes:e.length,percent:30,stage:"decode"});let y=this.decodeChars(l,h);if(m===3&&u&&this.encryptionKey&&i){let b=await this.getKeyHashAsync(r);this.reportProgress(t,{processedBytes:y.length,totalBytes:y.length,percent:55,stage:"decrypt"}),y=await r.decrypt(y,b);}if(f&&s&&(m===2||!u||i)){let b=this.normalizeLimit(t?.maxDecompressedBytes,this.defaultMaxDecompressedBytes,true,"maxDecompressedBytes");if(f==="brotli"){if(!r.brotliDecompress)throw new Error("[Ddu64 decompress] Brotli decompression is unavailable in the current runtime.");this.reportProgress(t,{processedBytes:y.length,totalBytes:y.length,percent:70,stage:"decompress"}),y=await r.brotliDecompress(y,b);}else this.reportProgress(t,{processedBytes:y.length,totalBytes:y.length,percent:70,stage:"decompress"}),y=await r.inflate(y,b);}if(d&&(m===2||!u||i)){this.reportProgress(t,{processedBytes:y.length,totalBytes:y.length,percent:85,stage:"checksum"});let b=D(y);if(b!==d)throw new Error(`[Ddu64 decode] Checksum mismatch. Expected: ${d}, Got: ${b}`)}if(m===2&&u&&this.encryptionKey&&i){let b=await this.getKeyHashAsync(r);this.reportProgress(t,{processedBytes:y.length,totalBytes:y.length,percent:90,stage:"decrypt"}),y=await r.decrypt(y,b);}return this.reportProgress(t,{processedBytes:y.length,totalBytes:y.length,percent:100,stage:"done"}),y}getCharSetInfo(){return {charSet:[...this.dduChar],paddingChar:this.paddingChar,bitLength:this.bitLength,usePowerOfTwo:this.usePowerOfTwo,encoding:"utf-8",defaultCompress:this.defaultCompress,defaultMaxDecodedBytes:this.defaultMaxDecodedBytes,defaultMaxDecompressedBytes:this.defaultMaxDecompressedBytes,urlSafe:this.urlSafe,hasEncryptionKey:!!this.encryptionKey,defaultChecksum:this.defaultChecksum,defaultChunkSize:this.defaultChunkSize,defaultChunkSeparator:this.defaultChunkSeparator,defaultCompressionLevel:this.defaultCompressionLevel,defaultCompressionAlgorithm:this.defaultCompressionAlgorithm}}getStats(e,t){let o=(typeof e=="string"?T(e):e).length,{encoded:s,compressedSize:i}=this.encodeInternal(e,t),a=s.length,c=o>0?a/o:0,l=(t?.compress??this.defaultCompress)&&i!==void 0&&o>0?i/o:void 0;return {originalSize:o,encodedSize:a,compressedSize:i,compressionRatio:l,expansionRatio:c,charsetSize:this.dduChar.length,bitLength:this.bitLength}}static setWorkerPoolSize(e){pe(e);}encodeInternal(e,t){let r=t?.compress??this.defaultCompress,o=t?.checksum??this.defaultChecksum,s=(t?.encrypt??true)&&!!this.encryptionKey,i=t?.chunkSize??this.defaultChunkSize,a=t?.chunkSeparator??this.defaultChunkSeparator,c=typeof e=="string"?T(e):e;this.reportProgress(t,{processedBytes:0,totalBytes:c.length,percent:0,stage:"start"});let d="";o&&(d=D(c));let l,h;if(r){let m=t?.compressionAlgorithm??this.defaultCompressionAlgorithm,g=x(t?.compressionLevel??this.defaultCompressionLevel,m);this.reportProgress(t,{processedBytes:c.length,totalBytes:c.length,percent:20,stage:"compress"});let p=this.compressSync(c,m,g);h=p.length,p.length<c.length&&(c=p,l=m);}let f=false;s&&(this.reportProgress(t,{processedBytes:c.length,totalBytes:c.length,percent:45,stage:"encrypt"}),c=this.encryptSync(c),f=true),this.reportProgress(t,{processedBytes:c.length,totalBytes:c.length,percent:70,stage:"encode"});let u=this.encodeBytes(c,l,f,t);return u=this.applyPostEncoding(u,t,d,o,i,a),this.reportProgress(t,{processedBytes:c.length,totalBytes:c.length,percent:100,stage:"done"}),{encoded:u,compressedSize:h}}applyPostEncoding(e,t,r,o,s,i){let a=e;return this.shouldObfuscate(t)&&(a=this.getObfuscationLayer().obfuscate(a)),o&&r&&(a=a+"CHK"+r),this.urlSafe&&(a=de(a)),s&&s>0&&(a=le(a,s,i)),a}encodeBytes(e,t,r,o){if(e.length===0)return "";let s=this.encodeBytesWithNativeBase64(e),i,a;if(s)i=s.indices,a=s.paddingBits;else {let l=this.shouldUseWasm(e.length)?_():null;if(l?.ready&&this.usePowerOfTwo){let h=l.encode(e,this.bitLength);i=h.indices,a=h.paddingBits;}else {let h=oe(e,this.bitPackConfig);i=h.indices,a=h.paddingBits;}}let c=new Array(i.length);for(let l=0;l<i.length;l++)c[l]=this.dduChar[i[l]];let d=o?.omitFooter?"":ce({paddingBits:a,compressionAlgorithm:t,isEncrypted:!!r,paddingChar:this.paddingChar,useRepeatPadding:this.useRepeatPadding&&!t&&!r,pipelineVersion:r?3:2});return c.join("")+d}decodeChars(e,t){let r=e.length;if(r===0)return new Uint8Array(0);let o=this.decodeCharsWithNativeBase64(e,t);if(o)return o;let s=r>=this.wasmThreshold||r>=4096?new Uint16Array(r):new Array(r);for(let a=0;a<r;a++){let c=e[a],d=this.dduBinaryLookup.get(c);if(d===void 0)throw new Error(`[Ddu64 decode] Invalid character "${c}" at ${a}`);s[a]=d;}let i=this.shouldUseWasm(r)?_():null;if(i?.ready&&this.usePowerOfTwo){let a=s instanceof Uint16Array?s:Uint16Array.from(s);return i.decode(a,this.bitLength,t)}return se(s,t,this.bitPackConfig)}encodeBytesWithNativeBase64(e){if(!this.canUseNativeBase64)return null;let t=this.bytesToBase64(e);if(t===null)return null;let r=0,o=t.length;for(;o>0&&t[o-1]===Me;)r++,o--;let s=o>=4096?new Uint16Array(o):new Array(o);for(let i=0;i<o;i++)s[i]=Rt[t[i]];return {indices:s,paddingBits:r===2?4:r===1?2:0}}decodeCharsWithNativeBase64(e,t){if(!this.canUseNativeBase64||!this.nativeDecodeMap)return null;let r=t===4?2:t===2?1:t===0?0:-1;if(r<0)return null;let o=new Array(e.length+r);for(let s=0;s<e.length;s++){let i=this.nativeDecodeMap.get(e[s]);if(i===void 0)return null;o[s]=i;}for(let s=0;s<r;s++)o[e.length+s]=Me;return this.base64ToBytes(o.join(""))}bytesToBase64(e){let t=e.toBase64;if(typeof t=="function")return t.call(e);let r=globalThis.Buffer;return r?.from?r.from(e.buffer,e.byteOffset,e.byteLength).toString("base64"):null}base64ToBytes(e){let t=Uint8Array;if(typeof t.fromBase64=="function")return t.fromBase64(e);let r=globalThis.Buffer;if(r?.from){let o=r.from(e,"base64");return new Uint8Array(o.buffer,o.byteOffset,o.byteLength)}return null}shouldUseWasm(e){return e>=this.wasmThreshold}reportProgress(e,t){e?.onProgress?.(t);}requireSyncAdapter(){if(!this.adapter)throw new Error("[Ddu64 adapter] No platform adapter available. Use encodeAsync()/decodeAsync() in browser environments, or provide an adapter via options.adapter.");return this.adapter}encryptSync(e){let t=this.requireSyncAdapter();if(!t.encryptSync)throw new Error("[Ddu64 encrypt] Sync encryption unavailable. Use encodeAsync() in browser environments.");if(!this.encryptionKeyHash){if(!t.deriveKeySync)throw new Error("[Ddu64 encrypt] Sync key derivation unavailable. Use encodeAsync() in browser environments.");this.encryptionKeyHash=t.deriveKeySync(this.encryptionKey,this.keyDerivation);}return t.encryptSync(e,this.encryptionKeyHash)}decryptSync(e){let t=this.requireSyncAdapter();if(!t.decryptSync)throw new Error("[Ddu64 decrypt] Sync decryption unavailable. Use decodeAsync() in browser environments.");if(!this.encryptionKeyHash){if(!t.deriveKeySync)throw new Error("[Ddu64 decrypt] Sync key derivation unavailable. Use decodeAsync() in browser environments.");this.encryptionKeyHash=t.deriveKeySync(this.encryptionKey,this.keyDerivation);}return t.decryptSync(e,this.encryptionKeyHash)}compressSync(e,t,r){let o=this.requireSyncAdapter();if(t==="brotli"){if(!o.brotliCompressSync)throw new Error("[Ddu64 compress] Brotli compression is unavailable in the current runtime.");return o.brotliCompressSync(e,r)}if(!o.deflateSync)throw new Error("[Ddu64 compress] Sync compression unavailable. Use encodeAsync() in browser environments.");return o.deflateSync(e,r)}decompressSync(e,t,r){let o=this.requireSyncAdapter();if(t==="brotli"){if(!o.brotliDecompressSync)throw new Error("[Ddu64 decompress] Brotli decompression is unavailable in the current runtime.");return o.brotliDecompressSync(e,r)}if(!o.inflateSync)throw new Error("[Ddu64 decompress] Sync decompression unavailable. Use decodeAsync() in browser environments.");return o.inflateSync(e,r)}async getAdapterAsync(){if(this.adapter)return this.adapter;let{getAdapter:e}=await Promise.resolve().then(()=>(te(),Ie));return this.adapter=await e(),this.adapter}async getKeyHashAsync(e){return this.encryptionKeyHash?this.encryptionKeyHash:(this.encryptionKeyHash=await e.deriveKey(this.encryptionKey,this.keyDerivation),this.encryptionKeyHash)}getObfuscationLayer(){if(!this._obfuscationLayer){let e=new Set(this.dduChar);e.add(this.paddingChar);let t="ELYSIAGRONCV01234567";for(let o of t)e.add(o);let r=[...e];this._obfuscationLayer=new C(r);}return this._obfuscationLayer}shouldObfuscate(e){let t=e?.obfuscate??this.defaultObfuscate;if(t&&!this.encryptionKey)throw new Error("[Ddu64 obfuscation] Obfuscation requires encryption to be enabled.");return t}normalizeLimit(e,t,r,o){if(e===void 0)return t;if(e===Number.POSITIVE_INFINITY)return Number.POSITIVE_INFINITY;if(!Number.isFinite(e)||e<=0){if(r)throw new Error(`[Ddu64 options] Invalid ${o}. Must be a positive finite number or Infinity.`);return t}return Math.floor(e)}estimateDecodedBytes(e,t){if(e===0)return 0;if(t<0||t>=this.effectiveBitLength)throw new Error(`[Ddu64 decode] Invalid padding bits: ${t}`);let r=this.usePowerOfTwo?1:2,s=Math.ceil(e/r)*this.effectiveBitLength-t;if(s<0)throw new Error("[Ddu64 decode] Invalid decoded bit length");return Math.ceil(s/Lt)}assertEncodedInputAligned(e){if(!this.usePowerOfTwo&&e.length%2!==0)throw new Error(`[Ddu64 decode] Invalid encoded length for variable charset. Expected multiple of 2, got ${e.length}`)}};var ne=class n{chars=[];constructor(){}static create(){return new n}static fromUnicodeRange(e,t){return new n().addUnicodeRange(e,t)}static fromString(e){return new n().addString(e)}static base64(){return new n().addString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")}static base32(){return new n().addString("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")}static uppercase(){return n.fromUnicodeRange(65,90)}static lowercase(){return n.fromUnicodeRange(97,122)}static digits(){return n.fromUnicodeRange(48,57)}static hangulJamo(){return new n().addUnicodeRange(4352,4370).addUnicodeRange(4449,4469).addUnicodeRange(4520,4546)}addUnicodeRange(e,t){for(let r=e;r<=t;r++)this.chars.push(String.fromCodePoint(r));return this}addString(e){return typeof e=="string"?this.chars.push(...e):this.chars.push(...e),this}add(...e){return this.chars.push(...e),this}excludeConfusing(){let e=new Set(["0","O","o","1","l","I","i","|","L"]);return this.chars=this.chars.filter(t=>!e.has(t)),this}exclude(...e){let t=new Set(e);return this.chars=this.chars.filter(r=>!t.has(r)),this}excludeUrlUnsafe(){let e=new Set(["+","/","=","?","&","#","%"," "]);return this.chars=this.chars.filter(t=>!e.has(t)),this}unique(){return this.chars=[...new Set(this.chars)],this}shuffle(e){let t=e!==void 0?this.seededRandom(e):Math.random;for(let r=this.chars.length-1;r>0;r--){let o=Math.floor(t()*(r+1));[this.chars[r],this.chars[o]]=[this.chars[o],this.chars[r]];}return this}seededRandom(e){let t=e|0||1;return ()=>(t^=t<<13,t^=t>>17,t^=t<<5,(t>>>0)/4294967296)}limit(e){return this.chars=this.chars.slice(0,e),this}limitToPowerOfTwo(){let e=this.chars.length;if(e===0)return this;let t=1<<Math.floor(Math.log2(e));return this.chars=this.chars.slice(0,t),this}sort(){return this.chars.sort(),this}reverse(){return this.chars.reverse(),this}get length(){return this.chars.length}buildString(){return this.chars.join("")}build(){return [...this.chars]}buildWithPadding(e){let t=[...this.chars],r=e;if(!r){let o=["=",".","_","-","~","!"];for(let s of o)if(!t.includes(s)){r=s;break}if(!r)throw new Error("Cannot find suitable padding character")}return {charset:t,padding:r}}};J();te();function _t(n,e){let t=n.getCharSetInfo(),r=e?.compress??t.defaultCompress,o=(e?.encrypt??true)&&t.hasEncryptionKey,s=r?e?.compressionAlgorithm??t.defaultCompressionAlgorithm:void 0,i=t.paddingChar,a=!r&&!o,c=false,d=[],l=0,h=null;return new TransformStream({async transform(f,u){if(a){if(!c){let b=v(i,{compressionAlgorithm:void 0,encrypted:false});u.enqueue(b),c=true;}let m;h&&h.length>0?(m=new Uint8Array(h.length+f.length),m.set(h,0),m.set(f,h.length)):m=f;let g=t.bitLength,p=Oe(g,8)/8,y=Math.floor(m.length/p)*p;if(y>0){let b=m.subarray(0,y),k=await n.encodeAsync(b,{compress:false,encrypt:false,checksum:false,chunkSize:void 0,chunkSeparator:void 0,omitFooter:true});u.enqueue(k);}y<m.length?h=m.slice(y):h=null;}else d.push(f),l+=f.length;},async flush(f){try{if(a){if(!c){let u=v(i,{compressionAlgorithm:void 0,encrypted:!1});f.enqueue(u);}if(h&&h.length>0){let u=await n.encodeAsync(h,{compress:!1,encrypt:!1,checksum:!1,chunkSize:void 0,chunkSeparator:void 0});f.enqueue(u);}h=null;}else {let u=v(i,{compressionAlgorithm:s,encrypted:o});if(f.enqueue(u),l>0){let m=new Uint8Array(l),g=0;for(let y of d)m.set(y,g),g+=y.length;let p=await n.encodeAsync(m,{...e,compress:r,encrypt:o,checksum:!1,chunkSize:void 0,chunkSeparator:void 0});f.enqueue(p);}d=[],l=0;}}catch(u){f.error(u instanceof Error?u:new Error(String(u)));}}})}function It(n,e){let t=n.getCharSetInfo(),r=t.paddingChar,o=H(r),s="",i=false,a=null,c=false;return new TransformStream({async transform(d,l){if(s+=d,!i&&s.length>=o){if(!s.startsWith(r)){l.error(new Error("[WebStreams decode] Invalid or missing stream header"));return}if(a=ae(s,r),a===null){l.error(new Error("[WebStreams decode] Invalid or missing stream header"));return}if(a.encrypted&&!t.hasEncryptionKey){l.error(new Error("[WebStreams decode] Encrypted stream requires an encryptionKey"));return}i=true,c=!a.compressionAlgorithm&&!a.encrypted,s=s.slice(o);}if(i&&c&&s.length>0){let h=t.bitLength,f=Oe(h,8)/h,u=Math.floor(s.length/f)*f;if(u>0){let m=s.slice(0,u);s=s.slice(u);try{let g=await n.decodeToUint8ArrayAsync(m,{compress:!1,encrypt:!1,checksum:!1,chunkSize:void 0,chunkSeparator:void 0});g.length>0&&l.enqueue(g);}catch{s=m+s;}}}},async flush(d){try{if(!i){if(s.length===0)return;d.error(new Error("[WebStreams decode] Incomplete stream header"));return}if(s.length===0)return;let l=a.compressionAlgorithm,h=a.encrypted,f=await n.decodeToUint8ArrayAsync(s,{...e,compress:!!l,compressionAlgorithm:l,encrypt:h,checksum:!1,chunkSize:void 0,chunkSeparator:void 0});f.length>0&&d.enqueue(f),s="";}catch(l){d.error(l instanceof Error?l:new Error(String(l)));}}})}function Oe(n,e){return n*e/Mt(n,e)}function Mt(n,e){for(;e!==0;){let t=e;e=n%e,n=t;}return n}exports.CharsetBuilder=ne;exports.Ddu64=M;exports.Ddu64Core=M;exports.DduSetSymbol=q;exports.HangulObfuscationLayer=C;exports.createObfuscationLayer=ot;exports.createReadableDecodeStream=It;exports.createReadableEncodeStream=_t;exports.detectRuntime=ee;exports.getAdapter=_e;exports.getWasmCodec=dt;exports.getWasmCodecSync=_;exports.preloadWasm=ct;//# sourceMappingURL=browser.cjs.map
7
+ //# sourceMappingURL=browser.cjs.map