Functional Mocks

You can write JSON mocks in JavaScript or TypeScript

Node 22.18+ or 23.6+ support TypeScript by default.

Option A: An Object, Array, or String is sent as JSON

api/foo.GET.200.js

export default { foo: 'bar' }

Option B: Function Mocks

Return a string | Buffer | Uint8Array, but don’t call response.end().

export default (request, response) =>
  JSON.stringify({ foo: 'bar' })

async functions are supported.

Custom HTTP Handlers

For example, you can intercept requests to write to a database. Or act based on some query string value, etc. In summary, you get Node’s request, response as arguments, so you can think of Mockaton as a router, but in the handlers you return, instead of ending the response.

Examples

Imagine you have an initial list of colors, and you want to concatenate newly added colors.

api/colors.POST.201.js
import { parseJSON } from 'mockaton'

export default async function insertColor(request, response) {
  const color = await parseJSON(request)
  globalThis.newColorsDatabase ??= []
  globalThis.newColorsDatabase.push(color)

  // These two lines are not needed but you can change their values
  //   response.statusCode = 201 // default derived from filename
  //   response.setHeader('Content-Type', 'application/json') // unconditional default

  return JSON.stringify({ msg: 'CREATED' })
}

api/colors.GET.200.js
import colorsFixture from './colors.json' with { type: 'json' }

export default function listColors() {
  return JSON.stringify([
    ...colorsFixture,
    ...(globalThis.newColorsDatabase || [])
  ])
}

What if I need to serve a static .js or .ts?

Option A: Put it in your config.staticDir without the .GET.200.js extension. Mocks in staticDir take precedence over mocksDir/*.

Option B: Read it and return it. For example:

import { readFileSync } from 'node:fs'

export default function (_, response) {
  response.setHeader('Content-Type', 'application/javascript')
  return readFileSync('./some-dir/foo.js', 'utf8')
}