diff --git a/.changeset/gentle-cheetahs-carry.md b/.changeset/gentle-cheetahs-carry.md new file mode 100644 index 00000000..e9279d20 --- /dev/null +++ b/.changeset/gentle-cheetahs-carry.md @@ -0,0 +1,5 @@ +--- +"@hyperdx/api": patch +--- + +feat: bundle api via esbuild for smaller image distribution diff --git a/docker/hyperdx/Dockerfile b/docker/hyperdx/Dockerfile index 0a41a6be..05c8a9b0 100644 --- a/docker/hyperdx/Dockerfile +++ b/docker/hyperdx/Dockerfile @@ -13,8 +13,6 @@ ARG OTEL_COLLECTOR_VERSION=0.126.0 ARG OTEL_COLLECTOR_OPAMPSUPERVISOR_VERSION=0.126.0 # base ############################################################################################# -# == Clickhouse/Base Image == -FROM clickhouse/clickhouse-server:${CLICKHOUSE_VERSION}-alpine AS clickhouse_base # == Otel Collector Image == FROM otel/opentelemetry-collector-contrib:${OTEL_COLLECTOR_VERSION} AS otel_collector_base FROM otel/opentelemetry-collector-opampsupervisor:${OTEL_COLLECTOR_OPAMPSUPERVISOR_VERSION} AS otel_collector_opampsupervisor_base @@ -51,8 +49,6 @@ ENV NEXT_TELEMETRY_DISABLED 1 ENV NEXT_OUTPUT_STANDALONE true ENV NEXT_PUBLIC_IS_LOCAL_MODE false RUN npx nx run-many --target=build --projects=@hyperdx/common-utils,@hyperdx/api,@hyperdx/app -RUN rm -rf node_modules && yarn workspaces focus @hyperdx/api --production - # prod ############################################################################################ FROM node:${NODE_VERSION}-alpine AS prod @@ -69,10 +65,7 @@ USER node # Set up API and App WORKDIR /app -COPY --chown=node:node --from=builder /app/node_modules ./node_modules -COPY --chown=node:node --from=builder /app/packages/api/build ./packages/api/build -COPY --chown=node:node --from=builder /app/packages/common-utils/dist ./packages/common-utils/dist -COPY --chown=node:node --from=node_base /app/packages/common-utils/node_modules ./packages/common-utils/node_modules +COPY --chown=node:node --from=builder /app/packages/api/dist ./packages/api COPY --chown=node:node --from=builder /app/packages/app/.next/standalone ./packages/app COPY --chown=node:node --from=builder /app/packages/app/.next/static ./packages/app/packages/app/.next/static COPY --chown=node:node --from=builder /app/packages/app/public ./packages/app/packages/app/public @@ -82,13 +75,12 @@ COPY --chown=node:node --from=hyperdx ./entry.prod.sh /etc/local/entry.sh ENTRYPOINT ["sh", "/etc/local/entry.sh"] # all-in-one base ############################################################################################ -FROM scratch AS all-in-one-base +FROM clickhouse/clickhouse-server:${CLICKHOUSE_VERSION}-alpine AS all-in-one-base ARG CODE_VERSION ENV CODE_VERSION=$CODE_VERSION -# Copy from clickhouse and otel collector bases -COPY --from=clickhouse_base / / +# Copy from otel collector bases COPY --from=otel_collector_base --chmod=755 /otelcol-contrib /otelcontribcol COPY --from=otel_collector_opampsupervisor_base --chmod=755 /usr/local/bin/opampsupervisor /usr/local/bin/opampsupervisor @@ -98,6 +90,9 @@ COPY --from=node_base --link /usr/local/lib /usr/local/lib COPY --from=node_base /usr/lib /usr/lib COPY --from=node_base /usr/local/include /usr/local/include +# Install libs used for the start script +RUN npm install -g concurrently@9.1.0 + # Set up Clickhouse COPY --from=clickhouse ./local/*.xml /etc/clickhouse-server COPY --from=hyperdx ./clickhouseConfig.xml /etc/clickhouse-server/config.xml diff --git a/docker/hyperdx/entry.local.base.sh b/docker/hyperdx/entry.local.base.sh index 5d31c415..f9006435 100644 --- a/docker/hyperdx/entry.local.base.sh +++ b/docker/hyperdx/entry.local.base.sh @@ -61,9 +61,9 @@ opampsupervisor --config /etc/otel/supervisor.yaml > /var/log/otel-collector.log npx concurrently \ "--kill-others" \ "--names=API,APP,ALERT-TASK" \ - "PORT=${HYPERDX_API_PORT:-8000} HYPERDX_APP_PORT=${HYPERDX_APP_PORT:-8080} node -r ./node_modules/@hyperdx/node-opentelemetry/build/src/tracing ./packages/api/build/index.js" \ + "PORT=${HYPERDX_API_PORT:-8000} HYPERDX_APP_PORT=${HYPERDX_APP_PORT:-8080} node -r ./packages/api/tracing ./packages/api/index" \ "cd ./packages/app/packages/app && HOSTNAME='0.0.0.0' HYPERDX_API_PORT=${HYPERDX_API_PORT:-8000} PORT=${HYPERDX_APP_PORT:-8080} node server.js" \ - "node -r ./node_modules/@hyperdx/node-opentelemetry/build/src/tracing ./packages/api/build/tasks/index.js check-alerts" \ + "node -r ./packages/api/tracing ./packages/api/tasks/index check-alerts" > /var/log/app.log 2>&1 & echo "" diff --git a/docker/hyperdx/entry.prod.sh b/docker/hyperdx/entry.prod.sh index 8bd254d3..55b866b9 100644 --- a/docker/hyperdx/entry.prod.sh +++ b/docker/hyperdx/entry.prod.sh @@ -15,6 +15,6 @@ echo "" npx concurrently \ "--kill-others" \ "--names=API,APP,ALERT-TASK" \ - "PORT=${HYPERDX_API_PORT:-8000} HYPERDX_APP_PORT=${HYPERDX_APP_PORT:-8080} node -r ./node_modules/@hyperdx/node-opentelemetry/build/src/tracing ./packages/api/build/index.js" \ + "PORT=${HYPERDX_API_PORT:-8000} HYPERDX_APP_PORT=${HYPERDX_APP_PORT:-8080} node -r ./packages/api/tracing ./packages/api/index" \ "cd ./packages/app/packages/app && HOSTNAME='0.0.0.0' HYPERDX_API_PORT=${HYPERDX_API_PORT:-8000} PORT=${HYPERDX_APP_PORT:-8080} node server.js" \ - "node -r ./node_modules/@hyperdx/node-opentelemetry/build/src/tracing ./packages/api/build/tasks/index.js check-alerts" + "node -r ./packages/api/tracing ./packages/api/tasks/index check-alerts" diff --git a/packages/api/package.json b/packages/api/package.json index 9633a91f..d2dcc2a3 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -75,6 +75,7 @@ "@types/supertest": "^2.0.12", "@types/swagger-jsdoc": "^6", "@types/uuid": "^8.3.4", + "esbuild": "^0.25.5", "jest": "^28.1.3", "migrate-mongo": "^11.0.0", "nodemon": "^2.0.20", @@ -89,10 +90,10 @@ "typescript": "^4.9.5" }, "scripts": { - "start": "node ./build/index.js", + "start": "node ./dist/index.js", "dev": "DOTENV_CONFIG_PATH=.env.development nodemon --signal SIGTERM -e ts,json --exec 'ts-node' --transpile-only -r tsconfig-paths/register -r dotenv-expand/config -r '@hyperdx/node-opentelemetry/build/src/tracing' ./src/index.ts", "dev-task": "DOTENV_CONFIG_PATH=.env.development nodemon --signal SIGTERM -e ts,json --exec 'ts-node' --transpile-only -r tsconfig-paths/register -r dotenv-expand/config -r '@hyperdx/node-opentelemetry/build/src/tracing' ./src/tasks/index.ts", - "build": "rimraf ./build && tsc && tsc-alias && cp -r src/opamp/proto build/opamp/", + "build": "tsc && tsc-alias && esbuild ../../node_modules/@hyperdx/node-opentelemetry/build/src/tracing --bundle --minify --platform=node --outfile=dist/tracing.js && esbuild ./build/src/index.js ./build/src/tasks/index.js --bundle --minify --platform=node --target=node22 --outdir=dist --alias:@='./src' && mkdir -p dist/opamp && cp -r src/opamp/proto dist/opamp/proto && rimraf ./build", "lint": "eslint --quiet . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "ci:lint": "yarn lint && yarn tsc --noEmit", diff --git a/packages/api/src/opamp/utils/protobuf.ts b/packages/api/src/opamp/utils/protobuf.ts index c2cf7c79..85247f1f 100644 --- a/packages/api/src/opamp/utils/protobuf.ts +++ b/packages/api/src/opamp/utils/protobuf.ts @@ -3,10 +3,14 @@ import * as fs from 'fs'; import * as path from 'path'; import * as protobuf from 'protobufjs'; +import { IS_PROD } from '@/config'; import logger from '@/utils/logger'; // Define the root path of the proto file -const PROTO_PATH = path.resolve(__dirname, '../proto/opamp.proto'); +const PROTO_PATH = path.resolve( + __dirname, + `${IS_PROD ? 'opamp' : '..'}/proto/opamp.proto`, +); // Load the OpAMP proto definition let root: protobuf.Root; diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index c864669e..d1fb5823 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -4,6 +4,7 @@ "paths": { "@/*": ["./*"] }, + "rootDir": ".", "allowSyntheticDefaultImports": true, "downlevelIteration": true, "esModuleInterop": true, diff --git a/yarn.lock b/yarn.lock index 694f02d2..47b7e540 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3717,6 +3717,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/aix-ppc64@npm:0.25.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/android-arm64@npm:0.20.2" @@ -3731,6 +3738,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm64@npm:0.25.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/android-arm@npm:0.20.2" @@ -3745,6 +3759,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm@npm:0.25.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/android-x64@npm:0.20.2" @@ -3759,6 +3780,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-x64@npm:0.25.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/darwin-arm64@npm:0.20.2" @@ -3773,6 +3801,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-arm64@npm:0.25.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/darwin-x64@npm:0.20.2" @@ -3787,6 +3822,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-x64@npm:0.25.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/freebsd-arm64@npm:0.20.2" @@ -3801,6 +3843,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-arm64@npm:0.25.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/freebsd-x64@npm:0.20.2" @@ -3815,6 +3864,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-x64@npm:0.25.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-arm64@npm:0.20.2" @@ -3829,6 +3885,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm64@npm:0.25.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-arm@npm:0.20.2" @@ -3843,6 +3906,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm@npm:0.25.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-ia32@npm:0.20.2" @@ -3857,6 +3927,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ia32@npm:0.25.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-loong64@npm:0.20.2" @@ -3871,6 +3948,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-loong64@npm:0.25.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-mips64el@npm:0.20.2" @@ -3885,6 +3969,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-mips64el@npm:0.25.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-ppc64@npm:0.20.2" @@ -3899,6 +3990,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ppc64@npm:0.25.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-riscv64@npm:0.20.2" @@ -3913,6 +4011,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-riscv64@npm:0.25.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-s390x@npm:0.20.2" @@ -3927,6 +4032,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-s390x@npm:0.25.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/linux-x64@npm:0.20.2" @@ -3941,6 +4053,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-x64@npm:0.25.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/netbsd-arm64@npm:0.25.1" @@ -3948,6 +4067,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-arm64@npm:0.25.5" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/netbsd-x64@npm:0.20.2" @@ -3962,6 +4088,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-x64@npm:0.25.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/openbsd-arm64@npm:0.25.1" @@ -3969,6 +4102,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-arm64@npm:0.25.5" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/openbsd-x64@npm:0.20.2" @@ -3983,6 +4123,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-x64@npm:0.25.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/sunos-x64@npm:0.20.2" @@ -3997,6 +4144,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/sunos-x64@npm:0.25.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/win32-arm64@npm:0.20.2" @@ -4011,6 +4165,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-arm64@npm:0.25.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/win32-ia32@npm:0.20.2" @@ -4025,6 +4186,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-ia32@npm:0.25.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.20.2": version: 0.20.2 resolution: "@esbuild/win32-x64@npm:0.20.2" @@ -4039,6 +4207,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-x64@npm:0.25.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -4305,6 +4480,7 @@ __metadata: cron: "npm:^3.5.0" date-fns: "npm:^2.28.0" date-fns-tz: "npm:^2.0.0" + esbuild: "npm:^0.25.5" express: "npm:^4.19.2" express-rate-limit: "npm:^6.7.1" express-session: "npm:^1.17.3" @@ -15265,6 +15441,92 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.25.5": + version: 0.25.5 + resolution: "esbuild@npm:0.25.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.5" + "@esbuild/android-arm": "npm:0.25.5" + "@esbuild/android-arm64": "npm:0.25.5" + "@esbuild/android-x64": "npm:0.25.5" + "@esbuild/darwin-arm64": "npm:0.25.5" + "@esbuild/darwin-x64": "npm:0.25.5" + "@esbuild/freebsd-arm64": "npm:0.25.5" + "@esbuild/freebsd-x64": "npm:0.25.5" + "@esbuild/linux-arm": "npm:0.25.5" + "@esbuild/linux-arm64": "npm:0.25.5" + "@esbuild/linux-ia32": "npm:0.25.5" + "@esbuild/linux-loong64": "npm:0.25.5" + "@esbuild/linux-mips64el": "npm:0.25.5" + "@esbuild/linux-ppc64": "npm:0.25.5" + "@esbuild/linux-riscv64": "npm:0.25.5" + "@esbuild/linux-s390x": "npm:0.25.5" + "@esbuild/linux-x64": "npm:0.25.5" + "@esbuild/netbsd-arm64": "npm:0.25.5" + "@esbuild/netbsd-x64": "npm:0.25.5" + "@esbuild/openbsd-arm64": "npm:0.25.5" + "@esbuild/openbsd-x64": "npm:0.25.5" + "@esbuild/sunos-x64": "npm:0.25.5" + "@esbuild/win32-arm64": "npm:0.25.5" + "@esbuild/win32-ia32": "npm:0.25.5" + "@esbuild/win32-x64": "npm:0.25.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1"