From 12d6d7e964fd5f510e2a3cba1069950b0a1127ec Mon Sep 17 00:00:00 2001 From: typeholes Date: Wed, 5 Jun 2024 15:17:49 -0400 Subject: [PATCH 01/24] (WIP) adding back live trace --- package.json | 1 + pnpm-lock.yaml | 8 ++ shared/src/traceData.ts | 2 +- src/commands.ts | 90 +++++++++++++-------- src/storage.ts | 29 ++++++- src/traceTree.ts | 79 +++++++++++++++++-- src/tsTrace.ts | 170 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 335 insertions(+), 44 deletions(-) create mode 100644 src/tsTrace.ts diff --git a/package.json b/package.json index bb13238..87ccdd6 100644 --- a/package.json +++ b/package.json @@ -382,6 +382,7 @@ "rollup-plugin-vue": "^6.0.0", "typescript": "^5.4.5", "vitest": "^1.6.0", + "@types/ts-expose-internals": "npm:ts-expose-internals@5.4.5", "zod": "^3.23.8" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 06cc51d..14c8209 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,6 +27,9 @@ importers: '@types/node': specifier: ^20.12.12 version: 20.12.12 + '@types/ts-expose-internals': + specifier: npm:ts-expose-internals@5.4.5 + version: ts-expose-internals@5.4.5 '@types/vscode': specifier: 1.70.0 version: 1.70.0 @@ -5329,6 +5332,9 @@ packages: peerDependencies: typescript: '>=4.2.0' + ts-expose-internals@5.4.5: + resolution: {integrity: sha512-0HfRwjgSIOyuDlHzkFedMWU4aHWq9pu4MUKHgH75U+L76wCAtK5WB0rc/dAIhulMRcPUlcKONeiiR5Sxy/7XcA==} + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -12247,6 +12253,8 @@ snapshots: dependencies: typescript: 5.4.5 + ts-expose-internals@5.4.5: {} + ts-interface-checker@0.1.13: {} tslib@1.14.1: {} diff --git a/shared/src/traceData.ts b/shared/src/traceData.ts index 4516821..ba83e93 100644 --- a/shared/src/traceData.ts +++ b/shared/src/traceData.ts @@ -6,7 +6,7 @@ export const typeLine = z.object({ intrinsicName: z.string().optional(), recursionId: z.number().optional(), flags: z.array(z.string()).optional(), - ts: z.number(), + ts: z.number().optional().default(0), dur: z.number().optional(), display: z.string().optional(), }) diff --git a/src/commands.ts b/src/commands.ts index 57b522b..ab0aa98 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -4,7 +4,7 @@ import { promisify } from 'node:util' import { spawn } from 'node:child_process' import { createReadStream, existsSync, readdir as readdirC, statSync } from 'node:fs' import * as vscode from 'vscode' -import { getStatsFromTree, processTraceFiles, showTree, treeIdNodes } from './traceTree' +import { getStatsFromTree, processTraceFiles, processedFiles, showTree, treeIdNodes } from './traceTree' import { getTracePanel, prepareWebView } from './webview' import { getCurrentConfig } from './configuration' import { log } from './logger' @@ -13,6 +13,7 @@ import { addTraceFile, getWorkspacePath, openTerminal, openTraceDirectoryExterna import { addTraceDiagnostics, clearTaceDiagnostics } from './traceDiagnostics' import { setStatusBarState } from './statusBar' import { afterWatches, projectPath, saveName, state, traceFiles, traceRunning } from './appState' +import { runLiveTrace } from './tsTrace' const readdir = promisify(readdirC) @@ -97,6 +98,7 @@ function gotoTracePosition(context: vscode.ExtensionContext) { showTree('', relativePath, startOffset - (editor.document.getText()[startOffset + 1] === '\n' ? 0 : 1)) } +const liveTrace = true // TODO config setting async function runTrace(args?: unknown[]) { const workspacePath = state.workspacePath.value const { traceCmd } = getCurrentConfig() @@ -119,58 +121,78 @@ async function runTrace(args?: unknown[]) { saveName.value = relative(workspacePath, dirName) } + traceFiles.value = {} + processedFiles.clear() + const newDirName = dirName // TODO: use logic from real time metrics that get the tsconfig path - afterWatches(() => { + afterWatches(async () => { const traceDir = state.tracePath.value if (!traceDir) { vscode.window.showWarningMessage('No workspace or folder open') return } - const quotedTraceDir = `'${traceDir}'` - // eslint-disable-next-line no-template-curly-in-string - const fullCmd = `(cd '${newDirName ?? workspacePath}'; ${traceCmd.replace('${traceDir}', quotedTraceDir)})` - - log(fullCmd) + if (liveTrace) { + try { + runLiveTrace(workspacePath, traceDir) + setStatusBarState('traceError', false) + } + catch (e) { + vscode.window.showErrorMessage('live trace failed') + log(`${e}`) + setStatusBarState('traceError', true) + } + setStatusBarState('tracing', false) + state.traceRunning.value = false - const newProjectPath = newDirName ?? projectPath.value - if (!newProjectPath) { - vscode.window.showErrorMessage('could not get project path from workspace folders') - return + await sendTraceDir(traceDir) } + else { + const quotedTraceDir = `'${traceDir}'` + // eslint-disable-next-line no-template-curly-in-string + const fullCmd = `(cd '${newDirName ?? workspacePath}'; ${traceCmd.replace('${traceDir}', quotedTraceDir)})` + + log(fullCmd) + + const newProjectPath = newDirName ?? projectPath.value + if (!newProjectPath) { + vscode.window.showErrorMessage('could not get project path from workspace folders') + return + } - traceRunning.value = true + traceRunning.value = true - traceFiles.value = {} - treeIdNodes.clear() + traceFiles.value = {} + treeIdNodes.clear() - setStatusBarState('traceError', false) + setStatusBarState('traceError', false) - log(`shell: ${process.env.SHELL}`) - const cmdProcess = spawn(fullCmd, [], { cwd: newProjectPath, shell: process.env.SHELL }) + log(`shell: ${process.env.SHELL}`) + const cmdProcess = spawn(fullCmd, [], { cwd: newProjectPath, shell: process.env.SHELL }) - let err = '' - cmdProcess.stderr.on('data', data => err += data.toString()) + let err = '' + cmdProcess.stderr.on('data', data => err += data.toString()) - cmdProcess.stdout.on('data', data => log(data.toString())) + cmdProcess.stdout.on('data', data => log(data.toString())) - cmdProcess.on('error', (error) => { - vscode.window.showErrorMessage(error.message) - }) + cmdProcess.on('error', (error) => { + vscode.window.showErrorMessage(error.message) + }) - cmdProcess.on('exit', async (code) => { - log('---- trace stderr -----') - log(err) - traceRunning.value = false - if (code) { - setStatusBarState('traceError', true) - vscode.window.showErrorMessage('error running trace') - return - } + cmdProcess.on('exit', async (code) => { + log('---- trace stderr -----') + log(err) + traceRunning.value = false + if (code) { + setStatusBarState('traceError', true) + vscode.window.showErrorMessage('error running trace') + return + } - await sendTraceDir(traceDir) - }) + await sendTraceDir(traceDir) + }) + } }) } diff --git a/src/storage.ts b/src/storage.ts index aa95859..7f2216b 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -1,4 +1,4 @@ -import { readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs' +import { existsSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs' import { join } from 'node:path' import { env } from 'node:process' import * as vscode from 'vscode' @@ -88,11 +88,12 @@ export function addTraceFile(fileName: string, contents: string) { try { const json = JSON.parse(contents) - const arr = traceData.safeParse(json) - if (!arr.success) + if (!Array.isArray(json)) { + vscode.window.showErrorMessage(`trace ${fileName} is not a json array`) return + } - state.traceFiles.value[fileName] = arr.data + state.traceFiles.value[fileName] = json } catch (e) { vscode.window.showErrorMessage(`${e}`) @@ -152,3 +153,23 @@ export async function deleteTraceFiles(fileName: string, dirName?: string) { rmSync(join(deleteDirName, fileName)) } } + +const typeTimestampsFileName = 'timestamps.json' +export async function writeTypeTimestamps(data: Map) { + const traceDir = state.tracePath.value + const fileName = join(traceDir, typeTimestampsFileName) + writeFileSync(fileName, JSON.stringify([...data.entries()], null, 2)) +} + +export async function readTypeTimestamps() { + const traceDir = await getTraceDir() + const fileName = join(traceDir, typeTimestampsFileName) + + if (!existsSync(fileName)) + return undefined + + const str = readFileSync(fileName).toString() + const json = JSON.parse(str) + + return new Map(json) +} diff --git a/src/traceTree.ts b/src/traceTree.ts index 0618d33..69b88fc 100644 --- a/src/traceTree.ts +++ b/src/traceTree.ts @@ -1,9 +1,11 @@ import { isAbsolute, join, relative } from 'node:path' +import * as vscode from 'vscode' import type { FileStat } from '../shared/src/messages' -import type { TraceData, TraceLine, TypeLine } from '../shared/src/traceData' +import { type TraceData, type TraceLine, type TypeLine, traceLine, typeLine } from '../shared/src/traceData' import { getWorkspacePath } from './storage' import { postMessage } from './webview' -import { traceFiles } from './appState' +import { state, traceFiles } from './appState' +import { getTypeTimestamps } from './tsTrace' export interface Tree { id: number, line: TraceLine, children: Tree[], types: TypeLine[], childCnt: number, childTypeCnt: number, typeCnt: number } function getRoot(): Tree { @@ -27,7 +29,7 @@ function getRoot(): Tree { } let treeIndexes: Tree[] = [] -export function toTree(traceData: TraceData, workspacePath: string): Tree { +export function toTree(traceData: TraceData): Tree { const tree: Tree = { ...getRoot() } let endTs = Number.MAX_SAFE_INTEGER let curr = tree @@ -38,6 +40,8 @@ export function toTree(traceData: TraceData, workspacePath: string): Tree { treeIndexes = [tree] + const workspacePath = state.workspacePath.value + const data = traceData.filter(x => 'id' in x || ('cat' in x)).sort((a, b) => a.ts - b.ts) // const data = traceData.filter(x => 'id' in x || ('cat' in x && x.cat?.startsWith('check'))).sort((a, b) => a.ts - b.ts) for (const line of data) { @@ -75,9 +79,74 @@ export function toTree(traceData: TraceData, workspacePath: string): Tree { } let traceTree: Tree | undefined +const traceLines: TraceLine[] = [] +const typeLines: TypeLine[] = [] +export const processedFiles = new Set() + export async function processTraceFiles() { - const workspacePath = await getWorkspacePath() - traceTree = toTree(Object.values(traceFiles.value).flat(1), workspacePath) + const typeTimestamps = await getTypeTimestamps() + let newFiles = false + const workspacePath = state.workspacePath.value + const traceFiles = state.traceFiles.value + + for (const name in traceFiles) { + if (processedFiles.has(name)) + continue + processedFiles.add(name) + newFiles = true + + const lines = traceFiles[name] + + if (name.includes('trace')) { + const starts: TraceLine[] = [] + for (const unparsed of lines) { + const parsed = traceLine.safeParse(unparsed) + if (!parsed.success) { + vscode.window.showErrorMessage(`trace file ${name} is not valid`) + return + } + + const line = parsed.data + if ('args' in line && line.args?.path && isAbsolute(line.args?.path)) + line.args.path = relative(workspacePath, line.args.path) + + if (line.ph === 'B') { + starts.push(line) + } + else if (line.ph === 'E') { + const start = starts.pop() + if (start) { + start.dur = line.ts - start.ts + traceLines.push(start) + } + } + else { + traceLines.push(line) + } + } + } + else if (name.includes('type')) { + for (const unparsed of lines) { + const parsed = typeLine.safeParse(unparsed) + if (!parsed.success) { + vscode.window.showErrorMessage(`type file ${name} is not valid`) + return + } + + const line = parsed.data + line.ts = typeTimestamps.get(line.id) ?? 0 + typeLines.push(line) + } + } + } + + if (!newFiles) + return traceTree + + const allLines = [...traceLines, ...typeLines] + allLines.sort((a, b) => a.ts - b.ts) + traceTree = toTree(allLines) + return traceTree } export function filterTree(startsWith: string, sourceFileName: string, position: number | '', tree = traceTree): Tree[] { diff --git a/src/tsTrace.ts b/src/tsTrace.ts new file mode 100644 index 0000000..05b06c4 --- /dev/null +++ b/src/tsTrace.ts @@ -0,0 +1,170 @@ +import type { BuilderProgram, CompilerHost, CompilerOptions, CreateProgramOptions, Diagnostic, DiagnosticReporter, ExtendedConfigCacheEntry, ParseConfigFileHost, ParsedCommandLine, PrinterOptions, Program, System, Type } from 'typescript' +import { JSDocParsingMode, NewLineKind, combinePaths, createGetCanonicalFileName, createGetSourceFile, createProgram, createWriteFileMeasuringIO, emitFilesAndReportErrorsAndGetExitStatus, findConfigFile, getConfigFileParsingDiagnostics, getDefaultLibFileName, getDirectoryPath, getParsedCommandLineOfConfigFile, maybeBind, memoize, programContainsEsModules, startTracing, sys, timestamp, tracing } from 'typescript' +import { readTypeTimestamps, writeTypeTimestamps } from './storage' + +export type ExecuteCommandLineCallbacks = (program: Program | BuilderProgram | ParsedCommandLine) => void + +let program: Program +export function getProgram() { + return program +} + +let typeTimestamps = new Map() +export async function getTypeTimestamps() { + if (typeTimestamps.size === 0) { + typeTimestamps = await readTypeTimestamps() ?? typeTimestamps + } + return typeTimestamps +} + +// TODO: see src/comipler/path.ts:632 +function normalizePath(path: string) { + return path +} + +export function runLiveTrace( + projectDirectory: string, + traceDir: string, +) { + const searchPath = normalizePath(projectDirectory) + const configFileName = findConfigFile(searchPath, fileName => sys.fileExists(fileName)) + const reportDiagnostic = (_diagnostic: Diagnostic) => {} + + if (configFileName) { + const extendedConfigCache = new Map() + const configParseResult = getParsedCommandLineOfConfigFile(configFileName, {}, sys as unknown as ParseConfigFileHost, extendedConfigCache, {}) + if (!configParseResult) + throw new Error('undefined configParseResult') + // const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, extendedConfigCache, commandLine.watchOptions, sys, reportDiagnostic)! // TODO: GH#18217 + + program = performCompilation( + sys, + reportDiagnostic, + configParseResult, + traceDir, + ) + + writeTypeTimestamps(typeTimestamps) + return program + } +} + +const defaultJSDocParsingMode = JSDocParsingMode.ParseForTypeErrors + +function performCompilation( + sys: System, + reportDiagnostic: DiagnosticReporter, + config: ParsedCommandLine, + traceDir: string, +) { + const { fileNames, options, projectReferences } = config + options.generateTrace = traceDir + const host = createCompilerHostWorker(options, /* setParentNodes */ undefined, sys) + host.jsDocParsingMode = defaultJSDocParsingMode + // const currentDirectory = host.getCurrentDirectory() + // const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()) + // changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName)) + enableTracing(sys, options, /* isBuildMode */ false) + + config.options.noEmit = true + + const programOptions: CreateProgramOptions = { + rootNames: fileNames, + options, + projectReferences, + host, + configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config), + } + const program = createProgram(programOptions) + emitFilesAndReportErrorsAndGetExitStatus( + program, + reportDiagnostic, + s => sys.write(s + sys.newLine), + () => undefined, // createReportErrorSummary(sys, options), + ) + + tracing?.stopTracing() + return program +} + +export function createCompilerHostWorker( + options: CompilerOptions, + setParentNodes?: boolean, + system: System = sys, +): CompilerHost { + const existingDirectories = new Map() + const getCanonicalFileName = createGetCanonicalFileName(system.useCaseSensitiveFileNames) + function directoryExists(directoryPath: string): boolean { + if (existingDirectories.has(directoryPath)) { + return true + } + if ((sys.directoryExists || system.directoryExists)(directoryPath)) { + existingDirectories.set(directoryPath, true) + return true + } + return false + } + + function getDefaultLibLocation(): string { + return getDirectoryPath(normalizePath(system.getExecutingFilePath())) + } + + const newLine = getNewLineCharacter(options) + const realpath = system.realpath && ((path: string) => system.realpath!(path)) + const compilerHost: CompilerHost = { + getSourceFile: createGetSourceFile(fileName => compilerHost.readFile(fileName), () => options, setParentNodes), + getDefaultLibLocation, + getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)), + writeFile: createWriteFileMeasuringIO( + (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark), + path => (compilerHost.createDirectory || system.createDirectory)(path), + path => directoryExists(path), + ), + getCurrentDirectory: memoize(() => system.getCurrentDirectory()), + useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames, + getCanonicalFileName, + getNewLine: () => newLine, + fileExists: fileName => system.fileExists(fileName), + readFile: fileName => system.readFile(fileName), + trace: (s: string) => system.write(s + newLine), + directoryExists: directoryName => system.directoryExists(directoryName), + getEnvironmentVariable: name => system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : '', + getDirectories: (path: string) => system.getDirectories(path), + realpath, + readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth), + createDirectory: d => system.createDirectory(d), + createHash: maybeBind(system, system.createHash), + } + return compilerHost +} + +const carriageReturnLineFeed = '\r\n' +const lineFeed = '\n' +export function getNewLineCharacter(options: CompilerOptions | PrinterOptions): string { + switch (options.newLine) { + case NewLineKind.CarriageReturnLineFeed: + return carriageReturnLineFeed + case NewLineKind.LineFeed: + case undefined: + return lineFeed + } +} + +function canTrace(system: System, compilerOptions: CompilerOptions) { + return system === sys && compilerOptions.generateTrace +} + +// TODO: do not call the held record type and just fetch the types by id from the program as needed +function enableTracing(system: System, compilerOptions: CompilerOptions, isBuildMode: boolean) { + if (canTrace(system, compilerOptions)) { + typeTimestamps.clear() + startTracing(isBuildMode ? 'build' : 'project', compilerOptions.generateTrace!, compilerOptions.configFilePath) + if (tracing) { + const holdRecordType = tracing.recordType + tracing.recordType = (type: Type) => { + typeTimestamps.set(type.id, 1000 * timestamp()) + holdRecordType(type) + } + } + } +} From 3b365297b7cf5598143ac772baa1f565307f93bd Mon Sep 17 00:00:00 2001 From: typeholes Date: Wed, 5 Jun 2024 15:50:54 -0400 Subject: [PATCH 02/24] displays for all types working again --- shared/src/traceData.ts | 2 +- src/traceTree.ts | 35 ++++++++++++++++++++++++++--------- src/tsTrace.ts | 9 ++++++++- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/shared/src/traceData.ts b/shared/src/traceData.ts index ba83e93..2a8748d 100644 --- a/shared/src/traceData.ts +++ b/shared/src/traceData.ts @@ -6,7 +6,7 @@ export const typeLine = z.object({ intrinsicName: z.string().optional(), recursionId: z.number().optional(), flags: z.array(z.string()).optional(), - ts: z.number().optional().default(0), + ts: z.number().default(0).optional(), dur: z.number().optional(), display: z.string().optional(), }) diff --git a/src/traceTree.ts b/src/traceTree.ts index 69b88fc..c71849c 100644 --- a/src/traceTree.ts +++ b/src/traceTree.ts @@ -1,11 +1,12 @@ import { isAbsolute, join, relative } from 'node:path' import * as vscode from 'vscode' +// import { getLineAndCharacterOfPosition } from 'typescript' import type { FileStat } from '../shared/src/messages' import { type TraceData, type TraceLine, type TypeLine, traceLine, typeLine } from '../shared/src/traceData' import { getWorkspacePath } from './storage' import { postMessage } from './webview' -import { state, traceFiles } from './appState' -import { getTypeTimestamps } from './tsTrace' +import { state } from './appState' +import { getProgram, getTypeDictionary, getTypeTimestamps } from './tsTrace' export interface Tree { id: number, line: TraceLine, children: Tree[], types: TypeLine[], childCnt: number, childTypeCnt: number, typeCnt: number } function getRoot(): Tree { @@ -29,7 +30,7 @@ function getRoot(): Tree { } let treeIndexes: Tree[] = [] -export function toTree(traceData: TraceData): Tree { +export function toTree(data: TraceData): Tree { const tree: Tree = { ...getRoot() } let endTs = Number.MAX_SAFE_INTEGER let curr = tree @@ -42,16 +43,15 @@ export function toTree(traceData: TraceData): Tree { const workspacePath = state.workspacePath.value - const data = traceData.filter(x => 'id' in x || ('cat' in x)).sort((a, b) => a.ts - b.ts) - // const data = traceData.filter(x => 'id' in x || ('cat' in x && x.cat?.startsWith('check'))).sort((a, b) => a.ts - b.ts) + // zod won't allow default for TS in the tree message so we have to assert it here for (const line of data) { if ('args' in line && line.args?.path && isAbsolute(line.args?.path)) line.args.path = relative(workspacePath, line.args.path) if (line.dur !== Number.MAX_SAFE_INTEGER && (line.dur ?? 0) > maxDur) - maxDur = line.ts + maxDur = line.ts! - while (line.ts > endTs) { + while (line.ts! > endTs) { if (stack.length === 0) throw new Error('tree stack empty') @@ -135,6 +135,7 @@ export async function processTraceFiles() { const line = parsed.data line.ts = typeTimestamps.get(line.id) ?? 0 + typeLines.push(line) } } @@ -144,7 +145,7 @@ export async function processTraceFiles() { return traceTree const allLines = [...traceLines, ...typeLines] - allLines.sort((a, b) => a.ts - b.ts) + allLines.sort((a, b) => a.ts! - b.ts!) traceTree = toTree(allLines) return traceTree } @@ -213,7 +214,23 @@ export function getChildrenById(id: number) { } export function getTypesById(id: number) { - return treeIdNodes.get(id)?.types ?? [] + const ret = treeIdNodes.get(id)?.types + const typeDictionary = getTypeDictionary() + if (!ret) + return [] + + const checker = getProgram()?.getTypeChecker() + if (!checker) + return ret + + for (const line of ret) { + if (!line.display) { + const type = typeDictionary.get(line.id) + if (type) + line.display = checker.typeToString(type) + } + } + return ret } export function getStatsFromTree(fileName: string) { diff --git a/src/tsTrace.ts b/src/tsTrace.ts index 05b06c4..8e0c7bd 100644 --- a/src/tsTrace.ts +++ b/src/tsTrace.ts @@ -4,18 +4,22 @@ import { readTypeTimestamps, writeTypeTimestamps } from './storage' export type ExecuteCommandLineCallbacks = (program: Program | BuilderProgram | ParsedCommandLine) => void -let program: Program +let program: Program | undefined export function getProgram() { return program } let typeTimestamps = new Map() +const typeDictionary = new Map() export async function getTypeTimestamps() { if (typeTimestamps.size === 0) { typeTimestamps = await readTypeTimestamps() ?? typeTimestamps } return typeTimestamps } +export function getTypeDictionary() { + return typeDictionary +} // TODO: see src/comipler/path.ts:632 function normalizePath(path: string) { @@ -158,11 +162,14 @@ function canTrace(system: System, compilerOptions: CompilerOptions) { function enableTracing(system: System, compilerOptions: CompilerOptions, isBuildMode: boolean) { if (canTrace(system, compilerOptions)) { typeTimestamps.clear() + typeDictionary.clear() + startTracing(isBuildMode ? 'build' : 'project', compilerOptions.generateTrace!, compilerOptions.configFilePath) if (tracing) { const holdRecordType = tracing.recordType tracing.recordType = (type: Type) => { typeTimestamps.set(type.id, 1000 * timestamp()) + typeDictionary.set(type.id, type) holdRecordType(type) } } From bd7296456289fb73da9cdb157e38f2184d0ca201 Mon Sep 17 00:00:00 2001 From: typeholes Date: Wed, 5 Jun 2024 16:06:34 -0400 Subject: [PATCH 03/24] show tree on client init --- src/handleMessages.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/handleMessages.ts b/src/handleMessages.ts index 4f321c3..cd5035e 100644 --- a/src/handleMessages.ts +++ b/src/handleMessages.ts @@ -10,6 +10,7 @@ import { state, triggerAll } from './appState' export function handleMessage(panel: vscode.WebviewPanel, message: unknown): void { if (message === 'init client') { triggerAll(false, true) + showTree('check', '', 0) return } From a7a61699365be8d4897f87a6a7236f2d8fc8363e Mon Sep 17 00:00:00 2001 From: typeholes Date: Fri, 7 Jun 2024 18:34:22 -0400 Subject: [PATCH 04/24] log errors from live trace --- src/tsTrace.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/tsTrace.ts b/src/tsTrace.ts index 8e0c7bd..70c623f 100644 --- a/src/tsTrace.ts +++ b/src/tsTrace.ts @@ -1,6 +1,7 @@ import type { BuilderProgram, CompilerHost, CompilerOptions, CreateProgramOptions, Diagnostic, DiagnosticReporter, ExtendedConfigCacheEntry, ParseConfigFileHost, ParsedCommandLine, PrinterOptions, Program, System, Type } from 'typescript' -import { JSDocParsingMode, NewLineKind, combinePaths, createGetCanonicalFileName, createGetSourceFile, createProgram, createWriteFileMeasuringIO, emitFilesAndReportErrorsAndGetExitStatus, findConfigFile, getConfigFileParsingDiagnostics, getDefaultLibFileName, getDirectoryPath, getParsedCommandLineOfConfigFile, maybeBind, memoize, programContainsEsModules, startTracing, sys, timestamp, tracing } from 'typescript' +import { JSDocParsingMode, NewLineKind, combinePaths, createGetCanonicalFileName, createGetSourceFile, createProgram, createWriteFileMeasuringIO, diagnosticToString, emitFilesAndReportErrorsAndGetExitStatus, findConfigFile, getConfigFileParsingDiagnostics, getDefaultLibFileName, getDirectoryPath, getParsedCommandLineOfConfigFile, maybeBind, memoize, programContainsEsModules, startTracing, sys, timestamp, tracing } from 'typescript' import { readTypeTimestamps, writeTypeTimestamps } from './storage' +import { log } from './logger' export type ExecuteCommandLineCallbacks = (program: Program | BuilderProgram | ParsedCommandLine) => void @@ -32,7 +33,9 @@ export function runLiveTrace( ) { const searchPath = normalizePath(projectDirectory) const configFileName = findConfigFile(searchPath, fileName => sys.fileExists(fileName)) - const reportDiagnostic = (_diagnostic: Diagnostic) => {} + const reportDiagnostic = (_diagnostic: Diagnostic) => { + log(`${_diagnostic.messageText}`) + } if (configFileName) { const extendedConfigCache = new Map() @@ -84,7 +87,14 @@ function performCompilation( program, reportDiagnostic, s => sys.write(s + sys.newLine), - () => undefined, // createReportErrorSummary(sys, options), + (a, b) => { + log(`summary a: ${a}`) + if (b) { + b.forEach((c) => { + log(`error at: ${c?.fileName}: ${c?.line}`) + }) + } + }, // createReportErrorSummary(sys, options), ) tracing?.stopTracing() From 4ee166d4cf32fcfefa110beb6aaf59e14a609563 Mon Sep 17 00:00:00 2001 From: typeholes Date: Sat, 8 Jun 2024 14:13:33 -0400 Subject: [PATCH 05/24] use ts-trace-server much cleanup left to do --- .vscode/launch.json | 22 +- .vscode/tasks.json | 20 +- package.json | 14 +- playground/index.ts | 3 + pnpm-lock.yaml | 495 +---- pnpm-workspace.yaml | 2 +- rollup.config.mjs | 4 +- server/.gitignore | 3 + server/package-lock.json | 2942 ++++++++++++++++++++++++++++++ server/package.json | 32 + server/rollup.config.mjs | 11 + server/src/commonState.ts | 0 server/src/dbSchema.ts | 96 + server/src/index.ts | 28 + server/src/messages.ts | 178 ++ server/src/server.ts | 217 +++ server/src/traceData.ts | 41 + server/src/traceDir.ts | 35 + server/src/tsTrace.ts | 311 ++++ {srcDev => server}/tsconfig.json | 16 +- shared/src/messages.ts | 6 +- src/appState.ts | 9 +- src/client/actions.ts | 37 + src/client/client.ts | 122 ++ src/commands.ts | 20 +- src/handleMessages.ts | 2 +- src/index.ts | 2 + src/storage.ts | 1 - src/tsTrace.ts | 2 +- src/webview.ts | 24 +- srcDev/.vscode/settings.json | 7 - srcDev/eslint.config.mjs | 5 - srcDev/package.json | 21 - srcDev/public/index.html | 23 - srcDev/rollup.config.mjs | 11 - srcDev/src/index.ts | 16 - srcDev/src/server.ts | 53 - tsconfig.json | 3 +- 38 files changed, 4206 insertions(+), 628 deletions(-) create mode 100644 server/.gitignore create mode 100644 server/package-lock.json create mode 100644 server/package.json create mode 100644 server/rollup.config.mjs create mode 100644 server/src/commonState.ts create mode 100644 server/src/dbSchema.ts create mode 100644 server/src/index.ts create mode 100644 server/src/messages.ts create mode 100644 server/src/server.ts create mode 100644 server/src/traceData.ts create mode 100644 server/src/traceDir.ts create mode 100644 server/src/tsTrace.ts rename {srcDev => server}/tsconfig.json (50%) create mode 100644 src/client/actions.ts create mode 100644 src/client/client.ts delete mode 100644 srcDev/.vscode/settings.json delete mode 100644 srcDev/eslint.config.mjs delete mode 100644 srcDev/package.json delete mode 100644 srcDev/public/index.html delete mode 100644 srcDev/rollup.config.mjs delete mode 100644 srcDev/src/index.ts delete mode 100644 srcDev/src/server.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 2f32f72..6e18ca3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,7 +14,27 @@ "outFiles": [ "${workspaceFolder}/dist/**/*.js" ], - "preLaunchTask": "${defaultBuildTask}" + "preLaunchTask": "npm: dev" + }, + { + "type": "node", + "request": "launch", + "name": "Launch Server", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/server/dist/index.js", + "preLaunchTask": "npm: server:dev", + "outFiles": [ + "${workspaceFolder}/server/dist/**/*.js" + ] + } + ], + "compounds": [ + { + "name": "Server/Extension", + "configurations": ["Run Extension", "Launch Server"], + "stopAll": true } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 2f4cb17..039d037 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -13,7 +13,25 @@ "group": { "kind": "build", "isDefault": true - } + }, + "problemMatcher": [], + "label": "npm: dev", + "detail": "nr build --watch --sourcemap" + }, + { + "type": "npm", + "script": "server:dev", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": false + }, + "problemMatcher": [], + "label": "npm: server:dev", + "detail": "cd server && nr build --watch --sourcemap" } ] } diff --git a/package.json b/package.json index 87ccdd6..df7b52a 100644 --- a/package.json +++ b/package.json @@ -346,12 +346,12 @@ "generate:contributes": "jiti ./scripts/generate-contributes.ts", "generate:experimental": "TraceExperimental=true jiti ./scripts/generate-contributes.ts", "pretest": "nr build && nr lint", - "build": "nr generate:contributes && nr srcDev:build && nr ui:build && rollup -c", + "build": "nr generate:contributes && nr ui:build && rollup -c", "dev": "nr build --watch --sourcemap", + "server:build": "cd server && rollup -c", + "server:dev": "cd server && nr build --watch --sourcemap", "ui:dev": "nuxt dev ui", "ui:build": "nuxt build ui", - "srcDev:dev": "nr build --filter ./srcDev --watch --srcmap", - "srcDev:build": "cd srcDev && rollup -c && cd ..", "lint": "eslint .", "vscode:prepublish": "nr build", "publish": "vsce publish --no-dependencies", @@ -361,15 +361,20 @@ "release": "bumpp && git push" }, "dependencies": { - "@vue/reactivity": "^3.4.27" + "@vue/reactivity": "^3.4.27", + "ws": "^8.17.0" }, "devDependencies": { "@antfu/eslint-config": "^2.19.1", "@antfu/ni": "^0.21.12", + "@rollup/plugin-commonjs": "^26.0.1", + "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "@types/d3": "^7.4.3", "@types/node": "^20.12.12", + "@types/ts-expose-internals": "npm:ts-expose-internals@5.4.5", "@types/vscode": "1.70.0", + "@types/ws": "^8.5.10", "@vscode/vsce": "^2.26.1", "bumpp": "^9.4.1", "d3": "^7.9.0", @@ -382,7 +387,6 @@ "rollup-plugin-vue": "^6.0.0", "typescript": "^5.4.5", "vitest": "^1.6.0", - "@types/ts-expose-internals": "npm:ts-expose-internals@5.4.5", "zod": "^3.23.8" } } diff --git a/playground/index.ts b/playground/index.ts index cc2ba69..a7a7a32 100644 --- a/playground/index.ts +++ b/playground/index.ts @@ -62,3 +62,6 @@ type MultiLine = typeof multiLine | ` 2 3 4` + +const opts + = { path: '/socket.io/', agent: false, withCredentials: false, upgrade: true, timestampParam: 't', rememberUpgrade: false, addTrailingSlash: true, rejectUnauthorized: false, perMessageDeflate: { threshold: 1024 }, transportOptions: {}, closeOnBeforeunload: false, host: '127.0.0.1', port: '80', hostname: 'undefined', secure: false, query: { EIO: 4, transport: 'polling' }, socket: { binaryType: 'nodebuffer', writeBuffer: [], secure: false, hostname: 'undefined', port: '80', transports: ['polling', 'websocket', 'webtransport'], prevBufferLen: 0, opts: { path: '/socket.io/', agent: false, withCredentials: false, upgrade: true, timestampParam: 't', rememberUpgrade: false, addTrailingSlash: true, rejectUnauthorized: false, perMessageDeflate: { threshold: 1024 }, transportOptions: {}, closeOnBeforeunload: false, host: '127.0.0.1', port: '80', hostname: 'undefined', secure: false }, id: null, upgrades: null, pingInterval: null, pingTimeout: null, pingTimeoutTimer: null, readyState: 'opening' } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 14c8209..dad26c6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@vue/reactivity': specifier: ^3.4.27 version: 3.4.27 + ws: + specifier: ^8.17.0 + version: 8.17.0 devDependencies: '@antfu/eslint-config': specifier: ^2.19.1 @@ -18,6 +21,12 @@ importers: '@antfu/ni': specifier: ^0.21.12 version: 0.21.12 + '@rollup/plugin-commonjs': + specifier: ^26.0.1 + version: 26.0.1(rollup@4.18.0) + '@rollup/plugin-json': + specifier: ^6.1.0 + version: 6.1.0(rollup@4.18.0) '@rollup/plugin-node-resolve': specifier: ^15.2.3 version: 15.2.3(rollup@4.18.0) @@ -33,6 +42,9 @@ importers: '@types/vscode': specifier: 1.70.0 version: 1.70.0 + '@types/ws': + specifier: ^8.5.10 + version: 8.5.10 '@vscode/vsce': specifier: ^2.26.1 version: 2.26.1 @@ -75,25 +87,6 @@ importers: playground: {} - srcDev: - dependencies: - socket.io-client: - specifier: ^4.7.5 - version: 4.7.5 - devDependencies: - '@rollup/plugin-babel': - specifier: ^6.0.4 - version: 6.0.4(@babel/core@7.24.5)(rollup@4.18.0) - '@types/express': - specifier: ^4.17.21 - version: 4.17.21 - express: - specifier: ^4.19.2 - version: 4.19.2 - socket.io: - specifier: ^4.7.5 - version: 4.7.5 - ui: dependencies: '@nuxt/devtools': @@ -1026,22 +1019,18 @@ packages: rollup: optional: true - '@rollup/plugin-babel@6.0.4': - resolution: {integrity: sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==} + '@rollup/plugin-commonjs@25.0.7': + resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} engines: {node: '>=14.0.0'} peerDependencies: - '@babel/core': ^7.0.0 - '@types/babel__core': ^7.1.9 - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + rollup: ^2.68.0||^3.0.0||^4.0.0 peerDependenciesMeta: - '@types/babel__core': - optional: true rollup: optional: true - '@rollup/plugin-commonjs@25.0.7': - resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} - engines: {node: '>=14.0.0'} + '@rollup/plugin-commonjs@26.0.1': + resolution: {integrity: sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} peerDependencies: rollup: ^2.68.0||^3.0.0||^4.0.0 peerDependenciesMeta: @@ -1220,9 +1209,6 @@ packages: resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} - '@socket.io/component-emitter@3.1.2': - resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} - '@stylistic/eslint-plugin-js@2.1.0': resolution: {integrity: sha512-gdXUjGNSsnY6nPyqxu6lmDTtVrwCOjun4x8PUn0x04d5ucLI74N3MT1Q0UhdcOR9No3bo5PGDyBgXK+KmD787A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1292,18 +1278,6 @@ packages: resolution: {integrity: sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==} engines: {node: ^16.14.0 || >=18.0.0} - '@types/body-parser@1.19.5': - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - - '@types/connect@3.4.38': - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - - '@types/cookie@0.4.1': - resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} - - '@types/cors@2.8.17': - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - '@types/d3-array@3.2.1': resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} @@ -1403,18 +1377,9 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/express-serve-static-core@4.19.3': - resolution: {integrity: sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg==} - - '@types/express@4.17.21': - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - '@types/geojson@7946.0.14': resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} - '@types/http-errors@2.0.4': - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - '@types/http-proxy@1.17.14': resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} @@ -1424,30 +1389,15 @@ packages: '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} - '@types/mime@1.3.5': - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/node@20.12.12': resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/qs@6.9.15': - resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} - - '@types/range-parser@1.2.7': - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@types/send@0.17.4': - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - - '@types/serve-static@1.15.7': - resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - '@types/unist@2.0.10': resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} @@ -1460,6 +1410,9 @@ packages: '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + '@types/ws@8.5.10': + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + '@typescript-eslint/eslint-plugin@7.11.0': resolution: {integrity: sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1968,9 +1921,6 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -2028,10 +1978,6 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - base64id@2.0.0: - resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} - engines: {node: ^4.5.0 || >= 5.9} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -2045,10 +1991,6 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -2099,10 +2041,6 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - c12@1.10.0: resolution: {integrity: sha512-0SsG7UDhoRWcuSvKWHaXmu5uNjDCDN3nkQLRL4Q42IlFy+ze58FcCoI3uPwINXinkz7ZinbhEgyzYFw9u9ZV8g==} @@ -2314,17 +2252,6 @@ packages: cookie-es@1.1.0: resolution: {integrity: sha512-L2rLOcK0wzWSfSDA33YR+PUHDG10a8px7rUHKWbGLP4YfbsMed2KFUw5fczvDPbT98DDe3LEzviswl810apTEw==} - cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - - cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - - cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - cookies@0.9.1: resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} engines: {node: '>= 0.8'} @@ -2335,10 +2262,6 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -2754,17 +2677,6 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - engine.io-client@6.5.3: - resolution: {integrity: sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==} - - engine.io-parser@5.2.2: - resolution: {integrity: sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==} - engines: {node: '>=10.0.0'} - - engine.io@6.5.4: - resolution: {integrity: sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==} - engines: {node: '>=10.2.0'} - enhanced-resolve@5.16.1: resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} engines: {node: '>=10.13.0'} @@ -3069,10 +2981,6 @@ packages: exponential-backoff@3.1.1: resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} - express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} - externality@1.0.2: resolution: {integrity: sha512-LyExtJWKxtgVzmgtEHyQtLFpw1KFhQphF9nTG8TpAIVkiI/xQ3FJh75tRFLYl4hkn7BNIIdLJInuDAavX35pMw==} @@ -3109,10 +3017,6 @@ packages: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} - finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -3152,10 +3056,6 @@ packages: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -3261,6 +3161,11 @@ packages: engines: {node: '>=16 || 14 >=14.18'} hasBin: true + glob@10.4.1: + resolution: {integrity: sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==} + engines: {node: '>=16 || 14 >=14.18'} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -3426,10 +3331,6 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -3489,10 +3390,6 @@ packages: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} @@ -3619,6 +3516,10 @@ packages: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} + jackspeak@3.4.0: + resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} + engines: {node: '>=14'} + jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true @@ -3905,9 +3806,6 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -4018,6 +3916,10 @@ packages: resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} engines: {node: '>=16 || 14 >=14.17'} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} @@ -4399,9 +4301,6 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - path-to-regexp@6.2.2: resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==} @@ -4719,10 +4618,6 @@ packages: protocols@2.0.1: resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} @@ -4730,10 +4625,6 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - qs@6.12.1: resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} engines: {node: '>=0.6'} @@ -4754,10 +4645,6 @@ packages: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} @@ -5045,21 +4932,6 @@ packages: smob@1.5.0: resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} - socket.io-adapter@2.5.4: - resolution: {integrity: sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==} - - socket.io-client@4.7.5: - resolution: {integrity: sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==} - engines: {node: '>=10.0.0'} - - socket.io-parser@4.2.4: - resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} - engines: {node: '>=10.0.0'} - - socket.io@4.7.5: - resolution: {integrity: sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==} - engines: {node: '>=10.2.0'} - socks-proxy-agent@8.0.3: resolution: {integrity: sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==} engines: {node: '>= 14'} @@ -5467,10 +5339,6 @@ packages: vite: optional: true - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - unplugin-vue-router@0.7.0: resolution: {integrity: sha512-ddRreGq0t5vlSB7OMy4e4cfU1w2AwBQCwmvW3oP/0IHQiokzbx4hd3TpwBu3eIAFVuhX2cwNQwp1U32UybTVCw==} peerDependencies: @@ -5559,10 +5427,6 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -5822,18 +5686,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.11.0: - resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.17.0: resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} engines: {node: '>=10.0.0'} @@ -5858,10 +5710,6 @@ packages: resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} engines: {node: '>=4.0'} - xmlhttprequest-ssl@2.0.0: - resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==} - engines: {node: '>=0.4.0'} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -7127,20 +6975,23 @@ snapshots: optionalDependencies: rollup: 4.18.0 - '@rollup/plugin-babel@6.0.4(@babel/core@7.24.5)(rollup@4.18.0)': + '@rollup/plugin-commonjs@25.0.7(rollup@4.18.0)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-imports': 7.24.3 '@rollup/pluginutils': 5.1.0(rollup@4.18.0) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 8.1.0 + is-reference: 1.2.1 + magic-string: 0.30.10 optionalDependencies: rollup: 4.18.0 - '@rollup/plugin-commonjs@25.0.7(rollup@4.18.0)': + '@rollup/plugin-commonjs@26.0.1(rollup@4.18.0)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.18.0) commondir: 1.0.1 estree-walker: 2.0.2 - glob: 8.1.0 + glob: 10.4.1 is-reference: 1.2.1 magic-string: 0.30.10 optionalDependencies: @@ -7285,8 +7136,6 @@ snapshots: '@sindresorhus/merge-streams@2.3.0': {} - '@socket.io/component-emitter@3.1.2': {} - '@stylistic/eslint-plugin-js@2.1.0(eslint@9.3.0)': dependencies: '@types/eslint': 8.56.10 @@ -7371,21 +7220,6 @@ snapshots: '@tufjs/canonical-json': 2.0.0 minimatch: 9.0.4 - '@types/body-parser@1.19.5': - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.12.12 - - '@types/connect@3.4.38': - dependencies: - '@types/node': 20.12.12 - - '@types/cookie@0.4.1': {} - - '@types/cors@2.8.17': - dependencies: - '@types/node': 20.12.12 - '@types/d3-array@3.2.1': {} '@types/d3-axis@3.0.6': @@ -7510,24 +7344,8 @@ snapshots: '@types/estree@1.0.5': {} - '@types/express-serve-static-core@4.19.3': - dependencies: - '@types/node': 20.12.12 - '@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 - '@types/express-serve-static-core': 4.19.3 - '@types/qs': 6.9.15 - '@types/serve-static': 1.15.7 - '@types/geojson@7946.0.14': {} - '@types/http-errors@2.0.4': {} - '@types/http-proxy@1.17.14': dependencies: '@types/node': 20.12.12 @@ -7538,31 +7356,14 @@ snapshots: dependencies: '@types/unist': 2.0.10 - '@types/mime@1.3.5': {} - '@types/node@20.12.12': dependencies: undici-types: 5.26.5 '@types/normalize-package-data@2.4.4': {} - '@types/qs@6.9.15': {} - - '@types/range-parser@1.2.7': {} - '@types/resolve@1.20.2': {} - '@types/send@0.17.4': - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.12.12 - - '@types/serve-static@1.15.7': - dependencies: - '@types/http-errors': 2.0.4 - '@types/node': 20.12.12 - '@types/send': 0.17.4 - '@types/unist@2.0.10': {} '@types/vscode-webview@1.57.5': {} @@ -7571,6 +7372,10 @@ snapshots: '@types/web-bluetooth@0.0.20': {} + '@types/ws@8.5.10': + dependencies: + '@types/node': 20.12.12 + '@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.10.0 @@ -8353,8 +8158,6 @@ snapshots: argparse@2.0.1: {} - array-flatten@1.1.1: {} - array-union@2.1.0: {} assertion-error@1.1.0: {} @@ -8415,8 +8218,6 @@ snapshots: base64-js@1.5.1: {} - base64id@2.0.0: {} - binary-extensions@2.3.0: {} bindings@1.5.0: @@ -8432,23 +8233,6 @@ snapshots: readable-stream: 3.6.2 optional: true - body-parser@1.20.2: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - boolbase@1.0.0: {} brace-expansion@1.1.11: @@ -8507,8 +8291,6 @@ snapshots: dependencies: run-applescript: 7.0.0 - bytes@3.1.2: {} - c12@1.10.0: dependencies: chokidar: 3.6.0 @@ -8736,12 +8518,6 @@ snapshots: cookie-es@1.1.0: {} - cookie-signature@1.0.6: {} - - cookie@0.4.2: {} - - cookie@0.6.0: {} - cookies@0.9.1: dependencies: depd: 2.0.0 @@ -8753,11 +8529,6 @@ snapshots: core-util-is@1.0.3: {} - cors@2.8.5: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - crc-32@1.2.2: {} crc32-stream@6.0.0: @@ -9163,37 +8934,6 @@ snapshots: once: 1.4.0 optional: true - engine.io-client@6.5.3: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.4 - engine.io-parser: 5.2.2 - ws: 8.11.0 - xmlhttprequest-ssl: 2.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - engine.io-parser@5.2.2: {} - - engine.io@6.5.4: - dependencies: - '@types/cookie': 0.4.1 - '@types/cors': 2.8.17 - '@types/node': 20.12.12 - accepts: 1.3.8 - base64id: 2.0.0 - cookie: 0.4.2 - cors: 2.8.5 - debug: 4.3.4 - engine.io-parser: 5.2.2 - ws: 8.11.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - enhanced-resolve@5.16.1: dependencies: graceful-fs: 4.2.11 @@ -9608,42 +9348,6 @@ snapshots: exponential-backoff@3.1.1: {} - express@4.19.2: - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - externality@1.0.2: dependencies: enhanced-resolve: 5.16.1 @@ -9685,18 +9389,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - finalhandler@1.2.0: - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -9743,8 +9435,6 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - forwarded@0.2.0: {} - fraction.js@4.3.7: {} fresh@0.5.2: {} @@ -9859,6 +9549,14 @@ snapshots: minipass: 7.1.1 path-scurry: 1.11.1 + glob@10.4.1: + dependencies: + foreground-child: 3.1.1 + jackspeak: 3.4.0 + minimatch: 9.0.4 + minipass: 7.1.2 + path-scurry: 1.11.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -10047,10 +9745,6 @@ snapshots: human-signals@5.0.0: {} - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -10108,8 +9802,6 @@ snapshots: jsbn: 1.1.0 sprintf-js: 1.1.3 - ipaddr.js@1.9.1: {} - iron-webcrypto@1.2.1: {} is-alphabetical@1.0.4: {} @@ -10210,6 +9902,12 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jackspeak@3.4.0: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jiti@1.21.0: {} js-tokens@4.0.0: {} @@ -10545,8 +10243,6 @@ snapshots: media-typer@0.3.0: {} - merge-descriptors@1.0.1: {} - merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -10639,6 +10335,8 @@ snapshots: minipass@7.1.1: {} + minipass@7.1.2: {} + minizlib@2.1.2: dependencies: minipass: 3.3.6 @@ -11246,9 +10944,7 @@ snapshots: path-scurry@1.11.1: dependencies: lru-cache: 10.2.2 - minipass: 7.1.1 - - path-to-regexp@0.1.7: {} + minipass: 7.1.2 path-to-regexp@6.2.2: {} @@ -11534,11 +11230,6 @@ snapshots: protocols@2.0.1: {} - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - pump@3.0.0: dependencies: end-of-stream: 1.4.4 @@ -11547,10 +11238,6 @@ snapshots: punycode@2.3.1: {} - qs@6.11.0: - dependencies: - side-channel: 1.0.6 - qs@6.12.1: dependencies: side-channel: 1.0.6 @@ -11567,13 +11254,6 @@ snapshots: range-parser@1.2.1: {} - raw-body@2.5.2: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - rc9@2.1.2: dependencies: defu: 6.1.4 @@ -11913,47 +11593,6 @@ snapshots: smob@1.5.0: {} - socket.io-adapter@2.5.4: - dependencies: - debug: 4.3.4 - ws: 8.11.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - socket.io-client@4.7.5: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.4 - engine.io-client: 6.5.3 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - socket.io-parser@4.2.4: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - - socket.io@4.7.5: - dependencies: - accepts: 1.3.8 - base64id: 2.0.0 - cors: 2.8.5 - debug: 4.3.4 - engine.io: 6.5.4 - socket.io-adapter: 2.5.4 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - socks-proxy-agent@8.0.3: dependencies: agent-base: 7.1.1 @@ -12414,8 +12053,6 @@ snapshots: - rollup - supports-color - unpipe@1.0.0: {} - unplugin-vue-router@0.7.0(rollup@4.18.0)(vue-router@4.3.2(vue@3.4.27(typescript@5.4.5)))(vue@3.4.27(typescript@5.4.5)): dependencies: '@babel/types': 7.24.5 @@ -12507,8 +12144,6 @@ snapshots: util-deprecate@1.0.2: {} - utils-merge@1.0.1: {} - uuid@8.3.2: {} validate-npm-package-license@3.0.4: @@ -12777,8 +12412,6 @@ snapshots: wrappy@1.0.2: {} - ws@8.11.0: {} - ws@8.17.0: {} xml-name-validator@4.0.0: {} @@ -12790,8 +12423,6 @@ snapshots: xmlbuilder@11.0.1: {} - xmlhttprequest-ssl@2.0.0: {} - y18n@5.0.8: {} yallist@3.1.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index fb8f535..bd13d31 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,4 @@ packages: - playground - - srcDev - ui + - server diff --git a/rollup.config.mjs b/rollup.config.mjs index b804efb..ab308dc 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -1,11 +1,13 @@ import { defineConfig } from 'rollup' import esbuild from 'rollup-plugin-esbuild' import resolve from '@rollup/plugin-node-resolve' +import commonjs from '@rollup/plugin-commonjs' +// import json from '@rollup/plugin-json' import { raw } from './build/raw.mjs' export default defineConfig({ external: ['vscode', 'typescript', /^node:.*/], input: ['./src/index.ts'], output: { format: 'cjs', dir: 'dist' }, - plugins: [esbuild(), raw(), resolve()], + plugins: [esbuild(), raw(), resolve(), commonjs()], }) diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..6905394 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,3 @@ +dist +node_modules +traces diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 0000000..3ea3263 --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,2942 @@ +{ + "name": "ts-trace-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ts-trace-server", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "arktype": "^2.0.0-dev.21", + "express": "^4.19.2", + "install": "^0.13.0", + "prettier": "^3.3.1", + "socket.io": "^4.7.5", + "sqlite": "^5.1.1", + "sqlite3": "^5.1.7", + "ws": "^8.17.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/sqlite3": "^3.1.11", + "@types/ts-expose-internals": "npm:ts-expose-internals@5.4.5", + "@types/ws": "^8.5.10", + "esbuild": "^0.21.4", + "typescript": "^5.4.5" + } + }, + "node_modules/@arktype/schema": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/@arktype/schema/-/schema-0.1.13.tgz", + "integrity": "sha512-qZjtCAKrnhsixDWsEGJtosWfi4bLpAg4OnnICVYTer/6v5hwlhsdYpYobTSJUc5eiBoI5Ai/kcNfYaQISshY2g==", + "dependencies": { + "@arktype/util": "0.0.48" + } + }, + "node_modules/@arktype/util": { + "version": "0.0.48", + "resolved": "https://registry.npmjs.org/@arktype/util/-/util-0.0.48.tgz", + "integrity": "sha512-U5FO5EUAJ4LoYtLSyAMmTf6CEVgslObfSQuua2zoK5Tv2FB3aESVQ3rdLfhuz+coRhlzlynbkmimyoQWwQT+aQ==" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.4.tgz", + "integrity": "sha512-Zrm+B33R4LWPLjDEVnEqt2+SLTATlru1q/xYKVn8oVTbiRBGmK2VIMoIYGJDGyftnGaC788IuzGFAlb7IQ0Y8A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.4.tgz", + "integrity": "sha512-E7H/yTd8kGQfY4z9t3nRPk/hrhaCajfA3YSQSBrst8B+3uTcgsi8N+ZWYCaeIDsiVs6m65JPCaQN/DxBRclF3A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.4.tgz", + "integrity": "sha512-fYFnz+ObClJ3dNiITySBUx+oNalYUT18/AryMxfovLkYWbutXsct3Wz2ZWAcGGppp+RVVX5FiXeLYGi97umisA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.4.tgz", + "integrity": "sha512-mDqmlge3hFbEPbCWxp4fM6hqq7aZfLEHZAKGP9viq9wMUBVQx202aDIfc3l+d2cKhUJM741VrCXEzRFhPDKH3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.4.tgz", + "integrity": "sha512-72eaIrDZDSiWqpmCzVaBD58c8ea8cw/U0fq/PPOTqE3c53D0xVMRt2ooIABZ6/wj99Y+h4ksT/+I+srCDLU9TA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.4.tgz", + "integrity": "sha512-uBsuwRMehGmw1JC7Vecu/upOjTsMhgahmDkWhGLWxIgUn2x/Y4tIwUZngsmVb6XyPSTXJYS4YiASKPcm9Zitag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.4.tgz", + "integrity": "sha512-8JfuSC6YMSAEIZIWNL3GtdUT5NhUA/CMUCpZdDRolUXNAXEE/Vbpe6qlGLpfThtY5NwXq8Hi4nJy4YfPh+TwAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.4.tgz", + "integrity": "sha512-8d9y9eQhxv4ef7JmXny7591P/PYsDFc4+STaxC1GBv0tMyCdyWfXu2jBuqRsyhY8uL2HU8uPyscgE2KxCY9imQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.4.tgz", + "integrity": "sha512-2rqFFefpYmpMs+FWjkzSgXg5vViocqpq5a1PSRgT0AvSgxoXmGF17qfGAzKedg6wAwyM7UltrKVo9kxaJLMF/g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.4.tgz", + "integrity": "sha512-/GLD2orjNU50v9PcxNpYZi+y8dJ7e7/LhQukN3S4jNDXCKkyyiyAz9zDw3siZ7Eh1tRcnCHAo/WcqKMzmi4eMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.4.tgz", + "integrity": "sha512-pNftBl7m/tFG3t2m/tSjuYeWIffzwAZT9m08+9DPLizxVOsUl8DdFzn9HvJrTQwe3wvJnwTdl92AonY36w/25g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.4.tgz", + "integrity": "sha512-cSD2gzCK5LuVX+hszzXQzlWya6c7hilO71L9h4KHwqI4qeqZ57bAtkgcC2YioXjsbfAv4lPn3qe3b00Zt+jIfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.4.tgz", + "integrity": "sha512-qtzAd3BJh7UdbiXCrg6npWLYU0YpufsV9XlufKhMhYMJGJCdfX/G6+PNd0+v877X1JG5VmjBLUiFB0o8EUSicA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.4.tgz", + "integrity": "sha512-yB8AYzOTaL0D5+2a4xEy7OVvbcypvDR05MsB/VVPVA7nL4hc5w5Dyd/ddnayStDgJE59fAgNEOdLhBxjfx5+dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.4.tgz", + "integrity": "sha512-Y5AgOuVzPjQdgU59ramLoqSSiXddu7F3F+LI5hYy/d1UHN7K5oLzYBDZe23QmQJ9PIVUXwOdKJ/jZahPdxzm9w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.4.tgz", + "integrity": "sha512-Iqc/l/FFwtt8FoTK9riYv9zQNms7B8u+vAI/rxKuN10HgQIXaPzKZc479lZ0x6+vKVQbu55GdpYpeNWzjOhgbA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.4.tgz", + "integrity": "sha512-Td9jv782UMAFsuLZINfUpoF5mZIbAj+jv1YVtE58rFtfvoKRiKSkRGQfHTgKamLVT/fO7203bHa3wU122V/Bdg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.4.tgz", + "integrity": "sha512-Awn38oSXxsPMQxaV0Ipb7W/gxZtk5Tx3+W+rAPdZkyEhQ6968r9NvtkjhnhbEgWXYbgV+JEONJ6PcdBS+nlcpA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.4.tgz", + "integrity": "sha512-IsUmQeCY0aU374R82fxIPu6vkOybWIMc3hVGZ3ChRwL9hA1TwY+tS0lgFWV5+F1+1ssuvvXt3HFqe8roCip8Hg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.4.tgz", + "integrity": "sha512-hsKhgZ4teLUaDA6FG/QIu2q0rI6I36tZVfM4DBZv3BG0mkMIdEnMbhc4xwLvLJSS22uWmaVkFkqWgIS0gPIm+A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.4.tgz", + "integrity": "sha512-UUfMgMoXPoA/bvGUNfUBFLCh0gt9dxZYIx9W4rfJr7+hKe5jxxHmfOK8YSH4qsHLLN4Ck8JZ+v7Q5fIm1huErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.4.tgz", + "integrity": "sha512-yIxbspZb5kGCAHWm8dexALQ9en1IYDfErzjSEq1KzXFniHv019VT3mNtTK7t8qdy4TwT6QYHI9sEZabONHg+aw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.4.tgz", + "integrity": "sha512-sywLRD3UK/qRJt0oBwdpYLBibk7KiRfbswmWRDabuncQYSlf8aLEEUor/oP6KRz8KEG+HoiVLBhPRD5JWjS8Sg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz", + "integrity": "sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sqlite3": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@types/sqlite3/-/sqlite3-3.1.11.tgz", + "integrity": "sha512-KYF+QgxAnnAh7DWPdNDroxkDI3/MspH1NMx6m/N/6fT1G6+jvsw4/ZePt8R8cr7ta58aboeTfYFBDxTJ5yv15w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ts-expose-internals": { + "name": "ts-expose-internals", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/ts-expose-internals/-/ts-expose-internals-5.4.5.tgz", + "integrity": "sha512-0HfRwjgSIOyuDlHzkFedMWU4aHWq9pu4MUKHgH75U+L76wCAtK5WB0rc/dAIhulMRcPUlcKONeiiR5Sxy/7XcA==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/arktype": { + "version": "2.0.0-dev.21", + "resolved": "https://registry.npmjs.org/arktype/-/arktype-2.0.0-dev.21.tgz", + "integrity": "sha512-dgHCjb3FK4BGvG2LuXqgdWXstbFmiYowSy0jiKnyk4KVcMT5DyIJ9d1nbQM3ztiAL3hIPmPdkmpfxUqR+BoOBQ==", + "dependencies": { + "@arktype/schema": "0.1.13", + "@arktype/util": "0.0.48" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "optional": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.4.tgz", + "integrity": "sha512-sFMcNNrj+Q0ZDolrp5pDhH0nRPN9hLIM3fRPwgbLYJeSHHgnXSnbV3xYgSVuOeLWH9c73VwmEverVzupIv5xuA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.4", + "@esbuild/android-arm": "0.21.4", + "@esbuild/android-arm64": "0.21.4", + "@esbuild/android-x64": "0.21.4", + "@esbuild/darwin-arm64": "0.21.4", + "@esbuild/darwin-x64": "0.21.4", + "@esbuild/freebsd-arm64": "0.21.4", + "@esbuild/freebsd-x64": "0.21.4", + "@esbuild/linux-arm": "0.21.4", + "@esbuild/linux-arm64": "0.21.4", + "@esbuild/linux-ia32": "0.21.4", + "@esbuild/linux-loong64": "0.21.4", + "@esbuild/linux-mips64el": "0.21.4", + "@esbuild/linux-ppc64": "0.21.4", + "@esbuild/linux-riscv64": "0.21.4", + "@esbuild/linux-s390x": "0.21.4", + "@esbuild/linux-x64": "0.21.4", + "@esbuild/netbsd-x64": "0.21.4", + "@esbuild/openbsd-x64": "0.21.4", + "@esbuild/sunos-x64": "0.21.4", + "@esbuild/win32-arm64": "0.21.4", + "@esbuild/win32-ia32": "0.21.4", + "@esbuild/win32-x64": "0.21.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "optional": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "optional": true + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/install": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", + "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "optional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "optional": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "optional": true + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "optional": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.63.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.63.0.tgz", + "integrity": "sha512-vAszCsOUrUxjGAmdnM/pq7gUgie0IRteCQMX6d4A534fQCR93EJU5qgzBvU6EkFfK27s0T3HEV3BOyJIr7OMYw==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", + "integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==", + "engines": { + "node": "^16 || ^18 || >= 20" + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", + "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "optional": true + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "optional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "optional": true + }, + "node_modules/sqlite": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-5.1.1.tgz", + "integrity": "sha512-oBkezXa2hnkfuJwUo44Hl9hS3er+YFtueifoajrgidvqsJRQFpc5fKoAkAor1O5ZnLoa28GBScfHXs8j0K358Q==" + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/server/package.json b/server/package.json new file mode 100644 index 0000000..e5d4937 --- /dev/null +++ b/server/package.json @@ -0,0 +1,32 @@ +{ + "name": "ts-trace-server", + "version": "1.0.0", + "description": "server for generating and querying ts trace files", + "author": "typeholes", + "license": "MIT", + "main": "index.js", + "scripts": { + "build": "rollup -c", + "dev": "nr build --watch --sourcemap", + "test": "true" + }, + "dependencies": { + "arktype": "^2.0.0-dev.21", + "express": "^4.19.2", + "install": "^0.13.0", + "prettier": "^3.3.1", + "socket.io": "^4.7.5", + "sqlite": "^5.1.1", + "sqlite3": "^5.1.7", + "ws": "^8.17.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/sqlite3": "^3.1.11", + "@types/ts-expose-internals": "npm:ts-expose-internals@5.4.5", + "@types/ws": "^8.5.10", + "esbuild": "^0.21.4", + "typescript": "^5.4.5" + } +} diff --git a/server/rollup.config.mjs b/server/rollup.config.mjs new file mode 100644 index 0000000..aad38b0 --- /dev/null +++ b/server/rollup.config.mjs @@ -0,0 +1,11 @@ +import { defineConfig } from 'rollup' +import esbuild from 'rollup-plugin-esbuild' +import resolve from '@rollup/plugin-node-resolve' +import commonjs from '@rollup/plugin-commonjs' + +export default defineConfig({ + external: [/^node:.*/], + input: ['./src/index.ts'], + output: { format: 'cjs', dir: 'dist' }, + plugins: [esbuild(), resolve(), commonjs()], +}) diff --git a/server/src/commonState.ts b/server/src/commonState.ts new file mode 100644 index 0000000..e69de29 diff --git a/server/src/dbSchema.ts b/server/src/dbSchema.ts new file mode 100644 index 0000000..8d3caec --- /dev/null +++ b/server/src/dbSchema.ts @@ -0,0 +1,96 @@ +// import { Database, Statement } from 'sqlite'; +// import sqlite3 from 'sqlite3'; +// import { +// ZodArray, +// ZodNumber, +// ZodOptional, +// ZodString, +// ZodType, +// ZodObject, +// ZodDefault, +// } from 'zod'; + +// export type DB = Database; + +// export function createSchema(db: DB) {} + +// export const tableColumns = new Map(); + +// export const inserts = new Map< +// string, +// (rec: Record[]) => Promise +// >(); + +// export async function mkInsert(db: DB, tableName: string) { +// const cached = inserts.get(tableName); +// if (cached) return cached; + +// const columns = tableColumns.get(tableName)!; +// const marks = `(${columns.map((x) => '?').join(',')})`; +// const multi = `${marks},`.repeat(19) + marks; +// const sqlStr = `insert into ${tableName} ( ${columns.join( +// ',' +// )} ) values ${multi}`; + +// console.log(sqlStr); +// const sql = await db.prepare(sqlStr); + +// let id = 0; +// const fn = async (recs: Record[]) => { +// const thisId = id++; +// await sql.bind( +// recs +// .map((rec) => columns.map((x) => (x === '"$id"' ? thisId : rec[x]))) +// .flat() +// ); +// sql.run(); +// return thisId; +// }; + +// inserts.set(tableName, fn); +// return fn; +// } + +// export async function createTable( +// db: Database, +// tableName: string, +// zodObject: ZodObject | ZodOptional | ZodDefault, +// parentTables: string[] = [] +// ) { +// const ids = ['id', ...parentTables]; +// const columns: string[] = ids.map((x) => `"$${x}"`); +// tableColumns.set(tableName, columns); + +// const columnsPrefix = ids.map((x) => `"$${x}" number`).join(','); + +// if (zodObject instanceof ZodOptional || zodObject instanceof ZodDefault) { +// createTable(db, tableName, zodObject._def.innerType, parentTables); +// return; +// } +// let sql = `create table if not exists ${tableName} ( ${columnsPrefix}`; +// for (const columnName in zodObject.shape) { +// const type = zodObject.shape[columnName as keyof typeof zodObject.shape]; +// const sqlType = getSqlType(type); +// if (sqlType === 'zodObject') { +// createTable(db, columnName, type, [tableName]); +// } else { +// columns.push(columnName); +// sql += ', ' + columnName + ' ' + getSqlType(type); +// } +// } +// sql += ')'; + +// console.log(sql, '\n'); +// await db.exec(sql); +// await mkInsert(db, tableName); +// } + +// function getSqlType(type: ZodType) { +// if (type instanceof ZodOptional || type instanceof ZodDefault) +// return getSqlType(type._def.innerType); +// if (type instanceof ZodNumber) return 'number'; +// if (type instanceof ZodString) return 'string'; +// if (type instanceof ZodArray) return 'json_array'; +// if (type instanceof ZodObject) return 'zodObject'; +// debugger; +// } diff --git a/server/src/index.ts b/server/src/index.ts new file mode 100644 index 0000000..65b4588 --- /dev/null +++ b/server/src/index.ts @@ -0,0 +1,28 @@ +// import sqlite3 from 'sqlite3'; +// import { open } from 'sqlite'; +// import { typeLine, traceLine } from './traceData'; + +// import * as dbSchema from './dbSchema'; +// import { loadTrace } from './traceDir'; +// import { printTree, runLiveTrace } from './tsTrace'; +import * as server from './server' + +async function main() { + // const db = await open({ + // filename: '/tmp/database.db', + // driver: sqlite3.Database, + // }); + // await db.exec('PRAGMA journal_mode=MEMORY;'); + // // await db.exec('PRAGMA journal_mode=OFF;'); + // await dbSchema.createTable(db, 'TypeLine', typeLine); + // await dbSchema.createTable(db, 'TraceLine', traceLine); + // await db.exec('begin transaction'); + // await loadTrace(); + // await db.exec('end transaction'); + + // runLiveTrace('/home/hw/projects/tracer/playground', '/tmp/tsTrace'); + // printTree(); + server.init() +} + +main() diff --git a/server/src/messages.ts b/server/src/messages.ts new file mode 100644 index 0000000..65cf0ce --- /dev/null +++ b/server/src/messages.ts @@ -0,0 +1,178 @@ +import z from 'zod' +import { typeLine } from './traceData' + +export const ping = z.object({ + message: z.literal('ping'), + text: z.string().optional(), +}) +export type Ping = z.infer + +export const pong = z.object({ + message: z.literal('pong'), +}) +export type Pong = z.infer + +export const gotoPosition = z.object({ + message: z.literal('gotoPosition'), + fileName: z.string(), + pos: z.number(), +}) +export type GotoPosition = z.infer + +export const gotoLocation = z.object({ + message: z.literal('gotoLocation'), + fileName: z.string(), + line: z.number(), + character: z.number(), +}) +export type GotoLocation = z.infer + +export const deleteTraceFile = z.object({ + message: z.literal('deletTraceFile'), + fileName: z.string(), + dirName: z.string(), +}) +export type DeleteTraceFile = z.infer + +export const traceFileLoaded = z.object({ + message: z.literal('traceFileLoaded'), + fileName: z.string(), + dirName: z.string(), + resetFileList: z.boolean().default(false), +}) +export type TraceFileLoaded = z.infer + +export const gotoTracePosition = z.object({ + message: z.literal('gotoTracePosition'), + fileName: z.string(), + position: z.number(), +}) +export type GotoTracePosition = z.infer + +export const positionTypeCounts = z.object({ + message: z.literal('postionTypeCounts'), + counts: z.record(z.string(), z.record(z.string(), z.number())), +}) +export type PositionTypeCounts = z.infer + +export const fileStat = z.object({ + pos: z.number(), + end: z.number(), + dur: z.number(), + types: z.number(), + totalTypes: z.number(), +}) +export type FileStat = z.infer + +export const fileStats = z.object({ + message: z.literal('fileStats'), + fileName: z.string(), + stats: z.array(fileStat), +}) +export type FileStats = z.infer + +export const traceStart = z.object({ + message: z.literal('traceStart'), + projectPath: z.string(), + traceDir: z.string(), +}) +export type TraceStart = z.infer + +export const traceStop = z.object({ + message: z.literal('traceStop'), +}) +export type TraceStop = z.infer + +export const log = z.object({ + message: z.literal('log'), + value: z.array(z.any()), +}) +export type Log = z.infer + +export const filterTree = z.object({ + message: z.literal('filterTree'), + startsWith: z.string(), + sourceFileName: z.string(), + position: z.literal('').or(z.number()), +}) +export type FilterTree = z.infer + +const showTree = z.object({ + message: z.literal('showTree'), + nodes: z.array(z.any()), + step: z.literal('start').or(z.literal('add').or(z.literal('done'))), +}) +export type ShowTree = z.infer + +// TODO: result message for filter tree +// message for getting tree by id and result message + +export const projectOpen = z.object({ + message: z.literal('projectOpen'), + name: z.string(), +}) +export type ProjectOpen = z.infer + +export const saveOpen = z.object({ + message: z.literal('saveOpen'), + name: z.string(), +}) +export type SaveOpen = z.infer + +export const projectNames = z.object({ + message: z.literal('projectNames'), + names: z.array(z.string()), +}) +export type ProjectNames = z.infer + +export const saveNames = z.object({ + message: z.literal('saveNames'), + names: z.array(z.string()), +}) +export type SaveNames = z.infer + +export const childrenById = z.object({ + message: z.literal('childrenById'), + id: z.number(), + children: z.array(z.any()).optional(), +}) +export type ChildrenById = z.infer + +export const typesById = z.object({ + message: z.literal('typesById'), + id: z.number(), + types: z.array(typeLine).optional(), +}) +export type TypesById = z.infer + +export type Message = z.infer +export const message = z.union([ + ping, + pong, + childrenById, + deleteTraceFile, + fileStats, + filterTree, + gotoLocation, + gotoPosition, + gotoTracePosition, + positionTypeCounts, + projectNames, + projectOpen, + saveNames, + saveOpen, + showTree, + traceStart, + traceStop, + traceFileLoaded, + typesById, + log, +]) + +export type MessageType = Message['message'] + +export type SpecificMessage = Message & { message: T } +export type MessageValues = Omit< + SpecificMessage, + 'message' +> diff --git a/server/src/server.ts b/server/src/server.ts new file mode 100644 index 0000000..07efb68 --- /dev/null +++ b/server/src/server.ts @@ -0,0 +1,217 @@ +/* eslint-disable no-console */ +import type { WebSocket } from 'ws' +import { WebSocketServer } from 'ws' + +import * as Messages from './messages' +import type { Tree } from './tsTrace' +import { runLiveTrace, treeRoot } from './tsTrace' + +const wss = new WebSocketServer({ port: 3010 }) + +console.log('listening on 3010') + +wss.on('connection', (ws) => { + console.log('connected') + ws.on('error', console.error) + + ws.on('message', (data) => { + const str = data.toString() + try { + const arr = JSON.parse(str) + if (Array.isArray(arr)) { + const [id, parsed] = arr + if (typeof id !== 'number') { + console.log('invalid message') + console.log(JSON.stringify(arr, null, 2)) + return + } + if (arr.length !== 2) { + console.log('invalid message') + console.log(JSON.stringify(arr, null, 2)) + sendError(ws, id, 'expected a single object payload') + return + } + + if (Array.isArray(parsed)) { + sendError(ws, id, 'expected a single object payload') + console.log('unhandled payload') + for (const item of parsed) console.log(`\t ${item}`) + } + else if (typeof parsed === 'object') { + receiveMessage(id, parsed, ws) + } + } + else { + console.log(`string payload ${JSON.stringify(arr, null, 2)}`) + } + } + catch (_e) { + console.log(`non message payload ${str}`) + } + }) +}) + +export function init() {} + +// let messageHandler = (message: any) => console.log(message); +// export function setMessageHandler(handler: (message: any) => void) { +// messageHandler = handler; +// } + +// export function emitMessage(message: any) { +// globalSocket?.emit(message.message, message); +// } + +/* +io.on('connection', (socket) => { + globalSocket = socket; // dumb but good enough. latest connection get's the vscode emits + console.log('a user connected'); + messageHandler('init client'); + socket.on('message', (...args: any[]) => { + receiveMessage(args, socket); + }); + socket.on('ping', () => { + console.log('pinged'); + socket.emit('pong'); + }); +}); + +server.listen(3010, 'localhost', () => { + console.log('server running at http://localhost:3010'); +}); + +*/ +function receiveMessage(id: number, args: unknown, ws: WebSocket) { + const parsed = Messages.message.safeParse(args) + if (parsed.error) { + console.log(JSON.stringify(args, null, 2)) + return + } + + switch (parsed.data.message) { + case 'traceStart': { + runLiveTrace(parsed.data.projectPath, parsed.data.traceDir) + const response: Messages.Message = { message: 'traceStop' } + sendResponse(ws, id, response) + break + } + + case 'filterTree': { + const { startsWith, sourceFileName, position } = parsed.data + const roots = filterTree(startsWith, sourceFileName, position) + showTree(ws, id, roots) + } + } +} + +export function filterTree( + startsWith: string, + sourceFileName: string, + position: number | '', + tree = treeRoot, +): Tree[] { + if (position === '') + position = 0 + + if (!tree) + return [] + + if ( + 'name' in tree.line + && tree.line.name.startsWith(startsWith) + && (!sourceFileName + || (tree.line.args?.path ?? '').endsWith(sourceFileName)) + && (!(position > 0) || (tree.line.args?.pos ?? 0) === position) + ) { + return [tree] + } + + return tree.children + .map(child => filterTree(startsWith, sourceFileName, position, child)) + .flat() +} + +export const treeIdNodes = new Map() +let showTreeInterval: undefined | ReturnType +export function showTree(ws: WebSocket, requestId: number, nodes: Tree[]) { + if (showTreeInterval) { + clearInterval(showTreeInterval) + showTreeInterval = undefined + } + + // TODO: parent should be a node id + const skinnyNodes = nodes.map(x => ({ + ...x, + parent: undefined, + children: [], + types: [], + })) + + sendResponse( + ws, + requestId, + { + message: 'showTree', + nodes: [], + step: 'start', + }, + false, + ) + + let i = 0 + + // this can be large enough to freeze the UI if sent at once + showTreeInterval = setInterval(() => { + if (!showTreeInterval) + return + + sendResponse( + ws, + requestId, + { + message: 'showTree', + nodes: skinnyNodes.slice(i, i + 10), + step: 'add', + }, + false, + ) + + i += 10 + if (i >= skinnyNodes.length) { + clearInterval(showTreeInterval) + showTreeInterval = undefined + sendResponse( + ws, + requestId, + { + message: 'showTree', + nodes: [], + step: 'done', + }, + true, + ) + } + }, 30) + + nodes.forEach(node => treeIdNodes.set(node.id, node)) + return nodes +} + +function sendResponse( + ws: WebSocket, + id: number, + response: Messages.Message, + complete = true, +) { + ws.send( + JSON.stringify([id, response, complete ? 'complete' : 'incomplete']), + ) +} + +function sendError(ws: WebSocket, id: number, errorMessage: string) { + ws.send(JSON.stringify([id, 'error', errorMessage])) +} + +// function sendMessage(ws: WebSocket, message: Messages.Message) { +// ws.send(JSON.stringify(message)) +// } diff --git a/server/src/traceData.ts b/server/src/traceData.ts new file mode 100644 index 0000000..2a8748d --- /dev/null +++ b/server/src/traceData.ts @@ -0,0 +1,41 @@ +import { z } from 'zod' + +export type TypeLine = z.infer +export const typeLine = z.object({ + id: z.number(), + intrinsicName: z.string().optional(), + recursionId: z.number().optional(), + flags: z.array(z.string()).optional(), + ts: z.number().default(0).optional(), + dur: z.number().optional(), + display: z.string().optional(), +}) + +export type TraceLine = z.infer +export const traceLine = z.object({ + pid: z.number(), + tid: z.number(), + ph: z.string(), + cat: z.string(), + ts: z.number(), + name: z.string(), + dur: z.number().optional(), + args: z + .object({ + kind: z.number().optional(), + pos: z.number().optional(), + end: z.number().optional(), + path: z.string().optional(), + results: z + .object({ + typeId: z.number().optional(), + }) + .optional(), + }) + .optional(), +}) + +export type DataLine = TraceLine | TypeLine + +export type TraceData = z.infer +export const traceData = z.array(typeLine.or(traceLine)) diff --git a/server/src/traceDir.ts b/server/src/traceDir.ts new file mode 100644 index 0000000..607c095 --- /dev/null +++ b/server/src/traceDir.ts @@ -0,0 +1,35 @@ +import { mkdirSync, readFileSync } from 'node:fs' +import { join } from 'node:path' +import { traceLine } from './traceData' +import { inserts } from './dbSchema' + +const traceDir = '/tmp/tsTrace/' // TODO: read from command line + +mkdirSync(traceDir, { recursive: true }) + +export async function loadTrace() { + const insert = inserts.get('TraceLine')! + + const traceStr = readFileSync(join(traceDir, 'trace.json')).toString() + const traceJson = JSON.parse(traceStr) + const arr = [] + let i = 0 + let statementsRan = 0 + if (Array.isArray(traceJson)) { + for (const line of traceJson) { + const parsed = traceLine.safeParse(line) + if (parsed.data) { + const mod = i % 20 + arr[mod] = parsed.data + if (i > 0 && mod === 0) { + await insert(arr) + statementsRan++ + } + i++ + + // await insert(parsed.data); + } + } + } + console.log(`trace lines inserted: ${i} in ${statementsRan} inserts`) +} diff --git a/server/src/tsTrace.ts b/server/src/tsTrace.ts new file mode 100644 index 0000000..35579e4 --- /dev/null +++ b/server/src/tsTrace.ts @@ -0,0 +1,311 @@ +import { performance } from 'node:perf_hooks' + +import type { + BuilderProgram, + CompilerHost, + CompilerOptions, + CreateProgramOptions, + Diagnostic, + DiagnosticReporter, + ExtendedConfigCacheEntry, + ParseConfigFileHost, + ParsedCommandLine, + PrinterOptions, + Program, + System, + Type, +} from 'typescript' +import { + JSDocParsingMode, + NewLineKind, + combinePaths, + createGetCanonicalFileName, + createGetSourceFile, + createProgram, + createWriteFileMeasuringIO, + emitFilesAndReportErrorsAndGetExitStatus, + findConfigFile, + getConfigFileParsingDiagnostics, + getDefaultLibFileName, + getDirectoryPath, + getParsedCommandLineOfConfigFile, + maybeBind, + memoize, + startTracing, + sys, + tracing, +} from 'typescript' + +export type ExecuteCommandLineCallbacks = ( + program: Program | BuilderProgram | ParsedCommandLine +) => void + +let program: Program | undefined +export function getProgram() { + return program +} + +let lastTreeId = 0 +const typeDictionary = new Map() +export interface Tree { + id: number + parent: Tree | undefined + line: any + children: Tree[] + typeIds: number[] +} +export const treeRoot: Tree = { + id: lastTreeId++, + parent: undefined, + line: { name: 'root', ts: performance.now() }, + children: [], + typeIds: [], +} +let tree = treeRoot + +export function printTree() { + console.log( + JSON.stringify(tree, (k, v) => (k === 'parent' ? undefined : v), 2), + ) +} + +export function getTypeDictionary() { + return typeDictionary +} + +// TODO: see src/compiler/path.ts:632 +function normalizePath(path: string) { + return path +} + +export function runLiveTrace(projectDirectory: string, traceDir: string) { + const searchPath = normalizePath(projectDirectory) + const configFileName = findConfigFile(searchPath, fileName => + sys.fileExists(fileName)) + const reportDiagnostic = (_diagnostic: Diagnostic) => { + console.log(`${_diagnostic.messageText}`) + } + + if (configFileName) { + const extendedConfigCache = new Map() + const configParseResult = getParsedCommandLineOfConfigFile( + configFileName, + {}, + sys as unknown as ParseConfigFileHost, + extendedConfigCache, + {}, + ) + if (!configParseResult) + throw new Error('undefined configParseResult') + // const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, extendedConfigCache, commandLine.watchOptions, sys, reportDiagnostic)! // TODO: GH#18217 + + program = performCompilation( + sys, + reportDiagnostic, + configParseResult, + traceDir, + ) + + // writeTypeTimestamps(typeTimestamps); + return program + } +} + +const defaultJSDocParsingMode = JSDocParsingMode.ParseForTypeErrors + +function performCompilation( + sys: System, + reportDiagnostic: DiagnosticReporter, + config: ParsedCommandLine, + traceDir: string, +) { + const { fileNames, options, projectReferences } = config + options.generateTrace = traceDir + const host = createCompilerHostWorker( + options, + /* setParentNodes */ undefined, + sys, + ) + host.jsDocParsingMode = defaultJSDocParsingMode + // const currentDirectory = host.getCurrentDirectory() + // const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()) + // changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName)) + enableTracing(sys, options, /* isBuildMode */ false) + + config.options.noEmit = true + + const programOptions: CreateProgramOptions = { + rootNames: fileNames, + options, + projectReferences, + host, + configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config), + } + const program = createProgram(programOptions) + emitFilesAndReportErrorsAndGetExitStatus( + program, + reportDiagnostic, + s => sys.write(s + sys.newLine), + (a, b) => { + if (b) { + b.forEach((c) => { + // console.log(`error at: ${c?.fileName}: ${c?.line}`); + }) + } + }, // createReportErrorSummary(sys, options), + ) + + tracing?.stopTracing() + return program +} + +export function createCompilerHostWorker( + options: CompilerOptions, + setParentNodes?: boolean, + system: System = sys, +): CompilerHost { + const existingDirectories = new Map() + const getCanonicalFileName = createGetCanonicalFileName( + system.useCaseSensitiveFileNames, + ) + function directoryExists(directoryPath: string): boolean { + if (existingDirectories.has(directoryPath)) { + return true + } + if ((sys.directoryExists || system.directoryExists)(directoryPath)) { + existingDirectories.set(directoryPath, true) + return true + } + return false + } + + function getDefaultLibLocation(): string { + return getDirectoryPath(normalizePath(system.getExecutingFilePath())) + } + + const newLine = getNewLineCharacter(options) + const realpath + = system.realpath && ((path: string) => system.realpath!(path)) + const compilerHost: CompilerHost = { + getSourceFile: createGetSourceFile( + fileName => compilerHost.readFile(fileName), + () => options, + setParentNodes, + ), + getDefaultLibLocation, + getDefaultLibFileName: options => + combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)), + writeFile: createWriteFileMeasuringIO( + (path, data, writeByteOrderMark) => + system.writeFile(path, data, writeByteOrderMark), + path => + (compilerHost.createDirectory || system.createDirectory)(path), + path => directoryExists(path), + ), + getCurrentDirectory: memoize(() => system.getCurrentDirectory()), + useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames, + getCanonicalFileName, + getNewLine: () => newLine, + fileExists: fileName => system.fileExists(fileName), + readFile: fileName => system.readFile(fileName), + trace: (s: string) => system.write(s + newLine), + directoryExists: directoryName => system.directoryExists(directoryName), + getEnvironmentVariable: name => + system.getEnvironmentVariable + ? system.getEnvironmentVariable(name) + : '', + getDirectories: (path: string) => system.getDirectories(path), + realpath, + readDirectory: (path, extensions, include, exclude, depth) => + system.readDirectory(path, extensions, include, exclude, depth), + createDirectory: d => system.createDirectory(d), + createHash: maybeBind(system, system.createHash), + } + return compilerHost +} + +const carriageReturnLineFeed = '\r\n' +const lineFeed = '\n' +export function getNewLineCharacter( + options: CompilerOptions | PrinterOptions, +): string { + switch (options.newLine) { + case NewLineKind.CarriageReturnLineFeed: + return carriageReturnLineFeed + case NewLineKind.LineFeed: + case undefined: + return lineFeed + } +} + +function canTrace(system: System, compilerOptions: CompilerOptions) { + return system === sys && compilerOptions.generateTrace +} + +// TODO: do not call the held record type and just fetch the types by id from the program as needed +function enableTracing( + system: System, + compilerOptions: CompilerOptions, + isBuildMode: boolean, +) { + if (canTrace(system, compilerOptions)) { + typeDictionary.clear() + + startTracing( + isBuildMode ? 'build' : 'project', + compilerOptions.generateTrace!, + compilerOptions.configFilePath, + ) + if (tracing) { + const holdRecordType = tracing.recordType + tracing.recordType = (type: Type) => { + // typeTimestamps.set(type.id, 1000 * timestamp()); + if (typeDictionary.size === 0) + holdRecordType(type) // need one or ts crashes + typeDictionary.set(type.id, type) + tree.typeIds.push(type.id) + } + + tracing.instant = (phase: string, name: string, args?: object) => { + tree.children.push({ + id: lastTreeId++, + parent: tree, + line: { + phase, + name, + args, + ts: performance.now(), + }, + children: [], + typeIds: [], + }) + } + + tracing.push = ( + phase: string, + name: string, + args?: object, + separateBeginAndEnd = false, + ) => { + const child: Tree = { + id: lastTreeId++, + parent: tree, + line: { phase, name, args, ts: performance.now() }, + children: [], + typeIds: [], + } + tree.children.push(child) + tree = child + } + + tracing.pop = (results?: object) => { + if (!tree.parent) { + throw new Error('Tree over popped') + } + tree = tree.parent + tree.line.results = results ?? {} + tree.line.dur = performance.now() - tree.line.ts + } + } + } +} diff --git a/srcDev/tsconfig.json b/server/tsconfig.json similarity index 50% rename from srcDev/tsconfig.json rename to server/tsconfig.json index 3f7a417..995d43a 100644 --- a/srcDev/tsconfig.json +++ b/server/tsconfig.json @@ -1,20 +1,18 @@ { "compilerOptions": { "target": "es2017", - "lib": ["esnext", "DOM"], + "lib": ["esnext"], + "rootDir": "src", "module": "ESNext", - "moduleResolution": "Bundler", + "moduleResolution": "node", + "resolveJsonModule": true, "strict": true, "strictNullChecks": true, - "declaration": true, - "declarationDir": "dist/server/", - "emitDeclarationOnly": true, - "outDir": "dist/server/", + "outDir": "dist", + "sourceMap": true, "esModuleInterop": true, "skipDefaultLibCheck": true, "skipLibCheck": true, "noErrorTruncation": true - }, - "files": ["src/server.ts"], - "exclude": [] + } } diff --git a/shared/src/messages.ts b/shared/src/messages.ts index 70c04e7..ec203ec 100644 --- a/shared/src/messages.ts +++ b/shared/src/messages.ts @@ -74,6 +74,8 @@ export type FileStats = z.infer export const traceStart = z.object({ message: z.literal('traceStart'), + projectPath: z.string(), + traceDir: z.string(), }) export type TraceStart = z.infer @@ -110,7 +112,9 @@ const zodTree: z.ZodType = z.lazy(() => const showTree = z.object({ message: z.literal('showTree'), - nodes: z.array(zodTree), + nodes: z.array(z.any()), + // TODO: type nodes correctly + // nodes: z.array(zodTree), step: z.literal('start').or(z.literal('add').or(z.literal('done'))), }) export type ShowTree = z.infer diff --git a/src/appState.ts b/src/appState.ts index b37c324..d2a3c88 100644 --- a/src/appState.ts +++ b/src/appState.ts @@ -8,6 +8,7 @@ import { getTracePanel, isTraceViewAlive, postMessage } from './webview' import { getProjectName, getWorkspacePath } from './storage' import { setStatusBarState } from './statusBar' import { sendTraceDir } from './commands' +import type { Tree } from './traceTree' export const afterWatches = nextTick @@ -26,6 +27,8 @@ export const traceRunning = ref(false) export const tracePath = ref('') +export const treeRoots = ref([] as Tree[]) + export const state = { workspacePath, projectName, @@ -37,6 +40,7 @@ export const state = { traceFiles, traceRunning, tracePath, + treeRoots, } as const type State = typeof state type StateType = State[K] extends Ref ? UnwrapRef : State[K] @@ -133,7 +137,10 @@ export async function initAppState(extensionContext: vscode.ExtensionContext) { }) watchT('traceRunning', (running: boolean) => setStatusBarState('tracing', running), (running: boolean) => { - postMessage({ message: running ? 'traceStart' : 'traceStop' }) + if (running) + postMessage({ message: 'traceStart', projectPath: projectPath.value, traceDir: '' }) + else + postMessage({ message: 'traceStop' }) }) workspacePath.value = getWorkspacePath() diff --git a/src/client/actions.ts b/src/client/actions.ts new file mode 100644 index 0000000..2b92614 --- /dev/null +++ b/src/client/actions.ts @@ -0,0 +1,37 @@ +import { log } from 'node:console' +import * as vscode from 'vscode' +import { state, traceRunning } from '../appState' +import { setStatusBarState } from '../statusBar' +import type { Tree } from '../traceTree' +import { postMessage } from '../webview' +import { wsMessage } from './client' + +export function runTrace(projectPath: string, traceDir: string) { + wsMessage('traceStart', { projectPath, traceDir }) ( + 'traceStop', + () => traceRunning.value = false, + (error: string) => { + traceRunning.value = false + setStatusBarState('traceError', true) + vscode.window.showErrorMessage(error) + }, + ) +} + +export function filterTree(startsWith: string, sourceFileName: string, position: number, updateUi: boolean) { + const treeRoots: Tree[] = [] + wsMessage('filterTree', { startsWith, sourceFileName, position }) ( + 'showTree', + (message, complete) => { + treeRoots.push(...message.nodes) + if (updateUi) + postMessage(message) + + if (complete) + state.treeRoots.value = treeRoots + }, + (error: string) => { + log(`error filtering tree: ${error}`) + }, + ) +} diff --git a/src/client/client.ts b/src/client/client.ts new file mode 100644 index 0000000..5506656 --- /dev/null +++ b/src/client/client.ts @@ -0,0 +1,122 @@ +import { log } from 'node:console' +import WebSocket from 'ws' +import * as Messages from '../../shared/src/messages' +import type { MessageType, MessageValues } from '../../shared/src/messages' +import { handleMessage } from '../handleMessages' + +// TODO: auto reconnect + +// eslint-disable-next-line import/no-mutable-exports +export let send = (_payload: unknown) => {} +export function initClient() { + const ws = new WebSocket('ws://localhost:3010') + + send = (payload: unknown) => { + if (typeof payload === 'string') { + payload = [payload] + } + ws.send(JSON.stringify(payload)) + } + + ws.on('error', console.error) + + ws.on('open', () => { + send('ping') + }) + + ws.on('pong', (data) => { + log('pong: %s', data) + }) + + ws.on('message', (data: WebSocket.RawData[]) => { + const str = data.toString() + try { + const arr = JSON.parse(str) + if (Array.isArray(arr)) { + const id = arr[0] + if (typeof id !== 'number') { + log('invalid message') + log(JSON.stringify(arr, null, 2)) + return + } + + if (arr.length === 3) { + if (arr[1] === 'error' && typeof arr[2] === 'string') { + handleResponseError(id, arr[2]) + } + else if (!Array.isArray(arr[1]) && typeof arr[1] == 'object' && arr[1] && (arr[2] === 'complete' || arr[2] === 'incomplete')) { + handleResponse(id, arr[1], arr[2] === 'complete') + } + else { + log(`invalid error payload ${str}`) + } + return + } + + if (arr.length === 1) { + if (Array.isArray(arr[0]) || typeof arr[0] !== 'object' || !arr[0]) { + log(`invalid response payload ${str}`) + return handleMessage(arr[0]) + } + + log(`unhandled payload ${str}`) + } + } + else { + log(`unhandled payload ${str}`) + } + } + catch (_e) { + log(`non message payload ${str}`) + } + }) +} + +const responseHandlers: ([MessageType, ((message: Messages.Message, complete: boolean) => void), (error: string) => void] | undefined)[] = [] +let responseIdx = 0 +export function wsMessage(type: T, value: MessageValues) { + send([responseIdx, { ...value, message: type }]) + const ret = (type: H, handler: (values: Messages.SpecificMessage, complete: boolean) => void, errorHandler: (error: string) => void) => { + function runHandler(message: Messages.SpecificMessage, complete: boolean) { + handler(message, complete) + } + responseHandlers[responseIdx] = [type, runHandler as any, errorHandler] + responseIdx = (responseIdx + 1) % 1000 + } + return ret +} + +function handleResponse(handlerIdx: number, message: object, complete: boolean) { + const [expectedType, handler] = responseHandlers[handlerIdx] ?? [] + if (!handler) { + log('response handler was not defined or the response was already handled') + return + } + + if (complete) + responseHandlers[handlerIdx] = undefined + + const parsed = Messages.message.safeParse(message) + if (!parsed.success) { + log('response payload was not a message object') + return + } + + if (expectedType !== parsed.data.message) { + log(`response type ${parsed.data.message} did not match expected type ${expectedType}`) + return + } + + handler(parsed.data, complete) +} + +function handleResponseError(handlerIdx: number, message: string) { + const handler = responseHandlers[handlerIdx]?.[2] + if (!handler) { + log('response error handler was not defined or the response was already handled') + return + } + + responseHandlers[handlerIdx] = undefined + handler(message) +} diff --git a/src/commands.ts b/src/commands.ts index ab0aa98..b3dc686 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -13,7 +13,7 @@ import { addTraceFile, getWorkspacePath, openTerminal, openTraceDirectoryExterna import { addTraceDiagnostics, clearTaceDiagnostics } from './traceDiagnostics' import { setStatusBarState } from './statusBar' import { afterWatches, projectPath, saveName, state, traceFiles, traceRunning } from './appState' -import { runLiveTrace } from './tsTrace' +import * as actions from './client/actions' const readdir = promisify(readdirC) @@ -133,20 +133,12 @@ async function runTrace(args?: unknown[]) { return } - if (liveTrace) { - try { - runLiveTrace(workspacePath, traceDir) - setStatusBarState('traceError', false) - } - catch (e) { - vscode.window.showErrorMessage('live trace failed') - log(`${e}`) - setStatusBarState('traceError', true) - } - setStatusBarState('tracing', false) - state.traceRunning.value = false + traceRunning.value = true - await sendTraceDir(traceDir) + // TODO: move after trace logic to response from startTrace + if (liveTrace) { + actions.runTrace(workspacePath, traceDir) + actions.filterTree('checkExpr', '', 0, true) } else { const quotedTraceDir = `'${traceDir}'` diff --git a/src/handleMessages.ts b/src/handleMessages.ts index cd5035e..4b5375e 100644 --- a/src/handleMessages.ts +++ b/src/handleMessages.ts @@ -7,7 +7,7 @@ import { postMessage } from './webview' import { deleteTraceFiles, setLastMessageTrigger } from './storage' import { state, triggerAll } from './appState' -export function handleMessage(panel: vscode.WebviewPanel, message: unknown): void { +export function handleMessage(message: unknown): void { if (message === 'init client') { triggerAll(false, true) showTree('check', '', 0) diff --git a/src/index.ts b/src/index.ts index ced41cc..3f868dc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,7 @@ import { initDiagnostics } from './traceDiagnostics' import { initWebviewPanel } from './webview' import { initStatusBar } from './statusBar' import { initAppState } from './appState' +import { initClient } from './client/client' let ts: typeof import('typescript') let tsPath: string @@ -29,6 +30,7 @@ export async function activate(context: vscode.ExtensionContext) { log('============extension activated============') initAppState(context) + initClient() updateConfig({ force: ['typescriptPathMode'] }) diff --git a/src/storage.ts b/src/storage.ts index 7f2216b..502ad95 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -2,7 +2,6 @@ import { existsSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync import { join } from 'node:path' import { env } from 'node:process' import * as vscode from 'vscode' -import { traceData } from '../shared/src/traceData' import { getCurrentConfig } from './configuration' import { log } from './logger' import { state } from './appState' diff --git a/src/tsTrace.ts b/src/tsTrace.ts index 70c623f..cbee273 100644 --- a/src/tsTrace.ts +++ b/src/tsTrace.ts @@ -1,5 +1,5 @@ import type { BuilderProgram, CompilerHost, CompilerOptions, CreateProgramOptions, Diagnostic, DiagnosticReporter, ExtendedConfigCacheEntry, ParseConfigFileHost, ParsedCommandLine, PrinterOptions, Program, System, Type } from 'typescript' -import { JSDocParsingMode, NewLineKind, combinePaths, createGetCanonicalFileName, createGetSourceFile, createProgram, createWriteFileMeasuringIO, diagnosticToString, emitFilesAndReportErrorsAndGetExitStatus, findConfigFile, getConfigFileParsingDiagnostics, getDefaultLibFileName, getDirectoryPath, getParsedCommandLineOfConfigFile, maybeBind, memoize, programContainsEsModules, startTracing, sys, timestamp, tracing } from 'typescript' +import { JSDocParsingMode, NewLineKind, combinePaths, createGetCanonicalFileName, createGetSourceFile, createProgram, createWriteFileMeasuringIO, emitFilesAndReportErrorsAndGetExitStatus, findConfigFile, getConfigFileParsingDiagnostics, getDefaultLibFileName, getDirectoryPath, getParsedCommandLineOfConfigFile, maybeBind, memoize, startTracing, sys, timestamp, tracing } from 'typescript' import { readTypeTimestamps, writeTypeTimestamps } from './storage' import { log } from './logger' diff --git a/src/webview.ts b/src/webview.ts index 77574b1..6667e0e 100644 --- a/src/webview.ts +++ b/src/webview.ts @@ -1,5 +1,4 @@ import { join } from 'node:path' -import { env } from 'node:process' import * as vscode from 'vscode' @@ -12,9 +11,8 @@ import type { Message } from '../shared/src/messages' import { noop, watchT } from './appState' import { handleMessage } from './handleMessages' import { logMessage } from './storage' -import { log } from './logger' -let devEmitter = (_message: any) => {} +function devEmitter(_message: any) {} let panel: undefined | ReturnType let disposed = true @@ -26,24 +24,6 @@ export function initWebviewPanel(extensionContext: vscode.ExtensionContext) { panel.title = `Trace Viewer - ${name}` }, noop) holdContext = extensionContext - - // You have to export TRACER_DEV from your shell source file - // annoying, but I haven't found any other way to get the launcher to pass an env variable through - const isDev = env.env && (env.env as any).TRACER_DEV - // eslint-disable-next-line node/prefer-global/process - const isDev2 = process.env.TRACER_DEV - if (isDev || isDev2) { - log('starting dev server') - // eslint-disable-next-line ts/prefer-ts-expect-error - // @ts-ignore types may not be generated - import('../srcDev/dist/server/server').then((server) => { - devEmitter = server.emitMessage - server.setMessageHandler((message: any) => handleMessage(getTracePanel(), message)) - }) - } - else { - log('skipping dev server') - } } export function isTraceViewAlive() { @@ -89,7 +69,7 @@ export function prepareWebView(context: vscode.ExtensionContext | undefined = ho panel.webview.html = processedHTML panel.webview.onDidReceiveMessage((message) => { - handleMessage(getTracePanel(context), message) + handleMessage(message) }) ret = panel diff --git a/srcDev/.vscode/settings.json b/srcDev/.vscode/settings.json deleted file mode 100644 index 209cd26..0000000 --- a/srcDev/.vscode/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "eslint.format.enable": true, - "eslint.experimental.useFlatConfig": true, - "editor.codeActionsOnSave": { - "source.fixAll": "explicit" - } -} diff --git a/srcDev/eslint.config.mjs b/srcDev/eslint.config.mjs deleted file mode 100644 index 3556d65..0000000 --- a/srcDev/eslint.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -import antfu from '@antfu/eslint-config' - -export default antfu({ - stylistic: true, -}) diff --git a/srcDev/package.json b/srcDev/package.json deleted file mode 100644 index fd8c97f..0000000 --- a/srcDev/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "srcdev", - "version": "1.0.0", - "description": "internal package for dev and testing", - "author": "", - "license": "MIT", - "main": "server.js", - "scripts": { - "build": "tsc && esbuild --bundle src/index.ts --outdir=dist/client --sourcemap --platform=browser && rollup -c --sourcemap", - "dev": "tsc && rollup -c && esbuild --bundle src/index.ts --outdir=dist/client --sourcemap --platform=browser --watch" - }, - "dependencies": { - "socket.io-client": "^4.7.5" - }, - "devDependencies": { - "@rollup/plugin-babel": "^6.0.4", - "@types/express": "^4.17.21", - "express": "^4.19.2", - "socket.io": "^4.7.5" - } -} diff --git a/srcDev/public/index.html b/srcDev/public/index.html deleted file mode 100644 index bd51399..0000000 --- a/srcDev/public/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - dev UI shim - - - - - - - diff --git a/srcDev/rollup.config.mjs b/srcDev/rollup.config.mjs deleted file mode 100644 index 589803e..0000000 --- a/srcDev/rollup.config.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from 'rollup' -import esbuild from 'rollup-plugin-esbuild' - -export default defineConfig([ - { - external: [/^node:.*/], - input: ['./src/server.ts'], - output: { format: 'cjs', dir: 'dist/server' }, - plugins: [esbuild()], - }, -]) diff --git a/srcDev/src/index.ts b/srcDev/src/index.ts deleted file mode 100644 index 7a04427..0000000 --- a/srcDev/src/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { io } from 'socket.io-client' - -export const socket = io({ port: 3010, host: 'localhost' }) - -// const devBtn = document.getElementById('devBtn') as HTMLButtonElement - -const iframe = document.getElementById('dev') as HTMLIFrameElement - -socket.onAny((name: string, ...args: any[]) => { - const message = { ...(args[0] as object), message: name } - iframe.contentWindow?.postMessage(message, '*') -}) - -window.addEventListener('message', (e) => { - socket.emit(e.data.message, e.data) -}) diff --git a/srcDev/src/server.ts b/srcDev/src/server.ts deleted file mode 100644 index a102ca0..0000000 --- a/srcDev/src/server.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* eslint-disable no-console */ -import { createServer } from 'node:http' -import { join } from 'node:path' -import express from 'express' -import { Server, type Socket } from 'socket.io' - -const app = express() -const server = createServer(app) -const io = new Server(server) - -let globalSocket: Socket - -// const __dirname = dirname(fileURLToPath(import.meta.url)) -console.log({ __dirname }) - -let messageHandler = (message: any) => console.log(message) -export function setMessageHandler(handler: (message: any) => void) { - messageHandler = handler -} - -export function emitMessage(message: any) { - globalSocket?.emit(message.message, message) -} - -app.get('/', (req, res) => { - res.sendFile(join(__dirname, '..', 'srcDev', 'public', 'index.html')) -}) - -app.get('/index.js', (req, res) => { - res.sendFile(join(__dirname, '..', 'srcDev', 'dist', 'client', 'index.js')) -}) - -app.get('/index.js.map', (req, res) => { - res.sendFile(join(__dirname, '..', 'srcDev', 'dist', 'client', 'index.js.map')) -}) - -io.on('connection', (socket) => { - globalSocket = socket // dumb but good enough. latest connection get's the vscode emits - console.log('a user connected') - messageHandler('init client') - socket.onAny((name, ...args: any[]) => { - console.log('message from client', name, args) - messageHandler({ ...args[0], message: name }) - }) - socket.on('ping', () => { - console.log('pinged') - socket.emit('pong') - }) -}) - -server.listen(3010, () => { - console.log('server running at http://localhost:3010') -}) diff --git a/tsconfig.json b/tsconfig.json index 4747e00..9ec7421 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,6 +19,7 @@ "node_modules", "ui", "devUiDriver", - "srcDev" + "srcDev", + "server" ] } From 7e2aec54b0afd4e1c65778d1bb2a8fbb70f51d41 Mon Sep 17 00:00:00 2001 From: typeholes Date: Sat, 8 Jun 2024 19:32:33 -0400 Subject: [PATCH 06/24] (WIP) moving functionality to server --- server/src/serverState.ts | 5 + server/src/traceMetrics.ts | 81 +++++++++++ server/src/tsTrace.ts | 236 ++++++++++++++++++++++++++++---- server/tsconfig.json | 1 - shared/src/messages.ts | 6 +- shared/src/traceData.ts | 1 + shared/src/tree.ts | 13 ++ src/appState.ts | 15 +- src/traceTree.ts | 271 ------------------------------------- src/tsTrace.ts | 187 ------------------------- 10 files changed, 315 insertions(+), 501 deletions(-) create mode 100644 server/src/serverState.ts create mode 100644 server/src/traceMetrics.ts create mode 100644 shared/src/tree.ts delete mode 100644 src/traceTree.ts delete mode 100644 src/tsTrace.ts diff --git a/server/src/serverState.ts b/server/src/serverState.ts new file mode 100644 index 0000000..2996145 --- /dev/null +++ b/server/src/serverState.ts @@ -0,0 +1,5 @@ +function ref(value: T) { + return { value } +} + +export const workspacePath = ref('') diff --git a/server/src/traceMetrics.ts b/server/src/traceMetrics.ts new file mode 100644 index 0000000..92238f3 --- /dev/null +++ b/server/src/traceMetrics.ts @@ -0,0 +1,81 @@ +import { join, relative } from 'node:path' +import type { FileStat } from '../../shared/src/messages' +import { type TraceData, type TraceLine, type TypeLine, traceLine, typeLine } from '../../shared/src/traceData' +import { workspacePath } from './serverState' +import { type Tree, getProgram, getTypeDictionary, treeIdNodes, typeToDescriptor } from './tsTrace' +import { filterTree } from './server' + +export const processedFiles = new Set() + +export function getChildrenById(id: number) { + const nodes = treeIdNodes.get(id)?.children ?? [] + const ret: typeof nodes = [] + nodes.forEach((node) => { + treeIdNodes.set(node.id, node) + ret.push({ ...node, children: [], typeIds: [] }) + }) + return ret +} + +export function getTypesById(id: number) { + const ids = treeIdNodes.get(id)?.typeIds + const typeDictionary = getTypeDictionary() + if (!ids) + return [] + + const ret = ids.map((id, idx) => { + const type = typeDictionary.get(id) + if (!type) + throw new Error(`type id not found ${ids[idx]}`) + + return typeToDescriptor(type) + }) + + const checker = getProgram()?.getTypeChecker() + if (!checker) + return ret + + for (const line of ret) { + if (!line.display) { + const type = typeDictionary.get(line.id) + if (type) + line.display = checker.typeToString(type) + } + } + return ret +} + +export function getStatsFromTree(fileName: string) { + const stats: FileStat[] = [] + function visit(node: Tree) { + if ('name' in node.line) { + const line = node.line + if ( + line.dur + && line.args?.path + && join(workspacePath.value, line.args.path) === fileName + && line.args?.pos + && line.args?.end + ) { + const types = node.typeIds.length + stats.push({ + dur: line.dur, + pos: line.args.pos, + end: line.args.end, + types, + totalTypes: types + node.childTypeCnt, + }) + } + } + node.children.forEach(visit) + } + + const fileNodes = filterTree('', relative(workspacePath.value, fileName), 0) + fileNodes.forEach(visit) + + return stats +} + +// export function getTreeAtIndex(idx: number) { +// return treeIndexes[idx] +// } diff --git a/server/src/tsTrace.ts b/server/src/tsTrace.ts index 35579e4..b92a50e 100644 --- a/server/src/tsTrace.ts +++ b/server/src/tsTrace.ts @@ -1,23 +1,38 @@ +/* eslint-disable no-console */ import { performance } from 'node:perf_hooks' import type { BuilderProgram, CompilerHost, CompilerOptions, + ConditionalType, CreateProgramOptions, Diagnostic, DiagnosticReporter, + EvolvingArrayType, ExtendedConfigCacheEntry, + IndexType, + IndexedAccessType, + IntersectionType, + LineAndCharacter, + Node, ParseConfigFileHost, ParsedCommandLine, PrinterOptions, Program, + ReverseMappedType, + SubstitutionType, System, Type, + TypeReference, + UnionType, } from 'typescript' import { + Debug, JSDocParsingMode, NewLineKind, + ObjectFlags, + TypeFlags, combinePaths, createGetCanonicalFileName, createGetSourceFile, @@ -28,14 +43,21 @@ import { getConfigFileParsingDiagnostics, getDefaultLibFileName, getDirectoryPath, + getLineAndCharacterOfPosition, getParsedCommandLineOfConfigFile, + getSourceFileOfNode, maybeBind, memoize, startTracing, sys, tracing, + unescapeLeadingUnderscores, } from 'typescript' +import type { Tree } from '../../shared/src/tree' + +export type { Tree } from '../../shared/src/tree' + export type ExecuteCommandLineCallbacks = ( program: Program | BuilderProgram | ParsedCommandLine ) => void @@ -45,29 +67,24 @@ export function getProgram() { return program } +export const treeIdNodes = new Map() + let lastTreeId = 0 const typeDictionary = new Map() -export interface Tree { - id: number - parent: Tree | undefined - line: any - children: Tree[] - typeIds: number[] -} export const treeRoot: Tree = { id: lastTreeId++, - parent: undefined, - line: { name: 'root', ts: performance.now() }, + parentId: -1, + line: { pid: 1, tid: 1, ph: 'root', cat: 'root', ts: performance.now(), name: 'root', dur: 0 }, children: [], typeIds: [], -} -let tree = treeRoot + childCnt: 0, + childTypeCnt: 0, + maxDepth: 0, + typeCnt: 0, -export function printTree() { - console.log( - JSON.stringify(tree, (k, v) => (k === 'parent' ? undefined : v), 2), - ) } +let tree = { ...treeRoot } +treeIdNodes.set(0, treeRoot) export function getTypeDictionary() { return typeDictionary @@ -106,6 +123,9 @@ export function runLiveTrace(projectDirectory: string, traceDir: string) { traceDir, ) + tree.line.dur = performance.now() - tree.line.ts + treeIdNodes.set(tree.id, tree) + // writeTypeTimestamps(typeTimestamps); return program } @@ -149,7 +169,7 @@ function performCompilation( (a, b) => { if (b) { b.forEach((c) => { - // console.log(`error at: ${c?.fileName}: ${c?.line}`); + console.log(`error at: ${c?.fileName}: ${c?.line}`) }) } }, // createReportErrorSummary(sys, options), @@ -250,6 +270,7 @@ function enableTracing( ) { if (canTrace(system, compilerOptions)) { typeDictionary.clear() + tree = { ...treeRoot } startTracing( isBuildMode ? 'build' : 'project', @@ -263,49 +284,212 @@ function enableTracing( if (typeDictionary.size === 0) holdRecordType(type) // need one or ts crashes typeDictionary.set(type.id, type) - tree.typeIds.push(type.id) + tree.typeCnt = tree.typeIds.push(type.id) } tracing.instant = (phase: string, name: string, args?: object) => { - tree.children.push({ + const node: Tree = { id: lastTreeId++, - parent: tree, + parentId: tree.id, line: { - phase, + pid: 1, + tid: 1, + cat: phase, + ph: 'x', name, args, ts: performance.now(), }, children: [], typeIds: [], - }) + childCnt: 0, + childTypeCnt: 0, + maxDepth: 0, + typeCnt: 0, + } + tree.childCnt = tree.children.push(node) + treeIdNodes.set(node.id, node) } tracing.push = ( phase: string, name: string, args?: object, - separateBeginAndEnd = false, + _separateBeginAndEnd = false, ) => { const child: Tree = { id: lastTreeId++, - parent: tree, - line: { phase, name, args, ts: performance.now() }, + parentId: tree.id, + line: { + pid: 1, + tid: 1, + cat: phase, + ph: 'x', + name, + args, + ts: performance.now(), + }, children: [], typeIds: [], + childCnt: 0, + childTypeCnt: 0, + maxDepth: 0, + typeCnt: 0, } tree.children.push(child) tree = child + treeIdNodes.set(child.id, child) } tracing.pop = (results?: object) => { - if (!tree.parent) { + if (tree.parentId === -1) { throw new Error('Tree over popped') } - tree = tree.parent + const parent = treeIdNodes.get(tree.parentId)! + parent.maxDepth = Math.max(parent.maxDepth, tree.maxDepth + 1) + parent.childTypeCnt += tree.typeCnt + tree = parent tree.line.results = results ?? {} tree.line.dur = performance.now() - tree.line.ts } } } } + +// TODO: we may want to make this on demand, or only populate commonly used properties eagerly + +const recursionIdentityMap = new Map() +// ripped straight from the ts repo in tracing.ts dumpTypes +export function typeToDescriptor(type: Type) { + const objectFlags = (type as any).objectFlags + const symbol = type.aliasSymbol ?? type.symbol + + // It's slow to compute the display text, so skip it unless it's really valuable (or cheap) + let display: string | undefined + if ((objectFlags & ObjectFlags.Anonymous) | (type.flags & TypeFlags.Literal)) { + try { + display = type.checker?.typeToString(type) + } + catch { + display = undefined + } + } + + let indexedAccessProperties: object = {} + if (type.flags & TypeFlags.IndexedAccess) { + const indexedAccessType = type as IndexedAccessType + indexedAccessProperties = { + indexedAccessObjectType: indexedAccessType.objectType?.id, + indexedAccessIndexType: indexedAccessType.indexType?.id, + } + } + + let referenceProperties: object = {} + if (objectFlags & ObjectFlags.Reference) { + const referenceType = type as TypeReference + referenceProperties = { + instantiatedType: referenceType.target?.id, + typeArguments: referenceType.resolvedTypeArguments?.map(t => t.id), + referenceLocation: getLocation(referenceType.node), + } + } + + let conditionalProperties: object = {} + if (type.flags & TypeFlags.Conditional) { + const conditionalType = type as ConditionalType + conditionalProperties = { + conditionalCheckType: conditionalType.checkType?.id, + conditionalExtendsType: conditionalType.extendsType?.id, + conditionalTrueType: conditionalType.resolvedTrueType?.id ?? -1, + conditionalFalseType: conditionalType.resolvedFalseType?.id ?? -1, + } + } + + let substitutionProperties: object = {} + if (type.flags & TypeFlags.Substitution) { + const substitutionType = type as SubstitutionType + substitutionProperties = { + substitutionBaseType: substitutionType.baseType?.id, + constraintType: substitutionType.constraint?.id, + } + } + + let reverseMappedProperties: object = {} + if (objectFlags & ObjectFlags.ReverseMapped) { + const reverseMappedType = type as ReverseMappedType + reverseMappedProperties = { + reverseMappedSourceType: reverseMappedType.source?.id, + reverseMappedMappedType: reverseMappedType.mappedType?.id, + reverseMappedConstraintType: reverseMappedType.constraintType?.id, + } + } + + let evolvingArrayProperties: object = {} + if (objectFlags & ObjectFlags.EvolvingArray) { + const evolvingArrayType = type as EvolvingArrayType + evolvingArrayProperties = { + evolvingArrayElementType: evolvingArrayType.elementType.id, + evolvingArrayFinalType: evolvingArrayType.finalArrayType?.id, + } + } + + // We can't print out an arbitrary object, so just assign each one a unique number. + // Don't call it an "id" so people don't treat it as a type id. + let recursionToken: number | undefined + const recursionIdentity = type.checker.getRecursionIdentity(type) + if (recursionIdentity) { + recursionToken = recursionIdentityMap.get(recursionIdentity) + if (!recursionToken) { + recursionToken = recursionIdentityMap.size + recursionIdentityMap.set(recursionIdentity, recursionToken) + } + } + + const descriptor = { + id: type.id, + intrinsicName: (type as any).intrinsicName, + symbolName: symbol?.escapedName && unescapeLeadingUnderscores(symbol.escapedName), + recursionId: recursionToken, + isTuple: objectFlags & ObjectFlags.Tuple ? true : undefined, + unionTypes: (type.flags & TypeFlags.Union) ? (type as UnionType).types?.map(t => t.id) : undefined, + intersectionTypes: (type.flags & TypeFlags.Intersection) ? (type as IntersectionType).types.map(t => t.id) : undefined, + aliasTypeArguments: type.aliasTypeArguments?.map(t => t.id), + keyofType: (type.flags & TypeFlags.Index) ? (type as IndexType).type?.id : undefined, + ...indexedAccessProperties, + ...referenceProperties, + ...conditionalProperties, + ...substitutionProperties, + ...reverseMappedProperties, + ...evolvingArrayProperties, + destructuringPattern: getLocation(type.pattern), + firstDeclaration: getLocation(symbol?.declarations?.[0]), + flags: Debug.formatTypeFlags(type.flags).split('|'), + display, + } + return descriptor +} + +// ripped from tracing.ts +function getLocation(node: Node | undefined) { + const file = getSourceFileOfNode(node) + return !file + ? undefined + : { + path: file.path, + start: indexFromOne(getLineAndCharacterOfPosition(file, node!.pos)), + _end: indexFromOne(getLineAndCharacterOfPosition(file, node!.end)), + get end() { + return this._end + }, + set end(value) { + this._end = value + }, + } + + function indexFromOne(lc: LineAndCharacter): LineAndCharacter { + return { + line: lc.line + 1, + character: lc.character + 1, + } + } +} diff --git a/server/tsconfig.json b/server/tsconfig.json index 995d43a..b4f0f06 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -2,7 +2,6 @@ "compilerOptions": { "target": "es2017", "lib": ["esnext"], - "rootDir": "src", "module": "ESNext", "moduleResolution": "node", "resolveJsonModule": true, diff --git a/shared/src/messages.ts b/shared/src/messages.ts index ec203ec..74bf31a 100644 --- a/shared/src/messages.ts +++ b/shared/src/messages.ts @@ -1,5 +1,5 @@ import z from 'zod' -import type { Tree } from '../../src/traceTree' +import type { Tree } from './tree' import { traceLine, typeLine } from './traceData' export const ping = z.object({ @@ -101,12 +101,14 @@ export type FilterTree = z.infer const zodTree: z.ZodType = z.lazy(() => z.object({ id: z.number(), + parentId: z.number(), line: traceLine, children: z.array(zodTree), - types: z.array(typeLine), + typeIds: z.array(z.number()), childTypeCnt: z.number(), childCnt: z.number(), typeCnt: z.number(), + maxDepth: z.number(), }), ) diff --git a/shared/src/traceData.ts b/shared/src/traceData.ts index 2a8748d..191d77d 100644 --- a/shared/src/traceData.ts +++ b/shared/src/traceData.ts @@ -33,6 +33,7 @@ export const traceLine = z.object({ .optional(), }) .optional(), + results: z.object({}).optional(), }) export type DataLine = TraceLine | TypeLine diff --git a/shared/src/tree.ts b/shared/src/tree.ts new file mode 100644 index 0000000..1d8830b --- /dev/null +++ b/shared/src/tree.ts @@ -0,0 +1,13 @@ +import type { TraceLine } from './traceData' + +export interface Tree { + id: number + parentId: number + line: TraceLine + children: Tree[] + typeIds: number[] + childCnt: number + maxDepth: number + childTypeCnt: number + typeCnt: number +} diff --git a/src/appState.ts b/src/appState.ts index d2a3c88..4311854 100644 --- a/src/appState.ts +++ b/src/appState.ts @@ -4,11 +4,11 @@ import { log } from 'node:console' import { type Ref, type ShallowRef, type UnwrapRef, nextTick, watch as plainWatch, ref, shallowRef } from '@vue/runtime-core' import type * as vscode from 'vscode' import type { TraceData } from '../shared/src/traceData' +import type { Tree } from '../shared/src/tree' import { getTracePanel, isTraceViewAlive, postMessage } from './webview' import { getProjectName, getWorkspacePath } from './storage' import { setStatusBarState } from './statusBar' import { sendTraceDir } from './commands' -import type { Tree } from './traceTree' export const afterWatches = nextTick @@ -21,8 +21,6 @@ export const savePath = ref('') export const saveNames: Ref = ref([]) export const projectNames: Ref = ref([]) -export const traceFiles: ShallowRef> = shallowRef({}) - export const traceRunning = ref(false) export const tracePath = ref('') @@ -37,7 +35,6 @@ export const state = { savePath, saveNames, projectNames, - traceFiles, traceRunning, tracePath, treeRoots, @@ -126,16 +123,6 @@ export async function initAppState(extensionContext: vscode.ExtensionContext) { postMessage({ message: 'saveOpen', name }) }) - watchT('traceFiles', noop, (files) => { - postMessage({ message: 'traceFileLoaded', fileName: '', dirName: tracePath.value, resetFileList: true }) - nextTick(() => - - Object.keys(files).forEach((fileName) => { - postMessage({ message: 'traceFileLoaded', fileName, dirName: tracePath.value, resetFileList: false }) - }), - ) - }) - watchT('traceRunning', (running: boolean) => setStatusBarState('tracing', running), (running: boolean) => { if (running) postMessage({ message: 'traceStart', projectPath: projectPath.value, traceDir: '' }) diff --git a/src/traceTree.ts b/src/traceTree.ts deleted file mode 100644 index c71849c..0000000 --- a/src/traceTree.ts +++ /dev/null @@ -1,271 +0,0 @@ -import { isAbsolute, join, relative } from 'node:path' -import * as vscode from 'vscode' -// import { getLineAndCharacterOfPosition } from 'typescript' -import type { FileStat } from '../shared/src/messages' -import { type TraceData, type TraceLine, type TypeLine, traceLine, typeLine } from '../shared/src/traceData' -import { getWorkspacePath } from './storage' -import { postMessage } from './webview' -import { state } from './appState' -import { getProgram, getTypeDictionary, getTypeTimestamps } from './tsTrace' - -export interface Tree { id: number, line: TraceLine, children: Tree[], types: TypeLine[], childCnt: number, childTypeCnt: number, typeCnt: number } -function getRoot(): Tree { - return { - id: 0, - line: { - cat: 'root', - name: 'root', - ph: 'root', - pid: 1, - tid: 1, - ts: 0, - dur: Number.MAX_SAFE_INTEGER, - }, - children: [], - types: [], - childCnt: 0, - childTypeCnt: 0, - typeCnt: 0, - } as const -} - -let treeIndexes: Tree[] = [] -export function toTree(data: TraceData): Tree { - const tree: Tree = { ...getRoot() } - let endTs = Number.MAX_SAFE_INTEGER - let curr = tree - let maxDur = 0 - let id = 0 - - const stack: Tree[] = [] - - treeIndexes = [tree] - - const workspacePath = state.workspacePath.value - - // zod won't allow default for TS in the tree message so we have to assert it here - for (const line of data) { - if ('args' in line && line.args?.path && isAbsolute(line.args?.path)) - line.args.path = relative(workspacePath, line.args.path) - - if (line.dur !== Number.MAX_SAFE_INTEGER && (line.dur ?? 0) > maxDur) - maxDur = line.ts! - - while (line.ts! > endTs) { - if (stack.length === 0) - throw new Error('tree stack empty') - - const childTotalTypeCnt = curr.childTypeCnt + curr.types.length - curr = stack.pop()! - curr.childTypeCnt += childTotalTypeCnt - endTs = curr.line.ts + (curr.line.dur ?? 0) - } - - if ('id' in line) { - curr.typeCnt = curr.types.push(line) - } - else if (line.dur) { - endTs = line.ts + (line.dur ?? 0) - const child = { id: ++id, line, children: [], types: [], childTypeCnt: 0, childCnt: 0, typeCnt: 0 } - treeIndexes[id] = child - curr.childCnt = curr.children.push(child) - stack.push(curr) - curr = child - } - } - - tree.line.dur = maxDur - return tree -} - -let traceTree: Tree | undefined -const traceLines: TraceLine[] = [] -const typeLines: TypeLine[] = [] -export const processedFiles = new Set() - -export async function processTraceFiles() { - const typeTimestamps = await getTypeTimestamps() - let newFiles = false - const workspacePath = state.workspacePath.value - const traceFiles = state.traceFiles.value - - for (const name in traceFiles) { - if (processedFiles.has(name)) - continue - processedFiles.add(name) - newFiles = true - - const lines = traceFiles[name] - - if (name.includes('trace')) { - const starts: TraceLine[] = [] - for (const unparsed of lines) { - const parsed = traceLine.safeParse(unparsed) - if (!parsed.success) { - vscode.window.showErrorMessage(`trace file ${name} is not valid`) - return - } - - const line = parsed.data - if ('args' in line && line.args?.path && isAbsolute(line.args?.path)) - line.args.path = relative(workspacePath, line.args.path) - - if (line.ph === 'B') { - starts.push(line) - } - else if (line.ph === 'E') { - const start = starts.pop() - if (start) { - start.dur = line.ts - start.ts - traceLines.push(start) - } - } - else { - traceLines.push(line) - } - } - } - else if (name.includes('type')) { - for (const unparsed of lines) { - const parsed = typeLine.safeParse(unparsed) - if (!parsed.success) { - vscode.window.showErrorMessage(`type file ${name} is not valid`) - return - } - - const line = parsed.data - line.ts = typeTimestamps.get(line.id) ?? 0 - - typeLines.push(line) - } - } - } - - if (!newFiles) - return traceTree - - const allLines = [...traceLines, ...typeLines] - allLines.sort((a, b) => a.ts! - b.ts!) - traceTree = toTree(allLines) - return traceTree -} - -export function filterTree(startsWith: string, sourceFileName: string, position: number | '', tree = traceTree): Tree[] { - if (position === '') - position = 0 - - if (!tree) - return [] - - if ( - ('name' in tree.line && tree.line.name.startsWith(startsWith)) - && (!sourceFileName || ((tree.line.args?.path ?? '').endsWith(sourceFileName))) - && (!(position > 0) || ((tree.line.args?.pos ?? 0) === position)) - ) { - return [tree] - } - - return tree.children.map(child => filterTree(startsWith, sourceFileName, position, child)).flat() -} - -export const treeIdNodes = new Map() -let showTreeInterval: undefined | ReturnType -export function showTree(startsWith: string, sourceFileName: string, position: number | '', updateUi = true, tree = traceTree) { - if (showTreeInterval) { - clearInterval(showTreeInterval) - showTreeInterval = undefined - } - - const nodes = filterTree(startsWith, sourceFileName, position, tree) - const skinnyNodes = nodes.map(x => ({ ...x, children: [], types: [] })) - if (updateUi) - postMessage({ message: 'filterTree', startsWith, sourceFileName, position }) - - postMessage({ message: 'showTree', nodes: [], step: 'start' }) - - let i = 0 - - // this can be large enough to freeze the UI if sent at once - showTreeInterval = setInterval(() => { - if (!showTreeInterval) - return - - postMessage({ message: 'showTree', nodes: skinnyNodes.slice(i, i + 10), step: 'add' }) - i += 10 - if (i >= skinnyNodes.length) { - clearInterval(showTreeInterval) - showTreeInterval = undefined - postMessage({ message: 'showTree', nodes: [], step: 'done' }) - } - }, 30) - - nodes.forEach(node => treeIdNodes.set(node.id, node)) - return nodes -} - -export function getChildrenById(id: number) { - const nodes = treeIdNodes.get(id)?.children ?? [] - const ret: typeof nodes = [] - nodes.forEach((node) => { - treeIdNodes.set(node.id, node) - ret.push({ ...node, children: [], types: [] }) - }) - return ret -} - -export function getTypesById(id: number) { - const ret = treeIdNodes.get(id)?.types - const typeDictionary = getTypeDictionary() - if (!ret) - return [] - - const checker = getProgram()?.getTypeChecker() - if (!checker) - return ret - - for (const line of ret) { - if (!line.display) { - const type = typeDictionary.get(line.id) - if (type) - line.display = checker.typeToString(type) - } - } - return ret -} - -export function getStatsFromTree(fileName: string) { - const workspacePath = getWorkspacePath() - - const stats: FileStat[] = [] - function visit(node: Tree) { - if ('name' in node.line) { - const line = node.line - if ( - line.dur - && line.args?.path - && join(workspacePath, line.args.path) === fileName - && line.args?.pos - && line.args?.end - ) { - const types = node.types.length - stats.push({ - dur: line.dur, - pos: line.args.pos, - end: line.args.end, - types, - totalTypes: types + node.childTypeCnt, - }) - } - } - node.children.forEach(visit) - } - - const fileNodes = filterTree('', relative(workspacePath, fileName), 0) - fileNodes.forEach(visit) - - return stats -} - -export function getTreeAtIndex(idx: number) { - return treeIndexes[idx] -} diff --git a/src/tsTrace.ts b/src/tsTrace.ts deleted file mode 100644 index cbee273..0000000 --- a/src/tsTrace.ts +++ /dev/null @@ -1,187 +0,0 @@ -import type { BuilderProgram, CompilerHost, CompilerOptions, CreateProgramOptions, Diagnostic, DiagnosticReporter, ExtendedConfigCacheEntry, ParseConfigFileHost, ParsedCommandLine, PrinterOptions, Program, System, Type } from 'typescript' -import { JSDocParsingMode, NewLineKind, combinePaths, createGetCanonicalFileName, createGetSourceFile, createProgram, createWriteFileMeasuringIO, emitFilesAndReportErrorsAndGetExitStatus, findConfigFile, getConfigFileParsingDiagnostics, getDefaultLibFileName, getDirectoryPath, getParsedCommandLineOfConfigFile, maybeBind, memoize, startTracing, sys, timestamp, tracing } from 'typescript' -import { readTypeTimestamps, writeTypeTimestamps } from './storage' -import { log } from './logger' - -export type ExecuteCommandLineCallbacks = (program: Program | BuilderProgram | ParsedCommandLine) => void - -let program: Program | undefined -export function getProgram() { - return program -} - -let typeTimestamps = new Map() -const typeDictionary = new Map() -export async function getTypeTimestamps() { - if (typeTimestamps.size === 0) { - typeTimestamps = await readTypeTimestamps() ?? typeTimestamps - } - return typeTimestamps -} -export function getTypeDictionary() { - return typeDictionary -} - -// TODO: see src/comipler/path.ts:632 -function normalizePath(path: string) { - return path -} - -export function runLiveTrace( - projectDirectory: string, - traceDir: string, -) { - const searchPath = normalizePath(projectDirectory) - const configFileName = findConfigFile(searchPath, fileName => sys.fileExists(fileName)) - const reportDiagnostic = (_diagnostic: Diagnostic) => { - log(`${_diagnostic.messageText}`) - } - - if (configFileName) { - const extendedConfigCache = new Map() - const configParseResult = getParsedCommandLineOfConfigFile(configFileName, {}, sys as unknown as ParseConfigFileHost, extendedConfigCache, {}) - if (!configParseResult) - throw new Error('undefined configParseResult') - // const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, extendedConfigCache, commandLine.watchOptions, sys, reportDiagnostic)! // TODO: GH#18217 - - program = performCompilation( - sys, - reportDiagnostic, - configParseResult, - traceDir, - ) - - writeTypeTimestamps(typeTimestamps) - return program - } -} - -const defaultJSDocParsingMode = JSDocParsingMode.ParseForTypeErrors - -function performCompilation( - sys: System, - reportDiagnostic: DiagnosticReporter, - config: ParsedCommandLine, - traceDir: string, -) { - const { fileNames, options, projectReferences } = config - options.generateTrace = traceDir - const host = createCompilerHostWorker(options, /* setParentNodes */ undefined, sys) - host.jsDocParsingMode = defaultJSDocParsingMode - // const currentDirectory = host.getCurrentDirectory() - // const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()) - // changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName)) - enableTracing(sys, options, /* isBuildMode */ false) - - config.options.noEmit = true - - const programOptions: CreateProgramOptions = { - rootNames: fileNames, - options, - projectReferences, - host, - configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config), - } - const program = createProgram(programOptions) - emitFilesAndReportErrorsAndGetExitStatus( - program, - reportDiagnostic, - s => sys.write(s + sys.newLine), - (a, b) => { - log(`summary a: ${a}`) - if (b) { - b.forEach((c) => { - log(`error at: ${c?.fileName}: ${c?.line}`) - }) - } - }, // createReportErrorSummary(sys, options), - ) - - tracing?.stopTracing() - return program -} - -export function createCompilerHostWorker( - options: CompilerOptions, - setParentNodes?: boolean, - system: System = sys, -): CompilerHost { - const existingDirectories = new Map() - const getCanonicalFileName = createGetCanonicalFileName(system.useCaseSensitiveFileNames) - function directoryExists(directoryPath: string): boolean { - if (existingDirectories.has(directoryPath)) { - return true - } - if ((sys.directoryExists || system.directoryExists)(directoryPath)) { - existingDirectories.set(directoryPath, true) - return true - } - return false - } - - function getDefaultLibLocation(): string { - return getDirectoryPath(normalizePath(system.getExecutingFilePath())) - } - - const newLine = getNewLineCharacter(options) - const realpath = system.realpath && ((path: string) => system.realpath!(path)) - const compilerHost: CompilerHost = { - getSourceFile: createGetSourceFile(fileName => compilerHost.readFile(fileName), () => options, setParentNodes), - getDefaultLibLocation, - getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)), - writeFile: createWriteFileMeasuringIO( - (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark), - path => (compilerHost.createDirectory || system.createDirectory)(path), - path => directoryExists(path), - ), - getCurrentDirectory: memoize(() => system.getCurrentDirectory()), - useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames, - getCanonicalFileName, - getNewLine: () => newLine, - fileExists: fileName => system.fileExists(fileName), - readFile: fileName => system.readFile(fileName), - trace: (s: string) => system.write(s + newLine), - directoryExists: directoryName => system.directoryExists(directoryName), - getEnvironmentVariable: name => system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : '', - getDirectories: (path: string) => system.getDirectories(path), - realpath, - readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth), - createDirectory: d => system.createDirectory(d), - createHash: maybeBind(system, system.createHash), - } - return compilerHost -} - -const carriageReturnLineFeed = '\r\n' -const lineFeed = '\n' -export function getNewLineCharacter(options: CompilerOptions | PrinterOptions): string { - switch (options.newLine) { - case NewLineKind.CarriageReturnLineFeed: - return carriageReturnLineFeed - case NewLineKind.LineFeed: - case undefined: - return lineFeed - } -} - -function canTrace(system: System, compilerOptions: CompilerOptions) { - return system === sys && compilerOptions.generateTrace -} - -// TODO: do not call the held record type and just fetch the types by id from the program as needed -function enableTracing(system: System, compilerOptions: CompilerOptions, isBuildMode: boolean) { - if (canTrace(system, compilerOptions)) { - typeTimestamps.clear() - typeDictionary.clear() - - startTracing(isBuildMode ? 'build' : 'project', compilerOptions.generateTrace!, compilerOptions.configFilePath) - if (tracing) { - const holdRecordType = tracing.recordType - tracing.recordType = (type: Type) => { - typeTimestamps.set(type.id, 1000 * timestamp()) - typeDictionary.set(type.id, type) - holdRecordType(type) - } - } - } -} From fe9f1faf17e2a6c878af3d5ceeda7088832b426b Mon Sep 17 00:00:00 2001 From: typeholes Date: Sat, 8 Jun 2024 21:52:55 -0400 Subject: [PATCH 07/24] (WIP) moving functionality to server - builds --- server/src/commonState.ts | 0 server/src/receiveMessage.ts | 130 +++++++++++++++++++++++++++++++++++ server/src/server.ts | 128 ++-------------------------------- server/src/traceMetrics.ts | 3 +- server/src/tsTrace.ts | 31 +++++++-- shared/src/traceData.ts | 4 ++ src/appState.ts | 5 +- src/client/actions.ts | 33 ++++++++- src/commands.ts | 113 +----------------------------- src/constants.ts | 1 - src/handleMessages.ts | 10 +-- src/traceDiagnostics.ts | 7 +- 12 files changed, 209 insertions(+), 256 deletions(-) delete mode 100644 server/src/commonState.ts create mode 100644 server/src/receiveMessage.ts diff --git a/server/src/commonState.ts b/server/src/commonState.ts deleted file mode 100644 index e69de29..0000000 diff --git a/server/src/receiveMessage.ts b/server/src/receiveMessage.ts new file mode 100644 index 0000000..aefa28d --- /dev/null +++ b/server/src/receiveMessage.ts @@ -0,0 +1,130 @@ +/* eslint-disable no-console */ +import type WebSocket from 'ws' +import type { Tree } from './tsTrace' +import { runLiveTrace, treeRoot } from './tsTrace' +import * as Messages from './messages' +import { sendResponse } from './server' +import { getStatsFromTree } from './traceMetrics' + +export function receiveMessage(id: number, args: unknown, ws: WebSocket) { + const parsed = Messages.message.safeParse(args) + if (parsed.error) { + console.log(JSON.stringify(args, null, 2)) + return + } + + switch (parsed.data.message) { + case 'traceStart': { + runLiveTrace(parsed.data.projectPath, parsed.data.traceDir) + const response: Messages.Message = { message: 'traceStop' } + sendResponse(ws, id, response) + break + } + + case 'filterTree': { + const { startsWith, sourceFileName, position } = parsed.data + const roots = filterTree(startsWith, sourceFileName, position) + showTree(ws, id, roots) + break + } + + case 'fileStats': { + const stats = getStatsFromTree(parsed.data.fileName) + sendResponse(ws, id, { ...parsed.data, stats }) + break + } + } +} + +export function filterTree( + startsWith: string, + sourceFileName: string, + position: number | '', + tree = treeRoot, +): Tree[] { + if (position === '') + position = 0 + + if (!tree) + return [] + + if ( + 'name' in tree.line + && tree.line.name.startsWith(startsWith) + && (!sourceFileName + || (tree.line.args?.path ?? '').endsWith(sourceFileName)) + && (!(position > 0) || (tree.line.args?.pos ?? 0) === position) + ) { + return [tree] + } + + return tree.children + .map(child => filterTree(startsWith, sourceFileName, position, child)) + .flat() +} + +export const treeIdNodes = new Map() +let showTreeInterval: undefined | ReturnType +export function showTree(ws: WebSocket, requestId: number, nodes: Tree[]) { + if (showTreeInterval) { + clearInterval(showTreeInterval) + showTreeInterval = undefined + } + + // TODO: parent should be a node id + const skinnyNodes = nodes.map(x => ({ + ...x, + parent: undefined, + children: [], + types: [], + })) + + sendResponse( + ws, + requestId, + { + message: 'showTree', + nodes: [], + step: 'start', + }, + false, + ) + + let i = 0 + + // this can be large enough to freeze the UI if sent at once + showTreeInterval = setInterval(() => { + if (!showTreeInterval) + return + + sendResponse( + ws, + requestId, + { + message: 'showTree', + nodes: skinnyNodes.slice(i, i + 10), + step: 'add', + }, + false, + ) + + i += 10 + if (i >= skinnyNodes.length) { + clearInterval(showTreeInterval) + showTreeInterval = undefined + sendResponse( + ws, + requestId, + { + message: 'showTree', + nodes: [], + step: 'done', + }, + true, + ) + } + }, 30) + + nodes.forEach(node => treeIdNodes.set(node.id, node)) + return nodes +} diff --git a/server/src/server.ts b/server/src/server.ts index 07efb68..f5376e5 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -2,9 +2,8 @@ import type { WebSocket } from 'ws' import { WebSocketServer } from 'ws' -import * as Messages from './messages' -import type { Tree } from './tsTrace' -import { runLiveTrace, treeRoot } from './tsTrace' +import type * as Messages from './messages' +import { receiveMessage } from './receiveMessage' const wss = new WebSocketServer({ port: 3010 }) @@ -81,123 +80,8 @@ server.listen(3010, 'localhost', () => { }); */ -function receiveMessage(id: number, args: unknown, ws: WebSocket) { - const parsed = Messages.message.safeParse(args) - if (parsed.error) { - console.log(JSON.stringify(args, null, 2)) - return - } - switch (parsed.data.message) { - case 'traceStart': { - runLiveTrace(parsed.data.projectPath, parsed.data.traceDir) - const response: Messages.Message = { message: 'traceStop' } - sendResponse(ws, id, response) - break - } - - case 'filterTree': { - const { startsWith, sourceFileName, position } = parsed.data - const roots = filterTree(startsWith, sourceFileName, position) - showTree(ws, id, roots) - } - } -} - -export function filterTree( - startsWith: string, - sourceFileName: string, - position: number | '', - tree = treeRoot, -): Tree[] { - if (position === '') - position = 0 - - if (!tree) - return [] - - if ( - 'name' in tree.line - && tree.line.name.startsWith(startsWith) - && (!sourceFileName - || (tree.line.args?.path ?? '').endsWith(sourceFileName)) - && (!(position > 0) || (tree.line.args?.pos ?? 0) === position) - ) { - return [tree] - } - - return tree.children - .map(child => filterTree(startsWith, sourceFileName, position, child)) - .flat() -} - -export const treeIdNodes = new Map() -let showTreeInterval: undefined | ReturnType -export function showTree(ws: WebSocket, requestId: number, nodes: Tree[]) { - if (showTreeInterval) { - clearInterval(showTreeInterval) - showTreeInterval = undefined - } - - // TODO: parent should be a node id - const skinnyNodes = nodes.map(x => ({ - ...x, - parent: undefined, - children: [], - types: [], - })) - - sendResponse( - ws, - requestId, - { - message: 'showTree', - nodes: [], - step: 'start', - }, - false, - ) - - let i = 0 - - // this can be large enough to freeze the UI if sent at once - showTreeInterval = setInterval(() => { - if (!showTreeInterval) - return - - sendResponse( - ws, - requestId, - { - message: 'showTree', - nodes: skinnyNodes.slice(i, i + 10), - step: 'add', - }, - false, - ) - - i += 10 - if (i >= skinnyNodes.length) { - clearInterval(showTreeInterval) - showTreeInterval = undefined - sendResponse( - ws, - requestId, - { - message: 'showTree', - nodes: [], - step: 'done', - }, - true, - ) - } - }, 30) - - nodes.forEach(node => treeIdNodes.set(node.id, node)) - return nodes -} - -function sendResponse( +export function sendResponse( ws: WebSocket, id: number, response: Messages.Message, @@ -208,10 +92,6 @@ function sendResponse( ) } -function sendError(ws: WebSocket, id: number, errorMessage: string) { +export function sendError(ws: WebSocket, id: number, errorMessage: string) { ws.send(JSON.stringify([id, 'error', errorMessage])) } - -// function sendMessage(ws: WebSocket, message: Messages.Message) { -// ws.send(JSON.stringify(message)) -// } diff --git a/server/src/traceMetrics.ts b/server/src/traceMetrics.ts index 92238f3..5d58422 100644 --- a/server/src/traceMetrics.ts +++ b/server/src/traceMetrics.ts @@ -1,9 +1,8 @@ import { join, relative } from 'node:path' import type { FileStat } from '../../shared/src/messages' -import { type TraceData, type TraceLine, type TypeLine, traceLine, typeLine } from '../../shared/src/traceData' import { workspacePath } from './serverState' import { type Tree, getProgram, getTypeDictionary, treeIdNodes, typeToDescriptor } from './tsTrace' -import { filterTree } from './server' +import { filterTree } from './receiveMessage' export const processedFiles = new Set() diff --git a/server/src/tsTrace.ts b/server/src/tsTrace.ts index b92a50e..16a3f99 100644 --- a/server/src/tsTrace.ts +++ b/server/src/tsTrace.ts @@ -67,6 +67,8 @@ export function getProgram() { return program } +// let getExistingSourceFile(fileName: string) + export const treeIdNodes = new Map() let lastTreeId = 0 @@ -287,7 +289,9 @@ function enableTracing( tree.typeCnt = tree.typeIds.push(type.id) } - tracing.instant = (phase: string, name: string, args?: object) => { + tracing.instant = (phase: string, name: string, args?: Record) => { + addLocation(args) + const node: Tree = { id: lastTreeId++, parentId: tree.id, @@ -317,6 +321,7 @@ function enableTracing( args?: object, _separateBeginAndEnd = false, ) => { + addLocation(args) const child: Tree = { id: lastTreeId++, parentId: tree.id, @@ -359,6 +364,14 @@ function enableTracing( // TODO: we may want to make this on demand, or only populate commonly used properties eagerly const recursionIdentityMap = new Map() +function addLocation(args: Record | undefined) { + if (args) { + args.location = (args && 'path' in args && 'pos' in args && typeof args.path === 'string' && typeof args.pos === 'number') + ? posToLocation(args.path, args.pos) + : undefined + } +} + // ripped straight from the ts repo in tracing.ts dumpTypes export function typeToDescriptor(type: Type) { const objectFlags = (type as any).objectFlags @@ -485,11 +498,17 @@ function getLocation(node: Node | undefined) { this._end = value }, } +} - function indexFromOne(lc: LineAndCharacter): LineAndCharacter { - return { - line: lc.line + 1, - character: lc.character + 1, - } +function indexFromOne(lc: LineAndCharacter): LineAndCharacter { + return { + line: lc.line + 1, + character: lc.character + 1, } } + +export function posToLocation(filename: string, position: number) { + const sourceFile = program?.getSourceFile(filename) + if (sourceFile) + return indexFromOne(getLineAndCharacterOfPosition(sourceFile, position)) +} diff --git a/shared/src/traceData.ts b/shared/src/traceData.ts index 191d77d..03625b6 100644 --- a/shared/src/traceData.ts +++ b/shared/src/traceData.ts @@ -25,6 +25,10 @@ export const traceLine = z.object({ kind: z.number().optional(), pos: z.number().optional(), end: z.number().optional(), + location: z.object({ + line: z.number(), + character: z.number(), + }).optional(), path: z.string().optional(), results: z .object({ diff --git a/src/appState.ts b/src/appState.ts index 4311854..3df51d1 100644 --- a/src/appState.ts +++ b/src/appState.ts @@ -3,12 +3,11 @@ import { basename, dirname, join, relative } from 'node:path' import { log } from 'node:console' import { type Ref, type ShallowRef, type UnwrapRef, nextTick, watch as plainWatch, ref, shallowRef } from '@vue/runtime-core' import type * as vscode from 'vscode' -import type { TraceData } from '../shared/src/traceData' import type { Tree } from '../shared/src/tree' import { getTracePanel, isTraceViewAlive, postMessage } from './webview' import { getProjectName, getWorkspacePath } from './storage' import { setStatusBarState } from './statusBar' -import { sendTraceDir } from './commands' +import * as actions from './client/actions' export const afterWatches = nextTick @@ -117,8 +116,6 @@ export async function initAppState(extensionContext: vscode.ExtensionContext) { setStatusBarState('saveName', saveName.value) tracePath.value = join(projectPath.value, name, 'traces') - - void sendTraceDir(tracePath.value) }, (name) => { postMessage({ message: 'saveOpen', name }) }) diff --git a/src/client/actions.ts b/src/client/actions.ts index 2b92614..84e255f 100644 --- a/src/client/actions.ts +++ b/src/client/actions.ts @@ -2,8 +2,9 @@ import { log } from 'node:console' import * as vscode from 'vscode' import { state, traceRunning } from '../appState' import { setStatusBarState } from '../statusBar' -import type { Tree } from '../traceTree' +import type { Tree } from '../../shared/src/tree' import { postMessage } from '../webview' +import { addTraceDiagnostics } from '../traceDiagnostics' import { wsMessage } from './client' export function runTrace(projectPath: string, traceDir: string) { @@ -35,3 +36,33 @@ export function filterTree(startsWith: string, sourceFileName: string, position: }, ) } + +export function getFileStats(fileName: string) { + wsMessage('fileStats', { fileName, stats: [] }) ( + 'fileStats', + message => addTraceDiagnostics(message.fileName, message.stats), + (error: string) => { + vscode.window.showErrorMessage(error) + }, + ) +} + +export function getChildrenById(id: number) { + wsMessage('childrenById', { id }) ( + 'childrenById', + postMessage, + (error: string) => { + vscode.window.showErrorMessage(error) + }, + ) +} + +export function getTypesById(id: number) { + wsMessage('typesById', { id }) ( + 'typesById', + postMessage, + (error: string) => { + vscode.window.showErrorMessage(error) + }, + ) +} diff --git a/src/commands.ts b/src/commands.ts index b3dc686..904b3b3 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -4,7 +4,6 @@ import { promisify } from 'node:util' import { spawn } from 'node:child_process' import { createReadStream, existsSync, readdir as readdirC, statSync } from 'node:fs' import * as vscode from 'vscode' -import { getStatsFromTree, processTraceFiles, processedFiles, showTree, treeIdNodes } from './traceTree' import { getTracePanel, prepareWebView } from './webview' import { getCurrentConfig } from './configuration' import { log } from './logger' @@ -12,10 +11,9 @@ import type { CommandId } from './constants' import { addTraceFile, getWorkspacePath, openTerminal, openTraceDirectoryExternal, setLastMessageTrigger } from './storage' import { addTraceDiagnostics, clearTaceDiagnostics } from './traceDiagnostics' import { setStatusBarState } from './statusBar' -import { afterWatches, projectPath, saveName, state, traceFiles, traceRunning } from './appState' +import { afterWatches, projectPath, saveName, state, traceRunning } from './appState' import * as actions from './client/actions' - -const readdir = promisify(readdirC) +import { filterTree } from './client/actions' const commandHandlers: Record< CommandId, @@ -24,49 +22,10 @@ const commandHandlers: Record< 'tsperf.tracer.runTrace': () => (...args: unknown[]) => runTrace(args), 'tsperf.tracer.openInBrowser': (context: vscode.ExtensionContext) => () => prepareWebView(context), 'tsperf.tracer.gotoTracePosition': (context: vscode.ExtensionContext) => () => gotoTracePosition(context), - 'tsperf.tracer.sendTrace': () => (event: unknown) => { - if (!(Array.isArray(event) && event[0] instanceof vscode.Uri)) - return - - const fsPath = event[0].fsPath - - sendTrace(dirname(fsPath), basename(fsPath)) - }, 'tsperf.tracer.openTerminal': () => () => openTerminal(), 'tsperf.tracer.openTraceDirExternal': () => () => openTraceDirectoryExternal(), } as const -async function sendTrace(dirName: string, fileName: string) { - const fullFileName = join(dirName, fileName) - - const stream = createReadStream(fullFileName, { autoClose: true, emitClose: true, encoding: 'utf-8' }) - - let fileContents = '' - - stream.on('end', () => { - addTraceFile(fileName, fileContents) - processTraceFiles().then(() => { - showTree('check', '', 0) - - clearTaceDiagnostics() - for (const editor of vscode.window.visibleTextEditors) { - const visibleFileName = editor.document.fileName - addTraceDiagnostics(visibleFileName, getStatsFromTree(visibleFileName)) - } - }) - }) - - function readChunks() { - const chunk = stream.read() - if (chunk === null) - return - - fileContents += chunk - setImmediate(readChunks) - } - stream.on('readable', readChunks) -} - export function registerCommands(context: vscode.ExtensionContext) { for (const cmd in commandHandlers) { const disposable = vscode.commands.registerCommand( @@ -95,13 +54,12 @@ function gotoTracePosition(context: vscode.ExtensionContext) { const relativePath = relative(workspacePth, editor.document.fileName) getTracePanel(context)?.reveal() - showTree('', relativePath, startOffset - (editor.document.getText()[startOffset + 1] === '\n' ? 0 : 1)) + filterTree('', relativePath, startOffset - (editor.document.getText()[startOffset + 1] === '\n' ? 0 : 1), true) } const liveTrace = true // TODO config setting async function runTrace(args?: unknown[]) { const workspacePath = state.workspacePath.value - const { traceCmd } = getCurrentConfig() let dirName if (args && args[0] && Array.isArray(args[0]) && args[0][0] instanceof vscode.Uri) { @@ -121,10 +79,6 @@ async function runTrace(args?: unknown[]) { saveName.value = relative(workspacePath, dirName) } - traceFiles.value = {} - processedFiles.clear() - - const newDirName = dirName // TODO: use logic from real time metrics that get the tsconfig path afterWatches(async () => { const traceDir = state.tracePath.value @@ -140,66 +94,5 @@ async function runTrace(args?: unknown[]) { actions.runTrace(workspacePath, traceDir) actions.filterTree('checkExpr', '', 0, true) } - else { - const quotedTraceDir = `'${traceDir}'` - // eslint-disable-next-line no-template-curly-in-string - const fullCmd = `(cd '${newDirName ?? workspacePath}'; ${traceCmd.replace('${traceDir}', quotedTraceDir)})` - - log(fullCmd) - - const newProjectPath = newDirName ?? projectPath.value - if (!newProjectPath) { - vscode.window.showErrorMessage('could not get project path from workspace folders') - return - } - - traceRunning.value = true - - traceFiles.value = {} - treeIdNodes.clear() - - setStatusBarState('traceError', false) - - log(`shell: ${process.env.SHELL}`) - const cmdProcess = spawn(fullCmd, [], { cwd: newProjectPath, shell: process.env.SHELL }) - - let err = '' - cmdProcess.stderr.on('data', data => err += data.toString()) - - cmdProcess.stdout.on('data', data => log(data.toString())) - - cmdProcess.on('error', (error) => { - vscode.window.showErrorMessage(error.message) - }) - - cmdProcess.on('exit', async (code) => { - log('---- trace stderr -----') - log(err) - traceRunning.value = false - if (code) { - setStatusBarState('traceError', true) - vscode.window.showErrorMessage('error running trace') - return - } - - await sendTraceDir(traceDir) - }) - } }) } - -export async function sendTraceDir(traceDir: string) { - try { - if (!existsSync(traceDir)) { - return - } - - const fileNames = await readdir(traceDir) - for (const fileName of fileNames) { - sendTrace(traceDir, fileName) - } - } - catch (e) { - vscode.window.showErrorMessage(e instanceof Error ? e.message : `${e}`) - } -} diff --git a/src/constants.ts b/src/constants.ts index fc97b3b..c33802e 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -25,7 +25,6 @@ export const commandIds = [ 'tsperf.tracer.gotoTracePosition', 'tsperf.tracer.openInBrowser', 'tsperf.tracer.runTrace', - 'tsperf.tracer.sendTrace', 'tsperf.tracer.openTerminal', 'tsperf.tracer.openTraceDirExternal', ] as const diff --git a/src/handleMessages.ts b/src/handleMessages.ts index 4b5375e..7ba2b58 100644 --- a/src/handleMessages.ts +++ b/src/handleMessages.ts @@ -1,7 +1,7 @@ import { join } from 'node:path' import * as vscode from 'vscode' import * as Messages from '../shared/src/messages' -import { getChildrenById, getTypesById, showTree } from './traceTree' +import { filterTree, getChildrenById, getTypesById } from './client/actions' import { log } from './logger' import { postMessage } from './webview' import { deleteTraceFiles, setLastMessageTrigger } from './storage' @@ -10,7 +10,7 @@ import { state, triggerAll } from './appState' export function handleMessage(message: unknown): void { if (message === 'init client') { triggerAll(false, true) - showTree('check', '', 0) + filterTree('check', '', 0, true) return } @@ -36,7 +36,7 @@ export function handleMessage(message: unknown): void { log(...data.value) break case 'filterTree': { - showTree(data.startsWith, data.sourceFileName, data.position, false) + filterTree(data.startsWith, data.sourceFileName, data.position || 0, true) break } case 'saveOpen': { @@ -44,11 +44,11 @@ export function handleMessage(message: unknown): void { break } case 'childrenById': { - postMessage({ ...data, children: getChildrenById(data.id) }) // TODO: stream these + getChildrenById(data.id) break } case 'typesById': { - postMessage({ ...data, types: getTypesById(data.id) }) + getTypesById(data.id) break } diff --git a/src/traceDiagnostics.ts b/src/traceDiagnostics.ts index 48e5601..42be040 100644 --- a/src/traceDiagnostics.ts +++ b/src/traceDiagnostics.ts @@ -1,7 +1,8 @@ import * as vscode from 'vscode' import type { FileStat } from '../shared/src/messages' -import { getStatsFromTree } from './traceTree' import { afterConfigUpdate, getCurrentConfig } from './configuration' +import { wsMessage } from './client/client' +import { getFileStats } from './client/actions' let diagnosticCollection: vscode.DiagnosticCollection @@ -20,7 +21,7 @@ vscode.workspace.onDidChangeTextDocument((event) => { vscode.window.onDidChangeActiveTextEditor((event) => { const fileName = event?.document?.fileName if (fileName) - addTraceDiagnostics(fileName, getStatsFromTree(fileName)) + getFileStats(fileName) }) export function clearTaceDiagnostics() { @@ -174,7 +175,7 @@ afterConfigUpdate(['enableTraceMetrics'], (config) => { else { vscode.window.visibleTextEditors.forEach((editor) => { const fileName = editor.document.uri.fsPath - addTraceDiagnostics(fileName, getStatsFromTree(fileName)) + getFileStats(fileName) }) } }) From e9975bf77d2a5de88f16adb9990ee1e44f8f7d3d Mon Sep 17 00:00:00 2001 From: typeholes Date: Sat, 8 Jun 2024 23:48:31 -0400 Subject: [PATCH 08/24] remove divisions by 1000 and get locations in trace lines --- server/src/receiveMessage.ts | 14 +++++++++++++- server/src/tsTrace.ts | 17 ++++++++++------- src/traceDiagnostics.ts | 6 +++--- ui/components/TreeNode.vue | 7 ++++--- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/server/src/receiveMessage.ts b/server/src/receiveMessage.ts index aefa28d..bb2e157 100644 --- a/server/src/receiveMessage.ts +++ b/server/src/receiveMessage.ts @@ -4,7 +4,7 @@ import type { Tree } from './tsTrace' import { runLiveTrace, treeRoot } from './tsTrace' import * as Messages from './messages' import { sendResponse } from './server' -import { getStatsFromTree } from './traceMetrics' +import { getChildrenById, getStatsFromTree, getTypesById } from './traceMetrics' export function receiveMessage(id: number, args: unknown, ws: WebSocket) { const parsed = Messages.message.safeParse(args) @@ -21,6 +21,18 @@ export function receiveMessage(id: number, args: unknown, ws: WebSocket) { break } + case 'childrenById': { + const response: Messages.ChildrenById = { ...parsed.data, children: getChildrenById(parsed.data.id) } + sendResponse(ws, id, response) + break + } + + case 'typesById': { + const response: Messages.TypesById = { ...parsed.data, types: getTypesById(parsed.data.id) } + sendResponse(ws, id, response) + break + } + case 'filterTree': { const { startsWith, sourceFileName, position } = parsed.data const roots = filterTree(startsWith, sourceFileName, position) diff --git a/server/src/tsTrace.ts b/server/src/tsTrace.ts index 16a3f99..0271061 100644 --- a/server/src/tsTrace.ts +++ b/server/src/tsTrace.ts @@ -92,11 +92,11 @@ export function getTypeDictionary() { return typeDictionary } -// TODO: see src/compiler/path.ts:632 function normalizePath(path: string) { return path } +// TODO: report errors via request error handler export function runLiveTrace(projectDirectory: string, traceDir: string) { const searchPath = normalizePath(projectDirectory) const configFileName = findConfigFile(searchPath, fileName => @@ -128,6 +128,12 @@ export function runLiveTrace(projectDirectory: string, traceDir: string) { tree.line.dur = performance.now() - tree.line.ts treeIdNodes.set(tree.id, tree) + function go(node: Tree) { + addLocation(node.line.args) + node.children.forEach(go) + } + go(tree) + // writeTypeTimestamps(typeTimestamps); return program } @@ -290,8 +296,6 @@ function enableTracing( } tracing.instant = (phase: string, name: string, args?: Record) => { - addLocation(args) - const node: Tree = { id: lastTreeId++, parentId: tree.id, @@ -321,7 +325,6 @@ function enableTracing( args?: object, _separateBeginAndEnd = false, ) => { - addLocation(args) const child: Tree = { id: lastTreeId++, parentId: tree.id, @@ -356,6 +359,7 @@ function enableTracing( tree = parent tree.line.results = results ?? {} tree.line.dur = performance.now() - tree.line.ts + tree.childCnt = tree.children.length } } } @@ -366,9 +370,8 @@ function enableTracing( const recursionIdentityMap = new Map() function addLocation(args: Record | undefined) { if (args) { - args.location = (args && 'path' in args && 'pos' in args && typeof args.path === 'string' && typeof args.pos === 'number') - ? posToLocation(args.path, args.pos) - : undefined + if (args && 'path' in args && 'pos' in args && typeof args.path === 'string' && typeof args.pos === 'number') + args.location = posToLocation(args.path, args.pos) } } diff --git a/src/traceDiagnostics.ts b/src/traceDiagnostics.ts index 42be040..7127223 100644 --- a/src/traceDiagnostics.ts +++ b/src/traceDiagnostics.ts @@ -102,7 +102,7 @@ function fileStatToRelativeDiagnostic({ pos, dur, types, totalTypes }: FileStat, const typeStr = types || totalTypes ? ` Types: ${types} / ${totalTypes} ${relativeString(relative.types)} / ${relativeString(relative.totalTypes)}` : '' - const msg = `Check ms: ${Math.round(dur) / 1000} ${relativeString(relative.dur)} ${typeStr}` + const msg = `Check ms: ${Math.round(dur)} ${relativeString(relative.dur)} ${typeStr}` const startPos = document.positionAt(pos + 1) const range = new vscode.Range(startPos, startPos) @@ -119,7 +119,7 @@ function fileStatToDiagnostic({ pos, dur, types, totalTypes }: FileStat, documen const typeStr = types || totalTypes ? ` Types: ${types} / ${totalTypes}` : '' - const msg = `Check ms: ${Math.round(dur) / 1000} ${typeStr}` + const msg = `Check ms: ${Math.round(dur)} ${typeStr}` const startPos = document.positionAt(pos + 1) const range = new vscode.Range(startPos, startPos) @@ -156,7 +156,7 @@ function getSeverity(measure: Partial<{ [k in keyof typeof severityThresholds]: const [thresholdType, value] = Object.entries(measure)[0] const thresholds = severityThresholds[thresholdType as keyof typeof severityThresholds] - const index = thresholds.findIndex(x => x >= 0 && x <= value / 1000) + const index = thresholds.findIndex(x => x >= 0 && x <= value) return index === -1 ? 99 : index } diff --git a/ui/components/TreeNode.vue b/ui/components/TreeNode.vue index 997a094..9e7b484 100644 --- a/ui/components/TreeNode.vue +++ b/ui/components/TreeNode.vue @@ -1,5 +1,5 @@