Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/bookkeeping.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Bookkeeping
name: bookkeeping
on:
schedule:
- cron: '0 0 1 * *' # run at 00:00 on the first day of every month
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/on_pull_request_approved.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
node: [ '18.x' ]
provider: [ 'aws', 'cloudflare', 'hetzner' ]
provider: [ 'aws', 'cloudflare', 'hetzner', 'backblaze' ]
name: build
steps:
- name: environment
Expand All @@ -34,3 +34,5 @@ jobs:
CF_SECRET_ACCESS_KEY: ${{ secrets.CF_SECRET_ACCESS_KEY }}
HETZNER_ACCESS_KEY_ID: ${{ secrets.HETZNER_ACCESS_KEY_ID }}
HETZNER_SECRET_ACCESS_KEY: ${{ secrets.HETZNER_SECRET_ACCESS_KEY }}
BACKBLAZE_ACCESS_KEY_ID: ${{ secrets.BACKBLAZE_ACCESS_KEY_ID }}
BACKBLAZE_SECRET_ACCESS_KEY: ${{ secrets.BACKBLAZE_SECRET_ACCESS_KEY }}
4 changes: 3 additions & 1 deletion .github/workflows/on_pull_request_owner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
matrix:
node: [ '18.x' ]
provider: [ 'aws', 'cloudflare', 'hetzner' ]
provider: [ 'aws', 'cloudflare', 'hetzner', 'backblaze' ]
name: build
steps:
- name: environment
Expand All @@ -32,3 +32,5 @@ jobs:
CF_SECRET_ACCESS_KEY: ${{ secrets.CF_SECRET_ACCESS_KEY }}
HETZNER_ACCESS_KEY_ID: ${{ secrets.HETZNER_ACCESS_KEY_ID }}
HETZNER_SECRET_ACCESS_KEY: ${{ secrets.HETZNER_SECRET_ACCESS_KEY }}
BACKBLAZE_ACCESS_KEY_ID: ${{ secrets.BACKBLAZE_ACCESS_KEY_ID }}
BACKBLAZE_SECRET_ACCESS_KEY: ${{ secrets.BACKBLAZE_SECRET_ACCESS_KEY }}
2 changes: 2 additions & 0 deletions bookkeeping.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
| --- | --- |
| Hetzner | +$54.01 |
| Cloudflare | +$0.00 |
| Backblaze | +$0.00 |
| AWS | -$7.00 |

## By Year
Expand All @@ -28,6 +29,7 @@
| Date | Description | Amount | Provider |
| --- | --- | --- | --- |
| 2025-02-12 | Hetzner Object Storage Billing | -$5.99 | Hetzner |
| 2025-02-12 | Backblaze B2 Billing | +$0.00 | Backblaze |
| 2025-02-10 | Hetzner Cloud Credits | +$60.00 | Hetzner |
| 2025-02-01 | AWS S3 Billing | -$0.28 | AWS |
| 2025-02-01 | Cloudflare R2 Billing | +$0.00 | Cloudflare |
Expand Down
7 changes: 7 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v1.6.1

- New provider: [Backblaze B2](https://www.backblaze.com/cloud-storage).
- New demo: [adapter-s3-backblaze.js](https://github.com/brihter/storage/blob/main/demo/adapter-s3-backblaze.js).

This release ensures integration tests are ran against Backblaze's B2 implementation.

## v1.6.0

- New provider: [Hetzner's Object Storage](https://www.hetzner.com/storage/object-storage/).
Expand Down
24 changes: 24 additions & 0 deletions demo/adapter-s3-backblazejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Storage } from '@brighter/storage-adapter-s3'

const BACKBLAZE_BUCKET = 'my-bucket'
const BACKBLAZE_REGION = '...'
const BACKBLAZE_ACCESS_KEY = '...'
const BACKBLAZE_SECRET_ACCESS_KEY = '...'

const storage = Storage({
path: BACKBLAZE_BUCKET
}, {
endpoint: `https://${BACKBLAZE_REGION}.your-objectstorage.com/`,
credentials: {
accessKeyId: BACKBLAZE_ACCESS_KEY,
secretAccessKey: BACKBLAZE_SECRET_ACCESS_KEY
}
})

const main = async () => {
await storage.write('info.log', 'hi')
const msg = await storage.read('info.log')
console.log(msg)
}

main().catch(console.error)
10 changes: 10 additions & 0 deletions env/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,15 @@
"region": "fsn1",
"signatureVersion": "v4"
}
},
"backblaze": {
"storage": {
"type": "s3",
"path": "conjure-storage-test-331eafd"
},
"storageClient": {
"region": "eu-central-003",
"signatureVersion": "v4"
}
}
}
3 changes: 2 additions & 1 deletion etc/bookkeeping.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ const income = [
const expenses = [
{ provider: 'AWS', desc: 'AWS S3 Billing', amount: 0.28, date: new Date('2023-02-01'), period: 'monthly' },
{ provider: 'Cloudflare', desc: 'Cloudflare R2 Billing', amount: 0.0, date: new Date('2023-02-01'), period: 'monthly' },
{ provider: 'Hetzner', desc: 'Hetzner Object Storage Billing', amount: 5.99, date: new Date('2025-02-12'), period: 'monthly' }
{ provider: 'Hetzner', desc: 'Hetzner Object Storage Billing', amount: 5.99, date: new Date('2025-02-12'), period: 'monthly' },
{ provider: 'Backblaze', desc: 'Backblaze B2 Billing', amount: 0.0, date: new Date('2025-02-12'), period: 'monthly' },
]

generateBookkeeping(income, expenses)
2 changes: 2 additions & 0 deletions ops/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ exports.bucket_aws = bucketAWS.id
exports.bucket_cf = 'conjure-storage-test-4x1a7ff'

exports.bucket_hetzner = 'conjure-storage-test-1a2f2cc'

exports.bucket_backblaze = 'conjure-storage-test-331eafd'
5 changes: 3 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ It offers:

- a unified [storage interface](src/storage/docs/StorageInterface.md) (for seamless switching between providers),
- a [local storage provider](src/storage-adapter-local/readme.md) implementation (enabling local development),
- an [S3 compatible storage provider](src/storage-adapter-s3/readme.md) (supporting AWS S3, Cloudflare R2, ...),
- an [S3 compatible storage provider](src/storage-adapter-s3/readme.md) (AWS S3, Cloudflare R2, Hetzner Object Storage, Backblaze B2, ...),
- a simple, concise [API](src/storage/docs/StorageInterface.md) that's tested against real infrastructure and
- comprehensive [documentation](src/storage/docs/Storage.md).

Expand All @@ -25,7 +25,7 @@ It's API is easy to use and remember. It removes away the complexity of manually
Instead of manually installing and injecting the dependencies, you'll most likely want to use one of the following storage adapters that come pre-bundled with everything required:

* [@brighter/storage-adapter-local](src/storage-adapter-local/) and
* [@brighter/storage-adapter-s3](src/storage-adapter-s3/) (AWS S3, Cloudflare R2, DigitalOcean Spaces, ...).
* [@brighter/storage-adapter-s3](src/storage-adapter-s3/) (AWS S3, Cloudflare R2, Hetzner Object Storage, Backblaze B2, ...).

*Note: Before installing, Node.js 18 or higher is required.*

Expand Down Expand Up @@ -197,6 +197,7 @@ The library is actively tested against the following object storage providers:
- [AWS S3](https://aws.amazon.com/s3/)
- [Cloudflare R2](https://www.cloudflare.com/developer-platform/products/r2/)
- [Hetzner Object Storage](https://www.hetzner.com/storage/object-storage/)
- [Backblaze B2](https://www.backblaze.com/cloud-storage)

## Sponsors

Expand Down
1 change: 1 addition & 0 deletions src/storage-adapter-local/bin/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fi

# integration tests

BACKBLAZE_PROFILE=conjure-usr-ops \
HETZNER_PROFILE=conjure-usr-ops \
CF_PROFILE=conjure-usr-ops \
AWS_PROFILE=conjure-usr-ops \
Expand Down
1 change: 1 addition & 0 deletions src/storage-adapter-s3/bin/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fi

# integration tests

BACKBLAZE_PROFILE=conjure-usr-ops \
HETZNER_PROFILE=conjure-usr-ops \
CF_PROFILE=conjure-usr-ops \
AWS_PROFILE=conjure-usr-ops \
Expand Down
24 changes: 24 additions & 0 deletions src/storage-adapter-s3/env/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const getCredentials = async provider => {
if (provider === 'aws') prefix = 'aws'
if (provider === 'cloudflare') prefix = 'cf'
if (provider === 'hetzner') prefix = 'hetzner'
if (provider === 'backblaze') prefix = 'backblaze'
credentials = {
[process.env[`${prefix.toUpperCase()}_PROFILE`]]: {
[`${prefix}_account_id`]:
Expand Down Expand Up @@ -103,6 +104,28 @@ const hetzner = async (cfg, ctx) => {
return cfg
}

const backblaze = async (cfg, ctx) => {
if (!ctx.specifiedTypes.includes('s3')) {
return cfg
}

if (!cfg.backblaze) {
return cfg
}

let credentials
credentials = await getCredentials('backblaze')
credentials = credentials[process.env.BACKBLAZE_PROFILE]

cfg.backblaze.storageClient.endpoint = `https://s3.${cfg.backblaze.storageClient.region}.backblazeb2.com`
cfg.backblaze.storageClient.credentials = {
accessKeyId: credentials.backblaze_access_key_id,
secretAccessKey: credentials.backblaze_secret_access_key
}

return cfg
}

const loadConfig = async (environment = process.env.NODE_ENV) => {
let ctx = {}
ctx.specifiedTypes = process.argv.filter(p => p.startsWith('--type')).map(p => p.split('=')[1])
Expand All @@ -125,6 +148,7 @@ const loadConfig = async (environment = process.env.NODE_ENV) => {
cfg = await aws(cfg, ctx)
cfg = await cloudflare(cfg, ctx)
cfg = await hetzner(cfg, ctx)
cfg = await backblaze(cfg, ctx)

return cfg
}
Expand Down
Loading