Skip to content

Commit 7c2edb0

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

4 files changed

Lines changed: 187 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: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ 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:
38+
~w(lib .formatter.exs mix.exs README.md LICENSE CHANGELOG.md usage-rules.md documentation)
3839
]
3940
end
4041

@@ -43,7 +44,7 @@ defmodule DurableObject.MixProject do
4344
main: "readme",
4445
source_ref: "v#{@version}",
4546
source_url: @source_url,
46-
extras: ["README.md", "guides/lifecycle.md", "guides/testing.md", "CHANGELOG.md", "LICENSE"],
47+
extras: extras(),
4748
before_closing_body_tag: fn type ->
4849
if type == :html do
4950
"""
@@ -57,18 +58,54 @@ defmodule DurableObject.MixProject do
5758
"""
5859
end
5960
end,
60-
groups_for_extras: [
61-
Guides: ~r/guides\/.*/
62-
],
61+
groups_for_extras: groups_for_extras(),
62+
groups_for_modules: groups_for_modules(),
6363
nest_modules_by_prefix: [
6464
DurableObject.Cluster,
6565
DurableObject.Dsl,
6666
DurableObject.Scheduler,
6767
DurableObject.Storage
68+
],
69+
spark: [
70+
mix_tasks: [
71+
Formatting: [
72+
Mix.Tasks.Spark.Formatter
73+
]
74+
]
6875
]
6976
]
7077
end
7178

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

83120
defp aliases do
84121
[
85-
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"]
122+
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
123+
docs: [
124+
"spark.cheat_sheets",
125+
"docs",
126+
"spark.replace_doc_links"
127+
],
128+
"spark.cheat_sheets": "spark.cheat_sheets --extensions DurableObject.Dsl.Extension",
129+
"spark.formatter": "spark.formatter --extensions DurableObject.Dsl.Extension"
86130
]
87131
end
88132

0 commit comments

Comments
 (0)