From 3e62a526dba3b2abd7b8fdbe6d15086ff3e5e6eb Mon Sep 17 00:00:00 2001 From: Luke Pighetti Date: Thu, 1 Dec 2022 07:43:25 -0500 Subject: [PATCH 1/4] remove async --- example/nanoid_async_example.dart | 9 --------- lib/async.dart | 18 ------------------ 2 files changed, 27 deletions(-) delete mode 100644 example/nanoid_async_example.dart delete mode 100644 lib/async.dart diff --git a/example/nanoid_async_example.dart b/example/nanoid_async_example.dart deleted file mode 100644 index 58c865a..0000000 --- a/example/nanoid_async_example.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:nanoid/async.dart'; - -void main() async { - var id = await nanoid(); - print(id); - - var custom_length_id = await nanoid(10); - print(custom_length_id); -} diff --git a/lib/async.dart b/lib/async.dart deleted file mode 100644 index 7aa890a..0000000 --- a/lib/async.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'dart:math'; -import 'package:nanoid/src/url_alphabet.dart'; -export 'package:nanoid/src/url_alphabet.dart'; - -final _random = Random.secure(); - -Future nanoid([int size = 21]) async { - return customAlphabet(urlAlphabet, size); -} - -Future customAlphabet(String alphabet, int size) async { - final len = alphabet.length; - String id = ''; - while (0 < size--) { - id += alphabet[_random.nextInt(len)]; - } - return id; -} From d56cb21db4e7f57a5fdcb4f1ed5313a93cc7efcb Mon Sep 17 00:00:00 2001 From: Luke Pighetti Date: Thu, 1 Dec 2022 08:42:42 -0500 Subject: [PATCH 2/4] 2.0.0 --- .github/workflows/test.yml | 6 +- CHANGELOG.md | 9 +++ LICENSE | 2 +- README.md | 24 ++----- analysis_options.yaml | 1 + example/nanoid_example.dart | 4 +- example/nanoid_non_secure_example.dart | 9 --- lib/nanoid.dart | 43 +++++++++---- lib/non_secure.dart | 18 ------ lib/src/url_alphabet.dart | 2 - pubspec.yaml | 3 +- test/custom_alphabet_test.dart | 29 --------- test/nanoid_test.dart | 89 ++++++++++++++++++++++---- 13 files changed, 132 insertions(+), 107 deletions(-) create mode 100644 analysis_options.yaml delete mode 100644 example/nanoid_non_secure_example.dart delete mode 100644 lib/non_secure.dart delete mode 100644 lib/src/url_alphabet.dart delete mode 100644 test/custom_alphabet_test.dart diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index da27058..1b3a54a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,5 +7,7 @@ jobs: image: google/dart:latest steps: - uses: actions/checkout@v2 - - run: pub get - - run: pub run test + - run: dart pub get + - run: dart format . --set-exit-if-changed + - run: dart analyze + - run: dart test diff --git a/CHANGELOG.md b/CHANGELOG.md index 811a4ec..81018db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# [2.0.0] + +- **BREAKING:** Custom alphabet + - Use `Nanoid(alphabet: a2z).generate(10)` instead of `customAlphabet(a2z, 10)` +- **BREAKING:** Nonsecure + - Use `Nanoid(random: Random()).generate(10)` instead of importing `nanoid/non_secure.dart` and using `nanoid(10)` +- **BREAKING:** Async + - async API has been removed + # [1.0.0](https://github.com/pd4d10/nanoid-dart/compare/v0.1.0...v1.0.0) (2021-03-07) ### Features diff --git a/LICENSE b/LICENSE index 6bb9fba..592565e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Rongjian Zhang +Copyright (c) 2022 Rongjian Zhang Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4bbd4e7..8e48c4d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ import 'package:nanoid/nanoid.dart'; void main() { var id = nanoid(); - var custom_length_id = nanoid(10); + var customLengthId = nanoid(10); // ... } ``` @@ -29,31 +29,21 @@ void main() { import 'package:nanoid/nanoid.dart'; void main() { - var id = customAlphabet('1234567890abcdef', 10); + var hexNanoid = Nanoid(alphabet: '1234567890abcdef'); + var id = hexNanoid(10); // ... } ``` -### Async API - -```dart -import 'package:nanoid/async.dart'; - -void main() async { - var id = await nanoid(); - var custom_length_id = await nanoid(10); - // ... -} -``` - -### Non-secure API +### Non-secure ```dart import 'package:nanoid/non_secure.dart'; void main() { - var non_secure_id = nanoid(); - var custom_length_id = nanoid(10); + var nonsecureNanoid = Nanoid(random: Random()); + var nonsecureId = nonsecureNanoid(); + var customLengthId = nonsecureNanoid(10); // ... } ``` diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..572dd23 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lints/recommended.yaml diff --git a/example/nanoid_example.dart b/example/nanoid_example.dart index cf59064..c3ca25e 100644 --- a/example/nanoid_example.dart +++ b/example/nanoid_example.dart @@ -4,6 +4,6 @@ void main() { var id = nanoid(); print(id); - var custom_length_id = nanoid(10); - print(custom_length_id); + var customLengthId = nanoid(10); + print(customLengthId); } diff --git a/example/nanoid_non_secure_example.dart b/example/nanoid_non_secure_example.dart deleted file mode 100644 index f5b2be3..0000000 --- a/example/nanoid_non_secure_example.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:nanoid/non_secure.dart'; - -void main() { - var non_secure_id = nanoid(); - print(non_secure_id); - - var custom_length_id = nanoid(10); - print(custom_length_id); -} diff --git a/lib/nanoid.dart b/lib/nanoid.dart index 18c683e..dd2f4e3 100644 --- a/lib/nanoid.dart +++ b/lib/nanoid.dart @@ -1,18 +1,37 @@ import 'dart:math'; -import 'package:nanoid/src/url_alphabet.dart'; -export 'package:nanoid/src/url_alphabet.dart'; -final _random = Random.secure(); +/// A convenience function for generating a secure nanoid +/// +/// ```dart +/// final id = nanoid(5); +/// print(id); // a5g4z +/// ``` +final nanoid = Nanoid(); -String nanoid([int size = 21]) { - return customAlphabet(urlAlphabet, size); -} +class Nanoid { + /// The source alphabet to use for generating a nanoid + final String alphabet; + + final Random _random; + + /// Create a secure nanoid generator + Nanoid({this.alphabet = urlSafeAlphabet, Random? random}) + : _random = random ?? Random.secure(); -String customAlphabet(String alphabet, int size) { - final len = alphabet.length; - String id = ''; - while (0 < size--) { - id += alphabet[_random.nextInt(len)]; + /// Convenience caller for `nanoid` shorthand + String call([int size = 21]) => generate(size); + + /// Generate a nanoid with a given size + String generate([int size = 21]) { + final len = alphabet.length; + final buffer = StringBuffer(); + while (0 < size--) { + buffer.write(alphabet[_random.nextInt(len)]); + } + return buffer.toString(); } - return id; + + /// The default alphabet used for generating a nanoid. Contains [a-zA-Z0-9_-] + static const urlSafeAlphabet = + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'; } diff --git a/lib/non_secure.dart b/lib/non_secure.dart deleted file mode 100644 index 7276d50..0000000 --- a/lib/non_secure.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'dart:math'; -import 'package:nanoid/src/url_alphabet.dart'; -export 'package:nanoid/src/url_alphabet.dart'; - -final _random = Random(); - -String nanoid([int size = 21]) { - return customAlphabet(urlAlphabet, size); -} - -String customAlphabet(String alphabet, int size) { - final len = alphabet.length; - String id = ''; - while (0 < size--) { - id += alphabet[_random.nextInt(len)]; - } - return id; -} diff --git a/lib/src/url_alphabet.dart b/lib/src/url_alphabet.dart deleted file mode 100644 index 6014040..0000000 --- a/lib/src/url_alphabet.dart +++ /dev/null @@ -1,2 +0,0 @@ -const urlAlphabet = - 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW'; diff --git a/pubspec.yaml b/pubspec.yaml index 79fa8ef..010e2bf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: nanoid -version: 1.0.0 +version: 2.0.0 description: A tiny, secure, URL-friendly, unique string ID generator. Dart implementation of ai/nanoid homepage: https://github.com/pd4d10/nanoid-dart @@ -7,4 +7,5 @@ environment: sdk: ">=2.12.0 <3.0.0" dev_dependencies: + lints: ^2.0.1 test: ^1.16.4 diff --git a/test/custom_alphabet_test.dart b/test/custom_alphabet_test.dart deleted file mode 100644 index a278b9c..0000000 --- a/test/custom_alphabet_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:test/test.dart'; -import 'package:nanoid/nanoid.dart'; - -void main() { - test('has options', () { - expect(customAlphabet('a', 5), equals('aaaaa')); - }); - - test('has flat distribution', () { - var count = 100 * 1000; - var length = 5; - var alphabet = 'abcdefghijklmnopqrstuvwxyz'; - - var chars = {}; - for (var i = 0; i < count; i++) { - var id = customAlphabet(alphabet, length); - for (var j = 0; j < id.length; j++) { - var char = id[j]; - if (chars[char] == null) chars[char] = 0; - chars[char] += 1; - } - } - - chars.forEach((k, _) { - var distribution = (chars[k] * alphabet.length) / (count * length); - expect(distribution, closeTo(1, 1)); - }); - }); -} diff --git a/test/nanoid_test.dart b/test/nanoid_test.dart index eb7fa7d..267db15 100644 --- a/test/nanoid_test.dart +++ b/test/nanoid_test.dart @@ -1,24 +1,85 @@ +import 'dart:math' show Random; + import 'package:test/test.dart'; import 'package:nanoid/nanoid.dart'; void main() { - test('generates URL-friendly IDs', () { - for (var i = 0; i < 10; i++) { - var id = nanoid(); - expect(id.length, equals(21)); - for (var j = 0; j < id.length; j++) { - expect(urlAlphabet.contains(id[j]), equals(true)); + group('nanoid', () { + test('generates URL-friendly IDs', () { + for (var i = 0; i < 10; i++) { + var id = nanoid(); + expect(id.length, equals(21)); + for (var j = 0; j < id.length; j++) { + expect(Nanoid.urlSafeAlphabet.contains(id[j]), equals(true)); + } + } + }); + + test('has no collisions', () { + var count = 100 * 1000; + var used = {}; + for (var i = 0; i < count; i++) { + var id = nanoid(); + expect(used[id], equals(null)); + used[id] = true; + } + }); + }); + + group('custom alphabet', () { + String customAlphabet(String alphabet, int length) => + Nanoid(alphabet: alphabet).generate(length); + + test('has options', () { + expect(customAlphabet('a', 5), equals('aaaaa')); + }); + + test('has flat distribution', () { + var count = 100 * 1000; + var length = 5; + var alphabet = 'abcdefghijklmnopqrstuvwxyz'; + + var chars = {}; + for (var i = 0; i < count; i++) { + var id = customAlphabet(alphabet, length); + for (var j = 0; j < id.length; j++) { + var char = id[j]; + if (chars[char] == null) chars[char] = 0; + chars[char] += 1; + } } - } + + chars.forEach((k, _) { + var distribution = (chars[k] * alphabet.length) / (count * length); + expect(distribution, closeTo(1, 1)); + }); + }); + }); + + test('urlSafeAlphabet', () { + expect(Nanoid.urlSafeAlphabet, matches(RegExp(r'[a-zA-Z0-9_-]'))); }); - test('has no collisions', () { - var count = 100 * 1000; - var used = {}; - for (var i = 0; i < count; i++) { + group('readme examples', () { + test('normal', () { var id = nanoid(); - expect(used[id], equals(null)); - used[id] = true; - } + expect(id.isNotEmpty, isTrue); + + var customLengthId = nanoid(10); + expect(customLengthId.length, equals(10)); + }); + + test('custom alphabet or length', () { + var hexNanoid = Nanoid(alphabet: '1234567890abcdef'); + var id = hexNanoid(10); + expect(id, matches(RegExp(r'^[a-z0-9]+$'))); + expect(id.length, equals(10)); + }); + + test('non-secure', () { + var nonsecureNanoid = Nanoid(random: Random()); + var id = nonsecureNanoid(10); + expect(id.length, equals(10)); + }); }); } From 1e472afda847a4e007a1e038b685cc312b525adf Mon Sep 17 00:00:00 2001 From: Luke Pighetti Date: Thu, 1 Dec 2022 08:48:57 -0500 Subject: [PATCH 3/4] clarify member doc --- lib/nanoid.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nanoid.dart b/lib/nanoid.dart index dd2f4e3..84a4b49 100644 --- a/lib/nanoid.dart +++ b/lib/nanoid.dart @@ -14,7 +14,7 @@ class Nanoid { final Random _random; - /// Create a secure nanoid generator + /// Create a nanoid generator that is secure by default Nanoid({this.alphabet = urlSafeAlphabet, Random? random}) : _random = random ?? Random.secure(); From 42262f392d05733d34aaf7b49222d0cc2db53172 Mon Sep 17 00:00:00 2001 From: Luke Pighetti Date: Thu, 1 Dec 2022 08:51:54 -0500 Subject: [PATCH 4/4] clarify member docs --- lib/nanoid.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nanoid.dart b/lib/nanoid.dart index 84a4b49..9eded9a 100644 --- a/lib/nanoid.dart +++ b/lib/nanoid.dart @@ -14,11 +14,11 @@ class Nanoid { final Random _random; - /// Create a nanoid generator that is secure by default + /// A nanoid generator that is secure by default Nanoid({this.alphabet = urlSafeAlphabet, Random? random}) : _random = random ?? Random.secure(); - /// Convenience caller for `nanoid` shorthand + /// Convenience caller for `nanoid()` shorthand String call([int size = 21]) => generate(size); /// Generate a nanoid with a given size