Move away from smartling CLI

This commit is contained in:
Fedor Indutny 2024-03-21 11:31:31 -07:00 committed by GitHub
parent e90553b3b3
commit f55e6e3407
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
76 changed files with 121916 additions and 244506 deletions

1
.gitignore vendored
View file

@ -4,6 +4,7 @@ node_modules_bkp
coverage/*
build/curve25519_compiled.js
build/dns-fallback.json
build/compact-locales
stylesheets/*.css.map
/dist
.DS_Store

View file

@ -21,6 +21,7 @@ ts/util/lint/exceptions.json
storybook-static
build/locale-display-names.json
build/country-display-names.json
build/compact-locales/**/*.json
# Third-party files
node_modules/**

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -19,11 +19,11 @@
"postinstall": "yarn build:acknowledgments && patch-package && yarn electron:install-app-deps",
"postuninstall": "yarn build:acknowledgments",
"start": "electron .",
"generate": "npm-run-all build-protobuf build:esbuild build:dns-fallback build:icu-types sass get-expire-time copy-components",
"generate": "npm-run-all build-protobuf build:esbuild build:dns-fallback build:icu-types build:compact-locales sass get-expire-time copy-components",
"build-release": "yarn run build",
"sign-release": "node ts/updater/generateSignature.js",
"notarize": "echo 'No longer necessary'",
"get-strings": "ts-node ts/scripts/get-strings.ts && ts-node ts/scripts/gen-nsis-script.ts && ts-node ts/scripts/gen-locales-config.ts && run-p get-strings:locales get-strings:countries get-strings:emoji mark-unusued-strings-deleted",
"get-strings": "ts-node ts/scripts/get-strings.ts && ts-node ts/scripts/gen-nsis-script.ts && ts-node ts/scripts/gen-locales-config.ts && run-p get-strings:locales get-strings:countries get-strings:emoji mark-unusued-strings-deleted && run-p build:complact-locales",
"get-strings:locales": "ts-node ./ts/scripts/build-localized-display-names.ts locales ts/scripts/locale-data/locale-display-names.csv build/locale-display-names.json",
"get-strings:countries": "ts-node ./ts/scripts/build-localized-display-names.ts countries ts/scripts/locale-data/country-display-names.csv build/country-display-names.json",
"get-strings:emoji": "ts-node ./ts/scripts/get-emoji-locales.ts",
@ -80,6 +80,7 @@
"build:acknowledgments": "node scripts/generate-acknowledgments.js",
"build:dns-fallback": "node ts/scripts/generate-dns-fallback.js",
"build:icu-types": "node ts/scripts/generate-icu-types.js",
"build:compact-locales": "node ts/scripts/generate-compact-locales.js",
"build:dev": "run-s --print-label generate build:esbuild:prod",
"build:esbuild": "node scripts/esbuild.js",
"build:esbuild:prod": "node scripts/esbuild.js --prod",
@ -267,6 +268,7 @@
"@types/sinon": "10.0.2",
"@types/split2": "3.2.1",
"@types/terser-webpack-plugin": "5.0.3",
"@types/unzipper": "0.10.9",
"@types/uuid": "3.4.4",
"@types/websocket": "1.0.0",
"@types/write-file-atomic": "4.0.3",
@ -334,6 +336,7 @@
"ts-node": "8.3.0",
"typed-scss-modules": "4.1.1",
"typescript": "5.3.3",
"unzipper": "0.10.14",
"wait-on": "7.0.1",
"webpack": "5.88.2",
"webpack-cli": "4.9.2",
@ -482,7 +485,11 @@
"permissions_popup.html",
"debug_log.html",
"loading.html",
"_locales/**",
{
"from": "build/compact-locales",
"to": "_locales",
"filter": "**/messages.json"
},
"js/**",
"libtextsecure/**",
"ts/**/*.js",

View file

@ -0,0 +1,44 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { readdir, mkdir, readFile, writeFile } from 'node:fs/promises';
import { join, dirname } from 'node:path';
async function main(): Promise<void> {
const rootDir = join(__dirname, '..', '..');
const sourceDir = join(rootDir, '_locales');
const targetDir = join(rootDir, 'build', 'compact-locales');
const locales = await readdir(sourceDir);
await Promise.all(
locales.map(async locale => {
const sourcePath = join(sourceDir, locale, 'messages.json');
const targetPath = join(targetDir, locale, 'messages.json');
await mkdir(dirname(targetPath), { recursive: true });
const json = JSON.parse(await readFile(sourcePath, 'utf8'));
for (const value of Object.values(json)) {
const typedValue = value as { description?: string };
delete typedValue.description;
}
delete json.smartling;
const entries = [...Object.entries(json)];
// Sort entries alphabetically for better incremental updates.
entries.sort(([a], [b]) => {
return a < b ? -1 : 1;
});
const result = Object.fromEntries(entries);
await writeFile(targetPath, JSON.stringify(result));
})
);
}
main().catch(err => {
console.error(err);
process.exit(1);
});

View file

@ -1,13 +1,36 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { execSync } from 'child_process';
import fsExtra from 'fs-extra';
import path from 'path';
import { rm, mkdir, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { Readable } from 'node:stream';
import fastGlob from 'fast-glob';
import unzipper from 'unzipper';
import prettier from 'prettier';
import { authenticate, API_BASE, PROJECT_ID } from '../util/smartling';
const { SMARTLING_USER, SMARTLING_SECRET } = process.env;
const RENAMES = new Map([
// Smartling uses "zh-YU" for Cantonese (or Yue Chinese).
// This is wrong.
// The language tag for Yue Chinese is "yue"
// "zh-YU" actually implies "Chinese as spoken in Yugoslavia (canonicalized to Serbia)"
['zh-YU', 'yue'],
// For most of the Chinese-speaking world, where we don't have a region specific
// locale available (e.g. zh-HK), zh-TW is a suitable choice for "Traditional Chinese".
//
// However, Intl.LocaleMatcher won't match "zh-Hant-XX" to "zh-TW",
// we need to rename it to "zh-Hant" explicitly to make it work.
['zh-TW', 'zh-Hant'],
// "YR" is not a valid region subtag. Smartling made it up.
['sr-YR', 'sr'],
]);
async function main() {
if (!SMARTLING_USER) {
console.error('Need to set SMARTLING_USER environment variable!');
process.exit(1);
@ -17,56 +40,81 @@ if (!SMARTLING_SECRET) {
process.exit(1);
}
console.log('Authenticating with Smartling');
const headers = await authenticate({
userIdentifier: SMARTLING_USER,
userSecret: SMARTLING_SECRET,
});
const zipURL = new URL(
`./files-api/v2/projects/${PROJECT_ID}/locales/all/file/zip`,
API_BASE
);
zipURL.searchParams.set('fileUri', '_locales/en/messages.json');
zipURL.searchParams.set('retrievalType', 'published');
zipURL.searchParams.set('includeOriginalStrings', 'true');
const fileRes = await fetch(zipURL, {
headers,
});
if (!fileRes.ok) {
throw new Error('Failed to fetch the file');
}
if (!fileRes.body) {
throw new Error('Missing body');
}
console.log('Cleaning _locales directory...');
const dirEntries = fastGlob.sync(['_locales/*', '!_locales/en'], {
const dirEntries = await fastGlob(['_locales/*', '!_locales/en'], {
onlyDirectories: true,
absolute: true,
});
for (const dirEntry of dirEntries) {
fsExtra.rmdirSync(dirEntry, { recursive: true });
}
console.log('Fetching latest strings!');
console.log();
execSync(
'smartling-cli' +
` --user "${SMARTLING_USER}"` +
` --secret "${SMARTLING_SECRET}"` +
' --config .smartling.yml' +
' --verbose' +
' --format "_locales/{{.Locale}}/messages.json"' +
' files pull',
{
stdio: [null, process.stdout, process.stderr],
}
await Promise.all(
dirEntries.map(dirEntry => rm(dirEntry, { recursive: true }))
);
function rename(from: string, to: string) {
console.log(`Renaming "${from}" to "${to}"`);
fsExtra.moveSync(path.join('_locales', from), path.join('_locales', to), {
overwrite: true,
});
console.log('Getting latest strings');
const prettierConfig = await prettier.resolveConfig('_locales');
const zip = Readable.from(
fileRes.body as unknown as AsyncIterable<Uint8Array>
).pipe(unzipper.Parse({ forceStream: true }));
for await (const entry of zip) {
if (entry.type !== 'File') {
entry.autodrain();
continue;
}
// Smartling uses "zh-YU" for Cantonese (or Yue Chinese).
// This is wrong.
// The language tag for Yue Chinese is "yue"
// "zh-YU" actually implies "Chinese as spoken in Yugoslavia (canonicalized to Serbia)"
rename('zh-YU', 'yue');
let [locale] = entry.path.split(/[\\/]/, 1);
locale = RENAMES.get(locale) ?? locale;
// For most of the Chinese-speaking world, where we don't have a region specific
// locale available (e.g. zh-HK), zh-TW is a suitable choice for "Traditional Chinese".
//
// However, Intl.LocaleMatcher won't match "zh-Hant-XX" to "zh-TW",
// we need to rename it to "zh-Hant" explicitly to make it work.
rename('zh-TW', 'zh-Hant');
const targetDir = path.join('_locales', locale);
try {
await mkdir(targetDir);
} catch (error) {
console.error(error);
}
// "YR" is not a valid region subtag. Smartling made it up.
rename('sr-YR', 'sr');
console.log('Formatting newly-downloaded strings!');
console.log();
execSync('yarn format', {
stdio: [null, process.stdout, process.stderr],
const targetFile = path.join(targetDir, 'messages.json');
console.log('Writing', locale);
const json = JSON.parse((await entry.buffer()).toString());
for (const value of Object.values(json)) {
const typedValue = value as { description?: string };
delete typedValue.description;
}
delete json.smartling;
const output = prettier.format(JSON.stringify(json, null, 2), {
...prettierConfig,
filepath: targetFile,
});
await writeFile(targetFile, output);
}
}
main().catch(err => {
console.error(err);
process.exit(1);
});

View file

@ -1,10 +1,14 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { execSync } from 'child_process';
import { randomBytes } from 'node:crypto';
import { readFile } from 'node:fs/promises';
import { API_BASE, PROJECT_ID, authenticate } from '../util/smartling';
const { SMARTLING_USER, SMARTLING_SECRET } = process.env;
async function main() {
if (!SMARTLING_USER) {
console.error('Need to set SMARTLING_USER environment variable!');
process.exit(1);
@ -14,16 +18,54 @@ if (!SMARTLING_SECRET) {
process.exit(1);
}
console.log('Pushing latest strings!');
console.log();
execSync(
'smartling-cli' +
` --user "${SMARTLING_USER}"` +
` --secret "${SMARTLING_SECRET}"` +
' --config .smartling.yml' +
' --verbose' +
' files push _locales/en/messages.json',
{
stdio: [null, process.stdout, process.stderr],
}
console.log('Authenticating with Smartling');
const headers = await authenticate({
userIdentifier: SMARTLING_USER,
userSecret: SMARTLING_SECRET,
});
const boundaryString = randomBytes(32).toString('hex');
headers.set(
'content-type',
`multipart/form-data; boundary=${boundaryString}`
);
const url = new URL(`./files-api/v2/projects/${PROJECT_ID}/file`, API_BASE);
const body = [
`--${boundaryString}`,
'Content-Disposition: form-data; name="fileUri"',
'Content-Type: text/plain',
'',
'_locales/en/messages.json',
`--${boundaryString}`,
'Content-Disposition: form-data; name="fileType"',
'Content-Type: text/plain',
'',
'json',
`--${boundaryString}`,
'Content-Disposition: form-data; name="file"',
'Content-Type: text/plain',
'',
await readFile('_locales/en/messages.json', 'utf8'),
`--${boundaryString}`,
'',
];
console.log('Pushing strings');
const res = await fetch(url, {
method: 'POST',
headers,
body: body.join('\r\n'),
});
if (!res.ok) {
throw new Error(`Failed to push strings: ${await res.text()}`);
}
}
main().catch(err => {
console.error(err);
process.exit(1);
});

View file

@ -276,6 +276,7 @@ const excludedFilesRegexp = RegExp(
'^node_modules/yargs-unparser/',
'^node_modules/yargs/.+',
'^node_modules/find-yarn-workspace-root/.+',
'^node_modules/unzipper/node_modules/bluebird/.+',
'^node_modules/update-notifier/.+',
'^node_modules/windows-release/.+',

41
ts/util/smartling.ts Normal file
View file

@ -0,0 +1,41 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as packageJson from '../../package.json';
import { getUserAgent } from './getUserAgent';
type AuthenticateOptionsType = Readonly<{
userIdentifier: string;
userSecret: string;
}>;
export const API_BASE = new URL('https://api.smartling.com/');
export const PROJECT_ID = 'ef62d1ebb';
export async function authenticate({
userIdentifier,
userSecret,
}: AuthenticateOptionsType): Promise<Headers> {
const res = await fetch(new URL('./auth-api/v2/authenticate', API_BASE), {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
userIdentifier,
userSecret,
}),
});
if (!res.ok) {
throw new Error('Failed to authenticate with Smartling');
}
const {
response: { data: auth },
} = await res.json();
return new Headers({
authorization: `${auth.tokenType} ${auth.accessToken}`,
'user-agent': getUserAgent(packageJson.version),
});
}

123
yarn.lock
View file

@ -5785,6 +5785,13 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
"@types/unzipper@0.10.9":
version "0.10.9"
resolved "https://registry.yarnpkg.com/@types/unzipper/-/unzipper-0.10.9.tgz#ccbc393ecd1ec013dbe9bc6f13332dad0aa00a0f"
integrity sha512-vHbmFZAw8emNAOVkHVbS3qBnbr0x/qHQZ+ei1HE7Oy6Tyrptl+jpqnOX+BF5owcu/HZLOV0nJK+K9sjs1Ox2JA==
dependencies:
"@types/node" "*"
"@types/uuid@3.4.4":
version "3.4.4"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5"
@ -7112,6 +7119,11 @@ better-opn@^3.0.2:
dependencies:
open "^8.0.4"
big-integer@^1.6.17:
version "1.6.52"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85"
integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==
big-integer@^1.6.44:
version "1.6.51"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
@ -7127,6 +7139,14 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
binary@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79"
integrity sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==
dependencies:
buffers "~0.1.1"
chainsaw "~0.1.0"
bindings@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
@ -7169,6 +7189,11 @@ bluebird@^3.5.5, bluebird@^3.7.2:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
bluebird@~3.4.1:
version "3.4.7"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
integrity sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==
blueimp-load-image@5.14.0:
version "5.14.0"
resolved "https://registry.yarnpkg.com/blueimp-load-image/-/blueimp-load-image-5.14.0.tgz#e8086415e580df802c33ff0da6b37a8d20205cc6"
@ -7335,6 +7360,11 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer-indexof-polyfill@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
buffer@6.0.3, buffer@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
@ -7351,6 +7381,11 @@ buffer@^5.5.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
buffers@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
integrity sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==
bufferutil@^4.0.1:
version "4.0.7"
resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad"
@ -7590,6 +7625,13 @@ chai@4.3.4:
pathval "^1.1.1"
type-detect "^4.0.5"
chainsaw@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
integrity sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==
dependencies:
traverse ">=0.3.0 <0.4"
chalk@4.1.2, chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@ -9081,6 +9123,13 @@ dotenv@^9.0.2:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05"
integrity sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==
duplexer2@~0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==
dependencies:
readable-stream "^2.0.2"
duplexify@^3.5.0:
version "3.7.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
@ -10798,6 +10847,16 @@ fsevents@^2.3.2:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
fstream@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
dependencies:
graceful-fs "^4.1.2"
inherits "~2.0.0"
mkdirp ">=0.5 0"
rimraf "2"
function-bind@^1.0.2, function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@ -11242,7 +11301,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9,
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
graceful-fs@^4.1.15:
graceful-fs@^4.1.15, graceful-fs@^4.2.2:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
@ -11881,7 +11940,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, 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==
@ -13637,6 +13696,11 @@ linkify-it@^3.0.1:
dependencies:
uc.micro "^1.0.1"
listenercount@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937"
integrity sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@ -14652,7 +14716,7 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.6:
"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
@ -17079,6 +17143,19 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.6, readable
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readable-stream@^2.0.2:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
@ -17577,19 +17654,19 @@ reusify@^1.0.0:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rimraf@2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies:
glob "^7.0.5"
rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
dependencies:
glob "^7.1.3"
rimraf@2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies:
glob "^7.0.5"
rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@ -17917,6 +17994,11 @@ set-value@^2.0.0:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setimmediate@~1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
setprototypeof@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
@ -19170,6 +19252,11 @@ tr46@~0.0.3:
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
"traverse@>=0.3.0 <0.4":
version "0.3.9"
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
integrity sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
@ -19609,6 +19696,22 @@ untildify@^4.0.0:
resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
unzipper@0.10.14:
version "0.10.14"
resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.14.tgz#d2b33c977714da0fbc0f82774ad35470a7c962b1"
integrity sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==
dependencies:
big-integer "^1.6.17"
binary "~0.3.0"
bluebird "~3.4.1"
buffer-indexof-polyfill "~1.0.0"
duplexer2 "~0.1.4"
fstream "^1.0.12"
graceful-fs "^4.2.2"
listenercount "~1.0.1"
readable-stream "~2.3.6"
setimmediate "~1.0.4"
upath@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b"