diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md index 931be5cfa..2bedd399c 100644 --- a/CONTRIBUTE.md +++ b/CONTRIBUTE.md @@ -17,7 +17,7 @@ Introduce how to setup environment, modify code and submit PR. ### Pre-requirements -- Node.js 16+ +- Node.js >=18.17.0 - pnpm (can be setup by node [corepack](https://nodejs.org/api/corepack.html)) ### Setup Dev Workspace diff --git a/package.json b/package.json index 168a04838..c4ba54b75 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,9 @@ }, "packageManager": "pnpm@8.2.0", "devDependencies": { - "tsx": "^3.12.6", - "typedoc": "^0.24.8", - "typescript": "^5.0.3", + "tsx": "^4.7.1", + "typedoc": "^0.25.8", + "typescript": "^5.3.3", "@vitest/coverage-c8": "^0.30.1", "vitest": "^0.32.0" } diff --git a/packages/asm/package.json b/packages/asm/package.json index 3d33077c6..a2d07d617 100644 --- a/packages/asm/package.json +++ b/packages/asm/package.json @@ -37,6 +37,6 @@ "esbuild": "^0.17.16", "eslint": "^8.37.0", "tslib": "^2.5.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/bytebuffer/package.json b/packages/bytebuffer/package.json index 58930f351..e76e1424c 100644 --- a/packages/bytebuffer/package.json +++ b/packages/bytebuffer/package.json @@ -61,6 +61,6 @@ "esbuild": "^0.17.16", "eslint": "^8.37.0", "tslib": "^2.5.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/client/package.json b/packages/client/package.json index f8bbb56b0..74c521972 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -44,6 +44,6 @@ "esbuild": "^0.17.16", "eslint": "^8.37.0", "tslib": "^2.5.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/core/diagnose.ts b/packages/core/diagnose.ts index 5e83a9452..af53e3b8f 100644 --- a/packages/core/diagnose.ts +++ b/packages/core/diagnose.ts @@ -131,6 +131,11 @@ export async function diagnoseFile({ file, expectedChecksum, r receivedChecksum = await checksumFunc(file, algorithm) if (signal?.aborted) return issue = receivedChecksum !== expectedChecksum + } else { + const fstat = await stat(file) + if (fstat.size === 0) { + issue = true + } } const type = fileExisted ? 'corrupted' : 'missing' as const if (issue) { diff --git a/packages/core/folder.ts b/packages/core/folder.ts index 0f10c7774..83dc5fe80 100644 --- a/packages/core/folder.ts +++ b/packages/core/folder.ts @@ -37,7 +37,13 @@ export class MinecraftFolder { getNativesRoot(version: string) { return join(this.getVersionRoot(version), version + '-natives') } getVersionRoot(version: string) { return join(this.versions, version) } getVersionJson(version: string) { return join(this.getVersionRoot(version), version + '.json') } - getVersionJar(version: string, type?: string) { return type === 'client' || type === undefined ? join(this.getVersionRoot(version), version + '.jar') : join(this.getVersionRoot(version), `${version}-${type}.jar`) } + getVersionServerJson(version: string) { return join(this.getVersionRoot(version), 'server.json') } + getVersionJar(version: string, type?: string) { + if (type === 'client' || !type) return join(this.getVersionRoot(version), version + '.jar') + if (type === 'server') return this.getPath('libraries', 'net', 'minecraft', 'server', version, `server-${version}-bundled.jar`) + return join(this.getVersionRoot(version), version + `-${type}.jar`) + } + getVersionAll(version: string) { return [ join(this.versions, version), join(this.versions, version, version + '.json'), diff --git a/packages/core/launch.ts b/packages/core/launch.ts index 93bc8b724..e47e721bb 100644 --- a/packages/core/launch.ts +++ b/packages/core/launch.ts @@ -393,10 +393,6 @@ export interface BaseServerOptions { * Java executable. */ javaPath: string - /** - * Current working directory. Default is the same with the path. - */ - cwd?: string /** * No gui for the server launch */ @@ -413,16 +409,6 @@ export interface BaseServerOptions { spawn?: (command: string, args?: ReadonlyArray, options?: SpawnOptions) => ChildProcess } -export interface MinecraftServerOptions extends BaseServerOptions { - /** - * Minecraft location. - */ - path: string - /** - * The version id. - */ - version: string | ResolvedVersion -} /** * This is the case you provide the server jar execution path. */ @@ -432,18 +418,16 @@ export interface ServerOptions extends BaseServerOptions { * * This is the case like you are launching forge server. */ - serverExectuableJarPath: string + serverExectuableJarPath?: string + + mainClass?: string + + classPath?: string[] } -export async function launchServer(options: MinecraftServerOptions | ServerOptions) { +export async function launchServer(options: ServerOptions) { const args = await generateArgumentsServer(options) - let cwd = options.cwd - if ('path' in options) { - cwd = options.path - } else { - cwd = dirname(options.serverExectuableJarPath) - } - const spawnOption = { cwd, env: process.env, ...(options.extraExecOption || {}) } + const spawnOption = { env: process.env, ...(options.extraExecOption || {}) } return (options.spawn ?? spawn)(args[0], args.slice(1), spawnOption) } @@ -521,7 +505,7 @@ export function createMinecraftProcessWatcher(process: ChildProcess, emitter: Ev } else if (string.indexOf('Crash report saved to:') !== -1) { crashReportLocation = string.substring(string.indexOf('Crash report saved to:') + 'Crash report saved to: #@!@# '.length) crashReportLocation = crashReportLocation.replace(EOL, '').trim() - } else if (waitForReady && (string.indexOf('Reloading ResourceManager') !== -1 || string.indexOf('LWJGL Version: ') !== -1 || string.indexOf('OpenAL initialized.') !== -1)) { + } else if (waitForReady && (string.indexOf('Missing metadata in pack') !== -1 || string.indexOf('Registering resource reload listener') !== -1 || string.indexOf('Reloading ResourceManager') !== -1 || string.indexOf('LWJGL Version: ') !== -1 || string.indexOf('OpenAL initialized.') !== -1)) { waitForReady = false emitter.emit('minecraft-window-ready') } @@ -577,7 +561,7 @@ export async function launch(options: LaunchOption): Promise { /** * Generate the argument for server */ -export async function generateArgumentsServer(options: MinecraftServerOptions | ServerOptions) { +export async function generateArgumentsServer(options: ServerOptions) { const { javaPath, minMemory = 1024, maxMemory = 1024, extraJVMArgs = [], extraMCArgs = [], extraExecOption = {} } = options const cmd = [ javaPath, @@ -585,13 +569,15 @@ export async function generateArgumentsServer(options: MinecraftServerOptions | `-Xmx${(maxMemory)}M`, ...extraJVMArgs, ] - if ('path' in options) { - const mc = MinecraftFolder.from(options.path) - const version = options.version - const resolvedVersion = typeof version === 'string' ? await Version.parse(mc, version) : version - cmd.push('-jar', mc.getVersionJar(resolvedVersion.minecraftVersion, 'server')) - } else { + + if (options.classPath && options.classPath.length > 0) { + cmd.push('-cp', options.classPath.join(delimiter)) + } + + if (options.serverExectuableJarPath) { cmd.push('-jar', options.serverExectuableJarPath) + } else if (options.mainClass) { + cmd.push(options.mainClass) } cmd.push(...extraMCArgs) @@ -681,8 +667,6 @@ export async function generateArguments(options: LaunchOption) { } } - cmd.push('-DlibraryDirectory=' + mc.getPath('libraries')) - const jvmOptions = { natives_directory: nativeRoot, launcher_name: launcherName, @@ -711,6 +695,10 @@ export async function generateArguments(options: LaunchOption) { cmd.push(...jvmArguments.map((arg) => format(arg, jvmOptions))) + if (!cmd.some(v => v.startsWith('-DlibraryDirectory'))) { + cmd.push('-DlibraryDirectory=' + mc.getPath('libraries')) + } + // add extra jvm args if (options.extraJVMArgs instanceof Array) { if (options.extraJVMArgs.some((v) => typeof v !== 'string')) { diff --git a/packages/core/package.json b/packages/core/package.json index cd0d58906..70953a8e7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -42,6 +42,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/core/version.ts b/packages/core/version.ts index e2f525694..c6b8cbc16 100644 --- a/packages/core/version.ts +++ b/packages/core/version.ts @@ -303,7 +303,14 @@ export namespace Version { checksums?: string[] } - export type Library = NormalLibrary | NativeLibrary | PlatformSpecificLibrary | LegacyLibrary + export interface FlatLibrary { + name: string + url: string + sha1: string + size: number + } + + export type Library = NormalLibrary | NativeLibrary | PlatformSpecificLibrary | LegacyLibrary | FlatLibrary export type LaunchArgument = string | { rules?: Rule[] @@ -680,6 +687,19 @@ export namespace Version { } return new ResolvedLibrary(lib.name, info, lib.downloads.artifact) } + // flat library + if ('url' in lib && 'sha1' in lib && 'size' in lib) { + if (!lib.url) { + throw new Error('Corrupted library: ' + JSON.stringify(lib)) + } + return new ResolvedLibrary(lib.name, info, { + size: lib.size, + sha1: lib.sha1, + url: lib.url, + path: info.path, + }) + } + const maven = lib.url || 'https://libraries.minecraft.net/' const artifact: Artifact = { size: -1, @@ -856,4 +876,12 @@ export interface Version { * NON CONVERSION! This only present in some third party launcher like Labymod to mark the real minecraft version */ _minecraftVersion?: string + /** + * NON CONVERSION! This only present in some third party launcher like Forge to mark the forge version + */ + _forgeVersion?: string + /** + * NON CONVERSION! This only present in some third party launcher like Fabric to mark the fabric version + */ + _fabricLoaderVersion?: string } diff --git a/packages/curseforge/index.ts b/packages/curseforge/index.ts index 630ea88da..6f2deef58 100644 --- a/packages/curseforge/index.ts +++ b/packages/curseforge/index.ts @@ -37,6 +37,7 @@ export const enum FileModLoaderType { LiteLoader = 3, Fabric = 4, Quilt = 5, + NeoForge = 6, } export interface FileIndex { gameVersion: string @@ -243,6 +244,8 @@ export interface File { hashes: FileHash[] + fileFingerprint: number + /** * The date of this file uploaded */ @@ -520,6 +523,38 @@ export interface CurseforgeClientOptions { baseUrl?: string } +export interface FingerprintMatch { + /** + * The mod id + */ + id: number + file: File + latestFiles: File[] +} +export interface FingerprintsMatchesResult { + data: { + isCacheBuilt: boolean + exactMatches: FingerprintMatch[] + exactFingerprints: number[] + partialMatches: FingerprintMatch[] + partialFingerprints: object + unmatchedFingerprints: number[] + } +} + +export interface FingerprintFuzzyMatch { + id: number + file: File + latestFiles: File[] + fingerprints: number[] +} + +export interface FingerprintFuzzyMatchResult { + data: { + fuzzyMatches: FingerprintFuzzyMatch[] + } +} + export class CurseforgeApiError extends Error { constructor(readonly url: string, readonly status: number, readonly body: string) { super(`Fail to fetch curseforge api ${url}. Status=${status}. ${body}`) @@ -753,4 +788,44 @@ export class CurseforgeV1Client { const result = await response.json() as { data: string } return result.data } + + async getFingerprintsMatchesByGameId(gameId: number, fingerprints: number[], signal?: AbortSignal) { + const url = new URL(this.baseUrl + `/v1/fingerprints/${gameId}`) + const response = await fetch(url, { + method: 'POST', + body: JSON.stringify({ fingerprints }), + headers: { + ...this.headers, + 'content-type': 'application/json', + accept: 'application/json', + }, + dispatcher: this.dispatcher, + signal, + }) + if (response.status !== 200) { + throw new CurseforgeApiError(url.toString(), response.status, await response.text()) + } + const result = await response.json() as FingerprintsMatchesResult + return result.data + } + + async getFingerprintsFuzzyMatchesByGameId(gameId: number, fingerprints: number[], signal?: AbortSignal) { + const url = new URL(this.baseUrl + `/v1/fingerprints/fuzzy/${gameId}`) + const response = await fetch(url, { + method: 'POST', + body: JSON.stringify({ fingerprints }), + headers: { + ...this.headers, + 'content-type': 'application/json', + accept: 'application/json', + }, + dispatcher: this.dispatcher, + signal, + }) + if (response.status !== 200) { + throw new CurseforgeApiError(url.toString(), response.status, await response.text()) + } + const result = await response.json() as FingerprintFuzzyMatchResult + return result.data + } } diff --git a/packages/curseforge/package.json b/packages/curseforge/package.json index 05348125d..441f22895 100644 --- a/packages/curseforge/package.json +++ b/packages/curseforge/package.json @@ -35,7 +35,7 @@ ], "license": "MIT", "dependencies": { - "undici": "6.0.1" + "undici": "6.14.0" }, "bugs": { "url": "https://github.com/Voxelum/minecraft-launcher-core-node/issues" diff --git a/packages/discord-rpc/package.json b/packages/discord-rpc/package.json index 222fa6c2b..2dac7556f 100644 --- a/packages/discord-rpc/package.json +++ b/packages/discord-rpc/package.json @@ -35,14 +35,14 @@ "sideEffects": false, "dependencies": { "discord-api-types": "^0.37.39", - "undici": "6.0.1" + "undici": "6.14.0" }, "devDependencies": { "@types/node": "~18", "eslint": "^8.37.0", "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", - "typescript": "^5.2.2", + "typescript": "^5.3.3", "tsx": "^3.12.1" }, "engines": { diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index b2aa90729..bf3a6b4e0 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -4,13 +4,13 @@ "version": "0.0.1", "description": "The xmcl commonly used eslint config for typescript", "dependencies": { - "@typescript-eslint/eslint-plugin": "^6.13.2", - "@typescript-eslint/parser": "^6.13.2", - "eslint": "^8.37.0", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", + "eslint": "^8.57.0", "eslint-config-standard": "^17.1.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^16.3.1", "eslint-plugin-promise": "^6.1.1", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } \ No newline at end of file diff --git a/packages/file-transfer/abort.ts b/packages/file-transfer/abort.ts index 0648744dc..abf674303 100644 --- a/packages/file-transfer/abort.ts +++ b/packages/file-transfer/abort.ts @@ -6,9 +6,3 @@ export function resolveAbortSignal(signal?: AbortSignal) { removeEventListener() { return this }, } } - -export interface AbortSignal { - readonly aborted: boolean - addEventListener(event: string, handler: () => void): this - removeEventListener(event: string, handler: () => void): this -} diff --git a/packages/file-transfer/agent.ts b/packages/file-transfer/agent.ts index 94e94352e..4601fc3e6 100644 --- a/packages/file-transfer/agent.ts +++ b/packages/file-transfer/agent.ts @@ -1,179 +1,57 @@ -import { FileHandle } from 'fs/promises' -import CachePolicy from 'http-cache-semantics' -import { Dispatcher, errors, getGlobalDispatcher } from 'undici' -import { AbortSignal } from './abort' -import { CheckpointHandler, createInMemoryCheckpointHandler } from './checkpoint' -import { DownloadAbortError } from './error' -import { parseRangeInfo } from './metadata' -import { createDefaultRetryHandler, RetryPolicy } from './retry' -import { head, range } from './range' -import { DefaultRangePolicy, Range, RangePolicy } from './rangePolicy' -import { ProgressController } from './progress' +import { Agent, Dispatcher, RedirectHandler, RetryHandler } from 'undici' -const { ResponseStatusCodeError, RequestAbortedError } = errors -export interface DownloadAgentOptions { - retryHandler?: RetryPolicy - rangePolicy?: RangePolicy - dispatcher?: Dispatcher - checkpointHandler?: CheckpointHandler -} +class NeoRedirectHandler extends RedirectHandler { + constructor(dispatch: Dispatcher['dispatch'], maxRedirections: number, opts: Dispatcher.RequestOptions, handler: Dispatcher.DispatchHandlers, follow: boolean) { + super(dispatch as any, maxRedirections, opts, handler, follow) + } -export function resolveAgent(agent?: DownloadAgent | DownloadAgentOptions) { - return agent instanceof DownloadAgent - ? agent - : new DownloadAgent( - agent?.retryHandler ?? createDefaultRetryHandler(3), - agent?.rangePolicy ?? new DefaultRangePolicy(2 * 1024 * 1024, 4), - agent?.dispatcher ?? getGlobalDispatcher(), - agent?.checkpointHandler ?? createInMemoryCheckpointHandler(), - ) + onConnect(abort: () => void) { + // @ts-ignore + this.abort = abort + // @ts-ignore + this.handler.onConnect(abort, { history: this.history, opts: this.opts }) + } } -export class DownloadAgent { - constructor( - readonly retryHandler: RetryPolicy, - readonly rangePolicy: RangePolicy, - readonly dispatcher: Dispatcher, - readonly checkpointHandler: CheckpointHandler | undefined, - ) { - +export function getDefaultAgentOptions(retry?: RetryHandler.RetryOptions, defaultMaxRedirections = 5) { + const options = { + connections: 16, + interceptors: { + Agent: [ + createRedirectInterceptor(defaultMaxRedirections), + ], + Client: [ + createRetryInterceptor(retry), + createRedirectInterceptor(defaultMaxRedirections), + ], + }, } + return options +} - private async head(url: URL, headers: Record, signal?: AbortSignal) { - const kernel = head(url, headers, signal, this.dispatcher) - - let current = await kernel.next() - let attempt = 0 - for (; !current.done; current = await kernel.next(), attempt++) { - const error = current.value - if (error instanceof RequestAbortedError || !await this.retryHandler.retry(url, attempt, error)) { - // won't retry anymore - await kernel.throw(error) - } +export function createRetryInterceptor(retry?: RetryHandler.RetryOptions): Dispatcher.DispatchInterceptor { + return (dispatch) => { + return function Intercept(opts, handler) { + return dispatch(opts, new RetryHandler({ ...opts, retryOptions: retry }, { + dispatch, + handler, + })) } - - return current.value } +} - async dispatch(url: URL, method: string, headers: Record, destination: string, handle: FileHandle, progressController: ProgressController | undefined, abortSignal: AbortSignal | undefined) { - let targetUrl: URL = url - let ranges: Range[] | undefined - - const req = { - url: url.toString(), - method, - headers, - } - const checkpoint = await this.checkpointHandler?.lookup(url, handle, destination) - let policy = checkpoint?.policy - if (checkpoint) { - if (checkpoint.policy.satisfiesWithoutRevalidation(req)) { - // Use checkpoint without revalidate - ranges = checkpoint.ranges - targetUrl = new URL(checkpoint.url) - } else { - // try to revalidate - headers = checkpoint.policy.revalidationHeaders(req) as Record - } - } - - let total = -1 - - if (!ranges) { - let location = url.toString() - // Fetch download metadata - const response = await this.head(url, headers, abortSignal) - - const history = (response.context as any)?.history as (URL[] | undefined) - location = history?.[history?.length - 1].toString() || location - - // Try to revalidate the resource - const revalidation = policy?.revalidatedPolicy(req, { - headers: response.headers, - status: response.statusCode, - }) - - if (!revalidation?.modified && checkpoint) { - // Resource is not modified and we trust the last checkpoint - ranges = checkpoint.ranges - targetUrl = new URL(location) - total = checkpoint.contentLength - } else if (response.statusCode === 200 || response.statusCode === 201) { - // Respect head request result - // Calculate the resource slices/ranges - const { contentLength, isAcceptRanges } = parseRangeInfo(response.headers) - ranges = contentLength && isAcceptRanges - ? this.rangePolicy.computeRanges(contentLength) - : [{ start: 0, end: contentLength - 1 }] - targetUrl = new URL(location) - total = contentLength - await handle.truncate(total) - } else if (response.statusCode === 405) { - // Do not support HEAD request, we just download without range - ranges = [{ start: 0, end: -1 }] - await handle.truncate() - } else { - // @ts-ignore - throw new ResponseStatusCodeError(`Fail to check metadata of ${url}`, response.statusCode, response.headers, response.body) - } - - // Update the checkpoint policy - policy = revalidation?.policy ?? new CachePolicy(req, { - status: response.statusCode, - headers: response.headers, - }) - - this.checkpointHandler?.put(url, handle, destination, { - policy, - ranges, - contentLength: total, - url: url.toString(), - }) - } - - // Update the download status - const remaining = ranges.map((s) => s.end - s.start).reduce((a, b) => a + b, 0) - progressController?.onProgress(targetUrl, -1, total - remaining, total) - const _ranges = ranges - const results = await Promise.all(ranges.map(async (r) => { - // Start download range - const kernel = range(targetUrl, r, headers, handle, total, progressController, abortSignal, this.dispatcher) - - let attempt = 0 - for (let current = await kernel.next(); !current.done; current = await kernel.next(), attempt++) { - // The yield value must be error - const err = current.value - if (err instanceof RequestAbortedError || !await this.retryHandler.retry(url, attempt, err)) { - // won't retry anymore - await kernel.return(err) - return err - } - - const remaining = _ranges.map((s) => s.end - s.start).reduce((a, b) => a + b, 0) - progressController?.onProgress(targetUrl, -1, total - remaining, total) - } - })) - - const errors = results.filter((r) => !!r) - - if (errors[0] instanceof RequestAbortedError) { - // Throw abort error anyway - throw new DownloadAbortError(`Download is aborted by user: ${targetUrl}`, [], headers, destination, ranges) - } +export function createRedirectInterceptor(defaultMaxRedirections: number): Dispatcher.DispatchInterceptor { + return (dispatch) => { + return function Intercept(opts, handler) { + const { maxRedirections = defaultMaxRedirections } = opts as any - if (errors.length > 0) { - if (policy && ranges.length > 0) { - await this.checkpointHandler?.put(url, handle, destination, { - url: targetUrl.toString(), - policy, - contentLength: total, - ranges, - }).catch(() => { }) + if (!maxRedirections) { + return dispatch(opts, handler) } - throw errors[0] + const redirectHandler = new NeoRedirectHandler(dispatch, maxRedirections, opts, handler, false) + opts = { ...opts, maxRedirections: 0 } as any // Stop sub dispatcher from also redirecting. + return dispatch(opts, redirectHandler) } - - await this.checkpointHandler?.delete(url, handle, destination) } } diff --git a/packages/file-transfer/download.ts b/packages/file-transfer/download.ts index fb0694783..a81616c00 100644 --- a/packages/file-transfer/download.ts +++ b/packages/file-transfer/download.ts @@ -1,13 +1,37 @@ -import { FileHandle, mkdir, open, rename, stat, unlink } from 'fs/promises' -import { constants, existsSync, unlinkSync } from 'fs' +import { fdatasync, close as sclose, open as sopen, rename as srename, stat as sstat, unlink as sunlink, write } from 'fs' +import { mkdir } from 'fs/promises' import { dirname } from 'path' -import { errors } from 'undici' -import { DownloadAgent, resolveAgent } from './agent' -import { DownloadAbortError, DownloadAggregateError, DownloadFileSystemError } from './error' -import { AbortSignal } from './abort' -import { resolveProgressController, ProgressController } from './progress' -import { ChecksumValidatorOptions, resolveValidator, ValidationError, Validator } from './validator' -import assert from 'assert' +import { PassThrough, Writable, finished as sfinished } from 'stream' +import { Agent, Dispatcher, errors, stream } from 'undici' +import { promisify } from 'util' +// @ts-ignore +import { parseRangeHeader } from 'undici/lib/core/util' +import { getDefaultAgentOptions } from './agent' +import { CheckpointHandler } from './checkpoint' +import { ProgressController, resolveProgressController } from './progress' +import { DefaultRangePolicy, Range, RangePolicy } from './rangePolicy' +import { ChecksumValidatorOptions, Validator, resolveValidator } from './validator' + +const rename = promisify(srename) +const unlink = promisify(sunlink) +const stat = promisify(sstat) +const open = promisify(sopen) +const close = promisify(sclose) +const finished = promisify(sfinished) +const datasync = promisify(fdatasync) + +export function getDownloadBaseOptions(options?: T): DownloadBaseOptions { + if (!options) return {} + return { + headers: options.headers, + rangePolicy: options.rangePolicy, + dispatcher: options.dispatcher, + checkpointHandler: options.checkpointHandler, + skipHead: options.skipHead, + skipRevalidate: options.skipRevalidate, + skipPrevalidate: options.skipPrevalidate, + } +} export interface DownloadBaseOptions { /** @@ -15,17 +39,27 @@ export interface DownloadBaseOptions { */ headers?: Record /** - * The download agent + * The range policy to compute the ranges to download + */ + rangePolicy?: RangePolicy + /** + * The undici dispatcher */ - agent?: DownloadAgent + dispatcher?: Dispatcher /** - * Re-validate the file after download success - * @default false + * The checkpoint handler to save & restore the download progress + */ + checkpointHandler?: CheckpointHandler + /** + * Skip pre-head request to get the file size and range support + */ + skipHead?: boolean + /** + * Skip revalidate the file checksum after download */ skipRevalidate?: boolean /** - * Should skip prevalidate the file - * @default false + * Skip prevalidate the file checksum before download */ skipPrevalidate?: boolean } @@ -54,36 +88,190 @@ export interface DownloadOptions extends DownloadBaseOptions { /** * The user abort signal to abort the download */ - abortSignal?: AbortSignal + signal?: AbortSignal /** * Will first download to pending file and then rename to actual file */ pendingFile?: string } -async function openFile(destination: string, validator: Validator, url: string, skipPrevalidate: boolean) { - let fd = undefined as FileHandle | undefined +interface Context { + history: URL[] + opts: Dispatcher.DispatchOptions +} +interface Metadata { + origin?: string + pathname?: string + offset: number + total: number + acceptRange: boolean +} + +async function head(url: string, headers: Record, dispatcher: Dispatcher, signal?: AbortSignal) { try { - // use O_RDWR for read write which won't be truncated - fd = await open(destination, constants.O_RDWR | constants.O_CREAT) - - const size = (await fd.stat()).size - // pre-validate the file - if (size !== 0 && !skipPrevalidate) { - const error = await validator.validate(destination, url).catch((e) => e) - // if the file size is not 0 and checksum matched, we just don't process the file - if (!error) { - await fd?.close().catch(() => { }) + const { opaque } = await stream(url, { + method: 'HEAD', + headers, + dispatcher, + signal, + opaque: {}, + headersTimeout: 5000, + bodyTimeout: 5000, + throwOnError: true, + }, ({ opaque, headers, context, statusCode }) => { + const length = headers['content-length'] ? parseInt(headers['content-length'] as string) : 0 + const rangeHeader = parseRangeHeader(headers['content-range']) + const offset = rangeHeader?.start ?? 0 + const total = rangeHeader?.size || length + const ctx = context as Context + const metadata = opaque as Metadata + + metadata.offset = offset + metadata.total = total + metadata.acceptRange = headers['accept-ranges'] === 'bytes' + + if (ctx) { + metadata.pathname = ctx.opts.path + metadata.origin = ctx.opts.origin as string + } + + const pass = new PassThrough() + + if (statusCode === 203) { + setImmediate(() => pass.emit('error', new errors.ResponseStatusCodeError('', statusCode, headers, ''))) + } + + return pass + }) + + return opaque as Metadata + } catch (e) { + if (e instanceof errors.ResponseStatusCodeError) { + if (e.statusCode === 405) { return undefined } } - return fd - } catch (e) { - await fd?.close().catch(() => { }) throw e } } +async function get( + url: string, + fd: number, + headers: Record, + range: Range | undefined, + dispatcher: Dispatcher, + progress: (url: URL, chunkSize: number, written: number, partLength: number, totalLength: number) => void, + signal?: AbortSignal, +) { + const parsedUrl = new URL(url) + + let writable: Writable | undefined + try { + const requestHeader = { ...headers } + if (range) { + requestHeader.range = `bytes=${range.start}-${range.end}` + } + await stream(url, { + method: 'GET', + maxRedirections: 5, + headers: requestHeader, + throwOnError: true, + dispatcher, + signal, + }, ({ statusCode, headers }) => { + if (statusCode === 203 || statusCode >= 300) { + const pass = new PassThrough() + + setImmediate(() => pass.emit('error', new errors.ResponseStatusCodeError('', statusCode, headers, ''))) + + return pass + } + + /** + * The length of the part + */ + const length = headers['content-length'] ? parseInt(headers['content-length'] as string) : 0 + const rangeHeader = parseRangeHeader(headers['content-range']) + const offset: number = rangeHeader?.start ?? range?.start ?? 0 + /** + * The length of the total file + */ + const totalLength: number = rangeHeader?.size ?? 0 + + let written = 0 + const writable = new Writable({ + write(chunk, encoding, callback) { + write(fd, chunk, offset + written, (err) => { + if (err) { + if (!err.stack) { + err.stack = new Error().stack + } + callback(err) + return + } + written += chunk.length + progress(parsedUrl, chunk.length, written, length, totalLength) + callback() + }) + }, + writev(chunks, callback) { + const buffer = Buffer.concat(chunks.map((c) => c.chunk)) + write(fd, buffer, offset + written, (err) => { + if (err) { + if (!err.stack) { + err.stack = new Error().stack + } + callback(err) + return + } + written += buffer.length + progress(parsedUrl, buffer.length, written, length, totalLength) + callback() + }) + }, + final(callback) { + progress(parsedUrl, 0, written, length, totalLength) + callback() + }, + highWaterMark: 1024 * 1024, + signal, + }) + + progress(parsedUrl, 0, written, length, totalLength) + + return writable + }) + + if (writable && !writable.writableFinished) { + await finished(writable) + } + } catch (e) { + const err = e as any + if (!err.stack) { + err.stack = new Error().stack + } + return e + } +} + +function computeRanges(metadata: Metadata | undefined, rangePolicy: RangePolicy) { + if (!metadata) return [undefined] + const ranges = rangePolicy.computeRanges(metadata.total) + if (ranges.length > 1) return ranges + return [undefined] +} + +function getUrl(metadata: Metadata | undefined, original: string) { + if (!metadata || !metadata.pathname || !metadata.origin) return original + try { + const url = new URL(metadata.pathname, metadata.origin) + return url.toString() + } catch { + return original + } +} + /** * Download url or urls to a file path. This process is abortable, it's compatible with the dom like `AbortSignal`. */ @@ -93,110 +281,167 @@ export async function download(options: DownloadOptions) { const destination = options.destination const progressController = resolveProgressController(options.progressController) const validator = resolveValidator(options.validator) - const abortSignal = options.abortSignal - const agent = resolveAgent(options.agent) - const skipRevalidate = options.skipRevalidate ?? false - const skipPrevalidate = options.skipPrevalidate ?? false + const abortSignal = options.signal const pendingFile = options.pendingFile - - let fd = undefined as FileHandle | undefined + const skipPrevalidate = options.skipPrevalidate + const skipRevalidate = options.skipRevalidate + const rangePolicy = options?.rangePolicy ?? new DefaultRangePolicy(2 * 1024 * 1024, 4) + const dispatcher = options?.dispatcher ?? new Agent(getDefaultAgentOptions()) await mkdir(dirname(destination), { recursive: true }).catch(() => { }) - // Access file handle - try { + + if (!skipPrevalidate && validator) { + const error = await validator.validate(destination, urls[0]).catch((e) => e) + if (!error) { + // file is already downloaded and validated + return + } + if (pendingFile) { const error = await validator.validate(destination, urls[0]).catch((e) => e) if (!error) { - // file is already downloaded and validated - return - } - fd = await openFile(pendingFile, validator, urls[0], skipPrevalidate) - if (!fd) { // file is already downloaded and validated // we will overwrite destination with pending file - await unlink(destination).catch((e) => undefined) + await unlink(destination).catch(() => undefined) await rename(pendingFile, destination) return } - } else { - fd = await openFile(destination, validator, urls[0], skipPrevalidate) - if (!fd) { - // file is already downloaded and validated - return - } } - } catch (e) { - throw new DownloadFileSystemError(`Fail to get access on ${destination}`, urls, headers, destination, e) } - // Start to download + const output = pendingFile || destination + const fd = await open(output, 'w').catch((e) => { + e.stack = new Error().stack + Object.assign(e, { + phase: 'open', + urls, + headers, + destination, + pendingFile, + }) + throw e + }) try { - // File descriptor scope - try { - // Aggregated errors - let aggregatedErrors: { url: string }[] = [] - for (const url of urls) { - try { - await agent.dispatch(new URL(url), 'GET', headers, destination, fd, progressController, abortSignal) - await fd.datasync() - if (!skipRevalidate) { - await validator.validate(pendingFile || destination, url) - } - // Dismiss all errors - aggregatedErrors = [] - break - } catch (e) { - if (e instanceof errors.RequestAbortedError) { - // User abortion during HEAD - throw new DownloadAbortError('Download is aborted by user.', urls, headers, destination, []) - } - if (e instanceof DownloadAbortError) { - // User abortion should throw anyway - throw e - } + const aggregate: Error[] = [] + for (const url of urls) { + const decorate = (e: any, phase: string) => Object.assign(e, { + phase, + urls, + url, + headers, + destination, + pendingFile, + }) + const metadataOrMetadata = !options.skipHead + ? await head(url, headers, dispatcher, abortSignal).catch((e) => { + return decorate(e, 'head') as Error + }) + : undefined + if (metadataOrMetadata instanceof Error) { + if (metadataOrMetadata instanceof errors.RequestAbortedError) throw metadataOrMetadata + aggregate.push(metadataOrMetadata) + continue + } + const metadata = metadataOrMetadata + const ranges = metadata?.acceptRange ? computeRanges(metadata, rangePolicy) : [undefined] + const redirectedUrl = getUrl(metadata, url) + let writtens = ranges.map(() => 0) + let totals = ranges.map(() => 0) + + progressController(new URL(url), 'start', 0, metadata?.total || 0) + + let results = await Promise.all(ranges.map( + (range, index) => get(redirectedUrl, fd, headers, range, dispatcher, (url, chunk, written, partLength, totalLength) => { + writtens[index] = written + totals[index] = partLength + const writtenTotal = writtens.reduce((a, b) => a + b, 0) + const totalTotal = metadata?.total || totalLength || totals.reduce((a, b) => a + b, 0) + progressController(url, chunk, writtenTotal, totalTotal) + }, abortSignal)), + ) + + if (metadataOrMetadata && results.some(e => e instanceof errors.ResponseStatusCodeError)) { + // Invalid range, we will retry without range + writtens = [0] + totals = [0] + results = [ + await get(redirectedUrl, fd, headers, undefined, dispatcher, (url, chunk, written, partLength, totalLength) => { + writtens[0] = written + totals[0] = partLength + const writtenTotal = writtens.reduce((a, b) => a + b, 0) + const totalTotal = metadata?.total || totalLength || totals.reduce((a, b) => a + b, 0) + progressController(url, chunk, writtenTotal, totalTotal) + }, abortSignal), + ] + } - aggregatedErrors.push(Object.assign((e as any), { - url, - })) + const writtenTotal = writtens.reduce((a, b) => a + b, 0) + const totalTotal = metadata?.total || totals.reduce((a, b) => a + b, 0) + progressController(new URL(url), 'end', writtenTotal, totalTotal) + + let noErrors = true + for (const e of results) { + if (!e) continue + if (e instanceof errors.RequestAbortedError) throw e + noErrors = false + aggregate.push(decorate(e, 'get')) + } + + try { + await datasync(fd) + } catch (e) { + noErrors = false + const err = e as any + if (!err.stack) { + err.stack = new Error().stack } + aggregate.push(decorate(e, 'datasync')) } - if (aggregatedErrors.length > 0) { - throw aggregatedErrors + if (!skipRevalidate && validator) { + const error = await validator.validate(output, urls[0]).catch((e) => e) + if (error) { + noErrors = false + aggregate.push(decorate(error, 'validate')) + } } - // No error, so we are done - if (pendingFile) { - // If pending file, we need to rename it to destination with overwrite - await unlink(destination).catch(() => undefined) - await rename(pendingFile, destination).catch((e) => { - throw new DownloadFileSystemError('Download file destination already existed', urls, headers, destination, e) - }) + // if we have any errors, we will continue to next url + if (!noErrors) continue + + // if we are not download to a pending file, we are good + if (!pendingFile) return + + await unlink(destination).catch(() => undefined) + const fStat = await stat(pendingFile).catch(() => undefined) + const err = await rename(pendingFile, destination).catch(e => decorate(e, 'rename')) + if (err && fStat?.ino !== (await stat(destination).catch(() => undefined))?.ino) { + err.stack = new Error().stack + throw err } - } finally { - await fd.close().catch(() => { }) - } - } catch (e) { - if (e instanceof DownloadAbortError) { - e.urls = urls - throw e - } - if (e instanceof DownloadFileSystemError) { - throw e + return } - assert(e instanceof Array) - - if (e[e.length - 1] instanceof ValidationError) { - // Last download corrupted... - await unlink(destination).catch(() => { }) - if (pendingFile) { - await unlink(pendingFile).catch(() => { }) + if (aggregate.length > 1) { + const flatten = [] as Error[] + const flatError = (e: any) => { + if (e instanceof AggregateError) { + for (const err of e.errors) { + flatError(err) + } + } + flatten.push(e) + } + for (const e of aggregate) { + flatError(e) } + throw new AggregateError(flatten) } - throw new DownloadAggregateError(e, 'Multiple errors occurred during download process', urls, headers, destination) + throw aggregate[0] + } finally { + await close(fd).catch(() => undefined) } } diff --git a/packages/file-transfer/error.ts b/packages/file-transfer/error.ts index f83be515d..119397ac6 100644 --- a/packages/file-transfer/error.ts +++ b/packages/file-transfer/error.ts @@ -13,26 +13,6 @@ export class DownloadError extends Error { } } -export class DownloadAbortError extends DownloadError { - constructor( - message: string, - urls: string[], - headers: Record, - destination: string, - readonly segments: Range[], - options?: ErrorOptions, - ) { - super( - message, - urls, - headers, - destination, - options, - ) - this.name = 'DownloadAbortError' - } -} - export class DownloadFileSystemError extends DownloadError { constructor( message: string, @@ -51,21 +31,3 @@ export class DownloadFileSystemError extends DownloadError { this.name = 'DownloadFileSystemError' } } - -export class DownloadAggregateError extends AggregateError { - constructor( - errors: any[], - message: string, - readonly urls: string[], - readonly headers: Record, - readonly destination: string, - options?: ErrorOptions, - ) { - super( - errors, - message, - options, - ) - this.name = 'DownloadAggregateError' - } -} diff --git a/packages/file-transfer/index.test.ts b/packages/file-transfer/index.test.ts new file mode 100644 index 000000000..26b2c67ae --- /dev/null +++ b/packages/file-transfer/index.test.ts @@ -0,0 +1 @@ +import { download } from '.' diff --git a/packages/file-transfer/package.json b/packages/file-transfer/package.json index e1104b303..ddfed2f12 100644 --- a/packages/file-transfer/package.json +++ b/packages/file-transfer/package.json @@ -19,7 +19,7 @@ "dependencies": { "@types/http-cache-semantics": "^4.0.1", "http-cache-semantics": "^4.1.1", - "undici": "6.0.1" + "undici": "6.14.0" }, "repository": { "type": "git", @@ -44,6 +44,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/file-transfer/progress.ts b/packages/file-transfer/progress.ts index 9b57734d8..fcf37652e 100644 --- a/packages/file-transfer/progress.ts +++ b/packages/file-transfer/progress.ts @@ -1,26 +1,18 @@ -import { URL } from 'url' - /** * The controller that maintain the download status */ export interface ProgressController { - readonly progress: number - onProgress(url: URL, chunkSize: number, progress: number, total: number): void + (url: URL, chunkSizeOrStatus: number | 'start' | 'end', written: number, total: number): void } -export function createProgressController(onProgress?: ProgressController['onProgress']): ProgressController { - let progress = 0 - const controller: ProgressController = { - get progress() { return progress }, - onProgress(url, chunk, _progress, total) { - progress = _progress - onProgress?.(url, chunk, _progress, total) - }, +export function createProgressController(onProgress?: ProgressController): ProgressController { + const controller: ProgressController = (url, chunk, _progress, total) => { + onProgress?.(url, chunk, _progress, total) } return controller } -export function resolveProgressController(controller?: ProgressController | ProgressController['onProgress']): ProgressController { +export function resolveProgressController(controller?: ProgressController | ProgressController): ProgressController { if (!controller) { return createProgressController() } if (typeof controller === 'function') { return createProgressController(controller) } return controller diff --git a/packages/file-transfer/range.ts b/packages/file-transfer/range.ts deleted file mode 100644 index 1830b60f5..000000000 --- a/packages/file-transfer/range.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { FileHandle } from 'fs/promises' -import { Writable } from 'stream' -import { Dispatcher, request, stream } from 'undici' -import { AbortSignal } from './abort' -import { Range } from './rangePolicy' -import { ProgressController } from './progress' - -export async function * head(url: URL, headers: Record, signal: AbortSignal | undefined, dispatcher: Dispatcher | undefined) { - let timeout = 5_000 - while (true) { - try { - const response = await request(url, { - method: 'HEAD', - maxRedirections: 2, - // @ts-ignore - connectTimeout: timeout, - headersTimeout: timeout, - headers, - signal, - dispatcher, - }) - return response - } catch (e) { - timeout = timeout * 2 > 40_000 ? 40_000 : timeout * 2 - yield e - } - } -} - -export async function * range( - url: URL, - segment: Range, - headers: Record, - handle: FileHandle, - total: number, - statusController: ProgressController | undefined, - abortSignal: AbortSignal | undefined, - dispatcher: Dispatcher | undefined, -): AsyncGenerator { - if (segment.start >= segment.end) { - // the segment is finished, just ignore it - return - } - let contentLength = -1 - const fileStream = new Writable({ - write(chunk, en, cb) { - // track the progress - const position = segment.start - segment.start += chunk.length - handle.write(chunk, 0, chunk.length, position).then(({ bytesWritten }) => { - statusController?.onProgress(url, bytesWritten, statusController.progress + bytesWritten, total) - cb() - }, cb) - }, - }) - - let nextUrl = url - while (true) { - if (segment.start >= segment.end) { - // the segment is finished, just ignore it - return - } - try { - const { opaque } = await stream(nextUrl, { - method: 'GET', - dispatcher, - headers: { - ...headers, - Range: segment.end < 0 ? undefined : `bytes=${segment.start}-${(segment.end) ?? ''}`, - }, - throwOnError: true, - maxRedirections: 2, - signal: abortSignal, - opaque: { fileStream }, - }, ({ opaque, headers: responseHeaders, statusCode }) => { - if (statusCode >= 300) { - if (typeof responseHeaders.location === 'string') { - nextUrl = new URL(responseHeaders.location) - Object.assign(opaque as any, { continue: true }) - } else { - (opaque as any).error = Object.assign(new Error(`Unexpected status code ${statusCode} from ${url}`), { - name: 'UnexpectedStatusCodeError', - range: segment.end < 0 ? undefined : `bytes=${segment.start}-${(segment.end) ?? ''}`, - }) - // return a run-away writable - return new Writable({ write(chunk, en, cb) { cb() } }) - } - } - if (typeof responseHeaders['content-length'] === 'string') { - contentLength = Number.parseInt(responseHeaders['content-length'] ?? '0') - const end = segment.start + contentLength - 1 - if (end !== segment.end) { - segment.end = segment.start + contentLength - } - } - return (opaque as any).fileStream as Writable - }) - if ((opaque as any).continue) { - continue - } - if ((opaque as any).error) { - throw (opaque as any).error - } - return - } catch (e) { - yield e - } - } -} diff --git a/packages/file-transfer/tsconfig.json b/packages/file-transfer/tsconfig.json index 69260bfc4..3d6b92bbc 100644 --- a/packages/file-transfer/tsconfig.json +++ b/packages/file-transfer/tsconfig.json @@ -3,13 +3,13 @@ "abort.ts", "agent.ts", "checkpoint.ts", + "download.ts", "error.ts", "index.ts", "metadata.ts", - "retry.ts", - "range.ts", - "rangePolicy.ts", "progress.ts", + "rangePolicy.ts", + "retry.ts", "validator.ts" ], "extends": "../../tsconfig.json", diff --git a/packages/file-transfer/validator.ts b/packages/file-transfer/validator.ts index df4b0f8ad..30e968f1f 100644 --- a/packages/file-transfer/validator.ts +++ b/packages/file-transfer/validator.ts @@ -1,6 +1,6 @@ import { createHash } from 'crypto' -import { createReadStream } from 'fs' -import { FileHandle, readFile } from 'fs/promises' +import { readFile, createReadStream, exists } from 'fs' +import { promisify } from 'util' import { pipeline } from 'stream/promises' export interface Validator { @@ -18,6 +18,9 @@ export class ChecksumValidator implements Validator { async validate(destination: string, url: string): Promise { if (this.checksum) { + if (!await promisify(exists)(destination)) { + throw new ChecksumNotMatchError(this.checksum.algorithm, this.checksum.hash, '', destination, url) + } const hash = createHash(this.checksum.algorithm) await pipeline(createReadStream(destination), hash) const actual = hash.digest('hex') @@ -34,12 +37,12 @@ export function isValidator(options?: Validator | ChecksumValidatorOptions): opt return 'validate' in options && typeof options.validate === 'function' } -export function resolveValidator(options?: ChecksumValidatorOptions | Validator): Validator { +export function resolveValidator(options?: ChecksumValidatorOptions | Validator): Validator | undefined { if (isValidator(options)) { return options } if (options) { return new ChecksumValidator({ hash: options.hash, algorithm: options.algorithm }) } - return { validate() { return Promise.resolve() } } + return undefined } export interface ChecksumValidatorOptions { @@ -49,7 +52,7 @@ export interface ChecksumValidatorOptions { export class JsonValidator implements Validator { async validate(destination: string, url: string): Promise { - const content = await readFile(destination, 'utf-8') + const content = await promisify(readFile)(destination, 'utf-8') JSON.parse(content) } } diff --git a/packages/forge-site-parser/package.json b/packages/forge-site-parser/package.json index 5740395df..6e452f4e5 100644 --- a/packages/forge-site-parser/package.json +++ b/packages/forge-site-parser/package.json @@ -45,6 +45,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/game-data/package.json b/packages/game-data/package.json index a3fb488b4..04f2310ca 100644 --- a/packages/game-data/package.json +++ b/packages/game-data/package.json @@ -45,6 +45,6 @@ "tslib": "^2.5.0", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/gamesetting/package.json b/packages/gamesetting/package.json index 6d9536e79..6ea6b8fc9 100644 --- a/packages/gamesetting/package.json +++ b/packages/gamesetting/package.json @@ -38,6 +38,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/installer/DownloadProgressPayload.ts b/packages/installer/DownloadProgressPayload.ts new file mode 100644 index 000000000..aa899a7d0 --- /dev/null +++ b/packages/installer/DownloadProgressPayload.ts @@ -0,0 +1,7 @@ +export interface DownloadProgressPayload { + url?: URL + file?: string + chunkSizeOrStatus: number | 'start' | 'end' + progress: number + total: number +} diff --git a/packages/installer/downloadTask.ts b/packages/installer/downloadTask.ts deleted file mode 100644 index 71bfa28b0..000000000 --- a/packages/installer/downloadTask.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { AbortSignal, download, DownloadAbortError, DownloadOptions, ProgressController } from '@xmcl/file-transfer' -import { AbortableTask } from '@xmcl/task' - -export class DownloadTask extends AbortableTask implements ProgressController { - protected abort: (isCancelled: boolean) => void = () => { } - - constructor(protected options: DownloadOptions) { - super() - this._from = options.url instanceof Array ? options.url[0] : options.url - this._to = options.destination - } - - onProgress(url: URL, chunkSize: number, progress: number, total: number): void { - this._progress = progress - this._total = total - this._from = url.toString() - this.update(chunkSize) - } - - protected process(): Promise { - const listeners: Array<() => void> = [] - const aborted = () => this.isCancelled || this.isPaused - const signal: AbortSignal = { - get aborted() { return aborted() }, - addEventListener(event, listener) { - if (event !== 'abort') { - return this - } - listeners.push(listener) - return this - }, - removeEventListener(event, listener) { - // noop as this will be auto gc - return this - }, - } - this.abort = () => { - listeners.forEach((l) => l()) - } - return download({ - ...this.options, - progressController: this, - abortSignal: signal, - }) - } - - protected isAbortedError(e: any): boolean { - if (e instanceof DownloadAbortError) { - return true - } - return false - } -} diff --git a/packages/installer/fabric.ts b/packages/installer/fabric.ts index 3fc35b8ea..e1d4a5db3 100644 --- a/packages/installer/fabric.ts +++ b/packages/installer/fabric.ts @@ -1,10 +1,7 @@ -import { MinecraftFolder, MinecraftLocation, Version } from '@xmcl/core' +import { MinecraftFolder, MinecraftLocation } from '@xmcl/core' +import type { Version } from '@xmcl/core' import { writeFile } from 'fs/promises' -import { Dispatcher, request } from 'undici' -import { ensureFile, InstallOptions } from './utils' - -export const YARN_MAVEN_URL = 'https://maven.fabricmc.net/net/fabricmc/yarn/maven-metadata.xml' -export const LOADER_MAVEN_URL = 'https://maven.fabricmc.net/net/fabricmc/fabric-loader/maven-metadata.xml' +import { FetchOptions, InstallOptions, doFetch, ensureFile } from './utils' export interface FabricArtifactVersion { gameVersion?: string // "20w10a", @@ -37,161 +34,68 @@ export interface FabricLoaderArtifact { } } -export interface FabricOptions { - dispatcher?: Dispatcher -} - /** - * Get all the artifacts provided by fabric - * @param remote The fabric API host - * @beta + * Get supported fabric game versions */ -export async function getFabricArtifacts(options?: FabricOptions): Promise { - const response = await request('https://meta.fabricmc.net/v2/versions', { throwOnError: true, dispatcher: options?.dispatcher }) - const body = response.body.json() as any - return body -} -/** - * Get fabric-yarn artifact list - * @param remote The fabric API host - * @beta - */ -export async function getYarnArtifactList(options?: FabricOptions): Promise { - const response = await request('https://meta.fabricmc.net/v2/versions/yarn', { throwOnError: true, dispatcher: options?.dispatcher }) - const body = response.body.json() as any - return body -} -/** - * Get fabric-yarn artifact list by Minecraft version - * @param minecraft The Minecraft version - * @param remote The fabric API host - * @beta - */ -export async function getYarnArtifactListFor(minecraft: string, options?: FabricOptions): Promise { - const response = await request('https://meta.fabricmc.net/v2/versions/yarn/' + minecraft, { throwOnError: true, dispatcher: options?.dispatcher }) - const body = response.body.json() as any - return body +export async function getFabricGames(options?: FetchOptions): Promise { + const response = await doFetch(options, `${DEFAULT_META_URL_FABRIC}/v2/game`) + const body = await response.json() as Array<{ version: string }> + return body.map((g) => g.version) } + /** * Get fabric-loader artifact list - * @param remote The fabric API host - * @beta */ -export async function getLoaderArtifactList(options?: FabricOptions): Promise { - const response = await request('https://meta.fabricmc.net/v2/versions/loader', { throwOnError: true, dispatcher: options?.dispatcher }) - const body = response.body.json() as any +export async function getFabricLoaders(options?: FetchOptions): Promise { + const response = await doFetch(options, `${DEFAULT_META_URL_FABRIC}/v2/versions/loader`) + const body = response.json() return body } + /** * Get fabric-loader artifact list by Minecraft version * @param minecraft The minecraft version - * @param remote The fabric API host - * @beta */ -export async function getLoaderArtifactListFor(minecraft: string, options?: FabricOptions): Promise { - const response = await request('https://meta.fabricmc.net/v2/versions/loader/' + minecraft, { throwOnError: true, dispatcher: options?.dispatcher }) - const body = response.body.json() as any +export async function getLoaderArtifactListFor(minecraft: string, options?: FetchOptions): Promise { + const response = await doFetch(options, `${DEFAULT_META_URL_FABRIC}/v2/versions/loader/` + minecraft) + const body = response.json() return body } /** * Get fabric-loader artifact list by Minecraft version * @param minecraft The minecraft version * @param loader The yarn-loader version - * @param remote The fabric API host - * @beta */ -export async function getFabricLoaderArtifact(minecraft: string, loader: string, options?: FabricOptions): Promise { - const response = await request('https://meta.fabricmc.net/v2/versions/loader/' + minecraft + '/' + loader, { throwOnError: true, dispatcher: options?.dispatcher }) - const body = response.body.json() as any +export async function getFabricLoaderArtifact(minecraft: string, loader: string, options?: FetchOptions): Promise { + const response = await doFetch(options, `${DEFAULT_META_URL_FABRIC}/v2/versions/loader/` + minecraft + '/' + loader) + const body = response.json() return body } -/** - * Install the fabric to the client. Notice that this will only install the json. - * You need to call `Installer.installDependencies` to get a full client. - * @param yarnVersion The yarn version - * @param loaderVersion The fabric loader version - * @param minecraft The minecraft location - * @returns The installed version id - */ -// export async function installFabricYarnAndLoader(yarnVersion: string, loaderVersion: string, minecraft: MinecraftLocation, options: InstallOptions = {}) { -// const folder = MinecraftFolder.from(minecraft); -// const mcversion = yarnVersion.split("+")[0]; -// const id = options.versionId || `${mcversion}-fabric${yarnVersion}-${loaderVersion}`; - -// const jsonFile = folder.getVersionJson(id); - -// const body: Version = constr esponse = await request(`https://fabricmc.net/download/technic/?yarn=${encodeURIComponent(yarnVersion)}&loader=${encodeURIComponent(loaderVersion)}`, { throwOnError: true, dispatcher: options?.dispatcher }); -// const body = response.body.json() as any; -// return body; -// body.id = id; -// if (typeof options.inheritsFrom === "string") { -// body.inheritsFrom = options.inheritsFrom; -// } -// await ensureFile(jsonFile); -// await writeFile(jsonFile, JSON.stringify(body)); - -// return id; -// } - export interface FabricInstallOptions extends InstallOptions { side?: 'client' | 'server' - yarnVersion?: string | FabricArtifactVersion } /** - * Generate fabric version json to the disk according to yarn and loader - * @param side Client or server - * @param yarnVersion The yarn version string or artifact - * @param loader The loader artifact - * @param minecraft The Minecraft Location - * @param options The options - * @beta + * Generate fabric version json from loader artifact. + * @param loader The fabric loader artifact + * @param side The side of the fabric + * @param options + * @returns The generated version json */ -export async function installFabric(loader: FabricLoaderArtifact, minecraft: MinecraftLocation, options: FabricInstallOptions = {}) { - const folder = MinecraftFolder.from(minecraft) - - let yarn: string | undefined - const side = options.side ?? 'client' - let id = options.versionId - let mcversion: string - if (options.yarnVersion) { - const yarnVersion = options.yarnVersion - if (typeof yarnVersion === 'string') { - yarn = yarnVersion - mcversion = yarn.split('+')[0] - } else { - yarn = yarnVersion.version - mcversion = yarnVersion.gameVersion || yarn.split('+')[0] - } - } else { - mcversion = loader.intermediary.version - } - - if (!id) { - id = mcversion - if (yarn) { - id += `-fabric${yarn}-loader${loader.loader.version}` - } else { - id += `-fabric${loader.loader.version}` - } - } +export function getVersionJsonFromLoaderArtifact(loader: FabricLoaderArtifact, side: 'client' | 'server', options: FabricInstallOptions = {}) { + const mcversion = loader.intermediary.version + const id = options.versionId || `${mcversion}-fabric${loader.loader.version}` const libraries = [ { name: loader.loader.maven, url: 'https://maven.fabricmc.net/' }, { name: loader.intermediary.maven, url: 'https://maven.fabricmc.net/' }, - ...(options.yarnVersion - ? [{ name: `net.fabricmc:yarn:${yarn}`, url: 'https://maven.fabricmc.net/' }] - : []), ...loader.launcherMeta.libraries.common, ...loader.launcherMeta.libraries[side], ] const mainClass = loader.launcherMeta.mainClass[side] const inheritsFrom = options.inheritsFrom || mcversion - const jsonFile = folder.getVersionJson(id) - - await ensureFile(jsonFile) - await writeFile(jsonFile, JSON.stringify({ + return { id, inheritsFrom, mainClass, @@ -202,7 +106,53 @@ export async function installFabric(loader: FabricLoaderArtifact, minecraft: Min }, releaseTime: new Date().toJSON(), time: new Date().toJSON(), - })) + } +} + +/** + * Install fabric version json. + * + * If side is `server`, it requires the Minecraft version json to be installed. + * + * @returns The installed version id + */ +export async function installFabricByLoaderArtifact(loader: FabricLoaderArtifact, minecraft: MinecraftLocation, options: FabricInstallOptions = {}) { + const folder = MinecraftFolder.from(minecraft) + + const side = options.side || 'client' + const version = getVersionJsonFromLoaderArtifact(loader, side, options) + + const jsonFile = side === 'client' ? folder.getVersionJson(version.id) : folder.getVersionServerJson(version.id) + await ensureFile(jsonFile) + await writeFile(jsonFile, JSON.stringify(version, null, 4)) + + return version.id +} + +export interface InstallFabricVersionOptions extends FetchOptions { + minecraftVersion: string + version: string + minecraft: MinecraftLocation + side?: 'client' | 'server' +} + +export const DEFAULT_META_URL_FABRIC = 'https://meta.fabricmc.net' + +export async function installFabric(options: InstallFabricVersionOptions) { + const side = options.side ?? 'client' + const url = side === 'client' + ? `${DEFAULT_META_URL_FABRIC}/v2/versions/loader/${options.minecraftVersion}/${options.version}/profile/json` + : `${DEFAULT_META_URL_FABRIC}/v2/versions/loader/${options.minecraftVersion}/${options.version}/server/json` + const response = await doFetch(options, url) + const content: Version = await response.json() as any + + const minecraft = MinecraftFolder.from(options.minecraft) + const versionName = content.id + + const jsonPath = side === 'client' ? minecraft.getVersionJson(versionName) : minecraft.getVersionServerJson(versionName) + + await ensureFile(jsonPath) + await writeFile(jsonPath, JSON.stringify(content)) - return id + return versionName } diff --git a/packages/installer/forge.ts b/packages/installer/forge.ts index d0571b85b..bcc41c8c2 100644 --- a/packages/installer/forge.ts +++ b/packages/installer/forge.ts @@ -1,18 +1,17 @@ import { LibraryInfo, MinecraftFolder, MinecraftLocation, Version as VersionJson } from '@xmcl/core' +import { download, getDownloadBaseOptions } from '@xmcl/file-transfer' import { parse as parseForge } from '@xmcl/forge-site-parser' -import { Task, task } from '@xmcl/task' import { filterEntries, open, openEntryReadStream, readAllEntries, readEntry } from '@xmcl/unzip' import { createWriteStream } from 'fs' import { writeFile } from 'fs/promises' import { dirname, join } from 'path' import { pipeline } from 'stream/promises' -import { Dispatcher, request } from 'undici' import { Entry, ZipFile } from 'yauzl' import { ZipFile as WriteableZipFile } from 'yazl' -import { DownloadTask } from './downloadTask' +import { DownloadProgressPayload } from './DownloadProgressPayload' import { LibraryOptions, resolveLibraryDownloadUrls } from './minecraft' -import { InstallProfile, InstallProfileOption, installByProfileTask } from './profile' -import { InstallOptions as InstallOptionsBase, ensureDir, ensureFile, joinUrl, normalizeArray } from './utils' +import { InstallProfile, InstallProfileOption, installByProfile } from './profile' +import { FetchOptions, InstallOptions as InstallOptionsBase, doFetch, ensureDir, ensureFile, joinUrl, normalizeArray, settled } from './utils' import { ZipValidator } from './zipValdiator' export interface ForgeVersionList { @@ -127,7 +126,7 @@ type RequiredVersion = { /** * The minecraft version */ - mcversion: string + minecraft: string /** * The forge version (without minecraft version) */ @@ -141,67 +140,65 @@ export const DEFAULT_FORGE_MAVEN = 'http://files.minecraftforge.net/maven' */ export interface InstallForgeOptions extends LibraryOptions, InstallOptionsBase, InstallProfileOption { side?: 'client' | 'server' + + onForgeInstallerDownloadUpdate?: (forgeVersion: string, progress: DownloadProgressPayload) => void } -export class DownloadForgeInstallerTask extends DownloadTask { - readonly installJarPath: string - - constructor(forgeVersion: string, installer: RequiredVersion['installer'], minecraft: MinecraftFolder, options: InstallForgeOptions, legacy?: boolean) { - const classifier = legacy ? 'universal' : 'installer' - const ext = legacy ? 'zip' : 'jar' - const path = installer - ? installer.path - : `net/minecraftforge/forge/${forgeVersion}/forge-${forgeVersion}-${classifier}.${ext}` - let url: string - if (installer) { - try { - const parsedUrl = new URL(path) - url = parsedUrl.toString() - } catch (e) { - const forgeMavenPath = path.replace('/maven', '').replace('maven', '') - url = joinUrl(DEFAULT_FORGE_MAVEN, forgeMavenPath) - } - } else { +async function downloadForgeInstaller(forgeVersion: string, installer: RequiredVersion['installer'], minecraft: MinecraftFolder, options: InstallForgeOptions, legacy?: boolean) { + const classifier = legacy ? 'universal' : 'installer' + const ext = legacy ? 'zip' : 'jar' + const path = installer + ? installer.path + : `net/minecraftforge/forge/${forgeVersion}/forge-${forgeVersion}-${classifier}.${ext}` + let url: string + if (installer) { + try { + const parsedUrl = new URL(path) + url = parsedUrl.toString() + } catch (e) { const forgeMavenPath = path.replace('/maven', '').replace('maven', '') url = joinUrl(DEFAULT_FORGE_MAVEN, forgeMavenPath) } + } else { + const forgeMavenPath = path.replace('/maven', '').replace('maven', '') + url = joinUrl(DEFAULT_FORGE_MAVEN, forgeMavenPath) + } - const library = VersionJson.resolveLibrary({ - name: `net.minecraftforge:forge:${forgeVersion}:${classifier}`, - downloads: { - artifact: { - url, - path: `net/minecraftforge/forge/${forgeVersion}/forge-${forgeVersion}-${classifier}.${ext}`, - size: -1, - sha1: installer?.sha1 || '', - }, + const library = VersionJson.resolveLibrary({ + name: `net.minecraftforge:forge:${forgeVersion}:${classifier}`, + downloads: { + artifact: { + url, + path: `net/minecraftforge/forge/${forgeVersion}/forge-${forgeVersion}-${classifier}.${ext}`, + size: -1, + sha1: installer?.sha1 || '', }, - })! - const mavenHost = options.mavenHost ? normalizeArray(options.mavenHost) : [] + }, + })! + const mavenHost = options.mavenHost ? normalizeArray(options.mavenHost) : [] - if (mavenHost.indexOf(DEFAULT_FORGE_MAVEN) === -1) { - mavenHost.push(DEFAULT_FORGE_MAVEN) - } + if (mavenHost.indexOf(DEFAULT_FORGE_MAVEN) === -1) { + mavenHost.push(DEFAULT_FORGE_MAVEN) + } - const urls = resolveLibraryDownloadUrls(library, { ...options, mavenHost }) + const urls = resolveLibraryDownloadUrls(library, { ...options, mavenHost }) - const installJarPath = minecraft.getLibraryByPath(library.path) + const installJarPath = minecraft.getLibraryByPath(library.path) - super({ - url: urls, - destination: installJarPath, - validator: installer?.sha1 - ? options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: installer?.sha1 }) || { algorithm: 'sha1', hash: installer?.sha1 } - : new ZipValidator(), - agent: options.agent, - skipPrevalidate: options.skipPrevalidate, - skipRevalidate: options.skipRevalidate, - }) + await download({ + url: urls, + destination: installJarPath, + validator: installer?.sha1 + ? options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: installer?.sha1 }) || { algorithm: 'sha1', hash: installer?.sha1 } + : new ZipValidator(), + ...getDownloadBaseOptions(options), + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onForgeInstallerDownloadUpdate?.(forgeVersion, { url, chunkSizeOrStatus: chunkSize, progress, total }) + }, + }) - this.installJarPath = installJarPath - this.name = 'downloadInstaller' - this.param = { version: forgeVersion } - } + return installJarPath } function getLibraryPathWithoutMaven(mc: MinecraftFolder, name: string) { @@ -324,7 +321,7 @@ async function installLegacyForgeFromZip(zip: ZipFile, entries: ForgeLegacyInsta const jarPath = mc.getLibraryByPath(library.path) await ensureFile(jarPath) - await Promise.all([ + await settled([ writeFile(versionJsonPath, JSON.stringify(versionJson, undefined, 4)), extractEntryTo(zip, entries.legacyUniversalJar, jarPath), ]) @@ -413,7 +410,7 @@ export async function unpackForgeInstaller(zip: ZipFile, entries: ForgeInstaller writeFile(versionJsonPath, JSON.stringify(versionJson)), ) - await Promise.all(promises) + await settled(promises) return versionJson.id } @@ -475,53 +472,6 @@ export class BadForgeInstallerJarError extends Error { } } -export function installByInstallerTask(version: RequiredVersion, minecraft: MinecraftLocation, options: InstallForgeOptions) { - return task('installForge', async function () { - function getForgeArtifactVersion() { - const [_, minor] = version.mcversion.split('.') - const minorVersion = Number.parseInt(minor) - if (minorVersion >= 7 && minorVersion <= 8) { - return `${version.mcversion}-${version.version}-${version.mcversion}` - } - if (version.version.startsWith(version.mcversion)) { - return version.version - } - return `${version.mcversion}-${version.version}` - } - const forgeVersion = getForgeArtifactVersion() - const isLegacy = version.mcversion.startsWith('1.4.') - const mc = MinecraftFolder.from(minecraft) - const jarPath = await this.yield(new DownloadForgeInstallerTask(forgeVersion, version.installer, mc, options, isLegacy) - .map(function () { return this.installJarPath })) - - if (isLegacy) { - const forgeZip = await open(jarPath, { lazyEntries: true, autoClose: false }) - const versionId = await installLegacyForgeFromUniversalZip(forgeZip, mc, forgeVersion, version.mcversion) - return versionId - } - - const zip = await open(jarPath, { lazyEntries: true, autoClose: false }) - const entries = await walkForgeInstallerEntries(zip, forgeVersion) - - if (!entries.installProfileJson) { - throw new BadForgeInstallerJarError(jarPath, 'install_profile.json') - } - const profile: InstallProfile = await readEntry(zip, entries.installProfileJson).then((b) => b.toString()).then(JSON.parse) - if (isForgeInstallerEntries(entries)) { - // new forge - const versionId = await unpackForgeInstaller(zip, entries, forgeVersion, profile, mc, jarPath, options) - await this.concat(installByProfileTask(profile, minecraft, options)) - return versionId - } else if (isLegacyForgeInstallerEntries(entries)) { - // legacy forge - return installLegacyForgeFromZip(zip, entries, profile, mc, jarPath, options) - } else { - // bad forge - throw new BadForgeInstallerJarError(jarPath) - } - }) -} - /** * Install forge to target location. * Installation task for forge with mcversion >= 1.13 requires java installed on your pc. @@ -529,19 +479,48 @@ export function installByInstallerTask(version: RequiredVersion, minecraft: Mine * @returns The installed version name. * @throws {@link BadForgeInstallerJarError} */ -export function installForge(version: RequiredVersion, minecraft: MinecraftLocation, options?: InstallForgeOptions) { - return installForgeTask(version, minecraft, options).startAndWait() -} +export async function installForge(version: RequiredVersion, minecraft: MinecraftLocation, options: InstallForgeOptions = {}): Promise { + function getForgeArtifactVersion() { + const [_, minor] = version.minecraft.split('.') + const minorVersion = Number.parseInt(minor) + if (minorVersion >= 7 && minorVersion <= 8) { + return `${version.minecraft}-${version.version}-${version.minecraft}` + } + if (version.version.startsWith(version.minecraft)) { + return version.version + } + return `${version.minecraft}-${version.version}` + } + const forgeVersion = getForgeArtifactVersion() + const isLegacy = version.minecraft.startsWith('1.4.') + const mc = MinecraftFolder.from(minecraft) + const jarPath: string = await downloadForgeInstaller(forgeVersion, version.installer, mc, options, isLegacy) + + if (isLegacy) { + const forgeZip = await open(jarPath, { lazyEntries: true, autoClose: false }) + const versionId = await installLegacyForgeFromUniversalZip(forgeZip, mc, forgeVersion, version.minecraft) + return versionId + } -/** - * Install forge to target location. - * Installation task for forge with mcversion >= 1.13 requires java installed on your pc. - * @param version The forge version meta - * @returns The task to install the forge - * @throws {@link BadForgeInstallerJarError} - */ -export function installForgeTask(version: RequiredVersion, minecraft: MinecraftLocation, options: InstallForgeOptions = {}): Task { - return installByInstallerTask(version, minecraft, options) + const zip = await open(jarPath, { lazyEntries: true, autoClose: false }) + const entries = await walkForgeInstallerEntries(zip, forgeVersion) + + if (!entries.installProfileJson) { + throw new BadForgeInstallerJarError(jarPath, 'install_profile.json') + } + const profile: InstallProfile = await readEntry(zip, entries.installProfileJson).then((b) => b.toString()).then(JSON.parse) + if (isForgeInstallerEntries(entries)) { + // new forge + const versionId = await unpackForgeInstaller(zip, entries, forgeVersion, profile, mc, jarPath, options) + await installByProfile(profile, minecraft, options) + return versionId + } else if (isLegacyForgeInstallerEntries(entries)) { + // legacy forge + return installLegacyForgeFromZip(zip, entries, profile, mc, jarPath, options) + } else { + // bad forge + throw new BadForgeInstallerJarError(jarPath) + } } /** @@ -557,14 +536,10 @@ export async function getForgeVersionList(options: { * The minecraft version you are requesting */ minecraft?: string - dispatcher?: Dispatcher -} = {}): Promise { +} & FetchOptions = {}): Promise { const mcversion = options.minecraft || '' const url = mcversion === '' ? 'http://files.minecraftforge.net/maven/net/minecraftforge/forge/index.html' : `http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_${mcversion}.html` - const response = await request(url, { - dispatcher: options.dispatcher, - maxRedirections: 3, - }) - const body = parseForge(await response.body.text()) + const response = await doFetch(options, url) + const body = parseForge(await response.text()) return body as any } diff --git a/packages/installer/index.ts b/packages/installer/index.ts index de5edd2cb..090f5f3a2 100644 --- a/packages/installer/index.ts +++ b/packages/installer/index.ts @@ -16,6 +16,5 @@ export * from './java-runtime' export * from './diagnose' export * from './quilt' export { InstallOptions } from './utils' -export * from './downloadTask' -export * from './unzip' +export * from './DownloadProgressPayload' export * from './labymod' diff --git a/packages/installer/java-runtime.ts b/packages/installer/java-runtime.ts index b3dd0b825..3e436cdfe 100644 --- a/packages/installer/java-runtime.ts +++ b/packages/installer/java-runtime.ts @@ -1,12 +1,10 @@ import { getPlatform, Platform } from '@xmcl/core' -import { ChecksumValidatorOptions, DownloadBaseOptions, DownloadOptions, Validator } from '@xmcl/file-transfer' -import { Task, task } from '@xmcl/task' +import { ChecksumValidatorOptions, download, DownloadBaseOptions, DownloadOptions, getDownloadBaseOptions, Validator } from '@xmcl/file-transfer' import { link } from 'fs/promises' import { dirname, join } from 'path' -import { Dispatcher, request } from 'undici' import { URL } from 'url' -import { DownloadTask } from './downloadTask' -import { ensureDir, ParallelTaskOptions } from './utils' +import { DownloadProgressPayload } from './DownloadProgressPayload' +import { ensureDir, settled, ChecksumOptions, FetchOptions, doFetch } from './utils' /** * Contain all java runtimes basic info */ @@ -158,33 +156,29 @@ function normalizeUrls(url: string, fileHost?: string | string[]): string[] { return result } -export interface FetchJavaRuntimeManifestOptions extends DownloadBaseOptions { +export interface FetchJavaRuntimeManifestOptions extends DownloadBaseOptions, FetchOptions { /** - * The alternative download host for the file - */ + * The alternative download host for the file + */ apiHost?: string | string[] /** - * The url of the all runtime json - */ + * The url of the all runtime json + */ url?: string /** - * The platform to install. It will be auto-resolved by default. - * @default getPlatform() - */ + * The platform to install. It will be auto-resolved by default. + * @default getPlatform() + */ platform?: Platform /** - * The install java runtime type - * @default InstallJavaRuntimeTarget.Next - */ + * The install java runtime type + * @default InstallJavaRuntimeTarget.Next + */ target?: JavaRuntimeTargetType | string /** - * The index manifest of the java runtime. If this is not presented, it will fetch by platform and all platform url. - */ + * The index manifest of the java runtime. If this is not presented, it will fetch by platform and all platform url. + */ manifestIndex?: JavaRuntimes - /** - * The dispatcher to request API - */ - dispatcher?: Dispatcher } /** @@ -196,8 +190,8 @@ export interface FetchJavaRuntimeManifestOptions extends DownloadBaseOptions { export async function fetchJavaRuntimeManifest(options: FetchJavaRuntimeManifestOptions = {}): Promise { let manifestIndex = options.manifestIndex if (!manifestIndex) { - const response = await request(normalizeUrls(options.url ?? DEFAULT_RUNTIME_ALL_URL, options.apiHost)[0], { dispatcher: options.dispatcher, throwOnError: true }) - manifestIndex = await response.body.json() as JavaRuntimes + const response = await doFetch(options, normalizeUrls(options.url ?? DEFAULT_RUNTIME_ALL_URL, options.apiHost)[0]) + manifestIndex = await response.json() as JavaRuntimes } const manifest = manifestIndex const platform = options.platform ?? getPlatform() @@ -228,8 +222,8 @@ export async function fetchJavaRuntimeManifest(options: FetchJavaRuntimeManifest if (targets && targets.length > 0) { const target = targets[0] const manifestUrl = normalizeUrls(target.manifest.url, options.apiHost)[0] - const response = await request(manifestUrl, { dispatcher: options.dispatcher, throwOnError: true }) - const manifest: JavaRuntimeManifest = await response.body.json() as any + const response = await doFetch(options, manifestUrl) + const manifest: JavaRuntimeManifest = await response.json() as any const result: JavaRuntimeManifest = { files: manifest.files, target: runtimeTarget, @@ -241,7 +235,7 @@ export async function fetchJavaRuntimeManifest(options: FetchJavaRuntimeManifest } } -export interface InstallJavaRuntimeOptions extends DownloadBaseOptions, ParallelTaskOptions { +export interface InstallJavaRuntimeOptions extends DownloadBaseOptions, ChecksumOptions { /** * The alternative download host for the file */ @@ -262,64 +256,59 @@ export interface InstallJavaRuntimeOptions extends DownloadBaseOptions, Parallel lzma?: boolean | ((compressedFilePath: string, targetPath: string) => Promise) checksumValidatorResolver?: (checksum: ChecksumValidatorOptions) => Validator + + signal?: AbortSignal + + onJavaRuntimeFileDownloadUpdate?: (entry: FileEntry, progress: DownloadProgressPayload) => void } /** * Install java runtime from java runtime manifest * @param options The options to install java runtime */ -export function installJavaRuntimeTask(options: InstallJavaRuntimeOptions): Task { - return task('installJavaRuntime', async function () { - const destination = options.destination - const manifest = options.manifest - const decompressFunction = typeof options.lzma === 'function' ? options.lzma : undefined - const downloadLzma = !!options.lzma - class DownloadAndDecompressTask extends DownloadTask { - constructor(options: DownloadOptions) { - super(options) +export async function installJavaRuntime(options: InstallJavaRuntimeOptions): Promise { + const destination = options.destination + const manifest = options.manifest + const decompressFunction = typeof options.lzma === 'function' ? options.lzma : undefined + const downloadLzma = !!options.lzma + await settled(Object.entries(manifest.files) + .filter(([file, entry]) => entry.type === 'file') + .map(async ([file, entry]) => { + const fEntry = entry as FileEntry + const downloadInfo = (downloadLzma && fEntry.downloads.lzma) ? fEntry.downloads.lzma : fEntry.downloads.raw + const isLzma = downloadInfo === fEntry.downloads.lzma + const dest = isLzma ? (join(destination, file) + '.lzma') : join(destination, file) + const urls = normalizeUrls(downloadInfo.url, options.apiHost) + const hash = downloadInfo.sha1 + const downloadOptions: DownloadOptions = { + url: urls, + validator: options.checksumValidatorResolver?.({ algorithm: 'sha1', hash }) || { algorithm: 'sha1', hash }, + destination: dest, + ...getDownloadBaseOptions(options), + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onJavaRuntimeFileDownloadUpdate?.(fEntry, { + url, + chunkSizeOrStatus: chunkSize, + progress, + total, + }) + }, } - - async runTask() { - const result = await super.runTask() - if (this._total === this._progress) { - const dest = this.options.destination.substring(0, this.options.destination.length - 5) - await decompressFunction!(this.options.destination, dest) - } - return result + await download(downloadOptions) + if (isLzma && decompressFunction) { + await decompressFunction!(dest, dest.substring(0, dest.length - 5)) } - } - await this.all(Object.entries(manifest.files) - .filter(([file, entry]) => entry.type === 'file') - .map(([file, entry]) => { - const fEntry = entry as FileEntry - const downloadInfo = (downloadLzma && fEntry.downloads.lzma) ? fEntry.downloads.lzma : fEntry.downloads.raw - const isLzma = downloadInfo === fEntry.downloads.lzma - const dest = isLzma ? (join(destination, file) + '.lzma') : join(destination, file) - const urls = normalizeUrls(downloadInfo.url, options.apiHost) - const hash = downloadInfo.sha1 - const downloadOptions: DownloadOptions = { - url: urls, - validator: options.checksumValidatorResolver?.({ algorithm: 'sha1', hash }) || { algorithm: 'sha1', hash }, - destination: dest, - agent: options.agent, - headers: options.headers, - } - return isLzma && decompressFunction - ? new DownloadAndDecompressTask(downloadOptions).setName('download') - : new DownloadTask(downloadOptions).setName('download') - }), { - throwErrorImmediately: options.throwErrorImmediately, - getErrorMessage: (e) => `Fail to install java runtime ${manifest.version.name} on ${manifest.target}`, - }) - await Promise.all(Object.entries(manifest.files) - .filter(([file, entry]) => entry.type !== 'file') - .map(async ([file, entry]) => { - const dest = join(destination, file) - if (entry.type === 'directory') { - await ensureDir(dest) - } else if (entry.type === 'link') { - await link(dest, join(dirname(dest), entry.target)).catch(() => { }) - } - })) - }) + }), + ) + await settled(Object.entries(manifest.files) + .filter(([file, entry]) => entry.type !== 'file') + .map(async ([file, entry]) => { + const dest = join(destination, file) + if (entry.type === 'directory') { + await ensureDir(dest) + } else if (entry.type === 'link') { + await link(dest, join(dirname(dest), entry.target)).catch(() => { }) + } + })) } diff --git a/packages/installer/java.test.ts b/packages/installer/java.test.ts index 5e3a1aab3..30603c657 100644 --- a/packages/installer/java.test.ts +++ b/packages/installer/java.test.ts @@ -22,5 +22,10 @@ describe('JavaInstaller', () => { const inf = parseJavaVersion(version) expect(inf).toEqual(undefined) }) + test('should parse', () => { + `openjdk version "1.8.0-262" +OpenJDK Runtime Environment (build 1.8.0-262-b10) +OpenJDK 64-Bit Server VM (build 25.71-b10, mixed mode)` + }) }) }) diff --git a/packages/installer/java.ts b/packages/installer/java.ts index 6051228c7..7c6d1a23f 100644 --- a/packages/installer/java.ts +++ b/packages/installer/java.ts @@ -1,13 +1,11 @@ import { getPlatform, Platform } from '@xmcl/core' -import { Task, task } from '@xmcl/task' +import { download, DownloadBaseOptions, getDownloadBaseOptions } from '@xmcl/file-transfer' import { exec } from 'child_process' import { unlink } from 'fs/promises' -import { arch, EOL, platform, tmpdir } from 'os' +import { EOL, platform, tmpdir } from 'os' import { basename, join, resolve } from 'path' -import { Dispatcher, request } from 'undici' -import { DownloadTask } from './downloadTask' -import { DownloadBaseOptions } from '@xmcl/file-transfer' -import { ensureDir, missing } from './utils' +import { DownloadProgressPayload } from './DownloadProgressPayload' +import { doFetch, ensureDir, FetchOptions, missing } from './utils' export interface JavaInfo { /** @@ -24,55 +22,51 @@ export interface JavaInfo { majorVersion: number } -export interface InstallJavaOptions extends DownloadBaseOptions { +export interface InstallJavaOptions extends DownloadBaseOptions, FetchOptions { /** - * The destination of this installation - */ + * The destination of this installation + */ destination: string /** - * The cached directory which compressed java lzma will be download to. - * @default os.tempdir() - */ + * The cached directory which compressed java lzma will be download to. + * @default os.tempdir() + */ cacheDir?: string /** - * The platform to install. It will be auto-resolved by default. - * @default currentPlatform - */ + * The platform to install. It will be auto-resolved by default. + * @default currentPlatform + */ platform?: Platform /** - * Unpack lzma function. It must present, else it will not be able to unpack mojang provided LZMA. - */ + * Unpack lzma function. It must present, else it will not be able to unpack mojang provided LZMA. + */ unpackLZMA: UnpackLZMAFunction - /** - * The dispatcher for API - */ - dispatcher?: Dispatcher + + onJavaAssetDownloadUpdate?: (name: string, progress: DownloadProgressPayload) => void } export type UnpackLZMAFunction = - ((src: string, dest: string) => Promise) | - ((src: string, dest: string) => Task) - -export class DownloadJRETask extends DownloadTask { - constructor(jre: DownloadInfo, dir: string, options: InstallJavaOptions) { - const { sha1, url } = jre - const filename = basename(url) - const downloadDestination = resolve(dir, filename) - - super({ - url, - destination: downloadDestination, - validator: { - algorithm: 'sha1', - hash: sha1, - }, - agent: options.agent, - headers: options.headers, - }) - - this.name = 'downloadJre' - this.param = jre - } + ((src: string, dest: string) => Promise) + +export async function downloadJRE(jre: DownloadInfo, dir: string, options: InstallJavaOptions) { + const { sha1, url } = jre + const filename = basename(url) + const downloadDestination = resolve(dir, filename) + + await download({ + url, + destination: downloadDestination, + validator: { + algorithm: 'sha1', + hash: sha1, + }, + ...getDownloadBaseOptions(options), + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onJavaAssetDownloadUpdate?.(filename, { url, chunkSizeOrStatus: chunkSize, progress, total }) + }, + }) + return downloadDestination } interface DownloadInfo { sha1: string; url: string; version: string } @@ -81,51 +75,34 @@ interface DownloadInfo { sha1: string; url: string; version: string } * Install JRE from Mojang offical resource. It should install jdk 8. * @param options The install options */ -export function installJreFromMojangTask(options: InstallJavaOptions) { +export async function installJreFromMojang(options: InstallJavaOptions) { const { destination, unpackLZMA, cacheDir = tmpdir(), platform = getPlatform(), } = options - return task('installJreFromMojang', async function () { - const info: { [system: string]: { [arch: string]: { jre: DownloadInfo } } } = - await this.yield(task('fetchInfo', async () => { - const response = await request('https://launchermeta.mojang.com/mc/launcher.json', { dispatcher: options.dispatcher, throwOnError: true }) - return response.body.json() as any - })) - const system = platform.name - function resolveArch() { - switch (platform.arch) { - case 'x86': - case 'x32': return '32' - case 'x64': return '64' - default: return '32' - } + const response = await doFetch(options, 'https://launchermeta.mojang.com/mc/launcher.json') + const info: { [system: string]: { [arch: string]: { jre: DownloadInfo } } } = response.json() as any + const system = platform.name + function resolveArch() { + switch (platform.arch) { + case 'x86': + case 'x32': return '32' + case 'x64': return '64' + default: return '32' } - const currentArch = resolveArch() - - if (!info[system] || !info[system][currentArch] || !info[system][currentArch].jre) { - throw new Error('No Java package available for your platform') - } - const lzmaPath = await this.yield(new DownloadJRETask(info[system][currentArch].jre, cacheDir, options).map(function () { return this.to! })) - const result = unpackLZMA(lzmaPath, destination) - await ensureDir(destination) - if (result instanceof Promise) { - await this.yield(task('decompress', () => result)) - } else { - await this.yield(result) - } - await this.yield(task('cleanup', () => unlink(lzmaPath))) - }) -} + } + const currentArch = resolveArch() -/** - * Install JRE from Mojang offical resource. It should install jdk 8. - * @param options The install options - */ -export function installJreFromMojang(options: InstallJavaOptions) { - return installJreFromMojangTask(options).startAndWait() + if (!info[system] || !info[system][currentArch] || !info[system][currentArch].jre) { + throw new Error('No Java package available for your platform') + } + const lzmaPath = await downloadJRE(info[system][currentArch].jre, cacheDir, options) + const result = unpackLZMA(lzmaPath, destination) + await ensureDir(destination) + await result + await unlink(lzmaPath) } /** @@ -166,12 +143,22 @@ export function parseJavaVersion(versionText: string): { version: string; majorV const getVersion = (str?: string) => { if (!str) { return undefined } const match = /(\d+)\.(\d)+\.(\d+)(_\d+)?/.exec(str) - if (match === null) { return undefined } + if (match === null) { + const openjdkMatch = /openjdk version "(\d+)"/.exec(str) + if (openjdkMatch) { + return { + version: openjdkMatch[1], + majorVersion: Number.parseInt(openjdkMatch[1]), + patch: -1, + } + } + return undefined + } if (match[1] === '1') { return { version: match[0], majorVersion: Number.parseInt(match[2]), - patch: Number.parseInt(match[4].substring(1) ?? '-1'), + patch: Number.parseInt(match[4]?.substring(1) ?? '-1'), } } return { @@ -199,7 +186,7 @@ export function parseJavaVersion(versionText: string): { version: string; majorV export async function getPotentialJavaLocations(): Promise { const unchecked = new Set() const currentPlatform = platform() - const javaFile = currentPlatform === 'win32' ? 'javaw.exe' : 'java' + const javaFile = currentPlatform === 'win32' ? 'java.exe' : 'java' if (process.env.JAVA_HOME) { unchecked.add(join(process.env.JAVA_HOME, 'bin', javaFile)) @@ -225,15 +212,12 @@ export async function getPotentialJavaLocations(): Promise { resolve(stdout.split(EOL).map((item) => item.replace(/[\r\n]/g, '')) .filter((item) => item != null && item !== undefined) .filter((item) => item[0] === ' ') - .map((item) => `${item.split(' ')[3]}\\bin\\javaw.exe`)) + .map((item) => `${item.split(' ')[3]}\\bin\\java.exe`)) }) }) for (const o of [...out, ...await where()]) { unchecked.add(o) } - const currentArch = arch() - unchecked.add('C:\\Program Files (x86)\\Minecraft Launcher\\runtime\\jre-x64/X86') - unchecked.add(`C:\\Program Files (x86)\\Minecraft Launcher\\runtime\\jre-legacy\\windows-${currentArch}\\jre-legacy`) } else if (currentPlatform === 'darwin') { unchecked.add('/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java') unchecked.add(await which()) diff --git a/packages/installer/labymod.ts b/packages/installer/labymod.ts index 36ff173c7..c117b4a73 100644 --- a/packages/installer/labymod.ts +++ b/packages/installer/labymod.ts @@ -1,11 +1,9 @@ -import { MinecraftFolder, MinecraftLocation, LibraryInfo } from '@xmcl/core' -import { DownloadBaseOptions } from '@xmcl/file-transfer' -import { Task, task, AbortableTask, CancelledError } from '@xmcl/task' +import { LibraryInfo, MinecraftFolder, MinecraftLocation } from '@xmcl/core' +import { DownloadBaseOptions, download, getDownloadBaseOptions } from '@xmcl/file-transfer' import { writeFile } from 'fs/promises' import { dirname } from 'path' -import { Dispatcher, request } from 'undici' -import { DownloadTask } from './downloadTask' -import { ensureDir } from './utils' +import { DownloadProgressPayload } from './DownloadProgressPayload' +import { FetchOptions, doFetch, ensureDir } from './utils' export interface LabyModManifest { labyModVersion: string @@ -38,111 +36,90 @@ interface MinecraftVersion { customManifestUrl: string } -export async function getLabyModManifest(env = 'production', options?: { dispatcher?: Dispatcher }): Promise { +export async function getLabyModManifest(env = 'production', options?: FetchOptions): Promise { const url = `https://laby-releases.s3.de.io.cloud.ovh.net/api/v1/manifest/${env}/latest.json` - const res = await request(url, options) - return await res.body.json() as any + const res = await doFetch(options, url) + return await res.json() as any } -export interface InstallLabyModOptions extends DownloadBaseOptions { - dispatcher?: Dispatcher +export interface InstallLabyModOptions extends DownloadBaseOptions, FetchOptions { environment?: string + + onLabyModAssetDownloadUpdate?: (name: string, progress: DownloadProgressPayload) => void } -class JsonTask extends AbortableTask { - private controller = new AbortController() +async function downloadJson(manifest: LabyModManifest, tag: string, folder: MinecraftFolder, environment: string, options?: InstallLabyModOptions) { + const librariesUrl = `https://laby-releases.s3.de.io.cloud.ovh.net/api/v1/libraries/${environment}.json` + const versionInfo = manifest.minecraftVersions.find((v) => v.tag === tag)! - constructor(private manifest: LabyModManifest, private tag: string, private folder: MinecraftFolder, private environment: string, private dispatcher?: Dispatcher) { - super() - this.name = 'json' - this.param = { version: tag } + interface LibInfo { + name: string + url: string + minecraftVersion: string + sha1: string + size: number + natives: any[] + resolvedAt: number } - - protected async process(): Promise { - this.controller = new AbortController() - const librariesUrl = `https://laby-releases.s3.de.io.cloud.ovh.net/api/v1/libraries/${this.environment}.json` - const versionInfo = this.manifest.minecraftVersions.find((v) => v.tag === this.tag)! - - interface LibInfo { - name: string - url: string - minecraftVersion: string - sha1: string - size: number - natives: any[] - resolvedAt: number - } - // Get version json and merge with libraries - const libraries: LibInfo[] = await request(librariesUrl, { dispatcher: this.dispatcher, signal: this.controller.signal }) - .then((res) => res.body.json() as any) - .then((res) => res.libraries as LibInfo[]) - .then((libs) => libs.filter(lib => lib.minecraftVersion === 'all' || lib.minecraftVersion === this.tag)) - const versionJson = await request(versionInfo.customManifestUrl, { dispatcher: this.dispatcher, signal: this.controller.signal }).then((res) => res.body.json() as any) - - versionJson.libraries.push(...libraries.map((l) => ({ - name: l.name, - downloads: { - artifact: { - path: LibraryInfo.resolve(l.name).path, - sha1: l.sha1, - size: l.size, - url: l.url, - }, + // Get version json and merge with libraries + const libraries: LibInfo[] = await doFetch(options, librariesUrl) + .then((res) => res.json() as any) + .then((res) => res.libraries as LibInfo[]) + .then((libs) => libs.filter(lib => lib.minecraftVersion === 'all' || lib.minecraftVersion === tag)) + const versionJson = await doFetch(options, versionInfo.customManifestUrl).then((res) => res.json() as any) + + versionJson.libraries.push(...libraries.map((l) => ({ + name: l.name, + downloads: { + artifact: { + path: LibraryInfo.resolve(l.name).path, + sha1: l.sha1, + size: l.size, + url: l.url, }, - })), { - name: `net.labymod:LabyMod:${this.manifest.labyModVersion}`, - downloads: { - artifact: { - path: `net/labymod/LabyMod/${this.manifest.labyModVersion}/LabyMod-${this.manifest.labyModVersion}.jar`, - sha1: this.manifest.sha1, - size: this.manifest.size, - url: `https://laby-releases.s3.de.io.cloud.ovh.net/api/v1/download/labymod4/${this.environment}/${this.manifest.commitReference}.jar`, - }, + }, + })), { + name: `net.labymod:LabyMod:${manifest.labyModVersion}`, + downloads: { + artifact: { + path: `net/labymod/LabyMod/${manifest.labyModVersion}/LabyMod-${manifest.labyModVersion}.jar`, + sha1: manifest.sha1, + size: manifest.size, + url: `https://laby-releases.s3.de.io.cloud.ovh.net/api/v1/download/labymod4/${environment}/${manifest.commitReference}.jar`, }, - }) - versionJson.id = `LabyMod-4-${this.tag}-${this.manifest.commitReference}` - - // write json to file - const versionPath = this.folder.getPath('versions', versionJson.id, `${versionJson.id}.json`) - await ensureDir(dirname(versionPath)) - await writeFile(versionPath, JSON.stringify(versionJson, null, 4)) + }, + }) + versionJson.id = `LabyMod-4-${tag}-${manifest.commitReference}` - return versionJson.id - } + // write json to file + const versionPath = folder.getPath('versions', versionJson.id, `${versionJson.id}.json`) + await ensureDir(dirname(versionPath)) + await writeFile(versionPath, JSON.stringify(versionJson, null, 4)) - protected abort(isCancelled: boolean): void { - this.controller.abort(new CancelledError()) - } - - protected isAbortedError(e: any): boolean { - return e instanceof CancelledError - } + return versionJson.id } -export function installLabyMod4Task(manifest: LabyModManifest, tag: string, minecraft: MinecraftLocation, options?: InstallLabyModOptions): Task { - return task('installLabyMod', async function () { - const folder = MinecraftFolder.from(minecraft) - const environment = options?.environment ?? 'production' - - const versionId = await this.yield(new JsonTask(manifest, tag, folder, environment, options?.dispatcher)) - - // Download assets - for (const [name, hash] of Object.entries(manifest.assets)) { - const url = `https://laby-releases.s3.de.io.cloud.ovh.net/api/v1/download/assets/labymod4/${environment}/${manifest.commitReference}/${name}/${hash}.jar` - const destination = folder.getPath('labymod-neo', 'assets', `${name}.jar`) - await this.yield(new DownloadTask({ - url, - destination, - validator: { algorithm: 'sha1', hash }, - agent: options?.agent, - headers: options?.headers, - }).setName('asset', { name })) - } - - return versionId - }) -} +export async function installLabyMod4(manifest: LabyModManifest, tag: string, minecraft: MinecraftLocation, options?: InstallLabyModOptions): Promise { + const folder = MinecraftFolder.from(minecraft) + const environment = options?.environment ?? 'production' + + const versionId = await downloadJson(manifest, tag, folder, environment, options) + + // Download assets + for (const [name, hash] of Object.entries(manifest.assets)) { + const url = `https://laby-releases.s3.de.io.cloud.ovh.net/api/v1/download/assets/labymod4/${environment}/${manifest.commitReference}/${name}/${hash}.jar` + const destination = folder.getPath('labymod-neo', 'assets', `${name}.jar`) + await download({ + url, + destination, + validator: { algorithm: 'sha1', hash }, + ...getDownloadBaseOptions(options), + signal: options?.signal, + progressController: (url, chunkSize, progress, total) => { + options?.onLabyModAssetDownloadUpdate?.(name, { url, chunkSizeOrStatus: chunkSize, progress, total }) + }, + }) + } -export function installLaby4Mod(manifest: LabyModManifest, tag: string, minecraft: MinecraftLocation, options?: InstallLabyModOptions): Promise { - return installLabyMod4Task(manifest, tag, minecraft, options).startAndWait() + return versionId } diff --git a/packages/installer/liteloader.ts b/packages/installer/liteloader.ts index 73cb4e4f6..9fc449db3 100644 --- a/packages/installer/liteloader.ts +++ b/packages/installer/liteloader.ts @@ -1,8 +1,6 @@ import { MinecraftFolder, MinecraftLocation } from '@xmcl/core' -import { Task, task } from '@xmcl/task' import { readFile, writeFile } from 'fs/promises' import { join } from 'path' -import { Dispatcher, request } from 'undici' import { ensureDir, InstallOptions, missing } from './utils' export const DEFAULT_VERSION_MANIFEST = 'http://dl.liteloader.com/versions/versions.json' @@ -34,7 +32,7 @@ export namespace LiteloaderVersionList { const metalist = { meta: result.meta, versions: {} } for (const mcversion in result.versions) { const versions: { release?: LiteloaderVersion; snapshot?: LiteloaderVersion } = - (metalist.versions as any)[mcversion] = {} + (metalist.versions as any)[mcversion] = {} const snapshots = result.versions[mcversion].snapshots const artifacts = result.versions[mcversion].artefacts // that's right, artefact const url = result.versions[mcversion].repo.url @@ -132,8 +130,27 @@ export async function getLiteloaderVersionList(options: { * @param version The real existed version id (under the the provided minecraft location) you want to installed liteloader inherit * @throws {@link MissingVersionJsonError} */ -export function installLiteloader(versionMeta: LiteloaderVersion, location: MinecraftLocation, options?: InstallOptions) { - return installLiteloaderTask(versionMeta, location, options).startAndWait() +export async function installLiteloader(versionMeta: LiteloaderVersion, location: MinecraftLocation, options: InstallOptions = {}) { + const mc: MinecraftFolder = MinecraftFolder.from(location) + + const mountVersion = options.inheritsFrom || versionMeta.mcversion + + if (await missing(mc.getVersionJson(mountVersion))) { + throw new MissingVersionJsonError(mountVersion, mc.getVersionJson(mountVersion)) + } + const mountedJSON: any = await readFile(mc.getVersionJson(mountVersion)).then((b) => b.toString()).then(JSON.parse) + + const inf = buildVersionInfo(versionMeta, mountedJSON) + + inf.id = options.versionId || inf.id + inf.inheritsFrom = options.inheritsFrom || inf.inheritsFrom + + const versionPath = mc.getVersionRoot(inf.id) + + await ensureDir(versionPath) + await writeFile(join(versionPath, inf.id + '.json'), JSON.stringify(inf, undefined, 4)) + + return inf.id as string } function buildVersionInfo(versionMeta: LiteloaderVersion, mountedJSON: any) { @@ -166,46 +183,3 @@ function buildVersionInfo(versionMeta: LiteloaderVersion, mountedJSON: any) { } return info } - -/** - * Install the liteloader to specific minecraft location. - * - * This will install the liteloader amount on the corresponded Minecraft version by default. - * If you want to install over the forge. You should first install forge and pass the installed forge version id to the third param, - * like `1.12-forge-xxxx` - * - * @tasks installLiteloader, installLiteloader.resolveVersionJson installLiteloader.generateLiteloaderJson - * - * @param versionMeta The liteloader version metadata. - * @param location The minecraft location you want to install - * @param version The real existed version id (under the the provided minecraft location) you want to installed liteloader inherit - */ -export function installLiteloaderTask(versionMeta: LiteloaderVersion, location: MinecraftLocation, options: InstallOptions = {}): Task { - return task('installLiteloader', async function installLiteloader() { - const mc: MinecraftFolder = MinecraftFolder.from(location) - - const mountVersion = options.inheritsFrom || versionMeta.mcversion - - const mountedJSON: any = await this.yield(task('resolveVersionJson', async function resolveVersionJson() { - if (await missing(mc.getVersionJson(mountVersion))) { - throw new MissingVersionJsonError(mountVersion, mc.getVersionJson(mountVersion)) - } - return readFile(mc.getVersionJson(mountVersion)).then((b) => b.toString()).then(JSON.parse) - })) - - const versionInf = await this.yield(task('generateLiteloaderJson', async function generateLiteloaderJson() { - const inf = buildVersionInfo(versionMeta, mountedJSON) - - inf.id = options.versionId || inf.id - inf.inheritsFrom = options.inheritsFrom || inf.inheritsFrom - - const versionPath = mc.getVersionRoot(inf.id) - - await ensureDir(versionPath) - await writeFile(join(versionPath, inf.id + '.json'), JSON.stringify(inf, undefined, 4)) - - return inf - })) - return versionInf.id as string - }) -} diff --git a/packages/installer/manifest.test.ts b/packages/installer/manifest.test.ts new file mode 100644 index 000000000..34951d444 --- /dev/null +++ b/packages/installer/manifest.test.ts @@ -0,0 +1,62 @@ +import { test, expect } from 'vitest' +import { convertClasspathToMaven, parseManifest } from './manifest' + +test('#convertClasspathToMaven', () => { + const result = convertClasspathToMaven([ + 'libraries/net/minecraftforge/JarJarFileSystems/0.3.26/JarJarFileSystems-0.3.26.jar', + 'libraries/com/google/guava/guava/32.1.2-jre/guava-32.1.2-jre.jar', + 'libraries/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar', + 'libraries/net/minecraftforge/securemodules/2.2.19/securemodules-2.2.19.jar', + 'libraries/net/minecraftforge/unsafe/0.9.2/unsafe-0.9.2.jar', + 'libraries/org/ow2/asm/asm/9.7/asm-9.7.jar', + 'libraries/org/ow2/asm/asm-tree/9.7/asm-tree-9.7.jar', + 'libraries/org/ow2/asm/asm-util/9.7/asm-util-9.7.jar', + 'libraries/org/ow2/asm/asm-commons/9.7/asm-commons-9.7.jar', + 'libraries/org/ow2/asm/asm-analysis/9.7/asm-analysis-9.7.jar', + 'libraries/net/minecraftforge/forge/1.20.6-50.1.9/forge-1.20.6-50.1.9-shim.jar', + ]) + expect(result).toEqual([ + 'net.minecraftforge:JarJarFileSystems:0.3.26', + 'com.google.guava:guava:32.1.2:jre', + 'com.google.guava:failureaccess:1.0.1', + 'net.minecraftforge:securemodules:2.2.19', + 'net.minecraftforge:unsafe:0.9.2', + 'org.ow2.asm:asm:9.7', + 'org.ow2.asm:asm-tree:9.7', + 'org.ow2.asm:asm-util:9.7', + 'org.ow2.asm:asm-commons:9.7', + 'org.ow2.asm:asm-analysis:9.7', + 'net.minecraftforge:forge:1.20.6-50.1.9:shim', + ]) +}) + +test('#parseManifest', () => { + const result = parseManifest(`Manifest-Version: 1.0 +Class-Path: libraries/net/minecraftforge/JarJarFileSystems/0.3.26/JarJar + FileSystems-0.3.26.jar libraries/com/google/guava/guava/32.1.2-jre/guav + a-32.1.2-jre.jar libraries/com/google/guava/failureaccess/1.0.1/failure + access-1.0.1.jar libraries/net/minecraftforge/securemodules/2.2.19/secu + remodules-2.2.19.jar libraries/net/minecraftforge/unsafe/0.9.2/unsafe-0 + .9.2.jar libraries/org/ow2/asm/asm/9.7/asm-9.7.jar libraries/org/ow2/as + m/asm-tree/9.7/asm-tree-9.7.jar libraries/org/ow2/asm/asm-util/9.7/asm- + util-9.7.jar libraries/org/ow2/asm/asm-commons/9.7/asm-commons-9.7.jar + libraries/org/ow2/asm/asm-analysis/9.7/asm-analysis-9.7.jar +Automatic-Module-Name: net.minecraftforge.bootstrap.shim +Main-Class: net.minecraftforge.bootstrap.shim.Main +`) + expect(result).toEqual({ + mainClass: 'net.minecraftforge.bootstrap.shim.Main', + classPaths: [ + 'libraries/net/minecraftforge/JarJarFileSystems/0.3.26/JarJarFileSystems-0.3.26.jar', + 'libraries/com/google/guava/guava/32.1.2-jre/guava-32.1.2-jre.jar', + 'libraries/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar', + 'libraries/net/minecraftforge/securemodules/2.2.19/securemodules-2.2.19.jar', + 'libraries/net/minecraftforge/unsafe/0.9.2/unsafe-0.9.2.jar', + 'libraries/org/ow2/asm/asm/9.7/asm-9.7.jar', + 'libraries/org/ow2/asm/asm-tree/9.7/asm-tree-9.7.jar', + 'libraries/org/ow2/asm/asm-util/9.7/asm-util-9.7.jar', + 'libraries/org/ow2/asm/asm-commons/9.7/asm-commons-9.7.jar', + 'libraries/org/ow2/asm/asm-analysis/9.7/asm-analysis-9.7.jar', + ], + }) +}) diff --git a/packages/installer/manifest.ts b/packages/installer/manifest.ts new file mode 100644 index 000000000..e85769889 --- /dev/null +++ b/packages/installer/manifest.ts @@ -0,0 +1,56 @@ +export function convertClasspathToMaven(paths: string[]): string[] { + return paths.map(path => { + const trimmedPath = path.replace(/^libraries\//, '') + + const parts = trimmedPath.split('/') + + let jarName = parts.pop() + const version = parts.pop() + const artifactId = parts.pop() + const groupIdParts = parts + + const groupId = groupIdParts.join('.') + + let classifier = '' + + if (jarName) { + jarName = jarName.replace(/\.jar$/, '') + const jarParts = jarName?.substring(`${artifactId}-${version}`.length + 1).split('-') + if (jarParts && jarParts.length > 0) { + classifier = jarParts[0] + } + } + + let mavenCoordinate = `${groupId}:${artifactId}:${version}` + if (classifier) { + mavenCoordinate += `:${classifier}` + } + + return mavenCoordinate + }) +} + +export function parseManifest(manifestContent: string): { mainClass: string; classPath: string[] } { + const lines = manifestContent.split('\r\n') + let mainClass = '' + let classPath = [] as string[] + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim() + if (line.startsWith('Main-Class:')) { + mainClass = line.substring('Main-Class:'.length).trim() + } else if (line.startsWith('Class-Path:')) { + let classPathLine = line.substring('Class-Path:'.length).trim() + while (i + 1 < lines.length && lines[i + 1].startsWith(' ')) { + i++ + classPathLine += lines[i].slice(1) + } + classPath = classPathLine.split(' ').filter(path => path.length > 0) + } + } + + return { + mainClass, + classPath, + } +} diff --git a/packages/installer/minecraft.ts b/packages/installer/minecraft.ts index 4b20e6c60..ef14c072b 100644 --- a/packages/installer/minecraft.ts +++ b/packages/installer/minecraft.ts @@ -1,11 +1,10 @@ import { MinecraftFolder, MinecraftLocation, ResolvedLibrary, ResolvedVersion, Version, Version as VersionJson } from '@xmcl/core' -import { ChecksumNotMatchError, ChecksumValidatorOptions, DownloadBaseOptions, JsonValidator, Validator } from '@xmcl/file-transfer' -import { task, Task } from '@xmcl/task' +import { ChecksumNotMatchError, DownloadBaseOptions, JsonValidator, download, getDownloadBaseOptions } from '@xmcl/file-transfer' +import type { Abortable } from 'events' import { readFile, stat, writeFile } from 'fs/promises' -import { join } from 'path' -import { Dispatcher, request } from 'undici' -import { DownloadTask } from './downloadTask' -import { ensureDir, errorToString, joinUrl, normalizeArray, ParallelTaskOptions } from './utils' +import { join, relative, sep } from 'path' +import { DownloadProgressPayload } from './DownloadProgressPayload' +import { ChecksumOptions, FetchOptions, doFetch, ensureDir, joinUrl, normalizeArray, settled } from './utils' import { ZipValidator } from './zipValdiator' /** @@ -83,20 +82,15 @@ export const DEFAULT_RESOURCE_ROOT_URL = 'https://resources.download.minecraft.n * * @returns The new list if there is */ -export async function getVersionList(options: { - /** - * Request dispatcher - */ - dispatcher?: Dispatcher -} = {}): Promise { - const response = await request(DEFAULT_VERSION_MANIFEST_URL, { dispatcher: options.dispatcher, throwOnError: true }) - return await response.body.json() as any +export async function getVersionList(options: FetchOptions = {}): Promise { + const response = await doFetch(options, DEFAULT_VERSION_MANIFEST_URL) + return await response.json() as MinecraftVersionList } /** * Change the library host url */ -export interface LibraryOptions extends DownloadBaseOptions, ParallelTaskOptions { +export interface LibraryOptions extends DownloadBaseOptions, ChecksumOptions, Abortable { /** * A more flexiable way to control library download url. * @see mavenHost @@ -106,42 +100,32 @@ export interface LibraryOptions extends DownloadBaseOptions, ParallelTaskOptions * The alterative maven host to download library. It will try to use these host from the `[0]` to the `[maven.length - 1]` */ mavenHost?: string | string[] - /** - * Control how many libraries download task should run at the same time. - * It will override the `maxConcurrencyOption` if this is presented. - * - * This will be ignored if you have your own downloader assigned. - */ - librariesDownloadConcurrency?: number - checksumValidatorResolver?: (checksum: ChecksumValidatorOptions) => Validator + onLibraryDownloadUpdate?: (library: ResolvedLibrary, progress: DownloadProgressPayload) => void } /** * Change the host url of assets download */ -export interface AssetsOptions extends DownloadBaseOptions, ParallelTaskOptions { +export interface AssetsOptions extends DownloadBaseOptions, ChecksumOptions, FetchOptions { /** - * The alternative assets host to download asset. It will try to use these host from the `[0]` to the `[assetsHost.length - 1]` - */ + * The alternative assets host to download asset. It will try to use these host from the `[0]` to the `[assetsHost.length - 1]` + */ assetsHost?: string | string[] - /** - * Control how many assets download task should run at the same time. - * It will override the `maxConcurrencyOption` if this is presented. - * - * This will be ignored if you have your own downloader assigned. - */ - assetsDownloadConcurrency?: number - /** * The assets index download or url replacement */ assetsIndexUrl?: string | string[] | ((version: ResolvedVersion) => string | string[]) - checksumValidatorResolver?: (checksum: ChecksumValidatorOptions) => Validator /** * Only precheck the size of the assets. Do not check the hash. */ prevalidSizeOnly?: boolean + + onLogFileDownloadUpdate?: (progress: DownloadProgressPayload) => void + + onAssetDownloadUpdate?: (asset: AssetInfo, progress: DownloadProgressPayload) => void + + onAssetIndexDownloadUpdate?: (index: Version.AssetIndex, progress: DownloadProgressPayload) => void } export type InstallLibraryVersion = Pick @@ -161,7 +145,7 @@ function resolveDownloadUrls(original: string, version: T, option?: string | /** * Replace the minecraft client or server jar download */ -export interface JarOption extends DownloadBaseOptions, ParallelTaskOptions, InstallSideOption { +export interface JarOption extends DownloadBaseOptions, ChecksumOptions, InstallSideOption, Abortable { /** * The version json url replacement */ @@ -175,7 +159,9 @@ export interface JarOption extends DownloadBaseOptions, ParallelTaskOptions, Ins */ server?: string | string[] | ((version: ResolvedVersion) => string | string[]) - checksumValidatorResolver?: (checksum: ChecksumValidatorOptions) => Validator + onJarDownloadUpdate?: (version: ResolvedVersion, progress: DownloadProgressPayload) => void + + onJsonDownloadUpdate?: (version: MinecraftVersionBaseInfo, progress: DownloadProgressPayload) => void } export interface InstallSideOption { @@ -185,7 +171,7 @@ export interface InstallSideOption { side?: 'client' | 'server' } -export type Options = DownloadBaseOptions & ParallelTaskOptions & AssetsOptions & JarOption & LibraryOptions & InstallSideOption +export type Options = DownloadBaseOptions & ChecksumOptions & AssetsOptions & JarOption & LibraryOptions & InstallSideOption /** * Install the Minecraft game to a location by version metadata. @@ -196,94 +182,47 @@ export type Options = DownloadBaseOptions & ParallelTaskOptions & AssetsOptions * @param minecraft The Minecraft location * @param option */ -export async function install(versionMeta: MinecraftVersionBaseInfo, minecraft: MinecraftLocation, option: Options = {}): Promise { - return installTask(versionMeta, minecraft, option).startAndWait() -} - -/** - * Only install the json/jar. Do not install dependencies. - * - * @param versionMeta the version metadata; get from updateVersionMeta - * @param minecraft minecraft location - */ -export function installVersion(versionMeta: MinecraftVersionBaseInfo, minecraft: MinecraftLocation, options: JarOption = {}): Promise { - return installVersionTask(versionMeta, minecraft, options).startAndWait() -} - -/** - * Install the completeness of the Minecraft game assets and libraries on a existed version. - * - * @param version The resolved version produced by Version.parse - * @param minecraft The minecraft location - */ -export function installDependencies(version: ResolvedVersion, options?: Options): Promise { - return installDependenciesTask(version, options).startAndWait() -} - -/** - * Install or check the assets to resolved version - * - * @param version The target version - * @param options The option to replace assets host url - */ -export function installAssets(version: ResolvedVersion, options: AssetsOptions = {}): Promise { - return installAssetsTask(version, options).startAndWait() -} - -/** - * Install all the libraries of providing version - * @param version The target version - * @param options The library host swap option - */ -export function installLibraries(version: ResolvedVersion, options: LibraryOptions = {}): Promise { - return installLibrariesTask(version, options).startAndWait() -} - -/** - * Only install several resolved libraries - * @param libraries The resolved libraries - * @param minecraft The minecraft location - * @param option The install option - */ -export async function installResolvedLibraries(libraries: ResolvedLibrary[], minecraft: MinecraftLocation, option?: LibraryOptions): Promise { - await installLibrariesTask({ libraries, minecraftDirectory: typeof minecraft === 'string' ? minecraft : minecraft.root }, option).startAndWait() +export async function install(versionMeta: MinecraftVersionBaseInfo, minecraft: MinecraftLocation, options: Options = {}): Promise { + const version = await installVersion(versionMeta, minecraft, options) + if (options.side !== 'server') { + await installDependencies(version, options) + } + return version } -/** - * Install the Minecraft game to a location by version metadata. - * - * This will install version json, version jar, and all dependencies (assets, libraries) - * - * @param type The type of game, client or server - * @param versionMeta The version metadata - * @param minecraft The Minecraft location - * @param options - */ -export function installTask(versionMeta: MinecraftVersionBaseInfo, minecraft: MinecraftLocation, options: Options = {}): Task { - return task('install', async function () { - const version = await this.yield(installVersionTask(versionMeta, minecraft, options)) - if (options.side !== 'server') { - await this.yield(installDependenciesTask(version, options)) - } - return version - }) -} /** * Only install the json/jar. Do not install dependencies. * - * @param type client or server * @param versionMeta the version metadata; get from updateVersionMeta * @param minecraft minecraft location */ -export function installVersionTask(versionMeta: MinecraftVersionBaseInfo, minecraft: MinecraftLocation, options: JarOption = {}): Task { - return task('version', async function () { - await this.yield(new InstallJsonTask(versionMeta, minecraft, options)) - const version = await VersionJson.parse(minecraft, versionMeta.id) - if (version.downloads[options.side ?? 'client']) { - await this.yield(new InstallJarTask(version as any, minecraft, options)) +export async function installVersion(versionMeta: MinecraftVersionBaseInfo, minecraft: MinecraftLocation, options: JarOption = {}): Promise { + const folder = MinecraftFolder.from(minecraft) + await installJson(versionMeta, folder, options) + const version = await VersionJson.parse(folder, versionMeta.id) + const side = options.side ?? 'client' + if (version.downloads[side]) { + await installJar(version as any, folder, options) + } + if (side === 'server') { + const jarPath = folder.getVersionJar(versionMeta.id, 'server') + const server: Version = { + id: versionMeta.id, + type: 'release', + time: version.time, + releaseTime: version.releaseTime, + jar: relative(folder.libraries, jarPath).replaceAll(sep, '/'), + arguments: { + game: [], + jvm: [], + }, + mainClass: '', + minimumLauncherVersion: 13, + libraries: [], } - return version - }, versionMeta) + await writeFile(join(folder.getVersionRoot(versionMeta.id), 'server.json'), JSON.stringify(server, null, 2)) + } + return version } /** @@ -292,14 +231,12 @@ export function installVersionTask(versionMeta: MinecraftVersionBaseInfo, minecr * @param version The resolved version produced by Version.parse * @param minecraft The minecraft location */ -export function installDependenciesTask(version: ResolvedVersion, options: Options = {}): Task { - return task('dependencies', async function () { - await Promise.all([ - this.yield(installAssetsTask(version, options)), - this.yield(installLibrariesTask(version, options)), - ]) - return version - }) +export async function installDependencies(version: ResolvedVersion, options?: Options): Promise { + await settled([ + installAssets(version, options), + installLibraries(version, options), + ]) + return version } /** @@ -308,71 +245,75 @@ export function installDependenciesTask(version: ResolvedVersion, options: Optio * @param version The target version * @param options The option to replace assets host url */ -export function installAssetsTask(version: ResolvedVersion, options: AssetsOptions = {}): Task { - return task('assets', async function () { - const folder = MinecraftFolder.from(version.minecraftDirectory) - if (version.logging?.client?.file) { - const file = version.logging.client.file - - await this.yield(new DownloadTask({ - url: file.url, - validator: { - algorithm: 'sha1', - hash: file.sha1, - }, - destination: folder.getLogConfig(file.id), - agent: options.agent, - headers: options.headers, - }).setName('asset', { name: file.id, hash: file.sha1, size: file.size })) - } - const jsonPath = folder.getPath('assets', 'indexes', version.assets + '.json') +export async function installAssets(version: ResolvedVersion, options: AssetsOptions = {}): Promise { + const folder = MinecraftFolder.from(version.minecraftDirectory) + if (version.logging?.client?.file) { + const file = version.logging.client.file + + await download({ + url: file.url, + validator: { + algorithm: 'sha1', + hash: file.sha1, + }, + destination: folder.getLogConfig(file.id), + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onLogFileDownloadUpdate?.({ + url, + chunkSizeOrStatus: chunkSize, + progress, + total, + }) + }, + ...getDownloadBaseOptions(options), + }) + } + const jsonPath = folder.getPath('assets', 'indexes', version.assets + '.json') - if (version.assetIndex) { - await this.yield(new InstallAssetIndexTask(version as any, options)) - } + if (version.assetIndex) { + await installAssetIndex(version as any, options) + } - await ensureDir(folder.getPath('assets', 'objects')) - interface AssetIndex { - objects: { - [key: string]: { - hash: string - size: number - } + await ensureDir(folder.getPath('assets', 'objects')) + interface AssetIndex { + objects: { + [key: string]: { + hash: string + size: number } } + } - const getAssetIndexFallback = async () => { - const urls = resolveDownloadUrls(version.assetIndex!.url, version, options.assetsIndexUrl) - for (const url of urls) { - try { - const response = await request(url, { dispatcher: options.agent?.dispatcher }) - const json = await response.body.json() as any - await writeFile(jsonPath, JSON.stringify(json)) - return json - } catch { - // ignore - } + const getAssetIndexFallback = async () => { + const urls = resolveDownloadUrls(version.assetIndex!.url, version, options.assetsIndexUrl) + for (const url of urls) { + try { + const response = await doFetch(options, url) + const json = await response.json() as any + await writeFile(jsonPath, JSON.stringify(json)) + return json + } catch { + // ignore } } + } - let objectArray: any[] - try { - const { objects } = JSON.parse(await readFile(jsonPath).then((b) => b.toString())) as AssetIndex - objectArray = Object.keys(objects).map((k) => ({ name: k, ...objects[k] })) - } catch (e) { - if ((e instanceof SyntaxError)) { - throw e - } - const { objects } = await getAssetIndexFallback() - objectArray = Object.keys(objects).map((k) => ({ name: k, ...objects[k] })) + let objectArray: any[] + try { + const { objects } = JSON.parse(await readFile(jsonPath).then((b) => b.toString())) as AssetIndex + objectArray = Object.keys(objects).map((k) => ({ name: k, ...objects[k] })) + } catch (e) { + if ((e instanceof SyntaxError)) { + throw e } - await this.all(objectArray.map((o) => new InstallAssetTask(o, folder, options)), { - throwErrorImmediately: options.throwErrorImmediately ?? false, - getErrorMessage: (errs) => `Errors during install Minecraft ${version.id}'s assets at ${version.minecraftDirectory}: ${errs.map(errorToString).join('\n')}`, - }) + const { objects } = await getAssetIndexFallback() + objectArray = Object.keys(objects).map((k) => ({ name: k, ...objects[k] })) + } - return version - }) + await settled(objectArray.map((o) => installAsset(o, folder, options))) + + return version } /** @@ -380,14 +321,9 @@ export function installAssetsTask(version: ResolvedVersion, options: AssetsOptio * @param version The target version * @param options The library host swap option */ -export function installLibrariesTask(version: InstallLibraryVersion, options: LibraryOptions = {}): Task { - return task('libraries', async function () { - const folder = MinecraftFolder.from(version.minecraftDirectory) - await this.all(version.libraries.map((lib) => new InstallLibraryTask(lib, folder, options)), { - throwErrorImmediately: options.throwErrorImmediately ?? false, - getErrorMessage: (errs) => `Errors during install libraries at ${version.minecraftDirectory}: ${errs.map(errorToString).join('\n')}`, - }) - }) +export async function installLibraries(version: InstallLibraryVersion, options: LibraryOptions = {}): Promise { + const folder = MinecraftFolder.from(version.minecraftDirectory) + await settled(version.libraries.map((lib) => installLibrary(lib, folder, options))) } /** @@ -396,8 +332,8 @@ export function installLibrariesTask(version: InstallLibraryVersion, options: Li * @param minecraft The minecraft location * @param option The install option */ -export function installResolvedLibrariesTask(libraries: ResolvedLibrary[], minecraft: MinecraftLocation, option?: LibraryOptions) { - return installLibrariesTask({ libraries, minecraftDirectory: typeof minecraft === 'string' ? minecraft : minecraft.root }, option) +export function installResolvedLibraries(libraries: ResolvedLibrary[], minecraft: MinecraftLocation, option?: LibraryOptions) { + return installLibraries({ libraries, minecraftDirectory: typeof minecraft === 'string' ? minecraft : minecraft.root }, option) } /** @@ -406,152 +342,152 @@ export function installResolvedLibrariesTask(libraries: ResolvedLibrary[], minec * @param folder The minecraft folder * @param options The asset option */ -export function installResolvedAssetsTask(assets: AssetInfo[], folder: MinecraftFolder, options: AssetsOptions = {}) { - return task('assets', async function () { - await ensureDir(folder.getPath('assets', 'objects')) +export async function installResolvedAssets(assets: AssetInfo[], folder: MinecraftFolder, options: AssetsOptions = {}) { + await ensureDir(folder.getPath('assets', 'objects')) - // const sizes = assets.map((a) => a.size).map((a, b) => a + b, 0); + // const sizes = assets.map((a) => a.size).map((a, b) => a + b, 0); - await this.all(assets.map((o) => new InstallAssetTask(o, folder, options)), { - throwErrorImmediately: false, - getErrorMessage: (errs) => `Errors during install assets at ${folder.root}:\n${errs.map(errorToString).join('\n')}`, - }) - }) + await settled(assets.map((o) => installAsset(o, folder, options))) } -export class InstallJsonTask extends DownloadTask { - constructor(version: MinecraftVersionBaseInfo, minecraft: MinecraftLocation, options: Options) { - const folder = MinecraftFolder.from(minecraft) - const destination = folder.getVersionJson(version.id) - const expectSha1 = version.url.split('/')[5] - const urls = resolveDownloadUrls(version.url, version, options.json) - - super({ - url: urls, - headers: options.headers, - agent: options.agent, - validator: expectSha1 ? options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: expectSha1 }) || { algorithm: 'sha1', hash: expectSha1 } : new JsonValidator(), - destination, - skipPrevalidate: options.skipPrevalidate, - skipRevalidate: options.skipRevalidate, - }) - - this.name = 'json' - this.param = version - } +async function installJson(version: MinecraftVersionBaseInfo, minecraft: MinecraftLocation, options: Options) { + const folder = MinecraftFolder.from(minecraft) + const destination = folder.getVersionJson(version.id) + const expectSha1 = version.url.split('/')[5] + const urls = resolveDownloadUrls(version.url, version, options.json) + + return download({ + url: urls, + validator: expectSha1 ? options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: expectSha1 }) || { algorithm: 'sha1', hash: expectSha1 } : new JsonValidator(), + destination, + ...getDownloadBaseOptions(options), + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onJsonDownloadUpdate?.(version, { + chunkSizeOrStatus: chunkSize, + progress, + total, + url, + }) + }, + }) } -export class InstallJarTask extends DownloadTask { - constructor(version: ResolvedVersion & { downloads: Required['downloads'] }, minecraft: MinecraftLocation, options: Options) { - const folder = MinecraftFolder.from(minecraft) - const type = options.side ?? 'client' - const destination = join(folder.getVersionRoot(version.id), - type === 'client' ? version.id + '.jar' : version.id + '-' + type + '.jar') - const download = version.downloads[type] - if (!download) { - throw new Error(`Cannot find downloadable jar in ${type}`) - } - const urls = resolveDownloadUrls(download.url, version, options[type]) - const expectSha1 = download.sha1 - - super({ - url: urls, - validator: options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: expectSha1 }) || { algorithm: 'sha1', hash: expectSha1 }, - destination, - headers: options.headers, - agent: options.agent, - skipPrevalidate: options.skipPrevalidate, - skipRevalidate: options.skipRevalidate, - }) - - this.name = 'jar' - this.param = version +export async function installJar(version: ResolvedVersion & { downloads: Required['downloads'] }, minecraft: MinecraftLocation, options: Options) { + const folder = MinecraftFolder.from(minecraft) + const type = options.side ?? 'client' + const destination = folder.getVersionJar(version.id, type) + const _download = version.downloads[type] + if (!_download) { + throw new Error(`Cannot find downloadable jar in ${type}`) } + const urls = resolveDownloadUrls(_download.url, version, options[type]) + const expectSha1 = _download.sha1 + + return download({ + url: urls, + validator: options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: expectSha1 }) || { algorithm: 'sha1', hash: expectSha1 }, + destination, + ...getDownloadBaseOptions(options), + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onJarDownloadUpdate?.(version, { + chunkSizeOrStatus: chunkSize, + progress, + total, + url, + }) + }, + }) } -export class InstallAssetIndexTask extends DownloadTask { - constructor(version: ResolvedVersion & { assetIndex: Version.AssetIndex }, options: AssetsOptions = {}) { - const folder = MinecraftFolder.from(version.minecraftDirectory) - const jsonPath = folder.getPath('assets', 'indexes', version.assets + '.json') - const expectSha1 = version.assetIndex.sha1 - - super({ - url: resolveDownloadUrls(version.assetIndex.url, version, options.assetsIndexUrl), - destination: jsonPath, - validator: options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: expectSha1 }) || { algorithm: 'sha1', hash: expectSha1 }, - headers: options.headers, - agent: options.agent, - skipPrevalidate: options.skipPrevalidate, - skipRevalidate: options.skipRevalidate, - }) - - this.name = 'assetIndex' - this.param = version - } +export async function installAssetIndex(version: ResolvedVersion & { assetIndex: Version.AssetIndex }, options: AssetsOptions = {}) { + const folder = MinecraftFolder.from(version.minecraftDirectory) + const jsonPath = folder.getPath('assets', 'indexes', version.assets + '.json') + const expectSha1 = version.assetIndex.sha1 + + return download({ + url: resolveDownloadUrls(version.assetIndex.url, version, options.assetsIndexUrl), + destination: jsonPath, + validator: options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: expectSha1 }) || { algorithm: 'sha1', hash: expectSha1 }, + ...getDownloadBaseOptions(options), + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onAssetIndexDownloadUpdate?.(version.assetIndex, { + chunkSizeOrStatus: chunkSize, + progress, + total, + url, + }) + }, + }) } -export class InstallLibraryTask extends DownloadTask { - constructor(lib: ResolvedLibrary, folder: MinecraftFolder, options: LibraryOptions) { - const libraryPath = lib.download.path - const destination = join(folder.libraries, libraryPath) - const urls: string[] = resolveLibraryDownloadUrls(lib, options) - const expectSha1 = lib.download.sha1 - - super({ - url: urls, - validator: lib.download.sha1 === '' - ? new ZipValidator() - : options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: expectSha1 }) || { algorithm: 'sha1', hash: expectSha1 }, - destination, - headers: options.headers, - agent: options.agent, - skipPrevalidate: options.skipPrevalidate, - skipRevalidate: options.skipRevalidate, - }) - - this.name = 'library' - this.param = lib - } +export async function installLibrary(lib: ResolvedLibrary, folder: MinecraftFolder, options: LibraryOptions) { + const libraryPath = lib.download.path + const destination = join(folder.libraries, libraryPath) + const urls: string[] = resolveLibraryDownloadUrls(lib, options) + const expectSha1 = lib.download.sha1 + + return download({ + url: urls, + validator: lib.download.sha1 === '' + ? new ZipValidator() + : options.checksumValidatorResolver?.({ algorithm: 'sha1', hash: expectSha1 }) || { algorithm: 'sha1', hash: expectSha1 }, + destination, + ...getDownloadBaseOptions(options), + skipHead: lib.download.size < 2 * 1024 * 1024, + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onLibraryDownloadUpdate?.(lib, { + chunkSizeOrStatus: chunkSize, + progress, + total, + url, + }) + }, + }) } -export class InstallAssetTask extends DownloadTask { - constructor(asset: AssetInfo, folder: MinecraftFolder, options: AssetsOptions) { - const assetsHosts = normalizeArray(options.assetsHost || []) - - if (assetsHosts.indexOf(DEFAULT_RESOURCE_ROOT_URL) === -1) { - assetsHosts.push(DEFAULT_RESOURCE_ROOT_URL) - } - - const { hash, size, name } = asset - - const head = hash.substring(0, 2) - const dir = folder.getPath('assets', 'objects', head) - const file = join(dir, hash) - const urls = assetsHosts.map((h) => `${h}/${head}/${hash}`) - - super({ - url: urls, - destination: file, - validator: options.prevalidSizeOnly - ? { - async validate(destination, url) { - const fstat = await stat(destination).catch(() => ({ size: -1 })) - if (fstat.size !== size) { - throw new ChecksumNotMatchError('size', size.toString(), fstat.size.toString(), destination, url) - } - }, - } - : options.checksumValidatorResolver?.({ algorithm: 'sha1', hash }) || { algorithm: 'sha1', hash }, - headers: options.headers, - agent: options.agent, - skipPrevalidate: options.skipPrevalidate, - skipRevalidate: options.skipRevalidate, - }) +async function installAsset(asset: AssetInfo, folder: MinecraftFolder, options: AssetsOptions) { + const assetsHosts = normalizeArray(options.assetsHost || []) - this._total = size - this.name = 'asset' - this.param = asset + if (assetsHosts.indexOf(DEFAULT_RESOURCE_ROOT_URL) === -1) { + assetsHosts.push(DEFAULT_RESOURCE_ROOT_URL) } + + const { hash, size, name } = asset + + const head = hash.substring(0, 2) + const dir = folder.getPath('assets', 'objects', head) + const file = join(dir, hash) + const urls = assetsHosts.map((h) => `${h}/${head}/${hash}`) + + return download({ + url: urls, + destination: file, + validator: options.prevalidSizeOnly + ? { + async validate(destination, url) { + const fstat = await stat(destination).catch(() => ({ size: -1 })) + if (fstat.size !== size) { + throw new ChecksumNotMatchError('size', size.toString(), fstat.size.toString(), destination, url) + } + }, + } + : options.checksumValidatorResolver?.({ algorithm: 'sha1', hash }) || { algorithm: 'sha1', hash }, + ...getDownloadBaseOptions(options), + skipHead: asset.size < 2 * 1024 * 1024, + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onAssetDownloadUpdate?.(asset, { + chunkSizeOrStatus: chunkSize, + progress, + total, + url, + }) + }, + }) } const DEFAULT_MAVENS = ['https://repo1.maven.org/maven2/'] @@ -563,15 +499,11 @@ const DEFAULT_MAVENS = ['https://repo1.maven.org/maven2/'] * @param libraryOptions The library install options */ export function resolveLibraryDownloadUrls(library: ResolvedLibrary, libraryOptions: LibraryOptions): string[] { - const libraryHosts = libraryOptions.libraryHost?.(library) ?? [] - const url = new URL(library.download.url) - - return [...new Set([ - // user defined alternative host to download - ...normalizeArray(libraryHosts), + const urls = libraryOptions.libraryHost?.(library) ?? [ ...normalizeArray(libraryOptions.mavenHost).map((m) => joinUrl(m, library.download.path)), library.download.url, - ...normalizeArray(libraryOptions.mavenHost).map((m) => joinUrl(m, url.pathname).replace('/maven/maven', '/maven')), ...DEFAULT_MAVENS.map((m) => joinUrl(m, library.download.path)), - ])] + ] + + return [...new Set(normalizeArray(urls))] } diff --git a/packages/installer/neoForged.ts b/packages/installer/neoForged.ts index 81662da0c..98b3f228b 100644 --- a/packages/installer/neoForged.ts +++ b/packages/installer/neoForged.ts @@ -1,77 +1,71 @@ import { MinecraftFolder, MinecraftLocation, Version as VersionJson } from '@xmcl/core' +import { download, getDownloadBaseOptions } from '@xmcl/file-transfer' import { open, readEntry } from '@xmcl/unzip' -import { DownloadTask } from './downloadTask' import { BadForgeInstallerJarError, InstallForgeOptions, isForgeInstallerEntries, unpackForgeInstaller, walkForgeInstallerEntries } from './forge' import { resolveLibraryDownloadUrls } from './minecraft' -import { InstallProfile, installByProfileTask } from './profile' +import { InstallProfile, installByProfile } from './profile' import { normalizeArray } from './utils' import { ZipValidator } from './zipValdiator' -import { Task, task } from '@xmcl/task' -export class DownloadNeoForgedInstallerTask extends DownloadTask { - readonly installJarPath: string +export async function downloadNeoForgedInstaller(project: 'forge' | 'neoforge', version: string, minecraft: MinecraftLocation, options: InstallForgeOptions): Promise { + const folder = MinecraftFolder.from(minecraft) + const url = `https://maven.neoforged.net/releases/net/neoforged/${project}/${version}/${project}-${version}-installer.jar` - constructor(project: 'forge' | 'neoforge', version: string, minecraft: MinecraftFolder, options: InstallForgeOptions) { - const url = `https://maven.neoforged.net/releases/net/neoforged/${project}/${version}/${project}-${version}-installer.jar` - - const library = VersionJson.resolveLibrary({ - name: `net.neoforged:${project}:${version}:installer`, - downloads: { - artifact: { - url, - path: `net/neoforged/${project}/${version}/${project}-${version}-installer.jar`, - size: -1, - sha1: '', - }, + const library = VersionJson.resolveLibrary({ + name: `net.neoforged:${project}:${version}:installer`, + downloads: { + artifact: { + url, + path: `net/neoforged/${project}/${version}/${project}-${version}-installer.jar`, + size: -1, + sha1: '', }, - })! - const mavenHost = options.mavenHost ? normalizeArray(options.mavenHost) : [] + }, + })! + const mavenHost = options.mavenHost ? normalizeArray(options.mavenHost) : [] - const urls = resolveLibraryDownloadUrls(library, { ...options, mavenHost }) + const urls = resolveLibraryDownloadUrls(library, { ...options, mavenHost }) - const installJarPath = minecraft.getLibraryByPath(library.path) + const installJarPath = folder.getLibraryByPath(library.path) - super({ - url: urls, - destination: installJarPath, - validator: new ZipValidator(), - agent: options.agent, - skipPrevalidate: options.skipPrevalidate, - skipRevalidate: options.skipRevalidate, - }) + await download({ + url: urls, + destination: installJarPath, + validator: new ZipValidator(), + ...getDownloadBaseOptions(options), + signal: options.signal, + progressController: (url, chunkSize, progress, total) => { + options.onForgeInstallerDownloadUpdate?.(version, { + url, + chunkSizeOrStatus: chunkSize, + progress, + total, + }) + }, + }) - this.installJarPath = installJarPath - this.name = 'downloadInstaller' - this.param = { version } - } + return installJarPath } export async function installNeoForged(project: 'forge' | 'neoforge', version: string, minecraft: MinecraftLocation, options: InstallForgeOptions): Promise { - return installNeoForgedTask(project, version, minecraft, options).startAndWait() -} + const [_, forgeVersion] = version.split('-') + const mc = MinecraftFolder.from(minecraft) + const jarPath = await downloadNeoForgedInstaller(project, version, mc, options) -export function installNeoForgedTask(project: 'forge' | 'neoforge', version: string, minecraft: MinecraftLocation, options: InstallForgeOptions): Task { - return task('installForge', async function () { - const [_, forgeVersion] = version.split('-') - const mc = MinecraftFolder.from(minecraft) - const jarPath = await this.yield(new DownloadNeoForgedInstallerTask(project, version, mc, options) - .map(function () { return this.installJarPath })) + const zip = await open(jarPath, { lazyEntries: true, autoClose: false }) + const entries = await walkForgeInstallerEntries(zip, forgeVersion) - const zip = await open(jarPath, { lazyEntries: true, autoClose: false }) - const entries = await walkForgeInstallerEntries(zip, forgeVersion) - - if (!entries.installProfileJson) { - throw new BadForgeInstallerJarError(jarPath, 'install_profile.json') - } - const profile: InstallProfile = await readEntry(zip, entries.installProfileJson).then((b) => b.toString()).then(JSON.parse) - if (isForgeInstallerEntries(entries)) { - // new forge - const versionId = await unpackForgeInstaller(zip, entries, forgeVersion, profile, mc, jarPath, options) - await this.concat(installByProfileTask(profile, minecraft, options)) - return versionId - } else { - // bad forge - throw new BadForgeInstallerJarError(jarPath) - } - }) + if (!entries.installProfileJson) { + throw new BadForgeInstallerJarError(jarPath, 'install_profile.json') + } + const profile: InstallProfile = await readEntry(zip, entries.installProfileJson).then((b) => b.toString()).then(JSON.parse) + if (isForgeInstallerEntries(entries)) { + // new forge + const versionId = await unpackForgeInstaller(zip, entries, forgeVersion, profile, mc, jarPath, options) + await installByProfile(profile, minecraft, options) + return versionId + } else { + // bad forge + throw new BadForgeInstallerJarError(jarPath) + } } diff --git a/packages/installer/optifine.ts b/packages/installer/optifine.ts index 2d98d54e1..87d69b174 100644 --- a/packages/installer/optifine.ts +++ b/packages/installer/optifine.ts @@ -1,9 +1,8 @@ import { ClassReader, ClassVisitor, Opcodes } from '@xmcl/asm' import { MinecraftFolder, MinecraftLocation, Version } from '@xmcl/core' -import { task } from '@xmcl/task' import { getEntriesRecord, open, readAllEntries, readEntry } from '@xmcl/unzip' import { writeFile } from 'fs/promises' -import { ensureFile, InstallOptions, SpawnJavaOptions, spawnProcess } from './utils' +import { InstallOptions, SpawnJavaOptions, ensureFile, spawnProcess } from './utils' export interface InstallOptifineOptions extends InstallOptions, SpawnJavaOptions { /** @@ -57,8 +56,62 @@ export function generateOptifineVersion(editionRelease: string, minecraftVersion * @beta Might be changed and don't break the major version * @throws {@link BadOptifineJarError} */ -export function installOptifine(installer: string, minecraft: MinecraftLocation, options?: InstallOptifineOptions) { - return installOptifineTask(installer, minecraft, options).startAndWait() +export async function installOptifine(installer: string, minecraft: MinecraftLocation, options: InstallOptifineOptions = {}) { + const mc = MinecraftFolder.from(minecraft) + + const zip = await open(installer) + const entries = await readAllEntries(zip) + const record = getEntriesRecord(entries) + + const entry = record['net/optifine/Config.class'] ?? record['Config.class'] ?? record['notch/net/optifine/Config.class'] + if (!entry) { + throw new BadOptifineJarError(installer, 'net/optifine/Config.class') + } + + const launchWrapperVersionEntry = record['launchwrapper-of.txt'] + const launchWrapperVersion = launchWrapperVersionEntry + ? await readEntry(zip, launchWrapperVersionEntry).then((b) => b.toString()) + : undefined + + const buf = await readEntry(zip, entry) + const reader = new ClassReader(buf) + class OptifineVisitor extends ClassVisitor { + fields: Record = {} + visitField(access: number, name: string, desc: string, signature: string, value: any) { + this.fields[name] = value + return null + } + } + const visitor = new OptifineVisitor(Opcodes.ASM5) + reader.accept(visitor) + const mcversion: string = visitor.fields.MC_VERSION // 1.14.4 + const edition: string = visitor.fields.OF_EDITION // HD_U + const release: string = visitor.fields.OF_RELEASE // F5 + const editionRelease = edition + '_' + release + + const versionJSON = generateOptifineVersion(editionRelease, mcversion, launchWrapperVersion, options) + const versionJSONPath = mc.getVersionJson(versionJSON.id) + + // write version json + await ensureFile(versionJSONPath) + await writeFile(versionJSONPath, JSON.stringify(versionJSON, null, 4)) + + const launchWrapperEntry = record[`launchwrapper-of-${launchWrapperVersion}.jar`] + // write launch wrapper + if (launchWrapperEntry) { + const wrapperDest = mc.getLibraryByPath(`optifine/launchwrapper-of/${launchWrapperVersion}/launchwrapper-of-${launchWrapperVersion}.jar`) + await ensureFile(wrapperDest) + await writeFile(wrapperDest, await readEntry(zip, launchWrapperEntry)) + } + + // write the optifine + const dest = mc.getLibraryByPath(`optifine/Optifine/${mcversion}_${editionRelease}/Optifine-${mcversion}_${editionRelease}.jar`) + const mcJar = mc.getVersionJar(mcversion) + + await ensureFile(dest) + await spawnProcess(options, ['-cp', installer, 'optifine.Patcher', mcJar, installer, dest]) + + return versionJSON.id } export class BadOptifineJarError extends Error { @@ -74,83 +127,3 @@ export class BadOptifineJarError extends Error { error = 'BadOptifineJarError' } - -/** - * Install optifine by optifine installer task - * - * @param installer The installer jar file path - * @param minecraft The minecraft location - * @param options The option to install - * @beta Might be changed and don't break the major version - * @throws {@link BadOptifineJarError} - */ -export function installOptifineTask(installer: string, minecraft: MinecraftLocation, options: InstallOptifineOptions = {}) { - return task('installOptifine', async function () { - const mc = MinecraftFolder.from(minecraft) - - // context.update(0, 100); - - const zip = await open(installer) - const entries = await readAllEntries(zip) - const record = getEntriesRecord(entries) - // context.update(10, 100); - - const entry = record['net/optifine/Config.class'] ?? record['Config.class'] ?? record['notch/net/optifine/Config.class'] - if (!entry) { - throw new BadOptifineJarError(installer, 'net/optifine/Config.class') - } - - const launchWrapperVersionEntry = record['launchwrapper-of.txt'] - const launchWrapperVersion = launchWrapperVersionEntry - ? await readEntry(zip, launchWrapperVersionEntry).then((b) => b.toString()) - : undefined - // context.update(15, 100); - - const buf = await readEntry(zip, entry) - const reader = new ClassReader(buf) - class OptifineVisitor extends ClassVisitor { - fields: Record = {} - visitField(access: number, name: string, desc: string, signature: string, value: any) { - this.fields[name] = value - return null - } - } - const visitor = new OptifineVisitor(Opcodes.ASM5) - reader.accept(visitor) - const mcversion: string = visitor.fields.MC_VERSION // 1.14.4 - const edition: string = visitor.fields.OF_EDITION // HD_U - const release: string = visitor.fields.OF_RELEASE // F5 - const editionRelease = edition + '_' + release - - const versionJSON = generateOptifineVersion(editionRelease, mcversion, launchWrapperVersion, options) - const versionJSONPath = mc.getVersionJson(versionJSON.id) - - // context.update(20, 100); - // write version json - await this.yield(task('json', async () => { - await ensureFile(versionJSONPath) - await writeFile(versionJSONPath, JSON.stringify(versionJSON, null, 4)) - })) - - const launchWrapperEntry = record[`launchwrapper-of-${launchWrapperVersion}.jar`] - // write launch wrapper - if (launchWrapperEntry) { - await this.yield(task('library', async () => { - const wrapperDest = mc.getLibraryByPath(`optifine/launchwrapper-of/${launchWrapperVersion}/launchwrapper-of-${launchWrapperVersion}.jar`) - await ensureFile(wrapperDest) - await writeFile(wrapperDest, await readEntry(zip, launchWrapperEntry)) - })) - } - - // write the optifine - await this.yield(task('jar', async () => { - const dest = mc.getLibraryByPath(`optifine/Optifine/${mcversion}_${editionRelease}/Optifine-${mcversion}_${editionRelease}.jar`) - const mcJar = mc.getVersionJar(mcversion) - - await ensureFile(dest) - await spawnProcess(options, ['-cp', installer, 'optifine.Patcher', mcJar, installer, dest]) - })) - - return versionJSON.id - }) -} diff --git a/packages/installer/package.json b/packages/installer/package.json index 5dfe27aa3..da9a3a43a 100644 --- a/packages/installer/package.json +++ b/packages/installer/package.json @@ -21,9 +21,8 @@ "@xmcl/core": "workspace:^*", "@xmcl/file-transfer": "workspace:^*", "@xmcl/forge-site-parser": "workspace:^*", - "@xmcl/task": "workspace:^*", "@xmcl/unzip": "workspace:^*", - "undici": "6.0.1", + "undici": "6.14.0", "yazl": "^2.5.1", "yauzl": "^2.10.0" }, @@ -52,6 +51,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/installer/profile.ts b/packages/installer/profile.ts index 37ff08cf7..db48146e4 100644 --- a/packages/installer/profile.ts +++ b/packages/installer/profile.ts @@ -1,12 +1,13 @@ -import { LibraryInfo, MinecraftFolder, MinecraftLocation, Version as VersionJson } from '@xmcl/core' -import { AbortableTask, CancelledError, task } from '@xmcl/task' -import { open, readEntry, walkEntriesGenerator } from '@xmcl/unzip' +import { LibraryInfo, MinecraftFolder, MinecraftLocation, Version, Version as VersionJson } from '@xmcl/core' +import { filterEntries, open, readEntry, walkEntriesGenerator } from '@xmcl/unzip' import { spawn } from 'child_process' -import { readFile } from 'fs/promises' -import { delimiter, dirname } from 'path' +import { Abortable } from 'events' +import { readFile, writeFile } from 'fs/promises' +import { delimiter, dirname, join, relative, sep } from 'path' import { ZipFile } from 'yauzl' -import { InstallLibraryTask, InstallSideOption, LibraryOptions } from './minecraft' -import { checksum, errorToString, missing, SpawnJavaOptions, waitProcess } from './utils' +import { convertClasspathToMaven, parseManifest } from './manifest' +import { InstallSideOption, LibraryOptions, installLibrary } from './minecraft' +import { SpawnJavaOptions, checksum, missing, settled, waitProcess } from './utils' export interface PostProcessor { /** @@ -37,7 +38,7 @@ export interface InstallProfile { */ json: string /** - * The maven artifact name: :: + * The maven artifact name: `::` */ path: string /** @@ -64,10 +65,14 @@ export interface InstallProfile { versionInfo?: VersionJson } -export interface InstallProfileOption extends LibraryOptions, InstallSideOption, SpawnJavaOptions { +export interface PostProcessOption extends SpawnJavaOptions, Abortable { + onPostProcessUpdate?: (proc: PostProcessor, finished: number, total: number) => void +} + +export interface InstallProfileOption extends PostProcessOption, LibraryOptions, InstallSideOption, SpawnJavaOptions { /** - * New forge (>=1.13) require java to install. Can be a executor or java executable path. - */ + * New forge (>=1.13) require java to install. Can be a executor or java executable path. + */ java?: string } @@ -159,100 +164,8 @@ export function resolveProcessors(side: 'client' | 'server', installProfile: Ins * @param java The java executable path * @throws {@link PostProcessError} */ -export function postProcess(processors: PostProcessor[], minecraft: MinecraftFolder, javaOptions: SpawnJavaOptions) { - return new PostProcessingTask(processors, minecraft, javaOptions).startAndWait() -} - -/** - * Install by install profile. The install profile usually contains some preprocess should run before installing dependencies. - * - * @param installProfile The install profile - * @param minecraft The minecraft location - * @param options The options to install - * @throws {@link PostProcessError} - */ -export function installByProfile(installProfile: InstallProfile, minecraft: MinecraftLocation, options: InstallProfileOption = {}) { - return installByProfileTask(installProfile, minecraft, options).startAndWait() -} - -/** - * Install by install profile. The install profile usually contains some preprocess should run before installing dependencies. - * - * @param installProfile The install profile - * @param minecraft The minecraft location - * @param options The options to install - */ -export function installByProfileTask(installProfile: InstallProfile, minecraft: MinecraftLocation, options: InstallProfileOption = {}) { - return task('installByProfile', async function () { - const minecraftFolder = MinecraftFolder.from(minecraft) - - const processor = resolveProcessors(options.side || 'client', installProfile, minecraftFolder) - - const versionJson: VersionJson = await readFile(minecraftFolder.getVersionJson(installProfile.version)).then((b) => b.toString()).then(JSON.parse) - const installRequiredLibs = VersionJson.resolveLibraries(installProfile.libraries) - - await this.all(installRequiredLibs.map((lib) => new InstallLibraryTask(lib, minecraftFolder, options)), { - throwErrorImmediately: options.throwErrorImmediately ?? false, - getErrorMessage: (errs) => `Errors during install libraries at ${minecraftFolder.root}: ${errs.map(errorToString).join('\n')}`, - }) - - await this.yield(new PostProcessingTask(processor, minecraftFolder, options)) - - const libraries = VersionJson.resolveLibraries(versionJson.libraries) - await this.all(libraries.map((lib) => new InstallLibraryTask(lib, minecraftFolder, options)), { - throwErrorImmediately: options.throwErrorImmediately ?? false, - getErrorMessage: (errs) => `Errors during install libraries at ${minecraftFolder.root}: ${errs.map(errorToString).join('\n')}`, - }) - }) -} - -export class PostProcessBadJarError extends Error { - constructor(public jarPath: string, public causeBy: Error) { - super(`Fail to post process bad jar: ${jarPath}`) - } - - name = 'PostProcessBadJarError' -} - -export class PostProcessNoMainClassError extends Error { - constructor(public jarPath: string) { - super(`Fail to post process bad jar without main class: ${jarPath}`) - } - - name = 'PostProcessNoMainClassError' -} - -export class PostProcessFailedError extends Error { - constructor(public jarPath: string, public commands: string[], message: string) { - super(message) - } - - name = 'PostProcessFailedError' -} - -const PAUSEED = Symbol('PAUSED') -/** - * Post process the post processors from `InstallProfile`. - * - * @param processors The processor info - * @param minecraft The minecraft location - * @param java The java executable path - * @throws {@link PostProcessError} - */ -export class PostProcessingTask extends AbortableTask { - readonly name: string = 'postProcessing' - - private pointer = 0 - - private _abort = () => { } - - constructor(private processors: PostProcessor[], private minecraft: MinecraftFolder, private java: SpawnJavaOptions) { - super() - this.param = processors - this._total = processors.length - } - - protected async findMainClass(lib: string) { +export async function postProcess(processors: PostProcessor[], minecraft: MinecraftFolder, options: PostProcessOption) { + async function findMainClass(lib: string) { let zip: ZipFile | undefined let mainClass: string | undefined try { @@ -277,10 +190,10 @@ export class PostProcessingTask extends AbortableTask { return mainClass } - protected async isInvalid(outputs: Required['outputs']) { + async function isInvalid(outputs: Required['outputs']) { for (const [file, expect] of Object.entries(outputs)) { if (!expect) { - return missing(file) + return false } const sha1 = await checksum(file, 'sha1').catch((e) => '') if (!sha1) return true // if file not exist, the file is not generated @@ -293,61 +206,179 @@ export class PostProcessingTask extends AbortableTask { return false } - protected async postProcess(mc: MinecraftFolder, proc: PostProcessor, javaOptions: SpawnJavaOptions) { + async function postProcess(mc: MinecraftFolder, proc: PostProcessor) { const jarRealPath = mc.getLibraryByPath(LibraryInfo.resolve(proc.jar).path) - const mainClass = await this.findMainClass(jarRealPath) - this._to = proc.jar + const mainClass = await findMainClass(jarRealPath) const cp = [...proc.classpath, proc.jar].map(LibraryInfo.resolve).map((p) => mc.getLibraryByPath(p.path)).join(delimiter) const cmd = ['-cp', cp, mainClass, ...proc.args] try { await new Promise((resolve, reject) => { - const process = (javaOptions?.spawn ?? spawn)(javaOptions.java ?? 'java', cmd) + const process = (options?.spawn ?? spawn)(options.java ?? 'java', cmd, { signal: options.signal }) waitProcess(process).then(resolve, reject) - this._abort = () => { - reject(PAUSEED) - process.kill(1) - } }) } catch (e) { if (typeof e === 'string') { - throw new PostProcessFailedError(proc.jar, [javaOptions.java ?? 'java', ...cmd], e) + throw new PostProcessFailedError(proc.jar, [options.java ?? 'java', ...cmd], e) } throw e } - if (proc.outputs && await this.isInvalid(proc.outputs)) { - throw new PostProcessFailedError(proc.jar, [javaOptions.java ?? 'java', ...cmd], 'Validate the output of process failed!') + if (proc.outputs && await isInvalid(proc.outputs)) { + throw new PostProcessFailedError(proc.jar, [options.java ?? 'java', ...cmd], 'Validate the output of process failed!') } } - protected async process(): Promise { - for (; this.pointer < this.processors.length; this.pointer++) { - const proc = this.processors[this.pointer] - if (this.isCancelled) { - throw new CancelledError() - } - if (this.isPaused) { - throw PAUSEED - } - if (!proc.outputs || Object.keys(proc.outputs).length === 0 || await this.isInvalid(proc.outputs)) { - await this.postProcess(this.minecraft, proc, this.java) + for (let pointer = 0; pointer < processors.length; pointer++) { + const proc = processors[pointer] + if (options.signal?.aborted) { + throw Object.assign(new Error(), { name: 'AbortError' }) + } + if (!proc.outputs || Object.keys(proc.outputs).length === 0 || await isInvalid(proc.outputs)) { + options.onPostProcessUpdate?.(proc, pointer, processors.length) + await postProcess(minecraft, proc) + } + if (options.signal?.aborted) { + throw Object.assign(new Error(), { name: 'AbortError' }) + } + options.onPostProcessUpdate?.(proc, pointer, processors.length) + } +} + +/** + * Install by install profile. The install profile usually contains some preprocess should run before installing dependencies. + * + * @param installProfile The install profile + * @param minecraft The minecraft location + * @param options The options to install + * @throws {@link PostProcessError} + */ +export async function installByProfile(installProfile: InstallProfile, minecraft: MinecraftLocation, options: InstallProfileOption = {}) { + const minecraftFolder = MinecraftFolder.from(minecraft) + + const processor = resolveProcessors(options.side || 'client', installProfile, minecraftFolder) + + const installRequiredLibs = VersionJson.resolveLibraries(installProfile.libraries) + + await settled(installRequiredLibs.map((lib) => installLibrary(lib, minecraftFolder, options))) + + await postProcess(processor, minecraftFolder, options) + + if (options.side === 'client') { + const versionJson: VersionJson = await readFile(minecraftFolder.getVersionJson(installProfile.version)).then((b) => b.toString()).then(JSON.parse) + const libraries = VersionJson.resolveLibraries(versionJson.libraries) + await settled(libraries.map((lib) => installLibrary(lib, minecraftFolder, options))) + } else { + const argsText = process.platform === 'win32' ? 'win_args.txt' : 'unix_args.txt' + + if (!installProfile.processors) { return } + + let txtPath: string | undefined + for (const p of installProfile.processors) { + txtPath = p.args.find(a => a.startsWith('{ROOT}') && a.endsWith(argsText)) + if (txtPath) break + } + if (!txtPath) { return } + txtPath = txtPath.replace('{ROOT}', minecraftFolder.root) + + if (await missing(txtPath)) { + throw new Error(`No ${argsText} found in the forge jar`) + } + + const content = await readFile(txtPath, 'utf-8') + const args = content.split('\n').map(v => v.trim().split(' ')).flatMap(v => v).filter(v => v) + // find the Main class or -jar + let mainClass: string = '' + let jar: string | undefined + const game = [] as string[] + const jvm = [] as string[] + let found = false + for (let i = 0; i < args.length; i++) { + if (args[i].startsWith('-')) { + if (args[i] === '-jar') { + jar = join(dirname(txtPath), args[i + 1]) + found = true + i++ + continue + } + } else { + mainClass = args[i] + found = true + continue } - if (this.isCancelled) { - throw new CancelledError() + if (!found) { + jvm.push(args[i]) + } else { + game.push(args[i]) } - if (this.isPaused) { - throw PAUSEED + } + + const libraries: Version.Library[] = [] + if (jar) { + // Open the jar and find the main class + let zip: ZipFile | undefined + try { + const jsonContent: Version = JSON.parse(await readFile(minecraftFolder.getVersionJson(installProfile.version), 'utf-8')) + zip = await open(jar, { lazyEntries: true, autoClose: false }) + const [entry] = await filterEntries(zip, ['META-INF/MANIFEST.MF']) + if (entry) { + const manifestContent = await readEntry(zip, entry).then((b) => b.toString()) + const result = parseManifest(manifestContent) + mainClass = result.mainClass + const cp = [...result.classPath, relative(minecraftFolder.libraries, jar).replaceAll(sep, '/')] + libraries.push(...jsonContent.libraries.filter(l => !l.name.endsWith(':client'))) + for (const name of convertClasspathToMaven(cp)) { + if (libraries.find(l => l.name === name)) continue + libraries.push({ name }) + } + } + } catch (e) { + throw new PostProcessBadJarError(jar, e as any) + } finally { + zip?.close() } - this._progress = this.pointer - this.update(1) } + + const serverProfile: Version = { + id: installProfile.version, + libraries, + type: 'release', + arguments: { + game, + jvm, + }, + jar: jar && !mainClass ? relative(minecraftFolder.libraries, jar).replaceAll(sep, '/') : undefined, + releaseTime: new Date().toJSON(), + time: new Date().toJSON(), + minimumLauncherVersion: 13, + mainClass, + inheritsFrom: installProfile.minecraft, + } + await writeFile(join(minecraftFolder.getVersionRoot(serverProfile.id), 'server.json'), JSON.stringify(serverProfile, null, 4)) + + const resolvedLibraries = VersionJson.resolveLibraries(serverProfile.libraries) + await settled(resolvedLibraries.map((lib) => installLibrary(lib, minecraftFolder, options))) } +} - protected async abort(isCancelled: boolean): Promise { - // this.activeProcess?.kill() - this._abort() +export class PostProcessBadJarError extends Error { + constructor(public jarPath: string, public causeBy: Error) { + super(`Fail to post process bad jar: ${jarPath}`) } - protected isAbortedError(e: any): boolean { - return e === PAUSEED + name = 'PostProcessBadJarError' +} + +export class PostProcessNoMainClassError extends Error { + constructor(public jarPath: string) { + super(`Fail to post process bad jar without main class: ${jarPath}`) } + + name = 'PostProcessNoMainClassError' +} + +export class PostProcessFailedError extends Error { + constructor(public jarPath: string, public commands: string[], message: string) { + super(message) + } + + name = 'PostProcessFailedError' } diff --git a/packages/installer/quilt.ts b/packages/installer/quilt.ts index 70c28c754..bcdf0f568 100644 --- a/packages/installer/quilt.ts +++ b/packages/installer/quilt.ts @@ -1,58 +1,70 @@ import { MinecraftFolder, MinecraftLocation, Version } from '@xmcl/core' import { writeFile } from 'fs/promises' -import { Dispatcher, request, CacheStorage } from 'undici' -import { ensureFile } from './utils' +import { FetchOptions, doFetch, ensureFile } from './utils' +import { FabricArtifactVersion, FabricLoaderArtifact } from './fabric' -export const DEFAULT_META_URL = 'https://meta.quiltmc.org' +export const DEFAULT_META_URL_QUILT = 'https://meta.quiltmc.org' -export interface InstallQuiltVersionOptions { +export interface GetQuiltOptions extends FetchOptions { + minecraftVersion: string +} + +export interface QuiltLoaderArtifact extends FabricLoaderArtifact { + hashed: FabricLoaderArtifact['intermediary'] +} + +/** + * Get supported fabric game versions + */ +export async function getQuiltGames(options?: FetchOptions): Promise { + const response = await doFetch(options, `${DEFAULT_META_URL_QUILT}/v3/game`) + const body = await response.json() as Array<{ version: string }> + return body.map((g) => g.version) +} + +/** + * Get quilt-loader artifact list + */ +export async function getQuiltLoaders(options?: FetchOptions): Promise { + const response = await doFetch(options, `${DEFAULT_META_URL_QUILT}/v3/versions/loader`) + const body = response.json() + return body +} + +/** + * Get quilt loader versions list for a specific minecraft version + */ +export async function getQuiltLoaderVersionsByMinecraft(options: GetQuiltOptions): Promise { + const response = await doFetch(options, `${DEFAULT_META_URL_QUILT}/v3/versions/loader/${options.minecraftVersion}`) + const content: QuiltLoaderArtifact[] = await response.json() + return content +} + +export interface InstallQuiltVersionOptions extends FetchOptions { minecraftVersion: string version: string minecraft: MinecraftLocation - - dispatcher?: Dispatcher + side?: 'client' | 'server' } +/** + * Install quilt version via profile API + */ export async function installQuiltVersion(options: InstallQuiltVersionOptions) { - const url = `${DEFAULT_META_URL}/v3/versions/loader/${options.minecraftVersion}/${options.version}/profile/json` - const response = await request(url, { dispatcher: options.dispatcher }) - const content: Version = await response.body.json() as any + const side = options.side ?? 'client' + const url = side === 'client' + ? `${DEFAULT_META_URL_QUILT}/v3/versions/loader/${options.minecraftVersion}/${options.version}/profile/json` + : `${DEFAULT_META_URL_QUILT}/v3/versions/loader/${options.minecraftVersion}/${options.version}/server/json` + const response = await doFetch(options, url) + const content: Version = await response.json() as any const minecraft = MinecraftFolder.from(options.minecraft) const versionName = content.id - const jsonPath = minecraft.getVersionJson(versionName) - - const hashed = content.libraries.find((l) => l.name.startsWith('org.quiltmc:hashed')) - if (hashed) { - hashed.name = hashed.name.replace('org.quiltmc:hashed', 'net.fabricmc:intermediary') - if ('url' in hashed) { - hashed.url = 'https://maven.fabricmc.net/' - } - } + const jsonPath = side === 'client' ? minecraft.getVersionJson(versionName) : minecraft.getVersionServerJson(versionName) await ensureFile(jsonPath) await writeFile(jsonPath, JSON.stringify(content)) return versionName } - -export interface GetQuiltOptions { - dispatcher?: Dispatcher -} - -export interface QuiltArtifactVersion { - separator: string - build: number - /** - * e.g. "org.quiltmc:quilt-loader:0.16.1", - */ - maven: string - version: string -} - -export async function getQuiltVersionsList(options?: GetQuiltOptions): Promise { - const response = await request(`${DEFAULT_META_URL}/v3/versions/loader`, { dispatcher: options?.dispatcher, throwOnError: true }) - const content: QuiltArtifactVersion[] = await response.body.json() as any - return content -} diff --git a/packages/installer/tsconfig.json b/packages/installer/tsconfig.json index c332b5d1c..b29e1cef7 100644 --- a/packages/installer/tsconfig.json +++ b/packages/installer/tsconfig.json @@ -9,12 +9,12 @@ "fabric.ts", "quilt.ts", "utils.ts", - "unzip.ts", "java.ts", "diagnose.ts", "profile.ts", "labymod.ts", - "downloadTask.ts" + "manifest.ts", + "DownloadProgressPayload.ts" ], "extends": "../../tsconfig.json", "compilerOptions": { diff --git a/packages/installer/unzip.ts b/packages/installer/unzip.ts deleted file mode 100644 index ed1110824..000000000 --- a/packages/installer/unzip.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { BaseTask, CancelledError, TaskState } from '@xmcl/task' -import { openEntryReadStream } from '@xmcl/unzip' -import { createWriteStream } from 'fs' -import { join } from 'path' -import { Readable, Writable } from 'stream' -import { pipeline } from 'stream/promises' -import { Entry, ZipFile } from 'yauzl' -import { ensureFile } from './utils' - -export interface EntryResolver { - (entry: Entry): Promise | string -} - -export function getDefaultEntryResolver(): EntryResolver { - return (e) => e.fileName -} - -export class UnzipTask extends BaseTask { - private streams: [Readable, Writable][] = [] - private _onCancelled = () => { } - - constructor(readonly zipFile: ZipFile, readonly entries: Entry[], destination: string, readonly resolver: EntryResolver = getDefaultEntryResolver(), readonly interpreter: (input: Readable, file: string) => void = () => { }) { - super() - this._to = destination - } - - protected async handleEntry(entry: Entry, relativePath: string) { - const file = join(this.to!, relativePath) - if (this._state === TaskState.Cancelled) { - throw new CancelledError() - } - - const readStream = await openEntryReadStream(this.zipFile, entry) - if (this.isCancelled) { - throw new CancelledError() - } - if (this._state === TaskState.Paused) { - readStream.pause() - } - - await ensureFile(file) - this.interpreter(readStream, file) - const writeStream = createWriteStream(file) - readStream.on('data', (buf: Buffer) => { - this._progress += buf.length - this.update(buf.length) - }) - this.streams.push([readStream, writeStream]) - await pipeline(readStream, writeStream) - } - - protected async runTask(): Promise { - const promises: Promise[] = [] - - for (const e of this.entries) { - const path = await this.resolver(e) - if (this.isCancelled) { - throw new CancelledError() - } - this._total += e.uncompressedSize - promises.push(this.handleEntry(e, path)) - } - - this.update(0) - - try { - await Promise.all(promises) - } catch (e) { - if (e instanceof CancelledError) { - this._onCancelled() - } - throw e - } - } - - protected cancelTask(): Promise { - for (const [read, write] of this.streams) { - read.unpipe() - read.destroy(new CancelledError()) - this.zipFile.close() - write.destroy(new CancelledError()) - } - return new Promise((resolve) => { - this._onCancelled = resolve - }) - } - - protected async pauseTask(): Promise { - const promise = Promise.all(this.streams.map(([read]) => new Promise((resolve) => - read.once('pause', resolve)))) - for (const [read] of this.streams) { - read.pause() - } - await promise - } - - protected async resumeTask(): Promise { - const promise = Promise.all(this.streams.map(([read]) => new Promise((resolve) => - read.once('readable', resolve)))) - for (const [read] of this.streams) { - read.resume() - } - await promise - } -} diff --git a/packages/installer/utils.ts b/packages/installer/utils.ts index a640b78b7..6e4ee38b3 100644 --- a/packages/installer/utils.ts +++ b/packages/installer/utils.ts @@ -1,7 +1,8 @@ -import { ChildProcess, ExecOptions, spawn, SpawnOptions } from 'child_process' +import { ChecksumValidatorOptions, Validator } from '@xmcl/file-transfer' +import { ChildProcess, ExecOptions, SpawnOptions, spawn } from 'child_process' +import type { Abortable } from 'events' import { access, mkdir, stat } from 'fs/promises' import { dirname } from 'path' - export { checksum } from '@xmcl/core' export function missing(target: string) { @@ -34,17 +35,17 @@ export async function ensureDir(target: string) { export interface SpawnJavaOptions { /** - * The java exectable path. It will use `java` by default. - * - * @defaults "java" - */ + * The java exectable path. It will use `java` by default. + * + * @defaults "java" + */ java?: string /** - * The spawn process function. Used for spawn the java process at the end. - * - * By default, it will be the spawn function from "child_process" module. You can use this option to change the 3rd party spawn like [cross-spawn](https://www.npmjs.com/package/cross-spawn) - */ + * The spawn process function. Used for spawn the java process at the end. + * + * By default, it will be the spawn function from "child_process" module. You can use this option to change the 3rd party spawn like [cross-spawn](https://www.npmjs.com/package/cross-spawn) + */ spawn?: (command: string, args?: ReadonlyArray, options?: SpawnOptions) => ChildProcess } @@ -91,26 +92,26 @@ export function joinUrl(a: string, b: string) { return a + b } -export interface ParallelTaskOptions { - throwErrorImmediately?: boolean +export interface ChecksumOptions { + checksumValidatorResolver?: (checksum: ChecksumValidatorOptions) => Validator } /** * Shared install options */ export interface InstallOptions { /** - * When you want to install a version over another one. - * - * Like, you want to install liteloader over a forge version. - * You should fill this with that forge version id. - */ + * When you want to install a version over another one. + * + * Like, you want to install liteloader over a forge version. + * You should fill this with that forge version id. + */ inheritsFrom?: string /** - * Override the newly installed version id. - * - * If this is absent, the installed version id will be either generated or provided by installer. - */ + * Override the newly installed version id. + * + * If this is absent, the installed version id will be either generated or provided by installer. + */ versionId?: string } @@ -120,3 +121,22 @@ export function errorToString(e: any) { } return e.toString() } + +export async function settled(promises: T) { + const promiesResults = await Promise.allSettled(promises) + const errored = promiesResults.filter((result) => result.status === 'rejected') + if (errored.length > 0) { + throw new AggregateError(errored.map((result) => (result as PromiseRejectedResult).reason)) + } +} + +type FetchParameters = Parameters + +export interface FetchOptions extends Abortable { + fetch?: (input: string | URL, init?: FetchParameters[1]) => Promise +} + +export function doFetch(o: FetchOptions | undefined, input: string | URL, init: FetchParameters[1] = {}) { + init.signal = init.signal ?? o?.signal + return o?.fetch ? o.fetch(input, init) : fetch(input, init) +} diff --git a/packages/mod-parser/package.json b/packages/mod-parser/package.json index ce87c3e6c..00b87ebc4 100644 --- a/packages/mod-parser/package.json +++ b/packages/mod-parser/package.json @@ -49,6 +49,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/model/package.json b/packages/model/package.json index 5f9b99366..3a9ef97dd 100644 --- a/packages/model/package.json +++ b/packages/model/package.json @@ -17,7 +17,7 @@ "dependencies": { "@types/three": "^0.150.0", "@xmcl/resourcepack": "workspace:^*", - "three": "^0.151.3" + "three": "0.156.1" }, "repository": { "type": "git", @@ -42,6 +42,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/modrinth/index.ts b/packages/modrinth/index.ts index 50cb9c8b5..9d240d067 100644 --- a/packages/modrinth/index.ts +++ b/packages/modrinth/index.ts @@ -189,7 +189,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/projects/operation/searchProjects + * @see https://docs.modrinth.com/#tag/projects/operation/searchProjects */ async searchProjects(options: SearchProjectOptions, signal?: AbortSignal): Promise { const url = new URL(this.baseUrl + '/v2/search') @@ -212,7 +212,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/projects/operation/getProject + * @see https://docs.modrinth.com/#tag/projects/operation/getProject */ async getProject(projectId: string, signal?: AbortSignal): Promise { if (projectId.startsWith('local-')) { projectId = projectId.slice('local-'.length) } @@ -230,7 +230,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/projects/operation/getProject + * @see https://docs.modrinth.com/#tag/projects/operation/getProject */ async getProjects(projectIds: string[], signal?: AbortSignal): Promise { const url = new URL(this.baseUrl + '/v2/projects') @@ -248,7 +248,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/versions/operation/getProjectVersions + * @see https://docs.modrinth.com/#tag/versions/operation/getProjectVersions */ async getProjectVersions(projectId: string, { loaders, gameVersions, featured }: { loaders?: string[]; gameVersions?: string[]; featured?: boolean } = {}, signal?: AbortSignal): Promise { const url = new URL(this.baseUrl + `/v2/project/${projectId}/version`) @@ -268,7 +268,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/versions/operation/getVersion + * @see https://docs.modrinth.com/#tag/versions/operation/getVersion */ async getProjectVersion(versionId: string, signal?: AbortSignal): Promise { const url = new URL(this.baseUrl + `/v2/version/${versionId}`) @@ -285,7 +285,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/versions/operation/getVersions + * @see https://docs.modrinth.com/#tag/versions/operation/getVersions */ async getProjectVersionsById(ids: string[], signal?: AbortSignal) { const url = new URL(this.baseUrl + '/v2/versions') @@ -303,7 +303,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/version-files/operation/versionsFromHashes + * @see https://docs.modrinth.com/#tag/version-files/operation/versionsFromHashes */ async getProjectVersionsByHash(hashes: string[], algorithm = 'sha1', signal?: AbortSignal) { const url = new URL(this.baseUrl + '/v2/version_files') @@ -352,7 +352,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/version-files/operation/getLatestVersionFromHash + * @see https://docs.modrinth.com/#tag/version-files/operation/getLatestVersionFromHash */ async getLatestProjectVersion(sha1: string, { algorithm, loaders = [], gameVersions = [] }: { algorithm?: string; loaders?: string[]; gameVersions?: string[] } = {}, signal?: AbortSignal): Promise { const url = new URL(this.baseUrl + `/v2/version_file/${sha1}/update`) @@ -375,7 +375,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/tags/operation/licenseList + * @see https://docs.modrinth.com/#tag/tags/operation/licenseList */ async getLicenseTags(signal?: AbortSignal) { const url = new URL(this.baseUrl + '/v2/tag/license') @@ -392,7 +392,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/tags/operation/categoryList + * @see https://docs.modrinth.com/#tag/tags/operation/categoryList */ async getCategoryTags(signal?: AbortSignal) { const url = new URL(this.baseUrl + '/v2/tag/category') @@ -409,7 +409,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/tags/operation/versionList + * @see https://docs.modrinth.com/#tag/tags/operation/versionList */ async getGameVersionTags(signal?: AbortSignal) { const url = new URL(this.baseUrl + '/v2/tag/game_version') @@ -426,7 +426,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/tags/operation/loaderList + * @see https://docs.modrinth.com/#tag/tags/operation/loaderList */ async getLoaderTags(signal?: AbortSignal) { const url = new URL(this.baseUrl + '/v2/tag/loader') @@ -443,7 +443,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/teams/operation/getProjectTeamMembers + * @see https://docs.modrinth.com/#tag/teams/operation/getProjectTeamMembers */ async getProjectTeamMembers(projectId: string, signal?: AbortSignal) { const url = new URL(this.baseUrl + `/v2/project/${projectId}/members`) @@ -460,7 +460,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/users/operation/getUser + * @see https://docs.modrinth.com/#tag/users/operation/getUser */ async getUser(id: string, signal?: AbortSignal) { const url = new URL(this.baseUrl + `/v2/user/${id}`) @@ -477,7 +477,7 @@ export class ModrinthV2Client { } /** - * @see https://docs.modrinth.com/api-spec/#tag/users/operation/getUserProjects + * @see https://docs.modrinth.com/#tag/users/operation/getUserProjects */ async getUserProjects(id: string, signal?: AbortSignal) { const url = new URL(this.baseUrl + `/v2/user/${id}/projects`) diff --git a/packages/modrinth/package.json b/packages/modrinth/package.json index ef44a8fc2..16c69402e 100644 --- a/packages/modrinth/package.json +++ b/packages/modrinth/package.json @@ -35,7 +35,7 @@ ], "license": "MIT", "dependencies": { - "undici": "6.0.1" + "undici": "6.14.0" }, "bugs": { "url": "https://github.com/Voxelum/minecraft-launcher-core-node/issues" diff --git a/packages/modrinth/types.ts b/packages/modrinth/types.ts index bad45a7cd..8ef90ecc1 100644 --- a/packages/modrinth/types.ts +++ b/packages/modrinth/types.ts @@ -152,6 +152,8 @@ export interface Project { project_type: string + game_versions: string[] + gallery: ProjectGallery[] } diff --git a/packages/nat-api/package.json b/packages/nat-api/package.json index b5c7ab8a3..2ae643e45 100644 --- a/packages/nat-api/package.json +++ b/packages/nat-api/package.json @@ -19,12 +19,12 @@ "dependencies": { "default-gateway": "^6.0.3", "fast-xml-parser": "^4.3.2", - "undici": "6.0.1" + "undici": "6.14.0" }, "devDependencies": { "@types/node": "^18.15.11", "esbuild": "^0.17.16", - "typescript": "^5.2.2" + "typescript": "^5.3.3" }, "author": { "name": "Alex", diff --git a/packages/nbt/package.json b/packages/nbt/package.json index 9277aff14..ac20381eb 100644 --- a/packages/nbt/package.json +++ b/packages/nbt/package.json @@ -46,6 +46,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/system/package.json b/packages/system/package.json index 83e8bcc8e..5d654d78f 100644 --- a/packages/system/package.json +++ b/packages/system/package.json @@ -15,6 +15,7 @@ }, "publishConfig": { "main": "./dist/index.js", + "browser": "./dist/index.browser.mjs", "module": "./dist/index.mjs", "access": "public" }, @@ -41,7 +42,7 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" }, "license": "MIT", "bugs": { diff --git a/packages/task/index.ts b/packages/task/index.ts index 7ebb32df2..6eee4a040 100644 --- a/packages/task/index.ts +++ b/packages/task/index.ts @@ -266,7 +266,7 @@ export abstract class AbortableTask extends BaseTask { const result = await this.process() return result } catch (e) { - if (this._state === TaskState.Paused && this.isAbortedError(e)) { + if (this.isAbortedError(e)) { // notify pauseTask method this._onAborted() continue @@ -325,7 +325,22 @@ export abstract class TaskGroup extends BaseTask { const result = await Promise.all(promises) // if not throwErrorImmediately, we still need to check if other task failed if (errors.length > 0) { - throw new AggregateError(errors, getErrorMessage?.(errors)) + if (errors.length === 1) { + throw errors[0] + } + const flatten = [] as Error[] + const flatError = (e: any) => { + if (e instanceof AggregateError) { + for (const err of e.errors) { + flatError(err) + } + } + flatten.push(e) + } + for (const e of errors) { + flatError(e) + } + throw new AggregateError(flatten, getErrorMessage?.(errors)) } return result } catch (e) { diff --git a/packages/task/package.json b/packages/task/package.json index aa108515d..0f758eb69 100644 --- a/packages/task/package.json +++ b/packages/task/package.json @@ -26,6 +26,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/text-component/package.json b/packages/text-component/package.json index 8a1133641..cceecf1e5 100644 --- a/packages/text-component/package.json +++ b/packages/text-component/package.json @@ -40,6 +40,6 @@ "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", "eslint": "^8.37.0", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/unzip/package.json b/packages/unzip/package.json index 5582c4e59..4b01ed8d4 100644 --- a/packages/unzip/package.json +++ b/packages/unzip/package.json @@ -45,6 +45,6 @@ "devDependencies": { "@xmcl/eslint-config": "workspace:^*", "esbuild": "^0.17.16", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/packages/user-offline-uuid/package.json b/packages/user-offline-uuid/package.json index 41ec5c897..b43837b34 100644 --- a/packages/user-offline-uuid/package.json +++ b/packages/user-offline-uuid/package.json @@ -5,7 +5,7 @@ "module": "index.ts", "browser": "index.browser.ts", "dependencies": { - "undici": "^4.0.1", + "undici": "6.14.0", "@types/node": "~18.15.11" } } diff --git a/packages/user/package.json b/packages/user/package.json index a5f1784bc..fb8f31ebd 100644 --- a/packages/user/package.json +++ b/packages/user/package.json @@ -19,7 +19,7 @@ "access": "public" }, "dependencies": { - "undici": "6.0.1", + "undici": "6.14.0", "uuid": "^9.0.0" }, "sideEffects": false, @@ -46,7 +46,7 @@ "devDependencies": { "@types/uuid": "^9.0.1", "esbuild": "^0.17.16", - "typescript": "^5.2.2", + "typescript": "^5.3.3", "user-offline-uuid": "workspace:^*", "undici-shim": "workspace:^*" } diff --git a/packages/user/yggdrasil.ts b/packages/user/yggdrasil.ts index d92551e5e..20d986127 100644 --- a/packages/user/yggdrasil.ts +++ b/packages/user/yggdrasil.ts @@ -49,7 +49,7 @@ export interface YggrasilAuthentication { export interface YggdrasilClientOptions { headers?: Record - dispatcher: Dispatcher + dispatcher?: Dispatcher } export interface ProfileLookupException { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 506f5e7a7..6899bb5fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,8 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false importers: @@ -8,14 +12,14 @@ importers: specifier: ^0.30.1 version: 0.30.1(vitest@0.32.0) tsx: - specifier: ^3.12.6 - version: 3.12.6 + specifier: ^4.7.1 + version: 4.7.1 typedoc: - specifier: ^0.24.8 - version: 0.24.8(typescript@5.0.4) + specifier: ^0.25.8 + version: 0.25.8(typescript@5.3.3) typescript: - specifier: ^5.0.3 - version: 5.0.4 + specifier: ^5.3.3 + version: 5.3.3 vitest: specifier: ^0.32.0 version: 0.32.0 @@ -66,8 +70,8 @@ importers: specifier: ^2.5.0 version: 2.5.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/bytebuffer: devDependencies: @@ -90,8 +94,8 @@ importers: specifier: ^2.5.0 version: 2.5.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/client: dependencies: @@ -121,8 +125,8 @@ importers: specifier: ^2.5.0 version: 2.5.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/core: dependencies: @@ -143,14 +147,14 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/curseforge: dependencies: undici: - specifier: 6.0.1 - version: 6.0.1 + specifier: 6.14.0 + version: 6.14.0 devDependencies: esbuild: specifier: ^0.17.16 @@ -165,8 +169,8 @@ importers: specifier: ^0.37.39 version: 0.37.39 undici: - specifier: 6.0.1 - version: 6.0.1 + specifier: 6.14.0 + version: 6.14.0 devDependencies: '@types/node': specifier: ~18 @@ -184,35 +188,35 @@ importers: specifier: ^3.12.1 version: 3.12.6 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/eslint-config: dependencies: '@typescript-eslint/eslint-plugin': - specifier: ^6.13.2 - version: 6.13.2(@typescript-eslint/parser@6.13.2)(eslint@8.38.0)(typescript@5.2.2) + specifier: ^7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.13.2 - version: 6.13.2(eslint@8.38.0)(typescript@5.2.2) + specifier: ^7.15.0 + version: 7.15.0(eslint@8.57.0)(typescript@5.3.3) eslint: - specifier: ^8.37.0 - version: 8.38.0 + specifier: ^8.57.0 + version: 8.57.0 eslint-config-standard: specifier: ^17.1.0 - version: 17.1.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@16.3.1)(eslint-plugin-promise@6.1.1)(eslint@8.38.0) + version: 17.1.0(eslint-plugin-import@2.27.5(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint-plugin-n@16.3.1(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: specifier: ^2.27.5 - version: 2.27.5(@typescript-eslint/parser@6.13.2)(eslint@8.38.0) + version: 2.27.5(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0) eslint-plugin-n: specifier: ^16.3.1 - version: 16.3.1(eslint@8.38.0) + version: 16.3.1(eslint@8.57.0) eslint-plugin-promise: specifier: ^6.1.1 - version: 6.1.1(eslint@8.38.0) + version: 6.1.1(eslint@8.57.0) typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/file-transfer: dependencies: @@ -223,8 +227,8 @@ importers: specifier: ^4.1.1 version: 4.1.1 undici: - specifier: 6.0.1 - version: 6.0.1 + specifier: 6.14.0 + version: 6.14.0 devDependencies: '@types/node': specifier: ~18.15.11 @@ -239,8 +243,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/forge-site-parser: dependencies: @@ -261,8 +265,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/game-data: dependencies: @@ -289,8 +293,8 @@ importers: specifier: ^2.5.0 version: 2.5.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/gamesetting: devDependencies: @@ -307,8 +311,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/installer: dependencies: @@ -324,15 +328,12 @@ importers: '@xmcl/forge-site-parser': specifier: workspace:^* version: link:../forge-site-parser - '@xmcl/task': - specifier: workspace:^* - version: link:../task '@xmcl/unzip': specifier: workspace:^* version: link:../unzip undici: - specifier: 6.0.1 - version: 6.0.1 + specifier: 6.14.0 + version: 6.14.0 yauzl: specifier: ^2.10.0 version: 2.10.0 @@ -359,8 +360,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/mod-parser: dependencies: @@ -387,8 +388,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/model: dependencies: @@ -399,8 +400,8 @@ importers: specifier: workspace:^* version: link:../resourcepack three: - specifier: ^0.151.3 - version: 0.151.3 + specifier: 0.156.1 + version: 0.156.1 devDependencies: '@types/node': specifier: ~18.15.11 @@ -415,14 +416,14 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/modrinth: dependencies: undici: - specifier: 6.0.1 - version: 6.0.1 + specifier: 6.14.0 + version: 6.14.0 devDependencies: esbuild: specifier: ^0.17.16 @@ -440,8 +441,8 @@ importers: specifier: ^4.3.2 version: 4.3.2 undici: - specifier: 6.0.1 - version: 6.0.1 + specifier: 6.14.0 + version: 6.14.0 devDependencies: '@types/node': specifier: ^18.15.11 @@ -450,8 +451,8 @@ importers: specifier: ^0.17.16 version: 0.17.16 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/nbt: dependencies: @@ -478,8 +479,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/nbt/zlib: dependencies: @@ -526,8 +527,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/task: devDependencies: @@ -544,8 +545,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/text-component: devDependencies: @@ -562,8 +563,8 @@ importers: specifier: ^8.37.0 version: 8.38.0 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/undici-shim: {} @@ -583,14 +584,14 @@ importers: specifier: ^0.17.16 version: 0.17.16 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages/user: dependencies: undici: - specifier: 6.0.1 - version: 6.0.1 + specifier: 6.14.0 + version: 6.14.0 uuid: specifier: ^9.0.0 version: 9.0.0 @@ -602,8 +603,8 @@ importers: specifier: ^0.17.16 version: 0.17.16 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 undici-shim: specifier: workspace:^* version: link:../undici-shim @@ -617,842 +618,2697 @@ importers: specifier: ~18.15.11 version: 18.15.11 undici: - specifier: ^4.0.1 - version: 4.1.0 + specifier: 6.14.0 + version: 6.14.0 packages: - /@actions/core@1.10.0: + '@actions/core@1.10.0': resolution: {integrity: sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==} - dependencies: - '@actions/http-client': 2.1.0 - uuid: 8.3.2 - dev: true - /@actions/http-client@2.1.0: + '@actions/http-client@2.1.0': resolution: {integrity: sha512-BonhODnXr3amchh4qkmjPMUO8mFi/zLaaCeCAJZqch8iQqyDnVIkySjB38VHAC8IJ+bnlgfOqlhpyCUZHlQsqw==} - dependencies: - tunnel: 0.0.6 - dev: true - /@babel/code-frame@7.15.8: + '@babel/code-frame@7.15.8': resolution: {integrity: sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.14.5 - dev: false - /@babel/helper-validator-identifier@7.15.7: + '@babel/helper-validator-identifier@7.15.7': resolution: {integrity: sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==} engines: {node: '>=6.9.0'} - dev: false - /@babel/highlight@7.14.5: + '@babel/highlight@7.14.5': resolution: {integrity: sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.15.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: false - /@bcoe/v8-coverage@0.2.3: + '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true - /@esbuild-kit/cjs-loader@2.4.2: + '@esbuild-kit/cjs-loader@2.4.2': resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==} - dependencies: - '@esbuild-kit/core-utils': 3.1.0 - get-tsconfig: 4.7.2 - dev: true - /@esbuild-kit/core-utils@3.1.0: + '@esbuild-kit/core-utils@3.1.0': resolution: {integrity: sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==} - dependencies: - esbuild: 0.17.16 - source-map-support: 0.5.21 - dev: true - /@esbuild-kit/esm-loader@2.5.5: + '@esbuild-kit/esm-loader@2.5.5': resolution: {integrity: sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==} - dependencies: - '@esbuild-kit/core-utils': 3.1.0 - get-tsconfig: 4.7.2 - dev: true - /@esbuild/android-arm64@0.17.16: + '@esbuild/aix-ppc64@0.19.12': + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.17.16': resolution: {integrity: sha512-QX48qmsEZW+gcHgTmAj+x21mwTz8MlYQBnzF6861cNdQGvj2jzzFjqH0EBabrIa/WVZ2CHolwMoqxVryqKt8+Q==} engines: {node: '>=12'} cpu: [arm64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.17.16: + '@esbuild/android-arm64@0.19.12': + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.17.16': resolution: {integrity: sha512-baLqRpLe4JnKrUXLJChoTN0iXZH7El/mu58GE3WIA6/H834k0XWvLRmGLG8y8arTRS9hJJibPnF0tiGhmWeZgw==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-x64@0.17.16: + '@esbuild/android-arm@0.19.12': + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.17.16': resolution: {integrity: sha512-G4wfHhrrz99XJgHnzFvB4UwwPxAWZaZBOFXh+JH1Duf1I4vIVfuYY9uVLpx4eiV2D/Jix8LJY+TAdZ3i40tDow==} engines: {node: '>=12'} cpu: [x64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-arm64@0.17.16: + '@esbuild/android-x64@0.19.12': + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.17.16': resolution: {integrity: sha512-/Ofw8UXZxuzTLsNFmz1+lmarQI6ztMZ9XktvXedTbt3SNWDn0+ODTwxExLYQ/Hod91EZB4vZPQJLoqLF0jvEzA==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-x64@0.17.16: + '@esbuild/darwin-arm64@0.19.12': + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.17.16': resolution: {integrity: sha512-SzBQtCV3Pdc9kyizh36Ol+dNVhkDyIrGb/JXZqFq8WL37LIyrXU0gUpADcNV311sCOhvY+f2ivMhb5Tuv8nMOQ==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-arm64@0.17.16: + '@esbuild/darwin-x64@0.19.12': + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.17.16': resolution: {integrity: sha512-ZqftdfS1UlLiH1DnS2u3It7l4Bc3AskKeu+paJSfk7RNOMrOxmeFDhLTMQqMxycP1C3oj8vgkAT6xfAuq7ZPRA==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-x64@0.17.16: + '@esbuild/freebsd-arm64@0.19.12': + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.17.16': resolution: {integrity: sha512-rHV6zNWW1tjgsu0dKQTX9L0ByiJHHLvQKrWtnz8r0YYJI27FU3Xu48gpK2IBj1uCSYhJ+pEk6Y0Um7U3rIvV8g==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm64@0.17.16: + '@esbuild/freebsd-x64@0.19.12': + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.17.16': resolution: {integrity: sha512-8yoZhGkU6aHu38WpaM4HrRLTFc7/VVD9Q2SvPcmIQIipQt2I/GMTZNdEHXoypbbGao5kggLcxg0iBKjo0SQYKA==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm@0.17.16: + '@esbuild/linux-arm64@0.19.12': + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.17.16': resolution: {integrity: sha512-n4O8oVxbn7nl4+m+ISb0a68/lcJClIbaGAoXwqeubj/D1/oMMuaAXmJVfFlRjJLu/ZvHkxoiFJnmbfp4n8cdSw==} engines: {node: '>=12'} cpu: [arm] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ia32@0.17.16: + '@esbuild/linux-arm@0.19.12': + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.17.16': resolution: {integrity: sha512-9ZBjlkdaVYxPNO8a7OmzDbOH9FMQ1a58j7Xb21UfRU29KcEEU3VTHk+Cvrft/BNv0gpWJMiiZ/f4w0TqSP0gLA==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.17.16: + '@esbuild/linux-ia32@0.19.12': + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.17.16': resolution: {integrity: sha512-TIZTRojVBBzdgChY3UOG7BlPhqJz08AL7jdgeeu+kiObWMFzGnQD7BgBBkWRwOtKR1i2TNlO7YK6m4zxVjjPRQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-mips64el@0.17.16: + '@esbuild/linux-loong64@0.19.12': + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.17.16': resolution: {integrity: sha512-UPeRuFKCCJYpBbIdczKyHLAIU31GEm0dZl1eMrdYeXDH+SJZh/i+2cAmD3A1Wip9pIc5Sc6Kc5cFUrPXtR0XHA==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ppc64@0.17.16: + '@esbuild/linux-mips64el@0.19.12': + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.17.16': resolution: {integrity: sha512-io6yShgIEgVUhExJejJ21xvO5QtrbiSeI7vYUnr7l+v/O9t6IowyhdiYnyivX2X5ysOVHAuyHW+Wyi7DNhdw6Q==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-riscv64@0.17.16: + '@esbuild/linux-ppc64@0.19.12': + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.17.16': resolution: {integrity: sha512-WhlGeAHNbSdG/I2gqX2RK2gfgSNwyJuCiFHMc8s3GNEMMHUI109+VMBfhVqRb0ZGzEeRiibi8dItR3ws3Lk+cA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-s390x@0.17.16: + '@esbuild/linux-riscv64@0.19.12': + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.17.16': resolution: {integrity: sha512-gHRReYsJtViir63bXKoFaQ4pgTyah4ruiMRQ6im9YZuv+gp3UFJkNTY4sFA73YDynmXZA6hi45en4BGhNOJUsw==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-x64@0.17.16: + '@esbuild/linux-s390x@0.19.12': + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.17.16': resolution: {integrity: sha512-mfiiBkxEbUHvi+v0P+TS7UnA9TeGXR48aK4XHkTj0ZwOijxexgMF01UDFaBX7Q6CQsB0d+MFNv9IiXbIHTNd4g==} engines: {node: '>=12'} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.17.16: + '@esbuild/linux-x64@0.19.12': + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.17.16': resolution: {integrity: sha512-n8zK1YRDGLRZfVcswcDMDM0j2xKYLNXqei217a4GyBxHIuPMGrrVuJ+Ijfpr0Kufcm7C1k/qaIrGy6eG7wvgmA==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/openbsd-x64@0.17.16: + '@esbuild/netbsd-x64@0.19.12': + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.17.16': resolution: {integrity: sha512-lEEfkfsUbo0xC47eSTBqsItXDSzwzwhKUSsVaVjVji07t8+6KA5INp2rN890dHZeueXJAI8q0tEIfbwVRYf6Ew==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.17.16: + '@esbuild/openbsd-x64@0.19.12': + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.17.16': resolution: {integrity: sha512-jlRjsuvG1fgGwnE8Afs7xYDnGz0dBgTNZfgCK6TlvPH3Z13/P5pi6I57vyLE8qZYLrGVtwcm9UbUx1/mZ8Ukag==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.17.16: + '@esbuild/sunos-x64@0.19.12': + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.17.16': resolution: {integrity: sha512-TzoU2qwVe2boOHl/3KNBUv2PNUc38U0TNnzqOAcgPiD/EZxT2s736xfC2dYQbszAwo4MKzzwBV0iHjhfjxMimg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-ia32@0.17.16: + '@esbuild/win32-arm64@0.19.12': + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.17.16': resolution: {integrity: sha512-B8b7W+oo2yb/3xmwk9Vc99hC9bNolvqjaTZYEfMQhzdpBsjTvZBlXQ/teUE55Ww6sg//wlcDjOaqldOKyigWdA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-x64@0.17.16: + '@esbuild/win32-ia32@0.19.12': + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.17.16': resolution: {integrity: sha512-xJ7OH/nanouJO9pf03YsL9NAFQBHd8AqfrQd7Pf5laGyyTt/gToul6QYOA/i5i/q8y9iaM5DQFNTgpi995VkOg==} engines: {node: '>=12'} cpu: [x64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.38.0): + '@esbuild/win32-x64@0.19.12': + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.38.0 - eslint-visitor-keys: 3.4.0 - /@eslint-community/regexpp@4.10.0: + '@eslint-community/regexpp@4.10.0': resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: false - /@eslint-community/regexpp@4.5.0: + '@eslint-community/regexpp@4.5.0': resolution: {integrity: sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - /@eslint/eslintrc@2.0.2: + '@eslint/eslintrc@2.0.2': resolution: {integrity: sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.5.1 - globals: 13.20.0 - ignore: 5.2.4 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - /@eslint/js@8.38.0: + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.38.0': resolution: {integrity: sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@fastify/busboy@2.1.0: - resolution: {integrity: sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==} - engines: {node: '>=14'} - dev: false + '@eslint/js@8.57.0': + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@humanwhocodes/config-array@0.11.14': + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead - /@humanwhocodes/config-array@0.11.8: + '@humanwhocodes/config-array@0.11.8': resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - /@humanwhocodes/module-importer@1.0.1: + '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - /@humanwhocodes/object-schema@1.2.1: + '@humanwhocodes/object-schema@1.2.1': resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} - /@istanbuljs/schema@0.1.3: + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead + + '@istanbuljs/schema@0.1.3': resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - dev: true - /@jridgewell/resolve-uri@3.1.0: + '@jridgewell/resolve-uri@3.1.0': resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} - dev: true - /@jridgewell/sourcemap-codec@1.4.14: + '@jridgewell/sourcemap-codec@1.4.14': resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - dev: true - /@jridgewell/trace-mapping@0.3.18: + '@jridgewell/trace-mapping@0.3.18': resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - /@nodelib/fs.scandir@2.1.5: + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - /@nodelib/fs.stat@2.0.5: + '@nodelib/fs.stat@2.0.5': resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - /@nodelib/fs.walk@1.2.8: + '@nodelib/fs.walk@1.2.8': resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.13.0 - /@types/chai-subset@1.3.3: + '@types/chai-subset@1.3.3': resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} - dependencies: - '@types/chai': 4.3.5 - dev: true - /@types/chai@4.3.5: + '@types/chai@4.3.5': resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} - dev: true - /@types/conventional-changelog-core@4.2.1: + '@types/conventional-changelog-core@4.2.1': resolution: {integrity: sha512-XdQKXrWvHYvnhuXal4JcvIh3sn9LpcER/WjWDDQHh0yz3/yt0r8TvE5AyJwX6xL9BwJRpE1Ce+A0Hj16nsfI6w==} - dependencies: - '@types/conventional-changelog-writer': 4.0.2 - '@types/conventional-commits-parser': 3.0.3 - '@types/conventional-recommended-bump': 6.1.0 - '@types/git-raw-commits': 2.0.1 - '@types/node': 18.15.11 - '@types/normalize-package-data': 2.4.1 - dev: false - /@types/conventional-changelog-writer@4.0.2: + '@types/conventional-changelog-writer@4.0.2': resolution: {integrity: sha512-3WZjXOh1k2FYDZlmR/lFCaTJlOGTfqOW0PWd4A1hwIVVSk5fWP8fRR9228DiEbcq9ZrQl07ACbPpxGCCEJ6cQQ==} - dependencies: - '@types/conventional-commits-parser': 3.0.3 - '@types/node': 18.15.11 - dev: false - /@types/conventional-commits-parser@3.0.3: + '@types/conventional-commits-parser@3.0.3': resolution: {integrity: sha512-aoUKfRQYvGMH+spFpOTX9jO4nZoz9/BKp4hlHPxL3Cj2r2Xj+jEcwlXtFIyZr5uL8bh1nbWynDEYaAota+XqPg==} - dependencies: - '@types/node': 18.15.11 - dev: false - /@types/conventional-recommended-bump@6.1.0: + '@types/conventional-recommended-bump@6.1.0': resolution: {integrity: sha512-AlhJsbzY2W+9xkn44qvEgeJGY6FbQIluPRZawwU2JgJw+o7PYB/yjeuRsJhNZRKto3j71hDj+hQik10w/7bI4Q==} - dependencies: - '@types/conventional-changelog-core': 4.2.1 - '@types/conventional-changelog-writer': 4.0.2 - '@types/conventional-commits-parser': 3.0.3 - dev: false - /@types/git-raw-commits@2.0.1: + '@types/git-raw-commits@2.0.1': resolution: {integrity: sha512-vE2lbXxqJ0AqMDoP4N6d+WVfbcBla9+z8IL6e+37JNQIwYZCYY0z3J7hdpY8D/VGwFZ0yIYQLcqk8eCnfXsaEg==} - dependencies: - '@types/node': 18.15.11 - dev: false - /@types/http-cache-semantics@4.0.1: + '@types/http-cache-semantics@4.0.1': resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} - dev: false - /@types/istanbul-lib-coverage@2.0.4: + '@types/istanbul-lib-coverage@2.0.4': resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} - dev: true - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: false - - /@types/json5@0.0.29: + '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: false - /@types/minimist@1.2.2: + '@types/minimist@1.2.2': resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} - dev: false - /@types/node@16.18.23: + '@types/node@16.18.23': resolution: {integrity: sha512-XAMpaw1s1+6zM+jn2tmw8MyaRDIJfXxqmIQIS0HfoGYPuf7dUWeiUKopwq13KFX9lEp1+THGtlaaYx39Nxr58g==} - dev: false - /@types/node@18.15.11: + '@types/node@18.15.11': resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==} - /@types/normalize-package-data@2.4.1: + '@types/normalize-package-data@2.4.1': resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: false - /@types/pako@2.0.0: + '@types/pako@2.0.0': resolution: {integrity: sha512-10+iaz93qR5WYxTo+PMifD5TSxiOtdRaxBf7INGGXMQgTCu8Z/7GYWYFUOS3q/G0nE5boj1r4FEB+WSy7s5gbA==} - dev: true - /@types/semver@7.3.13: + '@types/semver@7.3.13': resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} - dev: false - - /@types/semver@7.5.6: - resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} - dev: false - /@types/stats.js@0.17.0: + '@types/stats.js@0.17.0': resolution: {integrity: sha512-9w+a7bR8PeB0dCT/HBULU2fMqf6BAzvKbxFboYhmDtDkKPiyXYbjoe2auwsXlEFI7CFNMF1dCv3dFH5Poy9R1w==} - dev: false - /@types/three@0.150.1: + '@types/three@0.150.1': resolution: {integrity: sha512-ZXS1M3brsfAAbTeeUEt0defPi98yWQuEyPBnvjEYY1dCEYfJnFaww0mYgRpJ9JVfmtwRxqISpVcv/g/0lMl1DQ==} - dependencies: - '@types/stats.js': 0.17.0 - '@types/webxr': 0.4.0 - fflate: 0.6.10 - lil-gui: 0.17.0 - dev: false - /@types/uuid@9.0.1: + '@types/uuid@9.0.1': resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==} - dev: true - /@types/webxr@0.4.0: + '@types/webxr@0.4.0': resolution: {integrity: sha512-LQvrACV3Pj17GpkwHwXuTd733gfY+D7b9mKdrTmLdO7vo7P/o6209Qqtk63y/FCv/lspdmi0pWz6Qe/ull9kQg==} - dev: false - /@types/yauzl@2.10.0: + '@types/yauzl@2.10.0': resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} - dependencies: - '@types/node': 18.15.11 - /@types/yazl@2.4.5: + '@types/yazl@2.4.5': resolution: {integrity: sha512-qpmPfx32HS7vlGJf7EsoM9qJnLZhXJBf1KH0hzfdc+D794rljQWh4H0I/UrZy+6Nhqn0l2jdBZXBGZtR1vnHqw==} - dependencies: - '@types/node': 18.15.11 - dev: true - /@typescript-eslint/eslint-plugin@6.13.2(@typescript-eslint/parser@6.13.2)(eslint@8.38.0)(typescript@5.2.2): - resolution: {integrity: sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/eslint-plugin@7.15.0': + resolution: {integrity: sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.13.2(eslint@8.38.0)(typescript@5.2.2) - '@typescript-eslint/scope-manager': 6.13.2 - '@typescript-eslint/type-utils': 6.13.2(eslint@8.38.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.13.2(eslint@8.38.0)(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.13.2 - debug: 4.3.4 - eslint: 8.38.0 - graphemer: 1.4.0 - ignore: 5.2.4 - natural-compare: 1.4.0 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 - transitivePeerDependencies: - - supports-color - dev: false - /@typescript-eslint/parser@6.13.2(eslint@8.38.0)(typescript@5.2.2): - resolution: {integrity: sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/parser@7.15.0': + resolution: {integrity: sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.13.2 - '@typescript-eslint/types': 6.13.2 - '@typescript-eslint/typescript-estree': 6.13.2(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.13.2 - debug: 4.3.4 - eslint: 8.38.0 - typescript: 5.2.2 - transitivePeerDependencies: - - supports-color - dev: false - /@typescript-eslint/scope-manager@6.13.2: - resolution: {integrity: sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.13.2 - '@typescript-eslint/visitor-keys': 6.13.2 - dev: false + '@typescript-eslint/scope-manager@7.15.0': + resolution: {integrity: sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==} + engines: {node: ^18.18.0 || >=20.0.0} - /@typescript-eslint/type-utils@6.13.2(eslint@8.38.0)(typescript@5.2.2): - resolution: {integrity: sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/type-utils@7.15.0': + resolution: {integrity: sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - dependencies: - '@typescript-eslint/typescript-estree': 6.13.2(typescript@5.2.2) - '@typescript-eslint/utils': 6.13.2(eslint@8.38.0)(typescript@5.2.2) - debug: 4.3.4 - eslint: 8.38.0 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 - transitivePeerDependencies: - - supports-color - dev: false - /@typescript-eslint/types@6.13.2: - resolution: {integrity: sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==} - engines: {node: ^16.0.0 || >=18.0.0} - dev: false + '@typescript-eslint/types@7.15.0': + resolution: {integrity: sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==} + engines: {node: ^18.18.0 || >=20.0.0} - /@typescript-eslint/typescript-estree@6.13.2(typescript@5.2.2): - resolution: {integrity: sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/typescript-estree@7.15.0': + resolution: {integrity: sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - dependencies: - '@typescript-eslint/types': 6.13.2 - '@typescript-eslint/visitor-keys': 6.13.2 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 - transitivePeerDependencies: - - supports-color - dev: false - /@typescript-eslint/utils@6.13.2(eslint@8.38.0)(typescript@5.2.2): - resolution: {integrity: sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/utils@7.15.0': + resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.38.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 6.13.2 - '@typescript-eslint/types': 6.13.2 - '@typescript-eslint/typescript-estree': 6.13.2(typescript@5.2.2) - eslint: 8.38.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: false + eslint: ^8.56.0 - /@typescript-eslint/visitor-keys@6.13.2: - resolution: {integrity: sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.13.2 - eslint-visitor-keys: 3.4.3 - dev: false + '@typescript-eslint/visitor-keys@7.15.0': + resolution: {integrity: sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==} + engines: {node: ^18.18.0 || >=20.0.0} - /@vitest/coverage-c8@0.30.1(vitest@0.32.0): + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@vitest/coverage-c8@0.30.1': resolution: {integrity: sha512-/Wa3dtSuckpdngAmiCwowaEXXgJkqPrtfvrs9HTB9QoEfNbZWPu4E4cjEn4lJZb4qcGf4fxFtUA2f9DnDNAzBA==} peerDependencies: vitest: '>=0.30.0 <1' - dependencies: - c8: 7.13.0 - picocolors: 1.0.0 - std-env: 3.3.2 - vitest: 0.32.0 - dev: true - /@vitest/expect@0.32.0: + '@vitest/expect@0.32.0': resolution: {integrity: sha512-VxVHhIxKw9Lux+O9bwLEEk2gzOUe93xuFHy9SzYWnnoYZFYg1NfBtnfnYWiJN7yooJ7KNElCK5YtA7DTZvtXtg==} - dependencies: - '@vitest/spy': 0.32.0 + + '@vitest/runner@0.32.0': + resolution: {integrity: sha512-QpCmRxftHkr72xt5A08xTEs9I4iWEXIOCHWhQQguWOKE4QH7DXSKZSOFibuwEIMAD7G0ERvtUyQn7iPWIqSwmw==} + + '@vitest/snapshot@0.32.0': + resolution: {integrity: sha512-yCKorPWjEnzpUxQpGlxulujTcSPgkblwGzAUEL+z01FTUg/YuCDZ8dxr9sHA08oO2EwxzHXNLjQKWJ2zc2a19Q==} + + '@vitest/spy@0.32.0': + resolution: {integrity: sha512-MruAPlM0uyiq3d53BkwTeShXY0rYEfhNGQzVO5GHBmmX3clsxcWp79mMnkOVcV244sNTeDcHbcPFWIjOI4tZvw==} + + '@vitest/utils@0.32.0': + resolution: {integrity: sha512-53yXunzx47MmbuvcOPpLaVljHaeSu1G2dHdmy7+9ngMnQIkBQcvwOcoclWFnxDMxFbnq8exAfh3aKSZaK71J5A==} + + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-sequence-parser@1.1.0: + resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-includes@3.1.6: + resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.flat@1.3.1: + resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.1: + resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} + engines: {node: '>= 0.4'} + + arrify@1.0.1: + resolution: {integrity: sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=} + engines: {node: '>=0.10.0'} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + + available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + blueimp-md5@2.19.0: + resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + buffer-crc32@0.2.13: + resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + builtins@5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + + bytebuffer@5.0.1: + resolution: {integrity: sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ==} + engines: {node: '>=0.8'} + + c8@7.13.0: + resolution: {integrity: sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==} + engines: {node: '>=10.12.0'} + hasBin: true + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + chai@4.3.7: + resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} + engines: {node: '>=4'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + check-error@1.0.2: + resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + concat-map@0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + + concat-stream@2.0.0: + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} + + concordance@5.0.4: + resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==} + engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'} + + conventional-changelog-preset-loader@2.3.4: + resolution: {integrity: sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==} + engines: {node: '>=10'} + + conventional-commits-filter@2.0.7: + resolution: {integrity: sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==} + engines: {node: '>=10'} + + conventional-commits-parser@3.2.4: + resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==} + engines: {node: '>=10'} + hasBin: true + + conventional-recommended-bump@6.1.0: + resolution: {integrity: sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==} + engines: {node: '>=10'} + hasBin: true + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + dargs@7.0.0: + resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} + engines: {node: '>=8'} + + date-time@3.1.0: + resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} + engines: {node: '>=6'} + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize-keys@1.1.0: + resolution: {integrity: sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=} + engines: {node: '>=0.10.0'} + + decamelize@1.2.0: + resolution: {integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=} + engines: {node: '>=0.10.0'} + + deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + default-gateway@6.0.3: + resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} + engines: {node: '>= 10'} + + define-properties@1.1.4: + resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} + engines: {node: '>= 0.4'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + discord-api-types@0.37.39: + resolution: {integrity: sha512-hkhQsQyzsTJITp311WXvHZh9j4RAMfIk2hPmsWeOTN50QTpg6zqmJNfel9D/8lYNvsU01wzw9281Yke8NhYyHg==} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.0.1: + resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + entities@4.4.0: + resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} + engines: {node: '>=0.12'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-abstract@1.21.1: + resolution: {integrity: sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.0.0: + resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + esbuild@0.17.16: + resolution: {integrity: sha512-aeSuUKr9aFVY9Dc8ETVELGgkj4urg5isYx8pLf4wlGgB0vTFjxJQdHnNH6Shmx4vYYrOTLCHtRI5i1XZ9l2Zcg==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-compat-utils@0.1.2: + resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-config-standard@17.1.0: + resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: ^8.0.1 + eslint-plugin-import: ^2.25.2 + eslint-plugin-n: '^15.0.0 || ^16.0.0 ' + eslint-plugin-promise: ^6.0.0 + + eslint-import-resolver-node@0.3.7: + resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} + + eslint-module-utils@2.7.4: + resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-es-x@7.5.0: + resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + + eslint-plugin-import@2.27.5: + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-n@16.3.1: + resolution: {integrity: sha512-w46eDIkxQ2FaTHcey7G40eD+FhTXOdKudDXPUO2n9WNcslze/i/HT2qJ3GXjHngYSGDISIgPNhwGtgoix4zeOw==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-promise@6.1.1: + resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + + eslint-scope@7.1.1: + resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.0: + resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.38.0: + resolution: {integrity: sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + espree@9.5.1: + resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.2.0: + resolution: {integrity: sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.2.0: + resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} + + fast-glob@3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-xml-parser@4.3.2: + resolution: {integrity: sha512-rmrXUXwbJedoXkStenj1kkljNF7ugn5ZjR9FJcwmCfcCbtOMDghPajbc+Tck6vE6F5XsDmx+Pr2le9fw8+pXBg==} + hasBin: true + + fastq@1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + + fd-slicer@1.1.0: + resolution: {integrity: sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=} + + fflate@0.6.10: + resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + + flatted@3.2.2: + resolution: {integrity: sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==} + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + foreground-child@2.0.0: + resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} + engines: {node: '>=8.0.0'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-func-name@2.0.0: + resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} + + get-intrinsic@1.1.3: + resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + + git-raw-commits@2.0.10: + resolution: {integrity: sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==} + engines: {node: '>=10'} + hasBin: true + + git-semver-tags@4.1.1: + resolution: {integrity: sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==} + engines: {node: '>=10'} + hasBin: true + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + + globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} + engines: {node: '>=8'} + + globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + + has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + + has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + + hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + hosted-git-info@4.0.2: + resolution: {integrity: sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==} + engines: {node: '>=10'} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internal-slot@1.0.4: + resolution: {integrity: sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.1: + resolution: {integrity: sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==} + + is-arrayish@0.2.1: + resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + + is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha1-caUMhCnfync8kqOQpKA7OfzVHT4=} + engines: {node: '>=0.10.0'} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-text-path@1.0.1: + resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} + engines: {node: '>=0.10.0'} + + is-typed-array@1.1.10: + resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} + engines: {node: '>= 0.4'} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + istanbul-lib-coverage@3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.0: + resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} + engines: {node: '>=8'} + + istanbul-reports@3.1.5: + resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} + engines: {node: '>=8'} + + js-sdsl@4.4.0: + resolution: {integrity: sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==} + + js-string-escape@1.0.1: + resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} + engines: {node: '>= 0.8'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + + lil-gui@0.17.0: + resolution: {integrity: sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==} + + lines-and-columns@1.1.6: + resolution: {integrity: sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=} + + local-pkg@0.4.3: + resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + engines: {node: '>=14'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.ismatch@4.4.0: + resolution: {integrity: sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + long@3.2.0: + resolution: {integrity: sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==} + engines: {node: '>=0.6'} + + loupe@2.3.6: + resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lunr@2.3.9: + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + + magic-string@0.30.0: + resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} + engines: {node: '>=12'} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + map-obj@1.0.1: + resolution: {integrity: sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=} + engines: {node: '>=0.10.0'} + + map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + + marked@4.3.0: + resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} + engines: {node: '>= 12'} + hasBin: true + + md5-hex@3.0.1: + resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==} + engines: {node: '>=8'} + + meow@8.1.2: + resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} + engines: {node: '>=10'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.4: + resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==} + engines: {node: '>=8.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + + minimist@1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + + mlly@1.2.0: + resolution: {integrity: sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==} + + modify-values@1.0.1: + resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} + engines: {node: '>=0.10.0'} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-html-parser@6.1.5: + resolution: {integrity: sha512-fAaM511feX++/Chnhe475a0NHD8M7AxDInsqQpz6x63GRF7xYNdS8Vo5dKsIVPgsOvG7eioRRTZQnWBrhDHBSg==} + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-package-data@3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + + object.values@1.1.6: + resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} + engines: {node: '>= 0.4'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + optionator@0.9.1: + resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} + engines: {node: '>= 0.8.0'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@1.1.0: + resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + + pend@1.2.0: + resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=} + + picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + picomatch@2.3.0: + resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==} + engines: {node: '>=8.6'} + + pkg-types@1.0.2: + resolution: {integrity: sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==} + + postcss@8.4.21: + resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + punycode@2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + + q@1.5.1: + resolution: {integrity: sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + readable-stream@2.3.7: + resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + + readable-stream@3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + regexp.prototype.flags@1.4.3: + resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} + engines: {node: '>= 0.4'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + + rollup@3.20.2: + resolution: {integrity: sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + + semver@5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + + semver@6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shiki@0.14.7: + resolution: {integrity: sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==} + + side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@3.0.5: + resolution: {integrity: sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spdx-correct@3.1.1: + resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + + spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.10: + resolution: {integrity: sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==} + + split2@3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.3.2: + resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + + string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-literal@1.0.1: + resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + text-extensions@1.9.0: + resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} + engines: {node: '>=0.10'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + three@0.156.1: + resolution: {integrity: sha512-kP7H0FK9d/k6t/XvQ9FO6i+QrePoDcNhwl0I02+wmUJRNSLCUIDMcfObnzQvxb37/0Uc9TDT0T1HgsRRrO6SYQ==} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + time-zone@1.0.0: + resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} + engines: {node: '>=4'} + + tinybench@2.5.0: + resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} + + tinypool@0.5.0: + resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==} + engines: {node: '>=14.0.0'} + + tinyspy@2.1.0: + resolution: {integrity: sha512-7eORpyqImoOvkQJCSkL0d0mB4NHHIFAy4b1u8PHdDa7SjGS2njzl6/lyGoZLm+eyYEtlUmFGE0rFj66SWxZgQQ==} + engines: {node: '>=14.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toml@3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + + trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + tsconfig-paths@3.14.1: + resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} + + tslib@2.5.0: + resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + + tsx@3.12.6: + resolution: {integrity: sha512-q93WgS3lBdHlPgS0h1i+87Pt6n9K/qULIMNYZo07nSeu2z5QE2CellcAZfofVXBo2tQg9av2ZcRMQ2S2i5oadQ==} + hasBin: true + + tsx@4.7.1: + resolution: {integrity: sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==} + engines: {node: '>=18.0.0'} + hasBin: true + + tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + + typedarray@0.0.6: + resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} + + typedoc@0.25.8: + resolution: {integrity: sha512-mh8oLW66nwmeB9uTa0Bdcjfis+48bAjSH3uqdzSuSawfduROQLlXw//WSNZLYDdhmMVB7YcYZicq6e8T0d271A==} + engines: {node: '>= 16'} + hasBin: true + peerDependencies: + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x + + typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.1.1: + resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==} + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + undici@6.14.0: + resolution: {integrity: sha512-esJ/x2QU5boTG6thdA0o4qP3cv/oPx9mcQGcp8TAHI+ZBTa0EvM9Jiyp0ILdPGLGxs5HATTKrJqAK+YhrSFicg==} + engines: {node: '>=18.17'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + + v8-to-istanbul@9.1.0: + resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} + engines: {node: '>=10.12.0'} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + vite-node@0.32.0: + resolution: {integrity: sha512-220P/y8YacYAU+daOAqiGEFXx2A8AwjadDzQqos6wSukjvvTWNqleJSwoUn0ckyNdjHIKoxn93Nh1vWBqEKr3Q==} + engines: {node: '>=v14.18.0'} + hasBin: true + + vite@4.2.1: + resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@0.32.0: + resolution: {integrity: sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==} + engines: {node: '>=v14.18.0'} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@vitest/browser': '*' + '@vitest/ui': '*' + happy-dom: '*' + jsdom: '*' + playwright: '*' + safaridriver: '*' + webdriverio: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + + vscode-oniguruma@1.7.0: + resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + + vscode-textmate@8.0.0: + resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + + well-known-symbols@2.0.0: + resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==} + engines: {node: '>=6'} + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-typed-array@1.1.9: + resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.3: + resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + engines: {node: '>=0.10.0'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yauzl@2.10.0: + resolution: {integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=} + + yazl@2.5.1: + resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + +snapshots: + + '@actions/core@1.10.0': + dependencies: + '@actions/http-client': 2.1.0 + uuid: 8.3.2 + + '@actions/http-client@2.1.0': + dependencies: + tunnel: 0.0.6 + + '@babel/code-frame@7.15.8': + dependencies: + '@babel/highlight': 7.14.5 + + '@babel/helper-validator-identifier@7.15.7': {} + + '@babel/highlight@7.14.5': + dependencies: + '@babel/helper-validator-identifier': 7.15.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + + '@bcoe/v8-coverage@0.2.3': {} + + '@esbuild-kit/cjs-loader@2.4.2': + dependencies: + '@esbuild-kit/core-utils': 3.1.0 + get-tsconfig: 4.7.2 + + '@esbuild-kit/core-utils@3.1.0': + dependencies: + esbuild: 0.17.16 + source-map-support: 0.5.21 + + '@esbuild-kit/esm-loader@2.5.5': + dependencies: + '@esbuild-kit/core-utils': 3.1.0 + get-tsconfig: 4.7.2 + + '@esbuild/aix-ppc64@0.19.12': + optional: true + + '@esbuild/android-arm64@0.17.16': + optional: true + + '@esbuild/android-arm64@0.19.12': + optional: true + + '@esbuild/android-arm@0.17.16': + optional: true + + '@esbuild/android-arm@0.19.12': + optional: true + + '@esbuild/android-x64@0.17.16': + optional: true + + '@esbuild/android-x64@0.19.12': + optional: true + + '@esbuild/darwin-arm64@0.17.16': + optional: true + + '@esbuild/darwin-arm64@0.19.12': + optional: true + + '@esbuild/darwin-x64@0.17.16': + optional: true + + '@esbuild/darwin-x64@0.19.12': + optional: true + + '@esbuild/freebsd-arm64@0.17.16': + optional: true + + '@esbuild/freebsd-arm64@0.19.12': + optional: true + + '@esbuild/freebsd-x64@0.17.16': + optional: true + + '@esbuild/freebsd-x64@0.19.12': + optional: true + + '@esbuild/linux-arm64@0.17.16': + optional: true + + '@esbuild/linux-arm64@0.19.12': + optional: true + + '@esbuild/linux-arm@0.17.16': + optional: true + + '@esbuild/linux-arm@0.19.12': + optional: true + + '@esbuild/linux-ia32@0.17.16': + optional: true + + '@esbuild/linux-ia32@0.19.12': + optional: true + + '@esbuild/linux-loong64@0.17.16': + optional: true + + '@esbuild/linux-loong64@0.19.12': + optional: true + + '@esbuild/linux-mips64el@0.17.16': + optional: true + + '@esbuild/linux-mips64el@0.19.12': + optional: true + + '@esbuild/linux-ppc64@0.17.16': + optional: true + + '@esbuild/linux-ppc64@0.19.12': + optional: true + + '@esbuild/linux-riscv64@0.17.16': + optional: true + + '@esbuild/linux-riscv64@0.19.12': + optional: true + + '@esbuild/linux-s390x@0.17.16': + optional: true + + '@esbuild/linux-s390x@0.19.12': + optional: true + + '@esbuild/linux-x64@0.17.16': + optional: true + + '@esbuild/linux-x64@0.19.12': + optional: true + + '@esbuild/netbsd-x64@0.17.16': + optional: true + + '@esbuild/netbsd-x64@0.19.12': + optional: true + + '@esbuild/openbsd-x64@0.17.16': + optional: true + + '@esbuild/openbsd-x64@0.19.12': + optional: true + + '@esbuild/sunos-x64@0.17.16': + optional: true + + '@esbuild/sunos-x64@0.19.12': + optional: true + + '@esbuild/win32-arm64@0.17.16': + optional: true + + '@esbuild/win32-arm64@0.19.12': + optional: true + + '@esbuild/win32-ia32@0.17.16': + optional: true + + '@esbuild/win32-ia32@0.19.12': + optional: true + + '@esbuild/win32-x64@0.17.16': + optional: true + + '@esbuild/win32-x64@0.19.12': + optional: true + + '@eslint-community/eslint-utils@4.4.0(eslint@8.38.0)': + dependencies: + eslint: 8.38.0 + eslint-visitor-keys: 3.4.0 + + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.0 + + '@eslint-community/regexpp@4.10.0': {} + + '@eslint-community/regexpp@4.5.0': {} + + '@eslint/eslintrc@2.0.2': + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.5.1 + globals: 13.20.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/eslintrc@2.1.4': + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.20.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@8.38.0': {} + + '@eslint/js@8.57.0': {} + + '@humanwhocodes/config-array@0.11.14': + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/config-array@0.11.8': + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/object-schema@1.2.1': {} + + '@humanwhocodes/object-schema@2.0.3': {} + + '@istanbuljs/schema@0.1.3': {} + + '@jridgewell/resolve-uri@3.1.0': {} + + '@jridgewell/sourcemap-codec@1.4.14': {} + + '@jridgewell/trace-mapping@0.3.18': + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.13.0 + + '@types/chai-subset@1.3.3': + dependencies: + '@types/chai': 4.3.5 + + '@types/chai@4.3.5': {} + + '@types/conventional-changelog-core@4.2.1': + dependencies: + '@types/conventional-changelog-writer': 4.0.2 + '@types/conventional-commits-parser': 3.0.3 + '@types/conventional-recommended-bump': 6.1.0 + '@types/git-raw-commits': 2.0.1 + '@types/node': 18.15.11 + '@types/normalize-package-data': 2.4.1 + + '@types/conventional-changelog-writer@4.0.2': + dependencies: + '@types/conventional-commits-parser': 3.0.3 + '@types/node': 18.15.11 + + '@types/conventional-commits-parser@3.0.3': + dependencies: + '@types/node': 18.15.11 + + '@types/conventional-recommended-bump@6.1.0': + dependencies: + '@types/conventional-changelog-core': 4.2.1 + '@types/conventional-changelog-writer': 4.0.2 + '@types/conventional-commits-parser': 3.0.3 + + '@types/git-raw-commits@2.0.1': + dependencies: + '@types/node': 18.15.11 + + '@types/http-cache-semantics@4.0.1': {} + + '@types/istanbul-lib-coverage@2.0.4': {} + + '@types/json5@0.0.29': {} + + '@types/minimist@1.2.2': {} + + '@types/node@16.18.23': {} + + '@types/node@18.15.11': {} + + '@types/normalize-package-data@2.4.1': {} + + '@types/pako@2.0.0': {} + + '@types/semver@7.3.13': {} + + '@types/stats.js@0.17.0': {} + + '@types/three@0.150.1': + dependencies: + '@types/stats.js': 0.17.0 + '@types/webxr': 0.4.0 + fflate: 0.6.10 + lil-gui: 0.17.0 + + '@types/uuid@9.0.1': {} + + '@types/webxr@0.4.0': {} + + '@types/yauzl@2.10.0': + dependencies: + '@types/node': 18.15.11 + + '@types/yazl@2.4.5': + dependencies: + '@types/node': 18.15.11 + + '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3)': + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/type-utils': 7.15.0(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 7.15.0 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.3.3) + optionalDependencies: + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3)': + dependencies: + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.4 + eslint: 8.57.0 + optionalDependencies: + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@7.15.0': + dependencies: + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 + + '@typescript-eslint/type-utils@7.15.0(eslint@8.57.0)(typescript@5.3.3)': + dependencies: + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.3.3) + '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.3.3) + debug: 4.3.4 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.3.3) + optionalDependencies: + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@7.15.0': {} + + '@typescript-eslint/typescript-estree@7.15.0(typescript@5.3.3)': + dependencies: + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.3.3) + optionalDependencies: + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@7.15.0(eslint@8.57.0)(typescript@5.3.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.3.3) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@7.15.0': + dependencies: + '@typescript-eslint/types': 7.15.0 + eslint-visitor-keys: 3.4.3 + + '@ungap/structured-clone@1.2.0': {} + + '@vitest/coverage-c8@0.30.1(vitest@0.32.0)': + dependencies: + c8: 7.13.0 + picocolors: 1.0.0 + std-env: 3.3.2 + vitest: 0.32.0 + + '@vitest/expect@0.32.0': + dependencies: + '@vitest/spy': 0.32.0 '@vitest/utils': 0.32.0 chai: 4.3.7 - dev: true - /@vitest/runner@0.32.0: - resolution: {integrity: sha512-QpCmRxftHkr72xt5A08xTEs9I4iWEXIOCHWhQQguWOKE4QH7DXSKZSOFibuwEIMAD7G0ERvtUyQn7iPWIqSwmw==} + '@vitest/runner@0.32.0': dependencies: '@vitest/utils': 0.32.0 concordance: 5.0.4 p-limit: 4.0.0 pathe: 1.1.0 - dev: true - /@vitest/snapshot@0.32.0: - resolution: {integrity: sha512-yCKorPWjEnzpUxQpGlxulujTcSPgkblwGzAUEL+z01FTUg/YuCDZ8dxr9sHA08oO2EwxzHXNLjQKWJ2zc2a19Q==} + '@vitest/snapshot@0.32.0': dependencies: magic-string: 0.30.0 pathe: 1.1.0 pretty-format: 27.5.1 - dev: true - /@vitest/spy@0.32.0: - resolution: {integrity: sha512-MruAPlM0uyiq3d53BkwTeShXY0rYEfhNGQzVO5GHBmmX3clsxcWp79mMnkOVcV244sNTeDcHbcPFWIjOI4tZvw==} + '@vitest/spy@0.32.0': dependencies: tinyspy: 2.1.0 - dev: true - /@vitest/utils@0.32.0: - resolution: {integrity: sha512-53yXunzx47MmbuvcOPpLaVljHaeSu1G2dHdmy7+9ngMnQIkBQcvwOcoclWFnxDMxFbnq8exAfh3aKSZaK71J5A==} + '@vitest/utils@0.32.0': dependencies: concordance: 5.0.4 loupe: 2.3.6 pretty-format: 27.5.1 - dev: true - /JSONStream@1.3.5: - resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} - hasBin: true + JSONStream@1.3.5: dependencies: jsonparse: 1.3.1 through: 2.3.8 - dev: false - /acorn-jsx@5.3.2(acorn@8.8.2): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-jsx@5.3.2(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + + acorn-jsx@5.3.2(acorn@8.8.2): dependencies: acorn: 8.8.2 - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true + acorn-walk@8.2.0: {} - /acorn@8.8.2: - resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} - engines: {node: '>=0.4.0'} - hasBin: true + acorn@8.12.1: {} - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + acorn@8.8.2: {} + + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} + ansi-regex@5.0.1: {} - /ansi-sequence-parser@1.1.0: - resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==} - dev: true + ansi-sequence-parser@1.1.0: {} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 - dev: false - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true + ansi-styles@5.2.0: {} - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + argparse@2.0.1: {} - /array-includes@3.1.6: - resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} - engines: {node: '>= 0.4'} + array-includes@3.1.6: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 es-abstract: 1.21.1 get-intrinsic: 1.1.3 is-string: 1.0.7 - dev: false - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: false + array-union@2.1.0: {} - /array.prototype.flat@1.3.1: - resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} - engines: {node: '>= 0.4'} + array.prototype.flat@1.3.1: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 es-abstract: 1.21.1 es-shim-unscopables: 1.0.0 - dev: false - /array.prototype.flatmap@1.3.1: - resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} - engines: {node: '>= 0.4'} + array.prototype.flatmap@1.3.1: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 es-abstract: 1.21.1 es-shim-unscopables: 1.0.0 - dev: false - /arrify@1.0.1: - resolution: {integrity: sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=} - engines: {node: '>=0.10.0'} - dev: false + arrify@1.0.1: {} - /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: true + assertion-error@1.1.0: {} - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: false + available-typed-arrays@1.0.5: {} - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@1.0.2: {} - /blueimp-md5@2.19.0: - resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} - dev: true + blueimp-md5@2.19.0: {} - /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: false + boolbase@1.0.0: {} - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.0.1 - dev: false - /buffer-crc32@0.2.13: - resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} - dev: false + buffer-crc32@0.2.13: {} - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer-from@1.1.2: {} - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: false + builtin-modules@3.3.0: {} - /builtins@5.0.1: - resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + builtins@5.0.1: dependencies: semver: 7.5.4 - dev: false - /bytebuffer@5.0.1: - resolution: {integrity: sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ==} - engines: {node: '>=0.8'} + bytebuffer@5.0.1: dependencies: long: 3.2.0 - dev: true - /c8@7.13.0: - resolution: {integrity: sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==} - engines: {node: '>=10.12.0'} - hasBin: true + c8@7.13.0: dependencies: '@bcoe/v8-coverage': 0.2.3 '@istanbuljs/schema': 0.1.3 @@ -1466,41 +3322,25 @@ packages: v8-to-istanbul: 9.1.0 yargs: 16.2.0 yargs-parser: 20.2.9 - dev: true - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true + cac@6.7.14: {} - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + call-bind@1.0.2: dependencies: function-bind: 1.1.1 get-intrinsic: 1.1.3 - dev: false - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} + callsites@3.1.0: {} - /camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} + camelcase-keys@6.2.2: dependencies: camelcase: 5.3.1 map-obj: 4.3.0 quick-lru: 4.0.1 - dev: false - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: false + camelcase@5.3.1: {} - /chai@4.3.7: - resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} - engines: {node: '>=4'} + chai@4.3.7: dependencies: assertion-error: 1.1.0 check-error: 1.0.2 @@ -1509,71 +3349,48 @@ packages: loupe: 2.3.6 pathval: 1.1.1 type-detect: 4.0.8 - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - dev: false - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - /check-error@1.0.2: - resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} - dev: true + check-error@1.0.2: {} - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@7.0.4: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@1.9.3: dependencies: color-name: 1.1.3 - dev: false - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - /color-name@1.1.3: - resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} - dev: false + color-name@1.1.3: {} - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-name@1.1.4: {} - /concat-map@0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + concat-map@0.0.1: {} - /concat-stream@2.0.0: - resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} - engines: {'0': node >= 6.0} + concat-stream@2.0.0: dependencies: buffer-from: 1.1.2 inherits: 2.0.4 readable-stream: 3.6.0 typedarray: 0.0.6 - dev: false - /concordance@5.0.4: - resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==} - engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'} + concordance@5.0.4: dependencies: date-time: 3.1.0 esutils: 2.0.3 @@ -1583,25 +3400,15 @@ packages: md5-hex: 3.0.1 semver: 7.5.4 well-known-symbols: 2.0.0 - dev: true - /conventional-changelog-preset-loader@2.3.4: - resolution: {integrity: sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==} - engines: {node: '>=10'} - dev: false + conventional-changelog-preset-loader@2.3.4: {} - /conventional-commits-filter@2.0.7: - resolution: {integrity: sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==} - engines: {node: '>=10'} + conventional-commits-filter@2.0.7: dependencies: lodash.ismatch: 4.4.0 modify-values: 1.0.1 - dev: false - /conventional-commits-parser@3.2.4: - resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==} - engines: {node: '>=10'} - hasBin: true + conventional-commits-parser@3.2.4: dependencies: JSONStream: 1.3.5 is-text-path: 1.0.1 @@ -1609,12 +3416,8 @@ packages: meow: 8.1.2 split2: 3.2.2 through2: 4.0.2 - dev: false - /conventional-recommended-bump@6.1.0: - resolution: {integrity: sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==} - engines: {node: '>=10'} - hasBin: true + conventional-recommended-bump@6.1.0: dependencies: concat-stream: 2.0.0 conventional-changelog-preset-loader: 2.3.4 @@ -1624,180 +3427,104 @@ packages: git-semver-tags: 4.1.1 meow: 8.1.2 q: 1.5.1 - dev: false - /convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: true + convert-source-map@1.9.0: {} - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: false + core-util-is@1.0.3: {} - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - /css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + css-select@5.1.0: dependencies: boolbase: 1.0.0 css-what: 6.1.0 domhandler: 5.0.3 domutils: 3.0.1 nth-check: 2.1.1 - dev: false - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: false + css-what@6.1.0: {} - /dargs@7.0.0: - resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} - engines: {node: '>=8'} - dev: false + dargs@7.0.0: {} - /date-time@3.1.0: - resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} - engines: {node: '>=6'} + date-time@3.1.0: dependencies: time-zone: 1.0.0 - dev: true - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@3.2.7: dependencies: ms: 2.1.2 - dev: false - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.3.4: dependencies: ms: 2.1.2 - /decamelize-keys@1.1.0: - resolution: {integrity: sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=} - engines: {node: '>=0.10.0'} + decamelize-keys@1.1.0: dependencies: decamelize: 1.2.0 map-obj: 1.0.1 - dev: false - /decamelize@1.2.0: - resolution: {integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=} - engines: {node: '>=0.10.0'} - dev: false + decamelize@1.2.0: {} - /deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} + deep-eql@4.1.3: dependencies: type-detect: 4.0.8 - dev: true - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deep-is@0.1.4: {} - /default-gateway@6.0.3: - resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} - engines: {node: '>= 10'} + default-gateway@6.0.3: dependencies: execa: 5.1.1 - dev: false - /define-properties@1.1.4: - resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} - engines: {node: '>= 0.4'} + define-properties@1.1.4: dependencies: has-property-descriptors: 1.0.0 object-keys: 1.1.1 - dev: false - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 - dev: false - /discord-api-types@0.37.39: - resolution: {integrity: sha512-hkhQsQyzsTJITp311WXvHZh9j4RAMfIk2hPmsWeOTN50QTpg6zqmJNfel9D/8lYNvsU01wzw9281Yke8NhYyHg==} - dev: false + discord-api-types@0.37.39: {} - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} + doctrine@2.1.0: dependencies: esutils: 2.0.3 - dev: false - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} + doctrine@3.0.0: dependencies: esutils: 2.0.3 - /dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 entities: 4.4.0 - dev: false - /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: false + domelementtype@2.3.0: {} - /domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} + domhandler@5.0.3: dependencies: domelementtype: 2.3.0 - dev: false - /domutils@3.0.1: - resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==} + domutils@3.0.1: dependencies: dom-serializer: 2.0.0 domelementtype: 2.3.0 domhandler: 5.0.3 - dev: false - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true + emoji-regex@8.0.0: {} - /entities@4.4.0: - resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} - engines: {node: '>=0.12'} - dev: false + entities@4.4.0: {} - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - dev: false - /es-abstract@1.21.1: - resolution: {integrity: sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==} - engines: {node: '>= 0.4'} + es-abstract@1.21.1: dependencies: available-typed-arrays: 1.0.5 call-bind: 1.0.2 @@ -1832,37 +3559,24 @@ packages: typed-array-length: 1.0.4 unbox-primitive: 1.0.2 which-typed-array: 1.1.9 - dev: false - /es-set-tostringtag@2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} - engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.1: dependencies: get-intrinsic: 1.1.3 has: 1.0.3 has-tostringtag: 1.0.0 - dev: false - /es-shim-unscopables@1.0.0: - resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + es-shim-unscopables@1.0.0: dependencies: has: 1.0.3 - dev: false - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} + es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 is-date-object: 1.0.5 is-symbol: 1.0.4 - dev: false - /esbuild@0.17.16: - resolution: {integrity: sha512-aeSuUKr9aFVY9Dc8ETVELGgkj4urg5isYx8pLf4wlGgB0vTFjxJQdHnNH6Shmx4vYYrOTLCHtRI5i1XZ9l2Zcg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + esbuild@0.17.16: optionalDependencies: '@esbuild/android-arm': 0.17.16 '@esbuild/android-arm64': 0.17.16 @@ -1886,116 +3600,85 @@ packages: '@esbuild/win32-arm64': 0.17.16 '@esbuild/win32-ia32': 0.17.16 '@esbuild/win32-x64': 0.17.16 - dev: true - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} - engines: {node: '>=0.8.0'} - dev: false - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - /eslint-compat-utils@0.1.2(eslint@8.38.0): - resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==} - engines: {node: '>=12'} - peerDependencies: - eslint: '>=6.0.0' - dependencies: - eslint: 8.38.0 - dev: false - - /eslint-config-standard@17.1.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@16.3.1)(eslint-plugin-promise@6.1.1)(eslint@8.38.0): - resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==} - engines: {node: '>=12.0.0'} - peerDependencies: - eslint: ^8.0.1 - eslint-plugin-import: ^2.25.2 - eslint-plugin-n: '^15.0.0 || ^16.0.0 ' - eslint-plugin-promise: ^6.0.0 - dependencies: - eslint: 8.38.0 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@6.13.2)(eslint@8.38.0) - eslint-plugin-n: 16.3.1(eslint@8.38.0) - eslint-plugin-promise: 6.1.1(eslint@8.38.0) - dev: false - /eslint-import-resolver-node@0.3.7: - resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} + esbuild@0.19.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + + escalade@3.1.1: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-compat-utils@0.1.2(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + + eslint-config-standard@17.1.0(eslint-plugin-import@2.27.5(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint-plugin-n@16.3.1(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0) + eslint-plugin-n: 16.3.1(eslint@8.57.0) + eslint-plugin-promise: 6.1.1(eslint@8.57.0) + + eslint-import-resolver-node@0.3.7: dependencies: debug: 3.2.7 is-core-module: 2.11.0 resolve: 1.22.1 transitivePeerDependencies: - supports-color - dev: false - /eslint-module-utils@2.7.4(@typescript-eslint/parser@6.13.2)(eslint-import-resolver-node@0.3.7)(eslint@8.38.0): - resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true + eslint-module-utils@2.7.4(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.7)(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 6.13.2(eslint@8.38.0)(typescript@5.2.2) debug: 3.2.7 - eslint: 8.38.0 + optionalDependencies: + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.3.3) + eslint: 8.57.0 eslint-import-resolver-node: 0.3.7 transitivePeerDependencies: - supports-color - dev: false - /eslint-plugin-es-x@7.5.0(eslint@8.38.0): - resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '>=8' + eslint-plugin-es-x@7.5.0(eslint@8.57.0): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.38.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@eslint-community/regexpp': 4.10.0 - eslint: 8.38.0 - eslint-compat-utils: 0.1.2(eslint@8.38.0) - dev: false + eslint: 8.57.0 + eslint-compat-utils: 0.1.2(eslint@8.57.0) - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.13.2)(eslint@8.38.0): - resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true + eslint-plugin-import@2.27.5(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 6.13.2(eslint@8.38.0)(typescript@5.2.2) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.38.0 + eslint: 8.57.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4(@typescript-eslint/parser@6.13.2)(eslint-import-resolver-node@0.3.7)(eslint@8.38.0) + eslint-module-utils: 2.7.4(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.7)(eslint@8.57.0) has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 @@ -2004,22 +3687,19 @@ packages: resolve: 1.22.1 semver: 6.3.0 tsconfig-paths: 3.14.1 + optionalDependencies: + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.3.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - dev: false - /eslint-plugin-n@16.3.1(eslint@8.38.0): - resolution: {integrity: sha512-w46eDIkxQ2FaTHcey7G40eD+FhTXOdKudDXPUO2n9WNcslze/i/HT2qJ3GXjHngYSGDISIgPNhwGtgoix4zeOw==} - engines: {node: '>=16.0.0'} - peerDependencies: - eslint: '>=7.0.0' + eslint-plugin-n@16.3.1(eslint@8.57.0): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.38.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) builtins: 5.0.1 - eslint: 8.38.0 - eslint-plugin-es-x: 7.5.0(eslint@8.38.0) + eslint: 8.57.0 + eslint-plugin-es-x: 7.5.0(eslint@8.57.0) get-tsconfig: 4.7.2 ignore: 5.2.4 is-builtin-module: 3.2.1 @@ -2027,37 +3707,26 @@ packages: minimatch: 3.1.2 resolve: 1.22.8 semver: 7.5.4 - dev: false - /eslint-plugin-promise@6.1.1(eslint@8.38.0): - resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint-plugin-promise@6.1.1(eslint@8.57.0): dependencies: - eslint: 8.38.0 - dev: false + eslint: 8.57.0 - /eslint-scope@7.1.1: - resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@7.1.1: dependencies: esrecurse: 4.3.0 estraverse: 5.2.0 - /eslint-visitor-keys@3.4.0: - resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.2.0 - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: false + eslint-visitor-keys@3.4.0: {} - /eslint@8.38.0: - resolution: {integrity: sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true + eslint-visitor-keys@3.4.3: {} + + eslint@8.38.0: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.38.0) '@eslint-community/regexpp': 4.5.0 @@ -2102,37 +3771,74 @@ packages: transitivePeerDependencies: - supports-color - /espree@9.5.1: - resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint@8.57.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.20.0 + graphemer: 1.4.0 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@9.5.1: dependencies: acorn: 8.8.2 acorn-jsx: 5.3.2(acorn@8.8.2) eslint-visitor-keys: 3.4.0 - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} + espree@9.6.1: + dependencies: + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) + eslint-visitor-keys: 3.4.3 + + esquery@1.5.0: dependencies: estraverse: 5.2.0 - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} + esrecurse@4.3.0: dependencies: estraverse: 5.2.0 - /estraverse@5.2.0: - resolution: {integrity: sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==} - engines: {node: '>=4.0'} + estraverse@5.2.0: {} - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} + esutils@2.0.3: {} - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} + execa@5.1.1: dependencies: cross-spawn: 7.0.3 get-stream: 6.0.1 @@ -2143,209 +3849,132 @@ packages: onetime: 5.1.2 signal-exit: 3.0.5 strip-final-newline: 2.0.0 - dev: false - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-deep-equal@3.1.3: {} - /fast-diff@1.2.0: - resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} - dev: true + fast-diff@1.2.0: {} - /fast-glob@3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} + fast-glob@3.2.12: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.4 - dev: false - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fast-json-stable-stringify@2.1.0: {} - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-levenshtein@2.0.6: {} - /fast-xml-parser@4.3.2: - resolution: {integrity: sha512-rmrXUXwbJedoXkStenj1kkljNF7ugn5ZjR9FJcwmCfcCbtOMDghPajbc+Tck6vE6F5XsDmx+Pr2le9fw8+pXBg==} - hasBin: true + fast-xml-parser@4.3.2: dependencies: strnum: 1.0.5 - dev: false - /fastq@1.13.0: - resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + fastq@1.13.0: dependencies: reusify: 1.0.4 - /fd-slicer@1.1.0: - resolution: {integrity: sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=} + fd-slicer@1.1.0: dependencies: pend: 1.2.0 - dev: false - /fflate@0.6.10: - resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==} - dev: false + fflate@0.6.10: {} - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.0.4 - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 - dev: false - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + find-up@4.1.0: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - dev: false - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - /flat-cache@3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@3.0.4: dependencies: flatted: 3.2.2 rimraf: 3.0.2 - /flatted@3.2.2: - resolution: {integrity: sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==} + flatted@3.2.2: {} - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + for-each@0.3.3: dependencies: is-callable: 1.2.7 - dev: false - /foreground-child@2.0.0: - resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} - engines: {node: '>=8.0.0'} + foreground-child@2.0.0: dependencies: cross-spawn: 7.0.3 signal-exit: 3.0.5 - dev: true - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fs.realpath@1.0.0: {} - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true + fsevents@2.3.3: optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: false + function-bind@1.1.1: {} - /function.prototype.name@1.1.5: - resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} - engines: {node: '>= 0.4'} + function-bind@1.1.2: {} + + function.prototype.name@1.1.5: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 es-abstract: 1.21.1 functions-have-names: 1.2.3 - dev: false - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: false + functions-have-names@1.2.3: {} - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true + get-caller-file@2.0.5: {} - /get-func-name@2.0.0: - resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} - dev: true + get-func-name@2.0.0: {} - /get-intrinsic@1.1.3: - resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} + get-intrinsic@1.1.3: dependencies: function-bind: 1.1.1 has: 1.0.3 has-symbols: 1.0.3 - dev: false - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: false + get-stream@6.0.1: {} - /get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} + get-symbol-description@1.0.0: dependencies: call-bind: 1.0.2 get-intrinsic: 1.1.3 - dev: false - /get-tsconfig@4.7.2: - resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + get-tsconfig@4.7.2: dependencies: resolve-pkg-maps: 1.0.0 - /git-raw-commits@2.0.10: - resolution: {integrity: sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==} - engines: {node: '>=10'} - hasBin: true + git-raw-commits@2.0.10: dependencies: dargs: 7.0.0 lodash: 4.17.21 meow: 8.1.2 split2: 3.2.2 through2: 4.0.2 - dev: false - /git-semver-tags@4.1.1: - resolution: {integrity: sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==} - engines: {node: '>=10'} - hasBin: true + git-semver-tags@4.1.1: dependencies: meow: 8.1.2 semver: 6.3.0 - dev: false - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: false - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - /glob@7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + glob@7.2.0: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -2354,22 +3983,15 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 - /globals@13.20.0: - resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} - engines: {node: '>=8'} + globals@13.20.0: dependencies: type-fest: 0.20.2 - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} + globalthis@1.0.3: dependencies: define-properties: 1.1.4 - dev: false - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 @@ -2377,497 +3999,285 @@ packages: ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 - dev: false - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.0.1: dependencies: get-intrinsic: 1.1.3 - dev: false - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + grapheme-splitter@1.0.4: {} - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: false + graphemer@1.4.0: {} - /hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: false + hard-rejection@2.1.0: {} - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: false + has-bigints@1.0.2: {} - /has-flag@3.0.0: - resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} - engines: {node: '>=4'} - dev: false + has-flag@3.0.0: {} - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} + has-flag@4.0.0: {} - /has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + has-property-descriptors@1.0.0: dependencies: get-intrinsic: 1.1.3 - dev: false - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: false + has-proto@1.0.1: {} - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: false + has-symbols@1.0.3: {} - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} + has-tostringtag@1.0.0: dependencies: has-symbols: 1.0.3 - dev: false - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} + has@1.0.3: dependencies: function-bind: 1.1.1 - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} + hasown@2.0.0: dependencies: function-bind: 1.1.2 - dev: false - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: false + he@1.2.0: {} - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: false + hosted-git-info@2.8.9: {} - /hosted-git-info@4.0.2: - resolution: {integrity: sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==} - engines: {node: '>=10'} + hosted-git-info@4.0.2: dependencies: lru-cache: 6.0.0 - dev: false - /html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true + html-escaper@2.0.2: {} - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: false + http-cache-semantics@4.1.1: {} - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: false + human-signals@2.1.0: {} - /ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} + ignore@5.2.4: {} - /immediate@3.0.6: - resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} - dev: false + ignore@5.3.1: {} - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} + immediate@3.0.6: {} + + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} + imurmurhash@0.1.4: {} - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: false + indent-string@4.0.0: {} - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + inflight@1.0.6: dependencies: once: 1.4.0 wrappy: 1.0.2 - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inherits@2.0.4: {} - /internal-slot@1.0.4: - resolution: {integrity: sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==} - engines: {node: '>= 0.4'} + internal-slot@1.0.4: dependencies: get-intrinsic: 1.1.3 has: 1.0.3 side-channel: 1.0.4 - dev: false - /is-array-buffer@3.0.1: - resolution: {integrity: sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==} + is-array-buffer@3.0.1: dependencies: call-bind: 1.0.2 get-intrinsic: 1.1.3 is-typed-array: 1.1.10 - dev: false - /is-arrayish@0.2.1: - resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} - dev: false + is-arrayish@0.2.1: {} - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 - dev: false - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} + is-boolean-object@1.1.2: dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 - dev: false - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} + is-builtin-module@3.2.1: dependencies: builtin-modules: 3.3.0 - dev: false - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: false + is-callable@1.2.7: {} - /is-core-module@2.11.0: - resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + is-core-module@2.11.0: dependencies: has: 1.0.3 - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + is-core-module@2.13.1: dependencies: hasown: 2.0.0 - dev: false - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} + is-date-object@1.0.5: dependencies: has-tostringtag: 1.0.0 - dev: false - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + is-extglob@2.1.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true + is-fullwidth-code-point@3.0.0: {} - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: false + is-negative-zero@2.0.2: {} - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} + is-number-object@1.0.7: dependencies: has-tostringtag: 1.0.0 - dev: false - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: false + is-number@7.0.0: {} - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} + is-path-inside@3.0.3: {} - /is-plain-obj@1.1.0: - resolution: {integrity: sha1-caUMhCnfync8kqOQpKA7OfzVHT4=} - engines: {node: '>=0.10.0'} - dev: false + is-plain-obj@1.1.0: {} - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} + is-regex@1.1.4: dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 - dev: false - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + is-shared-array-buffer@1.0.2: dependencies: call-bind: 1.0.2 - dev: false - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: false + is-stream@2.0.1: {} - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.0 - dev: false - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} + is-symbol@1.0.4: dependencies: has-symbols: 1.0.3 - dev: false - /is-text-path@1.0.1: - resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} - engines: {node: '>=0.10.0'} + is-text-path@1.0.1: dependencies: text-extensions: 1.9.0 - dev: false - /is-typed-array@1.1.10: - resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} - engines: {node: '>= 0.4'} + is-typed-array@1.1.10: dependencies: available-typed-arrays: 1.0.5 call-bind: 1.0.2 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.0 - dev: false - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + is-weakref@1.0.2: dependencies: call-bind: 1.0.2 - dev: false - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: false + isarray@1.0.0: {} - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isexe@2.0.0: {} - /istanbul-lib-coverage@3.2.0: - resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} - engines: {node: '>=8'} - dev: true + istanbul-lib-coverage@3.2.0: {} - /istanbul-lib-report@3.0.0: - resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} - engines: {node: '>=8'} + istanbul-lib-report@3.0.0: dependencies: istanbul-lib-coverage: 3.2.0 make-dir: 3.1.0 supports-color: 7.2.0 - dev: true - /istanbul-reports@3.1.5: - resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} - engines: {node: '>=8'} + istanbul-reports@3.1.5: dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.0 - dev: true - /js-sdsl@4.4.0: - resolution: {integrity: sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==} + js-sdsl@4.4.0: {} - /js-string-escape@1.0.1: - resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} - engines: {node: '>= 0.8'} - dev: true + js-string-escape@1.0.1: {} - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: false + js-tokens@4.0.0: {} - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true + js-yaml@4.1.0: dependencies: argparse: 2.0.1 - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: false + json-parse-even-better-errors@2.3.1: {} - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@0.4.1: {} - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json-stable-stringify-without-jsonify@1.0.1: {} - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true + json5@1.0.2: dependencies: minimist: 1.2.7 - dev: false - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: true + jsonc-parser@3.2.0: {} - /jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - dev: false + jsonparse@1.3.1: {} - /jszip@3.10.1: - resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + jszip@3.10.1: dependencies: lie: 3.3.0 pako: 1.0.11 readable-stream: 2.3.7 setimmediate: 1.0.5 - dev: false - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: false + kind-of@6.0.3: {} - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - /lie@3.3.0: - resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lie@3.3.0: dependencies: immediate: 3.0.6 - dev: false - /lil-gui@0.17.0: - resolution: {integrity: sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==} - dev: false + lil-gui@0.17.0: {} - /lines-and-columns@1.1.6: - resolution: {integrity: sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=} - dev: false + lines-and-columns@1.1.6: {} - /local-pkg@0.4.3: - resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} - engines: {node: '>=14'} - dev: true + local-pkg@0.4.3: {} - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 - dev: false - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 - /lodash.ismatch@4.4.0: - resolution: {integrity: sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=} - dev: false + lodash.ismatch@4.4.0: {} - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.merge@4.6.2: {} - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.17.21: {} - /long@3.2.0: - resolution: {integrity: sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==} - engines: {node: '>=0.6'} - dev: true + long@3.2.0: {} - /loupe@2.3.6: - resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + loupe@2.3.6: dependencies: get-func-name: 2.0.0 - dev: true - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} + lru-cache@6.0.0: dependencies: yallist: 4.0.0 - /lunr@2.3.9: - resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} - dev: true + lunr@2.3.9: {} - /magic-string@0.30.0: - resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} - engines: {node: '>=12'} + magic-string@0.30.0: dependencies: '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} + make-dir@3.1.0: dependencies: semver: 6.3.0 - dev: true - /map-obj@1.0.1: - resolution: {integrity: sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=} - engines: {node: '>=0.10.0'} - dev: false + map-obj@1.0.1: {} - /map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: false + map-obj@4.3.0: {} - /marked@4.3.0: - resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} - engines: {node: '>= 12'} - hasBin: true - dev: true + marked@4.3.0: {} - /md5-hex@3.0.1: - resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==} - engines: {node: '>=8'} + md5-hex@3.0.1: dependencies: blueimp-md5: 2.19.0 - dev: true - /meow@8.1.2: - resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} - engines: {node: '>=10'} + meow@8.1.2: dependencies: '@types/minimist': 1.2.2 camelcase-keys: 6.2.2 @@ -2880,168 +4290,108 @@ packages: trim-newlines: 3.0.1 type-fest: 0.18.1 yargs-parser: 20.2.9 - dev: false - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: false + merge-stream@2.0.0: {} - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: false + merge2@1.4.1: {} - /micromatch@4.0.4: - resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==} - engines: {node: '>=8.6'} + micromatch@4.0.4: dependencies: braces: 3.0.2 picomatch: 2.3.0 - dev: false - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: false + mimic-fn@2.1.0: {} - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: false + min-indent@1.0.1: {} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - /minimatch@9.0.1: - resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.3: dependencies: brace-expansion: 2.0.1 - dev: true - /minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist-options@4.1.0: dependencies: arrify: 1.0.1 is-plain-obj: 1.1.0 kind-of: 6.0.3 - dev: false - /minimist@1.2.7: - resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} - dev: false + minimist@1.2.7: {} - /mlly@1.2.0: - resolution: {integrity: sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==} + mlly@1.2.0: dependencies: acorn: 8.8.2 pathe: 1.1.0 pkg-types: 1.0.2 ufo: 1.1.1 - dev: true - /modify-values@1.0.1: - resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} - engines: {node: '>=0.10.0'} - dev: false + modify-values@1.0.1: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.2: {} - /nanoid@3.3.6: - resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true + nanoid@3.3.6: {} - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + natural-compare@1.4.0: {} - /node-html-parser@6.1.5: - resolution: {integrity: sha512-fAaM511feX++/Chnhe475a0NHD8M7AxDInsqQpz6x63GRF7xYNdS8Vo5dKsIVPgsOvG7eioRRTZQnWBrhDHBSg==} + node-html-parser@6.1.5: dependencies: css-select: 5.1.0 he: 1.2.0 - dev: false - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 resolve: 1.22.8 semver: 5.7.1 validate-npm-package-license: 3.0.4 - dev: false - /normalize-package-data@3.0.3: - resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} - engines: {node: '>=10'} + normalize-package-data@3.0.3: dependencies: hosted-git-info: 4.0.2 is-core-module: 2.13.1 semver: 7.5.4 validate-npm-package-license: 3.0.4 - dev: false - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} + npm-run-path@4.0.1: dependencies: path-key: 3.1.1 - dev: false - /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + nth-check@2.1.1: dependencies: boolbase: 1.0.0 - dev: false - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: false + object-inspect@1.12.3: {} - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: false + object-keys@1.1.1: {} - /object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} + object.assign@4.1.4: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 has-symbols: 1.0.3 object-keys: 1.1.1 - dev: false - /object.values@1.1.6: - resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} - engines: {node: '>= 0.4'} + object.values@1.1.6: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 es-abstract: 1.21.1 - dev: false - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + once@1.4.0: dependencies: wrappy: 1.0.2 - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 - dev: false - /optionator@0.9.1: - resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} - engines: {node: '>= 0.8.0'} + optionator@0.9.1: dependencies: deep-is: 0.1.4 fast-levenshtein: 2.0.6 @@ -3050,185 +4400,118 @@ packages: type-check: 0.4.0 word-wrap: 1.2.3 - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@2.3.0: dependencies: p-try: 2.2.0 - dev: false - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - /p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-limit@4.0.0: dependencies: yocto-queue: 1.0.0 - dev: true - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-locate@4.1.0: dependencies: p-limit: 2.3.0 - dev: false - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + p-locate@5.0.0: dependencies: p-limit: 3.1.0 - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: false + p-try@2.2.0: {} - /pako@1.0.11: - resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - dev: false + pako@1.0.11: {} - /pako@2.1.0: - resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} - dev: false + pako@2.1.0: {} - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + parent-module@1.0.1: dependencies: callsites: 3.1.0 - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.15.8 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.1.6 - dev: false - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} + path-exists@4.0.0: {} - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} + path-is-absolute@1.0.1: {} - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} + path-key@3.1.1: {} - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-parse@1.0.7: {} - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: false + path-type@4.0.0: {} - /pathe@1.1.0: - resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} - dev: true + pathe@1.1.0: {} - /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: true + pathval@1.1.1: {} - /pend@1.2.0: - resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=} - dev: false + pend@1.2.0: {} - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true + picocolors@1.0.0: {} - /picomatch@2.3.0: - resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==} - engines: {node: '>=8.6'} - dev: false + picomatch@2.3.0: {} - /pkg-types@1.0.2: - resolution: {integrity: sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==} + pkg-types@1.0.2: dependencies: jsonc-parser: 3.2.0 mlly: 1.2.0 pathe: 1.1.0 - dev: true - /postcss@8.4.21: - resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} - engines: {node: ^10 || ^12 || >=14} + postcss@8.4.21: dependencies: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} + prelude-ls@1.2.1: {} - /pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 ansi-styles: 5.2.0 react-is: 17.0.2 - dev: true - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: false + process-nextick-args@2.0.1: {} - /punycode@2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} - engines: {node: '>=6'} + punycode@2.1.1: {} - /q@1.5.1: - resolution: {integrity: sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=} - engines: {node: '>=0.6.0', teleport: '>=0.2.0'} - dev: false + q@1.5.1: {} - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + queue-microtask@1.2.3: {} - /quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: false + quick-lru@4.0.1: {} - /react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - dev: true + react-is@17.0.2: {} - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} + read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 read-pkg: 5.2.0 type-fest: 0.8.1 - dev: false - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} + read-pkg@5.2.0: dependencies: '@types/normalize-package-data': 2.4.1 normalize-package-data: 2.5.0 parse-json: 5.2.0 type-fest: 0.6.0 - dev: false - /readable-stream@2.3.7: - resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + readable-stream@2.3.7: dependencies: core-util-is: 1.0.3 inherits: 2.0.4 @@ -3237,530 +4520,313 @@ packages: safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 - dev: false - /readable-stream@3.6.0: - resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} - engines: {node: '>= 6'} + readable-stream@3.6.0: dependencies: inherits: 2.0.4 string_decoder: 1.1.1 util-deprecate: 1.0.2 - dev: false - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} + redent@3.0.0: dependencies: indent-string: 4.0.0 strip-indent: 3.0.0 - dev: false - /regexp.prototype.flags@1.4.3: - resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} - engines: {node: '>= 0.4'} + regexp.prototype.flags@1.4.3: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 functions-have-names: 1.2.3 - dev: false - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true + require-directory@2.1.1: {} - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} + resolve-from@4.0.0: {} - /resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve-pkg-maps@1.0.0: {} - /resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} - hasBin: true + resolve@1.22.1: dependencies: is-core-module: 2.11.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true + resolve@1.22.8: dependencies: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: false - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + reusify@1.0.4: {} - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true + rimraf@3.0.2: dependencies: glob: 7.2.0 - /rollup@3.20.2: - resolution: {integrity: sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true + rollup@3.20.2: optionalDependencies: - fsevents: 2.3.2 - dev: true + fsevents: 2.3.3 - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: false + safe-buffer@5.1.2: {} - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + safe-regex-test@1.0.0: dependencies: call-bind: 1.0.2 get-intrinsic: 1.1.3 is-regex: 1.1.4 - dev: false - /semver@5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true - dev: false + semver@5.7.1: {} - /semver@6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true + semver@6.3.0: {} - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true + semver@7.5.4: dependencies: lru-cache: 6.0.0 - /setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - dev: false + semver@7.6.2: {} - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + setimmediate@1.0.5: {} + + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} + shebang-regex@3.0.0: {} - /shiki@0.14.1: - resolution: {integrity: sha512-+Jz4nBkCBe0mEDqo1eKRcCdjRtrCjozmcbTUjbPTX7OOJfEbTZzlUWlZtGe3Gb5oV1/jnojhG//YZc3rs9zSEw==} + shiki@0.14.7: dependencies: ansi-sequence-parser: 1.1.0 jsonc-parser: 3.2.0 vscode-oniguruma: 1.7.0 vscode-textmate: 8.0.0 - dev: true - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + side-channel@1.0.4: dependencies: call-bind: 1.0.2 get-intrinsic: 1.1.3 object-inspect: 1.12.3 - dev: false - /siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - dev: true + siginfo@2.0.0: {} - /signal-exit@3.0.5: - resolution: {integrity: sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==} + signal-exit@3.0.5: {} - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: false + slash@3.0.0: {} - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: true + source-map-js@1.0.2: {} - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: true - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true + source-map@0.6.1: {} - /spdx-correct@3.1.1: - resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + spdx-correct@3.1.1: dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.10 - dev: false - /spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: false + spdx-exceptions@2.3.0: {} - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.3.0 spdx-license-ids: 3.0.10 - dev: false - /spdx-license-ids@3.0.10: - resolution: {integrity: sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==} - dev: false + spdx-license-ids@3.0.10: {} - /split2@3.2.2: - resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + split2@3.2.2: dependencies: readable-stream: 3.6.0 - dev: false - /stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - dev: true + stackback@0.0.2: {} - /std-env@3.3.2: - resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} - dev: true + std-env@3.3.2: {} - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true - /string.prototype.trimend@1.0.6: - resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + string.prototype.trimend@1.0.6: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 es-abstract: 1.21.1 - dev: false - /string.prototype.trimstart@1.0.6: - resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + string.prototype.trimstart@1.0.6: dependencies: call-bind: 1.0.2 define-properties: 1.1.4 es-abstract: 1.21.1 - dev: false - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 - dev: false - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: false + strip-bom@3.0.0: {} - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: false + strip-final-newline@2.0.0: {} - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 - dev: false - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} + strip-json-comments@3.1.1: {} - /strip-literal@1.0.1: - resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} + strip-literal@1.0.1: dependencies: acorn: 8.8.2 - dev: true - /strnum@1.0.5: - resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} - dev: false + strnum@1.0.5: {} - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 - dev: false - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} + supports-preserve-symlinks-flag@1.0.0: {} - /test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} + test-exclude@6.0.0: dependencies: '@istanbuljs/schema': 0.1.3 glob: 7.2.0 minimatch: 3.1.2 - dev: true - /text-extensions@1.9.0: - resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} - engines: {node: '>=0.10'} - dev: false + text-extensions@1.9.0: {} - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + text-table@0.2.0: {} - /three@0.151.3: - resolution: {integrity: sha512-+vbuqxFy8kzLeO5MgpBHUvP/EAiecaDwDuOPPDe6SbrZr96kccF0ktLngXc7xA7bzyd3N0t2f6mw3Z9y6JCojQ==} - dev: false + three@0.156.1: {} - /through2@4.0.2: - resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + through2@4.0.2: dependencies: readable-stream: 3.6.0 - dev: false - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: false + through@2.3.8: {} - /time-zone@1.0.0: - resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} - engines: {node: '>=4'} - dev: true + time-zone@1.0.0: {} - /tinybench@2.5.0: - resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} - dev: true + tinybench@2.5.0: {} - /tinypool@0.5.0: - resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==} - engines: {node: '>=14.0.0'} - dev: true + tinypool@0.5.0: {} - /tinyspy@2.1.0: - resolution: {integrity: sha512-7eORpyqImoOvkQJCSkL0d0mB4NHHIFAy4b1u8PHdDa7SjGS2njzl6/lyGoZLm+eyYEtlUmFGE0rFj66SWxZgQQ==} - engines: {node: '>=14.0.0'} - dev: true + tinyspy@2.1.0: {} - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: false - /toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - dev: false + toml@3.0.0: {} - /trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: false + trim-newlines@3.0.1: {} - /ts-api-utils@1.0.3(typescript@5.2.2): - resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} - engines: {node: '>=16.13.0'} - peerDependencies: - typescript: '>=4.2.0' + ts-api-utils@1.3.0(typescript@5.3.3): dependencies: - typescript: 5.2.2 - dev: false + typescript: 5.3.3 - /tsconfig-paths@3.14.1: - resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} + tsconfig-paths@3.14.1: dependencies: '@types/json5': 0.0.29 json5: 1.0.2 minimist: 1.2.7 strip-bom: 3.0.0 - dev: false - /tslib@2.5.0: - resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - dev: true + tslib@2.5.0: {} - /tsx@3.12.6: - resolution: {integrity: sha512-q93WgS3lBdHlPgS0h1i+87Pt6n9K/qULIMNYZo07nSeu2z5QE2CellcAZfofVXBo2tQg9av2ZcRMQ2S2i5oadQ==} - hasBin: true + tsx@3.12.6: dependencies: '@esbuild-kit/cjs-loader': 2.4.2 '@esbuild-kit/core-utils': 3.1.0 '@esbuild-kit/esm-loader': 2.5.5 optionalDependencies: - fsevents: 2.3.2 - dev: true + fsevents: 2.3.3 - /tunnel@0.0.6: - resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} - engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - dev: true + tsx@4.7.1: + dependencies: + esbuild: 0.19.12 + get-tsconfig: 4.7.2 + optionalDependencies: + fsevents: 2.3.3 - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + tunnel@0.0.6: {} + + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true + type-detect@4.0.8: {} - /type-fest@0.18.1: - resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} - engines: {node: '>=10'} - dev: false + type-fest@0.18.1: {} - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} + type-fest@0.20.2: {} - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: false + type-fest@0.6.0: {} - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: false + type-fest@0.8.1: {} - /typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + typed-array-length@1.0.4: dependencies: call-bind: 1.0.2 for-each: 0.3.3 is-typed-array: 1.1.10 - dev: false - /typedarray@0.0.6: - resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} - dev: false + typedarray@0.0.6: {} - /typedoc@0.24.8(typescript@5.0.4): - resolution: {integrity: sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==} - engines: {node: '>= 14.14'} - hasBin: true - peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x + typedoc@0.25.8(typescript@5.3.3): dependencies: lunr: 2.3.9 marked: 4.3.0 - minimatch: 9.0.1 - shiki: 0.14.1 - typescript: 5.0.4 - dev: true - - /typescript@5.0.4: - resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} - engines: {node: '>=12.20'} - hasBin: true - dev: true + minimatch: 9.0.3 + shiki: 0.14.7 + typescript: 5.3.3 - /typescript@5.2.2: - resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} - engines: {node: '>=14.17'} - hasBin: true + typescript@5.3.3: {} - /ufo@1.1.1: - resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==} - dev: true + ufo@1.1.1: {} - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.0.2: dependencies: call-bind: 1.0.2 has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - dev: false - /undici@4.1.0: - resolution: {integrity: sha512-Y1e/pSDLtNT4nXSQc4C7eiqoiV7pq8QmsvD7/6cbUuUER0MewR3xwBswYiHYWqVI4FcUptjHixrdqW4xrmo4uA==} - engines: {node: '>=12.18'} - dev: false + undici@6.14.0: {} - /undici@6.0.1: - resolution: {integrity: sha512-eZFYQLeS9BiXpsU0cuFhCwfeda2MnC48EVmmOz/eCjsTgmyTdaHdVsPSC/kwC2GtW2e0uH0HIPbadf3/bRWSxw==} - engines: {node: '>=18.0'} - dependencies: - '@fastify/busboy': 2.1.0 - dev: false - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + uri-js@4.4.1: dependencies: punycode: 2.1.1 - /util-deprecate@1.0.2: - resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} - dev: false + util-deprecate@1.0.2: {} - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: true + uuid@8.3.2: {} - /uuid@9.0.0: - resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} - hasBin: true - dev: false + uuid@9.0.0: {} - /v8-to-istanbul@9.1.0: - resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} - engines: {node: '>=10.12.0'} + v8-to-istanbul@9.1.0: dependencies: '@jridgewell/trace-mapping': 0.3.18 '@types/istanbul-lib-coverage': 2.0.4 convert-source-map: 1.9.0 - dev: true - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.1.1 spdx-expression-parse: 3.0.1 - dev: false - /vite-node@0.32.0(@types/node@18.15.11): - resolution: {integrity: sha512-220P/y8YacYAU+daOAqiGEFXx2A8AwjadDzQqos6wSukjvvTWNqleJSwoUn0ckyNdjHIKoxn93Nh1vWBqEKr3Q==} - engines: {node: '>=v14.18.0'} - hasBin: true + vite-node@0.32.0(@types/node@18.15.11): dependencies: cac: 6.7.14 debug: 4.3.4 @@ -3776,72 +4842,18 @@ packages: - sugarss - supports-color - terser - dev: true - /vite@4.2.1(@types/node@18.15.11): - resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true + vite@4.2.1(@types/node@18.15.11): dependencies: - '@types/node': 18.15.11 esbuild: 0.17.16 postcss: 8.4.21 resolve: 1.22.1 rollup: 3.20.2 optionalDependencies: - fsevents: 2.3.2 - dev: true + '@types/node': 18.15.11 + fsevents: 2.3.3 - /vitest@0.32.0: - resolution: {integrity: sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==} - engines: {node: '>=v14.18.0'} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' - happy-dom: '*' - jsdom: '*' - playwright: '*' - safaridriver: '*' - webdriverio: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - playwright: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true + vitest@0.32.0: dependencies: '@types/chai': 4.3.5 '@types/chai-subset': 1.3.3 @@ -3875,34 +4887,22 @@ packages: - sugarss - supports-color - terser - dev: true - /vscode-oniguruma@1.7.0: - resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} - dev: true + vscode-oniguruma@1.7.0: {} - /vscode-textmate@8.0.0: - resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} - dev: true + vscode-textmate@8.0.0: {} - /well-known-symbols@2.0.0: - resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==} - engines: {node: '>=6'} - dev: true + well-known-symbols@2.0.0: {} - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 is-boolean-object: 1.1.2 is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.4 - dev: false - /which-typed-array@1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} - engines: {node: '>= 0.4'} + which-typed-array@1.1.9: dependencies: available-typed-arrays: 1.0.5 call-bind: 1.0.2 @@ -3910,55 +4910,35 @@ packages: gopd: 1.0.1 has-tostringtag: 1.0.0 is-typed-array: 1.1.10 - dev: false - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - /why-is-node-running@2.2.2: - resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} - engines: {node: '>=8'} - hasBin: true + why-is-node-running@2.2.2: dependencies: siginfo: 2.0.0 stackback: 0.0.2 - dev: true - /word-wrap@1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} + word-wrap@1.2.3: {} - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + wrappy@1.0.2: {} - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true + y18n@5.0.8: {} - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yallist@4.0.0: {} - /yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} + yargs-parser@20.2.9: {} - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} + yargs@16.2.0: dependencies: cliui: 7.0.4 escalade: 3.1.1 @@ -3967,26 +4947,16 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 20.2.9 - dev: true - /yauzl@2.10.0: - resolution: {integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=} + yauzl@2.10.0: dependencies: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 - dev: false - /yazl@2.5.1: - resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} + yazl@2.5.1: dependencies: buffer-crc32: 0.2.13 - dev: false - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + yocto-queue@0.1.0: {} - /yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} - dev: true + yocto-queue@1.0.0: {}