NestboltNestbolt

@nestbolt/factory

Sequences

Auto-increment, cycle, and compute field values across multiple generated entities.

Sequences generate unique or predictable values for fields across multiple entities in a batch. They are especially useful for fields that need to be unique (like email addresses) or follow a pattern (like incrementing IDs).

Importing

import { Sequence } from "@nestbolt/factory";

Built-in Sequence Types

Sequence.from(callback)

The most flexible sequence type. Pass a callback that receives an auto-incrementing index (starting from 0):

await factoryService.use(UserFactory)
  .count(3)
  .sequence("email", Sequence.from(i => `user${i}@test.com`))
  .create();
// user0@test.com, user1@test.com, user2@test.com

Sequence.increment(start?)

Generates incrementing numbers. Starts from 1 by default:

await factoryService.use(UserFactory)
  .count(3)
  .sequence("employeeId", Sequence.increment())
  .create();
// 1, 2, 3

await factoryService.use(UserFactory)
  .count(3)
  .sequence("employeeId", Sequence.increment(100))
  .create();
// 100, 101, 102

Sequence.cycle(values)

Cycles through an array of values, wrapping around when the end is reached:

await factoryService.use(PostFactory)
  .count(6)
  .sequence("status", Sequence.cycle(["draft", "published", "archived"]))
  .create();
// draft, published, archived, draft, published, archived

Custom Sequences

Create a Sequence directly with any callback function:

const seq = new Sequence((i) => i * 10);
seq.next(); // 0
seq.next(); // 10
seq.next(); // 20

Resetting Sequences

Call reset() to restart a sequence from index 0:

const seq = Sequence.increment();
seq.next(); // 1
seq.next(); // 2
seq.next(); // 3
seq.reset();
seq.next(); // 1

Note that sequences created inline in the builder (e.g., .sequence("email", Sequence.from(...))) are fresh for each builder chain. You only need reset() when reusing a sequence instance across multiple operations.

Combining with Other Builder Methods

Sequences are applied after states but before overrides. This means:

  • States do not override sequence values
  • override() does override sequence values
// Sequence wins over the state's email
await factoryService.use(UserFactory)
  .state({ email: "ignored@test.com" })
  .sequence("email", Sequence.from(i => `user${i}@test.com`))
  .create();
// email: "user0@test.com"

// Override wins over the sequence
await factoryService.use(UserFactory)
  .sequence("email", Sequence.from(i => `user${i}@test.com`))
  .override({ email: "forced@test.com" })
  .create();
// email: "forced@test.com"

Practical Examples

Unique Usernames

await factoryService.use(UserFactory)
  .count(5)
  .sequence("username", Sequence.from(i => `testuser_${i}`))
  .create();

Ordered Positions

await factoryService.use(TaskFactory)
  .count(10)
  .sequence("position", Sequence.increment())
  .create();

Rotating Categories

await factoryService.use(ProductFactory)
  .count(12)
  .sequence("category", Sequence.cycle(["electronics", "clothing", "books", "food"]))
  .create();

Computed Slugs

await factoryService.use(PostFactory)
  .count(3)
  .sequence("slug", Sequence.from(i => `post-${i + 1}`))
  .create();
// post-1, post-2, post-3