Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jcubic/wayne
Service Worker Routing library for in browser HTTP requests
https://github.com/jcubic/wayne
browser fake filesystem filesystem-library http http-server http-server-library javascript promise routing service-worker wayne web-server
Last synced: 23 days ago
JSON representation
Service Worker Routing library for in browser HTTP requests
- Host: GitHub
- URL: https://github.com/jcubic/wayne
- Owner: jcubic
- License: mit
- Created: 2022-07-07T14:10:45.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2024-09-04T15:04:36.000Z (2 months ago)
- Last Synced: 2024-09-06T20:02:00.045Z (2 months ago)
- Topics: browser, fake, filesystem, filesystem-library, http, http-server, http-server-library, javascript, promise, routing, service-worker, wayne, web-server
- Language: JavaScript
- Homepage: https://jcubic.github.io/wayne
- Size: 3.55 MB
- Stars: 550
- Watchers: 13
- Forks: 29
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
[![npm](https://img.shields.io/badge/npm-0.18.3-blue.svg)](https://www.npmjs.com/package/@jcubic/wayne)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://makeapullrequest.com)
[![jSDelivr](https://data.jsdelivr.com/v1/package/npm/@jcubic/wayne/badge)](https://www.jsdelivr.com/package/npm/@jcubic/wayne)[Service Worker Routing library for in-browser HTTP requests](https://github.com/jcubic/wayne/)
It's like an Express inside Service Worker.
Most of the time Service Worker is used for caching HTTP requests and making the app work when there
is no internet (mostly for [PWA](https://en.wikipedia.org/wiki/Progressive_web_application)), but in
fact, you can create completely new responses to requests that never leave the browser. This library
makes that easier by adding a simple API similar to Express.## Usage
Installation from npm:
```bash
npm install @jcubic/wayne
``````bash
yarn add @jcubic/wayne
```The standard way of installing the service worker
```javascript
if ('serviceWorker' in navigator) {
const scope = location.pathname.replace(/\/[^\/]+$/, '/');
navigator.serviceWorker.register('sw.js', { scope, type: 'module' })
.then(function(reg) {
reg.addEventListener('updatefound', function() {
const installingWorker = reg.installing;
console.log('A new service worker is being installed:',
installingWorker);
});
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
}
```If you want to support browsers that don't support ES Modules in Service Worker use this instead:
```javascript
if ('serviceWorker' in navigator) {
const scope = location.pathname.replace(/\/[^\/]+$/, '/');
navigator.serviceWorker.register('sw.js', { scope })
.then(function(reg) {
reg.addEventListener('updatefound', function() {
const installingWorker = reg.installing;
console.log('A new service worker is being installed:',
installingWorker);
});
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
}
```Inside the same file you can send [AJAX](https://en.wikipedia.org/wiki/Ajax_(programming)) requests with standard
[fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).```javascript
function get(url) {
fetch(url)
.then(res => res.text())
.then(text => output.innerHTML = text);
}input.addEventListener('click', () => {
get(`./user/${user_id.value}`);
});error.addEventListener('click', () => {
get(`./error`);
});
```Service worker - **sw.js** file
Importing Wayne module:
* when worker created as ES Module
```javascript
import { Wayne } from 'https://cdn.jsdelivr.net/npm/@jcubic/wayne';const app = new Wayne();
```* When the Service Worker created as normal script
```javascript
importScripts('https://cdn.jsdelivr.net/npm/@jcubic/wayne/index.umd.min.js');const app = new wayne.Wayne();
```* When using bundlers like Vite:
```javascript
import { Wayne } from '@jcubic/wayne';
```Using the library
```javascript
const users = {
1: 'Jakub T. Jankiewicz',
2: 'John Doe',
3: 'Jane Doe'
};app.get('/user/{id}', function(req, res) {
const user = users[req.params.id];
if (user) {
res.json({result: user});
} else {
res.json({error: 'User Not Found'});
}
});app.get('/error', function(req, res) {
nonExisting();
});app.get('/redirect', function(req, res) {
res.redirect(301, '/message');
});app.get('/message', function(req, res) {
res.text('Lorem Ipsum');
});app.get('/404', function(req, res) {
res.text('Not Found', { status: 404, statusText: 'Not Found' });
});app.get('/external', function(req, res) {
// lorem ipsum API
res.redirect('https://api.buildable.dev/@62d55492951509001abc363e/live/lorem-ipsum');
});
```### Handle the same extension for all requests
```javascript
importScripts(
'https://cdn.jsdelivr.net/npm/@jcubic/wayne/index.umd.min.js',
'https://cdn.jsdelivr.net/gh/jcubic/static@master/js/path.js'
);const app = new Wayne();
app.get('*', function(req, res) {
const url = new URL(req.url);
const extension = path.extname(url.pathname);
const accept = req.headers.get('Accept');
if (extension === '.js' && accept.match(/text\/html/)) {
res.text('// Sorry no source code for you');
} else {
res.fetch(req);
}
});
```This code will show the comment `// Sorry no source code for you` for every request to JavaScript
files from the browser (if open in a new tab). When you want to view the file the browser sends
`Accept: text/html` HTTP header.### File system middleware
```javascript
import { Wayne, FileSystem } from 'https://cdn.jsdelivr.net/npm/@jcubic/wayne';
import FS from "https://cdn.skypack.dev/@isomorphic-git/lightning-fs";
import mime from "https://cdn.skypack.dev/mime";
import path from "https://cdn.skypack.dev/path-browserify";const { promises: fs } = new FS("__wayne__");
const app = new Wayne();
app.use(FileSystem({ path, fs, mime, prefix: '__fs__' }));
```When not using a module the code will be similar. When you access URLs with
the prefix `__fs__` like `./__fs__/foo` it will read files from the indexedDB file
system named `__wayne__`. See [Lightning-FS](https://github.com/isomorphic-git/lightning-fs) repo for details about the library.From version 0.12 you can use `test` callback option to check if the file should serve from the filesystem. Note that it will receive URLs from all domains.
From version 0.13.0 you can use `dir` callback function that allow to dynamically change directory of served files.
```javascript
const test = url => {
const path = url.pathname;
// return true if pathname should go to filesystem
return path.match(/__fs__/);
};const dir = () => '/';
app.use(wayne.FileSystem({ path, fs, mime, test, dir }));
```From version 0.14.0 both functions `dir` and `test` can be async. So you can use data from IndexedDB
e.g. using [idb-keyval](https://github.com/jakearchibald/idb-keyval) by Jake Archibald.A patch in 0.14.3 allow putting interceptors to inject something into output HTML from FileSystem
middleware. You do this by adding middleware before FileSystem and patch `res.send` method:```javascript
function fs_interecept(callback) {
return function(req, res, next) {
const send = res.send.bind(res);
res.send = function(data, ...rest) {
const url = new URL(req.url);
if (test(url)) {
data = callback(data);
}
return send(data, ...rest);
};
next();
};
}app.use(fs_interecept(function(html) {
return html.replace(/<\/body>/, `console.log('intercepted')This request is blocked