Skip to content

Commit b5dccce

Browse files
authored
Merge pull request #125 from intent-framework/docs/alpha9-cache-key-docs
docs: update for alpha.9 — cache.key docs and resource-lifecycle example
2 parents edb9413 + 5d2105d commit b5dccce

5 files changed

Lines changed: 98 additions & 14 deletions

File tree

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ The current repository proves the core shape:
2323
- Typed router
2424
- Runtime-scoped resources
2525
- Resource reload and invalidation
26-
- Resource cache phase 1 (staleTime, deduplicate)
26+
- Resource cache phase 2 (staleTime, deduplicate, cache.key, ResourceKey)
2727
- Independent executable actions
2828
- Keyboard Enter default action
2929
- Accessible Enter hints
@@ -40,17 +40,17 @@ It is not production-ready yet. The goal right now is to keep the foundation sma
4040
Intent is available as experimental alpha packages on npm:
4141

4242
```sh
43-
pnpm add @intent-framework/core@0.1.0-alpha.8 @intent-framework/dom@0.1.0-alpha.8 @intent-framework/router@0.1.0-alpha.8 @intent-framework/testing@0.1.0-alpha.8
43+
pnpm add @intent-framework/core@0.1.0-alpha.9 @intent-framework/dom@0.1.0-alpha.9 @intent-framework/router@0.1.0-alpha.9 @intent-framework/testing@0.1.0-alpha.9
4444
```
4545

4646
```sh
47-
npm install @intent-framework/core@0.1.0-alpha.8 @intent-framework/dom@0.1.0-alpha.8 @intent-framework/router@0.1.0-alpha.8 @intent-framework/testing@0.1.0-alpha.8
47+
npm install @intent-framework/core@0.1.0-alpha.9 @intent-framework/dom@0.1.0-alpha.9 @intent-framework/router@0.1.0-alpha.9 @intent-framework/testing@0.1.0-alpha.9
4848
```
4949

5050
The quickstart pins the current alpha version so examples match the published APIs.
5151

5252
```txt
53-
Current alpha: v0.1.0-alpha.8
53+
Current alpha: v0.1.0-alpha.9
5454
First public alpha: v0.1.0-alpha.0
5555
GitHub Releases: https://github.com/intent-framework/intent/releases
5656
```
@@ -347,7 +347,7 @@ Current limitations include:
347347
* No native renderer yet
348348
* No SSR story yet
349349
* No backend persistence yet
350-
* Resource cache is phase 1 (staleTime, deduplicate); cache.key, cacheTime, swr, and cross-navigation cache are future
350+
* Resource cache is phase 2 (staleTime, deduplicate, cache.key); cacheTime, swr, and cross-navigation cache are future
351351
* No DevTools package yet
352352
* Automated version PR workflow and manual publish workflow are set up (Changesets configured)
353353
* Demo side panels use manual DOM

docs/Quickstart.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ This guide shows the fastest path from zero to a semantic screen using published
77
## 1. Install
88

99
```sh
10-
pnpm add @intent-framework/core@0.1.0-alpha.8 @intent-framework/dom@0.1.0-alpha.8 @intent-framework/testing@0.1.0-alpha.8
10+
pnpm add @intent-framework/core@0.1.0-alpha.9 @intent-framework/dom@0.1.0-alpha.9 @intent-framework/testing@0.1.0-alpha.9
1111
```
1212

1313
Or with npm:
1414

1515
```sh
16-
npm install @intent-framework/core@0.1.0-alpha.8 @intent-framework/dom@0.1.0-alpha.8 @intent-framework/testing@0.1.0-alpha.8
16+
npm install @intent-framework/core@0.1.0-alpha.9 @intent-framework/dom@0.1.0-alpha.9 @intent-framework/testing@0.1.0-alpha.9
1717
```
1818

19-
The quickstart pins `0.1.0-alpha.8` so the examples match the APIs shown below.
19+
The quickstart pins `0.1.0-alpha.9` so the examples match the APIs shown below.
2020

2121
You also need `typescript` and `vitest` for type checking and tests.
2222

docs/agent/RELEASE-STATE.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
| Package | Version | Published | Notes |
66
|---------|---------|-----------|-------|
7-
| `@intent-framework/core` | `0.1.0-alpha.1` | Yes | alpha prerelease |
8-
| `@intent-framework/dom` | `0.1.0-alpha.2` | Yes | alpha prerelease |
9-
| `@intent-framework/router` | `0.1.0-alpha.1` | Yes | alpha prerelease |
10-
| `@intent-framework/testing` | `0.1.0-alpha.1` | Yes | alpha prerelease |
7+
| `@intent-framework/core` | `0.1.0-alpha.9` | Yes | alpha prerelease |
8+
| `@intent-framework/dom` | `0.1.0-alpha.9` | Yes | alpha prerelease |
9+
| `@intent-framework/router` | `0.1.0-alpha.9` | Yes | alpha prerelease |
10+
| `@intent-framework/testing` | `0.1.0-alpha.9` | Yes | alpha prerelease |
1111
| `@intent-framework/server` | `0.1.0` | No | private workspace package |
1212

1313
`@intent-framework/server` must remain `"private": true`. Never publish it.

examples/resource-lifecycle/src/ResourceDemo.test.ts

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, it, expect } from "vitest"
22
import { testScreen } from "@intent-framework/testing"
33
import { createScreenRuntime, inspectScreen } from "@intent-framework/core"
4-
import { ResourceDemo, teamLoadCount, cachedTeamLoadCount, dedupeReportLoadCount } from "./ResourceDemo.js"
4+
import { ResourceDemo, teamLoadCount, cachedTeamLoadCount, dedupeReportLoadCount, keyedTeamLoadCount } from "./ResourceDemo.js"
55

66
const testServices = {
77
route: { name: "demo", path: "/:id", params: { id: "team_1" } },
@@ -116,12 +116,67 @@ describe("ResourceDemo", () => {
116116
}, { services: testServices as any })
117117
})
118118

119+
it("cache.key derives resource value from route context", async () => {
120+
const runtime = createScreenRuntime(ResourceDemo, { services: testServices as any })
121+
await runtime.start()
122+
const keyed = runtime.resources.find(r => r.name === "keyedTeam")!
123+
expect(keyed.status).toBe("ready")
124+
expect((keyed.value as any)?.id).toBe("team_1")
125+
expect((keyed.value as any)?.name).toBe("Team-team_1")
126+
runtime.dispose()
127+
})
128+
129+
it("cache.key: different keys are independent", async () => {
130+
const runtime = createScreenRuntime(ResourceDemo, { services: testServices as any })
131+
await runtime.start()
132+
const keyed = runtime.resources.find(r => r.name === "keyedTeam")!
133+
const before = keyedTeamLoadCount
134+
// Load with a different key
135+
await keyed.load({ route: { name: "demo", path: "/:id", params: { id: "team_b" } } })
136+
expect(keyed.status).toBe("ready")
137+
expect((keyed.value as any)?.id).toBe("team_b")
138+
expect((keyed.value as any)?.name).toBe("Team-team_b")
139+
expect(keyedTeamLoadCount).toBe(before + 1)
140+
runtime.dispose()
141+
})
142+
143+
it("cache.key: switching active key updates visible value/status", async () => {
144+
const runtime = createScreenRuntime(ResourceDemo, { services: testServices as any })
145+
await runtime.start()
146+
const keyed = runtime.resources.find(r => r.name === "keyedTeam")!
147+
// Initially keyed by route param "team_1"
148+
expect((keyed.value as any)?.id).toBe("team_1")
149+
// Switch to team_b
150+
await keyed.load({ route: { name: "demo", path: "/:id", params: { id: "team_b" } } })
151+
expect(keyed.status).toBe("ready")
152+
expect((keyed.value as any)?.id).toBe("team_b")
153+
// Switch back to team_1
154+
await keyed.load({ route: { name: "demo", path: "/:id", params: { id: "team_1" } } })
155+
expect(keyed.status).toBe("ready")
156+
expect((keyed.value as any)?.id).toBe("team_1")
157+
runtime.dispose()
158+
})
159+
160+
it("cache.key: no-arg reload reuses last active key", async () => {
161+
const runtime = createScreenRuntime(ResourceDemo, { services: testServices as any })
162+
await runtime.start()
163+
const keyed = runtime.resources.find(r => r.name === "keyedTeam")!
164+
// Load team_b — changes active key
165+
await keyed.load({ route: { name: "demo", path: "/:id", params: { id: "team_b" } } })
166+
const afterFirst = keyedTeamLoadCount
167+
// no-arg reload uses lastContext → reloads team_b
168+
await keyed.reload()
169+
expect(keyedTeamLoadCount).toBe(afterFirst + 1)
170+
expect((keyed.value as any)?.id).toBe("team_b")
171+
runtime.dispose()
172+
})
173+
119174
it("inspectScreen reports resources with status/stale/error", async () => {
120175
const runtime = createScreenRuntime(ResourceDemo, { services: testServices as any })
121176
await runtime.start()
122177
const graph = runtime.graph
123178
const resources = graph.resources
124-
expect(resources).toHaveLength(5)
179+
expect(resources).toHaveLength(6)
125180
const teamRes = resources.find(r => r.name === "team")!
126181
expect(teamRes.status).toBe("ready")
127182
expect(teamRes.hasValue).toBe(true)

examples/resource-lifecycle/src/ResourceDemo.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export let teamLoadCount = 0
55
export let auditLogLoadCount = 0
66
export let cachedTeamLoadCount = 0
77
export let dedupeReportLoadCount = 0
8+
export let keyedTeamLoadCount = 0
89

910
export type Team = {
1011
id: string
@@ -63,6 +64,19 @@ export const ResourceDemo = screen<AppServices>("Resource Demo", $ => {
6364
cache: { deduplicate: true },
6465
})
6566

67+
const keyedTeam = $.resource("keyedTeam", {
68+
load: async ({ route }) => {
69+
keyedTeamLoadCount++
70+
return {
71+
id: route.params.id,
72+
name: `Team-${route.params.id}`,
73+
members: 3,
74+
version: keyedTeamLoadCount,
75+
} satisfies Team
76+
},
77+
cache: { key: ({ route }) => route.params.id },
78+
})
79+
6680
const reloadTeam = $.act("Reload team")
6781
.does(async () => {
6882
await team.reload()
@@ -98,6 +112,19 @@ export const ResourceDemo = screen<AppServices>("Resource Demo", $ => {
98112
await dedupeReport.load()
99113
})
100114

115+
const loadKeyedTeamB = $.act("Load keyed team (team_b)")
116+
.does(async ({ navigate }) => {
117+
await keyedTeam.load({
118+
route: { name: "demo", path: "/:id", params: { id: "team_b" } },
119+
navigate,
120+
})
121+
})
122+
123+
const reloadKeyedTeam = $.act("Reload keyed team")
124+
.does(async () => {
125+
await keyedTeam.reload()
126+
})
127+
101128
$.surface("main").contains(
102129
reloadTeam,
103130
invalidateTeam,
@@ -106,5 +133,7 @@ export const ResourceDemo = screen<AppServices>("Resource Demo", $ => {
106133
loadAuditLog,
107134
reloadCachedTeam,
108135
loadDedupeReport,
136+
loadKeyedTeamB,
137+
reloadKeyedTeam,
109138
)
110139
})

0 commit comments

Comments
 (0)