Metadata-Version: 2.5
Name: nan-graph
Version: 0.1.0
Summary: In-memory Architecture Graph engine — blast radius, traversal, cost chain. Sync del core TypeScript @carloscortezcloud/nan-graph (fusión Ñan × BYaML / SOFE Architecture Graph).
Project-URL: homepage, https://github.com/breakingthecloud/nan-graph-py
Project-URL: repository, https://github.com/breakingthecloud/nan-graph-py
Author-email: Carlos Cortez <carlos@finoptix.dev>
License: Apache-2.0
License-File: LICENSE
Keywords: architecture,blast-radius,byaml,graph,sofe,topology,traversal
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Requires-Dist: pyyaml>=6.0
Description-Content-Type: text/markdown

# nan-graph (Python)

> **Port en Python** del core `@carloscortezcloud/nan-graph` (TypeScript) — el motor del grafo de
> **SOFE Architecture Graph** (fusión **Ñan** × **BYaML v2**). OSS, Apache-2.0, bajo `breakingthecloud`.
>
> Misma API que el core TS; se mantiene en sync manual (patrón `styrr` → `styrr-py`).

Grafo dirigido en memoria con relaciones tipadas: traversal **BFS/DFS**, **blast radius**,
**cost chain**, **fan-in / SPOF**, y filtrado por tipo de relación.

## Install

```bash
pip install nan-graph
```

## Uso

```python
from nangraph import NanGraph, blast_radius, cost_chain, from_yaml

g = (
    NanGraph()
    .add_node({"id": "api", "type": "aws.apigateway", "attrs": {"monthly_cost": 20}})
    .add_node({"id": "lambda", "type": "aws.lambda", "attrs": {"monthly_cost": 5}})
    .add_node({"id": "ddb", "type": "aws.dynamodb", "attrs": {"monthly_cost": 30}})
    .add_edge("api", "lambda", "routes_to")
    .add_edge("lambda", "ddb", "reads_writes")
)

blast_radius(g, "api")   # ['lambda', 'ddb'] — qué se cae si api falla
cost_chain(g, "api")     # 55.0 — costo downstream total
```

### Importar desde YAML / JSON

```python
from nangraph import from_yaml, from_object

# estilo dependency-graph.yaml
g = from_yaml("""
nodes:
  sofe-engine: { type: python-library }
  sofe-server: { type: python-api }
edges:
  - { from: sofe-engine, to: sofe-server, relType: bundles }
""")

# estilo BYaML v0.3 (components + relationships)
g2 = from_object({
    "components": [{"id": "api", "type": "aws.apigateway", "monthly_cost": 20}],
    "relationships": [{"from": "api", "to": "lambda", "type": "routes_to"}],
})
```

## API

| Función | Descripción |
|---------|-------------|
| `NanGraph()` | Grafo dirigido multi-borde en memoria |
| `add_node(dict)` / `add_edge(from, to, rel_type)` | Añadir nodo/arista (auto-crea nodos) |
| `get_related(id, rel_type?, direction?)` | Vecinos outgoing/incoming/both, con filtro |
| `traverse_bfs(g, start, rel_types?, max_depth?, direction?)` | BFS |
| `traverse_dfs(g, start, ...)` | DFS |
| `blast_radius(g, start)` | Nodos afectados downstream si `start` falla |
| `cost_chain(g, start)` | Suma `attrs.monthly_cost` de `start` + downstream |
| `team_cost(g, owner)` | Suma de costo por `attrs.owner` |
| `fan_in(g, id)` / `single_points_of_failure(g, threshold)` | SPOF por alta dependencia entrante |
| `from_object(dict)` / `from_yaml(str)` / `from_json(str)` | Construir grafo desde input |

## Paridad con el core TS

| TS (`@carloscortezcloud/nan-graph`) | Python (`nan-graph`) |
|-------------------------------------|----------------------|
| `new NanGraph()` | `NanGraph()` |
| `g.addNode` / `g.addEdge` | `g.add_node` / `g.add_edge` |
| `g.getRelated` | `g.get_related` |
| `traverseBFS` / `traverseDFS` | `traverse_bfs` / `traverse_dfs` |
| `blastRadius` / `costChain` | `blast_radius` / `cost_chain` |
| `teamCost` / `fanIn` / `singlePointsOfFailure` | `team_cost` / `fan_in` / `single_points_of_failure` |
| `fromObject` / `fromYaml` / `fromJson` | `from_object` / `from_yaml` / `from_json` |

## Licencia

Apache-2.0. Ver [`LICENSE`](LICENSE).
