@funish/basis
Version:
A unified development toolkit with CLI for package management, versioning, publishing, linting, and git hooks management for JavaScript/TypeScript projects.
541 lines (416 loc) • 16.3 kB
Markdown
# @funish/basis

[](https://www.npmjs.com/package/@funish/basis)
[](https://www.npmjs.com/package/@funish/basis)
> A unified development toolkit with CLI for package management, versioning, publishing, linting, and git hooks management for JavaScript/TypeScript projects.
**🧑💻 Contributing?** See the [monorepo documentation](https://github.com/funish/basis) for development setup and contribution guidelines.
## What is Basis?
Basis is your **unified development toolkit** for modern JavaScript/TypeScript projects. Instead of juggling multiple CLI tools, Basis provides a single interface for all your development workflow needs.
## Features
- 🎯 **Unified CLI**: One command interface for all development tasks
- 📦 **Package Management**: Install, add, remove dependencies with auto-detected package manager (npm, yarn, pnpm, bun, deno)
- 🏷️ **Version Management**: Semantic versioning with automated git tagging and releases
- 🚀 **Publishing**: Multi-tag publishing strategy with edge version tracking
- 🔧 **Tool Agnostic Linting**: Not tied to specific linters - use ESLint, Oxlint, Biome, or any tool you prefer
- 🛠️ **Auto-fix Issues**: Automatically fix dependencies, structure, and documentation issues
- 🪝 **Smart Git Hooks**: Automatic git repository initialization and hook management
- 💻 **Modern Stack**: Built on the unjs ecosystem (citty, consola, c12, nypm, semver)
- 💪 **TypeScript First**: Full TypeScript support with excellent DX
- 📚 **Smart Defaults**: Best practices built-in, fully customizable
- 🔧 **Single Configuration**: One config file for all functionality
## Quick Start
### Recommended Installation (Global with pnpm)
```bash
# Install globally with pnpm (recommended)
pnpm add -g @funish/basis
# Or install globally with npm
npm install -g @funish/basis
# Verify installation
basis --version
```
### Alternative Installation Methods
```bash
# Install in your project with pnpm
pnpm add -D @funish/basis
# Or with npm
npm install -D @funish/basis
# Or use directly without installation
npx @funish/basis init
```
### Initialize in Existing Project
```bash
cd your-existing-project
basis init
# Interactive setup will ask you to:
# 📁 Choose config format (.ts/.mjs/.cjs) - auto-detected based on your project
# 🔧 Optionally setup Git hooks and configuration
# Your project now has:
# ✅ Configuration file with Git hooks that adapt to your package manager
# ✅ Git hooks setup (if selected during init)
# ✅ Tool-agnostic linting workflow
# ✅ Package management through unified CLI
# ✅ Version management with semantic versioning
# ✅ Publishing workflow with multi-tag strategy
```
## CLI Commands
### Package Management
```bash
# Install dependencies (auto-detects package manager)
basis install # or basis i
basis install --frozen-lockfile
# Add dependencies
basis add lodash # Add to dependencies
basis add -D typescript # Add to devDependencies
basis add --workspace app react # Add to specific workspace
basis add -g @funish/basis # Install globally
# Remove dependencies
basis remove lodash # or basis rm / basis uninstall
basis remove -D typescript
# Run scripts
basis run build # Run package.json scripts
basis run test --silent
```
### Version Management
```bash
# Semantic version increments
basis version patch # 1.0.0 → 1.0.1
basis version minor # 1.0.0 → 1.1.0
basis version major # 1.0.0 → 2.0.0
# Prerelease versions
basis version --prerelease # 1.0.0 → 1.0.1-edge.0
basis version --prerelease --preid beta # 1.0.0 → 1.0.1-beta.0
# Specific version
basis version 2.0.0
# Custom commit message
basis version patch --message "fix: critical bug"
```
### Publishing
```bash
# Standard publishing (to edge tag)
basis publish
# Stable release (to latest + edge tags)
basis publish --stable
# Custom tag publishing (to custom + edge tags)
basis publish --tag beta
basis publish --tag alpha
# Dry run
basis publish --dry-run
# Skip build/tests
basis publish --skip-build --skip-tests
```
### Linting
```bash
# Lint staged files
basis lint --staged
# Run project-wide linting
basis lint --project
# Check dependencies
basis lint --deps
# Check project structure
basis lint --structure
# Check documentation
basis lint --docs
# Run all lint checks
basis lint --all
# Auto-fix issues (can be combined with any check)
basis lint --deps --fix # Check and fix dependency issues
basis lint --structure --fix # Check and fix structure issues
basis lint --docs --fix # Check and fix documentation issues
basis lint --all --fix # Check and fix all issues
basis lint --staged --fix # Note: --fix only works with --deps, --structure, --docs, --all
```
#### Auto-fix Features
The `--fix` flag enables automatic fixing of common issues:
**🔧 Dependency Fixes**:
- **Remove blocked packages**: Automatically uninstall packages listed in `blockedPackages`
- **Update outdated dependencies**: Use package manager's update command to fix outdated packages
- **Fix security vulnerabilities**: Attempt to fix security issues using `npm audit fix` or equivalent
**📁 Structure Fixes**:
- **Create missing files**: Generate empty files for items in `requiredFiles`
- **Create missing directories**: Generate directories for items in `requiredDirs`
**📝 Documentation Fixes**:
- **Generate README.md**: Create an empty README.md if missing
- **Generate CHANGELOG.md**: Create an empty CHANGELOG.md if missing
**Configuration**: All fix behaviors are controlled by the `lint.fix` configuration in your `basis.config.ts`:
```ts
export default defineBasisConfig({
lint: {
fix: {
dependencies: {
removeBlocked: true, // Enable automatic removal of blocked packages
updateOutdated: false, // Disable automatic updates (manual control)
fixSecurity: true, // Enable security fix attempts
},
structure: {
createMissingFiles: true, // Enable file creation
createMissingDirs: true, // Enable directory creation
},
docs: {
generateReadme: true, // Enable README generation
generateChangelog: false, // Disable CHANGELOG generation
},
},
},
});
```
### Git Hooks Management
```bash
# Setup git configuration and hooks
basis git setup
# Setup git configuration only
basis git config
# Setup git hooks only
basis git hooks
# Remove git hooks
basis git remove # Remove all basis-managed hooks
basis git remove pre-commit # Remove specific hook
basis git remove --update-config # Remove hooks AND config from basis.config.ts
# Reset git configuration
basis git reset # Reset config (keep user info)
basis git reset --no-keep-user # Reset config (remove user info)
basis git reset --update-config # Reset config AND remove from basis.config.ts
# Initialize git repository with basis configuration
basis git init
# Validate commit message
basis git --lint-commit
```
### Project Management
```bash
# Initialize configuration
basis init # Initialize basis configuration (interactive)
basis init --force # Overwrite existing configuration
basis init --skip-git-check # Skip git directory check
basis init --skip-install # Skip dependency installation
# Interactive setup will:
# 1. Auto-detect recommended config format (.ts/.mjs/.cjs)
# 2. Ask you to choose your preferred format
# 3. Offer to setup Git hooks and configuration
# Configuration
basis config # Show current configuration
basis config --json # Output configuration as JSON
basis config --path # Show configuration file path
# Help
basis --help # Show help
basis <command> --help # Show command-specific help
```
## Configuration
Basis uses a single configuration file for all its features. The `basis init` command creates a configuration file with customized Git hooks in your preferred format:
```ts
// basis.config.ts (TypeScript) or basis.config.mjs (ES Module)
import { defineBasisConfig } from "@funish/basis";
export default defineBasisConfig({
// Configure your project here
// See: https://github.com/funish/basis/tree/main/packages/basis#configuration
git: {
hooks: {
"pre-commit": "pnpm exec basis lint --staged", // Auto-adapts to your package manager
"commit-msg": "pnpm exec basis git --lint-commit",
},
},
});
```
```cjs
// basis.config.cjs (CommonJS)
const { defineBasisConfig } = require("@funish/basis");
module.exports = defineBasisConfig({
// Configure your project here
// See: https://github.com/funish/basis/tree/main/packages/basis#configuration
git: {
hooks: {
"pre-commit": "npx basis lint --staged", // Auto-adapts to your package manager
"commit-msg": "npx basis git --lint-commit",
},
},
});
```
> **💡 Configuration**: The generated config file only shows the Git hooks that are customized for your package manager. All other configuration options use smart defaults and can be added as needed.
### Full Configuration Example
Here's a complete configuration with all available options:
```ts
// basis.config.ts
import { defineBasisConfig } from "@funish/basis";
export default defineBasisConfig({
// Linting configuration
lint: {
// Staged files linting patterns
staged: {
"*.{ts,tsx,js,jsx}": "pnpm eslint --fix",
"*.{json,md,yml,yaml}": "pnpm prettier --write",
"*.vue": "pnpm vue-tsc --noEmit && pnpm eslint --fix",
},
// Project-wide linting commands
project: {
typecheck: "pnpm tsc --noEmit",
"format-check": "pnpm prettier --check .",
},
// Auto-fix configuration
fix: {
// Dependency fix options
dependencies: {
removeBlocked: true, // Auto-remove blocked packages
updateOutdated: true, // Auto-update outdated dependencies
fixSecurity: true, // Auto-fix security vulnerabilities
},
// Structure fix options
structure: {
createMissingFiles: true, // Auto-create missing required files
createMissingDirs: true, // Auto-create missing required directories
},
// Documentation fix options
docs: {
generateReadme: true, // Auto-create README.md if missing
generateChangelog: true, // Auto-create CHANGELOG.md if missing
},
},
},
// Git configuration
git: {
// Hook commands
hooks: {
"pre-commit": "pnpm exec basis lint --staged",
"commit-msg": "pnpm exec basis git --lint-commit",
},
// Commit message validation
commitMsg: {
types: [
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"build",
"ci",
"chore",
],
maxLength: 72,
minLength: 10,
scopeRequired: false,
allowedScopes: ["api", "ui", "core"],
},
// Options
autoInitGit: true, // Auto-initialize git repo if not found
skipGitCheck: false, // Skip git command availability check
force: false, // Force operation even if git unavailable
},
// Version management configuration
version: {
tagPrefix: "v", // Git tag prefix
autoCommit: true, // Auto commit version changes
autoTag: true, // Auto create git tag
autoPush: false, // Manual push control
prereleaseId: "edge", // Default prerelease identifier
commitMessage: "chore: release v{version}",
},
// Publishing configuration
publish: {
defaultTag: "edge", // Always published tag
stableTag: "latest", // Stable release tag
access: "public", // Package access level
registry: "https://registry.npmjs.org/",
buildCommand: "pnpm build", // Build before publish
testCommand: "pnpm test", // Test before publish
checkGitClean: true, // Check git status before publish
checkTests: true, // Run tests before publish
autoGitPush: true, // Push after publish
createGitTag: true, // Create git tag after publish
},
});
```
## Publishing Strategy
Basis implements an intelligent multi-tag publishing strategy:
### Tag Types
- **`edge`**: Always points to the latest published version (any type)
- **`latest`**: Points to stable releases
- **Prerelease Tags**: `alpha`, `beta`, `rc` versions get their own tags
- **Custom Tags**: Flexible tagging for different release channels
### Examples
```bash
# Version 1.0.0 (stable)
basis publish --stable
# → Published to: latest + edge
# Version 1.1.0-beta.1 (prerelease)
basis publish
# → Published to: beta + edge
# Version 1.2.0 (custom workflow)
basis publish --tag canary
# → Published to: canary + edge
```
### Installation Examples
```bash
# Install stable version
pnpm add @funish/basis # Gets latest tag
# Install edge version (latest published)
pnpm add @funish/basis@edge
# Install prerelease
pnpm add @funish/basis@beta
# Install specific version
pnpm add @funish/basis@1.0.0
```
## Core Concepts
### 🎯 **Unified CLI**
Single command interface for package management, versioning, publishing, linting, and git hooks. No more switching between different tools.
### 📦 **Auto-Detected Package Manager**
Basis automatically detects your preferred package manager (npm, yarn, pnpm, bun, deno) and uses the appropriate commands, powered by [nypm](https://github.com/unjs/nypm).
### 🏷️ **Semantic Versioning**
Built-in semantic versioning support using the standard [semver](https://www.npmjs.com/package/semver) package, with automated git tagging and commit generation.
### 🔧 **Tool Agnostic**
Basis doesn't force specific tools. Use ESLint, Oxlint, Biome, or any other linter. Basis orchestrates your existing tools, doesn't replace them.
### 📦 **Modern Foundations**
Built on the [unjs ecosystem](https://unjs.io/), leveraging proven tools like `citty`, `consola`, `c12`, `nypm`, and `semver` for maximum reliability and performance.
## Integration
Basis integrates seamlessly with:
- **Package Managers**: npm, yarn, pnpm, bun, deno (auto-detected)
- **Linters**: ESLint, Oxlint, Biome, Prettier, StyleLint
- **Git**: Works with any git workflow and hosting provider
- **CI/CD**: GitHub Actions, GitLab CI, Jenkins
- **Frameworks**: React, Vue, Angular, Next.js, Nuxt, SvelteKit
## Why Choose Basis?
### Instead of juggling multiple tools:
```bash
npm install package # Package management
yarn version patch # Version management
npm publish --tag beta # Publishing
npx lint-staged # Linting
git config --global ... # Git configuration
```
### Use one unified command:
```bash
basis add package # Unified package management
basis version patch # Unified version management
basis publish --tag beta # Unified publishing
basis lint --staged # Unified linting
basis git setup # Unified git setup
```
## API
```ts
import {
createBasis,
defineBasisConfig,
// Import module functions directly for maximum flexibility
init,
setupGit,
lintAll,
updatePackageVersion,
publishPackage,
} from "@funish/basis";
// Programmatic usage with Basis class (for config caching and workflows)
const basis = createBasis(process.cwd());
// High-level workflows
await basis.setup({ force: false, skipGitCheck: false, skipInstall: false }); // init + git setup
await basis.release({ patch: true }, { stable: true }); // lint + version + publish
// Configuration management
const config = await basis.getConfig(); // Cached config loading
await basis.reloadConfig(); // Force reload
basis.setCwd("/different/path"); // Change working directory
// Or use module functions directly for more control
const cwd = process.cwd();
await init(cwd, { force: true });
await setupGit(cwd);
await lintAll(cwd);
await updatePackageVersion(cwd, { patch: true });
await publishPackage(cwd, { stable: true });
```
## License
[MIT](../../LICENSE) © [Funish](https://funish.net/)