Exporting the repository as JSON
- Comparing
- v1 to v2
- Current
- Read the document
Abstract
A command that writes every document, its parsed sections, its resolved links and the relationships ArchDoc derives, as JSON conforming to a published schema, so a consumer renders or indexes the repository without reimplementing the front matter schema, the identifier rules or the repository walk.
Motivation
The index publishes the derived graph, as Markdown links inside table cells. A site that renders a specification has to reconstruct every relationship from those cells or from the documents, and has to parse Markdown to rewrite links into its own URL scheme. Both are the tool's own logic, duplicated by every consumer.
Proposal
Concepts
| Concept | Meaning |
|---|---|
| Export | The whole repository as one JSON object |
| Document | One RFC, ADR, spec page or ref, with its front matter, derived fields, sections, links and body |
| Section | One H2 and everything under it, keyed by anchor |
| Link | A relative Markdown link with what it resolves to |
| Term | One glossary entry as data |
| Schema | The JSON Schema the export conforms to, versioned by an integer |
Components
| Component | Responsibility |
|---|---|
internal/export |
The types, Build, and the embedded schema |
internal/export/schema.json |
The schema, embedded |
schema/export/v1.json |
The schema, published, generated from the embedded copy |
archdoc export |
Writes one document, a tree, or the schema |
The export
{
"schema": 1,
"name": "<archdoc.json name>",
"documents": [ ... ],
"glossary": [ ... ]
}
A document
| Field | Content |
|---|---|
type, id, number, page, path, title, status |
From discovery and front matter; id and number absent for a spec page, page absent otherwise, status absent where the type has none |
created, decided, backfilled, verified |
ISO 8601, each absent where unset |
depends, updates, obsoletes, includes |
As written |
updated_by, obsoleted_by, depended_on_by, included_in |
Derived, as ADR-0003 describes |
effectively_obsolete, implemented, stale |
Derived |
required_sections |
The sections the type calls for, in order, each as {title, anchor} |
sections |
An object keyed by anchor, each {title, body} |
body |
Raw Markdown |
links |
Each {text, destination, path, resolves_to, anchor, line} |
Rules
| Rule | Reason stated in the design |
|---|---|
sections is keyed by anchor |
A heading may repeat; the anchor walk numbers repeats, so nothing is lost |
| No section records a level | Every section is an H2 |
A required section may be absent from sections |
Lint checks them; a draft part-way through is the ordinary case. The anchor is still given |
Every array field is an array, never null |
A consumer handles one shape |
A link's path and resolves_to are absent for a destination with a URI scheme or a leading / |
It is not in the repository |
| Bodies are raw Markdown | There is no renderer, under ADR-0006 |
| The output records no generation time | It is deterministic, cacheable and diffable |
| The shape only ever gains optional fields | The principle of ADR-0004, applied to a second published shape |
The glossary
Emitted twice: as a spec page among the documents, and as glossary, an array of {name, anchor, definition, formerly}.
--out
<dir>/
├── index.json every document, without bodies
├── glossary.json when there is a glossary
└── <path>.json one per document, with bodies
index.json omits bodies whatever else was asked. Each document's file sits at its own path with .md replaced by .json.
--no-bodies
Omits body and every section's body, everywhere.
--schema
Prints the embedded schema and exits, without a repository.
The schema
Its $id is the URL of the published copy. A test compares the published copy against the embedded one byte for byte, and a test compares the schema's declared properties against the exported structs by reflection in both directions. Under ADR-0005 no validator is added, so the output is not validated against the schema; the reflection check catches a field added on one side and not the other.
Errors
| Condition | Result |
|---|---|
No repository, without --schema |
the usual not-found error |
--out names an unwritable directory |
the write error |
Out of scope
- Rendering Markdown to HTML. No renderer, and the consumer's sanitisation is the consumer's.
- Filtering by type or status.
jqover the single-document form does it, and--outgives a file per document. - Validating output against the schema. A validator is a dependency.
Alternatives considered
This design rests on ADR-0003, which is what makes the export worth having, on ADR-0004 as the compatibility rule for the shape, on ADR-0005, which rules out a validator, and on ADR-0006, which rules out rendering.
sectionskeyed by title. A repeated heading would overwrite one section with the other and nothing would notice.- A single JSON document only. A page rendering one RFC would fetch the whole specification.
--outgives a small index and a file per document.
No other alternatives were weighed.
Backwards compatibility
Nothing breaks. The command is new, and repo.Anchor is an addition.
Open questions
Changelog
Sources
- 72df287 adds the command, the package and the embedded schema, and sets
createdanddecided. - 285333b publishes the schema outside
internal/and addsdocs/EXPORT.md, on . docs/ARCHDOC.mdat 72df287a, sectionarchdoc export, describes the design.- The alternatives were weighed in a design session on , not publicly available, and first written down on .
Source rfc/0004-exporting-the-repository-as-json.md · commit fd11f56 · published