diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 708bcb2a..3fa8b7bb 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -8,3 +8,28 @@ export { FileSystem, FileInfo, WriteOptions } from './fs.js'; export function isRecord(value: unknown): value is Record { return typeof value === 'object' && value !== null; } + +/** + * Parse a s3/google storage URI into a bucket and key if the key exists + * + * @example + * ```typescript + * parseUri('s3://bucket-name') // { bucket: 'bucket-name', protocol: 's3' } + * parseUri('gs://bucket-name') // { bucket: 'bucket-name', protocol: 'gs' } + * ``` + */ +export function parseUri(uri: string): { protocol: string; bucket: string; key?: string } | null { + const parts = uri.split('/'); + + let protocol = parts[0]; + if (protocol == null || protocol === '') return null; + if (protocol.endsWith(':')) protocol = protocol.slice(0, protocol.length - 1); + + const bucket = parts[2]; + if (bucket == null || bucket.trim() === '') return null; + if (parts.length === 3) return { protocol, bucket }; + + const key = parts.slice(3).join('/'); + if (key == null || key.trim() === '') return { protocol, bucket }; + return { key, bucket, protocol }; +} diff --git a/packages/fs/package.json b/packages/fs/package.json index 9bc43d03..4d846362 100644 --- a/packages/fs/package.json +++ b/packages/fs/package.json @@ -18,10 +18,13 @@ "scripts": {}, "dependencies": { "@chunkd/core": "^8.2.0", - "@chunkd/source-aws": "^8.2.0", "@chunkd/source-file": "^8.2.0", "@chunkd/source-http": "^8.2.0" }, + "optionalDependencies": { + "@chunkd/source-aws": "*", + "@chunkd/source-google-cloud": "*" + }, "publishConfig": { "access": "public" }, diff --git a/packages/fs/src/index.node.ts b/packages/fs/src/index.node.ts index ead63ae4..624ebeb1 100644 --- a/packages/fs/src/index.node.ts +++ b/packages/fs/src/index.node.ts @@ -1,11 +1,7 @@ -import { FsAwsS3 } from '@chunkd/source-aws'; import { FsFile } from '@chunkd/source-file'; import { FsHttp } from '@chunkd/source-http'; -import S3 from 'aws-sdk/clients/s3.js'; import { fsa } from './fs.abstraction.js'; -export { FsAwsS3 } from '@chunkd/source-aws'; -export { FsHttp } from '@chunkd/source-http'; export { FileSystemAbstraction, fsa } from './fs.abstraction.js'; // Include local files by default in nodejs @@ -16,6 +12,3 @@ fsa.register('file://', fsFile); const fsHttp = new FsHttp(); fsa.register('http://', fsHttp); fsa.register('https://', fsHttp); - -const fsAwsS3 = new FsAwsS3(new S3()); -fsa.register('s3://', fsAwsS3); diff --git a/packages/fs/src/index.ts b/packages/fs/src/index.ts index 2b233ac2..e9786abf 100644 --- a/packages/fs/src/index.ts +++ b/packages/fs/src/index.ts @@ -1,3 +1,2 @@ export { FileSystemAbstraction, fsa } from './fs.abstraction.js'; -export { FsAwsS3 } from '@chunkd/source-aws'; export { FsHttp } from '@chunkd/source-http'; diff --git a/packages/fs/tsconfig.json b/packages/fs/tsconfig.json index 20d19fc8..f1020545 100644 --- a/packages/fs/tsconfig.json +++ b/packages/fs/tsconfig.json @@ -6,5 +6,10 @@ "lib": ["es2020"] }, "include": ["src/**/*"], - "references": [{ "path": "../core" }, { "path": "../source-aws" }, { "path": "../source-file" }] + "references": [ + { "path": "../core" }, + { "path": "../source-aws" }, + { "path": "../source-file" }, + { "path": "../source-google-cloud" } + ] } diff --git a/packages/source-aws/src/__test__/s3.fs.test.ts b/packages/source-aws/src/__test__/s3.fs.test.ts index c4d92436..46c1885f 100644 --- a/packages/source-aws/src/__test__/s3.fs.test.ts +++ b/packages/source-aws/src/__test__/s3.fs.test.ts @@ -2,6 +2,7 @@ import { FsAwsS3 } from '../s3.fs.js'; import o from 'ospec'; import S3 from 'aws-sdk/clients/s3.js'; import sinon from 'sinon'; +import { parseUri } from '@chunkd/core'; /** Utility to convert async generators into arrays */ async function toArray(generator: AsyncGenerator): Promise { @@ -17,21 +18,18 @@ o.spec('file.s3', () => { o.afterEach(() => sandbox.restore()); o.spec('parse', () => { - o('should only parse s3://', () => { - o(() => fs.parse('https://')).throws(Error); - o(() => fs.parse('https://google.com')).throws(Error); - o(() => fs.parse('/home/foo/bar')).throws(Error); - o(() => fs.parse('c:\\Program Files\\')).throws(Error); - }); - o('should parse s3 uris', () => { - o(fs.parse('s3://bucket/key')).deepEquals({ bucket: 'bucket', key: 'key' }); - o(fs.parse('s3://bucket/key/')).deepEquals({ bucket: 'bucket', key: 'key/' }); - o(fs.parse('s3://bucket/key/is/deep.txt')).deepEquals({ bucket: 'bucket', key: 'key/is/deep.txt' }); + o(parseUri('s3://bucket/key')).deepEquals({ bucket: 'bucket', key: 'key', protocol: 's3' }); + o(parseUri('s3://bucket/key/')).deepEquals({ bucket: 'bucket', key: 'key/', protocol: 's3' }); + o(parseUri('s3://bucket/key/is/deep.txt')).deepEquals({ + bucket: 'bucket', + key: 'key/is/deep.txt', + protocol: 's3', + }); }); o('should parse bucket only uris', () => { - o(fs.parse('s3://bucket')).deepEquals({ bucket: 'bucket' }); - o(fs.parse('s3://bucket/')).deepEquals({ bucket: 'bucket' }); + o(parseUri('s3://bucket')).deepEquals({ bucket: 'bucket', protocol: 's3' }); + o(parseUri('s3://bucket/')).deepEquals({ bucket: 'bucket', protocol: 's3' }); }); }); diff --git a/packages/source-aws/src/s3.fs.ts b/packages/source-aws/src/s3.fs.ts index 6d143b98..6a1411f8 100644 --- a/packages/source-aws/src/s3.fs.ts +++ b/packages/source-aws/src/s3.fs.ts @@ -1,4 +1,4 @@ -import { FileInfo, FileSystem, isRecord, WriteOptions } from '@chunkd/core'; +import { FileInfo, FileSystem, isRecord, parseUri, WriteOptions } from '@chunkd/core'; import type { Readable } from 'stream'; import { getCompositeError, SourceAwsS3 } from './s3.source.js'; import { ListRes, S3Like, toPromise } from './type.js'; @@ -34,30 +34,14 @@ export class FsAwsS3 implements FileSystem { } /** Parse a s3:// URI into the bucket and key components */ - static parse(uri: string): { bucket: string; key?: string } { - if (!uri.startsWith('s3://')) throw new Error(`Unable to parse s3 uri: "${uri}"`); - const parts = uri.split('/'); - const bucket = parts[2]; - if (bucket == null || bucket.trim() === '') { - throw new Error(`Unable to parse s3 uri: "${uri}"`); - } - - if (parts.length === 3) return { bucket }; - - const key = parts.slice(3).join('/'); - if (key == null || key.trim() === '') { - return { bucket }; - } - return { key, bucket }; - } - parse = FsAwsS3.parse; async *list(filePath: string): AsyncGenerator { for await (const obj of this.details(filePath)) yield obj.path; } async *details(filePath: string): AsyncGenerator { - const opts = this.parse(filePath); + const opts = parseUri(filePath); + if (opts == null) return; let ContinuationToken: string | undefined = undefined; const Bucket = opts.bucket; const Prefix = opts.key; @@ -91,8 +75,8 @@ export class FsAwsS3 implements FileSystem { } async read(filePath: string): Promise { - const opts = this.parse(filePath); - if (opts.key == null) throw new Error(`Failed to read: "${filePath}"`); + const opts = parseUri(filePath); + if (opts == null || opts.key == null) throw new Error(`Failed to read: "${filePath}"`); try { const res = await this.s3.getObject({ Bucket: opts.bucket, Key: opts.key }).promise(); @@ -103,8 +87,8 @@ export class FsAwsS3 implements FileSystem { } async write(filePath: string, buf: Buffer | Readable | string, ctx?: WriteOptions): Promise { - const opts = this.parse(filePath); - if (opts.key == null) throw new Error(`Failed to write: "${filePath}"`); + const opts = parseUri(filePath); + if (opts == null || opts.key == null) throw new Error(`Failed to write: "${filePath}"`); try { await toPromise( @@ -126,15 +110,15 @@ export class FsAwsS3 implements FileSystem { } stream(filePath: string): Readable { - const opts = this.parse(filePath); - if (opts.key == null) throw new Error(`S3: Unable to read "${filePath}"`); + const opts = parseUri(filePath); + if (opts == null || opts.key == null) throw new Error(`S3: Unable to read "${filePath}"`); return this.s3.getObject({ Bucket: opts.bucket, Key: opts.key }).createReadStream(); } async head(filePath: string): Promise { - const opts = this.parse(filePath); - if (opts.key == null) throw new Error(`Failed to exists: "${filePath}"`); + const opts = parseUri(filePath); + if (opts == null || opts.key == null) throw new Error(`Failed to exists: "${filePath}"`); try { const res = await toPromise(this.s3.headObject({ Bucket: opts.bucket, Key: opts.key })); return { size: res.ContentLength, path: filePath }; diff --git a/packages/source-aws/src/s3.source.ts b/packages/source-aws/src/s3.source.ts index 01ca06b2..4c5a3dc6 100644 --- a/packages/source-aws/src/s3.source.ts +++ b/packages/source-aws/src/s3.source.ts @@ -1,4 +1,4 @@ -import { ChunkSource, ChunkSourceBase, CompositeError, isRecord } from '@chunkd/core'; +import { ChunkSource, ChunkSourceBase, CompositeError, isRecord, parseUri } from '@chunkd/core'; import { S3Like, toPromise } from './type.js'; export function getCompositeError(e: unknown, msg: string): CompositeError { @@ -51,36 +51,21 @@ export class SourceAwsS3 extends ChunkSourceBase { }); return this._size; } - /** - * Parse a s3 URI and return the components - * - * @example - * `s3://foo/bar/baz.tiff` - * - * @param uri URI to parse - */ - static parse(uri: string): { key: string; bucket: string } | null { - if (!uri.startsWith('s3://')) return null; - - const parts = uri.split('/'); - const bucket = parts[2]; - if (bucket == null || bucket.trim() === '') return null; - const key = parts.slice(3).join('/'); - if (key == null || key.trim() === '') return null; - return { key, bucket }; - } /** * Parse a URI and create a source * * @example - * `s3://foo/bar/baz.tiff` + * ``` + * fromUri('s3://foo/bar/baz.tiff') + * ``` * * @param uri URI to parse */ static fromUri(uri: string, remote: S3Like): SourceAwsS3 | null { - const res = SourceAwsS3.parse(uri); - if (res == null) return null; + const res = parseUri(uri); + if (res == null || res.key == null) return null; + if (res.protocol !== 's3') return null; return new SourceAwsS3(res.bucket, res.key, remote); } diff --git a/packages/source-google-cloud/.npmignore b/packages/source-google-cloud/.npmignore new file mode 100644 index 00000000..cc1b7f16 --- /dev/null +++ b/packages/source-google-cloud/.npmignore @@ -0,0 +1 @@ +tsconfig.tsbuildinfo diff --git a/packages/source-google-cloud/CHANGELOG.md b/packages/source-google-cloud/CHANGELOG.md new file mode 100644 index 00000000..e69de29b diff --git a/packages/source-google-cloud/README.md b/packages/source-google-cloud/README.md new file mode 100644 index 00000000..94f572f1 --- /dev/null +++ b/packages/source-google-cloud/README.md @@ -0,0 +1,15 @@ +# @chunkd/source-gcp + +Load a chunks of a file from a AWS using `aws-sdk` + +## Usage + +```typescript +import { SourceAwsS3 } from '@chunkd/source-google-cloud'; +import { Storage } from '@google-cloud/storage'; + +const source = SourceGoogleStorage.fromUri('gs://bucket/path/to/cog.tif', new Storage()); + +// Load the first 1KB +await source.fetchBytes(0, 1024); +``` diff --git a/packages/source-google-cloud/package.json b/packages/source-google-cloud/package.json new file mode 100644 index 00000000..1f955be5 --- /dev/null +++ b/packages/source-google-cloud/package.json @@ -0,0 +1,31 @@ +{ + "name": "@chunkd/source-google-cloud", + "version": "8.2.0", + "type": "module", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/blacha/chunkd.git", + "directory": "packages/source-google-cloud" + }, + "author": "Blayne Chard", + "main": "./build/index.js", + "types": "./build/index.d.ts", + "license": "MIT", + "scripts": {}, + "dependencies": { + "@chunkd/core": "^8.2.0" + }, + "peerDependencies": { + "@google-cloud/storage": "*" + }, + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@google-cloud/storage": "^5.19.4", + "@types/node": "^16.11.7" + } +} diff --git a/packages/source-google-cloud/src/__test__/gcp.source.test.ts b/packages/source-google-cloud/src/__test__/gcp.source.test.ts new file mode 100644 index 00000000..983d1494 --- /dev/null +++ b/packages/source-google-cloud/src/__test__/gcp.source.test.ts @@ -0,0 +1,22 @@ +import o from 'ospec'; +import 'source-map-support/register.js'; +import { SourceGoogleStorage } from '../gcp.source.js'; +import { Storage } from '@google-cloud/storage'; + +o.spec('SourceGoogleStorage', () => { + const fakeRemote = new Storage(); + + o('should round trip uri', () => { + o(SourceGoogleStorage.fromUri('gs://foo/bar.tiff', fakeRemote)?.uri).equals('gs://foo/bar.tiff'); + o(SourceGoogleStorage.fromUri('gs://foo/bar/baz.tiff', fakeRemote)?.uri).equals('gs://foo/bar/baz.tiff'); + + // No Key + o(SourceGoogleStorage.fromUri('gs://foo', fakeRemote)).equals(null); + + // No Bucket + o(SourceGoogleStorage.fromUri('gs:///foo', fakeRemote)).equals(null); + + // Not s3 + o(SourceGoogleStorage.fromUri('http://example.com/foo.tiff', fakeRemote)).equals(null); + }); +}); diff --git a/packages/source-google-cloud/src/gcp.fs.ts b/packages/source-google-cloud/src/gcp.fs.ts new file mode 100644 index 00000000..f2f76f32 --- /dev/null +++ b/packages/source-google-cloud/src/gcp.fs.ts @@ -0,0 +1,119 @@ +import { FileInfo, FileSystem, isRecord, parseUri, WriteOptions } from '@chunkd/core'; +import { Storage } from '@google-cloud/storage'; +import { Readable } from 'stream'; +import { SourceGoogleStorage } from './gcp.source.js'; +import { getCompositeError, toReadable } from './stream.js'; + +function join(filePathA: string, filePathB: string): string { + return filePathA.replace(/\/$/, '') + '/' + filePathB.replace(/^\//, ''); +} + +export class FsGoogleStorage implements FileSystem { + static protocol = 'gs'; + protocol = FsGoogleStorage.protocol; + /** Max list requests to run before erroring */ + static MaxListCount = 100; + + /** Google storage client to use */ + storage: Storage; + + constructor(storage: Storage = new Storage()) { + this.storage = storage; + } + + source(filePath: string): SourceGoogleStorage { + const ret = SourceGoogleStorage.fromUri(filePath, this.storage); + if (ret == null) throw new Error('GoogleStorage: Failed to create for path: ${filePath}'); + return ret; + } + + /** Is this file system a gs file system */ + static is(fs: FileSystem): fs is FsGoogleStorage { + return fs.protocol === FsGoogleStorage.protocol; + } + + /** Is this pat a gs path */ + static isPath(path?: string): boolean { + if (path == null) return false; + return path.startsWith('gs://'); + } + + /** Parse a gs:// URI into the bucket and key components */ + static parse = parseUri; + parse = parseUri; + + async *list(filePath: string): AsyncGenerator { + for await (const obj of this.details(filePath)) yield obj.path; + } + + async *details(filePath: string): AsyncGenerator { + const opts = this.parse(filePath); + if (opts == null) throw new Error(`GoogleStorage: Failed to list: "${filePath}"`); + + const bucket = this.storage.bucket(opts.bucket); + const [files, , metadata] = await bucket.getFiles({ prefix: opts.key, autoPaginate: false, delimiter: '/' }); + if (files != null && files.length > 0) { + for (const file of files) { + yield { path: join(`gs://${opts.bucket}`, file.name), size: Number(file.metadata.size) }; + } + } + + // Recurse down + if (metadata != null && metadata.prefixes != null) { + for (const prefix of metadata.prefixes) yield* this.details(join(`gs://${opts.bucket}`, prefix)); + } + } + + async read(filePath: string): Promise { + const opts = parseUri(filePath); + if (opts == null || opts.key == null) throw new Error(`GoogleStorage: Failed to read: "${filePath}"`); + + try { + const fileData = this.storage.bucket(opts.bucket).file(opts.key); + const res = await fileData.download(); + return res[0] as Buffer; + } catch (e) { + throw getCompositeError(e, `Failed to read: "${filePath}"`); + } + } + + async write(filePath: string, buf: Buffer | Readable | string, ctx?: WriteOptions): Promise { + const opts = parseUri(filePath); + if (opts == null || opts.key == null) throw new Error(`GoogleStorage: Failed to write: "${filePath}"`); + + const file = this.storage.bucket(opts.bucket).file(opts.key); + + try { + const writeStream = file.createWriteStream({ contentType: ctx?.contentType }); + const readable = toReadable(buf); + await new Promise((resolve, reject) => { + readable.pipe(writeStream).on('error', reject).on('finish', resolve); + }); + } catch (e) { + throw getCompositeError(e, `Failed to write: "${filePath}"`); + } + } + + exists(filePath: string): Promise { + return this.head(filePath).then((f) => f != null); + } + + stream(filePath: string): Readable { + const opts = parseUri(filePath); + if (opts == null || opts.key == null) throw new Error(`GoogleStorage: Unable to read "${filePath}"`); + return this.storage.bucket(opts.bucket).file(opts.key).createReadStream(); + } + + async head(filePath: string): Promise { + const opts = parseUri(filePath); + if (opts == null || opts.key == null) throw new Error(`GoogleStorage: Failed to head: "${filePath}"`); + try { + const file = this.storage.bucket(opts.bucket).file(opts.key); + const res = await file.getMetadata(); + return { size: res[0].size, path: filePath }; + } catch (e) { + if (isRecord(e) && e.code === 'NotFound') return null; + throw getCompositeError(e, `Failed to head: "${filePath}"`); + } + } +} diff --git a/packages/source-google-cloud/src/gcp.source.ts b/packages/source-google-cloud/src/gcp.source.ts new file mode 100644 index 00000000..87e9d869 --- /dev/null +++ b/packages/source-google-cloud/src/gcp.source.ts @@ -0,0 +1,80 @@ +import { ChunkSource, ChunkSourceBase, parseUri } from '@chunkd/core'; +import { Storage, File } from '@google-cloud/storage'; +import { getCompositeError, toBuffer } from './stream.js'; + +export class SourceGoogleStorage extends ChunkSourceBase { + static type = 'google-cloud:storage'; + type = SourceGoogleStorage.type; + protocol = 'gs'; + + static DefaultChunkSize = 64 * 1024; + static DefaultMaxChunkCount = 32; + + // HTTP gets are slow, get a larger amount + chunkSize: number = SourceGoogleStorage.DefaultChunkSize; + maxChunkCount = SourceGoogleStorage.DefaultMaxChunkCount; + + bucket: string; + key: string; + file: File; + + constructor(bucket: string, key: string, storage: Storage) { + super(); + this.bucket = bucket; + this.key = key; + + this.file = storage.bucket(this.bucket).file(this.key); + } + + get uri(): string { + return this.name; + } + + get name(): string { + return `gs://${this.bucket}/${this.key}`; + } + + static isSource(source: ChunkSource): source is SourceGoogleStorage { + return source.type === SourceGoogleStorage.type; + } + + _size: Promise | undefined; + get size(): Promise { + if (this._size) return this._size; + this._size = Promise.resolve().then(async () => { + const res = await this.file.getMetadata(); + return res[0].size ?? -1; + }); + return this._size; + } + + /** + * Parse a URI and create a source + * + * @example + * `gs://foo/bar/baz.tiff` + * + * @param uri URI to parse + */ + static fromUri(uri: string, remote: Storage): SourceGoogleStorage | null { + const res = parseUri(uri); + if (res == null || res.key == null) return null; + if (res.protocol !== 'gs') return null; + return new SourceGoogleStorage(res.bucket, res.key, remote); + } + + async fetchBytes(offset: number, length?: number): Promise { + const fetchRange = this.toRange(offset, length); + try { + const resp = await this.file.createReadStream({ + start: offset, + end: length == null ? undefined : offset + length, + }); + + const buffer = await toBuffer(resp); + return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); + } catch (err) { + throw getCompositeError(err, `Failed to fetch ${this.name} ${fetchRange}`); + } + } +} diff --git a/packages/source-google-cloud/src/index.ts b/packages/source-google-cloud/src/index.ts new file mode 100644 index 00000000..049b72fc --- /dev/null +++ b/packages/source-google-cloud/src/index.ts @@ -0,0 +1,2 @@ +export { SourceGoogleStorage } from './gcp.source.js'; +export { FsGoogleStorage } from './gcp.fs.js'; diff --git a/packages/source-google-cloud/src/stream.ts b/packages/source-google-cloud/src/stream.ts new file mode 100644 index 00000000..0a8ec983 --- /dev/null +++ b/packages/source-google-cloud/src/stream.ts @@ -0,0 +1,23 @@ +import { CompositeError, isRecord } from '@chunkd/core'; +import { Readable } from 'stream'; + +export function getCompositeError(e: unknown, msg: string): CompositeError { + if (!isRecord(e)) return new CompositeError(msg, 500, e); + if (typeof e.statusCode !== 'number') return new CompositeError(msg, 500, e); + return new CompositeError(msg, e.statusCode, e); +} + +export function toReadable(r: string | Buffer | Readable): Readable { + if (typeof r === 'string') r = Buffer.from(r); + return Readable.from(r); +} + +export async function toBuffer(stream: Readable): Promise { + return new Promise((resolve, reject) => { + const buf: Buffer[] = []; + + stream.on('data', (chunk) => buf.push(chunk)); + stream.on('end', () => resolve(Buffer.concat(buf))); + stream.on('error', (err) => reject(`error converting stream - ${err}`)); + }); +} diff --git a/packages/source-google-cloud/tsconfig.json b/packages/source-google-cloud/tsconfig.json new file mode 100644 index 00000000..967dabd7 --- /dev/null +++ b/packages/source-google-cloud/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./build", + "lib": ["es2018", "dom"] + }, + "include": ["src/**/*"], + "references": [{ "path": "../core" }] +} diff --git a/tsconfig.json b/tsconfig.json index 4df01445..9b0514e9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ { "path": "./packages/source-aws" }, { "path": "./packages/source-aws-v2" }, { "path": "./packages/source-aws-v3" }, + { "path": "./packages/source-google-cloud" }, { "path": "./packages/source-file" }, { "path": "./packages/fs" } ] diff --git a/yarn.lock b/yarn.lock index e832c7ea..00e230cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -836,6 +836,55 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@google-cloud/paginator@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.7.tgz#fb6f8e24ec841f99defaebf62c75c2e744dd419b" + integrity sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/projectify@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-2.1.1.tgz#ae6af4fee02d78d044ae434699a630f8df0084ef" + integrity sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ== + +"@google-cloud/promisify@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-2.0.4.tgz#9d8705ecb2baa41b6b2673f3a8e9b7b7e1abc52a" + integrity sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA== + +"@google-cloud/storage@^5.19.4": + version "5.19.4" + resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-5.19.4.tgz#d3377f03b575c66f61e2782ffd0f65419a30ebe0" + integrity sha512-Jz7ugcPHhsEmMVvIxM9uoBsdEbKIYwDkh3u07tifsIymEWs47F4/D6+/Tv/W7kLhznqjyOjVJ/0frtBeIC0lJA== + dependencies: + "@google-cloud/paginator" "^3.0.7" + "@google-cloud/projectify" "^2.0.0" + "@google-cloud/promisify" "^2.0.0" + abort-controller "^3.0.0" + arrify "^2.0.0" + async-retry "^1.3.3" + compressible "^2.0.12" + configstore "^5.0.0" + date-and-time "^2.0.0" + duplexify "^4.0.0" + ent "^2.2.0" + extend "^3.0.2" + gaxios "^4.0.0" + get-stream "^6.0.0" + google-auth-library "^7.14.1" + hash-stream-validation "^0.2.2" + mime "^3.0.0" + mime-types "^2.0.8" + p-limit "^3.0.1" + pumpify "^2.0.0" + retry-request "^4.2.2" + snakeize "^0.1.0" + stream-events "^1.0.4" + teeny-request "^7.1.3" + xdg-basedir "^4.0.0" + "@humanwhocodes/config-array@^0.9.2": version "0.9.2" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.2.tgz#68be55c737023009dfc5fe245d51181bb6476914" @@ -1780,6 +1829,11 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -1922,6 +1976,13 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + acorn-jsx@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" @@ -2060,7 +2121,7 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -arrify@^2.0.1: +arrify@^2.0.0, arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== @@ -2082,6 +2143,13 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2122,7 +2190,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.3.0: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2139,6 +2207,11 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.0.tgz#09c40d92e936c64777aa385c4e9b904f8147eaf0" integrity sha512-jH6rKQIfroBbhEXVmI7XmXe3ix5S/PgJqpzdDPnR8JGLHWNYLsYZ6tK5iWOF/Ra3oqEX0NobXGlzbiylIzVphQ== +bignumber.js@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673" + integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== + bowser@^2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" @@ -2159,6 +2232,11 @@ braces@^3.0.1: dependencies: fill-range "^7.0.1" +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2442,6 +2520,13 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" +compressible@^2.0.12: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2465,6 +2550,18 @@ config-chain@^1.1.12: ini "^1.3.4" proto-list "~1.2.1" +configstore@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -2711,6 +2808,11 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -2742,6 +2844,11 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== +date-and-time@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-2.3.1.tgz#006675ec4943a0a5f85810e3a3fd6aa96f6130c9" + integrity sha512-OaIRmSJXifwEN21rMVVDs0Kz8uhJ3wWPYd86atkRiqN54liaMQYEbbrgjZQea75YXOBWL4ZFb3rG/waenw1TEg== + dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" @@ -2886,7 +2993,7 @@ dot-prop@^3.0.0: dependencies: is-obj "^1.0.0" -dot-prop@^5.1.0: +dot-prop@^5.1.0, dot-prop@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== @@ -2910,6 +3017,16 @@ duplexer@^0.1.1: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +duplexify@^4.0.0, duplexify@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" + integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -2918,6 +3035,13 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -2930,6 +3054,18 @@ encoding@^0.1.12: dependencies: iconv-lite "^0.6.2" +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +ent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= + entities@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -3130,6 +3266,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + eventemitter3@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -3160,7 +3301,7 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -extend@~3.0.2: +extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -3216,6 +3357,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-text-encoding@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53" + integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== + fast-xml-parser@3.19.0: version "3.19.0" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz#cb637ec3f3999f51406dd8ff0e6fc4d83e520d01" @@ -3375,6 +3521,25 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaxios@^4.0.0: + version "4.3.3" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.3.3.tgz#d44bdefe52d34b6435cc41214fdb160b64abfc22" + integrity sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA== + dependencies: + abort-controller "^3.0.0" + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.6.7" + +gcp-metadata@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.3.1.tgz#fb205fe6a90fef2fd9c85e6ba06e5559ee1eefa9" + integrity sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A== + dependencies: + gaxios "^4.0.0" + json-bigint "^1.0.0" + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -3574,6 +3739,28 @@ globby@^11.0.4: merge2 "^1.3.0" slash "^3.0.0" +google-auth-library@^7.14.1: + version "7.14.1" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.14.1.tgz#e3483034162f24cc71b95c8a55a210008826213c" + integrity sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^4.0.0" + gcp-metadata "^4.2.0" + gtoken "^5.0.4" + jws "^4.0.0" + lru-cache "^6.0.0" + +google-p12-pem@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.1.4.tgz#123f7b40da204de4ed1fbf2fd5be12c047fc8b3b" + integrity sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg== + dependencies: + node-forge "^1.3.1" + got@^8.0.0: version "8.3.2" resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" @@ -3607,6 +3794,15 @@ graceful-fs@^4.2.3: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +gtoken@^5.0.4: + version "5.3.2" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.3.2.tgz#deb7dc876abe002178e0515e383382ea9446d58f" + integrity sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ== + dependencies: + gaxios "^4.0.0" + google-p12-pem "^3.1.3" + jws "^4.0.0" + handlebars@^4.7.6: version "4.7.6" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" @@ -3676,6 +3872,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hash-stream-validation@^0.2.2: + version "0.2.4" + resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz#ee68b41bf822f7f44db1142ec28ba9ee7ccb7512" + integrity sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ== + hosted-git-info@^2.1.4: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" @@ -3714,6 +3915,15 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -4126,6 +4336,13 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" @@ -4190,6 +4407,23 @@ just-extend@^4.0.2: resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + keyv@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" @@ -4515,6 +4749,18 @@ mime-db@1.45.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.0.8: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mime-types@^2.1.12, mime-types@~2.1.19: version "2.1.28" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" @@ -4522,6 +4768,11 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.45.0" +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -4735,6 +4986,18 @@ node-fetch@^2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== +node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-gyp@^5.0.2: version "5.1.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e" @@ -4954,7 +5217,7 @@ object.getownpropertydescriptors@^2.0.3: define-properties "^1.1.3" es-abstract "^1.18.0-next.1" -once@^1.3.0, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -5034,6 +5297,13 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -5362,6 +5632,23 @@ psl@^1.1.28: resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e" + integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw== + dependencies: + duplexify "^4.1.1" + inherits "^2.0.3" + pump "^3.0.0" + punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -5522,7 +5809,7 @@ read@1, read@~1.0.1: dependencies: mute-stream "~0.0.4" -"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.5.0: +"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.5.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== @@ -5676,6 +5963,19 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +retry-request@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.2.2.tgz#b7d82210b6d2651ed249ba3497f07ea602f1a903" + integrity sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg== + dependencies: + debug "^4.1.1" + extend "^3.0.2" + +retry@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -5836,6 +6136,11 @@ smart-buffer@^4.1.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== +snakeize@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d" + integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0= + socks-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz#7c0f364e7b1cf4a7a437e71253bed72e9004be60" @@ -5962,6 +6267,18 @@ stream-browserify@3.0.0: inherits "~2.0.4" readable-stream "^3.5.0" +stream-events@^1.0.4, stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" @@ -6120,6 +6437,11 @@ strong-log-transformer@^2.1.0: minimist "^1.2.0" through "^2.3.4" +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" + integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls= + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -6159,6 +6481,17 @@ tar@^6.0.2, tar@^6.1.0: mkdirp "^1.0.3" yallist "^4.0.0" +teeny-request@^7.1.3: + version "7.2.0" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.2.0.tgz#41347ece068f08d741e7b86df38a4498208b2633" + integrity sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw== + dependencies: + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.6.1" + stream-events "^1.0.5" + uuid "^8.0.0" + temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -6247,6 +6580,11 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -6389,6 +6727,13 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + universal-user-agent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" @@ -6453,7 +6798,7 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.2: +uuid@^8.0.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -6499,11 +6844,24 @@ web-streams-polyfill@^3.0.3: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webidl-conversions@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^8.4.0: version "8.5.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.5.0.tgz#7752b8464fc0903fec89aa9846fc9efe07351fd3" @@ -6610,6 +6968,11 @@ write-pkg@^4.0.0: type-fest "^0.4.1" write-json-file "^3.2.0" +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + xml2js@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" @@ -6678,3 +7041,8 @@ yargs@^16.2.0: string-width "^4.2.0" y18n "^5.0.5" yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==