diff --git a/app/gateway-api/package.json b/app/gateway-api/package.json index edf831d..07a2791 100644 --- a/app/gateway-api/package.json +++ b/app/gateway-api/package.json @@ -23,6 +23,7 @@ "@trpc/server": "^11.4.4", "date-fns": "^4.1.0", "fastify": "^5.3.3", + "pm2": "^5.4.3", "redis": "^5.10.0", "zod": "^4.2.1" } diff --git a/app/gateway-api/src/adminRouter.ts b/app/gateway-api/src/adminRouter.ts new file mode 100644 index 0000000..476c120 --- /dev/null +++ b/app/gateway-api/src/adminRouter.ts @@ -0,0 +1,130 @@ +import { TRPCError } from '@trpc/server'; +import { z } from 'zod'; + +import { procedure, router } from './trpc.js'; +import { + GATEWAY_BUILD_STATUSES, + GATEWAY_PROFILE_STATUSES, +} from './orchestrator/profileRepository.js'; + +const zProfileStatus = z.enum(GATEWAY_PROFILE_STATUSES); +const zBuildStatus = z.enum(GATEWAY_BUILD_STATUSES); + +const adminProcedure = procedure.use(({ ctx, next }) => { + if (!ctx.adminToken) { + throw new TRPCError({ + code: 'FORBIDDEN', + message: 'Admin token is not configured.', + }); + } + const provided = + ctx.requestHeaders['x-admin-token'] ?? + ctx.requestHeaders['authorization'] ?? + ''; + const token = + Array.isArray(provided) ? provided[0] ?? '' : (provided as string); + if (!token || token !== ctx.adminToken) { + throw new TRPCError({ + code: 'UNAUTHORIZED', + message: 'Invalid admin token.', + }); + } + return next(); +}); + +export const adminRouter = router({ + profiles: router({ + list: adminProcedure.query(async ({ ctx }) => { + const profiles = await ctx.profiles.listProfiles(); + const runtimeStates = await ctx.orchestrator.listRuntimeStates( + profiles.map((profile) => profile.profileName) + ); + const runtimeMap = new Map( + runtimeStates.map((state) => [state.profileName, state]) + ); + return profiles.map((profile) => ({ + ...profile, + runtime: runtimeMap.get(profile.profileName) ?? { + profileName: profile.profileName, + apiRunning: false, + daemonRunning: false, + }, + })); + }), + upsert: adminProcedure + .input( + z.object({ + profile: z.string().min(1).max(32), + scenario: z.string().min(1).max(64), + apiPort: z.number().int().min(1).max(65535), + status: zProfileStatus.optional(), + scheduledStartAt: z.string().datetime().optional(), + }) + ) + .mutation(async ({ ctx, input }) => { + const status = input.status ?? 'STOPPED'; + return ctx.profiles.upsertProfile({ + profile: input.profile, + scenario: input.scenario, + apiPort: input.apiPort, + status, + scheduledStartAt: input.scheduledStartAt, + }); + }), + setStatus: adminProcedure + .input( + z.object({ + profileName: z.string().min(1), + status: zProfileStatus, + scheduledStartAt: z.string().datetime().optional(), + }) + ) + .mutation(async ({ ctx, input }) => { + if (input.status === 'RESERVED' && !input.scheduledStartAt) { + throw new TRPCError({ + code: 'BAD_REQUEST', + message: 'scheduledStartAt is required for RESERVED status.', + }); + } + const result = await ctx.profiles.updateStatus( + input.profileName, + input.status, + input.status === 'RESERVED' ? input.scheduledStartAt : null + ); + await ctx.orchestrator.reconcileNow(); + return result; + }), + requestBuild: adminProcedure + .input( + z.object({ + profileName: z.string().min(1), + }) + ) + .mutation(async ({ ctx, input }) => { + const requestedAt = new Date().toISOString(); + const result = await ctx.profiles.updateBuildStatus( + input.profileName, + 'QUEUED', + { + requestedAt, + error: null, + } + ); + return result; + }), + setBuildStatus: adminProcedure + .input( + z.object({ + profileName: z.string().min(1), + status: zBuildStatus, + }) + ) + .mutation(async ({ ctx, input }) => + ctx.profiles.updateBuildStatus(input.profileName, input.status) + ), + reconcileNow: adminProcedure.mutation(async ({ ctx }) => { + await ctx.orchestrator.reconcileNow(); + return { ok: true }; + }), + }), +}); diff --git a/app/gateway-api/src/config.ts b/app/gateway-api/src/config.ts index 12d600f..95aeac5 100644 --- a/app/gateway-api/src/config.ts +++ b/app/gateway-api/src/config.ts @@ -12,6 +12,12 @@ export interface GatewayApiConfig { kakaoAdminKey?: string; kakaoRedirectUri: string; publicBaseUrl: string; + adminToken?: string; + orchestratorEnabled: boolean; + orchestratorReconcileIntervalMs: number; + orchestratorScheduleIntervalMs: number; + orchestratorBuildIntervalMs: number; + workspaceRootHint: string; } const parseNumber = (value: string | undefined, fallback: number, label: string): number => { @@ -25,6 +31,20 @@ const parseNumber = (value: string | undefined, fallback: number, label: string) return parsed; }; +const parseBoolean = (value: string | undefined, fallback: boolean): boolean => { + if (!value) { + return fallback; + } + const normalized = value.trim().toLowerCase(); + if (['1', 'true', 'yes', 'y', 'on'].includes(normalized)) { + return true; + } + if (['0', 'false', 'no', 'n', 'off'].includes(normalized)) { + return false; + } + return fallback; +}; + export const resolveGatewayApiConfigFromEnv = ( env: NodeJS.ProcessEnv = process.env ): GatewayApiConfig => { @@ -61,5 +81,23 @@ export const resolveGatewayApiConfigFromEnv = ( kakaoAdminKey: env.KAKAO_ADMIN_KEY, kakaoRedirectUri, publicBaseUrl, + adminToken: env.GATEWAY_ADMIN_TOKEN, + orchestratorEnabled: parseBoolean(env.GATEWAY_ORCHESTRATOR_ENABLED, true), + orchestratorReconcileIntervalMs: parseNumber( + env.GATEWAY_ORCHESTRATOR_RECONCILE_MS, + 15000, + 'GATEWAY_ORCHESTRATOR_RECONCILE_MS' + ), + orchestratorScheduleIntervalMs: parseNumber( + env.GATEWAY_ORCHESTRATOR_SCHEDULE_MS, + 5000, + 'GATEWAY_ORCHESTRATOR_SCHEDULE_MS' + ), + orchestratorBuildIntervalMs: parseNumber( + env.GATEWAY_ORCHESTRATOR_BUILD_MS, + 10000, + 'GATEWAY_ORCHESTRATOR_BUILD_MS' + ), + workspaceRootHint: env.GATEWAY_WORKSPACE_ROOT ?? process.cwd(), }; }; diff --git a/app/gateway-api/src/context.ts b/app/gateway-api/src/context.ts index fc35edc..a1e7bb2 100644 --- a/app/gateway-api/src/context.ts +++ b/app/gateway-api/src/context.ts @@ -3,6 +3,8 @@ import type { GatewaySessionService } from './auth/sessionService.js'; import type { UserRepository } from './auth/userRepository.js'; import type { KakaoOAuthClient } from './auth/kakaoClient.js'; import type { OAuthSessionStore } from './auth/oauthSessionStore.js'; +import type { GatewayProfileRepository } from './orchestrator/profileRepository.js'; +import type { GatewayOrchestratorHandle } from './orchestrator/gatewayOrchestrator.js'; export interface GatewayApiContext { users: UserRepository; @@ -13,6 +15,10 @@ export interface GatewayApiContext { kakaoClient: KakaoOAuthClient; oauthSessions: OAuthSessionStore; publicBaseUrl: string; + profiles: GatewayProfileRepository; + orchestrator: GatewayOrchestratorHandle; + adminToken?: string; + requestHeaders: Record; } export const createGatewayApiContext = (options: { @@ -24,6 +30,10 @@ export const createGatewayApiContext = (options: { kakaoClient: KakaoOAuthClient; oauthSessions: OAuthSessionStore; publicBaseUrl: string; + profiles: GatewayProfileRepository; + orchestrator: GatewayOrchestratorHandle; + adminToken?: string; + requestHeaders?: Record; }): GatewayApiContext => ({ users: options.users, sessions: options.sessions, @@ -33,4 +43,8 @@ export const createGatewayApiContext = (options: { kakaoClient: options.kakaoClient, oauthSessions: options.oauthSessions, publicBaseUrl: options.publicBaseUrl, + profiles: options.profiles, + orchestrator: options.orchestrator, + adminToken: options.adminToken, + requestHeaders: options.requestHeaders ?? {}, }); diff --git a/app/gateway-api/src/orchestrator/buildRunner.ts b/app/gateway-api/src/orchestrator/buildRunner.ts new file mode 100644 index 0000000..be1fa97 --- /dev/null +++ b/app/gateway-api/src/orchestrator/buildRunner.ts @@ -0,0 +1,63 @@ +import { spawn } from 'node:child_process'; + +export interface BuildCommand { + command: string; + args: string[]; + cwd: string; + env?: Record; +} + +export interface BuildResult { + ok: boolean; + exitCode: number | null; + output: string; +} + +export interface BuildRunner { + run(commands: BuildCommand[]): Promise; +} + +const runCommand = (command: BuildCommand): Promise => + new Promise((resolve) => { + const child = spawn(command.command, command.args, { + cwd: command.cwd, + env: command.env, + stdio: ['ignore', 'pipe', 'pipe'], + }); + let output = ''; + child.stdout.on('data', (chunk) => { + output += chunk.toString(); + }); + child.stderr.on('data', (chunk) => { + output += chunk.toString(); + }); + child.on('close', (code) => { + resolve({ + ok: code === 0, + exitCode: code, + output, + }); + }); + }); + +export class PnpmBuildRunner implements BuildRunner { + async run(commands: BuildCommand[]): Promise { + let mergedOutput = ''; + for (const command of commands) { + const result = await runCommand(command); + mergedOutput += result.output; + if (!result.ok) { + return { + ok: false, + exitCode: result.exitCode, + output: mergedOutput, + }; + } + } + return { + ok: true, + exitCode: 0, + output: mergedOutput, + }; + } +} diff --git a/app/gateway-api/src/orchestrator/gatewayOrchestrator.ts b/app/gateway-api/src/orchestrator/gatewayOrchestrator.ts new file mode 100644 index 0000000..3ed19e4 --- /dev/null +++ b/app/gateway-api/src/orchestrator/gatewayOrchestrator.ts @@ -0,0 +1,328 @@ +import path from 'node:path'; + +import type { BuildRunner } from './buildRunner.js'; +import type { ProcessManager } from './processManager.js'; +import type { + GatewayProfileRecord, + GatewayProfileRepository, + GatewayProfileStatus, +} from './profileRepository.js'; + +export interface GatewayProcessConfig { + workspaceRoot: string; + redisKeyPrefix: string; + gameTokenSecret: string; + baseEnv?: Record; +} + +export interface GatewayOrchestratorOptions { + repository: GatewayProfileRepository; + processManager: ProcessManager; + buildRunner: BuildRunner; + processConfig: GatewayProcessConfig; + reconcileIntervalMs: number; + scheduleIntervalMs: number; + buildIntervalMs: number; + now?: () => Date; +} + +export interface ProfileRuntimeState { + apiRunning: boolean; + daemonRunning: boolean; +} + +export interface ProfileRuntimeSnapshot extends ProfileRuntimeState { + profileName: string; +} + +export interface GatewayOrchestratorHandle { + start(): void; + stop(): Promise; + reconcileNow(): Promise; + runScheduleNow(): Promise; + runBuildQueueNow(): Promise; + listRuntimeStates(profileNames: string[]): Promise; +} + +export const planProfileReconcile = ( + status: GatewayProfileStatus, + runtime: ProfileRuntimeState +): { shouldStart: boolean; shouldStop: boolean } => { + if (status === 'RUNNING') { + return { + shouldStart: !(runtime.apiRunning && runtime.daemonRunning), + shouldStop: false, + }; + } + return { + shouldStart: false, + shouldStop: runtime.apiRunning || runtime.daemonRunning, + }; +}; + +const buildProcessName = (profileName: string, role: 'api' | 'daemon'): string => + `sammo:${profileName}:${role === 'api' ? 'game-api' : 'turn-daemon'}`; + +const buildProcessDefinitions = ( + profile: GatewayProfileRecord, + config: GatewayProcessConfig +): { api: { name: string; script: string; cwd: string; env: Record }; + daemon: { name: string; script: string; cwd: string; env: Record } } => { + const baseEnv = { ...(config.baseEnv ?? {}) }; + const apiName = buildProcessName(profile.profileName, 'api'); + const daemonName = buildProcessName(profile.profileName, 'daemon'); + const apiCwd = path.join(config.workspaceRoot, 'app', 'game-api'); + const daemonCwd = path.join(config.workspaceRoot, 'app', 'game-engine'); + const apiScript = path.join(apiCwd, 'dist', 'index.js'); + const daemonScript = path.join(daemonCwd, 'dist', 'index.js'); + const apiEnv = { + ...baseEnv, + PROFILE: profile.profile, + SCENARIO: profile.scenario, + GAME_API_PORT: String(profile.apiPort), + GATEWAY_REDIS_PREFIX: config.redisKeyPrefix, + GAME_TOKEN_SECRET: config.gameTokenSecret, + }; + const daemonEnv = { + ...baseEnv, + TURN_PROFILE: profile.profile, + PROFILE: profile.profile, + SCENARIO: profile.scenario, + }; + return { + api: { + name: apiName, + script: apiScript, + cwd: apiCwd, + env: apiEnv, + }, + daemon: { + name: daemonName, + script: daemonScript, + cwd: daemonCwd, + env: daemonEnv, + }, + }; +}; + +const mapRuntimeStates = ( + profileNames: string[], + processNames: Map +): ProfileRuntimeSnapshot[] => + profileNames.map((profileName) => { + const apiName = buildProcessName(profileName, 'api'); + const daemonName = buildProcessName(profileName, 'daemon'); + return { + profileName, + apiRunning: processNames.get(apiName) ?? false, + daemonRunning: processNames.get(daemonName) ?? false, + }; + }); + +export class GatewayOrchestrator implements GatewayOrchestratorHandle { + private readonly repository: GatewayProfileRepository; + private readonly processManager: ProcessManager; + private readonly buildRunner: BuildRunner; + private readonly processConfig: GatewayProcessConfig; + private readonly reconcileIntervalMs: number; + private readonly scheduleIntervalMs: number; + private readonly buildIntervalMs: number; + private readonly now: () => Date; + private reconcileTimer?: NodeJS.Timeout; + private scheduleTimer?: NodeJS.Timeout; + private buildTimer?: NodeJS.Timeout; + private reconcileInFlight = false; + private scheduleInFlight = false; + private buildInFlight = false; + + constructor(options: GatewayOrchestratorOptions) { + this.repository = options.repository; + this.processManager = options.processManager; + this.buildRunner = options.buildRunner; + this.processConfig = options.processConfig; + this.reconcileIntervalMs = options.reconcileIntervalMs; + this.scheduleIntervalMs = options.scheduleIntervalMs; + this.buildIntervalMs = options.buildIntervalMs; + this.now = options.now ?? (() => new Date()); + } + + start(): void { + void this.reconcileNow(); + this.reconcileTimer = setInterval( + () => void this.reconcileNow(), + this.reconcileIntervalMs + ); + this.scheduleTimer = setInterval( + () => void this.runScheduleNow(), + this.scheduleIntervalMs + ); + this.buildTimer = setInterval( + () => void this.runBuildQueueNow(), + this.buildIntervalMs + ); + } + + async stop(): Promise { + if (this.reconcileTimer) { + clearInterval(this.reconcileTimer); + } + if (this.scheduleTimer) { + clearInterval(this.scheduleTimer); + } + if (this.buildTimer) { + clearInterval(this.buildTimer); + } + } + + async listRuntimeStates(profileNames: string[]): Promise { + const processStates = await this.loadProcessStatusMap(); + return mapRuntimeStates(profileNames, processStates); + } + + async reconcileNow(): Promise { + if (this.reconcileInFlight) { + return; + } + this.reconcileInFlight = true; + try { + const profiles = await this.repository.listProfiles(); + if (!profiles.length) { + return; + } + const processStates = await this.loadProcessStatusMap(); + for (const profile of profiles) { + const runtime = mapRuntimeStates([profile.profileName], processStates)[0]; + const plan = planProfileReconcile(profile.status, runtime); + if (plan.shouldStart) { + await this.startProfile(profile); + } else if (plan.shouldStop) { + await this.stopProfile(profile); + } + } + } finally { + this.reconcileInFlight = false; + } + } + + async runScheduleNow(): Promise { + if (this.scheduleInFlight) { + return; + } + this.scheduleInFlight = true; + try { + const now = this.now(); + const due = await this.repository.listReservedToStart(now); + for (const profile of due) { + try { + await this.repository.updateStatus( + profile.profileName, + 'RUNNING', + null + ); + await this.startProfile(profile); + } catch (error) { + await this.repository.updateLastError( + profile.profileName, + error instanceof Error ? error.message : 'Failed to start scheduled profile.' + ); + } + } + } finally { + this.scheduleInFlight = false; + } + } + + async runBuildQueueNow(): Promise { + if (this.buildInFlight) { + return; + } + this.buildInFlight = true; + try { + const queued = await this.repository.findQueuedBuild(); + if (!queued) { + return; + } + const startedAt = this.now().toISOString(); + await this.repository.updateBuildStatus(queued.profileName, 'RUNNING', { + startedAt, + error: null, + }); + const result = await this.buildRunner.run([ + { + command: 'pnpm', + args: ['--filter', '@sammo-ts/game-api', 'build'], + cwd: this.processConfig.workspaceRoot, + env: this.processConfig.baseEnv, + }, + { + command: 'pnpm', + args: ['--filter', '@sammo-ts/game-engine', 'build'], + cwd: this.processConfig.workspaceRoot, + env: this.processConfig.baseEnv, + }, + ]); + const completedAt = this.now().toISOString(); + if (result.ok) { + await this.repository.updateBuildStatus(queued.profileName, 'SUCCEEDED', { + completedAt, + error: null, + }); + if (queued.status !== 'RUNNING' && queued.status !== 'DISABLED') { + await this.repository.updateStatus( + queued.profileName, + 'COMPLETED', + queued.scheduledStartAt ? queued.scheduledStartAt : null + ); + } + } else { + await this.repository.updateBuildStatus(queued.profileName, 'FAILED', { + completedAt, + error: result.output.slice(-4000), + }); + } + } finally { + this.buildInFlight = false; + } + } + + private async startProfile(profile: GatewayProfileRecord): Promise { + const definitions = buildProcessDefinitions(profile, this.processConfig); + try { + await this.processManager.start(definitions.api); + await this.processManager.start(definitions.daemon); + await this.repository.updateLastError(profile.profileName, null); + } catch (error) { + await this.repository.updateLastError( + profile.profileName, + error instanceof Error ? error.message : 'Failed to start processes.' + ); + } + } + + private async stopProfile(profile: GatewayProfileRecord): Promise { + const apiName = buildProcessName(profile.profileName, 'api'); + const daemonName = buildProcessName(profile.profileName, 'daemon'); + try { + await this.processManager.stop(apiName); + } catch { + await this.processManager.delete(apiName); + } + try { + await this.processManager.stop(daemonName); + } catch { + await this.processManager.delete(daemonName); + } + } + + private async loadProcessStatusMap(): Promise> { + const processes = await this.processManager.list(); + const statusMap = new Map(); + for (const process of processes) { + const status = process.status.toLowerCase(); + const running = + status === 'online' || status === 'launching' || status === 'stopping'; + statusMap.set(process.name, running); + } + return statusMap; + } +} diff --git a/app/gateway-api/src/orchestrator/pm2ProcessManager.ts b/app/gateway-api/src/orchestrator/pm2ProcessManager.ts new file mode 100644 index 0000000..2e266ea --- /dev/null +++ b/app/gateway-api/src/orchestrator/pm2ProcessManager.ts @@ -0,0 +1,106 @@ +import { createRequire } from 'node:module'; + +import type { ProcessManager, ManagedProcessInfo, ProcessDefinition } from './processManager.js'; + +type Pm2Module = typeof import('pm2'); + +const require = createRequire(import.meta.url); + +const loadPm2 = (): Pm2Module => require('pm2') as Pm2Module; + +const withPm2 = async (handler: (pm2: Pm2Module) => Promise): Promise => { + const pm2 = loadPm2(); + await new Promise((resolve, reject) => { + pm2.connect((error) => { + if (error) { + reject(error); + return; + } + resolve(); + }); + }); + try { + return await handler(pm2); + } finally { + pm2.disconnect(); + } +}; + +export class Pm2ProcessManager implements ProcessManager { + async list(): Promise { + return withPm2( + (pm2) => + new Promise((resolve, reject) => { + pm2.list((error, list) => { + if (error) { + reject(error); + return; + } + const normalized = + list?.map((item) => ({ + name: item.name ?? 'unknown', + status: item.pm2_env?.status ?? 'unknown', + pid: item.pid ?? undefined, + })) ?? []; + resolve(normalized); + }); + }) + ); + } + + async start(definition: ProcessDefinition): Promise { + await withPm2( + (pm2) => + new Promise((resolve, reject) => { + pm2.start( + { + name: definition.name, + script: definition.script, + cwd: definition.cwd, + args: definition.args, + env: definition.env, + autorestart: true, + time: true, + }, + (error) => { + if (error) { + reject(error); + return; + } + resolve(); + } + ); + }) + ); + } + + async stop(name: string): Promise { + await withPm2( + (pm2) => + new Promise((resolve, reject) => { + pm2.stop(name, (error) => { + if (error) { + reject(error); + return; + } + resolve(); + }); + }) + ); + } + + async delete(name: string): Promise { + await withPm2( + (pm2) => + new Promise((resolve, reject) => { + pm2.delete(name, (error) => { + if (error) { + reject(error); + return; + } + resolve(); + }); + }) + ); + } +} diff --git a/app/gateway-api/src/orchestrator/processManager.ts b/app/gateway-api/src/orchestrator/processManager.ts new file mode 100644 index 0000000..2706c3c --- /dev/null +++ b/app/gateway-api/src/orchestrator/processManager.ts @@ -0,0 +1,20 @@ +export interface ManagedProcessInfo { + name: string; + status: string; + pid?: number; +} + +export interface ProcessDefinition { + name: string; + script: string; + cwd: string; + args?: string[]; + env?: Record; +} + +export interface ProcessManager { + list(): Promise; + start(definition: ProcessDefinition): Promise; + stop(name: string): Promise; + delete(name: string): Promise; +} diff --git a/app/gateway-api/src/orchestrator/profileRepository.ts b/app/gateway-api/src/orchestrator/profileRepository.ts new file mode 100644 index 0000000..9b96499 --- /dev/null +++ b/app/gateway-api/src/orchestrator/profileRepository.ts @@ -0,0 +1,235 @@ +import { Prisma, type PrismaClient } from '@prisma/client'; + +export const GATEWAY_PROFILE_STATUSES = [ + 'COMPLETED', + 'RESERVED', + 'RUNNING', + 'STOPPED', + 'DISABLED', +] as const; +export type GatewayProfileStatus = (typeof GATEWAY_PROFILE_STATUSES)[number]; + +export const GATEWAY_BUILD_STATUSES = [ + 'IDLE', + 'QUEUED', + 'RUNNING', + 'FAILED', + 'SUCCEEDED', +] as const; +export type GatewayBuildStatus = (typeof GATEWAY_BUILD_STATUSES)[number]; + +export interface GatewayProfileRecord { + profileName: string; + profile: string; + scenario: string; + apiPort: number; + status: GatewayProfileStatus; + buildStatus: GatewayBuildStatus; + scheduledStartAt?: string; + buildRequestedAt?: string; + buildStartedAt?: string; + buildCompletedAt?: string; + buildError?: string; + lastError?: string; + meta: Prisma.JsonObject; + createdAt: string; + updatedAt: string; +} + +export interface GatewayProfileUpsertInput { + profile: string; + scenario: string; + apiPort: number; + status?: GatewayProfileStatus; + scheduledStartAt?: string; + meta?: Prisma.JsonObject; +} + +export interface GatewayProfileRepository { + listProfiles(): Promise; + getProfile(profileName: string): Promise; + upsertProfile(input: GatewayProfileUpsertInput): Promise; + updateStatus( + profileName: string, + status: GatewayProfileStatus, + scheduledStartAt?: string | null + ): Promise; + updateBuildStatus( + profileName: string, + status: GatewayBuildStatus, + fields?: { + requestedAt?: string | null; + startedAt?: string | null; + completedAt?: string | null; + error?: string | null; + } + ): Promise; + listReservedToStart(now: Date): Promise; + findQueuedBuild(): Promise; + updateLastError(profileName: string, lastError: string | null): Promise; +} + +const toIso = (value: Date | null): string | undefined => + value ? value.toISOString() : undefined; + +const mapProfile = (row: { + profileName: string; + profile: string; + scenario: string; + apiPort: number; + status: GatewayProfileStatus; + buildStatus: GatewayBuildStatus; + scheduledStartAt: Date | null; + buildRequestedAt: Date | null; + buildStartedAt: Date | null; + buildCompletedAt: Date | null; + buildError: string | null; + lastError: string | null; + meta: Prisma.JsonValue; + createdAt: Date; + updatedAt: Date; +}): GatewayProfileRecord => ({ + profileName: row.profileName, + profile: row.profile, + scenario: row.scenario, + apiPort: row.apiPort, + status: row.status, + buildStatus: row.buildStatus, + scheduledStartAt: toIso(row.scheduledStartAt), + buildRequestedAt: toIso(row.buildRequestedAt), + buildStartedAt: toIso(row.buildStartedAt), + buildCompletedAt: toIso(row.buildCompletedAt), + buildError: row.buildError ?? undefined, + lastError: row.lastError ?? undefined, + meta: (row.meta ?? {}) as Prisma.JsonObject, + createdAt: row.createdAt.toISOString(), + updatedAt: row.updatedAt.toISOString(), +}); + +const buildProfileName = (profile: string, scenario: string): string => + `${profile}:${scenario}`; + +export const createGatewayProfileRepository = ( + prisma: PrismaClient +): GatewayProfileRepository => ({ + async listProfiles(): Promise { + const rows = await prisma.gatewayProfile.findMany({ + orderBy: [{ profile: 'asc' }, { scenario: 'asc' }], + }); + return rows.map(mapProfile); + }, + async getProfile(profileName: string): Promise { + const row = await prisma.gatewayProfile.findUnique({ + where: { profileName }, + }); + return row ? mapProfile(row) : null; + }, + async upsertProfile(input: GatewayProfileUpsertInput): Promise { + const profileName = buildProfileName(input.profile, input.scenario); + const row = await prisma.gatewayProfile.upsert({ + where: { profileName }, + create: { + profileName, + profile: input.profile, + scenario: input.scenario, + apiPort: input.apiPort, + status: input.status ?? 'STOPPED', + scheduledStartAt: input.scheduledStartAt + ? new Date(input.scheduledStartAt) + : null, + meta: (input.meta ?? {}) as Prisma.JsonObject, + }, + update: { + apiPort: input.apiPort, + status: input.status, + scheduledStartAt: input.scheduledStartAt + ? new Date(input.scheduledStartAt) + : input.scheduledStartAt === null + ? null + : undefined, + meta: input.meta ? (input.meta as Prisma.JsonObject) : undefined, + }, + }); + return mapProfile(row); + }, + async updateStatus( + profileName: string, + status: GatewayProfileStatus, + scheduledStartAt?: string | null + ): Promise { + const row = await prisma.gatewayProfile.update({ + where: { profileName }, + data: { + status, + scheduledStartAt: + scheduledStartAt === undefined + ? undefined + : scheduledStartAt + ? new Date(scheduledStartAt) + : null, + }, + }); + return row ? mapProfile(row) : null; + }, + async updateBuildStatus( + profileName: string, + status: GatewayBuildStatus, + fields?: { + requestedAt?: string | null; + startedAt?: string | null; + completedAt?: string | null; + error?: string | null; + } + ): Promise { + const row = await prisma.gatewayProfile.update({ + where: { profileName }, + data: { + buildStatus: status, + buildRequestedAt: + fields?.requestedAt === undefined + ? undefined + : fields?.requestedAt + ? new Date(fields.requestedAt) + : null, + buildStartedAt: + fields?.startedAt === undefined + ? undefined + : fields?.startedAt + ? new Date(fields.startedAt) + : null, + buildCompletedAt: + fields?.completedAt === undefined + ? undefined + : fields?.completedAt + ? new Date(fields.completedAt) + : null, + buildError: fields?.error === undefined ? undefined : fields.error, + }, + }); + return row ? mapProfile(row) : null; + }, + async listReservedToStart(now: Date): Promise { + const rows = await prisma.gatewayProfile.findMany({ + where: { + status: 'RESERVED', + scheduledStartAt: { + lte: now, + }, + }, + }); + return rows.map(mapProfile); + }, + async findQueuedBuild(): Promise { + const row = await prisma.gatewayProfile.findFirst({ + where: { buildStatus: 'QUEUED' }, + orderBy: { buildRequestedAt: 'asc' }, + }); + return row ? mapProfile(row) : null; + }, + async updateLastError(profileName: string, lastError: string | null): Promise { + await prisma.gatewayProfile.update({ + where: { profileName }, + data: { lastError }, + }); + }, +}); diff --git a/app/gateway-api/src/orchestrator/workspaceRoot.ts b/app/gateway-api/src/orchestrator/workspaceRoot.ts new file mode 100644 index 0000000..ca568c8 --- /dev/null +++ b/app/gateway-api/src/orchestrator/workspaceRoot.ts @@ -0,0 +1,25 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +const WORKSPACE_MARKERS = ['pnpm-workspace.yaml', 'package.json']; + +const hasWorkspaceMarker = (dir: string): boolean => + WORKSPACE_MARKERS.some((marker) => fs.existsSync(path.join(dir, marker))); + +export const resolveWorkspaceRoot = ( + startDir: string, + maxDepth = 5 +): string => { + let current = path.resolve(startDir); + for (let depth = 0; depth <= maxDepth; depth += 1) { + if (hasWorkspaceMarker(current)) { + return current; + } + const parent = path.dirname(current); + if (parent === current) { + break; + } + current = parent; + } + return path.resolve(startDir); +}; diff --git a/app/gateway-api/src/router.ts b/app/gateway-api/src/router.ts index 4cae667..40bfb30 100644 --- a/app/gateway-api/src/router.ts +++ b/app/gateway-api/src/router.ts @@ -9,6 +9,7 @@ import { decryptGameSessionToken, encryptGameSessionToken } from '@sammo-ts/comm import { procedure, router } from './trpc.js'; import { toPublicUser } from './auth/userRepository.js'; import type { UserOAuthInfo } from './auth/userRepository.js'; +import { adminRouter } from './adminRouter.js'; const zUsername = z.string().min(2).max(32); const zPassword = z.string().min(6).max(128); @@ -27,6 +28,7 @@ export const appRouter = router({ now: new Date().toISOString(), })), }), + admin: adminRouter, auth: router({ kakaoStart: procedure .input( diff --git a/app/gateway-api/src/server.ts b/app/gateway-api/src/server.ts index 0dcc5ab..55437d8 100644 --- a/app/gateway-api/src/server.ts +++ b/app/gateway-api/src/server.ts @@ -1,4 +1,4 @@ -import fastify from 'fastify'; +import fastify, { type FastifyRequest } from 'fastify'; import cors from '@fastify/cors'; import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify'; import type { PrismaClient } from '@prisma/client'; @@ -16,8 +16,20 @@ import { KakaoOAuthClient } from './auth/kakaoClient.js'; import { RedisOAuthSessionStore } from './auth/oauthSessionStore.js'; import { createPostgresUserRepository } from './auth/postgresUserRepository.js'; import { RedisGatewaySessionService } from './auth/redisSessionService.js'; +import { createGatewayProfileRepository } from './orchestrator/profileRepository.js'; +import { GatewayOrchestrator } from './orchestrator/gatewayOrchestrator.js'; +import { Pm2ProcessManager } from './orchestrator/pm2ProcessManager.js'; +import { PnpmBuildRunner } from './orchestrator/buildRunner.js'; +import { resolveWorkspaceRoot } from './orchestrator/workspaceRoot.js'; import { appRouter } from './router.js'; +const buildEnvMap = (env: NodeJS.ProcessEnv): Record => { + const entries = Object.entries(env).filter( + (entry): entry is [string, string] => typeof entry[1] === 'string' + ); + return Object.fromEntries(entries); +}; + export const createGatewayApiServer = async () => { const config = resolveGatewayApiConfigFromEnv(); const postgres = createPostgresConnector(resolvePostgresConfigFromEnv()); @@ -45,6 +57,28 @@ export const createGatewayApiServer = async () => { config.oauthSessionTtlSeconds ); + const profiles = createGatewayProfileRepository( + postgres.prisma as PrismaClient + ); + const workspaceRoot = resolveWorkspaceRoot(config.workspaceRootHint); + const processManager = new Pm2ProcessManager(); + const buildRunner = new PnpmBuildRunner(); + const baseEnv = buildEnvMap(process.env); + const orchestrator = new GatewayOrchestrator({ + repository: profiles, + processManager, + buildRunner, + processConfig: { + workspaceRoot, + redisKeyPrefix: config.redisKeyPrefix, + gameTokenSecret: config.gameTokenSecret, + baseEnv, + }, + reconcileIntervalMs: config.orchestratorReconcileIntervalMs, + scheduleIntervalMs: config.orchestratorScheduleIntervalMs, + buildIntervalMs: config.orchestratorBuildIntervalMs, + }); + const app = fastify({ logger: true, }); @@ -58,7 +92,7 @@ export const createGatewayApiServer = async () => { prefix: config.trpcPath, trpcOptions: { router: appRouter, - createContext: () => + createContext: ({ req }: { req: FastifyRequest }) => createGatewayApiContext({ users, sessions, @@ -68,6 +102,10 @@ export const createGatewayApiServer = async () => { kakaoClient, oauthSessions, publicBaseUrl: config.publicBaseUrl, + profiles, + orchestrator, + adminToken: config.adminToken, + requestHeaders: req.headers, }), }, }); @@ -76,7 +114,12 @@ export const createGatewayApiServer = async () => { ok: true, })); + if (config.orchestratorEnabled) { + orchestrator.start(); + } + app.addHook('onClose', async () => { + await orchestrator.stop(); await redis.disconnect(); await postgres.disconnect(); }); diff --git a/app/gateway-api/test/authFlow.test.ts b/app/gateway-api/test/authFlow.test.ts index 792465d..2a8cbeb 100644 --- a/app/gateway-api/test/authFlow.test.ts +++ b/app/gateway-api/test/authFlow.test.ts @@ -36,6 +36,26 @@ const buildCaller = () => { }), sendTalkMessage: async () => {}, }; + const profiles = { + listProfiles: async () => [], + getProfile: async () => null, + upsertProfile: async () => { + throw new Error('not used'); + }, + updateStatus: async () => null, + updateBuildStatus: async () => null, + listReservedToStart: async () => [], + findQueuedBuild: async () => null, + updateLastError: async () => {}, + }; + const orchestrator = { + start: () => {}, + stop: async () => {}, + reconcileNow: async () => {}, + runScheduleNow: async () => {}, + runBuildQueueNow: async () => {}, + listRuntimeStates: async () => [], + }; const caller = appRouter.createCaller( createGatewayApiContext({ users, @@ -46,6 +66,9 @@ const buildCaller = () => { kakaoClient, oauthSessions, publicBaseUrl: 'http://localhost', + profiles, + orchestrator, + requestHeaders: {}, }) ); return { caller, oauthSessions }; diff --git a/app/gateway-api/test/orchestratorPlan.test.ts b/app/gateway-api/test/orchestratorPlan.test.ts new file mode 100644 index 0000000..c0eb76a --- /dev/null +++ b/app/gateway-api/test/orchestratorPlan.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from 'vitest'; + +import { planProfileReconcile } from '../src/orchestrator/gatewayOrchestrator.js'; + +describe('planProfileReconcile', () => { + it('starts missing processes for running profiles', () => { + expect( + planProfileReconcile('RUNNING', { + apiRunning: true, + daemonRunning: false, + }) + ).toEqual({ shouldStart: true, shouldStop: false }); + }); + + it('does nothing when running profile is healthy', () => { + expect( + planProfileReconcile('RUNNING', { + apiRunning: true, + daemonRunning: true, + }) + ).toEqual({ shouldStart: false, shouldStop: false }); + }); + + it('stops processes for non-running profiles', () => { + expect( + planProfileReconcile('STOPPED', { + apiRunning: false, + daemonRunning: true, + }) + ).toEqual({ shouldStart: false, shouldStop: true }); + }); + + it('keeps reserved profiles off', () => { + expect( + planProfileReconcile('RESERVED', { + apiRunning: false, + daemonRunning: false, + }) + ).toEqual({ shouldStart: false, shouldStop: false }); + }); +}); diff --git a/docs/architecture/runtime.md b/docs/architecture/runtime.md index 030ff53..3a56cac 100644 --- a/docs/architecture/runtime.md +++ b/docs/architecture/runtime.md @@ -17,6 +17,47 @@ selection is required because it drives unit sets and DB settings. - Prefer `legacy/hwe/ts/util/LiteHashDRBG.ts` and `legacy/hwe/ts/util/RNG.ts` - Seed composition should include hidden base seed plus action context +## Gateway Orchestration (Single Host Draft) + +Gateway API is the single source of truth for profile state and reconciles +PM2-managed processes on boot and on a short interval. The DB owns the desired +state; PM2 is treated as the actuator. The runtime state is grouped so that +`game-api` + `turn-daemon` are either on together or off together. + +### DB-Owned Profile State + +Profiles are tracked by `profileName` (= `${profile}:${scenario}`). +Gateway loads the profile table on boot, then reconciles PM2 to match. + +- `완료됨` (COMPLETED): build output exists; processes should be off. +- `예약됨` (RESERVED): start is scheduled for a timestamp; processes off. +- `가동중` (RUNNING): both `game-api` and `turn-daemon` should be on. +- `정지됨` (STOPPED): processes off; may be resumed later. +- `비활성화` (DISABLED): excluded from orchestration; start forbidden. + +### Boot Reconciliation + +1) Load profile rows from DB. +2) List PM2 processes and map `profileName -> running state`. +3) For each profile: + - If desired `RUNNING` and any process is missing, start missing processes. + - If desired not `RUNNING` and any process is running, stop both processes. +4) Persist errors to DB for audit. + +### Internal Scheduler (Gateway Cron) + +Gateway runs a lightweight cron loop (setInterval) that: +- Promotes `RESERVED` profiles whose `scheduledStartAt <= now` to `RUNNING`. +- Triggers a reconcile immediately after promotion. +- Optionally drains a build queue (see build workflow). + +### Build Workflow (Admin) + +- Admin triggers a build request for a profile. +- Gateway queues a build job, runs `pnpm --filter @sammo-ts/game-api build` + and `pnpm --filter @sammo-ts/game-engine build`, then marks build success/failure. +- On success, profile status remains `COMPLETED` (or stays `RUNNING` if already on). + ## Current Implementation Status - Turn daemon lifecycle + in-memory state live in `app/game-engine` with DB flush hooks. diff --git a/docs/architecture/todo.md b/docs/architecture/todo.md index b068c16..7390588 100644 --- a/docs/architecture/todo.md +++ b/docs/architecture/todo.md @@ -14,7 +14,6 @@ Move items into the main docs once they are finalized. - [AI suggestion] Implement diplomacy/state transitions and monthly/command-based updates beyond read-only maps. - [AI suggestion] Integrate war/battle pipeline into turn processing (troop movement/war resolution hooks, not just isolated sim jobs). - [AI suggestion] Expand turn command catalog beyond the current subset (general/nation commands). -- [AI suggestion] Replace in-memory control queue with distributed control/lock primitives for multi-instance daemon operation. ## Runtime and Operations (Lower Priority) @@ -23,6 +22,8 @@ Move items into the main docs once they are finalized. - Document existing status/health endpoint requirements for ops and the current daemon loop behavior. - Document tick budget settings (wall time, max generals, catch-up cap) and partial progress persistence. - Document admin controls (pause/resume/manual run) and how they interact with lock/state. +- [AI suggestion] Define gateway admin build/daemon control approach (direct orchestration vs supervisor like systemd/pm2), security model, audit logging, and safe rollback/stop/start workflows. +- [AI suggestion] Specify single-host gateway orchestration: boot reconciliation from DB (완료/예약/가동중/정지됨/비활성화), desired-state mapping, and pm2-managed process lifecycles for api/daemon. - Turn daemon vs API server priority policy under load - Recovery behavior after partial flush or crash - Observability: metrics, logs, and alerts for turn processing diff --git a/packages/infra/prisma/schema.prisma b/packages/infra/prisma/schema.prisma index 09e5a8a..d725eb1 100644 --- a/packages/infra/prisma/schema.prisma +++ b/packages/infra/prisma/schema.prisma @@ -27,6 +27,22 @@ enum OAuthType { KAKAO } +enum GatewayProfileStatus { + COMPLETED + RESERVED + RUNNING + STOPPED + DISABLED +} + +enum GatewayBuildStatus { + IDLE + QUEUED + RUNNING + FAILED + SUCCEEDED +} + model AppUser { id String @id @default(uuid()) loginId String @unique @map("login_id") @@ -46,6 +62,27 @@ model AppUser { @@map("app_user") } +model GatewayProfile { + profileName String @id @map("profile_name") + profile String + scenario String + apiPort Int @map("api_port") + status GatewayProfileStatus + buildStatus GatewayBuildStatus @default(IDLE) @map("build_status") + scheduledStartAt DateTime? @map("scheduled_start_at") + buildRequestedAt DateTime? @map("build_requested_at") + buildStartedAt DateTime? @map("build_started_at") + buildCompletedAt DateTime? @map("build_completed_at") + buildError String? @map("build_error") + lastError String? @map("last_error") + meta Json @default(dbgenerated("'{}'::jsonb")) + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + @@unique([profile, scenario]) + @@map("gateway_profile") +} + model WorldState { id Int @id @default(autoincrement()) scenarioCode String @map("scenario_code") diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f16e17..5ac05c8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,9 +60,6 @@ importers: app/game-engine: dependencies: - '@prisma/client': - specifier: ^7.2.0 - version: 7.2.0(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3) '@sammo-ts/common': specifier: workspace:* version: link:../../packages/common @@ -111,6 +108,9 @@ importers: fastify: specifier: ^5.3.3 version: 5.6.2 + pm2: + specifier: ^5.4.3 + version: 5.4.3 redis: specifier: ^5.10.0 version: 5.10.0 @@ -459,6 +459,20 @@ packages: '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@pm2/agent@2.0.4': + resolution: {integrity: sha512-n7WYvvTJhHLS2oBb1PjOtgLpMhgImOq8sXkPBw6smeg9LJBWZjiEgPKOpR8mn9UJZsB5P3W4V/MyvNnp31LKeA==} + + '@pm2/io@6.0.1': + resolution: {integrity: sha512-KiA+shC6sULQAr9mGZ1pg+6KVW9MF8NpG99x26Lf/082/Qy8qsTCtnJy+HQReW1A9Rdf0C/404cz0RZGZro+IA==} + engines: {node: '>=6.0'} + + '@pm2/js-api@0.8.0': + resolution: {integrity: sha512-nmWzrA/BQZik3VBz+npRcNIu01kdBhWL0mxKmP1ciF/gTcujPTQqt027N9fc1pK9ERM8RipFhymw7RcmCyOEYA==} + engines: {node: '>=4.0'} + + '@pm2/pm2-version-check@1.0.4': + resolution: {integrity: sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==} + '@prisma/adapter-pg@7.2.0': resolution: {integrity: sha512-euIdQ13cRB2wZ3jPsnDnFhINquo1PYFPCg6yVL8b2rp3EdinQHsX9EDdCtRr489D5uhphcRk463OdQAFlsCr0w==} @@ -741,6 +755,9 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + '@trpc/server@11.8.1': resolution: {integrity: sha512-P4rzZRpEL7zDFgjxK65IdyH0e41FMFfTkQkuq0BA5tKcr7E6v9/v38DEklCpoDN6sPiB1Sigy/PUEzHENhswDA==} peerDependencies: @@ -799,6 +816,10 @@ packages: abstract-logging@2.0.1: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -810,10 +831,31 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + amp-message@0.1.2: + resolution: {integrity: sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==} + + amp@0.3.1: + resolution: {integrity: sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + ansis@4.2.0: resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} engines: {node: '>=14'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -822,6 +864,16 @@ packages: resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} engines: {node: '>=20.19.0'} + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + + async@2.6.4: + resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -833,9 +885,32 @@ packages: resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==} engines: {node: '>= 6.0.0'} + basic-ftp@5.1.0: + resolution: {integrity: sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==} + engines: {node: '>=10.0.0'} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + birpc@4.0.0: resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==} + blessed@0.1.81: + resolution: {integrity: sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==} + engines: {node: '>= 0.8.0'} + hasBin: true + + bodec@0.1.0: + resolution: {integrity: sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + c12@3.1.0: resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==} peerDependencies: @@ -852,9 +927,20 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + + charm@0.1.2: + resolution: {integrity: sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==} + chevrotain@10.5.0: resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + chokidar@4.0.3: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} @@ -862,10 +948,24 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + cli-tableau@2.0.1: + resolution: {integrity: sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==} + engines: {node: '>=8.10.0'} + cluster-key-slot@1.1.2: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@2.15.1: + resolution: {integrity: sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==} + confbox@0.2.2: resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} @@ -877,6 +977,9 @@ packages: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} + croner@4.1.97: + resolution: {integrity: sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -884,9 +987,39 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + culvert@0.1.2: + resolution: {integrity: sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + dayjs@1.11.19: + resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + + dayjs@1.8.36: + resolution: {integrity: sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==} + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -903,6 +1036,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -938,6 +1075,10 @@ packages: resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} engines: {node: '>=14'} + enquirer@2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -946,9 +1087,40 @@ packages: engines: {node: '>=18'} hasBin: true + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eventemitter2@0.4.14: + resolution: {integrity: sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==} + + eventemitter2@5.0.1: + resolution: {integrity: sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==} + + eventemitter2@6.4.9: + resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} + expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} @@ -956,6 +1128,9 @@ packages: exsolve@1.0.8: resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} + extrareqp2@1.0.0: + resolution: {integrity: sha512-Gum0g1QYb6wpPJCVypWP3bbIuaibcFiJcpuPM10YSXp/tzqi84x9PJageob+eN4xVRIOto4wjSGNLyMD54D2xA==} + fast-check@3.23.2: resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} engines: {node: '>=8.0.0'} @@ -966,6 +1141,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-json-patch@3.1.1: + resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==} + fast-json-stringify@6.1.1: resolution: {integrity: sha512-DbgptncYEXZqDUOEl4krff4mUiVrTZZVI7BBrQR/T3BqMj/eM1flTC1Uk2uUoLcWCxjT95xKulV/Lc6hhOZsBQ==} @@ -984,6 +1162,9 @@ packages: fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + fclone@1.0.11: + resolution: {integrity: sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -993,10 +1174,23 @@ packages: picomatch: optional: true + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + find-my-way@9.3.0: resolution: {integrity: sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==} engines: {node: '>=20'} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -1006,6 +1200,9 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + generate-function@2.3.1: resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} @@ -1015,10 +1212,29 @@ packages: get-tsconfig@4.13.0: resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + giget@2.0.0: resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} hasBin: true + git-node-fs@1.0.0: + resolution: {integrity: sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==} + peerDependencies: + js-git: ^0.7.8 + peerDependenciesMeta: + js-git: + optional: true + + git-sha1@0.1.2: + resolution: {integrity: sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} @@ -1028,6 +1244,14 @@ packages: grammex@3.1.12: resolution: {integrity: sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==} + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + hono@4.10.6: resolution: {integrity: sha512-BIdolzGpDO9MQ4nu3AUuDwHZZ+KViNm+EZ75Ae55eMXMqLVhDFqEMXxtUe9Qh8hjL+pIna/frs2j6Y2yD5Ua/g==} engines: {node: '>=16.9.0'} @@ -1035,9 +1259,21 @@ packages: hookable@6.0.1: resolution: {integrity: sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + http-status-codes@2.3.0: resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==} + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + iconv-lite@0.7.1: resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} engines: {node: '>=0.10.0'} @@ -1046,10 +1282,37 @@ packages: resolution: {integrity: sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==} engines: {node: '>=20.19.0'} + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + ipaddr.js@2.3.0: resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} engines: {node: '>= 10'} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + is-property@1.0.2: resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} @@ -1060,9 +1323,16 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + js-git@0.7.8: + resolution: {integrity: sha512-+E5ZH/HeRnoc/LW0AmAyhU+mNcWBzAKE+30+IDMLSLbbK+Tdt02AdkOKq9u15rlJsDEGFqtgckc8ZM59LhhiUA==} + js-sha512@0.9.0: resolution: {integrity: sha512-mirki9WS/SUahm+1TbAPkqvbCiCfOAAsyXeHxK1UkullnJVVqoJG2pL9ObvT05CN+tM7fxhfYm0NbXn+1hWoZg==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -1074,6 +1344,13 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + lazy@1.0.11: + resolution: {integrity: sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==} + engines: {node: '>=0.2.0'} + light-my-request@6.6.0: resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} @@ -1087,6 +1364,14 @@ packages: long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + lru.min@1.1.3: resolution: {integrity: sha512-Lkk/vx6ak3rYkRR0Nhu4lFUT2VDnQSxBe8Hbl7f36358p6ow8Bnvr8lrLt98H8J1aGxfhbX4Fs5tYg2+FTwr5Q==} engines: {bun: '>=1.0.0', deno: '>=1.30.0', node: '>=8.0.0'} @@ -1094,9 +1379,20 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + module-details-from-path@1.0.4: + resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + mysql2@3.15.3: resolution: {integrity: sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==} engines: {node: '>= 8.0'} @@ -1110,9 +1406,26 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + needle@2.4.0: + resolution: {integrity: sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==} + engines: {node: '>= 4.4.x'} + hasBin: true + + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + nssocket@0.6.0: + resolution: {integrity: sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==} + engines: {node: '>= 0.10.x'} + nypm@0.6.2: resolution: {integrity: sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==} engines: {node: ^14.16.0 || >=16.10.0} @@ -1128,10 +1441,24 @@ packages: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + + pako@0.2.9: + resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -1175,10 +1502,22 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + picomatch@4.0.3: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + pidusage@2.0.21: + resolution: {integrity: sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==} + engines: {node: '>=8'} + + pidusage@3.0.2: + resolution: {integrity: sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==} + engines: {node: '>=10'} + pino-abstract-transport@2.0.0: resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} @@ -1192,6 +1531,29 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + pm2-axon-rpc@0.7.1: + resolution: {integrity: sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==} + engines: {node: '>=5'} + + pm2-axon@4.0.1: + resolution: {integrity: sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==} + engines: {node: '>=5'} + + pm2-deploy@1.0.2: + resolution: {integrity: sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==} + engines: {node: '>=4.0.0'} + + pm2-multimeter@0.1.2: + resolution: {integrity: sha512-S+wT6XfyKfd7SJIBqRgOctGxaBzUOmVQzTAS+cg04TsEUObJVreha7lvCfX8zzGVr871XwCSnHUU7DQQ5xEsfA==} + + pm2-sysmonit@1.2.8: + resolution: {integrity: sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==} + + pm2@5.4.3: + resolution: {integrity: sha512-4/I1htIHzZk1Y67UgOCo4F1cJtas1kSds31N8zN0PybO230id1nigyjGuGFzUnGmUFPmrJ0On22fO1ChFlp7VQ==} + engines: {node: '>=12.0.0'} + hasBin: true + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -1239,9 +1601,19 @@ packages: process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + promptly@2.2.0: + resolution: {integrity: sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==} + proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + proxy-agent@6.3.1: + resolution: {integrity: sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} @@ -1263,6 +1635,14 @@ packages: resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} + read@1.0.7: + resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} + engines: {node: '>=0.8'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} @@ -1285,9 +1665,18 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + require-in-the-middle@5.2.0: + resolution: {integrity: sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==} + engines: {node: '>=6'} + resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + ret@0.5.0: resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} engines: {node: '>=10'} @@ -1332,6 +1721,12 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + run-series@1.1.9: + resolution: {integrity: sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-regex2@5.0.0: resolution: {integrity: sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==} @@ -1342,12 +1737,20 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sax@1.4.3: + resolution: {integrity: sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} secure-json-parse@4.1.0: resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + semver@7.7.3: resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} @@ -1367,6 +1770,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shimmer@1.2.1: + resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -1377,6 +1783,18 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + sonic-boom@4.2.0: resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} @@ -1384,10 +1802,20 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} + sprintf-js@1.1.2: + resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} + sqlstring@2.3.3: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} @@ -1401,6 +1829,20 @@ packages: std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + systeminformation@5.28.8: + resolution: {integrity: sha512-W2rXK+tTIoa1svfOEfhKPzJTw2OnoJ2XS57CftQkzvwt9Hj7RC2pfHKFAk8cHH+UkDAlGMW9Sf31kdOu5PZNIA==} + engines: {node: '>=8.0.0'} + os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] + hasBin: true + thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} @@ -1419,6 +1861,10 @@ packages: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + toad-cache@3.7.0: resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} engines: {node: '>=12'} @@ -1462,9 +1908,19 @@ packages: unplugin-unused: optional: true + tslib@1.9.3: + resolution: {integrity: sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tv4@1.3.0: + resolution: {integrity: sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==} + engines: {node: '>= 0.8.0'} + + tx2@1.0.5: + resolution: {integrity: sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==} + type-fest@4.41.0: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} @@ -1580,6 +2036,10 @@ packages: jsdom: optional: true + vizion@2.2.1: + resolution: {integrity: sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==} + engines: {node: '>=4.0'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1590,10 +2050,25 @@ packages: engines: {node: '>=8'} hasBin: true + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + zeptomatch@2.0.2: resolution: {integrity: sha512-H33jtSKf8Ijtb5BW6wua3G5DhnFjbFML36eFu+VdOoVY4HD9e7ggjqdM6639B+L87rjnR6Y+XeRzBXZdy52B/g==} @@ -1804,6 +2279,57 @@ snapshots: '@pinojs/redact@0.4.0': {} + '@pm2/agent@2.0.4': + dependencies: + async: 3.2.6 + chalk: 3.0.0 + dayjs: 1.8.36 + debug: 4.3.7 + eventemitter2: 5.0.1 + fast-json-patch: 3.1.1 + fclone: 1.0.11 + nssocket: 0.6.0 + pm2-axon: 4.0.1 + pm2-axon-rpc: 0.7.1 + proxy-agent: 6.3.1 + semver: 7.5.4 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@pm2/io@6.0.1': + dependencies: + async: 2.6.4 + debug: 4.3.7 + eventemitter2: 6.4.9 + require-in-the-middle: 5.2.0 + semver: 7.5.4 + shimmer: 1.2.1 + signal-exit: 3.0.7 + tslib: 1.9.3 + transitivePeerDependencies: + - supports-color + + '@pm2/js-api@0.8.0': + dependencies: + async: 2.6.4 + debug: 4.3.7 + eventemitter2: 6.4.9 + extrareqp2: 1.0.0(debug@4.3.7) + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@pm2/pm2-version-check@1.0.4': + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@prisma/adapter-pg@7.2.0': dependencies: '@prisma/driver-adapter-utils': 7.2.0 @@ -2026,6 +2552,8 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@tootallnate/quickjs-emscripten@0.23.0': {} + '@trpc/server@11.8.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 @@ -2099,6 +2627,8 @@ snapshots: abstract-logging@2.0.1: {} + agent-base@7.1.4: {} + ajv-formats@3.0.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 @@ -2110,8 +2640,27 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + amp-message@0.1.2: + dependencies: + amp: 0.3.1 + + amp@0.3.1: {} + + ansi-colors@4.1.3: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + ansis@4.2.0: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@2.0.1: {} + assertion-error@2.0.1: {} ast-kit@2.2.0: @@ -2119,6 +2668,16 @@ snapshots: '@babel/parser': 7.28.5 pathe: 2.0.3 + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + + async@2.6.4: + dependencies: + lodash: 4.17.21 + + async@3.2.6: {} + atomic-sleep@1.0.0: {} avvio@9.1.0: @@ -2128,8 +2687,22 @@ snapshots: aws-ssl-profiles@1.1.2: {} + basic-ftp@5.1.0: {} + + binary-extensions@2.3.0: {} + birpc@4.0.0: {} + blessed@0.1.81: {} + + bodec@0.1.0: {} + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + buffer-from@1.1.2: {} + c12@3.1.0: dependencies: chokidar: 4.0.3 @@ -2149,6 +2722,13 @@ snapshots: chai@6.2.2: {} + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + charm@0.1.2: {} + chevrotain@10.5.0: dependencies: '@chevrotain/cst-dts-gen': 10.5.0 @@ -2158,6 +2738,18 @@ snapshots: lodash: 4.17.21 regexp-to-ast: 0.5.0 + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + chokidar@4.0.3: dependencies: readdirp: 4.1.2 @@ -2166,14 +2758,28 @@ snapshots: dependencies: consola: 3.4.2 + cli-tableau@2.0.1: + dependencies: + chalk: 3.0.0 + cluster-key-slot@1.1.2: {} + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + commander@2.15.1: {} + confbox@0.2.2: {} consola@3.4.2: {} cookie@1.1.1: {} + croner@4.1.97: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -2182,8 +2788,24 @@ snapshots: csstype@3.2.3: {} + culvert@0.1.2: {} + + data-uri-to-buffer@6.0.2: {} + date-fns@4.1.0: {} + dayjs@1.11.19: {} + + dayjs@1.8.36: {} + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + debug@4.4.3: dependencies: ms: 2.1.3 @@ -2192,6 +2814,12 @@ snapshots: defu@6.1.4: {} + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + denque@2.1.0: {} dequal@2.0.3: {} @@ -2211,6 +2839,10 @@ snapshots: empathic@2.0.0: {} + enquirer@2.3.6: + dependencies: + ansi-colors: 4.1.3 + es-module-lexer@1.7.0: {} esbuild@0.27.2: @@ -2242,14 +2874,42 @@ snapshots: '@esbuild/win32-ia32': 0.27.2 '@esbuild/win32-x64': 0.27.2 + escape-string-regexp@4.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + esprima@4.0.1: {} + + estraverse@5.3.0: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.8 + esutils@2.0.3: {} + + eventemitter2@0.4.14: {} + + eventemitter2@5.0.1: {} + + eventemitter2@6.4.9: {} + expect-type@1.3.0: {} exsolve@1.0.8: {} + extrareqp2@1.0.0(debug@4.3.7): + dependencies: + follow-redirects: 1.15.11(debug@4.3.7) + transitivePeerDependencies: + - debug + fast-check@3.23.2: dependencies: pure-rand: 6.1.0 @@ -2258,6 +2918,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-json-patch@3.1.1: {} + fast-json-stringify@6.1.1: dependencies: '@fastify/merge-json-schemas': 0.2.1 @@ -2297,16 +2959,26 @@ snapshots: dependencies: reusify: 1.1.0 + fclone@1.0.11: {} + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + find-my-way@9.3.0: dependencies: fast-deep-equal: 3.1.3 fast-querystring: 1.1.2 safe-regex2: 5.0.0 + follow-redirects@1.15.11(debug@4.3.7): + optionalDependencies: + debug: 4.3.7 + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 @@ -2315,6 +2987,8 @@ snapshots: fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + generate-function@2.3.1: dependencies: is-property: 1.0.2 @@ -2325,6 +2999,14 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + get-uri@6.0.5: + dependencies: + basic-ftp: 5.1.0 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + giget@2.0.0: dependencies: citty: 0.1.6 @@ -2334,34 +3016,99 @@ snapshots: nypm: 0.6.2 pathe: 2.0.3 + git-node-fs@1.0.0(js-git@0.7.8): + optionalDependencies: + js-git: 0.7.8 + + git-sha1@0.1.2: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + globrex@0.1.2: {} graceful-fs@4.2.11: {} grammex@3.1.12: {} + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + hono@4.10.6: {} hookable@6.0.1: {} + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + http-status-codes@2.3.0: {} + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.7.1: dependencies: safer-buffer: 2.1.2 import-without-cache@0.2.5: {} + ini@1.3.8: {} + + ip-address@10.1.0: {} + ipaddr.js@2.3.0: {} + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + is-property@1.0.2: {} isexe@2.0.0: {} jiti@2.6.1: {} + js-git@0.7.8: + dependencies: + bodec: 0.1.0 + culvert: 0.1.2 + git-sha1: 0.1.2 + pako: 0.2.9 + js-sha512@0.9.0: {} + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + jsesc@3.1.0: {} json-schema-ref-resolver@3.0.0: @@ -2370,6 +3117,11 @@ snapshots: json-schema-traverse@1.0.0: {} + json-stringify-safe@5.0.1: + optional: true + + lazy@1.0.11: {} + light-my-request@6.6.0: dependencies: cookie: 1.1.1 @@ -2382,14 +3134,26 @@ snapshots: long@5.3.2: {} + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@7.18.3: {} + lru.min@1.1.3: {} magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + mkdirp@1.0.4: {} + + module-details-from-path@1.0.4: {} + ms@2.1.3: {} + mute-stream@0.0.8: {} + mysql2@3.15.3: dependencies: aws-ssl-profiles: 1.1.2 @@ -2408,8 +3172,25 @@ snapshots: nanoid@3.3.11: {} + needle@2.4.0: + dependencies: + debug: 3.2.7 + iconv-lite: 0.4.24 + sax: 1.4.3 + transitivePeerDependencies: + - supports-color + + netmask@2.0.2: {} + node-fetch-native@1.6.7: {} + normalize-path@3.0.0: {} + + nssocket@0.6.0: + dependencies: + eventemitter2: 0.4.14 + lazy: 1.0.11 + nypm@0.6.2: dependencies: citty: 0.1.6 @@ -2424,8 +3205,30 @@ snapshots: on-exit-leak-free@2.1.2: {} + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.4 + debug: 4.4.3 + get-uri: 6.0.5 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + + pako@0.2.9: {} + path-key@3.1.1: {} + path-parse@1.0.7: {} + pathe@2.0.3: {} perfect-debounce@1.0.0: {} @@ -2467,8 +3270,19 @@ snapshots: picocolors@1.1.1: {} + picomatch@2.3.1: {} + picomatch@4.0.3: {} + pidusage@2.0.21: + dependencies: + safe-buffer: 5.2.1 + optional: true + + pidusage@3.0.2: + dependencies: + safe-buffer: 5.2.1 + pino-abstract-transport@2.0.0: dependencies: split2: 4.2.0 @@ -2495,6 +3309,79 @@ snapshots: exsolve: 1.0.8 pathe: 2.0.3 + pm2-axon-rpc@0.7.1: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + pm2-axon@4.0.1: + dependencies: + amp: 0.3.1 + amp-message: 0.1.2 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + transitivePeerDependencies: + - supports-color + + pm2-deploy@1.0.2: + dependencies: + run-series: 1.1.9 + tv4: 1.3.0 + + pm2-multimeter@0.1.2: + dependencies: + charm: 0.1.2 + + pm2-sysmonit@1.2.8: + dependencies: + async: 3.2.6 + debug: 4.4.3 + pidusage: 2.0.21 + systeminformation: 5.28.8 + tx2: 1.0.5 + transitivePeerDependencies: + - supports-color + optional: true + + pm2@5.4.3: + dependencies: + '@pm2/agent': 2.0.4 + '@pm2/io': 6.0.1 + '@pm2/js-api': 0.8.0 + '@pm2/pm2-version-check': 1.0.4 + async: 3.2.6 + blessed: 0.1.81 + chalk: 3.0.0 + chokidar: 3.6.0 + cli-tableau: 2.0.1 + commander: 2.15.1 + croner: 4.1.97 + dayjs: 1.11.19 + debug: 4.4.3 + enquirer: 2.3.6 + eventemitter2: 5.0.1 + fclone: 1.0.11 + js-yaml: 4.1.1 + mkdirp: 1.0.4 + needle: 2.4.0 + pidusage: 3.0.2 + pm2-axon: 4.0.1 + pm2-axon-rpc: 0.7.1 + pm2-deploy: 1.0.2 + pm2-multimeter: 0.1.2 + promptly: 2.2.0 + semver: 7.7.3 + source-map-support: 0.5.21 + sprintf-js: 1.1.2 + vizion: 2.2.1 + optionalDependencies: + pm2-sysmonit: 1.2.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -2535,12 +3422,31 @@ snapshots: process-warning@5.0.0: {} + promptly@2.2.0: + dependencies: + read: 1.0.7 + proper-lockfile@4.1.2: dependencies: graceful-fs: 4.2.11 retry: 0.12.0 signal-exit: 3.0.7 + proxy-agent@6.3.1: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + pure-rand@6.1.0: {} quansync@1.0.0: {} @@ -2559,6 +3465,14 @@ snapshots: react@19.2.3: {} + read@1.0.7: + dependencies: + mute-stream: 0.0.8 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + readdirp@4.1.2: {} real-require@0.2.0: {} @@ -2579,8 +3493,22 @@ snapshots: require-from-string@2.0.2: {} + require-in-the-middle@5.2.0: + dependencies: + debug: 4.4.3 + module-details-from-path: 1.0.4 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + resolve-pkg-maps@1.0.0: {} + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + ret@0.5.0: {} retry@0.12.0: {} @@ -2652,6 +3580,10 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.54.0 fsevents: 2.3.3 + run-series@1.1.9: {} + + safe-buffer@5.2.1: {} + safe-regex2@5.0.0: dependencies: ret: 0.5.0 @@ -2660,10 +3592,16 @@ snapshots: safer-buffer@2.1.2: {} + sax@1.4.3: {} + scheduler@0.27.0: {} secure-json-parse@4.1.0: {} + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + semver@7.7.3: {} seq-queue@0.0.5: {} @@ -2676,20 +3614,46 @@ snapshots: shebang-regex@3.0.0: {} + shimmer@1.2.1: {} + siginfo@2.0.0: {} signal-exit@3.0.7: {} signal-exit@4.1.0: {} + smart-buffer@4.2.0: {} + + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + socks: 2.8.7 + transitivePeerDependencies: + - supports-color + + socks@2.8.7: + dependencies: + ip-address: 10.1.0 + smart-buffer: 4.2.0 + sonic-boom@4.2.0: dependencies: atomic-sleep: 1.0.0 source-map-js@1.2.1: {} + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + split2@4.2.0: {} + sprintf-js@1.1.2: {} + sqlstring@2.3.3: {} stackback@0.0.2: {} @@ -2698,6 +3662,15 @@ snapshots: std-env@3.9.0: {} + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + systeminformation@5.28.8: + optional: true + thread-stream@3.1.0: dependencies: real-require: 0.2.0 @@ -2713,6 +3686,10 @@ snapshots: tinyrainbow@3.0.3: {} + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + toad-cache@3.7.0: {} tree-kill@1.2.2: {} @@ -2748,7 +3725,15 @@ snapshots: - synckit - vue-tsc - tslib@2.8.1: + tslib@1.9.3: {} + + tslib@2.8.1: {} + + tv4@1.3.0: {} + + tx2@1.0.5: + dependencies: + json-stringify-safe: 5.0.1 optional: true type-fest@4.41.0: {} @@ -2831,6 +3816,13 @@ snapshots: - tsx - yaml + vizion@2.2.1: + dependencies: + async: 2.6.4 + git-node-fs: 1.0.0(js-git@0.7.8) + ini: 1.3.8 + js-git: 0.7.8 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -2840,8 +3832,12 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + ws@7.5.10: {} + xtend@4.0.2: {} + yallist@4.0.0: {} + zeptomatch@2.0.2: dependencies: grammex: 3.1.12