streamby-core 0.21.0 → 0.21.2

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.
@@ -5,15 +5,14 @@ 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 file_1 = require("../services/file");
9
- const presign_1 = require("../services/presign");
10
8
  const manager_1 = require("../models/manager");
11
9
  const storage_1 = require("../providers/storage");
12
10
  const connectionManager_1 = require("../adapters/database/connectionManager");
13
- const auth_1 = require("../services/auth");
14
- function isProjectMember(project, userId) {
15
- return project.members?.some((m) => m.userId?.toString() === userId?.toString());
16
- }
11
+ const auth_1 = require("./routes/auth");
12
+ const database_1 = require("./routes/database");
13
+ const file_1 = require("./routes/file");
14
+ const project_1 = require("./routes/project");
15
+ const export_1 = require("./routes/export");
17
16
  function createStreamByRouter(config) {
18
17
  const router = express_1.default.Router();
19
18
  (0, connectionManager_1.initConnections)(config.databases || []);
@@ -23,313 +22,10 @@ function createStreamByRouter(config) {
23
22
  (0, manager_1.registerModel)('projects', allDbIds, 'projects');
24
23
  (0, manager_1.registerModel)('exports', allDbIds, 'exports');
25
24
  }
26
- const Project = (0, manager_1.getModel)('projects');
27
- const Export = (0, manager_1.getModel)('exports');
28
- router.get('/auth', async (req, res) => {
29
- try {
30
- const auth = await (0, auth_1.resolveAuth)(config, req);
31
- res.status(200).json({ logged: true, ...auth });
32
- }
33
- catch (err) {
34
- res.status(401).json({ logged: false });
35
- }
36
- });
37
- router.get('/databases', async (req, res) => {
38
- try {
39
- const auth = await config.authProvider(req);
40
- if (!auth) {
41
- return res.status(401).json({ error: 'Unauthorized' });
42
- }
43
- const connectedDbIds = (0, connectionManager_1.getConnectedIds)();
44
- const databases = (config.databases || [])
45
- .filter(db => connectedDbIds.includes(db.id))
46
- .map(db => ({ name: db.id, value: db.type }));
47
- res.status(200).json({ databases });
48
- }
49
- catch (err) {
50
- res.status(500).json({ error: 'Failed to get databases' });
51
- }
52
- });
53
- router.get('/upload-project-image-url/:id', async (req, res) => {
54
- try {
55
- const auth = await config.authProvider(req);
56
- if (auth.role !== 'admin' && auth.role !== 'editor') {
57
- return res.status(403).json({ error: 'Permission denied' });
58
- }
59
- const projectId = req.params.id;
60
- if (!projectId) {
61
- return res.status(400).json({ error: 'Missing projectId' });
62
- }
63
- const url = await (0, presign_1.getPresignedProjectImageUrl)(adapter, projectId);
64
- res.json(url);
65
- }
66
- catch (err) {
67
- res.status(500).json({ error: 'Failed to generate presigned URL', details: err.message });
68
- }
69
- });
70
- router.delete('/delete-project-image-url/:id', async (req, res) => {
71
- try {
72
- const auth = await config.authProvider(req);
73
- if (auth.role !== 'admin' && auth.role !== 'editor') {
74
- return res.status(403).json({ error: 'Permission denied' });
75
- }
76
- const projectId = req.params.id;
77
- if (!projectId) {
78
- return res.status(400).json({ error: 'Missing projectId' });
79
- }
80
- await (0, file_1.deleteProjectImage)(adapter, projectId);
81
- const updated = await Project.update({ _id: projectId }, { image: '' });
82
- res.status(201).json(updated);
83
- }
84
- catch (err) {
85
- res.status(500).json({ error: 'Failed to delete image', details: err.message });
86
- }
87
- });
88
- router.get('/files', async (req, res) => {
89
- try {
90
- const auth = await config.authProvider(req);
91
- const projectId = (req.query.projectId || req.headers['x-project-id']);
92
- if (!projectId) {
93
- return res.status(403).json({ error: 'Unauthorized or missing projectId' });
94
- }
95
- const files = await (0, file_1.listFilesService)(adapter, req, projectId);
96
- res.json(files);
97
- }
98
- catch (err) {
99
- res.status(500).json({ error: 'Failed to list files', details: err });
100
- }
101
- });
102
- router.get('/projects', async (req, res) => {
103
- try {
104
- const auth = await config.authProvider(req);
105
- const archivedQuery = req.query.archived;
106
- const filterArchived = archivedQuery !== undefined ? String(archivedQuery).toLowerCase() === 'true' : undefined;
107
- const allProjects = await Project.find({}); // Fetch all projects
108
- const projects = allProjects
109
- .filter(project => {
110
- const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
111
- if (!isMember)
112
- return false;
113
- if (filterArchived !== undefined) {
114
- const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
115
- return currentUserMember ? (currentUserMember.archived || false) === filterArchived : false;
116
- }
117
- return true;
118
- })
119
- .map(project => {
120
- const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
121
- return {
122
- id: project._id || project.id,
123
- dbType: project.dbType,
124
- name: project.name,
125
- image: project.image || '',
126
- archived: currentUserMember ? currentUserMember.archived || false : false,
127
- };
128
- });
129
- res.json({ projects });
130
- }
131
- catch (err) {
132
- console.error('Error in /projects endpoint:', err);
133
- res.status(500).json({ error: 'Failed to list projects', details: err });
134
- }
135
- });
136
- router.post('/projects/create', async (req, res) => {
137
- try {
138
- const auth = await config.authProvider(req);
139
- if (auth.role !== 'admin' && auth.role !== 'editor') {
140
- return res.status(403).json({ error: 'Permission denied' });
141
- }
142
- const { name, description, dbType } = req.body;
143
- const newProject = await Project.create({
144
- dbType: dbType || 'nosql',
145
- name,
146
- description: description || '',
147
- members: [{ userId: auth.userId, role: "admin", archived: false }]
148
- });
149
- res.status(201).json({ project: { ...newProject, id: newProject._id || newProject.id, _id: undefined } });
150
- }
151
- catch (err) {
152
- res.status(500).json({ error: 'Failed to create project', details: err.message });
153
- }
154
- });
155
- router.get('/projects/:id', async (req, res) => {
156
- try {
157
- const auth = await config.authProvider(req);
158
- const projectId = req.params.id;
159
- const project = await Project.findOne({ _id: projectId });
160
- if (!project) {
161
- return res.status(404).json({ error: 'Project not found' });
162
- }
163
- if (!isProjectMember(project, auth.userId)) {
164
- return res.status(403).json({ error: 'Unauthorized project access' });
165
- }
166
- res.json({ project: { ...project, id: project._id || project.id, _id: undefined } });
167
- }
168
- catch (err) {
169
- res.status(500).json({ error: 'Failed to fetch project', details: err.message });
170
- }
171
- });
172
- router.patch('/projects/:id', async (req, res) => {
173
- try {
174
- const auth = await config.authProvider(req);
175
- if (auth.role !== 'admin' && auth.role !== 'editor') {
176
- return res.status(403).json({ error: 'Permission denied' });
177
- }
178
- const projectId = req.params.id;
179
- const updates = req.body;
180
- const project = await Project.findOne({ _id: projectId });
181
- if (!project) {
182
- return res.status(404).json({ error: 'Project not found' });
183
- }
184
- if (!updates || typeof updates !== 'object') {
185
- return res.status(400).json({ error: 'Missing updates payload' });
186
- }
187
- if (!isProjectMember(project, auth.userId)) {
188
- return res.status(403).json({ error: 'Unauthorized project access' });
189
- }
190
- const updated = await Project.update({ _id: projectId }, updates);
191
- if (!updated) {
192
- return res.status(404).json({ error: 'Project not found or not updated' });
193
- }
194
- res.status(200).json({ success: true, project: { ...updated, id: updated._id || updated.id, _id: undefined } });
195
- }
196
- catch (err) {
197
- res.status(500).json({ error: 'Failed to update project', details: err.message });
198
- }
199
- });
200
- router.delete('/projects/:id', async (req, res) => {
201
- try {
202
- const auth = await config.authProvider(req);
203
- const projectId = req.params.id;
204
- const project = await Project.findOne({ _id: projectId });
205
- if (!project) {
206
- return res.status(404).json({ error: 'Project not found' });
207
- }
208
- if (!isProjectMember(project, auth.userId)) {
209
- return res.status(403).json({ error: 'Unauthorized project access' });
210
- }
211
- await Project.delete({ _id: projectId });
212
- res.status(200).json({ success: true });
213
- }
214
- catch (err) {
215
- res.status(500).json({ error: 'Failed to delete project', details: err.message });
216
- }
217
- });
218
- router.patch('/projects/:id/archive', async (req, res) => {
219
- try {
220
- const auth = await config.authProvider(req);
221
- const projectId = req.params.id;
222
- const project = await Project.findOne({ _id: projectId });
223
- if (!project || !isProjectMember(project, auth.userId)) {
224
- return res.status(403).json({ error: 'Unauthorized project access' });
225
- }
226
- await Project.update({ _id: projectId, "members.userId": auth.userId }, { "members.$.archived": true, "members.$.archivedBy": auth.userId, "members.$.archivedAt": new Date() });
227
- const updatedProject = await Project.findOne({ _id: projectId }); // Fetch the updated project
228
- const projects = (await Project.find({ members: { $elemMatch: { userId: auth.userId } } })).map(project => {
229
- const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
230
- return {
231
- id: project._id || project.id,
232
- dbType: project.dbType,
233
- name: project.name,
234
- image: project.image || '',
235
- archived: currentUserMember ? currentUserMember.archived || false : false,
236
- };
237
- });
238
- // Replace the old project with the updated one in the list
239
- const finalProjects = projects.map(p => p.id === (updatedProject?._id || updatedProject?.id) ? ({ ...updatedProject, id: updatedProject._id || updatedProject.id, _id: undefined }) : p);
240
- res.status(200).json({ success: true, projects: finalProjects });
241
- }
242
- catch (err) {
243
- res.status(500).json({ error: 'Failed to archive project', details: err.message });
244
- }
245
- });
246
- router.patch('/projects/:id/unarchive', async (req, res) => {
247
- try {
248
- const auth = await config.authProvider(req);
249
- const projectId = req.params.id;
250
- const project = await Project.findOne({ _id: projectId });
251
- if (!project || !isProjectMember(project, auth.userId)) {
252
- return res.status(403).json({ error: 'Unauthorized project access' });
253
- }
254
- await Project.update({ _id: projectId, "members.userId": auth.userId }, { "members.$.archived": false, "members.$.archivedBy": null, "members.$.archivedAt": null });
255
- const updatedProject = await Project.findOne({ _id: projectId }); // Fetch the updated project
256
- const projects = (await Project.find({ members: { $elemMatch: { userId: auth.userId } } })).map(project => {
257
- const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
258
- return {
259
- id: project._id || project.id,
260
- dbType: project.dbType,
261
- name: project.name,
262
- image: project.image || '',
263
- archived: currentUserMember ? currentUserMember.archived || false : false,
264
- };
265
- });
266
- // Replace the old project with the updated one in the list
267
- const finalProjects = projects.map(p => p.id === (updatedProject?._id || updatedProject?.id) ? ({ ...updatedProject, id: updatedProject._id || updatedProject.id, _id: undefined }) : p);
268
- res.status(200).json({ success: true, projects: finalProjects });
269
- }
270
- catch (err) {
271
- res.status(500).json({ error: 'Failed to unarchive project', details: err.message });
272
- }
273
- });
274
- router.get('/projects/:id/exports/:export_id', async (req, res) => {
275
- try {
276
- const auth = await config.authProvider(req);
277
- const projectId = req.params.id;
278
- const exportId = req.params.export_id;
279
- const project = await Project.findOne({ _id: projectId });
280
- if (!project) {
281
- return res.status(404).json({ error: 'Project not found' });
282
- }
283
- if (!isProjectMember(project, auth.userId)) {
284
- return res.status(403).json({ error: 'Unauthorized access' });
285
- }
286
- const data = await Export.findOne({ _id: exportId });
287
- res.json({ data: { ...data, id: data._id || data.id, _id: undefined } });
288
- }
289
- catch (err) {
290
- res.status(500).json({ error: 'Failed to fetch export data', details: err.message });
291
- }
292
- });
293
- router.post('/projects/:id/exports', async (req, res) => {
294
- try {
295
- const auth = await config.authProvider(req);
296
- const projectId = req.params.id;
297
- const { name, description, collectionName } = req.body;
298
- if (!name || !collectionName) {
299
- return res.status(400).json({ error: 'Missing export name or collectionName' });
300
- }
301
- const project = await Project.findOne({ _id: projectId });
302
- if (!project || !isProjectMember(project, auth.userId)) {
303
- return res.status(403).json({ error: 'Unauthorized project access' });
304
- }
305
- const newExport = await Export.create({
306
- name,
307
- description,
308
- collectionName,
309
- projectId
310
- });
311
- res.status(201).json({ data: { ...newExport, id: newExport._id || newExport.id, _id: undefined } });
312
- }
313
- catch (err) {
314
- res.status(500).json({ error: 'Failed to create export', details: err.message });
315
- }
316
- });
317
- router.get('/projects/:id/members', async (req, res) => {
318
- try {
319
- const auth = await config.authProvider(req);
320
- const projectId = req.params.id;
321
- const project = await Project.findOne({ _id: projectId });
322
- if (!project) {
323
- return res.status(404).json({ error: 'Project not found' });
324
- }
325
- if (!isProjectMember(project, auth.userId)) {
326
- return res.status(403).json({ error: 'Unauthorized project access' });
327
- }
328
- res.json({ members: project.members });
329
- }
330
- catch (err) {
331
- res.status(500).json({ error: 'Failed to fetch project members', details: err.message });
332
- }
333
- });
25
+ router.use((0, auth_1.authRouter)(config));
26
+ router.use((0, database_1.databaseRouter)(config));
27
+ router.use((0, file_1.fileRouter)(config));
28
+ router.use((0, project_1.projectRouter)(config));
29
+ router.use((0, export_1.exportRouter)(config));
334
30
  return router;
335
31
  }
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ import { StreamByConfig } from '../../types';
3
+ export declare function authRouter(config: StreamByConfig): Router;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authRouter = authRouter;
4
+ const express_1 = require("express");
5
+ function authRouter(config) {
6
+ const router = (0, express_1.Router)();
7
+ router.get('/auth', async (req, res) => {
8
+ try {
9
+ const auth = await config.authProvider(req);
10
+ if (!auth ||
11
+ !auth.userId ||
12
+ !auth.role) {
13
+ throw new Error('Invalid or missing authentication context');
14
+ }
15
+ return res.status(200).json({ logged: true, ...auth });
16
+ }
17
+ catch (err) {
18
+ return res.status(401).json({ logged: false });
19
+ }
20
+ });
21
+ return router;
22
+ }
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ import { StreamByConfig } from '../../types';
3
+ export declare function databaseRouter(config: StreamByConfig): Router;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.databaseRouter = databaseRouter;
4
+ const express_1 = require("express");
5
+ const connectionManager_1 = require("../../adapters/database/connectionManager");
6
+ function databaseRouter(config) {
7
+ const router = (0, express_1.Router)();
8
+ router.get('/databases', async (req, res) => {
9
+ try {
10
+ const auth = await config.authProvider(req);
11
+ if (!auth ||
12
+ !auth.userId ||
13
+ !auth.role) {
14
+ return res.status(401).json({ error: 'Unauthorized' });
15
+ }
16
+ const connectedDbIds = (0, connectionManager_1.getConnectedIds)();
17
+ const databases = (config.databases || [])
18
+ .filter(db => connectedDbIds.includes(db.id))
19
+ .map(db => ({ name: db.id, value: db.type }));
20
+ res.status(200).json({ databases });
21
+ }
22
+ catch (err) {
23
+ res.status(500).json({ error: 'Failed to get databases' });
24
+ }
25
+ });
26
+ return router;
27
+ }
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ import { StreamByConfig } from '../../types';
3
+ export declare function exportRouter(config: StreamByConfig): Router;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.exportRouter = exportRouter;
4
+ const express_1 = require("express");
5
+ const manager_1 = require("../../models/manager");
6
+ const auth_1 = require("../../utils/auth");
7
+ function exportRouter(config) {
8
+ const router = (0, express_1.Router)();
9
+ const Project = (0, manager_1.getModel)('projects');
10
+ const Export = (0, manager_1.getModel)('exports');
11
+ router.get('/projects/:id/exports/:export_id', async (req, res) => {
12
+ try {
13
+ const auth = await config.authProvider(req);
14
+ if (!auth ||
15
+ !auth.userId ||
16
+ !auth.role) {
17
+ return res.status(401).json({ error: 'Unauthorized' });
18
+ }
19
+ const projectId = req.params.id;
20
+ const exportId = req.params.export_id;
21
+ const project = await Project.findOne({ _id: projectId });
22
+ if (!project) {
23
+ return res.status(404).json({ error: 'Project not found' });
24
+ }
25
+ if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
26
+ return res.status(403).json({ error: 'Unauthorized access' });
27
+ }
28
+ const data = await Export.findOne({ _id: exportId });
29
+ res.json({ data: { ...data, id: data._id || data.id, _id: undefined } });
30
+ }
31
+ catch (err) {
32
+ res.status(500).json({ error: 'Failed to fetch export data', details: err.message });
33
+ }
34
+ });
35
+ router.post('/projects/:id/exports', async (req, res) => {
36
+ try {
37
+ const auth = await config.authProvider(req);
38
+ if (!auth ||
39
+ !auth.userId ||
40
+ !auth.role) {
41
+ return res.status(401).json({ error: 'Unauthorized' });
42
+ }
43
+ const projectId = req.params.id;
44
+ const { name, description, collectionName } = req.body;
45
+ if (!name || !collectionName) {
46
+ return res.status(400).json({ error: 'Missing export name or collectionName' });
47
+ }
48
+ const project = await Project.findOne({ _id: projectId });
49
+ if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
50
+ return res.status(403).json({ error: 'Unauthorized project access' });
51
+ }
52
+ const newExport = await Export.create({
53
+ name,
54
+ description,
55
+ collectionName,
56
+ projectId
57
+ });
58
+ res.status(201).json({ data: { ...newExport, id: newExport._id || newExport.id, _id: undefined } });
59
+ }
60
+ catch (err) {
61
+ res.status(500).json({ error: 'Failed to create export', details: err.message });
62
+ }
63
+ });
64
+ return router;
65
+ }
@@ -0,0 +1,5 @@
1
+ import { Router } from 'express';
2
+ import { StreamByConfig, StorageAdapter } from '../../types';
3
+ export declare function fileRouter(config: StreamByConfig & {
4
+ adapter?: StorageAdapter;
5
+ }): Router;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fileRouter = fileRouter;
4
+ const express_1 = require("express");
5
+ const file_1 = require("../../services/file");
6
+ const presign_1 = require("../../services/presign");
7
+ const storage_1 = require("../../providers/storage");
8
+ const manager_1 = require("../../models/manager");
9
+ function fileRouter(config) {
10
+ const router = (0, express_1.Router)();
11
+ const adapter = config.adapter || (0, storage_1.createStorageProvider)(config.storageProviders);
12
+ const Project = (0, manager_1.getModel)('projects');
13
+ router.get('/upload-project-image-url/:id', async (req, res) => {
14
+ try {
15
+ const auth = await config.authProvider(req);
16
+ if (!auth ||
17
+ !auth.userId ||
18
+ !auth.role) {
19
+ return res.status(401).json({ error: 'Unauthorized' });
20
+ }
21
+ if (auth.role !== 'admin' && auth.role !== 'editor') {
22
+ return res.status(403).json({ error: 'Permission denied' });
23
+ }
24
+ const projectId = req.params.id;
25
+ if (!projectId) {
26
+ return res.status(400).json({ error: 'Missing projectId' });
27
+ }
28
+ const url = await (0, presign_1.getPresignedProjectImageUrl)(adapter, projectId);
29
+ res.json(url);
30
+ }
31
+ catch (err) {
32
+ res.status(500).json({ error: 'Failed to generate presigned URL', details: err.message });
33
+ }
34
+ });
35
+ router.delete('/delete-project-image-url/:id', async (req, res) => {
36
+ try {
37
+ const auth = await config.authProvider(req);
38
+ if (!auth ||
39
+ !auth.userId ||
40
+ !auth.role) {
41
+ return res.status(401).json({ error: 'Unauthorized' });
42
+ }
43
+ if (auth.role !== 'admin' && auth.role !== 'editor') {
44
+ return res.status(403).json({ error: 'Permission denied' });
45
+ }
46
+ const projectId = req.params.id;
47
+ if (!projectId) {
48
+ return res.status(400).json({ error: 'Missing projectId' });
49
+ }
50
+ await (0, file_1.deleteProjectImage)(adapter, projectId);
51
+ const updated = await Project.update({ _id: projectId }, { image: '' });
52
+ res.status(201).json(updated);
53
+ }
54
+ catch (err) {
55
+ res.status(500).json({ error: 'Failed to delete image', details: err.message });
56
+ }
57
+ });
58
+ router.get('/files', async (req, res) => {
59
+ try {
60
+ const auth = await config.authProvider(req);
61
+ if (!auth ||
62
+ !auth.userId ||
63
+ !auth.role) {
64
+ return res.status(401).json({ error: 'Unauthorized' });
65
+ }
66
+ const projectId = (req.query.projectId || req.headers['x-project-id']);
67
+ if (!projectId) {
68
+ return res.status(403).json({ error: 'Unauthorized or missing projectId' });
69
+ }
70
+ const files = await (0, file_1.listFilesService)(adapter, req, projectId);
71
+ res.json(files);
72
+ }
73
+ catch (err) {
74
+ res.status(500).json({ error: 'Failed to list files', details: err });
75
+ }
76
+ });
77
+ return router;
78
+ }
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ import { StreamByConfig } from '../../types';
3
+ export declare function projectRouter(config: StreamByConfig): Router;
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.projectRouter = projectRouter;
4
+ const express_1 = require("express");
5
+ const manager_1 = require("../../models/manager");
6
+ const auth_1 = require("../../utils/auth");
7
+ function projectRouter(config) {
8
+ const router = (0, express_1.Router)();
9
+ const Project = (0, manager_1.getModel)('projects');
10
+ const mapProjectToResponseFormat = (project, userId) => {
11
+ const currentUserMember = project.members?.find((member) => member.userId === userId);
12
+ return {
13
+ id: project._id || project.id,
14
+ dbType: project.dbType,
15
+ name: project.name,
16
+ image: project.image || '',
17
+ archived: currentUserMember ? currentUserMember.archived || false : false,
18
+ };
19
+ };
20
+ router.get('/projects', async (req, res) => {
21
+ try {
22
+ const auth = await config.authProvider(req);
23
+ if (!auth ||
24
+ !auth.userId ||
25
+ !auth.role) {
26
+ return res.status(401).json({ error: 'Unauthorized' });
27
+ }
28
+ const archivedQuery = req.query.archived;
29
+ const filterArchived = archivedQuery !== undefined ? String(archivedQuery).toLowerCase() === 'true' : undefined;
30
+ const allProjects = await Project.find({}); // Fetch all projects
31
+ const projects = allProjects
32
+ .filter(project => {
33
+ const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
34
+ if (!isMember)
35
+ return false;
36
+ if (filterArchived !== undefined) {
37
+ const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
38
+ return currentUserMember ? (currentUserMember.archived || false) === filterArchived : false;
39
+ }
40
+ return true;
41
+ })
42
+ .map(project => mapProjectToResponseFormat(project, auth.userId));
43
+ res.json({ projects });
44
+ }
45
+ catch (err) {
46
+ console.error('Error in /projects endpoint:', err);
47
+ res.status(500).json({ error: 'Failed to list projects', details: err });
48
+ }
49
+ });
50
+ router.post('/projects/create', async (req, res) => {
51
+ try {
52
+ const auth = await config.authProvider(req);
53
+ if (!auth ||
54
+ !auth.userId ||
55
+ !auth.role) {
56
+ return res.status(401).json({ error: 'Unauthorized' });
57
+ }
58
+ if (auth.role !== 'admin' && auth.role !== 'editor') {
59
+ return res.status(403).json({ error: 'Permission denied' });
60
+ }
61
+ const { name, description, dbType } = req.body;
62
+ const newProject = await Project.create({
63
+ dbType: dbType || 'nosql',
64
+ name,
65
+ description: description || '',
66
+ members: [{ userId: auth.userId, role: "admin", archived: false }]
67
+ });
68
+ res.status(201).json({ project: { ...newProject, id: newProject._id || newProject.id, _id: undefined } });
69
+ }
70
+ catch (err) {
71
+ res.status(500).json({ error: 'Failed to create project', details: err.message });
72
+ }
73
+ });
74
+ router.get('/projects/:id', async (req, res) => {
75
+ try {
76
+ const auth = await config.authProvider(req);
77
+ if (!auth ||
78
+ !auth.userId ||
79
+ !auth.role) {
80
+ return res.status(401).json({ error: 'Unauthorized' });
81
+ }
82
+ const projectId = req.params.id;
83
+ const project = await Project.findOne({ _id: projectId });
84
+ if (!project) {
85
+ return res.status(404).json({ error: 'Project not found' });
86
+ }
87
+ if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
88
+ return res.status(403).json({ error: 'Unauthorized project access' });
89
+ }
90
+ res.json({ project: { ...project, id: project._id || project.id, _id: undefined } });
91
+ }
92
+ catch (err) {
93
+ res.status(500).json({ error: 'Failed to fetch project', details: err.message });
94
+ }
95
+ });
96
+ router.patch('/projects/:id', async (req, res) => {
97
+ try {
98
+ const auth = await config.authProvider(req);
99
+ if (!auth ||
100
+ !auth.userId ||
101
+ !auth.role) {
102
+ return res.status(401).json({ error: 'Unauthorized' });
103
+ }
104
+ if (auth.role !== 'admin' && auth.role !== 'editor') {
105
+ return res.status(403).json({ error: 'Permission denied' });
106
+ }
107
+ const projectId = req.params.id;
108
+ const updates = req.body;
109
+ const project = await Project.findOne({ _id: projectId });
110
+ if (!project) {
111
+ return res.status(404).json({ error: 'Project not found' });
112
+ }
113
+ if (!updates || typeof updates !== 'object') {
114
+ return res.status(400).json({ error: 'Missing updates payload' });
115
+ }
116
+ if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
117
+ return res.status(403).json({ error: 'Unauthorized project access' });
118
+ }
119
+ const updated = await Project.update({ _id: projectId }, updates);
120
+ if (!updated) {
121
+ return res.status(404).json({ error: 'Project not found or not updated' });
122
+ }
123
+ res.status(200).json({ success: true, project: { ...updated, id: updated._id || updated.id, _id: undefined } });
124
+ }
125
+ catch (err) {
126
+ res.status(500).json({ error: 'Failed to update project', details: err.message });
127
+ }
128
+ });
129
+ router.delete('/projects/:id', async (req, res) => {
130
+ try {
131
+ const auth = await config.authProvider(req);
132
+ if (!auth ||
133
+ !auth.userId ||
134
+ !auth.role) {
135
+ return res.status(401).json({ error: 'Unauthorized' });
136
+ }
137
+ const projectId = req.params.id;
138
+ const project = await Project.findOne({ _id: projectId });
139
+ if (!project) {
140
+ return res.status(404).json({ error: 'Project not found' });
141
+ }
142
+ if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
143
+ return res.status(403).json({ error: 'Unauthorized project access' });
144
+ }
145
+ await Project.delete({ _id: projectId });
146
+ res.status(200).json({ success: true });
147
+ }
148
+ catch (err) {
149
+ res.status(500).json({ error: 'Failed to delete project', details: err.message });
150
+ }
151
+ });
152
+ router.patch('/projects/:id/archive', async (req, res) => {
153
+ try {
154
+ const auth = await config.authProvider(req);
155
+ if (!auth ||
156
+ !auth.userId ||
157
+ !auth.role) {
158
+ return res.status(401).json({ error: 'Unauthorized' });
159
+ }
160
+ const projectId = req.params.id;
161
+ const project = await Project.findOne({ _id: projectId });
162
+ if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
163
+ return res.status(403).json({ error: 'Unauthorized project access' });
164
+ }
165
+ await Project.update({ _id: projectId, "members.userId": auth.userId }, { "members.$.archived": true, "members.$.archivedBy": auth.userId, "members.$.archivedAt": new Date() });
166
+ // Re-fetch all projects for the user to ensure the list is up-to-date
167
+ const allProjects = await Project.find({});
168
+ const projects = allProjects
169
+ .filter(project => {
170
+ const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
171
+ return isMember; // Only include projects where the user is a member
172
+ })
173
+ .map(project => mapProjectToResponseFormat(project, auth.userId));
174
+ res.status(200).json({ success: true, projects: projects });
175
+ }
176
+ catch (err) {
177
+ res.status(500).json({ error: 'Failed to archive project', details: err.message });
178
+ }
179
+ });
180
+ router.patch('/projects/:id/unarchive', async (req, res) => {
181
+ try {
182
+ const auth = await config.authProvider(req);
183
+ if (!auth ||
184
+ !auth.userId ||
185
+ !auth.role) {
186
+ return res.status(401).json({ error: 'Unauthorized' });
187
+ }
188
+ const projectId = req.params.id;
189
+ const project = await Project.findOne({ _id: projectId });
190
+ if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
191
+ return res.status(403).json({ error: 'Unauthorized project access' });
192
+ }
193
+ await Project.update({ _id: projectId, "members.userId": auth.userId }, { "members.$.archived": false, "members.$.archivedBy": null, "members.$.archivedAt": null });
194
+ // Re-fetch all projects for the user to ensure the list is up-to-date
195
+ const allProjects = await Project.find({});
196
+ const projects = allProjects
197
+ .filter(project => {
198
+ const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
199
+ return isMember; // Only include projects where the user is a member
200
+ })
201
+ .map(project => mapProjectToResponseFormat(project, auth.userId));
202
+ res.status(200).json({ success: true, projects: projects });
203
+ }
204
+ catch (err) {
205
+ res.status(500).json({ error: 'Failed to unarchive project', details: err.message });
206
+ }
207
+ });
208
+ router.get('/projects/:id/members', async (req, res) => {
209
+ try {
210
+ const auth = await config.authProvider(req);
211
+ if (!auth ||
212
+ !auth.userId ||
213
+ !auth.role) {
214
+ return res.status(401).json({ error: 'Unauthorized' });
215
+ }
216
+ const projectId = req.params.id;
217
+ const project = await Project.findOne({ _id: projectId });
218
+ if (!project) {
219
+ return res.status(404).json({ error: 'Project not found' });
220
+ }
221
+ if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
222
+ return res.status(403).json({ error: 'Unauthorized project access' });
223
+ }
224
+ res.json({ members: project.members });
225
+ }
226
+ catch (err) {
227
+ res.status(500).json({ error: 'Failed to fetch project members', details: err.message });
228
+ }
229
+ });
230
+ return router;
231
+ }
@@ -1,4 +1,2 @@
1
- import { Request } from 'express';
2
- import { StreamByConfig, AuthContext } from '../types';
3
- export declare function resolveAuth(config: StreamByConfig, req: Request): Promise<AuthContext>;
1
+ import { AuthContext } from '../types';
4
2
  export declare function checkRole(auth: AuthContext, required: 'viewer' | 'editor' | 'admin'): void;
@@ -1,16 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveAuth = resolveAuth;
4
3
  exports.checkRole = checkRole;
5
- async function resolveAuth(config, req) {
6
- const auth = await config.authProvider(req);
7
- if (!auth ||
8
- !auth.userId ||
9
- !auth.role) {
10
- throw new Error('Invalid or missing authentication context');
11
- }
12
- return auth;
13
- }
14
4
  function checkRole(auth, required) {
15
5
  const roles = ['viewer', 'editor', 'admin'];
16
6
  const userIdx = roles.indexOf(auth.role);
@@ -0,0 +1 @@
1
+ export declare function isProjectMember(project: any, userId: string): any;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isProjectMember = isProjectMember;
4
+ function isProjectMember(project, userId) {
5
+ return project.members?.some((m) => m.userId?.toString() === userId?.toString());
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "streamby-core",
3
- "version": "0.21.0",
3
+ "version": "0.21.2",
4
4
  "description": "StreamBy middleware framework for media storage management",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",