commits
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>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SQLite is now the default for new projects and when no databaseEngine
is specified in config. Use --duckdb flag with hatk new to opt in.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diff lexicon-derived schema against actual DB columns on every startup.
Emit ALTER TABLE ADD/DROP COLUMN for changes, drop orphaned child tables,
and trigger backfill when new empty collection tables are detected.
Also includes:
- Skip post-backfill restart in dev mode (DEV_MODE env)
- Suppress ECONNREFUSED proxy errors in Vite plugin during startup
- Move db/schema.sql write after setup hooks
- Normalize SQL parameter passing to use arrays consistently
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactor hatk's monolithic DuckDB data layer into a hexagonal architecture
supporting both DuckDB and SQLite via DatabasePort/SearchPort interfaces.
- Add database/ports.ts with DatabasePort, BulkInserter, SearchPort interfaces
- Add database/dialect.ts with SqlDialect configs for DuckDB and SQLite
- Add DuckDB adapter (database/adapters/duckdb.ts) preserving read/write queues
- Add SQLite adapter (database/adapters/sqlite.ts) with $1→? param translation
- Add DuckDB SearchPort using PRAGMA FTS and SQLite SearchPort using FTS5
- Add adapter factory with dynamic imports for tree-shaking
- Refactor db.ts to use DatabasePort instead of direct DuckDB API calls
- Make schema generation dialect-aware (type maps, timestamps, JSON)
- Make FTS index building dialect-aware (string_agg, json_extract)
- Add databaseEngine config option ('duckdb' | 'sqlite')
- Add --sqlite flag to hatk new scaffolding
- Add db/schema.sql auto-generation on startup
- Fix hatk schema command to work with both engines
- Update reset command to clean up SQLite WAL files
- Update all import paths to new database/ directory
- Add database/index.ts barrel export
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Catch resolveHandle failures in handlePar and throw a clear
"Handle not found" error. PAR endpoint returns 400 instead of 500.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds an AGENTS.md file to new projects created with `hatk new`, providing
AI coding assistants with project structure and CLI usage context.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hatk schema now inits the DB from lexicons if it doesn't exist yet,
so you can inspect the schema without running the server first.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add module-level docs with examples to labels, setup, seed, xrpc, and
hooks. Add function-level JSDoc to logger, mst, indexer, and all exports.
Move hooks.ts from oauth/ to src/ since it's generic lifecycle infrastructure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace execSync with spawn-based helper that forwards SIGINT/SIGTERM
to child processes, eliminating the need to Ctrl+C twice.
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>
Add defineConfig() identity function for type inference. Rewrite loadConfig
to use dynamic import() instead of YAML parsing. Update all call sites
(main.ts, cli.ts, test.ts, vite-plugin.ts) and the scaffolder. Add
./config package export. Dockerfile template uses --experimental-strip-types
for native Node 25 TS support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Resync endpoint sets repos to pending then calls runBackfill
instead of triggerAutoBackfill, using the same batch worker pool
- runBackfill returns record count; restart only if work was done
- Shared runBackfillAndRestart function used by both boot and resync
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Diff lexicon-derived schema against actual DB columns on every startup.
Emit ALTER TABLE ADD/DROP COLUMN for changes, drop orphaned child tables,
and trigger backfill when new empty collection tables are detected.
Also includes:
- Skip post-backfill restart in dev mode (DEV_MODE env)
- Suppress ECONNREFUSED proxy errors in Vite plugin during startup
- Move db/schema.sql write after setup hooks
- Normalize SQL parameter passing to use arrays consistently
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactor hatk's monolithic DuckDB data layer into a hexagonal architecture
supporting both DuckDB and SQLite via DatabasePort/SearchPort interfaces.
- Add database/ports.ts with DatabasePort, BulkInserter, SearchPort interfaces
- Add database/dialect.ts with SqlDialect configs for DuckDB and SQLite
- Add DuckDB adapter (database/adapters/duckdb.ts) preserving read/write queues
- Add SQLite adapter (database/adapters/sqlite.ts) with $1→? param translation
- Add DuckDB SearchPort using PRAGMA FTS and SQLite SearchPort using FTS5
- Add adapter factory with dynamic imports for tree-shaking
- Refactor db.ts to use DatabasePort instead of direct DuckDB API calls
- Make schema generation dialect-aware (type maps, timestamps, JSON)
- Make FTS index building dialect-aware (string_agg, json_extract)
- Add databaseEngine config option ('duckdb' | 'sqlite')
- Add --sqlite flag to hatk new scaffolding
- Add db/schema.sql auto-generation on startup
- Fix hatk schema command to work with both engines
- Update reset command to clean up SQLite WAL files
- Update all import paths to new database/ directory
- Add database/index.ts barrel export
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add defineConfig() identity function for type inference. Rewrite loadConfig
to use dynamic import() instead of YAML parsing. Update all call sites
(main.ts, cli.ts, test.ts, vite-plugin.ts) and the scaffolder. Add
./config package export. Dockerfile template uses --experimental-strip-types
for native Node 25 TS support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Resync endpoint sets repos to pending then calls runBackfill
instead of triggerAutoBackfill, using the same batch worker pool
- runBackfill returns record count; restart only if work was done
- Shared runBackfillAndRestart function used by both boot and resync
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>