Generate updater JSON file (#287)

Co-authored-by: wangxianqiao <wangxianqiao@cloudfine.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
mantou
2022-11-01 06:25:56 +08:00
committed by GitHub
parent a99d0bae58
commit ce22b932cb
9 changed files with 678 additions and 63 deletions

450
packages/action/dist/918.index.js vendored Normal file
View File

@@ -0,0 +1,450 @@
export const id = 918;
export const ids = [918];
export const modules = {
/***/ 918:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "toFormData": () => (/* binding */ toFormData)
/* harmony export */ });
/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7445);
/* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9457);
let s = 0;
const S = {
START_BOUNDARY: s++,
HEADER_FIELD_START: s++,
HEADER_FIELD: s++,
HEADER_VALUE_START: s++,
HEADER_VALUE: s++,
HEADER_VALUE_ALMOST_DONE: s++,
HEADERS_ALMOST_DONE: s++,
PART_DATA_START: s++,
PART_DATA: s++,
END: s++
};
let f = 1;
const F = {
PART_BOUNDARY: f,
LAST_BOUNDARY: f *= 2
};
const LF = 10;
const CR = 13;
const SPACE = 32;
const HYPHEN = 45;
const COLON = 58;
const A = 97;
const Z = 122;
const lower = c => c | 0x20;
const noop = () => {};
class MultipartParser {
/**
* @param {string} boundary
*/
constructor(boundary) {
this.index = 0;
this.flags = 0;
this.onHeaderEnd = noop;
this.onHeaderField = noop;
this.onHeadersEnd = noop;
this.onHeaderValue = noop;
this.onPartBegin = noop;
this.onPartData = noop;
this.onPartEnd = noop;
this.boundaryChars = {};
boundary = '\r\n--' + boundary;
const ui8a = new Uint8Array(boundary.length);
for (let i = 0; i < boundary.length; i++) {
ui8a[i] = boundary.charCodeAt(i);
this.boundaryChars[ui8a[i]] = true;
}
this.boundary = ui8a;
this.lookbehind = new Uint8Array(this.boundary.length + 8);
this.state = S.START_BOUNDARY;
}
/**
* @param {Uint8Array} data
*/
write(data) {
let i = 0;
const length_ = data.length;
let previousIndex = this.index;
let {lookbehind, boundary, boundaryChars, index, state, flags} = this;
const boundaryLength = this.boundary.length;
const boundaryEnd = boundaryLength - 1;
const bufferLength = data.length;
let c;
let cl;
const mark = name => {
this[name + 'Mark'] = i;
};
const clear = name => {
delete this[name + 'Mark'];
};
const callback = (callbackSymbol, start, end, ui8a) => {
if (start === undefined || start !== end) {
this[callbackSymbol](ui8a && ui8a.subarray(start, end));
}
};
const dataCallback = (name, clear) => {
const markSymbol = name + 'Mark';
if (!(markSymbol in this)) {
return;
}
if (clear) {
callback(name, this[markSymbol], i, data);
delete this[markSymbol];
} else {
callback(name, this[markSymbol], data.length, data);
this[markSymbol] = 0;
}
};
for (i = 0; i < length_; i++) {
c = data[i];
switch (state) {
case S.START_BOUNDARY:
if (index === boundary.length - 2) {
if (c === HYPHEN) {
flags |= F.LAST_BOUNDARY;
} else if (c !== CR) {
return;
}
index++;
break;
} else if (index - 1 === boundary.length - 2) {
if (flags & F.LAST_BOUNDARY && c === HYPHEN) {
state = S.END;
flags = 0;
} else if (!(flags & F.LAST_BOUNDARY) && c === LF) {
index = 0;
callback('onPartBegin');
state = S.HEADER_FIELD_START;
} else {
return;
}
break;
}
if (c !== boundary[index + 2]) {
index = -2;
}
if (c === boundary[index + 2]) {
index++;
}
break;
case S.HEADER_FIELD_START:
state = S.HEADER_FIELD;
mark('onHeaderField');
index = 0;
// falls through
case S.HEADER_FIELD:
if (c === CR) {
clear('onHeaderField');
state = S.HEADERS_ALMOST_DONE;
break;
}
index++;
if (c === HYPHEN) {
break;
}
if (c === COLON) {
if (index === 1) {
// empty header field
return;
}
dataCallback('onHeaderField', true);
state = S.HEADER_VALUE_START;
break;
}
cl = lower(c);
if (cl < A || cl > Z) {
return;
}
break;
case S.HEADER_VALUE_START:
if (c === SPACE) {
break;
}
mark('onHeaderValue');
state = S.HEADER_VALUE;
// falls through
case S.HEADER_VALUE:
if (c === CR) {
dataCallback('onHeaderValue', true);
callback('onHeaderEnd');
state = S.HEADER_VALUE_ALMOST_DONE;
}
break;
case S.HEADER_VALUE_ALMOST_DONE:
if (c !== LF) {
return;
}
state = S.HEADER_FIELD_START;
break;
case S.HEADERS_ALMOST_DONE:
if (c !== LF) {
return;
}
callback('onHeadersEnd');
state = S.PART_DATA_START;
break;
case S.PART_DATA_START:
state = S.PART_DATA;
mark('onPartData');
// falls through
case S.PART_DATA:
previousIndex = index;
if (index === 0) {
// boyer-moore derrived algorithm to safely skip non-boundary data
i += boundaryEnd;
while (i < bufferLength && !(data[i] in boundaryChars)) {
i += boundaryLength;
}
i -= boundaryEnd;
c = data[i];
}
if (index < boundary.length) {
if (boundary[index] === c) {
if (index === 0) {
dataCallback('onPartData', true);
}
index++;
} else {
index = 0;
}
} else if (index === boundary.length) {
index++;
if (c === CR) {
// CR = part boundary
flags |= F.PART_BOUNDARY;
} else if (c === HYPHEN) {
// HYPHEN = end boundary
flags |= F.LAST_BOUNDARY;
} else {
index = 0;
}
} else if (index - 1 === boundary.length) {
if (flags & F.PART_BOUNDARY) {
index = 0;
if (c === LF) {
// unset the PART_BOUNDARY flag
flags &= ~F.PART_BOUNDARY;
callback('onPartEnd');
callback('onPartBegin');
state = S.HEADER_FIELD_START;
break;
}
} else if (flags & F.LAST_BOUNDARY) {
if (c === HYPHEN) {
callback('onPartEnd');
state = S.END;
flags = 0;
} else {
index = 0;
}
} else {
index = 0;
}
}
if (index > 0) {
// when matching a possible boundary, keep a lookbehind reference
// in case it turns out to be a false lead
lookbehind[index - 1] = c;
} else if (previousIndex > 0) {
// if our boundary turned out to be rubbish, the captured lookbehind
// belongs to partData
const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength);
callback('onPartData', 0, previousIndex, _lookbehind);
previousIndex = 0;
mark('onPartData');
// reconsider the current character even so it interrupted the sequence
// it could be the beginning of a new sequence
i--;
}
break;
case S.END:
break;
default:
throw new Error(`Unexpected state entered: ${state}`);
}
}
dataCallback('onHeaderField');
dataCallback('onHeaderValue');
dataCallback('onPartData');
// Update properties for the next call
this.index = index;
this.state = state;
this.flags = flags;
}
end() {
if ((this.state === S.HEADER_FIELD_START && this.index === 0) ||
(this.state === S.PART_DATA && this.index === this.boundary.length)) {
this.onPartEnd();
} else if (this.state !== S.END) {
throw new Error('MultipartParser.end(): stream ended unexpectedly');
}
}
}
function _fileName(headerValue) {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);
if (!m) {
return;
}
const match = m[2] || m[3] || '';
let filename = match.slice(match.lastIndexOf('\\') + 1);
filename = filename.replace(/%22/g, '"');
filename = filename.replace(/&#(\d{4});/g, (m, code) => {
return String.fromCharCode(code);
});
return filename;
}
async function toFormData(Body, ct) {
if (!/multipart/i.test(ct)) {
throw new TypeError('Failed to fetch');
}
const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
if (!m) {
throw new TypeError('no or bad content-type header, no multipart boundary');
}
const parser = new MultipartParser(m[1] || m[2]);
let headerField;
let headerValue;
let entryValue;
let entryName;
let contentType;
let filename;
const entryChunks = [];
const formData = new formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__/* .FormData */ .Ct();
const onPartData = ui8a => {
entryValue += decoder.decode(ui8a, {stream: true});
};
const appendToFile = ui8a => {
entryChunks.push(ui8a);
};
const appendFileToFormData = () => {
const file = new fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__/* .File */ .$B(entryChunks, filename, {type: contentType});
formData.append(entryName, file);
};
const appendEntryToFormData = () => {
formData.append(entryName, entryValue);
};
const decoder = new TextDecoder('utf-8');
decoder.decode();
parser.onPartBegin = function () {
parser.onPartData = onPartData;
parser.onPartEnd = appendEntryToFormData;
headerField = '';
headerValue = '';
entryValue = '';
entryName = '';
contentType = '';
filename = null;
entryChunks.length = 0;
};
parser.onHeaderField = function (ui8a) {
headerField += decoder.decode(ui8a, {stream: true});
};
parser.onHeaderValue = function (ui8a) {
headerValue += decoder.decode(ui8a, {stream: true});
};
parser.onHeaderEnd = function () {
headerValue += decoder.decode();
headerField = headerField.toLowerCase();
if (headerField === 'content-disposition') {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);
if (m) {
entryName = m[2] || m[3] || '';
}
filename = _fileName(headerValue);
if (filename) {
parser.onPartData = appendToFile;
parser.onPartEnd = appendFileToFormData;
}
} else if (headerField === 'content-type') {
contentType = headerValue;
}
headerValue = '';
headerField = '';
};
for await (const chunk of Body) {
parser.write(chunk);
}
parser.end();
return formData;
}
/***/ })
};

File diff suppressed because one or more lines are too long

View File

@@ -21,6 +21,7 @@
"@actions/core": "1.10.0",
"@actions/github": "5.1.1",
"@tauri-apps/action-core": "0.3.1",
"node-fetch": "3.2.6",
"string-argv": "0.3.1",
"tslib": "2.4.0"
},

View File

@@ -3,6 +3,7 @@ import * as core from '@actions/core'
import { join, resolve, dirname, basename } from 'path'
import { existsSync } from 'fs'
import uploadReleaseAssets from './upload-release-assets'
import uploadVersionJSON from './upload-version-json'
import createRelease from './create-release'
import { getPackageJson, buildProject, getInfo, execCommand } from '@tauri-apps/action-core'
import type { BuildOptions } from '@tauri-apps/action-core'
@@ -57,7 +58,7 @@ async function run(): Promise<void> {
throw new Error('No artifacts were found.')
}
console.log(`Artifacts: ${artifacts}.`)
console.log(`Artifacts: ${artifacts.map(a => a.path)}.`)
let releaseId: number
if (tagName) {
@@ -65,7 +66,7 @@ async function run(): Promise<void> {
const templates = [
{
key: '__VERSION__',
value: info.version
value: info.version || packageJson.version
}
]
@@ -98,10 +99,10 @@ async function run(): Promise<void> {
for (const artifact of artifacts) {
// updater provide a .tar.gz, this will prevent duplicate and overwriting of
// signed archive
if (artifact.endsWith('.app') && !existsSync(`${artifact}.tar.gz`)) {
await execCommand('tar', ['czf', `${artifact}.tar.gz`, '-C', dirname(artifact), basename(artifact)])
artifacts[i] += '.tar.gz'
} else if (artifact.endsWith('.app')) {
if (artifact.path.endsWith('.app') && !existsSync(`${artifact.path}.tar.gz`)) {
await execCommand('tar', ['czf', `${artifact}.tar.gz`, '-C', dirname(artifact.path), basename(artifact.path)])
artifact[i].path += '.tar.gz'
} else if (artifact.path.endsWith('.app')) {
// we can't upload a directory
artifacts.splice(i, 1);
}
@@ -109,6 +110,7 @@ async function run(): Promise<void> {
}
}
await uploadReleaseAssets(releaseId, artifacts)
await uploadVersionJSON({ version: info.version, notes: body, releaseId, artifacts });
}
} catch (error) {
core.setFailed(error.message)

View File

@@ -1,27 +1,17 @@
import { getOctokit, context } from '@actions/github'
import { Artifact } from '@tauri-apps/action-core'
import fs from 'fs'
import path from 'path'
import { getAssetName } from './utils'
export default async function uploadAssets(
releaseId: number,
assets: string[]
assets: Artifact[]
) {
if (process.env.GITHUB_TOKEN === undefined) {
throw new Error('GITHUB_TOKEN is required')
}
const extensions = [
'.app.tar.gz.sig',
'.app.tar.gz',
'.dmg',
'.AppImage.tar.gz.sig',
'.AppImage.tar.gz',
'.AppImage',
'.deb',
'.msi.zip.sig',
'.msi.zip',
'.msi'
]
const github = getOctokit(process.env.GITHUB_TOKEN)
@@ -36,29 +26,13 @@ export default async function uploadAssets(
// Determine content-length for header to upload asset
const contentLength = (filePath: string) => fs.statSync(filePath).size
for (const assetPath of assets) {
for (const asset of assets) {
const headers = {
'content-type': 'application/zip',
'content-length': contentLength(assetPath)
'content-length': contentLength(asset.path)
}
const basename = path.basename(assetPath)
const exts = extensions.filter((s) => basename.includes(s))
const ext = exts[0] || path.extname(assetPath)
const filename = basename.replace(ext, '')
let arch = ''
if (ext === '.app.tar.gz.sig' || ext === '.app.tar.gz') {
arch = assetPath.includes('universal-apple-darwin')
? '_universal'
: assetPath.includes('aarch64-apple-darwin')
? '_aarch64'
: '_x64'
}
const assetName = assetPath.includes(`${path.sep}debug${path.sep}`)
? `${filename}-debug${arch}${ext}`
: `${filename}${arch}${ext}`
const assetName = getAssetName(asset.path)
const existingAsset = existingAssets.find((a) => a.name === assetName)
if (existingAsset) {

View File

@@ -0,0 +1,94 @@
import { getOctokit, context } from "@actions/github";
import { resolve } from "path";
import { readFileSync, writeFileSync } from "fs";
import uploadAssets from "./upload-release-assets";
import fetch from "node-fetch";
import { arch, platform } from "os";
import { getAssetName } from "./utils";
import { Artifact } from "@tauri-apps/action-core";
export default async function uploadVersionJSON({
version,
notes,
releaseId,
artifacts,
}: {
version: string;
notes: string;
releaseId: number;
artifacts: Artifact[];
}) {
if (process.env.GITHUB_TOKEN === undefined) {
throw new Error("GITHUB_TOKEN is required");
}
const github = getOctokit(process.env.GITHUB_TOKEN);
const versionFilename = "latest.json";
const versionFile = resolve(process.cwd(), versionFilename);
const versionContent = {
version,
notes,
pub_date: new Date().toISOString(),
platforms: {},
};
const assets = await github.rest.repos.listReleaseAssets({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: releaseId,
});
const asset = assets.data.find((e) => e.name === versionFilename);
if (asset) {
versionContent.platforms = (
(await (await fetch(asset.browser_download_url)).json()) as any
).platforms;
// https://docs.github.com/en/rest/releases/assets#update-a-release-asset
await github.rest.repos.deleteReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: releaseId,
asset_id: asset.id,
});
}
const sigFile = artifacts.find((s) => s.path.endsWith(".sig"));
const assetNames = new Set(artifacts.map((p) => getAssetName(p.path)));
const downloadUrl = assets.data
.filter((e) => assetNames.has(e.name))
.find(
(s) => s.name.endsWith(".tar.gz") || s.name.endsWith(".zip")
)?.browser_download_url;
let os = platform() as string;
if (os === "win32") os = "windows";
if (downloadUrl && sigFile) {
let arch = sigFile.arch;
arch === 'amd64' || arch === 'x86_64' || arch === 'x64'
? 'x86_64'
: arch === 'x86' || arch === 'i386'
? 'i686'
: arch === 'arm'
? 'armv7'
: arch === 'arm64'
? 'aarch64'
: arch
// https://github.com/tauri-apps/tauri/blob/fd125f76d768099dc3d4b2d4114349ffc31ffac9/core/tauri/src/updater/core.rs#L856
versionContent.platforms[`${os}-${arch}`] = {
signature: readFileSync(sigFile.path).toString(),
url: downloadUrl,
};
} else {
const missing = downloadUrl ? 'Signature' : sigFile ? 'Asset' : 'Asset and signature'
console.warn(`${missing} not found for the updater JSON.`)
}
writeFileSync(versionFile, JSON.stringify(versionContent, null, 2));
console.log(`Uploading ${versionFile}...`);
await uploadAssets(releaseId, [{ path: versionFile, arch: '' }]);
}

View File

@@ -0,0 +1,34 @@
import path from 'path';
const extensions = [
'.app.tar.gz.sig',
'.app.tar.gz',
'.dmg',
'.AppImage.tar.gz.sig',
'.AppImage.tar.gz',
'.AppImage',
'.deb',
'.msi.zip.sig',
'.msi.zip',
'.msi'
]
export function getAssetName(assetPath: string) {
const basename = path.basename(assetPath)
const exts = extensions.filter((s) => basename.includes(s))
const ext = exts[0] || path.extname(assetPath)
const filename = basename.replace(ext, '')
let arch = ''
if (ext === '.app.tar.gz.sig' || ext === '.app.tar.gz') {
arch = assetPath.includes('universal-apple-darwin')
? '_universal'
: assetPath.includes('aarch64-apple-darwin')
? '_aarch64'
: '_x64'
}
return assetPath.includes(`${path.sep}debug${path.sep}`)
? `${filename}-debug${arch}${ext}`
: `${filename}${arch}${ext}`
}

View File

@@ -161,6 +161,11 @@ interface Info {
wixLanguage: string | string[] | { [language: string]: unknown }
}
export interface Artifact {
path: string
arch: string
}
function _getJson5Config(contents: string): TauriConfig | null {
try {
const config = JSON5.parse(contents) as TauriConfig
@@ -248,7 +253,7 @@ export async function buildProject(
root: string,
debug: boolean,
{ configPath, distPath, iconPath, tauriScript, args, bundleIdentifier }: BuildOptions
): Promise<string[]> {
): Promise<Artifact[]> {
return new Promise<Runner>((resolve, reject) => {
if (tauriScript) {
const [runnerCommand, ...runnerArgs] = tauriScript.split(' ')
@@ -422,7 +427,7 @@ export async function buildProject(
join(artifactsPath, `bundle/macos/${fileAppName}.app`),
join(artifactsPath, `bundle/macos/${fileAppName}.app.tar.gz`),
join(artifactsPath, `bundle/macos/${fileAppName}.app.tar.gz.sig`)
]
].map(path => ({ path, arch }))
} else if (platform() === 'win32') {
arch = arch.startsWith('i') ? 'x86' : 'x64'
@@ -457,7 +462,7 @@ export async function buildProject(
)
)
})
return artifacts
return artifacts.map(path => ({ path, arch }))
} else {
const debianArch =
arch === 'x64' || arch === 'x86_64'
@@ -477,28 +482,40 @@ export async function buildProject(
: arch
return [
join(
artifactsPath,
`bundle/deb/${fileAppName}_${app.version}_${debianArch}.deb`
),
join(
artifactsPath,
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage`
),
join(
artifactsPath,
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage.tar.gz`
),
join(
artifactsPath,
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage.tar.gz.sig`
)
{
path: join(
artifactsPath,
`bundle/deb/${fileAppName}_${app.version}_${debianArch}.deb`
),
arch: debianArch
},
{
path: join(
artifactsPath,
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage`
),
arch: appImageArch
},
{
path: join(
artifactsPath,
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage.tar.gz`
),
arch: appImageArch
},
{
path: join(
artifactsPath,
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage.tar.gz.sig`
),
arch: appImageArch
}
]
}
})
.then((paths) => {
console.log(`Expected artifacts paths:\n${paths.join('\n')}`)
return paths.filter((p) => existsSync(p))
.then((artifacts) => {
console.log(`Expected artifacts paths:\n${artifacts.map(a => a.path).join('\n')}`)
return artifacts.filter((p) => existsSync(p.path))
})
})
}

View File

@@ -639,6 +639,11 @@ ctrlc-windows@^2.0.0:
"@mapbox/node-pre-gyp" "^1.0.5"
neon-cli "^0.8.1"
data-uri-to-buffer@^4.0.0:
version "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==
debug@4:
version "4.3.2"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
@@ -790,6 +795,14 @@ fault@^1.0.0:
dependencies:
format "^0.2.0"
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
version "3.1.5"
resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.5.tgz#0077bf5f3fcdbd9d75a0b5362f77dbb743489863"
integrity sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==
dependencies:
node-domexception "^1.0.0"
web-streams-polyfill "^3.0.3"
figures@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
@@ -824,6 +837,13 @@ format@^0.2.0:
resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b"
integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=
formdata-polyfill@^4.0.10:
version "4.0.10"
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
dependencies:
fetch-blob "^3.1.2"
fs-minipass@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
@@ -1350,6 +1370,20 @@ neon-cli@^0.8.1:
validate-npm-package-license "^3.0.4"
validate-npm-package-name "^3.0.0"
node-domexception@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
node-fetch@3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.6.tgz#6d4627181697a9d9674aae0d61548e0d629b31b9"
integrity sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw==
dependencies:
data-uri-to-buffer "^4.0.0"
fetch-blob "^3.1.4"
formdata-polyfill "^4.0.10"
node-fetch@^2.6.1, node-fetch@^2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
@@ -1968,6 +2002,11 @@ vfile@^4.0.0:
unist-util-stringify-position "^2.0.0"
vfile-message "^2.0.0"
web-streams-polyfill@^3.0.3:
version "3.2.1"
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"