Skip to content

Architecture ​

Which module does what and how core is layered. The reasons are recorded in the Architecture Decisions; this page describes what is there.

Modules ​

Gradle modules (settings.gradle.kts):

ModuleWhat it isPublished to
bpmn-to-code-coreReads BPMN, validates, generates the Process API and the process JSONNot published. Its classes are packed into the Gradle plugin, Maven plugin and testing jars; the web app and the command-line tool depend on it directly.
bpmn-to-code-gradleGradle plugin io.miragon.bpmn-to-code-gradleGradle Plugin Portal
bpmn-to-code-mavenMaven plugin io.miragon:bpmn-to-code-maven (mojos written in Java)Maven Central
bpmn-to-code-runtimeDependency-free types the generated Kotlin and Java code refers to, plus ProcessPathMaven Central
bpmn-to-code-testingBpmnValidator, the test library for validation rulesMaven Central
bpmn-to-code-webKtor server with a static frontendDocker Hub (miragon/bpmn-to-code-web)
bpmn-to-code-cliCommand-line tool bpmn-to-code with the commands generate-api and validate; ./gradlew :bpmn-to-code-cli:cliArchive packs it with a jlink runtime for the current platformGitHub release assets, one zip per platform, and Homebrew miragon/tap/bpmn-to-code (experimental)
bpmn-to-code-architecture-testsKonsist tests that enforce the rules on this pageNot published
bpmn-to-code-benchmarkHand-run JMH comparison with a released version, see BenchmarkingNot published

Outside the Gradle build:

FolderWhat it is
bpmn-to-code-skillsClaude Code plugin for users of bpmn-to-code, installed through the marketplace manifest in .claude-plugin/
shared/bpmnThe MiraVelo BPMN models every module tests against, see Tests
toolsbpmnlint setup for those models
packages/nugetThe .NET tool Miragon.BpmnToCode (a C# launcher that starts the CLI jars on the installed Java), the C# runtime package Miragon.BpmnToCode.Runtime and the MSBuild integration Miragon.BpmnToCode.MSBuild, packed by publish-to-nuget.yml, and BpmnToCode.Runtime.Tests, which compiles generated C# against the runtime package
packages/npmThe npm package @miragon/bpmn-to-code with its launcher, which starts the CLI jars on the installed Java, and the TypeScript runtime package @miragon/bpmn-to-code-runtime with tests that type-check and run generated TypeScript against it, staged by publish-to-npm.yml
docsThis site

How the four output languages reach the JVM, .NET and Node: Languages and Ecosystems.

All published artifacts share one version, projectVersion in gradle.properties. Why core is embedded instead of published: ADR 001.

Layers of core ​

Core is a hexagon under io.miragon.bpmn. HexagonalArchitectureTest allows exactly these dependencies:

PackageHoldsMay depend on
domainProcess model, validation rules, domain servicesKotlin, Java, kotlin-logging, itself
application.port.inboundUse cases (…UseCase, …Query)domain
application.port.outboundPorts (…Port, …Repository)domain
application.serviceOne …Service per inbound portdomain, both port packages, adapter.outbound
adapter.outboundBPMN reading (engine), code generation (codegen), json, filesystemdomain, application.port.outbound
adapter.inboundThe …Plugin classes, one per use casedomain, application.port.inbound, application.service

There is no dependency-injection framework, hence these further rules:

  • A service or plugin takes its collaborators as constructor parameters typed as ports; the concrete implementation appears only as default value.
  • A service implements exactly one inbound port and does not call another service. That is why the filesystem and the in-memory variant of a use case are two services.
  • All ports are interfaces.

The other modules see core only through domain and adapter.inbound. ExternalModuleImportTest enforces that for the Gradle plugin, the Maven plugin, the web app and the command-line tool. domain is also what users compile custom validation rules against, so changes there are public API changes (ADR 011).

CodingGuidelinesTest adds two rules for every module: a file declares at most one top-level type, and a file that declares a type declares nothing else at top level.

Why it looks like this: ADR 002.