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.
@@ -62,8 +62,7 @@ const ensureTablesExist = async (pool) => {
62
62
  image TEXT,
63
63
  "allowedOrigin" JSONB DEFAULT '[]',
64
64
  exports JSONB DEFAULT '[]',
65
- credentials JSONB DEFAULT '[]',
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 credentials JSONB DEFAULT '[]';
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', 'apiConnectionNode',
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 apiConnection_1 = require("../../services/apiConnection");
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 API connections for a project
46
- router.get('/projects/:id/connections/api', async (req, res) => {
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.apiConnections || [] });
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 API connections', details: err.message });
61
+ res.status(500).json({ message: 'Failed to fetch connections', details: err.message });
61
62
  }
62
63
  });
63
- // Add a new API connection to a project
64
- router.post('/projects/:id/connections/api', async (req, res) => {
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, credentialId, prefix } = req.body;
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
- if (credentialId) {
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
- ...(credentialId !== undefined && { credentialId }),
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 API connection', details: err.message });
97
+ res.status(500).json({ message: 'Failed to add connection', details: err.message });
103
98
  }
104
99
  });
105
- // Update an API connection (name, url, method, prefix, credentialId, description)
106
- router.patch('/projects/:id/connections/api/:connectionId', async (req, res) => {
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, credentialId, prefix } = req.body;
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
- if (credentialId) {
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
- ...(credentialId !== undefined && { credentialId }),
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 API connection', details: err.message });
129
+ res.status(500).json({ message: 'Failed to update connection', details: err.message });
141
130
  }
142
131
  });
143
- // Execute the request represented by an API connection
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 apiConnection = project.apiConnections?.find((c) => c.id === connectionId);
156
- if (!apiConnection) {
157
- return res.status(404).json({ message: 'API connection not found' });
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 (apiConnection.credentialId) {
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 credential = project.credentials?.find((c) => c.id === apiConnection.credentialId);
166
- if (!credential) {
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(apiConnection.apiUrl, { method: apiConnection.method || 'GET', headers });
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 an API connection from a project
185
- router.delete('/projects/:id/connections/api/:connectionId', async (req, res) => {
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.apiConnections?.some((c) => c.id === connectionId);
185
+ const exists = project.connections?.some((c) => c.id === connectionId);
201
186
  if (!exists) {
202
- return res.status(404).json({ message: 'API connection not found' });
187
+ return res.status(404).json({ message: 'Connection not found' });
203
188
  }
204
- await (0, apiConnection_1.deleteApiConnection)(config, projectId, connectionId);
205
- return res.status(200).json({ message: 'API connection deleted successfully.' });
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 API connection', details: err.message });
193
+ res.status(500).json({ message: 'Failed to delete connection', details: err.message });
209
194
  }
210
195
  });
211
196
  return router;