This monorepo contains three related libraries that work together to help you record, sanitize, extract, and replay HTTP API traffic in your tests:
| Package | Description |
|---|---|
mustachr |
Extracts or injects values in string files using Mustache-style templates ({{ TOKEN }}) |
workhar |
Converts .har files to .json fixtures and back |
playhar |
Ties everything together — record via CLI, then mock HARs during tests |
playhar is the core workflow layer that ties everything together.
It launches a real Playwright browser, records API traffic into a .har file, sanitizes sensitive values with mustache-style templates, and extracts response bodies into editable .json fixtures. These can then be rebuilt into usable HARs and replayed with page.routeFromHAR() in your tests.
npm install --save-dev playharAlso ensure you have Playwright installed:
npm install -D @playwright/testimport { defineConfig } from 'playhar';
export default defineConfig({
directory: './recordings',
baseRequestUrl: 'https://api.example.com',
extractions: [
{
type: 'regex',
property: 'SECRET_TOKEN',
search: 'token":"[^"]*',
replace: 'token":"{{ property }}"'
}
],
});playhar record --url http://localhost:5173 --config ./playhar.config.ts
playhar mock --name auth-flow --injections ./injections.json --out ./mocked.harimport { record, mock, configFromFile } from 'playhar';
const config = await configFromFile({ file: './playhar.config.ts', fallbacks: [] });
await record({ config, name: 'auth-flow', url: 'http://localhost:5173' });
const har = await mock({
config,
name: 'auth-flow',
injections: { SECRET_TOKEN: 'mocked-token' },
});workhar is the engine that powers Playhar’s extraction and hydration process. It turns .har files into structured .json files you can edit, and then regenerates HARs from those responses.
npm install --save-dev workharworkhar har2json ./recording.har ./.workhar --json ./json
workhar json2har ./.workhar ./hydrated.har --json ./jsonimport { har2json, json2har } from 'workhar';
await har2json({
fromHarFile: './recording.har',
toWorkharFile: './.workhar',
withJsonDirectory: './json',
});
await json2har({
fromWorkHarFile: './.workhar',
withJsonDirectory: './json',
toHarFile: './hydrated.har',
});mustachr lets you extract hardcoded secrets or values from text files and replace them with mustache-style template tokens (like {{ SECRET }}). You can later inject them back using an injection map.
npm install --save-dev mustachrmustachr extract ./api.har --extractions ./mustachr.extractions.ts
mustachr inject ./api.har --injections ./mustachr.injections.tsimport { extract, inject, defineExtractions, defineInjections } from '@adameisfeld/mustachr';
const extracted = await extract({
input: fs.readFileSync('./api.har', 'utf-8'),
extractions: defineExtractions([
{
type: 'string',
property: 'SECRET',
search: 'SuperSecret123',
replace: '{{ property }}',
},
]),
});
const hydrated = inject({
input: extracted,
injections: defineInjections({ SECRET: 'MockedValue' }),
});All packages are 100% test-covered and tested with Vitest. Run all tests from the monorepo root:
npm run testworkhar-playhar/
├── packages/
│ ├── mustachr/
│ ├── workhar/
│ └── playhar/
├── README.md
├── turbo.json
└── ...
MIT © 2025 Adam Eisfeld