Skip to content

Commit 2d50a74

Browse files
update ego-graph packege
1 parent ef75462 commit 2d50a74

7 files changed

Lines changed: 174 additions & 7 deletions

File tree

bun.lock

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ego-graph/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
11
dist
2+
node_modules
3+
.cursor
4+
.claude
5+
6+
# Published glossary — the repo root ignores CONTEXT.md as a local agent file,
7+
# but here it is part of the package and the README links to it.
8+
!CONTEXT.md

packages/ego-graph/CONTEXT.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Context: ego-graph
2+
3+
The vocabulary of this package. Glossary only — no implementation, no decisions.
4+
For decisions see [docs/adr](./docs/adr).
5+
6+
## Terms
7+
8+
**Ego graph** — a graph seen from one node. Not a general graph: every layout
9+
here answers "what surrounds *this* node", and every distance is measured from it.
10+
11+
**Root** — the node the layout centres on. The ego. Its centre is the origin of
12+
the coordinate system the layout returns.
13+
14+
**Structural edge** — an edge that defines the hierarchy the layout draws. The
15+
spanning tree is built from these and nothing else.
16+
17+
**Associative edge** — an edge that exists and is rendered, but must never
18+
influence position. Two nodes can be associated without one being under the
19+
other. An associative edge between two ordinary nodes is legal and common.
20+
21+
The distinction is *not* importance. An associative edge may be the most
22+
significant relationship in the domain; it is simply not hierarchical.
23+
24+
**Satellite** — a node that never joins the spanning tree, whatever edges it
25+
has. A role, not a consequence: declaring a node a satellite settles its
26+
placement regardless of edge classes. Satellites are parked on the periphery so
27+
they cannot reparent branches or warp the ring.
28+
29+
Satellite and edge class are **orthogonal axes**. A satellite may have structural
30+
edges (it still stays out of the tree); an ordinary node may have only
31+
associative ones (it still is not a satellite).
32+
33+
**Spanning tree** — the one hierarchy every pass agrees on: structural edges
34+
between non-satellite nodes, breadth-first from the root. There is exactly one
35+
definition, shared by layout and folding.
36+
37+
**Ring** — the circle of level-1 branches around the root.
38+
39+
**Slot** — one angular position on a ring. **Sector** — a wedge of the circle
40+
allotted to a group of children.
41+
42+
**Pocket** — the angular region allotted to one satellite and the island hanging
43+
off it, on an arc outside everything the tree placed.
44+
45+
**Island** — a connected group of nodes the spanning tree could not reach,
46+
claimed by a satellite (or, if no satellite touches it, standing alone as an
47+
**orphan** island). Every island gets a pocket.
48+
49+
**Lateral half-extent** — half the width of a laid-out subtree, measured
50+
perpendicular to the ray it grows along. The packing measure: two neighbouring
51+
branches clear each other when the ring is wide enough for both half-extents
52+
plus padding.
53+
54+
**Fold** — a branch collapsed behind a single stand-in. **Folded group** — the
55+
nodes that disappeared. A fold names the branch by its **root**; the fold's
56+
members include that root.
57+
58+
**Fold plan** — what to collapse and what to redraw, with no opinion about how.
59+
The package emits a plan; the caller materialises whatever a collapsed branch
60+
should look like.
61+
62+
## Words this package does not use
63+
64+
`pivot`, `connector`, `person`, `company`, `match edge`, `link edge`, `cluster`,
65+
`chip`, `start`. They come from the domain this code was extracted from and mean
66+
nothing to anyone else.

packages/ego-graph/README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,18 @@ is *about*: a customer and their connections, a person and their network, an
1010
account and everything touching it. That is an ego graph, and it wants the root
1111
in the middle with its neighbourhood arranged around it.
1212

13-
> **Not published yet.** Currently consumed from source inside a workspace.
13+
## Install
14+
15+
```sh
16+
npm install ego-graph
17+
```
18+
19+
Zero dependencies. `@dagrejs/dagre` is an **optional** peer — install it only if
20+
you use `radialDagre` or `sectoredDagre`:
21+
22+
```sh
23+
npm install ego-graph @dagrejs/dagre
24+
```
1425

1526
## Quick start
1627

packages/ego-graph/RELEASING.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Releasing
2+
3+
**This directory is the source of truth.** `github.com/checkmarble/ego-graph` is a
4+
mirror, regenerated from here on every release. Never commit to the mirror
5+
directly — the next release overwrites it.
6+
7+
The one file that differs: the mirror needs its own `biome.json`, because here
8+
the monorepo root config governs. Everything else is identical, deliberately, so
9+
the split is lossless.
10+
11+
## Release
12+
13+
From the repo root, with a clean tree:
14+
15+
```sh
16+
# 1. Everything green
17+
bun run -F ego-graph type-check
18+
bun run -F ego-graph unit-tests
19+
bun run -F ego-graph build
20+
bun run -F ego-graph check-package
21+
22+
# 2. Bump the version in packages/ego-graph/package.json, commit.
23+
24+
# 3. Regenerate the mirror
25+
git subtree split --prefix=packages/ego-graph -b ego-graph-release
26+
27+
# 4. Push it (force: the split rewrites history each time)
28+
git push --force git@github.com:checkmarble/ego-graph.git ego-graph-release:main
29+
30+
# 5. Publish from a fresh clone of the mirror
31+
git clone git@github.com:checkmarble/ego-graph.git /tmp/ego-graph-publish
32+
cd /tmp/ego-graph-publish
33+
bun install
34+
# biome.json is mirror-only; add it if the lint script is needed there.
35+
npm publish --otp=<code>
36+
37+
# 6. Tag
38+
git tag v<version> && git push --tags
39+
```
40+
41+
`prepublishOnly` rebuilds and runs `publint` + `attw`, so a malformed package
42+
cannot get out.
43+
44+
## npm requires 2FA
45+
46+
`npm publish` fails with `E403 ... Two-factor authentication or granular access
47+
token with bypass 2fa enabled is required`. Two ways through:
48+
49+
- **Publishing by hand:** enable 2FA on the npm account, then pass `--otp=<code>`.
50+
- **From CI:** create a *granular* access token with "Bypass 2FA" enabled, scoped
51+
to this package, and set `NODE_AUTH_TOKEN`. Classic automation tokens no
52+
longer satisfy the requirement.
53+
54+
## Gotchas
55+
56+
- **Keep the `unit-tests` script.** The workspace runs `bun run -F '*'
57+
unit-tests`; rename it and this package silently drops out of `test:all`.
58+
- **`CONTEXT.md` is force-included** by this directory's `.gitignore`. The repo
59+
root ignores that filename as a local agent file, and without the negation the
60+
subtree split drops the glossary the README links to.
61+
- **`tsconfig.json` is self-contained**, not extending the monorepo base. That is
62+
what lets the same file work in the mirror. Do not re-add `extends`.

packages/ego-graph/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@
5555
"build": "tsdown",
5656
"lint": "biome lint",
5757
"type-check": "tsc --noEmit",
58-
"unit-tests": "vitest run",
58+
"test": "vitest run",
5959
"check-package": "publint --strict && attw --pack . --ignore-rules cjs-resolves-to-esm",
60-
"prepublishOnly": "bun run build && bun run check-package"
60+
"prepublishOnly": "bun run build && bun run check-package",
61+
"unit-tests": "vitest run"
6162
},
6263
"peerDependencies": {
6364
"@dagrejs/dagre": "^3.0.0"
@@ -72,6 +73,7 @@
7273
"@dagrejs/dagre": "^3.0.0",
7374
"publint": "^0.3.23",
7475
"tsdown": "^0.22.14",
76+
"typescript": "^5.8.2",
7577
"vite": "^7.3.6",
7678
"vite-tsconfig-paths": "6.1.1",
7779
"vitest": "4.1.8"

packages/ego-graph/tsconfig.json

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
11
{
2-
"extends": "../../tsconfig.base.json",
32
"compilerOptions": {
4-
"types": ["vitest/globals"]
3+
"target": "esnext",
4+
"module": "esnext",
5+
"moduleResolution": "Bundler",
6+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
7+
"types": ["vitest/globals"],
8+
9+
"strict": true,
10+
"noUncheckedIndexedAccess": true,
11+
"noImplicitOverride": true,
12+
"noPropertyAccessFromIndexSignature": true,
13+
"noFallthroughCasesInSwitch": true,
14+
15+
"isolatedModules": true,
16+
"esModuleInterop": true,
17+
"forceConsistentCasingInFileNames": true,
18+
"skipLibCheck": true,
19+
"noEmit": true,
20+
"pretty": true
521
},
622
"include": ["**/*.ts"],
7-
"exclude": []
23+
"exclude": ["dist", "node_modules"]
824
}

0 commit comments

Comments
 (0)