ForgeData

Documentation

Everything you need to install, seed, extend, and ship fake data with ForgeData.

Getting Started

npm install @sahinur/forgedata
import { ForgeData } from "@sahinur/forgedata";

const forge = new ForgeData();
console.log(forge.person.fullName());
console.log(forge.internet.email());

ForgeData is a plain class — create as many independent instances as you like. Each instance owns its own random stream, so seeding one never affects another. There's also a ready-made default instance for quick scripts:

import { forge } from "@sahinur/forgedata";
console.log(forge.person.fullName());

Deterministic Seeding

const forge = new ForgeData({ seed: 42 });
forge.person.fullName(); // always the same value for seed 42

forge.seed(42); // reseed an existing instance

Seeds accept a number or a string (strings are hashed into a seed), so you can seed with something readable like a test name.

Locales

const forge = new ForgeData({ locale: "ja" });
forge.person.fullName(); // Japanese name pool

forge.locale("fr"); // switch at runtime
forge.locale();     // "fr" — read the current locale

Built-in locales: en, bn (Bangla), hi (Hindi), ar (Arabic), ja (Japanese), fr (French), de (German), es (Spanish), zh (Chinese).

forge.defineLocale({
  code: "pirate",
  name: "Pirate",
  person: {
    firstNamesMale: ["Blackbeard", "Redbeard"],
    firstNamesFemale: ["Anne", "Mary"],
    lastNames: ["Silver", "Flint"],
    jobTitles: ["First Mate"],
    professions: ["Sailor"],
  },
  location: { cities: ["Tortuga"], states: ["Caribbean"], countries: ["Never Land"] },
  company: { suffixes: ["& Co"], catchPhraseAdjectives: ["Salty"], catchPhraseNouns: ["treasure"] },
  lorem: { words: ["arr", "matey", "doubloon"] },
});
forge.locale("pirate");

Custom Generators

forge.define("pokemon", (f) => f.pick(["Pikachu", "Bulbasaur", "Charmander"]));
forge.custom.pokemon(); // "Pikachu"

Unique Values

forge.unique.email();
forge.unique.username();
forge.unique.uuid();

const uniqueCity = forge.unique.wrap(() => forge.location.city());
uniqueCity();

forge.unique.clear(); // forget everything generated so far

Helpers & Randomness Utilities

forge.uuid();
forge.shuffle([1, 2, 3]);
forge.pick(["a", "b", "c"]);
forge.pickMultiple(["a", "b", "c", "d"], 2);
forge.randomEnum(MyEnum);
forge.probability(0.3);
forge.weighted([
  { weight: 9, value: "common" },
  { weight: 1, value: "rare" },
]);
forge.randomArray(() => forge.person.fullName(), 5);
forge.listGenerators(); // every "module.method" id (111+)
forge.invoke("person", "fullName"); // dynamic dispatch

API Reference

new ForgeData(options?)

OptionTypeDefaultDescription
seednumber | stringrandomMakes every generator on this instance deterministic.
localestring"en"Starting locale code.

Every module below is a plain class instantiated once per ForgeData:

ModuleExample methods
personfirstName, lastName, fullName, gender, jobTitle, profession
internetemail, username, password, url, domain, ipv4, ipv6, mac, userAgent, jwt, apiKey, jwtSecret
companyname, catchPhrase, logo
financecurrency, amount, creditCardNumber, creditCardCVV, iban, bitcoinAddress, ethereumAddress, cryptoCoin, stockSymbol
locationcountry, state, city, zipCode, latitude, longitude, timezone, airport
commerceproductName, price, department, isbn, barcode
phonenumber, imei
datepast, future, recent, birthdate, month, weekday, between
imageavatar, url, category, dataUri
loremword(s), sentence(s), paragraph(s), slug, markdown, html
colorhex, rgb, rgba, hsl, cssColorName, tailwindColor, materialColor, svgPattern
vehiclemanufacturer, model, type, vin
animaltype, name
scienceunit, chemicalElement
aiprompt, chatConversation, codeSnippet, sqlQuery, json, markdown, apiResponse, logLine, commitMessage, issueTitle, prDescription
miscemoji, hashtag, programmingLanguage, githubUsername, gitCommitHash, semver, dockerImageName, npmPackageName, otp, licenseKey, qrData, movie, book, music, food, holiday, university

Full method signatures live next to each implementation in src/<module>/index.ts with JSDoc.

Zod Schema Generation

npm install @sahinur/forgedata zod
import { z } from "zod";
import { fromZodSchema } from "@sahinur/forgedata/zod";

const UserSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  email: z.string().email(),
  age: z.number().int().min(18).max(99),
  role: z.enum(["admin", "user", "guest"]),
  tags: z.array(z.string()).min(1).max(3),
  bio: z.string().max(140).optional(),
});

const user = fromZodSchema(forge, UserSchema);
// fully typed as z.infer<typeof UserSchema> — every field respects the
// schema's constraints automatically.

Supports the full range of Zod v4 schema types recursively: primitives (with format-aware strings — .email(), .url(), .uuid(), .datetime(), .ipv4(), .jwt(), and more — plus .min()/.max()/ .length()), object, array, tuple, record, map, set, enum/native enums, literal, union/discriminated union, optional/ nullable/default/catch, and recursive schemas via z.lazy() (depth-capped, so a self-referential schema can't blow the stack).

.transform()/.pipe() are run through the schema's real safeParse() after generation, so the output reflects the actual post-transform shape. Arbitrary .refine() predicates aren't evaluated ahead of time — a generated value can occasionally fail one, in which case the raw pre-refine value is returned rather than throwing. zod is an optional peer dependency (^4.0.0); the main @sahinur/forgedata entry point never imports it.

React Integration

npm install @sahinur/forgedata react
import { ForgeDataProvider } from "@sahinur/forgedata/react";

function App() {
  return (
    <ForgeDataProvider seed={42} locale="en">
      <Dashboard />
    </ForgeDataProvider>
  );
}
PropTypeDescription
seednumber | stringPassed to new ForgeData({ seed }).
localestringPassed to new ForgeData({ locale }).
instanceForgeDataReuse an instance you already constructed.
import { useGenerator } from "@sahinur/forgedata/react";

function UserCard({ userId }) {
  const user = useGenerator(
    (forge) => ({
      name: forge.person.fullName(),
      email: forge.internet.email(),
    }),
    [userId], // regenerate only when userId changes
  );
  return <p>{user.name} — {user.email}</p>;
}

useForgeData() works even without a ForgeDataProvider (it falls back to a shared default instance). react is an optional peer dependency — the main @sahinur/forgedata entry point never imports it.

CLI Reference

npx --package=@sahinur/forgedata forgedata --help
forgedata v0.2.0 — fake data from the command line

Usage:
  forgedata list [--module <name>] [--json]
  forgedata generate <module.method> [--count <n>] [--seed <seed>] [--locale <code>] [--json]
  forgedata --help
  forgedata --version
forgedata list --module person
forgedata generate person.fullName
forgedata generate internet.email --count 5 --seed 42
forgedata generate location.country --locale ja --json
FlagDescription
--count <n>Generate n values (default 1). Must be a positive integer.
--seed <seed>Seed the underlying instance for reproducible output.
--locale <code>Use a built-in locale.
--jsonPrint JSON instead of plain lines.

Install globally for the short command: npm install -g @sahinur/forgedata, then just run forgedata ....

Migration from Faker.js

Faker.jsForgeData
faker.person.fullName()forge.person.fullName()
faker.internet.email()forge.internet.email()
faker.internet.userName()forge.internet.username()
faker.helpers.arrayElement(arr)forge.pick(arr)
faker.seed(42)new ForgeData({ seed: 42 })
faker.setLocale("de")forge.locale("de")

Key differences: ForgeData is instance-based (no required global singleton), ships a built-in React integration and CLI that Faker.js doesn't have, and covers 9 locales rather than 100+ — extend with forge.defineLocale() for anything domain-specific.

Contributing

git clone https://github.com/devSahinur/ForgeData.git
cd ForgeData
npm install
npm run preflight   # lint + typecheck + 100%-coverage tests + build

CI enforces 100% statement/branch/function/line coverage. Commit messages follow Conventional Commits — semantic-release derives the next version and changelog entry from them.