streamby-core 0.21.6 β†’ 0.21.7

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 CHANGED
@@ -1,206 +1,206 @@
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 **multi-project 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
- // extract token/cookie and validate
49
- return {
50
- userId: 'demo',
51
- projects: ['demo-project'],
52
- role: 'admin',
53
- };
54
- },
55
- projectProvider: async (projectId) => {
56
- // fetch project from your DB
57
- return {
58
- id: projectId,
59
- name: 'Demo Project',
60
- description: 'Demo for StreamBy integration',
61
- rootFolders: [],
62
- settings: { allowUpload: true }
63
- };
64
- }
65
- }));
66
-
67
- app.listen(3000);
68
- ```
69
-
70
- ---
71
-
72
- ## πŸ§ͺ Testing
73
-
74
- ```bash
75
- npm run test
76
- ```
77
-
78
- Unit tests use [Vitest](https://vitest.dev) and [Supertest](https://www.npmjs.com/package/supertest).
79
-
80
- ---
81
-
82
- ## πŸ“ Features
83
-
84
- - πŸ“‚ Multi-project access control
85
- - πŸ” Project-aware file uploads & listings
86
- - 🧹 Modular adapters per storage provider
87
- - 🧰 Built-in testability with mock auth & storage
88
- - ✨ Simple to extend for custom business logic
89
-
90
- ---
91
-
92
- ## πŸ—ΊοΈ API Endpoints
93
-
94
- Here's a summary of the key API endpoints provided by `@streamby/core`:
95
-
96
- ### `GET /streamby/projects`
97
-
98
- Lists all projects accessible by the authenticated user.
99
-
100
- **Query Parameters:**
101
- - `archived`: (Optional) Filter projects by their archived status.
102
- - `true`: Returns only archived projects.
103
- - `false`: Returns only unarchived projects.
104
- - (Omitted): Returns all projects (both archived and unarchived).
105
-
106
- **Example Response:**
107
- ```json
108
- {
109
- "projects": [
110
- {
111
- "id": "project1_id",
112
- "dbType": "nosql",
113
- "name": "My NoSQL Project",
114
- "image": "url_to_image",
115
- "archived": false
116
- },
117
- {
118
- "id": "project2_id",
119
- "dbType": "sql",
120
- "name": "My SQL Project",
121
- "image": "url_to_image",
122
- "archived": true
123
- }
124
- ]
125
- }
126
- ```
127
-
128
- ### `PATCH /streamby/projects/:id/archive`
129
-
130
- Archives a specific project. After archiving, it returns the complete list of projects for the user, including the updated project.
131
-
132
- **Example Response:**
133
- ```json
134
- {
135
- "success": true,
136
- "projects": [
137
- {
138
- "id": "project1_id",
139
- "dbType": "nosql",
140
- "name": "My NoSQL Project",
141
- "image": "url_to_image",
142
- "archived": true
143
- },
144
- {
145
- "id": "project2_id",
146
- "dbType": "sql",
147
- "name": "My SQL Project",
148
- "image": "url_to_image",
149
- "archived": false
150
- }
151
- ]
152
- }
153
- ```
154
-
155
- ### `PATCH /streamby/projects/:id/unarchive`
156
-
157
- Unarchives a specific project. After unarchiving, it returns the complete list of projects for the user, including the updated project.
158
-
159
- **Example Response:**
160
- ```json
161
- {
162
- "success": true,
163
- "projects": [
164
- {
165
- "id": "project1_id",
166
- "dbType": "nosql",
167
- "name": "My NoSQL Project",
168
- "image": "url_to_image",
169
- "archived": false
170
- },
171
- {
172
- "id": "project2_id",
173
- "dbType": "sql",
174
- "name": "My SQL Project",
175
- "image": "url_to_image",
176
- "archived": false
177
- }
178
- ]
179
- }
180
- ```
181
-
182
- ---
183
-
184
- ## 🚣 Roadmap
185
-
186
- - [ ] Support for Google Cloud Storage
187
- - [ ] CLI tool for uploading files
188
- - [ ] Role-based access control middleware
189
- - [ ] Plugin system for extended routes
190
- - [ ] Streaming support (HLS, audio, etc.)
191
-
192
- ---
193
-
194
- ## πŸ§‘β€πŸ’» Maintained by
195
-
196
- **TerminalCore Labs** – part of [Nhexa Entertainment](https://nhexa.cl)
197
- Developed as open-source infrastructure for creative and media-oriented apps.
198
-
199
- Visit us [here](https://terminalcore.cl)
200
-
201
- ---
202
-
203
- ## πŸ“Ÿ License
204
-
205
- [MIT](./LICENSE)
206
-
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 **multi-project 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
+ // extract token/cookie and validate
49
+ return {
50
+ userId: 'demo',
51
+ projects: ['demo-project'],
52
+ role: 'admin',
53
+ };
54
+ },
55
+ projectProvider: async (projectId) => {
56
+ // fetch project from your DB
57
+ return {
58
+ id: projectId,
59
+ name: 'Demo Project',
60
+ description: 'Demo for StreamBy integration',
61
+ rootFolders: [],
62
+ settings: { allowUpload: true }
63
+ };
64
+ }
65
+ }));
66
+
67
+ app.listen(3000);
68
+ ```
69
+
70
+ ---
71
+
72
+ ## πŸ§ͺ Testing
73
+
74
+ ```bash
75
+ npm run test
76
+ ```
77
+
78
+ Unit tests use [Vitest](https://vitest.dev) and [Supertest](https://www.npmjs.com/package/supertest).
79
+
80
+ ---
81
+
82
+ ## πŸ“ Features
83
+
84
+ - πŸ“‚ Multi-project access control
85
+ - πŸ” Project-aware file uploads & listings
86
+ - 🧹 Modular adapters per storage provider
87
+ - 🧰 Built-in testability with mock auth & storage
88
+ - ✨ Simple to extend for custom business logic
89
+
90
+ ---
91
+
92
+ ## πŸ—ΊοΈ API Endpoints
93
+
94
+ Here's a summary of the key API endpoints provided by `@streamby/core`:
95
+
96
+ ### `GET /streamby/projects`
97
+
98
+ Lists all projects accessible by the authenticated user.
99
+
100
+ **Query Parameters:**
101
+ - `archived`: (Optional) Filter projects by their archived status.
102
+ - `true`: Returns only archived projects.
103
+ - `false`: Returns only unarchived projects.
104
+ - (Omitted): Returns all projects (both archived and unarchived).
105
+
106
+ **Example Response:**
107
+ ```json
108
+ {
109
+ "projects": [
110
+ {
111
+ "id": "project1_id",
112
+ "dbType": "nosql",
113
+ "name": "My NoSQL Project",
114
+ "image": "url_to_image",
115
+ "archived": false
116
+ },
117
+ {
118
+ "id": "project2_id",
119
+ "dbType": "sql",
120
+ "name": "My SQL Project",
121
+ "image": "url_to_image",
122
+ "archived": true
123
+ }
124
+ ]
125
+ }
126
+ ```
127
+
128
+ ### `PATCH /streamby/projects/:id/archive`
129
+
130
+ Archives a specific project. After archiving, it returns the complete list of projects for the user, including the updated project.
131
+
132
+ **Example Response:**
133
+ ```json
134
+ {
135
+ "success": true,
136
+ "projects": [
137
+ {
138
+ "id": "project1_id",
139
+ "dbType": "nosql",
140
+ "name": "My NoSQL Project",
141
+ "image": "url_to_image",
142
+ "archived": true
143
+ },
144
+ {
145
+ "id": "project2_id",
146
+ "dbType": "sql",
147
+ "name": "My SQL Project",
148
+ "image": "url_to_image",
149
+ "archived": false
150
+ }
151
+ ]
152
+ }
153
+ ```
154
+
155
+ ### `PATCH /streamby/projects/:id/unarchive`
156
+
157
+ Unarchives a specific project. After unarchiving, it returns the complete list of projects for the user, including the updated project.
158
+
159
+ **Example Response:**
160
+ ```json
161
+ {
162
+ "success": true,
163
+ "projects": [
164
+ {
165
+ "id": "project1_id",
166
+ "dbType": "nosql",
167
+ "name": "My NoSQL Project",
168
+ "image": "url_to_image",
169
+ "archived": false
170
+ },
171
+ {
172
+ "id": "project2_id",
173
+ "dbType": "sql",
174
+ "name": "My SQL Project",
175
+ "image": "url_to_image",
176
+ "archived": false
177
+ }
178
+ ]
179
+ }
180
+ ```
181
+
182
+ ---
183
+
184
+ ## 🚣 Roadmap
185
+
186
+ - [ ] Support for Google Cloud Storage
187
+ - [ ] CLI tool for uploading files
188
+ - [ ] Role-based access control middleware
189
+ - [ ] Plugin system for extended routes
190
+ - [ ] Streaming support (HLS, audio, etc.)
191
+
192
+ ---
193
+
194
+ ## πŸ§‘β€πŸ’» Maintained by
195
+
196
+ **TerminalCore Labs** – part of [Nhexa Entertainment](https://nhexa.cl)
197
+ Developed as open-source infrastructure for creative and media-oriented apps.
198
+
199
+ Visit us [here](https://terminalcore.cl)
200
+
201
+ ---
202
+
203
+ ## πŸ“Ÿ License
204
+
205
+ [MIT](./LICENSE)
206
+
@@ -6,8 +6,10 @@ const manager_1 = require("../../models/manager");
6
6
  const auth_1 = require("../../utils/auth");
7
7
  const connectionManager_1 = require("../../adapters/database/connectionManager");
8
8
  const sql_1 = require("../../adapters/database/sql");
9
+ const auth_2 = require("../../services/auth");
9
10
  function projectRouter(config) {
10
11
  const router = (0, express_1.Router)();
12
+ router.use((0, auth_2.authenticate)(config));
11
13
  const Project = (0, manager_1.getModel)('projects');
12
14
  const mapProjectToResponseFormat = (project, userId) => {
13
15
  const currentUserMember = project.members?.find((member) => member.userId === userId);
@@ -21,12 +23,7 @@ function projectRouter(config) {
21
23
  };
22
24
  router.get('/projects', async (req, res) => {
23
25
  try {
24
- const auth = await config.authProvider(req);
25
- if (!auth ||
26
- !auth.userId ||
27
- !auth.role) {
28
- return res.status(401).json({ error: 'Unauthorized' });
29
- }
26
+ const auth = req.auth;
30
27
  const archivedQuery = req.query.archived;
31
28
  const filterArchived = archivedQuery !== undefined ? String(archivedQuery).toLowerCase() === 'true' : undefined;
32
29
  const allProjects = await Project.find({}); // Fetch all projects
@@ -51,12 +48,7 @@ function projectRouter(config) {
51
48
  });
52
49
  router.post('/projects/create', async (req, res) => {
53
50
  try {
54
- const auth = await config.authProvider(req);
55
- if (!auth ||
56
- !auth.userId ||
57
- !auth.role) {
58
- return res.status(401).json({ error: 'Unauthorized' });
59
- }
51
+ const auth = req.auth;
60
52
  if (auth.role !== 'admin' && auth.role !== 'editor') {
61
53
  return res.status(403).json({ error: 'Permission denied' });
62
54
  }
@@ -86,12 +78,7 @@ function projectRouter(config) {
86
78
  });
87
79
  router.get('/projects/:id', async (req, res) => {
88
80
  try {
89
- const auth = await config.authProvider(req);
90
- if (!auth ||
91
- !auth.userId ||
92
- !auth.role) {
93
- return res.status(401).json({ error: 'Unauthorized' });
94
- }
81
+ const auth = req.auth;
95
82
  const projectId = req.params.id;
96
83
  const project = await Project.findOne({ _id: projectId });
97
84
  if (!project) {
@@ -108,12 +95,7 @@ function projectRouter(config) {
108
95
  });
109
96
  router.patch('/projects/:id', async (req, res) => {
110
97
  try {
111
- const auth = await config.authProvider(req);
112
- if (!auth ||
113
- !auth.userId ||
114
- !auth.role) {
115
- return res.status(401).json({ error: 'Unauthorized' });
116
- }
98
+ const auth = req.auth;
117
99
  if (auth.role !== 'admin' && auth.role !== 'editor') {
118
100
  return res.status(403).json({ error: 'Permission denied' });
119
101
  }
@@ -141,12 +123,7 @@ function projectRouter(config) {
141
123
  });
142
124
  router.delete('/projects/:id', async (req, res) => {
143
125
  try {
144
- const auth = await config.authProvider(req);
145
- if (!auth ||
146
- !auth.userId ||
147
- !auth.role) {
148
- return res.status(401).json({ error: 'Unauthorized' });
149
- }
126
+ const auth = req.auth;
150
127
  const projectId = req.params.id;
151
128
  const project = await Project.findOne({ _id: projectId });
152
129
  if (!project) {
@@ -164,12 +141,7 @@ function projectRouter(config) {
164
141
  });
165
142
  router.patch('/projects/:id/archive', async (req, res) => {
166
143
  try {
167
- const auth = await config.authProvider(req);
168
- if (!auth ||
169
- !auth.userId ||
170
- !auth.role) {
171
- return res.status(401).json({ error: 'Unauthorized' });
172
- }
144
+ const auth = req.auth;
173
145
  const projectId = req.params.id;
174
146
  const project = await Project.findOne({ _id: projectId });
175
147
  if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
@@ -205,12 +177,7 @@ function projectRouter(config) {
205
177
  });
206
178
  router.patch('/projects/:id/unarchive', async (req, res) => {
207
179
  try {
208
- const auth = await config.authProvider(req);
209
- if (!auth ||
210
- !auth.userId ||
211
- !auth.role) {
212
- return res.status(401).json({ error: 'Unauthorized' });
213
- }
180
+ const auth = req.auth;
214
181
  const projectId = req.params.id;
215
182
  const project = await Project.findOne({ _id: projectId });
216
183
  if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
@@ -246,12 +213,7 @@ function projectRouter(config) {
246
213
  });
247
214
  router.get('/projects/:id/members', async (req, res) => {
248
215
  try {
249
- const auth = await config.authProvider(req);
250
- if (!auth ||
251
- !auth.userId ||
252
- !auth.role) {
253
- return res.status(401).json({ error: 'Unauthorized' });
254
- }
216
+ const auth = req.auth;
255
217
  const projectId = req.params.id;
256
218
  const project = await Project.findOne({ _id: projectId });
257
219
  if (!project) {
@@ -283,12 +245,7 @@ function projectRouter(config) {
283
245
  });
284
246
  router.post('/projects/:id/image', async (req, res) => {
285
247
  try {
286
- const auth = await config.authProvider(req);
287
- if (!auth ||
288
- !auth.userId ||
289
- !auth.role) {
290
- return res.status(401).json({ error: 'Unauthorized' });
291
- }
248
+ const auth = req.auth;
292
249
  if (auth.role !== 'admin' && auth.role !== 'editor') {
293
250
  return res.status(403).json({ error: 'Permission denied' });
294
251
  }
@@ -1,2 +1,5 @@
1
- import { AuthContext } from '../types';
2
- export declare function checkRole(auth: AuthContext, required: 'viewer' | 'editor' | 'admin'): void;
1
+ import { Auth } from '../types';
2
+ import { Request, Response, NextFunction } from 'express';
3
+ import { StreamByConfig } from '../types';
4
+ export declare const authenticate: (config: StreamByConfig) => (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
5
+ export declare function checkRole(auth: Auth, required: 'viewer' | 'editor' | 'admin'): void;
@@ -1,6 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authenticate = void 0;
3
4
  exports.checkRole = checkRole;
5
+ const authenticate = (config) => async (req, res, next) => {
6
+ try {
7
+ const auth = await config.authProvider(req);
8
+ if (!auth || !auth.userId || !auth.role) {
9
+ return res.status(401).json({ error: 'Unauthorized' });
10
+ }
11
+ req.auth = auth;
12
+ next();
13
+ }
14
+ catch (error) {
15
+ console.error('Authentication failed:', error);
16
+ return res.status(401).json({ error: 'Unauthorized' });
17
+ }
18
+ };
19
+ exports.authenticate = authenticate;
4
20
  function checkRole(auth, required) {
5
21
  const roles = ['viewer', 'editor', 'admin'];
6
22
  const userIdx = roles.indexOf(auth.role);
@@ -61,12 +61,12 @@ export interface StreamByConfig {
61
61
  databases?: DatabaseCredential[];
62
62
  adapter?: StorageAdapter;
63
63
  }
64
- export interface AuthContext {
64
+ export interface Auth {
65
65
  userId: string;
66
66
  username: string;
67
67
  role: 'viewer' | 'editor' | 'admin';
68
68
  }
69
- export type AuthProvider = (req: Request) => Promise<AuthContext>;
69
+ export type AuthProvider = (req: Request) => Promise<Auth>;
70
70
  export interface Export {
71
71
  _id?: string;
72
72
  id: string;
package/package.json CHANGED
@@ -1,60 +1,60 @@
1
- {
2
- "name": "streamby-core",
3
- "version": "0.21.6",
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": "ts-node-dev --respawn --clear dev.ts",
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
- "@aws-sdk/s3-request-presigner": "^3.787.0",
34
- "@prisma/client": "^6.12.0",
35
- "bcrypt": "^5.1.1",
36
- "dotenv": "^16.5.0",
37
- "express": "^4.0.0",
38
- "mongodb": "^6.17.0",
39
- "mongoose": "^8.13.2",
40
- "pg": "^8.16.3",
41
- "prisma": "^6.12.0"
42
- },
43
- "devDependencies": {
44
- "@types/bcrypt": "^5.0.2",
45
- "@types/cors": "^2.8.18",
46
- "@types/express": "^4.17.17",
47
- "@types/mongodb": "^4.0.7",
48
- "@types/node": "^22.15.21",
49
- "@types/pg": "^8.15.4",
50
- "@types/supertest": "^6.0.3",
51
- "cors": "^2.8.5",
52
- "supertest": "^7.1.4",
53
- "ts-node-dev": "^2.0.0",
54
- "typescript": "^5.8.3",
55
- "vitest": "^3.1.1"
56
- },
57
- "peerDependencies": {
58
- "express": "^4.0.0"
59
- }
60
- }
1
+ {
2
+ "name": "streamby-core",
3
+ "version": "0.21.7",
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": "ts-node-dev --respawn --clear dev.ts",
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
+ "@aws-sdk/s3-request-presigner": "^3.787.0",
34
+ "@prisma/client": "^6.12.0",
35
+ "bcrypt": "^5.1.1",
36
+ "dotenv": "^16.5.0",
37
+ "express": "^4.0.0",
38
+ "mongodb": "^6.17.0",
39
+ "mongoose": "^8.13.2",
40
+ "pg": "^8.16.3",
41
+ "prisma": "^6.12.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/bcrypt": "^5.0.2",
45
+ "@types/cors": "^2.8.18",
46
+ "@types/express": "^4.17.17",
47
+ "@types/mongodb": "^4.0.7",
48
+ "@types/node": "^22.15.21",
49
+ "@types/pg": "^8.15.4",
50
+ "@types/supertest": "^6.0.3",
51
+ "cors": "^2.8.5",
52
+ "supertest": "^7.1.4",
53
+ "ts-node-dev": "^2.0.0",
54
+ "typescript": "^5.8.3",
55
+ "vitest": "^3.1.1"
56
+ },
57
+ "peerDependencies": {
58
+ "express": "^4.0.0"
59
+ }
60
+ }