Skip to content

Instantly share code, notes, and snippets.

@andy0130tw
Created November 15, 2023 14:29
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 andy0130tw/76352f747f7a1d9b3210e9535db7e4a1 to your computer and use it in GitHub Desktop.
Save andy0130tw/76352f747f7a1d9b3210e9535db7e4a1 to your computer and use it in GitHub Desktop.
First try on WasmFS using petersalomonsen/wasm-git with emscripten 3.1.49
// place this at src/routes/git-proxy/[...path]/+server.js
// modified from
// https://github.com/petersalomonsen/wasm-git/blob/master/examples/webserverwithgithubproxy.js
import https from 'node:https'
import { Readable } from 'node:stream'
import { error } from '@sveltejs/kit'
/**
* Simple webserver with proxy to github.com
*/
/** @type {import('./$types').RequestHandler} */
export function fallback({ params, request }) {
const { path: pathname } = params
const query = new URL(request.url).searchParams
const path = '/' + pathname + '?' + query
if (path.indexOf('git-upload') != -1 ||
path.indexOf('git-receive') != -1) {
const options = {
hostname: 'github.com',
port: 443,
path: path,
method: request.method,
};
console.log(`Proxying ${options.method} request to ${options.hostname} with path ${options.path}`);
return new Promise(resolve => {
const proxy = https.request(options, incoming => {
const readable = Readable.toWeb(incoming)
resolve(new Response(readable))
})
if (options.method == 'GET') {
proxy.end()
} else {
const requestBody =
/** @type {import('node:stream/web').ReadableStream<Uint8Array>} */
(request.body)
Readable.fromWeb(requestBody).pipe(proxy, { end: true })
}
})
} else {
throw error(404, 'Not found')
}
}
export {}
function assertZero(/** @type {any} */n) {
if (n !== 0) {
throw new Error(`Return value is not zero: ${n}`)
}
}
function calculateTotalSize(
/** @type {Record<number, Uint8Array | undefined>} */ map) {
let size = 0
for (let buf of Object.values(map)) {
if (buf) size += buf.length
}
return size
}
// trick into that we are running in web (actually we are)
// @ts-ignore
self.window = {}
const Module = {
locateFile(s) {
if (s === 'lg2.wasm') {
s = 'lg2-wasmfs.wasm'
}
return '/' + s
},
print(s) {
postMessage({type: 'print', value: s})
},
printErr(v) {
console.error(v)
},
}
const module = await import('./lg2-wasmfs.js')
function makeAsyncFS(backends, JSFILEFS) {
function wrapBackendImplAt(ptr, opts) {
console.log(backends[ptr])
return backends[ptr]
}
return {
createBackend(opts) {
const ptr = JSFILEFS.createBackend()
backends[ptr] = wrapBackendImplAt(ptr, opts)
return ptr
}
}
}
Module.onRuntimeInitialized = async () => {
const lg = Module
const {
FS,
JSFILEFS,
wasmFS$backends,
wasmFS$JSMemoryFiles } = Module
console.warn(Object.keys(Module))
console.warn(Object.keys(FS))
const ASYNCFS = makeAsyncFS(wasmFS$backends, JSFILEFS)
// to work around WasmFS's bug where newly-mounted FS has empty dir name
// causing all operations using CWD to behave weirdly, as of emscripten 3.1.49
assertZero(FS.mount(ASYNCFS, { }, '/.xxx'))
assertZero(FS.rename('.xxx', 'working'))
assertZero(FS.chdir('/working'))
assertZero(
FS.writeFile('/home/web_user/.gitconfig',
'[user]\n' +
'name = Test User\n' +
'email = test@example.com'))
assertZero(FS.chdir('/working'))
console.log('dir', FS.cwd())
const ref = 'ewxrjk/sftpserver'
const repoUrl = new URL(`/git-proxy/${ref}.git`, self.location.toString()).toString()
lg.callMain(['clone', repoUrl, 'testrepo'])
assertZero(FS.chdir('testrepo'))
lg.callMain(['log'])
postMessage({type: 'readdir', value: FS.readdir('.')})
// console.warn(wasmFS$backends)
console.warn('total size', calculateTotalSize(wasmFS$JSMemoryFiles))
}
await module.default(Module)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment