es-toolkit 1.52.0-dev.2095 → 1.52.0-dev.2096

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 (42) hide show
  1. package/dist/browser.global.js +4 -4
  2. package/dist/index.d.mts +2 -1
  3. package/dist/index.d.ts +2 -1
  4. package/dist/index.js +2 -0
  5. package/dist/index.mjs +2 -1
  6. package/dist/util/hash/browser.d.mts +26 -0
  7. package/dist/util/hash/browser.d.ts +26 -0
  8. package/dist/util/hash/browser.js +31 -0
  9. package/dist/util/hash/browser.mjs +30 -0
  10. package/dist/util/hash/node.d.mts +26 -0
  11. package/dist/util/hash/node.d.ts +26 -0
  12. package/dist/util/hash/node.js +494 -0
  13. package/dist/util/hash/node.mjs +493 -0
  14. package/dist/util/hash/sha256.js +158 -0
  15. package/dist/util/hash/sha256.mjs +158 -0
  16. package/dist/util/index.d.mts +2 -1
  17. package/dist/util/index.d.ts +2 -1
  18. package/dist/util/index.js +2 -0
  19. package/dist/util/index.mjs +2 -1
  20. package/dist/util/serialize/compareValues.js +23 -0
  21. package/dist/util/serialize/compareValues.mjs +23 -0
  22. package/dist/util/serialize/serialize.d.mts +44 -0
  23. package/dist/util/serialize/serialize.d.ts +44 -0
  24. package/dist/util/serialize/serialize.js +64 -0
  25. package/dist/util/serialize/serialize.mjs +63 -0
  26. package/dist/util/serialize/serializeBigInt.js +15 -0
  27. package/dist/util/serialize/serializeBigInt.mjs +15 -0
  28. package/dist/util/serialize/serializeFunction.js +26 -0
  29. package/dist/util/serialize/serializeFunction.mjs +26 -0
  30. package/dist/util/serialize/serializeNumber.js +21 -0
  31. package/dist/util/serialize/serializeNumber.mjs +21 -0
  32. package/dist/util/serialize/serializeObject.js +85 -0
  33. package/dist/util/serialize/serializeObject.mjs +85 -0
  34. package/dist/util/serialize/serializePlainObject.js +31 -0
  35. package/dist/util/serialize/serializePlainObject.mjs +31 -0
  36. package/dist/util/serialize/serializeString.js +18 -0
  37. package/dist/util/serialize/serializeString.mjs +18 -0
  38. package/dist/util/serialize/serializeSymbol.js +23 -0
  39. package/dist/util/serialize/serializeSymbol.mjs +23 -0
  40. package/package.json +47 -1
  41. package/util/hash.d.ts +1 -0
  42. package/util/hash.js +1 -0
@@ -0,0 +1,493 @@
1
+ import { hash as hash$1 } from "node:crypto";
2
+ //#region src/util/serialize/serializeBigInt.ts
3
+ /**
4
+ * Serializes a bigint into a string with an `n` suffix, like a bigint literal.
5
+ *
6
+ * @param value - The bigint to serialize.
7
+ * @returns The serialized string.
8
+ *
9
+ * @example
10
+ * serializeBigInt(123n); // "123n"
11
+ */
12
+ function serializeBigInt(value) {
13
+ return `${value}n`;
14
+ }
15
+ //#endregion
16
+ //#region src/util/serialize/serializeFunction.ts
17
+ /**
18
+ * Serializes a function into a string of the form `name:source`.
19
+ *
20
+ * Native functions have no meaningful source, so they are serialized as
21
+ * `name:[native]`. For other functions, newlines and their surrounding
22
+ * whitespace are collapsed so that formatting differences do not change
23
+ * the output.
24
+ *
25
+ * @param value - The function to serialize.
26
+ * @returns The serialized string.
27
+ *
28
+ * @example
29
+ * function sum(a, b) {
30
+ * return a + b;
31
+ * }
32
+ * serializeFunction(sum); // "sum:function sum(a, b) {return a + b;}"
33
+ * serializeFunction(Math.max); // "max:[native]"
34
+ */
35
+ function serializeFunction(value) {
36
+ const source = Function.prototype.toString.call(value);
37
+ if (source.endsWith("[native code] }")) return `${value.name}:[native]`;
38
+ return `${value.name}:${source.replace(/\s*\n\s*/g, "")}`;
39
+ }
40
+ //#endregion
41
+ //#region src/util/serialize/serializeNumber.ts
42
+ /**
43
+ * Serializes a number into a string.
44
+ *
45
+ * `-0` is serialized as `0`, and `NaN` and `Infinity` are serialized
46
+ * as their string representations.
47
+ *
48
+ * @param value - The number to serialize.
49
+ * @returns The serialized string.
50
+ *
51
+ * @example
52
+ * serializeNumber(1); // "1"
53
+ * serializeNumber(-0); // "0"
54
+ * serializeNumber(NaN); // "NaN"
55
+ * serializeNumber(Infinity); // "Infinity"
56
+ */
57
+ function serializeNumber(value) {
58
+ return String(value);
59
+ }
60
+ //#endregion
61
+ //#region src/util/serialize/compareValues.ts
62
+ /**
63
+ * Compares two values for sorting `Set` values and `Map` keys.
64
+ *
65
+ * Numbers are compared numerically and strings by code unit. Any other
66
+ * combination is compared by the code unit order of the serialized values.
67
+ *
68
+ * @param a - The first value to compare.
69
+ * @param b - The second value to compare.
70
+ * @param refs - The circular reference context shared with the surrounding serialization.
71
+ * @returns A negative number if `a` sorts before `b`, a positive number if
72
+ * `a` sorts after `b`, and `0` if they are equal.
73
+ */
74
+ function compareValues(a, b, refs) {
75
+ if (typeof a === "number" && typeof b === "number") return a - b;
76
+ const serializedA = typeof a === "string" && typeof b === "string" ? a : serializeValue(a, refs);
77
+ const serializedB = typeof a === "string" && typeof b === "string" ? b : serializeValue(b, refs);
78
+ if (serializedA === serializedB) return 0;
79
+ return serializedA < serializedB ? -1 : 1;
80
+ }
81
+ //#endregion
82
+ //#region src/util/serialize/serializeString.ts
83
+ /**
84
+ * Serializes a string into a single-quoted string literal.
85
+ *
86
+ * The string is not escaped; the output is intended for hashing and
87
+ * change detection, not for parsing or re-evaluation.
88
+ *
89
+ * @param value - The string to serialize.
90
+ * @returns The serialized string.
91
+ *
92
+ * @example
93
+ * serializeString('abc'); // "'abc'"
94
+ */
95
+ function serializeString(value) {
96
+ return `'${value}'`;
97
+ }
98
+ //#endregion
99
+ //#region src/util/serialize/serializePlainObject.ts
100
+ /**
101
+ * Serializes the own enumerable string-keyed properties of an object
102
+ * into a `{'key':value}` string.
103
+ *
104
+ * Keys are sorted by code unit so that the output does not depend on
105
+ * property insertion order, and always quoted so that a key containing
106
+ * `:` or `,` cannot be confused with the surrounding structure. Symbol
107
+ * keys and non-enumerable properties are ignored.
108
+ *
109
+ * @param object - The object to serialize.
110
+ * @param refs - The circular reference context shared with the surrounding serialization.
111
+ * @returns The serialized string.
112
+ *
113
+ * @example
114
+ * serializePlainObject({ b: 2, a: 1 }, new Map()); // "{'a':1,'b':2}"
115
+ */
116
+ function serializePlainObject(object, refs) {
117
+ const keys = Object.keys(object).sort();
118
+ let result = "{";
119
+ for (let i = 0; i < keys.length; i++) {
120
+ const key = keys[i];
121
+ if (i > 0) result += ",";
122
+ result += `${serializeString(key)}:${serializeValue(object[key], refs)}`;
123
+ }
124
+ return result + "}";
125
+ }
126
+ //#endregion
127
+ //#region src/predicate/isArrayBuffer.ts
128
+ /**
129
+ * Checks if a given value is `ArrayBuffer`.
130
+ *
131
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `ArrayBuffer`.
132
+ *
133
+ * @param value The value to check if it is a `ArrayBuffer`.
134
+ * @returns Returns `true` if `value` is a `ArrayBuffer`, else `false`.
135
+ *
136
+ * @example
137
+ * const value1 = new ArrayBuffer();
138
+ * const value2 = new Array();
139
+ * const value3 = new Map();
140
+ *
141
+ * console.log(isArrayBuffer(value1)); // true
142
+ * console.log(isArrayBuffer(value2)); // false
143
+ * console.log(isArrayBuffer(value3)); // false
144
+ */
145
+ function isArrayBuffer(value) {
146
+ return value instanceof ArrayBuffer;
147
+ }
148
+ //#endregion
149
+ //#region src/predicate/isDate.ts
150
+ /**
151
+ * Checks if `value` is a Date object.
152
+ *
153
+ * @param value The value to check.
154
+ * @returns Returns `true` if `value` is a Date object, `false` otherwise.
155
+ *
156
+ * @example
157
+ * const value1 = new Date();
158
+ * const value2 = '2024-01-01';
159
+ *
160
+ * console.log(isDate(value1)); // true
161
+ * console.log(isDate(value2)); // false
162
+ */
163
+ function isDate(value) {
164
+ return value instanceof Date;
165
+ }
166
+ //#endregion
167
+ //#region src/predicate/isError.ts
168
+ /**
169
+ * Checks if `value` is an Error object.
170
+ *
171
+ * @param value The value to check.
172
+ * @returns Returns `true` if `value` is an Error object, `false` otherwise.
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * console.log(isError(new Error())); // true
177
+ * console.log(isError('Error')); // false
178
+ * console.log(isError({ name: 'Error', message: '' })); // false
179
+ * ```
180
+ */
181
+ function isError(value) {
182
+ return value instanceof Error;
183
+ }
184
+ //#endregion
185
+ //#region src/predicate/isMap.ts
186
+ /**
187
+ * Checks if a given value is `Map`.
188
+ *
189
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `Map`.
190
+ *
191
+ * @param value The value to check if it is a `Map`.
192
+ * @returns Returns `true` if `value` is a `Map`, else `false`.
193
+ *
194
+ * @example
195
+ * const value1 = new Map();
196
+ * const value2 = new Set();
197
+ * const value3 = new WeakMap();
198
+ *
199
+ * console.log(isMap(value1)); // true
200
+ * console.log(isMap(value2)); // false
201
+ * console.log(isMap(value3)); // false
202
+ */
203
+ function isMap(value) {
204
+ return value instanceof Map;
205
+ }
206
+ //#endregion
207
+ //#region src/predicate/isPlainObject.ts
208
+ /**
209
+ * Checks if a given value is a plain object.
210
+ *
211
+ * @param value - The value to check.
212
+ * @returns True if the value is a plain object, otherwise false.
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * // ✅👇 True
217
+ *
218
+ * isPlainObject({ }); // ✅
219
+ * isPlainObject({ key: 'value' }); // ✅
220
+ * isPlainObject({ key: new Date() }); // ✅
221
+ * isPlainObject(new Object()); // ✅
222
+ * isPlainObject(Object.create(null)); // ✅
223
+ * isPlainObject({ nested: { key: true} }); // ✅
224
+ * isPlainObject(new Proxy({}, {})); // ✅
225
+ * isPlainObject({ [Symbol('tag')]: 'A' }); // ✅
226
+ *
227
+ * // ✅👇 (cross-realms, node context, workers, ...)
228
+ * const runInNewContext = await import('node:vm').then(
229
+ * (mod) => mod.runInNewContext
230
+ * );
231
+ * isPlainObject(runInNewContext('({})')); // ✅
232
+ *
233
+ * // ❌👇 False
234
+ *
235
+ * class Test { };
236
+ * isPlainObject(new Test()) // ❌
237
+ * isPlainObject(10); // ❌
238
+ * isPlainObject(null); // ❌
239
+ * isPlainObject('hello'); // ❌
240
+ * isPlainObject([]); // ❌
241
+ * isPlainObject(new Date()); // ❌
242
+ * isPlainObject(new Uint8Array([1])); // ❌
243
+ * isPlainObject(Buffer.from('ABC')); // ❌
244
+ * isPlainObject(Promise.resolve({})); // ❌
245
+ * isPlainObject(Object.create({})); // ❌
246
+ * isPlainObject(new (class Cls {})); // ❌
247
+ * isPlainObject(globalThis); // ❌,
248
+ * ```
249
+ */
250
+ function isPlainObject(value) {
251
+ if (!value || typeof value !== "object") return false;
252
+ const proto = Object.getPrototypeOf(value);
253
+ if (!(proto === null || proto === Object.prototype || Object.getPrototypeOf(proto) === null)) return false;
254
+ return Object.prototype.toString.call(value) === "[object Object]";
255
+ }
256
+ //#endregion
257
+ //#region src/predicate/isRegExp.ts
258
+ /**
259
+ * Checks if `value` is a RegExp.
260
+ *
261
+ * @param value The value to check.
262
+ * @returns Returns `true` if `value` is a RegExp, `false` otherwise.
263
+ *
264
+ * @example
265
+ * const value1 = /abc/;
266
+ * const value2 = '/abc/';
267
+ *
268
+ * console.log(isRegExp(value1)); // true
269
+ * console.log(isRegExp(value2)); // false
270
+ */
271
+ function isRegExp(value) {
272
+ return value instanceof RegExp;
273
+ }
274
+ //#endregion
275
+ //#region src/predicate/isSet.ts
276
+ /**
277
+ * Checks if a given value is `Set`.
278
+ *
279
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `Set`.
280
+ *
281
+ * @param value The value to check if it is a `Set`.
282
+ * @returns Returns `true` if `value` is a `Set`, else `false`.
283
+ *
284
+ * @example
285
+ * const value1 = new Set();
286
+ * const value2 = new Map();
287
+ * const value3 = new WeakSet();
288
+ *
289
+ * console.log(isSet(value1)); // true
290
+ * console.log(isSet(value2)); // false
291
+ * console.log(isSet(value3)); // false
292
+ */
293
+ function isSet(value) {
294
+ return value instanceof Set;
295
+ }
296
+ //#endregion
297
+ //#region src/predicate/isTypedArray.ts
298
+ /**
299
+ * Checks if a value is a TypedArray.
300
+ * @param x The value to check.
301
+ * @returns Returns true if `x` is a TypedArray, false otherwise.
302
+ *
303
+ * @example
304
+ * const arr = new Uint8Array([1, 2, 3]);
305
+ * isTypedArray(arr); // true
306
+ *
307
+ * const regularArray = [1, 2, 3];
308
+ * isTypedArray(regularArray); // false
309
+ *
310
+ * const buffer = new ArrayBuffer(16);
311
+ * isTypedArray(buffer); // false
312
+ */
313
+ function isTypedArray(x) {
314
+ return ArrayBuffer.isView(x) && !(x instanceof DataView);
315
+ }
316
+ //#endregion
317
+ //#region src/util/serialize/serializeObject.ts
318
+ /**
319
+ * Serializes an object, handling circular references and repeated references.
320
+ *
321
+ * The first time an object is visited, it is registered as `#ref{n}` where `n`
322
+ * is the visit order; if the object is reached again while it is still being
323
+ * serialized, the back-reference is emitted instead. Once completed, the
324
+ * serialized string is memoized so that repeated references serialize
325
+ * in constant time.
326
+ *
327
+ * @param value - The object to serialize, or `null`.
328
+ * @param refs - The circular reference context shared across one serialization.
329
+ * @returns The serialized string.
330
+ * @throws {TypeError} If the object cannot be serialized.
331
+ */
332
+ function serializeObject(value, refs) {
333
+ if (value === null) return "null";
334
+ const cached = refs.get(value);
335
+ if (cached !== void 0) return cached;
336
+ refs.set(value, `#ref${refs.size}`);
337
+ const result = serializeObjectImpl(value, refs);
338
+ refs.set(value, result);
339
+ return result;
340
+ }
341
+ function serializeObjectImpl(value, refs) {
342
+ if (Array.isArray(value)) return serializeArray(value, refs);
343
+ if (isPlainObject(value)) return serializePlainObject(value, refs);
344
+ if (isDate(value)) return Number.isNaN(value.getTime()) ? "Date(null)" : `Date(${serializeString(value.toISOString())})`;
345
+ if (isRegExp(value)) return `RegExp(${value.toString()})`;
346
+ if (isSet(value)) return `Set${serializeArray(Array.from(value).sort((a, b) => compareValues(a, b, refs)), refs)}`;
347
+ if (isMap(value)) return serializeEntries("Map", value.entries(), refs);
348
+ if (isTypedArray(value)) {
349
+ const name = value[Symbol.toStringTag];
350
+ if (name === "BigInt64Array" || name === "BigUint64Array") return `${name}[${value.join("n,")}${value.length > 0 ? "n" : ""}]`;
351
+ return `${name}[${value.join(",")}]`;
352
+ }
353
+ if (isArrayBuffer(value)) return `ArrayBuffer[${new Uint8Array(value).join(",")}]`;
354
+ if (isError(value)) return `Error(${value.name}: ${serializeString(value.message)})`;
355
+ const tag = Object.prototype.toString.call(value).slice(8, -1);
356
+ if (tag === "Object") return serializeClassInstance(value, refs);
357
+ if (typeof value.entries === "function") return serializeEntries(tag, value.entries(), refs);
358
+ throw new TypeError(`Cannot serialize ${tag}`);
359
+ }
360
+ function serializeArray(array, refs) {
361
+ let result = "[";
362
+ for (let i = 0; i < array.length; i++) {
363
+ if (i > 0) result += ",";
364
+ result += serializeValue(array[i], refs);
365
+ }
366
+ return result + "]";
367
+ }
368
+ function serializeEntries(tag, entries, refs) {
369
+ const sortedEntries = Array.from(entries).sort((a, b) => compareValues(a[0], b[0], refs));
370
+ let result = `${tag}{`;
371
+ for (let i = 0; i < sortedEntries.length; i++) {
372
+ const [key, value] = sortedEntries[i];
373
+ if (i > 0) result += ",";
374
+ result += `${serializeValue(key, refs)}:${serializeValue(value, refs)}`;
375
+ }
376
+ return result + "}";
377
+ }
378
+ function serializeClassInstance(value, refs) {
379
+ const constructor = value.constructor;
380
+ const name = constructor === Object || constructor === void 0 ? "" : constructor.name;
381
+ if ("toJSON" in value && typeof value.toJSON === "function") {
382
+ const json = value.toJSON();
383
+ if (json !== null && typeof json === "object") return name + serializeObject(json, refs);
384
+ return `${name}(${serializeValue(json, refs)})`;
385
+ }
386
+ return name + serializePlainObject(value, refs);
387
+ }
388
+ //#endregion
389
+ //#region src/util/serialize/serializeSymbol.ts
390
+ /**
391
+ * Serializes a symbol into a string using its description.
392
+ *
393
+ * The description is quoted like any other string, so a symbol without a
394
+ * description (`Symbol()`) is distinguishable from one with an empty
395
+ * description (`Symbol('')`). Note that two different symbols with the same
396
+ * description still serialize to the same string, since a symbol's identity
397
+ * cannot be captured in a string.
398
+ *
399
+ * @param value - The symbol to serialize.
400
+ * @returns The serialized string.
401
+ *
402
+ * @example
403
+ * serializeSymbol(Symbol('test')); // "Symbol('test')"
404
+ * serializeSymbol(Symbol()); // "Symbol()"
405
+ */
406
+ function serializeSymbol(value) {
407
+ return value.description === void 0 ? "Symbol()" : `Symbol(${serializeString(value.description)})`;
408
+ }
409
+ //#endregion
410
+ //#region src/util/serialize/serialize.ts
411
+ /**
412
+ * Serializes any value into a stable string.
413
+ *
414
+ * Two values with the same structure always serialize to the same string,
415
+ * regardless of key insertion order, so the output is suitable for hashing,
416
+ * cache keys, and change detection. It is not designed for security purposes;
417
+ * intentional collisions can be crafted from user input.
418
+ *
419
+ * Plain object keys, `Map` keys, and `Set` values are sorted, so the output
420
+ * does not depend on insertion order. String keys are always quoted, so a
421
+ * string key never collides with a key of another type. Circular references
422
+ * are serialized as `#ref{n}` back-references, where `n` is the order in
423
+ * which the object was first visited.
424
+ *
425
+ * Objects that cannot be serialized meaningfully, such as `Promise`, `WeakMap`,
426
+ * or `Blob`, throw a `TypeError`.
427
+ *
428
+ * @param value - The value to serialize.
429
+ * @returns The serialized string.
430
+ * @throws {TypeError} If the value contains an object that cannot be serialized.
431
+ *
432
+ * @example
433
+ * serialize({ b: 2, a: 1 }); // "{'a':1,'b':2}"
434
+ * serialize([1, 2n, 'a', { k: 1 }]); // "[1,2n,'a',{'k':1}]"
435
+ * serialize(new Set([3, 1, 2])); // "Set[1,2,3]"
436
+ * serialize(new Date(0)); // "Date('1970-01-01T00:00:00.000Z')"
437
+ *
438
+ * const obj = {};
439
+ * obj.self = obj;
440
+ * serialize(obj); // "{'self':#ref0}"
441
+ */
442
+ function serialize(value) {
443
+ return serializeValue(value, /* @__PURE__ */ new Map());
444
+ }
445
+ /**
446
+ * Serializes a value with a shared circular reference context.
447
+ *
448
+ * @param value - The value to serialize.
449
+ * @param refs - Objects that are being serialized or have been serialized,
450
+ * mapped to their back-reference placeholder or completed serialization.
451
+ * @returns The serialized string.
452
+ */
453
+ function serializeValue(value, refs) {
454
+ switch (typeof value) {
455
+ case "string": return serializeString(value);
456
+ case "number": return serializeNumber(value);
457
+ case "bigint": return serializeBigInt(value);
458
+ case "symbol": return serializeSymbol(value);
459
+ case "function": return serializeFunction(value);
460
+ case "object": return serializeObject(value, refs);
461
+ case "boolean": return String(value);
462
+ case "undefined": return "undefined";
463
+ }
464
+ }
465
+ //#endregion
466
+ //#region src/util/hash/node.ts
467
+ /**
468
+ * Hashes any value into a stable 43-character string.
469
+ *
470
+ * The value is serialized with `serialize`, so two values with the same
471
+ * structure always hash to the same string regardless of key insertion
472
+ * order, and then digested with SHA-256 and encoded in Base64URL format.
473
+ *
474
+ * The hash is stable across platforms, but it is not designed for security
475
+ * purposes; intentional collisions can be crafted from user input.
476
+ *
477
+ * This entry uses the native `node:crypto` implementation and requires
478
+ * Node.js 20.12 or later; in browsers, a pure JavaScript implementation
479
+ * with identical output is used instead.
480
+ *
481
+ * @param value - The value to hash.
482
+ * @returns The Base64URL-encoded SHA-256 hash of the serialized value.
483
+ * @throws {TypeError} If the value contains an object that cannot be serialized.
484
+ *
485
+ * @example
486
+ * hash({ b: 2, a: 1 }) === hash({ a: 1, b: 2 }); // true
487
+ * hash([1, 2, 3]); // "phXuruId5Red4IDejDBSyNqQEThAa6ccOMAyhF99VPQ" (43 characters)
488
+ */
489
+ function hash(value) {
490
+ return hash$1("sha256", serialize(value), "base64url");
491
+ }
492
+ //#endregion
493
+ export { hash };
@@ -0,0 +1,158 @@
1
+ //#region src/util/hash/sha256.ts
2
+ const K = new Int32Array([
3
+ 1116352408,
4
+ 1899447441,
5
+ 3049323471,
6
+ 3921009573,
7
+ 961987163,
8
+ 1508970993,
9
+ 2453635748,
10
+ 2870763221,
11
+ 3624381080,
12
+ 310598401,
13
+ 607225278,
14
+ 1426881987,
15
+ 1925078388,
16
+ 2162078206,
17
+ 2614888103,
18
+ 3248222580,
19
+ 3835390401,
20
+ 4022224774,
21
+ 264347078,
22
+ 604807628,
23
+ 770255983,
24
+ 1249150122,
25
+ 1555081692,
26
+ 1996064986,
27
+ 2554220882,
28
+ 2821834349,
29
+ 2952996808,
30
+ 3210313671,
31
+ 3336571891,
32
+ 3584528711,
33
+ 113926993,
34
+ 338241895,
35
+ 666307205,
36
+ 773529912,
37
+ 1294757372,
38
+ 1396182291,
39
+ 1695183700,
40
+ 1986661051,
41
+ 2177026350,
42
+ 2456956037,
43
+ 2730485921,
44
+ 2820302411,
45
+ 3259730800,
46
+ 3345764771,
47
+ 3516065817,
48
+ 3600352804,
49
+ 4094571909,
50
+ 275423344,
51
+ 430227734,
52
+ 506948616,
53
+ 659060556,
54
+ 883997877,
55
+ 958139571,
56
+ 1322822218,
57
+ 1537002063,
58
+ 1747873779,
59
+ 1955562222,
60
+ 2024104815,
61
+ 2227730452,
62
+ 2361852424,
63
+ 2428436474,
64
+ 2756734187,
65
+ 3204031479,
66
+ 3329325298
67
+ ]);
68
+ const BASE64_URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
69
+ /**
70
+ * Computes the SHA-256 digest of a string and encodes it in Base64URL
71
+ * format without padding.
72
+ *
73
+ * The output is byte-identical to
74
+ * `crypto.hash('sha256', data, 'base64url')` in Node.js.
75
+ *
76
+ * @param data - The string to hash. Encoded as UTF-8 before hashing.
77
+ * @returns The 43-character Base64URL-encoded digest.
78
+ */
79
+ function sha256(data) {
80
+ const bytes = new TextEncoder().encode(data);
81
+ const byteLength = bytes.length;
82
+ const paddedLength = ((byteLength + 8 >> 6) + 1) * 64;
83
+ const padded = new Uint8Array(paddedLength);
84
+ padded.set(bytes);
85
+ padded[byteLength] = 128;
86
+ const view = new DataView(padded.buffer);
87
+ view.setUint32(paddedLength - 8, Math.floor(byteLength / 536870912));
88
+ view.setUint32(paddedLength - 4, byteLength << 3 >>> 0);
89
+ let h0 = 1779033703;
90
+ let h1 = -1150833019;
91
+ let h2 = 1013904242;
92
+ let h3 = -1521486534;
93
+ let h4 = 1359893119;
94
+ let h5 = -1694144372;
95
+ let h6 = 528734635;
96
+ let h7 = 1541459225;
97
+ const w = new Int32Array(64);
98
+ for (let offset = 0; offset < paddedLength; offset += 64) {
99
+ for (let i = 0; i < 16; i++) w[i] = view.getUint32(offset + i * 4) | 0;
100
+ for (let i = 16; i < 64; i++) {
101
+ const x = w[i - 15];
102
+ const y = w[i - 2];
103
+ const sigma0 = (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ x >>> 3 | 0;
104
+ const sigma1 = (y >>> 17 | y << 15) ^ (y >>> 19 | y << 13) ^ y >>> 10 | 0;
105
+ w[i] = w[i - 16] + sigma0 + w[i - 7] + sigma1 | 0;
106
+ }
107
+ let a = h0;
108
+ let b = h1;
109
+ let c = h2;
110
+ let d = h3;
111
+ let e = h4;
112
+ let f = h5;
113
+ let g = h6;
114
+ let h = h7;
115
+ for (let i = 0; i < 64; i++) {
116
+ const bigSigma1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7);
117
+ const ch = e & f ^ ~e & g;
118
+ const t1 = h + bigSigma1 + ch + K[i] + w[i] | 0;
119
+ const t2 = ((a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10)) + (a & b ^ a & c ^ b & c) | 0;
120
+ h = g;
121
+ g = f;
122
+ f = e;
123
+ e = d + t1 | 0;
124
+ d = c;
125
+ c = b;
126
+ b = a;
127
+ a = t1 + t2 | 0;
128
+ }
129
+ h0 = h0 + a | 0;
130
+ h1 = h1 + b | 0;
131
+ h2 = h2 + c | 0;
132
+ h3 = h3 + d | 0;
133
+ h4 = h4 + e | 0;
134
+ h5 = h5 + f | 0;
135
+ h6 = h6 + g | 0;
136
+ h7 = h7 + h | 0;
137
+ }
138
+ const digest = new Uint8Array(32);
139
+ const digestView = new DataView(digest.buffer);
140
+ digestView.setInt32(0, h0);
141
+ digestView.setInt32(4, h1);
142
+ digestView.setInt32(8, h2);
143
+ digestView.setInt32(12, h3);
144
+ digestView.setInt32(16, h4);
145
+ digestView.setInt32(20, h5);
146
+ digestView.setInt32(24, h6);
147
+ digestView.setInt32(28, h7);
148
+ let result = "";
149
+ for (let i = 0; i < 30; i += 3) {
150
+ const n = digest[i] << 16 | digest[i + 1] << 8 | digest[i + 2];
151
+ result += BASE64_URL_ALPHABET[n >>> 18 & 63] + BASE64_URL_ALPHABET[n >>> 12 & 63] + BASE64_URL_ALPHABET[n >>> 6 & 63] + BASE64_URL_ALPHABET[n & 63];
152
+ }
153
+ const n = digest[30] << 8 | digest[31];
154
+ result += BASE64_URL_ALPHABET[n >>> 10 & 63] + BASE64_URL_ALPHABET[n >>> 4 & 63] + BASE64_URL_ALPHABET[n << 2 & 63];
155
+ return result;
156
+ }
157
+ //#endregion
158
+ exports.sha256 = sha256;