hexwright 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +339 -0
- package/dist/chunk-ZXMDA7VB.js +16 -0
- package/dist/cli.js +2223 -0
- package/dist/client.js +339 -0
- package/dist/main-CUYP5EVX.js +2506 -0
- package/package.json +69 -0
- package/profiles/hexagonal-kotlin.yml +80 -0
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hexwright",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Design graph for hexagonal-architecture codebases. Renders what a branch changed as one picture a human can confirm at a glance, and gives a coding agent boundary verdicts it can run on itself before asking for review.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"hexagonal-architecture",
|
|
7
|
+
"ports-and-adapters",
|
|
8
|
+
"architecture",
|
|
9
|
+
"dependency-graph",
|
|
10
|
+
"static-analysis",
|
|
11
|
+
"kotlin",
|
|
12
|
+
"spring-boot",
|
|
13
|
+
"code-review",
|
|
14
|
+
"human-in-the-loop",
|
|
15
|
+
"coding-agent",
|
|
16
|
+
"mcp",
|
|
17
|
+
"mcp-server",
|
|
18
|
+
"visualization",
|
|
19
|
+
"svg"
|
|
20
|
+
],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=22"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/vonkernel/hexwright.git"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/vonkernel/hexwright#readme",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/vonkernel/hexwright/issues"
|
|
33
|
+
},
|
|
34
|
+
"bin": {
|
|
35
|
+
"hexwright": "./dist/cli.js"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"profiles"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"dev": "node --watch src/cli.ts",
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"lint": "biome check .",
|
|
47
|
+
"prepublishOnly": "npm run build && npm run typecheck"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
51
|
+
"cytoscape": "^3.34.0",
|
|
52
|
+
"cytoscape-fcose": "^2.2.0",
|
|
53
|
+
"yaml": "^2.6.0",
|
|
54
|
+
"zod": "^4.4.3"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@biomejs/biome": "^1.9.4",
|
|
58
|
+
"@types/cytoscape": "^3.21.9",
|
|
59
|
+
"@types/node": "^22.10.0",
|
|
60
|
+
"@xmldom/xmldom": "^0.9.10",
|
|
61
|
+
"esbuild": "^0.28.1",
|
|
62
|
+
"tsup": "^8.3.5",
|
|
63
|
+
"typescript": "^5.7.2",
|
|
64
|
+
"vitest": "^2.1.8"
|
|
65
|
+
},
|
|
66
|
+
"optionalDependencies": {
|
|
67
|
+
"@resvg/resvg-js": "^2.6.2"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Hexagonal architecture, domain-first (package-by-feature).
|
|
2
|
+
#
|
|
3
|
+
# The top level is a bounded context, not a layer; the three layers repeat inside each domain.
|
|
4
|
+
# Another project only has to swap this file — port/in vs port/inbound,
|
|
5
|
+
# infrastructure vs adapter, and so on are all absorbed here.
|
|
6
|
+
name: hexagonal-kotlin
|
|
7
|
+
language: kotlin
|
|
8
|
+
|
|
9
|
+
domain:
|
|
10
|
+
# What identifies a domain. package = a package segment.
|
|
11
|
+
from: package
|
|
12
|
+
# Strip this prefix first
|
|
13
|
+
base: "" # injected by --base-package. empty = infer the common prefix
|
|
14
|
+
# which segment is the domain (0-based, after the prefix is stripped)
|
|
15
|
+
at: 0
|
|
16
|
+
|
|
17
|
+
# Path fragments to exclude from analysis
|
|
18
|
+
exclude:
|
|
19
|
+
- /config/
|
|
20
|
+
- /test/
|
|
21
|
+
- /generated/
|
|
22
|
+
|
|
23
|
+
# Layers — decided by path fragment. First match from the top wins.
|
|
24
|
+
layers:
|
|
25
|
+
adapter: /adapter/
|
|
26
|
+
application: /application/
|
|
27
|
+
domain: /domain/
|
|
28
|
+
common: /common/
|
|
29
|
+
|
|
30
|
+
# Subdivisions within a layer
|
|
31
|
+
sublayers:
|
|
32
|
+
port/inbound: /application/port/inbound/
|
|
33
|
+
port/out: /application/port/out/
|
|
34
|
+
service: /application/service/
|
|
35
|
+
security: /application/security/
|
|
36
|
+
model: /domain/model/
|
|
37
|
+
event: /domain/event/
|
|
38
|
+
|
|
39
|
+
# Adapter direction — only outbound may touch an aggregate
|
|
40
|
+
adapterKinds:
|
|
41
|
+
out: /adapter/out/
|
|
42
|
+
in: /adapter/web/
|
|
43
|
+
event: /adapter/event/
|
|
44
|
+
|
|
45
|
+
# Component classification. First matching rule from the top wins.
|
|
46
|
+
# nameEnds is an exception applied before layer, regardless of it.
|
|
47
|
+
components:
|
|
48
|
+
- { nameEnds: Exception, as: Error }
|
|
49
|
+
- { layer: common, as: Shared }
|
|
50
|
+
- { layer: adapter, as: Adapter }
|
|
51
|
+
- { sublayer: model, kinds: [value class], as: VO }
|
|
52
|
+
- { sublayer: model, kinds: [enum class], as: VO }
|
|
53
|
+
- { sublayer: model, kinds: [data class], as: VO }
|
|
54
|
+
- { sublayer: model, as: Entity }
|
|
55
|
+
- { sublayer: event, as: Event }
|
|
56
|
+
- { sublayer: security, as: Service }
|
|
57
|
+
- { sublayer: service, kinds: [data class], as: Shared }
|
|
58
|
+
- { sublayer: service, nameEnds: Properties, as: Shared }
|
|
59
|
+
- { sublayer: service, as: Service }
|
|
60
|
+
- { sublayer: port/inbound, structs: [interface], as: UseCase }
|
|
61
|
+
- { sublayer: port/inbound, as: DTO }
|
|
62
|
+
- { sublayer: port/out, structs: [interface], as: Port }
|
|
63
|
+
- { sublayer: port/out, as: DTO }
|
|
64
|
+
- { nameEnds: Id, as: VO } # identifiers filed under the wrong layer
|
|
65
|
+
- { kinds: [enum class], as: VO }
|
|
66
|
+
- { as: DTO } # everything else
|
|
67
|
+
|
|
68
|
+
# Design rules
|
|
69
|
+
rules:
|
|
70
|
+
# What may touch an Entity — within the same domain
|
|
71
|
+
entityAccess:
|
|
72
|
+
allow: [Service, Port, Entity]
|
|
73
|
+
# outbound adapters too: port implementations have to map aggregates
|
|
74
|
+
allowAdapterKinds: [out]
|
|
75
|
+
crossDomain: deny
|
|
76
|
+
# No back-reference from the core to an adapter
|
|
77
|
+
layering:
|
|
78
|
+
- from: [application, domain]
|
|
79
|
+
to: [adapter]
|
|
80
|
+
message: layer back-reference
|