Created
December 29, 2021 16:31
-
-
Save tatemz/239be89051d557e33f23174dc42c1fce to your computer and use it in GitHub Desktop.
Sample of isomorphic git in Deno
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
import { encode } from "https://deno.land/[email protected]/encoding/base64url.ts"; | |
import { join } from "https://deno.land/[email protected]/path/mod.ts"; | |
import fs from "https://deno.land/[email protected]/node/fs.ts"; | |
import git from "http://esm.sh/[email protected]"; | |
import http from "http://esm.sh/[email protected]/http/web"; | |
import { QueryHandler } from "./QueryHandler.ts"; | |
const throwFSError = (e: Error) => { | |
if (e instanceof Deno.errors.AlreadyExists) { | |
throw { ...e, code: "EEXIST" }; | |
} | |
if (e instanceof Deno.errors.NotFound) { | |
throw { ...e, code: "ENOENT" }; | |
} | |
if (e.message.startsWith("Not a directory")) { | |
console.log(typeof e); | |
throw { ...e, code: "ENOTDIR" }; | |
} | |
throw e; | |
}; | |
const denoFS = { | |
...fs, | |
promises: { | |
...fs.promises, | |
readFile: async ( | |
...args: Parameters<typeof fs.promises.readFile> | |
) => { | |
try { | |
return await fs.promises.readFile(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
writeFile: async ( | |
...args: Parameters<typeof fs.promises.writeFile> | |
) => { | |
try { | |
return await fs.promises.writeFile(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
mkdir: async (...args: Parameters<typeof fs.promises.mkdir>) => { | |
try { | |
return await fs.promises.mkdir(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
rmdir: async (...args: Parameters<typeof fs.promises.rmdir>) => { | |
try { | |
return await fs.promises.rmdir(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
unlink: async (...args: Parameters<typeof fs.promises.unlink>) => { | |
try { | |
return await fs.promises.unlink(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
stat: async (...args: Parameters<typeof fs.promises.stat>) => { | |
try { | |
return await fs.promises.stat(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
lstat: async (...args: Parameters<typeof fs.promises.lstat>) => { | |
try { | |
return await fs.promises.lstat(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
readdir: async (...args: Parameters<typeof fs.promises.readdir>) => { | |
try { | |
return await fs.promises.readdir(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
readlink: async ( | |
...args: Parameters<typeof fs.promises.readlink> | |
) => { | |
try { | |
return await fs.promises.readlink(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
symlink: async (...args: Parameters<typeof fs.promises.symlink>) => { | |
try { | |
return await fs.promises.symlink(...args); | |
} catch (e) { | |
throwFSError(e); | |
} | |
}, | |
}, | |
}; | |
export const makeQueryHandler = (): QueryHandler => { | |
const cache = {}; | |
const tmpDir = Deno.makeTempDirSync(); | |
const textEncoder = new TextEncoder(); | |
return async (query) => { | |
const { params: { remote, ref } } = query; | |
const dir = join(tmpDir, encode(textEncoder.encode(`${remote}:${ref}`))); | |
const refsWithPrefix = await git.listServerRefs({ | |
http, | |
url: remote, | |
prefix: ref, | |
protocolVersion: 2, | |
}); | |
const matchingRefs = refsWithPrefix.filter((refWithPrefix) => | |
refWithPrefix.ref === ref | |
); | |
if (!matchingRefs || matchingRefs.length !== 1) { | |
throw new Error("ref invalid"); | |
} | |
const refSHA = matchingRefs[0].oid; | |
await git.init({ | |
fs: denoFS, | |
dir, | |
}); | |
await git.addRemote({ | |
fs: denoFS, | |
dir, | |
remote: "origin", | |
url: remote, | |
}); | |
await git.fetch({ | |
fs: denoFS, | |
http, | |
dir, | |
url: remote, | |
singleBranch: true, | |
ref: refSHA, | |
tags: ref.startsWith("refs/tags"), | |
cache, | |
}); | |
return { | |
type: "GitLog", | |
data: await git.log({ | |
fs: denoFS, | |
dir, | |
ref: refSHA, | |
cache, | |
}) || [], | |
}; | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment