commits
Move all 14 inlined dev.hatk.* lexicon definitions from cli.ts into
src/lexicons/dev/hatk/*.json. The hatk new command now copies them
with cpSync instead of writing each one inline. Build step copies
lexicons to dist/ alongside templates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SQLite adapter coerces boolean params to 0/1
- pdsCreateRecord and pdsPutRecord now run label rules after local indexing
- clearLabels() added for hot-reload support in server-init
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can submit reports via dev.hatk.createReport XRPC endpoint,
selecting from the app's defined labels with optional free-text reason.
Reports are stored in a new _reports table (dialect-aware for SQLite/DuckDB).
Admins see a Reports tab in the admin UI to review, apply labels, or
dismiss reports. Open report count appears on the Overview dashboard.
Also fixes the label scaffold template to use defineLabel from $hatk,
and adds the createReport lexicon to hatk new scaffolding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move inline template strings from cli.ts into separate .tpl files under
src/templates/ for readability and maintainability. Update xrpc template
with $hatk import and typed query results. Include viewer handle in
ScopeMissing and proxy error responses so the generated client can
preserve identity across re-authentication redirects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wraps existing pds-proxy functions so hooks and XRPC handlers can write
records through the PDS with local indexing, without raw SQL. Also adds
awaitBackfill so ensureRepo properly waits for in-flight backfills.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace HydrateContext with BaseContext (no items field, viewer gains handle)
- Feed hydrate signature: (ctx: BaseContext, items: Row<T>[]) => Promise<unknown[]>
- XrpcContext extends BaseContext, removing duplicate field declarations
- Add buildBaseContext and buildXrpcContext factories, eliminating 4 copy-pasted context constructions across xrpc.ts and opengraph.ts
- Tighten db layer: run/runBatch/all params from any[] to unknown[], typed all<T>() generics at every call site
- FeedContext.db.query tightened to unknown[]
- Codegen updated: BaseContext imports/exports, defineFeed overloads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
searchRecords was returning raw flat rows while all other context methods
(resolve, lookup, getRecords) return shaped Row<T> with .value. Now
search results are reshaped before returning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract duplicated getRecords logic (fetch by URIs, reshape, return Map)
into a generic getRecordsMap function in db.ts, used by both
HydrateContext and XrpcContext. Adds getRecords to the XrpcContext
interface so XRPC handlers can fetch shaped records by URI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SQLite maps JSON columns to TEXT, so checking col.sqlType === 'JSON'
only worked for DuckDB. This caused reshapeRow and insert operations
to skip JSON parsing/serialization on SQLite.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9 tasks in 5 batches: D1 adapter, Worker entry, Container entry,
build command, integration and docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Worker + Container architecture with D1, Service Binding RPC
for communication, and hatk build --target cloudflare output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of emitting one log per invalid record during backfill, collect
counts by collection and emit a single validation_skips event per repo.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Assets 404 without /hatk/ base when served from hatk-dev.github.io/hatk/.
Remove this once hatk.dev custom domain is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deploys VitePress site on pushes to docs/site/** on main.
CNAME configured for hatk.dev custom domain.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Jobs feature doesn't exist yet. Remove generate/destroy job commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every other define* helper is singular (defineFeed, defineQuery,
defineProcedure, defineHook, defineOG). Align labels to match.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite all documentation to reflect generated client helpers, SQLite-only,
SvelteKit remote commands, and login/logout/parseViewer from $hatk/client.
- Rewrite nav structure with new Frontend section
- Landing page with project tree and feature cards
- Getting Started: quickstart, project structure, configuration rewritten
- Guides: feeds, xrpc handlers, auth (new), seeds, labels, opengraph, hooks
- Frontend: 3 new pages (setup, data-loading, mutations)
- API reference: updated with dual auth (DPoP + cookies), callXrpc
- CLI reference: fixed src/ → app/, localhost → 127.0.0.1
- Remove obsolete: oauth.md, api-client.md, frontend.md, deployment.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a custom fetch function is provided (e.g. SvelteKit's fetch),
bypass the server bridge and use relative URLs so the framework can
deduplicate server/client requests. Guards window.location redirects
for safe server-side execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move login, logout, viewerDid, and parseViewer into the generated
client file so templates don't need a local auth.ts. Layout server
load reduces to a single parseViewer(cookies) call.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single-repo resync now uses triggerAutoBackfill directly instead of
triggering a full network re-enumeration and process restart. Bulk
resync-all still uses onResync callback in production for memory
reclamation restart.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin page failed on SQLite with "unrecognized token: ':''" due to
DuckDB-specific COUNT(*)::INTEGER and pragma_database_size() syntax.
Moved all inline SQL from admin routes into dialect-aware db.ts
functions. Removed unused schema endpoint and UI. Added resync
fallback via triggerAutoBackfill when onResync callback is not provided.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace HMAC-signed cookie with AES-GCM encrypted JSON containing
both DID and handle, using HKDF key derivation
- Remove wrapCallXrpcWithScopeRedirect — no longer needed now that
SvelteKit form actions handle scope errors with redirect() directly
- Simplify getViewer() to sync globalThis read (no more async cookie
parsing or $app/server imports)
- Widen viewer type to { did, handle? } across XrpcContext and handlers
- Extract scopeMissingResponse() helper, replacing 5 duplicate blocks
- Set __hatk_viewer in production SSR path around renderPage
- Add client-side 401 redirect for query endpoints (not just procedures)
- Fix unused import/param lint warnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BM25 FTS5 already indexes child table text (artist names) and with
incremental FTS the index is always current. The LIKE phases were
scanning 1.7M rows for 12-18s finding nothing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace drop-and-rebuild FTS strategy with incremental external content
FTS5 tables for SQLite. Records are indexed/deindexed inline during
insertRecord/deleteRecord. Periodic and post-backfill rebuilds are
skipped for SQLite. DuckDB retains its existing behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds validation that required fields exist in object properties,
catching typos like "createdAttt" at boot instead of at seed time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update AGENTS.md to reflect server/ directory, $hatk alias, SvelteKit
integration, and vp commands
- Remove generate job command, template, and directory mapping
- Remove jobs from all description strings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This path wasn't matched by the /oauth/ prefix since it starts with
/oauth- not /oauth/, causing it to fall through to SvelteKit (404).
Bumps to 0.0.1-alpha.30.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The $hatk module alias needs a Node.js resolve hook for dynamic import()
in scanServerDir. Previously only test.ts had it — now main.ts uses the
same shared hook so production also resolves $hatk correctly.
Bumps to 0.0.1-alpha.29.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SvelteKit SSR load functions call callXrpc via globalThis.__hatk_callXrpc,
but main.ts never set it. Now exposes callXrpc, parseSessionCookie, and
sessionCookieName before loading the SvelteKit handler.
Bumps to 0.0.1-alpha.28.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
scanServerDir uses raw import() which bypasses Vite's resolve.alias.
Register a Node.js module resolve hook in createTestContext so $hatk
resolves to hatk.generated.ts in all contexts.
Also adds resolve.alias in the vite plugin for dev/build consistency.
Bumps to 0.0.1-alpha.27.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The transform hook alone wasn't enough — Vitest resolves imports before
transform runs. Adding resolve.alias ensures $hatk resolves in all contexts.
Bumps to 0.0.1-alpha.26.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Already declared in packages/hatk/package.json where it's actually used.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Guard __dev/login with oauth check to prevent crash when OAuth not configured
- Fix sendResponse to preserve duplicate Set-Cookie headers (flat array format)
- Remove misleading status_code: 0 from telemetry emit
- Stabilize HMAC key derivation with sorted JSON keys
- Log PDS proxy local index failures via emit() instead of silent catch
- Extract shared withDpopRetry() to deduplicate proxy retry logic
- Share isHatkRoute() between adapter.ts and vite-plugin.ts
- Fix hasRenderer to use live function call instead of boot-time const
- Support configurable cookie name in generated client code
- Remove any types from pds-proxy.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite server.ts to Request→Response handler, add SSR renderer and
Node.js adapter, implement session cookies for viewer resolution in
SSR, add /__dev/login endpoint for test auth, register core XRPC
handlers for preferences, fix OAuth scope joining, switch test context
to SQLite, and add /__dev/ route forwarding in vite plugin.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add define functions (defineFeed, defineQuery, defineProcedure, defineSetup,
defineHook, defineLabels, defineOG) with __type discriminants. Add recursive
scanner that discovers and categorizes server/ modules by type. Add
server-init.ts that wires scanner results to registration functions. Update
main.ts to use initServer() when server/ directory exists, with fallback to
legacy separate directories. Update codegen to scaffold server/ files and
export all define functions from hatk.generated.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backfill was inserting records without lexicon validation, allowing
invalid data (e.g. createdAt: "wowzers") through. Now validates
each record against the lexicon schema, matching indexer behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can submit reports via dev.hatk.createReport XRPC endpoint,
selecting from the app's defined labels with optional free-text reason.
Reports are stored in a new _reports table (dialect-aware for SQLite/DuckDB).
Admins see a Reports tab in the admin UI to review, apply labels, or
dismiss reports. Open report count appears on the Overview dashboard.
Also fixes the label scaffold template to use defineLabel from $hatk,
and adds the createReport lexicon to hatk new scaffolding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move inline template strings from cli.ts into separate .tpl files under
src/templates/ for readability and maintainability. Update xrpc template
with $hatk import and typed query results. Include viewer handle in
ScopeMissing and proxy error responses so the generated client can
preserve identity across re-authentication redirects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace HydrateContext with BaseContext (no items field, viewer gains handle)
- Feed hydrate signature: (ctx: BaseContext, items: Row<T>[]) => Promise<unknown[]>
- XrpcContext extends BaseContext, removing duplicate field declarations
- Add buildBaseContext and buildXrpcContext factories, eliminating 4 copy-pasted context constructions across xrpc.ts and opengraph.ts
- Tighten db layer: run/runBatch/all params from any[] to unknown[], typed all<T>() generics at every call site
- FeedContext.db.query tightened to unknown[]
- Codegen updated: BaseContext imports/exports, defineFeed overloads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract duplicated getRecords logic (fetch by URIs, reshape, return Map)
into a generic getRecordsMap function in db.ts, used by both
HydrateContext and XrpcContext. Adds getRecords to the XrpcContext
interface so XRPC handlers can fetch shaped records by URI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite all documentation to reflect generated client helpers, SQLite-only,
SvelteKit remote commands, and login/logout/parseViewer from $hatk/client.
- Rewrite nav structure with new Frontend section
- Landing page with project tree and feature cards
- Getting Started: quickstart, project structure, configuration rewritten
- Guides: feeds, xrpc handlers, auth (new), seeds, labels, opengraph, hooks
- Frontend: 3 new pages (setup, data-loading, mutations)
- API reference: updated with dual auth (DPoP + cookies), callXrpc
- CLI reference: fixed src/ → app/, localhost → 127.0.0.1
- Remove obsolete: oauth.md, api-client.md, frontend.md, deployment.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin page failed on SQLite with "unrecognized token: ':''" due to
DuckDB-specific COUNT(*)::INTEGER and pragma_database_size() syntax.
Moved all inline SQL from admin routes into dialect-aware db.ts
functions. Removed unused schema endpoint and UI. Added resync
fallback via triggerAutoBackfill when onResync callback is not provided.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace HMAC-signed cookie with AES-GCM encrypted JSON containing
both DID and handle, using HKDF key derivation
- Remove wrapCallXrpcWithScopeRedirect — no longer needed now that
SvelteKit form actions handle scope errors with redirect() directly
- Simplify getViewer() to sync globalThis read (no more async cookie
parsing or $app/server imports)
- Widen viewer type to { did, handle? } across XrpcContext and handlers
- Extract scopeMissingResponse() helper, replacing 5 duplicate blocks
- Set __hatk_viewer in production SSR path around renderPage
- Add client-side 401 redirect for query endpoints (not just procedures)
- Fix unused import/param lint warnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace drop-and-rebuild FTS strategy with incremental external content
FTS5 tables for SQLite. Records are indexed/deindexed inline during
insertRecord/deleteRecord. Periodic and post-backfill rebuilds are
skipped for SQLite. DuckDB retains its existing behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
scanServerDir uses raw import() which bypasses Vite's resolve.alias.
Register a Node.js module resolve hook in createTestContext so $hatk
resolves to hatk.generated.ts in all contexts.
Also adds resolve.alias in the vite plugin for dev/build consistency.
Bumps to 0.0.1-alpha.27.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Guard __dev/login with oauth check to prevent crash when OAuth not configured
- Fix sendResponse to preserve duplicate Set-Cookie headers (flat array format)
- Remove misleading status_code: 0 from telemetry emit
- Stabilize HMAC key derivation with sorted JSON keys
- Log PDS proxy local index failures via emit() instead of silent catch
- Extract shared withDpopRetry() to deduplicate proxy retry logic
- Share isHatkRoute() between adapter.ts and vite-plugin.ts
- Fix hasRenderer to use live function call instead of boot-time const
- Support configurable cookie name in generated client code
- Remove any types from pds-proxy.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite server.ts to Request→Response handler, add SSR renderer and
Node.js adapter, implement session cookies for viewer resolution in
SSR, add /__dev/login endpoint for test auth, register core XRPC
handlers for preferences, fix OAuth scope joining, switch test context
to SQLite, and add /__dev/ route forwarding in vite plugin.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add define functions (defineFeed, defineQuery, defineProcedure, defineSetup,
defineHook, defineLabels, defineOG) with __type discriminants. Add recursive
scanner that discovers and categorizes server/ modules by type. Add
server-init.ts that wires scanner results to registration functions. Update
main.ts to use initServer() when server/ directory exists, with fallback to
legacy separate directories. Update codegen to scaffold server/ files and
export all define functions from hatk.generated.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>