Skip to main content

Core Overview

WIP

The framework-agnostic upload engine core.

@gentleduck/upload/core is the engine — the store, the reducer, the contracts your backend implements, the persistence layer, the typed error classes, and the default transport. It has no React dependency and runs anywhere File, Blob, and AbortController exist.

What you import from core

Values

ExportPurpose
createUploadStore(options)Build the store the single runtime object you interact with
resolveUploadConfig(partial)Apply config defaults (mostly used internally and in tests)
createXHRTransport()The browser transport (installed automatically when transport is omitted)
LocalStorageAdapter, IndexedDBAdapter, MemoryAdapter, createMemoryAdapter()Persistence adapters
UploadEngineError and subclassesTyped errors with static, XSS-safe messages

There is no createUploadClient; createUploadStore is the only constructor.

Types (namespaced)

The public type surface lives under a few namespaces rather than flat aliases:

NamespaceNotable members
ContractsApi.Me, Result.Base, Intent.Base/Intent.Map, Cursor.Map, Validation.Rejection, ValidationRules, FingerprintFile, Strategy.Me/Strategy.Registry
EngineCommand, Item, State, EventMap, Config, Phase/Phases, Progress, Outcome, Plugin, Hooks, RetryDecision
StoreUploadStore, Options
TransportOptions
UploadPersistenceAdapter, Options, Snapshot, PersistedItem

So the backend contract type is Contracts.Api.Me<M, P, R>, a command is Engine.Command<P>, and the store handle is Store.UploadStore<M, C, P, R>.

Module map

ModuleWhat lives there
engine/storecreateUploadStore, the runtime, dispatch, scheduler, command handlers
engineEngine namespace: state model, commands, events, config
contractsContracts namespace and the Transport interface
persistenceSnapshot serialize/deserialize + storage adapters
errorsUploadEngineError and its typed subclasses

Design principles

  • Immutable snapshots. Every reducer step returns a new state object, so reference equality drives React re-renders correctly.
  • One event layer. Public events emit from a single place after transitions, never from inside handlers — no duplicates, consistent semantics.
  • Typed results end-to-end. R flows from complete() through events to item.result.
  • Protocol-agnostic. The engine selects a strategy by the intent's strategy field and never depends on a concrete protocol.

Continue

  • Client — store options, plugins, hooks, custom fingerprinting.
  • Contracts — the API, transport, and strategy interfaces.
  • Engine — phases, scheduling, and retries.
  • Errors — the typed error model.
  • Persistence — resume across reloads.