streamby-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -0
- package/dist/adapters/gcs.d.ts +0 -0
- package/dist/adapters/gcs.js +1 -0
- package/dist/adapters/local.d.ts +0 -0
- package/dist/adapters/local.js +1 -0
- package/dist/adapters/s3.d.ts +2 -0
- package/dist/adapters/s3.js +33 -0
- package/dist/config.d.ts +0 -0
- package/dist/config.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/middleware/createRouter.d.ts +5 -0
- package/dist/middleware/createRouter.js +41 -0
- package/dist/services/auth.d.ts +4 -0
- package/dist/services/auth.js +19 -0
- package/dist/services/file.d.ts +4 -0
- package/dist/services/file.js +10 -0
- package/dist/types/index.d.ts +29 -0
- package/dist/types/index.js +2 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# @streamby/core
|
|
2
|
+
|
|
3
|
+
Middleware framework for building storage-agnostic media APIs.
|
|
4
|
+
Part of the [StreamBy](https://streamby.nhexa.cl) ecosystem by TerminalCore Labs.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## ๐ What is it?
|
|
9
|
+
|
|
10
|
+
`@streamby/core` is a plug-and-play middleware for Express (or compatible frameworks) that enables file uploads, listings and project-based access over services like:
|
|
11
|
+
|
|
12
|
+
- โ
AWS S3
|
|
13
|
+
- โ
Google Cloud Storage (soon)
|
|
14
|
+
- โ
Cloudflare R2 (soon)
|
|
15
|
+
- โ
Local/Personal servers (soon)
|
|
16
|
+
|
|
17
|
+
It's designed to be installed inside your existing API as a library โ **no need to run a separate backend**.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## ๐ฆ Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @streamby/core
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## ๐งฑ Basic usage
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import express from 'express';
|
|
33
|
+
import { createStreamByRouter } from '@streamby/core';
|
|
34
|
+
|
|
35
|
+
const app = express();
|
|
36
|
+
|
|
37
|
+
app.use('/streamby', createStreamByRouter({
|
|
38
|
+
storageProvider: {
|
|
39
|
+
type: 's3',
|
|
40
|
+
config: {
|
|
41
|
+
bucket: 'your-bucket-name',
|
|
42
|
+
region: 'your-region',
|
|
43
|
+
accessKeyId: 'YOUR_AWS_KEY',
|
|
44
|
+
secretAccessKey: 'YOUR_AWS_SECRET'
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
authProvider: async (req) => {
|
|
48
|
+
// validate token, session, etc.
|
|
49
|
+
return {
|
|
50
|
+
userId: 'demo',
|
|
51
|
+
projectId: 'demo-project',
|
|
52
|
+
role: 'admin',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
app.listen(3000);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## ๐งช Testing
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm run test
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Unit tests use [Vitest](https://vitest.dev) and [Supertest](https://www.npmjs.com/package/supertest).
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ๐ Features
|
|
73
|
+
|
|
74
|
+
- ๐งน Modular adapters per storage provider
|
|
75
|
+
- ๐ Auth/permission integration per request
|
|
76
|
+
- ๐ File listing, uploading and deletion
|
|
77
|
+
- ๐งฐ Built-in testability with mock adapters
|
|
78
|
+
- โก Easy to extend and compose
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## ๐ฃ Roadmap
|
|
83
|
+
|
|
84
|
+
- [ ] Support for Google Cloud Storage
|
|
85
|
+
- [ ] CLI tool for uploading files
|
|
86
|
+
- [ ] Role-based access control middleware
|
|
87
|
+
- [ ] Plugin system for extended routes
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## ๐งโ๐ป Maintained by
|
|
92
|
+
|
|
93
|
+
**TerminalCore Labs** โ part of [Nhexa Entertainment](https://nhexa.cl)
|
|
94
|
+
Developed as open-source infrastructure for creative and media-oriented apps.
|
|
95
|
+
|
|
96
|
+
Visit us [here](https://terminalcore.cl)
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## ๐ License
|
|
101
|
+
|
|
102
|
+
[MIT](./LICENSE)
|
|
103
|
+
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createS3Adapter = createS3Adapter;
|
|
4
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
5
|
+
function createS3Adapter(config) {
|
|
6
|
+
const s3 = new client_s3_1.S3Client({
|
|
7
|
+
region: config.region,
|
|
8
|
+
credentials: {
|
|
9
|
+
accessKeyId: config.accessKeyId,
|
|
10
|
+
secretAccessKey: config.secretAccessKey,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
async uploadFile(req, projectId) {
|
|
15
|
+
const file = req.body.file;
|
|
16
|
+
const command = new client_s3_1.PutObjectCommand({
|
|
17
|
+
Bucket: config.bucket,
|
|
18
|
+
Key: `${projectId}/${file.name}`,
|
|
19
|
+
Body: file.buffer,
|
|
20
|
+
});
|
|
21
|
+
await s3.send(command);
|
|
22
|
+
return { success: true, key: command.input.Key };
|
|
23
|
+
},
|
|
24
|
+
async listFiles(projectId) {
|
|
25
|
+
const command = new client_s3_1.ListObjectsV2Command({
|
|
26
|
+
Bucket: config.bucket,
|
|
27
|
+
Prefix: `${projectId}/`
|
|
28
|
+
});
|
|
29
|
+
const result = await s3.send(command);
|
|
30
|
+
return result.Contents || [];
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
package/dist/config.d.ts
ADDED
|
File without changes
|
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createStreamByRouter } from './middleware/createRouter';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createStreamByRouter = void 0;
|
|
4
|
+
var createRouter_1 = require("./middleware/createRouter");
|
|
5
|
+
Object.defineProperty(exports, "createStreamByRouter", { enumerable: true, get: function () { return createRouter_1.createStreamByRouter; } });
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createStreamByRouter = createStreamByRouter;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const s3_1 = require("../adapters/s3");
|
|
9
|
+
const file_1 = require("../services/file");
|
|
10
|
+
function createStreamByRouter(config) {
|
|
11
|
+
const router = express_1.default.Router();
|
|
12
|
+
const adapter = config.adapter || (() => {
|
|
13
|
+
switch (config.storageProvider.type) {
|
|
14
|
+
case 's3':
|
|
15
|
+
return (0, s3_1.createS3Adapter)(config.storageProvider.config);
|
|
16
|
+
default:
|
|
17
|
+
throw new Error('Unsupported storage type');
|
|
18
|
+
}
|
|
19
|
+
})();
|
|
20
|
+
router.get('/files', async (req, res) => {
|
|
21
|
+
try {
|
|
22
|
+
const auth = await config.authProvider(req);
|
|
23
|
+
const files = await (0, file_1.listFilesService)(adapter, req, auth.projectId);
|
|
24
|
+
res.json(files);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
res.status(500).json({ error: 'Failed to list files', details: err });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
router.post('/upload', async (req, res) => {
|
|
31
|
+
try {
|
|
32
|
+
const auth = await config.authProvider(req);
|
|
33
|
+
const result = await (0, file_1.uploadFileService)(adapter, req, auth.projectId);
|
|
34
|
+
res.json(result);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
res.status(500).json({ error: 'Failed to upload file', details: err });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return router;
|
|
41
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
import { StreamByConfig, AuthContext } from '../types';
|
|
3
|
+
export declare function resolveAuth(config: StreamByConfig, req: Request): Promise<AuthContext>;
|
|
4
|
+
export declare function checkRole(auth: AuthContext, required: 'viewer' | 'editor' | 'admin'): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveAuth = resolveAuth;
|
|
4
|
+
exports.checkRole = checkRole;
|
|
5
|
+
async function resolveAuth(config, req) {
|
|
6
|
+
const auth = await config.authProvider(req);
|
|
7
|
+
if (!auth || !auth.userId || !auth.projectId || !auth.role) {
|
|
8
|
+
throw new Error('Invalid or missing authentication context');
|
|
9
|
+
}
|
|
10
|
+
return auth;
|
|
11
|
+
}
|
|
12
|
+
function checkRole(auth, required) {
|
|
13
|
+
const roles = ['viewer', 'editor', 'admin'];
|
|
14
|
+
const userIdx = roles.indexOf(auth.role);
|
|
15
|
+
const requiredIdx = roles.indexOf(required);
|
|
16
|
+
if (userIdx < requiredIdx) {
|
|
17
|
+
throw new Error(`Insufficient role: requires ${required}, found ${auth.role}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { StorageAdapter } from '../types';
|
|
2
|
+
import { Request } from 'express';
|
|
3
|
+
export declare function listFilesService(adapter: StorageAdapter, req: Request, projectId: string): Promise<any[]>;
|
|
4
|
+
export declare function uploadFileService(adapter: StorageAdapter, req: Request, projectId: string): Promise<any>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listFilesService = listFilesService;
|
|
4
|
+
exports.uploadFileService = uploadFileService;
|
|
5
|
+
async function listFilesService(adapter, req, projectId) {
|
|
6
|
+
return adapter.listFiles(projectId);
|
|
7
|
+
}
|
|
8
|
+
async function uploadFileService(adapter, req, projectId) {
|
|
9
|
+
return adapter.uploadFile(req, projectId);
|
|
10
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
export interface S3Config {
|
|
3
|
+
bucket: string;
|
|
4
|
+
region: string;
|
|
5
|
+
accessKeyId: string;
|
|
6
|
+
secretAccessKey: string;
|
|
7
|
+
}
|
|
8
|
+
export type StorageProviderType = 's3';
|
|
9
|
+
export interface StorageAdapter {
|
|
10
|
+
uploadFile(req: Request, projectId: string): Promise<any>;
|
|
11
|
+
listFiles(projectId: string): Promise<any[]>;
|
|
12
|
+
}
|
|
13
|
+
export interface StreamByConfig {
|
|
14
|
+
storageProvider: {
|
|
15
|
+
type: StorageProviderType;
|
|
16
|
+
config: S3Config;
|
|
17
|
+
};
|
|
18
|
+
authProvider: (req: Request) => Promise<{
|
|
19
|
+
userId: string;
|
|
20
|
+
projectId: string;
|
|
21
|
+
role: 'viewer' | 'editor' | 'admin';
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
export interface AuthContext {
|
|
25
|
+
userId: string;
|
|
26
|
+
projectId: string;
|
|
27
|
+
role: 'viewer' | 'editor' | 'admin';
|
|
28
|
+
}
|
|
29
|
+
export type AuthProvider = (req: Request) => Promise<AuthContext>;
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "streamby-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "StreamBy middleware framework for media storage management",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "vitest",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/GwerhDev/StreamBy-Package.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"streamby",
|
|
22
|
+
"middleware",
|
|
23
|
+
"upload",
|
|
24
|
+
"storage",
|
|
25
|
+
"s3",
|
|
26
|
+
"express",
|
|
27
|
+
"typescript"
|
|
28
|
+
],
|
|
29
|
+
"author": "TerminalCore Labs",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@aws-sdk/client-s3": "^3.528.0",
|
|
33
|
+
"express": "^4.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/express": "^4.17.17",
|
|
37
|
+
"@types/supertest": "^6.0.3",
|
|
38
|
+
"supertest": "^7.1.0",
|
|
39
|
+
"typescript": "^5.8.3",
|
|
40
|
+
"vitest": "^3.1.1"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"express": "^4.0.0"
|
|
44
|
+
}
|
|
45
|
+
}
|