Scripts

A script is an ES module whose default export has any of five hooks:

import { limit } from './settings.mjs';

export default {
  // before the document's operations: a response answers the request
  onRequest(req, ctx) {
    if (req.path === '/pets/13') {
      return ctx.response(404, { title: 'No such pet' });
    }
  },
  // the response about to be sent: change it in place
  onResponse(req, res, ctx) {
    if (req.operationId === 'listPets') {
      res.body = res.body.slice(0, limit);
      res.headers['x-total-count'] = '3';
      res.delay = 250;
    }
  },
  // AsyncAPI messages, in and out: change msg.payload, or return false to drop the message
  onMessage(msg, ctx) {
    if (msg.direction === 'out') msg.payload.sentAt = ctx.now();
  },
  // GraphQL operations (each subscription event too): a result answers, its data completed
  onGraphQL(operation, ctx) {
    if (operation.name === 'GetUser') {
      return { data: { user: { id: operation.variables.id, name: ctx.fake('person.fullName') } } };
    }
  },
  // after the scripts were loaded, at the start and after each reload
  onReload(ctx) {},
};
  • req has method, path, query (an object; repeated parameters are arrays), headers (lower-case names), body (parsed JSON, or the text), rawBody, operationId and route (in onResponse), remote and connectionId.
  • res has status, headers, body, source, and delay (milliseconds) and drop (reset, close, timeout, truncate) to set. A response returned by onRequest has the same fields.
  • msg has direction (in or out), channel, operation, message, contentType and payload.
  • operation has name, type (query, mutation, subscription), query, variables and rootFields (["Query.user"]). The result’s data is cut to the selection set and completed with generated values, like an example’s.
  • ctx has state (get, set, delete and keys of JSON values kept between requests, the admin API’s /state), db (collections of documents, see Document store), log(level, ...values), random() (seeded by --seed), now(), response(status, body, headers), fake(name, ...arguments) (the faker providers of x-faker, with arguments by position and a last object by name: fake('string.alpha', {length: 4})) and scenarios (activate, deactivate, active).

Scripts run in a sandbox: the language only, modules next to the script, no file system, network or timers. Each call has scripting.timeout_ms (1000) and scripting.memory_limit_mb (64); a hook that throws or runs out of time is logged, and answered with 500 when scripting.fail_mode is error. --watch reloads changed scripts, and a broken script keeps the previous version.

Was this helpful?