API Packages@mockmaster/cli

@mockmaster/cli

File system operations & CLI tools

npm install @mockmaster/cli

Overview

The CLI package provides file system operations for reading, writing, and generating scenarios.

Key Features:

  • Save scenarios to disk as JSON files
  • Load scenarios from JSON files
  • Generate scenarios from OpenAPI specs
  • Scenario management utilities
  • File system operations

API Reference

writeScenario(directory, scenario)

Write a scenario to a JSON file.

import { writeScenario } from '@mockmaster/cli'
import { createScenario } from '@mockmaster/msw-adapter'
 
const scenario = createScenario('user-api', 'User API endpoints')
 
await writeScenario('./scenarios', scenario)
// Writes to: ./scenarios/user-api.json

Parameters:

  • directory (string) - Directory to write to
  • scenario (Scenario) - Scenario to write

Returns: Promise<void>

File Output:

{
  "name": "user-api",
  "description": "User API endpoints",
  "recordings": [...],
  "createdAt": 1234567890,
  "updatedAt": 1234567890
}

readScenario(directory, name)

Read a scenario from a JSON file.

import { readScenario } from '@mockmaster/cli'
 
const scenario = await readScenario('./scenarios', 'user-api')
// Reads from: ./scenarios/user-api.json
 
console.log(scenario.name)          // 'user-api'
console.log(scenario.recordings.length)  // Number of recordings

Parameters:

  • directory (string) - Directory to read from
  • name (string) - Scenario name (without .json extension)

Returns: Promise<Scenario>

generateScenariosFromSpec(spec, name)

Generate scenarios from an OpenAPI specification.

import { parseYaml } from '@mockmaster/openapi'
import { generateScenariosFromSpec } from '@mockmaster/cli'
 
const spec = parseYaml(`
openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
paths:
  /users:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id: { type: integer }
                    name: { type: string }
`)
 
const scenarios = generateScenariosFromSpec(spec, 'user-api')
 
console.log(scenarios.length)  // 1
console.log(scenarios[0].recordings.length)  // Number of operations

Parameters:

  • spec (OpenAPISpec) - Parsed OpenAPI spec
  • name (string) - Base name for scenarios

Returns: Array<Scenario> - Generated scenarios with recordings


Usage Examples

Save and Load Scenario

import { createScenario, addRecordingToScenario, createRecording } from '@mockmaster/msw-adapter'
import { writeScenario, readScenario } from '@mockmaster/cli'
 
// Create scenario
let scenario = createScenario('user-api', 'User API operations')
 
const recording = createRecording(
  { method: 'GET', url: 'https://api.example.com/users', path: '/users', timestamp: Date.now() },
  { status: 200, body: [], timestamp: Date.now() }
)
 
scenario = addRecordingToScenario(scenario, recording)
 
// Save to disk
await writeScenario('./scenarios', scenario)
 
// Load from disk
const loadedScenario = await readScenario('./scenarios', 'user-api')
 
console.log(loadedScenario.name)  // 'user-api'

Generate from OpenAPI

import { readFileSync } from 'fs'
import { parseYaml } from '@mockmaster/openapi'
import { generateScenariosFromSpec, writeScenario } from '@mockmaster/cli'
 
// Load spec from file
const specContent = readFileSync('./api-spec.yaml', 'utf-8')
const spec = parseYaml(specContent)
 
// Generate scenarios
const scenarios = generateScenariosFromSpec(spec, 'my-api')
 
// Save all scenarios
for (const scenario of scenarios) {
  await writeScenario('./scenarios', scenario)
}
 
console.log(`Generated ${scenarios.length} scenarios`)

Complete Workflow

import { parseYaml } from '@mockmaster/openapi'
import { generateScenariosFromSpec, writeScenario, readScenario } from '@mockmaster/cli'
import { createReplayHandler } from '@mockmaster/msw-adapter'
 
async function setup() {
  // 1. Parse OpenAPI spec
  const spec = parseYaml(`
    openapi: 3.0.0
    info:
      title: User API
      version: 1.0.0
    paths:
      /users:
        get:
          responses:
            '200':
              content:
                application/json:
                  schema:
                    type: array
  `)
 
  // 2. Generate scenarios
  const scenarios = generateScenariosFromSpec(spec, 'user-api')
 
  // 3. Save to disk
  for (const scenario of scenarios) {
    await writeScenario('./scenarios', scenario)
  }
 
  // 4. Load and use
  const loaded = await readScenario('./scenarios', 'user-api')
  const handler = createReplayHandler(loaded)
 
  // 5. Test
  const response = handler({ method: 'GET', path: '/users' })
  console.log(response.status)  // 200
}
 
setup()

File Structure

Scenario Files

Scenarios are saved as JSON files with the scenario name:

scenarios/
├── user-api.json
├── product-api.json
└── auth-flow.json

JSON Format

{
  "name": "user-api",
  "description": "User API endpoints",
  "recordings": [
    {
      "request": {
        "method": "GET",
        "url": "https://api.example.com/users",
        "path": "/users",
        "timestamp": 1234567890
      },
      "response": {
        "status": 200,
        "body": [
          { "id": 1, "name": "John Doe" },
          { "id": 2, "name": "Jane Smith" }
        ],
        "headers": {
          "content-type": "application/json"
        },
        "timestamp": 1234567890
      }
    }
  ],
  "createdAt": 1234567890,
  "updatedAt": 1234567890
}

Directory Organization

By Feature

scenarios/
├── auth/
│   ├── login-success.json
│   ├── login-failure.json
│   └── logout.json
├── users/
│   ├── list-users.json
│   ├── get-user.json
│   └── create-user.json
└── products/
    └── list-products.json

Example:

await writeScenario('./scenarios/auth', loginScenario)
await writeScenario('./scenarios/users', userListScenario)
 
const authScenario = await readScenario('./scenarios/auth', 'login-success')
const userScenario = await readScenario('./scenarios/users', 'list-users')

By Environment

scenarios/
├── development/
│   └── user-api.json
├── staging/
│   └── user-api.json
└── production/
    └── user-api.json

Generating Scenarios

From Simple Spec

const spec = parseYaml(`
openapi: 3.0.0
paths:
  /users:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id: { type: integer }
                    name: { type: string }
`)
 
const scenarios = generateScenariosFromSpec(spec, 'user-api')
// Generates scenarios with realistic data for all operations

From Complex Spec

const spec = parseYaml(`
openapi: 3.0.0
paths:
  /users:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                type: array
  /users/{id}:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
    put:
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
    delete:
      responses:
        '204':
          description: No content
`)
 
const scenarios = generateScenariosFromSpec(spec, 'user-api')
// Generates scenarios for:
// - GET /users
// - GET /users/{id}
// - PUT /users/{id}
// - DELETE /users/{id}

Error Handling

File Not Found

try {
  const scenario = await readScenario('./scenarios', 'non-existent')
} catch (error) {
  console.error('Scenario not found:', error.message)
}

Invalid JSON

try {
  const scenario = await readScenario('./scenarios', 'corrupted')
} catch (error) {
  console.error('Invalid scenario file:', error.message)
}

Write Permissions

try {
  await writeScenario('/readonly', scenario)
} catch (error) {
  console.error('Cannot write scenario:', error.message)
}

Integration with Build Tools

NPM Scripts

{
  "scripts": {
    "generate-scenarios": "node scripts/generate-scenarios.js",
    "test": "npm run generate-scenarios && vitest"
  }
}

Generate Script

// scripts/generate-scenarios.ts
import { readFileSync } from 'fs'
import { parseYaml } from '@mockmaster/openapi'
import { generateScenariosFromSpec, writeScenario } from '@mockmaster/cli'
 
async function main() {
  const specContent = readFileSync('./api-spec.yaml', 'utf-8')
  const spec = parseYaml(specContent)
 
  const scenarios = generateScenariosFromSpec(spec, 'api')
 
  for (const scenario of scenarios) {
    await writeScenario('./scenarios', scenario)
  }
 
  console.log(`✓ Generated ${scenarios.length} scenarios`)
}
 
main().catch(console.error)

TypeScript Types

import type {
  Scenario,
  Recording
} from '@mockmaster/msw-adapter'
 
async function saveScenario(dir: string, scenario: Scenario): Promise<void> {
  await writeScenario(dir, scenario)
}
 
async function loadScenario(dir: string, name: string): Promise<Scenario> {
  return await readScenario(dir, name)
}

Best Practices

1. Version Control

Always commit scenario files:

git add scenarios/
git commit -m "Add user API scenarios"

2. Organize by Feature

scenarios/
├── auth/
├── users/
└── products/

3. Update When APIs Change

# Re-generate from updated spec
npm run generate-scenarios
 
# Review changes
git diff scenarios/
 
# Commit updates
git add scenarios/
git commit -m "Update scenarios for API v2"

4. Use Descriptive Names

// Good
await writeScenario('./scenarios', createScenario('user-login-success', 'Successful login'))
 
// Bad
await writeScenario('./scenarios', createScenario('test1', 'test'))