Created
September 7, 2019 03:37
-
-
Save Dletta/a1856f223a0d8baf5fe618960328d811 to your computer and use it in GitHub Desktop.
Gun in Service Worker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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/[email protected]/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/[email protected]/lib/wire.js') | |
var res = await fetch(req); | |
var data = await res.text(); | |
eval(data); | |
var req = new Request('https://cdn.jsdelivr.net/npm/[email protected]/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/[email protected]/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