Prototype: FileCatalog.upload(name,size) requires nonempty name/nonnegative safe integer size, returns bool; duplicate preserves old size. get returns byte count including zero or null.
Final: FileStorage(quota) requires nonnegative integer and starts time/usage 0. advanceTo(timestamp) requires monotonic nonnegative integer, expires at expiresAt<=timestamp, releases quota once; only this method changes time. upload(name,size,ttl=null) validates nonempty name, nonnegative size, positive optional TTL before duplicate/quota checks; success charges and sets currentTime+ttl or null. get returns {name,size,expiresAt} or null. copy(source,destination) validates destination first, fails unchanged for missing/existing/over-quota, charges full size and preserves absolute expiry. delete releases once and returns bool. usage is payload byte total. search(prefix,limit=10) returns fresh snapshots sorted size descending/name; negative/noninteger limit raises, zero empty. Expired names reusable; no overwrite/filesystem access.
Every class is exported by name from exercise.mjs. Keep instances independent. Unless explicitly documented otherwise, input values have the stated collection/string types and do not contain null elements. Invalid calls preserve state; validate before mutation. Return fresh mutable snapshots unless stated otherwise.
Complete the starter code, then run the checks.
Results and errors will appear here.