diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33e980f0..62b113aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,9 +65,9 @@ jobs: - name: build test images run: | docker info - ./buildTestImages.ts + yarn synthetic-chain build - name: run test images - run: ./runTestImages.ts + run: yarn synthetic-chain test # XXX this should be instant because all the stages were already built in the steps above # but it's re-building the last stage. This is deemed good enough for now. diff --git a/README.md b/README.md index 8ab0cc46..431309d5 100644 --- a/README.md +++ b/README.md @@ -57,21 +57,21 @@ If the proposal is _pending_ and does not yet have a number, use a letter. The p To build the test images, ``` -./buildTestImages.ts +yarn synthetic-chain build ``` To build the test images for particular proposals, ``` # build just upgrades -./buildTestImages.ts --match upgrade +yarn synthetic-chain build --match upgrade ``` To run the tests for particular proposals, ``` # build just upgrades -./runTestImages.ts --match upgrade +yarn synthetic-chain test --match upgrade ``` ## Debugging diff --git a/buildTestImages.ts b/buildTestImages.ts deleted file mode 100755 index 05dfff77..00000000 --- a/buildTestImages.ts +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env tsx - -import { parseArgs } from 'node:util'; -import { execSync } from 'node:child_process'; -import { imageNameForProposal, readProposals } from './common'; -import { refreshDockerfile } from './makeDockerfile'; - -refreshDockerfile(); - -const options = { - match: { short: 'm', type: 'string' }, - dry: { type: 'boolean' }, -} as const; -const { values } = parseArgs({ options }); - -const { match, dry } = values; - -const allProposals = readProposals(); - -const proposals = match - ? allProposals.filter(p => p.proposalName.includes(match)) - : allProposals; - -for (const proposal of proposals) { - if (!dry) { - console.log(`\nBuilding test image for proposal ${proposal.proposalName}`); - } - const { name, target } = imageNameForProposal(proposal, 'test'); - // 'load' to ensure the images are output to the Docker client. Seems to be necessary - // for the CI docker/build-push-action to re-use the cached stages. - const cmd = `docker buildx build --load --tag ${name} --target ${target} .`; - console.log(cmd); - if (!dry) { - // `time` to output how long each build takes - execSync(`time ${cmd}`, { stdio: 'inherit' }); - } -} diff --git a/common.ts b/common.ts deleted file mode 100644 index 8642afa4..00000000 --- a/common.ts +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env tsx -// @ts-check - -import assert from 'node:assert'; -import fs from 'node:fs'; -import * as path from 'node:path'; - -export const repository = 'ghcr.io/agoric/agoric-3-proposals'; - -type ProposalCommon = { - proposalName: string; - proposalIdentifier: string; -}; - -export type SoftwareUpgradeProposal = ProposalCommon & { - sdkImageTag: string; - planName: string; - releaseNodes: string; - type: 'Software Upgrade Proposal'; -}; - -export type CoreEvalProposal = ProposalCommon & { - type: '/agoric.swingset.CoreEvalProposal'; -}; - -export type ProposalInfo = SoftwareUpgradeProposal | CoreEvalProposal; - -function readInfo(proposalPath: string): ProposalInfo { - const packageJsonPath = path.join('proposals', proposalPath, 'package.json'); - const packageJson = fs.readFileSync(packageJsonPath, 'utf-8'); - const { agoricProposal } = JSON.parse(packageJson); - const [proposalIdentifier, proposalName] = proposalPath.split(':'); - return { - ...agoricProposal, - proposalIdentifier, - proposalName, - }; -} - -export function readProposals(): ProposalInfo[] { - const proposalPaths = fs - .readdirSync('./proposals', { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) // omit files - .map(dirent => dirent.name) - .filter(name => name.includes(':')); // omit node_modules - return proposalPaths.map(readInfo); -} - -export const readOneProposal = (match: string) => { - const allProposals = readProposals(); - - const proposals = allProposals.filter(p => p.proposalName.includes(match)); - - assert(proposals.length > 0, 'no proposals match'); - assert(proposals.length === 1, 'too many proposals match'); - return proposals[0]; -}; - -export function lastPassedProposal(proposals: ProposalInfo[]): ProposalInfo { - // @ts-expect-error use es2023; findLast is available in Node 18 - const last = proposals.findLast(p => p.proposalIdentifier.match(/^\d/)); - assert(last, 'no passed proposals'); - return last; -} - -export function imageNameForProposal( - proposal: ProposalCommon, - stage: 'test' | 'eval', -) { - const target = `${stage}-${proposal.proposalName}`; - return { - name: `${repository}:${target}`, - target, - }; -} diff --git a/debugTestImage.ts b/debugTestImage.ts deleted file mode 100755 index 69ef8f1b..00000000 --- a/debugTestImage.ts +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env tsx -/** - * @file like runTestImages.ts, but for a single proposal, - * and leaves the chain running - */ -import { execSync } from 'node:child_process'; -import { parseArgs } from 'node:util'; -import { imageNameForProposal, readOneProposal } from './common'; - -const options = { - match: { short: 'm', type: 'string' }, -} as const; -const { values } = parseArgs({ options }); - -const proposal = readOneProposal(values.match!); -const { name } = imageNameForProposal(proposal, 'test'); - -console.log( - ` -Starting chain of test image for proposal ${proposal.proposalName} - -To get an interactive shell in the container, use an IDE feature like "Attach Shell" or this command:' - - docker exec -ti $(docker ps -q -f ancestor=${name}) bash - -And within that shell: - cd /usr/src/proposals/ && ./test.sh - -The 'proposals' path is mounted in the container so your edits will appear there. -`, -); - -// start the chain, with the repo mounted at /usr/src -const cmd = `docker run --mount type=bind,src=./proposals,dst=/usr/src/proposals -it --entrypoint /usr/src/upgrade-test-scripts/start_agd.sh ${name}`; -execSync(cmd, { stdio: 'inherit' }); diff --git a/makeDockerfile.ts b/makeDockerfile.ts deleted file mode 100755 index 6a6a9b06..00000000 --- a/makeDockerfile.ts +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env tsx -// @ts-check - -import assert from 'node:assert'; -import fs from 'node:fs'; -import { lastPassedProposal, readProposals } from './common'; -import type { - ProposalInfo, - SoftwareUpgradeProposal, - CoreEvalProposal, -} from './common'; - -const agZeroUpgrade = 'agoric-upgrade-7-2'; - -/** - * Templates for Dockerfile stages - */ -const stage = { - /** - * ag0, start of the chain - */ - START(proposalName: string, to: string) { - return ` -## START -# on ${agZeroUpgrade}, with upgrade to ${to} -FROM ghcr.io/agoric/ag0:${agZeroUpgrade} as prepare-${proposalName} -ENV UPGRADE_TO=${to} THIS_NAME=${agZeroUpgrade} - -# put env functions into shell environment -RUN echo '. /usr/src/upgrade-test-scripts/env_setup.sh' >> ~/.bashrc - -COPY --link --chmod=755 ./upgrade-test-scripts/env_setup.sh ./upgrade-test-scripts/start_ag0.sh /usr/src/upgrade-test-scripts/ -SHELL ["/bin/bash", "-c"] -# this is the only layer that starts ag0 -RUN /usr/src/upgrade-test-scripts/start_ag0.sh -`; - }, - /** - * Prepare an upgrade handler to run. - * - * - Submit the software-upgrade proposal for planName and run until upgradeHeight, leaving the state-dir ready for next agd. - */ - PREPARE( - { planName, proposalName }: SoftwareUpgradeProposal, - lastProposal: ProposalInfo, - ) { - return ` -# PREPARE ${proposalName} - -# upgrading to ${planName} -FROM use-${lastProposal.proposalName} as prepare-${proposalName} -ENV UPGRADE_TO=${planName} -# base is a fresh sdk image so copy these supports -COPY --link --chmod=755 ./upgrade-test-scripts/env_setup.sh ./upgrade-test-scripts/start_to_to.sh /usr/src/upgrade-test-scripts/ - -WORKDIR /usr/src/upgrade-test-scripts -SHELL ["/bin/bash", "-c"] -RUN ./start_to_to.sh -`; - }, - /** - * Execute a prepared upgrade. - * - Start agd with the SDK that has the upgradeHandler - * - Run any core-evals associated with the proposal (either the ones specified in prepare, or straight from the proposal) - */ - EXECUTE({ proposalName, planName, sdkImageTag }: SoftwareUpgradeProposal) { - return ` -# EXECUTE ${proposalName} -FROM ghcr.io/agoric/agoric-sdk:${sdkImageTag} as execute-${proposalName} -ENV THIS_NAME=${planName} - -# base is a fresh sdk image so copy these supports -COPY --link --chmod=755 ./upgrade-test-scripts/env_setup.sh ./upgrade-test-scripts/start_to_to.sh /usr/src/upgrade-test-scripts/ - -COPY --link --from=prepare-${proposalName} /root/.agoric /root/.agoric - -WORKDIR /usr/src/upgrade-test-scripts -SHELL ["/bin/bash", "-c"] -RUN ./start_to_to.sh -`; - }, - /** - * Run a core-eval proposal - * - Run the core-eval scripts from the proposal. They are only guaranteed to have started, not completed. - */ - EVAL( - { proposalIdentifier, proposalName }: CoreEvalProposal, - lastProposal: ProposalInfo, - ) { - return ` -# EVAL ${proposalName} -FROM use-${lastProposal.proposalName} as eval-${proposalName} - -COPY --link --chmod=755 ./proposals/${proposalIdentifier}:${proposalName} /usr/src/proposals/${proposalIdentifier}:${proposalName} - -WORKDIR /usr/src/upgrade-test-scripts - -# install using global cache -COPY --link ./upgrade-test-scripts/install_deps.sh /usr/src/upgrade-test-scripts/ -RUN --mount=type=cache,target=/root/.yarn ./install_deps.sh ${proposalIdentifier}:${proposalName} - -COPY --link --chmod=755 ./upgrade-test-scripts/run_eval.sh /usr/src/upgrade-test-scripts/ -SHELL ["/bin/bash", "-c"] -RUN ./run_eval.sh ${proposalIdentifier}:${proposalName} -`; - }, - /** - * Use the proposal - * - * - Perform any mutations that should be part of chain history - */ - USE({ proposalName, proposalIdentifier, type }: ProposalInfo) { - const previousStage = - type === 'Software Upgrade Proposal' ? 'execute' : 'eval'; - return ` -# USE ${proposalName} -FROM ${previousStage}-${proposalName} as use-${proposalName} - -COPY --link --chmod=755 ./proposals/${proposalIdentifier}:${proposalName} /usr/src/proposals/${proposalIdentifier}:${proposalName} - -WORKDIR /usr/src/upgrade-test-scripts - -# XXX for 'lib' dir for JS modules -COPY --link ./upgrade-test-scripts/lib /usr/src/upgrade-test-scripts/lib -# TODO remove network dependencies in stages -# install using global cache -COPY --link ./upgrade-test-scripts/install_deps.sh /usr/src/upgrade-test-scripts/ -RUN --mount=type=cache,target=/root/.yarn ./install_deps.sh ${proposalIdentifier}:${proposalName} - -COPY --link --chmod=755 ./upgrade-test-scripts/run_use.sh /usr/src/upgrade-test-scripts/ -SHELL ["/bin/bash", "-c"] -RUN ./run_use.sh ${proposalIdentifier}:${proposalName} -`; - }, - /** - * Generate image than can test the proposal - * - * - Run with the image of the last "use" - * - Run tests of the proposal - * - * Needs to be an image to have access to the SwingSet db. run it with `docker run --rm` to not make the container ephemeral. - */ - TEST({ proposalName, proposalIdentifier }: ProposalInfo) { - return ` -# TEST ${proposalName} -FROM use-${proposalName} as test-${proposalName} - -WORKDIR /usr/src/upgrade-test-scripts - -# install using global cache -COPY --link ./upgrade-test-scripts/install_deps.sh /usr/src/upgrade-test-scripts/ -RUN --mount=type=cache,target=/root/.yarn ./install_deps.sh ${proposalIdentifier}:${proposalName} - -# copy run_test for this entrypoint and start_agd for optional debugging -COPY --link --chmod=755 ./upgrade-test-scripts/run_test.sh ./upgrade-test-scripts/start_agd.sh /usr/src/upgrade-test-scripts/ -SHELL ["/bin/bash", "-c"] -ENTRYPOINT ./run_test.sh ${proposalIdentifier}:${proposalName} -`; - }, - /** - * The last target in the file, for untargeted `docker build` - */ - DEFAULT(lastProposal: ProposalInfo) { - return ` -# DEFAULT -FROM use-${lastProposal.proposalName} - -COPY --link --chmod=755 ./upgrade-test-scripts/start_agd.sh /usr/src/upgrade-test-scripts/ - -WORKDIR /usr/src/upgrade-test-scripts -SHELL ["/bin/bash", "-c"] -ENTRYPOINT ./start_agd.sh -`; - }, -}; - -// Each stage tests something about the left argument and prepare an upgrade to the right side (by passing the proposal and halting the chain.) -// The upgrade doesn't happen until the next stage begins executing. -const blocks: string[] = []; - -const allProposals = readProposals(); -let previousProposal: ProposalInfo | null = null; -for (const proposal of allProposals) { - // UNTIL region support https://github.com/microsoft/vscode-docker/issues/230 - blocks.push( - `#----------------\n# ${proposal.proposalName}\n#----------------`, - ); - - if (proposal.type === '/agoric.swingset.CoreEvalProposal') { - blocks.push(stage.EVAL(proposal, previousProposal!)); - } else if (proposal.type === 'Software Upgrade Proposal') { - // handle the first proposal specially - if (previousProposal) { - blocks.push(stage.PREPARE(proposal, previousProposal)); - } else { - blocks.push(stage.START(proposal.proposalName, proposal.planName)); - } - blocks.push(stage.EXECUTE(proposal)); - } - - // The stages must be output in dependency order because if the builder finds a FROM - // that it hasn't built yet, it will search for it in the registry. But it won't be there! - blocks.push(stage.USE(proposal)); - blocks.push(stage.TEST(proposal)); - previousProposal = proposal; -} -blocks.push(stage.DEFAULT(lastPassedProposal(allProposals))); - -export function refreshDockerfile() { - const contents = blocks.join('\n'); - fs.writeFileSync('Dockerfile', contents); -} - -if (require.main === module) { - refreshDockerfile(); -} diff --git a/package.json b/package.json new file mode 100644 index 00000000..b65e3f93 --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "private": true, + "scripts": { + "build": "echo Use synthetic-chain to build proposal images", + "test": "echo Use synthetic-chain to test proposal images" + }, + "dependencies": { + "@agoric/synthetic-chain": "file:/opt/agoric/agoric-sdk/packages/synthetic-chain" + }, + "license": "Apache-2.0" +} diff --git a/runTestImages.ts b/runTestImages.ts deleted file mode 100755 index 786a7416..00000000 --- a/runTestImages.ts +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env tsx - -import { parseArgs } from 'node:util'; -import { execSync } from 'node:child_process'; -import { imageNameForProposal, readProposals } from './common'; - -const options = { - match: { short: 'm', type: 'string' }, -} as const; -const { values } = parseArgs({ options }); - -const { match } = values; - -const allProposals = readProposals(); - -const proposals = match - ? allProposals.filter(p => p.proposalName.includes(match)) - : allProposals; - -for (const proposal of proposals) { - console.log(`Running test image for proposal ${proposal.proposalName}`); - const { name } = imageNameForProposal(proposal, 'test'); - // 'rm' to remove the container when it exits - const cmd = `docker run --rm ${name}`; - execSync(cmd, { stdio: 'inherit' }); -} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..a9b8d87c --- /dev/null +++ b/yarn.lock @@ -0,0 +1,192 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@agoric/synthetic-chain@file:../agoric-sdk/packages/synthetic-chain": + version "0.0.1-alpha" + dependencies: + tsx "^3.12.8" + +"@esbuild/android-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" + integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ== + +"@esbuild/android-arm@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682" + integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw== + +"@esbuild/android-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2" + integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg== + +"@esbuild/darwin-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1" + integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== + +"@esbuild/darwin-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d" + integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ== + +"@esbuild/freebsd-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54" + integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw== + +"@esbuild/freebsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e" + integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ== + +"@esbuild/linux-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0" + integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA== + +"@esbuild/linux-arm@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0" + integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg== + +"@esbuild/linux-ia32@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7" + integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA== + +"@esbuild/linux-loong64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d" + integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg== + +"@esbuild/linux-mips64el@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231" + integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ== + +"@esbuild/linux-ppc64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb" + integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA== + +"@esbuild/linux-riscv64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6" + integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A== + +"@esbuild/linux-s390x@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071" + integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ== + +"@esbuild/linux-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338" + integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== + +"@esbuild/netbsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1" + integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A== + +"@esbuild/openbsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae" + integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg== + +"@esbuild/sunos-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d" + integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ== + +"@esbuild/win32-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9" + integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg== + +"@esbuild/win32-ia32@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102" + integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g== + +"@esbuild/win32-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" + integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +esbuild@~0.18.20: + version "0.18.20" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6" + integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== + optionalDependencies: + "@esbuild/android-arm" "0.18.20" + "@esbuild/android-arm64" "0.18.20" + "@esbuild/android-x64" "0.18.20" + "@esbuild/darwin-arm64" "0.18.20" + "@esbuild/darwin-x64" "0.18.20" + "@esbuild/freebsd-arm64" "0.18.20" + "@esbuild/freebsd-x64" "0.18.20" + "@esbuild/linux-arm" "0.18.20" + "@esbuild/linux-arm64" "0.18.20" + "@esbuild/linux-ia32" "0.18.20" + "@esbuild/linux-loong64" "0.18.20" + "@esbuild/linux-mips64el" "0.18.20" + "@esbuild/linux-ppc64" "0.18.20" + "@esbuild/linux-riscv64" "0.18.20" + "@esbuild/linux-s390x" "0.18.20" + "@esbuild/linux-x64" "0.18.20" + "@esbuild/netbsd-x64" "0.18.20" + "@esbuild/openbsd-x64" "0.18.20" + "@esbuild/sunos-x64" "0.18.20" + "@esbuild/win32-arm64" "0.18.20" + "@esbuild/win32-ia32" "0.18.20" + "@esbuild/win32-x64" "0.18.20" + +fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +get-tsconfig@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.2.tgz#0dcd6fb330391d46332f4c6c1bf89a6514c2ddce" + integrity sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A== + dependencies: + resolve-pkg-maps "^1.0.0" + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +source-map-support@^0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +tsx@^3.12.8: + version "3.14.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-3.14.0.tgz#be6e2176b6f210fe8f48124fb6e22e0f075e927b" + integrity sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg== + dependencies: + esbuild "~0.18.20" + get-tsconfig "^4.7.2" + source-map-support "^0.5.21" + optionalDependencies: + fsevents "~2.3.3"