{"id":16597005,"url":"https://github.com/yakovkhalinsky/backblaze-b2","last_synced_at":"2025-04-13T04:58:56.831Z","repository":{"id":2486894,"uuid":"46591778","full_name":"yakovkhalinsky/backblaze-b2","owner":"yakovkhalinsky","description":"Node.js Library for the Backblaze B2 Storage Service","archived":false,"fork":false,"pushed_at":"2024-02-14T03:16:56.000Z","size":487,"stargazers_count":191,"open_issues_count":29,"forks_count":62,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-13T04:58:49.960Z","etag":null,"topics":["backblaze","nodejs"],"latest_commit_sha":null,"homepage":null,"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/yakovkhalinsky.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-20T23:09:33.000Z","updated_at":"2025-04-02T07:50:59.000Z","dependencies_parsed_at":"2023-12-19T15:07:06.360Z","dependency_job_id":"cc81a21c-68cb-4fc7-a877-91f473b4374d","html_url":"https://github.com/yakovkhalinsky/backblaze-b2","commit_stats":{"total_commits":148,"total_committers":25,"mean_commits":5.92,"dds":0.6824324324324325,"last_synced_commit":"fee559676253b7438f2f738da11a2c37fef2f1dd"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yakovkhalinsky%2Fbackblaze-b2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yakovkhalinsky%2Fbackblaze-b2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yakovkhalinsky%2Fbackblaze-b2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yakovkhalinsky%2Fbackblaze-b2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yakovkhalinsky","download_url":"https://codeload.github.com/yakovkhalinsky/backblaze-b2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248665759,"owners_count":21142123,"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":["backblaze","nodejs"],"created_at":"2024-10-11T23:54:43.065Z","updated_at":"2025-04-13T04:58:56.814Z","avatar_url":"https://github.com/yakovkhalinsky.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Backblaze B2 Node.js Library\n\n[![npm version](https://badge.fury.io/js/backblaze-b2.svg)](https://badge.fury.io/js/backblaze-b2) [![Build Status](https://travis-ci.org/yakovkhalinsky/backblaze-b2.svg?branch=master)](https://travis-ci.org/yakovkhalinsky/backblaze-b2)\n\nA customizable B2 client for Node.js:\n\n* Uses [axios](https://github.com/axios/axios). You can control the axios instance at the request level (see `axios` and `axiosOverride` config arguments) and at the global level (see `axios` config argument at instantiation) so you can use any axios feature.\n* Automatically retries on request failure. You can control retry behaviour using the `retries` argument at instantiation.\n\n## Usage\n\nThis library uses promises, so all actions on a `B2` instance return a promise in the following pattern:\n\n``` javascript\nb2.instanceFunction(arg1, arg2).then(\n    successFn(response) { ... },\n    errorFn(err) { ... }\n);\n```\n\n### Basic Example\n\n```javascript\nconst B2 = require('backblaze-b2');\n\nconst b2 = new B2({\n  applicationKeyId: 'applicationKeyId', // or accountId: 'accountId'\n  applicationKey: 'applicationKey' // or masterApplicationKey\n});\n\nasync function GetBucket() {\n  try {\n    await b2.authorize(); // must authorize first (authorization lasts 24 hrs)\n    let response = await b2.getBucket({ bucketName: 'my-bucket' });\n    console.log(response.data);\n  } catch (err) {\n    console.log('Error getting bucket:', err);\n  }\n}\n```\n\n### Response Object\n\nEach request returns an object with:\n\n* `status` - int, html error Status\n* `statusText`\n* `headers`\n* `config`\n* `request`\n* `data` - actual returned data from backblaze, https://www.backblaze.com/b2/docs/calling.html\n\n### How it works\n\nEach action (see reference below) takes arguments and constructs an axios request. You can add additional axios options at the request level using:\n\n* The `axios` argument (object): each property in this object is added to the axios request object *only if it does not conflict* with an existing property.\n* The `axiosOverride` argument (object): each property in this object is added to the axios request object by *overriding* conflicting properties, if any. Don't use this unless you know what you're doing!\n* Both `axios` and `axiosOverride` work by recursively merging properties, so if you pass ```axios: { headers: { 'your-custom-header': 'header-value' } }```, the entire headers object will not be overridden - each header property (`your-custom-header`) will be compared.\n\n### Reference\n\n```javascript\nconst B2 = require('backblaze-b2');\n\n// All functions on the b2 instance return the response from the B2 API in the success callback\n// i.e. b2.foo(...).then((b2JsonResponse) =\u003e {})\n\n// create B2 object instance\nconst b2 = new B2({\n    applicationKeyId: 'applicationKeyId', // or accountId: 'accountId'\n    applicationKey: 'applicationKey', // or masterApplicationKey\n    // optional:\n    axios: {\n        // overrides the axios instance default config, see https://github.com/axios/axios\n    },\n    retry: {\n        retries: 3 // this is the default\n        // for additional options, see https://github.com/softonic/axios-retry\n    }\n});\n\n// common arguments - you can use these in any of the functions below\nconst common_args = {\n    // axios request level config, see https://github.com/axios/axios#request-config\n    axios: {\n        timeout: 30000 // (example)\n    },\n    axiosOverride: {\n        /* Don't use me unless you know what you're doing! */\n    }\n}\n\n// authorize with provided credentials (authorization expires after 24 hours)\nb2.authorize({\n    // ...common arguments (optional)\n});  // returns promise\n\n// create bucket\nb2.createBucket({\n    bucketName: 'bucketName',\n    bucketType: 'bucketType' // one of `allPublic`, `allPrivate`\n    // ...common arguments (optional)\n});  // returns promise\n\n// delete bucket\nb2.deleteBucket({\n    bucketId: 'bucketId'\n    // ...common arguments (optional)\n});  // returns promise\n\n// list buckets\nb2.listBuckets({\n    // ...common arguments (optional)\n});  // returns promise\n\n// get the bucket\nb2.getBucket({\n    bucketName: 'bucketName',\n    bucketId: 'bucketId' // optional\n    // ...common arguments (optional)\n});  // returns promise\n\n// update bucket\nb2.updateBucket({\n    bucketId: 'bucketId',\n    bucketType: 'bucketType'\n    // ...common arguments (optional)\n});  // returns promise\n\n// get upload url\nb2.getUploadUrl({\n    bucketId: 'bucketId'\n    // ...common arguments (optional)\n});  // returns promise\n\n// upload file\nb2.uploadFile({\n    uploadUrl: 'uploadUrl',\n    uploadAuthToken: 'uploadAuthToken',\n    fileName: 'fileName',\n    contentLength: 0, // optional data length, will default to data.byteLength or data.length if not provided\n    mime: '', // optional mime type, will default to 'b2/x-auto' if not provided\n    data: 'data', // this is expecting a Buffer, not an encoded string\n    hash: 'sha1-hash', // optional data hash, will use sha1(data) if not provided\n    info: {\n        // optional info headers, prepended with X-Bz-Info- when sent, throws error if more than 10 keys set\n        // valid characters should be a-z, A-Z and '-', all other characters will cause an error to be thrown\n        key1: 'value',\n        key2: 'value'\n    },\n    onUploadProgress: (event) =\u003e {} || null // progress monitoring\n    // ...common arguments (optional)\n});  // returns promise\n\n// list file names\nb2.listFileNames({\n    bucketId: 'bucketId',\n    startFileName: 'startFileName',\n    maxFileCount: 100,\n    delimiter: '',\n    prefix: ''\n    // ...common arguments (optional)\n});  // returns promise\n\n// list file versions\nb2.listFileVersions({\n    bucketId: 'bucketId',\n    startFileName: 'startFileName',\n    startFileId: 'startFileId',\n    maxFileCount: 100\n    // ...common arguments (optional)\n});  // returns promise\n\n// list uploaded parts for a large file\nb2.listParts({\n    fileId: 'fileId',\n    startPartNumber: 0, // optional\n    maxPartCount: 100, // optional (max: 1000)\n    // ...common arguments (optional)\n});  // returns promise\n\n// hide file\nb2.hideFile({\n    bucketId: 'bucketId',\n    fileName: 'fileName'\n    // ...common arguments (optional)\n});  // returns promise\n\n// get file info\nb2.getFileInfo({\n    fileId: 'fileId'\n    // ...common arguments (optional)\n});  // returns promise\n\n// get download authorization\nb2.getDownloadAuthorization({\n    bucketId: 'bucketId',\n    fileNamePrefix: 'fileNamePrefix',\n    validDurationInSeconds: 'validDurationInSeconds', // a number from 0 to 604800\n    b2ContentDisposition: 'b2ContentDisposition'\n    // ...common arguments (optional)\n});  // returns promise\n\n// download file by name\nb2.downloadFileByName({\n    bucketName: 'bucketName',\n    fileName: 'fileName',\n    responseType: 'arraybuffer', // options are as in axios: 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'\n    onDownloadProgress: (event) =\u003e {} || null // progress monitoring\n    // ...common arguments (optional)\n});  // returns promise\n\n// download file by fileId\nb2.downloadFileById({\n    fileId: 'fileId',\n    responseType: 'arraybuffer', // options are as in axios: 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'\n    onDownloadProgress: (event) =\u003e {} || null // progress monitoring\n    // ...common arguments (optional)\n});  // returns promise\n\n// delete file version\nb2.deleteFileVersion({\n    fileId: 'fileId',\n    fileName: 'fileName'\n    // ...common arguments (optional)\n});  // returns promise\n\n// start large file\nb2.startLargeFile({\n    bucketId: 'bucketId',\n    fileName: 'fileName'\n    // ...common arguments (optional)\n}); // returns promise\n\n// get upload part url\nb2.getUploadPartUrl({\n    fileId: 'fileId'\n    // ...common arguments (optional)\n}); // returns promise\n\n// get upload part\nb2.uploadPart({\n    partNumber: 'partNumber', // A number from 1 to 10000\n    uploadUrl: 'uploadUrl',\n    uploadAuthToken: 'uploadAuthToken', // comes from getUploadPartUrl();\n    data: Buffer // this is expecting a Buffer not an encoded string,\n    hash: 'sha1-hash', // optional data hash, will use sha1(data) if not provided\n    onUploadProgress: (event) =\u003e {} || null, // progress monitoring\n    contentLength: 0, // optional data length, will default to data.byteLength or data.length if not provided\n    // ...common arguments (optional)\n}); // returns promise\n\n// finish large file\nb2.finishLargeFile({\n    fileId: 'fileId',\n    partSha1Array: [partSha1Array] // array of sha1 for each part\n    // ...common arguments (optional)\n}); // returns promise\n\n// cancel large file\nb2.cancelLargeFile({\n    fileId: 'fileId'\n    // ...common arguments (optional)\n}); // returns promise\n\n// create key\nb2.createKey({\n    capabilities: [\n        'readFiles',                    // option 1\n        b2.KEY_CAPABILITIES.READ_FILES, // option 2\n        // see https://www.backblaze.com/b2/docs/b2_create_key.html for full list\n    ],\n    keyName: 'my-key-1', // letters, numbers, and '-' only, \u003c=100 chars\n    validDurationInSeconds: 3600, // expire after duration (optional)\n    bucketId: 'bucketId', // restrict access to bucket (optional)\n    namePrefix: 'prefix_', // restrict access to file prefix (optional)\n    // ...common arguments (optional)\n});  // returns promise\n\n// delete key\nb2.deleteKey({\n    applicationKeyId: 'applicationKeyId',\n    // ...common arguments (optional)\n});  // returns promise\n\n// list keys\nb2.listKeys({\n    maxKeyCount: 10, // limit number of keys returned (optional)\n    startApplicationKeyId: '...', // use `nextApplicationKeyId` from previous response when `maxKeyCount` is set (optional)\n    // ...common arguments (optional)\n});  // returns promise\n```\n\n### Uploading Large Files Example\n\nTo upload large files, you should split the file into parts (between 5MB and 5GB) and upload each part seperately.\n\nFirst, you initiate the large file upload to get the fileId:\n\n```javascript\nlet response = await b2.startLargeFile({ bucketId, fileName });\nlet fileId = response.data.fileId;\n```\n\nThen, to upload parts, you request at least one `uploadUrl` and use the response to\nupload the part with `uploadPart`. The url and token returned by `getUploadPartUrl()`\nare valid for 24 hours or until `uploadPart()` fails, in which case you should request\nanother `uploadUrl` to continue. You may utilize multiple `uploadUrl`s in parallel to\nachieve greater upload throughput.\n\nIf you are unsure whether you should use multipart upload, refer to the `recommendedPartSize`\nvalue returned by a call to `authorize()`.\n\n```javascript\nlet response = await b2.getUploadPartUrl({ fileId });\n\nlet uploadURL = response.data.uploadUrl;\nlet authToken = response.data.authorizationToken;\n\nresponse = await b2.uploadPart({\n    partNumber: parNum,\n    uploadUrl: uploadURL,\n    uploadAuthToken: authToken,\n    data: buf\n});\n// status checks etc.\n```\n\nThen finish the uploadUrl:\n\n```javascript\nlet response = await b2.finishLargeFile({\n    fileId,\n    partSha1Array: parts.map(buf =\u003e sha1(buf))\n})\n```\n\nIf an upload is interrupted, the fileId can be used to get a list of parts\nwhich have already been transmitted. You can then send the remaining\nparts before finally calling `b2.finishLargeFile()`.\n\n```javascript\nlet response = await b2.listParts({\n    fileId,\n    startPartNumber: 0,\n    maxPartCount: 1000\n})\n```\n\n## Changes\n\nSee the [CHANGELOG](https://github.com/yakovkhalinsky/backblaze-b2/blob/master/CHANGELOG.md) for a history of updates.\n\n### Upgrading from 0.9.x to 1.0.x\n\nFor this update, we've switched the back end HTTP request library from `request` to `axios` as it has better Promise and progress support built in. However, there are a couple changes that will break your code and ruin your day. Here are the changes:\n\n* The Promise resolution has a different data structure. Where previously, the request response data was the root object in the promise resolution (`res`), this data now resides in `res.data`.\n* In v0.9.12, we added request progress reporting via the third parameter to `then()`. Because we are no longer using the same promise library, this functionality has been removed. However, progress reporting is still available by passing a callback function into the `b2.method()` that you're calling. See the documentation below for details.\n* In v0.9.x, `b2.downloadFileById()` accepted a `fileId` parameter as a String or Number. As of 1.0.0, the first parameter is now expected to be a plain Object of arguments.\n\n## Contributing\n\nContributions, suggestions, and questions are welcome. Please review the [contributing guidelines](CONTRIBUTING.md) for details.\n\n### Authors and Contributors\n\n* Yakov Khalinsky (@yakovkhalinsky)\n* Ivan Kalinin (@IvanKalinin) at Isolary\n* Brandon Patton (@crazyscience) at Isolary\n* C. Bess (@cbess)\n* Amit (@Amit-A)\n* Zsombor Paróczi (@realhidden)\n* Oden (@odensc)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyakovkhalinsky%2Fbackblaze-b2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyakovkhalinsky%2Fbackblaze-b2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyakovkhalinsky%2Fbackblaze-b2/lists"}