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/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