streamby-core 0.29.12 → 0.32.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/adapters/database/connectionManager.js +7 -4
- package/dist/middleware/createRouter.js +0 -2
- package/dist/middleware/routes/ai.js +1 -1
- package/dist/middleware/routes/connection.js +35 -50
- package/dist/middleware/routes/dbConnection.js +60 -222
- package/dist/middleware/routes/distribution.js +5 -4
- package/dist/middleware/routes/export.js +10 -17
- package/dist/middleware/routes/project.js +1 -1
- package/dist/middleware/routes/renderFarm.js +5 -4
- package/dist/middleware/routes/storage.js +2 -43
- package/dist/middleware/routes/storageConnection.js +15 -12
- package/dist/services/backfillBuiltinConnections.js +0 -2
- package/dist/services/connection.d.ts +18 -0
- package/dist/services/connection.js +78 -0
- package/dist/services/connectionResolver.d.ts +19 -0
- package/dist/services/connectionResolver.js +127 -0
- package/dist/services/executor.d.ts +5 -0
- package/dist/services/executor.js +53 -27
- package/dist/services/projectIntegration.js +4 -4
- package/dist/types/index.d.ts +20 -14
- package/dist/types/nodePersistence.d.ts +3 -0
- package/dist/types/nodePersistence.js +15 -0
- package/dist/utils/sanitize.d.ts +10 -0
- package/dist/utils/sanitize.js +16 -1
- package/package.json +1 -1
|
@@ -62,8 +62,7 @@ const ensureTablesExist = async (pool) => {
|
|
|
62
62
|
image TEXT,
|
|
63
63
|
"allowedOrigin" JSONB DEFAULT '[]',
|
|
64
64
|
exports JSONB DEFAULT '[]',
|
|
65
|
-
|
|
66
|
-
"apiConnections" JSONB DEFAULT '[]',
|
|
65
|
+
connections JSONB DEFAULT '[]',
|
|
67
66
|
"dbConnections" JSONB DEFAULT '[]',
|
|
68
67
|
"dbType" VARCHAR(50) NOT NULL DEFAULT 'sql',
|
|
69
68
|
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
@@ -75,13 +74,17 @@ const ensureTablesExist = async (pool) => {
|
|
|
75
74
|
await pool.query(`
|
|
76
75
|
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "allowedOrigin" JSONB DEFAULT '[]';
|
|
77
76
|
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS exports JSONB DEFAULT '[]';
|
|
78
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS
|
|
79
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "apiConnections" JSONB DEFAULT '[]';
|
|
77
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS connections JSONB DEFAULT '[]';
|
|
80
78
|
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "dbConnections" JSONB DEFAULT '[]';
|
|
81
79
|
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "storageConnections" JSONB DEFAULT '[]';
|
|
82
80
|
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS workflow JSONB;
|
|
83
81
|
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS pipelines JSONB DEFAULT '[]';
|
|
84
82
|
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "builtinBackfilledAt" TIMESTAMP WITH TIME ZONE;
|
|
83
|
+
-- Reverted: a project has no notion of a "default" database/storage connection —
|
|
84
|
+
-- each dataSourceNode/ingestNode always declares its own connection explicitly.
|
|
85
|
+
ALTER TABLE streamby.projects DROP COLUMN IF EXISTS "defaultDatabaseId";
|
|
86
|
+
ALTER TABLE streamby.projects DROP COLUMN IF EXISTS "defaultStorageId";
|
|
87
|
+
ALTER TABLE streamby.projects DROP COLUMN IF EXISTS "defaultConnectionsBackfilledAt";
|
|
85
88
|
`);
|
|
86
89
|
// Ensure dbType exists with a non-null default
|
|
87
90
|
await pool.query(`
|
|
@@ -19,7 +19,6 @@ const member_1 = require("./routes/member");
|
|
|
19
19
|
const storage_2 = require("./routes/storage");
|
|
20
20
|
const project_1 = require("./routes/project");
|
|
21
21
|
const database_1 = require("./routes/database");
|
|
22
|
-
const credential_1 = require("./routes/credential");
|
|
23
22
|
const connection_1 = require("./routes/connection");
|
|
24
23
|
const dbConnection_1 = require("./routes/dbConnection");
|
|
25
24
|
const storageConnection_1 = require("./routes/storageConnection");
|
|
@@ -98,7 +97,6 @@ function createStreamByRouter(config) {
|
|
|
98
97
|
router.use((0, storage_2.storageRouter)(config));
|
|
99
98
|
router.use((0, project_1.projectRouter)(config));
|
|
100
99
|
router.use((0, database_1.databaseRouter)(config));
|
|
101
|
-
router.use((0, credential_1.credentialRouter)(config));
|
|
102
100
|
router.use((0, connection_1.connectionRouter)(config));
|
|
103
101
|
router.use((0, dbConnection_1.dbConnectionRouter)(config));
|
|
104
102
|
router.use((0, storageConnection_1.storageConnectionRouter)(config));
|
|
@@ -7,7 +7,7 @@ const auth_1 = require("../../utils/auth");
|
|
|
7
7
|
const jobQueue_1 = require("../../services/jobQueue");
|
|
8
8
|
const aiProcessor_1 = require("../../services/aiProcessor");
|
|
9
9
|
const AVAILABLE_NODE_TYPES = [
|
|
10
|
-
'dataSourceNode', 'jsonInputNode', '
|
|
10
|
+
'dataSourceNode', 'jsonInputNode', 'connectionNode',
|
|
11
11
|
'processNode', 'filterNode',
|
|
12
12
|
'ingestNode', 'transcodeNode', 'captionNode', 'thumbnailNode',
|
|
13
13
|
'renderJobNode', 'formatConvertNode', 'lodNode', 'assetDependencyNode',
|
|
@@ -37,13 +37,14 @@ exports.connectionRouter = connectionRouter;
|
|
|
37
37
|
const express_1 = require("express");
|
|
38
38
|
const manager_1 = require("../../models/manager");
|
|
39
39
|
const auth_1 = require("../../utils/auth");
|
|
40
|
-
const
|
|
40
|
+
const connection_1 = require("../../services/connection");
|
|
41
|
+
const sanitize_1 = require("../../utils/sanitize");
|
|
41
42
|
const VALID_METHODS = ['GET', 'POST', 'PATCH', 'PUT', 'DELETE'];
|
|
42
43
|
function connectionRouter(config) {
|
|
43
44
|
const router = (0, express_1.Router)();
|
|
44
45
|
const Project = (0, manager_1.getModel)('projects');
|
|
45
|
-
// List
|
|
46
|
-
router.get('/projects/:id/connections
|
|
46
|
+
// List connections for a project
|
|
47
|
+
router.get('/projects/:id/connections', async (req, res) => {
|
|
47
48
|
try {
|
|
48
49
|
const auth = req.auth;
|
|
49
50
|
const projectId = req.params.id;
|
|
@@ -54,21 +55,21 @@ function connectionRouter(config) {
|
|
|
54
55
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
55
56
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
56
57
|
}
|
|
57
|
-
return res.status(200).json({ data: project.
|
|
58
|
+
return res.status(200).json({ data: (0, sanitize_1.sanitizeConnections)(project.connections) });
|
|
58
59
|
}
|
|
59
60
|
catch (err) {
|
|
60
|
-
res.status(500).json({ message: 'Failed to fetch
|
|
61
|
+
res.status(500).json({ message: 'Failed to fetch connections', details: err.message });
|
|
61
62
|
}
|
|
62
63
|
});
|
|
63
|
-
// Add a new
|
|
64
|
-
router.post('/projects/:id/connections
|
|
64
|
+
// Add a new connection to a project
|
|
65
|
+
router.post('/projects/:id/connections', async (req, res) => {
|
|
65
66
|
try {
|
|
66
67
|
const auth = req.auth;
|
|
67
68
|
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
68
69
|
return res.status(403).json({ message: 'Permission denied' });
|
|
69
70
|
}
|
|
70
71
|
const projectId = req.params.id;
|
|
71
|
-
const { name, apiUrl, method, description,
|
|
72
|
+
const { name, apiUrl, method, description, token, prefix } = req.body;
|
|
72
73
|
if (!name || !apiUrl) {
|
|
73
74
|
return res.status(400).json({ message: 'name and apiUrl are required' });
|
|
74
75
|
}
|
|
@@ -82,35 +83,29 @@ function connectionRouter(config) {
|
|
|
82
83
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
83
84
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
-
const credExists = project.credentials?.some((c) => c.id === credentialId);
|
|
87
|
-
if (!credExists) {
|
|
88
|
-
return res.status(400).json({ message: 'Credential not found in project' });
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const connection = await (0, apiConnection_1.addApiConnection)(config, projectId, {
|
|
86
|
+
const connection = await (0, connection_1.addConnection)(config, projectId, {
|
|
92
87
|
name,
|
|
93
88
|
apiUrl,
|
|
94
89
|
method,
|
|
95
90
|
prefix,
|
|
96
91
|
...(description !== undefined && { description }),
|
|
97
|
-
...(
|
|
92
|
+
...(token !== undefined && { token }),
|
|
98
93
|
});
|
|
99
|
-
return res.status(201).json({ data: connection });
|
|
94
|
+
return res.status(201).json({ data: (0, sanitize_1.sanitizeConnection)(connection) });
|
|
100
95
|
}
|
|
101
96
|
catch (err) {
|
|
102
|
-
res.status(500).json({ message: 'Failed to add
|
|
97
|
+
res.status(500).json({ message: 'Failed to add connection', details: err.message });
|
|
103
98
|
}
|
|
104
99
|
});
|
|
105
|
-
// Update
|
|
106
|
-
router.patch('/projects/:id/connections
|
|
100
|
+
// Update a connection (name, url, method, prefix, token, description)
|
|
101
|
+
router.patch('/projects/:id/connections/:connectionId', async (req, res) => {
|
|
107
102
|
try {
|
|
108
103
|
const auth = req.auth;
|
|
109
104
|
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
110
105
|
return res.status(403).json({ message: 'Permission denied' });
|
|
111
106
|
}
|
|
112
107
|
const { id: projectId, connectionId } = req.params;
|
|
113
|
-
const { name, apiUrl, method, description,
|
|
108
|
+
const { name, apiUrl, method, description, token, prefix } = req.body;
|
|
114
109
|
if (method && !VALID_METHODS.includes(method)) {
|
|
115
110
|
return res.status(400).json({ message: `method must be one of: ${VALID_METHODS.join(', ')}` });
|
|
116
111
|
}
|
|
@@ -120,27 +115,21 @@ function connectionRouter(config) {
|
|
|
120
115
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
121
116
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
122
117
|
}
|
|
123
|
-
|
|
124
|
-
const credExists = project.credentials?.some((c) => c.id === credentialId);
|
|
125
|
-
if (!credExists) {
|
|
126
|
-
return res.status(400).json({ message: 'Credential not found in project' });
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
const updated = await (0, apiConnection_1.updateApiConnection)(config, projectId, connectionId, {
|
|
118
|
+
const updated = await (0, connection_1.updateConnection)(config, projectId, connectionId, {
|
|
130
119
|
...(name !== undefined && { name }),
|
|
131
120
|
...(apiUrl !== undefined && { apiUrl }),
|
|
132
121
|
...(method !== undefined && { method }),
|
|
133
122
|
...(description !== undefined && { description }),
|
|
134
123
|
...(prefix !== undefined && { prefix }),
|
|
135
|
-
...(
|
|
124
|
+
...(token !== undefined && { token }),
|
|
136
125
|
});
|
|
137
|
-
return res.status(200).json({ data: updated });
|
|
126
|
+
return res.status(200).json({ data: (0, sanitize_1.sanitizeConnection)(updated) });
|
|
138
127
|
}
|
|
139
128
|
catch (err) {
|
|
140
|
-
res.status(500).json({ message: 'Failed to update
|
|
129
|
+
res.status(500).json({ message: 'Failed to update connection', details: err.message });
|
|
141
130
|
}
|
|
142
131
|
});
|
|
143
|
-
// Execute the request represented by
|
|
132
|
+
// Execute the request represented by a connection
|
|
144
133
|
router.get('/projects/:id/get-connection/:connectionId', async (req, res) => {
|
|
145
134
|
try {
|
|
146
135
|
const auth = req.auth;
|
|
@@ -152,25 +141,21 @@ function connectionRouter(config) {
|
|
|
152
141
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
153
142
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
154
143
|
}
|
|
155
|
-
const
|
|
156
|
-
if (!
|
|
157
|
-
return res.status(404).json({ message: '
|
|
144
|
+
const connection = project.connections?.find((c) => c.id === connectionId);
|
|
145
|
+
if (!connection) {
|
|
146
|
+
return res.status(404).json({ message: 'Connection not found' });
|
|
158
147
|
}
|
|
159
148
|
const headers = { 'Content-Type': 'application/json' };
|
|
160
|
-
if (
|
|
149
|
+
if (connection.encryptedCredential) {
|
|
161
150
|
const { decrypt, isEncryptionKeySet } = await Promise.resolve().then(() => __importStar(require('../../utils/encryption')));
|
|
162
151
|
if (!isEncryptionKeySet()) {
|
|
163
152
|
return res.status(500).json({ message: 'Encryption key is not set' });
|
|
164
153
|
}
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
return res.status(400).json({ message: 'Credential not found in project' });
|
|
168
|
-
}
|
|
169
|
-
const decrypted = decrypt(credential.encryptedValue);
|
|
170
|
-
const prefix = apiConnection.prefix ? `${apiConnection.prefix} ` : '';
|
|
154
|
+
const decrypted = decrypt(connection.encryptedCredential);
|
|
155
|
+
const prefix = connection.prefix ? `${connection.prefix} ` : '';
|
|
171
156
|
headers['Authorization'] = `${prefix}${decrypted}`;
|
|
172
157
|
}
|
|
173
|
-
const response = await fetch(
|
|
158
|
+
const response = await fetch(connection.apiUrl, { method: connection.method || 'GET', headers });
|
|
174
159
|
if (!response.ok) {
|
|
175
160
|
return res.status(response.status).json({ message: `External API error: ${response.statusText}` });
|
|
176
161
|
}
|
|
@@ -181,8 +166,8 @@ function connectionRouter(config) {
|
|
|
181
166
|
res.status(500).json({ message: 'Failed to fetch connection data', details: err.message });
|
|
182
167
|
}
|
|
183
168
|
});
|
|
184
|
-
// Delete
|
|
185
|
-
router.delete('/projects/:id/connections
|
|
169
|
+
// Delete a connection from a project
|
|
170
|
+
router.delete('/projects/:id/connections/:connectionId', async (req, res) => {
|
|
186
171
|
try {
|
|
187
172
|
const auth = req.auth;
|
|
188
173
|
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
@@ -197,15 +182,15 @@ function connectionRouter(config) {
|
|
|
197
182
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
198
183
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
199
184
|
}
|
|
200
|
-
const exists = project.
|
|
185
|
+
const exists = project.connections?.some((c) => c.id === connectionId);
|
|
201
186
|
if (!exists) {
|
|
202
|
-
return res.status(404).json({ message: '
|
|
187
|
+
return res.status(404).json({ message: 'Connection not found' });
|
|
203
188
|
}
|
|
204
|
-
await (0,
|
|
205
|
-
return res.status(200).json({ message: '
|
|
189
|
+
await (0, connection_1.deleteConnection)(config, projectId, connectionId);
|
|
190
|
+
return res.status(200).json({ message: 'Connection deleted successfully.' });
|
|
206
191
|
}
|
|
207
192
|
catch (err) {
|
|
208
|
-
res.status(500).json({ message: 'Failed to delete
|
|
193
|
+
res.status(500).json({ message: 'Failed to delete connection', details: err.message });
|
|
209
194
|
}
|
|
210
195
|
});
|
|
211
196
|
return router;
|