Skip to content

Commit c047603

Browse files
Add distinguishable character set (#14)
Co-authored-by: Sindre Sorhus <[email protected]>
1 parent 9f45399 commit c047603

File tree

4 files changed

+27
-3
lines changed

4 files changed

+27
-3
lines changed

index.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ interface TypeOption {
1515
1616
@default 'hex'
1717
18+
The `distinguishable` set contains only uppercase characters that are not easily confused: `CDEHKMPRTUWXY012458`. It can be useful if you need to print out a short string that you'd like users to read and type back in with minimal errors. For example, reading a code off of a screen that needs to be typed into a phone to connect two devices.
19+
1820
@example
1921
```
2022
cryptoRandomString({length: 10});
@@ -28,9 +30,12 @@ interface TypeOption {
2830
2931
cryptoRandomString({length: 10, type: 'numeric'});
3032
//=> '8314659141'
33+
34+
cryptoRandomString({length: 6, type: 'distinguishable'});
35+
//=> 'CDEHKM'
3136
```
3237
*/
33-
type?: 'hex' | 'base64' | 'url-safe' | 'numeric';
38+
type?: 'hex' | 'base64' | 'url-safe' | 'numeric' | 'distinguishable';
3439
}
3540

3641
interface CharactersOption {

index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const crypto = require('crypto');
33

44
const urlSafeCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~'.split('');
55
const numericCharacters = '0123456789'.split('');
6+
const distinguishableCharacters = 'CDEHKMPRTUWXY012458'.split('');
67

78
const generateForCustomCharacters = (length, characters) => {
89
// Generating entropy is faster than complex math operations, so we use the simplest way
@@ -36,7 +37,8 @@ const allowedTypes = [
3637
'hex',
3738
'base64',
3839
'url-safe',
39-
'numeric'
40+
'numeric',
41+
'distinguishable'
4042
];
4143

4244
module.exports = ({length, type, characters}) => {
@@ -76,6 +78,10 @@ module.exports = ({length, type, characters}) => {
7678
return generateForCustomCharacters(length, numericCharacters);
7779
}
7880

81+
if (type === 'distinguishable') {
82+
return generateForCustomCharacters(length, distinguishableCharacters);
83+
}
84+
7985
if (characters.length === 0) {
8086
throw new TypeError('Expected `characters` string length to be greater than or equal to 1');
8187
}

readme.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ cryptoRandomString({length: 10, type: 'url-safe'});
2727
cryptoRandomString({length: 10, type: 'numeric'});
2828
//=> '8314659141'
2929

30+
cryptoRandomString({length: 6, type: 'distinguishable'});
31+
//=> 'CDEHKM'
32+
3033
cryptoRandomString({length: 10, characters: 'abc'});
3134
//=> 'abaaccabac'
3235
```
@@ -52,12 +55,14 @@ Length of the returned string.
5255

5356
Type: `string`\
5457
Default: `'hex'`\
55-
Values: `'hex' | 'base64' | 'url-safe' | 'numeric'`
58+
Values: `'hex' | 'base64' | 'url-safe' | 'numeric' | 'distinguishable'`
5659

5760
Use only characters from a predefined set of allowed characters.
5861

5962
Cannot be set at the same time as the `characters` option.
6063

64+
The `distinguishable` set contains only uppercase characters that are not easily confused: `CDEHKMPRTUWXY012458`. It can be useful if you need to print out a short string that you'd like users to read and type back in with minimal errors. For example, reading a code off of a screen that needs to be typed into a phone to connect two devices.
65+
6166
##### characters
6267

6368
Type: `string`\

test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ test('numeric', t => {
5454
t.is(generatedCharacterSetSize({type: 'numeric'}, 10), 10);
5555
});
5656

57+
test('distinquishable', t => {
58+
t.is(cryptoRandomString({length: 0, type: 'distinguishable'}).length, 0);
59+
t.is(cryptoRandomString({length: 10, type: 'distinguishable'}).length, 10);
60+
t.is(cryptoRandomString({length: 100, type: 'distinguishable'}).length, 100);
61+
t.regex(cryptoRandomString({length: 100, type: 'distinguishable'}), /^[CDEHKMPRTUWXY012458]*$/); // Sanity check, probabilistic
62+
t.is(generatedCharacterSetSize({type: 'distinguishable'}, 19), 19);
63+
});
64+
5765
test('characters', t => {
5866
t.is(cryptoRandomString({length: 0, characters: '1234'}).length, 0);
5967
t.is(cryptoRandomString({length: 10, characters: '1234'}).length, 10);

0 commit comments

Comments
 (0)