CONTRACT.md 2.2 KB

Media Manager Contract

  • media-manager is dumb and generic: it only parses multipart streams and writes them to storage.
  • The library never decides filenames, folders, MIME rules, limits, auth, URLs, or database writes.
  • Each caller provides the full relative path (including filename) for every uploaded file, e.g. tea/452/photo.jpg.

Storage Strategies

  1. LOCAL_ONLY – persist only to local storage using <localRoot>/<localStoragePrefix>/<relativePath> (prefix defaults to local).
  2. S3_ONLY – always stage the file locally, upload the staged file to S3 (key == relativePath), and delete the stage on success. Failure rolls back the stage and returns status=0.
  3. S3_AND_LOCAL – stage locally and try to upload to S3. If S3 succeeds, both storages are considered written (status=1, storageStrategy='S3_AND_LOCAL'). If S3 fails, the local stage remains and the result downgrades to storageStrategy='LOCAL_ONLY' with savedPath pointing at the local file (status=1).

Inputs & Constraints

  • upload(storageStrategy, relativePath[], localStoragePrefix?) must include exactly one file stream and one relative path entry. If not, return failure before touching any storage.
  • Every relativePath entry must be strictly relative (no leading /, drive letters, or ..) and must include a filename.
  • Mapping is 1:1 in order: relativePath[i] corresponds to the ith file stream.

Outputs

{
  status: 0 | 1,
  storageStrategy: 'LOCAL_ONLY' | 'S3_ONLY' | 'S3_AND_LOCAL',
  relativePath: string[],
  savedPath: string // absolute local path or `s3://bucket/key`
}
  • storageStrategy should reflect what was actually persisted (downgrading to LOCAL_ONLY when S3 fails).
  • savedPath is the raw locator returned by the successful adapter: local absolute path for local persistence, or s3://bucket/key when S3 won.

Cleanup

  • cleanup(storageStrategy, relativePath[], localStoragePrefix?) deletes exactly the requested paths/keys according to the strategy.
  • For S3_AND_LOCAL, attempt both deletes; return status=1 only when every requested deletion succeeded.
  • No recursive deletion, no filesystem traversal beyond resolving <localStoragePrefix>/<relativePath>.