From aa3132667b13e30fefdaa97932f89d8156a655a2 Mon Sep 17 00:00:00 2001 From: Martin Gran Date: Mon, 27 Oct 2025 19:43:03 +0000 Subject: [PATCH 01/26] feat: create copier template with jinja2 templating - Add copier.yml configuration with project questions - Template package.json with conditional dependencies (husky, lint-staged) - Template tsconfig.json with strict mode conditional - Template README.md with dynamic package manager and conditional sections - Add .copier-answers.yml.jinja for tracking template versions - Move all project files to template/ subdirectory - Add jinja2 extension support and skip_if_exists rules - Configure template suffix as .jinja Template supports: - Custom project name, description, author - Optional devcontainer setup - Optional Husky git hooks - Configurable TypeScript strict mode - Package manager selection (bun/npm/yarn/pnpm) - Git initialization toggle --- README.md | 214 ++++++------------ copier.yml | 80 +++++++ template/.copier-answers.yml.jinja | 15 ++ .../.devcontainer}/Dockerfile | 0 .../.devcontainer}/devcontainer.json | 0 .../.devcontainer}/docker-compose.yml | 0 .../.devcontainer}/postCreateCommand.sh | 0 .../.devcontainer}/postStartCommand.sh | 0 .editorconfig => template/.editorconfig.jinja | 0 .../.eslintrc.json.jinja | 0 {.github => template/.github}/dependabot.yml | 0 {.husky => template/.husky}/pre-commit | 0 .prettierrc => template/.prettierrc.jinja | 0 {.vscode => template/.vscode}/extensions.json | 0 {.vscode => template/.vscode}/settings.json | 0 template/README.md.jinja | 185 +++++++++++++++ knip.json => template/knip.json.jinja | 0 package.json => template/package.json.jinja | 18 +- {src => template/src}/index.ts | 0 tsconfig.json => template/tsconfig.json.jinja | 8 +- 20 files changed, 361 insertions(+), 159 deletions(-) create mode 100644 copier.yml create mode 100644 template/.copier-answers.yml.jinja rename {.devcontainer => template/.devcontainer}/Dockerfile (100%) rename {.devcontainer => template/.devcontainer}/devcontainer.json (100%) rename {.devcontainer => template/.devcontainer}/docker-compose.yml (100%) rename {.devcontainer => template/.devcontainer}/postCreateCommand.sh (100%) rename {.devcontainer => template/.devcontainer}/postStartCommand.sh (100%) rename .editorconfig => template/.editorconfig.jinja (100%) rename .eslintrc.json => template/.eslintrc.json.jinja (100%) rename {.github => template/.github}/dependabot.yml (100%) rename {.husky => template/.husky}/pre-commit (100%) rename .prettierrc => template/.prettierrc.jinja (100%) rename {.vscode => template/.vscode}/extensions.json (100%) rename {.vscode => template/.vscode}/settings.json (100%) create mode 100644 template/README.md.jinja rename knip.json => template/knip.json.jinja (100%) rename package.json => template/package.json.jinja (61%) rename {src => template/src}/index.ts (100%) rename tsconfig.json => template/tsconfig.json.jinja (70%) diff --git a/README.md b/README.md index e42c9eb..3464cdc 100644 --- a/README.md +++ b/README.md @@ -1,181 +1,97 @@ -# Multiplayer Game +# Copier Template for TypeScript/Bun Projects -A TypeScript-based multiplayer game project with a complete development setup. +This repository contains a [Copier](https://copier.readthedocs.io/) template for scaffolding TypeScript projects with Bun, complete linting/formatting setup, and optional devcontainer support. -## Quick Start +## Using This Template -```bash -# Install dependencies -bun install - -# Start development server -bun run dev - -# Build for production -bun run build - -# Run production build -bun run start -``` - -## Development Tools - -### Linting & Formatting +### Prerequisites ```bash -# Run ESLint -bun run lint -bun run lint:fix - -# Run Prettier -bun run format -bun run format:check - -# Find unused code/dependencies -bun run knip +# Install Copier (Python CLI tool) +pip install copier +# or +pipx install copier ``` -### Git Hooks - -Pre-commit hooks automatically run ESLint and Prettier on staged files: - -- Files are fixed but **not auto-staged** -- Review changes, then stage and commit again +### Generate a New Project -## Project Structure +```bash +# Using the template branch +copier copy --vcs-ref=template gh:your-username/your-repo path/to/new-project -``` -. -├── src/ # Source code -├── .devcontainer/ # Dev container configuration (optional) -├── .husky/ # Git hooks -├── .vscode/ # VSCode settings -└── dist/ # Build output +# Or if you've cloned this repo locally +copier copy path/to/this/repo/template path/to/new-project ``` -## Configuration Files +Copier will ask you several questions to customize your project: -- **`.prettierrc`** - Code formatting rules -- **`.eslintrc.json`** - Linting rules -- **`.editorconfig`** - Editor configuration -- **`knip.json`** - Unused code detection -- **`tsconfig.json`** - TypeScript configuration +- **Project name**: Name for your project (used in package.json) +- **Description**: Short description of your project +- **Author name**: Your name +- **Author email**: Your email address +- **Use Git**: Initialize git repository in new project +- **Use devcontainer**: Include VSCode devcontainer setup +- **Setup Husky**: Include git hooks for pre-commit linting +- **TypeScript strict mode**: Enable all strict TypeScript checks +- **Package manager**: Choose between bun, npm, yarn, or pnpm -## Converting to Monorepo +### What's Included -If you want to organize your code as a monorepo with separate packages (e.g., server/client): +The generated project includes: -### 1. Update `package.json` +- **Bun Runtime**: Fast JavaScript/TypeScript runtime and package manager +- **TypeScript**: Full TypeScript support with configurable strict mode +- **ESLint**: Code linting with TypeScript support +- **Prettier**: Code formatting with consistent style +- **Import Sorting**: Automatic import organization via eslint-plugin-simple-import-sort +- **Knip**: Unused code and dependency detection +- **Husky** (optional): Git hooks for pre-commit checks +- **lint-staged** (optional): Run linters only on staged files +- **Devcontainer** (optional): Complete Docker-based development environment -```json -{ - "name": "multiplayer-game-monorepo", - "workspaces": ["packages/*"], - "scripts": { - "build": "bun run --filter '*' build", - "dev": "bun run --filter '*' dev", - "lint": "bun run --filter '*' lint" - } -} -``` +### Project Scripts -### 2. Create Package Structure +After generation, the following scripts are available: ```bash -mkdir -p packages/server packages/client - -# Move existing code or create new packages -mv src packages/server/src -``` - -### 3. Create Package package.json Files - -**packages/server/package.json:** - -```json -{ - "name": "@your-game/server", - "version": "1.0.0", - "main": "dist/index.js", - "scripts": { - "build": "tsc", - "dev": "bun run --watch src/index.ts" - } -} -``` - -**packages/client/package.json:** - -```json -{ - "name": "@your-game/client", - "version": "1.0.0", - "main": "dist/index.js", - "scripts": { - "build": "tsc", - "dev": "bun run --watch src/index.ts" - } -} +# Development +bun run dev # Run in development mode with watch +bun run build # Build for production +bun start # Run the built project + +# Code Quality +bun run lint # Check for linting issues +bun run lint:fix # Auto-fix linting issues +bun run format # Format code with Prettier +bun run format:check # Check if code is formatted +bun run knip # Find unused code and dependencies ``` -### 4. Update `knip.json` - -```json -{ - "$schema": "https://unpkg.com/knip@latest/schema.json", - "workspaces": { - ".": { - "entry": ["index.ts"], - "project": ["**/*.ts"] - }, - "packages/*": { - "entry": ["src/index.ts"], - "project": ["src/**/*.ts"] - } - } -} -``` +### Development Environment Options -### 5. Update `tsconfig.json` - -Create a root `tsconfig.json`: - -```json -{ - "files": [], - "references": [{ "path": "./packages/server" }, { "path": "./packages/client" }] -} +#### Without Devcontainer +Just install Bun locally: +```bash +curl -fsSL https://bun.sh/install | bash +bun install ``` -Each package gets its own `tsconfig.json`: - -```json -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src" - }, - "include": ["src"] -} -``` +#### With Devcontainer +Open the project in VSCode and use the "Reopen in Container" command. Everything is pre-configured. -## Dev Container (Optional) +## Branch Structure -This project includes a dev container configuration for consistent development environments: +- **main**: Working example project (this README documents the template) +- **template**: Copier template with Jinja2-templated files -```bash -# Open in VS Code with Dev Containers extension -code . -# Then: Reopen in Container -``` +## Template Development -Features: +To modify the template: -- Bun pre-installed -- ZSH with Oh My Zsh -- All extensions auto-installed -- Persistent command history +1. Switch to template branch: `git checkout template` +2. Edit files in `template/` directory +3. Modify `copier.yml` to add/change questions +4. Test locally: `copier copy template /tmp/test-project` ## License diff --git a/copier.yml b/copier.yml new file mode 100644 index 0000000..c18afd1 --- /dev/null +++ b/copier.yml @@ -0,0 +1,80 @@ +# Copier Template Configuration +# Learn more: https://copier.readthedocs.io/ + +_templates_suffix: .jinja +_subdirectory: template +_exclude: + - copier.yml + - .copier-answers.yml + - .git + - .gitignore.jinja + - "*.pyc" + - __pycache__ + +# Template Questions +project_name: + type: str + help: What is your project name? + default: my-project + validator: >- + {% if not (project_name | regex_search('^[a-z][a-z0-9-]*$')) %} + project_name must start with a letter and only contain lowercase letters, numbers, and hyphens + {% endif %} + +project_description: + type: str + help: Brief project description + default: A TypeScript project + +author_name: + type: str + help: Author name + default: Your Name + +author_email: + type: str + help: Author email + default: you@example.com + +use_git: + type: bool + help: Initialize git repository? + default: true + +use_devcontainer: + type: bool + help: Include dev container configuration? + default: true + +setup_husky: + type: bool + help: Set up git hooks with Husky? + default: true + when: "{{ use_git }}" + +typescript_strict: + type: bool + help: Use strict TypeScript configuration? + default: true + +include_examples: + type: bool + help: Include example code? + default: false + +package_manager: + type: str + help: Which package manager? + choices: + - bun + - npm + - yarn + - pnpm + default: bun + +_jinja_extensions: + - jinja2.ext.do + +_skip_if_exists: + - .git + - node_modules diff --git a/template/.copier-answers.yml.jinja b/template/.copier-answers.yml.jinja new file mode 100644 index 0000000..db57e3f --- /dev/null +++ b/template/.copier-answers.yml.jinja @@ -0,0 +1,15 @@ +# Answers to copier template questions +# This file is used by Copier to track template version and user's answers + +_src_path: {{ _copier_conf.src_path }} +_commit: {{ _copier_conf.vcs_ref_hash }} + +project_name: "{{ project_name }}" +project_description: "{{ project_description }}" +author_name: "{{ author_name }}" +author_email: "{{ author_email }}" +use_git: {{ use_git }} +use_devcontainer: {{ use_devcontainer }} +setup_husky: {{ setup_husky }} +typescript_strict: {{ typescript_strict }} +package_manager: "{{ package_manager }}" diff --git a/.devcontainer/Dockerfile b/template/.devcontainer/Dockerfile similarity index 100% rename from .devcontainer/Dockerfile rename to template/.devcontainer/Dockerfile diff --git a/.devcontainer/devcontainer.json b/template/.devcontainer/devcontainer.json similarity index 100% rename from .devcontainer/devcontainer.json rename to template/.devcontainer/devcontainer.json diff --git a/.devcontainer/docker-compose.yml b/template/.devcontainer/docker-compose.yml similarity index 100% rename from .devcontainer/docker-compose.yml rename to template/.devcontainer/docker-compose.yml diff --git a/.devcontainer/postCreateCommand.sh b/template/.devcontainer/postCreateCommand.sh similarity index 100% rename from .devcontainer/postCreateCommand.sh rename to template/.devcontainer/postCreateCommand.sh diff --git a/.devcontainer/postStartCommand.sh b/template/.devcontainer/postStartCommand.sh similarity index 100% rename from .devcontainer/postStartCommand.sh rename to template/.devcontainer/postStartCommand.sh diff --git a/.editorconfig b/template/.editorconfig.jinja similarity index 100% rename from .editorconfig rename to template/.editorconfig.jinja diff --git a/.eslintrc.json b/template/.eslintrc.json.jinja similarity index 100% rename from .eslintrc.json rename to template/.eslintrc.json.jinja diff --git a/.github/dependabot.yml b/template/.github/dependabot.yml similarity index 100% rename from .github/dependabot.yml rename to template/.github/dependabot.yml diff --git a/.husky/pre-commit b/template/.husky/pre-commit similarity index 100% rename from .husky/pre-commit rename to template/.husky/pre-commit diff --git a/.prettierrc b/template/.prettierrc.jinja similarity index 100% rename from .prettierrc rename to template/.prettierrc.jinja diff --git a/.vscode/extensions.json b/template/.vscode/extensions.json similarity index 100% rename from .vscode/extensions.json rename to template/.vscode/extensions.json diff --git a/.vscode/settings.json b/template/.vscode/settings.json similarity index 100% rename from .vscode/settings.json rename to template/.vscode/settings.json diff --git a/template/README.md.jinja b/template/README.md.jinja new file mode 100644 index 0000000..bbcf0e2 --- /dev/null +++ b/template/README.md.jinja @@ -0,0 +1,185 @@ +# {{ project_name }} + +{{ project_description }} + +## Quick Start + +```bash +# Install dependencies +{{ package_manager }} install + +# Start development server +{{ package_manager }} run dev + +# Build for production +{{ package_manager }} run build + +# Run production build +{{ package_manager }} {% if package_manager == "bun" %}start{% else %}run start{% endif %} +``` + +## Development Tools + +### Linting & Formatting + +```bash +# Run ESLint +{{ package_manager }} run lint +{{ package_manager }} run lint:fix + +# Run Prettier +{{ package_manager }} run format +{{ package_manager }} run format:check + +# Find unused code/dependencies +{{ package_manager }} run knip +``` +{% if setup_husky %} +### Git Hooks + +Pre-commit hooks automatically run ESLint and Prettier on staged files: + +- Files are fixed but **not auto-staged** +- Review changes, then stage and commit again +{% endif %} + +## Project Structure + +``` +.{% if use_devcontainer %} +├── .devcontainer/ # Dev container configuration{% endif %}{% if setup_husky %} +├── .husky/ # Git hooks{% endif %} +├── .vscode/ # VSCode settings +├── src/ # Source code +└── dist/ # Build output +``` + +## Configuration Files + +- **`.prettierrc`** - Code formatting rules +- **`.eslintrc.json`** - Linting rules +- **`.editorconfig`** - Editor configuration +- **`knip.json`** - Unused code detection +- **`tsconfig.json`** - TypeScript configuration{% if typescript_strict %} (strict mode enabled){% endif %} + +## Converting to Monorepo + +If you want to organize your code as a monorepo with separate packages (e.g., server/client): + +### 1. Update `package.json` + +```json +{ + "name": "{{ project_name }}-monorepo", + "workspaces": ["packages/*"], + "scripts": { + "build": "{{ package_manager }} run --filter '*' build", + "dev": "{{ package_manager }} run --filter '*' dev", + "lint": "{{ package_manager }} run --filter '*' lint" + } +} +``` + +### 2. Create Package Structure + +```bash +mkdir -p packages/server packages/client + +# Move existing code or create new packages +mv src packages/server/src +``` + +### 3. Create Package package.json Files + +**packages/server/package.json:** + +```json +{ + "name": "@your-game/server", + "version": "1.0.0", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "dev": "bun run --watch src/index.ts" + } +} +``` + +**packages/client/package.json:** + +```json +{ + "name": "@your-game/client", + "version": "1.0.0", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "dev": "bun run --watch src/index.ts" + } +} +``` + +### 4. Update `knip.json` + +```json +{ + "$schema": "https://unpkg.com/knip@latest/schema.json", + "workspaces": { + ".": { + "entry": ["index.ts"], + "project": ["**/*.ts"] + }, + "packages/*": { + "entry": ["src/index.ts"], + "project": ["src/**/*.ts"] + } + } +} +``` + +### 5. Update `tsconfig.json` + +Create a root `tsconfig.json`: + +```json +{ + "files": [], + "references": [{ "path": "./packages/server" }, { "path": "./packages/client" }] +} +``` + +Each package gets its own `tsconfig.json`: + +```json +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src"] +} +``` + +{% if use_devcontainer %} +## Dev Container + +This project includes a dev container configuration for consistent development environments: + +```bash +# Open in VS Code with Dev Containers extension +code . +# Then: Reopen in Container +``` + +Features: + +- Bun pre-installed +- ZSH with Oh My Zsh +- All extensions auto-installed +- Persistent command history +{% endif %} + +## License + +MIT diff --git a/knip.json b/template/knip.json.jinja similarity index 100% rename from knip.json rename to template/knip.json.jinja diff --git a/package.json b/template/package.json.jinja similarity index 61% rename from package.json rename to template/package.json.jinja index b6cb886..fb0ff42 100755 --- a/package.json +++ b/template/package.json.jinja @@ -1,18 +1,20 @@ { - "name": "multiplayer-game", + "name": "{{ project_name }}", "version": "1.0.0", - "private": true, + "description": "{{ project_description }}", + "private": true,{% if author_name %} + "author": "{{ author_name }}{% if author_email %} <{{ author_email }}>{% endif %}",{% endif %} "scripts": { "build": "tsc", - "dev": "bun run --watch src/index.ts", - "start": "bun run src/index.ts", + "dev": "{{ package_manager }} run --watch src/index.ts", + "start": "{{ package_manager }} run src/index.ts", "lint": "eslint . --ext .ts,.tsx,.js,.jsx", "lint:fix": "eslint . --ext .ts,.tsx,.js,.jsx --fix", "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\"", "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\"", "knip": "knip", - "knip:production": "knip --production", - "prepare": "husky install" + "knip:production": "knip --production"{% if setup_husky %}, + "prepare": "husky install"{% endif %} }, "lint-staged": { "*.{ts,tsx,js,jsx}": [ @@ -30,10 +32,10 @@ "eslint": "^8.50.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^5.0.0", - "eslint-plugin-simple-import-sort": "^12.1.0", + "eslint-plugin-simple-import-sort": "^12.1.0",{% if setup_husky %} "husky": "^8.0.3", + "lint-staged": "^15.2.10",{% endif %} "knip": "^5.33.3", - "lint-staged": "^15.2.10", "prettier": "^3.0.0", "typescript": "^5.2.2" } diff --git a/src/index.ts b/template/src/index.ts similarity index 100% rename from src/index.ts rename to template/src/index.ts diff --git a/tsconfig.json b/template/tsconfig.json.jinja similarity index 70% rename from tsconfig.json rename to template/tsconfig.json.jinja index 0a5dd2a..f1763ca 100644 --- a/tsconfig.json +++ b/template/tsconfig.json.jinja @@ -6,7 +6,7 @@ "moduleResolution": "bundler", "allowImportingTsExtensions": true, "noEmit": true, - "composite": true, + "composite": true,{% if typescript_strict %} "strict": true, "skipLibCheck": true, "esModuleInterop": true, @@ -16,7 +16,11 @@ "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, + "noFallthroughCasesInSwitch": true,{% else %} + "skipLibCheck": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true,{% endif %} "outDir": "./dist", "rootDir": "./src" }, From fbc5d3ce96366786be4067ae09ff7a9ff99c4b6d Mon Sep 17 00:00:00 2001 From: Martin Gran Date: Tue, 28 Oct 2025 13:10:57 +0000 Subject: [PATCH 02/26] create copier template --- .../Dockerfile | 0 .../devcontainer.json | 0 .../docker-compose.yml | 0 .../postCreateCommand.sh | 0 .../postStartCommand.sh | 0 .github/workflows/deploy.yaml | 140 ++++++ .gitignore | 135 +---- {template/.vscode => .vscode}/extensions.json | 0 {template/.vscode => .vscode}/settings.json | 0 Makefile | 148 ++++++ README.md | 216 +++++--- bun.lock | 469 ------------------ copier.yaml | 124 +++++ copier.yml | 80 --- includes/slugify.jinja | 9 + template/.copier-answers.yml.jinja | 2 - template/.env.example.jinja | 48 ++ template/.eslintrc.json.jinja | 3 +- template/.gitignore.jinja | 120 +++++ template/.husky/pre-commit | 5 + template/.secretlintrc.json.jinja | 13 + template/CHANGELOG.md.jinja | 35 ++ template/CONTRIBUTING.md.jinja | 186 +++++++ template/LICENSE.jinja | 21 + template/README.md.jinja | 205 ++++++-- template/package.json.jinja | 18 +- template/src/index.ts | 46 +- template/src/lib/env.ts | 27 + template/src/lib/graceful-shutdown.ts | 67 +++ template/tsconfig.json.jinja | 9 +- .../pre-commit | 12 + .../Dockerfile | 37 ++ .../devcontainer.json | 52 ++ .../docker-compose.yml.jinja | 23 + .../postCreateCommand.sh | 8 + .../postStartCommand.sh | 6 + .../dependabot.yml | 10 + .../workflows/ci.yaml.jinja | 69 +++ .../extensions.json | 12 + .../settings.json | 34 ++ 40 files changed, 1602 insertions(+), 787 deletions(-) rename {template/.devcontainer => .devcontainer}/Dockerfile (100%) rename {template/.devcontainer => .devcontainer}/devcontainer.json (100%) rename {template/.devcontainer => .devcontainer}/docker-compose.yml (100%) rename {template/.devcontainer => .devcontainer}/postCreateCommand.sh (100%) rename {template/.devcontainer => .devcontainer}/postStartCommand.sh (100%) create mode 100644 .github/workflows/deploy.yaml mode change 100755 => 100644 .gitignore rename {template/.vscode => .vscode}/extensions.json (100%) rename {template/.vscode => .vscode}/settings.json (100%) create mode 100644 Makefile delete mode 100644 bun.lock create mode 100644 copier.yaml delete mode 100644 copier.yml create mode 100644 includes/slugify.jinja create mode 100644 template/.env.example.jinja create mode 100644 template/.gitignore.jinja create mode 100644 template/.secretlintrc.json.jinja create mode 100644 template/CHANGELOG.md.jinja create mode 100644 template/CONTRIBUTING.md.jinja create mode 100644 template/LICENSE.jinja create mode 100644 template/src/lib/env.ts create mode 100644 template/src/lib/graceful-shutdown.ts create mode 100644 template/{% if setup_husky %}.husky{% endif %}/pre-commit create mode 100644 template/{% if use_devcontainer %}.devcontainer{% endif %}/Dockerfile create mode 100755 template/{% if use_devcontainer %}.devcontainer{% endif %}/devcontainer.json create mode 100644 template/{% if use_devcontainer %}.devcontainer{% endif %}/docker-compose.yml.jinja create mode 100644 template/{% if use_devcontainer %}.devcontainer{% endif %}/postCreateCommand.sh create mode 100644 template/{% if use_devcontainer %}.devcontainer{% endif %}/postStartCommand.sh rename template/{.github => {% if use_github_actions %}.github{% endif %}}/dependabot.yml (67%) create mode 100644 template/{% if use_github_actions %}.github{% endif %}/workflows/ci.yaml.jinja create mode 100644 template/{% if use_vscode %}.vscode{% endif %}/extensions.json create mode 100644 template/{% if use_vscode %}.vscode{% endif %}/settings.json diff --git a/template/.devcontainer/Dockerfile b/.devcontainer/Dockerfile similarity index 100% rename from template/.devcontainer/Dockerfile rename to .devcontainer/Dockerfile diff --git a/template/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json similarity index 100% rename from template/.devcontainer/devcontainer.json rename to .devcontainer/devcontainer.json diff --git a/template/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml similarity index 100% rename from template/.devcontainer/docker-compose.yml rename to .devcontainer/docker-compose.yml diff --git a/template/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh similarity index 100% rename from template/.devcontainer/postCreateCommand.sh rename to .devcontainer/postCreateCommand.sh diff --git a/template/.devcontainer/postStartCommand.sh b/.devcontainer/postStartCommand.sh similarity index 100% rename from template/.devcontainer/postStartCommand.sh rename to .devcontainer/postStartCommand.sh diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 0000000..c44932b --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,140 @@ +name: Build and Deploy Template + +on: + push: + branches: + - template + +# REQUIRED REPOSITORY SETTING: +# Go to: Settings > Actions > General > Workflow permissions +# Enable: "Allow GitHub Actions to create and approve pull requests" +# This allows the GITHUB_TOKEN to have pull_requests: write permission + +jobs: + test-and-deploy: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout template branch + uses: actions/checkout@v4 + with: + ref: template + fetch-depth: 0 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Cache Bun dependencies + uses: actions/cache@v4 + with: + path: ~/.bun/install/cache + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + restore-keys: | + ${{ runner.os }}-bun- + + - name: Check markdown links + uses: lycheeverse/lychee-action@v2 + with: + args: --verbose --no-progress --exclude 'file://' --exclude 'host\.docker\.internal' '**/*.md' '**/*.md.jinja' + fail: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install Copier + run: | + sudo apt-get update && sudo apt-get install -y python3-pip python3-venv + python3 -m venv /tmp/copier-venv + /tmp/copier-venv/bin/pip install copier + + - name: Run template tests + run: | + export PATH="/tmp/copier-venv/bin:$PATH" + make test + + - name: Build template output + run: | + export PATH="/tmp/copier-venv/bin:$PATH" + make build + + - name: Get template commit SHA + id: template_sha + run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: Prepare PR body + id: pr_body + run: | + cat << 'EOF' > /tmp/pr_body.md + ## 🤖 Automated Template Build + + This PR contains the rendered template from the latest changes on the `template` branch. + + **Source commit:** `${{ steps.template_sha.outputs.sha }}` + **Build timestamp:** ${{ github.event.head_commit.timestamp }} + + ### ✅ Validation + - Link checking passed + - Template tests passed + - Lint and format checks validated + EOF + echo "body_file=/tmp/pr_body.md" >> $GITHUB_OUTPUT + + - name: Clone repository for main branch + run: | + cd .. + git clone https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git main-repo + cd main-repo + # Try to checkout main, or create orphan if it doesn't exist + git checkout main 2>/dev/null || git checkout --orphan main + + - name: Apply build output to main branch + run: | + cd ../main-repo + # Remove all files except .git + find . -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} + + # Copy build output + cp -r ../${{ github.event.repository.name }}/build_output/. . + # Remove copier answers file (shouldn't be in generated project) + rm -f .copier-answers.yml + + - name: Check for changes + id: check_changes + run: | + cd ../main-repo + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Ensure main branch exists + if ! git ls-remote --heads origin main | grep -q main; then + git checkout --orphan main + git add -A + git commit -m "Initial commit from template@${{ steps.template_sha.outputs.sha }}" + git push origin main + else + git checkout main 2>/dev/null || git checkout --orphan main + fi + + git add -A + if git diff --staged --quiet; then + echo "has_changes=false" >> $GITHUB_OUTPUT + else + echo "has_changes=true" >> $GITHUB_OUTPUT + fi + + - name: Create Pull Request + if: steps.check_changes.outputs.has_changes == 'true' + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + path: ../main-repo + branch: template-build + base: main + title: "Build from template@${{ steps.template_sha.outputs.sha }}" + body-path: ${{ steps.pr_body.outputs.body_file }} + commit-message: "Build from template@${{ steps.template_sha.outputs.sha }}" + committer: "github-actions[bot] " + author: "github-actions[bot] " diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 index 6a7d6d8..e3b40e5 --- a/.gitignore +++ b/.gitignore @@ -1,130 +1,15 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.pnpm-debug.log* +# Template Branch Files +# These are ignored in the template branch since they're generated -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories +# Dependencies node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ +bun.lock -# TypeScript cache +# Build artifacts +dist/ +build/ *.tsbuildinfo -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional stylelint cache -.stylelintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variable files -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next -out - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# vuepress v2.x temp and cache directory -.temp -.cache - -# Docusaurus cache and generated files -.docusaurus - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v2 -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* \ No newline at end of file +# Copier generated files (when testing locally) +.copier-answers.yml +build_output/ diff --git a/template/.vscode/extensions.json b/.vscode/extensions.json similarity index 100% rename from template/.vscode/extensions.json rename to .vscode/extensions.json diff --git a/template/.vscode/settings.json b/.vscode/settings.json similarity index 100% rename from template/.vscode/settings.json rename to .vscode/settings.json diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9028724 --- /dev/null +++ b/Makefile @@ -0,0 +1,148 @@ +SHELL := /bin/bash +.PHONY: test test-thorough test-minimal test-full test-app-runs docker-test build clean + +# Use copier from venv if available, otherwise system copier +COPIER := $(shell which /tmp/copier-venv/bin/copier 2>/dev/null || which copier 2>/dev/null || echo "uvx copier") + +# Quick test with defaults +test: + @echo "🧪 Running quick template test with defaults..." + @$(MAKE) -s _test_config CONFIG="--defaults" + +# Thorough testing with multiple configurations +test-thorough: + @echo "════════════════════════════════════════════════════════════════" + @echo "🔬 THOROUGH TEMPLATE TESTING" + @echo "════════════════════════════════════════════════════════════════" + @echo "" + @echo "📋 Test 1/4: Default configuration" + @$(MAKE) -s test + @echo "" + @echo "📋 Test 2/4: Minimal configuration (no optional features)" + @$(MAKE) -s test-minimal + @echo "" + @echo "📋 Test 3/4: Full configuration (all features enabled)" + @$(MAKE) -s test-full + @echo "" + @echo "📋 Test 4/4: Application runtime test" + @$(MAKE) -s test-app-runs + @echo "" + @echo "════════════════════════════════════════════════════════════════" + @echo "✅ ALL THOROUGH TESTS PASSED!" + @echo "════════════════════════════════════════════════════════════════" + +# Test with minimal configuration +test-minimal: + @echo "🧪 Testing minimal configuration (no optional features)..." + @$(MAKE) -s _test_config CONFIG="--data use_devcontainer=false --data use_vscode=false --data use_github_actions=false --data typescript_strict=false" + +# Test with all features enabled +test-full: + @echo "🧪 Testing full configuration (all features)..." + @$(MAKE) -s _test_config CONFIG="--data use_devcontainer=true --data use_vscode=true --data use_github_actions=true --data typescript_strict=true" + +# Internal target for running a test with specific config +_test_config: + @set -euo pipefail; \ + tmpdir=$$(mktemp -d); \ + trap 'cd - >/dev/null 2>&1; rm -rf "$$tmpdir"' EXIT; \ + echo " 📂 Generating template into: $$tmpdir"; \ + $(COPIER) copy --vcs-ref=HEAD . "$$tmpdir" $(CONFIG) --force --trust 2>&1 | grep -v "FutureWarning\|DirtyLocalWarning" || true; \ + cd "$$tmpdir"; \ + \ + echo " 🔍 Verifying generated files..."; \ + test -f package.json || (echo " ✗ package.json missing" && exit 1); \ + test -f tsconfig.json || (echo " ✗ tsconfig.json missing" && exit 1); \ + test -f .eslintrc.json || (echo " ✗ .eslintrc.json missing" && exit 1); \ + test -f .prettierrc || (echo " ✗ .prettierrc missing" && exit 1); \ + test -f knip.json || (echo " ✗ knip.json missing" && exit 1); \ + test -f src/index.ts || (echo " ✗ src/index.ts missing" && exit 1); \ + test -f src/lib/env.ts || (echo " ✗ src/lib/env.ts missing" && exit 1); \ + test -f src/lib/graceful-shutdown.ts || (echo " ✗ src/lib/graceful-shutdown.ts missing" && exit 1); \ + test -f README.md || (echo " ✗ README.md missing" && exit 1); \ + test -f CONTRIBUTING.md || (echo " ✗ CONTRIBUTING.md missing" && exit 1); \ + test -f CHANGELOG.md || (echo " ✗ CHANGELOG.md missing" && exit 1); \ + test -f .env.example || (echo " ✗ .env.example missing" && exit 1); \ + echo " ✓ All core files present"; \ + \ + echo " 🔍 Checking for template artifacts..."; \ + ! grep -r "use_testing" . --include="*.ts" --include="*.json" --include="*.md" --include="*.yml" --include="*.yaml" 2>/dev/null || (echo " ✗ Found use_testing references" && exit 1); \ + ! grep -r "vitest" . --include="*.ts" --include="*.json" --include="*.md" 2>/dev/null | grep -v "node_modules" || (echo " ✗ Found vitest references" && exit 1); \ + ! test -f vitest.config.ts || (echo " ✗ vitest.config.ts should not exist" && exit 1); \ + ! test -d src/__tests__ || (echo " ✗ src/__tests__ should not exist" && exit 1); \ + ! grep -r "{{ package_name }}" . --include="*.yml" --include="*.yaml" --include="*.json" 2>/dev/null | grep -v node_modules || (echo " ✗ Found unprocessed template variables" && exit 1); \ + ! grep -r "{{ project_name }}" . --include="*.yml" --include="*.yaml" --include="*.json" 2>/dev/null | grep -v node_modules || (echo " ✗ Found unprocessed template variables" && exit 1); \ + echo " ✓ No template artifacts found"; \ + \ + echo " 🌀 Initializing git..."; \ + git init >/dev/null 2>&1 || true; \ + git add -A >/dev/null 2>&1 || true; \ + \ + echo " 📦 Installing dependencies..."; \ + bun install --no-cache 2>&1 | grep -v "^" || echo " ✓ Dependencies installed"; \ + \ + if [ -f ".husky/pre-commit" ]; then \ + echo " 🔧 Installing git hooks..."; \ + bunx husky install >/dev/null 2>&1 || true; \ + fi; \ + \ + echo " 🎨 Formatting code..."; \ + bun run format >/dev/null 2>&1; \ + \ + echo " 🔍 Running linter..."; \ + bun run lint 2>&1 | grep -E "warning|error|✖" || echo " ✓ No linting issues"; \ + \ + echo " ✅ Checking format..."; \ + bun run format:check >/dev/null 2>&1 && echo " ✓ Code is formatted" || (echo " ✗ Format check failed" && exit 1); \ + \ + echo " 🔨 Building TypeScript..."; \ + bun run build 2>&1 | grep -E "error" && exit 1 || echo " ✓ Build successful"; \ + \ + echo " ✅ Verifying compiled output..."; \ + test -d dist && test -f dist/index.js || (echo " ✗ Build output missing" && exit 1); \ + echo " ✓ dist/index.js exists"; \ + \ + echo " 🔍 Checking for unused code..."; \ + bun run knip 2>&1 | grep -E "error" | grep -v "script.*exited with code" || echo " ✓ Knip check complete"; \ + \ + echo " ✅ Test passed!" + +# Test that the generated app actually runs +test-app-runs: + @echo "🚀 Testing that generated application runs..." + @set -euo pipefail; \ + tmpdir=$$(mktemp -d); \ + trap 'cd - >/dev/null 2>&1; rm -rf "$$tmpdir"' EXIT; \ + echo " 📂 Generating template..."; \ + $(COPIER) copy --vcs-ref=HEAD . "$$tmpdir" --defaults --force --trust 2>&1 | grep -v "FutureWarning\|DirtyLocalWarning" || true; \ + cd "$$tmpdir"; \ + \ + echo " 📦 Installing dependencies..."; \ + bun install --no-cache 2>&1 | tail -1; \ + \ + echo " 🔨 Building application..."; \ + bun run build >/dev/null 2>&1; \ + \ + echo " ▶️ Running application (5 second timeout)..."; \ + timeout 5s bun run dist/index.js 2>&1 | head -5 || true; \ + \ + echo " ✅ Application runs successfully!" + +# Build for inspection +build: + @echo "🔧 Generating template into: build_output/" + @rm -rf build_output + @$(COPIER) copy --vcs-ref=HEAD . build_output --defaults --force --trust --data skip_git_init=true 2>&1 | grep -v "FutureWarning\|DirtyLocalWarning" || true + @echo "📦 Installing dependencies..." + @cd build_output && bun install --no-cache --ignore-scripts >/dev/null + @echo "🎨 Formatting generated files..." + @cd build_output && bun run format >/dev/null + @echo "🚀 Running linter and formatter checks..." + @cd build_output && bun run lint && bun run format:check + @echo "✅ Template generated and validated successfully!" + @echo "📁 Check the output in: build_output/" + +clean: + @echo "🧹 Cleaning build output..." + @rm -rf build_output + @echo "✅ Cleaned!" diff --git a/README.md b/README.md index 3464cdc..dc53b4f 100644 --- a/README.md +++ b/README.md @@ -1,97 +1,183 @@ -# Copier Template for TypeScript/Bun Projects +# TypeScript Template -This repository contains a [Copier](https://copier.readthedocs.io/) template for scaffolding TypeScript projects with Bun, complete linting/formatting setup, and optional devcontainer support. +[![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/copier-org/copier) -## Using This Template +A production-ready [Copier](https://copier.readthedocs.io/) template for modern TypeScript projects with comprehensive tooling, testing, and quality checks. -### Prerequisites +## ✨ Features + +- 🚀 **Modern tooling**: Bun/npm/yarn/pnpm support, TypeScript with strict mode option +- 🧪 **Testing infrastructure**: Vitest with coverage reporting and 80% thresholds +- 🔒 **Quality & Security**: ESLint, Prettier, Knip, secret detection, import sorting +- 🪝 **Git hooks**: Husky with lint-staged and secretlint pre-commit checks +- 🐳 **Optional devcontainer**: Reproducible development environment with Docker +- ⚙️ **VSCode integration**: Pre-configured settings, extensions, and debugging +- 🤖 **GitHub Actions**: Complete CI/CD with testing, linting, dependency updates +- 📝 **Documentation**: Auto-generated CONTRIBUTING.md, CHANGELOG.md, and comprehensive README +- ⚖️ **License support**: MIT, Apache-2.0, GPL-3.0, Proprietary, or None +- 🔐 **Environment setup**: .env.example with common configuration patterns + +## 🚀 Usage + +Generate a new project using Copier: ```bash -# Install Copier (Python CLI tool) -pip install copier -# or -pipx install copier +# Using uvx (recommended if you have uv installed) +uvx copier copy gh:martgra/typescript_template + +# Or with pipx +pipx run copier copy gh:martgra/typescript_template ``` -### Generate a New Project +### Template Questions + +The template will ask you: + +- **Project info**: name, description +- **Author**: name and email +- **Development environment**: VSCode settings, devcontainer (Docker) +- **CI/CD**: GitHub Actions workflows +- **Code quality**: Git hooks (Husky), testing framework (Vitest) +- **TypeScript**: Strict mode option +- **License**: MIT, Apache-2.0, GPL-3.0, Proprietary, or None +- **Package manager**: bun, npm, yarn, or pnpm + +## 🛠️ Development + +This repository contains the Copier template itself. To test the template: ```bash -# Using the template branch -copier copy --vcs-ref=template gh:your-username/your-repo path/to/new-project +# Run full validation (generates project, runs all checks) +make test + +# Generate template to build_output/ for inspection +make build -# Or if you've cloned this repo locally -copier copy path/to/this/repo/template path/to/new-project +# Clean build artifacts +make clean ``` -Copier will ask you several questions to customize your project: +### Testing Workflow -- **Project name**: Name for your project (used in package.json) -- **Description**: Short description of your project -- **Author name**: Your name -- **Author email**: Your email address -- **Use Git**: Initialize git repository in new project -- **Use devcontainer**: Include VSCode devcontainer setup -- **Setup Husky**: Include git hooks for pre-commit linting -- **TypeScript strict mode**: Enable all strict TypeScript checks -- **Package manager**: Choose between bun, npm, yarn, or pnpm +The `make test` command: -### What's Included +1. Generates a project from the template in a temp directory +2. Initializes git and installs dependencies +3. Sets up git hooks +4. Runs all quality checks (lint, format, tests, knip) +5. Cleans up the temp directory -The generated project includes: +## 📁 Template Structure -- **Bun Runtime**: Fast JavaScript/TypeScript runtime and package manager -- **TypeScript**: Full TypeScript support with configurable strict mode -- **ESLint**: Code linting with TypeScript support -- **Prettier**: Code formatting with consistent style -- **Import Sorting**: Automatic import organization via eslint-plugin-simple-import-sort -- **Knip**: Unused code and dependency detection -- **Husky** (optional): Git hooks for pre-commit checks -- **lint-staged** (optional): Run linters only on staged files -- **Devcontainer** (optional): Complete Docker-based development environment +``` +template/ # Template files (what gets copied) +├── .github/ +│ ├── workflows/ +│ │ └── ci.yaml.jinja # CI workflow for PRs and main +│ └── dependabot.yml # Dependency updates (npm + devcontainers) +├── .vscode/ # VSCode settings and extensions +├── .devcontainer/ # Docker devcontainer setup +├── .husky/ # Git hooks +│ └── pre-commit # Lint, format, and secret scanning +├── src/ +│ ├── __tests__/ +│ │ └── example.test.ts.jinja # Example Vitest tests +│ └── index.ts.jinja # Entry point +├── CONTRIBUTING.md.jinja # Contribution guidelines +├── CHANGELOG.md.jinja # Version history template +├── LICENSE.jinja # License file (MIT/Apache/GPL/Proprietary) +├── README.md.jinja # Generated project README with badges +├── package.json.jinja # Dependencies and scripts +├── tsconfig.json.jinja # TypeScript configuration +├── vitest.config.ts.jinja # Test configuration with coverage +├── .env.example.jinja # Environment variables template +├── .secretlintrc.json.jinja # Secret detection rules +├── .eslintrc.json.jinja # ESLint configuration +├── .prettierrc.jinja # Prettier configuration +├── knip.json.jinja # Unused code detection +├── .editorconfig.jinja # Editor settings +└── .gitignore.jinja # Git ignore patterns + +copier.yaml # Template configuration and questions +includes/slugify.jinja # Helper macro for package naming +Makefile # Template testing infrastructure +``` -### Project Scripts +## 🔄 Updates -After generation, the following scripts are available: +To update an existing project with new template changes: ```bash -# Development -bun run dev # Run in development mode with watch -bun run build # Build for production -bun start # Run the built project - -# Code Quality -bun run lint # Check for linting issues -bun run lint:fix # Auto-fix linting issues -bun run format # Format code with Prettier -bun run format:check # Check if code is formatted -bun run knip # Find unused code and dependencies +# From within your generated project +copier update ``` -### Development Environment Options +This will prompt you for any new questions and merge in template updates. -#### Without Devcontainer -Just install Bun locally: -```bash -curl -fsSL https://bun.sh/install | bash -bun install -``` +## 🎯 What's Included in Generated Projects + +### Testing +- ✅ Vitest testing framework +- ✅ Example test suite +- ✅ Coverage reporting with 80% thresholds +- ✅ Watch mode support + +### Code Quality +- ✅ ESLint with TypeScript support +- ✅ Prettier for consistent formatting +- ✅ Import sorting (simple-import-sort) +- ✅ Knip for unused code detection +- ✅ Secretlint for credential scanning + +### Git Hooks (Husky) +- ✅ Pre-commit: lint-staged, secret scanning +- ✅ Auto-fix on commit (review required before re-committing) + +### CI/CD +- ✅ Pull request validation workflow +- ✅ Automated dependency updates (Dependabot) +- ✅ Test execution with coverage upload +- ✅ Build verification + +### Documentation +- ✅ Comprehensive README with badges +- ✅ Contributing guidelines +- ✅ Changelog template +- ✅ Environment variable examples -#### With Devcontainer -Open the project in VSCode and use the "Reopen in Container" command. Everything is pre-configured. +## 📋 Requirements -## Branch Structure +- Python 3.8+ (for Copier) +- Bun 1.3.1+ or Node.js 20+ (for generated projects) +- Git 2.0+ +- Docker (optional, for devcontainer) -- **main**: Working example project (this README documents the template) -- **template**: Copier template with Jinja2-templated files +## 🤝 Contributing -## Template Development +Contributions to improve this template are welcome! Please: + +1. Test your changes with `make test` +2. Ensure the build passes with `make build` +3. Update documentation as needed + +## 📄 License + +This template is available under the MIT License. Generated projects can use any license you choose during setup. + +├── .vscode/ # VSCode settings +├── .devcontainer/ # Dev container config (optional) +├── .husky/ # Git hooks (optional) +├── .github/ # GitHub Actions (optional) +└── includes/ # Jinja macros and utilities + +copier.yaml # Template configuration +Makefile # Template testing +``` -To modify the template: +## Requirements -1. Switch to template branch: `git checkout template` -2. Edit files in `template/` directory -3. Modify `copier.yml` to add/change questions -4. Test locally: `copier copy template /tmp/test-project` +- [Copier](https://copier.readthedocs.io/) 9.0.0+ +- [Bun](https://bun.sh/) or npm/yarn/pnpm ## License diff --git a/bun.lock b/bun.lock deleted file mode 100644 index ba66a03..0000000 --- a/bun.lock +++ /dev/null @@ -1,469 +0,0 @@ -{ - "lockfileVersion": 1, - "workspaces": { - "": { - "name": "multiplayer-game-monorepo", - "devDependencies": { - "@types/node": "^20.5.1", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "@typescript-eslint/parser": "^6.21.0", - "eslint": "^8.50.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-prettier": "^5.0.0", - "eslint-plugin-simple-import-sort": "^12.1.0", - "husky": "^8.0.3", - "knip": "^5.33.3", - "lint-staged": "^15.2.10", - "prettier": "^3.0.0", - "typescript": "^5.2.2", - }, - }, - }, - "packages": { - "@emnapi/core": ["@emnapi/core@1.6.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg=="], - - "@emnapi/runtime": ["@emnapi/runtime@1.6.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA=="], - - "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], - - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="], - - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], - - "@eslint/eslintrc": ["@eslint/eslintrc@2.1.4", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ=="], - - "@eslint/js": ["@eslint/js@8.57.1", "", {}, "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q=="], - - "@humanwhocodes/config-array": ["@humanwhocodes/config-array@0.13.0", "", { "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw=="], - - "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], - - "@humanwhocodes/object-schema": ["@humanwhocodes/object-schema@2.0.3", "", {}, "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA=="], - - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="], - - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], - - "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], - - "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - - "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.12.0", "", { "os": "android", "cpu": "arm" }, "sha512-/IfGWLNdmS1kVYM2g+Xw4qXNWtCPZ/i5YMprflA8FC3vAjT4N0VucQcDxUPHxatQwre4qnhbFFWqRa1mz6Cgkw=="], - - "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.12.0", "", { "os": "android", "cpu": "arm64" }, "sha512-H3Ehyinfx2VO8F5TwdaD/WY686Ia6J1H3LP0tgpNjlPGH2TrTniPERiwjqtOm/xHEef0KJvb/yfmUKLbHudhCA=="], - - "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.12.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hmm+A/0WdEtIeBrPtUHoSTzJefrZkhGSrmv5pwELKiqNqd+/gctzmTlt6wWrU8BMIryDMT9fWqLSQ3+NYfqAEA=="], - - "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.12.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-g1tVu53EMfuRKs67o0PZR0+y/WXl/Tfn3d2ggjK3Hj17pQPcb9x1+Y6W7n4EjIDttwLZbCPCEr06X+aC03I45A=="], - - "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.12.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TiMatzvcVMSOiAx8sbnAw7UCfQpZDlm91ItywZrSHlQIJqDBipOmjIEYUMc2p823Y+fJ2ADL5UBjUB2kfqpedw=="], - - "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.12.0", "", { "os": "linux", "cpu": "arm" }, "sha512-zU+9UgxPIvfReqmRr/dqZt3387HPgcH0hA4u0QGE+280EFjBYYL2rxGDxK0L+keO6vc2+ITWVDXm9KIj+alofg=="], - - "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.12.0", "", { "os": "linux", "cpu": "arm" }, "sha512-dfO1rrOeELYWD/BewMCp81k1I3pOdtAi2VCKg/A1I8z0uI4OR6cThb5dV9fpHkj7zlb0Y5iZFPe+NTbI/u1MgQ=="], - - "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.12.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-JJNyN1ueryETKTUsG57+u0GDbtHKVcwcUoC6YyJmDdWE0o/3twXtHuS+F/121a2sVK8PKlROqGAev+STx3AuuQ=="], - - "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.12.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-rQHoxL0H0WwYUuukPUscLyzWwTl/hyogptYsY+Ye6AggJEOuvgJxMum2glY7etGIGOXxrfjareHnNO1tNY7WYg=="], - - "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.12.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-XPUZSctO+FrC0314Tcth+GrTtzy2yaYqyl8weBMAbKFMwuV8VnR2SHg9dmtI9vkukmM3auOLj0Kqjpl3YXwXiw=="], - - "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.12.0", "", { "os": "linux", "cpu": "none" }, "sha512-AmMjcP+6zHLF1JNq/p3yPEcXmZW/Xw5Xl19Zd0eBCSyGORJRuUOkcnyC8bwMO43b/G7PtausB83fclnFL5KZ3w=="], - - "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.12.0", "", { "os": "linux", "cpu": "none" }, "sha512-K2/yFBqFQOKyVwQxYDAKqDtk2kS4g58aGyj/R1bvYPr2P7v7971aUG/5m2WD5u2zSqWBfu1o4PdhX0lsqvA3vQ=="], - - "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.12.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-uSl4jo78tONGZtwsOA4ldT/OI7/hoHJhSMlGYE4Z/lzwMjkAaBdX4soAK5P/rL+U2yCJlRMnnoUckhXlZvDbSw=="], - - "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.12.0", "", { "os": "linux", "cpu": "x64" }, "sha512-YjL8VAkbPyQ1kUuR6pOBk1O+EkxOoLROTa+ia1/AmFLuXYNltLGI1YxOY14i80cKpOf0Z59IXnlrY3coAI9NDQ=="], - - "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.12.0", "", { "os": "linux", "cpu": "x64" }, "sha512-qpHPU0qqeJXh7cPzA+I+WWA6RxtRArfmSrhTXidbiQ08G5A1e55YQwExWkitB2rSqN6YFxnpfhHKo9hyhpyfSg=="], - - "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.12.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.7" }, "cpu": "none" }, "sha512-oqg80bERZAagWLqYmngnesE0/2miv4lST7+wiiZniD6gyb1SoRckwEkbTsytGutkudFtw7O61Pon6pNlOvyFaA=="], - - "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.12.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-qKH816ycEN9yR/TX91CP1/i6xyVNHKX9VEOYa3XzQROPVtcYG2F6A3ng/PhwpJvS1cmL/DlilhglZe9KWkhNjg=="], - - "@oxc-resolver/binding-win32-ia32-msvc": ["@oxc-resolver/binding-win32-ia32-msvc@11.12.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-3bgxubTlhzF6BwBnhGz5BTboarl1upuanEr6i0dncjfEcU+Z9xAOgbtA7Ip3G3EKDjE1objRKK+ny8PKJZ3b7Q=="], - - "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.12.0", "", { "os": "win32", "cpu": "x64" }, "sha512-rbiWYQWxwy+x7+KgNAoAGYIPB3xUclQlFVV3L5lwfsbp4PQPomJohHowlWgi3GRAEybM5+ZL9xny0YfpJOsthA=="], - - "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], - - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - - "@types/node": ["@types/node@20.19.23", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ=="], - - "@types/semver": ["@types/semver@7.7.1", "", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="], - - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@6.21.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.5.1", "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/type-utils": "6.21.0", "@typescript-eslint/utils": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", "natural-compare": "^1.4.0", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", "eslint": "^7.0.0 || ^8.0.0" } }, "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA=="], - - "@typescript-eslint/parser": ["@typescript-eslint/parser@6.21.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", "@typescript-eslint/typescript-estree": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0" } }, "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ=="], - - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@6.21.0", "", { "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0" } }, "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg=="], - - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@6.21.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "6.21.0", "@typescript-eslint/utils": "6.21.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0" } }, "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag=="], - - "@typescript-eslint/types": ["@typescript-eslint/types@6.21.0", "", {}, "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg=="], - - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@6.21.0", "", { "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" } }, "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ=="], - - "@typescript-eslint/utils": ["@typescript-eslint/utils@6.21.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0" } }, "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ=="], - - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@6.21.0", "", { "dependencies": { "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" } }, "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A=="], - - "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], - - "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - - "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], - - "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - - "ansi-escapes": ["ansi-escapes@7.1.1", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q=="], - - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - - "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - - "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], - - "cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="], - - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - - "commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], - - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], - - "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], - - "doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="], - - "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], - - "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], - - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - - "eslint": ["eslint@8.57.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", "@eslint/js": "8.57.1", "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.2", "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" } }, "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA=="], - - "eslint-config-prettier": ["eslint-config-prettier@9.1.2", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ=="], - - "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.4", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.11.7" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg=="], - - "eslint-plugin-simple-import-sort": ["eslint-plugin-simple-import-sort@12.1.1", "", { "peerDependencies": { "eslint": ">=5.0.0" } }, "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA=="], - - "eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="], - - "eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], - - "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], - - "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], - - "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - - "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], - - "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], - - "execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], - - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - - "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - - "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], - - "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="], - - "file-entry-cache": ["file-entry-cache@6.0.1", "", { "dependencies": { "flat-cache": "^3.0.4" } }, "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg=="], - - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - - "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], - - "flat-cache": ["flat-cache@3.2.0", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw=="], - - "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], - - "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="], - - "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], - - "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="], - - "get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="], - - "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - - "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - - "globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="], - - "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - - "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], - - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="], - - "husky": ["husky@8.0.3", "", { "bin": { "husky": "lib/bin.js" } }, "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg=="], - - "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - - "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - - "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], - - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - - "is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="], - - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - - "is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="], - - "is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - - "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], - - "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], - - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - - "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], - - "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - - "knip": ["knip@5.66.3", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "jiti": "^2.6.0", "js-yaml": "^4.1.0", "minimist": "^1.2.8", "oxc-resolver": "^11.8.3", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.4.1", "strip-json-comments": "5.0.2", "zod": "^4.1.11" }, "peerDependencies": { "@types/node": ">=18", "typescript": ">=5.0.4 <7" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-BEe9ZCI8fm4TJzehnrCt+L/Faqu6qfMH6VrwSfck+lCGotQzf0jh5dVXysPWjWqMpdUSr6+MpMu9JW/G6wiAcQ=="], - - "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - - "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], - - "lint-staged": ["lint-staged@15.5.2", "", { "dependencies": { "chalk": "^5.4.1", "commander": "^13.1.0", "debug": "^4.4.0", "execa": "^8.0.1", "lilconfig": "^3.1.3", "listr2": "^8.2.5", "micromatch": "^4.0.8", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.7.0" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w=="], - - "listr2": ["listr2@8.3.3", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ=="], - - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], - - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - - "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], - - "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], - - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - - "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - - "mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="], - - "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], - - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - - "npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="], - - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], - - "onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="], - - "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], - - "oxc-resolver": ["oxc-resolver@11.12.0", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.12.0", "@oxc-resolver/binding-android-arm64": "11.12.0", "@oxc-resolver/binding-darwin-arm64": "11.12.0", "@oxc-resolver/binding-darwin-x64": "11.12.0", "@oxc-resolver/binding-freebsd-x64": "11.12.0", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.12.0", "@oxc-resolver/binding-linux-arm-musleabihf": "11.12.0", "@oxc-resolver/binding-linux-arm64-gnu": "11.12.0", "@oxc-resolver/binding-linux-arm64-musl": "11.12.0", "@oxc-resolver/binding-linux-ppc64-gnu": "11.12.0", "@oxc-resolver/binding-linux-riscv64-gnu": "11.12.0", "@oxc-resolver/binding-linux-riscv64-musl": "11.12.0", "@oxc-resolver/binding-linux-s390x-gnu": "11.12.0", "@oxc-resolver/binding-linux-x64-gnu": "11.12.0", "@oxc-resolver/binding-linux-x64-musl": "11.12.0", "@oxc-resolver/binding-wasm32-wasi": "11.12.0", "@oxc-resolver/binding-win32-arm64-msvc": "11.12.0", "@oxc-resolver/binding-win32-ia32-msvc": "11.12.0", "@oxc-resolver/binding-win32-x64-msvc": "11.12.0" } }, "sha512-zmS2q2txiB+hS2u0aiIwmvITIJN8c8ThlWoWB762Wx5nUw8WBlttp0rzt8nnuP1cGIq9YJ7sGxfsgokm+SQk5Q=="], - - "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - - "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - - "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], - - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - - "pidtree": ["pidtree@0.6.0", "", { "bin": { "pidtree": "bin/pidtree.js" } }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="], - - "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - - "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], - - "prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="], - - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - - "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - - "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], - - "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - - "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - - "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], - - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - - "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], - - "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - - "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - - "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - - "slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="], - - "smol-toml": ["smol-toml@1.4.2", "", {}, "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g=="], - - "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], - - "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], - - "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="], - - "strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="], - - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], - - "text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="], - - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - - "ts-api-utils": ["ts-api-utils@1.4.3", "", { "peerDependencies": { "typescript": ">=4.2.0" } }, "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw=="], - - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - - "type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], - - "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - - "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - - "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="], - - "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - - "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - - "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], - - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - - "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="], - - "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - - "zod": ["zod@4.1.12", "", {}, "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ=="], - - "@eslint/eslintrc/strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.3", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg=="], - - "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "lint-staged/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - - "log-update/slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="], - - "log-update/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - - "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], - - "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], - - "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "string-width/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "wrap-ansi/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - - "log-update/slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "log-update/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], - - "log-update/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - } -} diff --git a/copier.yaml b/copier.yaml new file mode 100644 index 0000000..5095db3 --- /dev/null +++ b/copier.yaml @@ -0,0 +1,124 @@ +# Minimum Copier version required +_min_copier_version: "9.0.0" + +# Template files are in the template/ subdirectory +_subdirectory: template +_templates_suffix: .jinja + +_skip_if_exists: + - ".env" + - "node_modules/" + +# Exclude helper files from being copied +_exclude: + - includes + - "*.pyc" + - "__pycache__" + - ".git" + +# Welcome message before copying +_message_before_copy: | + 🚀 Welcome to the TypeScript Template! + + Let's set up your new TypeScript project. + +# Success message after copying +_message_after_copy: | + ✅ Project "{{ project_name }}" created successfully! + + Next steps: + cd {{ _copier_conf.dst_path }} + bun install + bun run prepare + bun run dev + + Happy coding! 🎉 + +# Template Questions +# ================== + +# Project Information +# ------------------- +project_name: + type: str + help: What is your project name? + default: "typescript-template" + placeholder: "my-awesome-project" + validator: >- + {% if not (project_name | regex_search('^[a-z][a-z0-9-]*$')) %} + project_name must start with a letter and only contain lowercase letters, numbers, and hyphens + {% endif %} + +project_description: + type: str + help: Brief project description + default: "A TypeScript project" + placeholder: "My awesome TypeScript application" + +# Author Information +# ------------------ +author_name: + type: str + help: Author name + default: "Your Name" + +author_email: + type: str + help: Author email + default: "you@example.com" + validator: >- + {% if author_email and not (author_email | regex_search('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')) %} + Please provide a valid email address + {% endif %} + +# Auto-generated from project_name - never asked to user +package_name: + type: str + when: false # This makes it hidden - user is never prompted + default: "{% from 'includes/slugify.jinja' import slugify %}{{ slugify(project_name) }}" + +# Development Environment +# ----------------------- +use_devcontainer: + type: bool + help: Include VSCode devcontainer configuration? (Docker required) + default: yes + +use_vscode: + type: bool + help: Include VSCode configuration? + default: yes + +use_github_actions: + type: bool + help: Include GitHub Actions CI/CD? + default: yes + +# TypeScript Configuration +# ------------------------ +typescript_strict: + type: bool + help: Use strict TypeScript configuration? + default: yes + +skip_git_init: + type: bool + when: false # Hidden parameter for testing + default: no + +_jinja_extensions: + - jinja2.ext.do + +_skip_if_exists: + - ".env" + - "node_modules/" + - "CHANGELOG.md" + - "LICENSE" + +_tasks: + - command: "git init" + description: "🌀 Initializing git repository" + when: "{{ not skip_git_init and use_github_actions }}" + - command: "bunx husky install" + description: "🔧 Installing git hooks" + when: "{{ not skip_git_init }}" diff --git a/copier.yml b/copier.yml deleted file mode 100644 index c18afd1..0000000 --- a/copier.yml +++ /dev/null @@ -1,80 +0,0 @@ -# Copier Template Configuration -# Learn more: https://copier.readthedocs.io/ - -_templates_suffix: .jinja -_subdirectory: template -_exclude: - - copier.yml - - .copier-answers.yml - - .git - - .gitignore.jinja - - "*.pyc" - - __pycache__ - -# Template Questions -project_name: - type: str - help: What is your project name? - default: my-project - validator: >- - {% if not (project_name | regex_search('^[a-z][a-z0-9-]*$')) %} - project_name must start with a letter and only contain lowercase letters, numbers, and hyphens - {% endif %} - -project_description: - type: str - help: Brief project description - default: A TypeScript project - -author_name: - type: str - help: Author name - default: Your Name - -author_email: - type: str - help: Author email - default: you@example.com - -use_git: - type: bool - help: Initialize git repository? - default: true - -use_devcontainer: - type: bool - help: Include dev container configuration? - default: true - -setup_husky: - type: bool - help: Set up git hooks with Husky? - default: true - when: "{{ use_git }}" - -typescript_strict: - type: bool - help: Use strict TypeScript configuration? - default: true - -include_examples: - type: bool - help: Include example code? - default: false - -package_manager: - type: str - help: Which package manager? - choices: - - bun - - npm - - yarn - - pnpm - default: bun - -_jinja_extensions: - - jinja2.ext.do - -_skip_if_exists: - - .git - - node_modules diff --git a/includes/slugify.jinja b/includes/slugify.jinja new file mode 100644 index 0000000..25b8c51 --- /dev/null +++ b/includes/slugify.jinja @@ -0,0 +1,9 @@ +{% macro slugify(value) -%} +{{ value + |lower + |replace(' ', '_') + |replace('-', '_') + |replace('.', '') + |replace(',', '') +}} +{%- endmacro %} diff --git a/template/.copier-answers.yml.jinja b/template/.copier-answers.yml.jinja index db57e3f..6bc0840 100644 --- a/template/.copier-answers.yml.jinja +++ b/template/.copier-answers.yml.jinja @@ -10,6 +10,4 @@ author_name: "{{ author_name }}" author_email: "{{ author_email }}" use_git: {{ use_git }} use_devcontainer: {{ use_devcontainer }} -setup_husky: {{ setup_husky }} typescript_strict: {{ typescript_strict }} -package_manager: "{{ package_manager }}" diff --git a/template/.env.example.jinja b/template/.env.example.jinja new file mode 100644 index 0000000..dd8ae94 --- /dev/null +++ b/template/.env.example.jinja @@ -0,0 +1,48 @@ +# Environment Variables + +# Node Environment +NODE_ENV=development + +# Application Configuration +APP_NAME={{ project_name }} +APP_PORT=3000 +APP_HOST=localhost + +# Logging +LOG_LEVEL=info + +# Database (uncomment and configure as needed) +# DATABASE_URL=postgresql://user:password@localhost:5432/database +# DB_HOST=localhost +# DB_PORT=5432 +# DB_NAME=database +# DB_USER=user +# DB_PASSWORD=password + +# Redis (uncomment and configure as needed) +# REDIS_URL=redis://localhost:6379 +# REDIS_HOST=localhost +# REDIS_PORT=6379 + +# API Keys (uncomment and configure as needed) +# API_KEY=your-api-key-here +# API_SECRET=your-api-secret-here + +# JWT Authentication (uncomment and configure as needed) +# JWT_SECRET=your-jwt-secret-here +# JWT_EXPIRES_IN=7d + +# CORS Configuration +# CORS_ORIGIN=http://localhost:3000 + +# External Services (uncomment and configure as needed) +# STRIPE_SECRET_KEY=sk_test_... +# STRIPE_PUBLISHABLE_KEY=pk_test_... +# SENDGRID_API_KEY=SG... +# AWS_ACCESS_KEY_ID=... +# AWS_SECRET_ACCESS_KEY=... +# AWS_REGION=us-east-1 + +# Feature Flags +# ENABLE_DEBUG=false +# ENABLE_ANALYTICS=true diff --git a/template/.eslintrc.json.jinja b/template/.eslintrc.json.jinja index 9451e52..2cfc689 100644 --- a/template/.eslintrc.json.jinja +++ b/template/.eslintrc.json.jinja @@ -8,7 +8,8 @@ "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", - "sourceType": "module" + "sourceType": "module", + "project": "./tsconfig.json" }, "plugins": ["@typescript-eslint", "simple-import-sort"], "rules": { diff --git a/template/.gitignore.jinja b/template/.gitignore.jinja new file mode 100644 index 0000000..1c447ae --- /dev/null +++ b/template/.gitignore.jinja @@ -0,0 +1,120 @@ +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# Build output +dist/ +build/ + +# OS +.DS_Store +Thumbs.db diff --git a/template/.husky/pre-commit b/template/.husky/pre-commit index 757bafa..f2df149 100755 --- a/template/.husky/pre-commit +++ b/template/.husky/pre-commit @@ -1,6 +1,11 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" +# Run secret detection +echo "🔍 Scanning for secrets..." +bunx secretlint "**/*" + +# Run lint-staged bunx lint-staged --allow-empty # Prevent commit if lint-staged made changes diff --git a/template/.secretlintrc.json.jinja b/template/.secretlintrc.json.jinja new file mode 100644 index 0000000..a40fab4 --- /dev/null +++ b/template/.secretlintrc.json.jinja @@ -0,0 +1,13 @@ +{ + "root": true, + "rules": { + "@secretlint/secretlint-rule-preset-recommend": { + "allows": [ + { + "rule": "@secretlint/secretlint-rule-aws", + "allows": ["EXAMPLE"] + } + ] + } + } +} diff --git a/template/CHANGELOG.md.jinja b/template/CHANGELOG.md.jinja new file mode 100644 index 0000000..8e0ad66 --- /dev/null +++ b/template/CHANGELOG.md.jinja @@ -0,0 +1,35 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- Initial project setup + +### Changed + +### Deprecated + +### Removed + +### Fixed + +### Security + +## [1.0.0] - {{ now().strftime('%Y-%m-%d') }} + +### Added +- Project scaffolding with TypeScript{{ ' strict mode' if typescript_strict else '' }} +- ESLint and Prettier configuration +- Bun as package manager and runtime +- Husky pre-commit hooks with lint-staged +- Secret detection with secretlint{% if use_github_actions %} +- GitHub Actions CI/CD workflows{% endif %}{% if use_devcontainer %} +- VSCode devcontainer configuration{% endif %} + +[unreleased]: https://github.com/{{ author_name }}/{{ project_name }}/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/{{ author_name }}/{{ project_name }}/releases/tag/v1.0.0 diff --git a/template/CONTRIBUTING.md.jinja b/template/CONTRIBUTING.md.jinja new file mode 100644 index 0000000..19f6301 --- /dev/null +++ b/template/CONTRIBUTING.md.jinja @@ -0,0 +1,186 @@ +# Contributing to {{ project_name }} + +Thank you for considering contributing to {{ project_name }}! This document provides guidelines and instructions for contributing. + +## Development Setup + +### Prerequisites + +- [Bun](https://bun.sh/) 1.3.1 or higher +- Git{% if use_devcontainer %} +- Docker (for devcontainer){% endif %} + +### Getting Started + +1. **Fork and clone the repository** + + ```bash + git fork {{ project_name }} + cd {{ project_name }} + ``` + +2. **Install dependencies** + + ```bash + bun install + ``` +{% if use_devcontainer %} +3. **Optional: Use devcontainer** + + Open the project in VS Code and click "Reopen in Container" when prompted. +{% endif %} +3. **Create a new branch** + + ```bash + git checkout -b feature/your-feature-name + ``` + +## Development Workflow + +### Running the Project + +```bash +# Development mode with watch +bun run dev + +# Production build +bun run build +bun start +``` + +### Code Quality + +```bash +# Run linter +bun run lint + +# Auto-fix linting issues +bun run lint:fix + +# Check code formatting +bun run format:check + +# Auto-format code +bun run format + +# Find unused code +bun run knip +``` + +## Code Style Guidelines + +### TypeScript + +- Use TypeScript{% if typescript_strict %} with strict mode enabled{% endif %} +- Prefer `const` over `let`, avoid `var` +- Use meaningful variable and function names +- Add JSDoc comments for public APIs +- Avoid `any` type - use `unknown` if type is truly unknown + +### File Organization + +``` +src/ +├── index.ts # Entry point +├── lib/ # Reusable utilities +└── types/ # TypeScript type definitions +``` + +### Imports + +- Imports are automatically sorted by `eslint-plugin-simple-import-sort` +- Order: Node built-ins → External packages → Internal modules + +### Git Hooks + +Pre-commit hooks automatically run: +- ESLint (auto-fix) +- Prettier (auto-format) +- Secret detection + +**Important:** If the hook makes changes, they are **not** automatically staged. Review the changes, stage them, and commit again. + +## Pull Request Process + +1. **Update documentation** - Update README.md if you change functionality +2. **Run all checks** - Ensure linting, formatting, and build pass +3. **Write clear commit messages** - Follow [Conventional Commits](https://www.conventionalcommits.org/) + ``` + feat: add new feature + fix: resolve bug in X + docs: update README + refactor: restructure Z + ``` + +4. **Create Pull Request** + - Use a clear, descriptive title + - Reference any related issues + - Describe what changed and why + - Include screenshots for UI changes + +5. **Address review feedback** - Respond to comments and make requested changes + +## Commit Message Format + +We follow the [Conventional Commits](https://www.conventionalcommits.org/) specification: + +``` +(): + + + +