Projects STRLCPY gradejs Commits bce2eadc
🤬
  • feat: add local startup helpers (#40)

    * feat: add local startup helpers
    
    * fix: review
    
    * fix: add simple sqs pull server
    
    * fix: use webpack env plugin
  • Loading...
  • Oleg Klimenko committed with GitHub 2 years ago
    bce2eadc
    1 parent ffa64807
  • ■ ■ ■ ■ ■
    .eslintignore
    skipped 1 lines
    2 2  index.d.ts
    3 3  webpack.config.js
    4 4  node_modules/
     5 +packages/*/build
    5 6   
  • ■ ■ ■ ■ ■ ■
    cli/development.env
     1 +API_ORIGIN=https://staging.api.gradejs.com
     2 +GA_ID=
     3 +PLAUSIBLE_DOMAIN=
     4 +DUMP_ANALYTICS=
  • ■ ■ ■ ■ ■ ■
    cli/localSqsPuller.ts
     1 +import {
     2 + SQSClient,
     3 + ReceiveMessageCommand,
     4 + DeleteMessageCommand,
     5 + ChangeMessageVisibilityCommand,
     6 +} from '@aws-sdk/client-sqs';
     7 +import fetch from 'node-fetch';
     8 + 
     9 +/*
     10 + * Simple server to pull messages from FE queue and push it into worker
     11 + * express app. Intended to be used ONLY LOCALLY, since AWS has this functionality
     12 + * built-in (contrary to elasticmq).
     13 + */
     14 + 
     15 +// This hardcode should be in sync with values in local_start.sh
     16 +const workerPort = 8084;
     17 +const sqsPort = 29324;
     18 +const sqsQueueUrl = '/test/frontend-queue';
     19 +const timeout = 300; // sec, visibility timeout
     20 +const pollInterval = 20; // sec
     21 + 
     22 +export async function startWorker(loop = true) {
     23 + let currentTask: WorkerTaskWrapper | undefined;
     24 + 
     25 + async function abortTimeoutCallback() {
     26 + if (currentTask) {
     27 + await skipWorkerTask(currentTask);
     28 + }
     29 + 
     30 + // Restart the application
     31 + process.exit();
     32 + }
     33 + 
     34 + do {
     35 + try {
     36 + currentTask = await receiveNextWorkerTask();
     37 + 
     38 + if (currentTask) {
     39 + const abortTimeoutId = setTimeout(() => abortTimeoutCallback(), timeout * 1000);
     40 + await fetch(`http://localhost:${workerPort}`, {
     41 + method: 'POST',
     42 + headers: {
     43 + 'Content-Type': 'application/json',
     44 + },
     45 + body: JSON.stringify(currentTask.body),
     46 + });
     47 + clearTimeout(abortTimeoutId);
     48 + await deleteWorkerTask(currentTask);
     49 + } else {
     50 + await wait(pollInterval);
     51 + }
     52 + } catch (e) {
     53 + console.log(e);
     54 + 
     55 + if (currentTask) {
     56 + await skipWorkerTask(currentTask);
     57 + }
     58 + }
     59 + // eslint-disable-next-line no-unmodified-loop-condition
     60 + } while (loop);
     61 +}
     62 + 
     63 +let sqsClient: SQSClient | undefined;
     64 +function getSQSClient() {
     65 + if (!sqsClient) {
     66 + sqsClient = new SQSClient({
     67 + endpoint: {
     68 + protocol: 'http',
     69 + hostname: 'localhost',
     70 + port: sqsPort,
     71 + path: '/',
     72 + },
     73 + });
     74 + }
     75 + 
     76 + return sqsClient;
     77 +}
     78 + 
     79 +export async function wait(seconds: number) {
     80 + return new Promise((resolve) => {
     81 + setTimeout(resolve, seconds * 1000);
     82 + });
     83 +}
     84 + 
     85 +export type WorkerTaskWrapper = {
     86 + receiptHandle?: string;
     87 + body: any;
     88 +};
     89 + 
     90 +export async function receiveNextWorkerTask(): Promise<WorkerTaskWrapper | undefined> {
     91 + const client = getSQSClient();
     92 + const command = new ReceiveMessageCommand({
     93 + QueueUrl: sqsQueueUrl,
     94 + MaxNumberOfMessages: 1,
     95 + MessageAttributeNames: ['All'],
     96 + VisibilityTimeout: timeout,
     97 + WaitTimeSeconds: pollInterval,
     98 + });
     99 + 
     100 + try {
     101 + const result = await client.send(command);
     102 + const message = result.Messages?.pop();
     103 + 
     104 + if (message?.Body) {
     105 + return {
     106 + receiptHandle: message.ReceiptHandle,
     107 + body: JSON.parse(message.Body),
     108 + };
     109 + }
     110 + } catch (e) {
     111 + console.error(e);
     112 + }
     113 + 
     114 + return undefined;
     115 +}
     116 + 
     117 +export async function deleteWorkerTask({ receiptHandle }: { receiptHandle?: string }) {
     118 + if (!receiptHandle) {
     119 + return;
     120 + }
     121 + 
     122 + const client = getSQSClient();
     123 + const command = new DeleteMessageCommand({
     124 + QueueUrl: sqsQueueUrl,
     125 + ReceiptHandle: receiptHandle,
     126 + });
     127 + 
     128 + return client.send(command);
     129 +}
     130 + 
     131 +export async function skipWorkerTask({ receiptHandle }: { receiptHandle?: string }) {
     132 + if (!receiptHandle) {
     133 + return;
     134 + }
     135 + 
     136 + const client = getSQSClient();
     137 + const command = new ChangeMessageVisibilityCommand({
     138 + QueueUrl: sqsQueueUrl,
     139 + ReceiptHandle: receiptHandle,
     140 + VisibilityTimeout: 0,
     141 + });
     142 + 
     143 + return client.send(command);
     144 +}
     145 + 
     146 +(async function () {
     147 + await startWorker(true);
     148 +})();
     149 + 
  • ■ ■ ■ ■ ■ ■
    cli/local_sqs.conf
     1 +include classpath("application.conf")
     2 + 
     3 +queues {
     4 + frontend-queue {
     5 + defaultVisibilityTimeout = 30 seconds
     6 + delay = 0 seconds
     7 + receiveMessageWait = 0 seconds
     8 + deadLetterQueue {
     9 + name: "dead-frontend-queue"
     10 + maxReceiveCount = 5
     11 + }
     12 + }
     13 + dead-frontend-queue {
     14 + defaultVisibilityTimeout = 30 seconds
     15 + delay = 0 seconds
     16 + receiveMessageWait = 0 seconds
     17 + }
     18 +}
     19 + 
  • ■ ■ ■ ■ ■ ■
    cli/local_start.sh
     1 +#!/usr/bin/env bash
     2 + 
     3 +# Note: script should be run from repo root.
     4 + 
     5 +echo "Running local setup"
     6 +echo "------------------------------------------"
     7 +echo "Prerequisites: "
     8 +echo "* PostgreSQL DBMS should be up and running on port 5432"
     9 +echo "* You should have a gradejs-public database (username and password should be 'gradejs', dbname should be 'gradejs-public')"
     10 +echo "* Gradejs internal api must be started on port 8082"
     11 +echo "------------------------------------------"
     12 +echo "Note: nodejs debug server started, you can attach a client (e.g. chrome://inspect) to ports below"
     13 +echo "- Public api debugger on localhost:9201"
     14 +echo "- Worker debugger on localhost:9202"
     15 + 
     16 +# Save current env and values passed in CLI
     17 +CURENV=$(declare -p -x)
     18 +# Set local development envvars
     19 +set -o allexport
     20 +source cli/development.env
     21 +set +o allexport
     22 +# Overwrite development defaults with values passed in CLI
     23 +eval "$CURENV"
     24 + 
     25 +# Ensure we have all the packages
     26 +yarn
     27 + 
     28 +# Rebuild packages
     29 +yarn build:backend
     30 + 
     31 +echo "Starting elasticmq to mock amazon sqs"
     32 +docker run --rm --name frontendqueue -p 29324:9324 -p 29325:9325 \
     33 + -v `pwd`/cli/local_sqs.conf:/opt/elasticmq.conf softwaremill/elasticmq-native 2>&1 &
     34 +ELASTICMQ_PID=$!
     35 + 
     36 +echo "Starting worker package"
     37 +AWS_REGION=test PORT=8084 DB_URL=postgres://gradejs:gradejs@localhost:5432/gradejs-public \
     38 + INTERNAL_API_ORIGIN=http://localhost:8082 SQS_WORKER_QUEUE_URL=/test/frontend-queue \
     39 + SQS_LOCAL_PORT=29324 AWS_ACCESS_KEY_ID=secret AWS_SECRET_ACCESS_KEY=secret \
     40 + npm run debug --prefix packages/worker 2>&1 &
     41 +WORKER_PID=$!
     42 + 
     43 +echo "Starting queue puller script"
     44 +AWS_REGION=test AWS_ACCESS_KEY_ID=secret AWS_SECRET_ACCESS_KEY=secret \
     45 + ts-node --swc cli/localSqsPuller.ts 2>&1 &
     46 +PULLER_PID=$!
     47 + 
     48 +echo "Starting public api package"
     49 +AWS_REGION=test PORT=8083 DB_URL=postgres://gradejs:gradejs@localhost:5432/gradejs-public \
     50 + INTERNAL_API_ORIGIN=http://localhost:8082 SQS_WORKER_QUEUE_URL=/test/frontend-queue \
     51 + SQS_LOCAL_PORT=29324 AWS_ACCESS_KEY_ID=secret AWS_SECRET_ACCESS_KEY=secret \
     52 + npm run debug --prefix packages/public-api 2>&1 &
     53 +API_PID=$!
     54 + 
     55 +echo "Starting web package dev server"
     56 +API_ORIGIN=http://localhost:8083 npm start --prefix packages/web 2>&1 &
     57 +WEB_PID=$!
     58 + 
     59 +# Some magic to shut down all services at once when requested
     60 + 
     61 +TRAPPED_SIGNAL=false
     62 +trap "TRAPPED_SIGNAL=true; kill -15 $ELASTICMQ_PID; kill -15 $WORKER_PID; kill -15 $PULLER_PID; kill -15 $API_PID; kill -15 $WEB_PID" SIGTERM SIGINT
     63 + 
     64 +while :
     65 +do
     66 + kill -0 $ELASTICMQ_PID 2> /dev/null
     67 + ELASTICMQ_STATUS=$?
     68 + 
     69 + kill -0 $WORKER_PID 2> /dev/null
     70 + WORKER_STATUS=$?
     71 + 
     72 + kill -0 $PULLER_PID 2> /dev/null
     73 + PULLER_STATUS=$?
     74 + 
     75 + kill -0 $API_PID 2> /dev/null
     76 + API_STATUS=$?
     77 + 
     78 + kill -0 $WEB_PID 2> /dev/null
     79 + WEB_STATUS=$?
     80 + 
     81 + if [ "$TRAPPED_SIGNAL" = "false" ]; then
     82 + if [ $ELASTICMQ_STATUS -ne 0 ] || [ $WORKER_STATUS -ne 0 ] || [ $PULLER_STATUS -ne 0 ] || [ $API_STATUS -ne 0 ] || [ $WEB_STATUS -ne 0 ]; then
     83 + if [ $ELASTICMQ_STATUS -eq 0 ]; then
     84 + kill -15 $ELASTICMQ_PID;
     85 + wait $ELASTICMQ_PID;
     86 + fi
     87 + if [ $WORKER_STATUS -eq 0 ]; then
     88 + kill -15 $WORKER_PID;
     89 + wait $WORKER_PID;
     90 + fi
     91 + if [ $PULLER_STATUS -eq 0 ]; then
     92 + kill -15 $PULLER_PID;
     93 + wait $PULLER_PID;
     94 + fi
     95 + if [ $API_STATUS -eq 0 ]; then
     96 + kill -15 $API_PID;
     97 + wait $API_PID;
     98 + fi
     99 + if [ $WEB_STATUS -eq 0 ]; then
     100 + kill -15 $WEB_PID;
     101 + wait $WEB_PID;
     102 + fi
     103 + exit 1;
     104 + fi
     105 + else
     106 + if [ $ELASTICMQ_STATUS -ne 0 ] && [ $WORKER_STATUS -ne 0 ] && [ $PULLER_STATUS -ne 0 ] && [ $API_STATUS -ne 0 ] && [ $WEB_STATUS -ne 0 ]; then
     107 + exit 0;
     108 + fi
     109 + fi
     110 + 
     111 + sleep 1
     112 +done
  • ■ ■ ■ ■
    pre-push.sh cli/pre-push.sh
    skipped 1 lines
    2 2   
    3 3  case "$1" in
    4 4   "setup")
    5  - echo "sh ./pre-push.sh" >> .git/hooks/pre-push
     5 + echo "sh ./cli/pre-push.sh" >> .git/hooks/pre-push
    6 6   chmod +x .git/hooks/pre-push
    7 7   ;;
    8 8   *)
    skipped 6 lines
  • ■ ■ ■ ■ ■
    package.json
    skipped 19 lines
    20 20   "build:shared": "yarn workspace @gradejs-public/shared run build",
    21 21   "build:worker": "yarn workspace @gradejs-public/worker run build",
    22 22   "build:public-api": "yarn workspace @gradejs-public/public-api run build",
    23  - "build:backend": "yarn build:shared && yarn build:public-api && yarn build:worker"
     23 + "build:backend": "yarn build:shared && yarn build:public-api && yarn build:worker",
     24 + "dev:start": "bash cli/local_start.sh",
     25 + "dev:worker:syncPackages": "curl -d '{\"type\":\"syncPackageIndex\"}' -H \"Content-Type: application/json\" -X POST http://localhost:8084",
     26 + "dev:worker:syncVulnerabilities": "curl -d '{\"type\":\"syncPackageVulnerabilities\"}' -H \"Content-Type: application/json\" -X POST http://localhost:8084"
    24 27   },
    25 28   "devDependencies": {
     29 + "@swc/core": "^1.2.233",
    26 30   "@types/jsonpath": "^0.2.0",
    27 31   "@types/node": "^17.0.23",
    28 32   "@typescript-eslint/eslint-plugin": "^5.21.0",
    skipped 12 lines
  • ■ ■ ■ ■ ■
    packages/public-api/package.json
    skipped 6 lines
    7 7   "typecheck": "tsc --project tsconfig.build.json --noEmit",
    8 8   "build": "tsc --project tsconfig.build.json",
    9 9   "test": "jest",
    10  - "start": "node build/index.js"
     10 + "start": "node build/index.js",
     11 + "debug": "node --inspect=9201 build/index.js"
    11 12   },
    12 13   "engines": {
    13 14   "node": "^16.14.2"
    skipped 25 lines
  • ■ ■ ■ ■ ■
    packages/shared/src/utils/aws.ts
    1  -import { SQSClient, SendMessageCommand } from '@aws-sdk/client-sqs';
     1 +import { SQSClient, SendMessageCommand, SQSClientConfig } from '@aws-sdk/client-sqs';
    2 2  import { WorkerTaskPayloadMap, WorkerTaskType } from '../worker/types';
    3  -import { getEnv, Env } from './env';
     3 +import { getEnv, Env, getSqsLocalPort } from './env';
    4 4   
    5 5  let sqsClient: SQSClient | undefined;
    6 6  function getSQSClient() {
    7 7   if (!sqsClient) {
    8  - sqsClient = new SQSClient({ region: getEnv(Env.AwsRegion) });
     8 + let config: SQSClientConfig = { region: getEnv(Env.AwsRegion) };
     9 + if (getSqsLocalPort() > 0) {
     10 + // Local development override
     11 + config = {
     12 + endpoint: {
     13 + protocol: 'http',
     14 + hostname: 'localhost',
     15 + port: getSqsLocalPort(),
     16 + path: '/',
     17 + },
     18 + };
     19 + }
     20 + sqsClient = new SQSClient(config);
    9 21   }
    10 22   
    11 23   return sqsClient;
    skipped 17 lines
  • ■ ■ ■ ■ ■ ■
    packages/shared/src/utils/env.ts
    skipped 6 lines
    7 7   // AWS
    8 8   AwsRegion = 'AWS_REGION',
    9 9   SqsWorkerQueueUrl = 'SQS_WORKER_QUEUE_URL',
     10 + SqsLocalPort = 'SQS_LOCAL_PORT',
    10 11   
    11 12   // GitHub
    12 13   GitHubAccessToken = 'GITHUB_ACCESS_TOKEN',
    skipped 11 lines
    24 25  export const isTest = () => getNodeEnv() === 'test';
    25 26   
    26 27  export const getInternalApiOrigin = () => getEnv(Env.InternalApiOrigin);
     28 +export const getSqsLocalPort = () => Number(getEnv(Env.SqsLocalPort, '0'));
    27 29   
    28 30  export const getGitHubAccessToken = () => getEnv(Env.GitHubAccessToken);
    29 31   
    skipped 18 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/webpack.config.js
    1 1  const path = require('path');
    2  -const dotenv = require('dotenv');
    3 2  const webpack = require('webpack');
    4 3  const HtmlWebpackPlugin = require('html-webpack-plugin');
    5 4  const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    skipped 1 lines
    7 6   
    8 7  const srcDir = 'src';
    9 8  const distDir = 'dist';
     9 + 
     10 +const env = ['API_ORIGIN', 'PLAUSIBLE_DOMAIN', 'GA_ID', 'DUMP_ANALYTICS'].reduce((acc, val) => {
     11 + acc[val] = `"${process.env[val]}"`;
     12 + return acc;
     13 +}, {});
    10 14   
    11 15  module.exports = (_, argv) => {
    12 16   const { mode = 'development' } = argv;
    skipped 61 lines
    74 78   new HtmlWebpackPlugin({
    75 79   template: path.join(__dirname, 'index.html'),
    76 80   }),
    77  - new webpack.DefinePlugin({
    78  - ...(isDevelopment ? { 'process.env': JSON.stringify(dotenv.config().parsed) } : {}),
    79  - }),
    80  - ...(isDevelopment
    81  - ? []
    82  - : [
    83  - new webpack.EnvironmentPlugin({
    84  - API_ORIGIN: 'https://staging.api.gradejs.com',
    85  - GA_ID: '',
    86  - PLAUSIBLE_DOMAIN: '',
    87  - DUMP_ANALYTICS: '',
    88  - }),
    89  - ]),
     81 + new webpack.EnvironmentPlugin(env),
    90 82   new CopyPlugin({
    91 83   patterns: [
    92 84   { from: 'robots.txt', to: 'robots.txt' },
    skipped 23 lines
  • ■ ■ ■ ■ ■
    packages/worker/package.json
    skipped 7 lines
    8 8   "build": "tsc --project tsconfig.build.json",
    9 9   "typecheck": "tsc --project tsconfig.build.json --noEmit",
    10 10   "test": "jest",
    11  - "start": "node build/index.js"
     11 + "start": "node build/index.js",
     12 + "debug": "node --inspect=9202 build/index.js"
    12 13   },
    13 14   "dependencies": {
    14 15   "@aws-sdk/client-sqs": "^3.87.0",
    skipped 19 lines
  • ■ ■ ■ ■ ■ ■
    yarn.lock
    skipped 3385 lines
    3386 3386   resolve-from "^5.0.0"
    3387 3387   store2 "^2.12.0"
    3388 3388   
     3389 +"@swc/[email protected]":
     3390 + version "1.2.233"
     3391 + resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.233.tgz#5fd99cae910e79dcb2cb75c23f05e4d17afa4bde"
     3392 + integrity sha512-+cbIa7+mcK2hoFSa0qPxeVvduqZlBzilKkg7OeYwvfDC7m7miaY6/BHcbDulvVhXmrjTwcfuMl05slZFKrgSTw==
     3393 + dependencies:
     3394 + "@swc/wasm" "1.2.122"
     3395 + 
     3396 +"@swc/[email protected]":
     3397 + version "1.2.233"
     3398 + resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.233.tgz#f8e8a6e38b52ff6d2372d10bc42fefabb4268152"
     3399 + integrity sha512-xNvbJB+cdg3/caIcITnlcEwKElot6EeutlLW6ZSNmNq82EZzR86TDPNWwdxrGROiaD1u/SxcqWy264CoxRlpRw==
     3400 + dependencies:
     3401 + "@swc/wasm" "1.2.130"
     3402 + 
     3403 +"@swc/[email protected]":
     3404 + version "1.2.233"
     3405 + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.233.tgz#c1bb0a6d24f8b0bf4c85cbd7c187e4ee8fd25007"
     3406 + integrity sha512-iHmkH73YoFsrsV/rvFZt09hGUCuQfTePwijGN+SdeRLegajChA35MXpusNlSOW9zQygHxxATRHMmwjvkLR627Q==
     3407 + 
     3408 +"@swc/[email protected]":
     3409 + version "1.2.233"
     3410 + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.233.tgz#c0ac776e8249e82037ebca91e0cad0a1c4392d1c"
     3411 + integrity sha512-Dpdvvbo5E67AMbxOX2p/Qfoz9t16GlSImL87uBNxp4RzIjq0kFMidMn5Y6v5gdbsHdqHHXyO1IZQ6CymzHSrDQ==
     3412 + 
     3413 +"@swc/[email protected]":
     3414 + version "1.2.233"
     3415 + resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.233.tgz#64ae3516af82808cda7315a4ce2e963c993e9062"
     3416 + integrity sha512-qE4F4nOH5T5xu4I9+2gT2zxcY5j3vEvtuxWfEn1ahFgiXtVWwYI6Y4k+VvlkSmLBnjZmGMW/FKjrUDKvroOclw==
     3417 + dependencies:
     3418 + "@swc/wasm" "1.2.130"
     3419 + 
     3420 +"@swc/[email protected]":
     3421 + version "1.2.233"
     3422 + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.233.tgz#6fb98149f41adf34fecc53e1bd599165f5b7762d"
     3423 + integrity sha512-PRIElsmCqtQP/+XFeHUAAUN7Fb7WG97iTjRLghETuGyA1N3fHV8wglpkbsY3UhfMfeDoUStNZmyHccjjv2SP9Q==
     3424 + dependencies:
     3425 + "@swc/wasm" "1.2.130"
     3426 + 
     3427 +"@swc/[email protected]":
     3428 + version "1.2.233"
     3429 + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.233.tgz#0cb85da4e74d8bb1780d8efb832c664bc2fd6c4f"
     3430 + integrity sha512-3RVWvbiY2/ntl06WR2Ei2g+dWyteqbx8Zxl2ZgFUOyLG1DW7ygNkXq2suRFOShpwz9JWdP4jge+bj7y4ZekdfA==
     3431 + 
     3432 +"@swc/[email protected]":
     3433 + version "1.2.233"
     3434 + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.233.tgz#b76b516dfd6d6074217ee76d87fc6e86c0fc8748"
     3435 + integrity sha512-UPvc8QGEkdodcATyp4eKL6QiHLUvXhS5h84KqL1buqrjUslJdKOT8bxYsiB6nXbAS9bEiggkaEdbCfPcnUWxRQ==
     3436 + 
     3437 +"@swc/[email protected]":
     3438 + version "1.2.233"
     3439 + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.233.tgz#d57c71b79097afa1d049840e7035ad8f7bbe66b0"
     3440 + integrity sha512-xIpRGBscAHaBW5/WNW5rmLH+0ckJ76JIOgfH2PUVRo6Sf7S/MAbM59Gt7d7iXfXYaSVl7sE4GlFzuxpTy9YSMg==
     3441 + 
     3442 +"@swc/[email protected]":
     3443 + version "1.2.233"
     3444 + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.233.tgz#6d465bab4376dcb66bf7df14f17d6dcc79f38734"
     3445 + integrity sha512-oCbzTM4A28izo5sW2seaN2I3wI40E4fUQ2/dBWM+eE/E5HdlVKlgmRkn7awJ5adxZyJqbNmM9t24pbaejEt6EQ==
     3446 + 
     3447 +"@swc/[email protected]":
     3448 + version "1.2.233"
     3449 + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.233.tgz#ebe1ea92a90d7eacb2e5b3fa8e7753c8dd7ed907"
     3450 + integrity sha512-vUhO59MzeeS4RG8e/bTqEMvBht7zpHRT4PDlL9hROiwJzqOkWFchmZB1DUSpnYMi1FRU0PAo/25wcNg+utQdgA==
     3451 + dependencies:
     3452 + "@swc/wasm" "1.2.130"
     3453 + 
     3454 +"@swc/[email protected]":
     3455 + version "1.2.233"
     3456 + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.233.tgz#5922281b416e14bea5f8e9de125494ab24eaccf1"
     3457 + integrity sha512-0sQ7c7sycZN0O1r4L5BGOAkXDh0agXkwKbhE1KsP24C+74CkVH57ZsZcparPitmHD2kkbtdnEy9E0aFueMndqA==
     3458 + dependencies:
     3459 + "@swc/wasm" "1.2.130"
     3460 + 
     3461 +"@swc/[email protected]":
     3462 + version "1.2.233"
     3463 + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.233.tgz#a055887107594fd0d40d170d2c3471ab9d96772a"
     3464 + integrity sha512-O2StLXXMA5eylLemN5Z2cJSpt+nFT3UCvUHzgLVue/tLuShBiD9M1wASYidfcZAab8ARs0fWZliNnBrNrkYBwg==
     3465 + 
     3466 +"@swc/core@^1.2.233":
     3467 + version "1.2.233"
     3468 + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.233.tgz#f61dc5cc76aac43fdf0d0f355635fb78bea08eef"
     3469 + integrity sha512-1sVSqkW0NCu/AROBa5rF5R26h53TGuHGkm9xtIkRgRypMzKORrC27TLDPitgnu3BfxdAWxKPdr6+yI3FoxMqkg==
     3470 + optionalDependencies:
     3471 + "@swc/core-android-arm-eabi" "1.2.233"
     3472 + "@swc/core-android-arm64" "1.2.233"
     3473 + "@swc/core-darwin-arm64" "1.2.233"
     3474 + "@swc/core-darwin-x64" "1.2.233"
     3475 + "@swc/core-freebsd-x64" "1.2.233"
     3476 + "@swc/core-linux-arm-gnueabihf" "1.2.233"
     3477 + "@swc/core-linux-arm64-gnu" "1.2.233"
     3478 + "@swc/core-linux-arm64-musl" "1.2.233"
     3479 + "@swc/core-linux-x64-gnu" "1.2.233"
     3480 + "@swc/core-linux-x64-musl" "1.2.233"
     3481 + "@swc/core-win32-arm64-msvc" "1.2.233"
     3482 + "@swc/core-win32-ia32-msvc" "1.2.233"
     3483 + "@swc/core-win32-x64-msvc" "1.2.233"
     3484 + 
     3485 +"@swc/[email protected]":
     3486 + version "1.2.122"
     3487 + resolved "https://registry.yarnpkg.com/@swc/wasm/-/wasm-1.2.122.tgz#87a5e654b26a71b2e84b801f41e45f823b856639"
     3488 + integrity sha512-sM1VCWQxmNhFtdxME+8UXNyPNhxNu7zdb6ikWpz0YKAQQFRGT5ThZgJrubEpah335SUToNg8pkdDF7ibVCjxbQ==
     3489 + 
     3490 +"@swc/[email protected]":
     3491 + version "1.2.130"
     3492 + resolved "https://registry.yarnpkg.com/@swc/wasm/-/wasm-1.2.130.tgz#88ac26433335d1f957162a9a92f1450b73c176a0"
     3493 + integrity sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==
     3494 + 
    3389 3495  "@szmarczak/http-timer@^1.1.2":
    3390 3496   version "1.1.2"
    3391 3497   resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
    skipped 11699 lines
Please wait...
Page is in error, reload to recover