diff --git a/.changeset/curly-walls-knock.md b/.changeset/curly-walls-knock.md new file mode 100644 index 0000000..61e8537 --- /dev/null +++ b/.changeset/curly-walls-knock.md @@ -0,0 +1,5 @@ +--- +"clide-plugin-command-menu": minor +--- + +Renamed `skip` option to `enabled`. diff --git a/.changeset/late-ears-push.md b/.changeset/late-ears-push.md new file mode 100644 index 0000000..e7ec227 --- /dev/null +++ b/.changeset/late-ears-push.md @@ -0,0 +1,13 @@ +--- +"clide-js": minor +--- + +- Polished up internal ✨**test utils**✨ and added them to the exports so you can easily test you're CLIs and plugins! +- Made the `logger` plugin more full featured with `prefix`, `logFile`, and `enabled` options, and util functions for enabling/disabling the logger during runtime. +- Added `formatFileName` util function to exports. +- Added getters to `State` for `client`, ... so they can be accessed without needing to go through through `Context`. +- Made the `Hooks` type a generic which takes a `HooksObject` type param. +- Made the `PluginInfo` type a generic which takes a `PluginMeta` type param. +- Renamed `StateOptions.data` to `StateOptions.initialData`. +- Refactored command resolution to ignore relative paths. +- Fixed the `optionValues` type on `State.fork` to work with command types that have an optional `options` field. \ No newline at end of file diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index c4c021d..0000000 --- a/.eslintrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": ["eslint-config"], - "ignorePatterns": ["**/dist", "**/node_modules"], -} diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index cbda0e6..ebc1c07 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -15,7 +15,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - tasks: [lint, build, typecheck, test:ci] + # tasks: [lint, build, typecheck, test] + tasks: [build, typecheck, test] steps: - name: Check out code diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index f06235c..0000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -dist diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 9be7e82..0000000 --- a/.prettierrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "plugins": ["prettier-plugin-organize-imports"], - "tabWidth": 2, - "useTabs": false, - "trailingComma": "all", - "singleQuote": true, - "semi": true, - "printWidth": 80 -} diff --git a/.vscode/settings.json b/.vscode/settings.json index 8800dcc..6c3c0c7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,27 @@ { - "cSpell.words": [ - "cfonts", - "cliui", - "divs", - "signale", - "unmock" - ] -} \ No newline at end of file + "cSpell.words": ["cfonts", "cliui", "divs", "signale", "unmock"], + "editor.defaultFormatter": "biomejs.biome", + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "quickfix.biome": "explicit", + "source.organizeImports.biome": "explicit" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[yaml]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[markdown]": { + "editor.defaultFormatter": "biomejs.biome" + } +} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..1fbae9f --- /dev/null +++ b/biome.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.7.2/schema.json", + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 80, + "attributePosition": "auto", + "ignore": ["**/node_modules/**", "**/dist/**"] + }, + "organizeImports": { "enabled": true }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "correctness": { + "noUnusedImports": "error" + }, + "style": { + "useNodejsImportProtocol": "warn" + }, + "suspicious": { + "noExplicitAny": "warn", + "noDoubleEquals": "warn" + } + }, + "ignore": ["./**/dist/**", "./**/node_modules/**"] + }, + "javascript": { + "formatter": { + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "trailingComma": "all", + "semicolons": "always", + "arrowParentheses": "always", + "bracketSpacing": true, + "bracketSameLine": false, + "quoteStyle": "single", + "attributePosition": "auto" + } + } +} diff --git a/examples/typescript/package.json b/examples/typescript/package.json index 1b0c949..dd1abc2 100644 --- a/examples/typescript/package.json +++ b/examples/typescript/package.json @@ -10,8 +10,8 @@ "dist" ], "scripts": { - "dev": "NODE_ENV=development ts-node --esm src/cli.ts", - "prod": "ts-node --esm src/cli.ts", + "dev": "NODE_ENV=development tesm-node src/cli.ts", + "prod": "node dist/cli.js", "build": "rimraf dist && tsc" }, "dependencies": { @@ -21,6 +21,7 @@ "devDependencies": { "@tsconfig/node-lts": "^18.12.5", "rimraf": "^5.0.5", + "tesm-node": "^1.3.1", "ts-node": "^10.9.1", "typescript": "^5.2.2" } diff --git a/examples/typescript/src/cli.ts b/examples/typescript/src/cli.ts index ab1751a..13f4378 100644 --- a/examples/typescript/src/cli.ts +++ b/examples/typescript/src/cli.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env node import { help, run } from 'clide-js'; import { commandMenu } from 'clide-plugin-command-menu'; diff --git a/notes/source-code.md b/notes/source-code.md index c7131a1..0125253 100644 --- a/notes/source-code.md +++ b/notes/source-code.md @@ -35,12 +35,11 @@ notes/ # misc notes packages/ # package directories ├─ clide-js/ # core package ├─ clide-plugin-command-menu/ # a plugin to prompt users for missing subcommands -├─ esling-config/ # shared eslint config ├─ extras/ # utilities from CLIs I've written in the past that might get used later. ├─ tsconfig/ # shared tsconfig ``` -The 2 published packages are [clide-js](https://www.npmjs.com/package/clide-js) and [clide-plugin-command-menu](https://www.npmjs.com/package/clide-plugin-command-menu) +The 2 published packages are [clide-js](https://www.npmjs.com/package/clide-js) and [clide-plugin-command-menu](https://www.npmjs.com/package/clide-plugin-command-menu) ## Clide-JS Source Code @@ -94,7 +93,7 @@ plugin](https://github.com/ryangoree/clide-js/blob/main/packages/clide-js/src/pl The [run](https://github.com/ryangoree/clide-js/blob/main/packages/clide-js/src/core/run.ts) -module contains the `run` function which is the primary entry to framework, +module contains the `run` function which is the primary entry to framework, used in the bin file of CLIs. It offers a simple unified API for running a CLI with the Clide-JS framework. It manages registering hooks, creating a `Context` instance, adding options, preparing and executing the context, and catching diff --git a/package.json b/package.json index 2584823..99a5207 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,22 @@ { "private": true, + "type": "module", "scripts": { "build:clide": "turbo run build --filter=./packages/clide*", "build": "turbo run build", - "format": "prettier --write \"**/*.{ts,md}\"", - "lint": "turbo run lint", + "format": "biome format --write ./packages/", + "lint": "biome lint ./packages/", "release": "turbo run build && changeset publish", "test": "turbo run test:ci", "typecheck": "turbo run typecheck" }, "devDependencies": { + "@biomejs/biome": "1.7.2", "@changesets/cli": "^2.27.1", - "eslint": "^9.1.0", - "prettier": "^3.2.5", - "prettier-plugin-organize-imports": "^3.2.4", "tsconfig": "*", "turbo": "latest" }, "name": "clide", "packageManager": "yarn@1.22.19", - "workspaces": [ - "packages/*", - "examples/*", - ".github/actions/*" - ] + "workspaces": ["packages/*", "examples/*", ".github/actions/*"] } diff --git a/packages/clide-js/package.json b/packages/clide-js/package.json index 686a9dc..8e0fae8 100644 --- a/packages/clide-js/package.json +++ b/packages/clide-js/package.json @@ -25,14 +25,12 @@ "yargs-parser": "^21.1.1" }, "devDependencies": { - "@types/cli-table": "^0.3.4", "@types/node": "^20.12.7", "@types/prompts": "^2.4.9", "@types/signale": "^1.4.7", "@types/yargs-parser": "^21.0.3", "@vitest/coverage-v8": "^1.5.0", "dotenv": "^16.4.5", - "prettier-plugin-organize-imports": "^3.2.4", "tesm-node": "^1.3.1", "ts-node": "^10.9.2", "tsconfig": "*", @@ -50,11 +48,17 @@ }, "import": "./dist/index.js", "require": "./dist/index.cjs" + }, + "./test-utils": { + "types": { + "import": "./dist/test-utils.d.ts", + "require": "./dist/test-utils.d.cts" + }, + "import": "./dist/test-utils.js", + "require": "./dist/test-utils.cjs" } }, "main": "dist/index.js", "types": "dist/index.d.ts", - "files": [ - "dist" - ] + "files": ["dist"] } diff --git a/packages/clide-js/src/cli/commands/bar.ts b/packages/clide-js/src/cli/commands/bar.ts deleted file mode 100644 index 5e6e459..0000000 --- a/packages/clide-js/src/cli/commands/bar.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { command } from 'src/core/command'; -import foo from './foo'; - -export default command({ - description: 'Get a greeting', - options: { - name: { - type: 'string', - description: 'The name to greet', - }, - }, - handler: async ({ next, options, fork }) => { - const name = await options.name({ - prompt: 'Enter your name', - }); - - await fork({ - commands: [foo], - optionValues: { - name, - }, - }); - - next(name); - }, -}); diff --git a/packages/clide-js/src/cli/commands/foo.ts b/packages/clide-js/src/cli/commands/foo.ts index dd4a023..10cb583 100644 --- a/packages/clide-js/src/cli/commands/foo.ts +++ b/packages/clide-js/src/cli/commands/foo.ts @@ -6,6 +6,7 @@ export default command({ name: { type: 'string', description: 'The name to greet', + default: '0xff', }, }, handler: async ({ next, options }) => { diff --git a/packages/clide-js/src/cli/commands/foo/bar.ts b/packages/clide-js/src/cli/commands/foo/bar.ts new file mode 100644 index 0000000..3074d22 --- /dev/null +++ b/packages/clide-js/src/cli/commands/foo/bar.ts @@ -0,0 +1,14 @@ +import { command } from 'src/core/command'; + +export default command({ + description: 'Get a greeting', + options: { + name: { + type: 'string', + description: 'The name to greet', + }, + }, + handler: async ({ options }) => { + console.log(options); + }, +}); diff --git a/packages/clide-js/src/cli/index.ts b/packages/clide-js/src/cli/index.ts index 0533721..3116e2f 100644 --- a/packages/clide-js/src/cli/index.ts +++ b/packages/clide-js/src/cli/index.ts @@ -1,12 +1,18 @@ +#!/usr/bin/env node import { run } from 'src/core/run'; import { help } from 'src/plugins/help'; import { logger } from 'src/plugins/logger'; const result = await run({ - plugins: [logger(), help()], + plugins: [ + logger({ + enabled: process.env.NODE_ENV === 'development', + }), + help(), + ], }).catch((e) => { console.error(e); process.exit(1); }); -console.log('result', result); +console.log('result:', result); diff --git a/packages/clide-js/src/core/context.ts b/packages/clide-js/src/core/context.ts index 0d28c33..ed4b4fd 100644 --- a/packages/clide-js/src/core/context.ts +++ b/packages/clide-js/src/core/context.ts @@ -140,11 +140,11 @@ export class Context { /** * Create a new `Context` instance and automatically prep it for execution. */ - static prepare = async (options: ContextOptions) => { + static async prepare(options: ContextOptions) { const context = new Context(options); await context.prepare(); return context; - }; + } /** The options config for the command. */ get options() { @@ -174,7 +174,7 @@ export class Context { * * @remarks This method is idempotent. */ - readonly prepare = async () => { + async prepare() { if (this.isReady) return; try { @@ -197,7 +197,12 @@ export class Context { // Mark the context as ready this.isReady = true; - }; + } + + // Note: The following methods are defined as arrow functions to ensure that + // they are bound to the context instance. This is necessary to allow them to + // be passed as callbacks to hooks and other functions while maintaining the + // correct `this` context. /** * Append additional options to the context's options config. Typically, this @@ -283,7 +288,7 @@ export class Context { // Create a new state for each execution const state = new State({ context: this, - data: initialData, + initialData, }); let _initialData = initialData; @@ -396,7 +401,7 @@ export class Context { * * @remarks This method is idempotent. */ - private _resolve = async () => { + private async _resolve() { if (this.isResolved) return; let resolved: ResolvedCommand | undefined; @@ -424,7 +429,7 @@ export class Context { }, }); - // Don't resolve if the hook skipped + // Only resolve if the hook didn't skip if (!this.isResolved) { resolved = await this.resolveCommand(); } @@ -508,7 +513,7 @@ export class Context { // Mark the context as resolved this.isResolved = true; - }; + } /** * Parse the command string with the final options config from plugins and @@ -516,7 +521,7 @@ export class Context { * * @remarks This method is idempotent. */ - private _parse = async () => { + private async _parse() { if (this.isParsed) return; await this.hooks.call('beforeParse', { @@ -549,5 +554,5 @@ export class Context { }, context: this, }); - }; + } } diff --git a/packages/clide-js/src/core/help.ts b/packages/clide-js/src/core/help.ts index 8307a8d..bbd6061 100644 --- a/packages/clide-js/src/core/help.ts +++ b/packages/clide-js/src/core/help.ts @@ -1,5 +1,5 @@ import initCliui from 'cliui'; -import fs from 'node:fs'; +import fs from 'fs'; import { getBin } from 'src/utils/argv'; import { Converted, convert } from 'src/utils/convert'; import { isDirectory } from 'src/utils/fs'; diff --git a/packages/clide-js/src/core/hooks.ts b/packages/clide-js/src/core/hooks.ts index 54ad5a6..b19459c 100644 --- a/packages/clide-js/src/core/hooks.ts +++ b/packages/clide-js/src/core/hooks.ts @@ -6,11 +6,14 @@ import { ResolveCommandFn, ResolvedCommand } from './resolve'; import { NextState, State } from './state'; /** - * The hooks that can be used to customize the CLI engine. + * The hooks that can be registered and called to modify the behavior of the + * CLI, keyed by event name, listed in the order they are called. * @group Hooks */ export interface Hooks { - // called once during preparation + /** + * 1. Called once during preparation. + */ beforeResolve: (payload: { /** The command string that was passed to the CLI. */ commandString: string; @@ -37,7 +40,9 @@ export interface Hooks { context: Context; }) => MaybePromise; - // called once for each subcommand during preparation + /** + * 2. Called once for each subcommand during preparation. + */ beforeResolveNext: (payload: { /** The remaining command string that needs to be resolved. */ commandString: string; @@ -69,7 +74,9 @@ export interface Hooks { context: Context; }) => MaybePromise; - // called once during preparation + /** + * 3. Called once during preparation. + */ afterResolve: (payload: { /** The resolved commands. */ resolvedCommands: ResolvedCommand[]; @@ -90,7 +97,9 @@ export interface Hooks { context: Context; }) => MaybePromise; - // called once during preparation + /** + * 4. Called once during preparation. + */ beforeParse: (payload: { /** The command string that was passed to the CLI. */ commandString: string | string[]; @@ -115,7 +124,9 @@ export interface Hooks { context: Context; }) => MaybePromise; - // called once during preparation + /** + * 5. Called once during preparation. + */ afterParse: (payload: { /** The resulting parsed options. */ parsedOptions: OptionValues; @@ -128,7 +139,9 @@ export interface Hooks { context: Context; }) => MaybePromise; - // called once for every execution + /** + * 6. Called once for every execution. + */ beforeExecute: (payload: { /** The initial data that was passed to the state. */ initialData: unknown; @@ -145,17 +158,34 @@ export interface Hooks { skip: () => void; }) => MaybePromise; - // called once for every execution - afterExecute: (payload: { + /** + * 7. Called for every call of `state.next()`. + * + * @remarks `state.start()` calls `state.next()` internally, so this hook is + * called before the first command is executed. + */ + beforeNext: (payload: { /** The state object. */ state: State; - /** The final result. */ - result: unknown; - /** Override the final result. */ - setResult: (result: unknown) => void; + /** The data that will be passed to the next command. */ + data: unknown; + /** + * Override the data that will be passed to the next command. + * @param data - The new data. + */ + setData: (data: unknown) => void; + /** The next command that will be executed. */ + nextCommand: ResolvedCommand | undefined; + /** + * Override the next command that will be executed. + * @param command - The new next command. + */ + setNextCommand: (command: ResolvedCommand) => void; }) => MaybePromise; - // called every time the state changes during execution + /** + * 8. Called every time the state changes during execution. + */ beforeStateChange: (payload: { /** The state object. */ state: State; @@ -170,7 +200,9 @@ export interface Hooks { skip: () => void; }) => MaybePromise; - // called every time the state changes during execution + /** + * 9. Called every time the state changes during execution. + */ afterStateChange: (payload: { /** The state object. */ state: State; @@ -178,40 +210,40 @@ export interface Hooks { changed: Partial; }) => MaybePromise; - // called for every call of state.next() - beforeNext: (payload: { + /** + * 10. Called once per execution, *before* the final state change, if + * `state.end()` is called. + */ + beforeEnd: (payload: { /** The state object. */ state: State; - /** The data that will be passed to the next command. */ + /** The data that will be returned. */ data: unknown; /** - * Override the data that will be passed to the next command. + * Override the data that will be returned. * @param data - The new data. */ setData: (data: unknown) => void; - /** The next command that will be executed. */ - nextCommand: ResolvedCommand | undefined; - /** - * Override the next command that will be executed. - * @param command - The new next command. - */ - setNextCommand: (command: ResolvedCommand) => void; }) => MaybePromise; - // called once per execution, but only if state.end() is called - beforeEnd: (payload: { + /** + * 11. Called once for every execution. + */ + afterExecute: (payload: { /** The state object. */ state: State; - /** The data that will be returned. */ - data: unknown; - /** - * Override the data that will be returned. - * @param data - The new data. - */ - setData: (data: unknown) => void; + /** The final result. */ + result: unknown; + /** Override the final result. */ + setResult: (result: unknown) => void; }) => MaybePromise; - // called whenever an error is thrown + // The following hooks are not part of the core lifecycle, but are included + // for convenience. + + /** + * Called whenever an error is thrown. + */ error: (payload: { /** The command's context object. */ context: Context; @@ -226,7 +258,9 @@ export interface Hooks { ignore: () => void; }) => MaybePromise; - // called whenever a plugin or command intend to exit the process + /** + * Called whenever a plugin or command intend to exit the process. + */ exit: (payload: { /** The command's context object. */ context: Context; @@ -250,129 +284,136 @@ export interface Hooks { } /** - * A generic type for the payload of a hook. - * @group Hooks - */ -export type HookPayload = Parameters< - Hooks[THook] ->[0]; - -/** - * A class for registering, un-registering, and calling hooks. The hooks called - * by the CLI engine are defined in the {@linkcode Hooks} type, but any string - * can be used as a hook name, allowing plugins to define their own hooks. + * A class for registering, un-registering, and calling hooks. The events that + * can be hooked into are defined in the {@linkcode Hooks} type, but any string + * can be used as an event name, allowing plugins to define their own hooks. * * @remarks - * Each registered hook handler is awaited in series to ensure that hooks are + * Each registered hook is awaited in series to ensure that hooks are * called in the order they were registered. * @group Hooks */ // similar to EventEmitter, but blocking -export class HooksEmitter { - private hooks: Record< - string, - { - handlers: ((...args: any) => any)[]; - } - > = {}; +export class HooksEmitter { + private hooks: { + [event: string]: ((...args: any) => void)[]; + } = {}; /** - * Register a new hook handler for a given hook. - * @param hook - The hook to register the handler for. - * @param fn - The function to call when the hook is called. + * Register a new hook for a given lifecycle event. + * @param event - The event to register the hook for. + * @param hook - The function to call when the event is triggered. */ - on(hook: THook, fn: Hooks[THook]): void; - on( - hook: string, - fn: THook extends keyof Hooks ? Hooks[THook] : (...args: any) => any, + on(event: TEvent, hook: THooks[TEvent]): void; + on( + event: string, + hook: TEvent extends keyof THooks + ? THooks[TEvent] + : (...args: any[]) => void, ): void; - on(hook: string, fn: (...args: any) => any): void { - const hooks = this.hooks[hook]; - if (hooks) { - hooks.handlers.push(fn); + on(event: string, hook: (...args: any) => any): void { + const existing = this.hooks[event]; + if (existing) { + existing.push(hook); } else { - this.hooks[hook] = { - handlers: [fn], - }; + this.hooks[event] = [hook]; } } /** - * Un-register a hook handler for a given hook. - * @param hook - The hook to un-register the handler for. - * @param fn - The function to un-register. - * @returns Whether or not the handler was un-registered. + * Un-register a hook for a given lifecycle event. + * @param event - The event to un-register the hook for. + * @param hook - The function to un-register. + * @returns Whether a hook was un-registered. */ - off(hook: THook, fn: Hooks[THook]): boolean; - off( - hook: string, - fn: THook extends keyof Hooks ? Hooks[THook] : (...args: any) => any, + off( + event: TEventName, + hook: THooks[TEventName], + ): boolean; + off( + event: string, + hook: TEventName extends keyof THooks + ? THooks[TEventName] + : (...args: any) => any, ): boolean; - off(hook: string, fn: (...args: any) => any) { + off(event: string, hook: (...args: any) => any) { let didRemove = false; - if (this.hooks[hook]) { - this.hooks[hook].handlers = this.hooks[hook].handlers.filter( - (handler) => { - if (handler === fn) { - didRemove = true; - return false; - } - return true; - }, - ); + const existing = this.hooks[event]; + if (existing) { + this.hooks[event] = existing.filter((handler) => { + if (handler === hook) { + didRemove = true; + return false; + } + return true; + }); } return didRemove; } /** - * Register a new hook handler for a given hook that will only be called once, - * then un-registered. - * @param hook - The hook to register the handler for. - * @param fn - The function to call when the hook is called. + * Register a new hook for a given lifecycle event that will only be called + * once, then un-registered. + * @param event - The event to register the hook for. + * @param hook - The function to call when the event is triggered. */ - once(hook: THook, fn: Hooks[THook]): void; - once( - hook: string, - fn: THook extends keyof Hooks ? Hooks[THook] : (...args: any) => any, + once( + event: TEventName, + hook: THooks[TEventName], ): void; - once(hook: string, fn: (...args: any) => any) { + once( + event: string, + hook: TEventName extends keyof THooks + ? THooks[TEventName] + : (...args: any) => any, + ): void; + once(event: string, hook: (...args: any) => any) { const wrapped = (...args: any) => { - this.off(hook, wrapped); - fn(...args); + this.off(event, wrapped as any); + hook(...args); }; - this.on(hook, wrapped); + this.on(event, wrapped as any); } /** - * Call a hook with the given arguments. - * @param hook - The hook to call. - * @param args - The arguments to pass to the hook handlers. + * Call all hooks for a given event. + * @param event - The event to call the hooks for. + * @param args - The arguments to pass to the hooks. */ - call( - hook: THook, - ...args: Parameters + call( + event: TEventName, + ...args: THooks[TEventName] extends (...args: any) => any + ? Parameters + : any[] ): Promise; - call( - hook: THook, - ...args: typeof hook extends keyof Hooks ? Parameters : any[] + call( + event: TEventName, + ...args: typeof event extends keyof THooks + ? THooks[TEventName] extends (...args: any) => any + ? Parameters + : any[] + : any[] ): Promise; - async call(hook: string, ...args: any) { - const { handlers } = this.hooks[hook] || {}; - for (const handler of handlers || []) { - await (handler as any)(...args); + async call(event: string, ...args: any) { + for (const hook of this.hooks[event] || []) { + await (hook as any)(...args); } } } -// wip idea: passing data via hooks - -// hooks.on('connected', ({ wallet }) => setWallet(wallet)); -// hooks.call('connect'); - -// myPlugin = ({ hooks }) => { -// hooks.on('connect', () => { -// // get wallet... +/** + * A generic type for the payload of a hook. + * @group Hooks + */ +export type HookPayload< + TEventName extends keyof THooks, + THooks extends HooksObject = Hooks, +> = THooks[TEventName] extends (...args: any) => any + ? Parameters[0] + : unknown; -// hooks.call('connected', { wallet: new Wallet(/* ... */) }); -// }); -// }; +export type HooksObject = + | { + [event: string]: (payload: any) => void; + } + | Hooks; diff --git a/packages/clide-js/src/core/parse.ts b/packages/clide-js/src/core/parse.ts index 50ff97e..46d01a3 100644 --- a/packages/clide-js/src/core/parse.ts +++ b/packages/clide-js/src/core/parse.ts @@ -116,7 +116,7 @@ export function parseCommand( } return true; }); - + return { // Coerce all tokens to strings (yargs-parser returns numbers for numbers) tokens: tokens.map(String), diff --git a/packages/clide-js/src/core/plugin.ts b/packages/clide-js/src/core/plugin.ts index 5437019..3119487 100644 --- a/packages/clide-js/src/core/plugin.ts +++ b/packages/clide-js/src/core/plugin.ts @@ -1,37 +1,55 @@ -import { MaybePromise } from 'src/utils/types'; +import { MaybePromise, Nothing, Prettify } from 'src/utils/types'; import { Context } from './context'; /** - * Metadata about a plugin. - * @catgory Core + * A Clide-JS plugin * @group Plugin */ -export interface PluginInfo { - /** The name of the plugin. */ - name: string; - /** The version of the plugin. */ - version: string; - /** A description of the plugin. */ - description?: string; - /** - * Any additional metadata about the plugin. This is useful for plugins that - * need to provide additional data to other plugins or commands. - */ - meta?: { - [key: string]: any; - }; -} +export type Plugin = Prettify< + PluginInfo & { + /** + * Initialize the plugin. + * @param context - The context the plugin is being initialized in. + * @returns A boolean or promise that resolves to a boolean indicating + * whether the plugin was successfully initialized. + */ + init: (context: Context) => MaybePromise; + } +>; /** - * A Clide-JS plugin + * Information about a plugin. + * @catgory Core * @group Plugin */ -export interface Plugin extends PluginInfo { - /** - * Initialize the plugin. - * @param context - The context the plugin is being initialized in. - * @returns A boolean or promise that resolves to a boolean indicating - * whether the plugin was successfully initialized. - */ - init: (context: Context) => MaybePromise; -} +export type PluginInfo = Prettify< + { + name: string; + version: string; + description?: string; + } & (unknown extends TMeta + ? { + /** + * Additional metadata about the plugin that doesn't fit in the standard + * fields. + * + * Note: Plugin info on the {@linkcode Context} object will be frozen + * after the plugin is initialized. However, the freeze is shallow, so + * the fields of this object will be mutable by default. + */ + meta?: Record; + } + : { + /** + * Additional metadata about the plugin that doesn't fit in the standard + * fields. + * + * Note: Plugin info on the {@linkcode Context} object will be frozen + * after the plugin is initialized. However, the freeze is shallow, so + * the fields of this object will be mutable by default. + */ + meta: TMeta; + }) +>; + +export type PluginMeta = Record | Nothing; diff --git a/packages/clide-js/src/core/resolve.ts b/packages/clide-js/src/core/resolve.ts index 235ad2b..cec8296 100644 --- a/packages/clide-js/src/core/resolve.ts +++ b/packages/clide-js/src/core/resolve.ts @@ -1,12 +1,14 @@ -import fs from 'node:fs'; -import path from 'node:path'; +import fs from 'fs'; +import path from 'path'; import { CommandModule, passThroughCommand } from 'src/core/command'; import { MissingDefaultExportError, NotFoundError, + OptionsError, UsageError, } from 'src/core/errors'; import { ParseCommandFn, parseCommand } from 'src/core/parse'; +import { formatFileName } from 'src/utils/format-file-name'; import { isDirectory, isFile } from 'src/utils/fs'; import { parseFileName } from 'src/utils/parse-file-name'; import { removeFileExtension } from 'src/utils/remove-file-extension'; @@ -65,6 +67,16 @@ export async function resolveCommand({ const [commandName, ...remainingTokens] = commandString.split(' '); + // Check if the first token is an option. + if (commandName.startsWith('-')) { + throw new OptionsError(`Unknown option "${commandName}"`); + } + + // Check if the command name is a relative path (e.g., ./foo, ../foo, /foo) + if (/^(\.|\/)/.test(commandName)) { + throw new UsageError(`Invalid command name: ${commandName}`); + } + // Ensure the command directory exists. if (!isDirectory(commandsDir)) { throw new NotFoundError(commandName, commandsDir); @@ -345,11 +357,3 @@ export interface ResolvedCommand { */ params?: Params; } - -/** - * Formats a file name to ensure it ends with `.js`. - * @group Resolve - */ -export function formatFileName(fileName: string) { - return `${removeFileExtension(fileName)}.js`; -} diff --git a/packages/clide-js/src/core/run.ts b/packages/clide-js/src/core/run.ts index 2f4c344..48639ee 100644 --- a/packages/clide-js/src/core/run.ts +++ b/packages/clide-js/src/core/run.ts @@ -1,4 +1,4 @@ -import path from 'node:path'; +import path from 'path'; import { hideBin } from 'src/utils/argv'; import { getCallerPath } from 'src/utils/caller-path'; import { isDirectory } from 'src/utils/fs'; diff --git a/packages/clide-js/src/core/state.ts b/packages/clide-js/src/core/state.ts index c8e7a44..5a6e614 100644 --- a/packages/clide-js/src/core/state.ts +++ b/packages/clide-js/src/core/state.ts @@ -10,7 +10,7 @@ interface StateOptions { /** The context for the command. */ context: Context; /** The initial data for the steps. */ - data?: TData; + initialData?: TData; /** * The commands to execute. If not provided, it defaults to the commands * resolved from the context. @@ -67,20 +67,20 @@ export class State< constructor({ context, - data, + initialData, commands, - options, - optionValues, + options = context.options, + optionValues = context.parsedOptions, }: StateOptions) { this._context = context; - this._data = data as TData; + this._data = initialData as TData; this._commands = commands || context.resolvedCommands; // Create a getter to dynamically get the options from context. this._options = createOptionsGetter({ client: context.client, - optionsConfig: options || context.options, - optionValues: optionValues || context.parsedOptions, + optionsConfig: options, + optionValues: optionValues, onPromptCancel: context.exit, }) as OptionsGetter; } @@ -113,13 +113,17 @@ export class State< get options() { return this._options; } + /** The client for the command. */ + get client() { + return this.context.client; + } /** * Start the steps. * @throws {ClideError} If the steps have already started. * @returns A promise that resolves when the steps are done. */ - readonly start = async (initialData?: unknown): Promise => { + readonly start = async (initialData: unknown = this._data): Promise => { // Avoid starting the steps if they're already started. if (this.executionPromise) { throw new ClideError('Steps have already started.'); @@ -258,9 +262,9 @@ export class State< commands: (TCommand | ResolvedCommand)[]; initialData?: any; optionValues?: OptionValues< - TCommand['options'] extends OptionsConfig - ? TCommand['options'] - : OptionsConfig + Required['options'] extends OptionsConfig + ? Required['options'] + : OptionsConfig >; // TODO: strict type for paramValues paramValues?: Record; @@ -292,7 +296,7 @@ export class State< // Create a new state for the invocation const state = new State({ context: this.context, - data: initialData, + initialData: initialData, commands: resolvedCommands, options: { ...this.context.options, diff --git a/packages/clide-js/src/index.ts b/packages/clide-js/src/index.ts index 6f81851..5c480c8 100644 --- a/packages/clide-js/src/index.ts +++ b/packages/clide-js/src/index.ts @@ -24,6 +24,7 @@ export * from './utils/argv'; export * from './utils/caller-path'; export * from './utils/camel-case'; export * from './utils/find-similar'; +export * from './utils/format-file-name'; export * from './utils/fs'; export * from './utils/parse-file-name'; export * from './utils/remove-file-extension'; diff --git a/packages/clide-js/src/plugins/help.ts b/packages/clide-js/src/plugins/help.ts index 87605b3..dba9f87 100644 --- a/packages/clide-js/src/plugins/help.ts +++ b/packages/clide-js/src/plugins/help.ts @@ -27,7 +27,7 @@ export interface HelpPluginOptions { export function help({ maxWidth = 80 }: HelpPluginOptions = {}): Plugin { return { name: 'help', - version: '0.0.0', + version: '0.0.1', description: 'Prints help information on execution if the -h or --help flags are present or when a usage error occurs.', init: ({ addOptions, client, hooks }) => { diff --git a/packages/clide-js/src/plugins/logger.ts b/packages/clide-js/src/plugins/logger.ts index c02a29b..68dc0f4 100644 --- a/packages/clide-js/src/plugins/logger.ts +++ b/packages/clide-js/src/plugins/logger.ts @@ -1,46 +1,240 @@ -import { Plugin } from 'src/core/plugin'; -import { State } from 'src/core/state'; +import fs from 'fs'; +import path from 'path'; +import type { Client } from 'src/core/client'; +import type { HookPayload } from 'src/core/hooks'; +import type { Plugin } from 'src/core/plugin'; + +interface LoggerOptions { + /** + * The prefix to use for log messages. Can be a string or a function that + * returns a string. If a function is provided, it will be called each time a + * log message is created. + * + * @defaultValue A timestamp. + * + * @example + * ```ts + * prefix: () => `${sessionId}-${new Date().toISOString()}`, + * ``` + */ + prefix?: string | (() => string); + + /** + * A path to a file to log to. If provided, the logger will log to this file + * instead of the console, appending each log message followed by a newline. + */ + logFile?: string; + + /** + * Whether the logger is enabled. + * @defaultValue `true` + */ + enabled?: boolean; +} + +export let disableLogger: () => void; +export let enableLogger: () => void; +export let toggleLogger: () => void; /** - * A minimal logger plugin that logs the result of each execution step. + * A minimal logger plugin that logs the result of each execution step. By + * default, it uses the {@linkcode Client} from {@linkcode Context}. If a + * `logFile` is provided, it will log to that file instead. + * + * The logger can be enabled or disabled at any time by emitting one of the + * {@linkcode LoggerHooks} events: + * - `enableLogger`: Turns the logger on. + * - `disableLogger`: Turns the logger off. + * - `toggleLogger`: Toggles the logger on or off. + * + * @example + * ### Basic Usage + * + * ```ts + * import { run, logger } from 'clide-js'; + * + * run({ plugins: [logger()] }); + * + * + * ``` + * + * ### Advanced Usage + * + * ```ts + * import { run, logger } from 'clide-js'; + * + * function timestamp() { + * return new Date().toISOString(); + * } + * + * run({ + * plugins: [ + * logger({ + * prefix: timestamp, + * logFile: `logs/${timestamp()}.log`, + * enabled: process.env.NODE_ENV === 'development', + * }) + * ], + * }); + * + * + * ``` + * + * ### Enable/Disable/Toggle the logger in a command + * + * ```ts + * import { command, disableLogger, enableLogger } from 'clide-js'; + * + * export default command({ + * options: { + * v { + * description: 'Enable verbose logging', + * type: 'boolean', + * default: false, + * }, + * }, + * handler: async ({ options, context }) => { + * const verbose = await options.verbose(); + * + * if (verbose) { + * enableLogger(); + * } else { + * disableLogger(); + * } + * + * // rest of the command... + * }, + * }); + * ``` + * * @group Plugins */ -export function logger(): Plugin { - return { - name: 'logger', - version: '0.0.0', - description: 'Logs the result of each execution step.', - init: ({ client, commandString, hooks }) => { - client.log(prefix('received command'), commandString); - - hooks.on('beforeNext', ({ data, state }) => { - log('next', data, state); - }); +export function logger({ + prefix = defaultPrefix, + logFile, + enabled = true, +}: LoggerOptions = {}): Plugin { + // Coerce the prefix to a function. + const prefixFn = typeof prefix === 'function' ? prefix : () => prefix; - hooks.on('beforeEnd', ({ data, state }) => { - log('end', data, state); - }); - - return true; - }, - }; + // if a logFile is provided, ensure the directory exists. + if (logFile) { + const dir = path.dirname(logFile); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + } - function prefix(str: string) { - return `[🪵 ${new Date().toISOString()}] ${str}:`; + // Create a function to centralize the logging logic. + function log(client: Client, message: string, ...data: any[]) { + const prefixedMessage = `${prefixFn()}${message}`; + if (logFile) { + logToFile(logFile, prefixedMessage, ...data); + } else { + client.log(`${prefixedMessage}:`, ...data); + } } - function log( + // Create a function to log state transitions. + function logTransition( transitionName: string, - data: unknown, - { command, context, params }: State, + { state }: HookPayload<'beforeNext' | 'beforeEnd'>, ) { + const { command, client, params, data } = state; if (!command) return; - context.client.log(prefix(transitionName), { - commandName: command.commandName, - commandTokens: command.commandTokens, - commandPath: command.commandPath, + const { commandName, commandTokens, commandPath } = command; + log(client, transitionName, { + commandName, + commandTokens, + commandPath, params, data, }); } + + // Create beforeNext and beforeEnd hooks that log the transitions. + function beforeNext(payload: HookPayload<'beforeNext'>) { + logTransition('next', payload); + } + function beforeEnd(payload: HookPayload<'beforeNext'>) { + logTransition('end', payload); + } + + // Return the plugin object. + return { + name: 'logger', + version: '0.0.1', + description: 'Logs the result of each execution step.', + meta: { + // Create a meta object to provide read-only access to the enabled state. + // It's important that the enabled state can't be modified directly because + // the hooks need to be aware of the state changes. + get enabled() { + return enabled; + }, + }, + init: async ({ client, commandString, hooks }) => { + // Create functions to enable and disable the hooks. + enableLogger = () => { + hooks.on('beforeNext', beforeNext); + hooks.on('beforeEnd', beforeEnd); + enabled = true; + }; + disableLogger = () => { + hooks.off('beforeNext', beforeNext); + hooks.off('beforeEnd', beforeEnd); + enabled = false; + }; + + // Log the command if the logger is enabled. + if (enabled) { + enableLogger(); + log(client, 'received command', commandString); + } + + // Add custom hooks to enable, disable, and toggle the logger. + hooks.on('enableLogger', () => enableLogger()); + hooks.on('disableLogger', () => disableLogger()); + hooks.on('toggleLogger', () => + enabled ? disableLogger() : enableLogger(), + ); + + return true; + }, + }; +} + +export interface LoggerMeta { + /** + * Whether the logger is enabled. + */ + readonly enabled: boolean; +} + +export interface LoggerHooks { + /** + * Turns the logger on. + */ + enableLogger: () => void; + /** + * Turns the logger off. + */ + disableLogger: () => void; + /** + * Toggles the logger on or off. + */ + toggleLogger: () => void; +} + +function defaultPrefix() { + return `[🪵 ${new Date().toISOString()}] `; +} + +function logToFile(logFile: string, message: string, ...data: any[]) { + const stringData = data + .map((value) => + typeof value === 'object' ? JSON.stringify(value, null, 2) : value, + ) + .join(' '); + fs.appendFileSync(logFile, `${message}: ${stringData}\n`); } diff --git a/packages/clide-js/src/utils/caller-path.ts b/packages/clide-js/src/utils/caller-path.ts index 7eaa98f..adc858b 100644 --- a/packages/clide-js/src/utils/caller-path.ts +++ b/packages/clide-js/src/utils/caller-path.ts @@ -56,7 +56,7 @@ export function getCallerPath(): string | undefined { // If the stack is a string, we're in a non-v8 environment and need to parse // the stack string to get the file path. - // https://regex101.com/r/LBLrQF/1 + // https://regex101.com/r/yyMI5W/1 const callerLine = target.stack.split('\n')[callerIndex].trim(); const callerFile = callerLine.match(/(file|\/)[^\s]+?(?=(:\d|\)))/)?.[0]; diff --git a/packages/clide-js/src/utils/convert.ts b/packages/clide-js/src/utils/convert.ts index d4ce02c..e7b9214 100644 --- a/packages/clide-js/src/utils/convert.ts +++ b/packages/clide-js/src/utils/convert.ts @@ -1,5 +1,10 @@ /** - * Deeply converts values in an object or array or a single value. + * Recursively converts a type to a new type. The `predicateFn` is + * used to determine if the `converterFn` should be run on the value. + * + * The function first checks the value itself, if the `predicateFn` returns + * false and the value is an array or object, the function will recursively + * check each item in the array or object. * * @param value - The value or object/array containing values to convert. * @param predicateFn - The predicate function to determine if a value should be @@ -7,7 +12,7 @@ * @param converterFn - The function to convert the value. * * @returns The converted value. - * + * * @internal */ export function convert( @@ -40,11 +45,14 @@ export function convert( return value as Converted; } -/** The type of a deeply converted value. */ +/** + * The converted type of `T` where all instances of `TOriginal` are replaced + * with `TNew`. + */ export type Converted = T extends TOriginal ? TNew : T extends Array - ? Converted[] - : T extends object - ? { [K in keyof T]: Converted } - : T; + ? Converted[] + : T extends object + ? { [K in keyof T]: Converted } + : T; diff --git a/packages/clide-js/src/utils/format-file-name.ts b/packages/clide-js/src/utils/format-file-name.ts new file mode 100644 index 0000000..3aeb942 --- /dev/null +++ b/packages/clide-js/src/utils/format-file-name.ts @@ -0,0 +1,9 @@ +import { removeFileExtension } from './remove-file-extension'; + +/** + * Formats a file name to ensure it ends with `.js`. + * @group Resolve + */ +export function formatFileName(fileName: string) { + return `${removeFileExtension(fileName)}.js`; +} diff --git a/packages/clide-js/src/utils/fs.ts b/packages/clide-js/src/utils/fs.ts index 16390b2..48b18f4 100644 --- a/packages/clide-js/src/utils/fs.ts +++ b/packages/clide-js/src/utils/fs.ts @@ -1,4 +1,4 @@ -import fs from 'node:fs'; +import fs from 'fs'; import { removeFileExtension } from './remove-file-extension'; /** @@ -50,8 +50,7 @@ export function isFile( * Attempt to determine if an error is a module not found error. * @group Utils * @remarks - * This function is not guaranteed to be accurate in every environment and is - * meant to be used when the source of the error is known. + * This function is not guaranteed to be accurate in every environment. */ function isModuleNotFoundError(err: unknown): boolean { if (err && (err as any).code === 'ENOENT') return true; diff --git a/packages/clide-js/src/utils/types.ts b/packages/clide-js/src/utils/types.ts index efd25a9..e965075 100644 --- a/packages/clide-js/src/utils/types.ts +++ b/packages/clide-js/src/utils/types.ts @@ -2,8 +2,36 @@ export type MaybePromise = T | Promise; export type MaybeReadonly = T | Readonly; +/** + * An absent or uninitialized value that can represent `null` even with + * [`strictNullChecks`](https://www.typescriptlang.org/tsconfig/#strictNullChecks) + * on. + */ +export type Nothing = void | null; + +/** + * Convert an intersection of objects to a single object, making the type easier + * to read. + * + * @example + * ```ts + * type Intersection = { a: number } & { b: string }; + * type Prettified = Prettify; + * // { a: number; b: string } + * ``` + */ export type Prettify = { [K in keyof T]: T[K] } & unknown; +/** + * Convert members of a union to an intersection. + * + * @example + * ```ts + * type Union = { a: number } | { b: string }; + * type Intersection = UnionToIntersection; + * // { a: number } & { b: string } + * ``` + */ type UnionToIntersection = (T extends any ? (x: T) => any : never) extends ( x: infer R, ) => any diff --git a/packages/clide-js/test/src/core/help.test.ts b/packages/clide-js/test/units/core/help.test.ts similarity index 97% rename from packages/clide-js/test/src/core/help.test.ts rename to packages/clide-js/test/units/core/help.test.ts index 54799dd..90ace93 100644 --- a/packages/clide-js/test/src/core/help.test.ts +++ b/packages/clide-js/test/units/core/help.test.ts @@ -2,7 +2,7 @@ import { mockCommandModule, unmockAllCommandModules, -} from 'test/mocks/command-modules'; +} from 'test/utils/command-modules'; import { Context } from 'src/core/context'; import { Help, getHelp } from 'src/core/help'; diff --git a/packages/clide-js/test/src/core/hooks.test.ts b/packages/clide-js/test/units/core/hooks.test.ts similarity index 100% rename from packages/clide-js/test/src/core/hooks.test.ts rename to packages/clide-js/test/units/core/hooks.test.ts diff --git a/packages/clide-js/test/src/core/options.test.ts b/packages/clide-js/test/units/core/options.test.ts similarity index 100% rename from packages/clide-js/test/src/core/options.test.ts rename to packages/clide-js/test/units/core/options.test.ts diff --git a/packages/clide-js/test/src/core/parse.test.ts b/packages/clide-js/test/units/core/parse.test.ts similarity index 98% rename from packages/clide-js/test/src/core/parse.test.ts rename to packages/clide-js/test/units/core/parse.test.ts index edb51ed..76869d5 100644 --- a/packages/clide-js/test/src/core/parse.test.ts +++ b/packages/clide-js/test/units/core/parse.test.ts @@ -1,5 +1,5 @@ import { ParsedCommand, parseCommand } from 'src/core/parse'; -import { unmockAllCommandModules } from 'test/mocks/command-modules'; +import { unmockAllCommandModules } from 'test/utils/command-modules'; import { beforeEach, describe, expect, it, vi } from 'vitest'; describe('parse', () => { diff --git a/packages/clide-js/test/src/core/resolve.test.ts b/packages/clide-js/test/units/core/resolve.test.ts similarity index 67% rename from packages/clide-js/test/src/core/resolve.test.ts rename to packages/clide-js/test/units/core/resolve.test.ts index 5e82001..053ef70 100644 --- a/packages/clide-js/test/src/core/resolve.test.ts +++ b/packages/clide-js/test/units/core/resolve.test.ts @@ -2,7 +2,7 @@ import { mockCommandModules, unmockAllCommandModules, -} from 'test/mocks/command-modules'; +} from 'test/utils/command-modules'; import { ResolvedCommand, resolveCommand } from 'src/core/resolve'; import { beforeEach, describe, expect, it, vi } from 'vitest'; @@ -44,44 +44,38 @@ describe('resolve', () => { commandsDir, }); - expect(resolved).toEqual( - expect.objectContaining({ - command: commandModules['commands/foo.js'], - commandPath: 'commands/foo.js', - commandName: 'foo', - commandTokens: ['foo'], - remainingCommandString: 'bar baz', - resolveNext: expect.any(Function), - subcommandsDir: 'commands/foo', - } as ResolvedCommand), - ); + expect(resolved).toMatchObject({ + command: commandModules['commands/foo.js'], + commandPath: 'commands/foo.js', + commandName: 'foo', + commandTokens: ['foo'], + remainingCommandString: 'bar baz', + resolveNext: expect.any(Function), + subcommandsDir: 'commands/foo', + } as ResolvedCommand); resolved = await resolved.resolveNext!(); - expect(resolved).toEqual( - expect.objectContaining({ - command: commandModules['commands/foo/bar.js'], - commandPath: 'commands/foo/bar.js', - commandName: 'bar', - commandTokens: ['bar'], - remainingCommandString: 'baz', - resolveNext: expect.any(Function), - subcommandsDir: 'commands/foo/bar', - } as ResolvedCommand), - ); + expect(resolved).toMatchObject({ + command: commandModules['commands/foo/bar.js'], + commandPath: 'commands/foo/bar.js', + commandName: 'bar', + commandTokens: ['bar'], + remainingCommandString: 'baz', + resolveNext: expect.any(Function), + subcommandsDir: 'commands/foo/bar', + } as ResolvedCommand); resolved = await resolved.resolveNext!(); - expect(resolved).toEqual( - expect.objectContaining({ - command: commandModules['commands/foo/bar/baz.js'], - commandPath: 'commands/foo/bar/baz.js', - commandName: 'baz', - commandTokens: ['baz'], - remainingCommandString: '', - subcommandsDir: 'commands/foo/bar/baz', - } as ResolvedCommand), - ); + expect(resolved).toMatchObject({ + command: commandModules['commands/foo/bar/baz.js'], + commandPath: 'commands/foo/bar/baz.js', + commandName: 'baz', + commandTokens: ['baz'], + remainingCommandString: '', + subcommandsDir: 'commands/foo/bar/baz', + } as ResolvedCommand); }); it('resolves param commands', async () => { diff --git a/packages/clide-js/test/src/core/run.test.ts b/packages/clide-js/test/units/core/run.test.ts similarity index 99% rename from packages/clide-js/test/src/core/run.test.ts rename to packages/clide-js/test/units/core/run.test.ts index 1fa4d6a..22acec1 100644 --- a/packages/clide-js/test/src/core/run.test.ts +++ b/packages/clide-js/test/units/core/run.test.ts @@ -3,9 +3,9 @@ import { mockCommandModule, mockCommandModules, unmockAllCommandModules, -} from 'test/mocks/command-modules'; +} from 'test/utils/command-modules'; -import path from 'node:path'; +import path from 'path'; import { Client } from 'src/core/client'; import { Context } from 'src/core/context'; import { ClideError } from 'src/core/errors'; @@ -13,7 +13,7 @@ import { HookPayload } from 'src/core/hooks'; import { Plugin } from 'src/core/plugin'; import { run } from 'src/core/run'; import { State } from 'src/core/state'; -import { mockPlugin, mockPluginInfo } from 'test/mocks/plugin'; +import { mockPlugin, mockPluginInfo } from 'test/utils/plugin'; import { beforeEach, describe, expect, it, vi } from 'vitest'; const __dirname = path.dirname(new URL(import.meta.url).pathname); diff --git a/packages/clide-js/test/src/plugins/help.test.ts b/packages/clide-js/test/units/plugins/help.test.ts similarity index 98% rename from packages/clide-js/test/src/plugins/help.test.ts rename to packages/clide-js/test/units/plugins/help.test.ts index ac737f2..9665eb1 100644 --- a/packages/clide-js/test/src/plugins/help.test.ts +++ b/packages/clide-js/test/units/plugins/help.test.ts @@ -2,7 +2,7 @@ import { mockCommandModule, unmockAllCommandModules, -} from 'test/mocks/command-modules'; +} from 'test/utils/command-modules'; vi.mock('src/core/client'); diff --git a/packages/clide-js/test/src/utils/camel-case.test.ts b/packages/clide-js/test/units/utils/camel-case.test.ts similarity index 100% rename from packages/clide-js/test/src/utils/camel-case.test.ts rename to packages/clide-js/test/units/utils/camel-case.test.ts diff --git a/packages/clide-js/test/units/utils/format-file-name.test.ts b/packages/clide-js/test/units/utils/format-file-name.test.ts new file mode 100644 index 0000000..2e03d74 --- /dev/null +++ b/packages/clide-js/test/units/utils/format-file-name.test.ts @@ -0,0 +1,23 @@ +import { formatFileName } from 'src/utils/format-file-name'; +import { describe, expect, it } from 'vitest'; + +describe('format-file-name', () => { + it('adds the .js extension', () => { + expect(formatFileName('foo')).toBe('foo.js'); + }); + + it('replaces non-.js extensions', () => { + expect(formatFileName('foo.ts')).toBe('foo.js'); + }); + + it('handles multiple file extensions', () => { + expect(formatFileName('foo.test.ts.js.ts')).toBe('foo.test.ts.js.js'); + }); + + it('handles multiple dots in a file name', () => { + expect(formatFileName('[...foo].ts')).toBe('[...foo].js'); + expect(formatFileName('[...foo]')).toBe('[...foo].js'); + expect(formatFileName('foo..bar.ts')).toBe('foo..bar.js'); + expect(formatFileName('foo..bar')).toBe('foo..bar.js'); + }); +}); diff --git a/packages/clide-js/test/src/utils/parse-file-name.test.ts b/packages/clide-js/test/units/utils/parse-file-name.test.ts similarity index 100% rename from packages/clide-js/test/src/utils/parse-file-name.test.ts rename to packages/clide-js/test/units/utils/parse-file-name.test.ts diff --git a/packages/clide-js/test/src/utils/remove-file-extension.test.ts b/packages/clide-js/test/units/utils/remove-file-extension.test.ts similarity index 100% rename from packages/clide-js/test/src/utils/remove-file-extension.test.ts rename to packages/clide-js/test/units/utils/remove-file-extension.test.ts diff --git a/packages/clide-js/test/utils/command-modules.test.ts b/packages/clide-js/test/utils/command-modules.test.ts new file mode 100644 index 0000000..6413ac4 --- /dev/null +++ b/packages/clide-js/test/utils/command-modules.test.ts @@ -0,0 +1,101 @@ +// Must be imported first +import { CommandModule } from 'src/core/command'; +import { describe, expect, it, test } from 'vitest'; +import { + mockCommandModule, + mockCommandModules, + mockCommandStringModules, +} from './command-modules'; + +const modules = { + 'commands/foo.js': { + handler: ({ next, data }) => next(data), + }, + 'commands/foo/bar.js': { + handler: ({ next, data }) => next(data), + }, + 'commands/foo/bar/baz.js': { + handler: ({ end, data }) => end(data), + }, +} satisfies Record; + +describe('mockCommandModule', () => { + it('Mocks and unmocks single command modules', async () => { + const [path] = Object.entries(modules)[0]; + + const { mock, unmock } = mockCommandModule(path); + expect(mock).toMatchObject({ + handler: expect.any(Function), + }); + + mock.handler({ next: (data: unknown) => data, data: 'foo' } as any); + expect(mock.handler).toHaveBeenCalledTimes(1); + + const imported = await import(path); + expect(imported.handler).toEqual(expect.any(Function)); + + unmock(); + expect(() => import(path)).rejects.toThrow(); + }); + + it('Uses the provided module', async () => { + const [path, module] = Object.entries(modules)[0]; + + const { mock } = mockCommandModule(path, { + handler: module.handler, + }); + expect(mock.handler).toBe(module.handler); + }); +}); + +describe('mockCommandModules', () => { + it('Mocks and unmocks multiple command modules', async () => { + const { mocks, unmock } = mockCommandModules(modules); + + expect(mocks).toEqual(modules); + + for (const [path, module] of Object.entries(modules)) { + const imported = await import(path); + expect(imported.handler).toBe(module.handler); + } + + unmock(); + for (const path of Object.keys(modules)) { + expect(() => import(path)).rejects.toThrow(); + } + }); +}); + +describe('mockCommandStringModules', () => { + test('Mocks and unmocks command string modules', async () => { + const { mocks, unmock } = mockCommandStringModules( + 'foo bar baz', + 'commands', + ); + + expect(mocks).toEqual({ + foo: expect.objectContaining({ handler: expect.any(Function) }), + bar: expect.objectContaining({ handler: expect.any(Function) }), + baz: expect.objectContaining({ handler: expect.any(Function) }), + }); + + for (const path of Object.keys(modules)) { + const imported = await import(path); + expect(imported.handler).toEqual(expect.any(Function)); + } + + unmock(); + for (const path of Object.keys(modules)) { + expect(() => import(path)).rejects.toThrow(); + } + }); + + it('Ignores options', async () => { + const { mocks } = mockCommandStringModules('foo --bar baz', 'commands'); + + expect(mocks).toEqual({ + foo: expect.objectContaining({ handler: expect.any(Function) }), + baz: expect.objectContaining({ handler: expect.any(Function) }), + }); + }); +}); diff --git a/packages/clide-js/test/mocks/command-modules.ts b/packages/clide-js/test/utils/command-modules.ts similarity index 73% rename from packages/clide-js/test/mocks/command-modules.ts rename to packages/clide-js/test/utils/command-modules.ts index 7203a57..31c2a16 100644 --- a/packages/clide-js/test/mocks/command-modules.ts +++ b/packages/clide-js/test/utils/command-modules.ts @@ -1,14 +1,14 @@ -import path from 'node:path'; +import path from 'path'; import { CommandModule } from 'src/core/command'; import { NotFoundError } from 'src/core/errors'; import { parseCommand } from 'src/core/parse'; -import { formatFileName } from 'src/core/resolve'; import { State } from 'src/core/state'; -import { vi } from 'vitest'; +import { formatFileName } from 'src/utils/format-file-name'; +import { Mock, vi } from 'vitest'; const mockCommandDirs = new Map>(); -vi.mock('node:fs', async (importOriginal) => { +vi.mock('fs', async (importOriginal) => { const fs = (await importOriginal()) as typeof import('fs'); const mod = { ...fs, @@ -88,10 +88,13 @@ export async function unmockAllCommandModules() { * handler: ({ result, data }) => result(data), * }); */ -export function mockCommandModule( +export function mockCommandModule( commandPath: string, - commandModule?: CommandModule, -) { + commandModule?: T, +): { + mock: undefined extends T ? MockCommandModule : T; + unmock: () => void; +} { const formattedFilePath = formatFileName(commandPath); const commandDir = path.dirname(commandPath); const commandName = path.basename(commandPath); @@ -104,7 +107,7 @@ export function mockCommandModule( } const mock = commandModule || { - handler: vi.fn(({ next, data }: State) => next(data)), + handler: vi.fn(({ next, data }) => next(data)), }; vi.doMock(formattedFilePath, () => { @@ -115,7 +118,7 @@ export function mockCommandModule( }); return { - mock, + mock: mock as any, unmock: () => { vi.doUnmock(formattedFilePath); }, @@ -135,17 +138,16 @@ export function mockCommandModule( * }, * }); */ -export function mockCommandModules( - commandModules: Record, -) { +export function mockCommandModules< + TModules extends Record, +>(commandModules: TModules) { const results = Object.entries(commandModules).map( ([commandPath, commandModule]) => mockCommandModule(commandPath, commandModule), ); + return { - mocks: Object.fromEntries( - results.map(({ mock }, i) => [Object.keys(commandModules)[i], mock]), - ), + mocks: commandModules, unmock: () => { for (const { unmock } of results) unmock(); }, @@ -156,10 +158,11 @@ export function mockCommandModules( * Mock the command modules for the given command string so that they can be * imported and resolved during testing. */ -export function mockCommandStringModules( - commandString: string, +export function mockCommandStringModules( + commandString: TCommandString, commandsDir: string, ) { + const mocks: Record = {}; const unMockFns: (() => void)[] = []; const { tokens } = parseCommand(commandString, {}); let commandPath = commandsDir; @@ -167,15 +170,41 @@ export function mockCommandStringModules( // mock each command in the command string for (const token of tokens) { commandPath = path.join(commandPath, token); - const { unmock } = mockCommandModule(commandPath, { + const { mock, unmock } = mockCommandModule(commandPath, { handler: vi.fn(({ next, data }) => next(data)), }); + mocks[token] = mock; unMockFns.push(unmock); } return { + mocks: mocks as CommandMap, unmock: () => { for (const unmock of unMockFns) unmock(); }, }; } + +type MockCommandModule = { + handler: Mock<[state: Readonly]>; +}; + +/** + * A utility type that converts a command string into a map of command modules + * with the command names as keys. + */ +type CommandMap< + TString extends string, + TValues = any, + TResult extends Record = {}, +> = Prettify< + TString extends `${infer Word} ${infer Rest}` + ? Word extends `-${string}` + ? CommandMap + : CommandMap + : TString extends `-${string}` + ? TResult + : TResult & { [k in TString]: TValues } +>; + +type Prettify = { [K in keyof T]: T[K] } & unknown; diff --git a/packages/clide-js/test/utils/index.ts b/packages/clide-js/test/utils/index.ts new file mode 100644 index 0000000..99e0065 --- /dev/null +++ b/packages/clide-js/test/utils/index.ts @@ -0,0 +1,13 @@ +export { + mockCommandModule, + mockCommandModules, + mockCommandStringModules, + unmockAllCommandModules, +} from './command-modules'; + +export { + mockPlugin, + mockPluginInfo, + notReadyMockPlugin, + readyMockPlugin, +} from './plugin'; diff --git a/packages/clide-js/test/mocks/plugin.ts b/packages/clide-js/test/utils/plugin.ts similarity index 100% rename from packages/clide-js/test/mocks/plugin.ts rename to packages/clide-js/test/utils/plugin.ts diff --git a/packages/clide-js/tsconfig.json b/packages/clide-js/tsconfig.json index 2ee0626..16778c0 100644 --- a/packages/clide-js/tsconfig.json +++ b/packages/clide-js/tsconfig.json @@ -4,17 +4,12 @@ "include": ["./*.ts", "src", "test"], "exclude": ["node_modules"], "compilerOptions": { - "module": "ESNext", - "moduleResolution": "Node", - "baseUrl": "./", - "rootDir": "./", - "outDir": "./dist", + "baseUrl": ".", + "rootDir": ".", + "outDir": "dist", "paths": { "src/*": ["./src/*"], "test/*": ["./test/*"] }, - "allowSyntheticDefaultImports": true, - "target": "ESNext", - "lib": ["ESNext"] } } diff --git a/packages/clide-js/tsup.config.ts b/packages/clide-js/tsup.config.ts index 5e47481..cc5c2ed 100644 --- a/packages/clide-js/tsup.config.ts +++ b/packages/clide-js/tsup.config.ts @@ -1,7 +1,10 @@ import { defineConfig } from 'tsup'; export default defineConfig({ - entry: ['src/index.ts'], + entry: { + index: 'src/index.ts', + 'test-utils': 'test/utils/index.ts', + }, format: ['esm', 'cjs'], sourcemap: true, dts: true, diff --git a/packages/clide-plugin-command-menu/example/cli.ts b/packages/clide-plugin-command-menu/example/cli.ts index c8385e7..63d9920 100644 --- a/packages/clide-plugin-command-menu/example/cli.ts +++ b/packages/clide-plugin-command-menu/example/cli.ts @@ -1,12 +1,12 @@ import { help, run } from 'clide-js'; -import { commandMenu } from '../src/command-menu.js'; +import { commandMenu } from 'src/command-menu.js'; run({ plugins: [ help(), commandMenu({ title: 'Command Menu', - skip: (options) => !!options.help, + enabled: (options) => !options.help, }), ], }); diff --git a/packages/clide-plugin-command-menu/package.json b/packages/clide-plugin-command-menu/package.json index 470859d..3fdfce5 100644 --- a/packages/clide-plugin-command-menu/package.json +++ b/packages/clide-plugin-command-menu/package.json @@ -11,7 +11,7 @@ }, "scripts": { "build": "tsup", - "dev": "NODE_ENV=development ts-node --esm example/cli.ts", + "dev": "NODE_ENV=development tesm-node example/cli.ts", "test": "vitest --reporter=verbose", "test:ci": "vitest --run", "typecheck": "tsc --noEmit" @@ -21,7 +21,8 @@ }, "dependencies": { "cfonts": "^3.2.0", - "colors": "^1.4.0" + "colors": "^1.4.0", + "tesm-node": "^1.3.1" }, "devDependencies": { "@types/node": "^20.12.7", diff --git a/packages/clide-plugin-command-menu/src/command-menu-prompt.ts b/packages/clide-plugin-command-menu/src/command-menu-prompt.ts index dcfed70..9570c23 100644 --- a/packages/clide-plugin-command-menu/src/command-menu-prompt.ts +++ b/packages/clide-plugin-command-menu/src/command-menu-prompt.ts @@ -9,8 +9,8 @@ import { resolveCommand, } from 'clide-js'; import colors from 'colors'; -import fs from 'node:fs'; -import path from 'node:path'; +import fs from 'fs'; +import path from 'path'; import { Choice } from 'prompts'; import { CommandMenuOptions } from './command-menu.js'; diff --git a/packages/clide-plugin-command-menu/src/command-menu.test.ts b/packages/clide-plugin-command-menu/src/command-menu.test.ts index 6511699..c3487f9 100644 --- a/packages/clide-plugin-command-menu/src/command-menu.test.ts +++ b/packages/clide-plugin-command-menu/src/command-menu.test.ts @@ -1,16 +1,40 @@ -import { run } from 'clide-js'; -import { expect, test, vi } from 'vitest'; +// Must be imported first +import { mockCommandModule } from 'clide-js/test-utils'; + +import { ResolvedCommand, passThroughCommand, run } from 'clide-js'; +import { Mock, beforeEach, expect, test, vi } from 'vitest'; import { commandMenu } from './command-menu'; -import { commandMenuPrompt } from './command-menu-prompt'; +import { + CommandMenuPromptOptions, + commandMenuPrompt, +} from './command-menu-prompt'; vi.mock('./command-menu-prompt', async (importOriginal) => { const original: any = await importOriginal(); return { ...original, - commandMenuPrompt: vi.fn(() => []), + commandMenuPrompt: vi.fn<[CommandMenuPromptOptions], ResolvedCommand[]>( + ({ commandsDir }): ResolvedCommand[] => [ + { + command: { + handler: vi.fn(({ next, data }) => next(data)), + }, + commandName: 'mock-command', + remainingCommandString: '', + commandPath: `${commandsDir}/mock-command`, + commandTokens: ['mock-command'], + subcommandsDir: `${commandsDir}/mock-command`, + params: {}, + }, + ], + ), }; }); +beforeEach(() => { + (commandMenuPrompt as Mock).mockClear(); +}); + test('It shows the command menu when no command string is provided', async () => { await run({ command: '', @@ -22,3 +46,27 @@ test('It shows the command menu when no command string is provided', async () => expect(commandMenuPrompt).toHaveBeenCalled(); }); + +test('It shows the command menu when the last resolved command requires a subcommand', async () => { + mockCommandModule('commands/foo', passThroughCommand); + + await run({ + command: 'foo', + commandsDir: 'commands', + plugins: [commandMenu()], + }); + + expect(commandMenuPrompt).toHaveBeenCalled(); +}); + +test("It doesn't show the command menu when the last resolved command doesn't require a subcommand", async () => { + mockCommandModule('commands/foo'); + + await run({ + command: 'foo', + commandsDir: 'commands', + plugins: [], + }); + + expect(commandMenuPrompt).not.toHaveBeenCalled(); +}); diff --git a/packages/clide-plugin-command-menu/src/command-menu.ts b/packages/clide-plugin-command-menu/src/command-menu.ts index 9d5040c..659460e 100644 --- a/packages/clide-plugin-command-menu/src/command-menu.ts +++ b/packages/clide-plugin-command-menu/src/command-menu.ts @@ -1,4 +1,4 @@ -import { Context, OptionValues, Plugin } from 'clide-js'; +import { OptionValues, Plugin } from 'clide-js'; import { commandMenuPrompt } from './command-menu-prompt.js'; export interface CommandMenuOptions { @@ -35,13 +35,12 @@ export interface CommandMenuOptions { maxDescriptionLength?: number; /** - * A predicate function that determines whether the command menu should be - * shown. + * Whether the command menu is enabled. Can be a boolean or a predicate + * function that determines whether the command menu should be shown. The + * predicate will only be called if the conditions for showing the menu are + * met. */ - skip?: ( - options: OptionValues, - context: Context, - ) => Promise | boolean; + enabled?: boolean | ((options: OptionValues) => Promise | boolean); } /** @@ -64,15 +63,19 @@ export function commandMenu({ message = 'Choose a command', showDescriptions = true, maxDescriptionLength = 60, - skip: _shouldSkip, + enabled, }: CommandMenuOptions = {}): Plugin { return { - name: 'clide-command-menu', - version: '0.0.0', + name: 'command-menu', + version: '0.1.0', description: 'Prompts the user to select a subcommand when a command requires one.', init: ({ hooks }) => { + if (enabled === false) return true; + const isPermanentlyEnabled = enabled === true; + const isEnabledFn = typeof enabled === 'function' ? enabled : () => true; + // Show the menu if the command string is empty hooks.on( 'beforeResolve', @@ -83,10 +86,13 @@ export function commandMenu({ addResolvedCommands, skip, }) => { - const parsed = await context.parseCommand(); - const shouldSkip = await _shouldSkip?.(parsed.options, context); + if (commandString.length) return; - if (shouldSkip) return; + if (!isPermanentlyEnabled) { + const parsed = await context.parseCommand(); + const isEnabled = await isEnabledFn(parsed.options); + if (!isEnabled) return; + } if (!commandString.length) { const selectedCommands = await commandMenuPrompt({ @@ -112,10 +118,11 @@ export function commandMenu({ hooks.on( 'afterResolve', async ({ context, resolvedCommands, addResolvedCommands }) => { - const parsed = await context.parseCommand(); - const shouldSkip = await _shouldSkip?.(parsed.options, context); - - if (shouldSkip) return; + if (!isPermanentlyEnabled) { + const parsed = await context.parseCommand(); + const isEnabled = await isEnabledFn(parsed.options); + if (!isEnabled) return; + } const lastResolved = resolvedCommands[resolvedCommands.length - 1]; diff --git a/packages/clide-plugin-command-menu/tsconfig.json b/packages/clide-plugin-command-menu/tsconfig.json index fae9c50..5bb75e0 100644 --- a/packages/clide-plugin-command-menu/tsconfig.json +++ b/packages/clide-plugin-command-menu/tsconfig.json @@ -4,13 +4,11 @@ "include": ["./*.ts", "src", "example"], "exclude": ["node_modules"], "compilerOptions": { - "module": "ESNext", - "moduleResolution": "Node", - "baseUrl": "./", - "rootDir": "./", - "outDir": "./dist", - "allowSyntheticDefaultImports": true, - "target": "ESNext", - "lib": ["ESNext"] + "baseUrl": ".", + "rootDir": ".", + "outDir": "dist", + "paths": { + "src/*": ["./src/*"] + } } } diff --git a/packages/eslint-config/.eslintrc.js b/packages/eslint-config/.eslintrc.js deleted file mode 100644 index a3fd5fe..0000000 --- a/packages/eslint-config/.eslintrc.js +++ /dev/null @@ -1,31 +0,0 @@ -const { resolve } = require("node:path"); - -const project = resolve(process.cwd(), "tsconfig.json"); - -module.exports = { - extends: [ - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "plugin:import/recommended", - - /** - * Prettier must be the last extension in the list. - * Prettier works best if you disable all other ESLint rules relating to - * code formatting, and only enable rules that detect potential bugs. - * (If another active ESLint rule disagrees with prettier about how code - * should be formatted, it will be impossible to avoid lint errors.) - */ - "prettier", - ].map(require.resolve), - parserOptions: { - project, - }, - settings: { - "import/resolver": { - typescript: { - project, - }, - }, - }, - ignorePatterns: ["node_modules/", "dist/"], -}; diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json deleted file mode 100644 index 0e000bb..0000000 --- a/packages/eslint-config/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "eslint-config", - "license": "MIT", - "version": "0.0.0", - "private": true, - "exports": "./.eslintrc.js", - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.7.0", - "@typescript-eslint/parser": "^7.7.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.1", - "typescript": "^5.4.5" - } -} diff --git a/packages/extras/package.json b/packages/extras/package.json index e8670aa..b47e908 100644 --- a/packages/extras/package.json +++ b/packages/extras/package.json @@ -33,7 +33,6 @@ "@types/yargs": "^17.0.24", "dotenv": "^16.3.1", "nodemon": "^3.0.1", - "prettier-plugin-organize-imports": "^3.2.3", "tesm-node": "^1.3.0", "ts-node": "^10.9.1", "tsconfig": "*", @@ -41,9 +40,7 @@ "tsup": "^7.2.0", "typescript": "^5.2.2" }, - "files": [ - "dist" - ], + "files": ["dist"], "keywords": [ "argument", "args", diff --git a/packages/extras/src/config/utils/JsonStore.ts b/packages/extras/src/config/utils/JsonStore.ts index 21ae84e..e0f67ec 100644 --- a/packages/extras/src/config/utils/JsonStore.ts +++ b/packages/extras/src/config/utils/JsonStore.ts @@ -1,7 +1,7 @@ import Ajv, { ValidateFunction } from 'ajv'; import type { JSONSchema } from 'json-schema-typed'; -import fs from 'node:fs'; -import path from 'node:path'; +import fs from 'fs'; +import path from 'path'; // TODO: see if this is still needed // const Ajv = _Ajv.default diff --git a/packages/extras/src/config/utils/getAppConfigPath.ts b/packages/extras/src/config/utils/getAppConfigPath.ts index f2714c2..6774f87 100644 --- a/packages/extras/src/config/utils/getAppConfigPath.ts +++ b/packages/extras/src/config/utils/getAppConfigPath.ts @@ -1,5 +1,5 @@ -import fs from 'node:fs'; -import path from 'node:path'; +import fs from 'fs'; +import path from 'path'; import { getAppRootDir } from './getAppRootDir'; export const DEFAULT_CONFIG_FILE_NAME = 'clide.config'; diff --git a/packages/extras/src/config/utils/getAppRootDir.ts b/packages/extras/src/config/utils/getAppRootDir.ts index 4a2a675..1b8bdd0 100644 --- a/packages/extras/src/config/utils/getAppRootDir.ts +++ b/packages/extras/src/config/utils/getAppRootDir.ts @@ -1,5 +1,5 @@ -import fs from 'node:fs'; -import path from 'node:path'; +import fs from 'fs'; +import path from 'path'; /** * Get the path to the nearest app root directory based on the presence of a diff --git a/packages/extras/src/config/utils/getOSConfigDir.ts b/packages/extras/src/config/utils/getOSConfigDir.ts index 8776322..c4546a9 100644 --- a/packages/extras/src/config/utils/getOSConfigDir.ts +++ b/packages/extras/src/config/utils/getOSConfigDir.ts @@ -1,5 +1,5 @@ -import os from 'node:os'; -import path from 'node:path'; +import os from 'os'; +import path from 'path'; /** * Get the path to an app specific config directory based on operating system @@ -22,11 +22,11 @@ export function getOSConfigDir(projectName: string): string { configDir = process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming'); // https://github.com/dirs-dev/directories-rs/issues/62 - } else if (platform === 'darwin') { - // macOS - // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html - // https://apple.fandom.com/wiki/Application_Support_folder - configDir = path.join(homeDir, 'Library', 'Application Support'); + } else if (platform === 'darwin') { + // macOS + // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html + // https://apple.fandom.com/wiki/Application_Support_folder + configDir = path.join(homeDir, 'Library', 'Application Support'); } else { // Linux and others // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html diff --git a/packages/clide-js/test/src/utils/deep-freeze.test.ts b/packages/extras/src/utils/deep-freeze.test.ts similarity index 100% rename from packages/clide-js/test/src/utils/deep-freeze.test.ts rename to packages/extras/src/utils/deep-freeze.test.ts diff --git a/packages/clide-js/src/utils/deep-freeze.ts b/packages/extras/src/utils/deep-freeze.ts similarity index 100% rename from packages/clide-js/src/utils/deep-freeze.ts rename to packages/extras/src/utils/deep-freeze.ts diff --git a/packages/extras/src/utils/json-store.ts b/packages/extras/src/utils/json-store.ts index 19376a3..c753fc4 100644 --- a/packages/extras/src/utils/json-store.ts +++ b/packages/extras/src/utils/json-store.ts @@ -1,7 +1,7 @@ import Ajv, { ValidateFunction } from 'ajv'; import type { JSONSchema } from 'json-schema-typed'; -import fs from 'node:fs'; -import path from 'node:path'; +import fs from 'fs'; +import path from 'path'; // TODO: see if this is still needed // const Ajv = _Ajv.default diff --git a/packages/tsconfig/base.json b/packages/tsconfig/base.json index 66b6f59..f56e7c9 100644 --- a/packages/tsconfig/base.json +++ b/packages/tsconfig/base.json @@ -1,13 +1,18 @@ { + "$schema": "https://json.schemastore.org/tsconfig", "extends": "@tsconfig/node-lts/tsconfig.json", "display": "Default", "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "target": "esnext", "composite": false, "isolatedModules": true, "noUnusedLocals": true, "noUnusedParameters": false, "preserveWatchOutput": true, - "strictNullChecks": true + "strictNullChecks": true, + "allowSyntheticDefaultImports": true }, "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index ff40a62..ccd6be3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,11 +2,6 @@ # yarn lockfile v1 -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - "@ampproject/remapping@^2.2.1": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -69,6 +64,60 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@biomejs/biome@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-1.7.2.tgz#982ca58428aecd9e85c1af7fa656f60615181235" + integrity sha512-6Skx9N47inLQzYi9RKgJ7PBnUnaHnMe/imqX43cOcJjZtfMnQLxEvfM2Eyo7gChkwrZlwc+VbA4huFRjw2fsYA== + optionalDependencies: + "@biomejs/cli-darwin-arm64" "1.7.2" + "@biomejs/cli-darwin-x64" "1.7.2" + "@biomejs/cli-linux-arm64" "1.7.2" + "@biomejs/cli-linux-arm64-musl" "1.7.2" + "@biomejs/cli-linux-x64" "1.7.2" + "@biomejs/cli-linux-x64-musl" "1.7.2" + "@biomejs/cli-win32-arm64" "1.7.2" + "@biomejs/cli-win32-x64" "1.7.2" + +"@biomejs/cli-darwin-arm64@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.7.2.tgz#2beabb95f62a5c46101ca842adea539cd760b922" + integrity sha512-CrldIueHivWEWmeTkK8bTXajeX53F8i2Rrkkt8cPZyMtzkrwxf8Riq4a/jz3SQBHkxHFT4TqGbSTNMXe3X1ogA== + +"@biomejs/cli-darwin-x64@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.7.2.tgz#538473a0112d84357433750a9c2189347f9325b4" + integrity sha512-UELnLJuJOsTL9meArvn8BtiXDURyPil2Ej9me2uVpEvee8UQdqd/bssP5we400OWShlL1AAML4fn6d2WX5332g== + +"@biomejs/cli-linux-arm64-musl@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.7.2.tgz#a990e735d5f33bfc8eaea8fbc53db215d7f69948" + integrity sha512-kKYZiem7Sj7wI0dpVxJlK7C+TFQwzO/ctufIGXGJAyEmUe9vEKSzV8CXpv+JIRiTWyqaZJ4K+eHz4SPdPCv05w== + +"@biomejs/cli-linux-arm64@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.7.2.tgz#0f8186dd4a807d273c14659e859d8d86c24fb948" + integrity sha512-Z1CSGQE6fHz55gkiFHv9E8wEAaSUd7dHSRaxSCBa7utonHqpIeMbvj3Evm1w0WfGLFDtRXLV1fTfEdM0FMTOhA== + +"@biomejs/cli-linux-x64-musl@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.7.2.tgz#2f9d5715d4a02bd4644bab9ed7f7680229ba8303" + integrity sha512-x10LpGMepDrLS+h2TZ6/T7egpHjGKtiI4GuShNylmBQJWfTotbFf9eseHggrqJ4WZf9yrGoVYrtbxXftuB95sQ== + +"@biomejs/cli-linux-x64@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-1.7.2.tgz#0071ea5a25f5ec5bbc1b3e6984a454bd198fbd6f" + integrity sha512-vXXyox8/CQijBxAu0+r8FfSO7JlC4tob3PbaFda8gPJFRz2uFJw39HtxVUwbTV1EcU6wSPh4SiRu5sZfP1VHrQ== + +"@biomejs/cli-win32-arm64@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.7.2.tgz#baa561b05c30ea22c9308f63161ddf63a6baa781" + integrity sha512-kRXdlKzcU7INf6/ldu0nVmkOgt7bKqmyXRRCUqqaJfA32+9InTbkD8tGrHZEVYIWr+eTuKcg16qZVDsPSDFZ8g== + +"@biomejs/cli-win32-x64@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-1.7.2.tgz#cc13738545ea4a6bc4fee0bf0108a0e90dc1e173" + integrity sha512-qHTtpAs+CNglAAuaTy09htoqUhrQyd3nd0aGTuLNqD10h1llMVi8WFZfoa+e5MuDSfYtMK6nW2Tbf6WgzzR1Qw== + "@changesets/apply-release-plan@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@changesets/apply-release-plan/-/apply-release-plan-7.0.0.tgz#ce3c3dfc5720550a5d592b54ad2f411f816ec5ff" @@ -505,62 +554,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== - -"@eslint/eslintrc@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.0.2.tgz#36180f8e85bf34d2fe3ccc2261e8e204a411ab4e" - integrity sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^10.0.1" - globals "^14.0.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@9.1.1": - version "9.1.1" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.1.1.tgz#eb0f82461d12779bbafc1b5045cde3143d350a8a" - integrity sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ== - -"@humanwhocodes/config-array@^0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" - integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== - dependencies: - "@humanwhocodes/object-schema" "^2.0.3" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== - -"@humanwhocodes/retry@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.2.3.tgz#c9aa036d1afa643f1250e83150f39efb3a15a631" - integrity sha512-X38nUbachlb01YMlvPFojKoiXq+LzZvuSce70KPMPdeM1Rj03k4dR7lDslhbqXn3Ang4EU3+EAmwEAsbrjHW3g== - "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -660,7 +653,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -788,7 +781,7 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/cli-table@^0.3.2", "@types/cli-table@^0.3.4": +"@types/cli-table@^0.3.2": version "0.3.4" resolved "https://registry.yarnpkg.com/@types/cli-table/-/cli-table-0.3.4.tgz#ecc3efce1b4d13503de59d2ddb49b8f9fd7203e7" integrity sha512-GsALrTL69mlwbAw/MHF1IPTadSLZQnsxe7a80G8l4inN/iEXCOcVeT/S7aRc6hbhqzL9qZ314kHPDQnQ3ev+HA== @@ -798,16 +791,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== -"@types/json-schema@^7.0.15": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - "@types/minimist@^1.2.0": version "1.2.5" resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" @@ -838,7 +821,7 @@ "@types/node" "*" kleur "^3.0.3" -"@types/semver@^7.5.0", "@types/semver@^7.5.8": +"@types/semver@^7.5.0": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== @@ -862,92 +845,6 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.0.tgz#bf34a02f221811505b8bf2f31060c8560c1bb0a3" - integrity sha512-GJWR0YnfrKnsRoluVO3PRb9r5aMZriiMMM/RHj5nnTrBy1/wIgk76XCtCKcnXGjpZQJQRFtGV9/0JJ6n30uwpQ== - dependencies: - "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.7.0" - "@typescript-eslint/type-utils" "7.7.0" - "@typescript-eslint/utils" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.3.1" - natural-compare "^1.4.0" - semver "^7.6.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/parser@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.7.0.tgz#6b1b3ce76c5de002c43af8ae933613b0f2b4bcc6" - integrity sha512-fNcDm3wSwVM8QYL4HKVBggdIPAy9Q41vcvC/GtDobw3c4ndVT3K6cqudUmjHPw8EAp4ufax0o58/xvWaP2FmTg== - dependencies: - "@typescript-eslint/scope-manager" "7.7.0" - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/typescript-estree" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.7.0.tgz#3f0db079b275bb8b0cb5be7613fb3130cfb5de77" - integrity sha512-/8INDn0YLInbe9Wt7dK4cXLDYp0fNHP5xKLHvZl3mOT5X17rK/YShXaiNmorl+/U4VKCVIjJnx4Ri5b0y+HClw== - dependencies: - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - -"@typescript-eslint/type-utils@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.7.0.tgz#36792ff4209a781b058de61631a48df17bdefbc5" - integrity sha512-bOp3ejoRYrhAlnT/bozNQi3nio9tIgv3U5C0mVDdZC7cpcQEDZXvq8inrHYghLVwuNABRqrMW5tzAv88Vy77Sg== - dependencies: - "@typescript-eslint/typescript-estree" "7.7.0" - "@typescript-eslint/utils" "7.7.0" - debug "^4.3.4" - ts-api-utils "^1.3.0" - -"@typescript-eslint/types@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.7.0.tgz#23af4d24bf9ce15d8d301236e3e3014143604f27" - integrity sha512-G01YPZ1Bd2hn+KPpIbrAhEWOn5lQBrjxkzHkWvP6NucMXFtfXoevK82hzQdpfuQYuhkvFDeQYbzXCjR1z9Z03w== - -"@typescript-eslint/typescript-estree@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.0.tgz#b5dd6383b4c6a852d7b256a37af971e8982be97f" - integrity sha512-8p71HQPE6CbxIBy2kWHqM1KGrC07pk6RJn40n0DSc6bMOBBREZxSDJ+BmRzc8B5OdaMh1ty3mkuWRg4sCFiDQQ== - dependencies: - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/utils@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.7.0.tgz#3d2b6606a60ac34f3c625facfb3b3ab7e126f58d" - integrity sha512-LKGAXMPQs8U/zMRFXDZOzmMKgFv3COlxUQ+2NMPhbqgVm6R1w+nU1i4836Pmxu9jZAuIeyySNrN/6Rc657ggig== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.15" - "@types/semver" "^7.5.8" - "@typescript-eslint/scope-manager" "7.7.0" - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/typescript-estree" "7.7.0" - semver "^7.6.0" - -"@typescript-eslint/visitor-keys@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.0.tgz#950148cf1ac11562a2d903fdf7acf76714a2dc9e" - integrity sha512-h0WHOj8MhdhY8YWkzIF30R379y0NqyOHExI9N9KCzvmu05EgG4FumeYa3ccfKUSphyWkWQE1ybVrgz/Pbam6YA== - dependencies: - "@typescript-eslint/types" "7.7.0" - eslint-visitor-keys "^3.4.3" - "@vitest/coverage-v8@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-1.5.0.tgz#2eb4472b497d820934b1a4e4d387547d3be62ba3" @@ -1016,11 +913,6 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - acorn-walk@^8.1.1, acorn-walk@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" @@ -1031,16 +923,6 @@ acorn@^8.11.3, acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - ajv@^8.12.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" @@ -1120,11 +1002,6 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - array-buffer-byte-length@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" @@ -1133,36 +1010,12 @@ array-buffer-byte-length@^1.0.1: call-bind "^1.0.5" is-array-buffer "^3.0.4" -array-includes@^3.1.7: - version "3.1.8" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" - integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - is-string "^1.0.7" - array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.findlastindex@^1.2.3: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" - integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.flat@^1.2.3, array.prototype.flat@^1.3.2: +array.prototype.flat@^1.2.3: version "1.3.2" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== @@ -1172,16 +1025,6 @@ array.prototype.flat@^1.2.3, array.prototype.flat@^1.3.2: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - arraybuffer.prototype.slice@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" @@ -1282,11 +1125,6 @@ call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: get-intrinsic "^1.2.4" set-function-length "^1.2.1" -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - camelcase-keys@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" @@ -1331,7 +1169,7 @@ chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.2: +chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1464,7 +1302,7 @@ cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -1530,14 +1368,7 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@^4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1564,11 +1395,6 @@ deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - defaults@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" @@ -1623,13 +1449,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - dotenv@^16.3.1, dotenv@^16.4.5: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" @@ -1665,7 +1484,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: +es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== @@ -1745,7 +1564,7 @@ es-set-tostringtag@^2.0.3: has-tostringtag "^1.0.2" hasown "^2.0.1" -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: +es-shim-unscopables@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== @@ -1829,146 +1648,11 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-prettier@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" - integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== - -eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== - dependencies: - debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" - -eslint-module-utils@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" - integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== - dependencies: - debug "^3.2.7" - -eslint-plugin-import@^2.29.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" - debug "^3.2.7" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" - semver "^6.3.1" - tsconfig-paths "^3.15.0" - -eslint-scope@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc" - integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint-visitor-keys@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" - integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== - -eslint@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.1.0.tgz#262625f6b0921f7550f128a0098d05ecaad989c6" - integrity sha512-1TCBecGFQtItia2o39P7Z4BK1X7ByNPxAiWJvwiyTGcOwYnTiiASgMpNA6a+beu8cFPhEDWvPf6mIlYUJv6sgA== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^3.0.2" - "@eslint/js" "9.1.1" - "@humanwhocodes/config-array" "^0.13.0" - "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.2.3" - "@nodelib/fs.walk" "^1.2.8" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - escape-string-regexp "^4.0.0" - eslint-scope "^8.0.1" - eslint-visitor-keys "^4.0.0" - espree "^10.0.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^8.0.0" - find-up "^5.0.0" - glob-parent "^6.0.2" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - 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.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f" - integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww== - dependencies: - acorn "^8.11.3" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^4.0.0" - esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - estree-walker@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" @@ -1976,11 +1660,6 @@ estree-walker@^3.0.3: dependencies: "@types/estree" "^1.0.0" -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -2025,7 +1704,7 @@ external-editor@^3.1.0: iconv-lite "^0.4.24" tmp "^0.0.33" -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: +fast-deep-equal@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -2041,16 +1720,6 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -2073,13 +1742,6 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" - integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== - dependencies: - flat-cache "^4.0.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -2118,19 +1780,6 @@ find-yarn-workspace-root2@1.2.16: micromatch "^4.0.2" pkg-dir "^4.2.0" -flat-cache@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" - integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.4" - -flatted@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== - for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -2248,13 +1897,6 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - glob@^10.3.10, glob@^10.3.7: version "10.3.12" resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" @@ -2278,11 +1920,6 @@ glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" - integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== - globalthis@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" @@ -2290,7 +1927,7 @@ globalthis@^1.0.3: dependencies: define-properties "^1.1.3" -globby@^11.0.0, globby@^11.0.3, globby@^11.1.0: +globby@^11.0.0, globby@^11.0.3: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -2319,11 +1956,6 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - hard-rejection@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" @@ -2412,24 +2044,11 @@ ignore-by-default@^1.0.1: resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== -ignore@^5.2.0, ignore@^5.3.1: +ignore@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -2509,7 +2128,7 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.13.1: +is-core-module@^2.13.0: version "2.13.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== @@ -2555,7 +2174,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -2586,11 +2205,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -2734,18 +2348,6 @@ js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.6.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -2756,11 +2358,6 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - json-schema-traverse@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" @@ -2771,18 +2368,6 @@ json-schema-typed@^8.0.1: resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-8.0.1.tgz#826ee39e3b6cef536f85412ff048d3ff6f19dfa0" integrity sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg== -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - json5@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" @@ -2800,13 +2385,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -keyv@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -2829,14 +2407,6 @@ kleur@^4.1.5: resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - lilconfig@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3" @@ -2902,11 +2472,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -3042,14 +2607,14 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.1, minimatch@^9.0.3, minimatch@^9.0.4: +minimatch@^9.0.1, minimatch@^9.0.3: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== @@ -3065,7 +2630,7 @@ minimist-options@^4.0.2: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.0, minimist@^1.2.6: +minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -3095,11 +2660,6 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -3114,11 +2674,6 @@ nanoid@^3.3.7: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - node-domexception@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" @@ -3210,34 +2765,6 @@ object.assign@^4.1.5: has-symbols "^1.0.3" object-keys "^1.1.1" -object.fromentries@^2.0.7: - version "2.0.8" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" - integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.groupby@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" - integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - -object.values@^1.1.7: - version "1.2.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" - integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -3259,18 +2786,6 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" -optionator@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -3352,13 +2867,6 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -3511,26 +3019,11 @@ preferred-pm@^3.0.0: path-exists "^4.0.0" which-pm "2.0.0" -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-plugin-organize-imports@^3.2.3, prettier-plugin-organize-imports@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz#77967f69d335e9c8e6e5d224074609309c62845e" - integrity sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog== - prettier@^2.7.1: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== -prettier@^3.2.5: - version "3.2.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" - integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== - pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -3652,17 +3145,12 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - resolve-from@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve@^1.10.0, resolve@^1.22.4: +resolve@^1.10.0: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -3744,12 +3232,7 @@ safe-regex-test@^1.0.3: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.3, semver@^7.6.0: +semver@^7.5.3: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== @@ -4030,11 +3513,6 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - strip-literal@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.0.tgz#6d82ade5e2e74f5c7e8739b6c84692bd65f0bd2a" @@ -4100,11 +3578,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" @@ -4177,11 +3650,6 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== -ts-api-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" @@ -4206,16 +3674,6 @@ ts-node@^10.9.1, ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths@^3.15.0: - version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" - integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - tsconfig-paths@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" @@ -4320,13 +3778,6 @@ turbo@latest: turbo-windows-64 "1.13.2" turbo-windows-arm64 "1.13.2" -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"