Skip to content

Commit

Permalink
Require Node.js 12 and move to ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Apr 5, 2021
1 parent d78436d commit 6e19619
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 35 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ jobs:
node-version:
- 14
- 12
- 10
- 8
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
Expand Down
24 changes: 14 additions & 10 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface TypeOption {
cryptoRandomString({length: 10, type: 'ascii-printable'});
//=> '`#Rt8$IK>B'
cryptoRandomString({length: 10, type: 'alphanumeric'});
//=> 'DMuKL8YtE7'
```
Expand All @@ -66,9 +66,7 @@ interface CharactersOption {
characters?: string;
}

declare namespace cryptoRandomString {
type Options = BaseOptions & MergeExclusive<TypeOption, CharactersOption>;
}
export type Options = BaseOptions & MergeExclusive<TypeOption, CharactersOption>;

declare const cryptoRandomString: {
/**
Expand All @@ -78,28 +76,34 @@ declare const cryptoRandomString: {
@example
```
import cryptoRandomString = require('crypto-random-string');
import cryptoRandomString from 'crypto-random-string';
cryptoRandomString({length: 10});
//=> '2cf05d94db'
```
*/
(options: cryptoRandomString.Options): string;
(options: Options): string;

/**
Asynchronously generate a [cryptographically strong](https://en.wikipedia.org/wiki/Strong_cryptography) random string.
For most use-cases, there's really no good reason to use this async version. From the Node.js docs:
> The `crypto.randomBytes()` method will not complete until there is sufficient entropy available. This should normally never take longer than a few milliseconds. The only time when generating the random bytes may conceivably block for a longer period of time is right after boot, when the whole system is still low on entropy.
In general, anything async comes with some overhead on it's own.
@returns A promise which resolves to a randomized string.
@example
```
import cryptoRandomString = require('crypto-random-string');
import cryptoRandomString from 'crypto-random-string';
await cryptoRandomString.async({length: 10});
//=> '2cf05d94db'
```
*/
async(options: cryptoRandomString.Options): Promise<string>;
}
async(options: Options): Promise<string>;
};

export = cryptoRandomString;
export default cryptoRandomString;
18 changes: 10 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict';
const {promisify} = require('util');
const crypto = require('crypto');
import {promisify} from 'util';
import crypto from 'crypto';

const randomBytesAsync = promisify(crypto.randomBytes);

Expand Down Expand Up @@ -71,7 +70,7 @@ const generateRandomBytesAsync = async (byteLength, type, length) => {
return buffer.toString(type).slice(0, length);
};

const allowedTypes = [
const allowedTypes = new Set([
undefined,
'hex',
'base64',
Expand All @@ -80,7 +79,7 @@ const allowedTypes = [
'distinguishable',
'ascii-printable',
'alphanumeric'
];
]);

const createGenerator = (generateForCustomCharacters, generateRandomBytes) => ({length, type, characters}) => {
if (!(length >= 0 && Number.isFinite(length))) {
Expand All @@ -95,7 +94,7 @@ const createGenerator = (generateForCustomCharacters, generateRandomBytes) => ({
throw new TypeError('Expected `characters` to be string');
}

if (!allowedTypes.includes(type)) {
if (!allowedTypes.has(type)) {
throw new TypeError(`Unknown type: ${type}`);
}

Expand Down Expand Up @@ -142,5 +141,8 @@ const createGenerator = (generateForCustomCharacters, generateRandomBytes) => ({
return generateForCustomCharacters(length, characters.split(''));
};

module.exports = createGenerator(generateForCustomCharacters, generateRandomBytes);
module.exports.async = createGenerator(generateForCustomCharactersAsync, generateRandomBytesAsync);
const cryptoRandomString = createGenerator(generateForCustomCharacters, generateRandomBytes);

cryptoRandomString.async = createGenerator(generateForCustomCharactersAsync, generateRandomBytesAsync);

export default cryptoRandomString;
2 changes: 1 addition & 1 deletion index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {expectType, expectError} from 'tsd';
import cryptoRandomString = require('.');
import cryptoRandomString from './index.js';

expectType<string>(cryptoRandomString({length: 10}));
expectType<string>(cryptoRandomString({length: 10, type: 'url-safe'}));
Expand Down
2 changes: 1 addition & 1 deletion license
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
"description": "Generate a cryptographically strong random string",
"license": "MIT",
"repository": "sindresorhus/crypto-random-string",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">=8"
"node": ">=12"
},
"scripts": {
"test": "xo && ava && tsd"
Expand All @@ -36,11 +39,11 @@
"protect"
],
"dependencies": {
"type-fest": "^0.8.1"
"type-fest": "^1.0.1"
},
"devDependencies": {
"ava": "^2.1.0",
"tsd": "^0.11.0",
"xo": "^0.25.3"
"ava": "^3.15.0",
"tsd": "^0.14.0",
"xo": "^0.38.2"
}
}
8 changes: 7 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ $ npm install crypto-random-string
## Usage

```js
const cryptoRandomString = require('crypto-random-string');
import cryptoRandomString from 'crypto-random-string';

cryptoRandomString({length: 10});
//=> '2cf05d94db'
Expand Down Expand Up @@ -50,6 +50,12 @@ Returns a randomized string. [Hex](https://en.wikipedia.org/wiki/Hexadecimal) by

Returns a promise which resolves to a randomized string. [Hex](https://en.wikipedia.org/wiki/Hexadecimal) by default.

For most use-cases, there's really no good reason to use this async version. From the Node.js docs:

> The `crypto.randomBytes()` method will not complete until there is sufficient entropy available. This should normally never take longer than a few milliseconds. The only time when generating the random bytes may conceivably block for a longer period of time is right after boot, when the whole system is still low on entropy.
In general, anything async comes with some overhead on it's own.

#### options

Type: `object`
Expand Down
12 changes: 6 additions & 6 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import test from 'ava';
import cryptoRandomString from '.';
import cryptoRandomString from './index.js';

// Probabilistic, result is always less than or equal to actual set size, chance it is less is below 1e-256 for sizes up to 32656
// Probabilistic, result is always less than or equal to actual set size, chance it is less is below 1e-256 for sizes up to 32656.
const generatedCharacterSetSize = (options, targetSize) => {
const set = new Set();
const length = targetSize * 640;
Expand Down Expand Up @@ -49,15 +49,15 @@ test('url-safe', t => {
t.is(cryptoRandomString({length: 0, type: 'url-safe'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'url-safe'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'url-safe'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'url-safe'}), /^[a-zA-Z\d._~-]*$/); // Sanity check, probabilistic
t.regex(cryptoRandomString({length: 100, type: 'url-safe'}), /^[\w.~-]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({type: 'url-safe'}, 66), 66);
});

test('numeric', t => {
t.is(cryptoRandomString({length: 0, type: 'numeric'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'numeric'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'numeric'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'numeric'}), /^[\d]*$/); // Sanity check, probabilistic
t.regex(cryptoRandomString({length: 100, type: 'numeric'}), /^\d*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({type: 'numeric'}, 10), 10);
});

Expand All @@ -73,7 +73,7 @@ test('ascii-printable', t => {
t.is(cryptoRandomString({length: 0, type: 'ascii-printable'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'ascii-printable'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'ascii-printable'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'ascii-printable'}), /^[!"#$%&'()*+,-./\d:;<=>?@A-Z[\\\]^_`a-z{|}~]*$/); // Sanity check, probabilistic
t.regex(cryptoRandomString({length: 100, type: 'ascii-printable'}), /^[!"#$%&'()*+,-./\w:;<=>?@[\\\]^`{|}~]*$/); // Sanity check, probabilistic
});

test('alphanumeric', t => {
Expand All @@ -95,7 +95,7 @@ test('characters', t => {

test('argument errors', t => {
t.throws(() => {
cryptoRandomString({length: Infinity});
cryptoRandomString({length: Number.POSITIVE_INFINITY});
});

t.throws(() => {
Expand Down

0 comments on commit 6e19619

Please sign in to comment.