Skip to content

Commit 17c9d4b

Browse files
Add Spark DSL documentation generation
Set up automatic DSL reference docs via spark.cheat_sheets, chain the docs alias through cheat_sheets → docs → replace_doc_links, and add a CI step to fail when the checked-in cheat sheets are stale.
1 parent a67a082 commit 17c9d4b

4 files changed

Lines changed: 186 additions & 6 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ jobs:
4747
- name: Compile with warnings as errors
4848
run: mix compile --warnings-as-errors
4949

50+
- name: Check DSL documentation is up-to-date
51+
env:
52+
MIX_ENV: dev
53+
run: mix spark.cheat_sheets --check
54+
5055
- name: Run tests
5156
run: mix test
5257

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Auto-generated DSL reference documentation via `mix spark.cheat_sheets`
13+
- `mix docs` alias now chains `spark.cheat_sheets``docs``spark.replace_doc_links`
14+
- CI check to verify DSL documentation is up-to-date (`mix spark.cheat_sheets --check`)
15+
1016
### Changed
1117

1218
- State is now returned as a struct (`%MyApp.Counter.State{count: 0}`) instead of a plain atom-keyed map (`%{count: 0}`)
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<!--
2+
This file was generated by Spark. Do not edit it by hand.
3+
-->
4+
# DurableObject.Dsl.Extension
5+
6+
Spark DSL extension defining the structure for Durable Objects.
7+
8+
This extension provides three sections:
9+
10+
- `state` - Define state fields
11+
- `handlers` - Define RPC handlers
12+
- `options` - Configure lifecycle options
13+
14+
15+
## state
16+
Define the state fields for this Durable Object
17+
18+
### Nested DSLs
19+
* [field](#state-field)
20+
21+
22+
23+
24+
25+
### state.field
26+
```elixir
27+
field name, type
28+
```
29+
30+
31+
A field in the Durable Object's state
32+
33+
34+
35+
36+
37+
### Arguments
38+
39+
| Name | Type | Default | Docs |
40+
|------|------|---------|------|
41+
| [`name`](#state-field-name){: #state-field-name .spark-required} | `atom` | | The name of the field |
42+
| [`type`](#state-field-type){: #state-field-type .spark-required} | `atom` | | The type of the field (for documentation) |
43+
### Options
44+
45+
| Name | Type | Default | Docs |
46+
|------|------|---------|------|
47+
| [`default`](#state-field-default){: #state-field-default } | `any` | | The default value for the field |
48+
49+
50+
51+
52+
53+
### Introspection
54+
55+
Target: `DurableObject.Dsl.Field`
56+
57+
58+
59+
60+
## handlers
61+
Define the handlers (RPC methods) for this Durable Object
62+
63+
### Nested DSLs
64+
* [handler](#handlers-handler)
65+
66+
67+
68+
69+
70+
### handlers.handler
71+
```elixir
72+
handler name
73+
```
74+
75+
76+
An RPC handler for the Durable Object
77+
78+
79+
80+
81+
82+
### Arguments
83+
84+
| Name | Type | Default | Docs |
85+
|------|------|---------|------|
86+
| [`name`](#handlers-handler-name){: #handlers-handler-name .spark-required} | `atom` | | The name of the handler |
87+
### Options
88+
89+
| Name | Type | Default | Docs |
90+
|------|------|---------|------|
91+
| [`args`](#handlers-handler-args){: #handlers-handler-args } | `list(atom)` | `[]` | List of argument names for the handler |
92+
93+
94+
95+
96+
97+
### Introspection
98+
99+
Target: `DurableObject.Dsl.Handler`
100+
101+
102+
103+
104+
## options
105+
Configure lifecycle options
106+
107+
108+
109+
110+
111+
112+
### Options
113+
114+
| Name | Type | Default | Docs |
115+
|------|------|---------|------|
116+
| [`hibernate_after`](#options-hibernate_after){: #options-hibernate_after } | `pos_integer \| :infinity` | `300000` | Hibernate process after this many ms of inactivity (default: 5 minutes) |
117+
| [`shutdown_after`](#options-shutdown_after){: #options-shutdown_after } | `pos_integer \| :infinity \| nil` | | Stop process after this many ms of inactivity (nil = never) |
118+
| [`object_keys`](#options-object_keys){: #options-object_keys } | `:strings \| :atoms! \| :atoms` | | How to convert string keys within field values when loading from JSON. :strings (default, no conversion), :atoms! (existing atoms only, raises otherwise), :atoms (creates atoms if needed). |
119+
120+
121+
122+
123+
124+
125+
126+
<style type="text/css">.spark-required::after { content: "*"; color: red !important; }</style>

mix.exs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ defmodule DurableObject.MixProject do
3434
links: %{
3535
"GitHub" => @source_url
3636
},
37-
files: ~w(lib .formatter.exs mix.exs README.md LICENSE CHANGELOG.md usage-rules.md)
37+
files: ~w(lib .formatter.exs mix.exs README.md LICENSE CHANGELOG.md usage-rules.md documentation)
3838
]
3939
end
4040

@@ -43,7 +43,7 @@ defmodule DurableObject.MixProject do
4343
main: "readme",
4444
source_ref: "v#{@version}",
4545
source_url: @source_url,
46-
extras: ["README.md", "guides/lifecycle.md", "guides/testing.md", "CHANGELOG.md", "LICENSE"],
46+
extras: extras(),
4747
before_closing_body_tag: fn type ->
4848
if type == :html do
4949
"""
@@ -57,18 +57,54 @@ defmodule DurableObject.MixProject do
5757
"""
5858
end
5959
end,
60-
groups_for_extras: [
61-
Guides: ~r/guides\/.*/
62-
],
60+
groups_for_extras: groups_for_extras(),
61+
groups_for_modules: groups_for_modules(),
6362
nest_modules_by_prefix: [
6463
DurableObject.Cluster,
6564
DurableObject.Dsl,
6665
DurableObject.Scheduler,
6766
DurableObject.Storage
67+
],
68+
spark: [
69+
mix_tasks: [
70+
Formatting: [
71+
Mix.Tasks.Spark.Formatter
72+
]
73+
]
6874
]
6975
]
7076
end
7177

78+
defp extras do
79+
[
80+
"README.md",
81+
"guides/lifecycle.md",
82+
"guides/testing.md",
83+
"CHANGELOG.md",
84+
"LICENSE"
85+
] ++ Path.wildcard("documentation/**/*.md")
86+
end
87+
88+
defp groups_for_extras do
89+
[
90+
Guides: ~r/guides\/.*/,
91+
"DSL Reference": ~r/documentation\/dsls\/.*/
92+
]
93+
end
94+
95+
defp groups_for_modules do
96+
[
97+
"DSL & Core": [
98+
DurableObject,
99+
DurableObject.Dsl,
100+
DurableObject.Dsl.Extension
101+
],
102+
Storage: ~r/DurableObject\.Storage.*/,
103+
Scheduling: ~r/DurableObject\.Scheduler.*/,
104+
Internals: ~r/.*/
105+
]
106+
end
107+
72108
# Run "mix help compile.app" to learn about applications.
73109
def application do
74110
[
@@ -82,7 +118,14 @@ defmodule DurableObject.MixProject do
82118

83119
defp aliases do
84120
[
85-
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"]
121+
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
122+
docs: [
123+
"spark.cheat_sheets",
124+
"docs",
125+
"spark.replace_doc_links"
126+
],
127+
"spark.cheat_sheets": "spark.cheat_sheets --extensions DurableObject.Dsl.Extension",
128+
"spark.formatter": "spark.formatter --extensions DurableObject.Dsl.Extension"
86129
]
87130
end
88131

0 commit comments

Comments
 (0)