-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add /install/prettier endpoint with package manager support #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Copilot
wants to merge
4
commits into
main
Choose a base branch
from
copilot/add-prettier-install-endpoint
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
94b647e
Initial plan
Copilot 434ee6c
feat: add /install/prettier endpoint with package manager support
Copilot 52db49f
refactor: improve script readability and remove hardcoded pnpm version
Copilot 00a6618
refactor: use Next.js page.tsx instead of inline HTML and improve basβ¦
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,393 @@ | ||
| #!/usr/bin/env bash | ||
| # DevMagic - Prettier Installation Script | ||
| # Installs and configures Prettier, Husky, and lint-staged | ||
| # Usage: | ||
| # Latest version: curl -fsSL https://devmagic.run/install/prettier | bash | ||
| # With npm: curl -fsSL https://devmagic.run/install/prettier?pm=npm | bash | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| # --- Configuration --- | ||
| PACKAGE_MANAGER="${PACKAGE_MANAGER:-pnpm}" | ||
|
|
||
| # --- Colors for output --- | ||
| readonly RED='\033[0;31m' | ||
| readonly GREEN='\033[0;32m' | ||
| readonly YELLOW='\033[1;33m' | ||
| readonly BLUE='\033[0;34m' | ||
| readonly PURPLE='\033[0;35m' | ||
| readonly NC='\033[0m' | ||
|
|
||
| # --- Helper Functions --- | ||
|
|
||
| show_header() { | ||
| echo -e "${PURPLE}" | ||
| echo "β¨ Prettier Installation" | ||
| echo "βββββββββββββββββββββββββ" | ||
| echo "Setting up automatic code formatting" | ||
| echo -e "Package Manager: ${PACKAGE_MANAGER}${NC}" | ||
| echo | ||
| } | ||
|
|
||
| check_prerequisites() { | ||
| echo -e "${BLUE}Checking prerequisites...${NC}" | ||
|
|
||
| # Check if package.json exists | ||
| if [[ ! -f "package.json" ]]; then | ||
| echo -e "${RED}β package.json not found. This script must be run in a Node.js project.${NC}" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Check if Git repository exists | ||
| if ! git rev-parse --is-inside-work-tree &>/dev/null; then | ||
| echo -e "${RED}β Not a Git repository. Husky requires Git to function.${NC}" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Verify package manager is installed | ||
| if ! command -v "$PACKAGE_MANAGER" &>/dev/null; then | ||
| echo -e "${RED}β ${PACKAGE_MANAGER} is not installed. Please install it first.${NC}" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Validate package manager | ||
| case "$PACKAGE_MANAGER" in | ||
| pnpm|npm|yarn|bun) | ||
| ;; | ||
| *) | ||
| echo -e "${RED}β Unsupported package manager: ${PACKAGE_MANAGER}${NC}" | ||
| echo -e "${YELLOW} Supported: pnpm, npm, yarn, bun${NC}" | ||
| exit 1 | ||
| ;; | ||
| esac | ||
|
|
||
| echo -e "${GREEN}β Prerequisites check passed${NC}" | ||
| echo | ||
| } | ||
|
|
||
| is_workspace() { | ||
| if [[ "$PACKAGE_MANAGER" == "pnpm" ]]; then | ||
| [[ -f "pnpm-workspace.yaml" ]] | ||
| elif [[ "$PACKAGE_MANAGER" == "npm" || "$PACKAGE_MANAGER" == "yarn" ]]; then | ||
| grep -q '"workspaces"' package.json 2>/dev/null | ||
| else | ||
| return 1 | ||
| fi | ||
| } | ||
|
|
||
| get_install_cmd() { | ||
| local packages="$1" | ||
| local dev_flag="$2" | ||
|
|
||
| case "$PACKAGE_MANAGER" in | ||
| pnpm) | ||
| if is_workspace; then | ||
| echo "pnpm add -w ${dev_flag} ${packages}" | ||
| else | ||
| echo "pnpm add ${dev_flag} ${packages}" | ||
| fi | ||
| ;; | ||
| npm) | ||
| echo "npm install ${dev_flag} ${packages}" | ||
| ;; | ||
| yarn) | ||
| echo "yarn add ${dev_flag} ${packages}" | ||
| ;; | ||
| bun) | ||
| echo "bun add ${dev_flag} ${packages}" | ||
| ;; | ||
| esac | ||
| } | ||
|
|
||
| get_dev_flag() { | ||
| case "$PACKAGE_MANAGER" in | ||
| pnpm|npm) | ||
| echo "--save-dev" | ||
| ;; | ||
| yarn|bun) | ||
| echo "-D" | ||
| ;; | ||
| esac | ||
| } | ||
|
|
||
| get_exact_flag() { | ||
| case "$PACKAGE_MANAGER" in | ||
| pnpm|npm) | ||
| echo "--save-exact" | ||
| ;; | ||
| yarn) | ||
| echo "--exact" | ||
| ;; | ||
| bun) | ||
| echo "" | ||
| ;; | ||
| esac | ||
| } | ||
|
|
||
| get_exec_cmd() { | ||
| local cmd="$1" | ||
|
|
||
| case "$PACKAGE_MANAGER" in | ||
| pnpm|npm|yarn) | ||
| echo "${PACKAGE_MANAGER} exec ${cmd}" | ||
| ;; | ||
| bun) | ||
| echo "bunx ${cmd}" | ||
| ;; | ||
| esac | ||
| } | ||
|
|
||
| install_prettier() { | ||
| echo -e "${BLUE}π¦ Step 1/7: Installing Prettier...${NC}" | ||
|
|
||
| local dev_flag | ||
| dev_flag=$(get_dev_flag) | ||
| local exact_flag | ||
| exact_flag=$(get_exact_flag) | ||
| local install_cmd | ||
| install_cmd=$(get_install_cmd "prettier" "${dev_flag} ${exact_flag}") | ||
|
|
||
| echo -e "${YELLOW}Running: ${install_cmd}${NC}" | ||
| eval "$install_cmd" | ||
|
|
||
| echo -e "${GREEN}β Prettier installed${NC}" | ||
| echo | ||
| } | ||
|
|
||
| create_prettierrc() { | ||
| echo -e "${BLUE}π Step 2/7: Creating .prettierrc...${NC}" | ||
|
|
||
| if [[ -f ".prettierrc" ]]; then | ||
| echo -e "${YELLOW}β οΈ .prettierrc already exists, skipping...${NC}" | ||
| else | ||
| cat > .prettierrc << 'EOF' | ||
| {} | ||
| EOF | ||
| echo -e "${GREEN}β .prettierrc created${NC}" | ||
| fi | ||
| echo | ||
| } | ||
|
|
||
| create_prettierignore() { | ||
| echo -e "${BLUE}π Step 3/7: Creating .prettierignore...${NC}" | ||
|
|
||
| if [[ -f ".prettierignore" ]]; then | ||
| echo -e "${YELLOW}β οΈ .prettierignore already exists, skipping...${NC}" | ||
| else | ||
| cat > .prettierignore << 'EOF' | ||
| # Ignore artifacts: | ||
| build | ||
| coverage | ||
| dist | ||
| .next | ||
| out | ||
| node_modules | ||
| pnpm-lock.yaml | ||
| yarn.lock | ||
| package-lock.json | ||
| bun.lockb | ||
| EOF | ||
| echo -e "${GREEN}β .prettierignore created${NC}" | ||
| fi | ||
| echo | ||
| } | ||
|
|
||
| create_editorconfig() { | ||
| echo -e "${BLUE}π Step 4/7: Creating .editorconfig...${NC}" | ||
|
|
||
| if [[ -f ".editorconfig" ]]; then | ||
| echo -e "${YELLOW}β οΈ .editorconfig already exists, skipping...${NC}" | ||
| else | ||
| cat > .editorconfig << 'EOF' | ||
| root = true | ||
|
|
||
| [*] | ||
| indent_style = space | ||
| indent_size = 2 | ||
| insert_final_newline = true | ||
| trim_trailing_whitespace = true | ||
| end_of_line = lf | ||
| charset = utf-8 | ||
| spelling_languages = en-US,en,pt-BR,pt | ||
| max_line_length = 120 | ||
|
|
||
| [*.{lua,toml,yaml,yml,json,jsonc,json5}] | ||
| max_line_length = 80 | ||
|
|
||
| [*.{fs,fsi,fsx}] | ||
| indent_size = 4 | ||
| # Simplifies reordering and adding new items. Details: | ||
| # https://learn.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting#multiline-bracket-formatting-style | ||
| fsharp_multiline_bracket_style = stroustrup | ||
|
|
||
| [*.{py,sh,zsh,bash,gitconfig,tmux.conf}] | ||
| indent_size = 4 | ||
| max_line_length = 80 | ||
|
|
||
| [*.{md,markdown,mdx}] | ||
| indent_size = 4 | ||
| max_line_length = unset # Not wrapping lines reduces diffs. | ||
| trim_trailing_whitespace = false # Double trailing spaces can be used to break lines. | ||
| EOF | ||
| echo -e "${GREEN}β .editorconfig created${NC}" | ||
| fi | ||
| echo | ||
| } | ||
|
|
||
| install_husky_lintstaged() { | ||
| echo -e "${BLUE}π¦ Step 5/7: Installing Husky and lint-staged...${NC}" | ||
|
|
||
| local dev_flag | ||
| dev_flag=$(get_dev_flag) | ||
| local install_cmd | ||
| install_cmd=$(get_install_cmd "husky lint-staged" "${dev_flag}") | ||
|
|
||
| echo -e "${YELLOW}Running: ${install_cmd}${NC}" | ||
| eval "$install_cmd" | ||
|
|
||
| echo -e "${GREEN}β Husky and lint-staged installed${NC}" | ||
| echo | ||
| } | ||
|
|
||
| configure_husky() { | ||
| echo -e "${BLUE}πͺ Step 6/7: Configuring Husky...${NC}" | ||
|
|
||
| local husky_init | ||
| husky_init=$(get_exec_cmd "husky init") | ||
| echo -e "${YELLOW}Running: ${husky_init}${NC}" | ||
| eval "$husky_init" | ||
|
|
||
| # Create pre-commit hook | ||
| local pre_commit_cmd | ||
| pre_commit_cmd=$(get_exec_cmd "lint-staged") | ||
| cat > .husky/pre-commit << EOF | ||
| ${pre_commit_cmd} | ||
| EOF | ||
|
|
||
| chmod +x .husky/pre-commit | ||
|
|
||
| echo -e "${GREEN}β Husky configured${NC}" | ||
| echo | ||
| } | ||
|
|
||
| configure_lintstaged() { | ||
| echo -e "${BLUE}βοΈ Step 7/7: Configuring lint-staged...${NC}" | ||
|
|
||
| # Check if lint-staged config already exists (look for the config object, not just dependency name) | ||
| if grep -q '"lint-staged"[[:space:]]*:[[:space:]]*{' package.json; then | ||
| echo -e "${YELLOW}β οΈ lint-staged configuration already exists in package.json, skipping...${NC}" | ||
| else | ||
| # Use node to add lint-staged config to package.json | ||
| node --eval " | ||
| const fs = require('fs'); | ||
| const pkgPath = 'package.json'; | ||
| const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); | ||
| pkg['lint-staged'] = { | ||
| '**/*': 'prettier --write --ignore-unknown' | ||
| }; | ||
| fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n'); | ||
| " | ||
| echo -e "${GREEN}β lint-staged configured in package.json${NC}" | ||
| fi | ||
| echo | ||
| } | ||
|
|
||
| create_github_workflow() { | ||
| echo -e "${BLUE}π Creating GitHub Actions workflow...${NC}" | ||
|
|
||
| local workflow_dir=".github/workflows" | ||
| local workflow_file="${workflow_dir}/format-check.yml" | ||
|
|
||
| if [[ -f "$workflow_file" ]]; then | ||
| echo -e "${YELLOW}β οΈ GitHub Actions workflow already exists, skipping...${NC}" | ||
| else | ||
| mkdir -p "$workflow_dir" | ||
|
|
||
| # Determine the install command for CI | ||
| local setup_step install_cmd_ci check_cmd | ||
| case "$PACKAGE_MANAGER" in | ||
| pnpm) | ||
| setup_step=' - uses: pnpm/action-setup@v4' | ||
| install_cmd_ci='pnpm install --frozen-lockfile' | ||
| check_cmd='pnpm exec prettier --check .' | ||
| ;; | ||
| npm) | ||
| setup_step='' | ||
| install_cmd_ci='npm ci' | ||
| check_cmd='npm exec prettier -- --check .' | ||
| ;; | ||
| yarn) | ||
| setup_step='' | ||
| install_cmd_ci='yarn install --frozen-lockfile' | ||
| check_cmd='yarn exec prettier --check .' | ||
| ;; | ||
| bun) | ||
| setup_step=' - uses: oven-sh/setup-bun@v2' | ||
| install_cmd_ci='bun install --frozen-lockfile' | ||
| check_cmd='bunx prettier --check .' | ||
| ;; | ||
| esac | ||
|
|
||
| cat > "$workflow_file" << EOF | ||
| name: Format Check | ||
| on: [push, pull_request] | ||
|
|
||
| jobs: | ||
| check-format: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| ${setup_step} | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "20" | ||
| cache: "${PACKAGE_MANAGER}" | ||
| - run: ${install_cmd_ci} | ||
| - run: ${check_cmd} | ||
| EOF | ||
| echo -e "${GREEN}β GitHub Actions workflow created at ${workflow_file}${NC}" | ||
| fi | ||
| echo | ||
| } | ||
|
|
||
| show_completion() { | ||
| echo -e "${GREEN}" | ||
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββ" | ||
| echo "β¨ Prettier setup complete!" | ||
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββ" | ||
| echo -e "${NC}" | ||
| echo "What was configured:" | ||
| echo " β Prettier installed with exact version pinning" | ||
| echo " β .prettierrc configuration file" | ||
| echo " β .prettierignore for excluding files" | ||
| echo " β .editorconfig for editor consistency" | ||
| echo " β Husky for Git hooks" | ||
| echo " β lint-staged for pre-commit formatting" | ||
| echo " β GitHub Actions workflow for CI checks" | ||
| echo | ||
| echo "Next steps:" | ||
| echo " 1. Customize .prettierrc with your preferences (optional)" | ||
| echo " 2. Run '$(get_exec_cmd "prettier --write .")' to format all files" | ||
| echo " 3. Commit your changes - formatting will run automatically!" | ||
| echo | ||
| echo -e "${YELLOW}Note: Your commits will now be automatically formatted.${NC}" | ||
| echo | ||
| } | ||
|
|
||
| # --- Main Pipeline --- | ||
| main() { | ||
| show_header | ||
| check_prerequisites | ||
| install_prettier | ||
| create_prettierrc | ||
| create_prettierignore | ||
| create_editorconfig | ||
| install_husky_lintstaged | ||
| configure_husky | ||
| configure_lintstaged | ||
| create_github_workflow | ||
| show_completion | ||
| } | ||
|
|
||
| # Run main function | ||
| main "$@" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot please, use the "main" idiom, creating a "pipeline" in it and having functions for the most relevant parts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in commit 00a6618. Restructured the script with a
main()function that creates a clear pipeline:main() { show_header check_prerequisites install_prettier create_prettierrc create_prettierignore create_editorconfig install_husky_lintstaged configure_husky configure_lintstaged create_github_workflow show_completion }All logic is now in named functions for better readability and maintainability.