Skip to content

A frontend developers best friend. A CLI for executing TS/JS snippets locally, testing changes on production, web scraping and more!

Notifications You must be signed in to change notification settings

heyMP/scratchpad

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@heymp/scratchpad

A super fast way of debugging javascript snippets in a Playwright browser. If you love Chrome snippets but hate that they aren't portable then give Scratchpad a try!

scratchpad-demo.mp4

Usage

npx @heymp/scratchpad@next run ./my-test-file.js

Note: This is still in development. Use the next tag until 1.0 release is ready.

Commands

Usage: @heymp/scratchpad@next run <file> [options]

Run TS/JS snippets in a locally

Options:
  -V, --version         output the version number
  -h, --help            display help for command

Commands:
  run [options] <file>  Execute a file in a browser.
  generate              Generate files from templates or remote data.
  help [command]        display help for command

Config

An alternative to using the CLI flags, you can create scratchpad.config.js.

export default /** @type {import('@heymp/scratchpad/src/config').Config} */ ({
  devtools: true,
  url: 'https://google.com',
  headless: true,
});

Playwright runtime

The scratchpad.config.js exposes a method for altering the playwright runtime. This allows you to interact with the Playwright API to perform actions like blocking network requests or navigating to different urls. See https://playwright.dev/ for documentation on using the Playwright runtime.

export default ({
  devtools: true,
  url: 'https://google.com',
  headless: true,
  playwright: async (args) => {
    const { page, context } = args;
  }
});

Define Config

While you can create a scratchpad.config.js file above without installing this package, it's recommended to install @heymp/scratchpad and use the defineConfig helper to access the correct types.

Usage:

scratchpad.config.js

import { defineConfig } from '@heymp/scratchpad';

export default defineConfig({
  devtools: true,
  url: 'https://google.com',
  headless: true,
});

Save browser session

Using Playwright, you can launch a new session with the generate login command. This will launch a new browser session where you can authenticate to a website. After you have authenticated you can close the browser session. You session will be saved to a local file .scratchpad/login.json.

npx @heymp/scratchpad@next login

You can then reuse the session by using the login option when using the run command.

npx @heymp/scratchpad@next run --login

Reroute Local Files

The rerouteLocal function allows you to replace the contents of a document or asset file with a local file from your system. This is incredibly useful for testing changes or developing components in the context of a live site without deploying your code.

When used, rerouteLocal also watches for file for changes. If you save an update to the file, the Playwright page will automatically reload to reflect your latest edits, providing a fast feedback loop.

How it works:

  • It intercepts requests made by the Playwright `page.
  • If the request is not of type document it will URL's path to a local file structure.
  • If the request is of type document (e.g. http://example.com/user/profile) and you've set your local directory to './my-pages', the function will look for './my-pages/user/profile/index.html'.

Usage:

You would typically use this function within the playwright async method in your scratchpad.config.js:

scratchpad.config.js

import { defineConfig, rerouteDocument } from '@heymp/scratchpad';

export default defineConfig({
  url: 'https://example.com', // The initial URL you are working with
  playwright: async (args) => {
    const { page } = args;

    // Tell Scratchpad to serve local HTML files from the './pages' directory
    // whenever a document is requested.
    await rerouteLocal(page, './pages');

    // Now, if you navigate to https://example.com/some/path,
    // Scratchpad will try to serve './pages/some/path/index.html'.
    // If that file doesn't exist, it will load the original page from the web.

    // If there is a local file of `./assets/scripts.js` it will serve the contents
    // of that local file.
  }
});

🚨 It is highly recommended to add the .scratchpad directory to your .gitignore file. Never commit or share your session login.json file!

Reroute Documents [deprecated]

The rerouteDocument function allows you to replace the HTML content of any webpage with a local HTML file from your system. This is incredibly useful for testing changes or developing components in the context of a live site without deploying your code.

When used, rerouteDocument also watches your local HTML file for changes. If you save an update to the file, the Playwright page will automatically reload to reflect your latest edits, providing a fast feedback loop.

How it works:

  • It intercepts requests made by the Playwright page that are for HTML documents.
  • It maps the URL's path to a local file structure. For instance, if you are on http://example.com/user/profile and you've set your local directory to './my-pages', the function will look for './my-pages/user/profile/index.html'.

Usage:

You would typically use this function within the playwright async method in your scratchpad.config.js:

scratchpad.config.js

import { defineConfig, rerouteDocument } from '@heymp/scratchpad';

export default defineConfig({
  url: 'https://example.com', // The initial URL you are working with
  playwright: async (args) => {
    const { page } = args;

    // Tell Scratchpad to serve local HTML files from the './pages' directory
    // whenever a document is requested.
    await rerouteDocument(page, './pages');

    // Now, if you navigate to https://example.com/some/path,
    // Scratchpad will try to serve './pages/some/path/index.html'.
    // If that file doesn't exist, it will load the original page from the web.
  }
});

Reroute URLs

The rerouteUrl function gives you the power to intercept network requests for specific assets (like JavaScript files, CSS, images, or API calls) and redirect them. You can reroute a target URL to either another live source URL or to a source local file from your system. This is incredibly useful for testing local versions of assets against a live site, mocking API responses, or redirecting to different service endpoints without deploying code.

If you save an update to this file, the Playwright page will automatically reload to show your latest edits, creating a very fast development feedback loop.

How it works:

  • It uses Playwright's page.route() to intercept network requests that match the target URL or pattern you specify.
  • If you set type: 'url', it fetches the content from your specified source URL instead of the original target.
  • If you set type: 'path', it serves the content from your local source file. It also starts watching this file, and if any changes are detected, it reloads the page.

Usage:

You typically use rerouteUrl within the playwright async method in your configuration file (e.g., scratchpad.config.js):

scratchpad.config.js

import * as Scratchpad from '@heymp/scratchpad';

export default Scratchpad.defineConfig({
  url: 'https://www.your-website.com',
  playwright: async (args) => {
    const { page } = args;

    // Example 1: Reroute a specific JavaScript file to a local version
    await Scratchpad.rerouteUrl(page, {
      type: 'path',
      target: '**/scripts/main-app.js', // Intercept requests for this JS file
      source: './local-dev/main-app.js'  // Serve your local version instead
    });

    // Example 2: Reroute an API call to a different endpoint
    await Scratchpad.rerouteUrl(page, {
      type: 'url',
      target: 'https://api.production.com/data', // Original API endpoint
      source: 'https://api.staging.com/data'     // Reroute to staging API
    });

    // Example 3: Reroute an API call to a local mock JSON file
    await Scratchpad.rerouteUrl(page, {
      type: 'path',
      target: 'https://api.production.com/user/settings',
      source: './mocks/user-settings.json' // Serve local mock data
    });

    // Now, when the page requests '**/scripts/main-app.js',
    // your local './local-dev/main-app.js' will be served and auto-reloaded on change.
    // Requests to 'https://api.production.com/data' will go to the staging API.
  }
});

Generate files

Method Description Example
document Fetch HTML source of url and save it to a local file. This is helpful when using the rerouteDocument command. npx @heymp/scratchpad@next generate document https://www.example.com pages
login Launch a new browser that saves your session so it can be reused. npx @heymp/scratchpad@next generate login

Default exposed functions

The following functions are exposed by default that can be used in the run commands target file.

Method Description Example
log Log data to the stdnout of our terminal and to the Chromium Console it's running. Supports logging advanced types like Arrays, Generators, Iteratiors, Maps, Sets, and Functions. log(new Map([[1,2]])
clear Clear the previous console output results. clear()
writeFile Write data to a local file. writeFile('./log.txt', data)
appendFile Append data to a local file. appendFile('./log.txt', data)
readFile read data from a local file. readFile('./log.txt', 'utf8')

Log example

clear();
function* generator(limit) {
  for (let i = 0; i < limit; i++) {
    yield i;
  }
}

const set = new Set([1,2]);
const map = new Map([[1,2]]);

const gen = generator(10);
log([1,3]);
log(gen);
log(gen.next());
log([...gen]);
log(set);
log(map);
log(set.values());
log([...set.values()]);
log([...set.entries()]);
log(new Promise(res => res()));
log(function hello() { return 'world' });
log(undefined);

Custom exposed functions

You can provide your own custom exposed functions using the scratchpad.config.js file.

import * as Scratchpad from '@heymp/scratchpad';
import { join } from 'node:path'
import fs from 'node:fs/promises';

function loadFile(path) {
  return fs.readFile(join(process.cwd(), path), 'utf8');
}

export default defineConfig({
  playwright: async (args) => {
    const { context, page } = args;
    await context.exposeFunction('loadFile', loadFile)
  }
});

Typescript

Scratchpad also has out of the box support for Typescript. Any file that ends with .ts will be first transpiled by esbuild command. While you can execute typescript files using the npx @heymp/scratchpad command, it is reccommended to install the package locally so you can import the library typings.

Example:

npm install @heymp/scratchpad

Recommended tsconfig.json settings. NOTE: your local tsconfig.json file is only used to for your local Typescript LSP. The tsc commnand built in to the Scratchpad ignores your local tsconfig.json file. If you need to add custom rules to the compiled output that is executed in the chromium browser then you will need hand the ts -> js compile step yourself.

{
  "target": "esnext",
  "compilerOptions": {
    "types": ["./node_modules/@heymp/scratchpad/types.d.ts"]
  }
}

An alternative to the tsconfig.json file is to use the following triple-slash comment in your .ts files:

/// <reference path="./node_modules/@heymp/scratchpad/types.d.ts" />

Development

npm install
./bin/cli.js -h

About

A frontend developers best friend. A CLI for executing TS/JS snippets locally, testing changes on production, web scraping and more!

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •