streamby-core 0.7.2 โ†’ 0.8.1

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,114 +1,114 @@
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
- ## ๐Ÿšฃ Roadmap
93
-
94
- - [ ] Support for Google Cloud Storage
95
- - [ ] CLI tool for uploading files
96
- - [ ] Role-based access control middleware
97
- - [ ] Plugin system for extended routes
98
- - [ ] Streaming support (HLS, audio, etc.)
99
-
100
- ---
101
-
102
- ## ๐Ÿง‘โ€๐Ÿ’ป Maintained by
103
-
104
- **TerminalCore Labs** โ€“ part of [Nhexa Entertainment](https://nhexa.cl)
105
- Developed as open-source infrastructure for creative and media-oriented apps.
106
-
107
- Visit us [here](https://terminalcore.cl)
108
-
109
- ---
110
-
111
- ## ๐Ÿ“Ÿ License
112
-
113
- [MIT](./LICENSE)
114
-
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
+ ## ๐Ÿšฃ Roadmap
93
+
94
+ - [ ] Support for Google Cloud Storage
95
+ - [ ] CLI tool for uploading files
96
+ - [ ] Role-based access control middleware
97
+ - [ ] Plugin system for extended routes
98
+ - [ ] Streaming support (HLS, audio, etc.)
99
+
100
+ ---
101
+
102
+ ## ๐Ÿง‘โ€๐Ÿ’ป Maintained by
103
+
104
+ **TerminalCore Labs** โ€“ part of [Nhexa Entertainment](https://nhexa.cl)
105
+ Developed as open-source infrastructure for creative and media-oriented apps.
106
+
107
+ Visit us [here](https://terminalcore.cl)
108
+
109
+ ---
110
+
111
+ ## ๐Ÿ“Ÿ License
112
+
113
+ [MIT](./LICENSE)
114
+
@@ -12,27 +12,15 @@ function createS3Adapter(config) {
12
12
  },
13
13
  });
14
14
  return {
15
- async getPresignedUrl(filename, contentType) {
16
- const command = new client_s3_1.PutObjectCommand({
17
- Bucket: config.bucket,
18
- Key: `uploads/${filename}`,
19
- ContentType: contentType,
20
- });
21
- return (0, s3_request_presigner_1.getSignedUrl)(s3, command, { expiresIn: 3600 });
22
- },
23
- async uploadFile(req, projectId) {
24
- const file = req.body?.file;
25
- if (!file || !file.name || !file.buffer) {
26
- throw new Error('Invalid file upload: missing name or buffer');
27
- }
28
- const key = `${projectId}/${file.name}`;
15
+ async getPresignedUrl(filename, contentType, projectId) {
16
+ const key = `${projectId}/file-${Date.now()}-${filename}`;
29
17
  const command = new client_s3_1.PutObjectCommand({
30
18
  Bucket: config.bucket,
31
19
  Key: key,
32
- Body: file.buffer,
20
+ ContentType: contentType,
33
21
  });
34
- await s3.send(command);
35
- return { success: true, key };
22
+ const url = await (0, s3_request_presigner_1.getSignedUrl)(s3, command, { expiresIn: 60 });
23
+ return { url, key };
36
24
  },
37
25
  async listFiles(projectId) {
38
26
  const command = new client_s3_1.ListObjectsV2Command({
@@ -34,12 +34,12 @@ function createStreamByRouter(config) {
34
34
  if (auth.role !== 'admin' && auth.role !== 'editor') {
35
35
  return res.status(403).json({ error: 'Permission denied' });
36
36
  }
37
- const { filename, contentType } = req.body;
38
- if (!filename || !contentType) {
39
- return res.status(400).json({ error: 'Missing filename or contentType' });
37
+ const { filename, contentType, projectId } = req.body;
38
+ if (!filename || !contentType || !projectId) {
39
+ return res.status(400).json({ error: 'Missing filename, contentType, or projectId' });
40
40
  }
41
- const url = await (0, presign_1.getPresignedUrl)(adapter, filename, contentType);
42
- res.json({ url });
41
+ const url = await (0, presign_1.getPresignedUrl)(adapter, filename, contentType, projectId);
42
+ res.json(url);
43
43
  }
44
44
  catch (err) {
45
45
  res.status(500).json({ error: 'Failed to generate presigned URL', details: err.message });
@@ -59,36 +59,22 @@ function createStreamByRouter(config) {
59
59
  res.status(500).json({ error: 'Failed to list files', details: err });
60
60
  }
61
61
  });
62
- router.patch('/projects/:id/image', async (req, res) => {
62
+ router.patch('/projects/:id', async (req, res) => {
63
63
  try {
64
64
  const auth = await config.authProvider(req);
65
65
  if (auth.role !== 'admin' && auth.role !== 'editor') {
66
66
  return res.status(403).json({ error: 'Permission denied' });
67
67
  }
68
68
  const projectId = req.params.id;
69
- const { image } = req.body;
70
- if (!image) {
71
- return res.status(400).json({ error: 'Missing image key' });
69
+ const updates = req.body;
70
+ if (!updates || typeof updates !== 'object') {
71
+ return res.status(400).json({ error: 'Missing updates payload' });
72
72
  }
73
- const updated = await config.projectProvider.updateImage(projectId, image);
74
- res.status(200).json(updated);
73
+ const updated = await config.projectProvider.update(projectId, updates);
74
+ res.status(200).json({ success: true, project: updated });
75
75
  }
76
76
  catch (err) {
77
- res.status(500).json({ error: 'Failed to update project image', details: err.message });
78
- }
79
- });
80
- router.post('/upload', async (req, res) => {
81
- try {
82
- const auth = await config.authProvider(req);
83
- const projectId = (req.query.projectId || req.headers['x-project-id']);
84
- if (!projectId || !auth.projects.includes(projectId)) {
85
- return res.status(403).json({ error: 'Unauthorized or missing projectId' });
86
- }
87
- const result = await (0, file_1.uploadFileService)(adapter, req, projectId);
88
- res.json(result);
89
- }
90
- catch (err) {
91
- res.status(500).json({ error: 'Failed to upload file', details: err });
77
+ res.status(500).json({ error: 'Failed to update project', details: err.message });
92
78
  }
93
79
  });
94
80
  router.get('/projects/:id', async (req, res) => {
@@ -1,4 +1,3 @@
1
1
  import { StorageAdapter } from '../types';
2
2
  import { Request } from 'express';
3
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>;
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listFilesService = listFilesService;
4
- exports.uploadFileService = uploadFileService;
5
4
  async function listFilesService(adapter, req, projectId) {
6
5
  return adapter.listFiles(projectId);
7
6
  }
8
- async function uploadFileService(adapter, req, projectId) {
9
- return adapter.uploadFile(req, projectId);
10
- }
@@ -1,2 +1,2 @@
1
1
  import { StorageAdapter } from '../types';
2
- export declare function getPresignedUrl(adapter: StorageAdapter, filename: string, contentType: string): Promise<string>;
2
+ export declare function getPresignedUrl(adapter: StorageAdapter, filename: string, contentType: string, projectId: string): Promise<any>;
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPresignedUrl = getPresignedUrl;
4
- async function getPresignedUrl(adapter, filename, contentType) {
4
+ async function getPresignedUrl(adapter, filename, contentType, projectId) {
5
5
  if (!('getPresignedUrl' in adapter)) {
6
6
  throw new Error('StorageAdapter does not support presigned URLs');
7
7
  }
8
- return adapter.getPresignedUrl(filename, contentType);
8
+ return adapter.getPresignedUrl(filename, contentType, projectId);
9
9
  }
@@ -7,9 +7,8 @@ export interface S3Config {
7
7
  }
8
8
  export type StorageProviderType = 's3';
9
9
  export interface StorageAdapter {
10
- uploadFile(req: Request, projectId: string): Promise<any>;
11
10
  listFiles(projectId: string): Promise<any[]>;
12
- getPresignedUrl?: (filename: string, contentType: string) => Promise<string>;
11
+ getPresignedUrl?: (filename: string, contentType: string, projectId: string) => Promise<any>;
13
12
  }
14
13
  export interface ProjectInfo {
15
14
  id: string;
@@ -44,7 +43,7 @@ export interface AuthContext {
44
43
  export type AuthProvider = (req: Request) => Promise<AuthContext>;
45
44
  export interface ProjectProvider {
46
45
  getById(projectId: string): Promise<ProjectInfo>;
47
- updateImage: (projectId: string, imageKey: string) => Promise<ProjectInfo>;
46
+ update(projectId: string, updates: Partial<Omit<ProjectInfo, 'id' | 'rootFolders'>>): Promise<ProjectInfo>;
48
47
  create(data: {
49
48
  name: string;
50
49
  image?: string;
package/package.json CHANGED
@@ -1,46 +1,46 @@
1
- {
2
- "name": "streamby-core",
3
- "version": "0.7.2",
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
- "@aws-sdk/s3-request-presigner": "^3.787.0",
34
- "express": "^4.0.0"
35
- },
36
- "devDependencies": {
37
- "@types/express": "^4.17.17",
38
- "@types/supertest": "^6.0.3",
39
- "supertest": "^7.1.0",
40
- "typescript": "^5.8.3",
41
- "vitest": "^3.1.1"
42
- },
43
- "peerDependencies": {
44
- "express": "^4.0.0"
45
- }
46
- }
1
+ {
2
+ "name": "streamby-core",
3
+ "version": "0.8.1",
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
+ "@aws-sdk/s3-request-presigner": "^3.787.0",
34
+ "express": "^4.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/express": "^4.17.17",
38
+ "@types/supertest": "^6.0.3",
39
+ "supertest": "^7.1.0",
40
+ "typescript": "^5.8.3",
41
+ "vitest": "^3.1.1"
42
+ },
43
+ "peerDependencies": {
44
+ "express": "^4.0.0"
45
+ }
46
+ }