unjwt 0.7.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +4 -4
  2. package/dist/THIRD-PARTY-LICENSES.md.gz +0 -0
  3. package/dist/_chunks/_codec-jwe.d.mts +170 -0
  4. package/dist/_chunks/_codec-jws.mjs +878 -0
  5. package/dist/_chunks/_internal.d.mts +7 -0
  6. package/dist/_chunks/_jwt-internal.mjs +388 -0
  7. package/dist/_chunks/algorithms.mjs +186 -0
  8. package/dist/_chunks/index.d.mts +500 -808
  9. package/dist/_chunks/index2.d.mts +11 -0
  10. package/dist/_chunks/index3.d.mts +108 -0
  11. package/dist/_chunks/jwe.d.mts +43 -66
  12. package/dist/_chunks/jwe.mjs +384 -252
  13. package/dist/_chunks/jwk.mjs +1374 -607
  14. package/dist/_chunks/jws.d.mts +48 -103
  15. package/dist/_chunks/jws.mjs +372 -184
  16. package/dist/_chunks/jwt.d.mts +56 -0
  17. package/dist/_chunks/libs/unsecure.d.mts +164 -85
  18. package/dist/_chunks/libs/unsecure.mjs +390 -123
  19. package/dist/adapters/elysia/index.d.mts +33 -171
  20. package/dist/adapters/elysia/index.mjs +106 -575
  21. package/dist/adapters/h3v1/index.d.mts +59 -344
  22. package/dist/adapters/h3v1/index.mjs +114 -619
  23. package/dist/adapters/h3v2/index.d.mts +58 -326
  24. package/dist/adapters/h3v2/index.mjs +108 -611
  25. package/dist/core/internal.d.mts +2 -0
  26. package/dist/core/internal.mjs +1 -0
  27. package/dist/core/jwe.d.mts +4 -2
  28. package/dist/core/jwe.mjs +4 -2
  29. package/dist/core/jwk.d.mts +183 -371
  30. package/dist/core/jwk.mjs +4 -3
  31. package/dist/core/jws.d.mts +4 -2
  32. package/dist/core/jws.mjs +4 -2
  33. package/dist/core/utils/index.d.mts +5 -158
  34. package/dist/core/utils/index.mjs +12 -3
  35. package/dist/index.d.mts +8 -4
  36. package/dist/index.mjs +6 -3
  37. package/package.json +29 -30
  38. package/dist/_chunks/_internal.mjs +0 -88
  39. package/dist/_chunks/utils.mjs +0 -392
@@ -1,69 +1,132 @@
1
- function safeJsonParse(json) {
2
- return JSON.parse(json, _jsonReviver);
1
+ var UnsecureError = class extends Error {
2
+ code;
3
+ constructor(code, message, options) {
4
+ super(message, options);
5
+ this.name = "UnsecureError";
6
+ this.code = code;
7
+ }
8
+ };
9
+ const textEncoder = /* @__PURE__ */ new TextEncoder();
10
+ /* @__NO_SIDE_EFFECTS__ */
11
+ function describeValue(value) {
12
+ if (value === null) return "null";
13
+ if (typeof value !== "object") return typeof value;
14
+ return value.constructor?.name ?? "object";
3
15
  }
4
- function sanitizeObject(obj) {
5
- if (!obj || typeof obj !== "object") return obj;
6
- const seen = /* @__PURE__ */ new WeakSet();
7
- seen.add(obj);
8
- _sanitizeInPlace(obj, seen);
9
- return obj;
16
+ /* @__NO_SIDE_EFFECTS__ */
17
+ function toBytes(value, label) {
18
+ if (typeof value === "string") return textEncoder.encode(value);
19
+ if (ArrayBuffer.isView(value)) return value instanceof Uint8Array ? value : new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
20
+ if (value instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer) return new Uint8Array(value);
21
+ throw new UnsecureError("INVALID_TYPE", `${label}: expected a string, ArrayBuffer or ArrayBuffer view, got ${/* @__PURE__ */ describeValue(value)}.`);
10
22
  }
11
- function sanitizeObjectCopy(obj) {
12
- if (!obj || typeof obj !== "object") return obj;
13
- return _sanitizeCopy(obj, /* @__PURE__ */ new WeakMap());
23
+ const textDecoder = /* @__PURE__ */ new TextDecoder("utf-8", { ignoreBOM: true });
24
+ const _fatalDecoder = /* @__PURE__ */ new TextDecoder("utf-8", {
25
+ ignoreBOM: true,
26
+ fatal: true
27
+ });
28
+ /* @__NO_SIDE_EFFECTS__ */
29
+ function _wholeBuffer(bytes) {
30
+ return bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength ? bytes : bytes.slice();
14
31
  }
15
- const _jsonReviver = (key, value) => _isDangerousKey(key) ? void 0 : value;
16
- function _isDangerousKey(key) {
17
- return key === "__proto__" || key === "prototype" || key === "constructor";
32
+ const _LATIN1_CHUNK = 32768;
33
+ /* @__NO_SIDE_EFFECTS__ */
34
+ function _latin1(bytes) {
35
+ if (bytes.length <= _LATIN1_CHUNK) return String.fromCharCode(...bytes);
36
+ let text = "";
37
+ for (let i = 0; i < bytes.length; i += _LATIN1_CHUNK) text += String.fromCharCode(...bytes.subarray(i, i + _LATIN1_CHUNK));
38
+ return text;
18
39
  }
19
- function _sanitizeInPlace(current, seen) {
20
- if (Array.isArray(current)) {
21
- for (let i = 0; i < current.length; i++) {
22
- const v = current[i];
23
- if (v !== null && typeof v === "object" && !seen.has(v)) {
24
- seen.add(v);
25
- _sanitizeInPlace(v, seen);
26
- }
27
- }
28
- return;
40
+ function _assertData(input, label) {
41
+ if (typeof input !== "string" && !/* @__PURE__ */ _isBytes(input)) throw new UnsecureError("INVALID_TYPE", `${label}: expected a string or Uint8Array, got ${/* @__PURE__ */ describeValue(input)}.`);
42
+ }
43
+ /* @__NO_SIDE_EFFECTS__ */
44
+ function _isBytes(input) {
45
+ return ArrayBuffer.isView(input) && input instanceof Uint8Array;
46
+ }
47
+ /* @__NO_SIDE_EFFECTS__ */
48
+ function _parsePrep(input, options) {
49
+ const isBytes = /* @__PURE__ */ _isBytes(input);
50
+ const returnAs = options?.returnAs ?? (isBytes ? "uint8array" : "string");
51
+ return {
52
+ text: isBytes ? /* @__PURE__ */ _latin1(input) : input,
53
+ wantString: returnAs === "string"
54
+ };
55
+ }
56
+ /* @__NO_SIDE_EFFECTS__ */
57
+ function _parseFinalize(bytes, wantString, strict, label) {
58
+ if (!wantString) return bytes;
59
+ if (!strict) return textDecoder.decode(bytes);
60
+ try {
61
+ return _fatalDecoder.decode(bytes);
62
+ } catch {
63
+ throw /* @__PURE__ */ _malformed(label, "decoded bytes are not valid UTF-8.");
29
64
  }
30
- const keys = Object.keys(current);
31
- for (let i = 0; i < keys.length; i++) {
32
- const key = keys[i];
33
- if (_isDangerousKey(key)) {
34
- delete current[key];
35
- continue;
36
- }
37
- const v = current[key];
38
- if (v !== null && typeof v === "object" && !seen.has(v)) {
39
- seen.add(v);
40
- _sanitizeInPlace(v, seen);
41
- }
65
+ }
66
+ /* @__NO_SIDE_EFFECTS__ */
67
+ function _malformed(label, detail) {
68
+ return new UnsecureError("MALFORMED", `${label}: ${detail}`);
69
+ }
70
+ /* @__NO_SIDE_EFFECTS__ */
71
+ function _tailBits(rem, bits) {
72
+ if (rem === 0) return 0;
73
+ const leftover = rem * bits % 8;
74
+ return leftover >= bits ? -1 : leftover;
75
+ }
76
+ /* @__NO_SIDE_EFFECTS__ */
77
+ function _strictBody(text, table, shape, label, padding) {
78
+ let end = text.length;
79
+ while (end > 0 && text.charCodeAt(end - 1) === 61) end--;
80
+ const padFound = text.length - end;
81
+ for (let i = 0; i < end; i++) {
82
+ const c = text.charCodeAt(i);
83
+ if ((c < 128 ? table[c] : -1) < 0) throw /* @__PURE__ */ _malformed(label, `invalid ${shape.name} character ${JSON.stringify(text[i])} at index ${i}.`);
42
84
  }
85
+ const rem = end % shape.group;
86
+ const tail = /* @__PURE__ */ _tailBits(rem, shape.bits);
87
+ if (tail < 0) throw /* @__PURE__ */ _malformed(label, `${end} ${shape.name} symbols cannot encode whole bytes.`);
88
+ const padNeeded = rem === 0 ? 0 : shape.group - rem;
89
+ if (padFound > 0) {
90
+ if (padNeeded === 0 || padding === false) throw /* @__PURE__ */ _malformed(label, `unexpected "=" padding.`);
91
+ if (padFound !== padNeeded) throw /* @__PURE__ */ _malformed(label, `expected ${padNeeded} "=" padding characters, found ${padFound}.`);
92
+ } else if (padding === true && padNeeded > 0) throw /* @__PURE__ */ _malformed(label, `expected ${padNeeded} "=" padding characters, found 0.`);
93
+ if (tail > 0 && (table[text.charCodeAt(end - 1)] & (1 << tail) - 1) !== 0) throw /* @__PURE__ */ _malformed(label, `the last ${shape.name} symbol sets bits past the final byte.`);
94
+ return end === text.length ? text : text.slice(0, end);
43
95
  }
44
- function _sanitizeCopy(current, seen) {
45
- const existing = seen.get(current);
46
- if (existing !== void 0) return existing;
47
- if (Array.isArray(current)) {
48
- const out = [];
49
- seen.set(current, out);
50
- for (let i = 0; i < current.length; i++) {
51
- const v = current[i];
52
- out.push(v !== null && typeof v === "object" ? _sanitizeCopy(v, seen) : v);
53
- }
54
- return out;
96
+ /* @__NO_SIDE_EFFECTS__ */
97
+ function _symbols(text, table) {
98
+ const values = new Uint8Array(text.length);
99
+ let n = 0;
100
+ for (let i = 0; i < text.length; i++) {
101
+ const c = text.charCodeAt(i);
102
+ const v = c < 128 ? table[c] : -1;
103
+ if (v >= 0) values[n++] = v;
55
104
  }
56
- const out = {};
57
- seen.set(current, out);
58
- const keys = Object.keys(current);
59
- for (let i = 0; i < keys.length; i++) {
60
- const key = keys[i];
61
- if (_isDangerousKey(key)) continue;
62
- const v = current[key];
63
- out[key] = v !== null && typeof v === "object" ? _sanitizeCopy(v, seen) : v;
105
+ return n === values.length ? values : values.subarray(0, n);
106
+ }
107
+ /* @__NO_SIDE_EFFECTS__ */
108
+ function _looseCount(n, shape) {
109
+ let count = n;
110
+ while (count > 0 && /* @__PURE__ */ _tailBits(count % shape.group, shape.bits) < 0) count--;
111
+ return count;
112
+ }
113
+ /* @__NO_SIDE_EFFECTS__ */
114
+ function _decodeSymbols(values, count, bits) {
115
+ const out = new Uint8Array(count * bits >>> 3);
116
+ let acc = 0;
117
+ let held = 0;
118
+ let j = 0;
119
+ for (let i = 0; i < count; i++) {
120
+ acc = acc << bits | values[i];
121
+ held += bits;
122
+ if (held >= 8) {
123
+ held -= 8;
124
+ out[j++] = acc >>> held & 255;
125
+ }
64
126
  }
65
127
  return out;
66
128
  }
129
+ const _ON_HEAP_MAX = 64;
67
130
  const _Buffer = /* @__PURE__ */ (() => {
68
131
  try {
69
132
  return globalThis.Buffer;
@@ -71,79 +134,283 @@ const _Buffer = /* @__PURE__ */ (() => {
71
134
  return;
72
135
  }
73
136
  })();
74
- const _hasBuffer = typeof _Buffer?.from === "function";
75
- function _toBuffer(data) {
76
- return data instanceof Uint8Array ? _Buffer.from(data.buffer, data.byteOffset, data.byteLength) : _Buffer.from(data);
77
- }
78
- const _hasToBase64 = !_hasBuffer && typeof Uint8Array.prototype.toBase64 === "function";
79
- const _hasFromBase64 = !_hasBuffer && typeof Uint8Array.fromBase64 === "function";
80
- const _b64UrlEncOpts = /* @__PURE__ */ Object.freeze({
81
- alphabet: "base64url",
82
- omitPadding: true
83
- });
84
- const _b64UrlDecOpts = /* @__PURE__ */ Object.freeze({ alphabet: "base64url" });
85
- function _bytesToBase64Fallback(bytes) {
137
+ const _hasBuffer = /* @__PURE__ */ (() => typeof _Buffer?.from === "function")();
138
+ /* @__NO_SIDE_EFFECTS__ */
139
+ function _toBuffer(bytes) {
140
+ return bytes.byteLength <= _ON_HEAP_MAX ? _Buffer.from(bytes) : _Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
141
+ }
142
+ const _nativeToBase64 = /* @__PURE__ */ (() => typeof Uint8Array.prototype.toBase64 === "function")();
143
+ const _nativeFromBase64 = /* @__PURE__ */ (() => typeof Uint8Array.fromBase64 === "function")();
144
+ const _B64_SHAPE = {
145
+ bits: 6,
146
+ group: 4,
147
+ name: "base64"
148
+ };
149
+ const _B64_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
150
+ /* @__NO_SIDE_EFFECTS__ */
151
+ function _b64Table(pairs) {
152
+ const t = (/* @__PURE__ */ new Int16Array(128)).fill(-1);
153
+ for (let i = 0; i < 62; i++) t[_B64_DIGITS.charCodeAt(i)] = i;
154
+ for (let i = 0; i < pairs.length; i += 2) {
155
+ t[pairs.charCodeAt(i)] = 62;
156
+ t[pairs.charCodeAt(i + 1)] = 63;
157
+ }
158
+ return t;
159
+ }
160
+ const _B64_TABLE_STD = /* @__PURE__ */ _b64Table("+/");
161
+ const _B64_TABLE_URL = /* @__PURE__ */ _b64Table("-_");
162
+ /* @__NO_SIDE_EFFECTS__ */
163
+ function _unpad(s) {
164
+ let end = s.length;
165
+ while (end > 0 && s.charCodeAt(end - 1) === 61) end--;
166
+ return end === s.length ? s : s.slice(0, end);
167
+ }
168
+ /* @__NO_SIDE_EFFECTS__ */
169
+ function _padTo4(s) {
170
+ const rem = s.length % 4;
171
+ return rem === 0 ? s : s + "=".repeat(4 - rem);
172
+ }
173
+ /* @__NO_SIDE_EFFECTS__ */
174
+ function _encodeBase64(bytes, alphabet, padding) {
175
+ const url = alphabet === "base64url";
176
+ if (_hasBuffer) {
177
+ const s = (/* @__PURE__ */ _toBuffer(bytes)).toString(url ? "base64url" : "base64");
178
+ if (url) return padding ? /* @__PURE__ */ _padTo4(s) : s;
179
+ return padding ? s : /* @__PURE__ */ _unpad(s);
180
+ }
181
+ if (_nativeToBase64) return (/* @__PURE__ */ _wholeBuffer(bytes)).toBase64({
182
+ alphabet,
183
+ omitPadding: !padding
184
+ });
86
185
  let binary = "";
87
186
  for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
88
- return btoa(binary);
89
- }
90
- function base64Encode(data) {
91
- if (data == null) throw new TypeError("base64Encode: data must be a string or Uint8Array.");
92
- if (_hasBuffer) return _toBuffer(data).toString("base64");
93
- const encodedData = data instanceof Uint8Array ? data : textEncoder.encode(data);
94
- if (_hasToBase64) return encodedData.toBase64();
95
- return _bytesToBase64Fallback(encodedData);
96
- }
97
- function base64UrlEncode(data) {
98
- if (data == null) throw new TypeError("base64UrlEncode: data must be a string or Uint8Array.");
99
- if (_hasBuffer) return _toBuffer(data).toString("base64url");
100
- const encodedData = data instanceof Uint8Array ? data : textEncoder.encode(data);
101
- if (_hasToBase64) return encodedData.toBase64(_b64UrlEncOpts);
102
- return _bytesToBase64Fallback(encodedData).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
103
- }
104
- function base64Decode(data, options) {
105
- if (data == null) throw new TypeError("base64Decode: data must be a string or Uint8Array.");
106
- const isBufferInput = data instanceof Uint8Array;
107
- const str = isBufferInput ? textDecoder.decode(data) : data;
108
- const decodeToString = (options?.returnAs ?? (isBufferInput ? "uint8array" : "string")) === "string";
109
- if (!str) return decodeToString ? "" : /* @__PURE__ */ new Uint8Array(0);
110
- if (_hasBuffer) {
111
- const buf = _Buffer.from(str, "base64");
112
- return decodeToString ? buf.toString("utf8") : new Uint8Array(buf);
113
- }
114
- const decoded = _hasFromBase64 ? Uint8Array.fromBase64(str) : Uint8Array.from(atob(str), (b) => b.codePointAt(0));
115
- return decodeToString ? textDecoder.decode(decoded) : decoded;
116
- }
117
- function base64UrlDecode(data, options) {
118
- if (data == null) throw new TypeError("base64UrlDecode: data must be a string or Uint8Array.");
119
- const isBufferInput = data instanceof Uint8Array;
120
- let str = isBufferInput ? textDecoder.decode(data) : data;
121
- const decodeToString = (options?.returnAs ?? (isBufferInput ? "uint8array" : "string")) === "string";
122
- if (!str) return decodeToString ? "" : /* @__PURE__ */ new Uint8Array(0);
123
- if (_hasBuffer) {
124
- const buf = _Buffer.from(str, "base64url");
125
- return decodeToString ? buf.toString("utf8") : new Uint8Array(buf);
187
+ let s = btoa(binary);
188
+ if (url) s = s.replace(/\+/g, "-").replace(/\//g, "_");
189
+ return padding ? s : /* @__PURE__ */ _unpad(s);
190
+ }
191
+ /* @__NO_SIDE_EFFECTS__ */
192
+ function _decodeCanonical(padded, symbols) {
193
+ if (_hasBuffer) return new Uint8Array(_Buffer.from(padded, "base64"));
194
+ if (_nativeFromBase64) return Uint8Array.fromBase64(padded);
195
+ return /* @__PURE__ */ _decodeSymbols(/* @__PURE__ */ _symbols(padded, _B64_TABLE_STD), symbols, 6);
196
+ }
197
+ /* @__NO_SIDE_EFFECTS__ */
198
+ function _decodeBase64(text, alphabet, loose, label, padding) {
199
+ const url = alphabet === "base64url";
200
+ let body;
201
+ if (loose) {
202
+ const clean = text.replace(/-/g, "+").replace(/_/g, "/").replace(/[^A-Za-z0-9+/]/g, "");
203
+ body = clean.slice(0, /* @__PURE__ */ _looseCount(clean.length, _B64_SHAPE));
204
+ } else {
205
+ const strict = /* @__PURE__ */ _strictBody(text, url ? _B64_TABLE_URL : _B64_TABLE_STD, _B64_SHAPE, label, padding);
206
+ body = url ? strict.replace(/-/g, "+").replace(/_/g, "/") : strict;
126
207
  }
127
- let decoded;
128
- if (_hasFromBase64) decoded = Uint8Array.fromBase64(str, _b64UrlDecOpts);
129
- else {
130
- str = str.replace(/-/g, "+").replace(/_/g, "/");
131
- while (str.length % 4) str += "=";
132
- decoded = Uint8Array.from(atob(str), (b) => b.codePointAt(0));
208
+ const rem = body.length % 4;
209
+ return /* @__PURE__ */ _decodeCanonical(rem === 0 ? body : body + (rem === 2 ? "==" : "="), body.length);
210
+ }
211
+ /* @__NO_SIDE_EFFECTS__ */
212
+ function base64Stringify(data, options) {
213
+ const alphabet = options?.alphabet ?? "base64";
214
+ const padding = options?.padding ?? alphabet !== "base64url";
215
+ return /* @__PURE__ */ _encodeBase64(/* @__PURE__ */ toBytes(data, "Base64.stringify"), alphabet, padding);
216
+ }
217
+ /* @__NO_SIDE_EFFECTS__ */
218
+ function base64Parse(input, options) {
219
+ _assertData(input, "Base64.parse");
220
+ const { text, wantString } = /* @__PURE__ */ _parsePrep(input, options);
221
+ if (!text) return wantString ? "" : /* @__PURE__ */ new Uint8Array(0);
222
+ const alphabet = options?.alphabet ?? "base64";
223
+ const loose = options?.loose ?? false;
224
+ return /* @__PURE__ */ _parseFinalize(/* @__PURE__ */ _decodeBase64(text, alphabet, loose, "Base64.parse", options?.padding), wantString, !loose, "Base64.parse");
225
+ }
226
+ /* @__NO_SIDE_EFFECTS__ */
227
+ function showValue(value) {
228
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
229
+ if (typeof value === "string") return JSON.stringify(value);
230
+ return /* @__PURE__ */ describeValue(value);
231
+ }
232
+ function assertInteger(source, name, value, min, max = Number.MAX_SAFE_INTEGER) {
233
+ if (Number.isSafeInteger(value) && value >= min && value <= max) return;
234
+ throw new UnsecureError("OUT_OF_RANGE", `${source}: ${name} must be ${max === Number.MAX_SAFE_INTEGER ? `an integer >= ${min}` : `an integer between ${min} and ${max}`}, got ${/* @__PURE__ */ showValue(value)}.`);
235
+ }
236
+ const SHARED_POOL_BYTES = 4096;
237
+ const _MAX_FILL = 65536;
238
+ /* @__NO_SIDE_EFFECTS__ */
239
+ function createEntropyPool(size) {
240
+ let bytes;
241
+ let words;
242
+ let offset = size;
243
+ function refill() {
244
+ if (bytes === void 0) {
245
+ const buffer = new ArrayBuffer(size);
246
+ bytes = new Uint8Array(buffer);
247
+ words = new Uint32Array(buffer);
248
+ }
249
+ crypto.getRandomValues(bytes);
250
+ offset = 0;
251
+ }
252
+ function nextUint32() {
253
+ offset = offset + 3 & -4;
254
+ if (offset >= size) refill();
255
+ const value = words[offset >>> 2];
256
+ offset += 4;
257
+ return value;
133
258
  }
134
- return decodeToString ? textDecoder.decode(decoded) : decoded;
259
+ function fill(target) {
260
+ const length = target.length;
261
+ if (length === 0) return target;
262
+ if (length > 64) {
263
+ if (length <= _MAX_FILL) crypto.getRandomValues(target);
264
+ else for (let start = 0; start < length; start += _MAX_FILL) crypto.getRandomValues(target.subarray(start, Math.min(start + _MAX_FILL, length)));
265
+ return target;
266
+ }
267
+ if (offset + length > size) refill();
268
+ const slot = bytes.subarray(offset, offset + length);
269
+ target.set(slot);
270
+ slot.fill(0);
271
+ offset += length;
272
+ return target;
273
+ }
274
+ function reset(now = false) {
275
+ bytes?.fill(0);
276
+ bytes = words = void 0;
277
+ offset = size;
278
+ if (now) refill();
279
+ }
280
+ _onSnapshotRestore(reset);
281
+ return {
282
+ nextUint32,
283
+ fill,
284
+ reset
285
+ };
135
286
  }
136
- !_hasBuffer && Uint8Array.prototype.toHex;
137
- !_hasBuffer && Uint8Array.fromHex;
138
- const textEncoder = /* @__PURE__ */ new TextEncoder();
139
- const textDecoder = /* @__PURE__ */ new TextDecoder();
287
+ const sharedPool = /* @__PURE__ */ createEntropyPool(SHARED_POOL_BYTES);
288
+ function _onSnapshotRestore(callback) {
289
+ try {
290
+ const proc = globalThis.process;
291
+ if (typeof proc?.getBuiltinModule !== "function") return;
292
+ const snapshot = proc.getBuiltinModule("node:v8")?.startupSnapshot;
293
+ if (snapshot?.isBuildingSnapshot()) snapshot.addDeserializeCallback(callback);
294
+ } catch {}
295
+ }
296
+ const MAX_RANDOM_BYTES = 2 ** 31 - 1;
297
+ /* @__NO_SIDE_EFFECTS__ */
140
298
  function secureRandomBytes(length) {
141
- if (!Number.isInteger(length) || length < 0) throw new RangeError("length must be a non-negative integer.");
142
- const bytes = new Uint8Array(length);
143
- if (length > 0) for (let offset = 0; offset < length; offset += 65536) {
144
- const chunk = bytes.subarray(offset, Math.min(offset + 65536, length));
145
- crypto.getRandomValues(chunk);
299
+ assertInteger("secureRandomBytes", "length", length, 0, MAX_RANDOM_BYTES);
300
+ return sharedPool.fill(new Uint8Array(length));
301
+ }
302
+ /* @__NO_SIDE_EFFECTS__ */
303
+ function safeJsonParse(json) {
304
+ let parsed;
305
+ try {
306
+ parsed = JSON.parse(json);
307
+ } catch (error) {
308
+ throw new UnsecureError("MALFORMED", `safeJsonParse: ${error.message}`, { cause: error });
146
309
  }
147
- return bytes;
310
+ if (parsed === null || typeof parsed !== "object") return parsed;
311
+ _sanitizeInPlace(parsed, /* @__PURE__ */ new WeakSet());
312
+ return parsed;
313
+ }
314
+ function sanitizeObject(obj) {
315
+ if (!obj || typeof obj !== "object") return obj;
316
+ _sanitizeInPlace(obj, /* @__PURE__ */ new WeakSet());
317
+ return obj;
318
+ }
319
+ /* @__NO_SIDE_EFFECTS__ */
320
+ function sanitizeObjectCopy(obj) {
321
+ if (!/* @__PURE__ */ _isCopyable(obj)) return obj;
322
+ return _sanitizeCopy(obj, /* @__PURE__ */ new WeakMap());
323
+ }
324
+ /* @__NO_SIDE_EFFECTS__ */
325
+ function _isDangerousKey(key) {
326
+ return key === "__proto__" || key === "prototype" || key === "constructor";
327
+ }
328
+ function _sanitizeInPlace(root, seen) {
329
+ seen.add(root);
330
+ const stack = [root];
331
+ while (stack.length > 0) {
332
+ const current = stack.pop();
333
+ if (Array.isArray(current)) {
334
+ for (let i = 0; i < current.length; i++) {
335
+ const descriptor = Object.getOwnPropertyDescriptor(current, i);
336
+ if (descriptor === void 0 || !("value" in descriptor)) continue;
337
+ const v = descriptor.value;
338
+ if (v !== null && typeof v === "object" && !seen.has(v)) {
339
+ seen.add(v);
340
+ stack.push(v);
341
+ }
342
+ }
343
+ continue;
344
+ }
345
+ const record = current;
346
+ const keys = Object.getOwnPropertyNames(record);
347
+ for (let i = 0; i < keys.length; i++) {
348
+ const key = keys[i];
349
+ if (/* @__PURE__ */ _isDangerousKey(key)) {
350
+ if (!Reflect.deleteProperty(record, key)) throw new UnsecureError("FROZEN", `sanitizeObject: cannot remove "${key}" from a frozen object; use sanitizeObjectCopy().`);
351
+ continue;
352
+ }
353
+ const descriptor = Object.getOwnPropertyDescriptor(record, key);
354
+ if (descriptor === void 0 || !("value" in descriptor)) continue;
355
+ const v = descriptor.value;
356
+ if (v !== null && typeof v === "object" && !seen.has(v)) {
357
+ seen.add(v);
358
+ stack.push(v);
359
+ }
360
+ }
361
+ }
362
+ }
363
+ /* @__NO_SIDE_EFFECTS__ */
364
+ function _isPlainObject(value) {
365
+ const proto = Object.getPrototypeOf(value);
366
+ return proto === Object.prototype || proto === null;
367
+ }
368
+ /* @__NO_SIDE_EFFECTS__ */
369
+ function _isCopyable(value) {
370
+ return value !== null && typeof value === "object" && (Array.isArray(value) || /* @__PURE__ */ _isPlainObject(value));
371
+ }
372
+ function _sanitizeCopy(root, seen) {
373
+ const rootTarget = Array.isArray(root) ? [] : {};
374
+ seen.set(root, rootTarget);
375
+ const stack = [{
376
+ source: root,
377
+ target: rootTarget
378
+ }];
379
+ while (stack.length > 0) {
380
+ const { source, target } = stack.pop();
381
+ if (Array.isArray(source)) {
382
+ const out = target;
383
+ out.length = source.length;
384
+ for (let i = 0; i < source.length; i++) {
385
+ const descriptor = Object.getOwnPropertyDescriptor(source, i);
386
+ if (descriptor === void 0 || !("value" in descriptor)) continue;
387
+ out[i] = _copyValue(descriptor.value, seen, stack);
388
+ }
389
+ continue;
390
+ }
391
+ const out = target;
392
+ const record = source;
393
+ const keys = Object.keys(record);
394
+ for (let i = 0; i < keys.length; i++) {
395
+ const key = keys[i];
396
+ if (/* @__PURE__ */ _isDangerousKey(key)) continue;
397
+ const descriptor = Object.getOwnPropertyDescriptor(record, key);
398
+ if (descriptor === void 0 || !("value" in descriptor)) continue;
399
+ out[key] = _copyValue(descriptor.value, seen, stack);
400
+ }
401
+ }
402
+ return rootTarget;
403
+ }
404
+ function _copyValue(value, seen, stack) {
405
+ if (!/* @__PURE__ */ _isCopyable(value)) return value;
406
+ const existing = seen.get(value);
407
+ if (existing !== void 0) return existing;
408
+ const target = Array.isArray(value) ? [] : {};
409
+ seen.set(value, target);
410
+ stack.push({
411
+ source: value,
412
+ target
413
+ });
414
+ return target;
148
415
  }
149
- export { base64Decode, base64Encode, base64UrlDecode, base64UrlEncode, safeJsonParse, sanitizeObject, sanitizeObjectCopy, secureRandomBytes, textDecoder, textEncoder };
416
+ export { UnsecureError, base64Parse, base64Stringify, safeJsonParse, sanitizeObject, sanitizeObjectCopy, secureRandomBytes, textDecoder, textEncoder };