From 279f53eafa6da09f5b114dff032cc3697c63535f Mon Sep 17 00:00:00 2001 From: Faris CHTATOU Date: Mon, 6 Oct 2025 15:03:24 +0100 Subject: [PATCH] Fixes and upgrades --- README.md | 197 +++++++++++++++++++++++++++++++++++++ package.json | 7 ++ src/.husky/pre-commit.json | 1 - src/eslint.mts | 4 +- src/husky.mts | 2 +- src/index.mts | 2 +- src/prettier.mts | 2 +- tsconfig.json | 6 +- 8 files changed, 215 insertions(+), 6 deletions(-) create mode 100644 README.md delete mode 100644 src/.husky/pre-commit.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..6fa9b73 --- /dev/null +++ b/README.md @@ -0,0 +1,197 @@ +# @avicenne-studio/typescript-config + +Avicenne Studio's shareable TypeScript configuration bundle that automatically sets up and configures development tools for TypeScript projects in a standardized way. + +## Overview + +This package acts as an **automated project setup tool** that configures three main development tools when installed: + +- **ESLint** - Code linting and quality enforcement +- **Prettier** - Code formatting and style consistency +- **Husky** - Git hooks for automated quality checks + +## What it does + +### 1. ESLint Configuration + +- Installs `@avicenne-studio/eslint-config` as a dev dependency +- Creates/updates `.eslintrc.json` with the Avicenne Studio ESLint configuration +- Adds npm scripts: `lint` and `lint:fix` +- Cleans up any conflicting ESLint config files +- Removes ESLint config from `package.json` if present + +### 2. Prettier Configuration + +- Installs `@avicenne-studio/prettier-config` as a dev dependency +- Creates/updates `.prettierrc.json` with the Avicenne Studio Prettier configuration +- Adds npm scripts: `format` and `format:check` +- Cleans up any conflicting Prettier config files +- Removes Prettier config from `package.json` if present + +### 3. Husky Git Hooks + +- Installs `husky` as a dev dependency +- Sets up Git hooks (specifically a pre-commit hook that runs `npm run lint`) +- Adds the `prepare` script to `package.json` +- Creates the `.husky` directory structure + +## Installation + +Install as a dev dependency in your TypeScript project: + +```bash +npm install --save-dev @avicenne-studio/typescript-config +``` + +## How it works + +1. **Post-install execution**: When you install this package, it automatically runs via the `postinstall` script +2. **Interactive setup**: It prompts you with questions about which tools you want to install (ESLint, Prettier, Husky) +3. **Smart configuration**: It intelligently merges with existing configurations rather than overwriting them +4. **Conflict resolution**: It detects and offers to clean up conflicting configuration files +5. **Dependency management**: Automatically installs the required peer dependencies + +## Key Features + +- **Non-destructive**: Uses `deepmerge` to intelligently merge configurations +- **Interactive**: Uses `inquirer` to ask for user preferences +- **Conflict-aware**: Detects and handles existing configurations gracefully +- **Standardized**: Ensures all Avicenne Studio projects use the same tooling setup +- **Extensible**: Has TODO comments for future features like lint-staged, GitHub Actions, PR templates, and commitlint + +## Requirements + +This package requires that you run NPM scripts with the following flags: + +```bash +--foreground-scripts --no-progress +``` + +## Peer Dependencies + +This package requires the following peer dependencies: + +- `@avicenne-studio/eslint-config` (>= 1) +- `@avicenne-studio/prettier-config` (>= 1) + +## Development + +### Building + +```bash +npm run build +``` + +### Linting + +```bash +npm run lint +npm run lint:fix +``` + +### Formatting + +```bash +npm run format +npm run format:check +``` + +## Testing Locally + +Here are different methods to test this package locally before publishing: + +### Method 1: Using npm pack (Recommended) + +This is the most realistic way to test since it simulates the actual package installation: + +```bash +# 1. Build and package your package +npm run build +npm pack + +# 2. Create a test project +mkdir ../test-project +cd ../test-project +npm init -y + +# 3. Install your local package +npm install ../typescript-config/avicenne-studio-typescript-config-1.0.3.tgz --foreground-scripts --no-progress + +# 4. Answer the interactive prompts (Y/n for ESLint, Prettier, Husky) +``` + +### Method 2: Using npm link + +This creates a symlink to your local package: + +```bash +# 1. Link your package globally +npm link + +# 2. Create a test project +mkdir ../test-project +cd ../test-project +npm init -y + +# 3. Link to your package +npm link @avicenne-studio/typescript-config + +# 4. Run the setup manually +node node_modules/@avicenne-studio/typescript-config/dist/index.mjs +``` + +### Method 3: Direct Testing + +Test the package logic directly without npm: + +```bash +# 1. Create a test project +mkdir ../test-project +cd ../test-project +npm init -y + +# 2. Run the package directly +node ../typescript-config/dist/index.mjs +``` + +### Method 4: Testing Specific Components + +You can test individual modules: + +```bash +# Test ESLint setup +node ../typescript-config/dist/eslint.mjs + +# Test Prettier setup +node ../typescript-config/dist/prettier.mjs + +# Test Husky setup +node ../typescript-config/dist/husky.mjs +``` + +### What to Test + +When testing, make sure to verify: + +1. **Interactive prompts work correctly** - The package should ask about ESLint, Prettier, and Husky +2. **Configuration files are created** - Check for `.eslintrc.json`, `.prettierrc.json`, `.husky/` directory +3. **Package.json scripts are added** - Verify `lint`, `lint:fix`, `format`, `format:check`, `prepare` scripts +4. **Dependencies are installed** - Check that peer dependencies are installed +5. **Conflict resolution** - Test with existing config files to ensure proper merging +6. **Error handling** - Test with missing dependencies or invalid configurations + +### Testing Notes + +- **Always use the flags**: `--foreground-scripts --no-progress` when installing +- **The package requires an interactive terminal** - It won't work in CI/CD without modifications +- **Clean test projects** - Remove `node_modules` and `package-lock.json` between tests +- **Version bumping** - Increment the version in `package.json` for each test to avoid caching issues + +## License + +ISC + +## Authors + +- **Aurélien** (https://garnier.dev) - Original author +- **Faris Chtatou** - Contributor & Maintainer diff --git a/package.json b/package.json index fd5e75e..6936958 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,13 @@ "eslint" ], "author": "Aurélien (https://garnier.dev)", + "contributors": [ + "Faris Chtatou " + ], + "maintainers": [ + "Aurélien (https://garnier.dev)", + "Faris Chtatou " + ], "license": "ISC", "scripts": { "postinstall": "node dist/index.mjs", diff --git a/src/.husky/pre-commit.json b/src/.husky/pre-commit.json deleted file mode 100644 index 0c8b247..0000000 --- a/src/.husky/pre-commit.json +++ /dev/null @@ -1 +0,0 @@ -["#!/usr/bin/env sh", "npm run lint"] diff --git a/src/eslint.mts b/src/eslint.mts index 3595793..89415eb 100644 --- a/src/eslint.mts +++ b/src/eslint.mts @@ -5,7 +5,9 @@ import inquirer from "inquirer"; import { exec, readJSON, writeJSON } from "./utils.mjs"; -import JSON_CONFIG from "./.eslintrc.json" assert { type: "json" }; +const JSON_CONFIG = { + extends: "@avicenne-studio", +}; const DEV_DEPENDENCIES = ["@avicenne-studio/eslint-config"]; const CONFIG_FILE = ".eslintrc.json"; diff --git a/src/husky.mts b/src/husky.mts index 48ad2b0..9826347 100644 --- a/src/husky.mts +++ b/src/husky.mts @@ -12,7 +12,7 @@ import { writeJSON, } from "./utils.mjs"; -import PRE_COMMIT_HOOK from "./.husky/pre-commit.json" assert { type: "json" }; +const PRE_COMMIT_HOOK = ["#!/usr/bin/env sh", "npm run lint"]; const DEV_DEPENDENCIES = ["husky"]; const SCRIPTS = { diff --git a/src/index.mts b/src/index.mts index 8fe5843..9ecba87 100644 --- a/src/index.mts +++ b/src/index.mts @@ -51,7 +51,7 @@ if (huskyTasks.length !== 0) { if (prompts.length === 0) process.exit(); if ( - !process.stdin.isTTY || + process.stdin.isTTY === false || ((process.env.npm_command === "install" || process.env.npm_command === "link") && process.env.npm_config_progress !== "") diff --git a/src/prettier.mts b/src/prettier.mts index 2552a55..645aa72 100644 --- a/src/prettier.mts +++ b/src/prettier.mts @@ -4,7 +4,7 @@ import inquirer from "inquirer"; import { exec, readJSON, writeJSON } from "./utils.mjs"; -import JSON_CONFIG from "./.prettierrc.json" assert { type: "json" }; +const JSON_CONFIG = "@avicenne-studio/prettier-config"; const DEV_DEPENDENCIES = ["@avicenne-studio/prettier-config"]; const CONFIG_FILE = ".prettierrc.json"; diff --git a/tsconfig.json b/tsconfig.json index 05658cb..562943e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,12 @@ { "compilerOptions": { - "module": "NodeNext", + "module": "ESNext", + "moduleResolution": "Node", + "target": "ES2022", "outDir": "dist", "strict": true, "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, }, }