@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 +210 -198
- package/dist/browser.cjs +7 -0
- package/dist/browser.d.cts +217 -0
- package/dist/browser.d.ts +217 -0
- package/dist/browser.js +7 -0
- package/dist/core-BccIjoLZ.d.cts +663 -0
- package/dist/core-BccIjoLZ.d.ts +663 -0
- package/dist/core.cjs +7 -0
- package/dist/core.d.cts +1 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +7 -0
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +62 -743
- package/dist/index.d.ts +62 -743
- package/dist/index.js +6 -4
- package/dist/wasm/codec.wasm +0 -0
- package/package.json +24 -3
- package/dist/DduStream-NP3CMCKK.js +0 -2
- package/dist/chunk-FVBZKVPE.js +0 -4
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
|
-
|
|
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 =
|
|
56
|
-
const
|
|
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
|
-
|
|
57
|
+
## Presets
|
|
60
58
|
|
|
61
59
|
```typescript
|
|
62
|
-
|
|
63
|
-
const encoder = new Ddu64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "=");
|
|
60
|
+
import { Ddu64, DduSetSymbol } from "@ddunigma/node";
|
|
64
61
|
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
105
|
+
const ddu = new Ddu64(charset, padding);
|
|
94
106
|
|
|
95
|
-
|
|
96
|
-
const
|
|
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
|
|
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
|
-
|
|
129
|
+
## Encryption
|
|
113
130
|
|
|
114
131
|
```typescript
|
|
115
|
-
|
|
132
|
+
// SHA-256 키 파생 (기본)
|
|
133
|
+
const ddu = new Ddu64(undefined, undefined, {
|
|
116
134
|
encryptionKey: "my-secret-key",
|
|
117
135
|
});
|
|
118
136
|
|
|
119
|
-
const encoded =
|
|
120
|
-
const decoded =
|
|
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
|
|
155
|
+
const ddu = new Ddu64(undefined, undefined, { checksum: true });
|
|
129
156
|
|
|
130
|
-
const encoded =
|
|
131
|
-
const decoded =
|
|
132
|
-
// 데이터 변조 시 에러 발생
|
|
157
|
+
const encoded = ddu.encode("data"); // CRC32 체크섬 포함
|
|
158
|
+
const decoded = ddu.decode(encoded); // 무결성 검증 후 반환
|
|
133
159
|
```
|
|
134
160
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
`+`, `/`, `=` 를 URL 안전 문자(`-`, `_`, `.`)로 변환합니다.
|
|
161
|
+
## URL-Safe
|
|
138
162
|
|
|
139
163
|
```typescript
|
|
140
|
-
const
|
|
164
|
+
const ddu = new Ddu64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "=", {
|
|
141
165
|
urlSafe: true,
|
|
142
166
|
});
|
|
143
|
-
```
|
|
144
167
|
|
|
145
|
-
|
|
168
|
+
// +→- /→_ =→. 로 자동 변환
|
|
169
|
+
const encoded = ddu.encode("URL safe text");
|
|
170
|
+
```
|
|
146
171
|
|
|
147
|
-
|
|
172
|
+
## Chunking
|
|
148
173
|
|
|
149
174
|
```typescript
|
|
150
|
-
const
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
183
|
-
|
|
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
|
-
|
|
207
|
+
Node.js에서도 async 메서드를 사용할 수 있습니다. 브라우저 진입점(`@ddunigma/node/browser`)은 Node.js 내장 모듈을 임포트하지 않습니다.
|
|
208
|
+
|
|
209
|
+
## Web Streams
|
|
187
210
|
|
|
188
211
|
```typescript
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
223
|
+
const decodedStream = encodedStream.pipeThrough(createReadableDecodeStream(ddu));
|
|
224
|
+
```
|
|
198
225
|
|
|
199
|
-
|
|
226
|
+
## WASM Acceleration
|
|
200
227
|
|
|
201
228
|
```typescript
|
|
202
|
-
import {
|
|
229
|
+
import { Ddu64, preloadWasm } from "@ddunigma/node";
|
|
203
230
|
|
|
204
|
-
//
|
|
205
|
-
CharsetBuilder.fromUnicodeRange(0x4e00, 0x4e3f).build();
|
|
231
|
+
await preloadWasm(); // 선택적 사전 로드
|
|
206
232
|
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
242
|
+
## Progress Callback
|
|
225
243
|
|
|
226
244
|
```typescript
|
|
227
|
-
|
|
245
|
+
const ddu = new Ddu64(undefined, undefined, { compress: true });
|
|
228
246
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
243
|
-
|
|
258
|
+
const ddu = new Ddu64(undefined, undefined, { compress: true });
|
|
259
|
+
const stats = ddu.getStats("A".repeat(1000));
|
|
244
260
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
encryptionKey: "stream-key",
|
|
248
|
-
});
|
|
261
|
+
// { originalSize, encodedSize, compressedSize, compressionRatio, expansionRatio, charsetSize, bitLength }
|
|
262
|
+
```
|
|
249
263
|
|
|
250
|
-
|
|
251
|
-
.pipe(createEncodeStream(encoder))
|
|
252
|
-
.pipe(fs.createWriteStream("output.ddu"));
|
|
264
|
+
## Size Limits
|
|
253
265
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
|
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
|
-
##
|
|
296
|
+
## Constructor Options
|
|
322
297
|
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
pnpm test:watch # 워치 모드
|
|
326
|
-
pnpm test:coverage # 커버리지
|
|
298
|
+
```typescript
|
|
299
|
+
new Ddu64(dduChar?, paddingChar?, options?);
|
|
327
300
|
```
|
|
328
301
|
|
|
329
|
-
|
|
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
|
package/dist/browser.cjs
ADDED
|
@@ -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
|