Yasumu LogoYasumu

Scripting

Pre-request and post-response scripting in Yasumu.

Scripting

Yasumu provides a powerful scripting system that allows you to modify requests before they're sent and process responses after they're received. Scripts are written in JavaScript or TypeScript and have access to request, response, and environment data.

Scripting Language

Yasumu supports both JavaScript and TypeScript syntax for scripting out-of-the-box. The editor also provides type definitions and autocomplete for the request and response objects.

Overview

Each request in Yasumu can have a script that exports two lifecycle functions:

  • onRequest(req) — Runs before the request is sent
  • onResponse(req, res) — Runs after the response is received

Script Structure

Scripts are written in the Scripts tab of the request editor:

Scripts Tab

export function onRequest(req) {
  // Modify the request before sending
  req.headers.set('X-Custom-Header', 'value');
}

export function onResponse(req, res) {
  // Process the response
  console.log('Status:', res.status);
  console.log('Body:', res.json());
}

Optional Functions

Both functions are optional. You can export just onRequest, just onResponse, or both depending on your needs.

The Request Object (req)

The req object represents the HTTP request and is available in both onRequest and onResponse functions.

Properties

PropertyTypeDescription
urlstringThe request URL (can be modified in onRequest)
methodstringHTTP method (GET, POST, etc.)
headersYasumuHeadersRequest headers object
bodyunknownRequest body
paramsYasumuURLSearchParamsURL search parameters
envYasumuWorkspaceEnvironmentEnvironment access

Methods

MethodReturnsDescription
json()unknownParse body as JSON
text()stringGet body as text
clone()YasumuRequestCreate a copy of the request

Modifying Headers

export function onRequest(req) {
  // Set a header
  req.headers.set('Authorization', 'Bearer my-token');

  // Append to existing header
  req.headers.append('Accept', 'application/json');

  // Delete a header
  req.headers.delete('X-Unwanted');

  // Check if header exists
  if (req.headers.has('Content-Type')) {
    console.log('Content-Type:', req.headers.get('Content-Type'));
  }
}

Modifying URL and Method

export function onRequest(req) {
  // Change the URL
  req.url = 'https://api.example.com/v2/users';

  // Change the HTTP method
  req.method = 'POST';
}

Modifying Body

export function onRequest(req) {
  // Set a JSON body
  req.body = JSON.stringify({ name: 'John', age: 30 });
}

The Response Object (res)

The res object represents the HTTP response and is only available in the onResponse function.

Properties

PropertyTypeDescription
statusnumberHTTP status code
statusTextstringHTTP status message
okbooleantrue if status is 200-299
headersYasumuHeadersResponse headers
bodyunknownResponse body
envYasumuWorkspaceEnvironmentEnvironment access

Methods

MethodReturnsDescription
json()unknownParse body as JSON
text()stringGet body as text
clone()YasumuResponseCreate a copy of the response

Reading Response Data

export function onResponse(req, res) {
  // Check status
  if (!res.ok) {
    console.log('Request failed with status:', res.status);
    return;
  }

  // Read JSON body
  const data = res.json();
  console.log('User:', data.user);

  // Read headers
  const contentType = res.headers.get('Content-Type');
  console.log('Content-Type:', contentType);
}

Environment Access

Both req and res objects provide access to the current environment through the env property.

Getting Variables and Secrets

export function onRequest(req) {
  // Get a variable
  const apiUrl = req.env.getVariable('API_URL');

  // Get a secret
  const apiKey = req.env.getSecret('API_KEY');

  // Use in headers
  req.headers.set('Authorization', `Bearer ${apiKey}`);
}

Setting Variables

You can set variables from scripts, which will be persisted to the environment:

export function onResponse(req, res) {
  const data = res.json();

  // Save a value from the response to the environment
  res.env.setVariable('AUTH_TOKEN', data.token);
  res.env.setVariable('USER_ID', data.user.id);
}

Environment Persistence

Variables set via setVariable() are automatically saved to the active environment after the script completes. This allows you to chain requests and pass data between them.

Setting Secrets

export function onResponse(req, res) {
  const data = res.json();

  // Save a sensitive value as a secret
  res.env.setSecret('REFRESH_TOKEN', data.refreshToken);
}

Environment Methods

MethodDescription
getVariable(key)Get a variable value (returns null if not found)
setVariable(key, value)Set a variable value
deleteVariable(key)Delete a variable
hasVariable(key)Check if variable exists
getSecret(key)Get a secret value (returns null if not found)
setSecret(key, value)Set a secret value
deleteSecret(key)Delete a secret
hasSecret(key)Check if secret exists
getAllVariables()Get all variables as an object
getAllSecrets()Get all secrets as an object

Mock Responses

You can return a YasumuResponse from onRequest to skip the actual HTTP request and return a mock response:

export function onRequest(req) {
  // Return a mock response instead of making the actual request
  if (req.url.includes('/mock')) {
    return new YasumuResponse(
      JSON.stringify({ message: 'This is a mock response' }),
      {
        status: 200,
        headers: { 'Content-Type': 'application/json' },
      },
    );
  }
}

This is useful for:

  • Testing without hitting the actual API
  • Simulating error responses
  • Development when the backend isn't available

Console Output

Use console.log() in your scripts to output debug information. The output appears in the Console tab of the response panel.

export function onRequest(req) {
  console.log('Request URL:', req.url);
  console.log('Request Method:', req.method);
}

export function onResponse(req, res) {
  console.log('Response Status:', res.status);
  console.log('Response Body:', res.json());
}

Runtime APIs

Yasumu scripts run in a Deno-based runtime, giving you access to modern JavaScript features and many Node.js/Deno APIs.

Web Standard APIs

These APIs are available in all modern JavaScript environments:

APIDescription
cryptoWeb Crypto API for hashing, encryption, etc.
TextEncoderEncode strings to Uint8Array
TextDecoderDecode Uint8Array to strings
atob / btoaBase64 encoding/decoding
fetchMake HTTP requests (use sparingly in scripts)
URL / URLSearchParamsURL manipulation
setTimeout / setIntervalTimers (async operations)
JSONJSON parsing and stringification
consoleLogging to the console tab

Node.js APIs

You can import Node.js built-in modules using the node: prefix:

import { Buffer } from 'node:buffer';
import { createHash, createHmac } from 'node:crypto';
import path from 'node:path';

export function onRequest(req) {
  // Using Node.js Buffer
  const data = Buffer.from('Hello, World!', 'utf-8');
  const base64 = data.toString('base64');
  req.headers.set('X-Encoded', base64);

  // Using Node.js crypto
  const hash = createHash('sha256').update(req.url).digest('hex');
  req.headers.set('X-URL-Hash', hash);
}

Example of some of the available Node.js modules

ModuleImportDescription
bufferimport { Buffer } from 'node:buffer'Binary data handling
cryptoimport crypto from 'node:crypto'Cryptographic functions
pathimport path from 'node:path'Path manipulation
utilimport util from 'node:util'Utility functions
querystringimport qs from 'node:querystring'Query string parsing
urlimport { URL } from 'node:url'URL parsing
assertimport assert from 'node:assert'Assertions for testing

Deno APIs

Deno-specific APIs are available through the global Deno object:

export function onRequest(req) {
  // Get environment variables (from system, not Yasumu env)
  const nodeEnv = Deno.env.get('NODE_ENV');
  console.log('NODE_ENV:', nodeEnv);

  // Check Deno version
  console.log('Deno version:', Deno.version.deno);
}

Permission System

Yasumu runs scripts in a sandboxed environment. When a script attempts to perform dangerous operations (like file system access), you'll be prompted to grant permission:

Permission Prompt

Example of some of the available Deno APIs

APIDescription
Deno.versionGet Deno, V8, and TypeScript versions
Deno.env.get(key)Read system environment variables
Deno.inspect(value)Pretty-print any value for debugging
Deno.noColorCheck if color output is disabled

Yasumu-Specific APIs

Yasumu provides additional utilities through the global Yasumu object:

APIDescription
Yasumu.cuid()Generate a collision-resistant unique identifier
Yasumu.versionGet the current Yasumu version
Yasumu.ui.showNotification()Show a toast notification in the UI
export function onRequest(req) {
  // Generate unique ID
  const id = Yasumu.cuid();
  req.headers.set('X-Request-ID', id);

  // Log Yasumu version
  console.log('Yasumu version:', Yasumu.version);
}

UI Notifications

You can display toast notifications in the Yasumu UI from your scripts:

export function onResponse(req, res) {
  if (res.ok) {
    await Yasumu.ui.showNotification({
      title: 'Success',
      message: 'Request completed successfully!',
      variant: 'success',
    });
  } else {
    await Yasumu.ui.showNotification({
      title: 'Error',
      message: `Request failed with status ${res.status}`,
      variant: 'error',
    });
  }
}

Notification Options

PropertyTypeDescription
titlestringThe title of the notification
messagestringThe message body of the notification
variantstringStyle variant: default, success, warning, info, error
// Different notification variants
await Yasumu.ui.showNotification({
  title: 'Info',
  message: 'Processing your request...',
  variant: 'info',
});

await Yasumu.ui.showNotification({
  title: 'Warning',
  message: 'Rate limit approaching',
  variant: 'warning',
});

Cryptographic Operations

Use the Web Crypto API for secure hashing and encryption:

export async function onRequest(req) {
  const apiKey = req.env.getSecret('API_KEY');
  const timestamp = Date.now().toString();

  // Create HMAC signature
  const encoder = new TextEncoder();
  const keyData = encoder.encode(apiKey);
  const message = encoder.encode(
    `${req.method}:${req.url}:${timestamp}`,
  );

  const key = await crypto.subtle.importKey(
    'raw',
    keyData,
    { name: 'HMAC', hash: 'SHA-256' },
    false,
    ['sign'],
  );

  const signature = await crypto.subtle.sign('HMAC', key, message);
  const signatureHex = Array.from(new Uint8Array(signature))
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('');

  req.headers.set('X-Timestamp', timestamp);
  req.headers.set('X-Signature', signatureHex);
}

Generating UUIDs

export function onRequest(req) {
  const requestId = crypto.randomUUID();
  req.headers.set('X-Request-ID', requestId);
}

Generating CUIDs

Yasumu provides a built-in method to generate collision-resistant unique identifiers (CUIDs):

export function onRequest(req) {
  const requestId = Yasumu.cuid();
  req.headers.set('X-Request-ID', requestId);
  console.log('Generated CUID:', requestId);
}

CUID vs UUID

CUIDs are shorter, URL-safe, and designed to be monotonically increasing, making them ideal for database IDs and distributed systems.

Hashing Data

export async function onResponse(req, res) {
  const body = res.text();
  const encoder = new TextEncoder();
  const data = encoder.encode(body);

  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('');

  console.log('Response SHA-256:', hashHex);
}

Base64 Encoding

export function onRequest(req) {
  const username = req.env.getVariable('USERNAME');
  const password = req.env.getSecret('PASSWORD');

  // Basic Auth header
  const credentials = btoa(`${username}:${password}`);
  req.headers.set('Authorization', `Basic ${credentials}`);
}

Async Functions

Scripts support async/await. If you use async APIs like crypto.subtle, make sure to declare your function as async and await the results.

Common Use Cases

Authentication

Add authentication headers dynamically:

export function onRequest(req) {
  const token = req.env.getSecret('AUTH_TOKEN');
  if (token) {
    req.headers.set('Authorization', `Bearer ${token}`);
  }
}

Token Refresh

Save tokens from login responses for use in subsequent requests:

export function onResponse(req, res) {
  if (res.ok && req.url.includes('/login')) {
    const data = res.json();
    res.env.setSecret('AUTH_TOKEN', data.accessToken);
    res.env.setSecret('REFRESH_TOKEN', data.refreshToken);
    console.log('Tokens saved to environment');
  }
}

Request Signing

Add signatures or timestamps to requests:

export function onRequest(req) {
  const timestamp = Date.now().toString();
  req.headers.set('X-Timestamp', timestamp);

  // Add a simple signature (in practice, use proper HMAC)
  const apiKey = req.env.getSecret('API_KEY');
  req.headers.set('X-Signature', btoa(`${apiKey}:${timestamp}`));
}

Response Validation

Validate responses and log warnings:

export function onResponse(req, res) {
  const data = res.json();

  if (!data.id) {
    console.warn('Response missing required field: id');
  }

  if (res.status === 401) {
    console.error('Authentication failed - token may be expired');
  }
}

Extracting Data for Chaining

Save response data for use in other requests:

export function onResponse(req, res) {
  const data = res.json();

  // Save the created resource ID for later requests
  res.env.setVariable('LAST_CREATED_ID', data.id);
  res.env.setVariable('LAST_CREATED_AT', data.createdAt);
}

Best Practices

  1. Keep scripts focused — Each script should do one thing well
  2. Use environment variables — Don't hardcode sensitive values in scripts
  3. Handle errors gracefully — Check for null values and error responses
  4. Use console.log for debugging — Output helps trace issues
  5. Document complex logic — Add comments for non-obvious code
  6. Test incrementally — Test scripts after each change

On this page