feat(upload-client): add hashContent, putToPresignedUrl, fetchFromUrl exports#1107
Merged
pyramation merged 5 commits intomainfrom May 10, 2026
Merged
feat(upload-client): add hashContent, putToPresignedUrl, fetchFromUrl exports#1107pyramation merged 5 commits intomainfrom
pyramation merged 5 commits intomainfrom
Conversation
… exports - hashContent: Node.js SHA-256 for strings/Buffers (tests, scripts, CLI) - putToPresignedUrl: extracted from private putWithFetch, now a named export - fetchFromUrl: fetch GET wrapper for presigned/CDN URL downloads - uploadFile's internal putToS3 now delegates to putToPresignedUrl - Updated README with unified API docs
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Drop hash-content.ts — it imported Node.js 'crypto' module which breaks the client-side contract of this package. All exports now use Web standards only (fetch, Web Crypto).
hashContent(string) computes SHA-256 using crypto.subtle.digest — same Web Crypto API as hashFile. No Node.js-only dependencies. Developers get one package for the complete upload pipeline: hashContent/hashFile → putToPresignedUrl → fetchFromUrl
…localhost DNS support)
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
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
Adds three new atomic exports to
@constructive-io/upload-clientfor custom presigned URL flows:hashContent(content: string)— SHA-256 hex digest of a plain string via Web Crypto API (crypto.subtle.digest). ComplementshashFile(which accepts File/Blob). New file:hash-content.ts.putToPresignedUrl(url, body, contentType, signal?)— Extracted from the privateputWithFetchinupload.tsinto a standalone export input.ts. The internalputToS3now delegates to this for its fetch path.fetchFromUrl(url, signal?)— Fetch GET wrapper with structuredUploadErroron failure. Useful for verifying downloads from presigned or CDN URLs.Isomorphic HTTP via
@constructive-io/fetchput.tsusescreateFetch()from@constructive-io/fetch(added as a new dependency) instead of rawglobalThis.fetch. This resolves*.localhostsubdomain DNS and Host header issues in Node.js — the same pattern used in@constructive-io/graphql-query/runtime. In browsers,createFetch()returnsglobalThis.fetchas-is.The internal
putWithFetchfunction is removed;putToS3now callsputToPresignedUrldirectly. Existing tests (24/24) pass unchanged.Motivation: The constructive-db storage security tests currently hand-roll
putToPresignedUrl()andhashContent()helpers inline. After this ships, those tests can import from this package instead — dogfooding our own tools. Related: constructive-db#1093.Review & Testing Checklist for Human
fetchFromUrlreusesPUT_UPLOAD_FAILEDerror code — both error paths infetchFromUrlthrow with code'PUT_UPLOAD_FAILED', which is semantically wrong for a GET operation. Decide whether to add a new error code (e.g.'FETCH_FAILED') to theUploadErrorCodeunion, or accept the reuse for now.put.tsorhash-content.ts— the existingupload.test.tsindirectly coversputToPresignedUrlvia theuploadFileorchestrator, buthashContentandfetchFromUrlhave zero test coverage. Consider whether to add them before merging.createFetch()call —const fetch = createFetch()input.tsruns at import time.createFetch()is synchronous and cached, so this should be safe, but verify no side effects at import in edge/serverless environments.pnpm testinpackages/upload-clientand verify 24/24 pass after merge.Notes
body: BodyInit | string—stringis technically already inBodyInitin modern TS DOM libs, but kept explicit for compatibility with environments that may not include it. The body is cast toBodyInitwhen passed to thecreateFetch()result since the wrapper's type signature expects standard fetch args.putToPresignedUrlreturn type isPromise<Response>(the oldputWithFetchreturnedvoid). The internalputToS3caller discards the return value, so no behavioral change foruploadFile.@constructive-io/fetch@1.0.0.Link to Devin session: https://app.devin.ai/sessions/7903d2a3e7a34c6daa605e12d6b80d9e
Requested by: @pyramation