|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## What is this? |
| 6 | + |
| 7 | +TypeScript implementation of [sgraph](https://github.com/softagram/sgraph) — a library for parsing, manipulating, and converting software dependency graph models stored in XML format. Used as an npm package (`sgraph.js`). |
| 8 | + |
| 9 | +## Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +npm test # Run all tests (Jest + ts-jest) |
| 13 | +npx jest test/sgraph/sgraph.test.ts # Run a single test file |
| 14 | +npx jest --testNamePattern "finds dir" # Run tests matching a name pattern |
| 15 | +npm run compile # Build TypeScript → dist/ (rimraf + tsc) |
| 16 | +``` |
| 17 | + |
| 18 | +CI uses `yarn install` and `yarn test` on Node 16.x and 18.x. |
| 19 | + |
| 20 | +## Architecture |
| 21 | + |
| 22 | +The core data model is a tree of `SElement` nodes connected by `SElementAssociation` edges: |
| 23 | + |
| 24 | +- **SElement** (`src/selement/selement.ts`) — Tree node with `name`, `parent`, `children[]`, `childrenObject{}` (name-keyed lookup), `outgoing[]`/`incoming[]` associations, and key-value `attrs`. Uses `object-hash` for identity. Slashes in names are encoded as `__slash__`. Constructor auto-attaches to parent. |
| 25 | +- **SElementAssociation** (`src/selement/selementAssociation.ts`) — Directed edge between two SElements with a `deptype` (e.g. `"function_ref"`) and attributes. `initElems()` must be called to wire into both elements' outgoing/incoming arrays. `createUniqueElementAssociation` prevents duplicates. |
| 26 | +- **SGraph** (`src/sgraph/sgraph.ts`) — Wraps a root SElement. Provides `parseXml()` (in-memory string) and `parseXmlFileOrZippedXml()` (file/zip on disk). `toXml()` serializes back. `createOrGetElementFromPath()` builds tree paths on demand. |
| 27 | +- **SGraphXMLParser** (`src/sgraph/sgraphXmlParser.ts`) — SAX-based streaming parser. XML uses `<e>` for elements (with `n=name`, `t=type`, `i=id`), `<r>` for references (with `R=target-id`, `T=type`), `<a>` for attributes. After parsing, `translateReferences()` resolves numeric ids to SElement objects. |
| 28 | +- **ModelApi** (`src/modelapi.ts`) — Higher-level API over SGraph: `getElementsByName`, `getCalledFunctions`/`getCallingFunctions`, `filterModel` (subgraph extraction with three modes: Ignore, Direct, DirectAndIndirect), `getCyclicDependencyCycles`. |
| 29 | +- **ModelLoader** (`src/loaders/modelLoader.ts`) — Loads model XML and optionally associated CSV attribute files from a Softagram analysis output directory structure. |
| 30 | +- **Converters** (`src/converters/`) — `sgraphToEcharts` (graph visualization data) and `sgraphToDot` (Graphviz DOT format). |
| 31 | + |
| 32 | +### XML model format |
| 33 | + |
| 34 | +```xml |
| 35 | +<model version="2.1"> |
| 36 | + <elements> |
| 37 | + <e n="name" t="type" i="numeric-id"> |
| 38 | + <r R="target-id,target-id" T="dep-type"/> |
| 39 | + <a N="attr-name" V="attr-value"/> |
| 40 | + <e n="child">...</e> |
| 41 | + </e> |
| 42 | + </elements> |
| 43 | +</model> |
| 44 | +``` |
| 45 | + |
| 46 | +Zipped models contain `modelfile.xml` inside the zip archive. |
| 47 | + |
| 48 | +### Browser vs Node |
| 49 | + |
| 50 | +`src/utils/browser.ts` detects the runtime. `SGraph.parseXmlFileOrZippedXml` and `ModelLoader` use `eval('require')` for Node-only modules (`adm-zip`, `fs/promises`) to avoid bundler issues. ModelLoader throws in browser context. |
| 51 | + |
| 52 | +## Key patterns |
| 53 | + |
| 54 | +- SElement constructor with a parent automatically adds itself to that parent's children. Creating duplicate child names throws. |
| 55 | +- Associations need `initElems()` after construction to register in both elements' arrays — except when using the static `createUniqueElementAssociation`. |
| 56 | +- Test fixtures use `test/modelfile.xml` and `test/modelfile.xml.zip`. |
0 commit comments