Data Seeding
The x-seed extension allows you to automatically populate initial data when the mock server starts. This is perfect for having realistic test data available immediately without manual setup.
When to Use x-seed
Use x-seed when you need:
- Initial test data available on server startup
- Realistic sample data for development and testing
- Consistent starting state across server restarts
- Quick prototyping without manual data entry
How It Works
- Automatic execution: Seed code runs automatically when the server starts
- Idempotent: Only seeds if the collection is empty (won't duplicate data on restart)
- Schema-based: Each schema can have its own seed code
- Collection naming: The schema key name is used as the collection name
Seed Helper
The seed helper provides a Laravel-inspired API for creating data. It automatically uses the schema key as the collection name.
seed.count(n, factory) - Create Multiple Items
Create n items using a factory function:
components:
schemas:
Post:
type: object
properties:
id: { type: string }
title: { type: string }
content: { type: string }
author: { type: string }
publishedAt: { type: string, format: date-time }
x-seed: |
seed.count(5, () => ({
id: faker.string.uuid(),
title: faker.lorem.sentence(),
content: faker.lorem.paragraphs(3),
author: faker.person.fullName(),
publishedAt: faker.date.past().toISOString()
}))
seed(array) - Create from Array
Create items from an array of objects:
components:
schemas:
Post:
type: object
x-seed: |
seed([
{
id: '1',
title: 'Getting Started with Scalar',
content: 'Learn how to use Scalar...',
author: 'Jane Doe'
},
{
id: '2',
title: 'Advanced API Documentation',
content: 'Take your docs to the next level...',
author: 'John Smith'
}
])
seed(factory) - Create Single Item
Create a single item using a factory function (shorthand for seed.count(1, factory)):
components:
schemas:
Post:
type: object
x-seed: |
seed(() => ({
id: faker.string.uuid(),
title: faker.lorem.sentence(),
content: faker.lorem.paragraphs(2),
author: faker.person.fullName(),
publishedAt: new Date().toISOString()
}))
Available Context
When writing x-seed code, you have access to:
store: The same store helper asx-handler(for advanced use cases)faker: Faker.js for generating realistic dataseed: The seed helper function (described above)schema: The schema key name (useful for debugging)
Example: Blog Posts with Seeding
Here's a complete example that combines x-seed for initial data and x-handler for endpoints:
openapi: 3.1.0
info:
title: Blog API
version: 1.0.0
paths:
/posts:
get:
summary: List all posts
operationId: listPosts
x-handler: |
return store.list('Post')
responses:
'200':
description: List of posts
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Post'
post:
summary: Create a new post
operationId: createPost
x-handler: |
return store.create('Post', {
id: faker.string.uuid(),
...req.body,
createdAt: new Date().toISOString()
})
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NewPost'
responses:
'201':
description: Post created
content:
application/json:
schema:
$ref: '#/components/schemas/Post'
components:
schemas:
Post:
type: object
properties:
id:
type: string
title:
type: string
content:
type: string
author:
type: string
publishedAt:
type: string
format: date-time
createdAt:
type: string
format: date-time
x-seed: |
seed.count(10, () => ({
id: faker.string.uuid(),
title: faker.lorem.sentence(),
content: faker.lorem.paragraphs(4),
author: faker.person.fullName(),
publishedAt: faker.date.past().toISOString(),
createdAt: faker.date.past().toISOString()
}))
NewPost:
type: object
required:
- title
- content
properties:
title:
type: string
content:
type: string
author:
type: string
When the server starts, it will automatically create 10 blog posts. You can immediately call GET /posts to see them.
Multiple Schemas
You can seed multiple collections by adding x-seed to multiple schemas:
components:
schemas:
Post:
type: object
x-seed: |
seed.count(5, () => ({
id: faker.string.uuid(),
title: faker.lorem.sentence(),
content: faker.lorem.paragraphs(3)
}))
Author:
type: object
x-seed: |
seed.count(3, () => ({
id: faker.string.uuid(),
name: faker.person.fullName(),
email: faker.internet.email(),
bio: faker.person.bio()
}))
Category:
type: object
x-seed: |
seed([
{ id: '1', name: 'Technology' },
{ id: '2', name: 'Design' },
{ id: '3', name: 'Business' }
])
Each schema seeds independently, and all collections are populated when the server starts.
Idempotent Behavior
The seed code only runs if the collection is empty. This means:
- First start: Seeds the data
- Subsequent starts: Skips seeding if data exists
- After clearing: Seeds again on next start
This prevents duplicate data and ensures consistent behavior. If you need to reseed, you can clear the collection using store.clear('Post') in an x-handler endpoint, or restart the server after clearing.
Best Practices
- Use meaningful counts: Seed enough data to be useful but not overwhelming (5-20 items is usually good)
- Generate realistic data: Use Faker to create believable test data
- Match schema structure: Ensure seeded data matches your schema properties
- Use factories: Prefer factory functions over hardcoded arrays for flexibility
- Combine with x-handler: Use
x-seedfor initial data andx-handlerfor CRUD operations
Common Patterns
Seeding with Relationships
Post:
type: object
x-seed: |
// First create authors
const authors = seed.count(3, () => ({
id: faker.string.uuid(),
name: faker.person.fullName()
}))
// Then create posts with author references
seed.count(10, () => ({
id: faker.string.uuid(),
title: faker.lorem.sentence(),
authorId: faker.helpers.arrayElement(authors).id
}))
Seeding with Varied Data
Post:
type: object
x-seed: |
seed.count(10, () => {
const isPublished = faker.datatype.boolean()
return {
id: faker.string.uuid(),
title: faker.lorem.sentence(),
content: faker.lorem.paragraphs(3),
published: isPublished,
publishedAt: isPublished ? faker.date.past().toISOString() : null
}
})