Skip to content
Merged
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
69 changes: 58 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- **GitRepositoryService.save()**: Introduced a polymorphic persistence method that automatically delegates to the appropriate low-level operation based on the entity type (Blob, Tree, or Commit).
- **Commit Lifecycle Guide**: Created `docs/COMMIT_LIFECYCLE.md`, a step-by-step tutorial covering manual graph construction and persistence.
- **Root Barrel Files**: Added `sha.js`, `ref.js`, `mode.js`, `signature.js`, and `errors.js` at the package root to provide a clean and stable public API.
- **Security Documentation**: Created `SECURITY.md` to document the library's security model and process isolation rationale.

### Changed
- **Documentation Overhaul**: Updated `README.md` with enhanced security details and prominent links to the new lifecycle guide.
- **Documentation Overhaul**: Updated `README.md` with enhanced security details, design principles, and prominent links to the new lifecycle guide.
- **Process Isolation**: Hardened shell runners with strict environment variable whitelisting and support for per-call overrides.
- **Runtime Optimization**: Updated `ByteMeasurer` to use `Buffer.byteLength` where available and pinned Deno to 2.6.3 in development environments.
- **GitStream Resource Management**: Made `destroy()` idempotent and optimized `collect()` to reuse a module-level `TextEncoder`.
- **CommandSanitizer Optimization**: Implemented a memory-efficient cache key and unified prohibited flag management.
- **Improved Validation**: Enhanced `GitRefSchema` to strictly follow Git's naming rules, including better handling of control characters and '@' symbol sequences.
- **Refined Exports**: Updated `package.json` to use root barrel files for all subpath exports, ensuring a consistent public API surface.

### Fixed
- **Node.js Shell Stability**: Resolved a critical bug in `NodeShellRunner` where processes were killed immediately if no timeout was specified.
- **Backoff Logic**: Fixed an off-by-one error in `ExecutionOrchestrator` that caused incorrect delay calculations during retries.
- **Type Safety**: Added type validation to `CommandSanitizer` to prevent `TypeError` when receiving non-string arguments.
- **Object Mapping**: Fixed a bug in `GitObjectType` where delta types were incorrectly mapped to strings instead of integers.
- **CI/CD Reliability**: Fixed GitHub Actions workflow by adding missing Node.js setup and dependency installation steps to the multi-runtime test job.
- **Persistence Accuracy**: Fixed incorrect tree entry type detection in `GitPersistenceService` that could cause tree corruption.
- **Persistence Accuracy**: Fixed incorrect tree entry type detection in `GitPersistenceService` and updated `commit-tree` to use `stdin` for messages.
- **Environment Reproducibility**: Pinned Deno to 2.6.3 in the Docker test environment.

## [2.5.0] - 2026-01-05
## [2.6.0] - 2026-01-07

### Added
- **GitCommandBuilder Fluent API**: Added static factory methods for all whitelisted Git commands (e.g., `.hashObject()`, `.catFile()`, `.writeTree()`) and fluent flag methods (e.g., `.stdin()`, `.write()`, `.pretty()`) for a more expressive command-building experience.
- **GitPersistenceService**: New domain service for persisting Git entities (Blobs, Trees, Commits) to the object database using plumbing commands.
- **GitPlumbing.commit()**: High-level orchestration method that handles the full sequence from content creation to reference update in a single atomic-like operation.
- **Environment Overrides**: `GitPlumbing.execute()` now supports per-call environment variable overrides, enabling precise control over identity (`GIT_AUTHOR_*`) during execution.

### Changed
- **GitRepositoryService Enhancement**: Added `writeBlob`, `writeTree`, and `writeCommit` methods, delegating to the persistence layer.
- **Runner Schema Evolution**: Updated `RunnerOptionsSchema` to include an optional `env` record for cross-runtime environment injection.

## [2.5.0] - 2026-01-07

### Added
- **GitCommandBuilder Fluent API**: Added static factory methods for all whitelisted Git commands (e.g., `.hashObject()`, `.catFile()`, `.writeTree()`) and fluent flag methods (e.g., `.stdin()`, `.write()`, `.pretty()`) for a more expressive command building experience.

### Changed
- **GitPlumbing DI Support**: Updated the constructor to accept optional `sanitizer` and `orchestrator` instances, enabling full Dependency Injection for easier testing and customization of core logic.

## [2.4.0] - 2026-01-03
## [2.4.0] - 2026-01-07

### Added
- **GitErrorClassifier**: Extracted error categorization logic from the orchestrator into a dedicated domain service. Uses regex and exit codes (e.g., 128) to identify lock contention and state issues.
Expand All @@ -45,7 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Sanitizer Memoization**: Implemented an internal LRU-ish cache in `CommandSanitizer` to skip re-validation of identical repetitive commands, improving performance for high-frequency operations.
- **Enhanced Deno Shim**: Updated the test shim to include `beforeEach`, `afterEach`, and other lifecycle hooks for full parity with Vitest.

## [2.3.0] - 2026-01-01
## [2.3.0] - 2026-01-07

### Changed
- **Validation Unification**: Completed the migration from `ajv` to `zod` for the entire library, reducing bundle size and unifying the type-safety engine.
Expand All @@ -55,7 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- **EnvironmentPolicy**: Extracted environment variable whitelisting into a dedicated domain service used by all shell runners.

## [2.2.0] - 2025-12-28
## [2.2.0] - 2026-01-07

### Added
- **ExecutionOrchestrator**: Extracted command execution lifecycle (retry, backoff, lock detection) into a dedicated domain service to improve SRP compliance.
Expand All @@ -72,7 +88,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Runtime Performance**: Optimized `ByteMeasurer` to use `Buffer.byteLength()` in Node.js and Bun, significantly improving performance for large string measurements.
- **Development Tooling**: Upgraded `vitest` to version 3.0.0 for improved testing capabilities and performance.

## [2.1.0] - 2025-12-20
## [2.1.0] - 2026-01-07

### Added
- **GitRepositoryService**: Extracted high-level repository operations (`revParse`, `updateRef`, `deleteRef`) into a dedicated domain service.
Expand All @@ -91,7 +107,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Deno Resource Leaks**: Resolved process leaks in Deno by ensuring proper stream consumption across all test cases.
- **Node.js Stream Performance**: Optimized async iteration in `GitStream` using native protocols.

## [2.0.0] - 2025-12-10
## [2.0.0] - 2026-01-07

### Added
- **Unified Streaming Architecture**: Refactored all shell runners (Node, Bun, Deno) to use a single "Streaming Only" pattern, simplifying the adapter layer and port interface.
- **Exhaustive Zod Schemas**: Centralized validation in `src/domain/schemas` using Zod for all Entities and Value Objects.
- **Safety Buffering**: Added `GitStream.collect({ maxBytes })` with default 10MB limit to prevent OOM during large command execution.
- **Runtime Factory**: Added `GitPlumbing.createDefault()` for zero-config instantiation in Node, Bun, and Deno.

### Changed
- **Strict Hexagonal Architecture**: Enforced strict dependency inversion by passing the runner port to domain services.
- **1 Class per File**: Reorganized the codebase to strictly adhere to the "one class per file" mandate.
- **Magic Number Elimination**: Replaced all hardcoded literals (timeouts, buffer sizes, SHA constants) with named exports in the ports layer.
- **Bound Context**: Ensured `ShellRunnerFactory` returns bound methods to prevent `this` context loss in production.

### Fixed
- **Performance**: Optimized `GitStream` for Node.js by using native `Symbol.asyncIterator` instead of high-frequency listener attachments.
- **Validation**: Fixed incomplete Git reference validation by implementing the full `git-check-ref-format` specification via Zod.

## [1.1.0] - 2026-01-07

### Added
- **Stream Completion Tracking**: Introduced `exitPromise` to `CommandRunnerPort` and `GitStream.finished` to track command success/failure after stream consumption.
- **Resource Limits**: Implemented `MAX_ARGS`, `MAX_ARG_LENGTH`, and `MAX_TOTAL_LENGTH` in `CommandSanitizer` to prevent resource exhaustion attacks.

### Changed
- **Security Hardening**: Restricted `CommandSanitizer` to Git-only commands (removed `sh`, `cat`) and added 12+ prohibited Git flags (e.g., `--exec-path`, `--config`, `--work-tree`).
- **Universal Timeout**: Applied execution timeouts to streaming mode across all adapters (Node, Bun, Deno).

### Fixed
- **Test Integrity**: Corrected critical race conditions in the test suite by ensuring all async Git operations are properly awaited.
- **Streaming Reliability**: Fixed Deno streaming adapter to capture stderr without conflicting with stdout consumption.

## [1.0.0] - 2025-10-15

### Added
- Initial release of the plumbing library.
6 changes: 6 additions & 0 deletions errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export { default as GitPlumbingError } from './src/domain/errors/GitPlumbingError.js';
export { default as GitRepositoryLockedError } from './src/domain/errors/GitRepositoryLockedError.js';
export { default as InvalidArgumentError } from './src/domain/errors/InvalidArgumentError.js';
export { default as InvalidGitObjectTypeError } from './src/domain/errors/InvalidGitObjectTypeError.js';
export { default as ProhibitedFlagError } from './src/domain/errors/ProhibitedFlagError.js';
export { default as ValidationError } from './src/domain/errors/ValidationError.js';
1 change: 1 addition & 0 deletions mode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './src/domain/value-objects/GitFileMode.js';
41 changes: 30 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
{
"name": "@git-stunts/plumbing",
"version": "2.7.0",
"description": "Git Stunts Lego Block: plumbing",
"description": "Robust async, stream-first Git plumbing for Node, Bun, and Deno.",
"type": "module",
"main": "index.js",
"exports": {
".": "./index.js",
"./ShellRunner": "./ShellRunner.js",
"./sha": "./src/domain/value-objects/GitSha.js",
"./ref": "./src/domain/value-objects/GitRef.js",
"./mode": "./src/domain/value-objects/GitFileMode.js",
"./signature": "./src/domain/value-objects/GitSignature.js",
"./errors": "./src/domain/errors/GitPlumbingError.js"
"./sha": "./sha.js",
"./ref": "./ref.js",
"./mode": "./mode.js",
"./signature": "./signature.js",
"./errors": "./errors.js"
},
"engines": {
"node": ">=22.0.0",
"node": ">=20.0.0",
"bun": ">=1.3.5",
"deno": ">=2.0.0"
},
"scripts": {
"test": "./scripts/run-multi-runtime-tests.sh",
"test:local": "vitest run --globals",
"prepare": "test -d .git && git config core.hooksPath scripts || true",
"prepare": "test -d .git || true",
"lint": "eslint .",
"format": "prettier --write ."
"format": "prettier --write .",
"hooks:install": "git config core.hooksPath scripts"
},
"author": "James Ross <james@flyingrobots.dev>",
"license": "Apache-2.0",
Expand All @@ -35,5 +36,23 @@
"eslint": "^9.17.0",
"prettier": "^3.4.2",
"vitest": "^3.0.0"
}
}
},
"files": [
"src",
"index.js",
"ShellRunner.js",
"sha.js",
"ref.js",
"mode.js",
"signature.js",
"errors.js",
"README.md",
"LICENSE",
"NOTICE",
"SECURITY.md"
],
"repository": { "type": "git", "url": "git+https://github.com/git-stunts/plumbing.git" },
"homepage": "https://github.com/git-stunts/plumbing#readme",
"bugs": { "url": "https://github.com/git-stunts/plumbing/issues" },
"keywords": ["git", "plumbing", "content-addressable", "dag", "merkle", "node", "deno", "bun"]
}
1 change: 1 addition & 0 deletions ref.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './src/domain/value-objects/GitRef.js';
1 change: 1 addition & 0 deletions sha.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './src/domain/value-objects/GitSha.js';
1 change: 1 addition & 0 deletions signature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './src/domain/value-objects/GitSignature.js';
Loading