domain-schema-documentation can be used to document the domain schema of an application. The domain model must be defined as JSON Schema, and domain-schema-documentation can then
- Generate HTML or Markdown documentation. This can easily be integrated into GitHub-Pages or similar to automatically document your domain model.
- Generate Java or TypeScript stubs as well as OpenAPI specifications.
- Check existing implementations for compliance with the domain model to ensure that the implementation is up-to-date with the domain model.
domain-schema-documentation can easily be extended to support additional languages or formats.
domain-schema-documentation can either be used as a command line tool or as a node.js package. While the command line tool is easy to use, the node.js package allows for more customization.
To use it as command line tool, you have to install it globally and then run against the domain model definition:
npm install -g domain-schema-documentation
npx domain-schema-documentation --html --input ./schema --output ./out
./schema
is you domain model (see Define the Input Model on how to define it) and ./out
is where the documentation is generated. Check domain-schema-documentation --help
to get a list of all available options. Check the Examples for a detailed setup.
To use domain-schema-documentation as a node.js package, you have to create your own node.js project and add domain-schema-documentation as a dependency. You can then generate documentation using the following code:
npm install domain-schema-documentation
import { run, defaultReader, htmlWriter } from 'domain-schema-documentation'
import * as path from 'path'
run({
reader: defaultReader('./schema'),
writers: [htmlWriter('./out')]
}).catch(console.error)
./schema
is you domain model (see Define the Input Model on how to define it) and ./out
is where the documentation is generated. Check RunOptions for a list of all available options. Check the Examples for a detailed setup.
By default, the input model is read from the folder ./input
. It consists of the following parts:
- A top level
index.yaml
file containing the Application Description. This file can contain the following fields (see also its Json Schema Definition):- The
title
of the application (required) - A
description
(required) - A list of
links
to other parts of the documentation (optional) - A list of
todos
that are still open in the domain model (optional)
- The
- For each module in the application a folder with an
index.yaml
file containing the Module Description. This file can contain the following fields (see also its Json Schema Definition):- The
$id
of the module, must be the name of the folder (required) - The
title
of the module (required) - A
description
(required) - A list of
links
to other parts of the documentation (optional) - A list of
todos
that are still open in the domain model (optional)
- The
- For each type a JSON-Schema file containing the Type Description. The Schema-File must be in one of the module folders, and it's
$id
must be equal the filename. Schemas must be valid JSON Schemas. You can add your own additional extensions, but to avoid conflicts, they must be prefixed withx-
. Additionally, the following restrictions must be fulfilled (see also its Json Schema Definition):- Each schema must define a
title
and an$id
. The title must be a string. - Schemas must be either an enum (
type: string
and have a propertyenum
), an object (type: object
and have a propertyproperties
) or an interface (type: object
and have a list ofoneOf
). You cannot mix these types in one schema or have a basic type as top level schema. - Each Schema must have an
x-schema-type
ofAggregate
,Entity
,ValueObject
,ReferenceData
, orOther
. - A Schema can define
x-links
(a list of links to other parts of the documentation) andx-todos
(a list of todos that are still open in the domain model). - An enum schema can define a property
x-enum-description
documenting the enum values - Each basic property can define a
x-references
property that contains a list of references to other types in the domain model. This is usefull, if you store an ID of another type in a property and want to describe the referenced type. - The following JSON Schema Parts are not supported:
additionalItems
,maxProperties
,minProperties
,patternProperties
,propertyNames
,allOf
, andanyOf
. - For
type
andenum
only string values are supported.
- Each schema must define a
If you want to change how the model is read, you can define your own reader by implementing the Reader interface. You can pass the reader to be included to the run function.
run({ reader: yourreader}).catch(console.error)
By default, the DefaultReader is used.
Writers are used to generate the documentation. An HTML and a Markdown writer is already included, but you can also define your own writers. You can use multiple writers at the same time.
The HTML writer generates a documentation in HTML format. Internally, Handlebars is used to generate the HTML files. You can customize the output by passing your own Handlebar templates to the writer. See HtmlWriterOptions for a list of all available options.
On the command line, use --html
to enable the HTML writer. In the node.js package, you can use the htmlWriter function.
run({ writers: [htmlWriter('./output', options)]}).catch(console.error)
The markdown writer generates a documentation in Markdown format. Internally, Handlebars is used to generate the Markdown files. You can customize the output by passing your own Handlebar templates to the writer. See MarkdownWriterOptions for a list of all available options.
On the command line, use --md
to enable the Markdown writer. In the node.js package, you can use the markdownWriter function.
run({ writers: [htmlWriter('./output', options)]}).catch(console.error)
To create a custom writer, implement the Writer interface. You can then use this writer as following
run({ writers: [yourWriter]}).catch(console.error)
Plugins can
- Update and change the read domain model
- Generate stubs in different languages
- Check existing implementations for compliance with the domain model
A plugin for Java and OpenAPI is already included, but you can also define your own plugins. You can use multiple plugins at the same time.
The Java-Plugin can be added using
run({ plugins: [javaPlugin('./out')]}).catch(console.error)
It will then do two things:
- For each schema it will generate a Java class in the folder
./out/java
that represents the schema. Those file will be linked into the generated documentation. - If an implementation folder is configured, it will check the implementation against the domain model. It will check if all classes are present and if the properties are correct. If the implementation is not up-to-date, it will generate a list of errors that will be added to the documentation.
You can configure the Java Plugin by passing an JavaPluginOptions object to the plugin.
TBD
You can define your own plugin by implementing the Plugin interface. You can then use this writer as following
run({ plugins: [yourPlugin]}).catch(console.error)
In the folder example you can find a full example of how to use this package. The example contains a domain model defined in JSON Schema in the folder input, a configuration script at main.js and a package.json file defining the script generate
to run the example. In will generate HTML and Markdown documentation in the folder out as well as Java and TypeScript stubs. The documentation is automatically published to GitHub Pages using the GitHub Action defined in build.yaml.
The source code can be found in the lib/src folder. It is organized in the following parts:
- The plugin folder contains the plugin definitions as well as the default plugins for Java and OpenAPI.
- The reader folder container the input model reader
- The writer folder contains the writer definition as well as the default writers for HTML and Markdown
- The Run.ts file contains the main function to run the documentation generation, RunOptions.ts contains the options for the run function.
- The cli.js file contains the command line interface.
- The index.ts file exports all functions and classes.
Besides the lib, there are also subfolders for the example and the tests
The following commands can be handy during development:
-
yarn build
to build the project -
yarn test
to run the tests -
yarn lint
to lint the project -
yarn check
to run all checks and tests in the project -
yarn integration-tests
to run the integration tests -
yarn unit-tests
to run the unit tests -
yarn workspace example generate
to run the example -
yarn workspace example generate:watch
to run the example in watch mode
The GitHub Action Pipeline at .github/workflows/build.yaml is used to run the tests and checks on every push. After a merge to main, a new version is build and published to NPM. Make sure to increase the version number before merging to main!
This software uses the following open source packages:
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests and documentation as appropriate.
If you encounter any issues, please let me know by opening an issue.
Licenced under the MIT License