archrip 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -68,7 +68,7 @@
68
68
  "implements": { "type": "string" },
69
69
  "externalService": { "type": "string" },
70
70
  "sqlExamples": { "type": "array", "items": { "type": "string" } },
71
- "depth": { "type": "integer", "minimum": 0, "maximum": 2, "description": "Abstraction depth: 0=overview (boundary), 1=structure (internal), 2=detail (implementation). Auto-inferred from category if omitted." }
71
+ "depth": { "type": "integer", "minimum": 0, "maximum": 2, "description": "Abstraction depth: 0=overview, 1=structure, 2=detail. Auto-inferred from layer if omitted." }
72
72
  },
73
73
  "additionalProperties": false
74
74
  },
@@ -25,16 +25,31 @@ Read existing documentation to understand architecture context:
25
25
  3. Use this knowledge to inform the analysis — documentation often reveals architectural intent that code alone does not show (use cases, business context, external dependencies)
26
26
 
27
27
  ## Phase 3: Layer Identification
28
- Based on the framework, identify architectural layers:
28
+ Assign each component a `layer` integer. The rule: **higher layer = closer to domain core (more stable, fewer external dependencies). Lower layer = closer to external world (more volatile, I/O-bound).**
29
29
 
30
- **Common patterns:**
31
- - Laravel: Controllers → Services → Ports → Adapters → Models
32
- - Express/NestJS: Routes/Controllers Services Repositories Models
33
- - Next.js: Pages → Components → Hooks → API Routes → Services
34
- - Django: Views → Serializers → Services → Models
35
- - Spring Boot: ControllersServicesRepositoriesEntities
36
- - Go: HandlersServicesRepositories → Models
37
- - Generic: Group by directory responsibility
30
+ Both layouts use this value — dagre places higher layers lower on screen, concentric places them at the center.
31
+
32
+ **Reference mappings** (layer numbers in parentheses adapt to actual project structure):
33
+
34
+ MVC / Layered:
35
+ - Laravel: External(0)Controllers(1)Services(2)Models(3)
36
+ - Rails: External(0)Controllers(1)Services(2) → Models(3)
37
+ - Django: External(0) Views(1) → Serializers(2) → Services(3) → Models(4)
38
+ - Spring Boot: External(0) → Controllers(1) → Services(2) → Repositories(3) → Entities(4)
39
+ - NestJS: External(0) → Controllers(1) → Services(2) → Repositories(3) → Entities(4)
40
+ - Next.js App Router: External(0) → Route Handlers/Pages(1) → Components(2) → Hooks/Services(3) → Data Access(4)
41
+ - FastAPI: External(0) → Routers(1) → Services(2) → Repositories(3) → Models(4)
42
+
43
+ DDD / Clean Architecture / Hexagonal (use `"layout": "concentric"`):
44
+ - Generic: External(0) → Adapters(1) → Controllers(2) → Application Services(3) → Ports(4) → Domain Entities(5)
45
+ - Go (Hex): External(0) → Handlers(1) → Adapters(2) → Use Cases(3) → Ports(4) → Domain(5)
46
+ - Flutter (Clean): External(0) → Data Sources(1) → Repositories(2) → Use Cases(3) → Entities(4)
47
+
48
+ Serverless / Microservices:
49
+ - SST/Lambda: External(0) → API Gateway(1) → Lambda Handlers(2) → Services(3) → Domain(4)
50
+ - Microservices: External(0) → Gateway/BFF(1) → Service Boundaries(2) → Internal Services(3) → Shared Domain(4)
51
+
52
+ For unlisted frameworks: group by directory responsibility and apply the abstract rule above.
38
53
 
39
54
  ## Phase 4: Read Key Files
40
55
  For each layer, read representative files to extract:
@@ -115,11 +130,11 @@ After writing the file:
115
130
 
116
131
  ### Node Rules
117
132
  - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, ext-, job-, dto-)
118
- - `layer`: integer indicating architectural depth (higher = closer to domain core). Concentric layout places high values at center. Example: 0=external, 1=adapters/infrastructure, 2=controllers/entry points, 3=application services, 4=ports/abstractions, 5=domain models/entities
133
+ - `layer`: non-negative integer. **Higher = closer to domain core / more stable. Lower = closer to external world / more volatile.** Dagre (TB) places higher layers lower on screen; concentric places them at center. Use as many layers as the architecture requires (typically 3-6). Example for DDD: 0=external, 1=adapters, 2=controllers, 3=app services, 4=ports, 5=domain entities. Example for MVC: 0=external, 1=controllers, 2=services, 3=models.
119
134
  - `category`: one of controller, service, port, adapter, model, external, job, dto (or custom)
120
135
  - `label`: display name for the node
121
136
  - `filePath`: relative from project root
122
- - `depth` (optional): 0=overview (boundary), 1=structure (internal), 2=detail (implementation). Auto-inferred from category if omitted
137
+ - `depth` (optional): 0=overview, 1=structure, 2=detail. Auto-inferred from `layer` if omitted: with 3+ unique layers, lowest → 0, middle → 1, highest → 2. With 1-2 layers, all nodes get depth 0 (always visible).
123
138
  - `useCases`: array of use case IDs this node participates in
124
139
 
125
140
  ### Edge Rules
@@ -25,16 +25,31 @@ Read existing documentation to understand architecture context:
25
25
  3. Use this knowledge to inform the analysis — documentation often reveals architectural intent that code alone does not show (use cases, business context, external dependencies)
26
26
 
27
27
  ## Phase 3: Layer Identification
28
- Based on the framework, identify architectural layers:
28
+ Assign each component a `layer` integer. The rule: **higher layer = closer to domain core (more stable, fewer external dependencies). Lower layer = closer to external world (more volatile, I/O-bound).**
29
29
 
30
- **Common patterns:**
31
- - Laravel: Controllers → Services → Ports → Adapters → Models
32
- - Express/NestJS: Routes/Controllers Services Repositories Models
33
- - Next.js: Pages → Components → Hooks → API Routes → Services
34
- - Django: Views → Serializers → Services → Models
35
- - Spring Boot: ControllersServicesRepositoriesEntities
36
- - Go: HandlersServicesRepositories → Models
37
- - Generic: Group by directory responsibility
30
+ Both layouts use this value — dagre places higher layers lower on screen, concentric places them at the center.
31
+
32
+ **Reference mappings** (layer numbers in parentheses adapt to actual project structure):
33
+
34
+ MVC / Layered:
35
+ - Laravel: External(0)Controllers(1)Services(2)Models(3)
36
+ - Rails: External(0)Controllers(1)Services(2) → Models(3)
37
+ - Django: External(0) Views(1) → Serializers(2) → Services(3) → Models(4)
38
+ - Spring Boot: External(0) → Controllers(1) → Services(2) → Repositories(3) → Entities(4)
39
+ - NestJS: External(0) → Controllers(1) → Services(2) → Repositories(3) → Entities(4)
40
+ - Next.js App Router: External(0) → Route Handlers/Pages(1) → Components(2) → Hooks/Services(3) → Data Access(4)
41
+ - FastAPI: External(0) → Routers(1) → Services(2) → Repositories(3) → Models(4)
42
+
43
+ DDD / Clean Architecture / Hexagonal (use `"layout": "concentric"`):
44
+ - Generic: External(0) → Adapters(1) → Controllers(2) → Application Services(3) → Ports(4) → Domain Entities(5)
45
+ - Go (Hex): External(0) → Handlers(1) → Adapters(2) → Use Cases(3) → Ports(4) → Domain(5)
46
+ - Flutter (Clean): External(0) → Data Sources(1) → Repositories(2) → Use Cases(3) → Entities(4)
47
+
48
+ Serverless / Microservices:
49
+ - SST/Lambda: External(0) → API Gateway(1) → Lambda Handlers(2) → Services(3) → Domain(4)
50
+ - Microservices: External(0) → Gateway/BFF(1) → Service Boundaries(2) → Internal Services(3) → Shared Domain(4)
51
+
52
+ For unlisted frameworks: group by directory responsibility and apply the abstract rule above.
38
53
 
39
54
  ## Phase 4: Read Key Files
40
55
  For each layer, read representative files to extract:
@@ -115,11 +130,11 @@ After writing the file:
115
130
 
116
131
  ### Node Rules
117
132
  - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, ext-, job-, dto-)
118
- - `layer`: integer indicating architectural depth (higher = closer to domain core). Concentric layout places high values at center. Example: 0=external, 1=adapters/infrastructure, 2=controllers/entry points, 3=application services, 4=ports/abstractions, 5=domain models/entities
133
+ - `layer`: non-negative integer. **Higher = closer to domain core / more stable. Lower = closer to external world / more volatile.** Dagre (TB) places higher layers lower on screen; concentric places them at center. Use as many layers as the architecture requires (typically 3-6). Example for DDD: 0=external, 1=adapters, 2=controllers, 3=app services, 4=ports, 5=domain entities. Example for MVC: 0=external, 1=controllers, 2=services, 3=models.
119
134
  - `category`: one of controller, service, port, adapter, model, external, job, dto (or custom)
120
135
  - `label`: display name for the node
121
136
  - `filePath`: relative from project root
122
- - `depth` (optional): 0=overview (boundary), 1=structure (internal), 2=detail (implementation). Auto-inferred from category if omitted
137
+ - `depth` (optional): 0=overview, 1=structure, 2=detail. Auto-inferred from `layer` if omitted: with 3+ unique layers, lowest → 0, middle → 1, highest → 2. With 1-2 layers, all nodes get depth 0 (always visible).
123
138
  - `useCases`: array of use case IDs this node participates in
124
139
 
125
140
  ### Edge Rules
@@ -25,16 +25,31 @@ Read existing documentation to understand architecture context:
25
25
  3. Use this knowledge to inform the analysis — documentation often reveals architectural intent that code alone does not show (use cases, business context, external dependencies)
26
26
 
27
27
  ## Phase 3: Layer Identification
28
- Based on the framework, identify architectural layers:
28
+ Assign each component a `layer` integer. The rule: **higher layer = closer to domain core (more stable, fewer external dependencies). Lower layer = closer to external world (more volatile, I/O-bound).**
29
29
 
30
- **Common patterns:**
31
- - Laravel: Controllers → Services → Ports → Adapters → Models
32
- - Express/NestJS: Routes/Controllers Services Repositories Models
33
- - Next.js: Pages → Components → Hooks → API Routes → Services
34
- - Django: Views → Serializers → Services → Models
35
- - Spring Boot: ControllersServicesRepositoriesEntities
36
- - Go: HandlersServicesRepositories → Models
37
- - Generic: Group by directory responsibility
30
+ Both layouts use this value — dagre places higher layers lower on screen, concentric places them at the center.
31
+
32
+ **Reference mappings** (layer numbers in parentheses adapt to actual project structure):
33
+
34
+ MVC / Layered:
35
+ - Laravel: External(0)Controllers(1)Services(2)Models(3)
36
+ - Rails: External(0)Controllers(1)Services(2) → Models(3)
37
+ - Django: External(0) Views(1) → Serializers(2) → Services(3) → Models(4)
38
+ - Spring Boot: External(0) → Controllers(1) → Services(2) → Repositories(3) → Entities(4)
39
+ - NestJS: External(0) → Controllers(1) → Services(2) → Repositories(3) → Entities(4)
40
+ - Next.js App Router: External(0) → Route Handlers/Pages(1) → Components(2) → Hooks/Services(3) → Data Access(4)
41
+ - FastAPI: External(0) → Routers(1) → Services(2) → Repositories(3) → Models(4)
42
+
43
+ DDD / Clean Architecture / Hexagonal (use `"layout": "concentric"`):
44
+ - Generic: External(0) → Adapters(1) → Controllers(2) → Application Services(3) → Ports(4) → Domain Entities(5)
45
+ - Go (Hex): External(0) → Handlers(1) → Adapters(2) → Use Cases(3) → Ports(4) → Domain(5)
46
+ - Flutter (Clean): External(0) → Data Sources(1) → Repositories(2) → Use Cases(3) → Entities(4)
47
+
48
+ Serverless / Microservices:
49
+ - SST/Lambda: External(0) → API Gateway(1) → Lambda Handlers(2) → Services(3) → Domain(4)
50
+ - Microservices: External(0) → Gateway/BFF(1) → Service Boundaries(2) → Internal Services(3) → Shared Domain(4)
51
+
52
+ For unlisted frameworks: group by directory responsibility and apply the abstract rule above.
38
53
 
39
54
  ## Phase 4: Read Key Files
40
55
  For each layer, read representative files to extract:
@@ -115,11 +130,11 @@ After writing the file:
115
130
 
116
131
  ### Node Rules
117
132
  - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, ext-, job-, dto-)
118
- - `layer`: integer indicating architectural depth (higher = closer to domain core). Concentric layout places high values at center. Example: 0=external, 1=adapters/infrastructure, 2=controllers/entry points, 3=application services, 4=ports/abstractions, 5=domain models/entities
133
+ - `layer`: non-negative integer. **Higher = closer to domain core / more stable. Lower = closer to external world / more volatile.** Dagre (TB) places higher layers lower on screen; concentric places them at center. Use as many layers as the architecture requires (typically 3-6). Example for DDD: 0=external, 1=adapters, 2=controllers, 3=app services, 4=ports, 5=domain entities. Example for MVC: 0=external, 1=controllers, 2=services, 3=models.
119
134
  - `category`: one of controller, service, port, adapter, model, external, job, dto (or custom)
120
135
  - `label`: display name for the node
121
136
  - `filePath`: relative from project root
122
- - `depth` (optional): 0=overview (boundary), 1=structure (internal), 2=detail (implementation). Auto-inferred from category if omitted
137
+ - `depth` (optional): 0=overview, 1=structure, 2=detail. Auto-inferred from `layer` if omitted: with 3+ unique layers, lowest → 0, middle → 1, highest → 2. With 1-2 layers, all nodes get depth 0 (always visible).
123
138
  - `useCases`: array of use case IDs this node participates in
124
139
 
125
140
  ### Edge Rules
@@ -9,6 +9,7 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
+ "@dagrejs/dagre": "^1.1.4",
12
13
  "@xyflow/react": "^12.10.0",
13
14
  "nuqs": "^2.8.8",
14
15
  "react": "^19.2.0",
@@ -14,6 +14,7 @@ import '@xyflow/react/dist/style.css';
14
14
  import type { ArchFlowNode, ArchNodeData } from './types.ts';
15
15
  import { getCategoryColors } from './types.ts';
16
16
  import { ArchNode } from './components/nodes/ArchNode.tsx';
17
+ import { GroupNode } from './components/nodes/GroupNode.tsx';
17
18
  import { DetailPanel } from './components/DetailPanel.tsx';
18
19
  import { UseCaseFilter } from './components/UseCaseFilter.tsx';
19
20
  import { DepthFilter } from './components/DepthFilter.tsx';
@@ -24,11 +25,11 @@ import { useDepthFilter } from './hooks/useDepthFilter.ts';
24
25
  import { useUseCaseFilter } from './hooks/useUseCaseFilter.ts';
25
26
  import { useTheme } from './hooks/useTheme.ts';
26
27
 
27
- const nodeTypes = { archNode: ArchNode };
28
+ const nodeTypes = { archNode: ArchNode, groupNode: GroupNode };
28
29
 
29
30
  function AppInner() {
30
- const { nodes, edges, useCases, projectName, loading, error, onNodesChange, onEdgesChange } = useArchitecture();
31
- const { depthLevel, setDepthLevel, visibleNodes, visibleEdges } = useDepthFilter(nodes, edges);
31
+ const { nodes, edges, useCases, projectName, layoutType, loading, error, onNodesChange, onEdgesChange } = useArchitecture();
32
+ const { depthLevel, setDepthLevel, visibleNodes, visibleEdges } = useDepthFilter(nodes, edges, layoutType);
32
33
  const { selectedUseCase, setSelectedUseCase, categories, filteredNodes, filteredEdges } = useUseCaseFilter(visibleNodes, visibleEdges, useCases);
33
34
  const [selectedNodeId, setSelectedNodeId] = useQueryState('node', parseAsString.withOptions({ history: 'replace' }));
34
35
  const { theme, toggleTheme } = useTheme();
@@ -36,9 +37,9 @@ function AppInner() {
36
37
 
37
38
  const selectedNodeData: ArchNodeData | null = useMemo(() => {
38
39
  if (!selectedNodeId) return null;
39
- const found = nodes.find((n) => n.id === selectedNodeId);
40
+ const found = visibleNodes.find((n) => n.id === selectedNodeId);
40
41
  return found?.data ?? null;
41
- }, [selectedNodeId, nodes]);
42
+ }, [selectedNodeId, visibleNodes]);
42
43
 
43
44
  const onNodeClick: NodeMouseHandler<ArchFlowNode> = useCallback((_event, node) => {
44
45
  void setSelectedNodeId(node.id);