cybertoken 3.0.16 → 4.0.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.
package/dist/cli.d.ts CHANGED
@@ -1,2 +1 @@
1
- #!/usr/bin/env node
2
- export {};
1
+ export { };
package/dist/cli.js CHANGED
@@ -1,21 +1,22 @@
1
1
  #!/usr/bin/env node
2
- var _a;
3
- import { createTokenGenerator } from "./index.js";
4
- const prefixWithoutUnderscore = (_a = process.argv[2]) !== null && _a !== void 0 ? _a : process.env.CYBERTOKEN_PREFIX;
2
+ import { t as createTokenGenerator } from "./src-C0ocXD_g.js";
3
+
4
+ //#region src/cli.ts
5
+ const prefixWithoutUnderscore = process.argv[2] ?? process.env.CYBERTOKEN_PREFIX;
5
6
  if (!prefixWithoutUnderscore) {
6
- console.error("Please specify a prefix for the token.");
7
- console.error("A prefix must be a non-empty string.");
8
- console.error();
9
- console.error("Usage:");
10
- console.error(" cybertoken <prefix>");
11
- console.error();
12
- console.error("You can also provide the prefix via the CYBERTOKEN_PREFIX environment variable.");
13
- console.error("For example:");
14
- console.error(" CYBERTOKEN_PREFIX=foo cybertoken");
15
- process.exit(1);
7
+ console.error("Please specify a prefix for the token.");
8
+ console.error("A prefix must be a non-empty string.");
9
+ console.error();
10
+ console.error("Usage:");
11
+ console.error(" cybertoken <prefix>");
12
+ console.error();
13
+ console.error("You can also provide the prefix via the CYBERTOKEN_PREFIX environment variable.");
14
+ console.error("For example:");
15
+ console.error(" CYBERTOKEN_PREFIX=foo cybertoken");
16
+ process.exit(1);
16
17
  }
17
- const tokenGenerator = createTokenGenerator({
18
- prefixWithoutUnderscore,
19
- });
20
- const token = tokenGenerator.generateToken();
18
+ const token = createTokenGenerator({ prefixWithoutUnderscore }).generateToken();
21
19
  console.log(token);
20
+
21
+ //#endregion
22
+ export { };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,12 @@
1
- export interface TokenGeneratorOptions {
2
- prefixWithoutUnderscore: string;
3
- entropyBytes?: number;
1
+ //#region src/index.d.ts
2
+ interface TokenGeneratorOptions {
3
+ prefixWithoutUnderscore: string;
4
+ entropyBytes?: number;
4
5
  }
5
- export interface TokenGenerator {
6
- generateToken: () => string;
7
- isTokenString: (value: unknown) => boolean;
6
+ interface TokenGenerator {
7
+ generateToken: () => string;
8
+ isTokenString: (value: unknown) => boolean;
8
9
  }
9
- export declare function createTokenGenerator(options: TokenGeneratorOptions): TokenGenerator;
10
+ declare function createTokenGenerator(options: TokenGeneratorOptions): TokenGenerator;
11
+ //#endregion
12
+ export { TokenGenerator, TokenGeneratorOptions, createTokenGenerator };
package/dist/index.js CHANGED
@@ -1,46 +1,3 @@
1
- import * as base62 from "./base62.js";
2
- import crc32 from "./crc32.js";
3
- import { getTokenPattern, parseTokenData, version } from "./parse.js";
4
- const cryptoServices = globalThis.crypto;
5
- export function createTokenGenerator(options) {
6
- var _a;
7
- if (!options.prefixWithoutUnderscore) {
8
- throw new Error("The `prefixWithoutUnderscore` option is required and must not be an empty string.");
9
- }
10
- const prefixWithUnderscore = `${options.prefixWithoutUnderscore}_`;
11
- const tokenPattern = getTokenPattern(prefixWithUnderscore);
12
- const tokenSecretByteCount = (_a = options.entropyBytes) !== null && _a !== void 0 ? _a : 22;
13
- if (tokenSecretByteCount <= 20) {
14
- throw new Error("The token secret byte count (`entropyBytes`) must be greater than 20.");
15
- }
16
- return {
17
- generateToken,
18
- isTokenString,
19
- };
20
- function generateToken() {
21
- const tokenData = generateTokenData();
22
- const encodedData = base62.encode(tokenData);
23
- return prefixWithUnderscore + encodedData;
24
- }
25
- function generateTokenData() {
26
- const entropyWithVersion = cryptoServices.getRandomValues(new Uint8Array(tokenSecretByteCount + 1));
27
- entropyWithVersion[entropyWithVersion.length - 1] = version;
28
- const checksum = crc32(entropyWithVersion);
29
- console.assert(checksum.byteLength === 4);
30
- const payloadWithChecksum = new Uint8Array(entropyWithVersion.byteLength + checksum.byteLength);
31
- payloadWithChecksum.set(entropyWithVersion, 0);
32
- payloadWithChecksum.set(checksum, entropyWithVersion.byteLength);
33
- console.assert(payloadWithChecksum.length === tokenSecretByteCount + 4 + 1);
34
- return payloadWithChecksum;
35
- }
36
- function isTokenString(value) {
37
- if (!value ||
38
- typeof value !== "string" ||
39
- !value.startsWith(prefixWithUnderscore) ||
40
- !tokenPattern.test(value)) {
41
- return false;
42
- }
43
- const tokenData = parseTokenData(value);
44
- return !!tokenData && tokenData.isSyntacticallyValid;
45
- }
46
- }
1
+ import { t as createTokenGenerator } from "./src-C0ocXD_g.js";
2
+
3
+ export { createTokenGenerator };
@@ -0,0 +1,697 @@
1
+ //#region src/base62.ts
2
+ const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
3
+ const BASE_MAP = new Uint8Array([
4
+ 255,
5
+ 255,
6
+ 255,
7
+ 255,
8
+ 255,
9
+ 255,
10
+ 255,
11
+ 255,
12
+ 255,
13
+ 255,
14
+ 255,
15
+ 255,
16
+ 255,
17
+ 255,
18
+ 255,
19
+ 255,
20
+ 255,
21
+ 255,
22
+ 255,
23
+ 255,
24
+ 255,
25
+ 255,
26
+ 255,
27
+ 255,
28
+ 255,
29
+ 255,
30
+ 255,
31
+ 255,
32
+ 255,
33
+ 255,
34
+ 255,
35
+ 255,
36
+ 255,
37
+ 255,
38
+ 255,
39
+ 255,
40
+ 255,
41
+ 255,
42
+ 255,
43
+ 255,
44
+ 255,
45
+ 255,
46
+ 255,
47
+ 255,
48
+ 255,
49
+ 255,
50
+ 255,
51
+ 255,
52
+ 0,
53
+ 1,
54
+ 2,
55
+ 3,
56
+ 4,
57
+ 5,
58
+ 6,
59
+ 7,
60
+ 8,
61
+ 9,
62
+ 255,
63
+ 255,
64
+ 255,
65
+ 255,
66
+ 255,
67
+ 255,
68
+ 255,
69
+ 10,
70
+ 11,
71
+ 12,
72
+ 13,
73
+ 14,
74
+ 15,
75
+ 16,
76
+ 17,
77
+ 18,
78
+ 19,
79
+ 20,
80
+ 21,
81
+ 22,
82
+ 23,
83
+ 24,
84
+ 25,
85
+ 26,
86
+ 27,
87
+ 28,
88
+ 29,
89
+ 30,
90
+ 31,
91
+ 32,
92
+ 33,
93
+ 34,
94
+ 35,
95
+ 255,
96
+ 255,
97
+ 255,
98
+ 255,
99
+ 255,
100
+ 255,
101
+ 36,
102
+ 37,
103
+ 38,
104
+ 39,
105
+ 40,
106
+ 41,
107
+ 42,
108
+ 43,
109
+ 44,
110
+ 45,
111
+ 46,
112
+ 47,
113
+ 48,
114
+ 49,
115
+ 50,
116
+ 51,
117
+ 52,
118
+ 53,
119
+ 54,
120
+ 55,
121
+ 56,
122
+ 57,
123
+ 58,
124
+ 59,
125
+ 60,
126
+ 61,
127
+ 255,
128
+ 255,
129
+ 255,
130
+ 255,
131
+ 255,
132
+ 255,
133
+ 255,
134
+ 255,
135
+ 255,
136
+ 255,
137
+ 255,
138
+ 255,
139
+ 255,
140
+ 255,
141
+ 255,
142
+ 255,
143
+ 255,
144
+ 255,
145
+ 255,
146
+ 255,
147
+ 255,
148
+ 255,
149
+ 255,
150
+ 255,
151
+ 255,
152
+ 255,
153
+ 255,
154
+ 255,
155
+ 255,
156
+ 255,
157
+ 255,
158
+ 255,
159
+ 255,
160
+ 255,
161
+ 255,
162
+ 255,
163
+ 255,
164
+ 255,
165
+ 255,
166
+ 255,
167
+ 255,
168
+ 255,
169
+ 255,
170
+ 255,
171
+ 255,
172
+ 255,
173
+ 255,
174
+ 255,
175
+ 255,
176
+ 255,
177
+ 255,
178
+ 255,
179
+ 255,
180
+ 255,
181
+ 255,
182
+ 255,
183
+ 255,
184
+ 255,
185
+ 255,
186
+ 255,
187
+ 255,
188
+ 255,
189
+ 255,
190
+ 255,
191
+ 255,
192
+ 255,
193
+ 255,
194
+ 255,
195
+ 255,
196
+ 255,
197
+ 255,
198
+ 255,
199
+ 255,
200
+ 255,
201
+ 255,
202
+ 255,
203
+ 255,
204
+ 255,
205
+ 255,
206
+ 255,
207
+ 255,
208
+ 255,
209
+ 255,
210
+ 255,
211
+ 255,
212
+ 255,
213
+ 255,
214
+ 255,
215
+ 255,
216
+ 255,
217
+ 255,
218
+ 255,
219
+ 255,
220
+ 255,
221
+ 255,
222
+ 255,
223
+ 255,
224
+ 255,
225
+ 255,
226
+ 255,
227
+ 255,
228
+ 255,
229
+ 255,
230
+ 255,
231
+ 255,
232
+ 255,
233
+ 255,
234
+ 255,
235
+ 255,
236
+ 255,
237
+ 255,
238
+ 255,
239
+ 255,
240
+ 255,
241
+ 255,
242
+ 255,
243
+ 255,
244
+ 255,
245
+ 255,
246
+ 255,
247
+ 255,
248
+ 255,
249
+ 255,
250
+ 255,
251
+ 255,
252
+ 255,
253
+ 255,
254
+ 255,
255
+ 255,
256
+ 255,
257
+ 255,
258
+ 255,
259
+ 255
260
+ ]);
261
+ const BASE = 62;
262
+ const LEADER = alphabet[0];
263
+ const FACTOR = Math.log(BASE) / Math.log(256);
264
+ const iFACTOR = Math.log(256) / Math.log(BASE);
265
+ function encode(source) {
266
+ let src;
267
+ if (source instanceof Uint8Array) src = source;
268
+ else if (ArrayBuffer.isView(source)) src = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
269
+ else throw new Error("`source` has non-supported type. Provide `Uint8Array` or `ArrayBufferView`.");
270
+ if (src.length === 0) return "";
271
+ let zeroes = 0;
272
+ let length = 0;
273
+ let pbegin = 0;
274
+ const pend = src.length;
275
+ while (pbegin !== pend && src[pbegin] === 0) {
276
+ pbegin++;
277
+ zeroes++;
278
+ }
279
+ const size = (pend - pbegin) * iFACTOR + 1 >>> 0;
280
+ const b58 = new Uint8Array(size);
281
+ while (pbegin !== pend) {
282
+ let carry = src[pbegin];
283
+ let i = 0;
284
+ for (let it1 = size - 1; (carry !== 0 || i < length) && it1 !== -1; it1--, i++) {
285
+ carry += 256 * b58[it1] >>> 0;
286
+ b58[it1] = carry % BASE >>> 0;
287
+ carry = carry / BASE >>> 0;
288
+ }
289
+ if (carry !== 0) throw new Error("Non-zero carry");
290
+ length = i;
291
+ pbegin++;
292
+ }
293
+ let it2 = size - length;
294
+ while (it2 !== size && b58[it2] === 0) it2++;
295
+ let str = LEADER.repeat(zeroes);
296
+ for (; it2 < size; ++it2) str += alphabet[b58[it2]];
297
+ return str;
298
+ }
299
+ function decodeUnsafe(source) {
300
+ if (typeof source !== "string") throw new TypeError("Expected String");
301
+ if (source.length === 0) return new Uint8Array();
302
+ let psz = 0;
303
+ let zeroes = 0;
304
+ let length = 0;
305
+ while (source[psz] === LEADER) {
306
+ zeroes++;
307
+ psz++;
308
+ }
309
+ const size = (source.length - psz) * FACTOR + 1 >>> 0;
310
+ const b256 = new Uint8Array(size);
311
+ while (source[psz]) {
312
+ let carry = BASE_MAP[source.charCodeAt(psz)];
313
+ if (carry === 255) return;
314
+ let i = 0;
315
+ for (let it3 = size - 1; (carry !== 0 || i < length) && it3 !== -1; it3--, i++) {
316
+ carry += BASE * b256[it3] >>> 0;
317
+ b256[it3] = carry % 256 >>> 0;
318
+ carry = carry / 256 >>> 0;
319
+ }
320
+ if (carry !== 0) throw new Error("Non-zero carry");
321
+ length = i;
322
+ psz++;
323
+ }
324
+ let it4 = size - length;
325
+ while (it4 !== size && b256[it4] === 0) it4++;
326
+ const vch = new Uint8Array(zeroes + (size - it4));
327
+ let j = zeroes;
328
+ while (it4 !== size) vch[j++] = b256[it4++];
329
+ return vch;
330
+ }
331
+ function decode(string) {
332
+ const buffer = decodeUnsafe(string);
333
+ if (buffer) return buffer;
334
+ throw new Error("Failed to decode string");
335
+ }
336
+
337
+ //#endregion
338
+ //#region src/crc32.ts
339
+ const table = new Uint32Array([
340
+ 0,
341
+ 1996959894,
342
+ 3993919788,
343
+ 2567524794,
344
+ 124634137,
345
+ 1886057615,
346
+ 3915621685,
347
+ 2657392035,
348
+ 249268274,
349
+ 2044508324,
350
+ 3772115230,
351
+ 2547177864,
352
+ 162941995,
353
+ 2125561021,
354
+ 3887607047,
355
+ 2428444049,
356
+ 498536548,
357
+ 1789927666,
358
+ 4089016648,
359
+ 2227061214,
360
+ 450548861,
361
+ 1843258603,
362
+ 4107580753,
363
+ 2211677639,
364
+ 325883990,
365
+ 1684777152,
366
+ 4251122042,
367
+ 2321926636,
368
+ 335633487,
369
+ 1661365465,
370
+ 4195302755,
371
+ 2366115317,
372
+ 997073096,
373
+ 1281953886,
374
+ 3579855332,
375
+ 2724688242,
376
+ 1006888145,
377
+ 1258607687,
378
+ 3524101629,
379
+ 2768942443,
380
+ 901097722,
381
+ 1119000684,
382
+ 3686517206,
383
+ 2898065728,
384
+ 853044451,
385
+ 1172266101,
386
+ 3705015759,
387
+ 2882616665,
388
+ 651767980,
389
+ 1373503546,
390
+ 3369554304,
391
+ 3218104598,
392
+ 565507253,
393
+ 1454621731,
394
+ 3485111705,
395
+ 3099436303,
396
+ 671266974,
397
+ 1594198024,
398
+ 3322730930,
399
+ 2970347812,
400
+ 795835527,
401
+ 1483230225,
402
+ 3244367275,
403
+ 3060149565,
404
+ 1994146192,
405
+ 31158534,
406
+ 2563907772,
407
+ 4023717930,
408
+ 1907459465,
409
+ 112637215,
410
+ 2680153253,
411
+ 3904427059,
412
+ 2013776290,
413
+ 251722036,
414
+ 2517215374,
415
+ 3775830040,
416
+ 2137656763,
417
+ 141376813,
418
+ 2439277719,
419
+ 3865271297,
420
+ 1802195444,
421
+ 476864866,
422
+ 2238001368,
423
+ 4066508878,
424
+ 1812370925,
425
+ 453092731,
426
+ 2181625025,
427
+ 4111451223,
428
+ 1706088902,
429
+ 314042704,
430
+ 2344532202,
431
+ 4240017532,
432
+ 1658658271,
433
+ 366619977,
434
+ 2362670323,
435
+ 4224994405,
436
+ 1303535960,
437
+ 984961486,
438
+ 2747007092,
439
+ 3569037538,
440
+ 1256170817,
441
+ 1037604311,
442
+ 2765210733,
443
+ 3554079995,
444
+ 1131014506,
445
+ 879679996,
446
+ 2909243462,
447
+ 3663771856,
448
+ 1141124467,
449
+ 855842277,
450
+ 2852801631,
451
+ 3708648649,
452
+ 1342533948,
453
+ 654459306,
454
+ 3188396048,
455
+ 3373015174,
456
+ 1466479909,
457
+ 544179635,
458
+ 3110523913,
459
+ 3462522015,
460
+ 1591671054,
461
+ 702138776,
462
+ 2966460450,
463
+ 3352799412,
464
+ 1504918807,
465
+ 783551873,
466
+ 3082640443,
467
+ 3233442989,
468
+ 3988292384,
469
+ 2596254646,
470
+ 62317068,
471
+ 1957810842,
472
+ 3939845945,
473
+ 2647816111,
474
+ 81470997,
475
+ 1943803523,
476
+ 3814918930,
477
+ 2489596804,
478
+ 225274430,
479
+ 2053790376,
480
+ 3826175755,
481
+ 2466906013,
482
+ 167816743,
483
+ 2097651377,
484
+ 4027552580,
485
+ 2265490386,
486
+ 503444072,
487
+ 1762050814,
488
+ 4150417245,
489
+ 2154129355,
490
+ 426522225,
491
+ 1852507879,
492
+ 4275313526,
493
+ 2312317920,
494
+ 282753626,
495
+ 1742555852,
496
+ 4189708143,
497
+ 2394877945,
498
+ 397917763,
499
+ 1622183637,
500
+ 3604390888,
501
+ 2714866558,
502
+ 953729732,
503
+ 1340076626,
504
+ 3518719985,
505
+ 2797360999,
506
+ 1068828381,
507
+ 1219638859,
508
+ 3624741850,
509
+ 2936675148,
510
+ 906185462,
511
+ 1090812512,
512
+ 3747672003,
513
+ 2825379669,
514
+ 829329135,
515
+ 1181335161,
516
+ 3412177804,
517
+ 3160834842,
518
+ 628085408,
519
+ 1382605366,
520
+ 3423369109,
521
+ 3138078467,
522
+ 570562233,
523
+ 1426400815,
524
+ 3317316542,
525
+ 2998733608,
526
+ 733239954,
527
+ 1555261956,
528
+ 3268935591,
529
+ 3050360625,
530
+ 752459403,
531
+ 1541320221,
532
+ 2607071920,
533
+ 3965973030,
534
+ 1969922972,
535
+ 40735498,
536
+ 2617837225,
537
+ 3943577151,
538
+ 1913087877,
539
+ 83908371,
540
+ 2512341634,
541
+ 3803740692,
542
+ 2075208622,
543
+ 213261112,
544
+ 2463272603,
545
+ 3855990285,
546
+ 2094854071,
547
+ 198958881,
548
+ 2262029012,
549
+ 4057260610,
550
+ 1759359992,
551
+ 534414190,
552
+ 2176718541,
553
+ 4139329115,
554
+ 1873836001,
555
+ 414664567,
556
+ 2282248934,
557
+ 4279200368,
558
+ 1711684554,
559
+ 285281116,
560
+ 2405801727,
561
+ 4167216745,
562
+ 1634467795,
563
+ 376229701,
564
+ 2685067896,
565
+ 3608007406,
566
+ 1308918612,
567
+ 956543938,
568
+ 2808555105,
569
+ 3495958263,
570
+ 1231636301,
571
+ 1047427035,
572
+ 2932959818,
573
+ 3654703836,
574
+ 1088359270,
575
+ 936918e3,
576
+ 2847714899,
577
+ 3736837829,
578
+ 1202900863,
579
+ 817233897,
580
+ 3183342108,
581
+ 3401237130,
582
+ 1404277552,
583
+ 615818150,
584
+ 3134207493,
585
+ 3453421203,
586
+ 1423857449,
587
+ 601450431,
588
+ 3009837614,
589
+ 3294710456,
590
+ 1567103746,
591
+ 711928724,
592
+ 3020668471,
593
+ 3272380065,
594
+ 1510334235,
595
+ 755167117
596
+ ]);
597
+ function crc32(inputBuffer) {
598
+ const ds = new Uint8Array(inputBuffer);
599
+ let crc = -1;
600
+ for (let i = 0; i < ds.length; i++) crc = crc >>> 8 ^ table[(crc ^ ds[i]) & 255];
601
+ const result = new Uint8Array(4);
602
+ new DataView(result.buffer).setUint32(0, (crc ^ -1) >>> 0);
603
+ return result;
604
+ }
605
+
606
+ //#endregion
607
+ //#region src/parse.ts
608
+ const version = 0;
609
+ function getTokenPattern(prefixWithUnderscore) {
610
+ return /* @__PURE__ */ new RegExp(`^${prefixWithUnderscore}[${alphabet}]+$`);
611
+ }
612
+ /**
613
+ * Only use this if you want to look at the parsed contents of the token. **Then using the tokens, this is usually not needed.** It is mostly used internally.
614
+ *
615
+ * You should treat the token contents as a black box.
616
+ */
617
+ function parseTokenData(token) {
618
+ if (!token.includes("_")) return;
619
+ const splitData = token.split("_");
620
+ if (splitData.length !== 2) return;
621
+ const [prefix, encodedTokenData] = splitData;
622
+ const secretWithVersionAndChecksum = decode(encodedTokenData);
623
+ if (!secretWithVersionAndChecksum || secretWithVersionAndChecksum.length <= 4) return;
624
+ const suppliedChecksum = secretWithVersionAndChecksum.slice(secretWithVersionAndChecksum.length - 4);
625
+ if (suppliedChecksum.length !== 4) return;
626
+ const secretAndVersionBuffer = secretWithVersionAndChecksum.slice(0, secretWithVersionAndChecksum.length - 4);
627
+ const actualChecksum = crc32(secretAndVersionBuffer);
628
+ const isSyntacticallyValid = secretAndVersionBuffer.length > 0 && buffersEqual(suppliedChecksum, actualChecksum);
629
+ const suppliedVersion = secretAndVersionBuffer[secretAndVersionBuffer.length - 1];
630
+ if (suppliedVersion !== version) return;
631
+ return {
632
+ version: suppliedVersion,
633
+ prefixWithoutUnderscore: prefix,
634
+ secret: secretAndVersionBuffer.slice(0, secretAndVersionBuffer.length - 1),
635
+ suppliedChecksum,
636
+ actualChecksum,
637
+ isSyntacticallyValid
638
+ };
639
+ }
640
+ function buffersEqual(a, b) {
641
+ if (a.byteLength !== b.byteLength) return false;
642
+ for (let i = 0; i < a.byteLength; ++i) if (a[i] !== b[i]) return false;
643
+ return true;
644
+ }
645
+
646
+ //#endregion
647
+ //#region src/index.ts
648
+ const cryptoServices = globalThis.crypto;
649
+ /**
650
+ * Creates a new {@link TokenGenerator}.
651
+ * @param {TokenGeneratorOptions} options Options bag.
652
+ */
653
+ function createTokenGenerator(options) {
654
+ if (!options.prefixWithoutUnderscore) throw new Error("The `prefixWithoutUnderscore` option is required and must not be an empty string.");
655
+ const prefixWithUnderscore = `${options.prefixWithoutUnderscore}_`;
656
+ const tokenPattern = getTokenPattern(prefixWithUnderscore);
657
+ const tokenSecretByteCount = options.entropyBytes ?? 22;
658
+ if (tokenSecretByteCount <= 20) throw new Error("The token secret byte count (`entropyBytes`) must be greater than 20.");
659
+ return {
660
+ generateToken,
661
+ isTokenString
662
+ };
663
+ function generateToken() {
664
+ const tokenData = generateTokenData();
665
+ return prefixWithUnderscore + encode(tokenData);
666
+ }
667
+ /**
668
+ * @remarks As the token generation uses cryptographically secure random numbers, keep in mind that generating a large amount of tokens will block the entire application for a short amount of time (until the entropy pool is filled again).
669
+ * This can lead to a Denial of Service (DoS) attack, so you might want to limit the amount of tokens that can be generated in a short amount of time.
670
+ */
671
+ function generateTokenData() {
672
+ const entropyWithVersion = cryptoServices.getRandomValues(new Uint8Array(tokenSecretByteCount + 1));
673
+ entropyWithVersion[entropyWithVersion.length - 1] = version;
674
+ const checksum = crc32(entropyWithVersion);
675
+ console.assert(checksum.byteLength === 4);
676
+ const payloadWithChecksum = new Uint8Array(entropyWithVersion.byteLength + checksum.byteLength);
677
+ payloadWithChecksum.set(entropyWithVersion, 0);
678
+ payloadWithChecksum.set(checksum, entropyWithVersion.byteLength);
679
+ console.assert(payloadWithChecksum.length === tokenSecretByteCount + 4 + 1);
680
+ return payloadWithChecksum;
681
+ }
682
+ /**
683
+ * Function to check if a token is syntactically valid. **Not** used for token validation.
684
+ * You can use this for secret scanning or as a heuristic/optimization before asking some backend whether the token is valid.
685
+ *
686
+ * @param {boolean} value The token candidate to check
687
+ * @returns `true` if the token is syntactically valid, `false` otherwise.
688
+ */
689
+ function isTokenString(value) {
690
+ if (!value || typeof value !== "string" || !value.startsWith(prefixWithUnderscore) || !tokenPattern.test(value)) return false;
691
+ const tokenData = parseTokenData(value);
692
+ return !!tokenData && tokenData.isSyntacticallyValid;
693
+ }
694
+ }
695
+
696
+ //#endregion
697
+ export { createTokenGenerator as t };
package/package.json CHANGED
@@ -1,26 +1,25 @@
1
1
  {
2
2
  "name": "cybertoken",
3
- "version": "3.0.16",
3
+ "version": "4.0.0",
4
4
  "description": "A token format for APIs inspired by the GitHub's API token format.",
5
5
  "author": "Niklas Mollenhauer",
6
6
  "license": "ISC",
7
7
  "type": "module",
8
8
  "main": "dist/index.js",
9
9
  "bin": "dist/cli.js",
10
+ "types": "dist/index.d.ts",
10
11
  "repository": {
11
12
  "type": "git",
12
13
  "url": "https://github.com/nikeee/cybertoken.git"
13
14
  },
14
15
  "scripts": {
15
- "compile": "tsc",
16
- "clean": "rimraf dist",
16
+ "build": "tsdown",
17
17
  "ci": "tsc --noEmit && biome ci ./src",
18
18
  "docs": "typedoc",
19
19
  "format": "biome format --write ./src",
20
- "test": "tsc --noEmit && vitest run",
21
- "test:coverage": "vitest run --coverage",
22
- "test:watch": "vitest watch --coverage",
23
- "prepublishOnly": "npm run clean && npm run compile"
20
+ "test": "tsc --noEmit && node --test",
21
+ "test:coverage": "node --test --experimental-test-coverage",
22
+ "prepublishOnly": "npm run build"
24
23
  },
25
24
  "keywords": [
26
25
  "token",
@@ -30,12 +29,11 @@
30
29
  "generator"
31
30
  ],
32
31
  "devDependencies": {
33
- "@biomejs/biome": "^2.2.3",
34
- "@types/node": "^24.3.1",
35
- "@vitest/coverage-v8": "^3.2.4",
36
- "rimraf": "^6.0.1",
37
- "typedoc": "^0.28.12",
38
- "vitest": "^3.2.4"
32
+ "@biomejs/biome": "^2.3.2",
33
+ "@types/node": "^24.9.2",
34
+ "expect": "^30.2.0",
35
+ "tsdown": "^0.15.12",
36
+ "typedoc": "^0.28.14"
39
37
  },
40
38
  "engines": {
41
39
  "node": ">=20"
package/dist/base62.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export declare const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2
- export declare function encode(source: Uint8Array | ArrayBufferView): string;
3
- export declare function decodeUnsafe(source: string): Uint8Array | undefined;
4
- export declare function decode(string: string): Uint8Array;
package/dist/base62.js DELETED
@@ -1,122 +0,0 @@
1
- export const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2
- const BASE_MAP = new Uint8Array([
3
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
4
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
5
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
6
- 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
7
- 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
8
- 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255, 255, 36, 37, 38, 39,
9
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
10
- 59, 60, 61, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
11
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
12
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
13
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
14
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
15
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
16
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
17
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
18
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
19
- ]);
20
- const BASE = alphabet.length;
21
- const LEADER = alphabet[0];
22
- const FACTOR = Math.log(BASE) / Math.log(256);
23
- const iFACTOR = Math.log(256) / Math.log(BASE);
24
- export function encode(source) {
25
- let src;
26
- if (source instanceof Uint8Array) {
27
- src = source;
28
- }
29
- else if (ArrayBuffer.isView(source)) {
30
- src = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
31
- }
32
- else {
33
- throw new Error("`source` has non-supported type. Provide `Uint8Array` or `ArrayBufferView`.");
34
- }
35
- if (src.length === 0) {
36
- return "";
37
- }
38
- let zeroes = 0;
39
- let length = 0;
40
- let pbegin = 0;
41
- const pend = src.length;
42
- while (pbegin !== pend && src[pbegin] === 0) {
43
- pbegin++;
44
- zeroes++;
45
- }
46
- const size = ((pend - pbegin) * iFACTOR + 1) >>> 0;
47
- const b58 = new Uint8Array(size);
48
- while (pbegin !== pend) {
49
- let carry = src[pbegin];
50
- let i = 0;
51
- for (let it1 = size - 1; (carry !== 0 || i < length) && it1 !== -1; it1--, i++) {
52
- carry += (256 * b58[it1]) >>> 0;
53
- b58[it1] = (carry % BASE) >>> 0;
54
- carry = (carry / BASE) >>> 0;
55
- }
56
- if (carry !== 0) {
57
- throw new Error("Non-zero carry");
58
- }
59
- length = i;
60
- pbegin++;
61
- }
62
- let it2 = size - length;
63
- while (it2 !== size && b58[it2] === 0) {
64
- it2++;
65
- }
66
- let str = LEADER.repeat(zeroes);
67
- for (; it2 < size; ++it2) {
68
- str += alphabet[b58[it2]];
69
- }
70
- return str;
71
- }
72
- export function decodeUnsafe(source) {
73
- if (typeof source !== "string") {
74
- throw new TypeError("Expected String");
75
- }
76
- if (source.length === 0) {
77
- return new Uint8Array();
78
- }
79
- let psz = 0;
80
- let zeroes = 0;
81
- let length = 0;
82
- while (source[psz] === LEADER) {
83
- zeroes++;
84
- psz++;
85
- }
86
- const size = ((source.length - psz) * FACTOR + 1) >>> 0;
87
- const b256 = new Uint8Array(size);
88
- while (source[psz]) {
89
- let carry = BASE_MAP[source.charCodeAt(psz)];
90
- if (carry === 255) {
91
- return undefined;
92
- }
93
- let i = 0;
94
- for (let it3 = size - 1; (carry !== 0 || i < length) && it3 !== -1; it3--, i++) {
95
- carry += (BASE * b256[it3]) >>> 0;
96
- b256[it3] = (carry % 256) >>> 0;
97
- carry = (carry / 256) >>> 0;
98
- }
99
- if (carry !== 0) {
100
- throw new Error("Non-zero carry");
101
- }
102
- length = i;
103
- psz++;
104
- }
105
- let it4 = size - length;
106
- while (it4 !== size && b256[it4] === 0) {
107
- it4++;
108
- }
109
- const vch = new Uint8Array(zeroes + (size - it4));
110
- let j = zeroes;
111
- while (it4 !== size) {
112
- vch[j++] = b256[it4++];
113
- }
114
- return vch;
115
- }
116
- export function decode(string) {
117
- const buffer = decodeUnsafe(string);
118
- if (buffer) {
119
- return buffer;
120
- }
121
- throw new Error("Failed to decode string");
122
- }
package/dist/crc32.d.ts DELETED
@@ -1 +0,0 @@
1
- export default function crc32(inputBuffer: Uint8Array): Uint8Array;
package/dist/crc32.js DELETED
@@ -1,56 +0,0 @@
1
- const table = new Uint32Array([
2
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
3
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
4
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
5
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
6
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
7
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
8
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
9
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
10
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
11
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
12
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
13
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
14
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
15
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
16
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
17
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
18
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
19
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
20
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
21
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
22
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
23
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
24
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
25
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
26
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
27
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
28
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
29
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
30
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
31
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
32
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
33
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
34
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
35
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
36
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
37
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
38
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
39
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
40
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
41
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
42
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
43
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
44
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
45
- ]);
46
- export default function crc32(inputBuffer) {
47
- const ds = new Uint8Array(inputBuffer);
48
- let crc = 0 ^ -1;
49
- for (let i = 0; i < ds.length; i++) {
50
- crc = (crc >>> 8) ^ table[(crc ^ ds[i]) & 0xff];
51
- }
52
- const result = new Uint8Array(4);
53
- const dv = new DataView(result.buffer);
54
- dv.setUint32(0, (crc ^ -1) >>> 0);
55
- return result;
56
- }
package/dist/parse.d.ts DELETED
@@ -1,11 +0,0 @@
1
- export declare const version = 0;
2
- export declare function getTokenPattern(prefixWithUnderscore: string): RegExp;
3
- export interface TokenContents {
4
- prefixWithoutUnderscore: string;
5
- secret: Uint8Array;
6
- version: number;
7
- suppliedChecksum: Uint8Array;
8
- actualChecksum: Uint8Array;
9
- isSyntacticallyValid: boolean;
10
- }
11
- export declare function parseTokenData(token: string): TokenContents | undefined;
package/dist/parse.js DELETED
@@ -1,53 +0,0 @@
1
- import * as base62 from "./base62.js";
2
- import crc32 from "./crc32.js";
3
- export const version = 0;
4
- export function getTokenPattern(prefixWithUnderscore) {
5
- return new RegExp(`^${prefixWithUnderscore}[${base62.alphabet}]+$`);
6
- }
7
- export function parseTokenData(token) {
8
- if (!token.includes("_")) {
9
- return undefined;
10
- }
11
- const splitData = token.split("_");
12
- if (splitData.length !== 2) {
13
- return undefined;
14
- }
15
- const [prefix, encodedTokenData] = splitData;
16
- const secretWithVersionAndChecksum = base62.decode(encodedTokenData);
17
- if (!secretWithVersionAndChecksum ||
18
- secretWithVersionAndChecksum.length <= 4) {
19
- return undefined;
20
- }
21
- const suppliedChecksum = secretWithVersionAndChecksum.slice(secretWithVersionAndChecksum.length - 4);
22
- if (suppliedChecksum.length !== 4) {
23
- return undefined;
24
- }
25
- const secretAndVersionBuffer = secretWithVersionAndChecksum.slice(0, secretWithVersionAndChecksum.length - 4);
26
- const actualChecksum = crc32(secretAndVersionBuffer);
27
- const isSyntacticallyValid = secretAndVersionBuffer.length > 0 &&
28
- buffersEqual(suppliedChecksum, actualChecksum);
29
- const suppliedVersion = secretAndVersionBuffer[secretAndVersionBuffer.length - 1];
30
- if (suppliedVersion !== version) {
31
- return undefined;
32
- }
33
- const secretPayload = secretAndVersionBuffer.slice(0, secretAndVersionBuffer.length - 1);
34
- return {
35
- version: suppliedVersion,
36
- prefixWithoutUnderscore: prefix,
37
- secret: secretPayload,
38
- suppliedChecksum,
39
- actualChecksum,
40
- isSyntacticallyValid,
41
- };
42
- }
43
- function buffersEqual(a, b) {
44
- if (a.byteLength !== b.byteLength) {
45
- return false;
46
- }
47
- for (let i = 0; i < a.byteLength; ++i) {
48
- if (a[i] !== b[i]) {
49
- return false;
50
- }
51
- }
52
- return true;
53
- }