# two-p-set _(no submodules)_ ## Purpose Provides `TwoPSet`, a Two-Phase Set CRDT. Elements can be added and removed exactly once; removed elements can never be re-added. The set value is the difference between the add-set and the remove-set. This guarantees eventual consistency at the cost of restricting re-addition. ## Features - `add(element)` — adds to the A-set; throws `OPERATION_INVALID` if element was previously removed - `remove(element)` — moves element to the R-set; no-op if not in A-set - `has(element)` — true if in A-set but not R-set - `value()` — returns a `Set` of live elements - `merge(state)` — union-merges both A-set and R-set - `toJSON()` / `fromJSON()` — serialization round-trip - `clone()` — deep copy ## Usage: Basic Example ```ts import { TwoPSet } from "@suaveplan/crdt"; const set = new TwoPSet(); set.add("alice"); set.remove("alice"); console.log(set.has("alice")); // false ``` ## Usage: Advanced Example ```ts import { TwoPSet } from "@suaveplan/crdt"; const a = new TwoPSet(); a.add(1); const b = new TwoPSet(); b.add(2); a.merge(b.state()); console.log([...a.value()]); // [1, 2] ``` ## API Reference ### `TwoPSet` - `add(element)` — throws `OPERATION_INVALID` if previously removed - `remove(element)` — no-op if element not in A-set - `has(element): boolean` - `value(): Set` - `merge(state: TwoPSetState): void` ## Implementation Notes Elements are serialised to JSON for key comparison, enabling support for object elements with structural equality. The restriction that removed elements cannot be re-added is a fundamental invariant of 2P-Set that enables simple merge logic.