streamby-core 0.26.1 → 0.26.3

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/index.d.ts CHANGED
@@ -1 +1,3 @@
1
1
  export { createStreamByRouter } from './middleware/createRouter';
2
+ export { emitToUser } from './services/wsHub';
3
+ export { createNotification } from './services/notification';
package/dist/index.js CHANGED
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createStreamByRouter = void 0;
3
+ exports.createNotification = exports.emitToUser = exports.createStreamByRouter = void 0;
4
4
  var createRouter_1 = require("./middleware/createRouter");
5
5
  Object.defineProperty(exports, "createStreamByRouter", { enumerable: true, get: function () { return createRouter_1.createStreamByRouter; } });
6
+ var wsHub_1 = require("./services/wsHub");
7
+ Object.defineProperty(exports, "emitToUser", { enumerable: true, get: function () { return wsHub_1.emitToUser; } });
8
+ var notification_1 = require("./services/notification");
9
+ Object.defineProperty(exports, "createNotification", { enumerable: true, get: function () { return notification_1.createNotification; } });
@@ -17,8 +17,10 @@ const credential_1 = require("./routes/credential");
17
17
  const connection_1 = require("./routes/connection");
18
18
  const member_1 = require("./routes/member");
19
19
  const user_1 = require("./routes/user");
20
+ const notification_1 = require("./routes/notification");
20
21
  const auth_2 = require("../services/auth");
21
22
  const encryption_1 = require("../utils/encryption");
23
+ const wsHub_1 = require("../services/wsHub");
22
24
  function createStreamByRouter(config) {
23
25
  const router = express_1.default.Router();
24
26
  if (config.encrypt)
@@ -31,11 +33,18 @@ function createStreamByRouter(config) {
31
33
  const streambySchema = sqlDbs.length > 0 ? 'streamby' : undefined;
32
34
  (0, manager_1.registerModel)('projects', allDbIds, 'projects', streambySchema);
33
35
  (0, manager_1.registerModel)('exports', allDbIds, 'exports', streambySchema);
36
+ const nosqlDbIds = config.databases.filter(db => db.type === 'nosql').map(db => db.id);
37
+ if (nosqlDbIds.length > 0) {
38
+ (0, manager_1.registerModel)('notifications', nosqlDbIds, 'notifications');
39
+ }
34
40
  const mainDb = config.databases.find(db => db.main);
35
41
  if (mainDb) {
36
42
  (0, manager_1.registerModel)('users', [mainDb.id], 'users', 'accounts');
37
43
  }
38
44
  }
45
+ if (config.websocket?.server) {
46
+ (0, wsHub_1.initWsHub)(config.websocket.server, config, config.websocket.path);
47
+ }
39
48
  router.use((0, auth_2.authenticate)(config));
40
49
  router.use((0, auth_1.authRouter)(config));
41
50
  router.use((0, database_1.databaseRouter)(config));
@@ -46,5 +55,6 @@ function createStreamByRouter(config) {
46
55
  router.use((0, connection_1.apiConnectionRouter)(config));
47
56
  router.use((0, member_1.memberRouter)(config));
48
57
  router.use((0, user_1.userRouter)(config));
58
+ router.use((0, notification_1.notificationRouter)(config));
49
59
  return router;
50
60
  }
@@ -68,9 +68,9 @@ function apiConnectionRouter(config) {
68
68
  return res.status(403).json({ message: 'Permission denied' });
69
69
  }
70
70
  const projectId = req.params.id;
71
- const { name, baseUrl, method, description, credentialId, prefix } = req.body;
72
- if (!name || !baseUrl) {
73
- return res.status(400).json({ message: 'name and baseUrl are required' });
71
+ const { name, apiUrl, method, description, credentialId, prefix } = req.body;
72
+ if (!name || !apiUrl) {
73
+ return res.status(400).json({ message: 'name and apiUrl are required' });
74
74
  }
75
75
  if (!VALID_METHODS.includes(method)) {
76
76
  return res.status(400).json({ message: `method must be one of: ${VALID_METHODS.join(', ')}` });
@@ -90,7 +90,7 @@ function apiConnectionRouter(config) {
90
90
  }
91
91
  const connection = await (0, apiConnection_1.addApiConnection)(config, projectId, {
92
92
  name,
93
- baseUrl,
93
+ apiUrl,
94
94
  method,
95
95
  prefix,
96
96
  ...(description !== undefined && { description }),
@@ -132,7 +132,7 @@ function apiConnectionRouter(config) {
132
132
  const prefix = apiConnection.prefix ? `${apiConnection.prefix} ` : '';
133
133
  headers['Authorization'] = `${prefix}${decrypted}`;
134
134
  }
135
- const response = await fetch(apiConnection.baseUrl, { method: apiConnection.method || 'GET', headers });
135
+ const response = await fetch(apiConnection.apiUrl, { method: apiConnection.method || 'GET', headers });
136
136
  if (!response.ok) {
137
137
  return res.status(response.status).json({ message: `External API error: ${response.statusText}` });
138
138
  }
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ import { StreamByConfig } from '../../types';
3
+ export declare function notificationRouter(config: StreamByConfig): Router;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.notificationRouter = notificationRouter;
4
+ const express_1 = require("express");
5
+ const manager_1 = require("../../models/manager");
6
+ function notificationRouter(config) {
7
+ const router = (0, express_1.Router)();
8
+ const Notification = (0, manager_1.getModel)('notifications');
9
+ router.get('/notifications', async (req, res) => {
10
+ try {
11
+ const auth = req.auth;
12
+ const notifications = await Notification.find({ userId: auth.userId, read: false });
13
+ res.status(200).json({ data: notifications });
14
+ }
15
+ catch (err) {
16
+ res.status(500).json({ message: 'Failed to fetch notifications', details: err.message });
17
+ }
18
+ });
19
+ router.patch('/notifications/read-all', async (req, res) => {
20
+ try {
21
+ const auth = req.auth;
22
+ const model = Notification;
23
+ if (model.updateMany) {
24
+ await model.updateMany({ userId: auth.userId, read: false }, { $set: { read: true, readAt: new Date() } });
25
+ }
26
+ res.status(200).json({ message: 'All notifications marked as read' });
27
+ }
28
+ catch (err) {
29
+ res.status(500).json({ message: 'Failed to update notifications', details: err.message });
30
+ }
31
+ });
32
+ router.patch('/notifications/:id/read', async (req, res) => {
33
+ try {
34
+ const auth = req.auth;
35
+ const { id } = req.params;
36
+ await Notification.update({ _id: id, userId: auth.userId }, { read: true, readAt: new Date() });
37
+ res.status(200).json({ message: 'Notification marked as read' });
38
+ }
39
+ catch (err) {
40
+ res.status(500).json({ message: 'Failed to update notification', details: err.message });
41
+ }
42
+ });
43
+ return router;
44
+ }
@@ -1,7 +1,7 @@
1
1
  import { StreamByConfig, ApiConnection, ApiConnectionMethod } from '../types';
2
2
  export declare function addApiConnection(config: StreamByConfig, projectId: string, data: {
3
3
  name: string;
4
- baseUrl: string;
4
+ apiUrl: string;
5
5
  method: ApiConnectionMethod;
6
6
  prefix?: string;
7
7
  description?: string;
@@ -14,7 +14,7 @@ async function addApiConnection(config, projectId, data) {
14
14
  id: new mongodb_1.ObjectId().toHexString(),
15
15
  name: data.name,
16
16
  prefix: data.prefix,
17
- baseUrl: data.baseUrl,
17
+ apiUrl: data.apiUrl,
18
18
  method: data.method,
19
19
  projectId,
20
20
  createdAt: new Date(),
@@ -0,0 +1 @@
1
+ export declare function createNotification(userId: string, type: string, message: string, data?: any, appId?: string, callback?: string): Promise<any>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNotification = createNotification;
4
+ const manager_1 = require("../models/manager");
5
+ const wsHub_1 = require("./wsHub");
6
+ async function createNotification(userId, type, message, data, appId, callback) {
7
+ const Notification = (0, manager_1.getModel)('notifications');
8
+ const notification = await Notification.create({
9
+ userId,
10
+ appId: appId ?? null,
11
+ type,
12
+ message,
13
+ data: data ?? null,
14
+ callback: callback ?? null,
15
+ read: false,
16
+ readAt: null,
17
+ createdAt: new Date(),
18
+ });
19
+ (0, wsHub_1.emitToUser)(userId, { type: 'notification', data: notification });
20
+ return notification;
21
+ }
@@ -53,7 +53,7 @@ async function executePipeline(nodeSchema, project, config) {
53
53
  headers['Authorization'] = `${prefix}${decrypted}`;
54
54
  }
55
55
  }
56
- const response = await fetch(apiConnection.baseUrl, { method: apiConnection.method || 'GET', headers });
56
+ const response = await fetch(apiConnection.apiUrl, { method: apiConnection.method || 'GET', headers });
57
57
  if (!response.ok)
58
58
  throw new Error(`API connection fetch failed: ${response.statusText}`);
59
59
  dataResults.push(await response.json());
@@ -0,0 +1,4 @@
1
+ import { Server } from 'http';
2
+ import { StreamByConfig } from '../types';
3
+ export declare function initWsHub(server: Server, config: StreamByConfig, path?: string): void;
4
+ export declare function emitToUser(userId: string, event: object): void;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initWsHub = initWsHub;
4
+ exports.emitToUser = emitToUser;
5
+ const ws_1 = require("ws");
6
+ const connections = new Map();
7
+ function initWsHub(server, config, path = '/streamby/ws') {
8
+ const wss = new ws_1.WebSocketServer({ server, path });
9
+ wss.on('connection', async (ws, req) => {
10
+ let userId = null;
11
+ try {
12
+ const auth = await config.authProvider(req);
13
+ if (!auth?.userId) {
14
+ ws.close(1008, 'Unauthorized');
15
+ return;
16
+ }
17
+ userId = auth.userId;
18
+ }
19
+ catch {
20
+ ws.close(1008, 'Unauthorized');
21
+ return;
22
+ }
23
+ if (!connections.has(userId))
24
+ connections.set(userId, new Set());
25
+ connections.get(userId).add(ws);
26
+ ws.on('close', () => {
27
+ connections.get(userId)?.delete(ws);
28
+ if (connections.get(userId)?.size === 0)
29
+ connections.delete(userId);
30
+ });
31
+ ws.send(JSON.stringify({ type: 'connected', userId }));
32
+ });
33
+ }
34
+ function emitToUser(userId, event) {
35
+ const userConnections = connections.get(userId);
36
+ if (!userConnections)
37
+ return;
38
+ const payload = JSON.stringify(event);
39
+ for (const ws of userConnections) {
40
+ if (ws.readyState === ws_1.WebSocket.OPEN)
41
+ ws.send(payload);
42
+ }
43
+ }
@@ -68,7 +68,7 @@ export type ApiConnectionMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
68
68
  export interface ApiConnection {
69
69
  id: string;
70
70
  name: string;
71
- baseUrl: string;
71
+ apiUrl: string;
72
72
  method: ApiConnectionMethod;
73
73
  projectId: string;
74
74
  createdAt: Date;
@@ -99,6 +99,22 @@ export interface StreamByConfig {
99
99
  databases?: DatabaseCredential[];
100
100
  adapter?: StorageAdapter;
101
101
  encrypt?: string;
102
+ websocket?: {
103
+ server: any;
104
+ path?: string;
105
+ };
106
+ }
107
+ export interface Notification {
108
+ _id?: string;
109
+ userId: string;
110
+ appId?: string;
111
+ type: string;
112
+ message: string;
113
+ data?: any;
114
+ callback?: string;
115
+ read: boolean;
116
+ readAt?: Date;
117
+ createdAt: Date;
102
118
  }
103
119
  export interface Auth {
104
120
  userId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "streamby-core",
3
- "version": "0.26.1",
3
+ "version": "0.26.3",
4
4
  "description": "StreamBy middleware framework for media storage management",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -37,9 +37,10 @@
37
37
  "express": "^4.0.0",
38
38
  "mongodb": "^6.17.0",
39
39
  "mongoose": "^8.13.2",
40
+ "node-fetch": "^3.0.0",
40
41
  "pg": "^8.16.3",
41
42
  "prisma": "^6.12.0",
42
- "node-fetch": "^3.0.0"
43
+ "ws": "^8.20.0"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@types/bcrypt": "^5.0.2",
@@ -49,6 +50,7 @@
49
50
  "@types/node": "^22.15.21",
50
51
  "@types/pg": "^8.15.4",
51
52
  "@types/supertest": "^6.0.3",
53
+ "@types/ws": "^8.18.1",
52
54
  "cors": "^2.8.5",
53
55
  "supertest": "^7.1.4",
54
56
  "ts-node-dev": "^2.0.0",