From 06044319edf27d8f5cb0e554d9cd2ba5b9bae5cf Mon Sep 17 00:00:00 2001 From: Ivan Zanov Date: Fri, 21 Aug 2026 10:06:12 +0200 Subject: [PATCH 01/12] chore: add stricter ESLint configuration --- eslint.config.mjs | 160 +++++++ executioner/languages/docker.ts | 101 +++-- lib/queue/src/amqp.ts | 92 ++-- package.json | 30 +- senatus/config/admin.ts | 12 +- senatus/config/database.ts | 41 +- senatus/config/server.ts | 18 +- .../api/submission/controllers/submission.ts | 295 +++++++------ senatus/src/index.ts | 99 +++-- web/eslint.config.js | 11 - web/src/components/ui/input.tsx | 19 +- web/src/components/ui/use-toast.ts | 141 +++---- web/src/contexts/AuthContext.tsx | 71 ++-- web/src/pages/CompetePage.tsx | 397 +++++++++++------- web/src/pages/EventDetailPage.tsx | 201 ++++++--- web/src/pages/EventsPage.tsx | 132 +++--- 16 files changed, 1143 insertions(+), 677 deletions(-) create mode 100644 eslint.config.mjs delete mode 100644 web/eslint.config.js diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..6aadd23 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,160 @@ +import js from "@eslint/js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import reactHooks from "eslint-plugin-react-hooks"; +import reactRefresh from "eslint-plugin-react-refresh"; + +export default [ + { + ignores: [ + "**/node_modules/**", + "**/dist/**", + "**/build/**", + "**/.cache/**", + "**/.strapi/**", + "**/.tmp/**", + "**/coverage/**", + + "senatus/types/generated/**", + + // Strapi-generated/example files that aren't application code. + "senatus/src/admin/*.example.*", + ], + }, + + { + linterOptions: { + reportUnusedDisableDirectives: "error", + }, + }, + + js.configs.recommended, + + ...tseslint.configs.recommended, + + { + files: ["**/*.{js,mjs,cjs,ts,tsx}"], + + rules: { + // Avoid coercion bugs. + eqeqeq: ["error", "always"], + + // Require braces around control-flow statements. + curly: ["error", "all"], + + // Avoid duplicate imports from the same module. + "no-duplicate-imports": [ + "error", + { + allowSeparateTypeImports: true, + }, + ], + + // Modern JavaScript basics. + "no-var": "error", + "prefer-const": "error", + "@typescript-eslint/no-require-imports": "off", + }, + }, + + { + files: ["**/*.{ts,tsx}"], + + rules: { + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + caughtErrorsIgnorePattern: "^_", + }, + ], + + // Keep visible, but don't block existing code. + "@typescript-eslint/no-explicit-any": "warn", + + // Allow both `type` and `interface`. + "@typescript-eslint/consistent-type-definitions": "off", + + // Variable shadowing is allowed for now. + "@typescript-eslint/no-shadow": "off", + "no-shadow": "off", + + // Existing CommonJS require() imports are allowed. + "@typescript-eslint/no-require-imports": "off", + }, + }, + + // Browser / React application. + { + files: ["web/**/*.{ts,tsx}"], + + languageOptions: { + globals: { + ...globals.browser, + ...globals.es2022, + }, + }, + + plugins: { + "react-hooks": reactHooks, + "react-refresh": reactRefresh, + }, + + rules: { + ...reactHooks.configs.recommended.rules, + + "react-refresh/only-export-components": [ + "warn", + { + allowConstantExport: true, + }, + ], + + // Allow warn/error, but flag leftover console.log calls. + "no-console": [ + "warn", + { + allow: ["warn", "error"], + }, + ], + }, + }, + + // Node / backend / infrastructure code. + { + files: [ + "senatus/**/*.{ts,tsx}", + "executioner/**/*.ts", + "lib/queue/**/*.ts", + ], + + languageOptions: { + globals: { + ...globals.node, + ...globals.es2022, + }, + }, + + rules: { + // Backend/service logging is expected. + "no-console": "off", + }, + }, + + // Frontend configuration files execute in Node. + { + files: ["web/*.config.{js,mjs,cjs,ts}", "web/codegen.ts"], + + languageOptions: { + globals: { + ...globals.node, + ...globals.es2022, + }, + }, + + rules: { + "no-console": "off", + }, + }, +]; diff --git a/executioner/languages/docker.ts b/executioner/languages/docker.ts index c6c1e51..cd21fe4 100644 --- a/executioner/languages/docker.ts +++ b/executioner/languages/docker.ts @@ -1,9 +1,9 @@ -import fs from 'fs'; -import path from 'path'; -import cp from 'child_process'; -import { v4 } from 'uuid'; +import fs from "fs"; +import path from "path"; +import cp from "child_process"; +import { v4 } from "uuid"; -import { readFile, writeFile } from 'fs/promises'; +import { readFile, writeFile } from "fs/promises"; type LanguageOptions = { [key: string]: string; @@ -19,10 +19,13 @@ type File = { }; const CPU_LIMIT_PER_EXECUTION = process.env.CPU_LIMIT_PER_EXECUTION; -const MEMORY_LIMIT_PER_EXECUTION = process.env.MEMORY_LIMIT_PER_EXECUTION ?? '1G'; -const ENABLE_NETWORK_IN_EXECUTION = process.env.ENABLE_NETWORK_IN_EXECUTION === 'true'; -const IMAGE_BASE = process.env.IMAGE_BASE || 'ghcr.io/42dotmk/colosseum-executioner-'; -const WORKDIR = process.env.WORKDIR || '_work'; +const MEMORY_LIMIT_PER_EXECUTION = + process.env.MEMORY_LIMIT_PER_EXECUTION ?? "1G"; +const ENABLE_NETWORK_IN_EXECUTION = + process.env.ENABLE_NETWORK_IN_EXECUTION === "true"; +const IMAGE_BASE = + process.env.IMAGE_BASE || "ghcr.io/42dotmk/colosseum-executioner-"; +const WORKDIR = process.env.WORKDIR || "_work"; if (!fs.existsSync(WORKDIR)) { fs.mkdirSync(WORKDIR); @@ -34,7 +37,9 @@ function parseDuration(duration: string) { return null; } const match = duration.match(/(\d+)m(\d+(?:\.\d+)?)s/); - if (!match) return null; + if (!match) { + return null; + } const minutes = Number(match[1]); const seconds = Number(match[2]); @@ -46,10 +51,14 @@ const readIfExists = async (path: string) => { if (fs.existsSync(path)) { return (await readFile(path)).toString(); } - return ''; -} + return ""; +}; -export const execute = async (files: File[], input: File[], options: LanguageOptions) => { +export const execute = async ( + files: File[], + input: File[], + options: LanguageOptions, +) => { const id = v4(); const subWorkspace = path.join(WORKDIR, id); @@ -83,12 +92,16 @@ export const execute = async (files: File[], input: File[], options: LanguageOpt const timePath = path.resolve(path.join(subWorkspace, timeFilename)); const stdoutPath = path.resolve(path.join(subWorkspace, stdoutFilename)); const stderrPath = path.resolve(path.join(subWorkspace, stderrFilename)); - const compileStdoutPath = path.resolve(path.join(subWorkspace, compileStdoutFilename)); - const compileStderrPath = path.resolve(path.join(subWorkspace, compileStderrFilename)); + const compileStdoutPath = path.resolve( + path.join(subWorkspace, compileStdoutFilename), + ); + const compileStderrPath = path.resolve( + path.join(subWorkspace, compileStderrFilename), + ); for (const file of files) { const filePath = path.resolve(path.join(srcDir, file.filename)); - console.log(`Writing file to ${filePath}`) + console.log(`Writing file to ${filePath}`); await writeFile(filePath, file.content); } @@ -98,13 +111,12 @@ export const execute = async (files: File[], input: File[], options: LanguageOpt } try { - return await new Promise(async (resolve) => { - await writeFile(timePath, ""); - await writeFile(stdoutPath, ""); - await writeFile(stderrPath, ""); - await writeFile(compileStdoutPath, ""); - await writeFile(compileStderrPath, ""); - + await writeFile(timePath, ""); + await writeFile(stdoutPath, ""); + await writeFile(stderrPath, ""); + await writeFile(compileStdoutPath, ""); + await writeFile(compileStderrPath, ""); + return await new Promise((resolve) => { const extraArgs = []; if (CPU_LIMIT_PER_EXECUTION) { @@ -120,7 +132,7 @@ export const execute = async (files: File[], input: File[], options: LanguageOpt } const args = [ - 'run', + "run", "--rm", "-v", `${srcDir}:/exc/src`, @@ -140,43 +152,48 @@ export const execute = async (files: File[], input: File[], options: LanguageOpt `${compileStderrPath}:/exc/${compileStderrFilename}`, ...extraArgs, "-i", - `${IMAGE_BASE}${lang}` + `${IMAGE_BASE}${lang}`, ]; - const child = cp.spawn('docker', args); - console.log(child.spawnargs.join(' ')) - - let stdout = ''; - let stderr = ''; + const child = cp.spawn("docker", args); + console.log(child.spawnargs.join(" ")); - child.stdout.on('data', (data) => { + child.stdout.on("data", (data) => { console.log(`stdout: ${data}`); - stdout += data; }); - child.stderr.on('data', (data) => { + child.stderr.on("data", (data) => { console.error(`stderr: ${data}`); - stderr += data; }); - child.on('close', async (code) => { + child.on("close", async (code) => { console.log(`child process exited with code ${code}`); const output = []; for (const inp of input) { - const stdoutPath = path.resolve(path.join(outputDir, `${inp.filename}.stdout`)); - const stderrPath = path.resolve(path.join(outputDir, `${inp.filename}.stderr`)); - const timePath = path.resolve(path.join(outputDir, `${inp.filename}.time`)); + const stdoutPath = path.resolve( + path.join(outputDir, `${inp.filename}.stdout`), + ); + const stderrPath = path.resolve( + path.join(outputDir, `${inp.filename}.stderr`), + ); + const timePath = path.resolve( + path.join(outputDir, `${inp.filename}.time`), + ); const stdout = await readIfExists(stdoutPath); - + const stderr = await readIfExists(stderrPath); const time = await readIfExists(timePath); let parsedTime = null; if (time) { - const timeSplits = time.split("\n").map((t) => t.trim()).filter(x => x).map(x => x.split("\t")); - const [ realTime ] = timeSplits; + const timeSplits = time + .split("\n") + .map((t) => t.trim()) + .filter((x) => x) + .map((x) => x.split("\t")); + const [realTime] = timeSplits; parsedTime = parseDuration(realTime[1]); if (!parsedTime) { console.error(`Failed to parse time from ${time}`); @@ -194,7 +211,7 @@ export const execute = async (files: File[], input: File[], options: LanguageOpt resolve(output); }); - console.log('child', child.pid); + console.log("child", child.pid); }); } catch (e) { console.error(e); diff --git a/lib/queue/src/amqp.ts b/lib/queue/src/amqp.ts index 8dac841..0250a3d 100644 --- a/lib/queue/src/amqp.ts +++ b/lib/queue/src/amqp.ts @@ -1,4 +1,9 @@ -import {Connection, Consumer, ConsumerStatus, Publisher} from 'rabbitmq-client'; +import { + Connection, + Consumer, + ConsumerStatus, + Publisher, +} from "rabbitmq-client"; type SubscriptionFn = (msg: string) => Promise; type UnsubscribeFn = () => Promise; @@ -10,53 +15,60 @@ export const connect = async (url: string) => { const consumers: Consumer[] = []; const publishers: { [key: string]: Publisher } = {}; - rabbit.on('error', (err) => { - console.log('RabbitMQ connection error', err) + rabbit.on("error", (err) => { + console.log("RabbitMQ connection error", err); }); - rabbit.on('connection', () => { - console.log('Connection successfully (re)established') + rabbit.on("connection", () => { + console.log("Connection successfully (re)established"); }); const disconnect = async () => { - console.log('Disconnecting'); + console.log("Disconnecting"); - console.log('Closing consumers' + consumers.length); + console.log("Closing consumers" + consumers.length); for (const sub of consumers) { - console.log('Closing consumer ' + sub.consumerTag); + console.log("Closing consumer " + sub.consumerTag); await sub.close(); } for (const pub of Object.values(publishers)) { - console.log('Closing publisher'); + console.log("Closing publisher"); await pub.close(); } await rabbit.close(); - } - - const subscribe = async (queue: string, fn?: SubscriptionFn, prefetchCount: number = 1): Promise => { - const sub = rabbit.createConsumer({ - queue, - queueOptions: {durable: true}, - qos: { prefetchCount }, - }, async (msg) => { - console.log('received message (user-events)', msg); - try { - const str = msg.body.toString('utf8'); - await fn?.(str); - return ConsumerStatus.ACK; - } catch (e: any) { - console.error("Error in subscription", e); - return ConsumerStatus.DROP; - } - }); - - sub.on('error', (err) => { + }; + + const subscribe = async ( + queue: string, + fn?: SubscriptionFn, + prefetchCount: number = 1, + ): Promise => { + const sub = rabbit.createConsumer( + { + queue, + queueOptions: { durable: true }, + qos: { prefetchCount }, + }, + async (msg) => { + console.log("received message (user-events)", msg); + try { + const str = msg.body.toString("utf8"); + await fn?.(str); + return ConsumerStatus.ACK; + } catch (e: any) { + console.error("Error in subscription", e); + return ConsumerStatus.DROP; + } + }, + ); + + sub.on("error", (err) => { // Maybe the consumer was cancelled, or the connection was reset before a // message could be acknowledged. - console.log('consumer error (user-events)', err) + console.log("consumer error (user-events)", err); }); consumers.push(sub); @@ -67,13 +79,15 @@ export const connect = async (url: string) => { } await sub.close(); }; - } + }; - const publish = async (queue: string, msg: string, deliveryMode = 2) => { - const pub = publishers[queue] ?? rabbit.createPublisher({ - confirm: true, - maxAttempts: 2, - }); + const publish = async (queue: string, msg: string, _deliveryMode = 2) => { + const pub = + publishers[queue] ?? + rabbit.createPublisher({ + confirm: true, + maxAttempts: 2, + }); if (!publishers[queue]) { publishers[queue] = pub; @@ -82,8 +96,7 @@ export const connect = async (url: string) => { await pub.send(queue, msg); }; - const unsubscribe = async (tag: string) => { - }; + const unsubscribe = async (_tag: string) => {}; return { subscribe, @@ -91,5 +104,4 @@ export const connect = async (url: string) => { publish, disconnect, }; -} - +}; diff --git a/package.json b/package.json index ccb4c92..f9160d2 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,37 @@ "name": "colosseum", "version": "1.0.0", "devDependencies": { - "husky": "^9.0.10" + "@eslint/js": "^10.0.1", + "@types/node": "^26.2.0", + "concurrently": "^9.2.4", + "eslint": "^10.8.1", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.4", + "globals": "^17.11.0", + "husky": "^9.0.10", + "typescript-eslint": "^8.67.0" }, "scripts": { + "install:all": "npm ci && npm --prefix senatus ci && npm --prefix executioner ci && npm --prefix web ci && npm --prefix lib/queue ci", + "dev": "npm run dev:infra && npm run build:queue && concurrently --kill-others-on-fail --names \"QUEUE,SENATUS,EXECUTIONER,WEB\" \"npm run dev:queue\" \"npm run dev:senatus\" \"npm run dev:executioner\" \"npm run dev:web\"", + "dev:infra": "docker compose -f docker-compose.q.yml up -d", + "dev:down": "docker compose -f docker-compose.q.yml down", + "dev:infra:logs": "docker compose -f docker-compose.q.yml logs -f", + "dev:queue": "npm --prefix lib/queue run watch", + "dev:senatus": "npm --prefix senatus run develop", + "dev:executioner": "npm --prefix executioner start", + "dev:web": "npm --prefix web run dev", + "build": "npm run build:queue && npm run build:senatus && npm run build:web", + "build:queue": "npm --prefix lib/queue run build", + "build:senatus": "npm --prefix senatus run build", + "build:web": "npm --prefix web run build", + "lint": "eslint senatus executioner lib/queue web", + "lint:fix": "eslint senatus executioner lib/queue web --fix", + "lint:senatus": "eslint senatus", + "lint:executioner": "eslint executioner", + "lint:queue": "eslint lib/queue", + "lint:web": "eslint web", + "typecheck:senatus": "npm --prefix senatus run typecheck", "prepareClientHusky": "husky client/.husky", "prepareSenatusHusky": "husky senatus/.husky" } diff --git a/senatus/config/admin.ts b/senatus/config/admin.ts index ee4807f..1362476 100644 --- a/senatus/config/admin.ts +++ b/senatus/config/admin.ts @@ -1,14 +1,16 @@ -export default ({ env }) => ({ +import type { StrapiConfigContext } from "../src/types/strapi-env"; + +export default ({ env }: StrapiConfigContext) => ({ auth: { - secret: env('ADMIN_JWT_SECRET'), + secret: env("ADMIN_JWT_SECRET"), }, apiToken: { - salt: env('API_TOKEN_SALT'), + salt: env("API_TOKEN_SALT"), }, transfer: { token: { - salt: env('TRANSFER_TOKEN_SALT'), + salt: env("TRANSFER_TOKEN_SALT"), }, }, - url: env('PUBLIC_ADMIN_URL', '/admin'), + url: env("PUBLIC_ADMIN_URL", "/admin"), }); diff --git a/senatus/config/database.ts b/senatus/config/database.ts index cada839..fc9d53c 100644 --- a/senatus/config/database.ts +++ b/senatus/config/database.ts @@ -1,29 +1,28 @@ -export default ({ env }) => ({ +import type { StrapiConfigContext } from "../src/types/strapi-env"; + +export default ({ env }: StrapiConfigContext) => ({ connection: { - client: 'postgres', + client: "postgres", connection: { - host: env('DATABASE_HOST', 'localhost'), - port: env.int('DATABASE_PORT', 5432), - database: env('DATABASE_NAME', 'strapi'), - user: env('DATABASE_USERNAME', 'strapi'), - password: env('DATABASE_PASSWORD', 'strapi'), - ssl: env.bool('DATABASE_SSL', false) && { - key: env('DATABASE_SSL_KEY', undefined), - cert: env('DATABASE_SSL_CERT', undefined), - ca: env('DATABASE_SSL_CA', undefined), - capath: env('DATABASE_SSL_CAPATH', undefined), - cipher: env('DATABASE_SSL_CIPHER', undefined), - rejectUnauthorized: env.bool( - 'DATABASE_SSL_REJECT_UNAUTHORIZED', - true - ), + host: env("DATABASE_HOST", "localhost"), + port: env.int("DATABASE_PORT", 5432), + database: env("DATABASE_NAME", "strapi"), + user: env("DATABASE_USERNAME", "strapi"), + password: env("DATABASE_PASSWORD", "strapi"), + ssl: env.bool("DATABASE_SSL", false) && { + key: env("DATABASE_SSL_KEY", undefined), + cert: env("DATABASE_SSL_CERT", undefined), + ca: env("DATABASE_SSL_CA", undefined), + capath: env("DATABASE_SSL_CAPATH", undefined), + cipher: env("DATABASE_SSL_CIPHER", undefined), + rejectUnauthorized: env.bool("DATABASE_SSL_REJECT_UNAUTHORIZED", true), }, - schema: env('DATABASE_SCHEMA', 'public'), + schema: env("DATABASE_SCHEMA", "public"), }, pool: { - min: env.int('DATABASE_POOL_MIN', 2), - max: env.int('DATABASE_POOL_MAX', 10) + min: env.int("DATABASE_POOL_MIN", 2), + max: env.int("DATABASE_POOL_MAX", 10), }, - acquireConnectionTimeout: env.int('DATABASE_CONNECTION_TIMEOUT', 60000), + acquireConnectionTimeout: env.int("DATABASE_CONNECTION_TIMEOUT", 60000), }, }); diff --git a/senatus/config/server.ts b/senatus/config/server.ts index 8e6849f..9a2e533 100644 --- a/senatus/config/server.ts +++ b/senatus/config/server.ts @@ -1,13 +1,15 @@ -export default ({ env }) => ({ - host: env('HOST', '0.0.0.0'), - port: env.int('PORT', 1337), - url: env('PUBLIC_URL', 'http://localhost:1337'), +import type { StrapiConfigContext } from "../src/types/strapi-env"; + +export default ({ env }: StrapiConfigContext) => ({ + host: env("HOST", "0.0.0.0"), + port: env.int("PORT", 1337), + url: env("PUBLIC_URL", "http://localhost:1337"), app: { - keys: env.array('APP_KEYS'), - rabbitUrl: env('RABBIT_URL', 'amqp://guest:guest@localhost'), - prefetchResults: env.int('PREFETCH_RESULTS', 10), // How many results to prefetch from the results queue + keys: env.array("APP_KEYS"), + rabbitUrl: env("RABBIT_URL", "amqp://guest:guest@localhost"), + prefetchResults: env.int("PREFETCH_RESULTS", 10), // How many results to prefetch from the results queue }, webhooks: { - populateRelations: env.bool('WEBHOOKS_POPULATE_RELATIONS', false), + populateRelations: env.bool("WEBHOOKS_POPULATE_RELATIONS", false), }, }); diff --git a/senatus/src/api/submission/controllers/submission.ts b/senatus/src/api/submission/controllers/submission.ts index f3984a8..fab99ad 100644 --- a/senatus/src/api/submission/controllers/submission.ts +++ b/senatus/src/api/submission/controllers/submission.ts @@ -2,145 +2,182 @@ * submission controller */ -import { connect } from '@colosseum/queue'; -import { factories } from '@strapi/strapi' - -export default factories.createCoreController('api::submission.submission', ({ strapi }) => ({ - async submit(ctx) { - try { - ctx.body = ctx.request.query; - - const id = ctx.request.query.id as string; - if (!id) { - ctx.body = { error: 'No submission id provided' }; - return; - } - - const submission = await strapi.documents('api::submission.submission').findOne({ - documentId: id, - populate: ['user', 'problem', 'language'] - }); +import { connect } from "@colosseum/queue"; +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController( + "api::submission.submission", + ({ strapi }) => ({ + async submit(ctx) { + try { + ctx.body = ctx.request.query; + + const id = ctx.request.query.id as string; + if (!id) { + ctx.body = { error: "No submission id provided" }; + return; + } - console.log(submission) + const submission = await strapi + .documents("api::submission.submission") + .findOne({ + documentId: id, + populate: ["user", "problem", "language"], + }); + + if (!submission) { + ctx.status = 404; + ctx.body = { erorr: "Submission not found" }; + return; + } - const testCases = await strapi.documents('api::test-case.test-case').findMany({ - filters: { - problem: { documentId: submission.problem.documentId as any }, + if (!submission.problem) { + ctx.status = 400; + ctx.body = { error: "Submission has no problem" }; + return; } - }); - console.log("Found test cases:", testCases.length); - if (!submission) { - ctx.body = { error: 'Submission not found' }; - return; - } - const executionsToQueue: { testCase: any, execution: any }[] = []; - for (const testCase of testCases) { - const execution = await strapi.documents('api::execution.execution').create({ - data: { - stdout: '', - stderr: '', - executionTime: -1, - testCase: testCase.id, - submission: submission.id, - processed: false, - publishedAt: new Date(), - code: submission.code, - }, - status: 'published', - }); - executionsToQueue.push({ - testCase, - execution, - }); - } + if (!submission.language) { + ctx.status = 400; + ctx.body = { error: "Submission has no source code" }; + return; + } - const qPayload = { - sources: [ - { - filename: submission.language.entrypoint, - content: submission.code, - } - ], - input: executionsToQueue.map(pair => ({ - filename: pair.execution.documentId.toString(), - content: pair.testCase.input, - metadata: { - testCaseId: pair.testCase.documentId, - executionId: pair.execution.documentId, - } - })), - options: { - language: submission.language.codeName, - entrypointFile: submission.language.entrypoint, - }, - metadata: { - submissionId: submission.documentId, + if (submission.code === null) { + ctx.status = 400; + ctx.body = { error: "Submission has no source code" }; + return; } - }; - const msg = JSON.stringify(qPayload); + const testCases = await strapi + .documents("api::test-case.test-case") + .findMany({ + filters: { + problem: { documentId: submission.problem.documentId as any }, + }, + }); + + const executionsToQueue: { testCase: any; execution: any }[] = []; + for (const testCase of testCases) { + const execution = await strapi + .documents("api::execution.execution") + .create({ + data: { + stdout: "", + stderr: "", + executionTime: -1, + testCase: testCase.id, + submission: submission.id, + processed: false, + publishedAt: new Date(), + code: submission.code, + }, + status: "published", + }); + executionsToQueue.push({ + testCase, + execution, + }); + } - const { - publish, - disconnect, - } = await connect(strapi.config.get("server.app.rabbitUrl")); - - console.log("Connected to RabbitMQ"); + const qPayload = { + sources: [ + { + filename: submission.language.entrypoint, + content: submission.code, + }, + ], + input: executionsToQueue.map((pair) => ({ + filename: pair.execution.documentId.toString(), + content: pair.testCase.input, + metadata: { + testCaseId: pair.testCase.documentId, + executionId: pair.execution.documentId, + }, + })), + options: { + language: submission.language.codeName, + entrypointFile: submission.language.entrypoint, + }, + metadata: { + submissionId: submission.documentId, + }, + }; - await publish("execution", msg); + const msg = JSON.stringify(qPayload); - await disconnect(); + const { publish, disconnect } = await connect( + strapi.config.get("server.app.rabbitUrl"), + ); - ctx.body = { - state: 'Queued', - executions: executionsToQueue.map(pair => pair.execution.documentId), - } - } catch (err) { - console.log(err); - ctx.body = err; - } - }, - - async getExecutions(ctx) { - try { - const ids = ctx.request.query.ids as string; - if (!ids) { - ctx.body = { error: 'No execution ids provided' }; - return; - } + console.log("Connected to RabbitMQ"); - const executionIds = ids.split(',').map(id => id.trim()); - - const executions = await strapi.documents('api::execution.execution').findMany({ - filters: { - documentId: { $in: executionIds } - }, - populate: ['testCase'] - }); - - const allProcessed = executions.every(exec => exec.processed); - const results = executions.map(exec => ({ - id: exec.documentId, - processed: exec.processed, - passed: exec.passed, - executionTime: exec.executionTime, - stdout: exec.stdout, - stderr: exec.stderr, - testCase: { - id: exec.testCase.documentId, - input: exec.testCase.input, - output: exec.testCase.output, + await publish("execution", msg); + + await disconnect(); + + ctx.body = { + state: "Queued", + executions: executionsToQueue.map( + (pair) => pair.execution.documentId, + ), + }; + } catch (err) { + console.log(err); + ctx.body = err; + } + }, + + async getExecutions(ctx) { + try { + const ids = ctx.request.query.ids as string; + if (!ids) { + ctx.body = { error: "No execution ids provided" }; + return; } - })); - - ctx.body = { - complete: allProcessed, - executions: results, - }; - } catch (err) { - console.error(err); - ctx.body = { error: 'Failed to fetch executions' }; - } - } -})); + + const executionIds = ids.split(",").map((id) => id.trim()); + + const executions = await strapi + .documents("api::execution.execution") + .findMany({ + filters: { + documentId: { $in: executionIds }, + }, + populate: ["testCase"], + }); + + const allProcessed = executions.every((exec) => exec.processed); + const results = executions.map((exec) => { + if (!exec.testCase) { + throw new Error( + `Execution ${exec.documentId} has no associated test case`, + ); + } + + return { + id: exec.documentId, + processed: exec.processed, + passed: exec.passed, + executionTime: exec.executionTime, + stdout: exec.stdout, + stderr: exec.stderr, + testCase: { + id: exec.testCase.documentId, + input: exec.testCase.input, + output: exec.testCase.output, + }, + }; + }); + + ctx.body = { + complete: allProcessed, + executions: results, + }; + } catch (err) { + console.error(err); + ctx.body = { error: "Failed to fetch executions" }; + } + }, + }), +); diff --git a/senatus/src/index.ts b/senatus/src/index.ts index f13daf7..90f5bfe 100644 --- a/senatus/src/index.ts +++ b/senatus/src/index.ts @@ -1,6 +1,7 @@ -import { connect } from '@colosseum/queue' +import { connect } from "@colosseum/queue"; +import type { Core } from "@strapi/strapi"; -let disconnectRabbit: () => Promise | undefined; +let disconnectRabbit: (() => Promise) | undefined; export default { /** @@ -18,57 +19,71 @@ export default { * This gives you an opportunity to set up your data model, * run jobs, or perform some special logic. */ - async bootstrap({ strapi }) { + async bootstrap({ strapi }: { strapi: Core.Strapi }) { console.log("Senatus is bootstrapping"); console.log(strapi.config.get("server.app.rabbitUrl")); - const prefetchCount = strapi.config.get("server.app.prefetchResults"); - const { - subscribe, - disconnect, - } = await connect(strapi.config.get("server.app.rabbitUrl")); + const rabbitUrl = strapi.config.get("server.app.rabbitUrl") as string; + const prefetchCount = strapi.config.get( + "server.app.prefetchResults", + ) as number; + const { subscribe, disconnect } = await connect(rabbitUrl); disconnectRabbit = disconnect; console.log("Connected to RabbitMQ!"); - - await subscribe("results", async (msg) => { - try { - const parsed = JSON.parse(msg); - const submission = await strapi.documents('api::submission.submission').findOne({ - documentId: parsed.metadata.submissionId, - populate: ['user', 'problem', 'language'] - }); - for (const result of parsed.result) { - console.log("Updating execution", result.metadata.executionId); - const existing = await strapi.documents('api::execution.execution').findOne({ - documentId: result.metadata.executionId, - populate: ['testCase'] - }); - const execution = await strapi.documents('api::execution.execution').update({ - documentId: result.metadata.executionId, + await subscribe( + "results", + async (msg) => { + try { + const parsed = JSON.parse(msg); - data: { - stdout: result.stdout, - stderr: result.stderr, - executionTime: result.time, - processed: true, - passed: existing.testCase.output === result.stdout, - processedAt: new Date(), - publishedAt: new Date(), - }, - status: 'published', - }); - } - } catch (err) { - console.error("Error in processing result", err); - console.error(err); - } + for (const result of parsed.result) { + console.log("Updating execution", result.metadata.executionId); + const existing = await strapi + .documents("api::execution.execution") + .findOne({ + documentId: result.metadata.executionId, + populate: ["testCase"], + }); + + if (!existing) { + throw new Error( + `Execution ${result.metadata.executionId} was not found`, + ); + } + + if (!existing.testCase) { + throw new Error( + `Execution ${result.metadata.executionId} has no test case`, + ); + } - }, prefetchCount); + await strapi.documents("api::execution.execution").update({ + documentId: result.metadata.executionId, + + data: { + stdout: result.stdout, + stderr: result.stderr, + executionTime: result.time, + processed: true, + passed: existing.testCase.output === result.stdout, + processedAt: new Date(), + publishedAt: new Date(), + }, + status: "published", + }); + } + } catch (err) { + console.error("Error in processing result", err); + console.error(err); + } + }, + prefetchCount, + ); }, async destroy() { console.log("Destroying Senatus"); await disconnectRabbit?.(); - } + }, }; diff --git a/web/eslint.config.js b/web/eslint.config.js deleted file mode 100644 index 06484ce..0000000 --- a/web/eslint.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import tseslint from "typescript-eslint"; - -export default tseslint.config( - ...tseslint.configs.recommended, - { - rules: { - "@typescript-eslint/no-unused-vars": "warn", - "@typescript-eslint/no-explicit-any": "warn", - }, - } -); diff --git a/web/src/components/ui/input.tsx b/web/src/components/ui/input.tsx index 677d05f..7de2a03 100644 --- a/web/src/components/ui/input.tsx +++ b/web/src/components/ui/input.tsx @@ -1,9 +1,8 @@ -import * as React from "react" +import * as React from "react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -export interface InputProps - extends React.InputHTMLAttributes {} +export type InputProps = React.InputHTMLAttributes; const Input = React.forwardRef( ({ className, type, ...props }, ref) => { @@ -12,14 +11,14 @@ const Input = React.forwardRef( type={type} className={cn( "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", - className + className, )} ref={ref} {...props} /> - ) - } -) -Input.displayName = "Input" + ); + }, +); +Input.displayName = "Input"; -export { Input } +export { Input }; diff --git a/web/src/components/ui/use-toast.ts b/web/src/components/ui/use-toast.ts index 4da06d4..277dc51 100644 --- a/web/src/components/ui/use-toast.ts +++ b/web/src/components/ui/use-toast.ts @@ -1,75 +1,70 @@ -import * as React from "react" +import * as React from "react"; -import type { - ToastActionElement, - ToastProps, -} from "@/components/ui/toast" +import type { ToastActionElement, ToastProps } from "@/components/ui/toast"; -const TOAST_LIMIT = 1 -const TOAST_REMOVE_DELAY = 1000000 +const TOAST_LIMIT = 1; +const TOAST_REMOVE_DELAY = 1000000; type ToasterToast = ToastProps & { - id: string - title?: React.ReactNode - description?: React.ReactNode - action?: ToastActionElement -} + id: string; + title?: React.ReactNode; + description?: React.ReactNode; + action?: ToastActionElement; +}; -const actionTypes = { - ADD_TOAST: "ADD_TOAST", - UPDATE_TOAST: "UPDATE_TOAST", - DISMISS_TOAST: "DISMISS_TOAST", - REMOVE_TOAST: "REMOVE_TOAST", -} as const +type ActionType = { + ADD_TOAST: "ADD_TOAST"; + UPDATE_TOAST: "UPDATE_TOAST"; + DISMISS_TOAST: "DISMISS_TOAST"; + REMOVE_TOAST: "REMOVE_TOAST"; +}; -let count = 0 +let count = 0; function genId() { - count = (count + 1) % Number.MAX_SAFE_INTEGER - return count.toString() + count = (count + 1) % Number.MAX_SAFE_INTEGER; + return count.toString(); } -type ActionType = typeof actionTypes - type Action = | { - type: ActionType["ADD_TOAST"] - toast: ToasterToast + type: ActionType["ADD_TOAST"]; + toast: ToasterToast; } | { - type: ActionType["UPDATE_TOAST"] - toast: Partial + type: ActionType["UPDATE_TOAST"]; + toast: Partial; } | { - type: ActionType["DISMISS_TOAST"] - toastId?: ToasterToast["id"] + type: ActionType["DISMISS_TOAST"]; + toastId?: ToasterToast["id"]; } | { - type: ActionType["REMOVE_TOAST"] - toastId?: ToasterToast["id"] - } + type: ActionType["REMOVE_TOAST"]; + toastId?: ToasterToast["id"]; + }; interface State { - toasts: ToasterToast[] + toasts: ToasterToast[]; } -const toastTimeouts = new Map>() +const toastTimeouts = new Map>(); const addToRemoveQueue = (toastId: string) => { if (toastTimeouts.has(toastId)) { - return + return; } const timeout = setTimeout(() => { - toastTimeouts.delete(toastId) + toastTimeouts.delete(toastId); dispatch({ type: "REMOVE_TOAST", toastId: toastId, - }) - }, TOAST_REMOVE_DELAY) + }); + }, TOAST_REMOVE_DELAY); - toastTimeouts.set(toastId, timeout) -} + toastTimeouts.set(toastId, timeout); +}; export const reducer = (state: State, action: Action): State => { switch (action.type) { @@ -77,25 +72,25 @@ export const reducer = (state: State, action: Action): State => { return { ...state, toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), - } + }; case "UPDATE_TOAST": return { ...state, toasts: state.toasts.map((t) => - t.id === action.toast.id ? { ...t, ...action.toast } : t + t.id === action.toast.id ? { ...t, ...action.toast } : t, ), - } + }; case "DISMISS_TOAST": { - const { toastId } = action + const { toastId } = action; if (toastId) { - addToRemoveQueue(toastId) + addToRemoveQueue(toastId); } else { state.toasts.forEach((toast) => { - addToRemoveQueue(toast.id) - }) + addToRemoveQueue(toast.id); + }); } return { @@ -106,46 +101,46 @@ export const reducer = (state: State, action: Action): State => { ...t, open: false, } - : t + : t, ), - } + }; } case "REMOVE_TOAST": if (action.toastId === undefined) { return { ...state, toasts: [], - } + }; } return { ...state, toasts: state.toasts.filter((t) => t.id !== action.toastId), - } + }; } -} +}; -const listeners: Array<(state: State) => void> = [] +const listeners: Array<(state: State) => void> = []; -let memoryState: State = { toasts: [] } +let memoryState: State = { toasts: [] }; function dispatch(action: Action) { - memoryState = reducer(memoryState, action) + memoryState = reducer(memoryState, action); listeners.forEach((listener) => { - listener(memoryState) - }) + listener(memoryState); + }); } -type Toast = Omit +type Toast = Omit; function toast({ ...props }: Toast) { - const id = genId() + const id = genId(); const update = (props: ToasterToast) => dispatch({ type: "UPDATE_TOAST", toast: { ...props, id }, - }) - const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) + }); + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); dispatch({ type: "ADD_TOAST", @@ -154,36 +149,38 @@ function toast({ ...props }: Toast) { id, open: true, onOpenChange: (open) => { - if (!open) dismiss() + if (!open) { + dismiss(); + } }, }, - }) + }); return { id: id, dismiss, update, - } + }; } function useToast() { - const [state, setState] = React.useState(memoryState) + const [state, setState] = React.useState(memoryState); React.useEffect(() => { - listeners.push(setState) + listeners.push(setState); return () => { - const index = listeners.indexOf(setState) + const index = listeners.indexOf(setState); if (index > -1) { - listeners.splice(index, 1) + listeners.splice(index, 1); } - } - }, [state]) + }; + }, [state]); return { ...state, toast, dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), - } + }; } -export { useToast, toast } +export { useToast, toast }; diff --git a/web/src/contexts/AuthContext.tsx b/web/src/contexts/AuthContext.tsx index 9f3de8c..d126388 100644 --- a/web/src/contexts/AuthContext.tsx +++ b/web/src/contexts/AuthContext.tsx @@ -1,5 +1,5 @@ -import React, { createContext, useContext, useState, useEffect } from 'react'; -import { REST_URL } from '@/config'; +import React, { createContext, useContext, useState } from "react"; +import { REST_URL } from "@/config"; interface User { documentId: string; @@ -10,7 +10,11 @@ interface User { interface AuthContextType { user: User | null; login: (identifier: string, password: string) => Promise; - register: (username: string, email: string, password: string) => Promise; + register: ( + username: string, + email: string, + password: string, + ) => Promise; logout: () => void; isLoading: boolean; } @@ -18,63 +22,82 @@ interface AuthContextType { const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: React.ReactNode }) { - const [user, setUser] = useState(null); - const [isLoading, setIsLoading] = useState(true); + const [user, setUser] = useState(() => { + const token = localStorage.getItem("jwt"); + const storedUser = localStorage.getItem("user"); - useEffect(() => { + if (!token || !storedUser) { + return null; + } + + try { + return JSON.parse(storedUser) as User; + } catch { + localStorage.removeItem("jwt"); + localStorage.removeItem("user"); + return null; + } + }); + const isLoading = false; + + /*useEffect(() => { // Check if user is already logged in - const token = localStorage.getItem('jwt'); - const storedUser = localStorage.getItem('user'); - + const token = localStorage.getItem("jwt"); + const storedUser = localStorage.getItem("user"); + if (token && storedUser) { setUser(JSON.parse(storedUser)); } setIsLoading(false); - }, []); + }, []);*/ const login = async (identifier: string, password: string) => { const response = await fetch(`${REST_URL}/auth/local`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify({ identifier, password }), }); if (!response.ok) { const error = await response.json(); - throw new Error(error.error?.message || 'Login failed'); + throw new Error(error.error?.message || "Login failed"); } const data = await response.json(); - localStorage.setItem('jwt', data.jwt); - localStorage.setItem('user', JSON.stringify(data.user)); + localStorage.setItem("jwt", data.jwt); + localStorage.setItem("user", JSON.stringify(data.user)); setUser(data.user); }; - const register = async (username: string, email: string, password: string) => { + const register = async ( + username: string, + email: string, + password: string, + ) => { const response = await fetch(`${REST_URL}/auth/local/register`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify({ username, email, password }), }); if (!response.ok) { const error = await response.json(); - throw new Error(error.error?.message || 'Registration failed'); + throw new Error(error.error?.message || "Registration failed"); } const data = await response.json(); - localStorage.setItem('jwt', data.jwt); - localStorage.setItem('user', JSON.stringify(data.user)); + localStorage.setItem("jwt", data.jwt); + localStorage.setItem("user", JSON.stringify(data.user)); setUser(data.user); }; const logout = () => { - localStorage.removeItem('jwt'); - localStorage.removeItem('user'); + localStorage.removeItem("jwt"); + localStorage.removeItem("user"); setUser(null); }; @@ -88,7 +111,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { export function useAuth() { const context = useContext(AuthContext); if (context === undefined) { - throw new Error('useAuth must be used within an AuthProvider'); + throw new Error("useAuth must be used within an AuthProvider"); } return context; } diff --git a/web/src/pages/CompetePage.tsx b/web/src/pages/CompetePage.tsx index 747a353..d542597 100644 --- a/web/src/pages/CompetePage.tsx +++ b/web/src/pages/CompetePage.tsx @@ -1,17 +1,31 @@ -import { useState, useEffect, useRef } from 'react'; -import { useParams, Link } from 'react-router-dom'; -import Editor from '@monaco-editor/react'; -import { Button } from '@/components/ui/button'; -import { Card } from '@/components/ui/card'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; -import { Separator } from '@/components/ui/separator'; -import { Badge } from '@/components/ui/badge'; -import { useToast } from '@/components/ui/use-toast'; -import { ArrowLeft, Play, CheckCircle2, XCircle, Clock, Loader2, AlertCircle } from 'lucide-react'; -import { cn } from '@/lib/utils'; -import { REST_URL } from '@/config'; -import Markdown from '@/components/Markdown'; +import { useState, useEffect, useRef } from "react"; +import { useParams, Link } from "react-router-dom"; +import Editor from "@monaco-editor/react"; +import { Button } from "@/components/ui/button"; +import { Card } from "@/components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Separator } from "@/components/ui/separator"; +import { Badge } from "@/components/ui/badge"; +import { useToast } from "@/components/ui/use-toast"; +import { + ArrowLeft, + Play, + CheckCircle2, + XCircle, + Clock, + Loader2, + AlertCircle, +} from "lucide-react"; +import { cn } from "@/lib/utils"; +import { REST_URL } from "@/config"; +import Markdown from "@/components/Markdown"; interface Problem { title: string; @@ -32,6 +46,12 @@ interface TestCase { explanation?: string; } +interface Language { + documentId: string; + name: string; + codeName: string; +} + interface Execution { documentId: string; stdout: string; @@ -61,38 +81,47 @@ interface Submission { export default function CompetePage() { const { problemId } = useParams(); const { toast } = useToast(); - const [code, setCode] = useState('// Write your solution here\n'); - const [selectedLanguage, setSelectedLanguage] = useState(''); + const [code, setCode] = useState("// Write your solution here\n"); + const [selectedLanguage, setSelectedLanguage] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); const [problem, setProblem] = useState(null); - const [languages, setLanguages] = useState([]); + const [languages, setLanguages] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [submissions, setSubmissions] = useState([]); - const [activeTab, setActiveTab] = useState('description'); - const pollingIntervalRef = useRef | null>(null); + const [activeTab, setActiveTab] = useState("description"); + const pollingIntervalRef = useRef | null>( + null, + ); const initialCodeLoadedRef = useRef(false); // Fetch submissions from API const fetchSubmissions = async (loadCodeFromSubmission = false) => { try { - const token = localStorage.getItem('jwt'); + const token = localStorage.getItem("jwt"); const headers = { - Authorization: token ? `Bearer ${token}` : '', + Authorization: token ? `Bearer ${token}` : "", }; const submissionsRes = await fetch( `${REST_URL}/submissions?filters[problem][documentId][$eq]=${problemId}&populate[language]=*&populate[executions][populate][testCase][fields][0]=documentId&populate[executions][populate][testCase][fields][1]=input&populate[executions][populate][testCase][fields][2]=output&populate[executions][populate][testCase][fields][3]=hidden&sort=createdAt:desc`, - { headers } + { headers }, ); if (submissionsRes.ok) { const submissionsData = await submissionsRes.json(); - const submissionsArray = Array.isArray(submissionsData) ? submissionsData : (submissionsData.data || []); + const submissionsArray = Array.isArray(submissionsData) + ? submissionsData + : submissionsData.data || []; setSubmissions(submissionsArray); - + // Load code from latest submission only on initial load or when explicitly requested - if (loadCodeFromSubmission && submissionsArray.length > 0 && submissionsArray[0].code && !initialCodeLoadedRef.current) { + if ( + loadCodeFromSubmission && + submissionsArray.length > 0 && + submissionsArray[0].code && + !initialCodeLoadedRef.current + ) { setCode(submissionsArray[0].code); if (submissionsArray[0].language?.documentId) { setSelectedLanguage(submissionsArray[0].language.documentId); @@ -101,16 +130,16 @@ export default function CompetePage() { } } } catch (err) { - console.error('Failed to fetch submissions:', err); + console.error("Failed to fetch submissions:", err); } }; useEffect(() => { const fetchData = async () => { try { - const token = localStorage.getItem('jwt'); + const token = localStorage.getItem("jwt"); const headers = { - Authorization: token ? `Bearer ${token}` : '', + Authorization: token ? `Bearer ${token}` : "", }; const [problemRes, languagesRes] = await Promise.all([ @@ -119,24 +148,32 @@ export default function CompetePage() { ]); if (!problemRes.ok || !languagesRes.ok) { - throw new Error('HTTP error fetching data'); + throw new Error("HTTP error fetching data"); } const problemData = await problemRes.json(); const languagesData = await languagesRes.json(); - - console.log('Problem API response:', problemData); - console.log('Languages API response:', languagesData); + + console.log("Problem API response:", problemData); + console.log("Languages API response:", languagesData); // Handle both wrapped and unwrapped responses setProblem(problemData.data || problemData); - setLanguages(Array.isArray(languagesData) ? languagesData : (languagesData.data || [])); - + + const fetchedLanguages: Language[] = Array.isArray(languagesData) + ? languagesData + : languagesData.data || []; + setLanguages(fetchedLanguages); + + setSelectedLanguage( + (current) => current || fetchedLanguages[0]?.documentId || "", + ); + // Fetch user's submissions and load code from latest submission await fetchSubmissions(true); } catch (err) { - console.error('Failed to load problem:', err); - setError('Failed to load problem'); + console.error("Failed to load problem:", err); + setError("Failed to load problem"); } finally { setLoading(false); } @@ -147,38 +184,34 @@ export default function CompetePage() { const testCases = problem?.testCases || []; const publicTestCases = testCases.filter((tc: TestCase) => !tc.hidden); - useEffect(() => { - if (languages.length > 0 && !selectedLanguage) { - setSelectedLanguage(languages[0].documentId); - } - }, [languages, selectedLanguage]); - // Keyboard shortcuts for tab switching (Cmd/Ctrl+Enter handled in Monaco editor) useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { // Alt+1, Alt+2, Alt+3 for tab switching - if (e.altKey && ['1', '2', '3'].includes(e.key)) { + if (e.altKey && ["1", "2", "3"].includes(e.key)) { e.preventDefault(); const tabMap: Record = { - '1': 'description', - '2': 'testcases', - '3': 'results', + "1": "description", + "2": "testcases", + "3": "results", }; setActiveTab(tabMap[e.key]); } }; - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); }, []); // Poll submissions for updates useEffect(() => { - if (submissions.length === 0) return; + if (submissions.length === 0) { + return; + } // Check if any submission has unprocessed executions - const hasUnprocessed = submissions.some(sub => - sub.executions?.some(exec => !exec.processed) + const hasUnprocessed = submissions.some((sub) => + sub.executions?.some((exec) => !exec.processed), ); if (!hasUnprocessed) { @@ -191,22 +224,26 @@ export default function CompetePage() { const pollSubmissions = async () => { await fetchSubmissions(); - + // Check if all done and show toast - const updatedHasUnprocessed = submissions.some(sub => - sub.executions?.some(exec => !exec.processed) + const updatedHasUnprocessed = submissions.some((sub) => + sub.executions?.some((exec) => !exec.processed), ); - + if (!updatedHasUnprocessed && submissions.length > 0) { const latestSub = submissions[0]; if (latestSub.executions) { - const passed = latestSub.executions.filter((exec: Execution) => - exec.stdout?.trim() === exec.testCase?.output?.trim() + const passed = latestSub.executions.filter( + (exec: Execution) => + exec.stdout?.trim() === exec.testCase?.output?.trim(), ).length; toast({ - title: 'Execution Complete', + title: "Execution Complete", description: `${passed}/${latestSub.executions.length} test cases passed`, - variant: passed === latestSub.executions.length ? 'default' : 'destructive', + variant: + passed === latestSub.executions.length + ? "default" + : "destructive", }); } } @@ -224,24 +261,24 @@ export default function CompetePage() { const handleSubmit = async () => { if (!selectedLanguage) { toast({ - title: 'No language selected', - description: 'Please select a programming language', - variant: 'destructive', + title: "No language selected", + description: "Please select a programming language", + variant: "destructive", }); return; } setIsSubmitting(true); try { - const token = localStorage.getItem('jwt'); + const token = localStorage.getItem("jwt"); const headers = { - 'Content-Type': 'application/json', - Authorization: token ? `Bearer ${token}` : '', + "Content-Type": "application/json", + Authorization: token ? `Bearer ${token}` : "", }; // Create submission const submissionRes = await fetch(`${REST_URL}/submissions`, { - method: 'POST', + method: "POST", headers, body: JSON.stringify({ data: { @@ -256,30 +293,33 @@ export default function CompetePage() { const submissionId = submissionData.data.documentId; // Submit for execution - const submitRes = await fetch(`${REST_URL}/submissions/submit?id=${submissionId}`, { - headers, - }); + const submitRes = await fetch( + `${REST_URL}/submissions/submit?id=${submissionId}`, + { + headers, + }, + ); const submitData = await submitRes.json(); - console.log('Submit response:', submitData); + console.log("Submit response:", submitData); if (submitData.executions && submitData.executions.length > 0) { // Fetch updated submissions await fetchSubmissions(); // Switch to submissions tab - setActiveTab('results'); + setActiveTab("results"); toast({ - title: 'Submitted!', - description: 'Your code is being executed...', + title: "Submitted!", + description: "Your code is being executed...", }); } else { - throw new Error('No executions returned'); + throw new Error("No executions returned"); } } catch (err) { toast({ - title: 'Submission failed', - description: err instanceof Error ? err.message : 'Please try again', - variant: 'destructive', + title: "Submission failed", + description: err instanceof Error ? err.message : "Please try again", + variant: "destructive", }); } finally { setIsSubmitting(false); @@ -297,12 +337,16 @@ export default function CompetePage() { if (error || !problem) { return (
-

Failed to load problem. Please try again later.

+

+ Failed to load problem. Please try again later. +

); } - const selectedLang = languages.find((l: any) => l.documentId === selectedLanguage); + const selectedLang = languages.find( + (language) => language.documentId === selectedLanguage, + ); return (
@@ -314,9 +358,7 @@ export default function CompetePage() { -

- {problem.title} -

+

{problem.title}

@@ -342,51 +384,73 @@ export default function CompetePage() {
{/* Left Panel - Problem Description */} - +
- Problem - Tests + + Problem + + + Tests + Results {submissions.length > 0 && ( - ({submissions.length}) + + ({submissions.length}) + )}
- +
- +
- + - +
- {testCases.length} test cases ({publicTestCases.length} visible) + {testCases.length} test cases ({publicTestCases.length}{" "} + visible)
- +
{publicTestCases.length === 0 ? ( -

No public test cases available

+

+ No public test cases available +

) : ( - publicTestCases.map((tc: any, index: number) => ( -
-
Test {index + 1}
+ publicTestCases.map((tc, index: number) => ( +
+
+ Test {index + 1} +
-
Input
+
+ Input +
                             {tc.input}
                           
-
Expected
+
+ Expected +
                             {tc.output}
                           
@@ -396,7 +460,7 @@ export default function CompetePage() { )}
- +
{submissions.length === 0 ? ( @@ -409,9 +473,13 @@ export default function CompetePage() { ) : ( submissions.map((submission, subIndex) => { const executions = submission.executions || []; - const hasUnprocessed = executions.some(exec => !exec.processed); - const passedCount = executions.filter((exec: Execution) => - exec.processed && exec.stdout?.trim() === exec.testCase?.output?.trim() + const hasUnprocessed = executions.some( + (exec) => !exec.processed, + ); + const passedCount = executions.filter( + (exec: Execution) => + exec.processed && + exec.stdout?.trim() === exec.testCase?.output?.trim(), ).length; return ( @@ -422,23 +490,29 @@ export default function CompetePage() { #{submissions.length - subIndex}

- {new Date(submission.createdAt).toLocaleTimeString()} • {submission.language?.name} + {new Date( + submission.createdAt, + ).toLocaleTimeString()}{" "} + • {submission.language?.name}

{hasUnprocessed ? ( - + Running ) : ( - {passedCount}/{executions.length} @@ -449,26 +523,34 @@ export default function CompetePage() {
{executions.map((execution, index) => { - const isPassed = execution.processed && - execution.stdout?.trim() === execution.testCase?.output?.trim(); + const isPassed = + execution.processed && + execution.stdout?.trim() === + execution.testCase?.output?.trim(); const isFailed = execution.processed && !isPassed; const isRunning = !execution.processed; return ( -
- {execution.testCase?.hidden ? 'Hidden' : ''} Test {index + 1} + {execution.testCase?.hidden + ? "Hidden" + : ""}{" "} + Test {index + 1} {isRunning && ( - + )} @@ -479,45 +561,57 @@ export default function CompetePage() { )}
- + {execution.processed && (
{!execution.testCase?.hidden && ( <>
-
Input
+
+ Input +
                                               {execution.testCase?.input}
                                             
-
Expected
+
+ Expected +
                                               {execution.testCase?.output}
                                             
)} - +
-
Output
-
-                                          {execution.stdout || '(empty)'}
+                                        
+ Output +
+
+                                          {execution.stdout || "(empty)"}
                                         
- + {execution.stderr && (
-
Error
+
+ Error +
                                             {execution.stderr}
                                           
)} - + {execution.executionTime >= 0 && (
@@ -543,19 +637,21 @@ export default function CompetePage() { {/* Right Panel - Code Editor */}
- Editor + + Editor +
setCode(value || '')} + onChange={(value) => setCode(value || "")} theme="vs-dark" options={{ minimap: { enabled: false }, fontSize: 13, - lineNumbers: 'on', + lineNumbers: "on", roundedSelection: false, scrollBeyondLastLine: false, automaticLayout: true, @@ -563,9 +659,12 @@ export default function CompetePage() { padding: { top: 12 }, }} onMount={(editor, monaco) => { - editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { - handleSubmit(); - }); + editor.addCommand( + monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, + () => { + handleSubmit(); + }, + ); }} />
@@ -576,19 +675,21 @@ export default function CompetePage() { } function getEditorLanguage(codeName: string | undefined): string { - if (!codeName) return 'javascript'; - + if (!codeName) { + return "javascript"; + } + const languageMap: Record = { - 'python': 'python', - 'javascript': 'javascript', - 'typescript': 'typescript', - 'java': 'java', - 'cpp': 'cpp', - 'c': 'c', - 'csharp': 'csharp', - 'go': 'go', - 'rust': 'rust', + python: "python", + javascript: "javascript", + typescript: "typescript", + java: "java", + cpp: "cpp", + c: "c", + csharp: "csharp", + go: "go", + rust: "rust", }; - - return languageMap[codeName] || 'javascript'; + + return languageMap[codeName] || "javascript"; } diff --git a/web/src/pages/EventDetailPage.tsx b/web/src/pages/EventDetailPage.tsx index 214182e..1b91a81 100644 --- a/web/src/pages/EventDetailPage.tsx +++ b/web/src/pages/EventDetailPage.tsx @@ -1,12 +1,25 @@ -import { useState, useEffect } from 'react'; -import { useParams, Link } from 'react-router-dom'; -import { Badge } from '@/components/ui/badge'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; -import { ArrowLeft, Circle, ChevronRight, FileText, Trophy } from 'lucide-react'; -import { REST_URL } from '@/config'; -import Markdown from '@/components/Markdown'; -import { cn } from '@/lib/utils'; +import { useState, useEffect } from "react"; +import { useParams, Link } from "react-router-dom"; +import { Badge } from "@/components/ui/badge"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { + ArrowLeft, + Circle, + ChevronRight, + FileText, + Trophy, +} from "lucide-react"; +import { REST_URL } from "@/config"; +import Markdown from "@/components/Markdown"; +import { cn } from "@/lib/utils"; interface Problem { documentId: string; @@ -30,22 +43,28 @@ interface Event { function getTimeRemaining(date: Date): string { const now = new Date(); const diff = date.getTime() - now.getTime(); - - if (diff < 0) return '0:00:00'; - + + if (diff < 0) { + return "0:00:00"; + } + const hours = Math.floor(diff / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((diff % (1000 * 60)) / 1000); - - return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; + + return `${hours}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`; } function getDifficultyColor(difficulty?: string) { switch (difficulty?.toLowerCase()) { - case 'easy': return 'text-emerald-500'; - case 'medium': return 'text-amber-500'; - case 'hard': return 'text-red-500'; - default: return 'text-muted-foreground'; + case "easy": + return "text-emerald-500"; + case "medium": + return "text-amber-500"; + case "hard": + return "text-red-500"; + default: + return "text-muted-foreground"; } } @@ -54,29 +73,32 @@ export default function EventDetailPage() { const [event, setEvent] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [activeTab, setActiveTab] = useState('problems'); - const [timeRemaining, setTimeRemaining] = useState(''); + const [activeTab, setActiveTab] = useState("problems"); + const [timeRemaining, setTimeRemaining] = useState(""); useEffect(() => { const fetchEvent = async () => { try { - const token = localStorage.getItem('jwt'); - const response = await fetch(`${REST_URL}/events/${eventId}?populate=*`, { - headers: { - Authorization: token ? `Bearer ${token}` : '', + const token = localStorage.getItem("jwt"); + const response = await fetch( + `${REST_URL}/events/${eventId}?populate=*`, + { + headers: { + Authorization: token ? `Bearer ${token}` : "", + }, }, - }); - + ); + if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } - + const data = await response.json(); const eventData = data.data || data; setEvent(eventData); } catch (err) { - console.error('Failed to load event:', err); - setError('Failed to load event'); + console.error("Failed to load event:", err); + setError("Failed to load event"); } finally { setLoading(false); } @@ -86,13 +108,15 @@ export default function EventDetailPage() { // Timer effect useEffect(() => { - if (!event) return; - + if (!event) { + return; + } + const endDate = new Date(event.end); const updateTimer = () => { setTimeRemaining(getTimeRemaining(endDate)); }; - + updateTimer(); const interval = setInterval(updateTimer, 1000); return () => clearInterval(interval); @@ -126,51 +150,70 @@ export default function EventDetailPage() {
{/* Header */}
- Back to contests - +
-

{event.title}

+

+ {event.title} +

{isActive && ( - LIVE + + LIVE + )} - {isUpcoming && ( - Upcoming - )} + {isUpcoming && Upcoming} {isEnded && ( - Ended + + Ended + )}
- +
- {startDate.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })} - {' · '} - {startDate.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} - {' – '} - {endDate.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} + {startDate.toLocaleDateString(undefined, { + weekday: "short", + month: "short", + day: "numeric", + })} + {" · "} + {startDate.toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + })} + {" – "} + {endDate.toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + })} · - {problems.length} {problems.length === 1 ? 'problem' : 'problems'} + + {problems.length}{" "} + {problems.length === 1 ? "problem" : "problems"} +
{isActive && (
-
Time Remaining
+
+ Time Remaining +
{timeRemaining}
@@ -193,7 +236,9 @@ export default function EventDetailPage() {

No problems yet

- {isUpcoming ? 'Problems will be revealed when the contest starts' : 'No problems have been added to this contest'} + {isUpcoming + ? "Problems will be revealed when the contest starts" + : "No problems have been added to this contest"}

) : ( @@ -203,7 +248,9 @@ export default function EventDetailPage() { # Problem - Difficulty + + Difficulty + Points Status @@ -211,16 +258,18 @@ export default function EventDetailPage() { {problems.map((problem, index) => ( - window.location.href = `/compete/${problem.documentId}`} + onClick={() => + (window.location.href = `/compete/${problem.documentId}`) + } > {index + 1} - e.stopPropagation()} @@ -234,12 +283,17 @@ export default function EventDetailPage() { )} - - {problem.difficulty || '—'} + + {problem.difficulty || "—"} - {problem.points ?? 'N/A'} + {problem.points ?? "N/A"} @@ -262,21 +316,30 @@ export default function EventDetailPage() {
) : ( -

No description provided.

+

+ No description provided. +

)} - {event.supportedLanguages && event.supportedLanguages.length > 0 && ( -
-

Supported Languages

-
- {event.supportedLanguages.map((lang: any) => ( - - {lang.name} - - ))} + {event.supportedLanguages && + event.supportedLanguages.length > 0 && ( +
+

+ Supported Languages +

+
+ {event.supportedLanguages.map((lang: any) => ( + + {lang.name} + + ))} +
-
- )} + )}
diff --git a/web/src/pages/EventsPage.tsx b/web/src/pages/EventsPage.tsx index 5fb7759..921c30a 100644 --- a/web/src/pages/EventsPage.tsx +++ b/web/src/pages/EventsPage.tsx @@ -1,9 +1,9 @@ -import { useState, useEffect } from 'react'; -import { Badge } from '@/components/ui/badge'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -import { Calendar, Clock, ChevronRight } from 'lucide-react'; -import { Link } from 'react-router-dom'; -import { REST_URL } from '@/config'; +import { useState, useEffect } from "react"; +import { Badge } from "@/components/ui/badge"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Calendar, Clock, ChevronRight } from "lucide-react"; +import { Link } from "react-router-dom"; +import { REST_URL } from "@/config"; interface Event { documentId: string; @@ -20,15 +20,15 @@ interface Event { function getTimeRemaining(date: Date): string { const now = new Date(); const diff = date.getTime() - now.getTime(); - - if (diff < 0) return 'Started'; - + + if (diff < 0) {return "Started";} + const days = Math.floor(diff / (1000 * 60 * 60 * 24)); const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); - - if (days > 0) return `${days}d ${hours}h`; - if (hours > 0) return `${hours}h ${minutes}m`; + + if (days > 0) {return `${days}d ${hours}h`;} + if (hours > 0) {return `${hours}h ${minutes}m`;} return `${minutes}m`; } @@ -36,38 +36,50 @@ function formatDuration(start: Date, end: Date): string { const diff = end.getTime() - start.getTime(); const hours = Math.floor(diff / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); - - if (hours > 0 && minutes > 0) return `${hours}h ${minutes}m`; - if (hours > 0) return `${hours}h`; + + if (hours > 0 && minutes > 0) {return `${hours}h ${minutes}m`;} + if (hours > 0) {return `${hours}h`;} return `${minutes}m`; } +interface EmptyStateProps { + message: string; +} + +function EmptyState({ message }: EmptyStateProps) { + return ( +
+

{message}

+
+ ); +} + export default function EventsPage() { const [events, setEvents] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [activeTab, setActiveTab] = useState('active'); + const [activeTab, setActiveTab] = useState("active"); useEffect(() => { const fetchEvents = async () => { try { - const token = localStorage.getItem('jwt'); + const token = localStorage.getItem("jwt"); const response = await fetch(`${REST_URL}/events?populate=*`, { headers: { - Authorization: token ? `Bearer ${token}` : '', + Authorization: token ? `Bearer ${token}` : "", }, }); - + if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } - + const data = await response.json(); - const eventsData = Array.isArray(data) ? data : (data.data || []); + const eventsData = Array.isArray(data) ? data : data.data || []; setEvents(eventsData); } catch (err) { - console.error('Failed to load events:', err); - setError('Failed to load events'); + console.error("Failed to load events:", err); + setError("Failed to load events"); } finally { setLoading(false); } @@ -76,13 +88,13 @@ export default function EventsPage() { }, []); const now = new Date(); - const activeEvents = events.filter(e => { + const activeEvents = events.filter((e) => { const start = new Date(e.start); const end = new Date(e.end); return now >= start && now <= end; }); - const upcomingEvents = events.filter(e => new Date(e.start) > now); - const pastEvents = events.filter(e => new Date(e.end) < now); + const upcomingEvents = events.filter((e) => new Date(e.start) > now); + const pastEvents = events.filter((e) => new Date(e.end) < now); if (loading) { return ( @@ -108,10 +120,7 @@ export default function EventsPage() { const problemCount = event.problems?.length || 0; return ( - +
@@ -125,16 +134,22 @@ export default function EventsPage() { - LIVE + + LIVE + )}
- +
- {startDate.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })} + {startDate.toLocaleDateString(undefined, { + month: "short", + day: "numeric", + year: "numeric", + })}
@@ -143,22 +158,29 @@ export default function EventsPage() {
{problemCount} - {problemCount === 1 ? 'problem' : 'problems'} + {problemCount === 1 ? "problem" : "problems"}
- {event.supportedLanguages && event.supportedLanguages.length > 0 && ( -
- {event.supportedLanguages.slice(0, 5).map((lang: any) => ( - - {lang.name} - - ))} - {event.supportedLanguages.length > 5 && ( - +{event.supportedLanguages.length - 5} - )} -
- )} + {event.supportedLanguages && + event.supportedLanguages.length > 0 && ( +
+ {event.supportedLanguages.slice(0, 5).map((lang: any) => ( + + {lang.name} + + ))} + {event.supportedLanguages.length > 5 && ( + + +{event.supportedLanguages.length - 5} + + )} +
+ )}
@@ -186,12 +208,6 @@ export default function EventsPage() { ); }; - const EmptyState = ({ message }: { message: string }) => ( -
-

{message}

-
- ); - return (
@@ -226,7 +242,9 @@ export default function EventsPage() { {activeEvents.length === 0 ? ( ) : ( - activeEvents.map(event => ) + activeEvents.map((event) => ( + + )) )} @@ -234,7 +252,9 @@ export default function EventsPage() { {upcomingEvents.length === 0 ? ( ) : ( - upcomingEvents.map(event => ) + upcomingEvents.map((event) => ( + + )) )} @@ -242,7 +262,9 @@ export default function EventsPage() { {pastEvents.length === 0 ? ( ) : ( - pastEvents.map(event => ) + pastEvents.map((event) => ( + + )) )} From a542cae9989475f9188cb0a0caadc40cd5b84820 Mon Sep 17 00:00:00 2001 From: Ivan Zanov Date: Fri, 21 Aug 2026 10:07:14 +0200 Subject: [PATCH 02/12] chore: update root tooling dependencies --- package-lock.json | 3503 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 3492 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 64c6463..f3128a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,1452 @@ "name": "colosseum", "version": "1.0.0", "devDependencies": { - "husky": "^9.0.10" + "@eslint/js": "^10.0.1", + "@types/node": "^26.2.0", + "concurrently": "^9.2.4", + "eslint": "^10.8.1", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.4", + "globals": "^17.11.0", + "husky": "^9.0.10", + "typescript-eslint": "^8.67.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", + "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz", + "integrity": "sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/type-utils": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.67.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.67.0.tgz", + "integrity": "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz", + "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz", + "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz", + "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz", + "integrity": "sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz", + "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz", + "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz", + "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz", + "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.15", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.15.tgz", + "integrity": "sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concurrently": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.4.tgz", + "integrity": "sha512-TZ0CEhyzvFjgtAvHTusDMgj7wNdihCh7LLLrzdUOXIhdlnL2JBBGA9eJxR24rtqgmdjh3OA3hrN1rCHj6HM8qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.9.0", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.411", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.411.tgz", + "integrity": "sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz", + "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==", + "dev": true, + "license": "MIT", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.4.tgz", + "integrity": "sha512-7bqTKz7T0r+HKWFarNXByDE9/5+73wI2ru+M3zuqGbR7s/b/5/pQJXZoufWlrngqGqoZto73ZkGumCdLxk+4rw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": "^9 || ^10" + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "17.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.11.0.tgz", + "integrity": "sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" } }, "node_modules/husky": { @@ -16,23 +1461,2059 @@ "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.10.tgz", "integrity": "sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA==", "dev": true, - "bin": { - "husky": "bin.mjs" - }, - "engines": { - "node": ">=18" + "bin": { + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.9.0.tgz", + "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.67.0.tgz", + "integrity": "sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.67.0", + "@typescript-eslint/parser": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + } + }, + "@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true + }, + "@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + } + }, + "@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "requires": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true + }, + "@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "requires": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + } + }, + "@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "requires": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + } + }, + "@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "requires": { + "@babel/types": "^7.29.8" + } + }, + "@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + } + }, + "@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + } + }, + "@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + } + }, + "@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.4.3" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + } + } + }, + "@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true + }, + "@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "requires": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + } + }, + "@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "dev": true, + "requires": { + "@eslint/core": "^1.2.1" + } + }, + "@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.15" + } + }, + "@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "requires": {} + }, + "@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true + }, + "@eslint/plugin-kit": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "dev": true, + "requires": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + } + }, + "@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "requires": { + "@humanfs/types": "^0.15.0" + } + }, + "@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "requires": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + } + }, + "@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true + }, + "@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "@types/node": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", + "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", + "dev": true, + "requires": { + "undici-types": "~8.3.0" + } + }, + "@typescript-eslint/eslint-plugin": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz", + "integrity": "sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/type-utils": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "dependencies": { + "ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true + } + } + }, + "@typescript-eslint/parser": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.67.0.tgz", + "integrity": "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3" + } + }, + "@typescript-eslint/project-service": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz", + "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==", + "dev": true, + "requires": { + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", + "debug": "^4.4.3" + } + }, + "@typescript-eslint/scope-manager": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz", + "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0" + } + }, + "@typescript-eslint/tsconfig-utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz", + "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==", + "dev": true, + "requires": {} + }, + "@typescript-eslint/type-utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz", + "integrity": "sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + } + }, + "@typescript-eslint/types": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz", + "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz", + "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==", + "dev": true, + "requires": { + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "dependencies": { + "semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true + } + } + }, + "@typescript-eslint/utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz", + "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz", + "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.67.0", + "eslint-visitor-keys": "^5.0.0" + } + }, + "acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true + }, + "baseline-browser-mapping": { + "version": "2.11.15", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.15.tgz", + "integrity": "sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA==", + "dev": true + }, + "brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "requires": { + "balanced-match": "^4.0.2" + } + }, + "browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, + "requires": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "funding": { - "url": "https://github.com/sponsors/typicode" + "dependencies": { + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } - } - }, - "dependencies": { + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concurrently": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.4.tgz", + "integrity": "sha512-TZ0CEhyzvFjgtAvHTusDMgj7wNdihCh7LLLrzdUOXIhdlnL2JBBGA9eJxR24rtqgmdjh3OA3hrN1rCHj6HM8qA==", + "dev": true, + "requires": { + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.9.0", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + } + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.5.411", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.411.tgz", + "integrity": "sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz", + "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + } + }, + "eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "requires": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + } + }, + "eslint-plugin-react-refresh": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.4.tgz", + "integrity": "sha512-7bqTKz7T0r+HKWFarNXByDE9/5+73wI2ru+M3zuqGbR7s/b/5/pQJXZoufWlrngqGqoZto73ZkGumCdLxk+4rw==", + "dev": true, + "requires": {} + }, + "eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "requires": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true + }, + "espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "requires": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + } + }, + "esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "requires": {} + }, + "file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "requires": { + "flat-cache": "^4.0.0" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + } + }, + "flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "17.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.11.0.tgz", + "integrity": "sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true + }, + "hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "requires": { + "hermes-estree": "0.25.1" + } + }, "husky": { "version": "9.0.10", "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.10.tgz", "integrity": "sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA==", "dev": true + }, + "ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "requires": { + "brace-expansion": "^5.0.8" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true + }, + "optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shell-quote": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.9.0.tgz", + "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "requires": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "requires": {} + }, + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "peer": true + }, + "typescript-eslint": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.67.0.tgz", + "integrity": "sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "8.67.0", + "@typescript-eslint/parser": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0" + } + }, + "undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "dev": true, + "requires": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + }, + "zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true + }, + "zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "requires": {} } } } From 8f3b583050275f07b5117290c209e4c1d38bf637 Mon Sep 17 00:00:00 2001 From: Ivan Zanov Date: Mon, 24 Aug 2026 11:24:04 +0200 Subject: [PATCH 03/12] configure eslint and prettier --- .editorconfig | 12 + .prettierignore | 31 + eslint.config.mjs | 151 ++- executioner/languages/docker.ts | 107 +- lib/queue/src/amqp.ts | 35 +- lint-staged.config.mjs | 5 + package-lock.json | 935 ++++++++++++++++++ package.json | 14 + prettier.config.mjs | 13 + senatus/config/admin.ts | 12 +- senatus/config/database.ts | 38 +- senatus/config/plugin.ts | 10 +- senatus/config/server.ts | 18 +- .../api/submission/controllers/submission.ts | 311 +++--- web/src/pages/CompetePage.tsx | 336 +++---- web/src/pages/EventDetailPage.tsx | 152 ++- web/src/pages/EventsPage.tsx | 108 +- web/src/types.ts | 4 + web/tailwind.config.js | 68 +- 19 files changed, 1619 insertions(+), 741 deletions(-) create mode 100644 .editorconfig create mode 100644 .prettierignore create mode 100644 lint-staged.config.mjs create mode 100644 prettier.config.mjs create mode 100644 web/src/types.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1014ba7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..542e864 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,31 @@ +# Dependencies +**/node_modules/** + +# Build output +**/dist/** +**/build/** + +# Tool caches +**/.cache/** +**/.tmp/** +**/.strapi/** +**/coverage/** + +# Generated GraphQL code +**/src/__generated__/** + +# Generated Strapi code +senatus/types/generated/** +senatus/.strapi-updater.json + +# Generated Strapi documentation +senatus/src/extensions/documentation/documentation/** +senatus/src/extensions/documentation/public/** + +# Package manager generated files +**/package-lock.json + +# Minified/generated assets +**/*.min.js +**/*.min.css +clear diff --git a/eslint.config.mjs b/eslint.config.mjs index 6aadd23..d5122c1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,30 +1,33 @@ -import js from "@eslint/js"; -import globals from "globals"; -import tseslint from "typescript-eslint"; -import reactHooks from "eslint-plugin-react-hooks"; -import reactRefresh from "eslint-plugin-react-refresh"; +import js from '@eslint/js'; +import { defineConfig, globalIgnores } from 'eslint/config'; +import eslintConfigPrettier from 'eslint-config-prettier'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import globals from 'globals'; +import tseslint from 'typescript-eslint'; -export default [ - { - ignores: [ - "**/node_modules/**", - "**/dist/**", - "**/build/**", - "**/.cache/**", - "**/.strapi/**", - "**/.tmp/**", - "**/coverage/**", - - "senatus/types/generated/**", - - // Strapi-generated/example files that aren't application code. - "senatus/src/admin/*.example.*", - ], - }, +export default defineConfig([ + globalIgnores([ + '**/node_modules/**', + '**/dist/**', + '**/build/**', + '**/.cache/**', + '**/.strapi/**', + '**/.tmp/**', + '**/coverage/**', + + '**/src/__generated__/**', + + 'senatus/types/generated/**', + + 'senatus/src/admin/*.example.*', + + 'senatus/src/extensions/documentation/documentation/**', + ]), { linterOptions: { - reportUnusedDisableDirectives: "error", + reportUnusedDisableDirectives: 'error', }, }, @@ -33,61 +36,50 @@ export default [ ...tseslint.configs.recommended, { - files: ["**/*.{js,mjs,cjs,ts,tsx}"], + files: ['**/*.{js,mjs,cjs,ts,tsx}'], rules: { - // Avoid coercion bugs. - eqeqeq: ["error", "always"], + eqeqeq: ['error', 'always'], - // Require braces around control-flow statements. - curly: ["error", "all"], + curly: ['error', 'all'], - // Avoid duplicate imports from the same module. - "no-duplicate-imports": [ - "error", + 'no-duplicate-imports': [ + 'error', { allowSeparateTypeImports: true, }, ], - // Modern JavaScript basics. - "no-var": "error", - "prefer-const": "error", - "@typescript-eslint/no-require-imports": "off", + 'no-var': 'error', + + 'prefer-const': 'error', + + 'no-debugger': 'error', }, }, - { - files: ["**/*.{ts,tsx}"], + files: ['**/*.{ts,tsx}'], rules: { - "@typescript-eslint/no-unused-vars": [ - "error", + '@typescript-eslint/no-unused-vars': [ + 'error', { - argsIgnorePattern: "^_", - varsIgnorePattern: "^_", - caughtErrorsIgnorePattern: "^_", + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + ignoreRestSiblings: true, }, ], - // Keep visible, but don't block existing code. - "@typescript-eslint/no-explicit-any": "warn", - - // Allow both `type` and `interface`. - "@typescript-eslint/consistent-type-definitions": "off", - - // Variable shadowing is allowed for now. - "@typescript-eslint/no-shadow": "off", - "no-shadow": "off", - - // Existing CommonJS require() imports are allowed. - "@typescript-eslint/no-require-imports": "off", + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/consistent-type-definitions': 'off', + '@typescript-eslint/no-shadow': 'off', + 'no-shadow': 'off', + '@typescript-eslint/no-require-imports': 'off', }, }, - - // Browser / React application. { - files: ["web/**/*.{ts,tsx}"], + files: ['client/src/**/*.{js,jsx,ts,tsx}', 'web/src/**/*.{js,jsx,ts,tsx}'], languageOptions: { globals: { @@ -97,36 +89,32 @@ export default [ }, plugins: { - "react-hooks": reactHooks, - "react-refresh": reactRefresh, + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, }, rules: { ...reactHooks.configs.recommended.rules, - "react-refresh/only-export-components": [ - "warn", + 'react-refresh/only-export-components': [ + 'warn', { allowConstantExport: true, }, ], - - // Allow warn/error, but flag leftover console.log calls. - "no-console": [ - "warn", + 'no-console': [ + 'warn', { - allow: ["warn", "error"], + allow: ['warn', 'error'], }, ], }, }, - - // Node / backend / infrastructure code. { files: [ - "senatus/**/*.{ts,tsx}", - "executioner/**/*.ts", - "lib/queue/**/*.ts", + 'senatus/**/*.{js,mjs,cjs,ts}', + 'executioner/**/*.{js,mjs,cjs,ts}', + 'lib/queue/**/*.{js,mjs,cjs,ts}', ], languageOptions: { @@ -137,14 +125,20 @@ export default [ }, rules: { - // Backend/service logging is expected. - "no-console": "off", + 'no-console': 'off', }, }, - - // Frontend configuration files execute in Node. { - files: ["web/*.config.{js,mjs,cjs,ts}", "web/codegen.ts"], + files: [ + 'client/*.config.{js,mjs,cjs,ts}', + 'client/codegen.ts', + + 'web/*.config.{js,mjs,cjs,ts}', + 'web/codegen.ts', + + '*.config.{js,mjs,cjs,ts}', + '*.mjs', + ], languageOptions: { globals: { @@ -154,7 +148,8 @@ export default [ }, rules: { - "no-console": "off", + 'no-console': 'off', }, }, -]; + eslintConfigPrettier, +]); diff --git a/executioner/languages/docker.ts b/executioner/languages/docker.ts index cd21fe4..fd23c58 100644 --- a/executioner/languages/docker.ts +++ b/executioner/languages/docker.ts @@ -1,9 +1,9 @@ -import fs from "fs"; -import path from "path"; -import cp from "child_process"; -import { v4 } from "uuid"; +import fs from 'fs'; +import path from 'path'; +import cp from 'child_process'; +import { v4 } from 'uuid'; -import { readFile, writeFile } from "fs/promises"; +import { readFile, writeFile } from 'fs/promises'; type LanguageOptions = { [key: string]: string; @@ -15,17 +15,14 @@ type File = { id?: string; filename: string; content: string; - metadata?: any; + metadata?: unknown; }; const CPU_LIMIT_PER_EXECUTION = process.env.CPU_LIMIT_PER_EXECUTION; -const MEMORY_LIMIT_PER_EXECUTION = - process.env.MEMORY_LIMIT_PER_EXECUTION ?? "1G"; -const ENABLE_NETWORK_IN_EXECUTION = - process.env.ENABLE_NETWORK_IN_EXECUTION === "true"; -const IMAGE_BASE = - process.env.IMAGE_BASE || "ghcr.io/42dotmk/colosseum-executioner-"; -const WORKDIR = process.env.WORKDIR || "_work"; +const MEMORY_LIMIT_PER_EXECUTION = process.env.MEMORY_LIMIT_PER_EXECUTION ?? '1G'; +const ENABLE_NETWORK_IN_EXECUTION = process.env.ENABLE_NETWORK_IN_EXECUTION === 'true'; +const IMAGE_BASE = process.env.IMAGE_BASE || 'ghcr.io/42dotmk/colosseum-executioner-'; +const WORKDIR = process.env.WORKDIR || '_work'; if (!fs.existsSync(WORKDIR)) { fs.mkdirSync(WORKDIR); @@ -51,20 +48,16 @@ const readIfExists = async (path: string) => { if (fs.existsSync(path)) { return (await readFile(path)).toString(); } - return ""; + return ''; }; -export const execute = async ( - files: File[], - input: File[], - options: LanguageOptions, -) => { +export const execute = async (files: File[], input: File[], options: LanguageOptions) => { const id = v4(); const subWorkspace = path.join(WORKDIR, id); - const srcDir = path.resolve(path.join(subWorkspace, "src")); - const inputDir = path.resolve(path.join(subWorkspace, "input")); - const outputDir = path.resolve(path.join(subWorkspace, "output")); + const srcDir = path.resolve(path.join(subWorkspace, 'src')); + const inputDir = path.resolve(path.join(subWorkspace, 'input')); + const outputDir = path.resolve(path.join(subWorkspace, 'output')); const lang = options.language; if (!fs.existsSync(subWorkspace)) { @@ -92,12 +85,8 @@ export const execute = async ( const timePath = path.resolve(path.join(subWorkspace, timeFilename)); const stdoutPath = path.resolve(path.join(subWorkspace, stdoutFilename)); const stderrPath = path.resolve(path.join(subWorkspace, stderrFilename)); - const compileStdoutPath = path.resolve( - path.join(subWorkspace, compileStdoutFilename), - ); - const compileStderrPath = path.resolve( - path.join(subWorkspace, compileStderrFilename), - ); + const compileStdoutPath = path.resolve(path.join(subWorkspace, compileStdoutFilename)); + const compileStderrPath = path.resolve(path.join(subWorkspace, compileStderrFilename)); for (const file of files) { const filePath = path.resolve(path.join(srcDir, file.filename)); @@ -111,11 +100,11 @@ export const execute = async ( } try { - await writeFile(timePath, ""); - await writeFile(stdoutPath, ""); - await writeFile(stderrPath, ""); - await writeFile(compileStdoutPath, ""); - await writeFile(compileStderrPath, ""); + await writeFile(timePath, ''); + await writeFile(stdoutPath, ''); + await writeFile(stderrPath, ''); + await writeFile(compileStdoutPath, ''); + await writeFile(compileStderrPath, ''); return await new Promise((resolve) => { const extraArgs = []; @@ -128,59 +117,53 @@ export const execute = async ( } if (!ENABLE_NETWORK_IN_EXECUTION) { - extraArgs.push("--network=none"); + extraArgs.push('--network=none'); } const args = [ - "run", - "--rm", - "-v", + 'run', + '--rm', + '-v', `${srcDir}:/exc/src`, - "-v", + '-v', `${inputDir}:/exc/input`, - "-v", + '-v', `${outputDir}:/exc/output`, - "-v", + '-v', `${timePath}:/exc/${timeFilename}`, - "-v", + '-v', `${stdoutPath}:/exc/${stdoutFilename}`, - "-v", + '-v', `${stderrPath}:/exc/${stderrFilename}`, - "-v", + '-v', `${compileStdoutPath}:/exc/${compileStdoutFilename}`, - "-v", + '-v', `${compileStderrPath}:/exc/${compileStderrFilename}`, ...extraArgs, - "-i", + '-i', `${IMAGE_BASE}${lang}`, ]; - const child = cp.spawn("docker", args); - console.log(child.spawnargs.join(" ")); + const child = cp.spawn('docker', args); + console.log(child.spawnargs.join(' ')); - child.stdout.on("data", (data) => { + child.stdout.on('data', (data) => { console.log(`stdout: ${data}`); }); - child.stderr.on("data", (data) => { + child.stderr.on('data', (data) => { console.error(`stderr: ${data}`); }); - child.on("close", async (code) => { + child.on('close', async (code) => { console.log(`child process exited with code ${code}`); const output = []; for (const inp of input) { - const stdoutPath = path.resolve( - path.join(outputDir, `${inp.filename}.stdout`), - ); - const stderrPath = path.resolve( - path.join(outputDir, `${inp.filename}.stderr`), - ); - const timePath = path.resolve( - path.join(outputDir, `${inp.filename}.time`), - ); + const stdoutPath = path.resolve(path.join(outputDir, `${inp.filename}.stdout`)); + const stderrPath = path.resolve(path.join(outputDir, `${inp.filename}.stderr`)); + const timePath = path.resolve(path.join(outputDir, `${inp.filename}.time`)); const stdout = await readIfExists(stdoutPath); const stderr = await readIfExists(stderrPath); @@ -189,10 +172,10 @@ export const execute = async ( let parsedTime = null; if (time) { const timeSplits = time - .split("\n") + .split('\n') .map((t) => t.trim()) .filter((x) => x) - .map((x) => x.split("\t")); + .map((x) => x.split('\t')); const [realTime] = timeSplits; parsedTime = parseDuration(realTime[1]); if (!parsedTime) { @@ -211,7 +194,7 @@ export const execute = async ( resolve(output); }); - console.log("child", child.pid); + console.log('child', child.pid); }); } catch (e) { console.error(e); diff --git a/lib/queue/src/amqp.ts b/lib/queue/src/amqp.ts index 0250a3d..2e1904e 100644 --- a/lib/queue/src/amqp.ts +++ b/lib/queue/src/amqp.ts @@ -1,9 +1,4 @@ -import { - Connection, - Consumer, - ConsumerStatus, - Publisher, -} from "rabbitmq-client"; +import { Connection, Consumer, ConsumerStatus, Publisher } from 'rabbitmq-client'; type SubscriptionFn = (msg: string) => Promise; type UnsubscribeFn = () => Promise; @@ -15,25 +10,25 @@ export const connect = async (url: string) => { const consumers: Consumer[] = []; const publishers: { [key: string]: Publisher } = {}; - rabbit.on("error", (err) => { - console.log("RabbitMQ connection error", err); + rabbit.on('error', (err) => { + console.log('RabbitMQ connection error', err); }); - rabbit.on("connection", () => { - console.log("Connection successfully (re)established"); + rabbit.on('connection', () => { + console.log('Connection successfully (re)established'); }); const disconnect = async () => { - console.log("Disconnecting"); + console.log('Disconnecting'); - console.log("Closing consumers" + consumers.length); + console.log('Closing consumers' + consumers.length); for (const sub of consumers) { - console.log("Closing consumer " + sub.consumerTag); + console.log('Closing consumer ' + sub.consumerTag); await sub.close(); } for (const pub of Object.values(publishers)) { - console.log("Closing publisher"); + console.log('Closing publisher'); await pub.close(); } @@ -53,22 +48,22 @@ export const connect = async (url: string) => { qos: { prefetchCount }, }, async (msg) => { - console.log("received message (user-events)", msg); + console.log('received message (user-events)', msg); try { - const str = msg.body.toString("utf8"); + const str = msg.body.toString('utf8'); await fn?.(str); return ConsumerStatus.ACK; - } catch (e: any) { - console.error("Error in subscription", e); + } catch (e) { + console.error('Error in subscription', e); return ConsumerStatus.DROP; } }, ); - sub.on("error", (err) => { + sub.on('error', (err) => { // Maybe the consumer was cancelled, or the connection was reset before a // message could be acknowledged. - console.log("consumer error (user-events)", err); + console.log('consumer error (user-events)', err); }); consumers.push(sub); diff --git a/lint-staged.config.mjs b/lint-staged.config.mjs new file mode 100644 index 0000000..313ffeb --- /dev/null +++ b/lint-staged.config.mjs @@ -0,0 +1,5 @@ +export default { + '**/*.{js,mjs,cjs,ts,tsx}': ['eslint --fix', 'prettier --write'], + + '**/*.{json,jsonc,yml,yaml,md,css,scss,html}': ['prettier --write'], +}; diff --git a/package-lock.json b/package-lock.json index f3128a2..480f89b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,13 @@ "@types/node": "^26.2.0", "concurrently": "^9.2.4", "eslint": "^10.8.1", + "eslint-config-prettier": "^10.1.8", "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.4", "globals": "^17.11.0", "husky": "^9.0.10", + "lint-staged": "^16.4.0", + "prettier": "^3.9.6", "typescript-eslint": "^8.67.0" } }, @@ -817,6 +820,22 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -964,6 +983,85 @@ "node": ">=8" } }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", + "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -999,6 +1097,23 @@ "dev": true, "license": "MIT" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/concurrently": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.4.tgz", @@ -1085,6 +1200,19 @@ "dev": true, "license": "MIT" }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -1167,6 +1295,22 @@ } } }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-plugin-react-hooks": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", @@ -1293,6 +1437,13 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1403,6 +1554,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -1609,6 +1773,133 @@ "node": ">= 0.8.0" } }, + "node_modules/lint-staged": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.4.0.tgz", + "integrity": "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^14.0.3", + "listr2": "^9.0.5", + "picomatch": "^4.0.3", + "string-argv": "^0.3.2", + "tinyexec": "^1.0.4", + "yaml": "^2.8.2" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1625,6 +1916,144 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -1635,6 +2064,19 @@ "yallist": "^3.0.2" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "10.2.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", @@ -1675,6 +2117,22 @@ "node": ">=18" } }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -1775,6 +2233,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -1795,6 +2269,30 @@ "node": ">=0.10.0" } }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -1851,6 +2349,75 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -1895,6 +2462,16 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", @@ -2103,6 +2680,22 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -2674,6 +3267,15 @@ "uri-js": "^4.2.2" } }, + "ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "requires": { + "environment": "^1.0.0" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2750,6 +3352,52 @@ } } }, + "cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "requires": { + "restore-cursor": "^5.0.0" + } + }, + "cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "dev": true, + "requires": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true + }, + "string-width": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", + "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "dev": true, + "requires": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + } + }, + "strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "requires": { + "ansi-regex": "^6.2.2" + } + } + } + }, "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -2776,6 +3424,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true + }, "concurrently": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.4.tgz", @@ -2834,6 +3494,12 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true + }, "escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2884,6 +3550,13 @@ "optionator": "^0.9.3" } }, + "eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "requires": {} + }, "eslint-plugin-react-hooks": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", @@ -2963,6 +3636,12 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3035,6 +3714,12 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true + }, "glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3171,6 +3856,85 @@ "type-check": "~0.4.0" } }, + "lint-staged": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.4.0.tgz", + "integrity": "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==", + "dev": true, + "requires": { + "commander": "^14.0.3", + "listr2": "^9.0.5", + "picomatch": "^4.0.3", + "string-argv": "^0.3.2", + "tinyexec": "^1.0.4", + "yaml": "^2.8.2" + } + }, + "listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "dev": true, + "requires": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true + }, + "emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true + }, + "string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "requires": { + "ansi-regex": "^6.2.2" + } + }, + "wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + } + } + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3180,6 +3944,89 @@ "p-locate": "^5.0.0" } }, + "log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "requires": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true + }, + "emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "requires": { + "get-east-asian-width": "^1.3.1" + } + }, + "slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + } + }, + "string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "requires": { + "ansi-regex": "^6.2.2" + } + }, + "wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + } + } + } + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3189,6 +4036,12 @@ "yallist": "^3.0.2" } }, + "mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true + }, "minimatch": { "version": "10.2.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", @@ -3216,6 +4069,15 @@ "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", "dev": true }, + "onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "requires": { + "mimic-function": "^5.0.0" + } + }, "optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3278,6 +4140,12 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true + }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3290,6 +4158,22 @@ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, + "restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "requires": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + } + }, + "rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, "rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -3326,6 +4210,45 @@ "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==", "dev": true }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "requires": { + "get-east-asian-width": "^1.3.1" + } + } + } + }, + "string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3355,6 +4278,12 @@ "has-flag": "^4.0.0" } }, + "tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "dev": true + }, "tinyglobby": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", @@ -3475,6 +4404,12 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true + }, "yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index f9160d2..7848227 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,21 @@ { "name": "colosseum", "version": "1.0.0", + "engines": { + "node": "20.x" + }, "devDependencies": { "@eslint/js": "^10.0.1", "@types/node": "^26.2.0", "concurrently": "^9.2.4", "eslint": "^10.8.1", + "eslint-config-prettier": "^10.1.8", "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.4", "globals": "^17.11.0", "husky": "^9.0.10", + "lint-staged": "^16.4.0", + "prettier": "^3.9.6", "typescript-eslint": "^8.67.0" }, "scripts": { @@ -28,11 +34,19 @@ "build:web": "npm --prefix web run build", "lint": "eslint senatus executioner lib/queue web", "lint:fix": "eslint senatus executioner lib/queue web --fix", + "lint:strict": "eslint senatus executioner lib/queue web --max-warnings=0", + "lint:client": "eslint client", "lint:senatus": "eslint senatus", "lint:executioner": "eslint executioner", "lint:queue": "eslint lib/queue", "lint:web": "eslint web", + "format": "prettier --write .", + "format:check": "prettier --check .", + "check": "npm run lint && npm run format:check && npm run build", + "quality": "npm run lint && npm run format:check", + "quality:strict": "npm run lint:strict && npm run format:check", "typecheck:senatus": "npm --prefix senatus run typecheck", + "prepare": "husky", "prepareClientHusky": "husky client/.husky", "prepareSenatusHusky": "husky senatus/.husky" } diff --git a/prettier.config.mjs b/prettier.config.mjs new file mode 100644 index 0000000..6bbb856 --- /dev/null +++ b/prettier.config.mjs @@ -0,0 +1,13 @@ +/** @type {import('prettier').Config} */ +export default { + printWidth: 100, + tabWidth: 2, + useTabs: false, + semi: true, + singleQuote: true, + trailingComma: 'all', + bracketSpacing: true, + bracketSameLine: false, + arrowParens: 'always', + endOfLine: 'lf', +}; diff --git a/senatus/config/admin.ts b/senatus/config/admin.ts index 1362476..ee4807f 100644 --- a/senatus/config/admin.ts +++ b/senatus/config/admin.ts @@ -1,16 +1,14 @@ -import type { StrapiConfigContext } from "../src/types/strapi-env"; - -export default ({ env }: StrapiConfigContext) => ({ +export default ({ env }) => ({ auth: { - secret: env("ADMIN_JWT_SECRET"), + secret: env('ADMIN_JWT_SECRET'), }, apiToken: { - salt: env("API_TOKEN_SALT"), + salt: env('API_TOKEN_SALT'), }, transfer: { token: { - salt: env("TRANSFER_TOKEN_SALT"), + salt: env('TRANSFER_TOKEN_SALT'), }, }, - url: env("PUBLIC_ADMIN_URL", "/admin"), + url: env('PUBLIC_ADMIN_URL', '/admin'), }); diff --git a/senatus/config/database.ts b/senatus/config/database.ts index fc9d53c..981c147 100644 --- a/senatus/config/database.ts +++ b/senatus/config/database.ts @@ -1,28 +1,26 @@ -import type { StrapiConfigContext } from "../src/types/strapi-env"; - -export default ({ env }: StrapiConfigContext) => ({ +export default ({ env }) => ({ connection: { - client: "postgres", + client: 'postgres', connection: { - host: env("DATABASE_HOST", "localhost"), - port: env.int("DATABASE_PORT", 5432), - database: env("DATABASE_NAME", "strapi"), - user: env("DATABASE_USERNAME", "strapi"), - password: env("DATABASE_PASSWORD", "strapi"), - ssl: env.bool("DATABASE_SSL", false) && { - key: env("DATABASE_SSL_KEY", undefined), - cert: env("DATABASE_SSL_CERT", undefined), - ca: env("DATABASE_SSL_CA", undefined), - capath: env("DATABASE_SSL_CAPATH", undefined), - cipher: env("DATABASE_SSL_CIPHER", undefined), - rejectUnauthorized: env.bool("DATABASE_SSL_REJECT_UNAUTHORIZED", true), + host: env('DATABASE_HOST', 'localhost'), + port: env.int('DATABASE_PORT', 5432), + database: env('DATABASE_NAME', 'strapi'), + user: env('DATABASE_USERNAME', 'strapi'), + password: env('DATABASE_PASSWORD', 'strapi'), + ssl: env.bool('DATABASE_SSL', false) && { + key: env('DATABASE_SSL_KEY', undefined), + cert: env('DATABASE_SSL_CERT', undefined), + ca: env('DATABASE_SSL_CA', undefined), + capath: env('DATABASE_SSL_CAPATH', undefined), + cipher: env('DATABASE_SSL_CIPHER', undefined), + rejectUnauthorized: env.bool('DATABASE_SSL_REJECT_UNAUTHORIZED', true), }, - schema: env("DATABASE_SCHEMA", "public"), + schema: env('DATABASE_SCHEMA', 'public'), }, pool: { - min: env.int("DATABASE_POOL_MIN", 2), - max: env.int("DATABASE_POOL_MAX", 10), + min: env.int('DATABASE_POOL_MIN', 2), + max: env.int('DATABASE_POOL_MAX', 10), }, - acquireConnectionTimeout: env.int("DATABASE_CONNECTION_TIMEOUT", 60000), + acquireConnectionTimeout: env.int('DATABASE_CONNECTION_TIMEOUT', 60000), }, }); diff --git a/senatus/config/plugin.ts b/senatus/config/plugin.ts index 83619c8..44d41f3 100644 --- a/senatus/config/plugin.ts +++ b/senatus/config/plugin.ts @@ -1,4 +1,4 @@ -export default ({ env }) => ({ +export default () => ({ graphql: { config: { endpoint: '/graphql', @@ -8,8 +8,8 @@ export default ({ env }) => ({ amountLimit: 100, apolloServer: { tracing: false, - introspection: true - } - } - } + introspection: true, + }, + }, + }, }); diff --git a/senatus/config/server.ts b/senatus/config/server.ts index 9a2e533..899a307 100644 --- a/senatus/config/server.ts +++ b/senatus/config/server.ts @@ -1,15 +1,15 @@ -import type { StrapiConfigContext } from "../src/types/strapi-env"; +export default ({ env }) => ({ + host: env('HOST', '0.0.0.0'), + port: env.int('PORT', 1337), + url: env('PUBLIC_URL', 'http://localhost:1337'), -export default ({ env }: StrapiConfigContext) => ({ - host: env("HOST", "0.0.0.0"), - port: env.int("PORT", 1337), - url: env("PUBLIC_URL", "http://localhost:1337"), app: { - keys: env.array("APP_KEYS"), - rabbitUrl: env("RABBIT_URL", "amqp://guest:guest@localhost"), - prefetchResults: env.int("PREFETCH_RESULTS", 10), // How many results to prefetch from the results queue + keys: env.array('APP_KEYS'), + rabbitUrl: env('RABBIT_URL', 'amqp://guest:guest@localhost'), + prefetchResults: env.int('PREFETCH_RESULTS', 10), }, + webhooks: { - populateRelations: env.bool("WEBHOOKS_POPULATE_RELATIONS", false), + populateRelations: env.bool('WEBHOOKS_POPULATE_RELATIONS', false), }, }); diff --git a/senatus/src/api/submission/controllers/submission.ts b/senatus/src/api/submission/controllers/submission.ts index fab99ad..781c5f5 100644 --- a/senatus/src/api/submission/controllers/submission.ts +++ b/senatus/src/api/submission/controllers/submission.ts @@ -2,182 +2,165 @@ * submission controller */ -import { connect } from "@colosseum/queue"; -import { factories } from "@strapi/strapi"; - -export default factories.createCoreController( - "api::submission.submission", - ({ strapi }) => ({ - async submit(ctx) { - try { - ctx.body = ctx.request.query; - - const id = ctx.request.query.id as string; - if (!id) { - ctx.body = { error: "No submission id provided" }; - return; - } +import { connect } from '@colosseum/queue'; +import { factories } from '@strapi/strapi'; + +export default factories.createCoreController('api::submission.submission', ({ strapi }) => ({ + async submit(ctx) { + try { + ctx.body = ctx.request.query; + + const id = ctx.request.query.id as string; + if (!id) { + ctx.body = { error: 'No submission id provided' }; + return; + } - const submission = await strapi - .documents("api::submission.submission") - .findOne({ - documentId: id, - populate: ["user", "problem", "language"], - }); - - if (!submission) { - ctx.status = 404; - ctx.body = { erorr: "Submission not found" }; - return; - } + const submission = await strapi.documents('api::submission.submission').findOne({ + documentId: id, + populate: ['user', 'problem', 'language'], + }); - if (!submission.problem) { - ctx.status = 400; - ctx.body = { error: "Submission has no problem" }; - return; - } + if (!submission) { + ctx.status = 404; + ctx.body = { erorr: 'Submission not found' }; + return; + } - if (!submission.language) { - ctx.status = 400; - ctx.body = { error: "Submission has no source code" }; - return; - } + if (!submission.problem) { + ctx.status = 400; + ctx.body = { error: 'Submission has no problem' }; + return; + } - if (submission.code === null) { - ctx.status = 400; - ctx.body = { error: "Submission has no source code" }; - return; - } + if (!submission.language) { + ctx.status = 400; + ctx.body = { error: 'Submission has no source code' }; + return; + } - const testCases = await strapi - .documents("api::test-case.test-case") - .findMany({ - filters: { - problem: { documentId: submission.problem.documentId as any }, - }, - }); - - const executionsToQueue: { testCase: any; execution: any }[] = []; - for (const testCase of testCases) { - const execution = await strapi - .documents("api::execution.execution") - .create({ - data: { - stdout: "", - stderr: "", - executionTime: -1, - testCase: testCase.id, - submission: submission.id, - processed: false, - publishedAt: new Date(), - code: submission.code, - }, - status: "published", - }); - executionsToQueue.push({ - testCase, - execution, - }); - } + if (submission.code === null) { + ctx.status = 400; + ctx.body = { error: 'Submission has no source code' }; + return; + } - const qPayload = { - sources: [ - { - filename: submission.language.entrypoint, - content: submission.code, - }, - ], - input: executionsToQueue.map((pair) => ({ - filename: pair.execution.documentId.toString(), - content: pair.testCase.input, - metadata: { - testCaseId: pair.testCase.documentId, - executionId: pair.execution.documentId, - }, - })), - options: { - language: submission.language.codeName, - entrypointFile: submission.language.entrypoint, + const testCases = await strapi.documents('api::test-case.test-case').findMany({ + filters: { + problem: { documentId: submission.problem.documentId }, + }, + }); + + const executionsToQueue = []; + for (const testCase of testCases) { + const execution = await strapi.documents('api::execution.execution').create({ + data: { + stdout: '', + stderr: '', + executionTime: -1, + testCase: testCase.id, + submission: submission.id, + processed: false, + publishedAt: new Date(), + code: submission.code, }, + status: 'published', + }); + executionsToQueue.push({ + testCase, + execution, + }); + } + + const qPayload = { + sources: [ + { + filename: submission.language.entrypoint, + content: submission.code, + }, + ], + input: executionsToQueue.map((pair) => ({ + filename: pair.execution.documentId.toString(), + content: pair.testCase.input, metadata: { - submissionId: submission.documentId, + testCaseId: pair.testCase.documentId, + executionId: pair.execution.documentId, }, - }; - - const msg = JSON.stringify(qPayload); - - const { publish, disconnect } = await connect( - strapi.config.get("server.app.rabbitUrl"), - ); - - console.log("Connected to RabbitMQ"); + })), + options: { + language: submission.language.codeName, + entrypointFile: submission.language.entrypoint, + }, + metadata: { + submissionId: submission.documentId, + }, + }; + + const msg = JSON.stringify(qPayload); + + const { publish, disconnect } = await connect(strapi.config.get('server.app.rabbitUrl')); + + console.log('Connected to RabbitMQ'); + + await publish('execution', msg); + + await disconnect(); + + ctx.body = { + state: 'Queued', + executions: executionsToQueue.map((pair) => pair.execution.documentId), + }; + } catch (err) { + console.log(err); + ctx.body = err; + } + }, + + async getExecutions(ctx) { + try { + const ids = ctx.request.query.ids as string; + if (!ids) { + ctx.body = { error: 'No execution ids provided' }; + return; + } - await publish("execution", msg); + const executionIds = ids.split(',').map((id) => id.trim()); - await disconnect(); + const executions = await strapi.documents('api::execution.execution').findMany({ + filters: { + documentId: { $in: executionIds }, + }, + populate: ['testCase'], + }); - ctx.body = { - state: "Queued", - executions: executionsToQueue.map( - (pair) => pair.execution.documentId, - ), - }; - } catch (err) { - console.log(err); - ctx.body = err; - } - }, - - async getExecutions(ctx) { - try { - const ids = ctx.request.query.ids as string; - if (!ids) { - ctx.body = { error: "No execution ids provided" }; - return; + const allProcessed = executions.every((exec) => exec.processed); + const results = executions.map((exec) => { + if (!exec.testCase) { + throw new Error(`Execution ${exec.documentId} has no associated test case`); } - const executionIds = ids.split(",").map((id) => id.trim()); - - const executions = await strapi - .documents("api::execution.execution") - .findMany({ - filters: { - documentId: { $in: executionIds }, - }, - populate: ["testCase"], - }); - - const allProcessed = executions.every((exec) => exec.processed); - const results = executions.map((exec) => { - if (!exec.testCase) { - throw new Error( - `Execution ${exec.documentId} has no associated test case`, - ); - } - - return { - id: exec.documentId, - processed: exec.processed, - passed: exec.passed, - executionTime: exec.executionTime, - stdout: exec.stdout, - stderr: exec.stderr, - testCase: { - id: exec.testCase.documentId, - input: exec.testCase.input, - output: exec.testCase.output, - }, - }; - }); - - ctx.body = { - complete: allProcessed, - executions: results, + return { + id: exec.documentId, + processed: exec.processed, + passed: exec.passed, + executionTime: exec.executionTime, + stdout: exec.stdout, + stderr: exec.stderr, + testCase: { + id: exec.testCase.documentId, + input: exec.testCase.input, + output: exec.testCase.output, + }, }; - } catch (err) { - console.error(err); - ctx.body = { error: "Failed to fetch executions" }; - } - }, - }), -); + }); + + ctx.body = { + complete: allProcessed, + executions: results, + }; + } catch (err) { + console.error(err); + ctx.body = { error: 'Failed to fetch executions' }; + } + }, +})); diff --git a/web/src/pages/CompetePage.tsx b/web/src/pages/CompetePage.tsx index d542597..1c2904e 100644 --- a/web/src/pages/CompetePage.tsx +++ b/web/src/pages/CompetePage.tsx @@ -1,31 +1,23 @@ -import { useState, useEffect, useRef } from "react"; -import { useParams, Link } from "react-router-dom"; -import Editor from "@monaco-editor/react"; -import { Button } from "@/components/ui/button"; -import { Card } from "@/components/ui/card"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { useCallback, useState, useEffect, useRef } from 'react'; +import { useParams, Link } from 'react-router-dom'; +import Editor from '@monaco-editor/react'; +import { Button } from '@/components/ui/button'; +import { Card } from '@/components/ui/card'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, -} from "@/components/ui/select"; -import { Separator } from "@/components/ui/separator"; -import { Badge } from "@/components/ui/badge"; -import { useToast } from "@/components/ui/use-toast"; -import { - ArrowLeft, - Play, - CheckCircle2, - XCircle, - Clock, - Loader2, - AlertCircle, -} from "lucide-react"; -import { cn } from "@/lib/utils"; -import { REST_URL } from "@/config"; -import Markdown from "@/components/Markdown"; +} from '@/components/ui/select'; +import { Separator } from '@/components/ui/separator'; +import { Badge } from '@/components/ui/badge'; +import { useToast } from '@/components/ui/use-toast'; +import { ArrowLeft, Play, CheckCircle2, XCircle, Clock, Loader2, AlertCircle } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import { REST_URL } from '@/config'; +import Markdown from '@/components/Markdown'; interface Problem { title: string; @@ -33,7 +25,7 @@ interface Problem { slug: string; points: number; testCases?: TestCase[]; - starterCodes?: any[]; + starterCodes?: unknown[]; } interface TestCase { @@ -81,65 +73,66 @@ interface Submission { export default function CompetePage() { const { problemId } = useParams(); const { toast } = useToast(); - const [code, setCode] = useState("// Write your solution here\n"); - const [selectedLanguage, setSelectedLanguage] = useState(""); + const [code, setCode] = useState('// Write your solution here\n'); + const [selectedLanguage, setSelectedLanguage] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); const [problem, setProblem] = useState(null); const [languages, setLanguages] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [submissions, setSubmissions] = useState([]); - const [activeTab, setActiveTab] = useState("description"); - const pollingIntervalRef = useRef | null>( - null, - ); + const [activeTab, setActiveTab] = useState('description'); + const pollingIntervalRef = useRef | null>(null); const initialCodeLoadedRef = useRef(false); // Fetch submissions from API - const fetchSubmissions = async (loadCodeFromSubmission = false) => { - try { - const token = localStorage.getItem("jwt"); - const headers = { - Authorization: token ? `Bearer ${token}` : "", - }; + const fetchSubmissions = useCallback( + async (loadCodeFromSubmission = false) => { + try { + const token = localStorage.getItem('jwt'); + const headers = { + Authorization: token ? `Bearer ${token}` : '', + }; - const submissionsRes = await fetch( - `${REST_URL}/submissions?filters[problem][documentId][$eq]=${problemId}&populate[language]=*&populate[executions][populate][testCase][fields][0]=documentId&populate[executions][populate][testCase][fields][1]=input&populate[executions][populate][testCase][fields][2]=output&populate[executions][populate][testCase][fields][3]=hidden&sort=createdAt:desc`, - { headers }, - ); + const submissionsRes = await fetch( + `${REST_URL}/submissions?filters[problem][documentId][$eq]=${problemId}&populate[language]=*&populate[executions][populate][testCase][fields][0]=documentId&populate[executions][populate][testCase][fields][1]=input&populate[executions][populate][testCase][fields][2]=output&populate[executions][populate][testCase][fields][3]=hidden&sort=createdAt:desc`, + { headers }, + ); - if (submissionsRes.ok) { - const submissionsData = await submissionsRes.json(); - const submissionsArray = Array.isArray(submissionsData) - ? submissionsData - : submissionsData.data || []; - setSubmissions(submissionsArray); - - // Load code from latest submission only on initial load or when explicitly requested - if ( - loadCodeFromSubmission && - submissionsArray.length > 0 && - submissionsArray[0].code && - !initialCodeLoadedRef.current - ) { - setCode(submissionsArray[0].code); - if (submissionsArray[0].language?.documentId) { - setSelectedLanguage(submissionsArray[0].language.documentId); + if (submissionsRes.ok) { + const submissionsData = await submissionsRes.json(); + const submissionsArray = Array.isArray(submissionsData) + ? submissionsData + : submissionsData.data || []; + setSubmissions(submissionsArray); + + // Load code from latest submission only on initial load or when explicitly requested + if ( + loadCodeFromSubmission && + submissionsArray.length > 0 && + submissionsArray[0].code && + !initialCodeLoadedRef.current + ) { + setCode(submissionsArray[0].code); + if (submissionsArray[0].language?.documentId) { + setSelectedLanguage(submissionsArray[0].language.documentId); + } + initialCodeLoadedRef.current = true; } - initialCodeLoadedRef.current = true; } + } catch (err) { + console.error('Failed to fetch submissions:', err); } - } catch (err) { - console.error("Failed to fetch submissions:", err); - } - }; + }, + [problemId], + ); useEffect(() => { const fetchData = async () => { try { - const token = localStorage.getItem("jwt"); + const token = localStorage.getItem('jwt'); const headers = { - Authorization: token ? `Bearer ${token}` : "", + Authorization: token ? `Bearer ${token}` : '', }; const [problemRes, languagesRes] = await Promise.all([ @@ -148,15 +141,12 @@ export default function CompetePage() { ]); if (!problemRes.ok || !languagesRes.ok) { - throw new Error("HTTP error fetching data"); + throw new Error('HTTP error fetching data'); } const problemData = await problemRes.json(); const languagesData = await languagesRes.json(); - console.log("Problem API response:", problemData); - console.log("Languages API response:", languagesData); - // Handle both wrapped and unwrapped responses setProblem(problemData.data || problemData); @@ -165,21 +155,19 @@ export default function CompetePage() { : languagesData.data || []; setLanguages(fetchedLanguages); - setSelectedLanguage( - (current) => current || fetchedLanguages[0]?.documentId || "", - ); + setSelectedLanguage((current) => current || fetchedLanguages[0]?.documentId || ''); // Fetch user's submissions and load code from latest submission await fetchSubmissions(true); } catch (err) { - console.error("Failed to load problem:", err); - setError("Failed to load problem"); + console.error('Failed to load problem:', err); + setError('Failed to load problem'); } finally { setLoading(false); } }; fetchData(); - }, [problemId]); + }, [problemId, fetchSubmissions]); const testCases = problem?.testCases || []; const publicTestCases = testCases.filter((tc: TestCase) => !tc.hidden); @@ -188,19 +176,19 @@ export default function CompetePage() { useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { // Alt+1, Alt+2, Alt+3 for tab switching - if (e.altKey && ["1", "2", "3"].includes(e.key)) { + if (e.altKey && ['1', '2', '3'].includes(e.key)) { e.preventDefault(); const tabMap: Record = { - "1": "description", - "2": "testcases", - "3": "results", + '1': 'description', + '2': 'testcases', + '3': 'results', }; setActiveTab(tabMap[e.key]); } }; - window.addEventListener("keydown", handleKeyDown); - return () => window.removeEventListener("keydown", handleKeyDown); + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); }, []); // Poll submissions for updates @@ -234,16 +222,12 @@ export default function CompetePage() { const latestSub = submissions[0]; if (latestSub.executions) { const passed = latestSub.executions.filter( - (exec: Execution) => - exec.stdout?.trim() === exec.testCase?.output?.trim(), + (exec: Execution) => exec.stdout?.trim() === exec.testCase?.output?.trim(), ).length; toast({ - title: "Execution Complete", + title: 'Execution Complete', description: `${passed}/${latestSub.executions.length} test cases passed`, - variant: - passed === latestSub.executions.length - ? "default" - : "destructive", + variant: passed === latestSub.executions.length ? 'default' : 'destructive', }); } } @@ -256,29 +240,29 @@ export default function CompetePage() { clearInterval(pollingIntervalRef.current); } }; - }, [submissions, toast]); + }, [submissions, toast, fetchSubmissions]); const handleSubmit = async () => { if (!selectedLanguage) { toast({ - title: "No language selected", - description: "Please select a programming language", - variant: "destructive", + title: 'No language selected', + description: 'Please select a programming language', + variant: 'destructive', }); return; } setIsSubmitting(true); try { - const token = localStorage.getItem("jwt"); + const token = localStorage.getItem('jwt'); const headers = { - "Content-Type": "application/json", - Authorization: token ? `Bearer ${token}` : "", + 'Content-Type': 'application/json', + Authorization: token ? `Bearer ${token}` : '', }; // Create submission const submissionRes = await fetch(`${REST_URL}/submissions`, { - method: "POST", + method: 'POST', headers, body: JSON.stringify({ data: { @@ -293,33 +277,29 @@ export default function CompetePage() { const submissionId = submissionData.data.documentId; // Submit for execution - const submitRes = await fetch( - `${REST_URL}/submissions/submit?id=${submissionId}`, - { - headers, - }, - ); + const submitRes = await fetch(`${REST_URL}/submissions/submit?id=${submissionId}`, { + headers, + }); const submitData = await submitRes.json(); - console.log("Submit response:", submitData); if (submitData.executions && submitData.executions.length > 0) { // Fetch updated submissions await fetchSubmissions(); // Switch to submissions tab - setActiveTab("results"); + setActiveTab('results'); toast({ - title: "Submitted!", - description: "Your code is being executed...", + title: 'Submitted!', + description: 'Your code is being executed...', }); } else { - throw new Error("No executions returned"); + throw new Error('No executions returned'); } } catch (err) { toast({ - title: "Submission failed", - description: err instanceof Error ? err.message : "Please try again", - variant: "destructive", + title: 'Submission failed', + description: err instanceof Error ? err.message : 'Please try again', + variant: 'destructive', }); } finally { setIsSubmitting(false); @@ -337,16 +317,12 @@ export default function CompetePage() { if (error || !problem) { return (
-

- Failed to load problem. Please try again later. -

+

Failed to load problem. Please try again later.

); } - const selectedLang = languages.find( - (language) => language.documentId === selectedLanguage, - ); + const selectedLang = languages.find((language) => language.documentId === selectedLanguage); return (
@@ -375,7 +351,7 @@ export default function CompetePage() {
@@ -384,11 +360,7 @@ export default function CompetePage() {
{/* Left Panel - Problem Description */} - +
@@ -412,14 +384,13 @@ export default function CompetePage() {
- +
- {testCases.length} test cases ({publicTestCases.length}{" "} - visible) + {testCases.length} test cases ({publicTestCases.length} visible)
@@ -427,30 +398,21 @@ export default function CompetePage() {
{publicTestCases.length === 0 ? ( -

- No public test cases available -

+

No public test cases available

) : ( publicTestCases.map((tc, index: number) => ( -
+
Test {index + 1}
-
- Input -
+
Input
                             {tc.input}
                           
-
- Expected -
+
Expected
                             {tc.output}
                           
@@ -466,20 +428,15 @@ export default function CompetePage() { {submissions.length === 0 ? (
-

- No submissions yet -

+

No submissions yet

) : ( submissions.map((submission, subIndex) => { const executions = submission.executions || []; - const hasUnprocessed = executions.some( - (exec) => !exec.processed, - ); + const hasUnprocessed = executions.some((exec) => !exec.processed); const passedCount = executions.filter( (exec: Execution) => - exec.processed && - exec.stdout?.trim() === exec.testCase?.output?.trim(), + exec.processed && exec.stdout?.trim() === exec.testCase?.output?.trim(), ).length; return ( @@ -490,18 +447,13 @@ export default function CompetePage() { #{submissions.length - subIndex}

- {new Date( - submission.createdAt, - ).toLocaleTimeString()}{" "} - • {submission.language?.name} + {new Date(submission.createdAt).toLocaleTimeString()} •{' '} + {submission.language?.name}

{hasUnprocessed ? ( - + Running @@ -509,10 +461,10 @@ export default function CompetePage() { {passedCount}/{executions.length} @@ -525,8 +477,7 @@ export default function CompetePage() { {executions.map((execution, index) => { const isPassed = execution.processed && - execution.stdout?.trim() === - execution.testCase?.output?.trim(); + execution.stdout?.trim() === execution.testCase?.output?.trim(); const isFailed = execution.processed && !isPassed; const isRunning = !execution.processed; @@ -534,32 +485,24 @@ export default function CompetePage() {
- {execution.testCase?.hidden - ? "Hidden" - : ""}{" "} - Test {index + 1} + {execution.testCase?.hidden ? 'Hidden' : ''} Test {index + 1} {isRunning && ( - + )} {isPassed && ( )} - {isFailed && ( - - )} + {isFailed && }
{execution.processed && ( @@ -591,21 +534,19 @@ export default function CompetePage() {
-                                          {execution.stdout || "(empty)"}
+                                          {execution.stdout || '(empty)'}
                                         
{execution.stderr && (
-
- Error -
+
Error
                                             {execution.stderr}
                                           
@@ -637,21 +578,19 @@ export default function CompetePage() { {/* Right Panel - Code Editor */}
- - Editor - + Editor
setCode(value || "")} + onChange={(value) => setCode(value || '')} theme="vs-dark" options={{ minimap: { enabled: false }, fontSize: 13, - lineNumbers: "on", + lineNumbers: 'on', roundedSelection: false, scrollBeyondLastLine: false, automaticLayout: true, @@ -659,12 +598,9 @@ export default function CompetePage() { padding: { top: 12 }, }} onMount={(editor, monaco) => { - editor.addCommand( - monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, - () => { - handleSubmit(); - }, - ); + editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { + handleSubmit(); + }); }} />
@@ -676,20 +612,20 @@ export default function CompetePage() { function getEditorLanguage(codeName: string | undefined): string { if (!codeName) { - return "javascript"; + return 'javascript'; } const languageMap: Record = { - python: "python", - javascript: "javascript", - typescript: "typescript", - java: "java", - cpp: "cpp", - c: "c", - csharp: "csharp", - go: "go", - rust: "rust", + python: 'python', + javascript: 'javascript', + typescript: 'typescript', + java: 'java', + cpp: 'cpp', + c: 'c', + csharp: 'csharp', + go: 'go', + rust: 'rust', }; - return languageMap[codeName] || "javascript"; + return languageMap[codeName] || 'javascript'; } diff --git a/web/src/pages/EventDetailPage.tsx b/web/src/pages/EventDetailPage.tsx index 1b91a81..aa4b5c8 100644 --- a/web/src/pages/EventDetailPage.tsx +++ b/web/src/pages/EventDetailPage.tsx @@ -1,7 +1,7 @@ -import { useState, useEffect } from "react"; -import { useParams, Link } from "react-router-dom"; -import { Badge } from "@/components/ui/badge"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { useState, useEffect } from 'react'; +import { useParams, Link } from 'react-router-dom'; +import { Badge } from '@/components/ui/badge'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Table, TableBody, @@ -9,17 +9,12 @@ import { TableHead, TableHeader, TableRow, -} from "@/components/ui/table"; -import { - ArrowLeft, - Circle, - ChevronRight, - FileText, - Trophy, -} from "lucide-react"; -import { REST_URL } from "@/config"; -import Markdown from "@/components/Markdown"; -import { cn } from "@/lib/utils"; +} from '@/components/ui/table'; +import { ArrowLeft, Circle, ChevronRight, FileText, Trophy } from 'lucide-react'; +import { REST_URL } from '@/config'; +import Markdown from '@/components/Markdown'; +import { cn } from '@/lib/utils'; +import type { Language } from '@/types'; interface Problem { documentId: string; @@ -28,7 +23,7 @@ interface Problem { slug: string; difficulty?: string; points: number; - testCases?: any[]; + testCases?: unknown[]; } interface Event { @@ -37,7 +32,7 @@ interface Event { start: string; end: string; problems?: Problem[]; - supportedLanguages?: any[]; + supportedLanguages?: Language[]; } function getTimeRemaining(date: Date): string { @@ -45,26 +40,26 @@ function getTimeRemaining(date: Date): string { const diff = date.getTime() - now.getTime(); if (diff < 0) { - return "0:00:00"; + return '0:00:00'; } const hours = Math.floor(diff / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((diff % (1000 * 60)) / 1000); - return `${hours}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`; + return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; } function getDifficultyColor(difficulty?: string) { switch (difficulty?.toLowerCase()) { - case "easy": - return "text-emerald-500"; - case "medium": - return "text-amber-500"; - case "hard": - return "text-red-500"; + case 'easy': + return 'text-emerald-500'; + case 'medium': + return 'text-amber-500'; + case 'hard': + return 'text-red-500'; default: - return "text-muted-foreground"; + return 'text-muted-foreground'; } } @@ -73,21 +68,18 @@ export default function EventDetailPage() { const [event, setEvent] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [activeTab, setActiveTab] = useState("problems"); - const [timeRemaining, setTimeRemaining] = useState(""); + const [activeTab, setActiveTab] = useState('problems'); + const [timeRemaining, setTimeRemaining] = useState(''); useEffect(() => { const fetchEvent = async () => { try { - const token = localStorage.getItem("jwt"); - const response = await fetch( - `${REST_URL}/events/${eventId}?populate=*`, - { - headers: { - Authorization: token ? `Bearer ${token}` : "", - }, + const token = localStorage.getItem('jwt'); + const response = await fetch(`${REST_URL}/events/${eventId}?populate=*`, { + headers: { + Authorization: token ? `Bearer ${token}` : '', }, - ); + }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); @@ -97,8 +89,8 @@ export default function EventDetailPage() { const eventData = data.data || data; setEvent(eventData); } catch (err) { - console.error("Failed to load event:", err); - setError("Failed to load event"); + console.error('Failed to load event:', err); + setError('Failed to load event'); } finally { setLoading(false); } @@ -161,18 +153,14 @@ export default function EventDetailPage() {
-

- {event.title} -

+

{event.title}

{isActive && ( - - LIVE - + LIVE )} {isUpcoming && Upcoming} @@ -186,34 +174,31 @@ export default function EventDetailPage() {
{startDate.toLocaleDateString(undefined, { - weekday: "short", - month: "short", - day: "numeric", + weekday: 'short', + month: 'short', + day: 'numeric', })} - {" · "} + {' · '} {startDate.toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", + hour: '2-digit', + minute: '2-digit', })} - {" – "} + {' – '} {endDate.toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", + hour: '2-digit', + minute: '2-digit', })} · - {problems.length}{" "} - {problems.length === 1 ? "problem" : "problems"} + {problems.length} {problems.length === 1 ? 'problem' : 'problems'}
{isActive && (
-
- Time Remaining -
+
Time Remaining
{timeRemaining}
@@ -237,8 +222,8 @@ export default function EventDetailPage() {

No problems yet

{isUpcoming - ? "Problems will be revealed when the contest starts" - : "No problems have been added to this contest"} + ? 'Problems will be revealed when the contest starts' + : 'No problems have been added to this contest'}

) : ( @@ -248,9 +233,7 @@ export default function EventDetailPage() { # Problem - - Difficulty - + Difficulty Points Status @@ -261,9 +244,7 @@ export default function EventDetailPage() { - (window.location.href = `/compete/${problem.documentId}`) - } + onClick={() => (window.location.href = `/compete/${problem.documentId}`)} > {index + 1} @@ -285,15 +266,15 @@ export default function EventDetailPage() { - {problem.difficulty || "—"} + {problem.difficulty || '—'} - {problem.points ?? "N/A"} + {problem.points ?? 'N/A'} @@ -316,30 +297,21 @@ export default function EventDetailPage() {
) : ( -

- No description provided. -

+

No description provided.

)} - {event.supportedLanguages && - event.supportedLanguages.length > 0 && ( -
-

- Supported Languages -

-
- {event.supportedLanguages.map((lang: any) => ( - - {lang.name} - - ))} -
+ {event.supportedLanguages && event.supportedLanguages.length > 0 && ( +
+

Supported Languages

+
+ {event.supportedLanguages.map((lang) => ( + + {lang.name} + + ))}
- )} +
+ )}
diff --git a/web/src/pages/EventsPage.tsx b/web/src/pages/EventsPage.tsx index 921c30a..8d7feb3 100644 --- a/web/src/pages/EventsPage.tsx +++ b/web/src/pages/EventsPage.tsx @@ -1,9 +1,10 @@ -import { useState, useEffect } from "react"; -import { Badge } from "@/components/ui/badge"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { Calendar, Clock, ChevronRight } from "lucide-react"; -import { Link } from "react-router-dom"; -import { REST_URL } from "@/config"; +import { useState, useEffect } from 'react'; +import { Badge } from '@/components/ui/badge'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { Calendar, Clock, ChevronRight } from 'lucide-react'; +import { Link } from 'react-router-dom'; +import { REST_URL } from '@/config'; +import { Language } from '@/types'; interface Event { documentId: string; @@ -12,8 +13,8 @@ interface Event { start: string; end: string; slug: string; - problems?: any[]; - supportedLanguages?: any[]; + problems?: unknown[]; + supportedLanguages?: Language[]; publishedAt: string; } @@ -21,14 +22,20 @@ function getTimeRemaining(date: Date): string { const now = new Date(); const diff = date.getTime() - now.getTime(); - if (diff < 0) {return "Started";} + if (diff < 0) { + return 'Started'; + } const days = Math.floor(diff / (1000 * 60 * 60 * 24)); const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); - if (days > 0) {return `${days}d ${hours}h`;} - if (hours > 0) {return `${hours}h ${minutes}m`;} + if (days > 0) { + return `${days}d ${hours}h`; + } + if (hours > 0) { + return `${hours}h ${minutes}m`; + } return `${minutes}m`; } @@ -37,8 +44,12 @@ function formatDuration(start: Date, end: Date): string { const hours = Math.floor(diff / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); - if (hours > 0 && minutes > 0) {return `${hours}h ${minutes}m`;} - if (hours > 0) {return `${hours}h`;} + if (hours > 0 && minutes > 0) { + return `${hours}h ${minutes}m`; + } + if (hours > 0) { + return `${hours}h`; + } return `${minutes}m`; } @@ -58,15 +69,15 @@ export default function EventsPage() { const [events, setEvents] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [activeTab, setActiveTab] = useState("active"); + const [activeTab, setActiveTab] = useState('active'); useEffect(() => { const fetchEvents = async () => { try { - const token = localStorage.getItem("jwt"); + const token = localStorage.getItem('jwt'); const response = await fetch(`${REST_URL}/events?populate=*`, { headers: { - Authorization: token ? `Bearer ${token}` : "", + Authorization: token ? `Bearer ${token}` : '', }, }); @@ -78,8 +89,8 @@ export default function EventsPage() { const eventsData = Array.isArray(data) ? data : data.data || []; setEvents(eventsData); } catch (err) { - console.error("Failed to load events:", err); - setError("Failed to load events"); + console.error('Failed to load events:', err); + setError('Failed to load events'); } finally { setLoading(false); } @@ -134,9 +145,7 @@ export default function EventsPage() { - - LIVE - + LIVE )}
@@ -146,9 +155,9 @@ export default function EventsPage() { {startDate.toLocaleDateString(undefined, { - month: "short", - day: "numeric", - year: "numeric", + month: 'short', + day: 'numeric', + year: 'numeric', })}
@@ -158,29 +167,28 @@ export default function EventsPage() {
{problemCount} - {problemCount === 1 ? "problem" : "problems"} + {problemCount === 1 ? 'problem' : 'problems'}
- {event.supportedLanguages && - event.supportedLanguages.length > 0 && ( -
- {event.supportedLanguages.slice(0, 5).map((lang: any) => ( - - {lang.name} - - ))} - {event.supportedLanguages.length > 5 && ( - - +{event.supportedLanguages.length - 5} - - )} -
- )} + {event.supportedLanguages && event.supportedLanguages.length > 0 && ( +
+ {event.supportedLanguages.slice(0, 5).map((lang) => ( + + {lang.name} + + ))} + {event.supportedLanguages.length > 5 && ( + + +{event.supportedLanguages.length - 5} + + )} +
+ )}
@@ -242,9 +250,7 @@ export default function EventsPage() { {activeEvents.length === 0 ? ( ) : ( - activeEvents.map((event) => ( - - )) + activeEvents.map((event) => ) )} @@ -252,9 +258,7 @@ export default function EventsPage() { {upcomingEvents.length === 0 ? ( ) : ( - upcomingEvents.map((event) => ( - - )) + upcomingEvents.map((event) => ) )} @@ -262,9 +266,7 @@ export default function EventsPage() { {pastEvents.length === 0 ? ( ) : ( - pastEvents.map((event) => ( - - )) + pastEvents.map((event) => ) )} diff --git a/web/src/types.ts b/web/src/types.ts new file mode 100644 index 0000000..40f8b60 --- /dev/null +++ b/web/src/types.ts @@ -0,0 +1,4 @@ +export interface Language { + documentId: string; + name: string; +} diff --git a/web/tailwind.config.js b/web/tailwind.config.js index d5c45f1..2d2272c 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -1,6 +1,8 @@ /** @type {import('tailwindcss').Config} */ +import typography from '@tailwindcss/typography'; +import tailwindcssAnimate from 'tailwindcss-animate'; export default { - darkMode: ["class"], + darkMode: ['class'], content: [ './pages/**/*.{ts,tsx}', './components/**/*.{ts,tsx}', @@ -10,67 +12,67 @@ export default { theme: { container: { center: true, - padding: "2rem", + padding: '2rem', screens: { - "2xl": "1400px", + '2xl': '1400px', }, }, extend: { colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))', }, secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))', }, destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))', }, muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))', }, accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))', }, popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))', }, card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))', }, }, borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)', }, keyframes: { - "accordion-down": { + 'accordion-down': { from: { height: 0 }, - to: { height: "var(--radix-accordion-content-height)" }, + to: { height: 'var(--radix-accordion-content-height)' }, }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, to: { height: 0 }, }, }, animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out', }, }, }, - plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")], -} + plugins: [tailwindcssAnimate, typography], +}; From 7cbb737be294277d01f48072eba0cbbc27725b57 Mon Sep 17 00:00:00 2001 From: Ivan Zanov Date: Mon, 24 Aug 2026 11:24:45 +0200 Subject: [PATCH 04/12] style: apply prettier formatting --- .github/pull_request_template.md | 2 +- .github/workflows/build.yml | 4 +- DOCUMENTATION.md | 3 +- README.md | 50 ++++--- SETUP.md | 4 +- client/.eslintrc.cjs | 7 +- client/.eslintrc.yml | 23 ++- client/README.md | 1 - client/codegen.ts | 8 +- client/src/App.tsx | 4 +- client/src/components/CodeEditor.tsx | 32 ++--- .../components/EmptySectionPlaceholder.tsx | 8 +- client/src/components/Header.tsx | 29 ++-- client/src/components/LanguageSelect.tsx | 40 +++--- client/src/components/PageLayout.tsx | 9 +- client/src/data/schema.ts | 7 +- client/src/data/useGetAllEvents.tsx | 75 +++++----- client/src/data/useGetProblem.tsx | 66 +++++---- client/src/index.css | 2 +- client/src/index.tsx | 22 +-- client/src/pages/Compete/CompeteTabs.tsx | 10 +- client/src/pages/Compete/InfoTabs.tsx | 14 +- .../pages/Compete/Problem/CodeEditorPane.tsx | 24 ++-- client/src/pages/Compete/Problem/index.tsx | 47 +++--- client/src/pages/Compete/SampleTestCases.tsx | 18 +-- client/src/pages/Compete/SubmissionStatus.tsx | 84 +++++------ .../Compete/Submissions/SubmissionPreview.tsx | 81 +++++------ .../Compete/Submissions/SubmissionsTable.tsx | 71 +++++----- .../src/pages/Compete/Submissions/index.tsx | 134 +++++++++--------- client/src/pages/Compete/index.tsx | 11 +- client/src/theme/index.ts | 10 +- docker-compose.q.yml | 8 +- executioner/index.ts | 59 ++++---- .../runtimes/languages/nodejs/tsconfig.json | 14 +- lib/queue/tsconfig.json | 14 +- senatus/src/admin/tsconfig.json | 12 +- senatus/src/api/event/controllers/event.ts | 2 +- .../api/event/documentation/1.0.0/event.json | 24 +--- .../api/execution/controllers/execution.ts | 2 +- .../src/api/language/controllers/language.ts | 2 +- .../documentation/1.0.0/language.json | 20 +-- .../src/api/problem/controllers/problem.ts | 2 +- .../problem/documentation/1.0.0/problem.json | 24 +--- senatus/src/api/submission/routes/0-submit.ts | 3 +- .../api/test-case/controllers/test-case.ts | 2 +- senatus/src/index.ts | 46 +++--- senatus/tsconfig.json | 7 +- web/README.md | 2 +- web/codegen.ts | 10 +- web/postcss.config.js | 2 +- web/src/App.tsx | 2 +- web/src/components/Layout.tsx | 36 ++--- web/src/components/ui/avatar.tsx | 31 ++-- web/src/components/ui/badge.tsx | 32 ++--- web/src/components/ui/button.tsx | 64 ++++----- web/src/components/ui/card.tsx | 125 +++++++--------- web/src/components/ui/dropdown-menu.tsx | 98 ++++++------- web/src/components/ui/input.tsx | 8 +- web/src/components/ui/label.tsx | 27 ++-- web/src/components/ui/select.tsx | 83 +++++------ web/src/components/ui/separator.tsx | 41 +++--- web/src/components/ui/table.tsx | 112 ++++++--------- web/src/components/ui/tabs.tsx | 34 ++--- web/src/components/ui/toast.tsx | 79 +++++------ web/src/components/ui/toaster.tsx | 14 +- web/src/components/ui/use-toast.ts | 48 +++---- web/src/contexts/AuthContext.tsx | 50 +++---- web/src/lib/utils.ts | 6 +- web/src/main.tsx | 2 +- web/src/pages/LoginPage.tsx | 11 +- web/src/pages/RegisterPage.tsx | 11 +- web/src/vite-env.d.ts | 4 +- web/vite.config.ts | 8 +- 73 files changed, 934 insertions(+), 1147 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index de80314..f3cf53f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,7 +4,7 @@ ## What has been done? - - [ ] +- [ ] ## Sceenshots/Videos diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d8bfa67..da7f219 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,7 +68,7 @@ jobs: - 'executioner/**/rust/**' golang_executioner: - 'executioner/**/golang/**' - + senatus: name: Senatus needs: find_modified_files @@ -180,7 +180,6 @@ jobs: docker-context: ./executioner/runtimes/languages/rust/ docker-file-path: ./executioner/runtimes/languages/rust/Dockerfile docker-tags: ghcr.io/42dotmk/colosseum-executioner-rust:latest - golang_executioner: name: Golang executioner @@ -191,4 +190,3 @@ jobs: docker-context: ./executioner/runtimes/languages/golang/ docker-file-path: ./executioner/runtimes/languages/golang/Dockerfile docker-tags: ghcr.io/42dotmk/colosseum-executioner-golang:latest - \ No newline at end of file diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 062ba2c..d3f944c 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -1,4 +1,4 @@ -# Documentation +# Documentation You can set up husky in 2 ways - automagical, or manual, pick your poision and follow the steps. @@ -17,6 +17,7 @@ It will install husky and set up the pre-commit hooks automagically. `npm i -g husky` > **Notes:** +> > - **IMPORTANT**: Make sure the `Git` version is 2.9 or above > - Currently ESLint and TypeScript checks are enabled for the client, should also setup for caesar and senatus as well diff --git a/README.md b/README.md index 304942e..5d2922f 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,50 @@ # Colosseum: Organize Competitive Programming and Interview Events + Join us every Tuesday at 5:30 PM in Base42 as we embark on the journey of crafting the colossal masterpiece Colosseum, our open-source web solution tailored for organizing competitive programming and interview events. ## Core Applications: -* **Client (Front-end)**: Crafted with React, our frontend provides an intuitive and seamless user experience. -* **Senatus (Back-end)**: Powered by Strapi, our backend handles the core functionalities of our platform. -* **Caesar (Code Execution)**: Currently in the prototyping phase, Caesar will be the engine behind code testing and execution, ensuring accuracy and efficiency. +- **Client (Front-end)**: Crafted with React, our frontend provides an intuitive and seamless user experience. +- **Senatus (Back-end)**: Powered by Strapi, our backend handles the core functionalities of our platform. +- **Caesar (Code Execution)**: Currently in the prototyping phase, Caesar will be the engine behind code testing and execution, ensuring accuracy and efficiency. ## Event Details: -* **Date**: Every Tuesday -* **Time**: 5:30 PM -* **Location**: Base42 + +- **Date**: Every Tuesday +- **Time**: 5:30 PM +- **Location**: Base42 > Besides app implementation, our community plans to organize competitive programming knowledge-sharing events and many competitions. Drop by if you're interested in participating in these activities! ## Quicklinks -* [Wiki](https://wiki.42.mk/en/projects/colosseum-competitive-programming-engine) -* [Source code](https://github.com/42dotmk/colosseum) -* [Task management board](https://plane.42.mk/colosseum) -* [Front-end DEV URL](https://colosseum.dev) -* [Back-end DEV URL](https://senatus.colosseum.dev/) + +- [Wiki](https://wiki.42.mk/en/projects/colosseum-competitive-programming-engine) +- [Source code](https://github.com/42dotmk/colosseum) +- [Task management board](https://plane.42.mk/colosseum) +- [Front-end DEV URL](https://colosseum.dev) +- [Back-end DEV URL](https://senatus.colosseum.dev/) ## List of Contributors + ### Development -* Veronika Gjoreva [@vergjor](https://github.com/vergjor) -* Ilija Boshkov [@iboshkov](https://github.com/iboshkov) -* Mario Stojchevski [@MarioStojcevski](https://github.com/MarioStojcevski) -* Vasilaki Tocili [@VasilakiG](https://github.com/VasilakiG) -* Gjorgi Krenkov [@gjorgi-krenkov](https://github.com/gjorgi-krenkov) -* Jovan Mihov [@jovanmihov](https://github.com/jovanmihov) + +- Veronika Gjoreva [@vergjor](https://github.com/vergjor) +- Ilija Boshkov [@iboshkov](https://github.com/iboshkov) +- Mario Stojchevski [@MarioStojcevski](https://github.com/MarioStojcevski) +- Vasilaki Tocili [@VasilakiG](https://github.com/VasilakiG) +- Gjorgi Krenkov [@gjorgi-krenkov](https://github.com/gjorgi-krenkov) +- Jovan Mihov [@jovanmihov](https://github.com/jovanmihov) ### Design -* Bojana Dimitrova -* Tereza Lozanovska + +- Bojana Dimitrova +- Tereza Lozanovska ### Organization -* Martin Dinev [@martin-dinev](https://github.com/martin-dinev) -* Pavlina Buchevska + +- Martin Dinev [@martin-dinev](https://github.com/martin-dinev) +- Pavlina Buchevska ## License + Colosseum is [MIT Licensed](https://github.com/42dotmk/colosseum/blob/main/LICENSE) diff --git a/SETUP.md b/SETUP.md index 34e2db0..fc4d62d 100644 --- a/SETUP.md +++ b/SETUP.md @@ -1,6 +1,6 @@ ## Prerequisites -Create a `.env` file in the root of the repository by following the example file: `.env.example` +Create a `.env` file in the root of the repository by following the example file: `.env.example` ### RabbitMQ @@ -55,7 +55,7 @@ Usually you just need to run `pull.sh` to get the images available locally. ### Senatus -You initially would need to setup the `.env` file by following the example file: `.env.example` +You initially would need to setup the `.env` file by following the example file: `.env.example` ```bash cd senatus; diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs index 204e558..3fce99a 100644 --- a/client/.eslintrc.cjs +++ b/client/.eslintrc.cjs @@ -10,9 +10,6 @@ module.exports = { parser: '@typescript-eslint/parser', plugins: ['react-refresh'], rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], + 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], }, -} +}; diff --git a/client/.eslintrc.yml b/client/.eslintrc.yml index 88167ac..756c183 100644 --- a/client/.eslintrc.yml +++ b/client/.eslintrc.yml @@ -1,6 +1,6 @@ parser: '@typescript-eslint/parser' parserOptions: - project: + project: - './**/client/tsconfig.json' - './**/client/tsconfig.node.json' plugins: @@ -19,18 +19,15 @@ settings: import/resolver: typescript: true node: true -rules: { - 'react/jsx-filename-extension': 'off', - 'react/react-in-jsx-scope': 'off', - 'react/function-component-definition': 'off', - 'import/extensions': 'off', - 'react/require-default-props': 'off', - "no-restricted-syntax": [ - "error", - "FunctionExpression", - "FunctionDeclaration" - ] -} +rules: + { + 'react/jsx-filename-extension': 'off', + 'react/react-in-jsx-scope': 'off', + 'react/function-component-definition': 'off', + 'import/extensions': 'off', + 'react/require-default-props': 'off', + 'no-restricted-syntax': ['error', 'FunctionExpression', 'FunctionDeclaration'], + } overrides: - files: vite.config.ts rules: diff --git a/client/README.md b/client/README.md index ddaab31..6b1f438 100644 --- a/client/README.md +++ b/client/README.md @@ -1,2 +1 @@ # Colosseum - diff --git a/client/codegen.ts b/client/codegen.ts index 43cb661..d6e79a7 100644 --- a/client/codegen.ts +++ b/client/codegen.ts @@ -1,4 +1,4 @@ -import 'dotenv/config' +import 'dotenv/config'; import { CodegenConfig } from '@graphql-codegen/cli'; import { GQL_URL } from './src/config'; @@ -12,10 +12,10 @@ const config: CodegenConfig = { plugins: [], presetConfig: { gqlTagName: 'gql', - } - } + }, + }, }, ignoreNoDocuments: true, }; -export default config; \ No newline at end of file +export default config; diff --git a/client/src/App.tsx b/client/src/App.tsx index 12f538b..4036c98 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,6 +1,4 @@ -import { - Route, Routes, BrowserRouter, Navigate, -} from 'react-router-dom'; +import { Route, Routes, BrowserRouter, Navigate } from 'react-router-dom'; import { Grid } from '@mui/material'; import HomePage from './pages/Home'; import CompetePage from './pages/Compete'; diff --git a/client/src/components/CodeEditor.tsx b/client/src/components/CodeEditor.tsx index 0877509..213fabf 100644 --- a/client/src/components/CodeEditor.tsx +++ b/client/src/components/CodeEditor.tsx @@ -1,13 +1,13 @@ -import { Editor, loader } from "@monaco-editor/react"; -import { Box } from "@mui/material"; +import { Editor, loader } from '@monaco-editor/react'; +import { Box } from '@mui/material'; loader.init().then((monaco) => { - monaco.editor.defineTheme("editorTheme", { - base: "vs-dark", + monaco.editor.defineTheme('editorTheme', { + base: 'vs-dark', inherit: true, rules: [], colors: { - "editor.background": "#282A36", + 'editor.background': '#282A36', }, }); }); @@ -23,19 +23,19 @@ const CodeEditor = ({ language, code, readOnly, onCodeChange }: Props) => { const handleOnChange = (codeText: string) => { if (readOnly) return; onCodeChange?.(codeText); - } + }; return ( { theme="editorTheme" language={language} value={code.join('\n')} - onChange={(e) => handleOnChange(e ?? "")} + onChange={(e) => handleOnChange(e ?? '')} options={{ readOnly, automaticLayout: true, - renderLineHighlight: "none", + renderLineHighlight: 'none', lineNumbersMinChars: 4, overviewRulerLanes: 0, - cursorStyle: "line-thin", + cursorStyle: 'line-thin', scrollbar: { horizontalSliderSize: 4, verticalSliderSize: 8, diff --git a/client/src/components/EmptySectionPlaceholder.tsx b/client/src/components/EmptySectionPlaceholder.tsx index 73cdc39..978fe82 100644 --- a/client/src/components/EmptySectionPlaceholder.tsx +++ b/client/src/components/EmptySectionPlaceholder.tsx @@ -6,13 +6,9 @@ type Props = { }; const EmptySectionPlaceholder = ({ message }: Props) => ( -
+
- + {message}
diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx index ae4c6fa..226d8fd 100644 --- a/client/src/components/Header.tsx +++ b/client/src/components/Header.tsx @@ -1,12 +1,4 @@ -import { - Toolbar, - Box, - Typography, - Button, - AppBar, - Tab, - Tabs, -} from '@mui/material'; +import { Toolbar, Box, Typography, Button, AppBar, Tab, Tabs } from '@mui/material'; import { Link, useLocation } from 'react-router-dom'; const Header = () => { @@ -14,13 +6,10 @@ const Header = () => { return ( - - - - + + + + logo Colosseum @@ -37,7 +26,13 @@ const Header = () => { role="navigation" > - + diff --git a/client/src/components/LanguageSelect.tsx b/client/src/components/LanguageSelect.tsx index 5bec647..24fdb82 100644 --- a/client/src/components/LanguageSelect.tsx +++ b/client/src/components/LanguageSelect.tsx @@ -1,4 +1,4 @@ -import { Box, FormControl, MenuItem, Select, Typography } from "@mui/material"; +import { Box, FormControl, MenuItem, Select, Typography } from '@mui/material'; type Props = { currentLanguage: string; @@ -6,44 +6,40 @@ type Props = { setCurrentLanguage: (language: string) => void; }; -const LanguageSelect = ({ - currentLanguage, - languages, - setCurrentLanguage, -}: Props) => ( +const LanguageSelect = ({ currentLanguage, languages, setCurrentLanguage }: Props) => ( SELECT LANGUAGE: - + ( ); }, ); -Input.displayName = "Input"; +Input.displayName = 'Input'; export { Input }; diff --git a/web/src/components/ui/label.tsx b/web/src/components/ui/label.tsx index 683faa7..470162f 100644 --- a/web/src/components/ui/label.tsx +++ b/web/src/components/ui/label.tsx @@ -1,24 +1,19 @@ -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from 'react'; +import * as LabelPrimitive from '@radix-ui/react-label'; +import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; const labelVariants = cva( - "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" -) + 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', +); const Label = React.forwardRef< React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps + React.ComponentPropsWithoutRef & VariantProps >(({ className, ...props }, ref) => ( - -)) -Label.displayName = LabelPrimitive.Root.displayName + +)); +Label.displayName = LabelPrimitive.Root.displayName; -export { Label } +export { Label }; diff --git a/web/src/components/ui/select.tsx b/web/src/components/ui/select.tsx index fe56d4d..343710e 100644 --- a/web/src/components/ui/select.tsx +++ b/web/src/components/ui/select.tsx @@ -1,14 +1,14 @@ -import * as React from "react" -import * as SelectPrimitive from "@radix-ui/react-select" -import { Check, ChevronDown, ChevronUp } from "lucide-react" +import * as React from 'react'; +import * as SelectPrimitive from '@radix-ui/react-select'; +import { Check, ChevronDown, ChevronUp } from 'lucide-react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -const Select = SelectPrimitive.Root +const Select = SelectPrimitive.Root; -const SelectGroup = SelectPrimitive.Group +const SelectGroup = SelectPrimitive.Group; -const SelectValue = SelectPrimitive.Value +const SelectValue = SelectPrimitive.Value; const SelectTrigger = React.forwardRef< React.ElementRef, @@ -17,8 +17,8 @@ const SelectTrigger = React.forwardRef< span]:line-clamp-1", - className + 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1', + className, )} {...props} > @@ -27,8 +27,8 @@ const SelectTrigger = React.forwardRef< -)) -SelectTrigger.displayName = SelectPrimitive.Trigger.displayName +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; const SelectScrollUpButton = React.forwardRef< React.ElementRef, @@ -36,16 +36,13 @@ const SelectScrollUpButton = React.forwardRef< >(({ className, ...props }, ref) => ( -)) -SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; const SelectScrollDownButton = React.forwardRef< React.ElementRef, @@ -53,30 +50,26 @@ const SelectScrollDownButton = React.forwardRef< >(({ className, ...props }, ref) => ( -)) -SelectScrollDownButton.displayName = - SelectPrimitive.ScrollDownButton.displayName +)); +SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName; const SelectContent = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, children, position = "popper", ...props }, ref) => ( +>(({ className, children, position = 'popper', ...props }, ref) => ( {children} @@ -94,8 +87,8 @@ const SelectContent = React.forwardRef< -)) -SelectContent.displayName = SelectPrimitive.Content.displayName +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; const SelectLabel = React.forwardRef< React.ElementRef, @@ -103,11 +96,11 @@ const SelectLabel = React.forwardRef< >(({ className, ...props }, ref) => ( -)) -SelectLabel.displayName = SelectPrimitive.Label.displayName +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; const SelectItem = React.forwardRef< React.ElementRef, @@ -116,8 +109,8 @@ const SelectItem = React.forwardRef< @@ -129,8 +122,8 @@ const SelectItem = React.forwardRef< {children} -)) -SelectItem.displayName = SelectPrimitive.Item.displayName +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; const SelectSeparator = React.forwardRef< React.ElementRef, @@ -138,11 +131,11 @@ const SelectSeparator = React.forwardRef< >(({ className, ...props }, ref) => ( -)) -SelectSeparator.displayName = SelectPrimitive.Separator.displayName +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; export { Select, @@ -155,4 +148,4 @@ export { SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, -} +}; diff --git a/web/src/components/ui/separator.tsx b/web/src/components/ui/separator.tsx index 6d7f122..37838d6 100644 --- a/web/src/components/ui/separator.tsx +++ b/web/src/components/ui/separator.tsx @@ -1,29 +1,24 @@ -import * as React from "react" -import * as SeparatorPrimitive from "@radix-ui/react-separator" +import * as React from 'react'; +import * as SeparatorPrimitive from '@radix-ui/react-separator'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; const Separator = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->( - ( - { className, orientation = "horizontal", decorative = true, ...props }, - ref - ) => ( - - ) -) -Separator.displayName = SeparatorPrimitive.Root.displayName +>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => ( + +)); +Separator.displayName = SeparatorPrimitive.Root.displayName; -export { Separator } +export { Separator }; diff --git a/web/src/components/ui/table.tsx b/web/src/components/ui/table.tsx index 7f3502f..e538a0f 100644 --- a/web/src/components/ui/table.tsx +++ b/web/src/components/ui/table.tsx @@ -1,40 +1,31 @@ -import * as React from "react" +import * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -const Table = React.forwardRef< - HTMLTableElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
- - -)) -Table.displayName = "Table" +const Table = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+
+ + ), +); +Table.displayName = 'Table'; const TableHeader = React.forwardRef< HTMLTableSectionElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( - -)) -TableHeader.displayName = "TableHeader" + +)); +TableHeader.displayName = 'TableHeader'; const TableBody = React.forwardRef< HTMLTableSectionElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( - -)) -TableBody.displayName = "TableBody" + +)); +TableBody.displayName = 'TableBody'; const TableFooter = React.forwardRef< HTMLTableSectionElement, @@ -42,29 +33,25 @@ const TableFooter = React.forwardRef< >(({ className, ...props }, ref) => ( tr]:last:border-b-0", - className - )} + className={cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', className)} {...props} /> -)) -TableFooter.displayName = "TableFooter" +)); +TableFooter.displayName = 'TableFooter'; -const TableRow = React.forwardRef< - HTMLTableRowElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( - -)) -TableRow.displayName = "TableRow" +const TableRow = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ), +); +TableRow.displayName = 'TableRow'; const TableHead = React.forwardRef< HTMLTableCellElement, @@ -73,13 +60,13 @@ const TableHead = React.forwardRef<
-)) -TableHead.displayName = "TableHead" +)); +TableHead.displayName = 'TableHead'; const TableCell = React.forwardRef< HTMLTableCellElement, @@ -87,31 +74,18 @@ const TableCell = React.forwardRef< >(({ className, ...props }, ref) => ( -)) -TableCell.displayName = "TableCell" +)); +TableCell.displayName = 'TableCell'; const TableCaption = React.forwardRef< HTMLTableCaptionElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( -
-)) -TableCaption.displayName = "TableCaption" + +)); +TableCaption.displayName = 'TableCaption'; -export { - Table, - TableHeader, - TableBody, - TableFooter, - TableHead, - TableRow, - TableCell, - TableCaption, -} +export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption }; diff --git a/web/src/components/ui/tabs.tsx b/web/src/components/ui/tabs.tsx index f57fffd..737a81c 100644 --- a/web/src/components/ui/tabs.tsx +++ b/web/src/components/ui/tabs.tsx @@ -1,9 +1,9 @@ -import * as React from "react" -import * as TabsPrimitive from "@radix-ui/react-tabs" +import * as React from 'react'; +import * as TabsPrimitive from '@radix-ui/react-tabs'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -const Tabs = TabsPrimitive.Root +const Tabs = TabsPrimitive.Root; const TabsList = React.forwardRef< React.ElementRef, @@ -12,13 +12,13 @@ const TabsList = React.forwardRef< -)) -TabsList.displayName = TabsPrimitive.List.displayName +)); +TabsList.displayName = TabsPrimitive.List.displayName; const TabsTrigger = React.forwardRef< React.ElementRef, @@ -27,13 +27,13 @@ const TabsTrigger = React.forwardRef< -)) -TabsTrigger.displayName = TabsPrimitive.Trigger.displayName +)); +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; const TabsContent = React.forwardRef< React.ElementRef, @@ -42,12 +42,12 @@ const TabsContent = React.forwardRef< -)) -TabsContent.displayName = TabsPrimitive.Content.displayName +)); +TabsContent.displayName = TabsPrimitive.Content.displayName; -export { Tabs, TabsList, TabsTrigger, TabsContent } +export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/web/src/components/ui/toast.tsx b/web/src/components/ui/toast.tsx index a822477..c387f75 100644 --- a/web/src/components/ui/toast.tsx +++ b/web/src/components/ui/toast.tsx @@ -1,11 +1,11 @@ -import * as React from "react" -import * as ToastPrimitives from "@radix-ui/react-toast" -import { cva, type VariantProps } from "class-variance-authority" -import { X } from "lucide-react" +import * as React from 'react'; +import * as ToastPrimitives from '@radix-ui/react-toast'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { X } from 'lucide-react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -const ToastProvider = ToastPrimitives.Provider +const ToastProvider = ToastPrimitives.Provider; const ToastViewport = React.forwardRef< React.ElementRef, @@ -14,34 +14,33 @@ const ToastViewport = React.forwardRef< -)) -ToastViewport.displayName = ToastPrimitives.Viewport.displayName +)); +ToastViewport.displayName = ToastPrimitives.Viewport.displayName; const toastVariants = cva( - "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", + 'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full', { variants: { variant: { - default: "border bg-background text-foreground", + default: 'border bg-background text-foreground', destructive: - "destructive group border-destructive bg-destructive text-destructive-foreground", + 'destructive group border-destructive bg-destructive text-destructive-foreground', }, }, defaultVariants: { - variant: "default", + variant: 'default', }, - } -) + }, +); const Toast = React.forwardRef< React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps + React.ComponentPropsWithoutRef & VariantProps >(({ className, variant, ...props }, ref) => { return ( - ) -}) -Toast.displayName = ToastPrimitives.Root.displayName + ); +}); +Toast.displayName = ToastPrimitives.Root.displayName; const ToastAction = React.forwardRef< React.ElementRef, @@ -60,13 +59,13 @@ const ToastAction = React.forwardRef< -)) -ToastAction.displayName = ToastPrimitives.Action.displayName +)); +ToastAction.displayName = ToastPrimitives.Action.displayName; const ToastClose = React.forwardRef< React.ElementRef, @@ -75,28 +74,24 @@ const ToastClose = React.forwardRef< -)) -ToastClose.displayName = ToastPrimitives.Close.displayName +)); +ToastClose.displayName = ToastPrimitives.Close.displayName; const ToastTitle = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( - -)) -ToastTitle.displayName = ToastPrimitives.Title.displayName + +)); +ToastTitle.displayName = ToastPrimitives.Title.displayName; const ToastDescription = React.forwardRef< React.ElementRef, @@ -104,15 +99,15 @@ const ToastDescription = React.forwardRef< >(({ className, ...props }, ref) => ( -)) -ToastDescription.displayName = ToastPrimitives.Description.displayName +)); +ToastDescription.displayName = ToastPrimitives.Description.displayName; -type ToastProps = React.ComponentPropsWithoutRef +type ToastProps = React.ComponentPropsWithoutRef; -type ToastActionElement = React.ReactElement +type ToastActionElement = React.ReactElement; export { type ToastProps, @@ -124,4 +119,4 @@ export { ToastDescription, ToastClose, ToastAction, -} +}; diff --git a/web/src/components/ui/toaster.tsx b/web/src/components/ui/toaster.tsx index a2209ba..1b4e561 100644 --- a/web/src/components/ui/toaster.tsx +++ b/web/src/components/ui/toaster.tsx @@ -5,11 +5,11 @@ import { ToastProvider, ToastTitle, ToastViewport, -} from "@/components/ui/toast" -import { useToast } from "@/components/ui/use-toast" +} from '@/components/ui/toast'; +import { useToast } from '@/components/ui/use-toast'; export function Toaster() { - const { toasts } = useToast() + const { toasts } = useToast(); return ( @@ -18,16 +18,14 @@ export function Toaster() {
{title && {title}} - {description && ( - {description} - )} + {description && {description}}
{action}
- ) + ); })}
- ) + ); } diff --git a/web/src/components/ui/use-toast.ts b/web/src/components/ui/use-toast.ts index 277dc51..c50ec45 100644 --- a/web/src/components/ui/use-toast.ts +++ b/web/src/components/ui/use-toast.ts @@ -1,6 +1,6 @@ -import * as React from "react"; +import * as React from 'react'; -import type { ToastActionElement, ToastProps } from "@/components/ui/toast"; +import type { ToastActionElement, ToastProps } from '@/components/ui/toast'; const TOAST_LIMIT = 1; const TOAST_REMOVE_DELAY = 1000000; @@ -13,10 +13,10 @@ type ToasterToast = ToastProps & { }; type ActionType = { - ADD_TOAST: "ADD_TOAST"; - UPDATE_TOAST: "UPDATE_TOAST"; - DISMISS_TOAST: "DISMISS_TOAST"; - REMOVE_TOAST: "REMOVE_TOAST"; + ADD_TOAST: 'ADD_TOAST'; + UPDATE_TOAST: 'UPDATE_TOAST'; + DISMISS_TOAST: 'DISMISS_TOAST'; + REMOVE_TOAST: 'REMOVE_TOAST'; }; let count = 0; @@ -28,20 +28,20 @@ function genId() { type Action = | { - type: ActionType["ADD_TOAST"]; + type: ActionType['ADD_TOAST']; toast: ToasterToast; } | { - type: ActionType["UPDATE_TOAST"]; + type: ActionType['UPDATE_TOAST']; toast: Partial; } | { - type: ActionType["DISMISS_TOAST"]; - toastId?: ToasterToast["id"]; + type: ActionType['DISMISS_TOAST']; + toastId?: ToasterToast['id']; } | { - type: ActionType["REMOVE_TOAST"]; - toastId?: ToasterToast["id"]; + type: ActionType['REMOVE_TOAST']; + toastId?: ToasterToast['id']; }; interface State { @@ -58,7 +58,7 @@ const addToRemoveQueue = (toastId: string) => { const timeout = setTimeout(() => { toastTimeouts.delete(toastId); dispatch({ - type: "REMOVE_TOAST", + type: 'REMOVE_TOAST', toastId: toastId, }); }, TOAST_REMOVE_DELAY); @@ -68,21 +68,19 @@ const addToRemoveQueue = (toastId: string) => { export const reducer = (state: State, action: Action): State => { switch (action.type) { - case "ADD_TOAST": + case 'ADD_TOAST': return { ...state, toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), }; - case "UPDATE_TOAST": + case 'UPDATE_TOAST': return { ...state, - toasts: state.toasts.map((t) => - t.id === action.toast.id ? { ...t, ...action.toast } : t, - ), + toasts: state.toasts.map((t) => (t.id === action.toast.id ? { ...t, ...action.toast } : t)), }; - case "DISMISS_TOAST": { + case 'DISMISS_TOAST': { const { toastId } = action; if (toastId) { @@ -105,7 +103,7 @@ export const reducer = (state: State, action: Action): State => { ), }; } - case "REMOVE_TOAST": + case 'REMOVE_TOAST': if (action.toastId === undefined) { return { ...state, @@ -130,20 +128,20 @@ function dispatch(action: Action) { }); } -type Toast = Omit; +type Toast = Omit; function toast({ ...props }: Toast) { const id = genId(); const update = (props: ToasterToast) => dispatch({ - type: "UPDATE_TOAST", + type: 'UPDATE_TOAST', toast: { ...props, id }, }); - const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); + const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id }); dispatch({ - type: "ADD_TOAST", + type: 'ADD_TOAST', toast: { ...props, id, @@ -179,7 +177,7 @@ function useToast() { return { ...state, toast, - dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), + dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }), }; } diff --git a/web/src/contexts/AuthContext.tsx b/web/src/contexts/AuthContext.tsx index d126388..f567fb9 100644 --- a/web/src/contexts/AuthContext.tsx +++ b/web/src/contexts/AuthContext.tsx @@ -1,5 +1,5 @@ -import React, { createContext, useContext, useState } from "react"; -import { REST_URL } from "@/config"; +import React, { createContext, useContext, useState } from 'react'; +import { REST_URL } from '@/config'; interface User { documentId: string; @@ -10,11 +10,7 @@ interface User { interface AuthContextType { user: User | null; login: (identifier: string, password: string) => Promise; - register: ( - username: string, - email: string, - password: string, - ) => Promise; + register: (username: string, email: string, password: string) => Promise; logout: () => void; isLoading: boolean; } @@ -23,8 +19,8 @@ const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState(() => { - const token = localStorage.getItem("jwt"); - const storedUser = localStorage.getItem("user"); + const token = localStorage.getItem('jwt'); + const storedUser = localStorage.getItem('user'); if (!token || !storedUser) { return null; @@ -33,8 +29,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { try { return JSON.parse(storedUser) as User; } catch { - localStorage.removeItem("jwt"); - localStorage.removeItem("user"); + localStorage.removeItem('jwt'); + localStorage.removeItem('user'); return null; } }); @@ -53,51 +49,47 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const login = async (identifier: string, password: string) => { const response = await fetch(`${REST_URL}/auth/local`, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: JSON.stringify({ identifier, password }), }); if (!response.ok) { const error = await response.json(); - throw new Error(error.error?.message || "Login failed"); + throw new Error(error.error?.message || 'Login failed'); } const data = await response.json(); - localStorage.setItem("jwt", data.jwt); - localStorage.setItem("user", JSON.stringify(data.user)); + localStorage.setItem('jwt', data.jwt); + localStorage.setItem('user', JSON.stringify(data.user)); setUser(data.user); }; - const register = async ( - username: string, - email: string, - password: string, - ) => { + const register = async (username: string, email: string, password: string) => { const response = await fetch(`${REST_URL}/auth/local/register`, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: JSON.stringify({ username, email, password }), }); if (!response.ok) { const error = await response.json(); - throw new Error(error.error?.message || "Registration failed"); + throw new Error(error.error?.message || 'Registration failed'); } const data = await response.json(); - localStorage.setItem("jwt", data.jwt); - localStorage.setItem("user", JSON.stringify(data.user)); + localStorage.setItem('jwt', data.jwt); + localStorage.setItem('user', JSON.stringify(data.user)); setUser(data.user); }; const logout = () => { - localStorage.removeItem("jwt"); - localStorage.removeItem("user"); + localStorage.removeItem('jwt'); + localStorage.removeItem('user'); setUser(null); }; @@ -111,7 +103,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { export function useAuth() { const context = useContext(AuthContext); if (context === undefined) { - throw new Error("useAuth must be used within an AuthProvider"); + throw new Error('useAuth must be used within an AuthProvider'); } return context; } diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts index d084cca..9ad0df4 100644 --- a/web/src/lib/utils.ts +++ b/web/src/lib/utils.ts @@ -1,6 +1,6 @@ -import { type ClassValue, clsx } from "clsx" -import { twMerge } from "tailwind-merge" +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } diff --git a/web/src/main.tsx b/web/src/main.tsx index 2339d59..9aa52ff 100644 --- a/web/src/main.tsx +++ b/web/src/main.tsx @@ -6,5 +6,5 @@ import './index.css'; ReactDOM.createRoot(document.getElementById('root')!).render( - + , ); diff --git a/web/src/pages/LoginPage.tsx b/web/src/pages/LoginPage.tsx index 3e47910..59db4fa 100644 --- a/web/src/pages/LoginPage.tsx +++ b/web/src/pages/LoginPage.tsx @@ -4,7 +4,14 @@ import { useAuth } from '@/contexts/AuthContext'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; -import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from '@/components/ui/card'; import { useToast } from '@/components/ui/use-toast'; import { Terminal } from 'lucide-react'; @@ -47,7 +54,7 @@ export default function LoginPage() { Colosseum - + Sign in diff --git a/web/src/pages/RegisterPage.tsx b/web/src/pages/RegisterPage.tsx index 8448ed8..81d7ea0 100644 --- a/web/src/pages/RegisterPage.tsx +++ b/web/src/pages/RegisterPage.tsx @@ -4,7 +4,14 @@ import { useAuth } from '@/contexts/AuthContext'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; -import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from '@/components/ui/card'; import { useToast } from '@/components/ui/use-toast'; import { Terminal } from 'lucide-react'; @@ -59,7 +66,7 @@ export default function RegisterPage() { Colosseum - + Create account diff --git a/web/src/vite-env.d.ts b/web/src/vite-env.d.ts index 42fda0d..547462d 100644 --- a/web/src/vite-env.d.ts +++ b/web/src/vite-env.d.ts @@ -1,9 +1,9 @@ /// interface ImportMetaEnv { - readonly VITE_SENATUS_URL: string + readonly VITE_SENATUS_URL: string; } interface ImportMeta { - readonly env: ImportMetaEnv + readonly env: ImportMetaEnv; } diff --git a/web/vite.config.ts b/web/vite.config.ts index 2e04ff9..94705de 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -1,6 +1,6 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' -import path from 'path' +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import path from 'path'; export default defineConfig({ plugins: [react()], @@ -12,4 +12,4 @@ export default defineConfig({ server: { port: 1338, }, -}) +}); From 46ef6f2b7d28bf418d4e5805626aec7c97b053ec Mon Sep 17 00:00:00 2001 From: MODDI1 <81722254+MODDI1@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:17:49 +0200 Subject: [PATCH 05/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- senatus/src/api/submission/controllers/submission.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/senatus/src/api/submission/controllers/submission.ts b/senatus/src/api/submission/controllers/submission.ts index 781c5f5..035fa75 100644 --- a/senatus/src/api/submission/controllers/submission.ts +++ b/senatus/src/api/submission/controllers/submission.ts @@ -23,7 +23,7 @@ export default factories.createCoreController('api::submission.submission', ({ s if (!submission) { ctx.status = 404; - ctx.body = { erorr: 'Submission not found' }; + ctx.body = { error: 'Submission not found' }; return; } From 69cdc88094ff0dc56743d313767d49e864ca61cb Mon Sep 17 00:00:00 2001 From: MODDI1 <81722254+MODDI1@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:18:08 +0200 Subject: [PATCH 06/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- senatus/src/api/submission/controllers/submission.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/senatus/src/api/submission/controllers/submission.ts b/senatus/src/api/submission/controllers/submission.ts index 035fa75..5d0e9c2 100644 --- a/senatus/src/api/submission/controllers/submission.ts +++ b/senatus/src/api/submission/controllers/submission.ts @@ -35,7 +35,7 @@ export default factories.createCoreController('api::submission.submission', ({ s if (!submission.language) { ctx.status = 400; - ctx.body = { error: 'Submission has no source code' }; + ctx.body = { error: 'Submission has no language' }; return; } From 905754529667fd9863084c596f3845cfea180e78 Mon Sep 17 00:00:00 2001 From: MODDI1 <81722254+MODDI1@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:19:56 +0200 Subject: [PATCH 07/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .prettierignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.prettierignore b/.prettierignore index 542e864..1a27240 100644 --- a/.prettierignore +++ b/.prettierignore @@ -28,4 +28,3 @@ senatus/src/extensions/documentation/public/** # Minified/generated assets **/*.min.js **/*.min.css -clear From c97ac3915f8d4a3e032660d9ddd81a9c31bc20b3 Mon Sep 17 00:00:00 2001 From: MODDI1 <81722254+MODDI1@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:18:12 +0200 Subject: [PATCH 08/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- senatus/src/api/submission/controllers/submission.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/senatus/src/api/submission/controllers/submission.ts b/senatus/src/api/submission/controllers/submission.ts index 5d0e9c2..2e89a12 100644 --- a/senatus/src/api/submission/controllers/submission.ts +++ b/senatus/src/api/submission/controllers/submission.ts @@ -98,7 +98,14 @@ export default factories.createCoreController('api::submission.submission', ({ s const msg = JSON.stringify(qPayload); - const { publish, disconnect } = await connect(strapi.config.get('server.app.rabbitUrl')); + const rabbitUrl = strapi.config.get('server.app.rabbitUrl') as string | undefined; + if (!rabbitUrl) { + ctx.status = 500; + ctx.body = { error: 'RabbitMQ URL is not configured (server.app.rabbitUrl)' }; + return; + } + + const { publish, disconnect } = await connect(rabbitUrl); console.log('Connected to RabbitMQ'); From 40b24c1bd2244d7270d822ec2963fb6b627576f4 Mon Sep 17 00:00:00 2001 From: MODDI1 <81722254+MODDI1@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:18:45 +0200 Subject: [PATCH 09/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- client/.eslintrc.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/client/.eslintrc.yml b/client/.eslintrc.yml index 756c183..416db9d 100644 --- a/client/.eslintrc.yml +++ b/client/.eslintrc.yml @@ -20,14 +20,15 @@ settings: typescript: true node: true rules: - { - 'react/jsx-filename-extension': 'off', - 'react/react-in-jsx-scope': 'off', - 'react/function-component-definition': 'off', - 'import/extensions': 'off', - 'react/require-default-props': 'off', - 'no-restricted-syntax': ['error', 'FunctionExpression', 'FunctionDeclaration'], - } + react/jsx-filename-extension: off + react/react-in-jsx-scope: off + react/function-component-definition: off + import/extensions: off + react/require-default-props: off + no-restricted-syntax: + - error + - FunctionExpression + - FunctionDeclaration overrides: - files: vite.config.ts rules: From 14dda746ffb855ea91db14090bb8a1a6d6a8c699 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Aug 2026 08:19:14 +0000 Subject: [PATCH 10/12] Remove dead commented auth block --- web/src/contexts/AuthContext.tsx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/web/src/contexts/AuthContext.tsx b/web/src/contexts/AuthContext.tsx index f567fb9..9ff8abc 100644 --- a/web/src/contexts/AuthContext.tsx +++ b/web/src/contexts/AuthContext.tsx @@ -36,17 +36,6 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { }); const isLoading = false; - /*useEffect(() => { - // Check if user is already logged in - const token = localStorage.getItem("jwt"); - const storedUser = localStorage.getItem("user"); - - if (token && storedUser) { - setUser(JSON.parse(storedUser)); - } - setIsLoading(false); - }, []);*/ - const login = async (identifier: string, password: string) => { const response = await fetch(`${REST_URL}/auth/local`, { method: 'POST', From 0c3f0fc07dff404764547fa459596b1b074ac2f0 Mon Sep 17 00:00:00 2001 From: Ivan Zanov Date: Tue, 25 Aug 2026 12:15:16 +0200 Subject: [PATCH 11/12] chore: update setup documentation and root scripts --- .gitignore | 1 + SETUP.md | 121 ++- executioner/package-lock.json | 15 +- executioner/package.json | 9 +- executioner/tsconfig.json | 3 +- lib/queue/package-lock.json | 24 +- lib/queue/package.json | 7 +- lib/queue/tsconfig.json | 5 +- package-lock.json | 8 +- package.json | 19 +- senatus/package-lock.json | 773 ++++++++++++++++-- senatus/package.json | 5 +- .../1.0.0/full_documentation.json | 2 +- senatus/tsconfig.json | 2 + senatus/types/generated/contentTypes.d.ts | 363 +++----- web/package-lock.json | 256 ++++-- web/package.json | 5 +- web/tsconfig.json | 1 - 18 files changed, 1164 insertions(+), 455 deletions(-) diff --git a/.gitignore b/.gitignore index 6ec2486..f99e005 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ *.sln *.sw? node_modules +*.tsbuildinfo diff --git a/SETUP.md b/SETUP.md index fc4d62d..7ae1039 100644 --- a/SETUP.md +++ b/SETUP.md @@ -1,64 +1,123 @@ +# Colosseum Local Setup + ## Prerequisites -Create a `.env` file in the root of the repository by following the example file: `.env.example` +Install: + +- Node.js 20+ +- npm +- Docker +- Docker Compose +- Git + +Create the root environment file: + +```bash +cp .env.example .env +``` + +Create and configure: + +```text +senatus/.env +``` + +For Senatus running directly on the host: + +```env +DATABASE_HOST=localhost +DATABASE_PORT=15432 +``` + +## First-Time Setup + +From the repository root: + +```bash +npm run setup +``` -### RabbitMQ +This will: -> Required to run the Executioner/code execution engine. +- install dependencies +- start PostgreSQL and RabbitMQ +- pull execution runtime images +- build the project -To run the RabbitMQ and PostgreSQL in Docker for development, just run: +## Start Development ```bash -docker compose -f docker-compose.q.yml up -d +npm run dev ``` -### Queue Library +Main local services: -Build the queue library before continuing. +```text +Web: http://localhost:1338 +Senatus: http://localhost:1337 +Strapi Admin: http://localhost:1337/admin +RabbitMQ UI: http://localhost:15672 +``` + +## Execution Runtime Images + +Pull the available runtime images: ```bash -cd lib/queue; -npm install; -npm run build; +npm run runtimes:pull ``` -### Client / Frontend +Rebuild them when modifying runtime Dockerfiles: -To start the frontend +```bash +npm run runtimes:build +``` + +## Infrastructure + +Start: ```bash -cd client; -npm install; -npm run dev; +npm run dev:infra ``` -### Executioner +Check status: -> Note: Node version should be v20 +```bash +npm run dev:infra:status +``` -There's no additional setup required, it will automatically connect to `amqp://localhost` (RabbitMQ on port `5672`). +View logs: ```bash -cd executioner; -npm install; -npm start; +npm run dev:infra:logs ``` -### Execution Environments +Stop: -The execution environments are defined in `./executioner/runtimes/languages` there are 2 scripts: +```bash +npm run dev:down +``` + +Reset local infrastructure and volumes: + +```bash +npm run dev:infra:reset +``` -- `build.sh` Will build all available languages (all directories contain a language defined by the directory name (ex: `csharp` is C#)) -- `pull.sh` Will pull all of the readily available images so that there's no pulling when a code execution is requested. +## Development Checks -Usually you just need to run `pull.sh` to get the images available locally. +Before pushing: -### Senatus +```bash +npm run check +``` -You initially would need to setup the `.env` file by following the example file: `.env.example` +Individual checks: ```bash -cd senatus; -npm install; -npm run develop; +npm run lint +npm run format:check +npm run typecheck +npm run build ``` diff --git a/executioner/package-lock.json b/executioner/package-lock.json index def8abf..375c626 100644 --- a/executioner/package-lock.json +++ b/executioner/package-lock.json @@ -15,10 +15,8 @@ "@types/dockerode": "^3.3.24", "@types/uuid": "^9.0.8", "bun-types": "latest", - "tsx": "^4.7.1" - }, - "peerDependencies": { - "typescript": "^5.0.0" + "tsx": "^4.7.1", + "typescript": "6.0.3" } }, "../lib/queue": { @@ -886,10 +884,11 @@ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "peer": true, + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/executioner/package.json b/executioner/package.json index 57994c7..211a4c0 100644 --- a/executioner/package.json +++ b/executioner/package.json @@ -3,16 +3,15 @@ "module": "index.ts", "type": "module", "scripts": { - "start": "tsx index.ts" + "start": "tsx index.ts", + "typecheck": "tsc --noEmit" }, "devDependencies": { "@types/dockerode": "^3.3.24", "@types/uuid": "^9.0.8", "bun-types": "latest", - "tsx": "^4.7.1" - }, - "peerDependencies": { - "typescript": "^5.0.0" + "tsx": "^4.7.1", + "typescript": "6.0.3" }, "dependencies": { "@colosseum/queue": "file:../lib/queue", diff --git a/executioner/tsconfig.json b/executioner/tsconfig.json index 60b258f..acc8cb3 100644 --- a/executioner/tsconfig.json +++ b/executioner/tsconfig.json @@ -3,14 +3,13 @@ "lib": ["ESNext"], "module": "esnext", "target": "esnext", - "moduleResolution": "node", + "moduleResolution": "bundler", "esModuleInterop": true, "moduleDetection": "force", "allowImportingTsExtensions": true, "noEmit": true, "composite": true, "strict": true, - "downlevelIteration": true, "skipLibCheck": true, "jsx": "preserve", "allowSyntheticDefaultImports": true, diff --git a/lib/queue/package-lock.json b/lib/queue/package-lock.json index c0bdb01..c5872d2 100644 --- a/lib/queue/package-lock.json +++ b/lib/queue/package-lock.json @@ -9,17 +9,18 @@ "rabbitmq-client": "^4.5.2" }, "devDependencies": { - "@types/node": "^20.11.30", - "typescript": "^5.0.0" + "@types/node": "20.19.43", + "typescript": "6.0.3" } }, "node_modules/@types/node": { - "version": "20.11.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", - "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.21.0" } }, "node_modules/rabbitmq-client": { @@ -31,10 +32,11 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -44,7 +46,9 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" } diff --git a/lib/queue/package.json b/lib/queue/package.json index becbf22..a6f4a83 100644 --- a/lib/queue/package.json +++ b/lib/queue/package.json @@ -4,13 +4,14 @@ "types": "dist/amqp.d.ts", "scripts": { "build": "tsc -p .", - "watch": "tsc -p . -w" + "watch": "tsc -p . -w", + "typecheck": "tsc --noEmit" }, "dependencies": { "rabbitmq-client": "^4.5.2" }, "devDependencies": { - "typescript": "^5.0.0", - "@types/node": "^20.11.30" + "@types/node": "20.19.43", + "typescript": "6.0.3" } } diff --git a/lib/queue/tsconfig.json b/lib/queue/tsconfig.json index e8c04cb..a83691a 100644 --- a/lib/queue/tsconfig.json +++ b/lib/queue/tsconfig.json @@ -1,14 +1,15 @@ { "compilerOptions": { - "moduleResolution": "node", + "moduleResolution": "NodeNext", "target": "ES2015", - "module": "CommonJS", + "module": "NodeNext", "lib": ["es2015", "es2016", "es2017", "dom"], "strict": true, "declaration": true, "allowSyntheticDefaultImports": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, + "rootDir": "src", "outDir": "dist" }, "include": ["src"], diff --git a/package-lock.json b/package-lock.json index 480f89b..6e89946 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,11 @@ "husky": "^9.0.10", "lint-staged": "^16.4.0", "prettier": "^3.9.6", + "typescript": "6.0.3", "typescript-eslint": "^8.67.0" + }, + "engines": { + "node": "20.x" } }, "node_modules/@babel/code-frame": { @@ -2538,7 +2542,6 @@ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4326,8 +4329,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", - "dev": true, - "peer": true + "dev": true }, "typescript-eslint": { "version": "8.67.0", diff --git a/package.json b/package.json index 7848227..b0995ae 100644 --- a/package.json +++ b/package.json @@ -16,14 +16,18 @@ "husky": "^9.0.10", "lint-staged": "^16.4.0", "prettier": "^3.9.6", + "typescript": "6.0.3", "typescript-eslint": "^8.67.0" }, "scripts": { "install:all": "npm ci && npm --prefix senatus ci && npm --prefix executioner ci && npm --prefix web ci && npm --prefix lib/queue ci", + "setup": "npm run install:all && npm run dev:infra && npm run runtimes:pull && npm run build", "dev": "npm run dev:infra && npm run build:queue && concurrently --kill-others-on-fail --names \"QUEUE,SENATUS,EXECUTIONER,WEB\" \"npm run dev:queue\" \"npm run dev:senatus\" \"npm run dev:executioner\" \"npm run dev:web\"", "dev:infra": "docker compose -f docker-compose.q.yml up -d", "dev:down": "docker compose -f docker-compose.q.yml down", + "dev:infra:status": "docker compose -f docker-compose.q.yml ps", "dev:infra:logs": "docker compose -f docker-compose.q.yml logs -f", + "dev:infra:reset": "docker compose -f docker-compose.q.yml down -v && docker compose -f docker-compose.q.yml up -d", "dev:queue": "npm --prefix lib/queue run watch", "dev:senatus": "npm --prefix senatus run develop", "dev:executioner": "npm --prefix executioner start", @@ -35,17 +39,22 @@ "lint": "eslint senatus executioner lib/queue web", "lint:fix": "eslint senatus executioner lib/queue web --fix", "lint:strict": "eslint senatus executioner lib/queue web --max-warnings=0", - "lint:client": "eslint client", "lint:senatus": "eslint senatus", "lint:executioner": "eslint executioner", "lint:queue": "eslint lib/queue", "lint:web": "eslint web", "format": "prettier --write .", "format:check": "prettier --check .", - "check": "npm run lint && npm run format:check && npm run build", - "quality": "npm run lint && npm run format:check", - "quality:strict": "npm run lint:strict && npm run format:check", - "typecheck:senatus": "npm --prefix senatus run typecheck", + "typecheck": "npm run typecheck:web && npm run typecheck:senatus && npm run typecheck:executioner && npm run typecheck:queue", + "typecheck:web": "tsc --noEmit -p web/tsconfig.json", + "typecheck:senatus": "tsc --noEmit -p senatus/tsconfig.json", + "typecheck:executioner": "tsc --noEmit -p executioner/tsconfig.json", + "typecheck:queue": "tsc --noEmit -p lib/queue/tsconfig.json", + "quality": "npm run lint && npm run format:check && npm run typecheck", + "quality:strict": "npm run lint:strict && npm run format:check && npm run typecheck", + "check": "npm run quality && npm run build", + "runtimes:pull": "cd executioner/runtimes/languages && ./pull.sh", + "runtimes:build": "cd executioner/runtimes/languages && ./build.sh", "prepare": "husky", "prepareClientHusky": "husky client/.husky", "prepareSenatusHusky": "husky senatus/.husky" diff --git a/senatus/package-lock.json b/senatus/package-lock.json index 531796f..291f420 100644 --- a/senatus/package-lock.json +++ b/senatus/package-lock.json @@ -24,7 +24,7 @@ }, "devDependencies": { "@types/node": "^22.10.5", - "typescript": "^5.7.3" + "typescript": "6.0.3" } }, "../lib/queue": { @@ -1526,29 +1526,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@formatjs/intl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", - "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "1.18.2", - "@formatjs/fast-memoize": "2.2.0", - "@formatjs/icu-messageformat-parser": "2.7.6", - "@formatjs/intl-displaynames": "6.6.6", - "@formatjs/intl-listformat": "7.5.5", - "intl-messageformat": "10.5.11", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "typescript": "^4.7 || 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@formatjs/intl-displaynames": { "version": "6.6.6", "resolved": "https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-6.6.6.tgz", @@ -4915,6 +4892,21 @@ } } }, + "node_modules/@sensinum/strapi-plugin-mcp/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@sensinum/strapi-plugin-mcp/node_modules/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", @@ -5144,6 +5136,56 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/admin/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/admin/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@strapi/admin/node_modules/typescript": { "version": "5.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", @@ -5261,6 +5303,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/content-manager/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/content-manager/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/content-manager/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/content-releases": { "version": "5.33.4", "resolved": "https://registry.npmjs.org/@strapi/content-releases/-/content-releases-5.33.4.tgz", @@ -5295,6 +5402,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/content-releases/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/content-releases/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/content-releases/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/content-type-builder": { "version": "5.33.4", "resolved": "https://registry.npmjs.org/@strapi/content-type-builder/-/content-type-builder-5.33.4.tgz", @@ -5340,6 +5512,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/content-type-builder/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/content-type-builder/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/content-type-builder/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/content-type-builder/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -5589,6 +5826,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/email/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/email/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/email/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/email/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -5651,6 +5953,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/i18n/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/i18n/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/i18n/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/i18n/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -5908,6 +6275,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/plugin-cloud/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/plugin-cloud/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/plugin-cloud/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/plugin-documentation": { "version": "5.33.4", "resolved": "https://registry.npmjs.org/@strapi/plugin-documentation/-/plugin-documentation-5.33.4.tgz", @@ -5944,6 +6376,29 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/plugin-documentation/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@strapi/plugin-documentation/node_modules/path-to-regexp": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", @@ -5953,6 +6408,48 @@ "node": ">=16" } }, + "node_modules/@strapi/plugin-documentation/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/plugin-documentation/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/plugin-graphql": { "version": "5.33.4", "resolved": "https://registry.npmjs.org/@strapi/plugin-graphql/-/plugin-graphql-5.33.4.tgz", @@ -6028,6 +6525,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/plugin-users-permissions/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/plugin-users-permissions/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/plugin-users-permissions/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/plugin-users-permissions/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -6096,6 +6658,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/review-workflows/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/review-workflows/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/review-workflows/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/sdk-plugin": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/@strapi/sdk-plugin/-/sdk-plugin-5.4.0.tgz", @@ -6720,6 +7347,71 @@ "styled-components": "^6.0.0" } }, + "node_modules/@strapi/upload/node_modules/@formatjs/intl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.0.tgz", + "integrity": "sha512-X3xT9guVkKDS86EKV80lS0KxoazUglkJTGZO66sKY7otgl0VeStPA8B3u8UkKT47PexVV98fUzjpkchYmbe9nw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/upload/node_modules/react-intl": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", + "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-messageformat-parser": "2.7.6", + "@formatjs/intl": "2.10.0", + "@formatjs/intl-displaynames": "6.6.6", + "@formatjs/intl-listformat": "7.5.5", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "10.5.11", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "react": "^16.6.0 || 17 || 18", + "typescript": "^4.7 || 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@strapi/upload/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@strapi/upload/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -18784,33 +19476,6 @@ "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", "license": "MIT" }, - "node_modules/react-intl": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.2.tgz", - "integrity": "sha512-IpW2IkLtGENSFlX3vfH11rjuCIsW0VyjT0Q1pPKMZPtT2z1FxLt4weFT5Ezti2TScT1xiyb3aQBFth9EB7jzAg==", - "license": "BSD-3-Clause", - "dependencies": { - "@formatjs/ecma402-abstract": "1.18.2", - "@formatjs/icu-messageformat-parser": "2.7.6", - "@formatjs/intl": "2.10.0", - "@formatjs/intl-displaynames": "6.6.6", - "@formatjs/intl-listformat": "7.5.5", - "@types/hoist-non-react-statics": "^3.3.1", - "@types/react": "16 || 17 || 18", - "hoist-non-react-statics": "^3.3.2", - "intl-messageformat": "10.5.11", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "react": "^16.6.0 || 17 || 18", - "typescript": "^4.7 || 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -21581,9 +22246,9 @@ } }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/senatus/package.json b/senatus/package.json index 2203ebe..78b51c0 100644 --- a/senatus/package.json +++ b/senatus/package.json @@ -7,7 +7,8 @@ "develop": "strapi develop", "start": "strapi start", "build": "strapi build", - "strapi": "strapi" + "strapi": "strapi", + "typecheck": "tsc --noEmit" }, "dependencies": { "@colosseum/queue": "file:../lib/queue", @@ -25,7 +26,7 @@ }, "devDependencies": { "@types/node": "^22.10.5", - "typescript": "^5.7.3" + "typescript": "6.0.3" }, "author": { "name": "A Strapi developer" diff --git a/senatus/src/extensions/documentation/documentation/1.0.0/full_documentation.json b/senatus/src/extensions/documentation/documentation/1.0.0/full_documentation.json index 7b279ea..d8b958d 100644 --- a/senatus/src/extensions/documentation/documentation/1.0.0/full_documentation.json +++ b/senatus/src/extensions/documentation/documentation/1.0.0/full_documentation.json @@ -14,7 +14,7 @@ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" }, - "x-generation-date": "2026-03-01T08:55:38.021Z" + "x-generation-date": "2026-08-25T09:30:56.642Z" }, "x-strapi-config": { "plugins": [ diff --git a/senatus/tsconfig.json b/senatus/tsconfig.json index e6663b0..9b867de 100644 --- a/senatus/tsconfig.json +++ b/senatus/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "@strapi/typescript-utils/tsconfigs/server", "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", "outDir": "dist", "rootDir": "." }, diff --git a/senatus/types/generated/contentTypes.d.ts b/senatus/types/generated/contentTypes.d.ts index a1cbe36..6240b1e 100644 --- a/senatus/types/generated/contentTypes.d.ts +++ b/senatus/types/generated/contentTypes.d.ts @@ -27,8 +27,7 @@ export interface AdminApiToken extends Struct.CollectionTypeSchema { minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; description: Schema.Attribute.String & Schema.Attribute.SetMinMaxLength<{ minLength: 1; @@ -50,17 +49,13 @@ export interface AdminApiToken extends Struct.CollectionTypeSchema { Schema.Attribute.SetMinMaxLength<{ minLength: 1; }>; - permissions: Schema.Attribute.Relation< - 'oneToMany', - 'admin::api-token-permission' - >; + permissions: Schema.Attribute.Relation<'oneToMany', 'admin::api-token-permission'>; publishedAt: Schema.Attribute.DateTime; type: Schema.Attribute.Enumeration<['read-only', 'full-access', 'custom']> & Schema.Attribute.Required & Schema.Attribute.DefaultTo<'read-only'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -91,19 +86,14 @@ export interface AdminApiTokenPermission extends Struct.CollectionTypeSchema { minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'admin::api-token-permission' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'admin::api-token-permission'> & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; token: Schema.Attribute.Relation<'manyToOne', 'admin::api-token'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -136,8 +126,7 @@ export interface AdminPermission extends Struct.CollectionTypeSchema { actionParameters: Schema.Attribute.JSON & Schema.Attribute.DefaultTo<{}>; conditions: Schema.Attribute.JSON & Schema.Attribute.DefaultTo<[]>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; localizations: Schema.Attribute.Relation<'oneToMany', 'admin::permission'> & Schema.Attribute.Private; @@ -149,8 +138,7 @@ export interface AdminPermission extends Struct.CollectionTypeSchema { minLength: 1; }>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -182,12 +170,10 @@ export interface AdminRole extends Struct.CollectionTypeSchema { minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; description: Schema.Attribute.String; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'admin::role'> & - Schema.Attribute.Private; + localizations: Schema.Attribute.Relation<'oneToMany', 'admin::role'> & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique & @@ -197,8 +183,7 @@ export interface AdminRole extends Struct.CollectionTypeSchema { permissions: Schema.Attribute.Relation<'oneToMany', 'admin::permission'>; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; users: Schema.Attribute.Relation<'manyToMany', 'admin::user'>; }; } @@ -230,20 +215,13 @@ export interface AdminSession extends Struct.CollectionTypeSchema { absoluteExpiresAt: Schema.Attribute.DateTime & Schema.Attribute.Private; childId: Schema.Attribute.String & Schema.Attribute.Private; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; - deviceId: Schema.Attribute.String & - Schema.Attribute.Required & - Schema.Attribute.Private; - expiresAt: Schema.Attribute.DateTime & - Schema.Attribute.Required & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + deviceId: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Private; + expiresAt: Schema.Attribute.DateTime & Schema.Attribute.Required & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; localizations: Schema.Attribute.Relation<'oneToMany', 'admin::session'> & Schema.Attribute.Private; - origin: Schema.Attribute.String & - Schema.Attribute.Required & - Schema.Attribute.Private; + origin: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; sessionId: Schema.Attribute.String & Schema.Attribute.Required & @@ -252,11 +230,8 @@ export interface AdminSession extends Struct.CollectionTypeSchema { status: Schema.Attribute.String & Schema.Attribute.Private; type: Schema.Attribute.String & Schema.Attribute.Private; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; - userId: Schema.Attribute.String & - Schema.Attribute.Required & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + userId: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Private; }; } @@ -287,8 +262,7 @@ export interface AdminTransferToken extends Struct.CollectionTypeSchema { minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; description: Schema.Attribute.String & Schema.Attribute.SetMinMaxLength<{ minLength: 1; @@ -298,10 +272,7 @@ export interface AdminTransferToken extends Struct.CollectionTypeSchema { lastUsedAt: Schema.Attribute.DateTime; lifespan: Schema.Attribute.BigInteger; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'admin::transfer-token' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token'> & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required & @@ -309,19 +280,14 @@ export interface AdminTransferToken extends Struct.CollectionTypeSchema { Schema.Attribute.SetMinMaxLength<{ minLength: 1; }>; - permissions: Schema.Attribute.Relation< - 'oneToMany', - 'admin::transfer-token-permission' - >; + permissions: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token-permission'>; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } -export interface AdminTransferTokenPermission - extends Struct.CollectionTypeSchema { +export interface AdminTransferTokenPermission extends Struct.CollectionTypeSchema { collectionName: 'strapi_transfer_token_permissions'; info: { description: ''; @@ -348,19 +314,14 @@ export interface AdminTransferTokenPermission minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'admin::transfer-token-permission' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token-permission'> & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; token: Schema.Attribute.Relation<'manyToOne', 'admin::transfer-token'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -389,8 +350,7 @@ export interface AdminUser extends Struct.CollectionTypeSchema { Schema.Attribute.Private & Schema.Attribute.DefaultTo; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; email: Schema.Attribute.Email & Schema.Attribute.Required & Schema.Attribute.Private & @@ -410,8 +370,7 @@ export interface AdminUser extends Struct.CollectionTypeSchema { minLength: 1; }>; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'admin::user'> & - Schema.Attribute.Private; + localizations: Schema.Attribute.Relation<'oneToMany', 'admin::user'> & Schema.Attribute.Private; password: Schema.Attribute.Password & Schema.Attribute.Private & Schema.Attribute.SetMinMaxLength<{ @@ -421,11 +380,9 @@ export interface AdminUser extends Struct.CollectionTypeSchema { publishedAt: Schema.Attribute.DateTime; registrationToken: Schema.Attribute.String & Schema.Attribute.Private; resetPasswordToken: Schema.Attribute.String & Schema.Attribute.Private; - roles: Schema.Attribute.Relation<'manyToMany', 'admin::role'> & - Schema.Attribute.Private; + roles: Schema.Attribute.Relation<'manyToMany', 'admin::role'> & Schema.Attribute.Private; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; username: Schema.Attribute.String; }; } @@ -448,8 +405,7 @@ export interface ApiEventEvent extends Struct.CollectionTypeSchema { }; attributes: { createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; description: Schema.Attribute.RichText & Schema.Attribute.SetPluginOptions<{ i18n: { @@ -479,10 +435,7 @@ export interface ApiEventEvent extends Struct.CollectionTypeSchema { localized: true; }; }>; - supportedLanguages: Schema.Attribute.Relation< - 'oneToMany', - 'api::language.language' - >; + supportedLanguages: Schema.Attribute.Relation<'oneToMany', 'api::language.language'>; title: Schema.Attribute.String & Schema.Attribute.SetPluginOptions<{ i18n: { @@ -490,8 +443,7 @@ export interface ApiEventEvent extends Struct.CollectionTypeSchema { }; }>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -509,14 +461,10 @@ export interface ApiExecutionExecution extends Struct.CollectionTypeSchema { attributes: { code: Schema.Attribute.Text; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; executionTime: Schema.Attribute.Float; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'api::execution.execution' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'api::execution.execution'> & Schema.Attribute.Private; passed: Schema.Attribute.Boolean; processed: Schema.Attribute.Boolean; @@ -524,14 +472,10 @@ export interface ApiExecutionExecution extends Struct.CollectionTypeSchema { publishedAt: Schema.Attribute.DateTime; stderr: Schema.Attribute.Text; stdout: Schema.Attribute.Text; - submission: Schema.Attribute.Relation< - 'manyToOne', - 'api::submission.submission' - >; + submission: Schema.Attribute.Relation<'manyToOne', 'api::submission.submission'>; testCase: Schema.Attribute.Relation<'oneToOne', 'api::test-case.test-case'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -549,22 +493,17 @@ export interface ApiLanguageLanguage extends Struct.CollectionTypeSchema { attributes: { codeName: Schema.Attribute.String; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; defaultMaxCpuTime: Schema.Attribute.Float; defaultMaxMemory: Schema.Attribute.Integer; entrypoint: Schema.Attribute.String; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'api::language.language' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'api::language.language'> & Schema.Attribute.Private; name: Schema.Attribute.String; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -586,8 +525,7 @@ export interface ApiProblemProblem extends Struct.CollectionTypeSchema { }; attributes: { createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; description: Schema.Attribute.RichText & Schema.Attribute.SetPluginOptions<{ i18n: { @@ -596,10 +534,7 @@ export interface ApiProblemProblem extends Struct.CollectionTypeSchema { }>; event: Schema.Attribute.Relation<'manyToOne', 'api::event.event'>; locale: Schema.Attribute.String; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'api::problem.problem' - >; + localizations: Schema.Attribute.Relation<'oneToMany', 'api::problem.problem'>; points: Schema.Attribute.Integer & Schema.Attribute.SetMinMax< { @@ -621,10 +556,7 @@ export interface ApiProblemProblem extends Struct.CollectionTypeSchema { localized: true; }; }>; - testCases: Schema.Attribute.Relation< - 'oneToMany', - 'api::test-case.test-case' - >; + testCases: Schema.Attribute.Relation<'oneToMany', 'api::test-case.test-case'>; title: Schema.Attribute.String & Schema.Attribute.SetPluginOptions<{ i18n: { @@ -632,8 +564,7 @@ export interface ApiProblemProblem extends Struct.CollectionTypeSchema { }; }>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -651,32 +582,21 @@ export interface ApiSubmissionSubmission extends Struct.CollectionTypeSchema { attributes: { code: Schema.Attribute.Text; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; event: Schema.Attribute.Relation<'oneToOne', 'api::event.event'>; - executions: Schema.Attribute.Relation< - 'oneToMany', - 'api::execution.execution' - >; + executions: Schema.Attribute.Relation<'oneToMany', 'api::execution.execution'>; finishedAt: Schema.Attribute.DateTime; language: Schema.Attribute.Relation<'oneToOne', 'api::language.language'>; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'api::submission.submission' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'api::submission.submission'> & Schema.Attribute.Private; metadata: Schema.Attribute.JSON; problem: Schema.Attribute.Relation<'oneToOne', 'api::problem.problem'>; publishedAt: Schema.Attribute.DateTime; triggeredAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; - user: Schema.Attribute.Relation< - 'oneToOne', - 'plugin::users-permissions.user' - >; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + user: Schema.Attribute.Relation<'oneToOne', 'plugin::users-permissions.user'>; }; } @@ -693,30 +613,24 @@ export interface ApiTestCaseTestCase extends Struct.CollectionTypeSchema { }; attributes: { createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; explanation: Schema.Attribute.RichText; hidden: Schema.Attribute.Boolean; input: Schema.Attribute.Text; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'api::test-case.test-case' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'api::test-case.test-case'> & Schema.Attribute.Private; locked: Schema.Attribute.Boolean; output: Schema.Attribute.Text; problem: Schema.Attribute.Relation<'manyToOne', 'api::problem.problem'>; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; weight: Schema.Attribute.Float; }; } -export interface PluginContentReleasesRelease - extends Struct.CollectionTypeSchema { +export interface PluginContentReleasesRelease extends Struct.CollectionTypeSchema { collectionName: 'strapi_releases'; info: { displayName: 'Release'; @@ -735,36 +649,25 @@ export interface PluginContentReleasesRelease }; }; attributes: { - actions: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::content-releases.release-action' - >; + actions: Schema.Attribute.Relation<'oneToMany', 'plugin::content-releases.release-action'>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::content-releases.release' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::content-releases.release'> & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required; publishedAt: Schema.Attribute.DateTime; releasedAt: Schema.Attribute.DateTime; scheduledAt: Schema.Attribute.DateTime; - status: Schema.Attribute.Enumeration< - ['ready', 'blocked', 'failed', 'done', 'empty'] - > & + status: Schema.Attribute.Enumeration<['ready', 'blocked', 'failed', 'done', 'empty']> & Schema.Attribute.Required; timezone: Schema.Attribute.String; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } -export interface PluginContentReleasesReleaseAction - extends Struct.CollectionTypeSchema { +export interface PluginContentReleasesReleaseAction extends Struct.CollectionTypeSchema { collectionName: 'strapi_release_actions'; info: { displayName: 'Release Action'; @@ -785,8 +688,7 @@ export interface PluginContentReleasesReleaseAction attributes: { contentType: Schema.Attribute.String & Schema.Attribute.Required; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; entryDocumentId: Schema.Attribute.String; isEntryValid: Schema.Attribute.Boolean; locale: Schema.Attribute.String & Schema.Attribute.Private; @@ -796,15 +698,10 @@ export interface PluginContentReleasesReleaseAction > & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; - release: Schema.Attribute.Relation< - 'manyToOne', - 'plugin::content-releases.release' - >; - type: Schema.Attribute.Enumeration<['publish', 'unpublish']> & - Schema.Attribute.Required; + release: Schema.Attribute.Relation<'manyToOne', 'plugin::content-releases.release'>; + type: Schema.Attribute.Enumeration<['publish', 'unpublish']> & Schema.Attribute.Required; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } @@ -831,13 +728,9 @@ export interface PluginI18NLocale extends Struct.CollectionTypeSchema { attributes: { code: Schema.Attribute.String & Schema.Attribute.Unique; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::i18n.locale' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::i18n.locale'> & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.SetMinMax< @@ -849,13 +742,11 @@ export interface PluginI18NLocale extends Struct.CollectionTypeSchema { >; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } -export interface PluginReviewWorkflowsWorkflow - extends Struct.CollectionTypeSchema { +export interface PluginReviewWorkflowsWorkflow extends Struct.CollectionTypeSchema { collectionName: 'strapi_workflows'; info: { description: ''; @@ -880,34 +771,23 @@ export interface PluginReviewWorkflowsWorkflow Schema.Attribute.Required & Schema.Attribute.DefaultTo<'[]'>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::review-workflows.workflow' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::review-workflows.workflow'> & Schema.Attribute.Private; - name: Schema.Attribute.String & - Schema.Attribute.Required & - Schema.Attribute.Unique; + name: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique; publishedAt: Schema.Attribute.DateTime; stageRequiredToPublish: Schema.Attribute.Relation< 'oneToOne', 'plugin::review-workflows.workflow-stage' >; - stages: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::review-workflows.workflow-stage' - >; + stages: Schema.Attribute.Relation<'oneToMany', 'plugin::review-workflows.workflow-stage'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } -export interface PluginReviewWorkflowsWorkflowStage - extends Struct.CollectionTypeSchema { +export interface PluginReviewWorkflowsWorkflowStage extends Struct.CollectionTypeSchema { collectionName: 'strapi_workflows_stages'; info: { description: ''; @@ -931,8 +811,7 @@ export interface PluginReviewWorkflowsWorkflowStage attributes: { color: Schema.Attribute.String & Schema.Attribute.DefaultTo<'#4945FF'>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; localizations: Schema.Attribute.Relation< 'oneToMany', @@ -943,12 +822,8 @@ export interface PluginReviewWorkflowsWorkflowStage permissions: Schema.Attribute.Relation<'manyToMany', 'admin::permission'>; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; - workflow: Schema.Attribute.Relation< - 'manyToOne', - 'plugin::review-workflows.workflow' - >; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + workflow: Schema.Attribute.Relation<'manyToOne', 'plugin::review-workflows.workflow'>; }; } @@ -975,8 +850,7 @@ export interface PluginUploadFile extends Struct.CollectionTypeSchema { alternativeText: Schema.Attribute.Text; caption: Schema.Attribute.Text; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; ext: Schema.Attribute.String; folder: Schema.Attribute.Relation<'manyToOne', 'plugin::upload.folder'> & Schema.Attribute.Private; @@ -990,10 +864,7 @@ export interface PluginUploadFile extends Struct.CollectionTypeSchema { hash: Schema.Attribute.String & Schema.Attribute.Required; height: Schema.Attribute.Integer; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::upload.file' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.file'> & Schema.Attribute.Private; mime: Schema.Attribute.String & Schema.Attribute.Required; name: Schema.Attribute.String & Schema.Attribute.Required; @@ -1004,8 +875,7 @@ export interface PluginUploadFile extends Struct.CollectionTypeSchema { related: Schema.Attribute.Relation<'morphToMany'>; size: Schema.Attribute.Decimal & Schema.Attribute.Required; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; url: Schema.Attribute.Text & Schema.Attribute.Required; width: Schema.Attribute.Integer; }; @@ -1032,14 +902,10 @@ export interface PluginUploadFolder extends Struct.CollectionTypeSchema { attributes: { children: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.folder'>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; files: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.file'>; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::upload.folder' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.folder'> & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required & @@ -1052,18 +918,14 @@ export interface PluginUploadFolder extends Struct.CollectionTypeSchema { Schema.Attribute.SetMinMaxLength<{ minLength: 1; }>; - pathId: Schema.Attribute.Integer & - Schema.Attribute.Required & - Schema.Attribute.Unique; + pathId: Schema.Attribute.Integer & Schema.Attribute.Required & Schema.Attribute.Unique; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } -export interface PluginUsersPermissionsPermission - extends Struct.CollectionTypeSchema { +export interface PluginUsersPermissionsPermission extends Struct.CollectionTypeSchema { collectionName: 'up_permissions'; info: { description: ''; @@ -1086,27 +948,18 @@ export interface PluginUsersPermissionsPermission attributes: { action: Schema.Attribute.String & Schema.Attribute.Required; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::users-permissions.permission' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.permission'> & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; - role: Schema.Attribute.Relation< - 'manyToOne', - 'plugin::users-permissions.role' - >; + role: Schema.Attribute.Relation<'manyToOne', 'plugin::users-permissions.role'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; }; } -export interface PluginUsersPermissionsRole - extends Struct.CollectionTypeSchema { +export interface PluginUsersPermissionsRole extends Struct.CollectionTypeSchema { collectionName: 'up_roles'; info: { description: ''; @@ -1128,38 +981,26 @@ export interface PluginUsersPermissionsRole }; attributes: { createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; description: Schema.Attribute.String; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::users-permissions.role' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.role'> & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.SetMinMaxLength<{ minLength: 3; }>; - permissions: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::users-permissions.permission' - >; + permissions: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.permission'>; publishedAt: Schema.Attribute.DateTime; type: Schema.Attribute.String & Schema.Attribute.Unique; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; - users: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::users-permissions.user' - >; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + users: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.user'>; }; } -export interface PluginUsersPermissionsUser - extends Struct.CollectionTypeSchema { +export interface PluginUsersPermissionsUser extends Struct.CollectionTypeSchema { collectionName: 'up_users'; info: { description: ''; @@ -1177,18 +1018,14 @@ export interface PluginUsersPermissionsUser confirmationToken: Schema.Attribute.String & Schema.Attribute.Private; confirmed: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; email: Schema.Attribute.Email & Schema.Attribute.Required & Schema.Attribute.SetMinMaxLength<{ minLength: 6; }>; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation< - 'oneToMany', - 'plugin::users-permissions.user' - > & + localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.user'> & Schema.Attribute.Private; password: Schema.Attribute.Password & Schema.Attribute.Private & @@ -1198,13 +1035,9 @@ export interface PluginUsersPermissionsUser provider: Schema.Attribute.String; publishedAt: Schema.Attribute.DateTime; resetPasswordToken: Schema.Attribute.String & Schema.Attribute.Private; - role: Schema.Attribute.Relation< - 'manyToOne', - 'plugin::users-permissions.role' - >; + role: Schema.Attribute.Relation<'manyToOne', 'plugin::users-permissions.role'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & - Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; username: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique & diff --git a/web/package-lock.json b/web/package-lock.json index bbffc7a..25d6433 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -43,7 +43,7 @@ "eslint": "^10.0.0", "postcss": "^8.5.3", "tailwindcss": "^3.4.17", - "typescript": "^5.7.3", + "typescript": "6.0.3", "vite": "^6.1.1" } }, @@ -90,7 +90,6 @@ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -2614,7 +2613,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -2626,7 +2624,6 @@ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -2636,7 +2633,8 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/@types/unist": { "version": "3.0.3", @@ -2673,19 +2671,18 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/parser": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", - "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", + "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", - "debug": "^4.4.3" + "@typescript-eslint/utils": "8.56.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2699,7 +2696,35 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/project-service": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", + "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.56.1", + "@typescript-eslint/tsconfig-utils": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { "version": "8.56.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", @@ -2721,30 +2746,35 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/scope-manager": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", - "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", + "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1" - }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", - "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", + "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", "dev": true, "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -2753,20 +2783,25 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", - "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", + "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", "dev": true, "license": "MIT", "dependencies": { + "@typescript-eslint/project-service": "8.56.1", + "@typescript-eslint/tsconfig-utils": "8.56.1", "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/utils": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "engines": { @@ -2777,25 +2812,87 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/types": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", - "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", + "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.56.1", + "@typescript-eslint/types": "^8.56.1", + "debug": "^4.4.3" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", + "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", + "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { "version": "8.56.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", @@ -2823,10 +2920,49 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", + "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.56.1", + "@typescript-eslint/types": "^8.56.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", + "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { @@ -2836,17 +2972,15 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/utils": { + "node_modules/@typescript-eslint/scope-manager": { "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", - "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", + "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1" + "@typescript-eslint/visitor-keys": "8.56.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2854,10 +2988,20 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", + "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/@typescript-eslint/visitor-keys": { @@ -2924,7 +3068,6 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3120,7 +3263,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3413,6 +3555,7 @@ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", "license": "(MPL-2.0 OR Apache-2.0)", + "peer": true, "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -3507,7 +3650,6 @@ "integrity": "sha512-uYixubwmqJZH+KLVYIVKY1JQt7tysXhtj21WSvjcSmU5SVNzMus1bgLe+pAt816yQ8opKfheVVoPLqvVMGejYw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", @@ -4250,7 +4392,6 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -4437,6 +4578,7 @@ "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", "license": "MIT", + "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -5582,7 +5724,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -5775,7 +5916,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -5788,7 +5928,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6300,7 +6439,6 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", "license": "MIT", - "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -6401,7 +6539,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6480,12 +6617,11 @@ } }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6742,7 +6878,6 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -6836,7 +6971,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, diff --git a/web/package.json b/web/package.json index 0444da9..01d251f 100644 --- a/web/package.json +++ b/web/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", - "preview": "vite preview" + "preview": "vite preview", + "typecheck": "tsc --noEmit" }, "dependencies": { "@monaco-editor/react": "^4.6.0", @@ -44,7 +45,7 @@ "eslint": "^10.0.0", "postcss": "^8.5.3", "tailwindcss": "^3.4.17", - "typescript": "^5.7.3", + "typescript": "6.0.3", "vite": "^6.1.1" } } diff --git a/web/tsconfig.json b/web/tsconfig.json index c20738e..2a27e96 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -15,7 +15,6 @@ "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"] } From d5223616760b83a902a9b925fc8214313d269619 Mon Sep 17 00:00:00 2001 From: Ivan Zanov Date: Tue, 25 Aug 2026 14:30:22 +0200 Subject: [PATCH 12/12] address review feedback --- package.json | 14 +- senatus/types/generated/contentTypes.d.ts | 363 ++++++++++++++++------ 2 files changed, 272 insertions(+), 105 deletions(-) diff --git a/package.json b/package.json index b0995ae..4c3aa7b 100644 --- a/package.json +++ b/package.json @@ -46,13 +46,13 @@ "format": "prettier --write .", "format:check": "prettier --check .", "typecheck": "npm run typecheck:web && npm run typecheck:senatus && npm run typecheck:executioner && npm run typecheck:queue", - "typecheck:web": "tsc --noEmit -p web/tsconfig.json", - "typecheck:senatus": "tsc --noEmit -p senatus/tsconfig.json", - "typecheck:executioner": "tsc --noEmit -p executioner/tsconfig.json", - "typecheck:queue": "tsc --noEmit -p lib/queue/tsconfig.json", - "quality": "npm run lint && npm run format:check && npm run typecheck", - "quality:strict": "npm run lint:strict && npm run format:check && npm run typecheck", - "check": "npm run quality && npm run build", + "typecheck:web": "npm --prefix web run typecheck", + "typecheck:senatus": "npm --prefix senatus run typecheck", + "typecheck:executioner": "npm --prefix executioner run typecheck", + "typecheck:queue": "npm --prefix lib/queue run typecheck", + "validate": "npm run lint && npm run format:check && npm run typecheck", + "validate:strict": "npm run lint:strict && npm run format:check && npm run typecheck", + "check": "npm run validate && npm run build", "runtimes:pull": "cd executioner/runtimes/languages && ./pull.sh", "runtimes:build": "cd executioner/runtimes/languages && ./build.sh", "prepare": "husky", diff --git a/senatus/types/generated/contentTypes.d.ts b/senatus/types/generated/contentTypes.d.ts index 6240b1e..a1cbe36 100644 --- a/senatus/types/generated/contentTypes.d.ts +++ b/senatus/types/generated/contentTypes.d.ts @@ -27,7 +27,8 @@ export interface AdminApiToken extends Struct.CollectionTypeSchema { minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; description: Schema.Attribute.String & Schema.Attribute.SetMinMaxLength<{ minLength: 1; @@ -49,13 +50,17 @@ export interface AdminApiToken extends Struct.CollectionTypeSchema { Schema.Attribute.SetMinMaxLength<{ minLength: 1; }>; - permissions: Schema.Attribute.Relation<'oneToMany', 'admin::api-token-permission'>; + permissions: Schema.Attribute.Relation< + 'oneToMany', + 'admin::api-token-permission' + >; publishedAt: Schema.Attribute.DateTime; type: Schema.Attribute.Enumeration<['read-only', 'full-access', 'custom']> & Schema.Attribute.Required & Schema.Attribute.DefaultTo<'read-only'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -86,14 +91,19 @@ export interface AdminApiTokenPermission extends Struct.CollectionTypeSchema { minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'admin::api-token-permission'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'admin::api-token-permission' + > & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; token: Schema.Attribute.Relation<'manyToOne', 'admin::api-token'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -126,7 +136,8 @@ export interface AdminPermission extends Struct.CollectionTypeSchema { actionParameters: Schema.Attribute.JSON & Schema.Attribute.DefaultTo<{}>; conditions: Schema.Attribute.JSON & Schema.Attribute.DefaultTo<[]>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; localizations: Schema.Attribute.Relation<'oneToMany', 'admin::permission'> & Schema.Attribute.Private; @@ -138,7 +149,8 @@ export interface AdminPermission extends Struct.CollectionTypeSchema { minLength: 1; }>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -170,10 +182,12 @@ export interface AdminRole extends Struct.CollectionTypeSchema { minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; description: Schema.Attribute.String; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'admin::role'> & Schema.Attribute.Private; + localizations: Schema.Attribute.Relation<'oneToMany', 'admin::role'> & + Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique & @@ -183,7 +197,8 @@ export interface AdminRole extends Struct.CollectionTypeSchema { permissions: Schema.Attribute.Relation<'oneToMany', 'admin::permission'>; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; users: Schema.Attribute.Relation<'manyToMany', 'admin::user'>; }; } @@ -215,13 +230,20 @@ export interface AdminSession extends Struct.CollectionTypeSchema { absoluteExpiresAt: Schema.Attribute.DateTime & Schema.Attribute.Private; childId: Schema.Attribute.String & Schema.Attribute.Private; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; - deviceId: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Private; - expiresAt: Schema.Attribute.DateTime & Schema.Attribute.Required & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + deviceId: Schema.Attribute.String & + Schema.Attribute.Required & + Schema.Attribute.Private; + expiresAt: Schema.Attribute.DateTime & + Schema.Attribute.Required & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; localizations: Schema.Attribute.Relation<'oneToMany', 'admin::session'> & Schema.Attribute.Private; - origin: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Private; + origin: Schema.Attribute.String & + Schema.Attribute.Required & + Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; sessionId: Schema.Attribute.String & Schema.Attribute.Required & @@ -230,8 +252,11 @@ export interface AdminSession extends Struct.CollectionTypeSchema { status: Schema.Attribute.String & Schema.Attribute.Private; type: Schema.Attribute.String & Schema.Attribute.Private; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; - userId: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + userId: Schema.Attribute.String & + Schema.Attribute.Required & + Schema.Attribute.Private; }; } @@ -262,7 +287,8 @@ export interface AdminTransferToken extends Struct.CollectionTypeSchema { minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; description: Schema.Attribute.String & Schema.Attribute.SetMinMaxLength<{ minLength: 1; @@ -272,7 +298,10 @@ export interface AdminTransferToken extends Struct.CollectionTypeSchema { lastUsedAt: Schema.Attribute.DateTime; lifespan: Schema.Attribute.BigInteger; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'admin::transfer-token' + > & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required & @@ -280,14 +309,19 @@ export interface AdminTransferToken extends Struct.CollectionTypeSchema { Schema.Attribute.SetMinMaxLength<{ minLength: 1; }>; - permissions: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token-permission'>; + permissions: Schema.Attribute.Relation< + 'oneToMany', + 'admin::transfer-token-permission' + >; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } -export interface AdminTransferTokenPermission extends Struct.CollectionTypeSchema { +export interface AdminTransferTokenPermission + extends Struct.CollectionTypeSchema { collectionName: 'strapi_transfer_token_permissions'; info: { description: ''; @@ -314,14 +348,19 @@ export interface AdminTransferTokenPermission extends Struct.CollectionTypeSchem minLength: 1; }>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token-permission'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'admin::transfer-token-permission' + > & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; token: Schema.Attribute.Relation<'manyToOne', 'admin::transfer-token'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -350,7 +389,8 @@ export interface AdminUser extends Struct.CollectionTypeSchema { Schema.Attribute.Private & Schema.Attribute.DefaultTo; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; email: Schema.Attribute.Email & Schema.Attribute.Required & Schema.Attribute.Private & @@ -370,7 +410,8 @@ export interface AdminUser extends Struct.CollectionTypeSchema { minLength: 1; }>; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'admin::user'> & Schema.Attribute.Private; + localizations: Schema.Attribute.Relation<'oneToMany', 'admin::user'> & + Schema.Attribute.Private; password: Schema.Attribute.Password & Schema.Attribute.Private & Schema.Attribute.SetMinMaxLength<{ @@ -380,9 +421,11 @@ export interface AdminUser extends Struct.CollectionTypeSchema { publishedAt: Schema.Attribute.DateTime; registrationToken: Schema.Attribute.String & Schema.Attribute.Private; resetPasswordToken: Schema.Attribute.String & Schema.Attribute.Private; - roles: Schema.Attribute.Relation<'manyToMany', 'admin::role'> & Schema.Attribute.Private; + roles: Schema.Attribute.Relation<'manyToMany', 'admin::role'> & + Schema.Attribute.Private; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; username: Schema.Attribute.String; }; } @@ -405,7 +448,8 @@ export interface ApiEventEvent extends Struct.CollectionTypeSchema { }; attributes: { createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; description: Schema.Attribute.RichText & Schema.Attribute.SetPluginOptions<{ i18n: { @@ -435,7 +479,10 @@ export interface ApiEventEvent extends Struct.CollectionTypeSchema { localized: true; }; }>; - supportedLanguages: Schema.Attribute.Relation<'oneToMany', 'api::language.language'>; + supportedLanguages: Schema.Attribute.Relation< + 'oneToMany', + 'api::language.language' + >; title: Schema.Attribute.String & Schema.Attribute.SetPluginOptions<{ i18n: { @@ -443,7 +490,8 @@ export interface ApiEventEvent extends Struct.CollectionTypeSchema { }; }>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -461,10 +509,14 @@ export interface ApiExecutionExecution extends Struct.CollectionTypeSchema { attributes: { code: Schema.Attribute.Text; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; executionTime: Schema.Attribute.Float; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'api::execution.execution'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::execution.execution' + > & Schema.Attribute.Private; passed: Schema.Attribute.Boolean; processed: Schema.Attribute.Boolean; @@ -472,10 +524,14 @@ export interface ApiExecutionExecution extends Struct.CollectionTypeSchema { publishedAt: Schema.Attribute.DateTime; stderr: Schema.Attribute.Text; stdout: Schema.Attribute.Text; - submission: Schema.Attribute.Relation<'manyToOne', 'api::submission.submission'>; + submission: Schema.Attribute.Relation< + 'manyToOne', + 'api::submission.submission' + >; testCase: Schema.Attribute.Relation<'oneToOne', 'api::test-case.test-case'>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -493,17 +549,22 @@ export interface ApiLanguageLanguage extends Struct.CollectionTypeSchema { attributes: { codeName: Schema.Attribute.String; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; defaultMaxCpuTime: Schema.Attribute.Float; defaultMaxMemory: Schema.Attribute.Integer; entrypoint: Schema.Attribute.String; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'api::language.language'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::language.language' + > & Schema.Attribute.Private; name: Schema.Attribute.String; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -525,7 +586,8 @@ export interface ApiProblemProblem extends Struct.CollectionTypeSchema { }; attributes: { createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; description: Schema.Attribute.RichText & Schema.Attribute.SetPluginOptions<{ i18n: { @@ -534,7 +596,10 @@ export interface ApiProblemProblem extends Struct.CollectionTypeSchema { }>; event: Schema.Attribute.Relation<'manyToOne', 'api::event.event'>; locale: Schema.Attribute.String; - localizations: Schema.Attribute.Relation<'oneToMany', 'api::problem.problem'>; + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::problem.problem' + >; points: Schema.Attribute.Integer & Schema.Attribute.SetMinMax< { @@ -556,7 +621,10 @@ export interface ApiProblemProblem extends Struct.CollectionTypeSchema { localized: true; }; }>; - testCases: Schema.Attribute.Relation<'oneToMany', 'api::test-case.test-case'>; + testCases: Schema.Attribute.Relation< + 'oneToMany', + 'api::test-case.test-case' + >; title: Schema.Attribute.String & Schema.Attribute.SetPluginOptions<{ i18n: { @@ -564,7 +632,8 @@ export interface ApiProblemProblem extends Struct.CollectionTypeSchema { }; }>; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -582,21 +651,32 @@ export interface ApiSubmissionSubmission extends Struct.CollectionTypeSchema { attributes: { code: Schema.Attribute.Text; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; event: Schema.Attribute.Relation<'oneToOne', 'api::event.event'>; - executions: Schema.Attribute.Relation<'oneToMany', 'api::execution.execution'>; + executions: Schema.Attribute.Relation< + 'oneToMany', + 'api::execution.execution' + >; finishedAt: Schema.Attribute.DateTime; language: Schema.Attribute.Relation<'oneToOne', 'api::language.language'>; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'api::submission.submission'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::submission.submission' + > & Schema.Attribute.Private; metadata: Schema.Attribute.JSON; problem: Schema.Attribute.Relation<'oneToOne', 'api::problem.problem'>; publishedAt: Schema.Attribute.DateTime; triggeredAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; - user: Schema.Attribute.Relation<'oneToOne', 'plugin::users-permissions.user'>; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + user: Schema.Attribute.Relation< + 'oneToOne', + 'plugin::users-permissions.user' + >; }; } @@ -613,24 +693,30 @@ export interface ApiTestCaseTestCase extends Struct.CollectionTypeSchema { }; attributes: { createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; explanation: Schema.Attribute.RichText; hidden: Schema.Attribute.Boolean; input: Schema.Attribute.Text; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'api::test-case.test-case'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::test-case.test-case' + > & Schema.Attribute.Private; locked: Schema.Attribute.Boolean; output: Schema.Attribute.Text; problem: Schema.Attribute.Relation<'manyToOne', 'api::problem.problem'>; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; weight: Schema.Attribute.Float; }; } -export interface PluginContentReleasesRelease extends Struct.CollectionTypeSchema { +export interface PluginContentReleasesRelease + extends Struct.CollectionTypeSchema { collectionName: 'strapi_releases'; info: { displayName: 'Release'; @@ -649,25 +735,36 @@ export interface PluginContentReleasesRelease extends Struct.CollectionTypeSchem }; }; attributes: { - actions: Schema.Attribute.Relation<'oneToMany', 'plugin::content-releases.release-action'>; + actions: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::content-releases.release-action' + >; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::content-releases.release'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::content-releases.release' + > & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required; publishedAt: Schema.Attribute.DateTime; releasedAt: Schema.Attribute.DateTime; scheduledAt: Schema.Attribute.DateTime; - status: Schema.Attribute.Enumeration<['ready', 'blocked', 'failed', 'done', 'empty']> & + status: Schema.Attribute.Enumeration< + ['ready', 'blocked', 'failed', 'done', 'empty'] + > & Schema.Attribute.Required; timezone: Schema.Attribute.String; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } -export interface PluginContentReleasesReleaseAction extends Struct.CollectionTypeSchema { +export interface PluginContentReleasesReleaseAction + extends Struct.CollectionTypeSchema { collectionName: 'strapi_release_actions'; info: { displayName: 'Release Action'; @@ -688,7 +785,8 @@ export interface PluginContentReleasesReleaseAction extends Struct.CollectionTyp attributes: { contentType: Schema.Attribute.String & Schema.Attribute.Required; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; entryDocumentId: Schema.Attribute.String; isEntryValid: Schema.Attribute.Boolean; locale: Schema.Attribute.String & Schema.Attribute.Private; @@ -698,10 +796,15 @@ export interface PluginContentReleasesReleaseAction extends Struct.CollectionTyp > & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; - release: Schema.Attribute.Relation<'manyToOne', 'plugin::content-releases.release'>; - type: Schema.Attribute.Enumeration<['publish', 'unpublish']> & Schema.Attribute.Required; + release: Schema.Attribute.Relation< + 'manyToOne', + 'plugin::content-releases.release' + >; + type: Schema.Attribute.Enumeration<['publish', 'unpublish']> & + Schema.Attribute.Required; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -728,9 +831,13 @@ export interface PluginI18NLocale extends Struct.CollectionTypeSchema { attributes: { code: Schema.Attribute.String & Schema.Attribute.Unique; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::i18n.locale'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::i18n.locale' + > & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.SetMinMax< @@ -742,11 +849,13 @@ export interface PluginI18NLocale extends Struct.CollectionTypeSchema { >; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } -export interface PluginReviewWorkflowsWorkflow extends Struct.CollectionTypeSchema { +export interface PluginReviewWorkflowsWorkflow + extends Struct.CollectionTypeSchema { collectionName: 'strapi_workflows'; info: { description: ''; @@ -771,23 +880,34 @@ export interface PluginReviewWorkflowsWorkflow extends Struct.CollectionTypeSche Schema.Attribute.Required & Schema.Attribute.DefaultTo<'[]'>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::review-workflows.workflow'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::review-workflows.workflow' + > & Schema.Attribute.Private; - name: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique; + name: Schema.Attribute.String & + Schema.Attribute.Required & + Schema.Attribute.Unique; publishedAt: Schema.Attribute.DateTime; stageRequiredToPublish: Schema.Attribute.Relation< 'oneToOne', 'plugin::review-workflows.workflow-stage' >; - stages: Schema.Attribute.Relation<'oneToMany', 'plugin::review-workflows.workflow-stage'>; + stages: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::review-workflows.workflow-stage' + >; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } -export interface PluginReviewWorkflowsWorkflowStage extends Struct.CollectionTypeSchema { +export interface PluginReviewWorkflowsWorkflowStage + extends Struct.CollectionTypeSchema { collectionName: 'strapi_workflows_stages'; info: { description: ''; @@ -811,7 +931,8 @@ export interface PluginReviewWorkflowsWorkflowStage extends Struct.CollectionTyp attributes: { color: Schema.Attribute.String & Schema.Attribute.DefaultTo<'#4945FF'>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; localizations: Schema.Attribute.Relation< 'oneToMany', @@ -822,8 +943,12 @@ export interface PluginReviewWorkflowsWorkflowStage extends Struct.CollectionTyp permissions: Schema.Attribute.Relation<'manyToMany', 'admin::permission'>; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; - workflow: Schema.Attribute.Relation<'manyToOne', 'plugin::review-workflows.workflow'>; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + workflow: Schema.Attribute.Relation< + 'manyToOne', + 'plugin::review-workflows.workflow' + >; }; } @@ -850,7 +975,8 @@ export interface PluginUploadFile extends Struct.CollectionTypeSchema { alternativeText: Schema.Attribute.Text; caption: Schema.Attribute.Text; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; ext: Schema.Attribute.String; folder: Schema.Attribute.Relation<'manyToOne', 'plugin::upload.folder'> & Schema.Attribute.Private; @@ -864,7 +990,10 @@ export interface PluginUploadFile extends Struct.CollectionTypeSchema { hash: Schema.Attribute.String & Schema.Attribute.Required; height: Schema.Attribute.Integer; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.file'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::upload.file' + > & Schema.Attribute.Private; mime: Schema.Attribute.String & Schema.Attribute.Required; name: Schema.Attribute.String & Schema.Attribute.Required; @@ -875,7 +1004,8 @@ export interface PluginUploadFile extends Struct.CollectionTypeSchema { related: Schema.Attribute.Relation<'morphToMany'>; size: Schema.Attribute.Decimal & Schema.Attribute.Required; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; url: Schema.Attribute.Text & Schema.Attribute.Required; width: Schema.Attribute.Integer; }; @@ -902,10 +1032,14 @@ export interface PluginUploadFolder extends Struct.CollectionTypeSchema { attributes: { children: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.folder'>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; files: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.file'>; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.folder'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::upload.folder' + > & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required & @@ -918,14 +1052,18 @@ export interface PluginUploadFolder extends Struct.CollectionTypeSchema { Schema.Attribute.SetMinMaxLength<{ minLength: 1; }>; - pathId: Schema.Attribute.Integer & Schema.Attribute.Required & Schema.Attribute.Unique; + pathId: Schema.Attribute.Integer & + Schema.Attribute.Required & + Schema.Attribute.Unique; publishedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } -export interface PluginUsersPermissionsPermission extends Struct.CollectionTypeSchema { +export interface PluginUsersPermissionsPermission + extends Struct.CollectionTypeSchema { collectionName: 'up_permissions'; info: { description: ''; @@ -948,18 +1086,27 @@ export interface PluginUsersPermissionsPermission extends Struct.CollectionTypeS attributes: { action: Schema.Attribute.String & Schema.Attribute.Required; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.permission'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::users-permissions.permission' + > & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; - role: Schema.Attribute.Relation<'manyToOne', 'plugin::users-permissions.role'>; + role: Schema.Attribute.Relation< + 'manyToOne', + 'plugin::users-permissions.role' + >; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } -export interface PluginUsersPermissionsRole extends Struct.CollectionTypeSchema { +export interface PluginUsersPermissionsRole + extends Struct.CollectionTypeSchema { collectionName: 'up_roles'; info: { description: ''; @@ -981,26 +1128,38 @@ export interface PluginUsersPermissionsRole extends Struct.CollectionTypeSchema }; attributes: { createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; description: Schema.Attribute.String; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.role'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::users-permissions.role' + > & Schema.Attribute.Private; name: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.SetMinMaxLength<{ minLength: 3; }>; - permissions: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.permission'>; + permissions: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::users-permissions.permission' + >; publishedAt: Schema.Attribute.DateTime; type: Schema.Attribute.String & Schema.Attribute.Unique; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; - users: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.user'>; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + users: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::users-permissions.user' + >; }; } -export interface PluginUsersPermissionsUser extends Struct.CollectionTypeSchema { +export interface PluginUsersPermissionsUser + extends Struct.CollectionTypeSchema { collectionName: 'up_users'; info: { description: ''; @@ -1018,14 +1177,18 @@ export interface PluginUsersPermissionsUser extends Struct.CollectionTypeSchema confirmationToken: Schema.Attribute.String & Schema.Attribute.Private; confirmed: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; email: Schema.Attribute.Email & Schema.Attribute.Required & Schema.Attribute.SetMinMaxLength<{ minLength: 6; }>; locale: Schema.Attribute.String & Schema.Attribute.Private; - localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.user'> & + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::users-permissions.user' + > & Schema.Attribute.Private; password: Schema.Attribute.Password & Schema.Attribute.Private & @@ -1035,9 +1198,13 @@ export interface PluginUsersPermissionsUser extends Struct.CollectionTypeSchema provider: Schema.Attribute.String; publishedAt: Schema.Attribute.DateTime; resetPasswordToken: Schema.Attribute.String & Schema.Attribute.Private; - role: Schema.Attribute.Relation<'manyToOne', 'plugin::users-permissions.role'>; + role: Schema.Attribute.Relation< + 'manyToOne', + 'plugin::users-permissions.role' + >; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; username: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique &