{"id":20766996,"url":"https://github.com/binded/abstract-tus-store","last_synced_at":"2025-03-11T18:51:23.627Z","repository":{"id":57172172,"uuid":"68565133","full_name":"binded/abstract-tus-store","owner":"binded","description":"Black box test suite and interface specification for Tus-like stores","archived":false,"fork":false,"pushed_at":"2016-11-05T21:28:51.000Z","size":30,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-02-15T09:37:46.088Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/binded.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-19T03:18:42.000Z","updated_at":"2019-10-23T20:26:42.000Z","dependencies_parsed_at":"2022-08-24T14:40:56.392Z","dependency_job_id":null,"html_url":"https://github.com/binded/abstract-tus-store","commit_stats":null,"previous_names":["blockai/abstract-tus-store"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binded%2Fabstract-tus-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binded%2Fabstract-tus-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binded%2Fabstract-tus-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binded%2Fabstract-tus-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/binded","download_url":"https://codeload.github.com/binded/abstract-tus-store/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243094590,"owners_count":20235531,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T11:27:10.109Z","updated_at":"2025-03-11T18:51:23.606Z","avatar_url":"https://github.com/binded.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# abstract-tus-store\n\n[![Build Status](https://travis-ci.org/blockai/abstract-tus-store.svg?branch=master)](https://travis-ci.org/blockai/abstract-tus-store)\n\nBlack box test suite and interface specification for [Tus](https://tus.io)-like stores.\nInspired by [abstract-blob-store](https://github.com/maxogden/abstract-blob-store).\n\nTus stores implement an API for creating and writing sequentially to\n\"upload resources\".\n\nThe required interface consists of 4 functions:\n\n  - `create(key[, opts])` creates a new upload resource\n  - `info(uploadId)` returns the current size, final key, size and metadata of an upload resource\n  - `append(uploadId, readStream, [offset,] [opts])` to append to an upload resource\n  - `createReadStream(key)` creates a readable stream for the key\n      (primarily used to test implementation)\n\nOptional interface:\n\n  - `createPartial([opts])` to create a new \"partial\" upload resource\n  - `concat(key, uploadIds, [opts])` concatenate \"partial\" upload resources to key\n  - `del(uploadId)` delete an upload resource to free up resources\n  - `minChunkSize` optional property that announces the minimal amount of\n      bytes to write in an append call (except for the last one)\n\n## Some modules that use this\n\n- [s3-tus-store](https://github.com/blockai/s3-tus-store)\n- [fs-tus-store](https://github.com/blockai/fs-tus-store)\n- [keyed-tus-store](https://github.com/blockai/keyed-tus-store)\n- [tusboy](https://github.com/blockai/tusboy) (express middleware for\n    Tus protocol)\n\nSend a PR adding yours if you write a new one.\n\n## Badge\n\nInclude this badge in your readme if you make a new module that uses the `abstract-tus-store` API:\n\n[![tus-store-compatible](badge.png)](https://github.com/blockai/abstract-tus-store)\n\n## Install\n\n```bash\nnpm install --save-dev abstract-tus-store\n```\n\nRequires Node v6+\n\n## Usage\n\nSee [./test](./test) directory for usage example.\n\nIn your tests:\n\n```javascript\nimport testStore from 'abstract-tus-store'\nimport memStore from 'abstract-tus-store/mem-store'\n\ntestStore({\n  setup() {\n    // Return your store instance (promise supported)\n    return memStore()\n  }\n\n  teardown() {\n    // you can use this hook to clean up, e.g. remove\n    // a temp directory\n  }\n})\n```\n\n## API\n\nThis documentation is mainly targeted at implementers.\n\nGeneral notes:\n\n* All functions must return promises\n* Error classes are available as keys on an `errors` object exported by `abstract-tus-store`, e.g.\n\n   ```javascript\n   import { errors } from 'abstract-tus-store'\n   new errors.UnknownKey('some unknown key')\n   ```\n\nSome terminology and definitions:\n\n* A *key* represents the final destination (in the store) of an *upload\n    resource*'s content and metadata (once the upload is *complete*).\n  * Keys should be used \"as is\" to ensure interoperability with\n      other libraries and external systems. For example, an AWS S3 store\n      should use the *key* directly as the S3 key.\n* An *upload resource*\n  * represents an upload in progress;\n  * is linked to exactly one or zero keys (for *partial uploads*);\n* A *deferred upload* is an upload resource which hasn't been assigned\n    an *upload length* yet.\n* A *partial upload* is an upload with no linked key.\n* An *upload length* is the total expected size of an upload resource\n    (e.g. the size of a file to upload).\n* An *offset* represents how many bytes have been written to an upload\n    resource (so far).\n* An upload resource is *complete* when its offset reaches its\n    upload length.\n* An *upload ID* uniquely identities an upload resource\n  * Upload IDs should be unique and unpredictable so that library users\n      can send/receive them directly to/from untrusted systems.\n\n### create(key[, opts])\n\nCreate a new upload resource that will be stored at `key` once\ncompleted.\n\n* `key`: **String** **required** location of the content and metadata of\n    the completed upload resource\n* `opts.uploadLength`: **Number** expected size of the upload in bytes\n* `opts.metadata`: **Object** arbitrary map of key/values\n\nMust resolve to an object with the following properties:\n\n* `uploadId`: **String** **required** unique, unpredictable identifier for\n    the created upload resource\n\nIf `opts.uploadLength` is not supplied, it must be passed to a\nsubsequent call to `append` or else the upload will never complete.\n\nCalls to create should always return a new and unique upload ID.\n\n### info(uploadId)\n\nGet the `offset` and `uploadLength` of an upload resource.\n\n* `uploadId`: **String** **required** a known upload ID\n\nMust resolve to an object with the following properties:\n\n* `offset`: **Number** **required** offset of the upload resource. Must be\n    present even if the offset is 0 or the upload is already completed.\n* `uploadLength`: **Number** (required if known) upload length of the\n    upload resource.\n* `metadata`: **Object** metadata that was set at creation.\n* `isPartial`: **Boolean** `true` if partial upload\n\nMust throw an `UploadNotFound` error if the upload resource does not\nexist.  Must not attempt to create the upload resource if it does not\nalready exist.\n\n### append(uploadId, data, [offset,] [opts])\n\nAppend data to an upload resource.\n\n* `uploadId`: **String** **required** a known Upload ID\n* `data`: **Readable Stream** **required** Data that will be appended to the upload resource.\n* `offset`: **Number** Optional offset to help prevent data corruption.\n* `opts.beforeComplete`: **Function** (async) function that will be called\n    as `beforeComplete(upload, uploadId)` before completing the upload.\n* `opts.uploadLength`: **Number** Used to set the length of a\n    deferred upload.\n\nResolves to an object with the following properties:\n\n* `offset`: **Number** **required** the new offset of the upload\n* `upload`: **Object** (required if the append causes the upload to\n    complete) the upload object as returned by `info(uploadId)`\n\nData must be read and written to the upload resource until the data\nstream ends or the upload completes (`offset === uploadLength`).\n\nThe optional `offset` parameter can be used to prevent data corruption.\nLet's say you want to continue uploading a file. You get the current\noffset of the upload with a call to `info`, and then call `append` with\na read stream that starts reading the file from `offset`. If `offset`\nhas changed between your call to `read` and `append`, `append` will\nthrow an `OffsetMismatch` error.\n\nIf the call to `append` causes the upload resource to complete, `append`\nmust not resolve until the upload resource's content and metadata become\navailable on its linked key (except for partial uploads which do not\nhave a key). If an object already exists at said key, it must be\noverwritten.\n\nMust throw an `OffsetMismatch` error if the supplied offset is\nincorrect.\n\nMust throw an `UploadNotFound` error if the upload doesn't exist.\n\n### createReadStream(key[, onInfo])\n\nCreates a readable stream to read the key's content from the backing\nstore. This is mostly used for testing implementations.\n\n* `key`: **String** **required** key to read from the store\n* `onInfo`: **Function** optional callback that will be called with\n    an `{ contentLength, metadata }` object\n\n## Optional APIs\n\nTODO...\n\n- `createPartial(opts)` to create a new \"partial\" upload resource\n- `concat(key, uploadIds, [opts])` concatenate \"partial\" upload resources to key\n- `del(uploadId)` delete an upload resource to free up resources\n- `minChunkSize` optional property that announces the minimal amount of\n    bytes that must be written in an append call (except for the last one)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinded%2Fabstract-tus-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbinded%2Fabstract-tus-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinded%2Fabstract-tus-store/lists"}