Skip to content

feat(core): resource cache phase 2 — cache.key#123

Merged
mahyarmlk merged 4 commits into
mainfrom
feat/resource-cache-key
Jun 27, 2026
Merged

feat(core): resource cache phase 2 — cache.key#123
mahyarmlk merged 4 commits into
mainfrom
feat/resource-cache-key

Conversation

@mahyarmlk

@mahyarmlk mahyarmlk commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds cache.key — an optional function that derives a cache key from the resource load context. Each unique key gets its own independent entry (value, status, error, stale flag, staleTime timer, in-flight promise) within a single ResourceNode.

API Added

  • ResourceKey type: string | number | boolean | null | undefined | ResourceKey[]
  • cache.key?: (context: ResourceLoadContext<TServices>) => ResourceKey option

Key Serialization

Keys are normalized via a type-tagged encoder (encodeResourceKey) wrapped in JSON.stringify for stable Map<string, Entry> lookups. The tagged approach preserves distinctions between null, undefined, "null", "undefined", 0, -0, NaN, Infinity, -Infinity, and nested arrays — unlike plain JSON.stringify which would collapse many of these.

Equivalent array content (e.g. ["a", "b"]) maps to the same entry.

Runtime Behavior

Aspect Before (Phase 1) After (Phase 2)
Cache entries Single entry per ResourceNode One entry per unique key
Value/status/error Shared Per key, independent
stale flag Single flag Per key
staleTime timer Single timer Per key, independent
Deduplication Single in-flight promise Per key; different keys load independently
no-arg reload() Reloads with lastContext Reloads last active key
invalidate() Marks stale Marks only the active key stale
Non-keyed resources Single-entry Unchanged — backward compatible

Not Implemented (Phase 2 Scope)

  • cacheTime — no time-based eviction
  • SWR (stale-while-revalidate) — explicit reload required
  • Cross-navigation cache store — entries live for the ResourceNode lifetime
  • Dependency-tracked keys — key is derived at load/reload time only
  • Server resources — unchanged

Validation

pnpm --filter @intent-framework/core test  ✓ 203 tests
pnpm test                                   ✓ all packages/examples
pnpm typecheck                              ✓
pnpm build                                  ✓
pnpm lint                                   ✓
pnpm pack:check                             ✓
pnpm changeset status                       ✓

Changeset

.changeset/tricky-terms-doubt.md — patch for @intent-framework/core. This is the source of truth for the unreleased change.

Note: .changeset/pre.json is not changed in the final diff. The prerelease-state issue was fixed before opening/finalizing the PR — tricky-terms-doubt was never committed as consumed in pre.json.

Changed Files

  • packages/core/src/resource.ts — main implementation
  • packages/core/src/screen.ts — type update
  • packages/core/src/index.ts — export ResourceKey
  • packages/core/src/core.test.ts — 27 new test cases
  • docs/Resources.md — public docs update
  • docs/proposals/Resource-Cache-And-Stale-Semantics.md — status update
  • .changeset/tricky-terms-doubt.md — changeset (source of truth)

Adds ResourceKey type and cache.key option for resource cache keying.

- cache.key derives a resource entry key from the current load context
- One ResourceNode holds multiple internal entries, one per key
- Each entry independently tracks value, error, status, stale flag,
  staleTime timer, and in-flight promise
- ResourceRef proxies the active key entry
- cache.staleTime timers are per key
- cache.deduplicate deduplicates per active key
- Resources without cache.key behave exactly as before

Reverts .changeset/pre.json to exclude the new changeset from the
prerelease consumed list (entries in pre.json changesets are treated
as already consumed; the source of truth is the .md file itself).
… API mismatch

- Replace JSON.stringify normalizeKey with encodeResourceKey (type-tagged)
- Tagged approach preserves null vs undefined vs 'null' vs 'undefined',
  NaN, Infinity, -Infinity, -0, and nested array distinctions
- Fix docs/Resources.md: key() -> cache.key() nested API
- Fix proposal doc examples to match nested API
- Add 8 new tests for key serialization edge cases
- Update PR body to remove .changeset/pre.json references
@mahyarmlk mahyarmlk merged commit ba62d1d into main Jun 27, 2026
1 check passed
@mahyarmlk mahyarmlk deleted the feat/resource-cache-key branch June 27, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant