diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..93c1e31 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# learn more: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +* @lewxdev diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5bf4285 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,25 @@ +name: 🚀 Create new release on GitHub +on: + push: + +permissions: + contents: write + +jobs: + publish: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v1 + + - run: | + bun install + bun run build + echo "dotfiles=dist/dotfiles" >> $GITHUB_ENV + + - env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create v$($dotfiles --version) $dotfiles --generate-notes \ + --prerelease=${{ github.ref != 'refs/heads/main' }} \ + --target=${{ github.ref }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..845ab9f --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# based on the githhub/node.gitignore template +# see: https://github.com/github/gitignore/blob/main/Node.gitignore + +# builds +dist +out +*.tgz + +# dependencies +node_modules + +# environment +.env +.env.*.local +.env.local + +# logs +logs +*.log +*-debug.log* +*-error.log* + +# miscellaneous +.cache +.temp +.DS_Store + +# runtime +pids +*.pid +*.seed +*.pid.lock + +# eslint cache +.eslintcache + +# npm cache +.npm + +# repl history +.node_repl_history + +# typescript cache +*.tsbuildinfo + +# addons +# see: https://nodejs.org/api/addons.html +build/Release + +# reports +# see: https://nodejs.org/api/report.html +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000..1a71a3c --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,3 @@ +#!/usr/bin/env zsh + +bun run commitlint --edit $1 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..d1164c3 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "biomejs.biome", + "bmalehorn.shell-syntax", + "github.vscode-github-actions", + "joshbolduc.commitlint", + "streetsidesoftware.code-spell-checker", + "yoavbls.pretty-ts-errors" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e34623a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "editor.defaultFormatter": "biomejs.biome", + "editor.codeActionsOnSave": { + "quickfix.biome": "explicit", + "source.organizeImports.biome": "explicit" + } +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..cd37869 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,20 @@ +# The MIT License (MIT) + +Copyright © 2021-Present, [lewxdev](https://github.com/lewxdev) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ddff7e1 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +``` + __ __ ____ __ + ___/ /__ / /_/ _(_) /__ ___ +/ _ / _ \/ __/ _/ / / -_|_-< +\_,_/\___/\__/_//_/_/\__/___/ +``` + +# @lewxdev/dotfiles + +This repository consists of infrequently updated personal configurations, +dotfiles, and scripts for a macOS-based environment. It provides the following: + +- a CLI as a [single-file executable](https://bun.sh/docs/bundler/executables) + that walks through a configurable installation process +- a one-time installation script that adds the `dotfiles` CLI to the PATH + +Although I cannot guarantee it will work for you, feel free to build on and +learn from this setup. If you have any questions or suggestions, please open an +issue. + +## Usage + +When installing for the first time, run the following command: + +```shell +curl -fsSL https://raw.githubusercontent.com/lewxdev/dotfiles/main/install.zsh | zsh +``` + +After installation, you can run the `dotfiles` CLI to manage your dotfiles: + +```shell +dotfiles --help +``` + +## Development + +```shell +# install dependencies +bun install +``` + +```shell +# invoke the CLI +bun start +``` + +```shell +# build the executable +bun run build +``` + +```shell +# update CLI installation +# note: this may prompt you for your password +bun run update +``` diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..4cf6225 --- /dev/null +++ b/biome.json @@ -0,0 +1,23 @@ +{ + "$schema": "node_modules/@biomejs/biome/configuration_schema.json", + "organizeImports": { + "enabled": true + }, + "files": { + "ignoreUnknown": true + }, + "formatter": { + "indentStyle": "tab" + }, + "linter": { + "rules": { + "recommended": true + } + }, + "vcs": { + "enabled": true, + "clientKind": "git", + "defaultBranch": "main", + "useIgnoreFile": true + } +} diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..e56384e Binary files /dev/null and b/bun.lockb differ diff --git a/cli.ts b/cli.ts new file mode 100644 index 0000000..4278396 --- /dev/null +++ b/cli.ts @@ -0,0 +1,27 @@ +import { $ } from "bun"; +import { program } from "commander"; + +import packageJson from "@/package.json"; + +const LOCAL_PATH = "~/projects/dotfiles"; +const REMOTE_PATH = packageJson.repository.url; + +program + .name("dotfiles") + .description(`a CLI to manage ${packageJson.description}`) + .version(packageJson.version); + +program + .command("install") + .description("run the configurable installation script") + .action(async () => { + try { + // check if local repository exists + await $`test -d ${LOCAL_PATH}`; + } catch { + // create if local repository is missing + await $`git clone ${REMOTE_PATH} ${LOCAL_PATH}`; + } + }); + +await program.parseAsync(); diff --git a/install.zsh b/install.zsh new file mode 100644 index 0000000..b8ccb57 --- /dev/null +++ b/install.zsh @@ -0,0 +1,30 @@ +#!/usr/bin/env zsh + +# get the latest release from GitHub +# TODO: update version to latest release before merging +echo "downloading the dotfiles CLI..." +curl -fsSL -o /usr/local/bin/dotfiles https://github.com/lewxdev/dotfiles/releases/download/v2.0.0/dotfiles + +# make the file executable +echo "completing installation..." +chmod +x /usr/local/bin/dotfiles + +if ! command -v dotfiles &> /dev/null; then + echo "error: dotfiles is not installed, try again or install manually" + exit 1 +fi + +# post installation message +echo " + __ __ ____ __ + ___/ /__ / /_/ _(_) /__ ___ +/ _ / _ \/ __/ _/ / / -_|_-< +\_,_/\___/\__/_//_/_/\__/___/ v$(dotfiles --version) + +successfully installed the dotfiles CLI 🎉 + +next steps: + 1. run 'dotfiles install' + 2. edit '~/projects/dotfiles' + +see 'dotfiles --help' for more" diff --git a/package.json b/package.json new file mode 100644 index 0000000..5f7c4f6 --- /dev/null +++ b/package.json @@ -0,0 +1,42 @@ +{ + "name": "@lewxdev/dotfiles", + "version": "2.0.0", + "description": "personal configurations, dotfiles, and scripts for a macOS-based environment", + "license": "MIT", + "author": "J. Lewis (https://lewx.dev)", + "module": "cli.ts", + "type": "module", + "repository": { + "type": "git", + "url": "https://github.com/lewxdev/dotfiles.git" + }, + "scripts": { + "start": "bun run cli.ts", + "build": "bun build cli.ts --compile --minify --outfile dist/dotfiles", + "update": "bun run build && sudo mv dist/dotfiles /usr/local/bin", + "prepare": "husky", + "format": "biome format --write .", + "lint": "biome lint ." + }, + "dependencies": { + "commander": "^12.1.0" + }, + "devDependencies": { + "@biomejs/biome": "1.7.3", + "@commitlint/cli": "^19.3.0", + "@commitlint/config-conventional": "^19.2.2", + "@tsconfig/bun": "latest", + "@tsconfig/strictest": "^2.0.5", + "@types/bun": "latest", + "husky": "^9.0.11", + "lint-staged": "^15.2.5", + "typescript": "^5.4.5" + }, + "commitlint": { + "extends": ["@commitlint/config-conventional"] + }, + "lint-staged": { + "*": "biome format --write", + "*.ts": "biome lint --apply" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..0832493 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": ["@tsconfig/bun", "@tsconfig/strictest"], + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./*"] + } + } +}