rand 5.0.1
rand: ^5.0.1 copied to clipboard
Seedable test-data generator: names, emails, IPs, UUIDv4/v7, ULID, hex, slugs, digits, semver, lorem, CSS colors, geo, weighted samples, CSPRNG tokens. Pure Dart. Agent skill.
Changelog #
5.0.1 - 2026-10-16 #
Fixed #
Rand.sampledocumentation: the example weights are now[1, 10, 89], so the quoted 1%, 10% and 89% odds are exact.
Changed #
- The README opens with what the package does, why to use it and a short example. Every Dart sample in the README and the agent skill is analyzed with the package's lints and fits pub.dev without scrolling sideways.
5.0.0 - 2026-10-15 #
Breaking #
CssColors.isDarkis now a direct getter onCssColors(removes theCssColorsXextension).Rand.integeris half-open,[min, max), likeRandom.nextIntand the other range methods (was inclusive on both ends). The default range is unchanged ([0, 2^31)) and the maximum span is now2^32.Rand.float()defaults to[0, 1), likeRandom.nextDouble(was[0, double.maxFinite)). Aminabove 1 without amaxnow throwsArgumentError.Rand.integer,Rand.float,Rand.durationandRand.dateTimethrowArgumentErroron an empty range (min >= max), likeRandom.nextInt(0), instead of returningminwithout a draw.floatcompares its bounds as doubles, so two distinctintbounds that round to the samedouble(above 2^53) also throw.dateTime(min: t)needstbefore 2038-01-01, anddateTime(max: t)needstafter 1970-01-01. Reverses a 4.3.0 decision.Rand.otpis renamedRand.digits(same output). The old name suggested a one-time-code primitive, but the digits come from the seedable RNG.Rand.nullabletakes its chance as a named parameter:Rand.nullable(value, nullChance: 90). The positional form read likeboolean's chance with the opposite meaning.Rand.uuidV7andRand.ulidrequiretime. Defaulting toDateTime.now()made a seeded ID change on every run; pass a fixed instant for snapshot-stable IDs orDateTime.now()for a live clock.Rand.samplerequiresweights.length == from.length(extra weights were ignored, hiding a weights list that drifted out of line withfrom), and throwsStateErrorfor an emptyfromwith a positivecount(returned[], unlikeelement). Weights are validated before the empty-pool check. Reverses two 4.3.0 decisions.Rand.noncerejects alengthbelow 1, likehex,base64anddigits(nonce(length: 0)returned an empty token). Reverses a 4.3.0 decision.Rand.sentence(count: 0)returns''(threw), likewords,paragraphandarticle: counts accept 0, single-token generators need at least 1.- One parameter style across the API: the value or collection a call works on
stays positional, and every option (count, length, precision, chance, bounds,
weights) is named. Seeded output is unchanged. Migrate (same on
RandGen):boolean(90)→boolean(trueChance: 90), likenullable(value, nullChance: 90).latitude(2)/longitude(2)→latitude(precision: 2)/longitude(precision: 2), likegeoPoint.sentence(2)/paragraph(2)/article(2)→sentence(count: 2)etc., likewords.bytes(32)→bytes(length: 32), likenonce,hexanddigits.dateTime(a, b)→dateTime(min: a, max: b), likeinteger,floatandduration;dateTime(null, b)→dateTime(max: b). Error messages namemin/max.sample(from: list, count: n)→sample(list, count: n), likeelement,shuffledandsubset.subSet(set, n)→subset(set, count: n)(Dart naming).
- The top-level
base62constant is nowRand.base62Alphabet, so abase62in your own code no longer collides with the package's. - Seeded output changes for
integercalls with an explicitmax(each draw is nownextInt(max - min)) and forfloat()/float(min: …)without amax. Other seeded output is unchanged, including methods that draw bounded integers internally (semver,email,ipv4, and the default lengths ofwords,paragraph,article) and bareinteger().
Added #
RandGen.seeded([seed])— convenience constructor forRandGen(Random(seed))without importingdart:math.
Changed #
Rand.semvervalidatesmaxMajor,maxMinor, andmaxPatchupfront (naming the offending parameter) before drawing from the RNG.Rand.slugvalidateswordCountupfront (naming'wordCount') before drawing from the RNG.Rand.emailthrowsArgumentErrornaming'domain'whendomainis empty or contains'@'.Rand.samplevalidatesweightseven whencount == 0(whenfromis non-empty).Rand.digits,Rand.sentence,Rand.slug,Rand.hex,Rand.password,Rand.base64, andRand.samplepopulateArgumentError.nameon invalid arguments.Rand.dateTimereversed-range error messages format timestamps in UTC (toUtc()).- The
sampleanduseRngdocs recommendRandGen(Random.secure())for a one-off secure draw instead of swapping the global RNG, which also clearscurrentSeed.
Fixed #
Rand.mapValueno longer performs a secondaryfrom[key]lookup, fixing throws on maps withdouble.nankeys and ensuringRand.mapValue({})/Rand.mapEntry({})report their own method names inStateError.
4.3.0 - 2026-10-04 #
Added #
RandGen— the non-cryptographic API as an instance over your ownRandom:RandGen(Random(1)).fullName(). Independent instances are independent streams.Rand.withSeed(seed, body)— runsbodywith every non-cryptographicRand.*call drawing fromRandom(seed). Zone-scoped: follows async continuations, nests, and never touches the global RNG.Rand.seed()without a value picks a random seed;Rand.currentSeedreports it (setUp(() { Rand.seed(); printOnFailure('Rand seed: ${Rand.currentSeed}'); })).- Seedable test IDs:
Rand.uuidV4(),Rand.uuidV7({time}),Rand.ulid({time})(also onRandGen). Drawn from the non-cryptographic RNG, so reproducible underseed/withSeed;timedefaults to now; not monotonic within a millisecond. Production IDs →package:uuid.
Changed #
- Requires Dart 3.13 / Flutter 3.47 (was Dart
>=3.0.0). samplethrowsArgumentErrornamingweightsfor negative weights, all-zero weights, or weights summing past 2^32 (was a silent skew or an unnamed error).- Seeded
charCodesequences change (now uniform over base62). - Seeded default
emaildomains change:test.com,demo.dev,sample.app,fake.iobecameacme.test,demo.test,sample.test,fake.test. paragraph/articletext changes: sentences are joined by" "(single periods).- Seeded
fullNameoutput changes wherever a middle or last name would have repeated an earlier part: a fresh name is drawn instead, which also shifts every later draw from that seeded stream. - Negative counts and lengths throw
ArgumentErrornaming the parameter:words,paragraph,article,subSet,sample,bytes,nonce. A count or length of 0 still returns an empty result. durationanddateTimethrowArgumentErroron reversed ranges, includingdateTime(start)withstartafter 2038-01-01 and noend(was a silently reversed range).latitude,longitudeandgeoPointthrowRangeErroroutside precision 0..15.- NaN
boolean/nullablechances and non-finitefloatbounds throwArgumentError; chance errors nametrueChanceornullChance(a badnullablechance used to reporttrueChance). - Seeded
durationanddateTimevalues change: negative and pre-1970 ranges are floored (were truncated toward zero), and a draw that rounded up tomaxon a positive range now returnsmax− 1 µs. - Seeded
floatdraws that rounded to exactlymaxon a narrow range now returnmin. integerspan errors are a plainArgumentErrornamingmax(was aRangeErrornamingdifference), soon RangeErrorhandlers no longer catch them.float,durationanddateTimeno longer consume a draw whenmin == max, so later draws from a seeded stream that makes such calls shift.- Agent skill directory renamed
skills/dart-rand→skills/rand-test-data(installable withdart run skills@ get --package rand --all).
Fixed #
samplewithweightslonger thanfromno longer throwsRangeError; the extra weights are ignored, as documented.samplewith an emptyfromreturns a growable list.nonce,secureCharCodeandcharCodeare uniform over base62. Digits were 33 % of characters instead of 16 %, so a 16-char nonce had 78.5 bits of min-entropy instead of ~95.- Default
emaildomains are all RFC 2606 reserved;test.com,demo.dev,sample.appandfake.ioare real domains. paragraphandarticleno longer emit..between sentences.fullNamenever repeats a name within one result.- Non-cryptographic methods no longer create
Random.secure(), so they work where it is unavailable (e.g.dart test -p node). - Half-open
[min, max)holds for everydurationanddateTimerange. Truncation toward zero could returnmaxand neverminon negative and pre-1970 ranges, and rounding could returnmaxon narrow positive ones (a 1 µs range returnedmaxin ~14 % of draws). floatreturns exactlyminwhenmin == max(could be off by one ulp).floatnever returnsmax. On narrow ranges the interpolation could round to exactlymax(adjacent doubles: a quarter to three quarters of draws).integeraccepts spans up to 2^32 − 1 (was 2^31 − 1).bytesdraws 4 bytes per CSPRNG call.dateTime's documented default end is 2038-01-01 (was documented as 2038-01-19).- The agent skill's networking snippet compiles (named arguments, not set literals).
- README: corpus size (167 unique words, not 1023), the
subSetpitfall (a list literal is a compile error), example values, and the reason to seed insetUpcorrected.
Removed #
SECURITY.md(no private vulnerability-report channel; the crypto-scope guidance is in the README).
4.2.0 #
Multi-sentence lorem. No breaking changes.
Added #
- Text —
Rand.sentence([count])accepts an optional count and returns that many unique sentences joined by" ", drawn viasubSetfrom the 856-sentence corpus.Rand.sentence()is unchanged. ThrowsArgumentErrorbelow 1,RangeErrorabove the corpus size — unlikeparagraph(count), which allows repeats.
4.1.1 #
Performance optimizations and bug fixes.
Fixed #
- Correctness — Fixed
Rand.boolean()to respect double-precision probabilities instead of rounding. - Correctness — Fixed
Rand.dateTime()to correctly return a UTCDateTimerepresentation as documented. - Correctness — Guaranteed representation of all enabled character sets in
Rand.password(). - Correctness — Fixed potential double overflow in boundary calculations.
- Performance — Removed expensive string format/parsing roundtrips in latitude/longitude calculations.
- Performance — Optimized
Rand.subSet()set traversal complexity using Fisher-Yates list partition. - Performance — Library-level caching for CSS colors and unique words to avoid dynamic allocations and repeated lazy filtering.
- Performance & Memory — Single-pass buffer allocation using
Uint16Listand directUint8Listpopulations in cryptographic and networking primitives. - Optimization — Converted all data corpus variables to
constlists.
4.1.0 #
Identity & networking test data. 12 new primitives, no breaking changes.
Added #
- Networking —
Rand.email({domain}),Rand.ipv4(),Rand.ipv6(),Rand.mac({separator}),Rand.hex({length}).emaildefaults to RFC 2606 example/test TLDs (example.com,test.com, etc.) — fixture-safe.ipv6is returned in full uncompressed form so length is stable.hexis general-purpose lowercase hex (git SHAs atlength: 40, ETags, etc.) and reproducible underRand.seed. - String synthesis —
Rand.semver({maxMajor, maxMinor, maxPatch})(no pre-release suffix),Rand.otp({length})(zero-padded decimal digits),Rand.slug({wordCount, separator})(unique lorem words),Rand.base64({byteLength})(crypto-secure parallel tononce). - Collection ergonomics —
Rand.enumValue<T extends Enum>(values)(type-safe wrapper overelementfor enums) andRand.shuffled<T>(list)(non-mutating copy + shuffle; distinct fromsample/subSet). - Geo —
Rand.geoPoint({precision})returns a named record({double lat, double lng})composinglatitude+longitude. - New mixin
_Networkingunderlib/src/_networking.dart. - Example app (
example/main.dart) gains Networking section and uses the new methods in Geo, Collections, and Cryptographic sections.
Changed #
- README adds a Networking section and extends Collections with
enumValue/shuffledrows. SKILL.md description and "Picking the right call" table updated to cover the new methods.
4.0.0 #
Breaking — major overhaul.
Bundles bug fixes, modern Dart conventions, mixin-based internal layout, and an
LLM-focused polish pass matching fluiver and collection_notifiers. Ships a
description-triggered LLM skill at skills/dart-rand/SKILL.md (folder named
dart-rand to avoid colliding with other languages' rand namespaces).
Breaking #
| v3.x | v4.0 |
|---|---|
CSSColors (enum) |
CssColors — modern Dart PascalCase |
c.color (int field) |
c.argb — clarifies it's a 32-bit ARGB packed int |
c.isDark (stored field) |
c.isDark (computed via CssColorsX extension, YIQ luminance) |
Rand.bytes(32, true) / Rand.bytes(32, secure: true) |
Rand.bytes(32) — always secure |
Rand.nonce(secure: true) |
Rand.nonce() — always secure |
Rand.subSet([1, 2, 2], 2) |
Rand.subSet({1, 2}, 2) — Set<T> only |
Rand.sample(..., secure: true) |
Rand.useRng(Random.secure()); Rand.sample(...) |
Rand.element([]) → RangeError |
Rand.element([]) → StateError |
Fixed #
Rand.nonce()now returns a true base62 string. The v3 implementation usedRandom.secure().nextInt(256)and produced arbitrary byte codepoints including control characters and surrogates despite documentation saying "base62 string."Rand.durationandRand.dateTimedartdoc now spells out the half-open[min, max)upper bound. Tests for both methods previously assertedinMicroseconds > minstrictly; the underlying_lerpreturns exactlyminwhennextDouble()returns 0, so the strict comparison was a flake waiting to happen. Both tests now use>=.Rand.element(Iterable)on an empty input now throwsStateError('Rand.element: cannot draw from empty iterable')instead of the crypticRangeError: 0.Rand.mapKey({})/Rand.mapValue({})/Rand.mapEntry({})get the same treatment.base62constant is no longer marked@visibleForTesting— it's a real public constant, exported as such.
Added #
Rand.useRng(Random rng)— replaces the global non-cryptographic RNG.Rand.seed(value)is now a shortcut foruseRng(Random(value)).CssColors implements Comparable<CssColors>— sort by named-color order.CssColorsXextension exposingisDarkas a computed getter (YIQ luminance fromargb). Replaces the hand-curatedisDarkfield. Some borderline colors may flip classification vs v3.skills/dart-rand/SKILL.md— tool-agnostic LLM skill. Description-triggered (activates only when the user's task matches its scope), so it stays out of the way for unrelated work. Folder nameddart-randto avoid colliding with other languages'randnamespaces. Vendor to~/.claude/skills/dart-rand/or.claude/skills/dart-rand/.- GitHub Actions CI (format, analyze, test on stable+beta matrix, coverage, pana, example analyze) and tag-triggered OIDC publish workflow.
SECURITY.mdwith a scope-of-security statement and private vulnerability-reporting flow.makefile,codecov.yml, PR template, bug/feature issue templates, dependabot config.pubspec.yamldeclaresplatforms:(android, ios, linux, macos, web, windows) anddocumentation:URL.- Heavy dartdoc on every public
Rand.*method with fenced examples, range notation ([min, max]inclusive vs[min, max)half-open spelled out),Throwsclauses, andSee also:cross-references. - Test coverage for seed reproducibility,
useRngequivalence, distribution uniformity, and crypto-methods-ignore-seed invariants.
Changed #
- File layout:
lib/rand.dartis now the class shell with 32 static delegators and the heavy dartdoc. Real implementation lives in per-category mixins underlib/src/_*.dart(_Booleans,_Numbers,_Crypto,_Time,_Collections,_Sampling,_Text,_Identity,_Colors)._RandImplcomposes them and holdsrng+secureRngfields. - README rewritten — no emoji, code-heavy, ~250 lines. Adds "What it's for" and
"What it isn't" framing and a
Color(c.argb)Flutter-usage note. topics:— dropfaker(misleading), addfixtures.analysis_options.yaml— comment explains whylib/data/*.dartis excluded (static corpora, no actionable lint signal, faster analyzer).
Removed #
metadependency — no longer needed after dropping@visibleForTesting.example/.metadata— stray Flutter project artifact from a reverted Flutter conversion (commit7ccb947).secure:parameter onRand.bytes,Rand.nonce, andRand.sample. The first two are now always secure; for a securesample, switch the global RNG first viaRand.useRng(Random.secure()).
3.1.0 #
duration()now uses named parameters:duration(max:, min:)nullable()parameter renamed:probability→nullChanceboolean()parameter renamed:probability→trueChance- Removed
id()— usenonce()(now has default length of 16) latitude()/longitude()now use decimal places (not significant figures)
3.0.2 #
- Not documented.
3.0.1 #
integer()andfloat()now use named parameters (min:,max:)sample()replacesweightedRandomizedArray()charCode()andsecureCharCode()replacechar()andcharSecure()- Removed
dateTimeYear()— usedateTime(DateTime(year1), DateTime(year2)) - Collection params renamed to
from - Password params:
lowercase,uppercase,digits,symbols color(),colorDark(),colorLight()for CSS colorsCSSColorsenum with 148 named colorsArgumentErrorexceptions instead of assertions- Comprehensive tests with
checkspackage
3.0.0 #
- Not documented.
2.0.3 #
- Updated dependencies
2.0.2+2 #
- Not documented.
2.0.2+1 #
- Not documented.
2.0.2 #
- Fixed
boolean()regression - Fixed max int for web
2.0.1 #
- Fixed
nullable()default value
2.0.0 #
- Removed
documentId,uid— useid() - Renamed
mayBeNull→nullable - Added
alias,firstName,lastName,city,latitude,longitude
1.0.3 #
- Not documented.
1.0.2 #
- Not documented.
1.0.1 #
- Not documented.
1.0.0 #
- Initial release