Skip to content

Commit b32b0d9

Browse files
committed
Apply changesets and update CHANGELOG [skip ci]
1 parent ab74a4d commit b32b0d9

File tree

1 file changed

+169
-49
lines changed

1 file changed

+169
-49
lines changed

lib/README.md

Lines changed: 169 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@ A Git-aware conflict resolver for **JSON-first structured data**.
1919
## Features
2020

2121
-**Primary focus on JSON** (first-class support)
22-
- 🔄 **YAML, XML, TOML** supported via conversion
23-
- 🧩 **Rule-based strategies** (per path/pattern)
24-
- 🗂️ Handles small configs to **huge repos** (optimizations built-in)
25-
- 🔌 **Pluggable matcher** abstraction (picomatch, micromatch supported out of the box with peerDependency)
26-
- 🛠️ Configurable trade-offs for **speed vs. memory**
27-
- 🗃️ **Planned**: extend configuration to use **different strategies per file** (ideas and edge cases welcome!)
22+
- 🔄 **YAML, XML, TOML, JSON5** supported via conversion
23+
- 🧩 **Rule-based strategies** with path/pattern matching
24+
- 📁 **Multiple file parallel processing** with include/exclude patterns
25+
- 🔌 **Pluggable matcher** abstraction (picomatch, micromatch, or custom)
26+
- 🛠️ **CLI and programmatic API** support
27+
- 📝 **Conflict sidecar files** for unresolved conflicts
28+
- 🔄 **Backup and restore** functionality
29+
- 📊 **Configurable logging** (memory or file-based)
30+
- 🔀 **Git merge driver** support for seamless Git integration
2831

2932
## Installation
3033

@@ -46,6 +49,24 @@ yarn add git-json-resolver
4649

4750
## Quick Start
4851

52+
### CLI Usage
53+
54+
```bash
55+
# Initialize config file
56+
npx git-json-resolver --init
57+
58+
# Run with default config
59+
npx git-json-resolver
60+
61+
# Run with options
62+
npx git-json-resolver --include "**/*.json" --debug --sidecar
63+
64+
# Restore from backups
65+
npx git-json-resolver --restore .merge-backups
66+
```
67+
68+
### Git Integration
69+
4970
Add a custom merge driver to your Git config:
5071

5172
```bash
@@ -57,73 +78,172 @@ Update `.gitattributes` to use it for JSON files:
5778

5879
```gitattributes
5980
*.json merge=json-resolver
81+
*.yaml merge=json-resolver
82+
*.yml merge=json-resolver
83+
*.toml merge=json-resolver
84+
*.xml merge=json-resolver
6085
```
6186

62-
## Example Config
87+
**How it works:**
88+
89+
- Git automatically calls the merge driver during conflicts
90+
- Uses same configuration and strategies as CLI mode
91+
- Supports 3-way merge (ours, base, theirs)
92+
- Returns proper exit codes (0 = success, 1 = conflicts)
93+
94+
## Configuration
95+
96+
### Programmatic API
6397

6498
```ts
6599
import { resolveConflicts } from "git-json-resolver";
66100

67-
const result = resolveConflicts({
68-
filePath: "package.json",
69-
rules: [
70-
{ pattern: "dependencies.*", strategy: "ours" },
71-
{ pattern: "version", strategy: "theirs", important: true },
72-
{ pattern: "scripts.build", strategy: "manual" },
73-
],
74-
matcher: "picomatch", // default
75-
optimize: {
76-
cacheMatchers: true,
77-
streamMode: false, // set true for very large repos
101+
await resolveConflicts({
102+
defaultStrategy: ["merge", "ours"],
103+
rules: {
104+
"dependencies.*": ["ours"],
105+
version: ["theirs!"], // ! marks as important
106+
"scripts.build": ["skip"],
78107
},
108+
include: ["**/*.json", "**/*.yaml"],
109+
exclude: ["**/node_modules/**"],
110+
matcher: "picomatch",
111+
debug: true,
112+
writeConflictSidecar: true,
113+
backupDir: ".merge-backups",
79114
});
80115
```
81116

82-
### Upcoming: File-Specific Strategies
83-
84-
We are exploring the ability to define **per-file strategy sets** in config, e.g.:
85-
86-
```ts
87-
rulesByFile: {
88-
"package.json": { version: ["theirs"], dependencies: ["ours"] },
89-
"*.config.json": { "*": ["merge"] },
90-
},
117+
### Config File (`git-json-resolver.config.js`)
118+
119+
```js
120+
module.exports = {
121+
defaultStrategy: ["merge", "ours"],
122+
rules: {
123+
// Exact path matching
124+
"package.json": {
125+
version: ["theirs!"],
126+
dependencies: ["ours"],
127+
},
128+
// Pattern matching
129+
"*.config.json": {
130+
"*": ["merge"],
131+
},
132+
},
133+
// Alternative: byStrategy format
134+
byStrategy: {
135+
ours: ["dependencies.*", "devDependencies.*"],
136+
"theirs!": ["version", "name"],
137+
},
138+
include: ["**/*.json", "**/*.yaml", "**/*.yml"],
139+
exclude: ["**/node_modules/**", "**/dist/**"],
140+
matcher: "picomatch",
141+
debug: false,
142+
writeConflictSidecar: false,
143+
loggerConfig: {
144+
mode: "memory", // or "stream"
145+
logDir: "logs",
146+
levels: {
147+
stdout: ["warn", "error"],
148+
file: ["info", "warn", "error"],
149+
},
150+
},
151+
};
91152
```
92153

93-
This raises interesting questions/edge cases:
94-
95-
- How to merge file-level vs. global rules?
96-
- Should `include/exclude` still apply if a file is explicitly listed?
97-
- Should conflicting rules between file + global fall back to default strategy or error?
98-
99-
We welcome ideas & edge cases here!
100-
101154
## Supported Strategies
102155

156+
- **merge** → deep merge objects/arrays where possible
103157
- **ours** → take current branch value
104158
- **theirs** → take incoming branch value
105-
- **manual** → mark for human resolution
106-
- **drop** → remove the key entirely
107-
- **custom** → user-defined resolver function
159+
- **base** → revert to common ancestor
160+
- **skip** → leave unresolved (creates conflict entry)
161+
- **drop** → remove the field entirely
162+
- **non-empty** → prefer non-empty value (ours > theirs > base)
163+
- **update** → update with theirs if field exists in ours
164+
- **concat** → concatenate arrays from both sides
165+
- **unique** → merge arrays and remove duplicates
166+
- **custom** → user-defined resolver functions
167+
168+
### Strategy Priority
169+
170+
- Strategies marked with `!` (important) are applied first
171+
- Multiple strategies can be specified as fallbacks
172+
- Custom strategies can be defined via `customStrategies` config
108173

109174
## Supported Formats
110175

111176
- **JSON** (native)
112-
- **YAML, XML, TOML** → converted to JSON → resolved → converted back
177+
- **JSON5** → via `json5` peer dependency
178+
- **YAML** → via `yaml` peer dependency
179+
- **TOML** → via `smol-toml` peer dependency
180+
- **XML** → via `fast-xml-parser` peer dependency
181+
182+
All non-JSON formats are converted to JSON → resolved → converted back to original format.
183+
184+
## CLI Options
185+
186+
```bash
187+
# File patterns
188+
--include "**/*.json,**/*.yaml" # Comma-separated patterns
189+
--exclude "**/node_modules/**" # Exclusion patterns
190+
191+
# Matcher selection
192+
--matcher picomatch # picomatch, micromatch, or custom
193+
194+
# Debug and logging
195+
--debug # Enable verbose logging
196+
--sidecar # Write conflict sidecar files
197+
198+
# Utilities
199+
--init # Create starter config file
200+
--restore .merge-backups # Restore from backup directory
201+
```
113202

114-
## Performance & Optimization
203+
## Architecture
115204

116-
- **Matcher caching** for repeated patterns
117-
- **Streaming mode** for very large repos (low memory footprint)
118-
- Trade-offs are configurable via `optimize` field
205+
- **Modular design**: Separate concerns (parsing, merging, serialization)
206+
- **Reusable utilities**: Common merge logic extracted for maintainability
207+
- **Optimized bundle**: Constants over enums for better minification
208+
- **Comprehensive testing**: Full test coverage with vitest
209+
- **Type-safe**: Full TypeScript support with proper type inference
210+
211+
## Advanced Features
212+
213+
### Pattern Matching
214+
215+
- **Exact paths**: `"package.json"`, `"src.config.database.host"`
216+
- **Field matching**: `"[version]"` → matches any `version` field
217+
- **Glob patterns**: `"dependencies.*"`, `"**.config.**"`
218+
- **Wildcards**: `"*.json"`, `"src/**/*.config.js"`
219+
220+
### Custom Strategies
221+
222+
```ts
223+
import { StrategyStatus } from "git-json-resolver";
224+
225+
const config = {
226+
customStrategies: {
227+
"semantic-version": ({ ours, theirs }) => {
228+
// Custom logic for semantic version resolution
229+
if (isNewerVersion(theirs, ours)) {
230+
return { status: StrategyStatus.OK, value: theirs };
231+
}
232+
return { status: StrategyStatus.CONTINUE };
233+
},
234+
},
235+
rules: {
236+
version: ["semantic-version", "theirs"],
237+
},
238+
};
239+
```
119240

120-
## Roadmap
241+
### Logging & Debugging
121242

122-
- [ ] Richer strategies via plugins (e.g., semantic version resolver)
123-
- [ ] CLI UX improvements
124-
- [ ] Pluggable format converters customizations
125-
- [ ] VSCode integration for previewing merge resolutions
126-
- [ ] **Per-file strategies support** (current RFC)
243+
- **Memory mode**: Fast, in-memory logging
244+
- **Stream mode**: File-based logging for large operations
245+
- **Per-file logs**: Separate log files for each processed file
246+
- **Debug mode**: Detailed conflict information and strategy traces
127247

128248
## Contributing
129249

0 commit comments

Comments
 (0)