Compare commits

...

4 commits

Author SHA1 Message Date
Cat /dev/Nulo 30b2482ed5 0.3.1 - compilar para webpack4 2023-05-16 19:56:12 -03:00
Cat /dev/Nulo b22f2b5741 0.3.0 - usar fetch y coso 2023-05-16 19:48:26 -03:00
Cat /dev/Nulo d44e35d40e 0.2.9 - don't need fs 2023-05-16 19:39:48 -03:00
Cat /dev/Nulo d64787ddc3 es2020 2023-05-16 19:31:24 -03:00
4 changed files with 37 additions and 50 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "@nulo/isogit-lfs", "name": "@nulo/isogit-lfs",
"version": "0.2.8", "version": "0.3.1",
"description": "LFS helpers for Isomorphic Git", "description": "LFS helpers for Isomorphic Git",
"main": "dist/index.js", "main": "dist/index.js",
"repository": "git@github.com:riboseinc/isogit-lfs.git", "repository": "git@github.com:riboseinc/isogit-lfs.git",

View file

@ -3,7 +3,7 @@ import { Buffer } from "buffer";
import { bodyToBuffer, getAuthHeader, isWriteable } from "./util"; import { bodyToBuffer, getAuthHeader, isWriteable } from "./util";
import { Pointer } from "./pointers"; import { Pointer } from "./pointers";
import { HTTPRequest } from "./types"; import { HTTPRequest, BasicAuth } from "./types";
import { PromiseFsClient } from "isomorphic-git"; import { PromiseFsClient } from "isomorphic-git";
interface LFSInfoResponse { interface LFSInfoResponse {
@ -28,23 +28,27 @@ function isValidLFSInfoResponseData(
* Uses already cached object, if size matches. * Uses already cached object, if size matches.
*/ */
export default async function downloadBlobFromPointer( export default async function downloadBlobFromPointer(
{ promises: fs }: PromiseFsClient, fs: PromiseFsClient | null,
{ http: { request }, headers = {}, url, auth }: HTTPRequest, url: string,
auth: BasicAuth | {},
{ info, objectPath }: Pointer { info, objectPath }: Pointer
): Promise<Buffer> { ): Promise<Blob> {
try { if (fs) {
const cached = await fs.readFile(objectPath); try {
if (cached.byteLength === info.size) { const cached = await fs?.promises.readFile(objectPath);
return cached; if (cached.byteLength === info.size) {
} return cached;
} catch (e) { }
// Silence file not found errors (implies cache miss) } catch (e) {
if ((e as any).code !== "ENOENT") { // Silence file not found errors (implies cache miss)
throw e; if ((e as any).code !== "ENOENT") {
throw e;
}
} }
} }
const authHeaders: Record<string, string> = auth ? getAuthHeader(auth) : {}; const authHeaders: Record<string, string> =
"username" in auth ? getAuthHeader(auth) : {};
// Request LFS transfer // Request LFS transfer
@ -54,29 +58,18 @@ export default async function downloadBlobFromPointer(
objects: [info], objects: [info],
}; };
const { body: lfsInfoBody } = await request({ const lfsInfoRes = await fetch(`${url}/info/lfs/objects/batch`, {
url: `${url}/info/lfs/objects/batch`,
method: "POST", method: "POST",
headers: { headers: {
// Github LFS doesnt seem to accept this UA, but works fine without any // Github LFS doesnt seem to accept this UA, but works fine without any
// 'User-Agent': `git/isomorphic-git@${git.version()}`, // 'User-Agent': `git/isomorphic-git@${git.version()}`,
...headers,
...authHeaders, ...authHeaders,
Accept: "application/vnd.git-lfs+json", Accept: "application/vnd.git-lfs+json",
"Content-Type": "application/vnd.git-lfs+json", "Content-Type": "application/vnd.git-lfs+json",
}, },
body: [Buffer.from(JSON.stringify(lfsInfoRequestData))], body: JSON.stringify(lfsInfoRequestData),
}); });
const lfsInfoResponseData = await lfsInfoRes.json();
const lfsInfoResponseRaw = (await bodyToBuffer(lfsInfoBody)).toString();
let lfsInfoResponseData: any;
try {
lfsInfoResponseData = JSON.parse(lfsInfoResponseRaw);
} catch (e) {
throw new Error(
`Unexpected structure received from LFS server: unable to parse JSON ${lfsInfoResponseRaw}`
);
}
if (isValidLFSInfoResponseData(lfsInfoResponseData)) { if (isValidLFSInfoResponseData(lfsInfoResponseData)) {
// Request the actual blob // Request the actual blob
@ -85,24 +78,21 @@ export default async function downloadBlobFromPointer(
const lfsObjectDownloadURL = downloadAction.href; const lfsObjectDownloadURL = downloadAction.href;
const lfsObjectDownloadHeaders = downloadAction.header ?? {}; const lfsObjectDownloadHeaders = downloadAction.header ?? {};
const dlHeaders = { const lfsObjectRes = await fetch(lfsObjectDownloadURL, {
...headers,
...authHeaders,
...lfsObjectDownloadHeaders,
};
const { body: lfsObjectBody } = await request({
url: lfsObjectDownloadURL,
method: "GET", method: "GET",
headers: dlHeaders, headers: {
...authHeaders,
...lfsObjectDownloadHeaders,
},
}); });
const blob = await lfsObjectRes.blob();
const blob = await bodyToBuffer(lfsObjectBody); if (fs) {
// Write LFS cache for this object, if cache path is accessible.
// Write LFS cache for this object, if cache path is accessible. if (await isWriteable(fs, objectPath)) {
if (await isWriteable({ promises: fs }, objectPath)) { await fs.promises.mkdir(path.dirname(objectPath), { recursive: true });
await fs.mkdir(path.dirname(objectPath), { recursive: true }); await fs.promises.writeFile(objectPath, blob);
await fs.writeFile(objectPath, blob); }
} }
return blob; return blob;

View file

@ -75,11 +75,7 @@ export default async function populateCache(
total: 10, total: 10,
}); });
await downloadBlobFromPointer( await downloadBlobFromPointer(fs, remoteURL, {}, pointer);
fs,
{ http, url: remoteURL },
pointer
);
} }
} }
} }

View file

@ -1,6 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es2018", "target": "es2015",
"lib": ["es2020", "DOM"],
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",