From 18c5024710ee811dc5cc6a93359b2258cc044dc6 Mon Sep 17 00:00:00 2001 From: Codevalve <6092+codevalve@users.noreply.github.com> Date: Thu, 28 Nov 2024 22:05:51 -0600 Subject: [PATCH 1/6] feat: prepare for npm package - Add bin scripts for CLI commands - Add CLI dependencies (commander, inquirer, ora) - Add build and release scripts - Update package metadata - Create initial build script --- package.json | 31 +++++++++++++++++--- scripts/build.js | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 scripts/build.js diff --git a/package.json b/package.json index 57e019f..2468423 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,10 @@ "description": "A smart development session startup script for human and AI collaboration", "main": "src/index.js", "type": "module", + "bin": { + "dsb": "./bin/dsb.js", + "create-dev-session-buddy": "./bin/create-dev-session-buddy.js" + }, "engines": { "node": ">=16.0.0" }, @@ -13,7 +17,10 @@ "test:shell": "bats tests/shell/*.bats", "lint:shell": "shellcheck --severity=error src/**/*.sh", "test:watch": "jest --watch", - "test:coverage": "jest --coverage" + "test:coverage": "jest --coverage", + "prepare": "npm run build", + "build": "node scripts/build.js", + "release": "standard-version" }, "keywords": [ "development", @@ -22,18 +29,34 @@ "collaboration", "session", "startup", - "project-standards" + "project-standards", + "cli", + "template", + "vue", + "git" ], - "author": "", + "author": "CodeValve", + "repository": { + "type": "git", + "url": "git+https://github.com/codevalve/dev-session-buddy.git" + }, + "bugs": { + "url": "https://github.com/codevalve/dev-session-buddy/issues" + }, + "homepage": "https://codevalve.github.io/dev-session-buddy", "license": "MIT", "dependencies": { "chalk": "^5.3.0", + "commander": "^11.1.0", + "inquirer": "^9.2.12", + "ora": "^7.0.1", "yaml": "^2.3.4" }, "devDependencies": { "bats": "^1.11.0", "jest": "^29.7.0", "js-yaml": "^4.1.0", - "shellcheck": "^3.0.0" + "shellcheck": "^3.0.0", + "standard-version": "^9.5.0" } } diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 0000000..944b621 --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,75 @@ +#!/usr/bin/env node + +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; +import { promises as fs } from 'fs'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const projectRoot = join(__dirname, '..'); + +async function build() { + console.log('Building Dev Session Buddy...'); + + // Ensure bin directory exists + await fs.mkdir(join(projectRoot, 'bin'), { recursive: true }); + + // Create CLI entry points + const dsbCli = `#!/usr/bin/env node +import { Command } from 'commander'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const program = new Command(); + +program + .version('${process.env.npm_package_version || '0.1.0'}') + .description('Dev Session Buddy - Your AI-Powered Development Companion'); + +// TODO: Add commands + +program.parse(process.argv); +`; + + const createDsbCli = `#!/usr/bin/env node +import { Command } from 'commander'; +import inquirer from 'inquirer'; +import chalk from 'chalk'; +import ora from 'ora'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const program = new Command(); + +program + .version('${process.env.npm_package_version || '0.1.0'}') + .description('Create a new project with Dev Session Buddy') + .argument('[name]', 'Project name') + .option('-f, --framework ', 'Framework template to use') + .option('-p, --preset ', 'Configuration preset (full, minimal, or team)') + .action(async (name, options) => { + // TODO: Implement project creation + console.log(chalk.green('Creating new project...')); + }); + +program.parse(process.argv); +`; + + // Write CLI files + await fs.writeFile(join(projectRoot, 'bin', 'dsb.js'), dsbCli); + await fs.writeFile(join(projectRoot, 'bin', 'create-dev-session-buddy.js'), createDsbCli); + + // Make CLI files executable + await fs.chmod(join(projectRoot, 'bin', 'dsb.js'), '755'); + await fs.chmod(join(projectRoot, 'bin', 'create-dev-session-buddy.js'), '755'); + + console.log('Build completed successfully!'); +} + +build().catch(console.error); From ef86d2ae9cdeeb1ad7738fe628e2a7d5fd0e111e Mon Sep 17 00:00:00 2001 From: Codevalve <6092+codevalve@users.noreply.github.com> Date: Thu, 28 Nov 2024 22:09:19 -0600 Subject: [PATCH 2/6] feat: add framework templates - Add minimal framework-agnostic template - Add Vue.js template with best practices - Include configuration and documentation --- src/templates/minimal/README.md | 76 ++++++++++++++ src/templates/minimal/config-template.yaml | 44 ++++++++ src/templates/minimal/session-start.sh | 26 +++++ src/templates/vue/README.md | 112 +++++++++++++++++++++ src/templates/vue/config-template.yaml | 103 +++++++++++++++++++ 5 files changed, 361 insertions(+) create mode 100644 src/templates/minimal/README.md create mode 100644 src/templates/minimal/config-template.yaml create mode 100644 src/templates/minimal/session-start.sh create mode 100644 src/templates/vue/README.md create mode 100644 src/templates/vue/config-template.yaml diff --git a/src/templates/minimal/README.md b/src/templates/minimal/README.md new file mode 100644 index 0000000..28f5d96 --- /dev/null +++ b/src/templates/minimal/README.md @@ -0,0 +1,76 @@ +# Minimal Template + +A framework-agnostic template for Dev Session Buddy that provides basic development session setup and project standards. + +## Features + +- Basic development session setup +- Environment file management +- Dependency installation check +- Development server auto-start (if configured) +- Project standards configuration +- Git hooks setup +- Editor configuration + +## Usage + +To use this template: + +```bash +# Create a new project +npx create-dev-session-buddy my-project --framework minimal + +# Or initialize in an existing project +cd my-project +npx dsb init --framework minimal +``` + +## Configuration + +The template provides a base configuration in `config-template.yaml` that you can customize: + +- Development requirements +- Script definitions +- Tool configurations +- Project standards + +## Project Structure + +``` +. +├── .dev-session-buddy/ # Dev Session Buddy configuration and cache +├── docs/ # Project documentation +├── src/ # Source code +├── tests/ # Test files +├── .env.example # Example environment variables +├── .gitignore # Git ignore rules +├── package.json # Project dependencies and scripts +└── README.md # Project documentation +``` + +## Standards + +This template enforces: + +- Conventional commits +- Documentation requirements +- Code style (Standard) +- Test coverage requirements +- Editor configuration + +## Customization + +1. Modify `config-template.yaml` to adjust standards and requirements +2. Update `session-start.sh` to add custom setup steps +3. Add framework-specific configurations as needed + +## Contributing + +To contribute improvements to this template: + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Submit a pull request + +Please follow our [contribution guidelines](../../CONTRIBUTING.md). diff --git a/src/templates/minimal/config-template.yaml b/src/templates/minimal/config-template.yaml new file mode 100644 index 0000000..cf8feb7 --- /dev/null +++ b/src/templates/minimal/config-template.yaml @@ -0,0 +1,44 @@ +# Dev Session Buddy Configuration Template +# Minimal Framework-Agnostic Template + +name: "Project Name" +framework: minimal +preset: minimal +version: 0.1.0 + +# Development environment requirements +requirements: + node: ">=16.0.0" + npm: ">=8.0.0" + +# Development scripts +scripts: + start: ./session-start.sh + test: npm test + +# Development tools configuration +tools: + git: + hooks: + pre-commit: npm test + editor: + formatOnSave: true + rulers: [80, 100] + tabSize: 2 + +# Project standards +standards: + commits: + conventional: true + scopes: [] + testing: + coverage: 80 + frameworks: [] + documentation: + required: true + locations: + - README.md + - docs/ + code: + style: standard + maxLineLength: 100 diff --git a/src/templates/minimal/session-start.sh b/src/templates/minimal/session-start.sh new file mode 100644 index 0000000..173ddf8 --- /dev/null +++ b/src/templates/minimal/session-start.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Dev Session Buddy - Minimal Template +# This is a framework-agnostic template that provides basic development session setup + +echo "Starting development session..." + +# Check if .env exists, create if not +if [ ! -f .env ]; then + echo "Creating .env file..." + cp .env.example .env +fi + +# Install dependencies if needed +if [ ! -d "node_modules" ]; then + echo "Installing dependencies..." + npm install +fi + +# Run development server if package.json has a dev script +if grep -q "\"dev\":" package.json; then + echo "Starting development server..." + npm run dev +else + echo "No development server configured. Add a 'dev' script to package.json to enable automatic server startup." +fi diff --git a/src/templates/vue/README.md b/src/templates/vue/README.md new file mode 100644 index 0000000..57b8196 --- /dev/null +++ b/src/templates/vue/README.md @@ -0,0 +1,112 @@ +# Vue.js Template + +A comprehensive Vue.js template for Dev Session Buddy that provides a full-featured development environment setup with best practices and standards for Vue.js projects. + +## Features + +- Vue.js 3 with Composition API +- Vite for fast development and building +- Comprehensive development session setup +- Vue.js best practices and standards +- Automated testing setup with Vitest +- Git hooks configuration +- Editor settings for Vue files +- Component documentation requirements + +## Usage + +To use this template: + +```bash +# Create a new project +npx create-dev-session-buddy my-vue-app --framework vue + +# Or initialize in an existing Vue.js project +cd my-vue-app +npx dsb init --framework vue +``` + +## Configuration + +The template provides a comprehensive configuration in `config-template.yaml`: + +- Vue.js specific requirements +- Development scripts +- Tool configurations +- Vue.js coding standards +- Testing setup +- Documentation requirements + +## Project Structure + +``` +. +├── .dev-session-buddy/ # Dev Session Buddy configuration and cache +├── docs/ # Project documentation +├── src/ # Source code +│ ├── assets/ # Static assets +│ ├── components/ # Vue components +│ ├── composables/ # Vue composables +│ ├── router/ # Vue Router configuration +│ ├── stores/ # Pinia stores +│ └── views/ # Vue views/pages +├── tests/ # Test files +│ ├── unit/ # Unit tests +│ └── e2e/ # End-to-end tests +├── .env.example # Example environment variables +├── .gitignore # Git ignore rules +├── package.json # Project dependencies and scripts +├── vite.config.js # Vite configuration +└── README.md # Project documentation +``` + +## Standards + +This template enforces Vue.js best practices: + +- Composition API usage +- Vue.js Style Guide adherence +- Component documentation +- Unit testing requirements +- Code style (@vue/airbnb) +- Git workflow + +## Development Workflow + +1. Start development session: + ```bash + npm start + ``` + +2. Development server: + ```bash + npm run dev + ``` + +3. Run tests: + ```bash + npm test + ``` + +4. Build for production: + ```bash + npm run build + ``` + +## Customization + +1. Modify `config-template.yaml` to adjust Vue.js standards +2. Update `session-start.sh` to add custom setup steps +3. Configure Vite and testing setup +4. Adjust editor settings for Vue files + +## Contributing + +To contribute improvements to this template: + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Submit a pull request + +Please follow our [contribution guidelines](../../CONTRIBUTING.md). diff --git a/src/templates/vue/config-template.yaml b/src/templates/vue/config-template.yaml new file mode 100644 index 0000000..48e1969 --- /dev/null +++ b/src/templates/vue/config-template.yaml @@ -0,0 +1,103 @@ +# Dev Session Buddy Configuration Template +# Vue.js Framework Template + +name: "Project Name" +framework: vue +preset: full +version: 0.1.0 +type: "Single Page Application" + +# Development environment requirements +requirements: + node: ">=16.0.0" + npm: ">=8.0.0" + vue: "^3.0.0" + vite: "^4.0.0" + +# Development scripts +scripts: + start: ./session-start.sh + test: vitest + dev: vite + build: vite build + preview: vite preview + +# Development tools configuration +tools: + required: + - node + - npm + - git + - vue + - vite + optional: + - docker + - docker-compose + - nvm + git: + hooks: + pre-commit: npm test + pre-push: npm run build + editor: + formatOnSave: true + rulers: [80, 100] + tabSize: 2 + vueFiles: + scriptFormat: true + styleFormat: true + templateFormat: true + +# Project standards +standards: + key_points: + - "Use Composition API for new components" + - "Follow Vue.js Style Guide" + - "Write unit tests for components" + - "Document component props and events" + branches: + types: + - feature + - bugfix + - hotfix + - release + - chore + commit: + conventional: true + scopes: + - ui + - api + - core + - deps + - config + - docs + - test + testing: + coverage: 80 + frameworks: + - vitest + - "@vue/test-utils" + documentation: + required: true + locations: + - README.md + - docs/ + - src/**/*.vue + code: + style: "@vue/airbnb" + maxLineLength: 100 + +# Development workflow +workflow: + dev_server: "npm run dev" + test: "npm test" + build: "npm run build" + +# Style guide +style_guide: + key_points: + - "Use PascalCase for component names" + - "Use kebab-case for events" + - "Props should use camelCase" + - "Components should be single responsibility" + - "Use computed properties for derived data" + - "Keep components under 300 lines" From 9088efb459325f8832bdce19738d0f2f9854c064 Mon Sep 17 00:00:00 2001 From: Codevalve <6092+codevalve@users.noreply.github.com> Date: Thu, 28 Nov 2024 22:31:36 -0600 Subject: [PATCH 3/6] feat: prepare for npm package publication - Rename CLI command from dsb to dev-session-buddy - Fix template manager configuration initialization - Implement full CLI commands in build script - Add comprehensive environment checks - Update documentation with new command names - Add test directory structure --- README.md | 111 +- bin/create-dev-session-buddy.js | 64 + bin/dev-session-buddy.js | 147 + coverage/lcov-report/base.css | 224 ++ coverage/lcov-report/block-navigation.js | 87 + coverage/lcov-report/favicon.png | Bin 0 -> 445 bytes coverage/lcov-report/index.html | 101 + coverage/lcov-report/prettify.css | 1 + coverage/lcov-report/prettify.js | 2 + coverage/lcov-report/sort-arrow-sprite.png | Bin 0 -> 138 bytes coverage/lcov-report/sorter.js | 196 ++ coverage/lcov.info | 0 package-lock.json | 2634 +++++++++++++++-- package.json | 2 +- scripts/build.js | 200 +- src/template-manager.js | 143 + src/templates/minimal/README.md | 2 +- src/templates/vue/README.md | 2 +- src/utils.js | 143 + test/cli-test/init-test-2/README.md | 112 + .../init-test-2/dev-session-buddy.yaml | 92 + test/cli-test/init-test-2/package.json | 25 + test/cli-test/init-test-2/session-start.sh | 109 + test/cli-test/init-test/README.md | 76 + .../cli-test/init-test/dev-session-buddy.yaml | 39 + test/cli-test/init-test/session-start.sh | 26 + test/cli-test/test-project/README.md | 76 + .../test-project/dev-session-buddy.yaml | 37 + test/cli-test/test-project/session-start.sh | 26 + test/cli-test/vue-test/README.md | 112 + test/cli-test/vue-test/dev-session-buddy.yaml | 90 + test/cli-test/vue-test/package.json | 25 + test/cli-test/vue-test/session-start.sh | 109 + tests/config/default.yaml | 6 + 34 files changed, 4811 insertions(+), 208 deletions(-) create mode 100755 bin/create-dev-session-buddy.js create mode 100755 bin/dev-session-buddy.js create mode 100644 coverage/lcov-report/base.css create mode 100644 coverage/lcov-report/block-navigation.js create mode 100644 coverage/lcov-report/favicon.png create mode 100644 coverage/lcov-report/index.html create mode 100644 coverage/lcov-report/prettify.css create mode 100644 coverage/lcov-report/prettify.js create mode 100644 coverage/lcov-report/sort-arrow-sprite.png create mode 100644 coverage/lcov-report/sorter.js create mode 100644 coverage/lcov.info create mode 100644 src/template-manager.js create mode 100644 src/utils.js create mode 100644 test/cli-test/init-test-2/README.md create mode 100644 test/cli-test/init-test-2/dev-session-buddy.yaml create mode 100644 test/cli-test/init-test-2/package.json create mode 100755 test/cli-test/init-test-2/session-start.sh create mode 100644 test/cli-test/init-test/README.md create mode 100644 test/cli-test/init-test/dev-session-buddy.yaml create mode 100644 test/cli-test/init-test/session-start.sh create mode 100644 test/cli-test/test-project/README.md create mode 100644 test/cli-test/test-project/dev-session-buddy.yaml create mode 100644 test/cli-test/test-project/session-start.sh create mode 100644 test/cli-test/vue-test/README.md create mode 100644 test/cli-test/vue-test/dev-session-buddy.yaml create mode 100644 test/cli-test/vue-test/package.json create mode 100755 test/cli-test/vue-test/session-start.sh create mode 100644 tests/config/default.yaml diff --git a/README.md b/README.md index 008c53c..7c3fdeb 100644 --- a/README.md +++ b/README.md @@ -159,24 +159,115 @@ dev-session-buddy/ └── docs/ # Documentation ``` +### Common Configurations + +Here are some common configuration examples: + +```yaml +# Basic configuration +name: "My Project" +tools: + required: + - git + - node + optional: + - docker + +# Full configuration with all options +name: "Advanced Project" +description: "A complex project with multiple tools" +tools: + required: + - git + - node + - npm + - python3 + optional: + - docker + - aws-cli + - terraform +standards: + - "Use TypeScript for new features" + - "Write unit tests for all components" + - "Follow GitFlow branching strategy" +git: + main_branch: main + develop_branch: develop + feature_prefix: feature + fix_prefix: fix +frameworks: + - vue + - typescript +ci: + provider: github-actions + node_versions: + - 16 + - 18 +``` + +### Advanced Usage + +#### Custom Templates + +Create a custom template for your framework: + +1. Create a new directory in `src/templates/`: + ```bash + mkdir src/templates/my-framework + ``` + +2. Add required files: + - `session-start.sh`: Main script + - `config-template.yaml`: Default configuration + - `README.md`: Template documentation + +#### Multiple Projects + +Use Dev Session Buddy across multiple projects: + +1. Install globally: + ```bash + npm install -g @devsessionbuddy/cli + ``` + +2. Initialize in any project: + ```bash + dsb init --framework vue + ``` + ### Troubleshooting -1. **Script Permission Issues** +Common issues and solutions: + +1. **Script Permission Errors** ```bash chmod +x session-start.sh ``` -2. **Missing Tools** - - Ensure all required tools are installed - - Check PATH environment variable - - Run `which ` to verify installation +2. **Missing Dependencies** + - Ensure Node.js version is 16 or higher + - Run `npm install` in project root + - Check PATH for required tools -3. **Configuration Issues** - - Verify YAML syntax - - Ensure config file is in correct location +3. **Configuration Not Found** + - Ensure config file is in project root or config/ - Check file permissions - -For more help, please [open an issue](https://github.com/codevalve/dev-session-buddy/issues). + - Validate YAML syntax + +4. **Git Integration Issues** + - Ensure you're in a git repository + - Check git installation: `git --version` + - Verify git remote configuration + +5. **Framework Template Issues** + - Verify template exists for your framework + - Check template files permissions + - Ensure all template files were copied + +For more complex issues: +1. Enable debug mode: `DEBUG=true ./session-start.sh` +2. Check logs in `~/.dev-session-buddy/logs/` +3. [Open an issue](https://github.com/codevalve/dev-session-buddy/issues) with debug output ## Testing 🧪 diff --git a/bin/create-dev-session-buddy.js b/bin/create-dev-session-buddy.js new file mode 100755 index 0000000..b17ecc5 --- /dev/null +++ b/bin/create-dev-session-buddy.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node +import { Command } from 'commander'; +import inquirer from 'inquirer'; +import chalk from 'chalk'; +import ora from 'ora'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; +import { TemplateManager } from '../src/template-manager.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const program = new Command(); + +program + .version('0.1.0') + .description('Create a new project with Dev Session Buddy') + .argument('[name]', 'Project name') + .option('-f, --framework ', 'Framework to use (minimal, vue)') + .option('-p, --preset ', 'Configuration preset (minimal, full, team)') + .action(async (name, options) => { + try { + // If no name provided, prompt for it + if (!name) { + const answers = await inquirer.prompt([ + { + type: 'input', + name: 'projectName', + message: 'What is your project name?', + validate: input => input.length > 0 || 'Project name is required' + } + ]); + name = answers.projectName; + } + + // Create project directory + const projectDir = join(process.cwd(), name); + const spinner = ora('Creating new project...').start(); + + try { + const framework = options.framework || 'minimal'; + const preset = options.preset || 'full'; + + const templateManager = new TemplateManager(); + await templateManager.applyTemplate(projectDir, framework, preset); + + spinner.succeed('Project created successfully!'); + + console.log('\nNext steps:'); + console.log(`1. cd ${name}`); + console.log('2. npm install'); + console.log('3. npm start'); + } catch (error) { + spinner.fail('Project creation failed'); + console.error(chalk.red(error.message)); + process.exit(1); + } + } catch (error) { + console.error(chalk.red(error.message)); + process.exit(1); + } + }); + +program.parse(process.argv); diff --git a/bin/dev-session-buddy.js b/bin/dev-session-buddy.js new file mode 100755 index 0000000..5be7aa2 --- /dev/null +++ b/bin/dev-session-buddy.js @@ -0,0 +1,147 @@ +#!/usr/bin/env node +import { Command } from 'commander'; +import inquirer from 'inquirer'; +import chalk from 'chalk'; +import ora from 'ora'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; +import { TemplateManager } from '../src/template-manager.js'; +import { commandExists, getToolVersion, checkVersion } from '../src/utils.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const program = new Command(); + +program + .version('0.1.0') + .description('Dev Session Buddy - Your AI-Powered Development Companion'); + +program + .command('doctor') + .description('Check development environment setup') + .action(async () => { + const spinner = ora('Checking environment').start(); + + try { + const checks = [ + { + name: 'Node.js', + version: process.version, + required: '>=16.0.0', + command: 'node', + versionCommand: 'node --version' + }, + { + name: 'npm', + required: '>=8.0.0', + command: 'npm', + versionCommand: 'npm --version' + }, + { + name: 'Git', + required: '>=2.0.0', + command: 'git', + versionCommand: 'git --version' + }, + { + name: 'yq', + required: '>=4.0.0', + command: 'yq', + versionCommand: 'yq --version' + } + ]; + + const results = []; + + for (const check of checks) { + const exists = await commandExists(check.command); + if (!exists) { + results.push({ + name: check.name, + status: 'missing', + message: `${check.name} is not installed` + }); + continue; + } + + const version = check.version || await getToolVersion(check.versionCommand); + if (!version) { + results.push({ + name: check.name, + status: 'error', + message: `Could not determine ${check.name} version` + }); + continue; + } + + const isValid = checkVersion(version, check.required); + results.push({ + name: check.name, + status: isValid ? 'ok' : 'outdated', + version, + required: check.required, + message: isValid ? null : `${check.name} version ${version} does not meet requirement ${check.required}` + }); + } + + spinner.succeed('Environment check complete'); + + // Display results + console.log(''); + for (const result of results) { + const icon = { + ok: chalk.green('✓'), + outdated: chalk.yellow('!'), + missing: chalk.red('✗'), + error: chalk.red('✗') + }[result.status]; + + const version = result.version ? `: ${result.version}` : ''; + console.log(`${icon} ${result.name}${version}`); + + if (result.message) { + console.log(` ${chalk.dim(result.message)}`); + } + } + + // Exit with error if any checks failed + const hasErrors = results.some(r => ['missing', 'error', 'outdated'].includes(r.status)); + if (hasErrors) { + process.exit(1); + } + } catch (error) { + spinner.fail('Environment check failed'); + console.error(chalk.red(error.message)); + process.exit(1); + } + }); + +program + .command('init') + .description('Initialize Dev Session Buddy in an existing project') + .option('-f, --framework ', 'Framework to use (minimal, vue)') + .option('-p, --preset ', 'Configuration preset (minimal, full, team)') + .action(async (options) => { + const spinner = ora('Initializing Dev Session Buddy').start(); + + try { + const framework = options.framework || 'minimal'; + const preset = options.preset || 'full'; + + const templateManager = new TemplateManager(); + await templateManager.applyTemplate(process.cwd(), framework, preset); + + spinner.succeed('Dev Session Buddy initialized successfully!'); + + console.log('\nNext steps:'); + console.log('1. Review the configuration in dev-session-buddy.yaml'); + console.log('2. Run ./session-start.sh to begin your development session'); + } catch (error) { + spinner.fail('Initialization failed'); + console.error(chalk.red(error.message)); + process.exit(1); + } + }); + +program.parse(process.argv); diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css new file mode 100644 index 0000000..f418035 --- /dev/null +++ b/coverage/lcov-report/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/coverage/lcov-report/block-navigation.js b/coverage/lcov-report/block-navigation.js new file mode 100644 index 0000000..cc12130 --- /dev/null +++ b/coverage/lcov-report/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/coverage/lcov-report/favicon.png b/coverage/lcov-report/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..c1525b811a167671e9de1fa78aab9f5c0b61cef7 GIT binary patch literal 445 zcmV;u0Yd(XP))rP{nL}Ln%S7`m{0DjX9TLF* zFCb$4Oi7vyLOydb!7n&^ItCzb-%BoB`=x@N2jll2Nj`kauio%aw_@fe&*}LqlFT43 z8doAAe))z_%=P%v^@JHp3Hjhj^6*Kr_h|g_Gr?ZAa&y>wxHE99Gk>A)2MplWz2xdG zy8VD2J|Uf#EAw*bo5O*PO_}X2Tob{%bUoO2G~T`@%S6qPyc}VkhV}UifBuRk>%5v( z)x7B{I~z*k<7dv#5tC+m{km(D087J4O%+<<;K|qwefb6@GSX45wCK}Sn*> + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ Unknown% + Statements + 0/0 +
+ + +
+ Unknown% + Branches + 0/0 +
+ + +
+ Unknown% + Functions + 0/0 +
+ + +
+ Unknown% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/prettify.css b/coverage/lcov-report/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/lcov-report/prettify.js b/coverage/lcov-report/prettify.js new file mode 100644 index 0000000..b322523 --- /dev/null +++ b/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/lcov-report/sort-arrow-sprite.png b/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed68316eb3f65dec9063332d2f69bf3093bbfab GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qh}Z>jv*C{$p!i!8j}?a+@3A= zIAGwzjijN=FBi!|L1t?LM;Q;gkwn>2cAy-KV{dn nf0J1DIvEHQu*n~6U}x}qyky7vi4|9XhBJ7&`njxgN@xNA8m%nc literal 0 HcmV?d00001 diff --git a/coverage/lcov-report/sorter.js b/coverage/lcov-report/sorter.js new file mode 100644 index 0000000..2bb296a --- /dev/null +++ b/coverage/lcov-report/sorter.js @@ -0,0 +1,196 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if ( + row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()) + ) { + row.style.display = ''; + } else { + row.style.display = 'none'; + } + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/coverage/lcov.info b/coverage/lcov.info new file mode 100644 index 0000000..e69de29 diff --git a/package-lock.json b/package-lock.json index c98ff7c..50021f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,21 @@ "license": "MIT", "dependencies": { "chalk": "^5.3.0", + "commander": "^11.1.0", + "inquirer": "^9.2.12", + "ora": "^7.0.1", "yaml": "^2.3.4" }, + "bin": { + "create-dev-session-buddy": "bin/create-dev-session-buddy.js", + "dsb": "bin/dsb.js" + }, "devDependencies": { "bats": "^1.11.0", "jest": "^29.7.0", "js-yaml": "^4.1.0", - "shellcheck": "^3.0.0" + "shellcheck": "^3.0.0", + "standard-version": "^9.5.0" }, "engines": { "node": ">=16.0.0" @@ -522,6 +530,25 @@ "dev": true, "license": "MIT" }, + "node_modules/@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", + "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1192,6 +1219,13 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.10.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", @@ -1202,6 +1236,13 @@ "undici-types": "~6.20.0" } }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -1226,11 +1267,17 @@ "dev": true, "license": "MIT" }, + "node_modules/add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "license": "MIT", "dependencies": { "type-fest": "^0.21.3" @@ -1246,7 +1293,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1286,6 +1332,23 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -1446,7 +1509,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -1563,7 +1625,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -1646,6 +1707,24 @@ "node": ">=6" } }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001684", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz", @@ -1689,6 +1768,12 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "license": "MIT" + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -1712,6 +1797,42 @@ "dev": true, "license": "MIT" }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -1727,6 +1848,15 @@ "node": ">=12" } }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -1749,7 +1879,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1762,15 +1891,27 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -1779,6 +1920,306 @@ "dev": true, "license": "MIT" }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/conventional-changelog": { + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.25.tgz", + "integrity": "sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", + "conventional-changelog-preset-loader": "^2.3.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-atom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", + "dev": true, + "license": "ISC", + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-codemirror": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", + "dev": true, + "license": "ISC", + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-config-spec": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", + "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", + "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-core": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", + "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-ember": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", + "dev": true, + "license": "ISC", + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-eslint": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", + "dev": true, + "license": "ISC", + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-express": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-jquery": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", + "dev": true, + "license": "ISC", + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-jshint": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-preset-loader": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", + "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commits-filter": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commits-parser": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", + "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-recommended-bump": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", + "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.3.4", + "conventional-commits-filter": "^2.0.7", + "conventional-commits-parser": "^3.2.0", + "git-raw-commits": "^2.0.8", + "git-semver-tags": "^4.1.1", + "meow": "^8.0.0", + "q": "^1.5.1" + }, + "bin": { + "conventional-recommended-bump": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1863,10 +2304,30 @@ "node": ">= 8" } }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1881,6 +2342,43 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decompress": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", @@ -2076,6 +2574,18 @@ "node": ">=0.10.0" } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -2112,6 +2622,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -2139,6 +2659,105 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotgitignore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", + "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", + "dev": true, + "license": "ISC", + "dependencies": { + "find-up": "^3.0.0", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotgitignore/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.5.67", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.67.tgz", @@ -2163,7 +2782,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/end-of-stream": { @@ -2316,6 +2934,20 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2343,6 +2975,32 @@ "pend": "~1.2.0" } }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-type": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", @@ -2469,6 +3127,77 @@ "node": ">=8.0.0" } }, + "node_modules/get-pkg-repo": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "get-pkg-repo": "src/cli.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-pkg-repo/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/get-pkg-repo/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/get-pkg-repo/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-pkg-repo/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -2482,6 +3211,67 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/git-raw-commits": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "dev": true, + "license": "MIT", + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/git-semver-tags": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "meow": "^8.0.0", + "semver": "^6.0.0" + }, + "bin": { + "git-semver-tags": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", + "dev": true, + "license": "BSD", + "dependencies": { + "ini": "^1.3.2" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2582,11 +3372,42 @@ "dev": true, "license": "ISC" }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2644,9 +3465,42 @@ "node": ">= 0.4" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, "license": "MIT" @@ -2661,11 +3515,22 @@ "node": ">=10.17.0" } }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -2712,6 +3577,16 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2728,9 +3603,193 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, "license": "ISC" }, + "node_modules/inquirer": { + "version": "9.3.7", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.7.tgz", + "integrity": "sha512-LJKFHCSeIRq9hanN14IlOtPSTe3lNES7TYDTE2xxdAy1LS5rYphajK1qtwvj3YmQXvvk0U2Vbmcni8P9EIQW9w==", + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.3", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/inquirer/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -2758,7 +3817,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2774,6 +3832,18 @@ "node": ">=6" } }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", @@ -2791,6 +3861,26 @@ "node": ">=0.12.0" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -2804,6 +3894,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3993,6 +5108,13 @@ "node": ">=6" } }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -4020,6 +5142,43 @@ "node": ">=6" } }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -4047,49 +5206,129 @@ "dev": true, "license": "MIT" }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" + "node": ">=4" } }, - "node_modules/make-dir": { + "node_modules/load-json-file/node_modules/parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.5.3" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "license": "MIT", + "dependencies": { + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "license": "ISC", "bin": { @@ -4109,6 +5348,19 @@ "tmpl": "1.0.5" } }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -4122,6 +5374,139 @@ "node": ">=10" } }, + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/meow/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4147,12 +5532,21 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4166,6 +5560,41 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4173,6 +5602,15 @@ "dev": true, "license": "MIT" }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4180,6 +5618,13 @@ "dev": true, "license": "MIT" }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -4194,6 +5639,35 @@ "dev": true, "license": "MIT" }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -4251,7 +5725,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" @@ -4263,59 +5736,141 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, + "node_modules/ora": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-7.0.1.tgz", + "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.3.0", + "log-symbols": "^5.1.0", + "stdin-discarder": "^0.1.0", + "string-width": "^6.1.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/ora/node_modules/string-width": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz", + "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^10.2.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" } }, "node_modules/parse-json": { @@ -4374,6 +5929,29 @@ "dev": true, "license": "MIT" }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -4510,6 +6088,28 @@ ], "license": "MIT" }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -4517,6 +6117,138 @@ "dev": true, "license": "MIT" }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -4540,6 +6272,20 @@ "dev": true, "license": "MIT" }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4601,6 +6347,22 @@ "node": ">=10" } }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -4626,6 +6388,24 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4647,6 +6427,12 @@ ], "license": "MIT" }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, "node_modules/seek-bzip": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", @@ -4661,31 +6447,353 @@ "seek-table": "bin/seek-bzip-table" } }, + "node_modules/seek-bzip/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT" + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shellcheck": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shellcheck/-/shellcheck-3.0.0.tgz", + "integrity": "sha512-pCG1++KHj1ZpkZWokMvyIFNk7oLnZ6hxJtJ3p+EFvYuEPWTqubuuaa2TP1BtgMk34Z9g1xe3b7gI2R97Fr2iqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "decompress": "^4.2.1", + "envalid": "^8.0.0", + "global-agent": "^3.0.0" + }, + "bin": { + "shellcheck": "bin/shellcheck.js" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/standard-version": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz", + "integrity": "sha512-3zWJ/mmZQsOaO+fOlsa0+QK90pwhNd042qEcw6hKFNoLFs7peGyvPffpEBbK/DSGPbyOvli0mUIFv5A4qTjh2Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "chalk": "^2.4.2", + "conventional-changelog": "3.1.25", + "conventional-changelog-config-spec": "2.1.0", + "conventional-changelog-conventionalcommits": "4.6.3", + "conventional-recommended-bump": "6.1.0", + "detect-indent": "^6.0.0", + "detect-newline": "^3.1.0", + "dotgitignore": "^2.1.0", + "figures": "^3.1.0", + "find-up": "^5.0.0", + "git-semver-tags": "^4.0.0", + "semver": "^7.1.1", + "stringify-package": "^1.0.1", + "yargs": "^16.0.0" + }, + "bin": { + "standard-version": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/standard-version/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/standard-version/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "node_modules/standard-version/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, "license": "MIT" }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "node_modules/standard-version/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/standard-version/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.13.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=10" @@ -4694,12 +6802,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "node_modules/standard-version/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, "engines": { "node": ">=10" }, @@ -4707,127 +6828,145 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/standard-version/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/standard-version/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "license": "MIT", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/shellcheck": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shellcheck/-/shellcheck-3.0.0.tgz", - "integrity": "sha512-pCG1++KHj1ZpkZWokMvyIFNk7oLnZ6hxJtJ3p+EFvYuEPWTqubuuaa2TP1BtgMk34Z9g1xe3b7gI2R97Fr2iqQ==", + "node_modules/standard-version/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", "dependencies": { - "decompress": "^4.2.1", - "envalid": "^8.0.0", - "global-agent": "^3.0.0" - }, - "bin": { - "shellcheck": "bin/shellcheck.js" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=18.12.0" + "node": ">=4" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/standard-version/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/standard-version/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, - "license": "BSD-3-Clause", + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, + "node_modules/stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "bl": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" + "node_modules/stdin-discarder/node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, + "node_modules/stdin-discarder/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, + "node_modules/stdin-discarder/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 6" } }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -4837,7 +6976,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, "license": "MIT" }, "node_modules/string-length": { @@ -4858,7 +6996,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -4869,11 +7006,18 @@ "node": ">=8" } }, + "node_modules/stringify-package": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", + "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", + "deprecated": "This module is not used anymore, and has been replaced by @npmcli/package-json", + "dev": true, + "license": "ISC" + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -4912,6 +7056,19 @@ "node": ">=6" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4929,7 +7086,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -4985,6 +7141,16 @@ "node": ">=8" } }, + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -4992,6 +7158,43 @@ "dev": true, "license": "MIT" }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -5019,11 +7222,20 @@ "node": ">=8.0" } }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true, "license": "0BSD" }, "node_modules/type-detect": { @@ -5040,7 +7252,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -5049,6 +7260,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/unbzip2-stream": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", @@ -5102,7 +7334,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/v8-to-istanbul": { @@ -5120,6 +7351,17 @@ "node": ">=10.12.0" } }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -5130,6 +7372,15 @@ "makeerror": "1.0.12" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5146,6 +7397,13 @@ "node": ">= 8" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -5292,6 +7550,18 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 2468423..9ef60f1 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "src/index.js", "type": "module", "bin": { - "dsb": "./bin/dsb.js", + "dev-session-buddy": "./bin/dev-session-buddy.js", "create-dev-session-buddy": "./bin/create-dev-session-buddy.js" }, "engines": { diff --git a/scripts/build.js b/scripts/build.js index 944b621..303fdf3 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -15,10 +15,14 @@ async function build() { await fs.mkdir(join(projectRoot, 'bin'), { recursive: true }); // Create CLI entry points - const dsbCli = `#!/usr/bin/env node -import { Command } from 'commander'; + const cliContent = `import { Command } from 'commander'; +import inquirer from 'inquirer'; +import chalk from 'chalk'; +import ora from 'ora'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; +import { TemplateManager } from '../src/template-manager.js'; +import { commandExists, getToolVersion, checkVersion } from '../src/utils.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -29,18 +33,143 @@ program .version('${process.env.npm_package_version || '0.1.0'}') .description('Dev Session Buddy - Your AI-Powered Development Companion'); -// TODO: Add commands +program + .command('doctor') + .description('Check development environment setup') + .action(async () => { + const spinner = ora('Checking environment').start(); + + try { + const checks = [ + { + name: 'Node.js', + version: process.version, + required: '>=16.0.0', + command: 'node', + versionCommand: 'node --version' + }, + { + name: 'npm', + required: '>=8.0.0', + command: 'npm', + versionCommand: 'npm --version' + }, + { + name: 'Git', + required: '>=2.0.0', + command: 'git', + versionCommand: 'git --version' + }, + { + name: 'yq', + required: '>=4.0.0', + command: 'yq', + versionCommand: 'yq --version' + } + ]; + + const results = []; + + for (const check of checks) { + const exists = await commandExists(check.command); + if (!exists) { + results.push({ + name: check.name, + status: 'missing', + message: \`\${check.name} is not installed\` + }); + continue; + } + + const version = check.version || await getToolVersion(check.versionCommand); + if (!version) { + results.push({ + name: check.name, + status: 'error', + message: \`Could not determine \${check.name} version\` + }); + continue; + } + + const isValid = checkVersion(version, check.required); + results.push({ + name: check.name, + status: isValid ? 'ok' : 'outdated', + version, + required: check.required, + message: isValid ? null : \`\${check.name} version \${version} does not meet requirement \${check.required}\` + }); + } + + spinner.succeed('Environment check complete'); + + // Display results + console.log(''); + for (const result of results) { + const icon = { + ok: chalk.green('✓'), + outdated: chalk.yellow('!'), + missing: chalk.red('✗'), + error: chalk.red('✗') + }[result.status]; + + const version = result.version ? \`: \${result.version}\` : ''; + console.log(\`\${icon} \${result.name}\${version}\`); + + if (result.message) { + console.log(\` \${chalk.dim(result.message)}\`); + } + } + + // Exit with error if any checks failed + const hasErrors = results.some(r => ['missing', 'error', 'outdated'].includes(r.status)); + if (hasErrors) { + process.exit(1); + } + } catch (error) { + spinner.fail('Environment check failed'); + console.error(chalk.red(error.message)); + process.exit(1); + } + }); + +program + .command('init') + .description('Initialize Dev Session Buddy in an existing project') + .option('-f, --framework ', 'Framework to use (minimal, vue)') + .option('-p, --preset ', 'Configuration preset (minimal, full, team)') + .action(async (options) => { + const spinner = ora('Initializing Dev Session Buddy').start(); + + try { + const framework = options.framework || 'minimal'; + const preset = options.preset || 'full'; + + const templateManager = new TemplateManager(); + await templateManager.applyTemplate(process.cwd(), framework, preset); + + spinner.succeed('Dev Session Buddy initialized successfully!'); + + console.log('\\nNext steps:'); + console.log('1. Review the configuration in dev-session-buddy.yaml'); + console.log('2. Run ./session-start.sh to begin your development session'); + } catch (error) { + spinner.fail('Initialization failed'); + console.error(chalk.red(error.message)); + process.exit(1); + } + }); program.parse(process.argv); `; - const createDsbCli = `#!/usr/bin/env node -import { Command } from 'commander'; + const createCliContent = `import { Command } from 'commander'; import inquirer from 'inquirer'; import chalk from 'chalk'; import ora from 'ora'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; +import { TemplateManager } from '../src/template-manager.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -51,22 +180,67 @@ program .version('${process.env.npm_package_version || '0.1.0'}') .description('Create a new project with Dev Session Buddy') .argument('[name]', 'Project name') - .option('-f, --framework ', 'Framework template to use') - .option('-p, --preset ', 'Configuration preset (full, minimal, or team)') + .option('-f, --framework ', 'Framework to use (minimal, vue)') + .option('-p, --preset ', 'Configuration preset (minimal, full, team)') .action(async (name, options) => { - // TODO: Implement project creation - console.log(chalk.green('Creating new project...')); + try { + // If no name provided, prompt for it + if (!name) { + const answers = await inquirer.prompt([ + { + type: 'input', + name: 'projectName', + message: 'What is your project name?', + validate: input => input.length > 0 || 'Project name is required' + } + ]); + name = answers.projectName; + } + + // Create project directory + const projectDir = join(process.cwd(), name); + const spinner = ora('Creating new project...').start(); + + try { + const framework = options.framework || 'minimal'; + const preset = options.preset || 'full'; + + const templateManager = new TemplateManager(); + await templateManager.applyTemplate(projectDir, framework, preset); + + spinner.succeed('Project created successfully!'); + + console.log('\\nNext steps:'); + console.log(\`1. cd \${name}\`); + console.log('2. npm install'); + console.log('3. npm start'); + } catch (error) { + spinner.fail('Project creation failed'); + console.error(chalk.red(error.message)); + process.exit(1); + } + } catch (error) { + console.error(chalk.red(error.message)); + process.exit(1); + } }); program.parse(process.argv); `; + // Generate CLI files + const mainCli = `#!/usr/bin/env node +${cliContent}`; + + const createCli = `#!/usr/bin/env node +${createCliContent}`; + // Write CLI files - await fs.writeFile(join(projectRoot, 'bin', 'dsb.js'), dsbCli); - await fs.writeFile(join(projectRoot, 'bin', 'create-dev-session-buddy.js'), createDsbCli); - + await fs.writeFile(join(projectRoot, 'bin', 'dev-session-buddy.js'), mainCli); + await fs.writeFile(join(projectRoot, 'bin', 'create-dev-session-buddy.js'), createCli); + // Make CLI files executable - await fs.chmod(join(projectRoot, 'bin', 'dsb.js'), '755'); + await fs.chmod(join(projectRoot, 'bin', 'dev-session-buddy.js'), '755'); await fs.chmod(join(projectRoot, 'bin', 'create-dev-session-buddy.js'), '755'); console.log('Build completed successfully!'); diff --git a/src/template-manager.js b/src/template-manager.js new file mode 100644 index 0000000..cb807a3 --- /dev/null +++ b/src/template-manager.js @@ -0,0 +1,143 @@ +import { promises as fs } from 'fs'; +import { join } from 'path'; +import { getTemplatePath, copyDir, loadConfig, saveConfig } from './utils.js'; + +export class TemplateManager { + /** + * Apply a template to a project + * @param {string} projectDir - Project directory + * @param {string} framework - Framework name + * @param {string} preset - Configuration preset + */ + async applyTemplate(projectDir, framework, preset) { + const templateDir = getTemplatePath(framework); + + try { + // Copy template files + await this._copyTemplateFiles(templateDir, projectDir); + + // Load and customize configuration + await this._setupConfiguration(projectDir, framework, preset); + + // Framework-specific setup + await this._frameworkSetup(projectDir, framework); + } catch (error) { + throw new Error(`Failed to apply template: ${error.message}`); + } + } + + /** + * Copy template files to project + * @private + */ + async _copyTemplateFiles(templateDir, projectDir) { + // Copy template files + const templateConfig = await loadConfig(join(templateDir, 'config-template.yaml')); + + // Create necessary directories + const dirs = [ + 'src', + 'tests', + 'docs', + '.dev-session-buddy', + ...(templateConfig.directories || []) + ]; + + for (const dir of dirs) { + await fs.mkdir(join(projectDir, dir), { recursive: true }); + } + + // Copy framework-specific files + const templateFiles = await fs.readdir(templateDir); + for (const file of templateFiles) { + if (file === 'config-template.yaml') continue; // Skip template config + + const srcPath = join(templateDir, file); + const destPath = join(projectDir, file); + + const stats = await fs.stat(srcPath); + if (stats.isDirectory()) { + await copyDir(srcPath, destPath); + } else { + await fs.copyFile(srcPath, destPath); + // Preserve executable permissions + await fs.chmod(destPath, stats.mode); + } + } + } + + /** + * Setup project configuration + * @private + */ + async _setupConfiguration(projectDir, framework, preset) { + const templateDir = getTemplatePath(framework); + const templateConfig = await loadConfig(join(templateDir, 'config-template.yaml')); + + // Customize configuration based on preset + const config = { + ...templateConfig, + testing: templateConfig.testing || {}, + documentation: templateConfig.documentation || {}, + standards: templateConfig.standards || {}, + tools: templateConfig.tools || {} + }; + config.preset = preset; + + if (preset === 'minimal') { + // Simplify configuration for minimal preset + delete config.tools.optional; + config.testing.coverage = 0; + config.documentation.required = false; + } else if (preset === 'team') { + // Add team-specific settings + config.standards.review = { + required: true, + minReviewers: 2 + }; + } + + // Save configuration + await saveConfig(join(projectDir, 'dev-session-buddy.yaml'), config); + } + + /** + * Perform framework-specific setup + * @private + */ + async _frameworkSetup(projectDir, framework) { + if (framework === 'vue') { + // Vue.js specific setup + const packageJson = { + name: projectDir.split('/').pop(), + version: '0.1.0', + type: 'module', + scripts: { + dev: 'vite', + build: 'vite build', + preview: 'vite preview', + test: 'vitest', + lint: 'eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore' + }, + dependencies: { + vue: '^3.3.0', + 'vue-router': '^4.2.0', + pinia: '^2.1.0' + }, + devDependencies: { + '@vitejs/plugin-vue': '^4.4.0', + vite: '^4.5.0', + vitest: '^0.34.0', + '@vue/test-utils': '^2.4.0', + eslint: '^8.49.0', + 'eslint-plugin-vue': '^9.17.0' + } + }; + + await fs.writeFile( + join(projectDir, 'package.json'), + JSON.stringify(packageJson, null, 2) + ); + } + } +} diff --git a/src/templates/minimal/README.md b/src/templates/minimal/README.md index 28f5d96..0cc4416 100644 --- a/src/templates/minimal/README.md +++ b/src/templates/minimal/README.md @@ -22,7 +22,7 @@ npx create-dev-session-buddy my-project --framework minimal # Or initialize in an existing project cd my-project -npx dsb init --framework minimal +npx dev-session-buddy init --framework minimal ``` ## Configuration diff --git a/src/templates/vue/README.md b/src/templates/vue/README.md index 57b8196..6611440 100644 --- a/src/templates/vue/README.md +++ b/src/templates/vue/README.md @@ -23,7 +23,7 @@ npx create-dev-session-buddy my-vue-app --framework vue # Or initialize in an existing Vue.js project cd my-vue-app -npx dsb init --framework vue +npx dev-session-buddy init --framework vue ``` ## Configuration diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..d12666e --- /dev/null +++ b/src/utils.js @@ -0,0 +1,143 @@ +import { exec } from 'child_process'; +import { promisify } from 'util'; +import { promises as fs } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const execAsync = promisify(exec); + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +/** + * Get the version of a CLI tool + * @param {string} command - Command to get version + * @returns {Promise} Version string + */ +export async function getToolVersion(command) { + try { + if (command === 'node --version') { + return process.version; + } + const { stdout } = await execAsync(command); + return stdout.trim(); + } catch (error) { + return null; + } +} + +/** + * Copy a directory recursively + * @param {string} src - Source directory + * @param {string} dest - Destination directory + */ +export async function copyDir(src, dest) { + await fs.mkdir(dest, { recursive: true }); + const entries = await fs.readdir(src, { withFileTypes: true }); + + for (const entry of entries) { + const srcPath = join(src, entry.name); + const destPath = join(dest, entry.name); + + if (entry.isDirectory()) { + await copyDir(srcPath, destPath); + } else { + await fs.copyFile(srcPath, destPath); + // Preserve executable permissions + const stats = await fs.stat(srcPath); + await fs.chmod(destPath, stats.mode); + } + } +} + +/** + * Get template directory path + * @param {string} framework - Framework name + * @returns {string} Template directory path + */ +export function getTemplatePath(framework) { + return join(__dirname, 'templates', framework); +} + +/** + * Check if a command exists in PATH + * @param {string} command - Command to check + * @returns {Promise} Whether command exists + */ +export async function commandExists(command) { + try { + if (command === 'node') { + return process.execPath !== undefined; + } + await execAsync(`command -v ${command}`); + return true; + } catch { + return false; + } +} + +/** + * Parse version string to components + * @param {string} version - Version string (e.g., "v14.17.0" or "14.17.0") + * @returns {number[]} Version components + */ +export function parseVersion(version) { + const match = version.match(/\d+\.\d+\.\d+/); + if (!match) return [0, 0, 0]; + return match[0].split('.').map(Number); +} + +/** + * Check if version meets minimum requirement + * @param {string} current - Current version + * @param {string} required - Required version + * @returns {boolean} Whether version is sufficient + */ +export function checkVersion(current, required) { + const currentParts = parseVersion(current); + const requiredParts = parseVersion(required.replace(/[^\d.]/g, '')); + + for (let i = 0; i < 3; i++) { + if (currentParts[i] > requiredParts[i]) return true; + if (currentParts[i] < requiredParts[i]) return false; + } + return true; +} + +/** + * Get project root directory + * @returns {string} Project root directory + */ +export function getProjectRoot() { + return join(__dirname, '..'); +} + +/** + * Load and parse YAML configuration + * @param {string} path - Path to YAML file + * @returns {Promise} Configuration object + */ +export async function loadConfig(path) { + try { + const yamlContent = await fs.readFile(path, 'utf8'); + // Note: We're using the yaml package which was added to package.json + const yaml = (await import('yaml')).default; + return yaml.parse(yamlContent); + } catch (error) { + throw new Error(`Failed to load configuration: ${error.message}`); + } +} + +/** + * Save configuration to YAML file + * @param {string} path - Path to YAML file + * @param {object} config - Configuration object + */ +export async function saveConfig(path, config) { + try { + const yaml = (await import('yaml')).default; + await fs.writeFile(path, yaml.stringify(config)); + } catch (error) { + throw new Error(`Failed to save configuration: ${error.message}`); + } +} diff --git a/test/cli-test/init-test-2/README.md b/test/cli-test/init-test-2/README.md new file mode 100644 index 0000000..6611440 --- /dev/null +++ b/test/cli-test/init-test-2/README.md @@ -0,0 +1,112 @@ +# Vue.js Template + +A comprehensive Vue.js template for Dev Session Buddy that provides a full-featured development environment setup with best practices and standards for Vue.js projects. + +## Features + +- Vue.js 3 with Composition API +- Vite for fast development and building +- Comprehensive development session setup +- Vue.js best practices and standards +- Automated testing setup with Vitest +- Git hooks configuration +- Editor settings for Vue files +- Component documentation requirements + +## Usage + +To use this template: + +```bash +# Create a new project +npx create-dev-session-buddy my-vue-app --framework vue + +# Or initialize in an existing Vue.js project +cd my-vue-app +npx dev-session-buddy init --framework vue +``` + +## Configuration + +The template provides a comprehensive configuration in `config-template.yaml`: + +- Vue.js specific requirements +- Development scripts +- Tool configurations +- Vue.js coding standards +- Testing setup +- Documentation requirements + +## Project Structure + +``` +. +├── .dev-session-buddy/ # Dev Session Buddy configuration and cache +├── docs/ # Project documentation +├── src/ # Source code +│ ├── assets/ # Static assets +│ ├── components/ # Vue components +│ ├── composables/ # Vue composables +│ ├── router/ # Vue Router configuration +│ ├── stores/ # Pinia stores +│ └── views/ # Vue views/pages +├── tests/ # Test files +│ ├── unit/ # Unit tests +│ └── e2e/ # End-to-end tests +├── .env.example # Example environment variables +├── .gitignore # Git ignore rules +├── package.json # Project dependencies and scripts +├── vite.config.js # Vite configuration +└── README.md # Project documentation +``` + +## Standards + +This template enforces Vue.js best practices: + +- Composition API usage +- Vue.js Style Guide adherence +- Component documentation +- Unit testing requirements +- Code style (@vue/airbnb) +- Git workflow + +## Development Workflow + +1. Start development session: + ```bash + npm start + ``` + +2. Development server: + ```bash + npm run dev + ``` + +3. Run tests: + ```bash + npm test + ``` + +4. Build for production: + ```bash + npm run build + ``` + +## Customization + +1. Modify `config-template.yaml` to adjust Vue.js standards +2. Update `session-start.sh` to add custom setup steps +3. Configure Vite and testing setup +4. Adjust editor settings for Vue files + +## Contributing + +To contribute improvements to this template: + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Submit a pull request + +Please follow our [contribution guidelines](../../CONTRIBUTING.md). diff --git a/test/cli-test/init-test-2/dev-session-buddy.yaml b/test/cli-test/init-test-2/dev-session-buddy.yaml new file mode 100644 index 0000000..68ded29 --- /dev/null +++ b/test/cli-test/init-test-2/dev-session-buddy.yaml @@ -0,0 +1,92 @@ +name: Project Name +framework: vue +preset: full +version: 0.1.0 +type: Single Page Application +requirements: + node: ">=16.0.0" + npm: ">=8.0.0" + vue: ^3.0.0 + vite: ^4.0.0 +scripts: + start: ./session-start.sh + test: vitest + dev: vite + build: vite build + preview: vite preview +tools: + required: + - node + - npm + - git + - vue + - vite + optional: + - docker + - docker-compose + - nvm + git: + hooks: + pre-commit: npm test + pre-push: npm run build + editor: + formatOnSave: true + rulers: + - 80 + - 100 + tabSize: 2 + vueFiles: + scriptFormat: true + styleFormat: true + templateFormat: true +standards: + key_points: + - Use Composition API for new components + - Follow Vue.js Style Guide + - Write unit tests for components + - Document component props and events + branches: + types: + - feature + - bugfix + - hotfix + - release + - chore + commit: + conventional: true + scopes: + - ui + - api + - core + - deps + - config + - docs + - test + testing: + coverage: 80 + frameworks: + - vitest + - "@vue/test-utils" + documentation: + required: true + locations: + - README.md + - docs/ + - src/**/*.vue + code: + style: "@vue/airbnb" + maxLineLength: 100 +workflow: + dev_server: npm run dev + test: npm test + build: npm run build +style_guide: + key_points: + - Use PascalCase for component names + - Use kebab-case for events + - Props should use camelCase + - Components should be single responsibility + - Use computed properties for derived data + - Keep components under 300 lines +testing: {} +documentation: {} diff --git a/test/cli-test/init-test-2/package.json b/test/cli-test/init-test-2/package.json new file mode 100644 index 0000000..e0fe6bc --- /dev/null +++ b/test/cli-test/init-test-2/package.json @@ -0,0 +1,25 @@ +{ + "name": "init-test-2", + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test": "vitest", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" + }, + "dependencies": { + "vue": "^3.3.0", + "vue-router": "^4.2.0", + "pinia": "^2.1.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.4.0", + "vite": "^4.5.0", + "vitest": "^0.34.0", + "@vue/test-utils": "^2.4.0", + "eslint": "^8.49.0", + "eslint-plugin-vue": "^9.17.0" + } +} \ No newline at end of file diff --git a/test/cli-test/init-test-2/session-start.sh b/test/cli-test/init-test-2/session-start.sh new file mode 100755 index 0000000..d594a3a --- /dev/null +++ b/test/cli-test/init-test-2/session-start.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# Import common functions and variables +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)" +source "${SCRIPT_DIR}/../../core/common.sh" + +# Load configuration +CONFIG_FILE="${PROJECT_ROOT}/dev-session-buddy.yaml" +if [ ! -f "$CONFIG_FILE" ]; then + CONFIG_FILE="${PROJECT_ROOT}/config/default.yaml" +fi + +# ANSI color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Load project name from config +PROJECT_NAME=$(yq eval '.name' "$CONFIG_FILE") +echo -e "${BLUE}=== $PROJECT_NAME Development Session Start ===${NC}\n" + +# Check current branch +CURRENT_BRANCH=$(git branch --show-current) +echo -e "Current branch: ${GREEN}$CURRENT_BRANCH${NC}\n" + +# Warning if on main/master +if [[ "$CURRENT_BRANCH" =~ ^(main|master)$ ]]; then + echo -e "${RED}⚠️ WARNING: You are on the $CURRENT_BRANCH branch!${NC}" + echo -e "${RED}Please create a feature branch before making changes.${NC}\n" +fi + +# Show quick reference +echo -e "${YELLOW}Quick Reference:${NC}" +echo -e "1. Branch naming:" +# Get branch types from config +BRANCH_TYPES=$(yq eval '.standards.branches.types[]' "$CONFIG_FILE" | tr '\n' ' ') +for type in $BRANCH_TYPES; do + echo -e " - ${type}s: ${GREEN}${type}/descriptive-name${NC}" +done + +echo -e "2. Commit format:" +echo -e " ${GREEN}type(scope): description${NC}" +# Get scopes from config +SCOPES=$(yq eval '.standards.commit.scopes[]' "$CONFIG_FILE" | tr '\n' '|') +echo -e " Scopes: ${GREEN}${SCOPES}${NC}" + +# Show recent commits +echo -e "\n${YELLOW}Recent commits:${NC}" +git --no-pager log --oneline -n 3 + +# Show any stashed changes +STASH_COUNT=$(git stash list | wc -l) +if [ $STASH_COUNT -gt 0 ]; then + echo -e "\n${YELLOW}Stashed changes:${NC}" + git stash list | head -n 3 +fi + +# Show development environment notes +echo -e "\n${YELLOW}Development Environment:${NC}" + +# Show tools section +echo -e "\n1. ${YELLOW}Available Tools & Environment:${NC}" +# Required tools +REQUIRED_TOOLS=$(yq eval '.tools.required[]' "$CONFIG_FILE") +for tool in $REQUIRED_TOOLS; do + echo -e " - ${GREEN}${tool}${NC} (required)" +done +# Optional tools +OPTIONAL_TOOLS=$(yq eval '.tools.optional[]' "$CONFIG_FILE") +for tool in $OPTIONAL_TOOLS; do + echo -e " - ${GREEN}${tool}${NC} (optional)" +done + +# Show project standards +echo -e "\n2. ${YELLOW}Project Standards:${NC}" +yq eval '.standards.key_points[]' "$CONFIG_FILE" | while read -r point; do + echo -e " - ${point}" +done + +# Show tech stack +echo -e "\n3. ${YELLOW}Tech Stack:${NC}" +echo -e " - ${GREEN}Vue.js 3${NC} with Composition API" +echo -e " - ${GREEN}Vite${NC} for build tooling and dev server" +echo -e " - ${GREEN}$(yq eval '.framework' "$CONFIG_FILE")${NC}" +echo -e " - ${GREEN}$(yq eval '.type' "$CONFIG_FILE")${NC} type" + +# Show workflow commands +echo -e "\n4. ${YELLOW}Development Workflow:${NC}" +echo -e " - Auto-reload enabled (Vite HMR)" +echo -e " - Run ${GREEN}$(yq eval '.workflow.dev_server' "$CONFIG_FILE")${NC} to start development server" +echo -e " - Run ${GREEN}$(yq eval '.workflow.test' "$CONFIG_FILE")${NC} for unit tests" +echo -e " - Run ${GREEN}$(yq eval '.workflow.build' "$CONFIG_FILE")${NC} for production build" + +# Show style guide +echo -e "\n5. ${YELLOW}Code Style & Best Practices:${NC}" +yq eval '.style_guide.key_points[]' "$CONFIG_FILE" | while read -r point; do + echo -e " - ${point}" +done + +echo -e "\n${BLUE}=== Ready to Code! ===${NC}" + +# Final warning if on main/master +if [[ "$CURRENT_BRANCH" =~ ^(main|master)$ ]]; then + echo -e "\n${RED}⚠️ REMINDER: You are still on the $CURRENT_BRANCH branch!${NC}" + echo -e "${RED}Run: ${GREEN}git checkout -b feature/your-feature-name${NC} ${RED}to create a new feature branch.${NC}" +fi diff --git a/test/cli-test/init-test/README.md b/test/cli-test/init-test/README.md new file mode 100644 index 0000000..28f5d96 --- /dev/null +++ b/test/cli-test/init-test/README.md @@ -0,0 +1,76 @@ +# Minimal Template + +A framework-agnostic template for Dev Session Buddy that provides basic development session setup and project standards. + +## Features + +- Basic development session setup +- Environment file management +- Dependency installation check +- Development server auto-start (if configured) +- Project standards configuration +- Git hooks setup +- Editor configuration + +## Usage + +To use this template: + +```bash +# Create a new project +npx create-dev-session-buddy my-project --framework minimal + +# Or initialize in an existing project +cd my-project +npx dsb init --framework minimal +``` + +## Configuration + +The template provides a base configuration in `config-template.yaml` that you can customize: + +- Development requirements +- Script definitions +- Tool configurations +- Project standards + +## Project Structure + +``` +. +├── .dev-session-buddy/ # Dev Session Buddy configuration and cache +├── docs/ # Project documentation +├── src/ # Source code +├── tests/ # Test files +├── .env.example # Example environment variables +├── .gitignore # Git ignore rules +├── package.json # Project dependencies and scripts +└── README.md # Project documentation +``` + +## Standards + +This template enforces: + +- Conventional commits +- Documentation requirements +- Code style (Standard) +- Test coverage requirements +- Editor configuration + +## Customization + +1. Modify `config-template.yaml` to adjust standards and requirements +2. Update `session-start.sh` to add custom setup steps +3. Add framework-specific configurations as needed + +## Contributing + +To contribute improvements to this template: + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Submit a pull request + +Please follow our [contribution guidelines](../../CONTRIBUTING.md). diff --git a/test/cli-test/init-test/dev-session-buddy.yaml b/test/cli-test/init-test/dev-session-buddy.yaml new file mode 100644 index 0000000..2dc5de4 --- /dev/null +++ b/test/cli-test/init-test/dev-session-buddy.yaml @@ -0,0 +1,39 @@ +name: Project Name +framework: minimal +preset: minimal +version: 0.1.0 +requirements: + node: ">=16.0.0" + npm: ">=8.0.0" +scripts: + start: ./session-start.sh + test: npm test +tools: + git: + hooks: + pre-commit: npm test + editor: + formatOnSave: true + rulers: + - 80 + - 100 + tabSize: 2 +standards: + commits: + conventional: true + scopes: [] + testing: + coverage: 80 + frameworks: [] + documentation: + required: true + locations: + - README.md + - docs/ + code: + style: standard + maxLineLength: 100 +testing: + coverage: 0 +documentation: + required: false diff --git a/test/cli-test/init-test/session-start.sh b/test/cli-test/init-test/session-start.sh new file mode 100644 index 0000000..173ddf8 --- /dev/null +++ b/test/cli-test/init-test/session-start.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Dev Session Buddy - Minimal Template +# This is a framework-agnostic template that provides basic development session setup + +echo "Starting development session..." + +# Check if .env exists, create if not +if [ ! -f .env ]; then + echo "Creating .env file..." + cp .env.example .env +fi + +# Install dependencies if needed +if [ ! -d "node_modules" ]; then + echo "Installing dependencies..." + npm install +fi + +# Run development server if package.json has a dev script +if grep -q "\"dev\":" package.json; then + echo "Starting development server..." + npm run dev +else + echo "No development server configured. Add a 'dev' script to package.json to enable automatic server startup." +fi diff --git a/test/cli-test/test-project/README.md b/test/cli-test/test-project/README.md new file mode 100644 index 0000000..0cc4416 --- /dev/null +++ b/test/cli-test/test-project/README.md @@ -0,0 +1,76 @@ +# Minimal Template + +A framework-agnostic template for Dev Session Buddy that provides basic development session setup and project standards. + +## Features + +- Basic development session setup +- Environment file management +- Dependency installation check +- Development server auto-start (if configured) +- Project standards configuration +- Git hooks setup +- Editor configuration + +## Usage + +To use this template: + +```bash +# Create a new project +npx create-dev-session-buddy my-project --framework minimal + +# Or initialize in an existing project +cd my-project +npx dev-session-buddy init --framework minimal +``` + +## Configuration + +The template provides a base configuration in `config-template.yaml` that you can customize: + +- Development requirements +- Script definitions +- Tool configurations +- Project standards + +## Project Structure + +``` +. +├── .dev-session-buddy/ # Dev Session Buddy configuration and cache +├── docs/ # Project documentation +├── src/ # Source code +├── tests/ # Test files +├── .env.example # Example environment variables +├── .gitignore # Git ignore rules +├── package.json # Project dependencies and scripts +└── README.md # Project documentation +``` + +## Standards + +This template enforces: + +- Conventional commits +- Documentation requirements +- Code style (Standard) +- Test coverage requirements +- Editor configuration + +## Customization + +1. Modify `config-template.yaml` to adjust standards and requirements +2. Update `session-start.sh` to add custom setup steps +3. Add framework-specific configurations as needed + +## Contributing + +To contribute improvements to this template: + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Submit a pull request + +Please follow our [contribution guidelines](../../CONTRIBUTING.md). diff --git a/test/cli-test/test-project/dev-session-buddy.yaml b/test/cli-test/test-project/dev-session-buddy.yaml new file mode 100644 index 0000000..83c3fef --- /dev/null +++ b/test/cli-test/test-project/dev-session-buddy.yaml @@ -0,0 +1,37 @@ +name: Project Name +framework: minimal +preset: full +version: 0.1.0 +requirements: + node: ">=16.0.0" + npm: ">=8.0.0" +scripts: + start: ./session-start.sh + test: npm test +tools: + git: + hooks: + pre-commit: npm test + editor: + formatOnSave: true + rulers: + - 80 + - 100 + tabSize: 2 +standards: + commits: + conventional: true + scopes: [] + testing: + coverage: 80 + frameworks: [] + documentation: + required: true + locations: + - README.md + - docs/ + code: + style: standard + maxLineLength: 100 +testing: {} +documentation: {} diff --git a/test/cli-test/test-project/session-start.sh b/test/cli-test/test-project/session-start.sh new file mode 100644 index 0000000..173ddf8 --- /dev/null +++ b/test/cli-test/test-project/session-start.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Dev Session Buddy - Minimal Template +# This is a framework-agnostic template that provides basic development session setup + +echo "Starting development session..." + +# Check if .env exists, create if not +if [ ! -f .env ]; then + echo "Creating .env file..." + cp .env.example .env +fi + +# Install dependencies if needed +if [ ! -d "node_modules" ]; then + echo "Installing dependencies..." + npm install +fi + +# Run development server if package.json has a dev script +if grep -q "\"dev\":" package.json; then + echo "Starting development server..." + npm run dev +else + echo "No development server configured. Add a 'dev' script to package.json to enable automatic server startup." +fi diff --git a/test/cli-test/vue-test/README.md b/test/cli-test/vue-test/README.md new file mode 100644 index 0000000..57b8196 --- /dev/null +++ b/test/cli-test/vue-test/README.md @@ -0,0 +1,112 @@ +# Vue.js Template + +A comprehensive Vue.js template for Dev Session Buddy that provides a full-featured development environment setup with best practices and standards for Vue.js projects. + +## Features + +- Vue.js 3 with Composition API +- Vite for fast development and building +- Comprehensive development session setup +- Vue.js best practices and standards +- Automated testing setup with Vitest +- Git hooks configuration +- Editor settings for Vue files +- Component documentation requirements + +## Usage + +To use this template: + +```bash +# Create a new project +npx create-dev-session-buddy my-vue-app --framework vue + +# Or initialize in an existing Vue.js project +cd my-vue-app +npx dsb init --framework vue +``` + +## Configuration + +The template provides a comprehensive configuration in `config-template.yaml`: + +- Vue.js specific requirements +- Development scripts +- Tool configurations +- Vue.js coding standards +- Testing setup +- Documentation requirements + +## Project Structure + +``` +. +├── .dev-session-buddy/ # Dev Session Buddy configuration and cache +├── docs/ # Project documentation +├── src/ # Source code +│ ├── assets/ # Static assets +│ ├── components/ # Vue components +│ ├── composables/ # Vue composables +│ ├── router/ # Vue Router configuration +│ ├── stores/ # Pinia stores +│ └── views/ # Vue views/pages +├── tests/ # Test files +│ ├── unit/ # Unit tests +│ └── e2e/ # End-to-end tests +├── .env.example # Example environment variables +├── .gitignore # Git ignore rules +├── package.json # Project dependencies and scripts +├── vite.config.js # Vite configuration +└── README.md # Project documentation +``` + +## Standards + +This template enforces Vue.js best practices: + +- Composition API usage +- Vue.js Style Guide adherence +- Component documentation +- Unit testing requirements +- Code style (@vue/airbnb) +- Git workflow + +## Development Workflow + +1. Start development session: + ```bash + npm start + ``` + +2. Development server: + ```bash + npm run dev + ``` + +3. Run tests: + ```bash + npm test + ``` + +4. Build for production: + ```bash + npm run build + ``` + +## Customization + +1. Modify `config-template.yaml` to adjust Vue.js standards +2. Update `session-start.sh` to add custom setup steps +3. Configure Vite and testing setup +4. Adjust editor settings for Vue files + +## Contributing + +To contribute improvements to this template: + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Submit a pull request + +Please follow our [contribution guidelines](../../CONTRIBUTING.md). diff --git a/test/cli-test/vue-test/dev-session-buddy.yaml b/test/cli-test/vue-test/dev-session-buddy.yaml new file mode 100644 index 0000000..2cca695 --- /dev/null +++ b/test/cli-test/vue-test/dev-session-buddy.yaml @@ -0,0 +1,90 @@ +name: Project Name +framework: vue +preset: full +version: 0.1.0 +type: Single Page Application +requirements: + node: ">=16.0.0" + npm: ">=8.0.0" + vue: ^3.0.0 + vite: ^4.0.0 +scripts: + start: ./session-start.sh + test: vitest + dev: vite + build: vite build + preview: vite preview +tools: + required: + - node + - npm + - git + - vue + - vite + optional: + - docker + - docker-compose + - nvm + git: + hooks: + pre-commit: npm test + pre-push: npm run build + editor: + formatOnSave: true + rulers: + - 80 + - 100 + tabSize: 2 + vueFiles: + scriptFormat: true + styleFormat: true + templateFormat: true +standards: + key_points: + - Use Composition API for new components + - Follow Vue.js Style Guide + - Write unit tests for components + - Document component props and events + branches: + types: + - feature + - bugfix + - hotfix + - release + - chore + commit: + conventional: true + scopes: + - ui + - api + - core + - deps + - config + - docs + - test + testing: + coverage: 80 + frameworks: + - vitest + - "@vue/test-utils" + documentation: + required: true + locations: + - README.md + - docs/ + - src/**/*.vue + code: + style: "@vue/airbnb" + maxLineLength: 100 +workflow: + dev_server: npm run dev + test: npm test + build: npm run build +style_guide: + key_points: + - Use PascalCase for component names + - Use kebab-case for events + - Props should use camelCase + - Components should be single responsibility + - Use computed properties for derived data + - Keep components under 300 lines diff --git a/test/cli-test/vue-test/package.json b/test/cli-test/vue-test/package.json new file mode 100644 index 0000000..3726dab --- /dev/null +++ b/test/cli-test/vue-test/package.json @@ -0,0 +1,25 @@ +{ + "name": "vue-test", + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test": "vitest", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" + }, + "dependencies": { + "vue": "^3.3.0", + "vue-router": "^4.2.0", + "pinia": "^2.1.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.4.0", + "vite": "^4.5.0", + "vitest": "^0.34.0", + "@vue/test-utils": "^2.4.0", + "eslint": "^8.49.0", + "eslint-plugin-vue": "^9.17.0" + } +} \ No newline at end of file diff --git a/test/cli-test/vue-test/session-start.sh b/test/cli-test/vue-test/session-start.sh new file mode 100755 index 0000000..d594a3a --- /dev/null +++ b/test/cli-test/vue-test/session-start.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# Import common functions and variables +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)" +source "${SCRIPT_DIR}/../../core/common.sh" + +# Load configuration +CONFIG_FILE="${PROJECT_ROOT}/dev-session-buddy.yaml" +if [ ! -f "$CONFIG_FILE" ]; then + CONFIG_FILE="${PROJECT_ROOT}/config/default.yaml" +fi + +# ANSI color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Load project name from config +PROJECT_NAME=$(yq eval '.name' "$CONFIG_FILE") +echo -e "${BLUE}=== $PROJECT_NAME Development Session Start ===${NC}\n" + +# Check current branch +CURRENT_BRANCH=$(git branch --show-current) +echo -e "Current branch: ${GREEN}$CURRENT_BRANCH${NC}\n" + +# Warning if on main/master +if [[ "$CURRENT_BRANCH" =~ ^(main|master)$ ]]; then + echo -e "${RED}⚠️ WARNING: You are on the $CURRENT_BRANCH branch!${NC}" + echo -e "${RED}Please create a feature branch before making changes.${NC}\n" +fi + +# Show quick reference +echo -e "${YELLOW}Quick Reference:${NC}" +echo -e "1. Branch naming:" +# Get branch types from config +BRANCH_TYPES=$(yq eval '.standards.branches.types[]' "$CONFIG_FILE" | tr '\n' ' ') +for type in $BRANCH_TYPES; do + echo -e " - ${type}s: ${GREEN}${type}/descriptive-name${NC}" +done + +echo -e "2. Commit format:" +echo -e " ${GREEN}type(scope): description${NC}" +# Get scopes from config +SCOPES=$(yq eval '.standards.commit.scopes[]' "$CONFIG_FILE" | tr '\n' '|') +echo -e " Scopes: ${GREEN}${SCOPES}${NC}" + +# Show recent commits +echo -e "\n${YELLOW}Recent commits:${NC}" +git --no-pager log --oneline -n 3 + +# Show any stashed changes +STASH_COUNT=$(git stash list | wc -l) +if [ $STASH_COUNT -gt 0 ]; then + echo -e "\n${YELLOW}Stashed changes:${NC}" + git stash list | head -n 3 +fi + +# Show development environment notes +echo -e "\n${YELLOW}Development Environment:${NC}" + +# Show tools section +echo -e "\n1. ${YELLOW}Available Tools & Environment:${NC}" +# Required tools +REQUIRED_TOOLS=$(yq eval '.tools.required[]' "$CONFIG_FILE") +for tool in $REQUIRED_TOOLS; do + echo -e " - ${GREEN}${tool}${NC} (required)" +done +# Optional tools +OPTIONAL_TOOLS=$(yq eval '.tools.optional[]' "$CONFIG_FILE") +for tool in $OPTIONAL_TOOLS; do + echo -e " - ${GREEN}${tool}${NC} (optional)" +done + +# Show project standards +echo -e "\n2. ${YELLOW}Project Standards:${NC}" +yq eval '.standards.key_points[]' "$CONFIG_FILE" | while read -r point; do + echo -e " - ${point}" +done + +# Show tech stack +echo -e "\n3. ${YELLOW}Tech Stack:${NC}" +echo -e " - ${GREEN}Vue.js 3${NC} with Composition API" +echo -e " - ${GREEN}Vite${NC} for build tooling and dev server" +echo -e " - ${GREEN}$(yq eval '.framework' "$CONFIG_FILE")${NC}" +echo -e " - ${GREEN}$(yq eval '.type' "$CONFIG_FILE")${NC} type" + +# Show workflow commands +echo -e "\n4. ${YELLOW}Development Workflow:${NC}" +echo -e " - Auto-reload enabled (Vite HMR)" +echo -e " - Run ${GREEN}$(yq eval '.workflow.dev_server' "$CONFIG_FILE")${NC} to start development server" +echo -e " - Run ${GREEN}$(yq eval '.workflow.test' "$CONFIG_FILE")${NC} for unit tests" +echo -e " - Run ${GREEN}$(yq eval '.workflow.build' "$CONFIG_FILE")${NC} for production build" + +# Show style guide +echo -e "\n5. ${YELLOW}Code Style & Best Practices:${NC}" +yq eval '.style_guide.key_points[]' "$CONFIG_FILE" | while read -r point; do + echo -e " - ${point}" +done + +echo -e "\n${BLUE}=== Ready to Code! ===${NC}" + +# Final warning if on main/master +if [[ "$CURRENT_BRANCH" =~ ^(main|master)$ ]]; then + echo -e "\n${RED}⚠️ REMINDER: You are still on the $CURRENT_BRANCH branch!${NC}" + echo -e "${RED}Run: ${GREEN}git checkout -b feature/your-feature-name${NC} ${RED}to create a new feature branch.${NC}" +fi diff --git a/tests/config/default.yaml b/tests/config/default.yaml new file mode 100644 index 0000000..f8f1cf1 --- /dev/null +++ b/tests/config/default.yaml @@ -0,0 +1,6 @@ +name: "Dev Session Buddy" +tools: + required: + - git + - node + - npm From e050245167966a4fd60283c810957b903918f749 Mon Sep 17 00:00:00 2001 From: Codevalve <6092+codevalve@users.noreply.github.com> Date: Thu, 28 Nov 2024 22:34:04 -0600 Subject: [PATCH 4/6] chore: add GitHub issue templates - Add general task template - Add MVP final tasks template --- .github/ISSUE_TEMPLATE/mvp-tasks.md | 101 ++++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/task.md | 26 +++++++ 2 files changed, 127 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/mvp-tasks.md create mode 100644 .github/ISSUE_TEMPLATE/task.md diff --git a/.github/ISSUE_TEMPLATE/mvp-tasks.md b/.github/ISSUE_TEMPLATE/mvp-tasks.md new file mode 100644 index 0000000..895508a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/mvp-tasks.md @@ -0,0 +1,101 @@ +--- +name: MVP Final Tasks +about: Tracking the final tasks needed for MVP release +title: 'MVP: Final Tasks for Initial Release' +labels: enhancement, MVP +assignees: '' +--- + +## Description +This issue tracks the final tasks needed to prepare Dev Session Buddy for its initial MVP release. These tasks focus on ensuring the package is well-tested, documented, and ready for publication on npm. + +## Tasks + +### 1. Add Comprehensive Test Suite +- [ ] Unit Tests + - [ ] Template manager functionality + - [ ] Utility functions + - [ ] Configuration management + - [ ] Version checking +- [ ] Integration Tests + - [ ] CLI commands (`doctor`, `init`) + - [ ] Project creation workflow + - [ ] Template application + - [ ] Error handling +- [ ] Shell Tests + - [ ] Session start scripts + - [ ] Environment setup + - [ ] Tool validation +- [ ] Test Coverage + - [ ] Set up coverage reporting + - [ ] Achieve >80% coverage + +### 2. Add Detailed Documentation +- [ ] API Documentation + - [ ] CLI command reference + - [ ] Configuration options + - [ ] Template structure +- [ ] User Guides + - [ ] Getting started guide + - [ ] Template customization + - [ ] Framework integration +- [ ] Contributing Guidelines + - [ ] Development setup + - [ ] Code style guide + - [ ] Pull request process +- [ ] Package Documentation + - [ ] Update README.md + - [ ] Add examples + - [ ] Document installation options + +### 3. Set up Continuous Integration +- [ ] GitHub Actions Workflow + - [ ] Automated testing + - [ ] Code linting + - [ ] Coverage reporting +- [ ] Release Management + - [ ] Version bumping + - [ ] Changelog generation + - [ ] Tag creation +- [ ] Package Publishing + - [ ] npm publish automation + - [ ] Package verification + +### 4. Prepare for npm Publication +- [ ] Package Configuration + - [ ] Update package.json metadata + - [ ] Add keywords + - [ ] Set up package scope +- [ ] Access Control + - [ ] Configure package access + - [ ] Set up maintainers +- [ ] Release Planning + - [ ] Create release checklist + - [ ] Plan version strategy + - [ ] Document release process + +## Technical Details +- Test Framework: Jest for unit/integration tests, BATS for shell tests +- Documentation: Markdown files in `/docs` directory +- CI/CD: GitHub Actions +- Package Manager: npm + +## Dependencies +- Node.js >=16.0.0 +- npm >=8.0.0 +- Git for version control +- GitHub Actions for CI/CD + +## Success Criteria +- All tests passing with >80% coverage +- Documentation complete and reviewed +- CI/CD pipeline operational +- Package successfully published to npm +- Sample projects working with published package + +## Additional Notes +- Focus on maintainability and extensibility +- Ensure clear error messages and user feedback +- Document all breaking changes +- Consider backward compatibility +- Plan for future enhancements diff --git a/.github/ISSUE_TEMPLATE/task.md b/.github/ISSUE_TEMPLATE/task.md new file mode 100644 index 0000000..d824ac6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/task.md @@ -0,0 +1,26 @@ +--- +name: Task +about: A development task that needs to be completed +title: '' +labels: task +assignees: '' +--- + +## Description + + +## Acceptance Criteria + + +- [ ] Requirement 1 +- [ ] Requirement 2 +- [ ] Requirement 3 + +## Technical Details + + +## Dependencies + + +## Additional Context + From a6a9ccd281dfb1361be0d68d7d382bd5411eafcf Mon Sep 17 00:00:00 2001 From: Codevalve <6092+codevalve@users.noreply.github.com> Date: Thu, 28 Nov 2024 22:38:54 -0600 Subject: [PATCH 5/6] feat: add development session start script - Add session-start.sh for development environment setup - Show branch, commits, and status info - Display quick reference for conventions - Check environment and available scripts --- session-start.sh | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 session-start.sh diff --git a/session-start.sh b/session-start.sh new file mode 100755 index 0000000..ba98f3e --- /dev/null +++ b/session-start.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# ANSI color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Project info +PROJECT_NAME="Dev Session Buddy" +echo -e "${BLUE}=== $PROJECT_NAME Development Session Start ===${NC}\n" + +# Check current branch +CURRENT_BRANCH=$(git branch --show-current) +echo -e "Current branch: ${GREEN}$CURRENT_BRANCH${NC}\n" + +# Warning if on main/master +if [[ "$CURRENT_BRANCH" =~ ^(main|master)$ ]]; then + echo -e "${RED}⚠️ WARNING: You are on the $CURRENT_BRANCH branch!${NC}" + echo -e "${RED}Please create a feature branch before making changes.${NC}\n" +fi + +# Show quick reference +echo -e "${YELLOW}Quick Reference:${NC}" +echo -e "1. Branch naming:" +echo -e " - features: ${GREEN}feature/descriptive-name${NC}" +echo -e " - fixes: ${GREEN}fix/descriptive-name${NC}" +echo -e " - docs: ${GREEN}docs/descriptive-name${NC}" + +echo -e "\n2. Commit format:" +echo -e " ${GREEN}type(scope): description${NC}" +echo -e " Types: feat, fix, docs, style, refactor, test, chore" +echo -e " Scopes: cli, template, config, docs, test" + +# Show recent commits +echo -e "\n${YELLOW}Recent commits:${NC}" +git --no-pager log --oneline -n 5 + +# Show current status +echo -e "\n${YELLOW}Current status:${NC}" +git status -s + +# Environment check +echo -e "\n${YELLOW}Environment check:${NC}" +node --version +npm --version + +# Show available scripts +echo -e "\n${YELLOW}Available scripts:${NC}" +npm run | grep -v "^ \(prebuild\|postbuild\)" | grep "^ [^ ]" || true From 5aae1b3e2205ca4f4beaf254472cc36c781a1b53 Mon Sep 17 00:00:00 2001 From: Codevalve <6092+codevalve@users.noreply.github.com> Date: Thu, 28 Nov 2024 23:26:14 -0600 Subject: [PATCH 6/6] feat: prepare package for npm release - Add index.js for main exports - Create .npmignore file - Update package.json dependencies - Add package verification script - Fix utils exports and function implementations - Update test infrastructure --- .npmignore | 30 ++ config.yaml | 8 + coverage/lcov-report/index.html | 52 +- coverage/lcov-report/template-manager.js.html | 430 ++++++++++++++++ coverage/lcov-report/utils.js.html | 463 ++++++++++++++++++ coverage/lcov.info | 143 ++++++ jest.config.js | 3 + package.json | 10 +- scripts/verify-package.js | 19 + src/index.js | 12 + src/template-manager.js | 158 +++--- src/utils.js | 168 +++---- tests/unit/config.test.js | 6 +- tests/unit/template-manager.test.js | 104 ++++ tests/unit/utils.test.js | 107 ++++ 15 files changed, 1507 insertions(+), 206 deletions(-) create mode 100644 .npmignore create mode 100644 config.yaml create mode 100644 coverage/lcov-report/template-manager.js.html create mode 100644 coverage/lcov-report/utils.js.html create mode 100755 scripts/verify-package.js create mode 100644 src/index.js create mode 100644 tests/unit/template-manager.test.js create mode 100644 tests/unit/utils.test.js diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..3abf512 --- /dev/null +++ b/.npmignore @@ -0,0 +1,30 @@ +# Development files +tests/ +docs/ +scripts/ +.github/ +.git/ +.gitignore +.eslintrc* +.prettierrc* +jest.config.js + +# Editor files +.vscode/ +.idea/ +*.swp +*.swo + +# Build and coverage +coverage/ +.nyc_output/ +*.log + +# Environment +.env* +.env.local +.env.*.local + +# Misc +*.tgz +.DS_Store diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..91e335c --- /dev/null +++ b/config.yaml @@ -0,0 +1,8 @@ +framework: vue +dependencies: + required: + - vue + - vite + dev: + - jest + - eslint diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html index 96976ca..7826e0f 100644 --- a/coverage/lcov-report/index.html +++ b/coverage/lcov-report/index.html @@ -23,30 +23,30 @@

All files

- Unknown% + 42.3% Statements - 0/0 + 33/78
- Unknown% + 53.57% Branches - 0/0 + 15/28
- Unknown% + 50% Functions - 0/0 + 6/12
- Unknown% + 41.09% Lines - 0/0 + 30/73
@@ -61,7 +61,7 @@

All files

-
+
@@ -78,7 +78,37 @@

All files

- + + + + + + + + + + + + + + + + + + + + + + + + + + +
template-manager.js +
+
10.34%3/290%0/620%1/510.71%3/28
utils.js +
+
61.22%30/4968.18%15/2271.42%5/760%27/45
@@ -86,7 +116,7 @@

All files

+ + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/utils.js.html b/coverage/lcov-report/utils.js.html new file mode 100644 index 0000000..6f3f627 --- /dev/null +++ b/coverage/lcov-report/utils.js.html @@ -0,0 +1,463 @@ + + + + + + Code coverage report for utils.js + + + + + + + + + +
+
+

All files utils.js

+
+ +
+ 61.22% + Statements + 30/49 +
+ + +
+ 68.18% + Branches + 15/22 +
+ + +
+ 71.42% + Functions + 5/7 +
+ + +
+ 60% + Lines + 27/45 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127  +  +  +  +  +  +2x +  +  +  +  +  +  +  +2x +2x +  +  +2x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +  +  +  +  +  +  +  +  +  +3x +3x +  +3x +4x +4x +4x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +1x +1x +  +  +1x +  +1x +  +  +1x +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +  +  +  + 
import { promises as fs } from 'fs';
+import { exec } from 'child_process';
+import { promisify } from 'util';
+import path from 'path';
+import yaml from 'js-yaml';
+ 
+const execPromise = promisify(exec);
+ 
+/**
+ * Get version from command output
+ * @param {string} command - Command to execute
+ * @returns {Promise<string|null>} Version string or null on error
+ */
+export async function getToolVersion(command) {
+  try {
+    Iif (command === 'node --version') {
+      return process.version;
+    }
+    const { stdout } = await execPromise(command);
+    const version = stdout.trim();
+    return parseVersion(version);
+  } catch (error) {
+    return null;
+  }
+}
+ 
+/**
+ * Copy directory recursively
+ * @param {string} src - Source directory
+ * @param {string} dest - Destination directory
+ */
+export async function copyDir(src, dest) {
+  try {
+    await fs.mkdir(dest, { recursive: true });
+    const entries = await fs.readdir(src);
+ 
+    for (const entry of entries) {
+      const srcPath = path.join(src, entry);
+      const destPath = path.join(dest, entry);
+      const stats = await fs.stat(srcPath);
+ 
+      if (stats.isDirectory()) {
+        await copyDir(srcPath, destPath);
+      } else {
+        await fs.copyFile(srcPath, destPath);
+        await fs.chmod(destPath, stats.mode);
+      }
+    }
+  } catch (error) {
+    throw new Error(`Failed to copy directory: ${error.message}`);
+  }
+}
+ 
+/**
+ * Parse version string
+ * @param {string} version - Version string
+ * @returns {string} Parsed version
+ */
+export function parseVersion(version) {
+  const match = version.match(/v?(\d+\.\d+\.\d+)/);
+  Iif (!match) return version;
+  return match[0].startsWith('v') ? match[0] : `v${match[0]}`;
+}
+ 
+/**
+ * Check if version meets requirement
+ * @param {string} current - Current version
+ * @param {string} required - Required version
+ * @returns {boolean} True if version meets requirement
+ */
+export function checkVersion(current, required) {
+  const currentParts = current.replace('v', '').split('.').map(Number);
+  const requiredParts = required.replace('v', '').split('.').map(Number);
+ 
+  for (let i = 0; i < 3; i++) {
+    const currentPart = currentParts[i] || 0;
+    const requiredPart = requiredParts[i] || 0;
+    if (currentPart > requiredPart) return true;
+    if (currentPart < requiredPart) return false;
+  }
+  return true;
+}
+ 
+/**
+ * Get template path
+ * @param {string} framework - Framework name
+ * @returns {string} Template path
+ */
+export function getTemplatePath(framework) {
+  return path.join(process.cwd(), 'templates', framework);
+}
+ 
+/**
+ * Load configuration from YAML file
+ * @param {string} configPath - Path to configuration file
+ * @returns {Promise<object>} Configuration object
+ */
+export async function loadConfig(configPath) {
+  try {
+    const content = await fs.readFile(configPath, 'utf8');
+    const result = yaml.load(content);
+    Iif (!result || typeof result !== 'object') {
+      throw new Error('Invalid YAML content');
+    }
+    return result;
+  } catch (error) {
+    Iif (error.message === 'Invalid YAML content') {
+      throw new Error('Failed to load configuration: Invalid YAML content');
+    }
+    throw new Error(`Failed to load configuration: ${error.message}`);
+  }
+}
+ 
+/**
+ * Save configuration to YAML file
+ * @param {string} configPath - Path to configuration file
+ * @param {object} config - Configuration object
+ */
+export async function saveConfig(configPath, config) {
+  try {
+    const content = yaml.dump(config);
+    await fs.writeFile(configPath, content, 'utf8');
+  } catch (error) {
+    throw new Error(`Failed to save configuration: ${error.message}`);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov.info b/coverage/lcov.info index e69de29..9ea7c32 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -0,0 +1,143 @@ +TN: +SF:src/template-manager.js +FN:12,(anonymous_0) +FN:41,(anonymous_1) +FN:60,(anonymous_2) +FN:81,(anonymous_3) +FN:104,(anonymous_4) +FNF:5 +FNH:1 +FNDA:4,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +DA:13,4 +DA:15,4 +DA:18,0 +DA:21,0 +DA:24,0 +DA:27,0 +DA:30,0 +DA:32,4 +DA:42,0 +DA:49,0 +DA:50,0 +DA:61,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:71,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:92,0 +DA:105,0 +DA:106,0 +DA:109,0 +DA:110,0 +DA:111,0 +LF:28 +LH:3 +BRDA:65,0,0,0 +BRDA:65,0,1,0 +BRDA:109,1,0,0 +BRDA:109,1,1,0 +BRDA:109,2,0,0 +BRDA:109,2,1,0 +BRF:6 +BRH:0 +end_of_record +TN: +SF:src/utils.js +FN:14,getToolVersion +FN:32,copyDir +FN:59,parseVersion +FN:71,checkVersion +FN:89,getTemplatePath +FN:98,loadConfig +FN:119,saveConfig +FNF:7 +FNH:5 +FNDA:2,getToolVersion +FNDA:0,copyDir +FNDA:3,parseVersion +FNDA:3,checkVersion +FNDA:0,getTemplatePath +FNDA:2,loadConfig +FNDA:1,saveConfig +DA:7,2 +DA:15,2 +DA:16,2 +DA:17,0 +DA:19,2 +DA:20,1 +DA:21,1 +DA:23,1 +DA:33,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:50,0 +DA:60,3 +DA:61,3 +DA:62,3 +DA:72,3 +DA:73,3 +DA:75,3 +DA:76,4 +DA:77,4 +DA:78,4 +DA:79,2 +DA:81,0 +DA:90,0 +DA:99,2 +DA:100,2 +DA:101,1 +DA:102,1 +DA:103,0 +DA:105,1 +DA:107,1 +DA:108,0 +DA:110,1 +DA:120,1 +DA:121,1 +DA:122,1 +DA:124,0 +LF:45 +LH:27 +BRDA:16,0,0,0 +BRDA:16,0,1,2 +BRDA:42,1,0,0 +BRDA:42,1,1,0 +BRDA:61,2,0,0 +BRDA:61,2,1,3 +BRDA:62,3,0,1 +BRDA:62,3,1,2 +BRDA:76,4,0,4 +BRDA:76,4,1,0 +BRDA:77,5,0,4 +BRDA:77,5,1,1 +BRDA:78,6,0,2 +BRDA:78,6,1,2 +BRDA:79,7,0,1 +BRDA:79,7,1,1 +BRDA:102,8,0,0 +BRDA:102,8,1,1 +BRDA:102,9,0,1 +BRDA:102,9,1,1 +BRDA:107,10,0,0 +BRDA:107,10,1,1 +BRF:22 +BRH:15 +end_of_record diff --git a/jest.config.js b/jest.config.js index 7aa9378..2dfb2dc 100644 --- a/jest.config.js +++ b/jest.config.js @@ -10,4 +10,7 @@ export default { ], moduleFileExtensions: ['js'], transform: {}, + moduleNameMapper: { + '^(\\.{1,2}/.*)\\.js$': '$1' + } }; diff --git a/package.json b/package.json index 9ef60f1..69ba6ab 100644 --- a/package.json +++ b/package.json @@ -13,14 +13,15 @@ }, "scripts": { "test": "npm run test:unit && npm run test:shell", - "test:unit": "jest", + "test:unit": "NODE_OPTIONS=--experimental-vm-modules jest", "test:shell": "bats tests/shell/*.bats", "lint:shell": "shellcheck --severity=error src/**/*.sh", "test:watch": "jest --watch", "test:coverage": "jest --coverage", "prepare": "npm run build", "build": "node scripts/build.js", - "release": "standard-version" + "release": "standard-version", + "verify": "node scripts/verify-package.js" }, "keywords": [ "development", @@ -49,13 +50,12 @@ "chalk": "^5.3.0", "commander": "^11.1.0", "inquirer": "^9.2.12", - "ora": "^7.0.1", - "yaml": "^2.3.4" + "js-yaml": "^4.1.0", + "ora": "^7.0.1" }, "devDependencies": { "bats": "^1.11.0", "jest": "^29.7.0", - "js-yaml": "^4.1.0", "shellcheck": "^3.0.0", "standard-version": "^9.5.0" } diff --git a/scripts/verify-package.js b/scripts/verify-package.js new file mode 100755 index 0000000..f63b48f --- /dev/null +++ b/scripts/verify-package.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +import { TemplateManager, getToolVersion } from '../src/index.js'; + +async function verifyPackage() { + console.log('Verifying package functionality...'); + + // Test importing and instantiating TemplateManager + const templateManager = new TemplateManager(); + console.log('✓ Successfully imported and instantiated TemplateManager'); + + // Test utility function + const nodeVersion = await getToolVersion('node --version'); + console.log(`✓ Successfully retrieved Node.js version: ${nodeVersion}`); + + console.log('\nPackage verification complete! 🎉'); +} + +verifyPackage().catch(console.error); diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..f1da5ba --- /dev/null +++ b/src/index.js @@ -0,0 +1,12 @@ +// Main exports +export { TemplateManager } from './template-manager.js'; +export { + getToolVersion, + checkVersion, + loadConfig, + saveConfig, + commandExists, + parseVersion, + copyDir, + getTemplatePath +} from './utils.js'; diff --git a/src/template-manager.js b/src/template-manager.js index cb807a3..05dad86 100644 --- a/src/template-manager.js +++ b/src/template-manager.js @@ -1,24 +1,31 @@ import { promises as fs } from 'fs'; -import { join } from 'path'; -import { getTemplatePath, copyDir, loadConfig, saveConfig } from './utils.js'; +import path from 'path'; +import * as utils from './utils.js'; export class TemplateManager { /** - * Apply a template to a project + * Create a new project from a template * @param {string} projectDir - Project directory * @param {string} framework - Framework name - * @param {string} preset - Configuration preset + * @param {string} preset - Preset name */ async applyTemplate(projectDir, framework, preset) { - const templateDir = getTemplatePath(framework); - try { + // Create project directory first + await fs.mkdir(projectDir, { recursive: true }); + + // Get template directory + const templateDir = utils.getTemplatePath(framework); + + // Create project structure + await this._createProjectStructure(projectDir); + // Copy template files await this._copyTemplateFiles(templateDir, projectDir); - - // Load and customize configuration + + // Setup configuration await this._setupConfiguration(projectDir, framework, preset); - + // Framework-specific setup await this._frameworkSetup(projectDir, framework); } catch (error) { @@ -27,117 +34,82 @@ export class TemplateManager { } /** - * Copy template files to project + * Create project directory structure + * @param {string} projectDir - Project directory * @private */ - async _copyTemplateFiles(templateDir, projectDir) { - // Copy template files - const templateConfig = await loadConfig(join(templateDir, 'config-template.yaml')); - - // Create necessary directories + async _createProjectStructure(projectDir) { const dirs = [ 'src', 'tests', 'docs', - '.dev-session-buddy', - ...(templateConfig.directories || []) + '.dev-session-buddy' ]; for (const dir of dirs) { - await fs.mkdir(join(projectDir, dir), { recursive: true }); + await fs.mkdir(path.join(projectDir, dir), { recursive: true }); } + } - // Copy framework-specific files - const templateFiles = await fs.readdir(templateDir); - for (const file of templateFiles) { - if (file === 'config-template.yaml') continue; // Skip template config - - const srcPath = join(templateDir, file); - const destPath = join(projectDir, file); - - const stats = await fs.stat(srcPath); - if (stats.isDirectory()) { - await copyDir(srcPath, destPath); - } else { - await fs.copyFile(srcPath, destPath); - // Preserve executable permissions - await fs.chmod(destPath, stats.mode); - } + /** + * Copy template files + * @param {string} templateDir - Template directory + * @param {string} projectDir - Project directory + * @private + */ + async _copyTemplateFiles(templateDir, projectDir) { + const config = await utils.loadConfig(path.join(templateDir, 'config-template.yaml')); + const entries = await fs.readdir(templateDir); + + for (const entry of entries) { + if (entry === 'config-template.yaml') continue; + const srcPath = path.join(templateDir, entry); + const destPath = path.join(projectDir, entry); + await utils.copyDir(srcPath, destPath); } + + return config; } /** * Setup project configuration + * @param {string} projectDir - Project directory + * @param {string} framework - Framework name + * @param {string} preset - Preset name * @private */ async _setupConfiguration(projectDir, framework, preset) { - const templateDir = getTemplatePath(framework); - const templateConfig = await loadConfig(join(templateDir, 'config-template.yaml')); - - // Customize configuration based on preset - const config = { - ...templateConfig, - testing: templateConfig.testing || {}, - documentation: templateConfig.documentation || {}, - standards: templateConfig.standards || {}, - tools: templateConfig.tools || {} + const templateDir = utils.getTemplatePath(framework); + const config = await utils.loadConfig(path.join(templateDir, 'config-template.yaml')); + + const projectConfig = { + ...config, + framework, + preset, + createdAt: new Date().toISOString() }; - config.preset = preset; - - if (preset === 'minimal') { - // Simplify configuration for minimal preset - delete config.tools.optional; - config.testing.coverage = 0; - config.documentation.required = false; - } else if (preset === 'team') { - // Add team-specific settings - config.standards.review = { - required: true, - minReviewers: 2 - }; - } - // Save configuration - await saveConfig(join(projectDir, 'dev-session-buddy.yaml'), config); + await utils.saveConfig( + path.join(projectDir, 'dev-session-buddy.yaml'), + projectConfig + ); } /** - * Perform framework-specific setup + * Framework-specific setup + * @param {string} projectDir - Project directory + * @param {string} framework - Framework name * @private */ async _frameworkSetup(projectDir, framework) { - if (framework === 'vue') { - // Vue.js specific setup - const packageJson = { - name: projectDir.split('/').pop(), - version: '0.1.0', - type: 'module', - scripts: { - dev: 'vite', - build: 'vite build', - preview: 'vite preview', - test: 'vitest', - lint: 'eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore' - }, - dependencies: { - vue: '^3.3.0', - 'vue-router': '^4.2.0', - pinia: '^2.1.0' - }, - devDependencies: { - '@vitejs/plugin-vue': '^4.4.0', - vite: '^4.5.0', - vitest: '^0.34.0', - '@vue/test-utils': '^2.4.0', - eslint: '^8.49.0', - 'eslint-plugin-vue': '^9.17.0' - } - }; - - await fs.writeFile( - join(projectDir, 'package.json'), - JSON.stringify(packageJson, null, 2) - ); + const templateDir = utils.getTemplatePath(framework); + const config = await utils.loadConfig(path.join(templateDir, 'config-template.yaml')); + + // Create framework-specific directories + if (config.directories && Array.isArray(config.directories)) { + for (const dir of config.directories) { + await fs.mkdir(path.join(projectDir, 'src', dir), { recursive: true }); + } } } } diff --git a/src/utils.js b/src/utils.js index d12666e..f0e5c34 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,128 +1,74 @@ +import { promises as fsPromises } from 'fs'; import { exec } from 'child_process'; import { promisify } from 'util'; -import { promises as fs } from 'fs'; -import { join, dirname } from 'path'; -import { fileURLToPath } from 'url'; +import path from 'path'; +import yaml from 'js-yaml'; const execAsync = promisify(exec); -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - /** - * Get the version of a CLI tool - * @param {string} command - Command to get version - * @returns {Promise} Version string + * Check if a command exists in the system + * @param {string} command - Command to check + * @returns {Promise} - True if command exists */ -export async function getToolVersion(command) { +export async function commandExists(command) { try { - if (command === 'node --version') { - return process.version; - } - const { stdout } = await execAsync(command); - return stdout.trim(); - } catch (error) { - return null; - } -} - -/** - * Copy a directory recursively - * @param {string} src - Source directory - * @param {string} dest - Destination directory - */ -export async function copyDir(src, dest) { - await fs.mkdir(dest, { recursive: true }); - const entries = await fs.readdir(src, { withFileTypes: true }); - - for (const entry of entries) { - const srcPath = join(src, entry.name); - const destPath = join(dest, entry.name); - - if (entry.isDirectory()) { - await copyDir(srcPath, destPath); - } else { - await fs.copyFile(srcPath, destPath); - // Preserve executable permissions - const stats = await fs.stat(srcPath); - await fs.chmod(destPath, stats.mode); - } + const { stdout } = await execAsync(`command -v ${command}`); + return !!stdout; + } catch { + return false; } } /** - * Get template directory path - * @param {string} framework - Framework name - * @returns {string} Template directory path - */ -export function getTemplatePath(framework) { - return join(__dirname, 'templates', framework); -} - -/** - * Check if a command exists in PATH - * @param {string} command - Command to check - * @returns {Promise} Whether command exists + * Get version of a tool from command line + * @param {string} command - Command to execute + * @returns {Promise} - Version string or null if error */ -export async function commandExists(command) { +export async function getToolVersion(command) { try { - if (command === 'node') { - return process.execPath !== undefined; - } - await execAsync(`command -v ${command}`); - return true; + const { stdout } = await execAsync(command); + return parseVersion(stdout.trim()); } catch { - return false; + return null; } } /** - * Parse version string to components - * @param {string} version - Version string (e.g., "v14.17.0" or "14.17.0") - * @returns {number[]} Version components + * Parse version string + * @param {string} version - Version string + * @returns {string} - Normalized version string */ export function parseVersion(version) { - const match = version.match(/\d+\.\d+\.\d+/); - if (!match) return [0, 0, 0]; - return match[0].split('.').map(Number); + return version.startsWith('v') ? version : `v${version}`; } /** * Check if version meets minimum requirement - * @param {string} current - Current version - * @param {string} required - Required version - * @returns {boolean} Whether version is sufficient + * @param {string} version - Version to check + * @param {string} minVersion - Minimum version required + * @returns {boolean} - True if version meets requirement */ -export function checkVersion(current, required) { - const currentParts = parseVersion(current); - const requiredParts = parseVersion(required.replace(/[^\d.]/g, '')); +export function checkVersion(version, minVersion) { + const v1 = version.replace('v', '').split('.').map(Number); + const v2 = minVersion.replace('v', '').split('.').map(Number); for (let i = 0; i < 3; i++) { - if (currentParts[i] > requiredParts[i]) return true; - if (currentParts[i] < requiredParts[i]) return false; + if (v1[i] > v2[i]) return true; + if (v1[i] < v2[i]) return false; } return true; } /** - * Get project root directory - * @returns {string} Project root directory - */ -export function getProjectRoot() { - return join(__dirname, '..'); -} - -/** - * Load and parse YAML configuration - * @param {string} path - Path to YAML file - * @returns {Promise} Configuration object + * Load YAML configuration file + * @param {string} configPath - Path to config file + * @returns {Promise} - Configuration object */ -export async function loadConfig(path) { +export async function loadConfig(configPath) { try { - const yamlContent = await fs.readFile(path, 'utf8'); - // Note: We're using the yaml package which was added to package.json - const yaml = (await import('yaml')).default; - return yaml.parse(yamlContent); + const content = await fsPromises.readFile(configPath, 'utf8'); + return yaml.load(content); } catch (error) { throw new Error(`Failed to load configuration: ${error.message}`); } @@ -130,14 +76,48 @@ export async function loadConfig(path) { /** * Save configuration to YAML file - * @param {string} path - Path to YAML file + * @param {string} configPath - Path to save config * @param {object} config - Configuration object */ -export async function saveConfig(path, config) { +export async function saveConfig(configPath, config) { try { - const yaml = (await import('yaml')).default; - await fs.writeFile(path, yaml.stringify(config)); + const yamlStr = yaml.dump(config); + await fsPromises.writeFile(configPath, yamlStr, 'utf8'); } catch (error) { throw new Error(`Failed to save configuration: ${error.message}`); } } + +/** + * Copy directory recursively + * @param {string} src - Source directory + * @param {string} dest - Destination directory + */ +export async function copyDir(src, dest) { + try { + const entries = await fsPromises.readdir(src, { withFileTypes: true }); + await fsPromises.mkdir(dest, { recursive: true }); + + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + if (entry.isDirectory()) { + await copyDir(srcPath, destPath); + } else { + await fsPromises.copyFile(srcPath, destPath); + } + } + } catch (error) { + throw new Error(`Failed to copy directory: ${error.message}`); + } +} + +/** + * Get template path for framework + * @param {string} framework - Framework name + * @returns {string} - Template path + */ +export function getTemplatePath(framework) { + return path.join(process.cwd(), 'templates', framework); +} diff --git a/tests/unit/config.test.js b/tests/unit/config.test.js index 8e47e39..b7df5da 100644 --- a/tests/unit/config.test.js +++ b/tests/unit/config.test.js @@ -1,6 +1,6 @@ -const fs = require('fs'); -const path = require('path'); -const yaml = require('js-yaml'); +import fs from 'fs'; +import path from 'path'; +import yaml from 'js-yaml'; describe('Configuration Files', () => { test('default.yaml has valid syntax', () => { diff --git a/tests/unit/template-manager.test.js b/tests/unit/template-manager.test.js new file mode 100644 index 0000000..cddd739 --- /dev/null +++ b/tests/unit/template-manager.test.js @@ -0,0 +1,104 @@ +import { jest } from '@jest/globals'; +import { TemplateManager } from '../../src/template-manager.js'; +import path from 'path'; + +// Mock dependencies +const mockFsPromises = { + mkdir: jest.fn().mockResolvedValue(undefined), + readdir: jest.fn().mockResolvedValue(['config-template.yaml', 'package.json']), + copyFile: jest.fn().mockResolvedValue(undefined), + stat: jest.fn().mockResolvedValue({ isDirectory: () => false }), + chmod: jest.fn().mockResolvedValue(undefined) +}; + +jest.mock('fs', () => ({ + promises: mockFsPromises +})); + +const mockTemplateConfig = { + dependencies: { + required: ['vue', 'vite'], + dev: ['jest', 'eslint'] + } +}; + +const mockUtils = { + loadConfig: jest.fn().mockResolvedValue(mockTemplateConfig), + saveConfig: jest.fn().mockResolvedValue(undefined), + copyDir: jest.fn().mockResolvedValue(undefined), + getTemplatePath: jest.fn().mockReturnValue('/templates/vue') +}; + +jest.mock('../../src/utils.js', () => mockUtils); + +// Mock path +const mockPath = { + join: jest.fn().mockImplementation((...args) => args.join('/')), + resolve: jest.fn().mockImplementation((...args) => args.join('/')) +}; + +jest.mock('path', () => mockPath); + +describe('TemplateManager', () => { + let templateManager; + const projectDir = '/test/project'; + const framework = 'vue'; + const preset = 'default'; + + beforeEach(() => { + templateManager = new TemplateManager(); + jest.clearAllMocks(); + }); + + describe('Template Application', () => { + test('should create project directory', async () => { + await templateManager.applyTemplate(projectDir, framework, preset); + + expect(mockFsPromises.mkdir).toHaveBeenCalledWith( + projectDir, + { recursive: true } + ); + + // Verify essential directories are created + const essentialDirs = ['src', 'tests', 'docs', '.dev-session-buddy']; + essentialDirs.forEach(dir => { + expect(mockFsPromises.mkdir).toHaveBeenCalledWith( + projectDir + '/' + dir, + { recursive: true } + ); + }); + }); + + test('should copy template files', async () => { + await templateManager.applyTemplate(projectDir, framework, preset); + + expect(mockUtils.getTemplatePath).toHaveBeenCalledWith(framework); + expect(mockUtils.loadConfig).toHaveBeenCalledWith( + '/templates/vue/config-template.yaml' + ); + expect(mockUtils.copyDir).toHaveBeenCalled(); + }); + + test('should save project configuration', async () => { + await templateManager.applyTemplate(projectDir, framework, preset); + + expect(mockUtils.saveConfig).toHaveBeenCalledWith( + projectDir + '/dev-session-buddy.yaml', + expect.objectContaining({ + framework, + preset, + dependencies: mockTemplateConfig.dependencies, + createdAt: expect.any(String) + }) + ); + }); + + test('should handle errors gracefully', async () => { + mockFsPromises.mkdir.mockRejectedValue(new Error('Failed to create directory')); + + await expect( + templateManager.applyTemplate(projectDir, framework, preset) + ).rejects.toThrow('Failed to apply template'); + }); + }); +}); diff --git a/tests/unit/utils.test.js b/tests/unit/utils.test.js new file mode 100644 index 0000000..74c4d37 --- /dev/null +++ b/tests/unit/utils.test.js @@ -0,0 +1,107 @@ +import { jest } from '@jest/globals'; +import * as utils from '../../src/utils.js'; +import { promises as fsPromises } from 'fs'; +import path from 'path'; +import yaml from 'js-yaml'; + +// Mock dependencies +const mockFsPromises = { + readFile: jest.fn(), + writeFile: jest.fn() +}; + +jest.mock('fs', () => ({ + promises: mockFsPromises +})); + +const mockExec = jest.fn(); +jest.mock('child_process', () => ({ + exec: (cmd, cb) => mockExec(cmd, cb) +})); + +// Mock yaml +const mockYaml = { + load: jest.fn(), + dump: jest.fn() +}; + +jest.mock('js-yaml', () => mockYaml); + +describe('Utils', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('getToolVersion', () => { + test('should return version from command execution', async () => { + mockExec.mockImplementation((cmd, cb) => cb(null, { stdout: 'v1.2.3' })); + const result = await utils.getToolVersion('git --version'); + expect(result).toMatch(/^v\d+\.\d+\.\d+$/); + }); + + test('should return null on error', async () => { + mockExec.mockImplementation((cmd, cb) => cb(new Error('Command failed'))); + const result = await utils.getToolVersion('invalid-command'); + expect(result).toBeNull(); + }); + }); + + describe('parseVersion', () => { + test('should parse version string with v prefix', () => { + const result = utils.parseVersion('v1.2.3'); + expect(result).toBe('v1.2.3'); + }); + + test('should parse version string without v prefix', () => { + const result = utils.parseVersion('1.2.3'); + expect(result).toBe('v1.2.3'); + }); + }); + + describe('checkVersion', () => { + test('should compare versions correctly', () => { + expect(utils.checkVersion('v2.0.0', 'v1.0.0')).toBe(true); + expect(utils.checkVersion('2.1.0', '2.0.0')).toBe(true); + expect(utils.checkVersion('v1.0.0', 'v2.0.0')).toBe(false); + }); + }); + + describe('configuration', () => { + const mockConfig = { + framework: 'vue', + dependencies: { + required: ['vue', 'vite'], + dev: ['jest', 'eslint'] + } + }; + + const mockYamlContent = 'framework: vue\ndependencies:\n required:\n - vue\n - vite\n dev:\n - jest\n - eslint\n'; + + beforeEach(() => { + mockFsPromises.readFile.mockResolvedValue(mockYamlContent); + mockYaml.load.mockReturnValue(mockConfig); + mockYaml.dump.mockReturnValue(mockYamlContent); + }); + + test('should load configuration', async () => { + const result = await utils.loadConfig('config.yaml'); + expect(result).toEqual(mockConfig); + expect(mockYaml.load).toHaveBeenCalledWith(mockYamlContent); + }); + + test('should handle load errors', async () => { + mockFsPromises.readFile.mockRejectedValue(new Error('File not found')); + await expect(utils.loadConfig('invalid.yaml')).rejects.toThrow('Failed to load configuration'); + }); + + test('should save configuration', async () => { + await utils.saveConfig('config.yaml', mockConfig); + expect(mockYaml.dump).toHaveBeenCalledWith(mockConfig); + expect(mockFsPromises.writeFile).toHaveBeenCalledWith( + 'config.yaml', + mockYamlContent, + 'utf8' + ); + }); + }); +});