streamby-core 0.9.21 → 0.10.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/dist/db/initProjectModel.d.ts +240 -240
- package/dist/index.d.ts +4 -3
- package/dist/index.js +12 -7
- package/dist/middleware/createRouter.d.ts +5 -2
- package/dist/middleware/createRouter.js +168 -17
- package/dist/services/auth.d.ts +1 -0
- package/dist/services/auth.js +9 -0
- package/dist/services/project.d.ts +2 -2
- package/dist/services/project.js +5 -4
- package/dist/types/index.d.ts +0 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
1
|
+
import { StreamByConfig, StorageAdapter } from './types';
|
|
2
|
+
export declare function createStreamByApp(config: StreamByConfig & {
|
|
3
|
+
adapter?: StorageAdapter;
|
|
4
|
+
}): import("express-serve-static-core").Express;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
exports.createStreamByApp = createStreamByApp;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const createRouter_1 = require("./middleware/createRouter");
|
|
9
|
+
function createStreamByApp(config) {
|
|
10
|
+
const app = (0, express_1.default)();
|
|
11
|
+
app.use(express_1.default.json());
|
|
12
|
+
app.use((0, createRouter_1.createStreamByRouter)(config));
|
|
13
|
+
return app;
|
|
14
|
+
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { StreamByConfig, StorageAdapter } from '../types';
|
|
3
|
+
export declare function createStreamByRouter(config: StreamByConfig & {
|
|
4
|
+
adapter?: StorageAdapter;
|
|
5
|
+
}): Router;
|
|
@@ -5,23 +5,174 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createStreamByRouter = createStreamByRouter;
|
|
7
7
|
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const s3_1 = require("../adapters/s3");
|
|
9
|
+
const file_1 = require("../services/file");
|
|
8
10
|
const project_1 = require("../services/project");
|
|
11
|
+
const presign_1 = require("../services/presign");
|
|
12
|
+
function isProjectMember(project, userId) {
|
|
13
|
+
return project.members?.some((m) => m.userId?.toString() === userId?.toString());
|
|
14
|
+
}
|
|
9
15
|
function createStreamByRouter(config) {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
const router = express_1.default.Router();
|
|
17
|
+
const adapter = config.adapter || (() => {
|
|
18
|
+
switch (config.storageProvider.type) {
|
|
19
|
+
case 's3':
|
|
20
|
+
return (0, s3_1.createS3Adapter)(config.storageProvider.config);
|
|
21
|
+
default:
|
|
22
|
+
throw new Error('Unsupported storage type');
|
|
23
|
+
}
|
|
24
|
+
})();
|
|
25
|
+
router.get('/auth', async (req, res) => {
|
|
26
|
+
try {
|
|
27
|
+
const auth = await config.authProvider(req);
|
|
28
|
+
res.status(200).json({ logged: true, ...auth });
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
res.status(401).json({ logged: false });
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
router.get('/upload-project-image-url/:id', async (req, res) => {
|
|
35
|
+
try {
|
|
36
|
+
const auth = await config.authProvider(req);
|
|
37
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
38
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
39
|
+
}
|
|
40
|
+
const projectId = req.params.id;
|
|
41
|
+
if (!projectId) {
|
|
42
|
+
return res.status(400).json({ error: 'Missing projectId' });
|
|
43
|
+
}
|
|
44
|
+
const url = await (0, presign_1.getPresignedProjectImageUrl)(adapter, projectId);
|
|
45
|
+
res.json(url);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
res.status(500).json({ error: 'Failed to generate presigned URL', details: err.message });
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
router.delete('/delete-project-image-url/:id', async (req, res) => {
|
|
52
|
+
try {
|
|
53
|
+
const auth = await config.authProvider(req);
|
|
54
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
55
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
56
|
+
}
|
|
57
|
+
const projectId = req.params.id;
|
|
58
|
+
if (!projectId) {
|
|
59
|
+
return res.status(400).json({ error: 'Missing projectId' });
|
|
60
|
+
}
|
|
61
|
+
await (0, file_1.deleteProjectImage)(adapter, projectId);
|
|
62
|
+
const updated = await (0, project_1.deleteProjectImageService)(req, config.authProvider, config.projectProvider);
|
|
63
|
+
res.status(201).json(updated);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
res.status(500).json({ error: 'Failed to delete image', details: err.message });
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
router.post('/upload-url', async (req, res) => {
|
|
70
|
+
try {
|
|
71
|
+
const auth = await config.authProvider(req);
|
|
72
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
73
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
74
|
+
}
|
|
75
|
+
const { filename, contentType, projectId } = req.body;
|
|
76
|
+
if (!filename || !contentType || !projectId) {
|
|
77
|
+
return res.status(400).json({ error: 'Missing filename, contentType, or projectId' });
|
|
78
|
+
}
|
|
79
|
+
const url = await (0, presign_1.getPresignedUrl)(adapter, contentType, projectId);
|
|
80
|
+
res.json(url);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
res.status(500).json({ error: 'Failed to generate upload URL', details: err.message });
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
router.get('/files', async (req, res) => {
|
|
87
|
+
try {
|
|
88
|
+
const auth = await config.authProvider(req);
|
|
89
|
+
const projectId = (req.query.projectId || req.headers['x-project-id']);
|
|
90
|
+
if (!projectId || !auth.projects.includes(projectId)) {
|
|
91
|
+
return res.status(403).json({ error: 'Unauthorized or missing projectId' });
|
|
92
|
+
}
|
|
93
|
+
const files = await (0, file_1.listFilesService)(adapter, req, projectId);
|
|
94
|
+
res.json(files);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
res.status(500).json({ error: 'Failed to list files', details: err });
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
router.patch('/projects/:id', async (req, res) => {
|
|
101
|
+
try {
|
|
102
|
+
const auth = await config.authProvider(req);
|
|
103
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
104
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
105
|
+
}
|
|
106
|
+
const projectId = req.params.id;
|
|
107
|
+
const updates = req.body;
|
|
108
|
+
if (!updates || typeof updates !== 'object') {
|
|
109
|
+
return res.status(400).json({ error: 'Missing updates payload' });
|
|
110
|
+
}
|
|
111
|
+
const updated = await config.projectProvider.update(projectId, updates);
|
|
112
|
+
res.status(200).json({ success: true, project: updated });
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
res.status(500).json({ error: 'Failed to update project', details: err.message });
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
router.get('/projects/:id', async (req, res) => {
|
|
119
|
+
try {
|
|
120
|
+
const auth = await config.authProvider(req);
|
|
121
|
+
const projectId = req.params.id;
|
|
122
|
+
const project = await config.projectProvider.getById(projectId);
|
|
123
|
+
if (!project) {
|
|
124
|
+
return res.status(404).json({ error: 'Project not found' });
|
|
125
|
+
}
|
|
126
|
+
if (!isProjectMember(project, auth.userId)) {
|
|
127
|
+
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
128
|
+
}
|
|
129
|
+
res.json({ project });
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
res.status(500).json({ error: 'Failed to fetch project', details: err.message });
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
router.post('/projects/create', async (req, res) => {
|
|
136
|
+
try {
|
|
137
|
+
const auth = await config.authProvider(req);
|
|
138
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
139
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
140
|
+
}
|
|
141
|
+
const created = await (0, project_1.createProjectService)(req, config.authProvider, config.projectProvider);
|
|
142
|
+
res.status(201).json(created);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
res.status(500).json({ error: 'Failed to create project', details: err.message });
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
router.delete('/projects/:id', async (req, res) => {
|
|
149
|
+
try {
|
|
150
|
+
const auth = await config.authProvider(req);
|
|
151
|
+
const projectId = req.params.id;
|
|
152
|
+
const project = await config.projectProvider.getById(projectId);
|
|
153
|
+
if (!project) {
|
|
154
|
+
return res.status(404).json({ error: 'Project not found' });
|
|
155
|
+
}
|
|
156
|
+
if (!isProjectMember(project, auth.userId)) {
|
|
157
|
+
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
158
|
+
}
|
|
159
|
+
await config.projectProvider.delete(projectId);
|
|
160
|
+
await adapter.deleteProjectDirectory(projectId);
|
|
161
|
+
res.status(200).json({ success: true });
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
res.status(500).json({ error: 'Failed to delete project', details: err.message });
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
router.get('/projects', async (req, res) => {
|
|
168
|
+
try {
|
|
169
|
+
const auth = await config.authProvider(req);
|
|
170
|
+
const projects = await config.projectProvider.list(auth.userId);
|
|
171
|
+
res.json({ projects });
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
res.status(500).json({ error: 'Failed to list projects', details: err });
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
return router;
|
|
27
178
|
}
|
package/dist/services/auth.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ import { Request } from 'express';
|
|
|
2
2
|
import { StreamByConfig, AuthContext } from '../types';
|
|
3
3
|
export declare function resolveAuth(config: StreamByConfig, req: Request): Promise<AuthContext>;
|
|
4
4
|
export declare function checkRole(auth: AuthContext, required: 'viewer' | 'editor' | 'admin'): void;
|
|
5
|
+
export declare function dummyAuthProvider(req: Request): Promise<AuthContext>;
|
package/dist/services/auth.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveAuth = resolveAuth;
|
|
4
4
|
exports.checkRole = checkRole;
|
|
5
|
+
exports.dummyAuthProvider = dummyAuthProvider;
|
|
5
6
|
async function resolveAuth(config, req) {
|
|
6
7
|
const auth = await config.authProvider(req);
|
|
7
8
|
if (!auth ||
|
|
@@ -21,3 +22,11 @@ function checkRole(auth, required) {
|
|
|
21
22
|
throw new Error(`Insufficient role: requires ${required}, found ${auth.role}`);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
async function dummyAuthProvider(req) {
|
|
26
|
+
return {
|
|
27
|
+
userId: '67ad0832cae5e7e270ee086a',
|
|
28
|
+
username: 'dev-user',
|
|
29
|
+
projects: [],
|
|
30
|
+
role: 'admin'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request } from 'express';
|
|
2
|
-
import { AuthProvider, ProjectProvider
|
|
2
|
+
import { AuthProvider, ProjectProvider } from '../types';
|
|
3
3
|
export declare function createProjectService(req: Request, authProvider: AuthProvider, projectProvider: ProjectProvider): Promise<{
|
|
4
4
|
success: boolean;
|
|
5
5
|
project: import("../types").ProjectInfo;
|
|
@@ -8,6 +8,6 @@ export declare function updateProjectService(req: Request, authProvider: AuthPro
|
|
|
8
8
|
success: boolean;
|
|
9
9
|
project: import("../types").ProjectInfo;
|
|
10
10
|
}>;
|
|
11
|
-
export declare function deleteProjectImageService(req: Request, authProvider: AuthProvider, projectProvider: ProjectProvider
|
|
11
|
+
export declare function deleteProjectImageService(req: Request, authProvider: AuthProvider, projectProvider: ProjectProvider): Promise<{
|
|
12
12
|
success: boolean;
|
|
13
13
|
}>;
|
package/dist/services/project.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createProjectService = createProjectService;
|
|
4
4
|
exports.updateProjectService = updateProjectService;
|
|
5
5
|
exports.deleteProjectImageService = deleteProjectImageService;
|
|
6
|
-
const file_1 = require("./file");
|
|
7
6
|
async function createProjectService(req, authProvider, projectProvider) {
|
|
8
7
|
const { name, description } = req.body;
|
|
9
8
|
const auth = await authProvider(req);
|
|
@@ -37,7 +36,7 @@ async function updateProjectService(req, authProvider, projectProvider) {
|
|
|
37
36
|
project: updatedProject,
|
|
38
37
|
};
|
|
39
38
|
}
|
|
40
|
-
async function deleteProjectImageService(req, authProvider, projectProvider
|
|
39
|
+
async function deleteProjectImageService(req, authProvider, projectProvider) {
|
|
41
40
|
const { projectId } = req.params;
|
|
42
41
|
const auth = await authProvider(req);
|
|
43
42
|
const project = await projectProvider.getById(projectId);
|
|
@@ -47,6 +46,8 @@ async function deleteProjectImageService(req, authProvider, projectProvider, sto
|
|
|
47
46
|
if (!project.members?.find((e) => e.userId === auth.userId)) {
|
|
48
47
|
throw new Error('Unauthorized');
|
|
49
48
|
}
|
|
50
|
-
await
|
|
51
|
-
return {
|
|
49
|
+
await projectProvider.update(projectId, { image: '' });
|
|
50
|
+
return {
|
|
51
|
+
success: true,
|
|
52
|
+
};
|
|
52
53
|
}
|
package/dist/types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "streamby-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.00",
|
|
4
4
|
"description": "StreamBy middleware framework for media storage management",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"test": "vitest",
|
|
13
|
-
"dev": "
|
|
13
|
+
"dev": "ts-node-dev --respawn --clear dev.ts",
|
|
14
14
|
"prepublishOnly": "npm run build"
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
@@ -32,14 +32,17 @@
|
|
|
32
32
|
"@aws-sdk/client-s3": "^3.528.0",
|
|
33
33
|
"@aws-sdk/s3-request-presigner": "^3.787.0",
|
|
34
34
|
"bcrypt": "^5.1.1",
|
|
35
|
+
"dotenv": "^16.5.0",
|
|
35
36
|
"express": "^4.0.0",
|
|
36
37
|
"mongoose": "^8.13.2"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@types/bcrypt": "^5.0.2",
|
|
40
41
|
"@types/express": "^4.17.17",
|
|
42
|
+
"@types/node": "^22.15.21",
|
|
41
43
|
"@types/supertest": "^6.0.3",
|
|
42
44
|
"supertest": "^7.1.0",
|
|
45
|
+
"ts-node-dev": "^2.0.0",
|
|
43
46
|
"typescript": "^5.8.3",
|
|
44
47
|
"vitest": "^3.1.1"
|
|
45
48
|
},
|