Add Go to the build environment (#731)

* Move TPN CLI from bin to lib and publish from there.

* Fix TPN CLI path

* Add tasks to download, install, build, and run Go programs as part of the build environment. In each package, Go source is under /go/<project> and binaries are compiled to /bin.

* repalce ?. with equivalent code

* Replace ?. with equivalent code

* fix windows plaform name in go distro list

* fix go executable filename on windows

* Change files

* Change build-tools build output to verbose for CI loops. Doesn't appear to be a way to keep dev builds as warning-only without duplicating preinstall/posinstall commands (which I don't want to maintain).

* separate go task for hello world example

* Add a Go build step to each package build

* Add missing dependency

* Change files

* Move Go infra into its own package so other repos can use it. Add documentation. Remove dependency on just-scripts.

* Change files

* update readme file

* Update packages/go/README.md

Co-authored-by: Lorenzo Sciandra <lsciandra@microsoft.com>

* Update packages/go/README.md

Co-authored-by: Tommy Nguyen <4123478+tido64@users.noreply.github.com>

* Rename package from go to golang. Revert loglevel on yarn build-tools.

* Add handling for non-monorepo cases.

* Update packages/golang/package.json

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

Co-authored-by: Lorenzo Sciandra <lsciandra@microsoft.com>
Co-authored-by: Tommy Nguyen <4123478+tido64@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Adam Foxman 2021-10-22 11:24:53 -07:00 коммит произвёл GitHub
Родитель 47418f2732
Коммит 3c965a3209
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
27 изменённых файлов: 896 добавлений и 33 удалений

3
.github/workflows/build.yml поставляемый
Просмотреть файл

@ -15,6 +15,9 @@ jobs:
uses: actions/setup-node@v2.4.1
with:
node-version: 14
- uses: actions/setup-go@v2
with:
go-version: "^1.14.0"
- name: Checkout
uses: actions/checkout@v2.3.5
with:

5
.github/workflows/pr.yml поставляемый
Просмотреть файл

@ -23,6 +23,8 @@ jobs:
key: ${{ hashFiles('yarn.lock') }}
- name: Install package dependencies
run: yarn ci
env:
CI_SKIP_GO: 1
- name: Check for change files
run: yarn run beachball check --branch origin/${{ github.base_ref }} --changehint \"Run 'yarn run change' from root of repo to generate a change file.\"
- name: Format
@ -53,6 +55,9 @@ jobs:
uses: actions/setup-node@v2.4.1
with:
node-version: ${{ matrix.node-version }}
- uses: actions/setup-go@v2
with:
go-version: "^1.14.0"
- name: Checkout
uses: actions/checkout@v2.3.5
with:

2
.gitignore поставляемый
Просмотреть файл

@ -7,8 +7,10 @@
.idea/
Pods/
coverage/
/packages/*/bin/
/packages/*/dist/
/packages/*/lib/
/scripts/bin/
/scripts/lib/
local.properties
node_modules/

Просмотреть файл

@ -113,30 +113,31 @@ individually, as features are added and fixes are made.
<!-- The following table can be updated by running `yarn update-readme` -->
<!-- @rnx-kit start -->
| Name | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [@rnx-kit/babel-plugin-import-path-remapper](https://github.com/microsoft/rnx-kit/tree/main/packages/babel-plugin-import-path-remapper) | Babel plugin for remapping 'lib/' imports to 'src/' |
| [@rnx-kit/babel-preset-metro-react-native](https://github.com/microsoft/rnx-kit/tree/main/packages/babel-preset-metro-react-native) | Babel preset for React Native applications |
| [@rnx-kit/bundle-diff](https://github.com/microsoft/rnx-kit/tree/main/packages/bundle-diff) | Simple tool for diffing the content of two bundles |
| [@rnx-kit/cli](https://github.com/microsoft/rnx-kit/tree/main/packages/cli) | Command-line interface for working with kit packages in your repo |
| [@rnx-kit/config](https://github.com/microsoft/rnx-kit/tree/main/packages/config) | Define and query information about a kit package |
| [@rnx-kit/console](https://github.com/microsoft/rnx-kit/tree/main/packages/console) | Simple console logger |
| [@rnx-kit/dep-check](https://github.com/microsoft/rnx-kit/tree/main/packages/dep-check) | Dependency checker for React Native apps |
| [@rnx-kit/esbuild-plugin-import-path-remapper](https://github.com/microsoft/rnx-kit/tree/main/packages/esbuild-plugin-import-path-remapper) | Esbuild plugin for remapping 'lib/' imports to 'src/' |
| [@rnx-kit/jest-preset](https://github.com/microsoft/rnx-kit/tree/main/packages/jest-preset) | Jest preset for React Native code bases |
| [@rnx-kit/metro-config](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-config) | Metro config for monorepos |
| [@rnx-kit/metro-plugin-cyclic-dependencies-detector](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-plugin-cyclic-dependencies-detector) | Cyclic dependencies detector for Metro |
| [@rnx-kit/metro-plugin-duplicates-checker](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-plugin-duplicates-checker) | Duplicate packages checker |
| [@rnx-kit/metro-plugin-typescript-validation](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-plugin-typescript-validation) | Typescript validation during Metro bundling |
| [@rnx-kit/metro-resolver-symlinks](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-resolver-symlinks) | Metro resolver with support for symlinks |
| [@rnx-kit/metro-serializer](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-serializer) | Metro's default JavaScript bundle serializer but with plugin support |
| [@rnx-kit/metro-serializer-esbuild](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-serializer-esbuild) | Experimental esbuild serializer for Metro |
| [@rnx-kit/metro-service](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-service) | Metro service for bundling and bundle-serving |
| [@rnx-kit/third-party-notices](https://github.com/microsoft/rnx-kit/tree/main/packages/third-party-notices) | Library and tool to build a third party notices file based on a js bundle's source map |
| [@rnx-kit/tools-language](https://github.com/microsoft/rnx-kit/tree/main/packages/tools-language) | A collection of supplemental JavaScript functions and types |
| [@rnx-kit/tools-node](https://github.com/microsoft/rnx-kit/tree/main/packages/tools-node) | A collection of supplemental NodeJS functions and types |
| [@rnx-kit/tools-react-native](https://github.com/microsoft/rnx-kit/tree/main/packages/tools-react-native) | A collection of supplemental react-native functions and types |
| [@rnx-kit/typescript-service](https://github.com/microsoft/rnx-kit/tree/main/packages/typescript-service) | TypeScript language services with support for custom module resolution |
| Name | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| [@rnx-kit/babel-plugin-import-path-remapper](https://github.com/microsoft/rnx-kit/tree/main/packages/babel-plugin-import-path-remapper) | Babel plugin for remapping 'lib/' imports to 'src/' |
| [@rnx-kit/babel-preset-metro-react-native](https://github.com/microsoft/rnx-kit/tree/main/packages/babel-preset-metro-react-native) | Babel preset for React Native applications |
| [@rnx-kit/bundle-diff](https://github.com/microsoft/rnx-kit/tree/main/packages/bundle-diff) | Simple tool for diffing the content of two bundles |
| [@rnx-kit/cli](https://github.com/microsoft/rnx-kit/tree/main/packages/cli) | Command-line interface for working with kit packages in your repo |
| [@rnx-kit/config](https://github.com/microsoft/rnx-kit/tree/main/packages/config) | Define and query information about a kit package |
| [@rnx-kit/console](https://github.com/microsoft/rnx-kit/tree/main/packages/console) | Simple console logger |
| [@rnx-kit/dep-check](https://github.com/microsoft/rnx-kit/tree/main/packages/dep-check) | Dependency checker for React Native apps |
| [@rnx-kit/esbuild-plugin-import-path-remapper](https://github.com/microsoft/rnx-kit/tree/main/packages/esbuild-plugin-import-path-remapper) | Esbuild plugin for remapping 'lib/' imports to 'src/' |
| [@rnx-kit/golang](https://github.com/microsoft/rnx-kit/tree/main/packages/golang) | Integrate Go into your monorepo and create native apps that accelerate development and CI builds |
| [@rnx-kit/jest-preset](https://github.com/microsoft/rnx-kit/tree/main/packages/jest-preset) | Jest preset for React Native code bases |
| [@rnx-kit/metro-config](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-config) | Metro config for monorepos |
| [@rnx-kit/metro-plugin-cyclic-dependencies-detector](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-plugin-cyclic-dependencies-detector) | Cyclic dependencies detector for Metro |
| [@rnx-kit/metro-plugin-duplicates-checker](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-plugin-duplicates-checker) | Duplicate packages checker |
| [@rnx-kit/metro-plugin-typescript-validation](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-plugin-typescript-validation) | Typescript validation during Metro bundling |
| [@rnx-kit/metro-resolver-symlinks](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-resolver-symlinks) | Metro resolver with support for symlinks |
| [@rnx-kit/metro-serializer](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-serializer) | Metro's default JavaScript bundle serializer but with plugin support |
| [@rnx-kit/metro-serializer-esbuild](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-serializer-esbuild) | Experimental esbuild serializer for Metro |
| [@rnx-kit/metro-service](https://github.com/microsoft/rnx-kit/tree/main/packages/metro-service) | Metro service for bundling and bundle-serving |
| [@rnx-kit/third-party-notices](https://github.com/microsoft/rnx-kit/tree/main/packages/third-party-notices) | Library and tool to build a third party notices file based on a js bundle's source map |
| [@rnx-kit/tools-language](https://github.com/microsoft/rnx-kit/tree/main/packages/tools-language) | A collection of supplemental JavaScript functions and types |
| [@rnx-kit/tools-node](https://github.com/microsoft/rnx-kit/tree/main/packages/tools-node) | A collection of supplemental NodeJS functions and types |
| [@rnx-kit/tools-react-native](https://github.com/microsoft/rnx-kit/tree/main/packages/tools-react-native) | A collection of supplemental react-native functions and types |
| [@rnx-kit/typescript-service](https://github.com/microsoft/rnx-kit/tree/main/packages/typescript-service) | TypeScript language services with support for custom module resolution |
<!-- @rnx-kit end -->

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Add missing dependency",
"packageName": "@rnx-kit/esbuild-plugin-import-path-remapper",
"email": "afoxman@microsoft.com",
"dependentChangeType": "none"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Move Go infra into its own package so other repos can use it. Add documentation. Remove dependency on just-scripts.",
"packageName": "@rnx-kit/golang",
"email": "afoxman@microsoft.com",
"dependentChangeType": "none"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Move TPN CLI from bin to lib and publish from there.",
"packageName": "@rnx-kit/third-party-notices",
"email": "afoxman@microsoft.com",
"dependentChangeType": "none"
}

Просмотреть файл

@ -21,7 +21,8 @@
},
"devDependencies": {
"prettier": "^2.0.0",
"esbuild": "^0.13.4"
"esbuild": "^0.13.4",
"rnx-kit-scripts": "*"
},
"depcheck": {
"ignorePatterns": [

135
packages/golang/README.md Normal file
Просмотреть файл

@ -0,0 +1,135 @@
# @rnx-kit/golang
[![Build](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml/badge.svg)](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml)
[![npm version](https://img.shields.io/npm/v/@rnx-kit/golang)](https://www.npmjs.com/package/@rnx-kit/golang)
Integrate [Go](https://golang.org) into your monorepo and create native apps
that accelerate development and CI builds.
## Motivation
JavaScript monorepos make extensive use of NodeJs-based tools like TypeScript,
Babel, Metro and Webpack, to name just a few. As monorepos grow in size and
complexity, developers are finding that the tools don't scale well. Native
applications like esbuild and swc are emerging to address poor toolchain
performance, and more are expected to appear in the coming years.
Developers need to optimize the tools they use to keep engineering productivity
high. Turning the crank on a PR should take minutes, not hours. Converting
pieces of the toolchain to native code is required to achieve this goal.
## Usage
There are three core functions in this library. To build and use Go programs,
you'll need to integrate them into your task runner and CI loops.
```typescript
type Logger = {
info: (message: string) => void;
warn: (message: string) => void;
error: (message: string) => void;
};
// Task factories for installing Go, and building/running Go programs.
function goInstallTask(logger?: Logger): () => Promise<void>;
function goBuildTask(logger?: Logger): () => Promise<void>;
function goTask(
logger: Logger | undefined,
name: string,
...args: string[]
): () => Promise<void>;
```
Go installation first looks for an existing version of Go in the system path. If
nothing was found, a local distribution of Go is downloaded and cached in the
monorepo. Future "install" calls will detect the local installation, skipping
this entire step.
The Go build task looks for Go apps under ./go/`{project-name}` and stores built
binaries under ./bin. Each app is built using the command "go build -o
`{bin-path}`". The Go app's binary name doesn't need to match `{project-name}`.
The Go execution task looks for the named binary in ./bin and executes it with
an optional set of arguments.
### Pre-requisites
Windows 10 in a minimum requirement. This package uses `tar` which ships with
that version of Windows.
### Build Tasks
The three functions are task factories. They each return a function that you can
run as a build step in systems like [Just](https://microsoft.github.io/just) or
[Gulp](https://gulpjs.com).
```typescript
import { task, logger } from "just-scripts";
import { goBuildTask, goTask } from "@rnx-kit/golang";
// Make new Just tasks to install Go and build Go programs
task("go:install", goInstallTask(logger));
task("go:build", goBuildTask(logger));
task("go", series("go:install", "go:build"));
// Tie them into the mainline build task
task("build", build("clean", "go", "lint", "ts"));
// Add a Just task wrapper to execute the Go app named "transcode-media"
// which reformats video files into 640x480 @ 30 fps using a well-known
// encoding like AVC/H.264.
//
// This can be executed as part of other tasks, or directly on the
// command-line: npm run just-scripts transcode-media.
//
task(
"transcode-media",
goTask(logger, "transcoder", assetsDir, transcoderOutputDir)
);
```
### CI Loop Tasks
Some CI systems like [GitHub Actions](https://github.com/features/actions) have
VM images that come with Go preinstalled. To use the installed copy in GitHub
Actions, you may need to add a step like
[setup-go](https://github.com/actions/setup-go) to your CI pipeline definition:
```yaml
- uses: actions/setup-go@v2
with:
go-version: "^1.14.0"
```
If you're using a different CI provider, find out if Go is on the build VMs. It
will save you time and bandwidth on each CI run.
### .gitignore
Avoid checking in Go apps, as they are platform-specific and take up a lot of
room. Add an entry to `.gitignore` to exclude the bin directory from each
package:
```diff
+/packages/*/bin/
/packages/*/dist/
/packages/*/lib/
node_modules/
```
### `clean` build task
It's a good idea to clean out each package's `bin` directory when running a
`clean` build task. This removes any stale Go apps, which will be rebuilt as
needed.
```diff
import { cleanTask } from "just-scripts";
export const clean = cleanTask({
paths: [
+ "bin",
"lib",
].map((p) => path.join(process.cwd(), p)),
});
```

Просмотреть файл

@ -0,0 +1,41 @@
{
"name": "@rnx-kit/golang",
"version": "0.1.0",
"description": "Integrate Go into your monorepo and create native apps that accelerate development and CI builds",
"homepage": "https://github.com/microsoft/rnx-kit/tree/main/packages/golang#readme",
"license": "MIT",
"files": [
"src/*"
],
"main": "src/index.js",
"types": "src/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/rnx-kit",
"directory": "packages/golang"
},
"engines": {
"node": ">= 14"
},
"scripts": {
"build": "tsc",
"format": "prettier --write src/**/*.js",
"lint": "eslint src/* --ext .js,.jsx,.ts,.tsx --config package.json --color"
},
"dependencies": {
"find-up": "^5.0.0",
"got": "^11.8.2",
"hasha": "^5.2.2",
"typescript": "^4.0.0",
"workspace-tools": "^0.16.2"
},
"devDependencies": {
"@rnx-kit/eslint-config": "^0.0.1",
"@types/node": "^14.15.0",
"eslint": "^8.0.0",
"prettier": "^2.0.0"
},
"eslintConfig": {
"extends": "@rnx-kit/eslint-config"
}
}

Просмотреть файл

@ -0,0 +1,80 @@
// @ts-check
const fs = require("fs");
const got = require("got");
const hasha = require("hasha");
const path = require("path");
const stream = require("stream");
const { promisify } = require("util");
/**
* @typedef {{ info: (m: string) => void; warn: (m: string) => void; error: (m: string) => void; }} Logger
*/
/**
* Download a file from an http(s) URL using a GET request. Verify the file
* contents using a hash.
*
* @param {Logger | undefined} logger Optional logger to use when reporting progress
* @param {string} url Url of the file to download. Can be http or https.
* @param {string} targetFile File name and path to use for the downloaded file. Existing files are overwritten. Relative paths are resolved using the current working directory.
* @param {"sha256" | "sha512" | "md5" | "sha1" | string} hashAlgorithm Name of the hash algorithm to use. See https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options.
* @param {string} expectedHash Expected hash value for the file. Hex-encoded, lower-case.
* @returns Task function to be used with Just.
*/
function downloadTask(logger, url, targetFile, hashAlgorithm, expectedHash) {
async function validateHash() {
logger?.info(`Verifying ${hashAlgorithm} hash of file '${targetFile}'`);
const calculatedHash = await hasha.fromFile(targetFile, {
encoding: "hex",
algorithm: hashAlgorithm,
});
if (calculatedHash === expectedHash) {
logger?.info("File is valid (hash matches)");
} else {
logger?.warn(
`File is invalid -- hash mismatch:\n calculated: ${calculatedHash}\n expected: ${expectedHash}'\n algorithm: ${hashAlgorithm}`
);
}
return Promise.resolve(calculatedHash === expectedHash);
}
return async function download() {
const pipeline = promisify(stream.pipeline);
const targetPath = path.resolve(targetFile);
logger?.info(`Downloading '${url}' to '${targetPath}'`);
if (fs.existsSync(targetPath)) {
logger?.info(`Found target file '${targetPath}'`);
if (await validateHash()) {
return Promise.resolve();
}
}
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
const options = {
resolveBodyOnly: false,
decompress: false,
throwHttpErrors: true,
timeout: 60 * 1000,
https: {
rejectUnauthorized: true,
},
};
await pipeline(
got.default.stream.get(url, options),
fs.createWriteStream(targetPath, { flags: "w" })
);
if (!(await validateHash())) {
throw new Error(`Download from '${url}' failed with a hash mismatch`);
}
return Promise.resolve();
};
}
exports.downloadTask = downloadTask;

244
packages/golang/src/go.js Normal file
Просмотреть файл

@ -0,0 +1,244 @@
// @ts-check
const findUp = require("find-up");
const fs = require("fs");
const path = require("path");
const { getWorkspaceRoot } = require("workspace-tools");
const { downloadTask } = require("./download");
const { unpackTask } = require("./unpack");
const { spawn } = require("./spawn");
/**
* @typedef {{url: string, hashAlgorithm: string, hash: string }} GoDistribution
* @typedef {{ info: (m: string) => void; warn: (m: string) => void; error: (m: string) => void; }} Logger
*/
/**
* Listing of known Go binary distributions, indexed by NodeJs process.platform
* then further indexed by process.arch.
*
* @type {{[platform: string]: {[architecture: string]: GoDistribution }}}
*/
const goDistributions = {
darwin: {
arm64: {
url: "https://golang.org/dl/go1.17.2.darwin-arm64.tar.gz",
hashAlgorithm: "sha256",
hash: "ce8771bd3edfb5b28104084b56bbb532eeb47fbb7769c3e664c6223712c30904",
},
x64: {
url: "https://golang.org/dl/go1.17.2.darwin-amd64.tar.gz",
hashAlgorithm: "sha256",
hash: "7914497a302a132a465d33f5ee044ce05568bacdb390ab805cb75a3435a23f94",
},
},
linux: {
x32: {
url: "https://golang.org/dl/go1.17.2.linux-386.tar.gz",
hashAlgorithm: "sha256",
hash: "8617f2e40d51076983502894181ae639d1d8101bfbc4d7463a2b442f239f5596",
},
x64: {
url: "https://golang.org/dl/go1.17.2.linux-amd64.tar.gz",
hashAlgorithm: "sha256",
hash: "f242a9db6a0ad1846de7b6d94d507915d14062660616a61ef7c808a76e4f1676",
},
arm64: {
url: "https://golang.org/dl/go1.17.2.linux-arm64.tar.gz",
hashAlgorithm: "sha256",
hash: "a5a43c9cdabdb9f371d56951b14290eba8ce2f9b0db48fb5fc657943984fd4fc",
},
},
win32: {
x32: {
url: "https://golang.org/dl/go1.17.2.windows-386.zip",
hashAlgorithm: "sha256",
hash: "8a85257a351996fdf045fe95ed5fdd6917dd48636d562dd11dedf193005a53e0",
},
x64: {
url: "https://golang.org/dl/go1.17.2.windows-amd64.zip",
hashAlgorithm: "sha256",
hash: "fa6da0b829a66f5fab7e4e312fd6aa1b2d8f045c7ecee83b3d00f6fe5306759a",
},
},
};
/**
* Get info on the Go distrubution matching the current plaform/architecture.
*
* @returns {GoDistribution | undefined} Go distribution info, or `undefined` if a distribution isn't available.
*/
function getGoDistribution() {
const p = goDistributions[process.platform];
if (p) {
return p[process.arch];
}
return undefined;
}
/**
* Get the path of the monorepo's root node_modules/.cache directory.
*
* @returns {string} Path to the root node_modules/.cache directory
*/
function getWorkspaceCacheDir() {
let workspaceRoot;
try {
workspaceRoot = getWorkspaceRoot(process.cwd());
} catch (_) {
// not a monorepo
}
if (!workspaceRoot) {
workspaceRoot = findUp.sync("package-lock.json");
if (workspaceRoot) {
workspaceRoot = path.dirname(workspaceRoot);
}
}
if (!workspaceRoot) {
throw new Error("Cannot find the root of the repository");
}
return path.join(workspaceRoot, "node_modules", ".cache");
}
/**
* Get the path to the Go executable.
*
* This looks for a local installation of Go first. If not found, it assumes
* Go is available through the system PATH.
*/
function getGoExecutable() {
const goExecutableFileName = process.platform === "win32" ? "go.exe" : "go";
const goLocalExecutable = path.join(
getWorkspaceCacheDir(),
// The "go" subdirectory comes from unpacking the Go archive. It is part
// of the Go distribution.
"go",
"bin",
goExecutableFileName
);
if (fs.existsSync(goLocalExecutable)) {
return goLocalExecutable;
}
return "go";
}
/**
* Ensure that Go is installed and available for building Go projects via
* `goBuildTask()`.
*
* @param {Logger | undefined} logger Optional logger to use when reporting progress
*/
function goInstallTask(logger) {
return async function goInstall() {
logger?.info("Looking for an installation of Go");
try {
spawn(logger, "go", ["version"]).trim();
logger?.info("Found Go in the system PATH");
return Promise.resolve();
} catch (_) {
// nop
}
logger?.info("Go is not installed on this machine");
const goDistribution = getGoDistribution();
if (!goDistribution) {
logger?.error(
`This build system requires Go, but there isn't currently a distribution for your build machine architecture '${process.platform}-${process.arch}'. Common architectures like 64-bit linux, windows, and mac are all supported. If you can't use those types of systems and require support for '${process.platform}-${process.arch}', please open an issue: https://github.com/microsoft/rnx-kit/issues.`
);
throw new Error(
`Unsupported build machine architecture '${process.platform}-${process.arch}'`
);
}
const downloadDir = path.join(process.cwd(), "node_modules", ".cache");
const downloadFile = path.join(
downloadDir,
path.basename(goDistribution.url)
);
await downloadTask(
logger,
goDistribution.url,
downloadFile,
goDistribution.hashAlgorithm,
goDistribution.hash
)();
const unpackDir = getWorkspaceCacheDir();
// The "go" subdirectory comes from unpacking the archive. It is part of
// the Go distribution.
const probeDir = path.join(unpackDir, "go");
await unpackTask(logger, downloadFile, unpackDir, probeDir)();
logger?.info(`Installed Go: ${probeDir}`);
return Promise.resolve();
};
}
exports.goInstallTask = goInstallTask;
/**
* Build all Go projects in the current package.
*
* Go projects are expected to be under <packageRoot>/go/<projectName>.
*
* Built binaries are stored under <packageRoot>/bin.
*
* @param {Logger | undefined} logger Optional logger to use when reporting progress
* @returns Task function for use with Just.
*/
function goBuildTask(logger) {
const goSourceRoot = path.join(process.cwd(), "go");
const binPath = path.join(process.cwd(), "bin");
/** @type string[] */
let projectDirs = [];
if (fs.existsSync(goSourceRoot)) {
projectDirs = fs
.readdirSync(goSourceRoot, { withFileTypes: true })
.filter((e) => e.isDirectory())
.map((e) => e.name);
}
if (projectDirs.length > 0) {
return async function buildGo() {
const goExecutable = getGoExecutable();
fs.mkdirSync(binPath, { recursive: true });
for (const projectDir of projectDirs) {
logger?.info(`Building Go project '${projectDir}'`);
const cwd = path.join(goSourceRoot, projectDir);
spawn(logger, goExecutable, ["build", "-o", binPath], cwd);
}
return Promise.resolve();
};
}
return async function skipBuildGo() {
logger?.info("No projects found -- skipping");
};
}
exports.goBuildTask = goBuildTask;
/**
* Execute a Go program with optional arguments.
*
* @param {Logger | undefined} logger Optional logger to use when reporting progress
* @param {string} name Path to the Go program file. Relative paths are resolved to the current package's "bin" directory.
* @param {string[]} args Optional program arguments.
* @returns Task function for use with Just.
*/
function goTask(logger, name, ...args) {
return async function go() {
const executable = path.resolve(path.join(process.cwd(), "bin"), name);
spawn(logger, executable, args);
return Promise.resolve();
};
}
exports.goTask = goTask;

13
packages/golang/src/index.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
export declare type Logger = {
info: (message: string) => void;
warn: (message: string) => void;
error: (message: string) => void;
};
export declare function goInstallTask(logger?: Logger): () => Promise<void>;
export declare function goBuildTask(logger?: Logger): () => Promise<void>;
export declare function goTask(
logger: Logger | undefined,
name: string,
...args: string[]
): () => Promise<void>;

Просмотреть файл

@ -0,0 +1,6 @@
const { goInstallTask, goBuildTask, goTask } = require("./go");
module.exports = {
goInstallTask,
goBuildTask,
goTask,
};

Просмотреть файл

@ -0,0 +1,46 @@
const child_process = require("child_process");
/**
* @typedef {{ info: (m: string) => void; warn: (m: string) => void; error: (m: string) => void; }} Logger
*/
/**
* Spawn a child process, and wait for it to complete. Print stdout and stderr
* to the build log. On success, returns stdout. On failure, throw an Error
* explaining the problem.
*
* @param {Logger | undefined} logger Optional logger to use when reporting progress
* @param {string} command Name of the executable to run.
* @param {string[]} [args] Optional command-line arguments.
* @param {string} [cwd] Optional working directory for the child process. When not given, the current working directory is used.
* @returns Contents of stdout.
*/
function spawn(logger, command, args, cwd) {
logger?.info(`Executing: ${command} ${args ? args.join(" ") : ""}`);
const cp = child_process.spawnSync(command, args, {
stdio: ["ignore", "pipe", "pipe"],
...(cwd ? { cwd } : undefined),
});
const stdout = cp.stdout ? cp.stdout.toString("utf8") : "";
const stderr = cp.stderr ? cp.stderr.toString("utf8") : "";
if (stdout) {
logger?.info("STDOUT:");
stdout.split("\n").forEach((l) => logger?.info(l));
}
if (stderr) {
logger?.error("STDERR:");
stderr.split("\n").forEach((l) => logger?.error(l));
}
if (cp.error) {
throw cp.error;
} else if (cp.signal) {
throw new Error(`Failed with signal ${cp.signal}'`);
} else if (cp.status !== 0) {
throw new Error(`Failed with exit code ${cp.status}'`);
}
return stdout;
}
exports.spawn = spawn;

Просмотреть файл

@ -0,0 +1,35 @@
// @ts-check
const fs = require("fs");
const { spawn } = require("./spawn");
/**
* @typedef {{ info: (m: string) => void; warn: (m: string) => void; error: (m: string) => void; }} Logger
*/
/**
* Unpack a compressed archive (`.tar.gz` on Mac/Linux, `.zip` on Windows).
*
* @param {Logger | undefined} logger Optional logger to use when reporting progress
* @param {string} archiveFile Path to the compressed archive file.
* @param {string} targetDir Root directory where the archive should be unpacked.
* @param {string} [probeDir] Optional "probe" directory to check as an indicator that the archive has already been unpacked. This is useful if the archive includes a root directory under which all files are listed.
* @returns Task function for use with Just.
*/
function unpackTask(logger, archiveFile, targetDir, probeDir) {
return async function unpack() {
logger?.info(`Unpacking '${archiveFile}' to '${targetDir}'`);
if (probeDir && fs.existsSync(probeDir)) {
logger?.info("Already unpacked -- skipping");
return Promise.resolve();
}
fs.mkdirSync(targetDir, { recursive: true });
spawn(logger, "tar", ["-xzf", archiveFile, "-C", targetDir]);
return Promise.resolve();
};
}
exports.unpackTask = unpackTask;

Просмотреть файл

@ -0,0 +1,7 @@
{
"extends": "rnx-kit-scripts/tsconfig-shared.json",
"compilerOptions": {
"noEmit": true
},
"include": ["src"]
}

Просмотреть файл

@ -1,2 +0,0 @@
#!/usr/bin/env node
require("../lib/cli.js");

Просмотреть файл

@ -10,7 +10,7 @@
],
"main": "lib/index.js",
"bin": {
"build-tpn": "./bin/build-tpn.js"
"build-tpn": "./lib/build-tpn.js"
},
"repository": {
"type": "git",

Просмотреть файл

@ -0,0 +1,2 @@
#!/usr/bin/env node
require("./cli.js");

3
scripts/go/hello/go.mod Normal file
Просмотреть файл

@ -0,0 +1,3 @@
module example/hello
go 1.17

13
scripts/go/hello/hello.go Normal file
Просмотреть файл

@ -0,0 +1,13 @@
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("Hello, World!")
for index, arg := range os.Args {
fmt.Printf("args[%d]=%s\n", index, arg)
}
}

Просмотреть файл

@ -8,12 +8,16 @@ const {
tscTask,
cleanTask,
eslintTask,
logger,
} = require("just-scripts");
const path = require("path");
const { goInstallTask, goBuildTask } = require("@rnx-kit/golang");
const srcPath = path.join(process.cwd(), "src");
const libPath = path.join(process.cwd(), "lib");
const binPath = path.join(process.cwd(), "bin");
const checkPublishing = () => {
const { checkPublishingTask } = require("./lib/tasks/checkPublishingTask");
@ -23,8 +27,13 @@ const checkPublishing = () => {
module.exports = function preset() {
option("production");
task("cleanlib", cleanTask({ paths: [libPath] }));
task("cleanlib", cleanTask({ paths: [binPath, libPath] }));
task("eslint", eslintTask({ files: ["src/*"] }));
task("go:install", goInstallTask(logger));
task("go:build", goBuildTask(logger));
task("go", series("go:install", "go:build"));
task(
"ts",
tscTask({
@ -42,6 +51,10 @@ module.exports = function preset() {
task("depcheck", checkPublishing);
task("no-op", () => {});
task("build", series("cleanlib", "eslint", "ts"));
if (process.env["CI_SKIP_GO"]) {
task("build", series("cleanlib", "eslint", "ts"));
} else {
task("build", series("cleanlib", "go", "eslint", "ts"));
}
task("clean", "no-op");
};

Просмотреть файл

@ -17,6 +17,7 @@
"@babel/parser": "^7.0.0",
"@babel/types": "^7.0.0",
"@microsoft/tsdoc": "^0.13.0",
"@rnx-kit/golang": "^0.1.0",
"chalk": "^4.1.0",
"depcheck": "^1.0.0",
"glob": "^7.0.0",

Просмотреть файл

@ -1,4 +1,12 @@
import { addResolvePath, option, parallel, series, task } from "just-scripts";
import path from "path";
import {
addResolvePath,
option,
parallel,
series,
task,
logger,
} from "just-scripts";
import { build } from "./tasks/build";
import { clean } from "./tasks/clean";
import { depcheck } from "./tasks/depcheck";
@ -7,6 +15,9 @@ import { jest } from "./tasks/jest";
import { prettier } from "./tasks/prettier";
import { ts } from "./tasks/ts";
import { updateApiReadme } from "./tasks/updateApiReadme";
import { goBuildTask, goTask } from "@rnx-kit/golang";
const scriptsBinDir = path.join(__dirname, "..", "bin");
export function configureJust(): void {
// add a resolve path for the build tooling deps like TS from the scripts folder
@ -25,9 +36,15 @@ export function configureJust(): void {
task("no-op", () => undefined);
task("prettier", prettier);
task("ts", ts);
task("go:build", goBuildTask(logger));
task(
"hello",
goTask(logger, path.join(scriptsBinDir, "hello"), "a", "b", "c")
);
// hierarchical task definintions
task("build", build("clean", "depcheck", "lint", "ts"));
task("build", build("clean", "go:build", "depcheck", "lint", "ts"));
task("code-style", series("prettier", "lint"));
task("format", prettier);
task("update-api-readme", updateApiReadme);

Просмотреть файл

@ -3,6 +3,7 @@ import { cleanTask } from "just-scripts";
export const clean = cleanTask({
paths: [
"bin",
"coverage",
"dist",
"lib",

177
yarn.lock
Просмотреть файл

@ -1831,6 +1831,11 @@
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@sindresorhus/is@^4.0.0":
version "4.2.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.2.0.tgz#667bfc6186ae7c9e0b45a08960c551437176e1ca"
integrity sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==
"@sinonjs/commons@^1.7.0":
version "1.8.2"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b"
@ -1845,6 +1850,13 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
"@szmarczak/http-timer@^4.0.5":
version "4.0.6"
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==
dependencies:
defer-to-connect "^2.0.0"
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@ -1895,6 +1907,16 @@
dependencies:
"@babel/types" "^7.3.0"
"@types/cacheable-request@^6.0.1":
version "6.0.2"
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9"
integrity sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==
dependencies:
"@types/http-cache-semantics" "*"
"@types/keyv" "*"
"@types/node" "*"
"@types/responselike" "*"
"@types/glob@^7.0.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
@ -1910,6 +1932,11 @@
dependencies:
"@types/node" "*"
"@types/http-cache-semantics@*":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
@ -1950,6 +1977,13 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
"@types/keyv@*":
version "3.1.3"
resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.3.tgz#1c9aae32872ec1f20dcdaee89a9f3ba88f465e41"
integrity sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==
dependencies:
"@types/node" "*"
"@types/lodash@^4.14.172":
version "4.14.176"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.176.tgz#641150fc1cda36fbfa329de603bbb175d7ee20c0"
@ -2016,6 +2050,13 @@
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/responselike@*", "@types/responselike@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29"
integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==
dependencies:
"@types/node" "*"
"@types/scheduler@*":
version "0.16.1"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275"
@ -3043,6 +3084,24 @@ cache-base@^1.0.1:
union-value "^1.0.0"
unset-value "^1.0.0"
cacheable-lookup@^5.0.3:
version "5.0.4"
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==
cacheable-request@^7.0.1:
version "7.0.2"
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27"
integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==
dependencies:
clone-response "^1.0.2"
get-stream "^5.1.0"
http-cache-semantics "^4.0.0"
keyv "^4.0.0"
lowercase-keys "^2.0.0"
normalize-url "^6.0.1"
responselike "^2.0.0"
call-bind@^1.0.0, call-bind@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@ -3231,6 +3290,13 @@ clone-deep@^4.0.1:
kind-of "^6.0.2"
shallow-clone "^3.0.0"
clone-response@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
dependencies:
mimic-response "^1.0.0"
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
@ -3578,6 +3644,13 @@ decode-uri-component@^0.2.0:
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
dependencies:
mimic-response "^3.1.0"
dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@ -3610,6 +3683,11 @@ defaults@^1.0.3:
dependencies:
clone "^1.0.2"
defer-to-connect@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@ -4723,7 +4801,7 @@ get-stream@^4.0.0:
dependencies:
pump "^3.0.0"
get-stream@^5.0.0:
get-stream@^5.0.0, get-stream@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
@ -4825,6 +4903,23 @@ globby@^7.1.1:
pify "^3.0.0"
slash "^1.0.0"
got@^11.8.2:
version "11.8.2"
resolved "https://registry.yarnpkg.com/got/-/got-11.8.2.tgz#7abb3959ea28c31f3576f1576c1effce23f33599"
integrity sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==
dependencies:
"@sindresorhus/is" "^4.0.0"
"@szmarczak/http-timer" "^4.0.5"
"@types/cacheable-request" "^6.0.1"
"@types/responselike" "^1.0.0"
cacheable-lookup "^5.0.3"
cacheable-request "^7.0.1"
decompress-response "^6.0.0"
http2-wrapper "^1.0.0-beta.5.2"
lowercase-keys "^2.0.0"
p-cancelable "^2.0.0"
responselike "^2.0.0"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
version "4.2.6"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
@ -4917,6 +5012,14 @@ hash-sum@^2.0.0:
resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a"
integrity sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==
hasha@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1"
integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==
dependencies:
is-stream "^2.0.0"
type-fest "^0.8.0"
hermes-engine@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.9.0.tgz#84d9cfe84e8f6b1b2020d6e71b350cec84ed982f"
@ -4946,6 +5049,11 @@ html-escaper@^2.0.0:
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
http-cache-semantics@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
http-errors@~1.7.2:
version "1.7.3"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
@ -4966,6 +5074,14 @@ http-proxy-agent@^4.0.1:
agent-base "6"
debug "4"
http2-wrapper@^1.0.0-beta.5.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d"
integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==
dependencies:
quick-lru "^5.1.1"
resolve-alpn "^1.0.0"
https-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
@ -6105,6 +6221,11 @@ jsesc@~0.5.0:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
json-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
json-parse-better-errors@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@ -6233,6 +6354,13 @@ just-scripts@^1.4.1:
undertaker-registry "^1.0.1"
yargs-parser "^20.2.3"
keyv@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.3.tgz#4f3aa98de254803cafcd2896734108daa35e4254"
integrity sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==
dependencies:
json-buffer "3.0.1"
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@ -6427,6 +6555,11 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lowercase-keys@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@ -6883,6 +7016,16 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mimic-response@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
mimic-response@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
minimatch@^3.0.2, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
@ -7090,6 +7233,11 @@ normalize-url@^3.3.0:
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
normalize-url@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
now-and-later@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c"
@ -7329,6 +7477,11 @@ os-tmpdir@^1.0.0:
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
p-cancelable@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==
p-defer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
@ -7817,6 +7970,11 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
quick-lru@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
@ -8145,6 +8303,11 @@ require-package-name@^2.0.1:
resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
integrity sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=
resolve-alpn@^1.0.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==
resolve-cwd@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
@ -8200,6 +8363,13 @@ resolve@~1.17.0:
dependencies:
path-parse "^1.0.6"
responselike@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723"
integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==
dependencies:
lowercase-keys "^2.0.0"
restore-cursor@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
@ -9122,6 +9292,11 @@ type-fest@^0.7.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48"
integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==
type-fest@^0.8.0:
version "0.8.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
type-fest@^2.1.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.5.1.tgz#17ba4f36a6abfabf0a92005d045dca77564607b0"