feat(storage): add provider-neutral object storage package (#106) - #107
feat(storage): add provider-neutral object storage package (#106)#107kauandotnet wants to merge 4 commits into
Conversation
5cc8276 to
d7cd728
Compare
ReviewI ran the full gate locally on this branch: A lot here is genuinely good, and worth saying first: the capability gating is The items below are what I think should land before merge/publish. Publish blockers (npm)1.
|
# Conflicts: # CHANGELOG.md
Addresses the four merge/publish blockers from the PR #107 review. - signDownload now rejects a requested expiresIn with NOT_SUPPORTED unless the store advertises signedDownloadPolicy.expiresIn. The capability was published by the S3 adapter (false when publicBaseUrl makes URLs permanent) and read by nothing, so signDownload(key, { expiresIn }) returned a permanent public URL to a private object with no error. Only the S3 adapter advertises the guarantee today; every other provider now rejects expiresIn until its adapter declares it. - signDownload validates its options: expiresIn must be a positive safe integer and must not exceed the lower of the provider-enforced signedDownload.maxExpiresIn and the new adapter-declared signedDownloadPolicy.maxExpiresIn (SigV4's 7 days, documented but not enforced upstream). Omitting expiresIn falls back to the provider default, now documented rather than silently inherited. Both signed-URL validators carry store, operation, and key. - normalizeStorageError fills the store, operation, and key a driver deliberately sanitized out instead of returning early and discarding them. Fields the driver did set stay authoritative; the stack is preserved, and an error needing no context keeps its identity. - sync() refuses an implicit compare: 'etag' when the two stores use different drivers. ETags are opaque per-driver tokens that can never match across drivers, so the default silently re-uploaded every object on every run. The check is on driver name and deliberately conservative. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Es4VGiJ3j33W1cbotqVcXW
Review follow-up — the four blockers are fixedPushed in 0cb5bef. Items 1, 2, 4 and 5 from the review are addressed; item 8 1 + 2.
|
Pull Request
Summary
Adds the preview
@concepta/rockets-storagepackage: a provider-neutral objectstorage contract, named NestJS stores, structured signed transfers, fail-closed
capability handling, hardened provider adapters, and reusable testing support.
Closes #106.
Related to #86 and #94, but does not close either. This PR supplies the storage
runtime that application services and operation handlers can inject; it does
not add inbound multipart routes or bind PR #94's
FILE_STORAGE_SERVICE_TOKEN.Changes
StorageDriverandStorageClientwith streamingreads/writes, explicitly bounded convenience reads, metadata, range reads,
list/search, copy/move, bulk operations, resumable uploads, conditional
operations, and structured signed transfers.
timeouts, retries, plugins, and exact provider capabilities. Unsupported
guarantees fail closed rather than being approximated with racy operations.
StorageModule,StorageService,@InjectStorage(), default and namedstores,
forRoot()/forRootAsync(), and feature-scoped sync/asyncregistration. Async stores support factory, class, and existing providers.
destination-prefix safeguards.
testing entry points. Native provider SDKs remain optional and do not leak
through the package root or
rockets-core.profiles and read-only defaults for unverified custom S3 endpoints.
always-on filesystem conformance suite, gated live AWS/R2/custom suites, and
a real NestJS HTTP end-to-end test for named-store injection.
reports, documentation, release-readiness CI, and clean packed-consumer
verification.
Type of Change
Verification
yarn buildyarn api:report:update- 17 entry points and 7 API report testsyarn typecheck:specyarn test- 119 files and 1,219 tests passedyarn test:e2e- 54 files; 450 tests passed and 3 live cloudconformance suites skipped
yarn lint:allpassed; 3 live cloud suites skipped
yarn release:packages- 7 stable assertions, 95 public artifacttargets, all workspaces dry-packed, and all 7 public packages verified in
clean CommonJS, ESM, TypeScript, NestJS, legacy-resolution, and
peer-minimal consumers
git diff --checkLive cloud conformance was not run. It is opt-in, requires disposable provider
fixtures, and remains skipped in the normal test matrix. The full filesystem
provider contract runs on every end-to-end test execution.
Scope and Compatibility
>=20.19.0 <21or>=22.12.0. This exactrange is required for synchronous
require()support across the ESMdependency graph; Node 21 and Node 22.0-22.11 are intentionally excluded.
/core, and/files-sdkentry points support legacy TypeScriptNode10 resolution. Provider and testing subpaths require
node16,nodenext,or
bundlerresolution because upstream provider packages expose modernexport maps only.
/coreentry point has no NestJS runtime or type dependency.scanning, transformation, and product encryption policy remain application
concerns.
multipart/form-dataparsing, and byte-range support does not add a storage HTTP gateway.
Checklist