From 4d8e37177bb8fb7ddc0a187549a28b1ce7810ce6 Mon Sep 17 00:00:00 2001 From: Tim Griesser Date: Sat, 2 Jul 2022 16:08:16 -0400 Subject: [PATCH] feat: better esm support, remove top-level node imports (#1112) * test for esm/esbuild use of nexus * refactor: add nodeImports, remove top-level references * Don't minify the esbuild test script * A bit more explicit of a check on the process being node --- .gitignore | 1 + package.json | 1 + src/node.ts | 8 +++ src/typegenAutoConfig.ts | 12 ++-- src/typegenFormatPrettier.ts | 4 +- src/typegenMetadata.ts | 26 +++----- src/typegenUtils.ts | 94 ++++++++++++++------------ src/utils.ts | 24 +++---- tests/esm/esm-entry.js | 16 +++++ tests/esm/standalone.spec.ts | 30 +++++++++ yarn.lock | 126 +++++++++++++++++++++++++++++++++++ 11 files changed, 263 insertions(+), 79 deletions(-) create mode 100644 src/node.ts create mode 100644 tests/esm/esm-entry.js create mode 100644 tests/esm/standalone.spec.ts diff --git a/.gitignore b/.gitignore index 7961131e..d4153ece 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ examples/*/dist website/static/playground-dist yarn-error.log coverage/* +tests/esm/out/ \ No newline at end of file diff --git a/package.json b/package.json index cd6f3f5a..cc45544b 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "@types/prettier": "^1.18.3", "@typescript-eslint/eslint-plugin": "2.7.0", "dripip": "^0.10.0", + "esbuild": "^0.14.48", "eslint": "^6.6.0", "get-port": "^5.1.1", "graphql": "^16.3.0", diff --git a/src/node.ts b/src/node.ts new file mode 100644 index 00000000..bddbe25d --- /dev/null +++ b/src/node.ts @@ -0,0 +1,8 @@ +export function nodeImports() { + const fs = require('fs') as typeof import('fs') + const path = require('path') as typeof import('path') + return { + fs, + path, + } +} diff --git a/src/typegenAutoConfig.ts b/src/typegenAutoConfig.ts index 3a31890a..a39cd853 100644 --- a/src/typegenAutoConfig.ts +++ b/src/typegenAutoConfig.ts @@ -1,8 +1,8 @@ import { GraphQLNamedType, GraphQLSchema, isOutputType } from 'graphql' -import * as path from 'path' import type { TypegenInfo } from './builder' import type { TypingImport } from './definitions/_types' import { TYPEGEN_HEADER } from './lang' +import { nodeImports } from './node' import { getOwnPackage, log, objValues, relativePathTo, typeScriptFileExtension } from './utils' /** Any common types / constants that would otherwise be circular-imported */ @@ -129,16 +129,12 @@ export function typegenAutoConfig(options: SourceTypesConfigOptions, contextType } }) + const path = nodeImports().path const typeSources = await Promise.all( options.modules.map(async (source) => { // Keeping all of this in here so if we don't have any sources // e.g. in the Playground, it doesn't break things. - // Yeah, this doesn't exist in Node 6, but since this is a new - // lib and Node 6 is close to EOL so if you really need it, open a PR :) - const fs = require('fs') as typeof import('fs') - const util = require('util') as typeof import('util') - const readFile = util.promisify(fs.readFile) const { module: pathOrModule, glob = true, onlyTypes, alias, typeMatch } = source if (path.isAbsolute(pathOrModule) && path.extname(pathOrModule) !== '.ts') { return console.warn( @@ -154,7 +150,7 @@ export function typegenAutoConfig(options: SourceTypesConfigOptions, contextType if (path.extname(resolvedPath) !== '.ts') { resolvedPath = findTypingForFile(resolvedPath, pathOrModule) } - fileContents = await readFile(resolvedPath, 'utf-8') + fileContents = String(await nodeImports().fs.promises.readFile(resolvedPath, 'utf-8')) } catch (e) { if (e instanceof Error && e.message.indexOf('Cannot find module') !== -1) { console.error(`GraphQL Nexus: Unable to find file or module ${pathOrModule}, skipping`) @@ -277,7 +273,7 @@ export function typegenAutoConfig(options: SourceTypesConfigOptions, contextType function findTypingForFile(absolutePath: string, pathOrModule: string) { // First try to find the "d.ts" adjacent to the file try { - const typeDefPath = absolutePath.replace(path.extname(absolutePath), '.d.ts') + const typeDefPath = absolutePath.replace(nodeImports().path.extname(absolutePath), '.d.ts') require.resolve(typeDefPath) return typeDefPath } catch (e) { diff --git a/src/typegenFormatPrettier.ts b/src/typegenFormatPrettier.ts index 68a22831..f75a244b 100644 --- a/src/typegenFormatPrettier.ts +++ b/src/typegenFormatPrettier.ts @@ -1,5 +1,5 @@ -import * as path from 'path' import type * as Prettier from 'prettier' +import { nodeImports } from './node' export type TypegenFormatFn = (content: string, type: 'types' | 'schema') => string | Promise @@ -22,6 +22,8 @@ export function typegenFormatPrettier(prettierConfig: string | object): TypegenF let prettierConfigResolved: Prettier.Options + const path = nodeImports().path + if (typeof prettierConfig === 'string') { /* istanbul ignore if */ if (!path.isAbsolute(prettierConfig)) { diff --git a/src/typegenMetadata.ts b/src/typegenMetadata.ts index 6feee585..336ab046 100644 --- a/src/typegenMetadata.ts +++ b/src/typegenMetadata.ts @@ -1,9 +1,9 @@ import { GraphQLSchema, lexicographicSortSchema } from 'graphql' -import * as path from 'path' import type { BuilderConfigInput, TypegenInfo } from './builder' import type { ConfiguredTypegen } from './core' import type { NexusGraphQLSchema } from './definitions/_types' import { SDL_HEADER, TYPEGEN_HEADER } from './lang' +import { nodeImports } from './node' import { printSchemaWithDirectives } from './printSchemaWithDirectives' import { typegenAutoConfig } from './typegenAutoConfig' import { typegenFormatPrettier } from './typegenFormatPrettier' @@ -75,30 +75,26 @@ export class TypegenMetadata { } async writeFile(type: 'schema' | 'types', output: string, filePath: string) { - if (typeof filePath !== 'string' || !path.isAbsolute(filePath)) { + if (typeof filePath !== 'string' || !nodeImports().path.isAbsolute(filePath)) { return Promise.reject( new Error(`Expected an absolute path to output the Nexus ${type}, saw ${filePath}`) ) } - const fs = require('fs') as typeof import('fs') - const util = require('util') as typeof import('util') - const [readFile, writeFile, removeFile, mkdir] = [ - util.promisify(fs.readFile), - util.promisify(fs.writeFile), - util.promisify(fs.unlink), - util.promisify(fs.mkdir), - ] + const fs = nodeImports().fs const formattedOutput = typeof this.config.formatTypegen === 'function' ? await this.config.formatTypegen(output, type) : output const content = this.config.prettierConfig ? await typegenFormatPrettier(this.config.prettierConfig)(formattedOutput, type) : formattedOutput - const [toSave, existing] = await Promise.all([content, readFile(filePath, 'utf8').catch(() => '')]) + const [toSave, existing] = await Promise.all([ + content, + fs.promises.readFile(filePath, 'utf8').catch(() => ''), + ]) if (toSave !== existing) { - const dirPath = path.dirname(filePath) + const dirPath = nodeImports().path.dirname(filePath) try { - await mkdir(dirPath, { recursive: true }) + await fs.promises.mkdir(dirPath, { recursive: true }) } catch (e) { if (e.code !== 'EEXIST') { throw e @@ -108,14 +104,14 @@ export class TypegenMetadata { // apparently. See issue motivating this logic here: // https://github.com/graphql-nexus/schema/issues/247. try { - await removeFile(filePath) + await fs.promises.unlink(filePath) } catch (e) { /* istanbul ignore next */ if (e.code !== 'ENOENT' && e.code !== 'ENOTDIR') { throw e } } - return writeFile(filePath, toSave) + return fs.promises.writeFile(filePath, toSave) } } diff --git a/src/typegenUtils.ts b/src/typegenUtils.ts index 364c1122..0dc79fce 100644 --- a/src/typegenUtils.ts +++ b/src/typegenUtils.ts @@ -1,65 +1,75 @@ -import * as path from 'path' import type { BuilderConfigInput } from './builder' import type { ConfiguredTypegen } from './core' +import { nodeImports } from './node' import type { TypegenMetadataConfig } from './typegenMetadata' import { assertAbsolutePath, getOwnPackage, isProductionStage } from './utils' /** Normalizes the builder config into the config we need for typegen */ export function resolveTypegenConfig(config: BuilderConfigInput): TypegenMetadataConfig { - const { - outputs, - shouldGenerateArtifacts = Boolean(!process.env.NODE_ENV || process.env.NODE_ENV !== 'production'), - ...rest - } = config + const { outputs, shouldGenerateArtifacts = defaultShouldGenerateArtifacts(), ...rest } = config - const defaultSDLFilePath = path.join(process.cwd(), 'schema.graphql') + function getOutputPaths() { + const defaultSDLFilePath = nodeImports().path.join(process.cwd(), 'schema.graphql') - let typegenFilePath: ConfiguredTypegen | null = null - let sdlFilePath: string | null = null + let typegenFilePath: ConfiguredTypegen | null = null + let sdlFilePath: string | null = null - if (outputs === undefined) { - if (isProductionStage()) { - sdlFilePath = defaultSDLFilePath - } - } else if (outputs === true) { - sdlFilePath = defaultSDLFilePath - } else if (typeof outputs === 'object') { - if (outputs.schema === true) { + if (outputs === undefined) { + if (isProductionStage()) { + sdlFilePath = defaultSDLFilePath + } + } else if (outputs === true) { sdlFilePath = defaultSDLFilePath - } else if (typeof outputs.schema === 'string') { - sdlFilePath = assertAbsolutePath(outputs.schema, 'outputs.schema') - } else if (outputs.schema === undefined && isProductionStage()) { - } - // handle typegen configuration - if (typeof outputs.typegen === 'string') { - typegenFilePath = { - outputPath: assertAbsolutePath(outputs.typegen, 'outputs.typegen'), + } else if (typeof outputs === 'object') { + if (outputs.schema === true) { + sdlFilePath = defaultSDLFilePath + } else if (typeof outputs.schema === 'string') { + sdlFilePath = assertAbsolutePath(outputs.schema, 'outputs.schema') + } else if (outputs.schema === undefined && isProductionStage()) { } - } else if (typeof outputs.typegen === 'object') { - typegenFilePath = { - ...outputs.typegen, - outputPath: assertAbsolutePath(outputs.typegen.outputPath, 'outputs.typegen.outputPath'), - } as ConfiguredTypegen - if (outputs.typegen.globalsPath) { - typegenFilePath.globalsPath = assertAbsolutePath( - outputs.typegen.globalsPath, - 'outputs.typegen.globalsPath' - ) + // handle typegen configuration + if (typeof outputs.typegen === 'string') { + typegenFilePath = { + outputPath: assertAbsolutePath(outputs.typegen, 'outputs.typegen'), + } + } else if (typeof outputs.typegen === 'object') { + typegenFilePath = { + ...outputs.typegen, + outputPath: assertAbsolutePath(outputs.typegen.outputPath, 'outputs.typegen.outputPath'), + } as ConfiguredTypegen + if (outputs.typegen.globalsPath) { + typegenFilePath.globalsPath = assertAbsolutePath( + outputs.typegen.globalsPath, + 'outputs.typegen.globalsPath' + ) + } } + } else if (outputs !== false) { + console.warn( + `You should specify a configuration value for outputs in Nexus' makeSchema. ` + + `Provide one to remove this warning.` + ) + } + return { + typegenFilePath, + sdlFilePath, } - } else if (outputs !== false) { - console.warn( - `You should specify a configuration value for outputs in Nexus' makeSchema. ` + - `Provide one to remove this warning.` - ) } return { ...rest, nexusSchemaImportId: getOwnPackage().name, outputs: { - typegen: shouldGenerateArtifacts ? typegenFilePath : null, - schema: shouldGenerateArtifacts ? sdlFilePath : null, + typegen: shouldGenerateArtifacts ? getOutputPaths().typegenFilePath : null, + schema: shouldGenerateArtifacts ? getOutputPaths().sdlFilePath : null, }, } } + +function defaultShouldGenerateArtifacts() { + return Boolean( + typeof process === 'object' && + typeof process.cwd === 'function' && + (!process.env.NODE_ENV || process.env.NODE_ENV !== 'production') + ) +} diff --git a/src/utils.ts b/src/utils.ts index 73895fc8..2459ae2d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,3 @@ -import * as fs from 'fs' import { GraphQLEnumType, GraphQLInputObjectType, @@ -22,7 +21,6 @@ import { isWrappingType, specifiedScalarTypes, } from 'graphql' -import * as Path from 'path' import { decorateType } from './definitions/decorateType' import { isNexusMetaType, NexusMetaType, resolveNexusMetaType } from './definitions/nexusMeta' import { @@ -42,6 +40,7 @@ import { TypingImport, withNexusSymbol, } from './definitions/_types' +import { nodeImports } from './node' export const isInterfaceField = (type: GraphQLObjectType, fieldName: string) => { return type.getInterfaces().some((i) => Boolean(i.getFields()[fieldName])) @@ -150,7 +149,7 @@ export function eachObj(obj: Record, iter: (val: T, key: string, i export const isObject = (obj: any): boolean => obj !== null && typeof obj === 'object' export const assertAbsolutePath = (pathName: string, property: string) => { - if (!Path.isAbsolute(pathName)) { + if (!nodeImports().path.isAbsolute(pathName)) { throw new Error(`Expected path for "${property}" to be an absolute path, saw "${pathName}"`) } return pathName @@ -221,7 +220,7 @@ export function isPromiseLike(value: any): value is PromiseLike { export const typeScriptFileExtension = /(\.d)?\.ts$/ function makeRelativePathExplicitlyRelative(path: string) { - if (Path.isAbsolute(path)) return path + if (nodeImports().path.isAbsolute(path)) return path if (path.startsWith('./')) return path return `./${path}` } @@ -243,6 +242,7 @@ export function formatPathForModuleImport(path: string) { } export function relativePathTo(absolutePath: string, fromPath: string): string { + const Path = nodeImports().path const filename = Path.basename(absolutePath) const relative = Path.relative(Path.dirname(fromPath), Path.dirname(absolutePath)) return formatPathForModuleImport(Path.join(relative, filename)) @@ -477,20 +477,18 @@ export function casesHandled(x: never): never { throw new Error(`A case was not handled for value: "${x}"`) } -/** Quickly log objects */ -export function dump(x: any) { - console.log(require('util').inspect(x, { depth: null })) -} - function isNodeModule(path: string) { // Avoid treating absolute windows paths as Node packages e.g. D:/a/b/c - return !Path.isAbsolute(path) && /^([A-z0-9@])/.test(path) + return !nodeImports().path.isAbsolute(path) && /^([A-z0-9@])/.test(path) } export function resolveImportPath(rootType: TypingImport, typeName: string, outputPath: string) { const rootTypePath = rootType.module - if (typeof rootTypePath !== 'string' || (!Path.isAbsolute(rootTypePath) && !isNodeModule(rootTypePath))) { + if ( + typeof rootTypePath !== 'string' || + (!nodeImports().path.isAbsolute(rootTypePath) && !isNodeModule(rootTypePath)) + ) { throw new Error( `Expected an absolute path or Node package for the root typing path of the type "${typeName}", saw "${rootTypePath}"` ) @@ -502,7 +500,7 @@ export function resolveImportPath(rootType: TypingImport, typeName: string, outp } catch (e) { throw new Error(`Module "${rootTypePath}" for the type "${typeName}" does not exist`) } - } else if (!fs.existsSync(rootTypePath)) { + } else if (!nodeImports().fs.existsSync(rootTypePath)) { throw new Error(`Root typing path "${rootTypePath}" for the type "${typeName}" does not exist`) } @@ -510,7 +508,7 @@ export function resolveImportPath(rootType: TypingImport, typeName: string, outp return rootTypePath } - if (Path.isAbsolute(rootTypePath)) { + if (nodeImports().path.isAbsolute(rootTypePath)) { return relativePathTo(rootTypePath, outputPath) } diff --git a/tests/esm/esm-entry.js b/tests/esm/esm-entry.js new file mode 100644 index 00000000..09c6ef0b --- /dev/null +++ b/tests/esm/esm-entry.js @@ -0,0 +1,16 @@ +import { GraphQLSchema } from 'graphql' +import { makeSchema, queryType } from '../../dist' + +const schema = makeSchema({ + types: [ + queryType({ + definition(t) { + t.boolean('ok') + }, + }), + ], +}) + +if (!(schema instanceof GraphQLSchema)) { + throw new Error('Not a schema') +} diff --git a/tests/esm/standalone.spec.ts b/tests/esm/standalone.spec.ts new file mode 100644 index 00000000..73519350 --- /dev/null +++ b/tests/esm/standalone.spec.ts @@ -0,0 +1,30 @@ +import esbuild from 'esbuild' +import path from 'path' +import vm from 'vm' +import fs from 'fs' + +describe('standalone esm', () => { + it('should build the esbuild', async () => { + const out = await esbuild.build({ + bundle: true, + format: 'esm', + target: 'esnext', + // minify: true, + mainFields: ['module', 'main'], + external: ['path', 'fs', 'prettier'], + entryPoints: [path.join(__dirname, 'esm-entry.js')], + outdir: path.join(__dirname, 'out'), + outExtension: { '.js': '.mjs' }, + metafile: true, + }) + + const context = vm.createContext() + // @ts-ignore + const outPath = path.join(__dirname, 'out', 'esm-entry.mjs') + fs.writeFileSync(path.join(path.dirname(outPath), 'meta.json'), JSON.stringify(out.metafile)) + const script = new vm.Script(fs.readFileSync(outPath, 'utf8'), { + filename: outPath, + }) + script.runInNewContext(context) + }) +}) diff --git a/yarn.lock b/yarn.lock index 249ef938..74c49116 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2520,6 +2520,132 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +esbuild-android-64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz#7e6394a0e517f738641385aaf553c7e4fb6d1ae3" + integrity sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg== + +esbuild-android-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz#6877566be0f82dd5a43030c0007d06ece7f7c02f" + integrity sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g== + +esbuild-darwin-64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz#ea3caddb707d88f844b1aa1dea5ff3b0a71ef1fd" + integrity sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA== + +esbuild-darwin-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz#4e5eaab54df66cc319b76a2ac0e8af4e6f0d9c2f" + integrity sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA== + +esbuild-freebsd-64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz#47b5abc7426eae66861490ffbb380acc67af5b15" + integrity sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA== + +esbuild-freebsd-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz#e8c54c8637cd44feed967ea12338b0a4da3a7b11" + integrity sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw== + +esbuild-linux-32@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz#229cf3246de2b7937c3ac13fac622d4d7a1344c5" + integrity sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ== + +esbuild-linux-64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz#7c0e7226c02c42aacc5656c36977493dc1e96c4f" + integrity sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug== + +esbuild-linux-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz#0af1eda474b5c6cc0cace8235b74d0cb8fcf57a7" + integrity sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw== + +esbuild-linux-arm@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz#de4d1fa6b77cdcd00e2bb43dd0801e4680f0ab52" + integrity sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw== + +esbuild-linux-mips64le@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz#822c1778495f7868e990d4da47ad7281df28fd15" + integrity sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA== + +esbuild-linux-ppc64le@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz#55de0a9ec4a48fedfe82a63e083164d001709447" + integrity sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ== + +esbuild-linux-riscv64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz#cd2b7381880b2f4b21a5a598fb673492120f18a5" + integrity sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA== + +esbuild-linux-s390x@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz#4b319eca2a5c64637fc7397ffbd9671719cdb6bf" + integrity sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g== + +esbuild-netbsd-64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz#c27cde8b5cb55dcc227943a18ab078fb98d0adbf" + integrity sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw== + +esbuild-openbsd-64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz#af5ab2d1cb41f09064bba9465fc8bf1309150df1" + integrity sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA== + +esbuild-sunos-64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz#db3ae20526055cf6fd5c4582676233814603ac54" + integrity sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA== + +esbuild-windows-32@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz#021ffceb0a3f83078262870da88a912293c57475" + integrity sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg== + +esbuild-windows-64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz#a4d3407b580f9faac51f61eec095fa985fb3fee4" + integrity sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA== + +esbuild-windows-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz#762c0562127d8b09bfb70a3c816460742dd82880" + integrity sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g== + +esbuild@^0.14.48: + version "0.14.48" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.48.tgz#da5d8d25cd2d940c45ea0cfecdca727f7aee2b85" + integrity sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA== + optionalDependencies: + esbuild-android-64 "0.14.48" + esbuild-android-arm64 "0.14.48" + esbuild-darwin-64 "0.14.48" + esbuild-darwin-arm64 "0.14.48" + esbuild-freebsd-64 "0.14.48" + esbuild-freebsd-arm64 "0.14.48" + esbuild-linux-32 "0.14.48" + esbuild-linux-64 "0.14.48" + esbuild-linux-arm "0.14.48" + esbuild-linux-arm64 "0.14.48" + esbuild-linux-mips64le "0.14.48" + esbuild-linux-ppc64le "0.14.48" + esbuild-linux-riscv64 "0.14.48" + esbuild-linux-s390x "0.14.48" + esbuild-netbsd-64 "0.14.48" + esbuild-openbsd-64 "0.14.48" + esbuild-sunos-64 "0.14.48" + esbuild-windows-32 "0.14.48" + esbuild-windows-64 "0.14.48" + esbuild-windows-arm64 "0.14.48" + escape-goat@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"