diff --git a/Dockerfile b/Dockerfile index 79555821..ad6f8bc8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,50 @@ -FROM node:20-alpine - -# Set the working directory in the container -WORKDIR /usr/src/app - -# Copy the entire monorepo into the container +FROM node:18-alpine AS base + +FROM base AS builder +RUN apk update +RUN apk add --no-cache libc6-compat +# Set working directory +WORKDIR /app +# Replace with the major version installed in your repository. For example: +# RUN yarn global add turbo@^2 +RUN yarn global add turbo@latest COPY . . - -# Install dependencies + +# Generate a partial monorepo with a pruned lockfile for a target workspace. +# Assuming "web" is the name entered in the project's package.json: { name: "web" } +RUN turbo prune web --docker + +# Add lockfile and package.json's of isolated subworkspace +FROM base AS installer +RUN apk update +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# First install the dependencies (as they change less often) +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/yarn.lock ./yarn.lock RUN yarn install -# Generate Prisma client -RUN cd packages/db && npx prisma generate - -# Expose ports for both applications -EXPOSE 3000 - -WORKDIR /usr/src/app - -# Command to start both services -CMD ["yarn", "run", "dev:docker"] +# Build the project +COPY --from=builder /app/out/full/ . +RUN yarn turbo run build --filter=web... + +FROM base AS runner +WORKDIR /app + +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs +USER nextjs + +COPY --from=installer /app/apps/web/next.config.js . +COPY --from=installer /app/apps/web/package.json . + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/standalone ./ +COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static +COPY --from=installer --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public + +CMD node apps/web/server.js diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 00000000..79555821 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,21 @@ +FROM node:20-alpine + +# Set the working directory in the container +WORKDIR /usr/src/app + +# Copy the entire monorepo into the container +COPY . . + +# Install dependencies +RUN yarn install + +# Generate Prisma client +RUN cd packages/db && npx prisma generate + +# Expose ports for both applications +EXPOSE 3000 + +WORKDIR /usr/src/app + +# Command to start both services +CMD ["yarn", "run", "dev:docker"] diff --git a/apps/leaderboard-generator/.env.example b/apps/leaderboard-generator/.env.example new file mode 100644 index 00000000..e9cb9099 --- /dev/null +++ b/apps/leaderboard-generator/.env.example @@ -0,0 +1 @@ +CONTEST_ID="##CONTEST_ID##" \ No newline at end of file diff --git a/apps/leaderboard-generator/Dockerfile b/apps/leaderboard-generator/Dockerfile new file mode 100644 index 00000000..b21615d0 --- /dev/null +++ b/apps/leaderboard-generator/Dockerfile @@ -0,0 +1,43 @@ +FROM node:18-alpine AS base + +FROM base AS builder +RUN apk update +RUN apk add --no-cache libc6-compat +# Set working directory +WORKDIR /app +# Replace with the major version installed in your repository. For example: +# RUN yarn global add turbo@^2 +RUN yarn global add turbo@latest +COPY . . + +# Generate a partial monorepo with a pruned lockfile for a target workspace. +# Assuming "web" is the name entered in the project's package.json: { name: "web" } +RUN turbo prune leaderboard-generator --docker + +# Add lockfile and package.json's of isolated subworkspace +FROM base AS installer +RUN apk update +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# First install the dependencies (as they change less often) +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/yarn.lock ./yarn.lock +RUN yarn install + +# Build the project +COPY --from=builder /app/out/full/ . +RUN yarn turbo run build --filter=leaderboard-generator... + +FROM base AS runner +WORKDIR /app + +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nodejs +USER nodejs + +COPY --from=installer /app/apps/leaderboard-generator/dist . + +CMD node index.js diff --git a/apps/leaderboard-generator/package.json b/apps/leaderboard-generator/package.json index ec9205a5..4f0a1c43 100644 --- a/apps/leaderboard-generator/package.json +++ b/apps/leaderboard-generator/package.json @@ -4,7 +4,12 @@ "description": "", "main": "index.js", "scripts": { - "leaderboard:create": "CONTEST_ID=clx19tibu00054lu9fpb3c3zx ts-node src/index.ts" + "build": "esbuild ./src/index.ts --bundle --platform=node --outfile=dist/index.js --sourcemap", + "leaderboard:create": "ts-node src/index.ts" + }, + "dependencies": { + "@repo/db": "*", + "esbuild": "^0.21.5" }, "keywords": [], "author": "", diff --git a/apps/leaderboard-generator/src/index.ts b/apps/leaderboard-generator/src/index.ts index b894af8c..d08f7521 100644 --- a/apps/leaderboard-generator/src/index.ts +++ b/apps/leaderboard-generator/src/index.ts @@ -1,5 +1,4 @@ -import { PrismaClient } from "@prisma/client"; -const prisma = new PrismaClient(); +import prisma from "@repo/db/src"; async function main(contestId: string) { const userPoints = new Map(); @@ -16,7 +15,7 @@ async function main(contestId: string) { if (userPoints.has(submission.userId)) { userPoints.set( submission.userId, - userPoints.get(submission.userId)! + submission.points, + userPoints.get(submission.userId)! + submission.points ); } else { userPoints.set(submission.userId, submission.points); @@ -24,7 +23,7 @@ async function main(contestId: string) { }); const sortedUserPoints = Array.from(userPoints.entries()).sort( - (a, b) => b[1] - a[1], + (a, b) => b[1] - a[1] ); // clean existing leaderboard diff --git a/apps/leaderboard-generator/tsconfig.json b/apps/leaderboard-generator/tsconfig.json index e075f973..958d582a 100644 --- a/apps/leaderboard-generator/tsconfig.json +++ b/apps/leaderboard-generator/tsconfig.json @@ -26,7 +26,7 @@ /* Modules */ "module": "commonjs", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ + "rootDir": "./src", /* Specify the root folder within your source files. */ // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ @@ -55,7 +55,7 @@ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ + "outDir": "./dist", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ // "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ diff --git a/apps/sweeper/Dockerfile b/apps/sweeper/Dockerfile new file mode 100644 index 00000000..b21615d0 --- /dev/null +++ b/apps/sweeper/Dockerfile @@ -0,0 +1,43 @@ +FROM node:18-alpine AS base + +FROM base AS builder +RUN apk update +RUN apk add --no-cache libc6-compat +# Set working directory +WORKDIR /app +# Replace with the major version installed in your repository. For example: +# RUN yarn global add turbo@^2 +RUN yarn global add turbo@latest +COPY . . + +# Generate a partial monorepo with a pruned lockfile for a target workspace. +# Assuming "web" is the name entered in the project's package.json: { name: "web" } +RUN turbo prune leaderboard-generator --docker + +# Add lockfile and package.json's of isolated subworkspace +FROM base AS installer +RUN apk update +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# First install the dependencies (as they change less often) +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/yarn.lock ./yarn.lock +RUN yarn install + +# Build the project +COPY --from=builder /app/out/full/ . +RUN yarn turbo run build --filter=leaderboard-generator... + +FROM base AS runner +WORKDIR /app + +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nodejs +USER nodejs + +COPY --from=installer /app/apps/leaderboard-generator/dist . + +CMD node index.js diff --git a/apps/sweeper/package.json b/apps/sweeper/package.json index 65a9fec4..104588f7 100644 --- a/apps/sweeper/package.json +++ b/apps/sweeper/package.json @@ -5,6 +5,7 @@ "license": "MIT", "dependencies": { "@repo/db": "*", + "esbuild": "^0.21.5", "nodemon": "^3.1.3" }, "scripts": { diff --git a/apps/sweeper/src/db/index.ts b/apps/sweeper/src/db/index.ts deleted file mode 100644 index 0b88b724..00000000 --- a/apps/sweeper/src/db/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { PrismaClient } from "@prisma/client"; - -const prismaClientSingleton = () => { - return new PrismaClient(); -}; - -type PrismaClientSingleton = ReturnType; - -// eslint-disable-next-line -const globalForPrisma = globalThis as unknown as { - prisma: PrismaClientSingleton | undefined; -}; - -const prisma = globalForPrisma.prisma ?? prismaClientSingleton(); - -export const db = prisma; - -if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; diff --git a/apps/sweeper/src/index.ts b/apps/sweeper/src/index.ts index 4c68c6ab..7233c5ae 100644 --- a/apps/sweeper/src/index.ts +++ b/apps/sweeper/src/index.ts @@ -1,5 +1,5 @@ import { Prisma } from "@prisma/client"; -import { db } from "./db"; +import db from "@repo/db/src"; import { updateContest, updateMemoryAndExecutionTime } from "./utils"; type SubmissionWithTestcases = Prisma.SubmissionGetPayload<{ include: { diff --git a/apps/sweeper/src/utils.ts b/apps/sweeper/src/utils.ts index 70efa043..33563d8c 100644 --- a/apps/sweeper/src/utils.ts +++ b/apps/sweeper/src/utils.ts @@ -1,5 +1,5 @@ import { Prisma } from "@prisma/client"; -import { db } from "./db"; +import db from "@repo/db/src"; import { getPoints } from "./points"; type SubmissionWithTestcases = Prisma.SubmissionGetPayload<{ diff --git a/apps/web/app/api/submission/bulk/route.ts b/apps/web/app/api/submission/bulk/route.ts index 9c4a0ad9..0e717af9 100644 --- a/apps/web/app/api/submission/bulk/route.ts +++ b/apps/web/app/api/submission/bulk/route.ts @@ -1,5 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; -import { db } from "../../../db"; +import db from "@repo/db/client"; import { getServerSession } from "next-auth"; import { authOptions } from "../../../lib/auth"; diff --git a/apps/web/app/api/submission/route.ts b/apps/web/app/api/submission/route.ts index 7a40ab60..bc0698a6 100644 --- a/apps/web/app/api/submission/route.ts +++ b/apps/web/app/api/submission/route.ts @@ -3,7 +3,7 @@ import { SubmissionInput } from "@repo/common/zod"; import { getProblem } from "../../lib/problems"; import axios from "axios"; import { LANGUAGE_MAPPING } from "@repo/common/language"; -import { db } from "../../db"; +import db from "@repo/db/client"; import { getServerSession } from "next-auth"; import { authOptions } from "../../lib/auth"; import { rateLimit } from "../../lib/rateLimit"; diff --git a/apps/web/app/db/contest.ts b/apps/web/app/db/contest.ts index 0c7b0560..0a81b7e0 100644 --- a/apps/web/app/db/contest.ts +++ b/apps/web/app/db/contest.ts @@ -1,5 +1,5 @@ import { getServerSession } from "next-auth"; -import { db } from "."; +import db from "@repo/db/client"; import { authOptions } from "../lib/auth"; export const getContest = async (contestId: string) => { diff --git a/apps/web/app/db/contestPoints.tsx b/apps/web/app/db/contestPoints.tsx index 41645a57..22459cb8 100644 --- a/apps/web/app/db/contestPoints.tsx +++ b/apps/web/app/db/contestPoints.tsx @@ -1,6 +1,6 @@ import { getServerSession } from "next-auth"; import { authOptions } from "../lib/auth"; -import { db } from "./index"; +import db from "@repo/db/client"; export const getContestPoints = async ( contestId: string, diff --git a/apps/web/app/db/index.ts b/apps/web/app/db/index.ts deleted file mode 100644 index 0b88b724..00000000 --- a/apps/web/app/db/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { PrismaClient } from "@prisma/client"; - -const prismaClientSingleton = () => { - return new PrismaClient(); -}; - -type PrismaClientSingleton = ReturnType; - -// eslint-disable-next-line -const globalForPrisma = globalThis as unknown as { - prisma: PrismaClientSingleton | undefined; -}; - -const prisma = globalForPrisma.prisma ?? prismaClientSingleton(); - -export const db = prisma; - -if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; diff --git a/apps/web/app/db/problem.ts b/apps/web/app/db/problem.ts index 07931ebc..420500c3 100644 --- a/apps/web/app/db/problem.ts +++ b/apps/web/app/db/problem.ts @@ -1,4 +1,4 @@ -import { db } from "."; +import db from "@repo/db/client"; export const getProblem = async (problemId: string, contestId?: string) => { if (contestId) { diff --git a/apps/web/next.config.js b/apps/web/next.config.js index a5b0aec2..c7519b0f 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -1,4 +1,5 @@ /** @type {import('next').NextConfig} */ module.exports = { transpilePackages: ["@repo/ui"], + output: 'standalone' }; diff --git a/apps/web/package.json b/apps/web/package.json index a0fef64f..f67a1cb2 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -13,6 +13,8 @@ "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-slot": "^1.0.2", "@repo/ui": "*", + "@repo/common": "*", + "@repo/db": "*", "@types/bcrypt": "^5.0.2", "axios": "^1.7.2", "bcrypt": "^5.1.1", diff --git a/docker-compose.yml b/docker-compose.yml index ecfbcf80..67ebf9f1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ services: app: build: context: . - dockerfile: Dockerfile + dockerfile: Dockerfile.dev container_name: app-container environment: - DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres diff --git a/packages/ops/docker-compose.yaml b/packages/ops/docker-compose.yaml new file mode 100644 index 00000000..81d9191f --- /dev/null +++ b/packages/ops/docker-compose.yaml @@ -0,0 +1,20 @@ +version: '3.5' + +services: + app: + image: 100xdevs/algo-arena:latest + container_name: algo-arena + environment: + - NEXTAUTH_URL= + - NEXTAUTH_SECRET= + # - NEXTAUTH_URL_INTERNAL= + - DATABASE_URL= + - REDIS_URL= + - JUDGE0_URI= + - MOUNT_PATH=/problems + - NODE_ENV=production + - PORT=443 + ports: + - '443:443' # Next.js app + volumes: + - ~/algorithmic-arena/apps/problems/:/problems diff --git a/packages/ops/prometh-conf.yaml b/packages/ops/prometh-conf.yaml new file mode 100644 index 00000000..bbfd5050 --- /dev/null +++ b/packages/ops/prometh-conf.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: prometheus-config +data: + prometheus.yml: | + global: + scrape_interval: 15s + scrape_configs: + - job_name: 'redis' + static_configs: + - targets: ['redis-exporter:9121'] + diff --git a/packages/ops/prometh-svc.yaml b/packages/ops/prometh-svc.yaml new file mode 100644 index 00000000..f6972ed4 --- /dev/null +++ b/packages/ops/prometh-svc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: prometheus +spec: + type: ClusterIP + ports: + - port: 9090 + targetPort: 9090 + selector: + app: prometheus + diff --git a/packages/ops/prometh.yaml b/packages/ops/prometh.yaml new file mode 100644 index 00000000..cab687e0 --- /dev/null +++ b/packages/ops/prometh.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prometheus +spec: + replicas: 1 + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + spec: + containers: + - name: prometheus + image: prom/prometheus:v2.30.3 + ports: + - containerPort: 9090 + volumeMounts: + - name: prometheus-config + mountPath: /etc/prometheus/ + volumes: + - name: prometheus-config + configMap: + name: prometheus-config diff --git a/packages/ops/redis-exporter.yaml b/packages/ops/redis-exporter.yaml new file mode 100644 index 00000000..055fa49f --- /dev/null +++ b/packages/ops/redis-exporter.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-exporter +spec: + replicas: 1 + selector: + matchLabels: + app: redis-exporter + template: + metadata: + labels: + app: redis-exporter + spec: + containers: + - name: redis-exporter + image: oliver006/redis_exporter:v1.29.0 + ports: + - containerPort: 9121 + env: + - name: REDIS_ADDR + value: "redis:6379" + diff --git a/packages/ops/redis.yaml b/packages/ops/redis.yaml new file mode 100644 index 00000000..1bd6e654 --- /dev/null +++ b/packages/ops/redis.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis +spec: + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis + image: redis:6.2 + ports: + - containerPort: 6379 diff --git a/turbo.json b/turbo.json index 95e946a7..80293872 100644 --- a/turbo.json +++ b/turbo.json @@ -6,7 +6,8 @@ "tasks": { "build": { "dependsOn": [ - "^build" + "^build", + "db:generate" ], "outputs": [ ".next/**", diff --git a/yarn.lock b/yarn.lock index 41a6c643..6ca16e0c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -229,6 +229,121 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -2430,6 +2545,35 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +esbuild@^0.21.5: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + escalade@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"