Migrate from Cloudflare Workers to Haverstack server backend#99
Open
cuibonobo wants to merge 8 commits into
Open
Migrate from Cloudflare Workers to Haverstack server backend#99cuibonobo wants to merge 8 commits into
cuibonobo wants to merge 8 commits into
Conversation
- Replace Cloudflare Functions (/stack, /media) with haverstack REST API
- Rewrite src/lib/api.ts to speak haverstack wire format (records/query/types/attachments)
- Update attachment model: id → fileId, upload via raw binary POST instead of multipart
- Rename ResourceBase date fields: created_date/updated_date → createdAt/updatedAt
- Remove is_public field; createResource now sets { access: 'public' } permissions
- Update CLI init command to register types in haverstack format (id, baseId, version, schema)
- Replace wrangler dev server with npx serve; remove D1/R2/migrate scripts
- Delete codec/bucket.ts and all functions/ (no longer needed)
- Add .env.example documenting STACK_SERVER_URL and API_TOKEN
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz
Articles no longer carry a slug in their content — the slug lives in a linked site.gen/page-meta@1 record (parentId → article ID). The CLI editing workflow is unchanged: slug still appears in the frontmatter, but on commit it is written to/updated in page-meta rather than the article. The site generator, feed builder, and sitemap builder all load a page-meta map once and use it to resolve article slugs when constructing URLs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz
- Add @haverstack/adapter-api, @haverstack/wire-types, @haverstack/core - Rewrite api.ts around APIAdapter singleton; wire types now come from @haverstack/wire-types instead of local definitions - Date fields on records are already Date objects via the adapter, so wireToResource no longer needs to parse ISO strings - hashSchema from @haverstack/core replaces the local getTypeHash implementation in codec/type.ts; exported via api.ts to keep the TypeSchema cast internal - media.ts is unchanged: attachment uploads require Content-Type and Content-Disposition headers that the adapter's putAttachment does not support Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz
Upgrades @haverstack/core to 0.8.0 and @haverstack/adapter-api to 0.6.0. Exposes getStack() from api.ts (Stack.create wrapping the APIAdapter singleton) and rewrites media.ts to use stack.putAttachment/getAttachment/deleteAttachment, removing direct fetch calls and the auth.ts dependency. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz
Removes the attachments array from record content schemas and from ResourceBase. Attachments are now stored as AttachmentAssociation entries on the record via Stack.associate/dissociate. The label field carries the filename, replacing the old tag categorization (which is derivable from mimeType). On commit, existing associations are dissociated and their bytes deleted before re-uploading. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz
Reads all resources from the old stack API, transforms the format (snake_case dates, attachments-in-content → AttachmentAssociation, article slug → site.gen/page-meta@1), and writes to the new haverstack server. Preserves original resource IDs by calling adapter.createRecord() directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz
Adds ensureTypes() which creates the four content types (note, article, page, site.gen/page-meta) before migrating resources, skipping any that already exist. Resource creation now checks adapter.getRecord() first and skips if present. Page-meta is checked via queryRecords before creating. Attachments compare expected filenames against existing association labels and skip if all are present; a partial set is cleared and fully re-uploaded. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz
Uses @haverstack/adapter-sqlite directly so adapter.createRecord() stores the original resource id, createdAt, and updatedAt exactly — the HTTP API path (APIAdapter) ignored those fields and generated new values. - Install @haverstack/adapter-sqlite@^0.5.0 (migration-only dependency) - Replace APIAdapter with SQLiteAdapter; open or initialize based on whether DB_PATH already exists - Replace NEW_STACK_URL / NEW_API_TOKEN env vars with DB_PATH / ENTITY_ID / TIMEZONE - Cast SQLiteAdapter to StackAdapter to bridge adapter-sqlite targeting @haverstack/core@0.5.0 while the app uses core@0.8.0; the missing fields (ownerEntityId, timezone) are not used by the migration logic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz
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.
Summary
This PR migrates the website from a custom Cloudflare Workers-based backend to the Haverstack server as the primary backend service. The API client has been completely refactored to communicate with Haverstack's wire format instead of the previous custom format.
Key Changes
Backend Migration
functions/directory code including custom resource/type controllers, database models, and media handlersfunctions/stack/models/)wrangler.tomlto only contain basic project metadataAPI Client Refactoring (
src/lib/api.ts)WireRecord,WireListResult,WireType) matching Haverstack server formatwireToResource,wireToPageMeta,toWireContent) to translate between wire format and application models/resourcesto/recordsendpointsrecords/queryPOST endpoint for filtered searchestypeIdformat (type@version)PageMetaTypesupport for managing article metadata (slugs, publication dates) separately from contentType System Updates
ResourceBaseinterface: renamedcreated_date/updated_datetocreatedAt/updatedAt, replacedis_publicwithparentIdslugfield fromArticleType.content(now stored in separatePageMetaType)PageMetaTypeinterface for site generator metadataCLI and Build System Updates
cli.tsto use new API functions and handle page metadata separatelylock.tsto manage article slugs through the new page metadata systemsite.ts,feed.ts, andsitemap.tsto usebuildPageMetaMap()for slug resolutionfileIdinstead ofidConfiguration
.env.exampledocumentingSTACK_SERVER_URLand authentication token configurationImplementation Details
Content-Typeheaders and authenticationhttps://claude.ai/code/session_01NCjeen8sSta78QhUWGDQSz