nanoid function
This generator function create a tiny, secure, URL-friendly, unique string ID
The length
of the nanoid is adjustable (default is 21 characters).
The characters are taken from alphabet
(Defaults to Alphabet.url [a-zA-Z0-9_-]
) at random
order.
Examples:
BGmaV2KoFx0Ar2yS6zMDc
TZGlaZw38c43IILQQ-Jxc
n_vyOfT-Q9hwWyYQZSYop
nMbnyHZiCV_NGgXNdANLX
0hpndh5fAcjBU3ZTABFdR
nonoid uses Random.secure by default. When platforms don't support it, it falls back to Random.
For predictable ID generation during tests, you can pass a seeded random
number generator.
final random = Random(42);
for (int i = 0; i < 3; i++) {
final id = nanoid(random: random);
print(id);
}
// NI2rPCdXKSZyNNboBnBIy
// oduoyIeuj6itVcufRe11I
// 8rnfaUlBaqZ97p13lEhsT
Implementation
String nanoid({
int length = 21,
String? alphabet,
Random? random,
}) {
if (length < 2) {
throw ArgumentError.value(
length,
"length",
"Length must be greater than 2",
);
}
if (length > 255) {
throw ArgumentError.value(length, "length", "Length must be less than 255");
}
int i = length;
if (alphabet != null && alphabet.isEmpty) {
throw ArgumentError.value(
alphabet,
"alphabet",
"Alphabet must not be empty",
);
}
final String characters = alphabet ?? Alphabet.url;
final int alphabetSize = characters.length;
assert(alphabetSize > 0);
final Random secureRandom = random ?? Random.secure();
Random? insecureRandom;
int nextRandomIndex() {
try {
return secureRandom.nextInt(alphabetSize);
// ignore: avoid_catching_errors
} on UnsupportedError {
// Random.secure() is not supported on this platform, fallback to the insecure version
insecureRandom ??= Random();
return insecureRandom!.nextInt(alphabetSize);
}
}
final sb = StringBuffer();
while (0 < i--) {
final randomIndex = nextRandomIndex();
final character = characters[randomIndex];
sb.write(character);
}
return sb.toString();
}