Initial commit
This commit is contained in:
commit
ea6e7a8ece
11 changed files with 520 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/dist
|
||||||
|
/node_modules
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 Ribose
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
21
README.adoc
Normal file
21
README.adoc
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Aspirationally, it is a set of low-level helpers
|
||||||
|
to simplify working with Git LFS via Isomorphic Git.
|
||||||
|
|
||||||
|
As of 0.1.0, support is limited to:
|
||||||
|
|
||||||
|
- `readPointer({ dir, gitdir, content })`
|
||||||
|
+
|
||||||
|
where `dir`, `gitdir` behavior mimics that of Isomorphic Git,
|
||||||
|
and content is a `Buffer`.
|
||||||
|
|
||||||
|
|
||||||
|
- `downloadBlobFromPointer({ http, headers, url }, lfsPointer)`
|
||||||
|
+
|
||||||
|
where `http` is an `HttpClient` as supported by Isomorphic Git,
|
||||||
|
URL is repository URL
|
||||||
|
and pointer is an object returned by `readPointer()`.
|
||||||
|
|
||||||
|
- `populateCache(workDir, ref?)`
|
||||||
|
+
|
||||||
|
where `workDir` is a path to working directory,
|
||||||
|
and `ref` should probably be left at the default `"HEAD"`.
|
32
package.json
Normal file
32
package.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "@riboseinc/isogit-lfs",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "LFS helpers for Isomorphic Git (Node only)",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": "git@github.com:riboseinc/isogit-lfs.git",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rm -r dist; mkdir dist; tsc --outDir dist; cp package.json README.adoc dist/"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"README.adoc",
|
||||||
|
"*.js",
|
||||||
|
"*.js.map",
|
||||||
|
"*.d.ts",
|
||||||
|
"*/**/*.js",
|
||||||
|
"*/**/*.js.map",
|
||||||
|
"*/**/*.d.ts"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Ribose Inc.",
|
||||||
|
"email": "open.source@ribose.com"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"isomorphic-git": "^1.7.8"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^16.11.7",
|
||||||
|
"isomorphic-git": "^1.7.8",
|
||||||
|
"typescript": "^4.4.2"
|
||||||
|
},
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
74
src/download.ts
Normal file
74
src/download.ts
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import git from 'isomorphic-git';
|
||||||
|
import { HttpClient } from 'isomorphic-git/http/node';
|
||||||
|
|
||||||
|
import { bodyToBuffer } from './util';
|
||||||
|
import { Pointer } from './pointers';
|
||||||
|
|
||||||
|
|
||||||
|
interface DownloadBlobRequset {
|
||||||
|
http: HttpClient;
|
||||||
|
headers?: Record<string, any>;
|
||||||
|
|
||||||
|
/** Repository URL. */
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LFSInfoResponse {
|
||||||
|
objects: {
|
||||||
|
actions: {
|
||||||
|
download: {
|
||||||
|
href: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function isValidLFSInfoResponseData(val: Record<string, any>): val is LFSInfoResponse {
|
||||||
|
return val.objects?.[0]?.actions?.download?.href?.trim !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Downloads a blob corresponding to given LFS pointer. */
|
||||||
|
export default async function downloadBlobFromPointer(
|
||||||
|
{ http: { request }, headers = {}, url }: DownloadBlobRequset,
|
||||||
|
{ info, objectPath }: Pointer
|
||||||
|
): Promise<Buffer> {
|
||||||
|
// Request LFS metadata
|
||||||
|
|
||||||
|
const lfsInfoRequestData = {
|
||||||
|
operation: 'download',
|
||||||
|
transfers: ['basic'],
|
||||||
|
objects: [info],
|
||||||
|
};
|
||||||
|
|
||||||
|
const { body: lfsInfoBody } = await request({
|
||||||
|
url: `${url}/info/lfs/objects/batch`,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'User-Agent': `git/isomorphic-git@${git.version()}`,
|
||||||
|
...headers,
|
||||||
|
'Accept': 'application/vnd.git-lfs+json',
|
||||||
|
'Content-Type': 'application/vnd.git-lfs+json',
|
||||||
|
},
|
||||||
|
body: [Buffer.from(JSON.stringify(lfsInfoRequestData))],
|
||||||
|
});
|
||||||
|
|
||||||
|
const lfsInfoResponseData = JSON.parse((await bodyToBuffer(lfsInfoBody)).toString());
|
||||||
|
|
||||||
|
if (isValidLFSInfoResponseData(lfsInfoResponseData)) {
|
||||||
|
|
||||||
|
// Request the actual blob
|
||||||
|
const lfsObjectDownloadURL = lfsInfoResponseData.objects[0].actions.download.href;
|
||||||
|
|
||||||
|
const { body: lfsObjectBody } = await request({
|
||||||
|
url: lfsObjectDownloadURL,
|
||||||
|
method: 'GET',
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
return await bodyToBuffer(lfsObjectBody);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Error("LFS response didn’t return an expected structure");
|
||||||
|
}
|
||||||
|
}
|
3
src/index.ts
Normal file
3
src/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export { default as downloadBlobFromPointer } from './download';
|
||||||
|
export { default as populateCache } from './populateCache';
|
||||||
|
export { readPointer } from './pointers';
|
52
src/pointers.ts
Normal file
52
src/pointers.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
|
||||||
|
interface PointerInfo {
|
||||||
|
oid: string;
|
||||||
|
size: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Pointer {
|
||||||
|
info: PointerInfo;
|
||||||
|
|
||||||
|
/** Path to blob in LFS cache. */
|
||||||
|
objectPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isValidPointerInfo(val: Record<string, any>): val is PointerInfo {
|
||||||
|
return val.oid.trim !== undefined && val.oid.size !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PointerRequest {
|
||||||
|
dir: string;
|
||||||
|
gitdir?: string;
|
||||||
|
content: Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function readPointer({ dir, gitdir = path.join(dir, '.git'), content }: PointerRequest): Pointer {
|
||||||
|
const info = content.toString().trim().split('\n').reduce((accum, line) => {
|
||||||
|
const [k, v] = line.split(' ', 2);
|
||||||
|
if (k === 'oid') {
|
||||||
|
accum[k] = v.split(':', 2)[1];
|
||||||
|
} else if (k === 'size') {
|
||||||
|
accum[k] = v;
|
||||||
|
}
|
||||||
|
return accum;
|
||||||
|
}, {} as Record<string, any>);
|
||||||
|
|
||||||
|
if (isValidPointerInfo(info)) {
|
||||||
|
const objectPath = path.join(
|
||||||
|
gitdir,
|
||||||
|
'lfs',
|
||||||
|
'objects',
|
||||||
|
info.oid.substr(0, 2),
|
||||||
|
info.oid.substr(2, 2),
|
||||||
|
info.oid);
|
||||||
|
|
||||||
|
return { info, objectPath };
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Error("LFS pointer is incomplete or cannot be read");
|
||||||
|
}
|
||||||
|
}
|
79
src/populateCache.ts
Normal file
79
src/populateCache.ts
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
|
||||||
|
import git from 'isomorphic-git';
|
||||||
|
import http from 'isomorphic-git/http/node';
|
||||||
|
|
||||||
|
import { isWriteable, pointsToLFS } from './util';
|
||||||
|
import downloadBlobFromPointer from './download';
|
||||||
|
import { readPointer } from "./pointers";
|
||||||
|
|
||||||
|
|
||||||
|
const SYMLINK_MODE = 40960;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates LFS cache for each repository object that is an LFS pointer.
|
||||||
|
*
|
||||||
|
* Does not touch working directory.
|
||||||
|
*
|
||||||
|
* NOTE: If LFS cache path, as extracted from the pointer,
|
||||||
|
* is not writeable at the time of download start,
|
||||||
|
* the object will be silently skipped;
|
||||||
|
* if LFS cache path is not writeable at the time download completes,
|
||||||
|
* an error will be thrown.
|
||||||
|
*/
|
||||||
|
export default async function populateCache(workDir: string, ref: string = 'HEAD') {
|
||||||
|
const remoteURL = await git.getConfig({
|
||||||
|
fs,
|
||||||
|
dir: workDir,
|
||||||
|
path: 'remote.origin.url',
|
||||||
|
});
|
||||||
|
if (remoteURL) {
|
||||||
|
await git.walk({
|
||||||
|
fs,
|
||||||
|
dir: workDir,
|
||||||
|
trees: [git.TREE({ ref })],
|
||||||
|
map: async (filepath, entries) => {
|
||||||
|
if (entries === null || entries[0] === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [entry] = entries;
|
||||||
|
const entryType = await entry.type();
|
||||||
|
|
||||||
|
if (entryType === 'tree') {
|
||||||
|
// Walk children
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (entryType === 'blob' && (await entry.mode()) !== SYMLINK_MODE) {
|
||||||
|
const content = await entry.content();
|
||||||
|
|
||||||
|
if (content) {
|
||||||
|
const buff = Buffer.from(content.buffer);
|
||||||
|
|
||||||
|
if (pointsToLFS(buff)) {
|
||||||
|
const pointer = readPointer({ dir: workDir, content: buff });
|
||||||
|
|
||||||
|
// Don’t even start the download if LFS cache path is not accessible.
|
||||||
|
if (await isWriteable(pointer.objectPath) === false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const content = await downloadBlobFromPointer(
|
||||||
|
{ http, url: remoteURL },
|
||||||
|
pointer);
|
||||||
|
|
||||||
|
// Write LFS cache for this object, if cache path is still accessible.
|
||||||
|
if (await isWriteable(pointer.objectPath) === false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await fs.mkdir(path.dirname(pointer.objectPath), { recursive: true });
|
||||||
|
await fs.writeFile(pointer.objectPath, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
47
src/util.ts
Normal file
47
src/util.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import { constants as fsConstants } from 'fs';
|
||||||
|
|
||||||
|
export const LFS_POINTER_PREAMBLE = 'version https://git-lfs.github.com/spec/v1\n';
|
||||||
|
|
||||||
|
|
||||||
|
export function pointsToLFS(content: Buffer): boolean {
|
||||||
|
return (
|
||||||
|
content[0] === 118 // 'v'
|
||||||
|
&& content.subarray(0, 100).indexOf(LFS_POINTER_PREAMBLE) === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if given path is available for writing,
|
||||||
|
* regardless of whether or not it is occupied.
|
||||||
|
*/
|
||||||
|
export async function isWriteable(filepath: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await fs.access(filepath, fsConstants.W_OK);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
if ((e as { code: string }).code !== 'ENOENT') {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function bodyToBuffer(body: Uint8Array[]): Promise<Buffer> {
|
||||||
|
const buffers = [];
|
||||||
|
let offset = 0;
|
||||||
|
let size = 0;
|
||||||
|
for await (const chunk of body) {
|
||||||
|
buffers.push(chunk);
|
||||||
|
size += chunk.byteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = new Uint8Array(size);
|
||||||
|
for (const buffer of buffers) {
|
||||||
|
result.set(buffer, offset);
|
||||||
|
offset += buffer.byteLength;
|
||||||
|
}
|
||||||
|
return Buffer.from(result.buffer);
|
||||||
|
}
|
22
tsconfig.json
Normal file
22
tsconfig.json
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2017",
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
|
||||||
|
"sourceMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
|
||||||
|
"newLine": "lf",
|
||||||
|
|
||||||
|
"declaration": true
|
||||||
|
}
|
||||||
|
}
|
167
yarn.lock
Normal file
167
yarn.lock
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@types/node@^16.11.7":
|
||||||
|
version "16.11.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.10.tgz#2e3ad0a680d96367103d3e670d41c2fed3da61ae"
|
||||||
|
integrity sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==
|
||||||
|
|
||||||
|
async-lock@^1.1.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.3.0.tgz#0fba111bea8b9693020857eba4f9adca173df3e5"
|
||||||
|
integrity sha512-8A7SkiisnEgME2zEedtDYPxUPzdv3x//E7n5IFktPAtMYSEAV7eNJF0rMwrVyUFj6d/8rgajLantbjcNRQYXIg==
|
||||||
|
|
||||||
|
clean-git-ref@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/clean-git-ref/-/clean-git-ref-2.0.1.tgz#dcc0ca093b90e527e67adb5a5e55b1af6816dcd9"
|
||||||
|
integrity sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==
|
||||||
|
|
||||||
|
crc-32@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
|
||||||
|
integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==
|
||||||
|
dependencies:
|
||||||
|
exit-on-epipe "~1.0.1"
|
||||||
|
printj "~1.1.0"
|
||||||
|
|
||||||
|
decompress-response@^4.2.0:
|
||||||
|
version "4.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
|
||||||
|
integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
|
||||||
|
dependencies:
|
||||||
|
mimic-response "^2.0.0"
|
||||||
|
|
||||||
|
diff3@0.0.3:
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/diff3/-/diff3-0.0.3.tgz#d4e5c3a4cdf4e5fe1211ab42e693fcb4321580fc"
|
||||||
|
integrity sha1-1OXDpM305f4SEatC5pP8tDIVgPw=
|
||||||
|
|
||||||
|
exit-on-epipe@~1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
|
||||||
|
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
|
||||||
|
|
||||||
|
ignore@^5.1.4:
|
||||||
|
version "5.1.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb"
|
||||||
|
integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==
|
||||||
|
|
||||||
|
inherits@^2.0.1, inherits@^2.0.3:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
|
||||||
|
isomorphic-git@^1.7.8:
|
||||||
|
version "1.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/isomorphic-git/-/isomorphic-git-1.10.1.tgz#2f3a3d2d41baf6a88e046a21e0527bc13a21d663"
|
||||||
|
integrity sha512-abbPpKkykIVDJ92rtYoD4AOuT5/7PABHR2fDBrsm7H0r2ZT+MGpPL/FynrEJM6nTcFSieaIDxnHNGhfHO/v+bA==
|
||||||
|
dependencies:
|
||||||
|
async-lock "^1.1.0"
|
||||||
|
clean-git-ref "^2.0.1"
|
||||||
|
crc-32 "^1.2.0"
|
||||||
|
diff3 "0.0.3"
|
||||||
|
ignore "^5.1.4"
|
||||||
|
minimisted "^2.0.0"
|
||||||
|
pako "^1.0.10"
|
||||||
|
pify "^4.0.1"
|
||||||
|
readable-stream "^3.4.0"
|
||||||
|
sha.js "^2.4.9"
|
||||||
|
simple-get "^3.0.2"
|
||||||
|
|
||||||
|
mimic-response@^2.0.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
|
||||||
|
integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
|
||||||
|
|
||||||
|
minimist@^1.2.5:
|
||||||
|
version "1.2.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||||
|
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||||
|
|
||||||
|
minimisted@^2.0.0:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimisted/-/minimisted-2.0.1.tgz#d059fb905beecf0774bc3b308468699709805cb1"
|
||||||
|
integrity sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==
|
||||||
|
dependencies:
|
||||||
|
minimist "^1.2.5"
|
||||||
|
|
||||||
|
once@^1.3.1:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
|
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||||
|
dependencies:
|
||||||
|
wrappy "1"
|
||||||
|
|
||||||
|
pako@^1.0.10:
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
||||||
|
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
|
||||||
|
|
||||||
|
pify@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
||||||
|
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
||||||
|
|
||||||
|
printj@~1.1.0:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
|
||||||
|
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
|
||||||
|
|
||||||
|
readable-stream@^3.4.0:
|
||||||
|
version "3.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||||
|
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||||
|
dependencies:
|
||||||
|
inherits "^2.0.3"
|
||||||
|
string_decoder "^1.1.1"
|
||||||
|
util-deprecate "^1.0.1"
|
||||||
|
|
||||||
|
safe-buffer@^5.0.1, safe-buffer@~5.2.0:
|
||||||
|
version "5.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|
||||||
|
sha.js@^2.4.9:
|
||||||
|
version "2.4.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
|
||||||
|
integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
|
||||||
|
dependencies:
|
||||||
|
inherits "^2.0.1"
|
||||||
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
|
simple-concat@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
|
||||||
|
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
|
||||||
|
|
||||||
|
simple-get@^3.0.2:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3"
|
||||||
|
integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==
|
||||||
|
dependencies:
|
||||||
|
decompress-response "^4.2.0"
|
||||||
|
once "^1.3.1"
|
||||||
|
simple-concat "^1.0.0"
|
||||||
|
|
||||||
|
string_decoder@^1.1.1:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||||
|
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
|
typescript@^4.4.2:
|
||||||
|
version "4.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.2.tgz#8ac1fba9f52256fdb06fb89e4122fa6a346c2998"
|
||||||
|
integrity sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==
|
||||||
|
|
||||||
|
util-deprecate@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||||
|
|
||||||
|
wrappy@1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
|
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
Loading…
Reference in a new issue