Skip to content

Instantly share code, notes, and snippets.

@pwFoo
Forked from Dletta/index.html
Created August 8, 2023 07:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pwFoo/d83608e34ba3b1603838c2783ad5bb51 to your computer and use it in GitHub Desktop.
Save pwFoo/d83608e34ba3b1603838c2783ad5bb51 to your computer and use it in GitHub Desktop.
Gun in Service Worker
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Concept Chat</title>
<link rel="stylesheet" href="index.css" >
</head>
<body>
Service Worker Example, connect to gun super peer from any other client and see the magic
then close the tabe and write to gun.get('test') again and see even more magic!!
</body>
<script type="text/javascript">
// register service worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
Notification.requestPermission(function(result) {
if (result === 'granted') {
navigator.serviceWorker.ready
}
});
} else {
console.log('Your browser does not support Service Workers.')
}
// register handler for messages from sw
navigator.serviceWorker.addEventListener('message', receipt);
</script>
</html>
/* Service Worker to receive notification via gun even when the page is not open */
//initialize a sw
const CACHE_NAME = "Cachev2";
const urlsToCache = ["/"];
var client;
// handle fetch events
self.addEventListener('fetch', (event) => {
console.log('[SERVICEWORKER] Fetching', event.request)
event.respondWith (
fetchHandler(event)
)
})
async function fetchHandler(event) {
var res = await caches.match(event.request);
if(res) {
console.log('served from Cache');
return res;
} else {
console.log('served from Network');
var res = await fetch(event.request);
return res;
}
}
// Handle install event
self.addEventListener('install', function(event) {
console.log('[SERVICEWORKER] Install step called', event);
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache', CACHE_NAME);
return cache.addAll(urlsToCache);
}).then(()=>{
return self.skipWaiting();
})
)
})
// Handle activation event // directly claim without waiting for refresh
self.addEventListener('activate', (event) => {
event.waitUntil(
activateHandler(event)
)
})
async function activateHandler (event) {
console.log('[SERVICEWORKER] Activation called', event);
var clients = await self.clients.matchAll({includeUncontrolled:true});
if(clients) {
var urls = clients.map((client) => {
return client.url;
});
console.log('[ServiceWorker] Matching clients:', urls.join(', '));
}
var cacheNames = await caches.keys();
await Promise.all(
cacheNames.map(function(cacheName) {
if (cacheName !== CACHE_NAME) {
console.log('[ServiceWorker] Deleting old cache:', cacheName);
return caches.delete(cacheName);
}
}
)
)
console.log('[ServiceWorker] Claiming clients for version', CACHE_NAME);
return self.clients.claim();
}
/* Push notification via Gun */
self.addEventListener('push', function(event){
// register the a notification will go through
self.registration.showNotification('Notify Gun', {
body: event.data.name //needs to be a string to show up good (tried object and gave [Object object]
});
});
var evPush = new CustomEvent('push', {body:'test'}); //so we can fire it when we want to (usually if is fired from the server
/* Gun implementation in Service Worker */
var window = {}; // Gun injects into global window (sw env doesn't have that
var gun; //instantiate gun
var app; //app etc
var ws; //ws for 'imports'
// to avoid having to use url utility from node / browser (also not available in sw env)
function url () {
this.parse = function (string) {
return string
}
}
// not available in serviceworker, so need to add here to fake it and bake it
function require (string) {
console.log(string);
if(string == '../gun'){
return window.Gun;
} else if (string == 'ws') {
return WebSocket;
} else if (string == 'url'){
return new url;
}
}
// IIFE to create a gun instance from the cdn in the serviceworker haven't tried with latest gun (sorry Mark)
(async function (){
var req = new Request('https://cdn.jsdelivr.net/npm/gun@0.2019.627/gun.min.js')
var res = await fetch(req);
var data = await res.text(); //turns file into text
eval(data); //evals the data Let's hope cdn wasn't overtaken by hackers
var req = new Request('https://cdn.jsdelivr.net/npm/gun@0.2019.627/lib/wire.js')
var res = await fetch(req);
var data = await res.text();
eval(data);
var req = new Request('https://cdn.jsdelivr.net/npm/gun@0.2019.627/lib/ws.js')
var res = await fetch(req);
ws = await res.text();
eval(ws); //make websocket 'global'
var req = new Request('https://cdn.jsdelivr.net/npm/gun@0.2019.627/lib/then.js') //will change to promise.js later
var res = await fetch(req);
var data = await res.text();
eval(data);
var peers = ['ws://guntest.herokuapp.com/gun'] //any super peer will do
gun = window.Gun({peers:peers, localStorage:false, radisk:false, axe:false}); //don't need persistence but indexeddb is available in sw
// just watch out, as the client code uses the same indexeddb and there might be write issues
gun._.on('hi', console.log); //set up some logging to show we are connected
gun._.on('out', (msg) => {console.log('out',msg)}); // log outgoing stuff
gun._.on('in', (msg) => {console.log('in--------',msg)}); // log coming in stuff
app = gun.get('conceptChat'); // namespace to global object
console.log(await app.then()); //checking if there is something
gun.get('test').on(async function (data) { //subscribe to 'address' where notifications are written to
evPush.data = data; //get data and pass it to the custom event
self.dispatchEvent(evPush) //fire the custom event (which fires 'push' listener and send message to index.html
/*
self.registration.showNotification('Notify Gun', {
body: event.data.name //needs to be a string to show up good (tried object and gave [Object object]
});*/ //might work too, haven't tried, saves us making an event listener, but might mean it won't keep service worker running
})
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment