Upgrade Harper to v5#2
Open
BboyAkers wants to merge 13 commits into
Open
Conversation
dawsontoth
approved these changes
May 20, 2026
- UncachedBlog.get(), PageBuilder.get(), CachedBlog.get() → static - this → target (record properties and renderPost argument) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
target is a RequestTarget (URLSearchParams), not the record. Fetch post/cached via tables.Post.get(target) and tables.BlogCache.get(target) before passing to renderPost or accessing .content. Remove unused context parameter. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Bump harper 5.0.11 -> 5.0.28; add @harperfast/integration-testing + typescript dev deps - Add integration tests covering SSR render path (UncachedBlog), Harper multi-tier caching (CachedBlog 304 cache hits + invalidation on Post update), and Post REST GET/PATCH; assembles a clean dist/ component fixture - Apply harperBinPath harness fix (harper exports only ".") - Add pinned-hash Integration Tests CI workflow (Node 22/24/26) - Add tsconfig.json - Branding: HarperDB -> Harper in README; fix v4 CLI (harperdb run -> harper run) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts: # package.json
The macOS-generated lockfile omitted bufferutil/utf-8-validate/node-gyp-build entries, causing npm ci to fail on CI. Regenerated via clean npm install. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
resources.js imports solid-js/web at runtime; the fixture now ships solid-js and its closed dependency set so Harper can load the component, matching a real deployment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The custom CachedBlog.get override returns a hand-built response object, which sits outside Harper's conditional-request (ETag/304) handling, so it always returns 200. Validate Harper v5's native caching/304 + source invalidation against the BlogCache cache table (the actual caching primitive), and assert CachedBlog still SSR-renders and serves byte-identical cached HTML. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
In Harper v5 a `sourcedFrom` source is resolved per-id by instantiating
the source resource and calling its INSTANCE `get()` — a `static get()`
is never invoked. The previous migration mechanically converted
PageBuilder/UncachedBlog/CachedBlog to `static async get(target)`, so the
PageBuilder source was never run: the BlogCache stored the raw Post
record instead of rendered HTML, CachedBlog's `cached.content` was
undefined, and `/CachedBlog/:id` served an empty body.
Convert PageBuilder, UncachedBlog, and CachedBlog to instance
`async get(query)` calling `await super.get(query)`, matching harper's
own SimpleCacheSource reference and the react-ssr-example pattern.
Preserves solid's async renderPost + generateHydrationScript and the
{contentType, data} response shape on CachedBlog.
Strengthen the integration test so it fails on the pre-fix bug: assert
GET /CachedBlog/0 returns 200 with a non-empty text/html body containing
the rendered markers (__INITIAL_POST_DATA__ + post title), add a 304
conditional-hit assertion through /CachedBlog, and drive the
source-update invalidation -> re-cache flow through /CachedBlog,
asserting the re-rendered HTML reflects the mutated Post.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrade Harper to v5
Completes the v4 → v5 upgrade for this Solid SSR + Harper caching example. Resumes the existing branch (no clobber/duplicate); the prior commits had swapped the dependency and (incorrectly) converted resources to static methods, and this work finalizes the migration, fixes a caching-source correctness bug, adds integration tests + CI, and merges
main.A prior migration commit mechanically converted the resource handlers to
static async get(target). In Harper v5, asourcedFromsource is resolved per-id by instantiating the source resource and calling its INSTANCEget(query)— astatic get()is never invoked (this matches harper's ownSimpleCacheSourcereference and thereact-ssr-examplepattern). As a result thePageBuildersource never ran:BlogCachestored the rawPostrecord instead of rendered HTML,CachedBlog'scached.contentwasundefined, andGET /CachedBlog/:idserved an empty 200 body. The earlier test only checked theBlogCachetable directly, so it stayed green.Fix: convert
PageBuilder,UncachedBlog, andCachedBlogto instanceasync get(query)callingawait super.get(query)(preserving solid's asyncrenderPost+generateHydrationScriptand the{ contentType, data }shape onCachedBlog). The integration test was strengthened to fail on the pre-fix bug:GET /CachedBlog/0must now return 200 with a non-emptytext/htmlbody containing the rendered markers (__INITIAL_POST_DATA__+ the post title), plus a 304 conditional-hit and a source-update→invalidate→re-cache flow driven through/CachedBlog(asserting the re-render reflects the mutatedPost). Verified the strengthened test fails on the pre-fix static-getcode and passes after the fix; CI green on Node 22/24/26.Dependency
harper^5.0.11→^5.0.28@harperfast/integration-testing@^0.4.0,typescript@^6.0.3main(picked upversionfield +postinstall: npm run buildfor npm-pack /deploy_componentcompatibility) and resolved the package.json conflict.Migration items applied
harperdb→harper(resources.js:import { tables } from 'harper'). ✅PageBuilder) and the SSR resources (UncachedBlog,CachedBlog) use instanceasync get(query)withawait super.get(query), as v5 requires forsourcedFromsources. ✅ (corrected from the prior static-method commit — see fix above)Migration items N/A
getContext().transaction.commit) — no cross-call transaction polling. N/A.allowedSpawnCommands) — app spawns nothing. N/A.blob.save→saveBeforeCommit) — no blobs. N/A.wasLoadedFromSource→loadedFromSource— not used. N/A.Tests (
integrationTests/solid-ssr.test.ts,node:test+ ESM/TS)Runs against a real ephemeral Harper instance. The suite builds the Vite SSR output and assembles a clean component fixture (config + resources + schema +
dist/+ a minimalsolid-jsruntime dependency set, sinceresources.jsimportssolid-js/webat runtime), pre-installed viasetupHarperWithFixture. Coverage:Postseed + RESTGET;UncachedBlogserver-side-renders the Solid app to HTML (title, body, hydration data);CachedBlogrenders SSR HTML into the cache and serves byte-identical cached bytes for an unchanged Post — asserting a non-emptytext/htmlbody with__INITIAL_POST_DATA__+ title (regression guard for the static-getbug).BlogCachecache table (sourcedFromPageBuilder,expiration: 3600) serves a conditional-request 304 cache hit; the same 304 hit is also asserted through/CachedBlog; updating the sourcePost(RESTPATCH) invalidates the cached/CachedBlogrender (200 with fresh HTML reflecting the new comment) and then re-caches (304 once settled).PostGET/PATCH.Applied the mandatory
harperBinPathharness fix (harper'sexportsonly exposes., soharper/dist/bin/harper.jsis not resolvable) — resolve the CLI from the package main and pass{ harperBinPath }.Local: blocked by the macOS loopback bind (
EADDRNOTAVAILon 127.0.0.2+; environmental, not a code/v5 bug — even--isolation=nonevalidates a pool address).CI (ubuntu): ✅ all green on Node 22 / 24 / 26 — https://github.com/HarperFast/solid-ssr-example/actions/runs/27149436373
CI
Added
.github/workflows/integration-tests.yml(repo root) — Node matrix[22, 24, 26], actions pinned to commit hashes;pretest:integrationbuilds before tests; uploads Harper logs on failure.Notes / observed v5 behavior
get()fix,CachedBlogreads throughBlogCacheand does participate in Harper's conditional-request handling:/CachedBlog/0returns a 304 cache hit on a matchingIf-None-Match/If-Modified-Since, and invalidates → re-caches when the sourcePostchanges. (The earlier note claiming/CachedBlogalways returned 200 reflected the broken static-getstate and no longer applies.)package-lock.jsonalready includes harper's optional native deps (bufferutil,utf-8-validate,node-gyp-build), sonpm cisucceeds across the full Node 22/24/26 matrix; no regeneration needed for this fix.Manual / human items
@harperdb/code-guidelines(devDep) is on the legacy@harperdbscope. Per policy, npm-scope moves are manual — flagged, not changed here.🤖 Generated with Claude Code