elm-ssr 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -342
- package/elm-src/ElmSsr/Island/Sse.elm +151 -0
- package/package.json +53 -24
- package/{packages/elm-ssr/src → src}/client-runtime/islands.ts +113 -15
- package/src/sse.ts +162 -0
- package/AGENTS.md +0 -289
- package/CHANGELOG.md +0 -87
- package/LICENSE +0 -21
- package/bun.lock +0 -259
- package/docker-compose.yml +0 -33
- package/docs/README.md +0 -51
- package/docs/backends.md +0 -146
- package/docs/cli.md +0 -117
- package/docs/effects.md +0 -91
- package/docs/getting-started.md +0 -94
- package/docs/islands.md +0 -197
- package/docs/loaders-and-actions.md +0 -241
- package/docs/middleware.md +0 -93
- package/docs/migrations.md +0 -143
- package/docs/routing.md +0 -108
- package/docs/sessions.md +0 -218
- package/docs/tasks.md +0 -149
- package/docs/testing.md +0 -84
- package/elm-ssr.config.json +0 -14
- package/examples/basic/elm.json +0 -27
- package/examples/basic/migrations/0001_guestbook.down.sql +0 -1
- package/examples/basic/migrations/0001_guestbook.sql +0 -10
- package/examples/basic/package.json +0 -10
- package/examples/basic/runtime.ts +0 -148
- package/examples/basic/src/Example/Basic/Islands/Counter.elm +0 -110
- package/examples/basic/src/Example/Basic/Islands/Observer.elm +0 -67
- package/examples/basic/src/Example/Basic/Islands/Tasks.elm +0 -151
- package/examples/basic/src/Example/Basic/Routes/Chart.elm +0 -87
- package/examples/basic/src/Example/Basic/Routes/Counter.elm +0 -42
- package/examples/basic/src/Example/Basic/Routes/Echo.elm +0 -76
- package/examples/basic/src/Example/Basic/Routes/Greet/Name_.elm +0 -37
- package/examples/basic/src/Example/Basic/Routes/Guestbook.elm +0 -86
- package/examples/basic/src/Example/Basic/Routes/Index.elm +0 -41
- package/examples/basic/src/Example/Basic/Routes/NotFound.elm +0 -37
- package/examples/basic/src/Example/Basic/Routes/Profile.elm +0 -112
- package/examples/basic/src/Example/Basic/Routes/Session.elm +0 -89
- package/examples/basic/src/Example/Basic/Routes/Status.elm +0 -90
- package/examples/basic/src/Example/Basic/View/Shared.elm +0 -60
- package/examples/basic/styles.ts +0 -204
- package/examples/basic/worker.ts +0 -3
- package/examples/crypto-dashboard/elm.json +0 -30
- package/examples/crypto-dashboard/package.json +0 -10
- package/examples/crypto-dashboard/runtime.ts +0 -97
- package/examples/crypto-dashboard/src/CryptoDashboard/Islands/MarketOverview.elm +0 -204
- package/examples/crypto-dashboard/src/CryptoDashboard/Islands/PriceChart.elm +0 -200
- package/examples/crypto-dashboard/src/CryptoDashboard/Routes/Index.elm +0 -67
- package/examples/crypto-dashboard/src/CryptoDashboard/Routes/NotFound.elm +0 -30
- package/examples/crypto-dashboard/src/CryptoDashboard/View/Shared.elm +0 -39
- package/examples/crypto-dashboard/styles.ts +0 -23
- package/examples/crypto-dashboard/worker.ts +0 -3
- package/llms.txt +0 -69
- package/packages/elm-ssr/README.md +0 -67
- package/packages/elm-ssr/package.json +0 -61
- package/scripts/benchmark.mjs +0 -60
- package/test/action.test.ts +0 -81
- package/test/adapters.test.ts +0 -173
- package/test/advanced-robustness.test.ts +0 -75
- package/test/app.test.ts +0 -209
- package/test/browser-island.test.ts +0 -184
- package/test/cli-migrate.test.ts +0 -97
- package/test/cli.test.ts +0 -94
- package/test/cookies.test.ts +0 -156
- package/test/crypto-dashboard.test.ts +0 -35
- package/test/effects.test.ts +0 -117
- package/test/http.test.ts +0 -50
- package/test/integration/redis-postgres.test.ts +0 -174
- package/test/island-runtime.test.ts +0 -214
- package/test/middleware.test.ts +0 -134
- package/test/migrations.test.ts +0 -244
- package/test/profile.test.ts +0 -159
- package/test/robustness.test.ts +0 -135
- package/test/serialize.test.ts +0 -92
- package/test/sessions.test.ts +0 -429
- package/test/svg.test.ts +0 -65
- package/tsconfig.json +0 -20
- package/wrangler.jsonc +0 -11
- /package/{packages/elm-ssr/bin → bin}/elm-ssr.mjs +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Action.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Document/Encode.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Document/Events.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Document.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Html/Attributes.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Html/Events.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Html.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Island/Shared.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Island.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Loader.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Page.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Route.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Runtime.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Svg/Attributes.elm +0 -0
- /package/{packages/elm-ssr/elm-src → elm-src}/ElmSsr/Svg.elm +0 -0
- /package/{packages/elm-ssr/lib → lib}/build.mjs +0 -0
- /package/{packages/elm-ssr/lib → lib}/migrate.mjs +0 -0
- /package/{packages/elm-ssr/lib → lib}/scaffold.mjs +0 -0
- /package/{packages/elm-ssr/lib → lib}/workspace.mjs +0 -0
- /package/{packages/elm-ssr/src → src}/app.ts +0 -0
- /package/{packages/elm-ssr/src → src}/backends.ts +0 -0
- /package/{packages/elm-ssr/src → src}/effects.ts +0 -0
- /package/{packages/elm-ssr/src → src}/http.ts +0 -0
- /package/{packages/elm-ssr/src → src}/middleware.ts +0 -0
- /package/{packages/elm-ssr/src → src}/migrations.ts +0 -0
- /package/{packages/elm-ssr/src → src}/protocol.ts +0 -0
- /package/{packages/elm-ssr/src → src}/render.ts +0 -0
- /package/{packages/elm-ssr/src → src}/request-handler.ts +0 -0
- /package/{packages/elm-ssr/src → src}/response-headers.ts +0 -0
- /package/{packages/elm-ssr/src → src}/serialize.ts +0 -0
- /package/{packages/elm-ssr/src → src}/sessions/crypto.ts +0 -0
- /package/{packages/elm-ssr/src → src}/sessions/effects.ts +0 -0
- /package/{packages/elm-ssr/src → src}/sessions/index.ts +0 -0
- /package/{packages/elm-ssr/src → src}/sessions/middleware.ts +0 -0
- /package/{packages/elm-ssr/src → src}/sessions/store.ts +0 -0
- /package/{packages/elm-ssr/src → src}/sessions/types.ts +0 -0
- /package/{packages/elm-ssr/src → src}/tasks.ts +0 -0
package/CHANGELOG.md
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to the `elm-ssr` package. Dates are ISO; "Unreleased" lives
|
|
4
|
-
at the top until a version is cut.
|
|
5
|
-
|
|
6
|
-
## 0.2.0 — 2026-05-30
|
|
7
|
-
|
|
8
|
-
Sessions + CSRF land as a first-class, opt-in layer; cookie primitives gain
|
|
9
|
-
hardened defaults; the CLI's `new` command stops scaffolding under
|
|
10
|
-
`examples/`.
|
|
11
|
-
|
|
12
|
-
### Added
|
|
13
|
-
|
|
14
|
-
- **Sessions and CSRF** ([docs/sessions.md](docs/sessions.md))
|
|
15
|
-
- New subpath `elm-ssr/sessions` exports `sessionMiddleware`,
|
|
16
|
-
`csrfMiddleware`, `sessionEffects`, `memorySessionStore`,
|
|
17
|
-
`cacheStore`, `signValue`, `verifyValue`, `generateSessionId`,
|
|
18
|
-
`generateCsrfToken`, plus the `SessionStore` / `SessionRecord` /
|
|
19
|
-
`RequestSession` types.
|
|
20
|
-
- `createWorkerApp` gains two opt-in options:
|
|
21
|
-
- `sessions: { secret, store, cookieName?, maxAgeSeconds?, cookiePath?, cookieDomain?, secure?, sameSite? }` — installs the signed-cookie session middleware and auto-wraps your effect runner with `sessionEffects`.
|
|
22
|
-
- `csrf: true | CsrfMiddlewareOptions` — installs the CSRF middleware (requires `sessions`). Header (`X-CSRF-Token`) or form field (`_csrf`); `skipPaths` for webhook receivers.
|
|
23
|
-
- HMAC-SHA256 cookie signing via WebCrypto (constant-time verify).
|
|
24
|
-
- `memorySessionStore()` for dev/tests; `cacheStore(backend, options?)` reuses any `CacheBackend` (works over `redisCache(...)`, KV-backed wrappers, …).
|
|
25
|
-
- **Elm-side session API** ([packages/elm-ssr/elm-src/ElmSsr/Loader.elm](packages/elm-ssr/elm-src/ElmSsr/Loader.elm))
|
|
26
|
-
- `Loader.session : Decoder a -> Loader (Maybe a)` — read the current session payload.
|
|
27
|
-
- `Loader.csrfToken : Loader (Maybe String)` — embed in forms (hidden `_csrf` input) or `X-CSRF-Token` on `fetch`.
|
|
28
|
-
- `Loader.setSession : Value -> Loader ()` — replace session data; middleware persists + rolls the cookie.
|
|
29
|
-
- `Loader.clearSession : Loader ()` — destroy the session.
|
|
30
|
-
- **Cookies as a first-class `Action` primitive** ([docs/loaders-and-actions.md#cookies](docs/loaders-and-actions.md#cookies))
|
|
31
|
-
- `Action.setCookie : Cookie -> Action a -> Action a`, `Action.clearCookie`, propagated through `map`/`andThen`/`fromLoader`.
|
|
32
|
-
- `Action.defaultCookie` (permissive base) and `Action.sessionCookie` (hardened: `Secure`, `HttpOnly`, `SameSite=Lax`, 7-day `Max-Age`, `Path=/`).
|
|
33
|
-
- `Action.Cookie`, `Action.SameSite = Lax | Strict | None`.
|
|
34
|
-
- `Loader.getCookie : String -> Loader (Maybe String)` for the matching read side.
|
|
35
|
-
- `Set-Cookie` headers attach to **every** response path: HTML page, redirect, JSON, and `/api/render`'s SPA-nav preview.
|
|
36
|
-
- **CLI**
|
|
37
|
-
- `elm-ssr new <name>` scaffolds at `<workspace>/<name>/` (previously hardcoded `examples/<name>/`).
|
|
38
|
-
- New `--in <subdir>` flag: `elm-ssr new my-app --in apps` → `<workspace>/apps/my-app/`.
|
|
39
|
-
- **Test loops**
|
|
40
|
-
- `bun run test:unit` — fast loop, no Docker.
|
|
41
|
-
- `bun run test:integration` — only the integration suite, self-manages Docker.
|
|
42
|
-
- `bun run test` — full suite, self-manages Docker. (Replaces the old `test:docker`, which is now redundant.)
|
|
43
|
-
- **Docs**
|
|
44
|
-
- New [docs/sessions.md](docs/sessions.md).
|
|
45
|
-
- Doc tree: [docs/README.md](docs/README.md) + 11 topic pages
|
|
46
|
-
(getting-started, routing, loaders-and-actions, effects, backends,
|
|
47
|
-
tasks, islands, migrations, cli, middleware, sessions, testing).
|
|
48
|
-
- [llms.txt](llms.txt) at the repo root for AI agents (llmstxt.org format).
|
|
49
|
-
- **Example app**
|
|
50
|
-
- `examples/basic/src/Example/Basic/Routes/Profile.elm` — end-to-end session + CSRF demo with `Loader.session` / `csrfToken` / `setSession` / `clearSession`. Exposed via `createSessionExampleWorker` in [runtime.ts](examples/basic/runtime.ts).
|
|
51
|
-
- `examples/basic/src/Example/Basic/Routes/Session.elm` — raw cookie demo (login/logout via `Action.setCookie` + `Action.clearCookie`).
|
|
52
|
-
|
|
53
|
-
### Changed
|
|
54
|
-
|
|
55
|
-
- `Action.encodeStep` now takes a `List Cookie` parameter for the cookies to
|
|
56
|
-
attach. Used internally by the runtime; no impact unless you build your
|
|
57
|
-
own encoded steps by hand.
|
|
58
|
-
- `Action.step` skips top-level `WithCookies` wrappers; use the new
|
|
59
|
-
`Action.collectCookies : Action a -> ( List Cookie, Action a )` first if
|
|
60
|
-
you need the cookies separately.
|
|
61
|
-
- `AppContext` and `EffectContext` gained an optional `session?` field
|
|
62
|
-
populated by `sessionMiddleware`. Existing code is source-compatible.
|
|
63
|
-
- Default `bun run test` now brings Postgres + Redis up via Docker
|
|
64
|
-
automatically and tears them down on exit. Use `bun run test:unit` for the
|
|
65
|
-
fast no-Docker loop.
|
|
66
|
-
|
|
67
|
-
### Fixed
|
|
68
|
-
|
|
69
|
-
- `elm-ssr new <name>` no longer hardcodes `examples/<name>/`.
|
|
70
|
-
|
|
71
|
-
### Removed
|
|
72
|
-
|
|
73
|
-
- `bun run test:docker` (redundant — `bun run test` now self-manages Docker).
|
|
74
|
-
- The `@elm-ssr/cli` + `@elm-ssr/runtime-worker` scoped packages were
|
|
75
|
-
collapsed into the single unscoped `elm-ssr` package back in 0.1.0; this
|
|
76
|
-
release does not republish them. Deprecate them in your registry to point
|
|
77
|
-
users at `elm-ssr`:
|
|
78
|
-
```
|
|
79
|
-
npm deprecate @elm-ssr/cli@0.1.0 "Replaced by the unscoped 'elm-ssr' package."
|
|
80
|
-
npm deprecate @elm-ssr/runtime-worker@0.1.0 "Replaced by the unscoped 'elm-ssr' package."
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## 0.1.0 — 2026-05-30
|
|
84
|
-
|
|
85
|
-
First public release. Single package `elm-ssr` covering CLI, TS runtime,
|
|
86
|
-
effect adapters, tasks/queues, SQL migrations, and the Elm authoring
|
|
87
|
-
modules (`ElmSsr.*`).
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Michał Majchrzak and elm-ssr contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/bun.lock
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"lockfileVersion": 1,
|
|
3
|
-
"configVersion": 1,
|
|
4
|
-
"workspaces": {
|
|
5
|
-
"": {
|
|
6
|
-
"name": "elmssr",
|
|
7
|
-
"devDependencies": {
|
|
8
|
-
"elm": "^0.19.1-6",
|
|
9
|
-
"elm-ssr": "workspace:*",
|
|
10
|
-
"happy-dom": "^20.9.0",
|
|
11
|
-
"typescript": "^5.9.0",
|
|
12
|
-
"wrangler": "^4.0.0",
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
"examples/basic": {
|
|
16
|
-
"name": "@elm-ssr/example-basic",
|
|
17
|
-
"version": "0.0.0",
|
|
18
|
-
"dependencies": {
|
|
19
|
-
"elm-ssr": "workspace:*",
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
"examples/crypto-dashboard": {
|
|
23
|
-
"name": "@elm-ssr/example-crypto-dashboard",
|
|
24
|
-
"version": "0.0.0",
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"elm-ssr": "workspace:*",
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
"packages/elm-ssr": {
|
|
30
|
-
"name": "elm-ssr",
|
|
31
|
-
"version": "0.1.0",
|
|
32
|
-
"bin": {
|
|
33
|
-
"elm-ssr": "bin/elm-ssr.mjs",
|
|
34
|
-
},
|
|
35
|
-
"dependencies": {
|
|
36
|
-
"cookie": "^1.0.1",
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
"packages": {
|
|
41
|
-
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.5.0", "", {}, "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg=="],
|
|
42
|
-
|
|
43
|
-
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="],
|
|
44
|
-
|
|
45
|
-
"@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260526.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/pR3GH3gfv0PUp7DjI8v0aAIDOqFwibq4bg5xT7TZgcVdBV/cJQWckdXCMqiRtHiawLwogUX00EIOINkYJ1Zqg=="],
|
|
46
|
-
|
|
47
|
-
"@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260526.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rcyu0iANYfaiezKh3Mcao1O4IIgVfQldxduiL5TZT1sP0NIeRY4YReSTrzPxNnXxSYaIqaqRHMcHbUM/ic4knA=="],
|
|
48
|
-
|
|
49
|
-
"@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260526.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5EZAEnlLwa9oGJRo8Nd3iY5Wcd9ROGNNG90xNIGp8MEjj8v2jTn42NC47fCZKFdnLj3+S+vWEhu1x0GVJnALjA=="],
|
|
50
|
-
|
|
51
|
-
"@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260526.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-X/YBQXeXFeCN7QTStoWrATEBc9WKl7PIqkw/dQkjyJ72gh3rkLe0+Xkzp3wO7gtxTDQMa7NPGy1W4+sdMf8q1g=="],
|
|
52
|
-
|
|
53
|
-
"@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260526.1", "", { "os": "win32", "cpu": "x64" }, "sha512-R+tqpFFdcfZIljx8fIW9rj9fRTtDgfoA2yonsfAGa6e8snrmr+38mdFHtkRC0D3UyZpn/hOtmXiUBfdX2gMR7Q=="],
|
|
54
|
-
|
|
55
|
-
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
|
|
56
|
-
|
|
57
|
-
"@elm-ssr/example-basic": ["@elm-ssr/example-basic@workspace:examples/basic"],
|
|
58
|
-
|
|
59
|
-
"@elm-ssr/example-crypto-dashboard": ["@elm-ssr/example-crypto-dashboard@workspace:examples/crypto-dashboard"],
|
|
60
|
-
|
|
61
|
-
"@elm_binaries/darwin_arm64": ["@elm_binaries/darwin_arm64@0.19.1-0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mjbsH7BNHEAmoE2SCJFcfk5fIHwFIpxtSgnEAqMsVLpBUFoEtAeX+LQ+N0vSFJB3WAh73+QYx/xSluxxLcL6dA=="],
|
|
62
|
-
|
|
63
|
-
"@elm_binaries/darwin_x64": ["@elm_binaries/darwin_x64@0.19.1-0", "", { "os": "darwin", "cpu": "x64" }, "sha512-QGUtrZTPBzaxgi9al6nr+9313wrnUVHuijzUK39UsPS+pa+n6CmWyV/69sHZeX9qy6UfeugE0PzF3qcUiy2GDQ=="],
|
|
64
|
-
|
|
65
|
-
"@elm_binaries/linux_x64": ["@elm_binaries/linux_x64@0.19.1-0", "", { "os": "linux", "cpu": "x64" }, "sha512-T1ZrWVhg2kKAsi8caOd3vp/1A3e21VuCpSG63x8rDie50fHbCytTway9B8WHEdnBFv4mYWiA68dzGxYCiFmU2w=="],
|
|
66
|
-
|
|
67
|
-
"@elm_binaries/win32_x64": ["@elm_binaries/win32_x64@0.19.1-0", "", { "os": "win32", "cpu": "x64" }, "sha512-yDleiXqSE9EcqKtd9SkC/4RIW8I71YsXzMPL79ub2bBPHjWTcoyyeBbYjoOB9SxSlArJ74HaoBApzT6hY7Zobg=="],
|
|
68
|
-
|
|
69
|
-
"@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
|
|
70
|
-
|
|
71
|
-
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
|
|
72
|
-
|
|
73
|
-
"@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
|
|
74
|
-
|
|
75
|
-
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="],
|
|
76
|
-
|
|
77
|
-
"@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="],
|
|
78
|
-
|
|
79
|
-
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="],
|
|
80
|
-
|
|
81
|
-
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="],
|
|
82
|
-
|
|
83
|
-
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="],
|
|
84
|
-
|
|
85
|
-
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="],
|
|
86
|
-
|
|
87
|
-
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="],
|
|
88
|
-
|
|
89
|
-
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="],
|
|
90
|
-
|
|
91
|
-
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="],
|
|
92
|
-
|
|
93
|
-
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="],
|
|
94
|
-
|
|
95
|
-
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="],
|
|
96
|
-
|
|
97
|
-
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="],
|
|
98
|
-
|
|
99
|
-
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="],
|
|
100
|
-
|
|
101
|
-
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="],
|
|
102
|
-
|
|
103
|
-
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="],
|
|
104
|
-
|
|
105
|
-
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="],
|
|
106
|
-
|
|
107
|
-
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="],
|
|
108
|
-
|
|
109
|
-
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="],
|
|
110
|
-
|
|
111
|
-
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="],
|
|
112
|
-
|
|
113
|
-
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="],
|
|
114
|
-
|
|
115
|
-
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="],
|
|
116
|
-
|
|
117
|
-
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="],
|
|
118
|
-
|
|
119
|
-
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="],
|
|
120
|
-
|
|
121
|
-
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
|
|
122
|
-
|
|
123
|
-
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
|
|
124
|
-
|
|
125
|
-
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
|
126
|
-
|
|
127
|
-
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="],
|
|
128
|
-
|
|
129
|
-
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="],
|
|
130
|
-
|
|
131
|
-
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="],
|
|
132
|
-
|
|
133
|
-
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="],
|
|
134
|
-
|
|
135
|
-
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="],
|
|
136
|
-
|
|
137
|
-
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="],
|
|
138
|
-
|
|
139
|
-
"@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="],
|
|
140
|
-
|
|
141
|
-
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="],
|
|
142
|
-
|
|
143
|
-
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="],
|
|
144
|
-
|
|
145
|
-
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="],
|
|
146
|
-
|
|
147
|
-
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="],
|
|
148
|
-
|
|
149
|
-
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="],
|
|
150
|
-
|
|
151
|
-
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="],
|
|
152
|
-
|
|
153
|
-
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="],
|
|
154
|
-
|
|
155
|
-
"@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="],
|
|
156
|
-
|
|
157
|
-
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="],
|
|
158
|
-
|
|
159
|
-
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="],
|
|
160
|
-
|
|
161
|
-
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="],
|
|
162
|
-
|
|
163
|
-
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="],
|
|
164
|
-
|
|
165
|
-
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="],
|
|
166
|
-
|
|
167
|
-
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="],
|
|
168
|
-
|
|
169
|
-
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="],
|
|
170
|
-
|
|
171
|
-
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
|
|
172
|
-
|
|
173
|
-
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
|
174
|
-
|
|
175
|
-
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
|
176
|
-
|
|
177
|
-
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
|
178
|
-
|
|
179
|
-
"@poppinss/colors": ["@poppinss/colors@4.1.6", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg=="],
|
|
180
|
-
|
|
181
|
-
"@poppinss/dumper": ["@poppinss/dumper@0.6.5", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw=="],
|
|
182
|
-
|
|
183
|
-
"@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="],
|
|
184
|
-
|
|
185
|
-
"@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
|
|
186
|
-
|
|
187
|
-
"@speed-highlight/core": ["@speed-highlight/core@1.2.15", "", {}, "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw=="],
|
|
188
|
-
|
|
189
|
-
"@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="],
|
|
190
|
-
|
|
191
|
-
"@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="],
|
|
192
|
-
|
|
193
|
-
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
|
194
|
-
|
|
195
|
-
"blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
|
|
196
|
-
|
|
197
|
-
"cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
|
|
198
|
-
|
|
199
|
-
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
|
200
|
-
|
|
201
|
-
"elm": ["elm@0.19.1-6", "", { "optionalDependencies": { "@elm_binaries/darwin_arm64": "0.19.1-0", "@elm_binaries/darwin_x64": "0.19.1-0", "@elm_binaries/linux_x64": "0.19.1-0", "@elm_binaries/win32_x64": "0.19.1-0" }, "bin": { "elm": "bin/elm" } }, "sha512-mKYyierHICPdMx/vhiIacdPmTPnh889gjHOZ75ZAoCxo3lZmSWbGP8HMw78wyctJH0HwvTmeKhlYSWboQNYPeQ=="],
|
|
202
|
-
|
|
203
|
-
"elm-ssr": ["elm-ssr@workspace:packages/elm-ssr"],
|
|
204
|
-
|
|
205
|
-
"entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
|
|
206
|
-
|
|
207
|
-
"error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
|
|
208
|
-
|
|
209
|
-
"esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
|
|
210
|
-
|
|
211
|
-
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
212
|
-
|
|
213
|
-
"happy-dom": ["happy-dom@20.9.0", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.18.3" } }, "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ=="],
|
|
214
|
-
|
|
215
|
-
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
|
216
|
-
|
|
217
|
-
"miniflare": ["miniflare@4.20260526.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.24.8", "workerd": "1.20260526.1", "ws": "8.20.1", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-JYQ7jPZZWoaaj9jWHb8Ucp6Cu2SbDVqIsAJhumqdzzLkkfq0pYkDeino/sZfW1ixJWPjv/C44zjm9gVJC2izCA=="],
|
|
218
|
-
|
|
219
|
-
"path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
|
|
220
|
-
|
|
221
|
-
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
|
222
|
-
|
|
223
|
-
"rosie-skills": ["rosie-skills@0.6.4", "", { "optionalDependencies": { "rosie-skills-darwin-arm64": "0.6.4", "rosie-skills-freebsd-x64": "0.6.4", "rosie-skills-linux-x64": "0.6.4" }, "bin": { "rosie-skills": "dist/bin.js" } }, "sha512-ojfhSiQRdZ2QyWbmKAHOSAUbaLYrTc5zIH7mS1jKoP8KCFSQddwVhMyFqldckTeybTfW3zNcsZzyOTzGTN1SBA=="],
|
|
224
|
-
|
|
225
|
-
"rosie-skills-darwin-arm64": ["rosie-skills-darwin-arm64@0.6.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rn1s5hqFKcxeiDEWWoFa1hdGPshR8TkwHLzy/cBavb9XJNAaUxbe3oQ78W9sQkRHAgRyzJYyk9tw68Qrdnizgg=="],
|
|
226
|
-
|
|
227
|
-
"rosie-skills-freebsd-x64": ["rosie-skills-freebsd-x64@0.6.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SxCRduPBMtfjkQ+q56Yw9OLA3PyaqoALzt7kER7IDKuUVfM2O/1w8sa5xhTDiCvWkZJixnH5d5Ya6KT+/Mwcng=="],
|
|
228
|
-
|
|
229
|
-
"rosie-skills-linux-x64": ["rosie-skills-linux-x64@0.6.4", "", { "os": "linux", "cpu": "x64" }, "sha512-D9Y9mfu7goB0s0X59uU3hcFeUTef3VbpCIDwFMzyvJrAq3XhRACWBDMHQsHlyWdHxTXPX/ILyW65RXyrJlgqng=="],
|
|
230
|
-
|
|
231
|
-
"semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="],
|
|
232
|
-
|
|
233
|
-
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
|
|
234
|
-
|
|
235
|
-
"supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
|
|
236
|
-
|
|
237
|
-
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
238
|
-
|
|
239
|
-
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
240
|
-
|
|
241
|
-
"undici": ["undici@7.24.8", "", {}, "sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ=="],
|
|
242
|
-
|
|
243
|
-
"undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="],
|
|
244
|
-
|
|
245
|
-
"unenv": ["unenv@2.0.0-rc.24", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw=="],
|
|
246
|
-
|
|
247
|
-
"whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="],
|
|
248
|
-
|
|
249
|
-
"workerd": ["workerd@1.20260526.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260526.1", "@cloudflare/workerd-darwin-arm64": "1.20260526.1", "@cloudflare/workerd-linux-64": "1.20260526.1", "@cloudflare/workerd-linux-arm64": "1.20260526.1", "@cloudflare/workerd-windows-64": "1.20260526.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-IHzymht98p10JH1zzwdCpbViAqw97HrwKl7+KfZeASFMsYSrIsAULWdPn0LRC5FTUzBpamLNyKCCKxbgXHgRHQ=="],
|
|
250
|
-
|
|
251
|
-
"wrangler": ["wrangler@4.95.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", "miniflare": "4.20260526.0", "path-to-regexp": "6.3.0", "rosie-skills": "^0.6.3", "unenv": "2.0.0-rc.24", "workerd": "1.20260526.1" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20260526.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-vgXzFVSCdUbeCadgVXvu8fK5tzNm8T9W+7lriyGWZMx0B1+CAdr4d8JTlZszHfgjypRAHmAxb49etZGIRD9pgg=="],
|
|
252
|
-
|
|
253
|
-
"ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="],
|
|
254
|
-
|
|
255
|
-
"youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="],
|
|
256
|
-
|
|
257
|
-
"youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="],
|
|
258
|
-
}
|
|
259
|
-
}
|
package/docker-compose.yml
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Local services for integration tests.
|
|
2
|
-
#
|
|
3
|
-
# docker compose up -d # start postgres + redis
|
|
4
|
-
# bun run test:integration # run the gated tests against them
|
|
5
|
-
# docker compose down # tear down
|
|
6
|
-
#
|
|
7
|
-
# Tests in test/integration/ skip themselves when DATABASE_URL or REDIS_URL
|
|
8
|
-
# isn't set, so the default `bun test` stays clean on machines without Docker.
|
|
9
|
-
|
|
10
|
-
services:
|
|
11
|
-
postgres:
|
|
12
|
-
image: postgres:16-alpine
|
|
13
|
-
environment:
|
|
14
|
-
POSTGRES_USER: elmssr
|
|
15
|
-
POSTGRES_PASSWORD: elmssr
|
|
16
|
-
POSTGRES_DB: elmssr
|
|
17
|
-
ports:
|
|
18
|
-
- "5432:5432"
|
|
19
|
-
healthcheck:
|
|
20
|
-
test: ["CMD-SHELL", "pg_isready -U elmssr -d elmssr"]
|
|
21
|
-
interval: 1s
|
|
22
|
-
timeout: 3s
|
|
23
|
-
retries: 30
|
|
24
|
-
|
|
25
|
-
redis:
|
|
26
|
-
image: redis:7-alpine
|
|
27
|
-
ports:
|
|
28
|
-
- "6379:6379"
|
|
29
|
-
healthcheck:
|
|
30
|
-
test: ["CMD", "redis-cli", "ping"]
|
|
31
|
-
interval: 1s
|
|
32
|
-
timeout: 3s
|
|
33
|
-
retries: 30
|
package/docs/README.md
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# elm-ssr docs
|
|
2
|
-
|
|
3
|
-
Topic-by-topic documentation for [elm-ssr](../README.md). The top-level
|
|
4
|
-
[README](../README.md) is the quickstart and end-to-end overview; these pages
|
|
5
|
-
go deeper, one concern at a time.
|
|
6
|
-
|
|
7
|
-
## Getting started
|
|
8
|
-
|
|
9
|
-
- [Getting started](getting-started.md) — install, scaffold an app, build it,
|
|
10
|
-
run it locally.
|
|
11
|
-
|
|
12
|
-
## Authoring
|
|
13
|
-
|
|
14
|
-
- [Routing](routing.md) — file-based routes, dynamic segments, NotFound.
|
|
15
|
-
- [Loaders and Actions](loaders-and-actions.md) — describe data fetching for
|
|
16
|
-
pages and handle non-GET requests (forms).
|
|
17
|
-
- [Effects](effects.md) — the backend-neutral effect vocabulary
|
|
18
|
-
(`fetchJson`, `cacheGet/Put`, `query/queryOne/execute`, `env`, `getCookie`,
|
|
19
|
-
`enqueue`).
|
|
20
|
-
- [Islands](islands.md) — interactive `Browser.element` islands, embedding,
|
|
21
|
-
cross-island bus, persistence across SPA navigation.
|
|
22
|
-
|
|
23
|
-
## Runtime
|
|
24
|
-
|
|
25
|
-
- [Backends](backends.md) — composing effect adapters (`inMemoryEffects`,
|
|
26
|
-
`cloudflareEffects`, `withCache`, `redisCache`, `postgresSql`).
|
|
27
|
-
- [Tasks and queues](tasks.md) — background work with `withTasks`
|
|
28
|
-
(`waitUntil`) or Cloudflare Queues (`withQueueProducer` /
|
|
29
|
-
`createQueueConsumer`).
|
|
30
|
-
- [Migrations](migrations.md) — SQL-file migrations (`runMigrations`,
|
|
31
|
-
`revertMigrations`, `listMigrations`); transactional per-migration.
|
|
32
|
-
- [Middleware](middleware.md) — the standard middleware stack and
|
|
33
|
-
`composeMiddleware`.
|
|
34
|
-
- [Sessions and CSRF](sessions.md) — signed-cookie sessions (memory + cache
|
|
35
|
-
stores), CSRF protection, `Loader.session`/`csrfToken`/`setSession`/
|
|
36
|
-
`clearSession`.
|
|
37
|
-
|
|
38
|
-
## Tooling
|
|
39
|
-
|
|
40
|
-
- [CLI](cli.md) — `elm-ssr build|new|migrate|dev|compress|routes|info`.
|
|
41
|
-
- [Testing](testing.md) — unit/integration test loops, Docker-managed PG+Redis.
|
|
42
|
-
|
|
43
|
-
## See also
|
|
44
|
-
|
|
45
|
-
- [CHANGELOG](../CHANGELOG.md) — release notes.
|
|
46
|
-
- [AGENTS.md](../AGENTS.md) — hard rules + orientation for AI agents working on
|
|
47
|
-
this repo.
|
|
48
|
-
- [examples/basic/](../examples/basic/) — reference app (pages, islands, forms,
|
|
49
|
-
cache, sql, tasks).
|
|
50
|
-
- [examples/crypto-dashboard/](../examples/crypto-dashboard/) — Tailwind +
|
|
51
|
-
`elm/svg` + `elm/http` islands with 15s refresh and cross-island bus.
|
package/docs/backends.md
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# Backends
|
|
2
|
-
|
|
3
|
-
A backend is what actually runs an effect. The Worker takes a single
|
|
4
|
-
`EffectRunner` (`(effect, context) => Promise<{ ok, value? | error? }>`); the
|
|
5
|
-
adapters in `elm-ssr/effects`, `elm-ssr/backends`, and `elm-ssr/tasks` are
|
|
6
|
-
composable functions of type `EffectRunner -> EffectRunner` that intercept
|
|
7
|
-
specific kinds and forward the rest.
|
|
8
|
-
|
|
9
|
-
## Two starting runners
|
|
10
|
-
|
|
11
|
-
### `cloudflareEffects(config?)`
|
|
12
|
-
|
|
13
|
-
Maps the effect vocabulary onto Cloudflare bindings:
|
|
14
|
-
|
|
15
|
-
```ts
|
|
16
|
-
import { cloudflareEffects } from "elm-ssr/effects";
|
|
17
|
-
|
|
18
|
-
const effects = cloudflareEffects({
|
|
19
|
-
cacheBinding: "CACHE", // KV — default "CACHE"
|
|
20
|
-
dbBinding: "DB" // D1 — default "DB"
|
|
21
|
-
});
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
| Effect | Backend |
|
|
25
|
-
| ------ | ------- |
|
|
26
|
-
| `fetchJson` | `fetch` |
|
|
27
|
-
| `cacheGet`/`cachePut` | `env[cacheBinding]` (KV, JSON-encoded values, TTL) |
|
|
28
|
-
| `query`/`queryOne`/`execute` | `env[dbBinding]` (D1) |
|
|
29
|
-
| `env name` | `env[name]` |
|
|
30
|
-
| `cookie` | parsed from `request.headers["cookie"]` |
|
|
31
|
-
|
|
32
|
-
Missing bindings → the effect fails with `Missing KV binding "CACHE"` /
|
|
33
|
-
`Missing D1 binding "DB"`.
|
|
34
|
-
|
|
35
|
-
### `inMemoryEffects(options?)`
|
|
36
|
-
|
|
37
|
-
Local / test runner. Cache is an in-memory `Map` with TTL; `env` comes from
|
|
38
|
-
the options; `fetchJson` is real `fetch` unless you pass a fake. SQL is
|
|
39
|
-
pluggable — pass a handler (or wrap `postgresSql(client)`).
|
|
40
|
-
|
|
41
|
-
```ts
|
|
42
|
-
import { inMemoryEffects } from "elm-ssr/effects";
|
|
43
|
-
|
|
44
|
-
const effects = inMemoryEffects({
|
|
45
|
-
env: { ANALYTICS_KEY: "abc" },
|
|
46
|
-
sql: postgresSql(myPgClient), // see below
|
|
47
|
-
fetchJson: async (url) => fixtures[url], // optional, defaults to real fetch
|
|
48
|
-
cache: new Map(), // optional — pass one to share/inspect
|
|
49
|
-
now: () => Date.now() // optional — useful in tests
|
|
50
|
-
});
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Unknown kinds fall through to `defaultEffectRunner` (which still handles
|
|
54
|
-
`fetchJson` and `cookie`).
|
|
55
|
-
|
|
56
|
-
## Cache adapters (`withCache`, `redisCache`)
|
|
57
|
-
|
|
58
|
-
`withCache` wraps any runner so that `cacheGet`/`cachePut` are served by a
|
|
59
|
-
`CacheBackend` instead of the runner's own cache logic. Useful to swap KV for
|
|
60
|
-
Redis in dev, or to plug in any cache without writing your own runner.
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
import { withCache, redisCache } from "elm-ssr/backends";
|
|
64
|
-
|
|
65
|
-
const effects = withCache(
|
|
66
|
-
inMemoryEffects({ sql: postgresSql(pg) }),
|
|
67
|
-
redisCache({
|
|
68
|
-
// Bun.redis:
|
|
69
|
-
get: (k) => Bun.redis.get(k),
|
|
70
|
-
set: (k, v, ttl) => ttl !== undefined ? Bun.redis.set(k, v, "EX", ttl) : Bun.redis.set(k, v)
|
|
71
|
-
})
|
|
72
|
-
);
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
The `CacheClient` interface is minimal so it fits `Bun.redis`, `ioredis`,
|
|
76
|
-
`node-redis`, anything with a get/set:
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
interface CacheClient {
|
|
80
|
-
get(key: string): Promise<string | null>;
|
|
81
|
-
set(key: string, value: string, ttlSeconds?: number): Promise<unknown>;
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Values are JSON-encoded going in and decoded coming out.
|
|
86
|
-
|
|
87
|
-
## SQL adapter (`postgresSql`)
|
|
88
|
-
|
|
89
|
-
`postgresSql(client)` adapts a minimal client to the `SqlQuery` handler shape
|
|
90
|
-
used by `inMemoryEffects({ sql })`. It maps the three SQL modes (`query`,
|
|
91
|
-
`queryOne`, `execute`) onto a single `run(sql, params)` call.
|
|
92
|
-
|
|
93
|
-
```ts
|
|
94
|
-
import { postgresSql } from "elm-ssr/backends";
|
|
95
|
-
import { SQL } from "bun";
|
|
96
|
-
|
|
97
|
-
const pg = new SQL(process.env.DATABASE_URL!);
|
|
98
|
-
|
|
99
|
-
const effects = inMemoryEffects({
|
|
100
|
-
sql: postgresSql({
|
|
101
|
-
run: async (sql, params) => {
|
|
102
|
-
const rows = await pg.unsafe(sql, params);
|
|
103
|
-
return { rows: [...rows], rowCount: (rows as { count?: number }).count ?? rows.length };
|
|
104
|
-
}
|
|
105
|
-
})
|
|
106
|
-
});
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
For SQLite via `bun:sqlite`, write a `run` that calls `db.query(sql).all(params)`
|
|
110
|
-
(or `.run(...)` for execute) and report `rowCount` from `changes`.
|
|
111
|
-
|
|
112
|
-
## Background tasks
|
|
113
|
-
|
|
114
|
-
`enqueue` is handled by `withTasks` (inline via `waitUntil`) or
|
|
115
|
-
`withQueueProducer` (durable Cloudflare Queues). See [Tasks and
|
|
116
|
-
queues](tasks.md).
|
|
117
|
-
|
|
118
|
-
## A complete recipe
|
|
119
|
-
|
|
120
|
-
```ts
|
|
121
|
-
import { inMemoryEffects } from "elm-ssr/effects";
|
|
122
|
-
import { withCache, redisCache, postgresSql } from "elm-ssr/backends";
|
|
123
|
-
import { withTasks } from "elm-ssr/tasks";
|
|
124
|
-
|
|
125
|
-
const effects = withTasks(
|
|
126
|
-
withCache(
|
|
127
|
-
inMemoryEffects({
|
|
128
|
-
env: { GIT_SHA: process.env.GIT_SHA ?? "dev" },
|
|
129
|
-
sql: postgresSql({ run: pgRun })
|
|
130
|
-
}),
|
|
131
|
-
redisCache({ get: Bun.redis.get, set: Bun.redis.set })
|
|
132
|
-
),
|
|
133
|
-
{
|
|
134
|
-
sendEmail: async (payload) => { /* … */ },
|
|
135
|
-
warmCache: async () => { /* … */ }
|
|
136
|
-
}
|
|
137
|
-
);
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
The same Elm runs against this **and** against `cloudflareEffects()` in
|
|
141
|
-
production — only the adapter changes.
|
|
142
|
-
|
|
143
|
-
## Source
|
|
144
|
-
|
|
145
|
-
- [packages/elm-ssr/src/effects.ts](../packages/elm-ssr/src/effects.ts)
|
|
146
|
-
- [packages/elm-ssr/src/backends.ts](../packages/elm-ssr/src/backends.ts)
|