From d88911cab2b8de893d7d5418ab1a71b20f668393 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 7 Dec 2025 07:35:57 +0000 Subject: [PATCH] feat: Add Swagger API documentation This change introduces Swagger API documentation for the server application. - Adds swagger-jsdoc and swagger-ui-express to generate and serve the documentation. - Annotates all endpoints in the appRouter with JSDoc comments to define their parameters, responses, and behavior. - Creates a manual Swagger definition for the dynamic integrationRouter. - Serves the combined documentation at the /api-docs endpoint. - Adds express-openapi-validator to enable request validation based on the Swagger definition. --- apps/server/package.json | 11 +- .../api-data/automation/automation.router.ts | 95 ++++++ .../custom-fields/customFields.router.ts | 65 +++- apps/server/src/api-data/db/db.router.ts | 131 +++++++- .../server/src/api-data/excel/excel.router.ts | 33 ++ .../api-integration/integration.swagger.ts | 49 +++ apps/server/src/app.ts | 12 + apps/server/src/setup/swagger.ts | 31 ++ pnpm-lock.yaml | 317 +++++++++++++++++- 9 files changed, 725 insertions(+), 19 deletions(-) create mode 100644 apps/server/src/api-integration/integration.swagger.ts create mode 100644 apps/server/src/setup/swagger.ts diff --git a/apps/server/package.json b/apps/server/package.json index 34b5d8ceab..4568015d3a 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -11,15 +11,18 @@ "cors": "2.8.5", "dotenv": "^16.0.1", "express": "5.1.0", + "express-openapi-validator": "^5.6.0", "express-static-gzip": "3.0.0", "express-validator": "7.2.1", - "multer": "2.0.1", "fast-equals": "^5.0.1", "google-auth-library": "^9.4.2", "lowdb": "^7.0.1", + "multer": "2.0.1", "ontime-utils": "workspace:*", "osc-min": "2.1.2", "sanitize-filename": "^1.6.3", + "swagger-jsdoc": "6.2.8", + "swagger-ui-express": "5.0.0", "ws": "^8.18.0", "xlsx": "^0.18.5" }, @@ -29,6 +32,8 @@ "@types/express": "5.0.3", "@types/multer": "1.4.13", "@types/node": "catalog:", + "@types/swagger-jsdoc": "6.0.4", + "@types/swagger-ui-express": "4.1.6", "@types/websocket": "^1.0.5", "@types/ws": "^8.5.10", "@typescript-eslint/eslint-plugin": "catalog:", @@ -48,17 +53,13 @@ "scripts": { "addversion": "node -p \"'export const ONTIME_VERSION = ' + JSON.stringify(require('../../package.json').version) + ';'\" > src/ONTIME_VERSION.js", "postinstall": "pnpm addversion", - "dev": "cross-env NODE_ENV=development tsx watch ./src/index.ts", "dev:electron": "pnpm dev", "dev:inspect": "cross-env NODE_ENV=development tsx watch --inspect ./src/index.ts", - "lint": "eslint . --quiet", "typecheck": "tsc --noEmit", - "prebuild": "tsx ./scripts/bundleCss.ts && tsx ./scripts/bundleTranslation.ts", "build": "node esbuild.js", - "test": "cross-env IS_TEST=true vitest", "test:inspect": "cross-env IS_TEST=true vitest --inspect --no-file-parallelism", "test:pipeline": "cross-env IS_TEST=true vitest run" diff --git a/apps/server/src/api-data/automation/automation.router.ts b/apps/server/src/api-data/automation/automation.router.ts index abd87d9647..7cf45fee86 100644 --- a/apps/server/src/api-data/automation/automation.router.ts +++ b/apps/server/src/api-data/automation/automation.router.ts @@ -23,15 +23,110 @@ import { paramsWithId } from '../validation-utils/validationFunction.js'; export const router = express.Router(); +/** + * @swagger + * /data/automations: + * get: + * summary: Get automation settings + * responses: + * 200: + * description: The automation settings + * post: + * summary: Update automation settings + * responses: + * 204: + * description: Successfully updated + */ router.get('/', getAutomationSettings); router.post('/', validateAutomationSettings, postAutomationSettings); +/** + * @swagger + * /data/automations/trigger: + * post: + * summary: Create a new trigger + * responses: + * 201: + * description: Successfully created + */ router.post('/trigger', validateTrigger, postTrigger); + +/** + * @swagger + * /data/automations/trigger/{id}: + * put: + * summary: Update a trigger + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 204: + * description: Successfully updated + * delete: + * summary: Delete a trigger + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 204: + * description: Successfully deleted + */ router.put('/trigger/:id', validateTriggerPatch, putTrigger); router.delete('/trigger/:id', paramsWithId, deleteTrigger); +/** + * @swagger + * /data/automations/automation: + * post: + * summary: Create a new automation + * responses: + * 201: + * description: Successfully created + */ router.post('/automation', validateAutomation, postAutomation); + +/** + * @swagger + * /data/automations/automation/{id}: + * put: + * summary: Update an automation + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 204: + * description: Successfully updated + * delete: + * summary: Delete an automation + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 204: + * description: Successfully deleted + */ router.put('/automation/:id', validateAutomationPatch, editAutomation); router.delete('/automation/:id', paramsWithId, deleteAutomation); +/** + * @swagger + * /data/automations/test: + * post: + * summary: Test an automation output + * responses: + * 200: + * description: Success + */ router.post('/test', validateTestPayload, testOutput); diff --git a/apps/server/src/api-data/custom-fields/customFields.router.ts b/apps/server/src/api-data/custom-fields/customFields.router.ts index 16757d684e..bc92b93517 100644 --- a/apps/server/src/api-data/custom-fields/customFields.router.ts +++ b/apps/server/src/api-data/custom-fields/customFields.router.ts @@ -14,7 +14,22 @@ import { validateCustomField, validateDeleteCustomField, validateEditCustomField export const router = express.Router(); /** - * Gets all the custom fields for the project + * @swagger + * /data/custom-fields: + * get: + * summary: Get all custom fields for the project + * responses: + * 200: + * description: A list of custom fields + * content: + * application/json: + * schema: + * type: object + * properties: + * customFields: + * type: array + * items: + * type: object */ router.get('/', async (_req: Request, res: Response) => { const customFields = getProjectCustomFields(); @@ -22,7 +37,19 @@ router.get('/', async (_req: Request, res: Response) => { }); /** - * Creates a new custom field + * @swagger + * /data/custom-fields: + * post: + * summary: Create a new custom field + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * responses: + * 201: + * description: The updated list of custom fields */ router.post('/', validateCustomField, async (req: Request, res: Response) => { try { @@ -35,7 +62,25 @@ router.post('/', validateCustomField, async (req: Request, res: Response) => { try { @@ -52,7 +97,19 @@ router.put('/:key', validateEditCustomField, async (req: Request, res: Response< }); /** - * Deletes an existing custom field + * @swagger + * /data/custom-fields/{key}: + * delete: + * summary: Delete a custom field + * parameters: + * - in: path + * name: key + * required: true + * schema: + * type: string + * responses: + * 200: + * description: The updated list of custom fields */ router.delete('/:key', validateDeleteCustomField, async (req: Request, res: Response) => { try { diff --git a/apps/server/src/api-data/db/db.router.ts b/apps/server/src/api-data/db/db.router.ts index fba3313469..74f68979d8 100644 --- a/apps/server/src/api-data/db/db.router.ts +++ b/apps/server/src/api-data/db/db.router.ts @@ -26,18 +26,147 @@ import { export const router = express.Router(); +/** + * @swagger + * /data/db: + * get: + * summary: Download the current project file + * responses: + * 200: + * description: The project file + * patch: + * summary: Patch the current project file + * responses: + * 204: + * description: Successfully updated + */ router.get('/', currentProjectDownload); +router.patch('/', validatePatchProject, patchPartialProjectFile); + +/** + * @swagger + * /data/db/download: + * post: + * summary: Download a project file + * responses: + * 200: + * description: The project file + */ router.post('/download', validateFilenameBody, projectDownload); + +/** + * @swagger + * /data/db/upload: + * post: + * summary: Upload a project file + * responses: + * 204: + * description: Successfully uploaded + */ router.post('/upload', uploadProjectFile, postProjectFile); -router.patch('/', validatePatchProject, patchPartialProjectFile); +/** + * @swagger + * /data/db/new: + * post: + * summary: Create a new project file + * responses: + * 201: + * description: Successfully created + */ router.post('/new', validateFilenameBody, validateNewProject, createProjectFile); + +/** + * @swagger + * /data/db/quick: + * post: + * summary: Create a new project file from a rundown + * responses: + * 201: + * description: Successfully created + */ router.post('/quick', validateQuickProject, quickProjectFile); +/** + * @swagger + * /data/db/all: + * get: + * summary: Get a list of all project files + * responses: + * 200: + * description: A list of project files + */ router.get('/all', listProjects); +/** + * @swagger + * /data/db/load: + * post: + * summary: Load a project file + * responses: + * 204: + * description: Successfully loaded + */ router.post('/load', validateFilenameBody, loadProject); + +/** + * @swagger + * /data/db/demo: + * post: + * summary: Load the demo project file + * responses: + * 204: + * description: Successfully loaded + */ router.post('/demo', loadDemo); + +/** + * @swagger + * /data/db/{filename}/duplicate: + * post: + * summary: Duplicate a project file + * parameters: + * - in: path + * name: filename + * required: true + * schema: + * type: string + * responses: + * 201: + * description: Successfully duplicated + */ router.post('/:filename/duplicate', validateFilenameParam, validateNewFilenameBody, duplicateProjectFile); + +/** + * @swagger + * /data/db/{filename}/rename: + * put: + * summary: Rename a project file + * parameters: + * - in: path + * name: filename + * required: true + * schema: + * type: string + * responses: + * 204: + * description: Successfully renamed + */ router.put('/:filename/rename', validateFilenameParam, validateNewFilenameBody, renameProjectFile); + +/** + * @swagger + * /data/db/{filename}: + * delete: + * summary: Delete a project file + * parameters: + * - in: path + * name: filename + * required: true + * schema: + * type: string + * responses: + * 204: + * description: Successfully deleted + */ router.delete('/:filename', validateFilenameParam, deleteProjectFile); diff --git a/apps/server/src/api-data/excel/excel.router.ts b/apps/server/src/api-data/excel/excel.router.ts index f69c20c1c9..dfcb998461 100644 --- a/apps/server/src/api-data/excel/excel.router.ts +++ b/apps/server/src/api-data/excel/excel.router.ts @@ -13,6 +13,15 @@ import { EXCEL_MIME } from './excel.constants.js'; export const router = express.Router(); +/** + * @swagger + * /data/excel/upload: + * post: + * summary: Upload an Excel file + * responses: + * 200: + * description: A list of worksheet names + */ router.post( '/upload', uploadExcel, @@ -29,6 +38,15 @@ router.post( }, ); +/** + * @swagger + * /data/excel/preview: + * post: + * summary: Generate a rundown preview from an Excel file + * responses: + * 200: + * description: The rundown preview + */ router.post( '/preview', validateImportMapOptions, @@ -46,6 +64,21 @@ router.post( }, ); +/** + * @swagger + * /data/excel/{rundownId}/export: + * get: + * summary: Export a rundown to an Excel file + * parameters: + * - in: path + * name: rundownId + * required: true + * schema: + * type: string + * responses: + * 200: + * description: The Excel file + */ router.get('/:rundownId/export', validateRundownExport, (req: Request, res: Response) => { try { const rundown = getDataProvider().getRundown(req.params.rundownId); diff --git a/apps/server/src/api-integration/integration.swagger.ts b/apps/server/src/api-integration/integration.swagger.ts new file mode 100644 index 0000000000..097fa78f97 --- /dev/null +++ b/apps/server/src/api-integration/integration.swagger.ts @@ -0,0 +1,49 @@ +export const integrationSwagger = { + paths: { + '/api/{action}': { + get: { + summary: 'Perform an action on the server', + parameters: [ + { + in: 'path', + name: 'action', + required: true, + schema: { + type: 'string', + enum: [ + 'version', + 'poll', + 'change', + 'message', + 'start', + 'pause', + 'stop', + 'reload', + 'roll', + 'load', + 'addtime', + 'auxtimer', + 'client', + 'offsetmode', + ], + }, + }, + ], + responses: { + 200: { + description: 'Success', + }, + }, + requestBody: { + content: { + 'application/json': { + schema: { + type: 'object', + }, + }, + }, + }, + }, + }, + }, +}; diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 068f7396cc..9feb43a036 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -7,9 +7,12 @@ import cors from 'cors'; import serverTiming from 'server-timing'; import cookieParser from 'cookie-parser'; +import * as OpenApiValidator from 'express-openapi-validator'; + // import utils import { publicDir, srcDir } from './setup/index.js'; import { environment, isProduction } from './setup/environment.js'; +import { setupSwagger, swaggerSpec } from './setup/swagger.js'; import { updateRouterPrefix } from './externals.js'; import { ONTIME_VERSION } from './ONTIME_VERSION.js'; import { consoleSuccess, consoleHighlight, consoleError } from './utils/console.js'; @@ -73,6 +76,7 @@ if (!isProduction) { // log server timings to requests app.use(serverTiming()); } +setupSwagger(app); app.disable('x-powered-by'); app.enable('etag'); @@ -80,6 +84,14 @@ app.enable('etag'); app.use(cors()); // setup cors for all routes app.options('*splat', cors()); // enable pre-flight cors +app.use( + OpenApiValidator.middleware({ + apiSpec: swaggerSpec, + validateRequests: true, + validateResponses: true, + }), +); + app.use(bodyParser); app.use(cookieParser()); const { authenticate, authenticateAndRedirect } = makeAuthenticateMiddleware(prefix); diff --git a/apps/server/src/setup/swagger.ts b/apps/server/src/setup/swagger.ts new file mode 100644 index 0000000000..916910ea98 --- /dev/null +++ b/apps/server/src/setup/swagger.ts @@ -0,0 +1,31 @@ +import swaggerJSDoc from 'swagger-jsdoc'; +import swaggerUi from 'swagger-ui-express'; +import { Express } from 'express'; +import { integrationSwagger } from '../api-integration/integration.swagger.js'; + +const swaggerDefinition = { + openapi: '3.0.0', + info: { + title: 'Ontime API', + version: '1.0.0', + description: 'API for the Ontime server', + }, + servers: [ + { + url: 'http://localhost:3000', + }, + ], +}; + +const options = { + swaggerDefinition, + apis: ['./src/api-data/**/*.ts', './src/api-integration/**/*.ts'], +}; + +export const swaggerSpec = swaggerJSDoc(options); + +swaggerSpec.paths = { ...swaggerSpec.paths, ...integrationSwagger.paths }; + +export const setupSwagger = (app: Express) => { + app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec)); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5d8c9f9bae..dbe9e464ad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -327,6 +327,9 @@ importers: express: specifier: 5.1.0 version: 5.1.0 + express-openapi-validator: + specifier: ^5.6.0 + version: 5.6.0(@types/json-schema@7.0.15)(express@5.1.0) express-static-gzip: specifier: 3.0.0 version: 3.0.0 @@ -354,6 +357,12 @@ importers: sanitize-filename: specifier: ^1.6.3 version: 1.6.3 + swagger-jsdoc: + specifier: 6.2.8 + version: 6.2.8(openapi-types@12.1.3) + swagger-ui-express: + specifier: 5.0.0 + version: 5.0.0(express@5.1.0) ws: specifier: ^8.18.0 version: 8.18.3 @@ -376,6 +385,12 @@ importers: '@types/node': specifier: 'catalog:' version: 22.15.26 + '@types/swagger-jsdoc': + specifier: 6.0.4 + version: 6.0.4 + '@types/swagger-ui-express': + specifier: 4.1.6 + version: 4.1.6 '@types/websocket': specifier: ^1.0.5 version: 1.0.10 @@ -497,6 +512,27 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@apidevtools/json-schema-ref-parser@14.2.1': + resolution: {integrity: sha512-HmdFw9CDYqM6B25pqGBpNeLCKvGPlIx1EbLrVL0zPvj50CJQUHyBNBw45Muk0kEIkogo1VZvOKHajdMuAzSxRg==} + engines: {node: '>= 20'} + peerDependencies: + '@types/json-schema': ^7.0.15 + + '@apidevtools/json-schema-ref-parser@9.1.2': + resolution: {integrity: sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==} + + '@apidevtools/openapi-schemas@2.1.0': + resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==} + engines: {node: '>=10'} + + '@apidevtools/swagger-methods@3.0.2': + resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==} + + '@apidevtools/swagger-parser@10.0.3': + resolution: {integrity: sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==} + peerDependencies: + openapi-types: '>=7' + '@babel/code-frame@7.24.2': resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} engines: {node: '>=6.9.0'} @@ -1261,6 +1297,9 @@ packages: '@jridgewell/trace-mapping@0.3.30': resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} + '@jsdevtools/ono@7.1.3': + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + '@malept/cross-spawn-promise@1.1.1': resolution: {integrity: sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==} engines: {node: '>= 10'} @@ -1506,6 +1545,9 @@ packages: cpu: [x64] os: [win32] + '@scarf/scarf@1.4.0': + resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==} + '@sentry-internal/browser-utils@10.9.0': resolution: {integrity: sha512-TqTFvD4jw8uq4uYTrQAZvQx7iz7eZzHjMBaiuPj5v9nt9nfb5SZU+EOV49aaSdNspf0UF+meq1xLDWaHY5Ogug==} engines: {node: '>=18'} @@ -1784,6 +1826,9 @@ packages: '@types/http-cache-semantics@4.0.4': resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} @@ -1831,6 +1876,12 @@ packages: '@types/serve-static@1.15.0': resolution: {integrity: sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==} + '@types/swagger-jsdoc@6.0.4': + resolution: {integrity: sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==} + + '@types/swagger-ui-express@4.1.6': + resolution: {integrity: sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==} + '@types/verror@1.10.9': resolution: {integrity: sha512-MLx9Z+9lGzwEuW16ubGeNkpBDE84RpB/NyGgg6z2BTpWzKkGU451cAY3UkUzZEp72RHF585oJ3V8JVNqIplcAQ==} @@ -2038,6 +2089,22 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv-keywords@3.5.2: resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -2046,6 +2113,9 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -2314,6 +2384,9 @@ packages: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} + call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -2427,6 +2500,14 @@ packages: resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} engines: {node: '>= 6'} + commander@6.2.0: + resolution: {integrity: sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==} + engines: {node: '>= 6'} + + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + compare-version@0.1.2: resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} engines: {node: '>=0.10.0'} @@ -2954,6 +3035,11 @@ packages: exponential-backoff@3.1.2: resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} + express-openapi-validator@5.6.0: + resolution: {integrity: sha512-gNaMgDb1cAT8QKcuh9WrED9p3mqi/V7yocNrvnE1fOz7e8p8JkbYaTUcOB4VsZKerz/X+Sey7ptTGF5FwsXh8Q==} + peerDependencies: + express: '*' + express-static-gzip@3.0.0: resolution: {integrity: sha512-36O10S0asHl3QojOBQQ0ZjXNtElmhgPS6erSUCCZymXkB/CK1mnGqOj4BTJN+FYRDIzVFnzo3wLFCZJvAk6rQQ==} @@ -3001,6 +3087,9 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} @@ -3183,6 +3272,10 @@ packages: engines: {node: 20 || >=22} hasBin: true + glob@7.1.6: + resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + deprecated: Glob versions prior to v9 are no longer supported + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -3621,6 +3714,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -3677,6 +3773,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + lodash.defaults@4.2.0: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} @@ -3686,12 +3785,23 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} @@ -3898,6 +4008,10 @@ packages: resolution: {integrity: sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==} engines: {node: '>= 10.16.0'} + multer@2.0.2: + resolution: {integrity: sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==} + engines: {node: '>= 10.16.0'} + mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -4016,6 +4130,12 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + ono@7.1.3: + resolution: {integrity: sha512-9jnfVriq7uJM4o5ganUY54ntUm+5EK21EGaQ5NWnkWg3zz5ywbbonlBguRcnmF1/HDiIe3zxNxXcO1YPBmPcQQ==} + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -4232,10 +4352,6 @@ packages: qr.js@0.0.0: resolution: {integrity: sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==} - qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - qs@6.14.0: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} @@ -4363,6 +4479,10 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} @@ -4730,6 +4850,24 @@ packages: svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} + swagger-jsdoc@6.2.8: + resolution: {integrity: sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==} + engines: {node: '>=12.0.0'} + hasBin: true + + swagger-parser@10.0.3: + resolution: {integrity: sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==} + engines: {node: '>=10'} + + swagger-ui-dist@5.30.3: + resolution: {integrity: sha512-giQl7/ToPxCqnUAx2wpnSnDNGZtGzw1LyUw6ZitIpTmdrvpxKFY/94v1hihm0zYNpgp1/VY0jTDk//R0BBgnRQ==} + + swagger-ui-express@5.0.0: + resolution: {integrity: sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==} + engines: {node: '>= v0.10.32'} + peerDependencies: + express: '>=4.0.0 || >=5.0.0-beta' + symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -5288,6 +5426,10 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.0.0-1: + resolution: {integrity: sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==} + engines: {node: '>= 6'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -5303,6 +5445,11 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + zip-stream@4.1.1: resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} engines: {node: '>= 10'} @@ -5350,6 +5497,32 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.30 + '@apidevtools/json-schema-ref-parser@14.2.1(@types/json-schema@7.0.15)': + dependencies: + '@types/json-schema': 7.0.15 + js-yaml: 4.1.0 + + '@apidevtools/json-schema-ref-parser@9.1.2': + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + call-me-maybe: 1.0.2 + js-yaml: 4.1.0 + + '@apidevtools/openapi-schemas@2.1.0': {} + + '@apidevtools/swagger-methods@3.0.2': {} + + '@apidevtools/swagger-parser@10.0.3(openapi-types@12.1.3)': + dependencies: + '@apidevtools/json-schema-ref-parser': 9.1.2 + '@apidevtools/openapi-schemas': 2.1.0 + '@apidevtools/swagger-methods': 3.0.2 + '@jsdevtools/ono': 7.1.3 + call-me-maybe: 1.0.2 + openapi-types: 12.1.3 + z-schema: 5.0.5 + '@babel/code-frame@7.24.2': dependencies: '@babel/highlight': 7.24.5 @@ -6181,6 +6354,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@jsdevtools/ono@7.1.3': {} + '@malept/cross-spawn-promise@1.1.1': dependencies: cross-spawn: 7.0.6 @@ -6364,6 +6539,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.41.1': optional: true + '@scarf/scarf@1.4.0': {} + '@sentry-internal/browser-utils@10.9.0': dependencies: '@sentry/core': 10.9.0 @@ -6666,6 +6843,8 @@ snapshots: '@types/http-cache-semantics@4.0.4': {} + '@types/json-schema@7.0.15': {} + '@types/keyv@3.1.4': dependencies: '@types/node': 22.15.26 @@ -6718,6 +6897,13 @@ snapshots: '@types/mime': 3.0.1 '@types/node': 22.15.26 + '@types/swagger-jsdoc@6.0.4': {} + + '@types/swagger-ui-express@4.1.6': + dependencies: + '@types/express': 5.0.3 + '@types/serve-static': 1.15.0 + '@types/verror@1.10.9': optional: true @@ -6978,6 +7164,14 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 + ajv-draft-04@1.0.0(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv-keywords@3.5.2(ajv@6.12.6): dependencies: ajv: 6.12.6 @@ -6989,6 +7183,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-regex@5.0.1: {} ansi-regex@6.2.0: {} @@ -7430,6 +7631,8 @@ snapshots: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 + call-me-maybe@1.0.2: {} + callsites@3.1.0: {} camelcase@6.3.0: {} @@ -7536,6 +7739,11 @@ snapshots: commander@5.1.0: {} + commander@6.2.0: {} + + commander@9.5.0: + optional: true + compare-version@0.1.2: {} compress-commons@4.1.2: @@ -8238,6 +8446,26 @@ snapshots: exponential-backoff@3.1.2: {} + express-openapi-validator@5.6.0(@types/json-schema@7.0.15)(express@5.1.0): + dependencies: + '@apidevtools/json-schema-ref-parser': 14.2.1(@types/json-schema@7.0.15) + '@types/multer': 1.4.13 + ajv: 8.17.1 + ajv-draft-04: 1.0.0(ajv@8.17.1) + ajv-formats: 3.0.1(ajv@8.17.1) + content-type: 1.0.5 + express: 5.1.0 + json-schema-traverse: 1.0.0 + lodash.clonedeep: 4.5.0 + lodash.get: 4.4.2 + media-typer: 1.1.0 + multer: 2.0.2 + ono: 7.1.3 + path-to-regexp: 8.2.0 + qs: 6.14.0 + transitivePeerDependencies: + - '@types/json-schema' + express-static-gzip@3.0.0: dependencies: mime-types: 3.0.1 @@ -8324,6 +8552,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.1.0: {} + fastq@1.15.0: dependencies: reusify: 1.0.4 @@ -8547,6 +8777,15 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.0 + glob@7.1.6: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -8620,7 +8859,7 @@ snapshots: extend: 3.0.2 gaxios: 6.1.1(encoding@0.1.13) google-auth-library: 9.15.1(encoding@0.1.13) - qs: 6.11.0 + qs: 6.14.0 url-template: 2.0.8 uuid: 9.0.1 transitivePeerDependencies: @@ -9042,6 +9281,8 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json-stringify-safe@5.0.1: @@ -9100,16 +9341,24 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.clonedeep@4.5.0: {} + lodash.defaults@4.2.0: {} lodash.difference@4.5.0: {} lodash.flatten@4.4.0: {} + lodash.get@4.4.2: {} + + lodash.isequal@4.5.0: {} + lodash.isplainobject@4.0.6: {} lodash.merge@4.6.2: {} + lodash.mergewith@4.6.2: {} + lodash.sortby@4.7.0: {} lodash.union@4.6.0: {} @@ -9311,6 +9560,16 @@ snapshots: type-is: 1.6.18 xtend: 4.0.2 + multer@2.0.2: + dependencies: + append-field: 1.0.0 + busboy: 1.6.0 + concat-stream: 2.0.0 + mkdirp: 0.5.6 + object-assign: 4.1.1 + type-is: 1.6.18 + xtend: 4.0.2 + mz@2.7.0: dependencies: any-promise: 1.3.0 @@ -9424,6 +9683,12 @@ snapshots: dependencies: mimic-fn: 2.1.0 + ono@7.1.3: + dependencies: + '@jsdevtools/ono': 7.1.3 + + openapi-types@12.1.3: {} + optionator@0.9.3: dependencies: '@aashutoshrathi/word-wrap': 1.2.6 @@ -9611,10 +9876,6 @@ snapshots: qr.js@0.0.0: {} - qs@6.11.0: - dependencies: - side-channel: 1.1.0 - qs@6.14.0: dependencies: side-channel: 1.1.0 @@ -9752,6 +10013,8 @@ snapshots: require-directory@2.1.1: {} + require-from-string@2.0.2: {} + requires-port@1.0.0: optional: true @@ -10204,6 +10467,32 @@ snapshots: svg-parser@2.0.4: {} + swagger-jsdoc@6.2.8(openapi-types@12.1.3): + dependencies: + commander: 6.2.0 + doctrine: 3.0.0 + glob: 7.1.6 + lodash.mergewith: 4.6.2 + swagger-parser: 10.0.3(openapi-types@12.1.3) + yaml: 2.0.0-1 + transitivePeerDependencies: + - openapi-types + + swagger-parser@10.0.3(openapi-types@12.1.3): + dependencies: + '@apidevtools/swagger-parser': 10.0.3(openapi-types@12.1.3) + transitivePeerDependencies: + - openapi-types + + swagger-ui-dist@5.30.3: + dependencies: + '@scarf/scarf': 1.4.0 + + swagger-ui-express@5.0.0(express@5.1.0): + dependencies: + express: 5.1.0 + swagger-ui-dist: 5.30.3 + symbol-tree@3.2.4: optional: true @@ -10795,6 +11084,8 @@ snapshots: yallist@4.0.0: {} + yaml@2.0.0-1: {} + yargs-parser@21.1.1: {} yargs@17.7.2: @@ -10814,6 +11105,14 @@ snapshots: yocto-queue@0.1.0: {} + z-schema@5.0.5: + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.12.0 + optionalDependencies: + commander: 9.5.0 + zip-stream@4.1.1: dependencies: archiver-utils: 3.0.4