Skip to content

Instantly share code, notes, and snippets.

@billiegoose
Created November 25, 2018 21:31
Show Gist options
  • Save billiegoose/0d01856a63c45e24ffe88e0470909b18 to your computer and use it in GitHub Desktop.
Save billiegoose/0d01856a63c45e24ffe88e0470909b18 to your computer and use it in GitHub Desktop.
worker-gist (isomorphic-git)
<div>
<input id="repository" type="text" style="width: 50em" title="Tip: enter a private repo URL to see the credentialManager plugin prompt for a password.">
<button type="button" onClick="clone()" id="cloneButton">Clone</button>
</div>
<output id="log" style="white-space: pre; font-family: monospace;"></output>
<script src="./proxyReceiver.js"></script>
<script src="./proxySender.js"></script>
<script>
let worker = new Worker("./worker.js")
worker.addEventListener('message', ({data}) => console.log(data))
// Wrap whatever functions you use
const git = proxySender(worker, 'git', ['clone', 'listBranches'])
const readyHandler = async ({ data }) => {
if (data.type === 'ready') {
worker.removeEventListener('message', readyHandler)
document.getElementById('log').textContent += 'ready\n';
document.getElementById('repository').value = 'https://github.com/isomorphic-git/isomorphic-git'
document.getElementById('cloneButton').addEventListener('click', async () => {
document.getElementById('log').textContent = '';
await git.clone({
dir: '.',
corsProxy: 'https://cors.isomorphic-git.org',
url: document.getElementById('repository').value,
singleBranch: true,
depth: 100
})
let branches = await git.listBranches({ dir: '.', remote: 'origin' })
console.log('branches', branches)
document.getElementById('log').textContent += 'branches ' + branches + '\n';
})
}
}
worker.addEventListener('message', readyHandler)
// 'emitter' plugin
const emitter = {
async emit (event, message) {
if (event === 'message') {
document.getElementById('log').textContent += message + '\n';
}
}
}
proxyReceiver(worker, 'emitter', emitter)
// 'credentialManager' plugin
const credentialManager = {
async fill({ url }) {
let username = window.prompt("Username:")
let password = window.prompt("Password:")
return { username, password }
},
async approved({ url, auth }) {
return
},
async rejected({ url, auth }) {
window.alert('Authentication rejected')
return
}
}
proxyReceiver(worker, 'credentialManager', credentialManager)
window.git = git;
window.worker = worker;
console.log(git);
</script>
function proxyReceiver (channel, name, object) {
channel.addEventListener('message', ({ data }) => {
if (data.type === 'RPC_CALL' && data.object === name) {
object[data.method](...data.args)
.then(result => data.reply && channel.postMessage({ type: 'RPC_RETURN', object: name, method: data.method, id: data.id, result }))
.catch(err => channel.postMessage({ type: 'RPC_RETURN', object: name, method: data.method, id: data.id, error: err.message }))
}
})
}
let rpc_counter = 0
function proxySender(channel, object, methods, reply = true) {
const proxy = {}
for (let method of methods) {
proxy[method] = (...args) => {
rpc_counter = (rpc_counter + 1) % Number.MAX_SAFE_INTEGER
return new Promise((resolve, reject) => {
let callId = rpc_counter
if (reply) {
// Wait for response
const handler = ({ data }) => {
if (data.type === 'RPC_RETURN' && data.id === callId) {
// Don't leak event listeners
channel.removeEventListener('message', handler)
if (data.error) {
reject(data.error)
} else {
resolve(data.result)
}
}
}
channel.addEventListener('message', handler)
}
// Send message to worker
channel.postMessage({ type: 'RPC_CALL', object, method, id: callId, args, reply })
if (!reply) resolve()
})
}
}
return proxy
}
importScripts(
"https://isomorphic-git.org/js/browserfs.js",
"https://unpkg.com/isomorphic-git",
"./proxyReceiver.js",
"./proxySender.js"
)
let fsOptions = {
fs: 'IndexedDB',
options: {}
}
BrowserFS.configure(fsOptions, function (err) {
if (err) return console.log(err)
// Initialize isomorphic-git
const fs = BrowserFS.BFSRequire('fs')
git.plugins.set('fs', fs)
let emitter = proxySender(self, 'emitter', ['emit'], false)
git.plugins.set('emitter', emitter)
let credentialManager = proxySender(self, 'credentialManager', ['fill', 'approved', 'rejected'])
git.plugins.set('credentialManager', credentialManager)
fs.getRootFS().empty(() => {
fs.mkdir('/', () => {
proxyReceiver(self, 'git', git)
self.postMessage({ type: 'ready' })
})
})
})
self.addEventListener('message', ({data}) => console.log(data))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment