streamby-core 0.25.8 → 0.26.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/README.md +242 -242
- package/dist/adapters/database/connectionManager.js +41 -41
- package/dist/adapters/database/nosql.d.ts +2 -2
- package/dist/adapters/database/nosql.js +4 -5
- package/dist/adapters/database/sql.d.ts +1 -1
- package/dist/adapters/database/sql.js +22 -18
- package/dist/middleware/createRouter.js +2 -2
- package/dist/middleware/routes/connection.d.ts +3 -0
- package/dist/middleware/routes/connection.js +174 -0
- package/dist/middleware/routes/export.js +82 -70
- package/dist/middleware/routes/project.js +10 -1
- package/dist/models/Model.js +5 -5
- package/dist/services/export.d.ts +5 -6
- package/dist/services/export.js +18 -81
- package/dist/services/pipeline.d.ts +2 -0
- package/dist/services/pipeline.js +76 -0
- package/dist/types/index.d.ts +10 -4
- package/dist/utils/crypto.d.ts +3 -0
- package/dist/utils/crypto.js +32 -0
- package/package.json +61 -61
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sqlAdapter = exports.createSQLRawExportTable = exports.createSQLExportTable = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
4
5
|
const createSQLExportTable = async (connection, projectId, exportName, fields) => {
|
|
5
6
|
const slug = exportName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
6
7
|
const tableName = `export_${projectId}_${slug}`;
|
|
7
8
|
const columns = fields.map(field => `"${field.name}" ${field.type}`).join(',');
|
|
8
|
-
const createTableQuery = `
|
|
9
|
-
CREATE TABLE IF NOT EXISTS "${tableName}" (
|
|
10
|
-
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
11
|
-
"projectId" UUID NOT NULL,
|
|
12
|
-
__metadata JSONB NOT NULL,
|
|
13
|
-
${columns ? `, ${columns}` : ''}
|
|
14
|
-
);
|
|
9
|
+
const createTableQuery = `
|
|
10
|
+
CREATE TABLE IF NOT EXISTS "${tableName}" (
|
|
11
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
12
|
+
"projectId" UUID NOT NULL,
|
|
13
|
+
__metadata JSONB NOT NULL,
|
|
14
|
+
${columns ? `, ${columns}` : ''}
|
|
15
|
+
);
|
|
15
16
|
`;
|
|
16
17
|
await connection.query(createTableQuery);
|
|
17
18
|
console.log(`✅ Table '${tableName}' created with metadata.`);
|
|
@@ -26,21 +27,24 @@ const createSQLExportTable = async (connection, projectId, exportName, fields) =
|
|
|
26
27
|
return { collectionName: tableName, exportId: tableName };
|
|
27
28
|
};
|
|
28
29
|
exports.createSQLExportTable = createSQLExportTable;
|
|
29
|
-
const createSQLRawExportTable = async (connection,
|
|
30
|
+
const createSQLRawExportTable = async (connection, exportName, nodeSchema) => {
|
|
30
31
|
const slug = exportName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
31
|
-
const tableName =
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const tableName = slug;
|
|
33
|
+
const exportId = (0, crypto_1.randomUUID)();
|
|
34
|
+
const createTableQuery = `
|
|
35
|
+
CREATE TABLE IF NOT EXISTS "${tableName}" (
|
|
36
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
37
|
+
node_schema JSONB,
|
|
38
|
+
name TEXT,
|
|
39
|
+
method TEXT,
|
|
40
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
41
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
42
|
+
);
|
|
37
43
|
`;
|
|
38
44
|
await connection.query(createTableQuery);
|
|
45
|
+
await connection.query(`INSERT INTO "${tableName}" (id, node_schema, name, method) VALUES ($1, $2, $3, $4)`, [exportId, nodeSchema ? JSON.stringify(nodeSchema) : null, exportName, 'GET']);
|
|
39
46
|
console.log(`✅ Raw table '${tableName}' created.`);
|
|
40
|
-
|
|
41
|
-
await connection.query(`INSERT INTO "${tableName}" (data) VALUES ($1)`, [jsonData]);
|
|
42
|
-
console.log(`✅ Raw JSON data inserted into table '${tableName}'.`);
|
|
43
|
-
return { collectionName: tableName, exportId: tableName };
|
|
47
|
+
return { collectionName: tableName, exportId };
|
|
44
48
|
};
|
|
45
49
|
exports.createSQLRawExportTable = createSQLRawExportTable;
|
|
46
50
|
exports.sqlAdapter = {
|
|
@@ -14,7 +14,7 @@ const storage_2 = require("./routes/storage");
|
|
|
14
14
|
const project_1 = require("./routes/project");
|
|
15
15
|
const export_1 = require("./routes/export");
|
|
16
16
|
const credential_1 = require("./routes/credential");
|
|
17
|
-
const
|
|
17
|
+
const connection_1 = require("./routes/connection");
|
|
18
18
|
const member_1 = require("./routes/member");
|
|
19
19
|
const user_1 = require("./routes/user");
|
|
20
20
|
const auth_2 = require("../services/auth");
|
|
@@ -43,7 +43,7 @@ function createStreamByRouter(config) {
|
|
|
43
43
|
router.use((0, project_1.projectRouter)(config));
|
|
44
44
|
router.use((0, export_1.exportRouter)(config));
|
|
45
45
|
router.use((0, credential_1.credentialRouter)(config));
|
|
46
|
-
router.use((0,
|
|
46
|
+
router.use((0, connection_1.apiConnectionRouter)(config));
|
|
47
47
|
router.use((0, member_1.memberRouter)(config));
|
|
48
48
|
router.use((0, user_1.userRouter)(config));
|
|
49
49
|
return router;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.apiConnectionRouter = apiConnectionRouter;
|
|
37
|
+
const express_1 = require("express");
|
|
38
|
+
const manager_1 = require("../../models/manager");
|
|
39
|
+
const auth_1 = require("../../utils/auth");
|
|
40
|
+
const apiConnection_1 = require("../../services/apiConnection");
|
|
41
|
+
const VALID_METHODS = ['GET', 'POST', 'PATCH', 'PUT', 'DELETE'];
|
|
42
|
+
function apiConnectionRouter(config) {
|
|
43
|
+
const router = (0, express_1.Router)();
|
|
44
|
+
const Project = (0, manager_1.getModel)('projects');
|
|
45
|
+
// List API connections for a project
|
|
46
|
+
router.get('/projects/:id/connections/api', async (req, res) => {
|
|
47
|
+
try {
|
|
48
|
+
const auth = req.auth;
|
|
49
|
+
const projectId = req.params.id;
|
|
50
|
+
const project = await Project.findOne({ _id: projectId });
|
|
51
|
+
if (!project) {
|
|
52
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
53
|
+
}
|
|
54
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
55
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
56
|
+
}
|
|
57
|
+
return res.status(200).json({ data: project.apiConnections || [] });
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
res.status(500).json({ message: 'Failed to fetch API connections', details: err.message });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// Add a new API connection to a project
|
|
64
|
+
router.post('/projects/:id/connections/api', async (req, res) => {
|
|
65
|
+
try {
|
|
66
|
+
const auth = req.auth;
|
|
67
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
68
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
69
|
+
}
|
|
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' });
|
|
74
|
+
}
|
|
75
|
+
if (!VALID_METHODS.includes(method)) {
|
|
76
|
+
return res.status(400).json({ message: `method must be one of: ${VALID_METHODS.join(', ')}` });
|
|
77
|
+
}
|
|
78
|
+
const project = await Project.findOne({ _id: projectId });
|
|
79
|
+
if (!project) {
|
|
80
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
81
|
+
}
|
|
82
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
83
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
84
|
+
}
|
|
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, {
|
|
92
|
+
name,
|
|
93
|
+
baseUrl,
|
|
94
|
+
method,
|
|
95
|
+
prefix,
|
|
96
|
+
...(description !== undefined && { description }),
|
|
97
|
+
...(credentialId !== undefined && { credentialId }),
|
|
98
|
+
});
|
|
99
|
+
return res.status(201).json({ data: connection });
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
res.status(500).json({ message: 'Failed to add API connection', details: err.message });
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
// Execute the request represented by an API connection
|
|
106
|
+
router.get('/projects/:id/get-connection/:connectionId', async (req, res) => {
|
|
107
|
+
try {
|
|
108
|
+
const auth = req.auth;
|
|
109
|
+
const { id: projectId, connectionId } = req.params;
|
|
110
|
+
const project = await Project.findOne({ _id: projectId });
|
|
111
|
+
if (!project) {
|
|
112
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
113
|
+
}
|
|
114
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
115
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
116
|
+
}
|
|
117
|
+
const apiConnection = project.apiConnections?.find((c) => c.id === connectionId);
|
|
118
|
+
if (!apiConnection) {
|
|
119
|
+
return res.status(404).json({ message: 'API connection not found' });
|
|
120
|
+
}
|
|
121
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
122
|
+
if (apiConnection.credentialId) {
|
|
123
|
+
const { decrypt, isEncryptionKeySet } = await Promise.resolve().then(() => __importStar(require('../../utils/encryption')));
|
|
124
|
+
if (!isEncryptionKeySet()) {
|
|
125
|
+
return res.status(500).json({ message: 'Encryption key is not set' });
|
|
126
|
+
}
|
|
127
|
+
const credential = project.credentials?.find((c) => c.id === apiConnection.credentialId);
|
|
128
|
+
if (!credential) {
|
|
129
|
+
return res.status(400).json({ message: 'Credential not found in project' });
|
|
130
|
+
}
|
|
131
|
+
const decrypted = decrypt(credential.encryptedValue);
|
|
132
|
+
const prefix = apiConnection.prefix ? `${apiConnection.prefix} ` : '';
|
|
133
|
+
headers['Authorization'] = `${prefix}${decrypted}`;
|
|
134
|
+
}
|
|
135
|
+
const response = await fetch(apiConnection.baseUrl, { method: apiConnection.method || 'GET', headers });
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
return res.status(response.status).json({ message: `External API error: ${response.statusText}` });
|
|
138
|
+
}
|
|
139
|
+
const data = await response.json();
|
|
140
|
+
return res.status(200).json({ data });
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
res.status(500).json({ message: 'Failed to fetch connection data', details: err.message });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// Delete an API connection from a project
|
|
147
|
+
router.delete('/projects/:id/connections/api/:connectionId', async (req, res) => {
|
|
148
|
+
try {
|
|
149
|
+
const auth = req.auth;
|
|
150
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
151
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
152
|
+
}
|
|
153
|
+
const projectId = req.params.id;
|
|
154
|
+
const { connectionId } = req.params;
|
|
155
|
+
const project = await Project.findOne({ _id: projectId });
|
|
156
|
+
if (!project) {
|
|
157
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
158
|
+
}
|
|
159
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
160
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
161
|
+
}
|
|
162
|
+
const exists = project.apiConnections?.some((c) => c.id === connectionId);
|
|
163
|
+
if (!exists) {
|
|
164
|
+
return res.status(404).json({ message: 'API connection not found' });
|
|
165
|
+
}
|
|
166
|
+
await (0, apiConnection_1.deleteApiConnection)(config, projectId, connectionId);
|
|
167
|
+
return res.status(200).json({ message: 'API connection deleted successfully.' });
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
res.status(500).json({ message: 'Failed to delete API connection', details: err.message });
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
return router;
|
|
174
|
+
}
|
|
@@ -5,6 +5,7 @@ const express_1 = require("express");
|
|
|
5
5
|
const manager_1 = require("../../models/manager");
|
|
6
6
|
const auth_1 = require("../../utils/auth");
|
|
7
7
|
const export_1 = require("../../services/export");
|
|
8
|
+
const pipeline_1 = require("../../services/pipeline");
|
|
8
9
|
const connectionManager_1 = require("../../adapters/database/connectionManager");
|
|
9
10
|
const mongodb_1 = require("mongodb");
|
|
10
11
|
const encryption_1 = require("../../utils/encryption");
|
|
@@ -40,7 +41,18 @@ function exportRouter(config) {
|
|
|
40
41
|
let data;
|
|
41
42
|
if (project.dbType === 'nosql') {
|
|
42
43
|
const db = connection.client.db();
|
|
43
|
-
if (exportMetadata.
|
|
44
|
+
if (exportMetadata.nodeSchema) {
|
|
45
|
+
data = {
|
|
46
|
+
name: exportMetadata.name,
|
|
47
|
+
description: exportMetadata.description,
|
|
48
|
+
collectionName: exportMetadata.collectionName,
|
|
49
|
+
nodeSchema: exportMetadata.nodeSchema,
|
|
50
|
+
useConnections: exportMetadata.useConnections,
|
|
51
|
+
useCredentials: exportMetadata.useCredentials,
|
|
52
|
+
type: exportMetadata.type,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
else if (exportMetadata.type === 'json') {
|
|
44
56
|
const rawData = await db.collection(exportMetadata.collectionName).findOne({ _id: new mongodb_1.ObjectId(exportId) });
|
|
45
57
|
data = {
|
|
46
58
|
json: rawData?.json,
|
|
@@ -146,23 +158,19 @@ function exportRouter(config) {
|
|
|
146
158
|
return res.status(401).json({ message: 'Unauthorized' });
|
|
147
159
|
}
|
|
148
160
|
const projectId = req.params.id;
|
|
149
|
-
const { name, description,
|
|
150
|
-
if (!name
|
|
151
|
-
return res.status(400).json({ message: 'Missing export name
|
|
161
|
+
const { name, description, isPrivate, allowedOrigin, useConnections, useCredentials, nodeSchema } = req.body;
|
|
162
|
+
if (!name) {
|
|
163
|
+
return res.status(400).json({ message: 'Missing export name' });
|
|
152
164
|
}
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
return res.status(400).json({ message: 'API URL is required for externalApi export type' });
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
else if (!jsonData) {
|
|
159
|
-
return res.status(400).json({ message: 'Missing jsonData for non-externalApi export types' });
|
|
165
|
+
if (!nodeSchema) {
|
|
166
|
+
return res.status(400).json({ message: 'Missing nodeSchema' });
|
|
160
167
|
}
|
|
168
|
+
const exportType = useConnections ? 'externalApi' : 'json';
|
|
161
169
|
const project = await Project.findOne({ _id: projectId });
|
|
162
170
|
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
163
171
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
164
172
|
}
|
|
165
|
-
const result = await (0, export_1.createExport)(config, projectId, description,
|
|
173
|
+
const result = await (0, export_1.createExport)(config, projectId, description, name, project.dbType, exportType, isPrivate, allowedOrigin, nodeSchema, useConnections, useCredentials);
|
|
166
174
|
res.status(201).json({ data: result, message: result.message });
|
|
167
175
|
}
|
|
168
176
|
catch (err) {
|
|
@@ -176,23 +184,23 @@ function exportRouter(config) {
|
|
|
176
184
|
return res.status(401).json({ message: 'Unauthorized' });
|
|
177
185
|
}
|
|
178
186
|
const { id: projectId, export_id: exportId } = req.params;
|
|
179
|
-
const { name,
|
|
180
|
-
if (!name
|
|
181
|
-
return res.status(400).json({ message: 'Missing name
|
|
182
|
-
}
|
|
183
|
-
if (exportType === 'externalApi') {
|
|
184
|
-
if (!apiUrl) {
|
|
185
|
-
return res.status(400).json({ message: 'API URL is required for externalApi export type' });
|
|
186
|
-
}
|
|
187
|
+
const { name, description, isPrivate, allowedOrigin, useConnections, useCredentials, nodeSchema } = req.body;
|
|
188
|
+
if (!name) {
|
|
189
|
+
return res.status(400).json({ message: 'Missing name' });
|
|
187
190
|
}
|
|
188
|
-
|
|
189
|
-
return res.status(400).json({ message: 'Missing
|
|
191
|
+
if (!nodeSchema) {
|
|
192
|
+
return res.status(400).json({ message: 'Missing nodeSchema' });
|
|
190
193
|
}
|
|
194
|
+
const exportType = useConnections ? 'externalApi' : 'json';
|
|
191
195
|
const project = await Project.findOne({ _id: projectId });
|
|
192
196
|
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
193
197
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
194
198
|
}
|
|
195
|
-
const
|
|
199
|
+
const exportMetadata = project.exports?.find((e) => e.id.toString() === exportId);
|
|
200
|
+
if (!exportMetadata) {
|
|
201
|
+
return res.status(404).json({ message: 'Export not found' });
|
|
202
|
+
}
|
|
203
|
+
const result = await (0, export_1.updateExport)(config, projectId, exportId, description, name, exportMetadata.name, project.dbType, exportType, isPrivate, allowedOrigin, nodeSchema, useConnections, useCredentials);
|
|
196
204
|
res.status(200).json({ data: result, message: result.message });
|
|
197
205
|
}
|
|
198
206
|
catch (err) {
|
|
@@ -214,7 +222,7 @@ function exportRouter(config) {
|
|
|
214
222
|
if (!exportMetadata) {
|
|
215
223
|
return res.status(404).json({ message: 'Export not found in this project' });
|
|
216
224
|
}
|
|
217
|
-
await (0, export_1.deleteExport)(config, projectId, exportId, project.dbType, exportMetadata.
|
|
225
|
+
await (0, export_1.deleteExport)(config, projectId, exportId, project.dbType, exportMetadata.name);
|
|
218
226
|
res.status(200).json({ message: 'Export deleted successfully' });
|
|
219
227
|
}
|
|
220
228
|
catch (err) {
|
|
@@ -257,59 +265,63 @@ function exportRouter(config) {
|
|
|
257
265
|
if (!isAllowed) {
|
|
258
266
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
259
267
|
}
|
|
260
|
-
const targetDb = config.databases?.find(db => db.type === project.dbType);
|
|
261
|
-
if (!targetDb) {
|
|
262
|
-
return res.status(500).json({ message: `Database connection not found for type ${project.dbType}` });
|
|
263
|
-
}
|
|
264
|
-
const connection = (0, connectionManager_1.getConnection)(targetDb.id);
|
|
265
268
|
let data;
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
if (exportMetadata.nodeSchema) {
|
|
270
|
+
data = await (0, pipeline_1.executePipeline)(exportMetadata.nodeSchema, project, config);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
const targetDb = config.databases?.find(db => db.type === project.dbType);
|
|
274
|
+
if (!targetDb) {
|
|
275
|
+
return res.status(500).json({ message: `Database connection not found for type ${project.dbType}` });
|
|
271
276
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
+
const connection = (0, connectionManager_1.getConnection)(targetDb.id);
|
|
278
|
+
if (project.dbType === 'nosql') {
|
|
279
|
+
const db = connection.client.db();
|
|
280
|
+
if (exportMetadata.type === 'json') {
|
|
281
|
+
const rawData = await db.collection(exportMetadata.collectionName).findOne({ _id: new mongodb_1.ObjectId(exportMetadata.id) });
|
|
282
|
+
data = rawData ? rawData.json : null;
|
|
283
|
+
}
|
|
284
|
+
else if (exportMetadata.type === 'externalApi') {
|
|
285
|
+
let headers = {};
|
|
286
|
+
if (exportMetadata.credentialId) {
|
|
287
|
+
if (!(0, encryption_1.isEncryptionKeySet)()) {
|
|
288
|
+
throw new Error('Encryption key is not set. Cannot use encrypted credentials.');
|
|
289
|
+
}
|
|
290
|
+
const credential = project.credentials?.find((cred) => cred.id === exportMetadata.credentialId);
|
|
291
|
+
if (!credential) {
|
|
292
|
+
throw new Error(`Credential with ID ${exportMetadata.credentialId} not found.`);
|
|
293
|
+
}
|
|
294
|
+
const decryptedValue = (0, encryption_1.decrypt)(credential.encryptedValue);
|
|
295
|
+
const authPrefix = exportMetadata.prefix ? `${exportMetadata.prefix} ` : '';
|
|
296
|
+
headers = {
|
|
297
|
+
'Authorization': `${authPrefix}${decryptedValue}`,
|
|
298
|
+
'Content-Type': 'application/json',
|
|
299
|
+
};
|
|
277
300
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
301
|
+
try {
|
|
302
|
+
const response = await fetch(exportMetadata.apiUrl, { headers });
|
|
303
|
+
if (!response.ok) {
|
|
304
|
+
throw new Error(`Failed to fetch from external API: ${response.statusText}`);
|
|
305
|
+
}
|
|
306
|
+
data = await response.json();
|
|
281
307
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
throw new Error(`Failed to fetch from external API: ${response.statusText}`);
|
|
308
|
+
catch (error) {
|
|
309
|
+
throw new Error(`Error fetching from external API: ${error.message}`);
|
|
310
|
+
}
|
|
311
|
+
if (exportMetadata.fields && exportMetadata.fields.length > 0) {
|
|
312
|
+
data = data.map((item) => {
|
|
313
|
+
return exportMetadata.fields.reduce((filtered, field) => {
|
|
314
|
+
filtered[field.name] = item[field.name];
|
|
315
|
+
return filtered;
|
|
316
|
+
}, {});
|
|
317
|
+
});
|
|
293
318
|
}
|
|
294
|
-
data = await response.json();
|
|
295
|
-
}
|
|
296
|
-
catch (error) {
|
|
297
|
-
throw new Error(`Error fetching from external API: ${error.message}`);
|
|
298
|
-
}
|
|
299
|
-
if (exportMetadata.fields && exportMetadata.fields.length > 0) {
|
|
300
|
-
data = data.map((item) => {
|
|
301
|
-
return exportMetadata.fields.reduce((filtered, field) => {
|
|
302
|
-
filtered[field.name] = item[field.name];
|
|
303
|
-
return filtered;
|
|
304
|
-
}, {});
|
|
305
|
-
});
|
|
306
319
|
}
|
|
307
320
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
321
|
+
else if (project.dbType === 'sql') {
|
|
322
|
+
return res.status(501).json({ message: 'SQL public exports not yet implemented' });
|
|
323
|
+
}
|
|
324
|
+
} // end legacy else block
|
|
313
325
|
if (!data) {
|
|
314
326
|
return res.status(404).json({ message: 'Export data not found' });
|
|
315
327
|
}
|
|
@@ -96,7 +96,16 @@ function projectRouter(config) {
|
|
|
96
96
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
97
97
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
98
98
|
}
|
|
99
|
-
|
|
99
|
+
const exports = (project.exports || []).map((e) => ({
|
|
100
|
+
id: e.id,
|
|
101
|
+
name: e.name,
|
|
102
|
+
description: e.description,
|
|
103
|
+
method: e.method,
|
|
104
|
+
private: e.private,
|
|
105
|
+
useConnections: e.useConnections,
|
|
106
|
+
useCredentials: e.useCredentials,
|
|
107
|
+
}));
|
|
108
|
+
res.json({ project: { ...project, id: project._id || project.id, _id: undefined, apiConnections: project.apiConnections || [], exports }, message: 'Project fetched successfully' });
|
|
100
109
|
}
|
|
101
110
|
catch (err) {
|
|
102
111
|
res.status(500).json({ message: 'Failed to fetch project', details: err.message });
|
package/dist/models/Model.js
CHANGED
|
@@ -45,11 +45,11 @@ class Model {
|
|
|
45
45
|
// Handle members filter for SQL projects
|
|
46
46
|
const userId = processedFilter.members.$elemMatch.userId;
|
|
47
47
|
const schema = this.schema || 'streamby'; // Default to 'streamby' if schema not provided
|
|
48
|
-
const query = `
|
|
49
|
-
SELECT p.*, pm."userId" as memberUserId, pm.archived as memberArchived
|
|
50
|
-
FROM "${schema}"."projects" p
|
|
51
|
-
JOIN "${schema}"."project_members" pm ON p.id = pm."projectId"
|
|
52
|
-
WHERE pm."userId" = $1
|
|
48
|
+
const query = `
|
|
49
|
+
SELECT p.*, pm."userId" as memberUserId, pm.archived as memberArchived
|
|
50
|
+
FROM "${schema}"."projects" p
|
|
51
|
+
JOIN "${schema}"."project_members" pm ON p.id = pm."projectId"
|
|
52
|
+
WHERE pm."userId" = $1
|
|
53
53
|
`;
|
|
54
54
|
const result = await connection.query(query, [userId]);
|
|
55
55
|
sqlResults = result.rows.map(row => ({
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
interface
|
|
1
|
+
import { NodeSchema, DatabaseType, StreamByConfig } from '../types';
|
|
2
|
+
interface ExportResult {
|
|
3
3
|
exportId: string;
|
|
4
|
-
collectionName: string;
|
|
5
4
|
message: string;
|
|
6
5
|
}
|
|
7
|
-
export declare function createExport(config: StreamByConfig, projectId: string, description: string,
|
|
8
|
-
export declare function updateExport(config: StreamByConfig, projectId: string, exportId: string, description: string,
|
|
9
|
-
export declare function deleteExport(config: StreamByConfig, projectId: string, exportId: string, dbType: DatabaseType,
|
|
6
|
+
export declare function createExport(config: StreamByConfig, projectId: string, description: string, exportName: string, dbType: DatabaseType, exportType: 'json' | 'externalApi', isPrivate?: boolean, allowedOrigin?: string[], nodeSchema?: NodeSchema, useConnections?: boolean, useCredentials?: boolean): Promise<ExportResult>;
|
|
7
|
+
export declare function updateExport(config: StreamByConfig, projectId: string, exportId: string, description: string, exportName: string, storedExportName: string, dbType: DatabaseType, exportType: 'json' | 'externalApi', isPrivate?: boolean, allowedOrigin?: string[], nodeSchema?: NodeSchema, useConnections?: boolean, useCredentials?: boolean): Promise<ExportResult>;
|
|
8
|
+
export declare function deleteExport(config: StreamByConfig, projectId: string, exportId: string, dbType: DatabaseType, exportName: string): Promise<{
|
|
10
9
|
message: string;
|
|
11
10
|
}>;
|
|
12
11
|
export {};
|