diff --git a/CHANGELOG.md b/CHANGELOG.md index d8265f80..f17f3ddb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **docs**: All install instructions now target `@deepl/cli` (10 occurrences across `docs/SYNC.md`, four example scripts, `examples/README.md`, and the git-hook template in `src/services/git-hooks.ts`). The README installation section documents three install paths — Homebrew (`brew install deepl/tap/deepl`, which manages Node itself), npm (`npm install -g @deepl/cli`), and from source — with an explicit Node.js 24 prerequisite, replacing the `better-sqlite3` native-compilation caveat (Xcode CLT / python3-make-gcc), which no longer applies. The `TROUBLESHOOTING.md` `NODE_MODULE_VERSION` / `npm rebuild better-sqlite3` entry is replaced by accurate guidance for the one remaining cache-degradation cause (running on Node < 24). Six stale `DeepLcom` GitHub URLs now point at the `DeepL` org directly. `CONTRIBUTING.md` states the Node 24 development prerequisite, and `SECURITY.md`'s supported-versions table reflects that only 2.x is a published, supported line. - **tests**: Jest's haste map no longer indexes `.claude/` (via `modulePathIgnorePatterns`). A leftover agent worktree under `.claude/worktrees/` duplicated the manual mocks in `tests/__mocks__/` and made every jest run emit a `jest-haste-map: duplicate manual mock found` warning; test files in worktrees were already excluded, but module indexing was not. Verified warning-free with a worktree present. - **BREAKING — package**: The package is now published as the scoped **`@deepl/cli`** (previously the unpublished working name `deepl-cli`). Scoped packages default to restricted visibility, so `publishConfig.access: "public"` is set explicitly — without it the publish fails. The `bin` name is unchanged: the command is still `deepl`, and scoping changes only the install string (`npm install -g @deepl/cli`). Repository, bugs, and homepage metadata now point at `github.com/DeepL/deepl-cli` directly instead of relying on the redirect from the legacy `DeepLcom` org name. - **BREAKING — cache/runtime**: The translation cache now uses Node's built-in `node:sqlite` module instead of the `better-sqlite3` native addon, and the CLI consequently requires **Node.js >= 24** (`engines.node` is now `>=24.0.0`). Node 24 is the first release where `node:sqlite` is non-experimental; Node 18/20 lack the module entirely and Node 22 would both warn on every invocation and downgrade the bundled SQLite (3.50.4 vs 3.53.1). Existing cache databases are read in place with no migration — the on-disk format is unchanged (SQLite 3.53.2-written files verified readable, WAL mode and `user_version` stamp included). **Migration**: upgrade to Node 24 (current LTS), e.g. `nvm install 24`; no other action is needed, and the cache keeps its contents. @@ -23,6 +24,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **deps**: `commander` 14.0.3 → 15.0.0. commander 15 is ESM-only (`"type": "module"`) and requires Node >=22.12.0, so it was unmergeable until the Node 24 baseline landed. Jest's `transformIgnorePatterns` allowlist gains `commander` so ts-jest transforms it under CommonJS test execution; without that, 28 suites fail to load with `SyntaxError: Cannot use import statement outside a module`. - **ci**: Test matrix, release workflow, and security workflow now target Node 24 (previously Node 20 and 22). Node 20 reached end-of-life in April 2026, and Node 24 is the current LTS. This aligns CI with the runtime the project is moving to; the `engines.node` range is unchanged in this entry and is bumped separately. +### Fixed + +- **hooks**: Generated git hooks no longer emit a broken install instruction. The `pre-push` hook template told users to globally install the unpublished `deepl-cli` name — which fails with `ENOVERSIONS` — and now points at `@deepl/cli`. Reported by **@maa-xx** in #70, who correctly diagnosed that the documentation instructed readers to install a package that does not resolve; their docs fix was superseded by actually publishing the package, but this source-level occurrence was the one their PR missed and is now guarded by a regression test asserting generated hook output never references an unpublished package name. + ### Removed - **deps**: `better-sqlite3` and `@types/better-sqlite3`. The production dependency tree no longer contains any native addon, removing the entire class of ABI-mismatch failures (`ERR_DLOPEN_FAILED` / `NODE_MODULE_VERSION` errors after a Node major upgrade, e.g. via `brew upgrade node`), a 1.9 MB platform-specific binary, and the C++ compilation-toolchain requirement for installs from source. The cacheless-degradation safety net remains: a runtime whose `node:sqlite` is missing (Node < 22.5.0) warns once and runs uncached rather than crashing, and never touches the cache database. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bc99a5fb..4481bfbe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ project maintainer. ## Prerequisites -- **Node.js** >= 20.0.0 +- **Node.js** >= 24.0.0 - **npm** >= 9.0.0 - A [DeepL API key](https://www.deepl.com/pro-api) (free tier works for development) @@ -20,7 +20,7 @@ project maintainer. ```bash # Clone the repository -git clone https://github.com/DeepLcom/deepl-cli.git +git clone https://github.com/DeepL/deepl-cli.git cd deepl-cli # Install dependencies @@ -228,4 +228,4 @@ When filing a bug report, include: - [docs/API.md](./docs/API.md) -- Complete CLI command reference - [DeepL API Docs](https://www.deepl.com/docs-api) -- Official API documentation -[issues]: https://github.com/DeepLcom/deepl-cli/issues +[issues]: https://github.com/DeepL/deepl-cli/issues diff --git a/README.md b/README.md index 020582ff..3064ec99 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > A next-generation command-line interface for DeepL translation and writing enhancement -[![CI](https://github.com/DeepLcom/deepl-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/DeepLcom/deepl-cli/actions/workflows/ci.yml) +[![CI](https://github.com/DeepL/deepl-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/DeepL/deepl-cli/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT) **DeepL CLI** is a comprehensive, developer-friendly command-line tool that integrates DeepL's powerful translation API and cutting-edge Write API for grammar and style enhancement. Built with TypeScript and designed for modern development workflows. @@ -53,11 +53,32 @@ For security policy and vulnerability reporting, see [SECURITY.md](SECURITY.md). ## 📦 Installation +> **Prerequisite:** Node.js **24 or later** (except for Homebrew, which installs Node for you). The cache uses Node's built-in [`node:sqlite`](https://nodejs.org/api/sqlite.html) module — no native compilation, no build toolchain needed. + +### Homebrew (macOS / Linux) + +```bash +brew install deepl/tap/deepl +``` + +Installs the `deepl` command and everything it needs, including Node. + +### npm + +```bash +npm install -g @deepl/cli + +# Verify installation +deepl --version +``` + +The package is scoped, but the command is just `deepl`. + ### From Source ```bash # Clone the repository -git clone https://github.com/DeepLcom/deepl-cli.git +git clone https://github.com/DeepL/deepl-cli.git cd deepl-cli # Install dependencies @@ -71,21 +92,8 @@ npm link # Verify installation deepl --version -# Output: deepl-cli 1.x.x ``` -> **Note:** This project uses [`better-sqlite3`](https://github.com/WiseLibs/better-sqlite3) for local caching, which requires native compilation. If `npm install` fails with build errors, ensure you have: -> -> - **macOS**: Xcode Command Line Tools (`xcode-select --install`) -> - **Linux**: `python3`, `make`, and `gcc` (`apt install python3 make gcc g++`) -> - **Windows**: Visual Studio Build Tools or `windows-build-tools` (`npm install -g windows-build-tools`) - -### From npm (not yet published) - -An npm package is not yet published; install from source until then. - -> **CI examples below** (and generated hook output) assume a published npm package; source-installed users should substitute the source-install path. - ## 🚀 Quick Start ### 1. Get Your DeepL API Key @@ -1331,7 +1339,7 @@ Cache location: `~/.cache/deepl-cli/cache.db` (or `~/.deepl-cli/cache.db` for le ```bash # Clone repository -git clone https://github.com/DeepLcom/deepl-cli.git +git clone https://github.com/DeepL/deepl-cli.git cd deepl-cli # Install dependencies diff --git a/SECURITY.md b/SECURITY.md index ee58f23f..52b2fafb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,9 +4,10 @@ | Version | Supported | |---------|--------------------| -| 1.1.x | :white_check_mark: | -| 1.0.x | :white_check_mark: | -| < 1.0 | :x: | +| 2.x | :white_check_mark: | +| < 2.0 | :x: | + +Versions before 2.0.0 were never published to a package registry (source installs only) and are not supported. ## Reporting a Vulnerability diff --git a/docs/SYNC.md b/docs/SYNC.md index 624ec781..066c9ee0 100644 --- a/docs/SYNC.md +++ b/docs/SYNC.md @@ -808,7 +808,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - run: npm install -g deepl-cli + - run: npm install -g @deepl/cli - name: Check translations are up to date run: deepl sync --frozen env: @@ -832,7 +832,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - run: npm install -g deepl-cli + - run: npm install -g @deepl/cli - name: Sync and commit translations run: | git config user.name "github-actions[bot]" @@ -863,7 +863,7 @@ i18n-check: stage: test image: node:20 script: - - npm install -g deepl-cli + - npm install -g @deepl/cli - deepl sync --frozen variables: DEEPL_API_KEY: $DEEPL_API_KEY diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 89966e8f..8cc995fd 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -417,19 +417,13 @@ rm ~/.cache/deepl-cli/cache.db # or ~/.deepl-cli/cache.db for legacy installat deepl cache enable ``` -### "Translation cache backend failed to load" with NODE_MODULE_VERSION mismatch +### "Translation cache backend failed to load" -**Cause:** The `better-sqlite3` native addon was compiled for a different Node.js version than the one currently running. This happens when you switch Node.js versions (e.g., via `nvm use`, `fnm`, or a system upgrade) without rebuilding native modules. +**Cause:** The cache uses Node's built-in `node:sqlite` module, which requires Node.js 24 or later (the CLI's minimum supported version). On an older runtime the module doesn't exist, so caching cannot start. -Translation and write commands keep working with caching disabled for the run; your cache database is not modified. `deepl cache` subcommands fail until the backend loads again. +Translation and write commands keep working with caching disabled for the run; your cache database is not modified. `deepl cache` subcommands fail until the CLI runs on a supported Node.js version. -**Solution:** - -```bash -npm rebuild better-sqlite3 -``` - -or reinstall the CLI / switch back to the Node.js version it was installed with. +**Solution:** run the CLI with Node.js 24+ (e.g. `nvm install 24 && nvm use 24`), or install via Homebrew (`brew install deepl/tap/deepl`), which manages Node for you. --- @@ -534,7 +528,7 @@ If you encounter an issue not covered here, check the [DeepL API documentation]( ## Still Having Issues? -If your problem isn't listed above, [file a bug report](https://github.com/DeepLcom/deepl-cli/issues/new) with: +If your problem isn't listed above, [file a bug report](https://github.com/DeepL/deepl-cli/issues/new) with: - The command you ran - The full error output diff --git a/examples/05-document-translation.sh b/examples/05-document-translation.sh index 80c3dd68..7239d22c 100755 --- a/examples/05-document-translation.sh +++ b/examples/05-document-translation.sh @@ -83,7 +83,7 @@ Key Features: - Real-time file watching Installation: -npm install -g deepl-cli +npm install -g @deepl/cli Usage: deepl translate "Hello, world!" --to es diff --git a/examples/18-cicd-integration.sh b/examples/18-cicd-integration.sh index 50b186ba..17c7b61f 100755 --- a/examples/18-cicd-integration.sh +++ b/examples/18-cicd-integration.sh @@ -139,7 +139,7 @@ jobs: node-version: '20' - name: Install DeepL CLI - run: npm install -g deepl-cli + run: npm install -g @deepl/cli - name: Configure API Key env: diff --git a/examples/31-sync-ci.sh b/examples/31-sync-ci.sh index 1b7b76c4..746a672b 100755 --- a/examples/31-sync-ci.sh +++ b/examples/31-sync-ci.sh @@ -117,7 +117,7 @@ cat << 'WORKFLOW' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - run: npm install -g deepl-cli + - run: npm install -g @deepl/cli - name: Check translations are up to date run: deepl sync --frozen env: @@ -133,7 +133,7 @@ cat << 'GITLAB' stage: test image: node:20 script: - - npm install -g deepl-cli + - npm install -g @deepl/cli - deepl sync --frozen variables: DEEPL_API_KEY: $DEEPL_API_KEY @@ -158,7 +158,7 @@ cat << 'AUTOSYNC' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - run: npm install -g deepl-cli + - run: npm install -g @deepl/cli - name: Sync translations run: deepl sync --format json env: diff --git a/examples/README.md b/examples/README.md index e8fee41d..8631120d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -73,7 +73,7 @@ This directory contains practical, real-world examples of using the DeepL CLI. All examples assume you have: -1. Installed DeepL CLI (`npm install -g deepl-cli` or `npm link`) +1. Installed DeepL CLI (`npm install -g @deepl/cli` or `npm link`) 2. A DeepL API key configured (`deepl auth set-key YOUR_API_KEY`) ## Running Examples diff --git a/src/services/git-hooks.ts b/src/services/git-hooks.ts index be11c733..7e850724 100644 --- a/src/services/git-hooks.ts +++ b/src/services/git-hooks.ts @@ -268,7 +268,7 @@ echo "🔍 Validating all translations before push..." # Check if deepl CLI is available if ! command -v deepl &> /dev/null; then echo "⚠️ DeepL CLI not found in PATH" - echo " Install: npm install -g deepl-cli" + echo " Install: npm install -g @deepl/cli" exit 0 fi diff --git a/tests/unit/services/git-hooks.test.ts b/tests/unit/services/git-hooks.test.ts index 20002084..b098ae13 100644 --- a/tests/unit/services/git-hooks.test.ts +++ b/tests/unit/services/git-hooks.test.ts @@ -56,6 +56,25 @@ describe('GitHooksService', () => { }); }); + describe('generated hook content', () => { + // Regression guard for the class of bug reported in PR #70: docs pointed + // at the unpublished `deepl-cli` npm name, and the fix missed this file — + // so the CLI itself kept emitting a broken install instruction into + // generated hooks. Generated output must only ever name the published + // package, @deepl/cli. + const hookTypes = ['pre-commit', 'pre-push', 'commit-msg', 'post-commit'] as const; + + it.each(hookTypes)('%s output never references an unpublished package name', (hookType) => { + gitHooksService.install(hookType); + + const content = fs.readFileSync(path.join(testHooksDir, hookType), 'utf-8'); + expect(content).not.toMatch(/install\s+-g\s+deepl-cli\b/); + if (/npm install/.test(content)) { + expect(content).toContain('npm install -g @deepl/cli'); + } + }); + }); + describe('install()', () => { it('should install pre-commit hook', () => { gitHooksService.install('pre-commit');