Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add navigation to src folder

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be
npm install ../avicenne-studio-typescript-config-1.0.3.tgz --foreground-scripts --no-progress ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The installation fails

Image


# 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** <git@garnier.dev> (https://garnier.dev) - Original author
- **Faris Chtatou** <faris.manage@gmail.com> - Contributor & Maintainer
7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
"eslint"
],
"author": "Aurélien <git@garnier.dev> (https://garnier.dev)",
"contributors": [
"Faris Chtatou <faris.manage@gmail.com>"
],
"maintainers": [
"Aurélien <git@garnier.dev> (https://garnier.dev)",
"Faris Chtatou <faris.manage@gmail.com>"
],
"license": "ISC",
"scripts": {
"postinstall": "node dist/index.mjs",
Expand Down
1 change: 0 additions & 1 deletion src/.husky/pre-commit.json

This file was deleted.

4 changes: 3 additions & 1 deletion src/eslint.mts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 1 addition & 1 deletion src/husky.mts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
2 changes: 1 addition & 1 deletion src/index.mts
Original file line number Diff line number Diff line change
Expand Up @@ -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 !== "")
Expand Down
2 changes: 1 addition & 1 deletion src/prettier.mts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
6 changes: 5 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"compilerOptions": {
"module": "NodeNext",
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES2022",
"outDir": "dist",
"strict": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
},
}