@jaypie/fabricator
Prerequisites: npm install @jaypie/fabricator
Status: Experimental - APIs may change
Overview
Section titled âOverviewâ@jaypie/fabricator provides deterministic test data generation with seeding support, built on Faker.js with Jaypie conventions.
Installation
Section titled âInstallationânpm install @jaypie/fabricatorQuick Reference
Section titled âQuick ReferenceâExports
Section titled âExportsâ| Export | Purpose |
|---|---|
Fabricator |
Base class for data generation |
fabricator |
Factory function |
EventFabricator |
Temporal event generation |
CHANCE |
Probability constants |
CHANCE Constants
Section titled âCHANCE Constantsâ| Constant | Value | Description |
|---|---|---|
UNCOMMON |
0.236 | ~1 in 4 |
RARE |
0.146 | ~1 in 7 |
EPIC |
0.021 | ~1 in 50 |
LEGENDARY |
0.005 | ~1 in 200 |
Basic Usage
Section titled âBasic UsageâCreate Fabricator
Section titled âCreate Fabricatorâimport { fabricator } from "@jaypie/fabricator";
const fab = fabricator("seed-123");
fab.person.firstName(); // Always same for seedfab.person.lastName();fab.internet.email();Deterministic Output
Section titled âDeterministic Outputâconst fab1 = fabricator("seed-123");const fab2 = fabricator("seed-123");
fab1.person.firstName() === fab2.person.firstName(); // trueRandom Numbers
Section titled âRandom NumbersâBasic Random
Section titled âBasic Randomâconst fab = fabricator("seed");
fab.random(); // 0-1fab.random({ min: 1, max: 100 }); // 1-100fab.random({ integer: true }); // Whole numberPrecision
Section titled âPrecisionâfab.random({ precision: 2 }); // 0.00-1.00fab.random({ min: 0, max: 100, precision: 2 }); // 0.00-100.00Normal Distribution
Section titled âNormal Distributionâfab.random({ min: 0, max: 100, distribution: "normal", mean: 50, stdDev: 15,});Currency
Section titled âCurrencyâconst price = fab.random({ min: 10, max: 1000, precision: 2,});// 123.45Word Generation
Section titled âWord GenerationâTwo-Word Combinations
Section titled âTwo-Word Combinationsâimport { Fabricator } from "@jaypie/fabricator";
const fab = new Fabricator("seed");
fab.generate.words(); // "swift eagle"fab.generate.words(3); // "swift eagle dance"Corpus Generation
Section titled âCorpus GenerationâGenerate deterministic prose for fixtures, snapshots, or seeded benchmarks.
Basic Usage
Section titled âBasic Usageâconst fab = fabricator("seed");
fab.corpus(); // 108 words of English-ish prose (default)fab.corpus(1000); // 1000 wordsfab.corpus({ wordsPerPeriod: 10 });fab.corpus(500, { typoRate: 0.20 });Determinism
Section titled âDeterminismâ- Each call advances the fabricatorâs faker state, so successive calls with the same parameters return different output.
- Replaying from a fresh
fabricator(seed)reproduces the same sequence. - Word counts and options are folded into the per-call seed, so different parameters produce independent streams â
corpus(100)andcorpus(101)differ across the whole text, not by one word.
Custom Corpus
Section titled âCustom CorpusâMix domain vocabulary into the output. By default the custom pool blends 50/50 with default English; typo and phonotactic invention rates stay at their defaults.
fab.corpus(500, { corpus: deployLogText });fab.corpus(500, { words: [["deploy", 5], ["lambda", 2]] });fab.corpus(500, { corpus: deployLogText, blend: 0.7 });fab.corpus(500, { corpus: deployLogText, replaceDefaults: true });Custom Token Functions
Section titled âCustom Token FunctionsâFor tokens that arenât word-shaped (UUIDs, dollar amounts, IDs), pass functions. Each function receives the fabricator and emits one token per draw. The weight is the share of total content tokens taken from the main word stream.
// Single function â shorthandfab.corpus(500, { functions: [({ fab }) => fab.string.uuid(), 0.03],});
// Multiple functionsfab.corpus(500, { functions: [ [({ fab }) => fab.string.uuid(), 0.03], [({ fab }) => "$" + fab.finance.amount(), 0.04], [({ fab }) => fab.internet.email(), 0.02], ],});Person Generation
Section titled âPerson GenerationâBasic Person
Section titled âBasic Personâconst person = fab.generate.person();// {// firstName: "Alice",// lastName: "Smith",// email: "alice.smith@example.com",// phone: "+1-555-123-4567"// }With Variations
Section titled âWith Variationsâconst person = fab.generate.person({ includeMiddleName: CHANCE.UNCOMMON, includeNickname: CHANCE.RARE,});Custom Fabricator
Section titled âCustom FabricatorâExtend for Domain
Section titled âExtend for Domainâimport { Fabricator } from "@jaypie/fabricator";
class UserFabricator extends Fabricator { user() { return { id: this.string.uuid(), name: this.person.fullName(), email: this.internet.email(), createdAt: this.date.recent(), role: this.helpers.arrayElement(["admin", "user", "guest"]), }; }
users(count: number) { return Array.from({ length: count }, () => this.user()); }}
const fab = new UserFabricator("seed");const users = fab.users(10);Event Fabricator
Section titled âEvent FabricatorâGenerate temporal event sequences.
Basic Events
Section titled âBasic Eventsâimport { EventFabricator } from "@jaypie/fabricator";
const events = new EventFabricator("seed", { startDate: new Date("2024-01-01"), endDate: new Date("2024-12-31"),});
const loginEvents = events.generate({ type: "login", count: 100, distribution: "uniform",});Weighted Time Distribution
Section titled âWeighted Time Distributionâconst events = events.generate({ type: "purchase", count: 50, distribution: "weighted", weights: { morning: 0.3, // 6am-12pm afternoon: 0.4, // 12pm-6pm evening: 0.25, // 6pm-10pm night: 0.05, // 10pm-6am },});Derived Events
Section titled âDerived EventsâEvents that follow other events:
const purchases = events.generate({ type: "purchase", count: 100,});
const refunds = events.derive(purchases, { type: "refund", probability: 0.05, // 5% of purchases delay: { min: 1, max: 30, unit: "days" },});Event Templates
Section titled âEvent Templatesâconst events = events.generate({ type: "order", count: 100, template: (fab, timestamp) => ({ id: fab.string.uuid(), timestamp, amount: fab.random({ min: 10, max: 500, precision: 2 }), items: fab.random({ min: 1, max: 5, integer: true }), }),});Probability Patterns
Section titled âProbability PatternsâConditional Fields
Section titled âConditional Fieldsâconst user = { name: fab.person.fullName(), email: fab.internet.email(), // Include phone ~24% of time ...(fab.random() < CHANCE.UNCOMMON && { phone: fab.phone.number(), }),};Weighted Selection
Section titled âWeighted Selectionâconst status = fab.helpers.weightedArrayElement([ { value: "active", weight: 0.7 }, { value: "pending", weight: 0.2 }, { value: "inactive", weight: 0.1 },]);Faker Access
Section titled âFaker AccessâAccess underlying Faker modules:
const fab = fabricator("seed");
fab.person.firstName();fab.person.lastName();fab.internet.email();fab.internet.url();fab.date.recent();fab.date.past();fab.string.uuid();fab.number.int({ min: 1, max: 100 });Testing Usage
Section titled âTesting Usageâdescribe("User Service", () => { const fab = fabricator("test-seed");
it("creates user", async () => { const userData = { name: fab.person.fullName(), email: fab.internet.email(), };
const user = await createUser(userData);
expect(user.name).toBe(userData.name); });});Related
Section titled âRelatedâ- @jaypie/testkit - Testing utilities
- Testing - Testing guide