feat: add @constructive-io/upload-client package (Phase 2B) + README header fixes#960
Merged
pyramation merged 2 commits intomainfrom Apr 3, 2026
Merged
Conversation
Vanilla TypeScript utilities for client-side presigned URL uploads: - hashFile() — SHA-256 via Web Crypto API - hashFileChunked() — chunked SHA-256 for large files with progress - uploadFile() — full orchestrator (hash → requestUploadUrl → PUT → confirmUpload) - GraphQLExecutor type — works with any GraphQL client (urql, Apollo, fetch) - UploadError class with typed error codes - AbortSignal support for cancellation - Progress tracking via XHR upload events - Deduplication support (skip PUT when file already exists) 23 tests passing across 2 test suites.
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:
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
…DMEs - graphile/graphile-presigned-url-plugin/README.md - graphql/node-type-registry/README.md - jobs/README.md (no version badge — top-level docs, not a package) - packages/upload-client/README.md
5 tasks
5 tasks
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
New standalone vanilla TypeScript package (
@constructive-io/upload-client) providing client-side presigned URL upload utilities. Framework-agnostic — works with any GraphQL client via aGraphQLExecutorfunction parameter.Atomic functions:
hashFile(file)— SHA-256 via Web Crypto API (single-pass)hashFileChunked(file, chunkSize?, onProgress?)— chunked SHA-256 with progress callbackuploadFile(options)— full orchestrator: hash →requestUploadUrl→ PUT to S3 →confirmUploadFeatures: deduplication (skip PUT when content hash matches), AbortSignal cancellation, progress tracking (XHR when available, fetch fallback), typed
UploadErrorwith error codes.23 tests across 2 suites, all passing. Build produces CJS + ESM outputs via makage.
Updates since last revision
Added standard README headers (logo, CI badge, license badge, version badge) to 4 READMEs that were missing them:
packages/upload-client/README.md— new package from this PRgraphile/graphile-presigned-url-plugin/README.md— from earlier storage pipeline workgraphql/node-type-registry/README.mdjobs/README.md— logo + CI + license only (no version badge since it's a top-level docs file, not a package); also fixedn#→#typo on line 1Review & Testing Checklist for Human
src/queries.tsmatch the server-sidegraphile-presigned-url-pluginschema exactly (uploadUrl,fileId,key,deduplicated,expiresAt,status,success). These are plain strings with no compile-time validation.hashFileChunkedusefulness — it reads chunks sequentially but concatenates them in memory before the finalcrypto.subtle.digestcall, so peak memory is not reduced vshashFile. The JSDoc is transparent about this. Decide if this API should ship as-is, be renamed, or be deferred until a WASM-based streaming hash is available.putWithXHR) is untested — Node.js test environment has noXMLHttpRequest, so only theputWithFetchpath is exercised. Consider whether browser-level testing is needed before merge, or if this is acceptable for v0.1.0.cd packages/upload-client && pnpm test(23 tests),pnpm build(CJS + ESM). Lint is broken repo-wide (ESLint 9 migration issue, not specific to this package —packages/csrfhas the same failure).Notes
FileInputinterface is a minimal abstraction compatible with browserFile, Node.jsBlob, and custom implementations.UploadErrorcodes:HASH_FAILED,INVALID_FILE,GRAPHQL_ERROR,REQUEST_UPLOAD_URL_FAILED,PUT_UPLOAD_FAILED,CONFIRM_UPLOAD_FAILED,ABORTED.hashFilebut rejected byuploadFile(size <= 0). This is intentional — hashing is a pure utility, uploading has business validation.Link to Devin session: https://app.devin.ai/sessions/4c882ba2dfbf4045adf85fb83cde6f77
Requested by: @pyramation