npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@joxnathan/mock-randomizer

v0.3.0

Published

fills a structure with randomized data to mock a service or other model provider. number of items in a collection of objects can also be random.

Readme

Mock Randomizer

fills a structure with randomized data to mock a service or other model provider. number of items in a collection of objects can also be random.

Installation

npm install @joxnathan/mock-randomizer -D

Usage

JSON DSL v2 is the preferred way to describe generated values. Put a $mock object anywhere a synthetic value should be created, then pass generation controls such as range, nested array ranges, and seed through the options object.

import mock from '@joxnathan/mock-randomizer';

const changeHistoryTemplate = {
  Id: { $mock: 'guid', $version: 2 },
  TimeStamp: { $mock: 'date', min: 'now', max: 'now' },
  User: {
    Id: { $mock: 'number', min: 100, max: 501 },
    Name: { $mock: 'string', size: 8 },
    Email: { $mock: 'email' }
  },
  Data: [{
    Id: { $mock: 'number', min: 1000, max: 2001 },
    ChangeType: { $mock: 'choose', choices: ['Insert', 'Update', 'Delete'] },
    TableName: { $mock: 'choose', choices: ['Claimant', 'Processor', 'Advisor', 'Supervisor', 'Client', 'Vendor'] },
    RecordId: { $mock: 'number', min: 10, max: 41 },
    FieldName: { $mock: 'choose', choices: ['Id', 'Name', 'Address', 'City', 'State', 'Zip'] },
    PrevValue: '{}',
    CurrValue: '{}'
  }]
};

const detailTemplate = {
  Id: { $mock: 'guid', $version: 2 },
  Version: { $mock: 'ver' },
  Name: { $mock: 'string' },
  Value: { $mock: 'string', minLength: 4, maxLength: 6, case: 'upper' },
  FullName: { $mock: 'fullname' },
  FirstName: { $mock: 'firstname' },
  LastName: { $mock: 'lastname' },
  Company: { $mock: 'company' },
  Street: { $mock: 'street' },
  City: { $mock: 'city' },
  State: { $mock: 'state' },
  Zip: { $mock: 'zip' },
  Tz: { $mock: 'tz' },
  Phone: { $mock: 'phone' },
  Email: { $mock: 'email' },
  Book: { $mock: 'title' },
  TypeSet: { $mock: 'typeset' },
  Locations: [{ $mock: 'city' }],
  HasApproval: { $mock: 'boolean' },
  CreatedOn: { $mock: 'date', min: 'today-12M', max: 'now-1M' },
  CreatedBy: { $mock: 'string' },
  ModifiedOn: { $mock: 'date', min: 'today-7D', max: 'now' },
  ModifiedBy: { $mock: 'string' }
};

this.history.GetChangeHistory = () => Promise.resolve(
  mock.filledList(changeHistoryTemplate, {
    range: { min: 11, max: 75 },
    Data: { min: 1, max: 4 },
    seed: 'history:change-history:v2:case-001'
  }).map(entry => {
    const getData = () => JSON.stringify(mock.filledObject(detailTemplate, {
      Locations: { min: 1, max: 3 }
    }));
    for (const data of entry.Data ?? []) {
      const vals = {
        prev: ['Delete', 'Update'].includes(data.ChangeType) ? getData() : undefined,
        curr: ['Insert', 'Update'].includes(data.ChangeType) ? getData() : undefined
      };
      data.PrevValue = vals.prev;
      data.CurrValue = vals.curr;
    }
    return entry;
  })
);

RunKit Usage

const mock = require("@joxnathan/mock-randomizer").default;

const records = mock.filledList({
  Id: { $mock: 'guid', $version: 2 },
  Name: { $mock: 'fullname' },
  Status: { $mock: 'choose', choices: ['New', 'Open', 'Closed'] },
  CreatedOn: { $mock: 'date', min: 'today-7D', max: 'now' }
}, {
  range: { min: 2, max: 4 },
  seed: 'runkit:sample:v2'
});

console.log({ records });

JSON DSL v2

JSON DSL v2 is the current template language for new work. A JSON instruction is an object with $mock and an optional $version. If $version is omitted, the current JSON DSL version is used. For long-lived templates, snapshots, or database seed files, include $version: 2 so the intended DSL contract is explicit.

const record = mock.filledObject({
  Id: { $mock: 'guid', $version: 2 },
  Name: { $mock: 'fullname', gender: 'female' },
  Status: { $mock: 'choose', choices: ['New', 'Open', 'Closed'] },
  Score: { $mock: 'number', min: 80, max: 101, inclusive: true },
  Code: { $mock: 'string', minLength: 4, maxLength: 6, case: 'upper' },
  CreatedOn: { $mock: 'date', min: 'today', max: 'now' }
});

Common v2 instructions include:

{ $mock: 'guid' }
{ $mock: 'number', min: 1, max: 100, inclusive: true }
{ $mock: 'date', min: 'today-7D', max: 'now' }
{ $mock: 'string', minLength: 4, maxLength: 12, case: 'mixed' }
{ $mock: 'choose', choices: ['New', 'Open', 'Closed'] }
{ $mock: 'fullname', gender: 'female' }
{ $mock: 'email' }
{ $mock: 'phone', state: 'AZ' }

JSON DSL objects are validated before generation. Unknown fields, unsupported $mock types, invalid enum values, empty choice lists, invalid ranges, and conflicting aliases throw DSLParseError with a stable code and path.

Synthetic Data Layer

The synthetic layer adds preflight validation and reusable dataset definitions on top of JSON DSL templates. Use validateTemplate when you want a report instead of a thrown generation error.

const validation = mock.synthetic.validateTemplate({
  User: {
    Email: { $mock: 'email', $version: 2 }
  },
  Orders: [{
    Total: { $mock: 'number', min: 10, max: 1 }
  }]
});

if (!validation.valid) {
  console.log(validation.issues);
  // [{ code: 'invalid_range', path: 'Orders[0].Total.max', ... }]
}

Use compileTemplate when a template should be checked once and reused many times.

const userTemplate = mock.synthetic.compileTemplate({
  Id: { $mock: 'guid', $version: 2 },
  Name: { $mock: 'fullname' },
  Email: { $mock: 'email' },
  Status: { $mock: 'choose', choices: ['New', 'Active', 'Disabled'] }
});

const user = userTemplate.fill({ seed: 'users:v2:case-001' });
const users = userTemplate.fillList({
  seed: 'users:v2:list-001',
  range: { min: 10, max: 10 }
});

Use generateSyntheticData for simple entity/table style datasets. Dataset seeds are expanded per entity so each table has a deterministic but separate generated stream.

const data = mock.synthetic.generateSyntheticData({
  seed: 'claims-sandbox:v2',
  entities: {
    Users: {
      template: userTemplate.template,
      options: { range: { min: 25, max: 25 } }
    },
    AuditEvents: {
      template: {
        Id: { $mock: 'guid', $version: 2 },
        EventType: { $mock: 'choose', choices: ['Created', 'Updated', 'Deleted'] },
        Actor: { $mock: 'fullname' }
      },
      options: { range: { min: 100, max: 100 } }
    }
  }
});

Synthetic references let later entities point at records generated by earlier entities. By default, $ref picks a deterministic random record from the target entity, then returns the requested path.

const data = mock.generateSyntheticData({
  seed: 'claims-sandbox:v2',
  entities: {
    Users: {
      template: {
        Id: { $mock: 'guid', $version: 2 },
        Name: { $mock: 'fullname' },
        Email: { $mock: 'email' }
      },
      options: { range: { min: 10, max: 10 } }
    },
    Claims: {
      template: {
        Id: { $mock: 'guid', $version: 2 },
        AssignedUserId: { $ref: 'Users', path: 'Id' },
        AssignedUserEmail: { $ref: 'Users.Email' }
      },
      options: { range: { min: 50, max: 50 } }
    }
  }
});

Use index when a scenario needs an exact fixture row. Indexes are zero-based and must exist in the generated entity list.

const claim = mock.generateSyntheticData({
  seed: 'claims-sandbox:v2:indexed',
  entities: {
    Users: {
      template: {
        Id: { $mock: 'guid', $version: 2 },
        Name: { $mock: 'fullname' }
      },
      options: { range: { min: 4, max: 4 } }
    },
    Claims: {
      template: {
        ReviewerName: { $ref: 'Users', index: 3, path: 'Name' },
        SameReviewerName: { $ref: 'Users[3].Name' }
      },
      options: { range: { min: 1, max: 1 } }
    }
  }
}).Claims[0];

References only point backward to entities that have already been generated. Missing entities, forward references, empty target lists, out-of-range indexes, and missing paths throw stable synthetic reference errors.

Use scope when multiple fields in the same generated record should come from the same selected related record. The scope is local to each generated root record, so each claim below gets one deterministic assigned user while AssignedUserId, AssignedUserName, and AssignedUserEmail stay consistent with each other.

const data = mock.generateSyntheticData({
  seed: 'claims-sandbox:v2:scoped',
  entities: {
    Users: {
      template: {
        Id: { $mock: 'guid', $version: 2 },
        Name: { $mock: 'fullname' },
        Email: { $mock: 'email' }
      },
      options: { range: { min: 10, max: 10 } }
    },
    Claims: {
      template: {
        AssignedUserId: { $ref: 'Users', scope: 'assignedUser', path: 'Id' },
        AssignedUserName: { $ref: 'Users', scope: 'assignedUser', path: 'Name' },
        AssignedUserEmail: { $ref: 'Users.Email', scope: 'assignedUser' }
      },
      options: { range: { min: 50, max: 50 } }
    }
  }
});

References that share a scope must target the same entity. They must also either all omit index or all use the same explicit index, so scoped references do not depend on traversal order.

Do not write references with v1-style strings. A value such as "$ref:Users.Id" is rejected during validation. Use JSON object form instead:

{ "$ref": "Users", "path": "Id" }

Templates can also be loaded from JSON files. Relative paths are resolved from the current project directory unless baseDir is provided.

const template = await mock.loadTemplate('./templates/user.json');
const compiled = await mock.loadCompiledTemplate('./templates/user.json');

const user = compiled.fill({ seed: 'users:v2:case-001' });

Dataset files can reference template files with paths relative to the dataset file.

const data = await mock.loadSyntheticData('./datasets/claims-sandbox.json', {
  rootDir: '.'
});

Example dataset file:

{
  "seed": "claims-sandbox:v2",
  "entities": {
    "Users": {
      "template": "../templates/user.json",
      "options": { "range": { "min": 25, "max": 25 } }
    },
    "AuditEvents": {
      "template": {
        "Id": { "$mock": "guid", "$version": 2 },
        "EventType": { "$mock": "choose", "choices": ["Created", "Updated", "Deleted"] }
      },
      "options": { "range": { "min": 100, "max": 100 } }
    }
  }
}

Absolute disk paths and UNC paths are supported. Use rootDir to restrict where templates may be loaded from. HTTP(S) template loading is disabled by default; set allowNetwork: true only for trusted sources.

Output Adapters

Output adapters turn generated data into plain strings for tests, snapshots, pipeline artifacts, or handoff to database-specific tooling. They do not write files or connect to databases.

const data = mock.generateSyntheticData({
  seed: 'claims-sandbox:v2',
  entities: {
    Users: {
      template: {
        Id: { $mock: 'guid', $version: 2 },
        Name: { $mock: 'fullname' },
        Email: { $mock: 'email' },
        CreatedOn: { $mock: 'date', min: 'today', max: 'now' }
      },
      options: { range: { min: 2, max: 2 } }
    }
  }
});

const prettyJson = mock.toJson(data);
const compactJson = mock.toJson(data, { pretty: false });
const usersNdjson = mock.toNdjson(data, { entity: 'Users' });
const allNdjson = mock.toNdjson(data);
const usersCsv = mock.toCsv(data, 'Users');

JSON output is pretty printed by default and can be made compact with { pretty: false }. Dates are serialized as ISO strings.

NDJSON output can target one entity or the whole dataset. Whole-dataset NDJSON includes the entity name on each line so records from different tables do not lose context.

CSV output targets one entity at a time because each entity can have a different shape. Nested objects and arrays are written as JSON strings inside the cell. Use columns to control field order or project a smaller export.

const csv = mock.toCsv(data, {
  entity: 'Users',
  columns: ['Id', 'Email', 'CreatedOn'],
  delimiter: ','
});

When columns is provided, adapters reject a column that is not present in any selected record. Empty record sets also fail by default. Use allowMissingColumns: true or allowEmpty: true only when that shape is intentional.

Database insert payload adapters are also pure string/object builders. They do not open connections, execute SQL, or write files.

Use toInsertRows when a test database client already handles parameterization.

const rows = mock.toInsertRows(data, {
  entity: 'Users',
  columns: ['Id', 'Email', 'CreatedOn']
});

// example shape for a query builder:
// await db('Users').insert(rows);

Dates are normalized to ISO strings. Nested objects and arrays are JSON strings by default so rows stay scalar-friendly. Set nested: 'preserve' when the target client accepts structured JSON column values.

const jsonColumnRows = mock.toInsertRows(data, {
  entity: 'Users',
  nested: 'preserve'
});

Use toSqlInserts for deterministic non-production fixture scripts. Identifiers are validated before SQL is produced, string values are escaped, and table names must be explicit for raw record arrays.

const sql = mock.toSqlInserts(data, {
  entity: 'Users',
  schema: 'sandbox',
  table: 'UserSeed',
  dialect: 'postgres',
  columns: ['Id', 'Email', 'CreatedOn'],
  batchSize: 100
});

Reproducible Data

Seeded generation is optional. Without a seed, the package continues to use Math.random().

A seed may be a string or number. The simplest good seed is a stable, readable value that describes the test case. Use the same seed with the same template and options to replay the same generated data.

const template = {
  Id: { $mock: 'guid', $version: 2 },
  Name: { $mock: 'fullname' },
  Status: { $mock: 'choose', choices: ['New', 'Open', 'Closed'] }
};

const first = mock.withSeed('case-001', () => mock.filledObject(template));
const second = mock.withSeed('case-001', () => mock.filledObject(template));
// first and second are equal

const third = mock.filledObject(template, { seed: 'case-001' });
// per-call seed injection is also supported from the options object

For most tests, do not overthink the seed. Pick a short value that will stay the same when the test is renamed or moved.

const record = mock.filledObject(template, {
  seed: 'claim-update-happy-path'
});

For larger suites, build seed values from stable business context. This makes failures easier to replay and keeps unrelated tests from accidentally sharing the same generated data stream.

const seed = [
  'claims-api',
  'change-history',
  'v2',
  'update-with-attachments',
  'case-001'
].join(':');

const records = mock.filledList(template, {
  seed,
  range: { min: 10, max: 10 }
});

Good seed values are stable, descriptive, and safe to commit. Avoid Date.now(), random GUIDs, environment-specific paths, database IDs, secrets, or personal data. When the template changes in a meaningful way, include a schema or scenario version such as v2 so old snapshots and new snapshots do not pretend to be the same generated case.

mock.random.setSeed('suite-001');
const value = mock.filledList(template, {
  range: { min: 2, max: 4 }
});
mock.random.clearSeed();

Dates that use now or today can also be made deterministic with clock injection.

const fixedNow = '2024-07-15T16:45:30.005Z';

const dated = mock.withClock(fixedNow, () => mock.filledObject({
  Id: { $mock: 'guid', $version: 2 },
  CreatedOn: { $mock: 'date', min: 'today', max: 'now' }
}, { seed: 'case-001' }));

mock.clock.setClock(fixedNow);
const suiteValue = mock.filledObject({
  CreatedOn: { $mock: 'date', min: 'today', max: 'now' }
});
mock.clock.clearClock();

Legacy String DSL

The old v1 string shorthand exists only as a migration aid for existing templates. It is deprecated, disabled by default, and not recommended for new test suites or seed data. Prefer JSON DSL v2.

To run an old template temporarily, set allowLegacyDsl explicitly:

const sameStyle = mock.filledObject({
  Id: 'guid',
  CreatedOn: 'date:today:now'
}, { allowLegacyDsl: true });

Without that switch, v1 strings throw DSLParseError with code: 'legacy_dsl_disabled'. The error message points to JSON DSL object examples first, then mentions { allowLegacyDsl: true } as the last-resort migration switch.

Legacy v1 strings are scalar value shorthand only. They cannot express JSON DSL metadata, $version, synthetic references, reference indexes, reference paths, dataset entities, entity options, template file paths, loader safety options, or future output adapters. When a dataset uses $ref, validation rejects any remaining v1 string DSL in that dataset with code: 'legacy_dsl_unsupported_feature'; convert those fields to JSON DSL v2 first.

In dataset files, string values in an entity's template field are treated as template file paths. A value like "template": "guid" is rejected with TemplateLoadError code legacy_template_source_unsupported. Use an inline JSON object template instead:

{
  "entities": {
    "Users": {
      "template": {
        "Id": { "$mock": "guid", "$version": 2 }
      }
    }
  }
}

Or point to a JSON template file explicitly:

{
  "entities": {
    "Users": {
      "templatePath": "./templates/user.json"
    }
  }
}

Potential Upcoming Features

1. JSON DSL composition for multi-part generated values.
2. Schema bridges for JSON Schema, Zod, and/or OpenAPI template generation.
3. A CLI with commands such as validate, generate, to-csv, to-sql, and pack.
4. Richer relationship modeling, including one-to-many, many-to-many, uniqueness, required foreign keys, weighted references, and relationship cardinality helpers.
5. Custom generator and plugin support for domain-specific test data.
6. Large-data streaming and batching for bigger non-production database fixture generation.
7. Dialect-specific database payload helpers beyond raw insert statements.
8. Official examples for Jest/Vitest snapshots, API mock data, SQL seed files, and non-production database seeding.
9. Release confidence improvements such as Bitbucket pipeline badges, coverage badges, npm provenance/2FA notes, and a changelog.

Contributing

In lieu of a formal style guide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code.