UCD Store Architecture notes for @ucdjs/ucd-store
@ucdjs/ucd-store is the high-level storage coordination layer for UCD.js.
Coordinates file access, mirroring, sync, verification, and reporting.
Works across different backend types through @ucdjs/fs-backend.
Bridges store metadata, local state, and remote file access behavior.
Use this page for mode boundaries, metadata authority, and store-lifecycle notes.
The diagrams below focus on the runtime behavior of the main store entrypoints.
They are intentionally close to the current implementation so they can be used
as both design docs and test-planning references.
verify() Lockfile Filesystem backend UCD client Endpoint discovery createUCDStore() verify() Lockfile Filesystem backend UCD client Endpoint discovery createUCDStore() alt [no endpointConfig and no client] alt [no client provided] alt [user provided versions] [no user versions] alt [requireExistingStore] [initialize automatically] alt [no versions resolved] alt [writable backend with existing lockfile] [writable backend without lockfile] [read-only backend] alt [invalid versions] opt [verify enabled and versions resolved] Caller createUCDStore(options) normalize defaults + build path filter discoverEndpointsFromConfig(baseUrl) endpoint config or default config createUCDClientWithConfig(...) client instance create backend from fs factory detect lockfile support + path versions.list() for early validation available versions readLockfileOrUndefined() lockfile versions handleVersionConflict(strategy) resolved versions use lockfile/config versions throw missing lockfile error initLockfile() empty/new lockfile written resolve versions from input or config throw read-only backend error verify(context) validation result throw verification error store with files/get/list/tree + mirror/sync/analyze/compare Caller
UCD client files.get() Filesystem backend Path filter files.get() UCD client files.get() Filesystem backend Path filter files.get() alt [version missing] alt [filtered out] alt [local read succeeds] [local read fails and allowApi is false] alt [local file exists] alt [API error] [API returns no data] [API succeeds] alt [local file missing or unreadable and allowApi is true] [local file missing and allowApi is false] Caller files.get(version, filePath, options) validate version is resolved UCDStoreVersionNotFoundError match global + per-call filters blocked UCDStoreFilterError exists(version/filePath) read(version/filePath) file content { data, error: null } UCDStoreGenericError get(version/ucd/filePath) error UCDStoreApiFallbackError null UCDStoreApiFallbackError string or JSON content { data, error: null } UCDStoreGenericError Caller
Lockfile writer Snapshot writer Filesystem backend Tree filter UCD client mirror() Lockfile writer Snapshot writer Filesystem backend Tree filter UCD client mirror() alt [no versions selected] loop [each version] alt [file exists and not force] [download file] par [queued files with concurrency limit] loop [each mirrored version] Caller mirror({ versions, filters, force, concurrency }) validate fs supports mkdir + write empty MirrorReport versions.getFileTree(version) file tree normalize + filter tree file paths to mirror queue directories + files create missing directories exists(localPath) skip files.get(remotePath) file contents write(localPath, content) read mirrored files writeSnapshot(version, hashes + sizes) snapshot written writeLockfile(updated versions + filters) lockfile updated MirrorReport Caller
listFiles() Filesystem backend mirror() Lockfile UCD client sync() listFiles() Filesystem backend mirror() Lockfile UCD client sync() alt [no versions need mirroring] [versions need mirroring] alt [snapshot exists] [no snapshot] loop [each synced version] opt [cleanOrphaned] Caller sync({ versions, force, removeUnavailable, cleanOrphaned }) validate fs supports mkdir + write versions.list() available API versions readLockfileOrUndefined() current lockfile state compute added / removed / unchanged / finalVersions write updated lockfile lockfile persisted compute versionsToSync SyncResult with empty MirrorReport mirror({ versions: versionsToSync, ... }) MirrorReport readSnapshot(version) versions.getManifest(version) listFiles(version, { allowApi: false }) actual local files remove orphaned files SyncResult Caller
These sequence diagrams are also the right place to derive scenario matrices:
initialization mode matrix: writable, read-only, lockfile present, lockfile absent
file read matrix: local hit, filtered, local miss, API fallback success, API fallback failure
mirror matrix: empty version set, skips, force re-download, API/tree failure, snapshot update
sync matrix: add/remove versions, force mirror, remove unavailable, orphan cleanup