Skip to content

Commit 41d8c29

Browse files
committed
Add additional documentation and cleanup
- Ensure autogenerated API documentation is linted - Fix favicon light/dark theme preference colouring - Add a doc section on general middleware usage
1 parent 3c88509 commit 41d8c29

File tree

6 files changed

+196
-50
lines changed

6 files changed

+196
-50
lines changed

.github/workflows/deploy.yml

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,50 @@
1-
name: Deploy to GitHub Pages
1+
name: "Deploy to GitHub Pages"
22

33
on:
44
push:
5-
branches: [ main ]
5+
branches: [ "main" ]
66
workflow_dispatch:
77

88
permissions:
9-
contents: read
10-
pages: write
11-
id-token: write
9+
contents: "read"
10+
pages: "write"
11+
id-token: "write"
1212

1313
jobs:
1414
build:
15-
runs-on: ubuntu-latest
15+
runs-on: "ubuntu-latest"
1616
steps:
17-
- name: Checkout
18-
uses: actions/checkout@v4
19-
- name: Install Nix
20-
uses: DeterminateSystems/nix-installer-action@main
21-
- name: Connect Magic Nix Cache
22-
uses: DeterminateSystems/flakehub-cache-action@main
23-
- name: Install Dependencies
24-
run: nix develop --command pnpm install
25-
- name: Generate API Documentation
26-
run: nix develop --command pnpm run docgen
27-
- name: Build
28-
uses: withastro/action@v3
17+
- name: "Checkout"
18+
uses: "actions/checkout@v4"
19+
- name: "Install Nix"
20+
uses: "DeterminateSystems/nix-installer-action@main"
21+
- name: "Connect Magic Nix Cache"
22+
uses: "DeterminateSystems/flakehub-cache-action@main"
23+
- name: "Install Dependencies"
24+
run: "nix develop --command pnpm install"
25+
- name: "Generate API Documentation"
26+
run: "nix develop --command pnpm run docgen"
27+
- name: "[DOCS] Install Dependencies"
28+
run: "nix develop --command pnpm install"
29+
working-directory: "./docs"
30+
- name: "[DOCS] Lint Generated Code"
31+
run: "nix develop --command pnpm lint:fix"
32+
working-directory: "./docs"
33+
continue-on-error: true
34+
- name: "Build"
35+
uses: "withastro/action@v3"
2936
with:
30-
path: ./docs
37+
path: "./docs"
3138
node-version: 20
32-
package-manager: pnpm@latest
39+
package-manager: "pnpm@latest"
3340

3441
deploy:
35-
needs: build
36-
runs-on: ubuntu-latest
42+
needs: "build"
43+
runs-on: "ubuntu-latest"
3744
environment:
38-
name: github-pages
39-
url: ${{ steps.deployment.outputs.page_url }}
45+
name: "github-pages"
46+
url: "${{ steps.deployment.outputs.page_url }}"
4047
steps:
41-
- name: Deploy to GitHub Pages
42-
id: deployment
43-
uses: actions/deploy-pages@v4
48+
- name: "Deploy to GitHub Pages"
49+
id: "deployment"
50+
uses: "actions/deploy-pages@v4"

docs/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
"type": "module",
44
"version": "0.0.1",
55
"scripts": {
6-
"dev": "astro dev",
7-
"start": "astro dev",
6+
"astro": "astro",
87
"build": "astro build",
8+
"dev": "astro dev",
9+
"lint": "eslint 'src/content/docs/**/*.md'",
10+
"lint:fix": "eslint --fix 'src/content/docs/**/*.md'",
911
"preview": "astro preview",
10-
"lint": "eslint --fix 'src/content/docs/**/*.md'",
11-
"astro": "astro"
12+
"start": "astro dev"
1213
},
1314
"dependencies": {
1415
"@astrojs/starlight": "^0.30.2",

docs/public/favicon.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/content/docs/docs/getting-started/middleware-usage.md

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,153 @@ title: Middleware Usage
33
description: An introductory guide to Redux Sonnet middleware usage with Redux.
44
---
55

6-
## Defining Sonnets
6+
## Declaring Side-effects
77

8-
## Deciding Data Structures
8+
`Sonnet`s immediately execute the provided root `Stanza` in a forking manner.
9+
`Stanza`s must be declared as part of `Sonnet` instantiation.
10+
11+
```ts twoslash
12+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
13+
/// <reference types="effect" />
14+
/// <reference types="redux" />
15+
// @paths: {"redux-sonnet": ["../packages/redux-sonnet/src"], "redux-sonnet/*": ["../packages/redux-sonnet/src/*"]}
16+
// ---cut---
17+
import { Effect } from "effect"
18+
import { Sonnet } from "redux-sonnet"
19+
20+
declare const initialize: Effect.Effect<void>
21+
declare const watchThingOne: Effect.Effect<void>
22+
declare const watchThingTwo: Effect.Effect<void>
23+
24+
/**
25+
* Run `initialize` first, and then run `watchThingOne` and `watchThingTwo`
26+
* concurrently.
27+
*/
28+
const rootStanza = initialize.pipe(
29+
Effect.andThen(() =>
30+
Effect.all([
31+
watchThingOne,
32+
watchThingTwo
33+
], {
34+
discard: true,
35+
concurrency: "unbounded"
36+
})
37+
)
38+
)
39+
40+
// @errors: 2345
41+
const sonnet = Sonnet.make(
42+
rootStanza,
43+
Sonnet.defaultLayer
44+
)
45+
```
46+
47+
## Deciding Data Structures
48+
49+
`Sonnet`s accept a [`Layer`][layer] which describes the data structures used to
50+
communicate between side-effect declarations (`Stanza`s) and the Redux dispatcher.
51+
52+
Data structures are modeled as such:
53+
* Actions -- A [`Queue`][queue] which has configurable capacity and bounding behaviors.
54+
* Reducer State -- A [`SynchronizedRef`][synchronizedref] which has current
55+
value exposed as well as a `Stream` of its changes over time.
56+
* Dispatch Actions -- An unbounded `Queue`.
57+
<sup>* this needs consideration</sup>
58+
### Default
59+
60+
```ts twoslash {3}
61+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
62+
/// <reference types="effect" />
63+
/// <reference types="redux" />
64+
// @paths: {"redux-sonnet": ["../packages/redux-sonnet/src"], "redux-sonnet/*": ["../packages/redux-sonnet/src/*"]}
65+
import { Effect } from "effect"
66+
import { Sonnet } from "redux-sonnet"
67+
// ---cut---
68+
// @errors: 2345
69+
const sonnet = Sonnet.make(
70+
Effect.void,
71+
Sonnet.defaultLayer
72+
// ^?
73+
)
74+
```
75+
76+
### Configurable
77+
78+
```ts twoslash {3-9}
79+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
80+
/// <reference types="effect" />
81+
/// <reference types="redux" />
82+
// @paths: {"redux-sonnet": ["../packages/redux-sonnet/src"], "redux-sonnet/*": ["../packages/redux-sonnet/src/*"]}
83+
import { Effect } from "effect"
84+
import { Sonnet } from "redux-sonnet"
85+
// ---cut---
86+
// @errors: 2345
87+
const sonnet = Sonnet.make(
88+
Effect.void,
89+
Sonnet.layer({
90+
replay: 8,
91+
// ^?
92+
backing: {
93+
// ^?
94+
strategy: "bounded",
95+
capacity: 8
96+
}
97+
})
98+
)
99+
```
100+
101+
### Advanced
102+
103+
Any Effect service which satisfies `Sonnet.Service` may be constructed manually.
104+
105+
See [`Sonnet.Service`][sonnet.service] for reference.
106+
107+
## Adding to Redux
108+
109+
### With `@reduxjs/toolkit`
110+
```ts twoslash
111+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
112+
/// <reference types="effect" />
113+
/// <reference types="@reduxjs/toolkit" />
114+
// @paths: {"redux-sonnet": ["../packages/redux-sonnet/src"], "redux-sonnet/*": ["../packages/redux-sonnet/src/*"]}
115+
import { configureStore, Tuple } from "@reduxjs/toolkit"
116+
import { Effect } from "effect"
117+
import { Sonnet } from "redux-sonnet"
118+
// ---cut---
119+
const sonnet = Sonnet.make(
120+
Effect.void,
121+
Sonnet.defaultLayer
122+
)
123+
124+
// @errors: 2345
125+
const store = configureStore({
126+
// ^?
127+
reducer: () => {},
128+
middleware: () => new Tuple(sonnet)
129+
})
130+
```
131+
132+
### With `redux`
133+
```ts twoslash
134+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
135+
/// <reference types="effect" />
136+
/// <reference types="redux" />
137+
// @paths: {"redux-sonnet": ["../packages/redux-sonnet/src"], "redux-sonnet/*": ["../packages/redux-sonnet/src/*"]}
138+
import { Effect } from "effect"
139+
import { applyMiddleware, createStore } from "redux"
140+
import { Sonnet } from "redux-sonnet"
141+
// ---cut---
142+
const sonnet = Sonnet.make(
143+
Effect.void,
144+
Sonnet.defaultLayer
145+
)
146+
147+
// @errors: 2345
148+
const store = applyMiddleware(sonnet)(createStore)(() => {})
149+
// ^?
150+
```
151+
152+
[queue]: https://effect.website/docs/concurrency/queue/
153+
[synchronizedref]: https://effect.website/docs/state-management/synchronizedref/
154+
[layer]: https://effect.website/docs/requirements-management/layers
155+
[sonnet.service]: /redux-sonnet/api/redux-sonnet/sonnetts/#service-interface

docs/src/content/docs/docs/getting-started/why-redux-sonnet.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,4 @@ description: Discover how Redux Sonnet provides a superior development experienc
44
---
55

66
Redux Sonnet is born from the desire to fortify proven, existing side-effect
7-
management patterns with the [Effect](https://efffect.website) ecosystem.
8-
9-
#
7+
management patterns with the [Effect](https://efffect.website) ecosystem.

packages/redux-sonnet/src/internal/sonnet.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,10 @@ export const makeService = (
223223
* Takes incoming actions from Redux
224224
*/
225225
const actionQueue = yield* Queue[queue.strategy]<Action>(capacity as any)
226-
const dispatchQueue = yield* Queue[queue.strategy]<Take.Take<Action>>(
227-
capacity as any
228-
)
226+
/**
227+
* Dispatches actions from `Stanzas`
228+
*/
229+
const dispatchQueue = yield* Queue.unbounded<Take.Take<Action>>()
229230

230231
/**
231232
* Takes incoming state from Reudx on each new action.
@@ -234,22 +235,14 @@ export const makeService = (
234235

235236
const changes = yield* pipe(
236237
stateRef.changes,
237-
// Stream.share({
238-
// capacity: capacity ?? "unbounded",
239-
// replay: options.replay
240-
// })
241-
Stream.broadcastDynamic({ capacity: "unbounded" })
238+
Stream.broadcastDynamic({ capacity: "unbounded", replay: options.replay })
242239
)
243240

244241
const latest = Stream.fromEffect(Ref.get(stateRef))
245242

246243
const action$ = yield* pipe(
247244
Stream.fromQueue(actionQueue, {}),
248-
// Stream.share({
249-
// capacity: "unbounded",
250-
// replay: options.replay
251-
// })
252-
Stream.broadcastDynamic({ capacity: "unbounded" })
245+
Stream.broadcastDynamic({ capacity: "unbounded", replay: options.replay })
253246
)
254247

255248
const dispatch$ = Stream.fromQueue(dispatchQueue)

0 commit comments

Comments
 (0)