From 3050e6a564573549e09988e0dbd175362f2193ac Mon Sep 17 00:00:00 2001 From: bzp2010 Date: Sun, 27 Jul 2025 16:46:12 +0800 Subject: [PATCH 1/8] feat(core): add ingress server mode --- apps/cli/package.json | 9 +- apps/cli/src/command/helper.ts | 48 ++-- apps/cli/src/command/index.ts | 2 + .../cli/src/command/ingress-server.command.ts | 6 + apps/cli/src/server/index.ts | 20 ++ apps/cli/src/server/schema.ts | 20 ++ apps/cli/src/server/sync.ts | 95 +++++++ pnpm-lock.yaml | 240 +++++++++++++++++- 8 files changed, 417 insertions(+), 23 deletions(-) create mode 100644 apps/cli/src/command/ingress-server.command.ts create mode 100644 apps/cli/src/server/index.ts create mode 100644 apps/cli/src/server/schema.ts create mode 100644 apps/cli/src/server/sync.ts diff --git a/apps/cli/package.json b/apps/cli/package.json index 71ffc5d0..f6faea61 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,10 +1,15 @@ { "private": true, "devDependencies": { - "@api7/adc-sdk": "workspace:*", "@api7/adc-backend-api7": "workspace:*", "@api7/adc-backend-apisix": "workspace:*", "@api7/adc-backend-apisix-standalone": "workspace:*", - "@api7/adc-converter-openapi": "workspace:*" + "@api7/adc-converter-openapi": "workspace:*", + "@api7/adc-sdk": "workspace:*", + "@types/express": "^5.0.3" + }, + "dependencies": { + "body-parser": "^2.2.0", + "express": "^5.1.0" } } diff --git a/apps/cli/src/command/helper.ts b/apps/cli/src/command/helper.ts index 2c8c9431..9884ca9b 100644 --- a/apps/cli/src/command/helper.ts +++ b/apps/cli/src/command/helper.ts @@ -7,7 +7,12 @@ import { resolve } from 'node:path'; import parseDuration from 'parse-duration'; import qs from 'qs'; -export class BaseCommand extends Command { +export interface BaseOptions { + verbose: boolean; +} +export class BaseCommand< + OPTS extends BaseOptions = BaseOptions, +> extends Command { private examples: Array<{ title: string; command: string }> = []; constructor(name: string, summary?: string, description?: string) { @@ -49,9 +54,16 @@ export class BaseCommand extends Command { this.description(`${currDescription}\n\n${exampleHeader}\n${exampleText}`); return this; } + + public handle(cb: (opts: OPTS, command: Command) => void | Promise) { + this.action((_, command: Command) => cb(command.opts(), command)); + return this; + } } -export class BackendCommand extends BaseCommand { +export class BackendCommand< + OPTS extends BaseOptions = BaseOptions, +> extends BaseCommand { constructor(name: string, summary?: string, description?: string) { super(name, summary, description); @@ -59,24 +71,20 @@ export class BackendCommand extends BaseCommand { } public handle(cb: (opts: OPTS, command: Command) => void | Promise) { - this.action(async (_, command: Command) => { - const opts = command.opts(); - - if ( - (has(opts, 'tlsClientCertFile') && !has(opts, 'tlsClientKeyFile')) || - (has(opts, 'tlsClientKeyFile') && !has(opts, 'tlsClientCertFile')) - ) { - console.log( - chalk.red( - 'TLS client certificate and key must be provided at the same time', - ), - ); - return; - } - - await cb(opts, command); - }); - return this; + const opts = this.opts(); + + if ( + (has(opts, 'tlsClientCertFile') && !has(opts, 'tlsClientKeyFile')) || + (has(opts, 'tlsClientKeyFile') && !has(opts, 'tlsClientCertFile')) + ) { + console.log( + chalk.red( + 'TLS client certificate and key must be provided at the same time', + ), + ); + return this; + } + return super.handle(cb); } private addBackendOptions() { diff --git a/apps/cli/src/command/index.ts b/apps/cli/src/command/index.ts index f666a564..ac7da5ae 100644 --- a/apps/cli/src/command/index.ts +++ b/apps/cli/src/command/index.ts @@ -6,6 +6,7 @@ import { ConvertCommand } from './convert.command'; import { DevCommand } from './dev.command'; import { DiffCommand } from './diff.command'; import { DumpCommand } from './dump.command'; +import { IngressServerCommand } from './ingress-server.command'; import { IngressSyncCommand } from './ingress-sync.command'; import { LintCommand } from './lint.command'; import { PingCommand } from './ping.command'; @@ -73,6 +74,7 @@ export const setupIngressCommands = (): Command => { } program.addCommand(IngressSyncCommand); + program.addCommand(IngressServerCommand); if (process.env.NODE_ENV === 'development') program.addCommand(DevCommand); diff --git a/apps/cli/src/command/ingress-server.command.ts b/apps/cli/src/command/ingress-server.command.ts new file mode 100644 index 00000000..76e30065 --- /dev/null +++ b/apps/cli/src/command/ingress-server.command.ts @@ -0,0 +1,6 @@ +import { ADCServer } from '../server'; +import { BaseCommand } from './helper'; + +export const IngressServerCommand = new BaseCommand('server').handle(() => + new ADCServer().start(), +); diff --git a/apps/cli/src/server/index.ts b/apps/cli/src/server/index.ts new file mode 100644 index 00000000..f9bf54b4 --- /dev/null +++ b/apps/cli/src/server/index.ts @@ -0,0 +1,20 @@ +import express from 'express'; +import type { Express } from 'express'; + +import { syncHandler } from './sync'; + +export class ADCServer { + private express: Express; + + constructor() { + this.express = express(); + this.express.disable('x-powered-by'); + this.express.use(express.json({ limit: '10mb' })); + this.express.put('/sync', syncHandler); + } + + public start() { + console.log('ADC server is running on: http://127.0.0.1:3000'); + this.express.listen(3000, '127.0.0.1'); + } +} diff --git a/apps/cli/src/server/schema.ts b/apps/cli/src/server/schema.ts new file mode 100644 index 00000000..396265e4 --- /dev/null +++ b/apps/cli/src/server/schema.ts @@ -0,0 +1,20 @@ +import { z } from 'zod'; + +const SyncTask = z.strictObject({ + opts: z.looseObject({ + backend: z.union([ + z.literal('apisix'), + z.literal('api7ee'), + z.literal('apisix-standalone'), + ]), + server: z.url().min(1), + token: z.string().min(1), + lint: z.boolean().optional().default(true), + }), + config: z.looseObject({}), +}); + +export const SyncInput = z.strictObject({ + task: SyncTask, +}); +export type SyncInputType = z.infer; diff --git a/apps/cli/src/server/sync.ts b/apps/cli/src/server/sync.ts new file mode 100644 index 00000000..196b7b6d --- /dev/null +++ b/apps/cli/src/server/sync.ts @@ -0,0 +1,95 @@ +import * as ADCSDK from '@api7/adc-sdk'; +import type { RequestHandler } from 'express'; +import { omit, toString } from 'lodash'; +import { lastValueFrom, toArray } from 'rxjs'; + +import { loadBackend } from '../command/utils'; +import { DifferV3 } from '../differ/differv3'; +import { check } from '../linter'; +import { SyncInput, type SyncInputType } from './schema'; + +export const syncHandler: RequestHandler< + unknown, + unknown, + SyncInputType +> = async (req, res) => { + const parsedInput = SyncInput.safeParse(req.body); + if (!parsedInput.success) + return res.status(400).json({ + message: parsedInput.error.message, + errors: parsedInput.error.issues, + }); + const { task } = parsedInput.data; + + // load local configuration and validate it + const local = task.config as ADCSDK.Configuration; + if (task.opts.lint) { + const result = check(local); + if (!result.success) + return res.status(400).json({ + message: result.error.message, + errors: result.error.issues, + }); + } + + // load remote configuration and diff with local + const backend = loadBackend(task.opts.backend, { ...task.opts }); + const remote = await lastValueFrom(backend.dump()); + const diff = DifferV3.diff(local, remote, await backend.defaultValue()); + + // sync the diff + try { + const results = await lastValueFrom( + backend + .sync(diff, { + exitOnFailure: false, + concurrent: 4, + }) + .pipe(toArray()), + ); + const successes = results.filter((result) => result.success); + const faileds = results.filter((result) => !result.success); + const simplifyEvent = (event: ADCSDK.Event) => + omit(event, ['diff', 'oldValue', 'newValue', 'subEvents']); + const output = { + status: + results.length === successes.length + ? 'success' + : results.length === faileds.length + ? 'all_failed' + : 'partial_failure', + total_resources: results.length, + success_count: successes.length, + failed_count: faileds.length, + success: [ + ...successes.map(({ event, axiosResponse }) => ({ + event: simplifyEvent(event), + synced_at: new Date( + axiosResponse?.headers?.date ?? new Date(), + ).toISOString(), + })), + ], + failed: [ + ...faileds.map(({ event, error, axiosResponse }) => ({ + event: simplifyEvent(event), + failed_at: new Date( + axiosResponse?.headers?.date ?? new Date(), + ).toISOString(), + reason: error.message, + ...(axiosResponse && { + response: { + status: axiosResponse.status, + headers: axiosResponse.headers, + data: axiosResponse.data, + }, + }), + })), + ], + }; + res.status(200).json(output); + } catch (err) { + res.status(500).send({ + message: toString(err), + }); + } +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1feae037..993d823d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -206,6 +206,13 @@ importers: version: 5.98.0(@swc/core@1.5.7(@swc/helpers@0.5.12))(esbuild@0.19.12) apps/cli: + dependencies: + body-parser: + specifier: ^2.2.0 + version: 2.2.0 + express: + specifier: ^5.1.0 + version: 5.1.0 devDependencies: '@api7/adc-backend-api7': specifier: workspace:* @@ -222,6 +229,9 @@ importers: '@api7/adc-sdk': specifier: workspace:* version: link:../../libs/sdk + '@types/express': + specifier: ^5.0.3 + version: 5.0.3 libs/backend-api7: devDependencies: @@ -1751,9 +1761,15 @@ packages: '@types/express-serve-static-core@4.19.1': resolution: {integrity: sha512-ej0phymbFLoCB26dbbq5PGScsf2JAJ4IJHjG10LalgUV36XKTmA4GdA+PVllKvRk0sEKt64X8975qFnkSi0hqA==} + '@types/express-serve-static-core@5.0.7': + resolution: {integrity: sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==} + '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + '@types/express@5.0.3': + resolution: {integrity: sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==} + '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -2023,6 +2039,10 @@ packages: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -2247,6 +2267,10 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@2.2.0: + resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + engines: {node: '>=18'} + bonjour-service@1.2.1: resolution: {integrity: sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==} @@ -2469,6 +2493,10 @@ packages: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} + content-disposition@1.0.0: + resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} + engines: {node: '>= 0.6'} + content-type@1.0.5: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} @@ -2479,6 +2507,10 @@ packages: cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + cookie@0.7.1: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} @@ -2970,6 +3002,10 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} + express@5.1.0: + resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + engines: {node: '>= 18'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -3024,6 +3060,10 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} + finalhandler@2.1.0: + resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} + engines: {node: '>= 0.8'} + find-cache-dir@4.0.0: resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} engines: {node: '>=14.16'} @@ -3094,6 +3134,10 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + front-matter@4.0.2: resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} @@ -3416,6 +3460,9 @@ packages: resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} engines: {node: '>=10'} + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -3838,6 +3885,10 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + memfs@3.5.3: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} engines: {node: '>= 4.0.0'} @@ -3849,6 +3900,10 @@ packages: merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -3872,10 +3927,18 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -3950,6 +4013,10 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -4157,6 +4224,10 @@ packages: path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -4480,6 +4551,10 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + raw-body@3.0.0: + resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} + engines: {node: '>= 0.8'} + react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -4588,6 +4663,10 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + run-applescript@7.0.0: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} engines: {node: '>=18'} @@ -4793,6 +4872,10 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} + send@1.2.0: + resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} + engines: {node: '>= 18'} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -4804,6 +4887,10 @@ packages: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} + serve-static@2.2.0: + resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} + engines: {node: '>= 18'} + setprototypeof@1.1.0: resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} @@ -5205,6 +5292,10 @@ packages: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} + typed-assert@1.0.9: resolution: {integrity: sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==} @@ -7333,6 +7424,13 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 0.17.4 + '@types/express-serve-static-core@5.0.7': + dependencies: + '@types/node': 22.16.5 + '@types/qs': 6.9.15 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 @@ -7340,6 +7438,12 @@ snapshots: '@types/qs': 6.9.15 '@types/serve-static': 1.15.7 + '@types/express@5.0.3': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 5.0.7 + '@types/serve-static': 1.15.7 + '@types/graceful-fs@4.1.9': dependencies: '@types/node': 22.16.5 @@ -7400,7 +7504,7 @@ snapshots: '@types/serve-index@1.9.4': dependencies: - '@types/express': 4.17.21 + '@types/express': 5.0.3 '@types/serve-static@1.15.7': dependencies: @@ -7692,6 +7796,11 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 + accepts@2.0.0: + dependencies: + mime-types: 3.0.1 + negotiator: 1.0.0 + acorn-jsx@5.3.2(acorn@8.11.3): dependencies: acorn: 8.11.3 @@ -7940,6 +8049,20 @@ snapshots: transitivePeerDependencies: - supports-color + body-parser@2.2.0: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.1 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + on-finished: 2.4.1 + qs: 6.14.0 + raw-body: 3.0.0 + type-is: 2.0.1 + transitivePeerDependencies: + - supports-color + bonjour-service@1.2.1: dependencies: fast-deep-equal: 3.1.3 @@ -8155,12 +8278,18 @@ snapshots: dependencies: safe-buffer: 5.2.1 + content-disposition@1.0.0: + dependencies: + safe-buffer: 5.2.1 + content-type@1.0.5: {} convert-source-map@2.0.0: {} cookie-signature@1.0.6: {} + cookie-signature@1.2.2: {} + cookie@0.7.1: {} copy-anything@2.0.6: @@ -8692,6 +8821,38 @@ snapshots: transitivePeerDependencies: - supports-color + express@5.1.0: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.0 + content-disposition: 1.0.0 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.2.2 + debug: 4.4.1 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.0 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: 2.0.0 + mime-types: 3.0.1 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.0 + serve-static: 2.2.0 + statuses: 2.0.1 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + fast-deep-equal@3.1.3: {} fast-glob@3.3.2: @@ -8754,6 +8915,17 @@ snapshots: transitivePeerDependencies: - supports-color + finalhandler@2.1.0: + dependencies: + debug: 4.4.1 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + find-cache-dir@4.0.0: dependencies: common-path-prefix: 3.0.0 @@ -8824,6 +8996,8 @@ snapshots: fresh@0.5.2: {} + fresh@2.0.0: {} + front-matter@4.0.2: dependencies: js-yaml: 3.14.1 @@ -9116,6 +9290,8 @@ snapshots: is-plain-obj@3.0.0: {} + is-promise@4.0.0: {} + is-stream@2.0.1: {} is-unicode-supported@0.1.0: {} @@ -9727,6 +9903,8 @@ snapshots: media-typer@0.3.0: {} + media-typer@1.1.0: {} + memfs@3.5.3: dependencies: fs-monkey: 1.0.6 @@ -9740,6 +9918,8 @@ snapshots: merge-descriptors@1.0.3: {} + merge-descriptors@2.0.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -9758,10 +9938,16 @@ snapshots: mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + mime@1.6.0: {} mimic-fn@2.1.0: {} @@ -9820,6 +10006,8 @@ snapshots: negotiator@0.6.3: {} + negotiator@1.0.0: {} + neo-async@2.6.2: {} no-case@3.0.4: @@ -10059,6 +10247,8 @@ snapshots: path-to-regexp@0.1.12: {} + path-to-regexp@8.2.0: {} + path-type@4.0.0: {} picocolors@1.0.1: {} @@ -10345,6 +10535,13 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + raw-body@3.0.0: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + unpipe: 1.0.0 + react-is@18.3.1: {} react-refresh@0.10.0: {} @@ -10446,6 +10643,16 @@ snapshots: dependencies: glob: 7.2.3 + router@2.2.0: + dependencies: + debug: 4.4.1 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.2.0 + transitivePeerDependencies: + - supports-color + run-applescript@7.0.0: {} run-parallel@1.2.0: @@ -10617,6 +10824,22 @@ snapshots: transitivePeerDependencies: - supports-color + send@1.2.0: + dependencies: + debug: 4.4.1 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.0 + mime-types: 3.0.1 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -10642,6 +10865,15 @@ snapshots: transitivePeerDependencies: - supports-color + serve-static@2.2.0: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.0 + transitivePeerDependencies: + - supports-color + setprototypeof@1.1.0: {} setprototypeof@1.2.0: {} @@ -11061,6 +11293,12 @@ snapshots: media-typer: 0.3.0 mime-types: 2.1.35 + type-is@2.0.1: + dependencies: + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.1 + typed-assert@1.0.9: {} typescript@5.8.3: {} From bcda19ab8b74ec338a77cce8d58200c1d27362dd Mon Sep 17 00:00:00 2001 From: bzp2010 Date: Mon, 28 Jul 2025 18:31:04 +0800 Subject: [PATCH 2/8] feat: refresh server module --- apps/cli/src/command/ingress-server.command.ts | 7 +++++-- apps/cli/src/server/index.ts | 15 +++++++++++---- apps/cli/src/server/schema.ts | 6 +----- apps/cli/src/server/sync.ts | 16 ++++++++-------- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/apps/cli/src/command/ingress-server.command.ts b/apps/cli/src/command/ingress-server.command.ts index 76e30065..1e63bb9d 100644 --- a/apps/cli/src/command/ingress-server.command.ts +++ b/apps/cli/src/command/ingress-server.command.ts @@ -1,6 +1,9 @@ import { ADCServer } from '../server'; import { BaseCommand } from './helper'; -export const IngressServerCommand = new BaseCommand('server').handle(() => - new ADCServer().start(), +export const IngressServerCommand = new BaseCommand('server').handle( + async () => { + await new ADCServer().start(); + console.log('ADC server is running on: http://127.0.0.1:3000'); + }, ); diff --git a/apps/cli/src/server/index.ts b/apps/cli/src/server/index.ts index f9bf54b4..c9f1d2d1 100644 --- a/apps/cli/src/server/index.ts +++ b/apps/cli/src/server/index.ts @@ -1,10 +1,12 @@ import express from 'express'; import type { Express } from 'express'; +import type { Server } from 'node:http'; import { syncHandler } from './sync'; export class ADCServer { - private express: Express; + private readonly express: Express; + private server?: Server; constructor() { this.express = express(); @@ -13,8 +15,13 @@ export class ADCServer { this.express.put('/sync', syncHandler); } - public start() { - console.log('ADC server is running on: http://127.0.0.1:3000'); - this.express.listen(3000, '127.0.0.1'); + public async start() { + return new Promise((resolve) => { + this.server = this.express.listen(3000, '127.0.0.1', () => resolve()); + }); + } + + public TEST_ONLY_getExpress() { + return this.express; } } diff --git a/apps/cli/src/server/schema.ts b/apps/cli/src/server/schema.ts index 396265e4..fd6f5820 100644 --- a/apps/cli/src/server/schema.ts +++ b/apps/cli/src/server/schema.ts @@ -2,11 +2,7 @@ import { z } from 'zod'; const SyncTask = z.strictObject({ opts: z.looseObject({ - backend: z.union([ - z.literal('apisix'), - z.literal('api7ee'), - z.literal('apisix-standalone'), - ]), + backend: z.string().min(1), server: z.url().min(1), token: z.string().min(1), lint: z.boolean().optional().default(true), diff --git a/apps/cli/src/server/sync.ts b/apps/cli/src/server/sync.ts index 196b7b6d..f7f0743b 100644 --- a/apps/cli/src/server/sync.ts +++ b/apps/cli/src/server/sync.ts @@ -32,13 +32,13 @@ export const syncHandler: RequestHandler< }); } - // load remote configuration and diff with local - const backend = loadBackend(task.opts.backend, { ...task.opts }); - const remote = await lastValueFrom(backend.dump()); - const diff = DifferV3.diff(local, remote, await backend.defaultValue()); - - // sync the diff try { + // load remote configuration and diff with local + const backend = loadBackend(task.opts.backend, { ...task.opts }); + const remote = await lastValueFrom(backend.dump()); + const diff = DifferV3.diff(local, remote, await backend.defaultValue()); + + // sync the diff const results = await lastValueFrom( backend .sync(diff, { @@ -86,9 +86,9 @@ export const syncHandler: RequestHandler< })), ], }; - res.status(200).json(output); + res.status(202).json(output); } catch (err) { - res.status(500).send({ + res.status(500).json({ message: toString(err), }); } From 6bc44d254bf9bd241598702b7fb160469a6383ea Mon Sep 17 00:00:00 2001 From: bzp2010 Date: Mon, 28 Jul 2025 18:33:10 +0800 Subject: [PATCH 3/8] test: add server mode e2e --- apps/cli/e2e/server/basic.e2e-spec.ts | 80 +++++++++++++ apps/cli/e2e/support/global-setup.ts | 5 + apps/cli/e2e/support/global-teardown.ts | 3 + apps/cli/e2e/support/utils.ts | 67 +++++++++++ apps/cli/jest.config.e2e.ts | 19 +++ apps/cli/package.json | 4 +- apps/cli/project.json | 11 ++ apps/cli/tsconfig.spec.json | 13 +- pnpm-lock.yaml | 152 ++++++++++++++++++++++++ 9 files changed, 350 insertions(+), 4 deletions(-) create mode 100644 apps/cli/e2e/server/basic.e2e-spec.ts create mode 100644 apps/cli/e2e/support/global-setup.ts create mode 100644 apps/cli/e2e/support/global-teardown.ts create mode 100644 apps/cli/e2e/support/utils.ts create mode 100644 apps/cli/jest.config.e2e.ts diff --git a/apps/cli/e2e/server/basic.e2e-spec.ts b/apps/cli/e2e/server/basic.e2e-spec.ts new file mode 100644 index 00000000..d8ac375b --- /dev/null +++ b/apps/cli/e2e/server/basic.e2e-spec.ts @@ -0,0 +1,80 @@ +import * as ADCSDK from '@api7/adc-sdk'; +import { lastValueFrom } from 'rxjs'; +import request from 'supertest'; + +import { ADCServer } from '../../src/server'; +import { jestMockBackend } from '../support/utils'; + +describe('Server - Basic', () => { + let mockedBackend: ADCSDK.Backend; + let server: ADCServer; + + beforeAll(async () => { + mockedBackend = jestMockBackend(); + server = new ADCServer(); + }); + + it('test mocked load backend', async () => { + const { status, body } = await request(server.TEST_ONLY_getExpress()) + .put('/sync') + .send({ + task: { + opts: { + backend: 'mock', + server: 'http://1.1.1.1:3000', + token: 'mock', + }, + config: {}, + }, + }); + + expect(status).toBe(202); + expect(body.status).toBe('success'); + await expect(lastValueFrom(mockedBackend.dump())).resolves.toEqual({}); + }); + + it('test real apisix backend (expect connect refused)', async () => { + const { status, body } = await request(server.TEST_ONLY_getExpress()) + .put('/sync') + .send({ + task: { + opts: { + backend: 'apisix', + server: 'http://127.0.0.1:50000', + token: 'mock', + }, + config: {}, + }, + }); + + expect(status).toBe(500); + expect(body.message).toBe('Error: connect ECONNREFUSED 127.0.0.1:50000'); + }); + + it('test sync', async () => { + const config = { + consumers: [ + { + username: 'test-consumer', + plugins: { 'limit-count': { count: 10, time_window: 60 } }, + }, + ], + } as ADCSDK.Configuration; + const { status, body } = await request(server.TEST_ONLY_getExpress()) + .put('/sync') + .send({ + task: { + opts: { + backend: 'mock', + server: 'http://1.1.1.1:3000', + token: 'mock', + }, + config: config, + }, + }); + + expect(status).toBe(202); + expect(body.status).toBe('success'); + await expect(lastValueFrom(mockedBackend.dump())).resolves.toEqual(config); + }); +}); diff --git a/apps/cli/e2e/support/global-setup.ts b/apps/cli/e2e/support/global-setup.ts new file mode 100644 index 00000000..db363033 --- /dev/null +++ b/apps/cli/e2e/support/global-setup.ts @@ -0,0 +1,5 @@ +import { configurePluralize } from '../../src/command/utils'; + +export default () => { + configurePluralize(); +}; diff --git a/apps/cli/e2e/support/global-teardown.ts b/apps/cli/e2e/support/global-teardown.ts new file mode 100644 index 00000000..bab0a073 --- /dev/null +++ b/apps/cli/e2e/support/global-teardown.ts @@ -0,0 +1,3 @@ +export default () => { + /* */ +}; diff --git a/apps/cli/e2e/support/utils.ts b/apps/cli/e2e/support/utils.ts new file mode 100644 index 00000000..7a66c8a0 --- /dev/null +++ b/apps/cli/e2e/support/utils.ts @@ -0,0 +1,67 @@ +import * as ADCSDK from '@api7/adc-sdk'; +import pluralize from 'pluralize'; +import { Subscription, from, of, switchMap, tap, toArray } from 'rxjs'; +import { SemVer } from 'semver'; + +import * as commandUtils from '../../src/command/utils'; + +export const mockBackend = (): ADCSDK.Backend => { + class MockBackend implements ADCSDK.Backend { + private readonly cache: { config?: ADCSDK.Configuration } = {}; + + public metadata() { + return { logScope: ['mock'] }; + } + public ping() { + return Promise.resolve(); + } + public version() { + return Promise.resolve(new SemVer('0.0.0-mock')); + } + public defaultValue() { + return Promise.resolve({}); + } + public dump() { + return of(this.cache.config); + } + public sync(events: Array) { + const config: ADCSDK.Configuration = {}; + const resourceTypeToPluralKey = (type: ADCSDK.ResourceType) => + pluralize.plural(type); + return from(events).pipe( + tap((event) => { + if (event.type === ADCSDK.EventType.DELETE) return; + const key = resourceTypeToPluralKey(event.resourceType); + if (!config[key]) config[key] = []; + config[key].push(event.newValue); + }), + toArray(), + switchMap( + () => ( + (this.cache.config = config), + of({ + success: true, + event: {} as ADCSDK.Event, // keep empty + } as ADCSDK.BackendSyncResult) + ), + ), + ); + } + on: () => Subscription; + supportValidate?: () => Promise; + supportStreamRoute?: () => Promise; + } + return new MockBackend(); +}; + +export const jestMockBackend = (mockedBackend?: ADCSDK.Backend) => { + if (!mockedBackend) mockedBackend = mockBackend(); + const originalLoadBackend = commandUtils.loadBackend; + jest + .spyOn(commandUtils, 'loadBackend') + .mockImplementation((backend, opts) => { + if (backend === 'mock') return mockedBackend; + return originalLoadBackend(backend, opts); + }); + return mockedBackend; +}; diff --git a/apps/cli/jest.config.e2e.ts b/apps/cli/jest.config.e2e.ts new file mode 100644 index 00000000..62fce50d --- /dev/null +++ b/apps/cli/jest.config.e2e.ts @@ -0,0 +1,19 @@ +/* eslint-disable */ +export default { + displayName: 'cli', + preset: '../../jest.preset.js', + globalSetup: '/e2e/support/global-setup.ts', + globalTeardown: '/e2e/support/global-teardown.ts', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': [ + 'ts-jest', + { + tsconfig: '/tsconfig.spec.json', + }, + ], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/libs/backend-api7/e2e', + testMatch: ['**/?(*.)+(e2e-spec).[jt]s?(x)'], +}; diff --git a/apps/cli/package.json b/apps/cli/package.json index f6faea61..97c9bf10 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -6,7 +6,9 @@ "@api7/adc-backend-apisix-standalone": "workspace:*", "@api7/adc-converter-openapi": "workspace:*", "@api7/adc-sdk": "workspace:*", - "@types/express": "^5.0.3" + "@types/express": "^5.0.3", + "@types/supertest": "^6.0.3", + "supertest": "^7.1.4" }, "dependencies": { "body-parser": "^2.2.0", diff --git a/apps/cli/project.json b/apps/cli/project.json index 6527e4c7..896af655 100644 --- a/apps/cli/project.json +++ b/apps/cli/project.json @@ -57,6 +57,17 @@ "jestConfig": "apps/cli/jest.config.ts" } }, + "e2e": { + "executor": "@nx/jest:jest", + "outputs": [ + "{workspaceRoot}/coverage/{e2eProjectRoot}" + ], + "options": { + "jestConfig": "apps/cli/jest.config.e2e.ts", + "passWithNoTests": true, + "runInBand": true + } + }, "export-schema": { "executor": "nx:run-commands", "options": { diff --git a/apps/cli/tsconfig.spec.json b/apps/cli/tsconfig.spec.json index 9b2a121d..8572be44 100644 --- a/apps/cli/tsconfig.spec.json +++ b/apps/cli/tsconfig.spec.json @@ -2,13 +2,20 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] + "module": "nodenext", + "types": [ + "jest", + "node" + ] }, "include": [ "jest.config.ts", + "src/**/*.ts", "src/**/*.test.ts", "src/**/*.spec.ts", - "src/**/*.d.ts" + "src/**/*.d.ts", + "e2e/support/**/*.ts", + "e2e/**/*.e2e-spec.ts", + "src/linter/**/*.ts" ] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 993d823d..9b1edd06 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -232,6 +232,12 @@ importers: '@types/express': specifier: ^5.0.3 version: 5.0.3 + '@types/supertest': + specifier: ^6.0.3 + version: 6.0.3 + supertest: + specifier: ^7.1.4 + version: 7.1.4 libs/backend-api7: devDependencies: @@ -1267,6 +1273,10 @@ packages: '@napi-rs/wasm-runtime@0.2.4': resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1380,6 +1390,9 @@ packages: '@nx/workspace@21.2.4': resolution: {integrity: sha512-NX/dADO0JqcS0FAIJT9E9xpvAmP1vriyP4lBaYQxxiAeN4Tg0CMg4KxYIkiq7cAyvj/2Wjchrt8kbHyMmEJcUA==} + '@paralleldrive/cuid2@2.2.2': + resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} + '@parcel/watcher-android-arm64@2.5.1': resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} engines: {node: '>= 10.0.0'} @@ -1746,6 +1759,9 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/cookiejar@2.1.5': + resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} + '@types/deep-diff@1.0.5': resolution: {integrity: sha512-PQyNSy1YMZU1hgZA5tTYfHPpUAo9Dorn1PZho2/budQLfqLu3JIP37JAavnwYpR1S2yFZTXa3hxaE4ifGW5jaA==} @@ -1800,6 +1816,9 @@ packages: '@types/lodash@4.17.4': resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==} + '@types/methods@1.1.4': + resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} + '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} @@ -1845,6 +1864,12 @@ packages: '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/superagent@8.1.9': + resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} + + '@types/supertest@6.0.3': + resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==} + '@types/ws@8.5.10': resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} @@ -2163,6 +2188,9 @@ packages: resolution: {integrity: sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==} engines: {node: '>=12'} + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} @@ -2471,6 +2499,9 @@ packages: common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + compressible@2.0.18: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} @@ -2515,6 +2546,9 @@ packages: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} + cookiejar@2.1.4: + resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} + copy-anything@2.0.6: resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} @@ -2757,6 +2791,9 @@ packages: engines: {node: '>= 4.0.0'} hasBin: true + dezalgo@1.0.4: + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2887,6 +2924,10 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + esbuild@0.19.12: resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} engines: {node: '>=12'} @@ -3019,6 +3060,9 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -3123,6 +3167,14 @@ packages: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + engines: {node: '>= 6'} + + formidable@3.5.4: + resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} + engines: {node: '>=14.0.0'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -3268,6 +3320,10 @@ packages: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -3944,6 +4000,11 @@ packages: engines: {node: '>=4'} hasBin: true + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -5093,6 +5154,14 @@ packages: engines: {node: '>=16'} hasBin: true + superagent@10.2.3: + resolution: {integrity: sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==} + engines: {node: '>=14.18.0'} + + supertest@7.1.4: + resolution: {integrity: sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==} + engines: {node: '>=14.18.0'} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -6747,6 +6816,8 @@ snapshots: '@emnapi/runtime': 1.3.1 '@tybys/wasm-util': 0.9.0 + '@noble/hashes@1.8.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -7040,6 +7111,10 @@ snapshots: - '@swc/core' - debug + '@paralleldrive/cuid2@2.2.2': + dependencies: + '@noble/hashes': 1.8.0 + '@parcel/watcher-android-arm64@2.5.1': optional: true @@ -7403,6 +7478,8 @@ snapshots: dependencies: '@types/node': 22.16.5 + '@types/cookiejar@2.1.5': {} + '@types/deep-diff@1.0.5': {} '@types/eslint-scope@3.7.7': @@ -7475,6 +7552,8 @@ snapshots: '@types/lodash@4.17.4': {} + '@types/methods@1.1.4': {} + '@types/mime@1.3.5': {} '@types/node-forge@1.3.11': @@ -7522,6 +7601,18 @@ snapshots: '@types/stack-utils@2.0.3': {} + '@types/superagent@8.1.9': + dependencies: + '@types/cookiejar': 2.1.5 + '@types/methods': 1.1.4 + '@types/node': 22.16.5 + form-data: 4.0.4 + + '@types/supertest@6.0.3': + dependencies: + '@types/methods': 1.1.4 + '@types/superagent': 8.1.9 + '@types/ws@8.5.10': dependencies: '@types/node': 22.16.5 @@ -7889,6 +7980,8 @@ snapshots: array-union@3.0.1: {} + asap@2.0.6: {} + async@3.2.5: {} asynckit@0.4.0: {} @@ -8252,6 +8345,8 @@ snapshots: common-path-prefix@3.0.0: {} + component-emitter@1.3.1: {} + compressible@2.0.18: dependencies: mime-db: 1.52.0 @@ -8292,6 +8387,8 @@ snapshots: cookie@0.7.1: {} + cookiejar@2.1.4: {} + copy-anything@2.0.6: dependencies: is-what: 3.14.1 @@ -8520,6 +8617,11 @@ snapshots: transitivePeerDependencies: - supports-color + dezalgo@1.0.4: + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + diff-sequences@29.6.3: {} diff@4.0.2: {} @@ -8635,6 +8737,13 @@ snapshots: dependencies: es-errors: 1.3.0 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + esbuild@0.19.12: optionalDependencies: '@esbuild/aix-ppc64': 0.19.12 @@ -8867,6 +8976,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-safe-stringify@2.1.1: {} + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -8990,6 +9101,20 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + form-data@4.0.4: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formidable@3.5.4: + dependencies: + '@paralleldrive/cuid2': 2.2.2 + dezalgo: 1.0.4 + once: 1.4.0 + forwarded@0.2.0: {} fraction.js@4.3.7: {} @@ -9130,6 +9255,10 @@ snapshots: has-symbols@1.1.0: {} + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -9950,6 +10079,8 @@ snapshots: mime@1.6.0: {} + mime@2.6.0: {} + mimic-fn@2.1.0: {} mini-css-extract-plugin@2.4.7(webpack@5.99.9(@swc/core@1.5.7(@swc/helpers@0.5.12))(esbuild@0.19.12)): @@ -11091,6 +11222,27 @@ snapshots: transitivePeerDependencies: - supports-color + superagent@10.2.3: + dependencies: + component-emitter: 1.3.1 + cookiejar: 2.1.4 + debug: 4.4.1 + fast-safe-stringify: 2.1.1 + form-data: 4.0.4 + formidable: 3.5.4 + methods: 1.1.2 + mime: 2.6.0 + qs: 6.14.0 + transitivePeerDependencies: + - supports-color + + supertest@7.1.4: + dependencies: + methods: 1.1.2 + superagent: 10.2.3 + transitivePeerDependencies: + - supports-color + supports-color@5.5.0: dependencies: has-flag: 3.0.0 From 2dba1b9b1beaeb80b7ec7bd8ec3ca2e651735b4a Mon Sep 17 00:00:00 2001 From: bzp2010 Date: Mon, 28 Jul 2025 18:34:23 +0800 Subject: [PATCH 4/8] chore: remove separate e2e project --- apps/cli-e2e/.eslintrc.json | 18 -------------- apps/cli-e2e/README.md | 5 ---- apps/cli-e2e/jest.config.ts | 18 -------------- apps/cli-e2e/project.json | 26 --------------------- apps/cli-e2e/src/support/global-setup.ts | 3 --- apps/cli-e2e/src/support/global-teardown.ts | 3 --- apps/cli-e2e/tsconfig.json | 13 ----------- apps/cli-e2e/tsconfig.spec.json | 9 ------- 8 files changed, 95 deletions(-) delete mode 100644 apps/cli-e2e/.eslintrc.json delete mode 100644 apps/cli-e2e/README.md delete mode 100644 apps/cli-e2e/jest.config.ts delete mode 100644 apps/cli-e2e/project.json delete mode 100644 apps/cli-e2e/src/support/global-setup.ts delete mode 100644 apps/cli-e2e/src/support/global-teardown.ts delete mode 100644 apps/cli-e2e/tsconfig.json delete mode 100644 apps/cli-e2e/tsconfig.spec.json diff --git a/apps/cli-e2e/.eslintrc.json b/apps/cli-e2e/.eslintrc.json deleted file mode 100644 index 9d9c0db5..00000000 --- a/apps/cli-e2e/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - } - ] -} diff --git a/apps/cli-e2e/README.md b/apps/cli-e2e/README.md deleted file mode 100644 index b66ae09c..00000000 --- a/apps/cli-e2e/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# E2E Test for CLI - -**Currently we don't do E2E testing on the cli, but rather unit testing and E2E testing in each module separately.** - -**So this package is used as a placeholder in the project.** diff --git a/apps/cli-e2e/jest.config.ts b/apps/cli-e2e/jest.config.ts deleted file mode 100644 index c7474ce8..00000000 --- a/apps/cli-e2e/jest.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'cli-e2e', - preset: '../../jest.preset.js', - globalSetup: '/src/support/global-setup.ts', - globalTeardown: '/src/support/global-teardown.ts', - testEnvironment: 'node', - transform: { - '^.+\\.[tj]s$': [ - 'ts-jest', - { - tsconfig: '/tsconfig.spec.json', - }, - ], - }, - moduleFileExtensions: ['ts', 'js', 'html'], - coverageDirectory: '../../coverage/cli-e2e', -}; diff --git a/apps/cli-e2e/project.json b/apps/cli-e2e/project.json deleted file mode 100644 index f99b2058..00000000 --- a/apps/cli-e2e/project.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "cli-e2e", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "implicitDependencies": [ - "cli" - ], - "projectType": "application", - "targets": { - "e2e": { - "executor": "@nx/jest:jest", - "outputs": [ - "{workspaceRoot}/coverage/{e2eProjectRoot}" - ], - "options": { - "jestConfig": "apps/cli-e2e/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": [ - "{options.outputFile}" - ] - } - }, -} \ No newline at end of file diff --git a/apps/cli-e2e/src/support/global-setup.ts b/apps/cli-e2e/src/support/global-setup.ts deleted file mode 100644 index bab0a073..00000000 --- a/apps/cli-e2e/src/support/global-setup.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default () => { - /* */ -}; diff --git a/apps/cli-e2e/src/support/global-teardown.ts b/apps/cli-e2e/src/support/global-teardown.ts deleted file mode 100644 index bab0a073..00000000 --- a/apps/cli-e2e/src/support/global-teardown.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default () => { - /* */ -}; diff --git a/apps/cli-e2e/tsconfig.json b/apps/cli-e2e/tsconfig.json deleted file mode 100644 index ed633e1d..00000000 --- a/apps/cli-e2e/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "esModuleInterop": true - } -} diff --git a/apps/cli-e2e/tsconfig.spec.json b/apps/cli-e2e/tsconfig.spec.json deleted file mode 100644 index d7f9cf20..00000000 --- a/apps/cli-e2e/tsconfig.spec.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": ["jest.config.ts", "src/**/*.ts"] -} From 7dd94eb6dd017ae600a204755b197a3d27de324d Mon Sep 17 00:00:00 2001 From: bzp2010 Date: Mon, 28 Jul 2025 18:36:22 +0800 Subject: [PATCH 5/8] test: add cli e2e workflow --- .github/workflows/e2e.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 0a60723d..026d655b 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -10,6 +10,24 @@ on: - main types: [opened, synchronize, reopened, labeled] jobs: + cli: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # Build and test ADC CLI + - uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + - uses: pnpm/action-setup@v2 + with: + version: latest + - name: Install dependencies + run: pnpm install + + # Run E2E tests + - name: Run E2E tests + run: npx nx run cli:e2e apisix: runs-on: ubuntu-latest strategy: From dc354c516695844fcc72147dda8acceb840c545a Mon Sep 17 00:00:00 2001 From: bzp2010 Date: Mon, 28 Jul 2025 18:52:21 +0800 Subject: [PATCH 6/8] feat: more bigger json input size limitation --- apps/cli/src/server/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cli/src/server/index.ts b/apps/cli/src/server/index.ts index c9f1d2d1..54e93702 100644 --- a/apps/cli/src/server/index.ts +++ b/apps/cli/src/server/index.ts @@ -11,7 +11,7 @@ export class ADCServer { constructor() { this.express = express(); this.express.disable('x-powered-by'); - this.express.use(express.json({ limit: '10mb' })); + this.express.use(express.json({ limit: '100mb' })); this.express.put('/sync', syncHandler); } From e35f2a5b91d9f2c8414c15bb6d9275942fbb98f1 Mon Sep 17 00:00:00 2001 From: Zeping Bai Date: Tue, 29 Jul 2025 11:23:10 +0800 Subject: [PATCH 7/8] apply suggestion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 琚致远 / Zhiyuan Ju --- apps/cli/src/command/helper.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/cli/src/command/helper.ts b/apps/cli/src/command/helper.ts index 9884ca9b..4c320d98 100644 --- a/apps/cli/src/command/helper.ts +++ b/apps/cli/src/command/helper.ts @@ -73,9 +73,7 @@ export class BackendCommand< public handle(cb: (opts: OPTS, command: Command) => void | Promise) { const opts = this.opts(); - if ( - (has(opts, 'tlsClientCertFile') && !has(opts, 'tlsClientKeyFile')) || - (has(opts, 'tlsClientKeyFile') && !has(opts, 'tlsClientCertFile')) + if (!has(opts, 'tlsClientCertFile') || !has(opts, 'tlsClientKeyFile')) ) { console.log( chalk.red( From bd99f8885d229093aff072cf46528f67aa9257f0 Mon Sep 17 00:00:00 2001 From: bzp2010 Date: Tue, 29 Jul 2025 11:32:28 +0800 Subject: [PATCH 8/8] fix --- apps/cli/src/command/helper.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/cli/src/command/helper.ts b/apps/cli/src/command/helper.ts index 4c320d98..800e5415 100644 --- a/apps/cli/src/command/helper.ts +++ b/apps/cli/src/command/helper.ts @@ -73,8 +73,7 @@ export class BackendCommand< public handle(cb: (opts: OPTS, command: Command) => void | Promise) { const opts = this.opts(); - if (!has(opts, 'tlsClientCertFile') || !has(opts, 'tlsClientKeyFile')) - ) { + if (!has(opts, 'tlsClientCertFile') || !has(opts, 'tlsClientKeyFile')) { console.log( chalk.red( 'TLS client certificate and key must be provided at the same time',