first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
# pn-counter
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Provides `PNCounter`, a positive-negative counter CRDT that supports both increment and decrement operations. Built from two G-Counters (one for increments, one for decrements), the net value is `sum(increments) - sum(decrements)`. All CRDT invariants (commutativity, associativity, idempotency) are preserved.
## Features
- `increment(nodeId, delta?)` — adds to the increment counter for `nodeId`
- `decrement(nodeId, delta?)` — adds to the decrement counter for `nodeId`
- `total()` — net value: sum of all increments minus sum of all decrements
- `merge(state)` — element-wise maximum on both increment and decrement counters
- `toJSON()` / `fromJSON()` — serialization round-trip
- `clone()` — deep copy
## Usage: Basic Example
```ts
import { PNCounter } from "@suaveplan/crdt";
const counter = new PNCounter();
counter.increment("n1", 10);
counter.decrement("n1", 3);
console.log(counter.total()); // 7
```
## Usage: Advanced Example
```ts
import { PNCounter } from "@suaveplan/crdt";
const a = new PNCounter("likes");
a.increment("user-1", 5);
const b = new PNCounter("likes");
b.decrement("user-2", 2);
a.merge(b.state());
console.log(a.total()); // 3 (5 - 2)
```
## API Reference
### `PNCounter`
- `increment(nodeId, delta?)` — throws `OPERATION_INVALID` if delta ≤ 0
- `decrement(nodeId, delta?)` — throws `OPERATION_INVALID` if delta ≤ 0
- `total(): number` — net counter value
## Implementation Notes
The value can be negative if decrements exceed increments. This is intentional — PNCounter does not enforce a floor of 0.