streamby-core 0.24.5 → 0.24.8
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/nosql.d.ts +1 -1
- package/dist/adapters/database/nosql.js +1 -1
- package/dist/adapters/database/sql.d.ts +1 -1
- package/dist/middleware/createRouter.js +2 -0
- package/dist/middleware/routes/credential.d.ts +3 -0
- package/dist/middleware/routes/credential.js +79 -0
- package/dist/middleware/routes/export.js +101 -14
- package/dist/middleware/routes/project.js +1 -1
- package/dist/services/credential.d.ts +8 -0
- package/dist/services/credential.js +70 -0
- package/dist/services/export.d.ts +3 -4
- package/dist/services/export.js +64 -9
- package/dist/types/index.d.ts +10 -1
- package/dist/utils/crypto.d.ts +3 -0
- package/dist/utils/crypto.js +32 -0
- package/dist/utils/encryption.d.ts +4 -0
- package/dist/utils/encryption.js +75 -0
- package/package.json +61 -60
|
@@ -5,7 +5,7 @@ export declare const createNoSQLExportCollection: (connection: MongoClient, proj
|
|
|
5
5
|
collectionName: string;
|
|
6
6
|
exportId: string;
|
|
7
7
|
}>;
|
|
8
|
-
export declare const createNoSQLRawExportCollection: (connection: MongoClient, projectId: string, exportName: string,
|
|
8
|
+
export declare const createNoSQLRawExportCollection: (connection: MongoClient, projectId: string, exportName: string, method: string, jsonData?: any) => Promise<{
|
|
9
9
|
collectionName: string;
|
|
10
10
|
exportId: string;
|
|
11
11
|
}>;
|
|
@@ -33,7 +33,7 @@ const createNoSQLExportCollection = async (connection, projectId, exportName, fi
|
|
|
33
33
|
return { collectionName, exportId: collectionName };
|
|
34
34
|
};
|
|
35
35
|
exports.createNoSQLExportCollection = createNoSQLExportCollection;
|
|
36
|
-
const createNoSQLRawExportCollection = async (connection, projectId, exportName,
|
|
36
|
+
const createNoSQLRawExportCollection = async (connection, projectId, exportName, method, jsonData) => {
|
|
37
37
|
const db = connection.db();
|
|
38
38
|
const slug = exportName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
39
39
|
const collectionName = `raw_export_${projectId}_${slug}`;
|
|
@@ -4,7 +4,7 @@ export declare const createSQLExportTable: (connection: Pool, projectId: string,
|
|
|
4
4
|
collectionName: string;
|
|
5
5
|
exportId: string;
|
|
6
6
|
}>;
|
|
7
|
-
export declare const createSQLRawExportTable: (connection: Pool, projectId: string, exportName: string, jsonData
|
|
7
|
+
export declare const createSQLRawExportTable: (connection: Pool, projectId: string, exportName: string, jsonData?: any) => Promise<{
|
|
8
8
|
collectionName: string;
|
|
9
9
|
exportId: string;
|
|
10
10
|
}>;
|
|
@@ -13,6 +13,7 @@ const database_1 = require("./routes/database");
|
|
|
13
13
|
const storage_2 = require("./routes/storage");
|
|
14
14
|
const project_1 = require("./routes/project");
|
|
15
15
|
const export_1 = require("./routes/export");
|
|
16
|
+
const credential_1 = require("./routes/credential");
|
|
16
17
|
const auth_2 = require("../services/auth");
|
|
17
18
|
function createStreamByRouter(config) {
|
|
18
19
|
const router = express_1.default.Router();
|
|
@@ -35,5 +36,6 @@ function createStreamByRouter(config) {
|
|
|
35
36
|
router.use((0, storage_2.storageRouter)(config));
|
|
36
37
|
router.use((0, project_1.projectRouter)(config));
|
|
37
38
|
router.use((0, export_1.exportRouter)(config));
|
|
39
|
+
router.use((0, credential_1.credentialRouter)(config));
|
|
38
40
|
return router;
|
|
39
41
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.credentialRouter = credentialRouter;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const manager_1 = require("../../models/manager");
|
|
6
|
+
const auth_1 = require("../../utils/auth");
|
|
7
|
+
const credential_1 = require("../../services/credential");
|
|
8
|
+
function credentialRouter(config) {
|
|
9
|
+
const router = (0, express_1.Router)();
|
|
10
|
+
const Project = (0, manager_1.getModel)('projects');
|
|
11
|
+
// Add a new credential to a project
|
|
12
|
+
router.post('/projects/:id/credentials', async (req, res) => {
|
|
13
|
+
try {
|
|
14
|
+
const auth = req.auth;
|
|
15
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
16
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
17
|
+
}
|
|
18
|
+
const projectId = req.params.id;
|
|
19
|
+
const { id, key, value } = req.body;
|
|
20
|
+
if (!key || !value) {
|
|
21
|
+
return res.status(400).json({ message: 'Missing credential key or value' });
|
|
22
|
+
}
|
|
23
|
+
const project = await Project.findOne({ _id: projectId });
|
|
24
|
+
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
25
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
26
|
+
}
|
|
27
|
+
const updatedProject = await (0, credential_1.addCredential)(config, projectId, { id, key, value });
|
|
28
|
+
res.status(201).json({ message: 'Credential added successfully', project: updatedProject });
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
res.status(500).json({ message: 'Failed to add credential', details: err.message });
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
// Update an existing credential in a project
|
|
35
|
+
router.patch('/projects/:id/credentials/:credentialId', async (req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const auth = req.auth;
|
|
38
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
39
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
40
|
+
}
|
|
41
|
+
const projectId = req.params.id;
|
|
42
|
+
const credentialId = req.params.credentialId;
|
|
43
|
+
const { key, value } = req.body;
|
|
44
|
+
if (!key && !value) {
|
|
45
|
+
return res.status(400).json({ message: 'No update fields provided' });
|
|
46
|
+
}
|
|
47
|
+
const project = await Project.findOne({ _id: projectId });
|
|
48
|
+
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
49
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
50
|
+
}
|
|
51
|
+
const updatedProject = await (0, credential_1.updateCredential)(config, projectId, credentialId, { key, value });
|
|
52
|
+
res.status(200).json({ message: 'Credential updated successfully', project: updatedProject });
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
res.status(500).json({ message: 'Failed to update credential', details: err.message });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
// Delete a credential from a project
|
|
59
|
+
router.delete('/projects/:id/credentials/:credentialId', async (req, res) => {
|
|
60
|
+
try {
|
|
61
|
+
const auth = req.auth;
|
|
62
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
63
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
64
|
+
}
|
|
65
|
+
const projectId = req.params.id;
|
|
66
|
+
const credentialId = req.params.credentialId;
|
|
67
|
+
const project = await Project.findOne({ _id: projectId });
|
|
68
|
+
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
69
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
70
|
+
}
|
|
71
|
+
const updatedProject = await (0, credential_1.deleteCredential)(config, projectId, credentialId);
|
|
72
|
+
res.status(200).json({ message: 'Credential deleted successfully', project: updatedProject });
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
res.status(500).json({ message: 'Failed to delete credential', details: err.message });
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return router;
|
|
79
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.exportRouter = exportRouter;
|
|
4
7
|
const express_1 = require("express");
|
|
@@ -7,6 +10,8 @@ const auth_1 = require("../../utils/auth");
|
|
|
7
10
|
const export_1 = require("../../services/export");
|
|
8
11
|
const connectionManager_1 = require("../../adapters/database/connectionManager");
|
|
9
12
|
const mongodb_1 = require("mongodb");
|
|
13
|
+
const encryption_1 = require("../../utils/encryption");
|
|
14
|
+
const node_fetch_1 = __importDefault(require("node-fetch")); // Import fetch here
|
|
10
15
|
function exportRouter(config) {
|
|
11
16
|
const router = (0, express_1.Router)();
|
|
12
17
|
const Project = (0, manager_1.getModel)('projects');
|
|
@@ -43,6 +48,37 @@ function exportRouter(config) {
|
|
|
43
48
|
const rawData = await db.collection(exportMetadata.collectionName).findOne({ _id: new mongodb_1.ObjectId(exportId) });
|
|
44
49
|
data = rawData ? { json: rawData.json, name: rawData.name, method: rawData.method, collectionName: rawData.collectionName, createdAt: rawData.createdAt, updatedAt: rawData.updatedAt, type: exportMetadata.type } : null;
|
|
45
50
|
}
|
|
51
|
+
else if (exportMetadata.type === 'externalApi') {
|
|
52
|
+
const ProjectModel = (0, manager_1.getModel)('projects', 'nosql');
|
|
53
|
+
const currentProject = await ProjectModel.findOne({ _id: projectId });
|
|
54
|
+
if (!currentProject) {
|
|
55
|
+
return res.status(404).json({ message: 'Project not found.' });
|
|
56
|
+
}
|
|
57
|
+
let headers = {};
|
|
58
|
+
if (exportMetadata.credentialId) {
|
|
59
|
+
const credential = currentProject.credentials?.find((cred) => cred.id === exportMetadata.credentialId);
|
|
60
|
+
if (!credential) {
|
|
61
|
+
return res.status(404).json({ message: `Credential with ID ${exportMetadata.credentialId} not found.` });
|
|
62
|
+
}
|
|
63
|
+
const decryptedValue = (0, encryption_1.decrypt)(credential.encryptedValue);
|
|
64
|
+
const authPrefix = exportMetadata.prefix ? `${exportMetadata.prefix} ` : 'Bearer ';
|
|
65
|
+
headers = {
|
|
66
|
+
'Authorization': `${authPrefix}${decryptedValue}`,
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const response = await (0, node_fetch_1.default)(exportMetadata.apiUrl, { headers });
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw new Error(`Failed to fetch from external API: ${response.statusText}`);
|
|
74
|
+
}
|
|
75
|
+
const responseData = await response.json();
|
|
76
|
+
data = { responseData, name: exportMetadata.name, createdAt: exportMetadata.createdAt, updatedAt: exportMetadata.updatedAt, type: exportMetadata.type, collectionName: exportMetadata.collectionName };
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
return res.status(500).json({ message: 'Failed to fetch from external API', details: error.message });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
46
82
|
else {
|
|
47
83
|
data = await db.collection(exportMetadata.collectionName).find({ __metadata: { $exists: false } }).toArray();
|
|
48
84
|
}
|
|
@@ -86,15 +122,23 @@ function exportRouter(config) {
|
|
|
86
122
|
return res.status(401).json({ message: 'Unauthorized' });
|
|
87
123
|
}
|
|
88
124
|
const projectId = req.params.id;
|
|
89
|
-
const { name, description, collectionName, jsonData, isPrivate, allowedOrigin } = req.body;
|
|
90
|
-
if (!name || !collectionName
|
|
91
|
-
return res.status(400).json({ message: 'Missing export name
|
|
125
|
+
const { name, description, collectionName, jsonData, isPrivate, allowedOrigin, exportType, apiUrl, credentialId, prefix } = req.body;
|
|
126
|
+
if (!name || !collectionName) {
|
|
127
|
+
return res.status(400).json({ message: 'Missing export name or collectionName' });
|
|
128
|
+
}
|
|
129
|
+
if (exportType === 'externalApi') {
|
|
130
|
+
if (!apiUrl) {
|
|
131
|
+
return res.status(400).json({ message: 'API URL is required for externalApi export type' });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else if (!jsonData) {
|
|
135
|
+
return res.status(400).json({ message: 'Missing jsonData for non-externalApi export types' });
|
|
92
136
|
}
|
|
93
137
|
const project = await Project.findOne({ _id: projectId });
|
|
94
138
|
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
95
139
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
96
140
|
}
|
|
97
|
-
const result = await (0, export_1.createExport)(config, projectId, name, collectionName, jsonData, project.dbType, isPrivate, allowedOrigin);
|
|
141
|
+
const result = await (0, export_1.createExport)(config, projectId, name, collectionName, jsonData, project.dbType, exportType || 'raw', isPrivate, allowedOrigin, apiUrl, credentialId, prefix);
|
|
98
142
|
res.status(201).json({ data: result, message: result.message });
|
|
99
143
|
}
|
|
100
144
|
catch (err) {
|
|
@@ -108,15 +152,23 @@ function exportRouter(config) {
|
|
|
108
152
|
return res.status(401).json({ message: 'Unauthorized' });
|
|
109
153
|
}
|
|
110
154
|
const { id: projectId, export_id: exportId } = req.params;
|
|
111
|
-
const { name, collectionName, description, jsonData, isPrivate, allowedOrigin } = req.body;
|
|
112
|
-
if (!name || !collectionName
|
|
113
|
-
return res.status(400).json({ message: 'Missing name
|
|
155
|
+
const { name, collectionName, description, jsonData, isPrivate, allowedOrigin, exportType, apiUrl, credentialId, prefix } = req.body;
|
|
156
|
+
if (!name || !collectionName) {
|
|
157
|
+
return res.status(400).json({ message: 'Missing name or collectionName' });
|
|
158
|
+
}
|
|
159
|
+
if (exportType === 'externalApi') {
|
|
160
|
+
if (!apiUrl) {
|
|
161
|
+
return res.status(400).json({ message: 'API URL is required for externalApi export type' });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else if (!jsonData) {
|
|
165
|
+
return res.status(400).json({ message: 'Missing jsonData for non-externalApi export types' });
|
|
114
166
|
}
|
|
115
167
|
const project = await Project.findOne({ _id: projectId });
|
|
116
168
|
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
117
169
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
118
170
|
}
|
|
119
|
-
const result = await (0, export_1.updateExport)(config, projectId, exportId, name, collectionName, jsonData, project.dbType, isPrivate, allowedOrigin);
|
|
171
|
+
const result = await (0, export_1.updateExport)(config, projectId, exportId, name, collectionName, jsonData, project.dbType, exportType || 'raw', isPrivate, allowedOrigin, apiUrl, credentialId, prefix);
|
|
120
172
|
res.status(200).json({ data: result, message: result.message });
|
|
121
173
|
}
|
|
122
174
|
catch (err) {
|
|
@@ -158,15 +210,25 @@ function exportRouter(config) {
|
|
|
158
210
|
}
|
|
159
211
|
const origin = req.headers.origin;
|
|
160
212
|
let effectiveAllowedOrigins = exportMetadata.allowedOrigin;
|
|
161
|
-
|
|
213
|
+
const projectOrigins = project.allowedOrigin;
|
|
214
|
+
// If export's allowedOrigin is ['*'] or it's not set, it inherits from the project.
|
|
162
215
|
if (!effectiveAllowedOrigins || (effectiveAllowedOrigins.length === 1 && effectiveAllowedOrigins[0] === '*')) {
|
|
163
|
-
effectiveAllowedOrigins =
|
|
216
|
+
effectiveAllowedOrigins = projectOrigins;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// If the export has its own list, ensure it's a subset of the project's list (if project is not public).
|
|
220
|
+
if (projectOrigins && !projectOrigins.includes('*')) {
|
|
221
|
+
const isSubset = effectiveAllowedOrigins.every((o) => projectOrigins.includes(o));
|
|
222
|
+
if (!isSubset) {
|
|
223
|
+
return res.status(403).json({ message: 'Unauthorized: Export origins are not allowed by the parent project.' });
|
|
224
|
+
}
|
|
225
|
+
}
|
|
164
226
|
}
|
|
165
|
-
// If there's no origin, deny access unless
|
|
227
|
+
// If there's no origin header, deny access unless the effective scope is public.
|
|
166
228
|
if (!origin && !(effectiveAllowedOrigins && effectiveAllowedOrigins.includes('*'))) {
|
|
167
229
|
return res.status(403).json({ message: 'Origin header required' });
|
|
168
230
|
}
|
|
169
|
-
// Check for public access ('*') or if the origin is in the list.
|
|
231
|
+
// Check for public access ('*') or if the request's origin is in the effective list.
|
|
170
232
|
const isAllowed = effectiveAllowedOrigins && (effectiveAllowedOrigins.includes('*') || (origin && effectiveAllowedOrigins.includes(origin)));
|
|
171
233
|
if (!isAllowed) {
|
|
172
234
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
@@ -183,8 +245,33 @@ function exportRouter(config) {
|
|
|
183
245
|
const rawData = await db.collection(exportMetadata.collectionName).findOne({ _id: new mongodb_1.ObjectId(exportMetadata.id) });
|
|
184
246
|
data = rawData ? rawData.json : null;
|
|
185
247
|
}
|
|
186
|
-
else {
|
|
187
|
-
|
|
248
|
+
else if (exportMetadata.type === 'externalApi') {
|
|
249
|
+
let headers = {};
|
|
250
|
+
if (exportMetadata.credentialId) {
|
|
251
|
+
if (!(0, encryption_1.isEncryptionKeySet)()) {
|
|
252
|
+
throw new Error('Encryption key is not set. Cannot use encrypted credentials.');
|
|
253
|
+
}
|
|
254
|
+
const credential = project.credentials?.find((cred) => cred.id === exportMetadata.credentialId);
|
|
255
|
+
if (!credential) {
|
|
256
|
+
throw new Error(`Credential with ID ${exportMetadata.credentialId} not found.`);
|
|
257
|
+
}
|
|
258
|
+
const decryptedValue = (0, encryption_1.decrypt)(credential.encryptedValue);
|
|
259
|
+
const authPrefix = exportMetadata.prefix ? `${exportMetadata.prefix} ` : '';
|
|
260
|
+
headers = {
|
|
261
|
+
'Authorization': `${authPrefix}${decryptedValue}`,
|
|
262
|
+
'Content-Type': 'application/json',
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
const response = await (0, node_fetch_1.default)(exportMetadata.apiUrl, { headers });
|
|
267
|
+
if (!response.ok) {
|
|
268
|
+
throw new Error(`Failed to fetch from external API: ${response.statusText}`);
|
|
269
|
+
}
|
|
270
|
+
data = await response.json();
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
throw new Error(`Error fetching from external API: ${error.message}`);
|
|
274
|
+
}
|
|
188
275
|
}
|
|
189
276
|
}
|
|
190
277
|
else if (project.dbType === 'sql') {
|
|
@@ -69,7 +69,7 @@ function projectRouter(config) {
|
|
|
69
69
|
description: description || '',
|
|
70
70
|
image: image || '',
|
|
71
71
|
allowedOrigin: allowedOrigin || [],
|
|
72
|
-
members: [{ userId: auth.userId, username: user.username, role: "admin", archived: false }]
|
|
72
|
+
members: [{ userId: auth.userId, username: user.username, role: "admin", archived: false }],
|
|
73
73
|
});
|
|
74
74
|
const allProjects = await Project.find({});
|
|
75
75
|
const projects = allProjects
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { StreamByConfig, Credential, ProjectInfo } from '../types';
|
|
2
|
+
export declare function addCredential(config: StreamByConfig, projectId: string, newCredential: Omit<Credential, 'encryptedValue'> & {
|
|
3
|
+
value: string;
|
|
4
|
+
}): Promise<ProjectInfo>;
|
|
5
|
+
export declare function updateCredential(config: StreamByConfig, projectId: string, credentialId: string, updates: Partial<Omit<Credential, 'encryptedValue'> & {
|
|
6
|
+
value: string;
|
|
7
|
+
}>): Promise<ProjectInfo>;
|
|
8
|
+
export declare function deleteCredential(config: StreamByConfig, projectId: string, credentialId: string): Promise<ProjectInfo>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addCredential = addCredential;
|
|
4
|
+
exports.updateCredential = updateCredential;
|
|
5
|
+
exports.deleteCredential = deleteCredential;
|
|
6
|
+
const manager_1 = require("../models/manager");
|
|
7
|
+
const encryption_1 = require("../utils/encryption");
|
|
8
|
+
const mongodb_1 = require("mongodb");
|
|
9
|
+
async function addCredential(config, projectId, newCredential) {
|
|
10
|
+
if (!(0, encryption_1.isEncryptionKeySet)()) {
|
|
11
|
+
throw new Error('Encryption key is not set. Cannot add credentials.');
|
|
12
|
+
}
|
|
13
|
+
const ProjectModel = (0, manager_1.getModel)('projects', 'nosql');
|
|
14
|
+
const project = await ProjectModel.findOne({ _id: projectId });
|
|
15
|
+
if (!project) {
|
|
16
|
+
throw new Error('Project not found.');
|
|
17
|
+
}
|
|
18
|
+
const encryptedValue = (0, encryption_1.encrypt)(newCredential.value);
|
|
19
|
+
const credentialToSave = {
|
|
20
|
+
id: newCredential.id || new mongodb_1.ObjectId().toHexString(), // Generate ID if not provided
|
|
21
|
+
key: newCredential.key,
|
|
22
|
+
encryptedValue: encryptedValue,
|
|
23
|
+
};
|
|
24
|
+
const updatedProject = await ProjectModel.update({ _id: projectId }, { $push: { credentials: credentialToSave } });
|
|
25
|
+
if (!updatedProject) {
|
|
26
|
+
throw new Error('Failed to add credential to project.');
|
|
27
|
+
}
|
|
28
|
+
return updatedProject;
|
|
29
|
+
}
|
|
30
|
+
async function updateCredential(config, projectId, credentialId, updates) {
|
|
31
|
+
if (!(0, encryption_1.isEncryptionKeySet)()) {
|
|
32
|
+
throw new Error('Encryption key is not set. Cannot update credentials.');
|
|
33
|
+
}
|
|
34
|
+
const ProjectModel = (0, manager_1.getModel)('projects', 'nosql');
|
|
35
|
+
const project = await ProjectModel.findOne({ _id: projectId });
|
|
36
|
+
if (!project) {
|
|
37
|
+
throw new Error('Project not found.');
|
|
38
|
+
}
|
|
39
|
+
const credentialIndex = project.credentials?.findIndex(cred => cred.id === credentialId);
|
|
40
|
+
if (credentialIndex === undefined || credentialIndex === -1) {
|
|
41
|
+
throw new Error(`Credential with ID ${credentialId} not found.`);
|
|
42
|
+
}
|
|
43
|
+
const currentCredential = project.credentials[credentialIndex];
|
|
44
|
+
let encryptedValue = currentCredential.encryptedValue;
|
|
45
|
+
if (updates.value !== undefined) {
|
|
46
|
+
encryptedValue = (0, encryption_1.encrypt)(updates.value);
|
|
47
|
+
}
|
|
48
|
+
const updatedCredential = {
|
|
49
|
+
...currentCredential,
|
|
50
|
+
key: updates.key || currentCredential.key,
|
|
51
|
+
encryptedValue: encryptedValue,
|
|
52
|
+
};
|
|
53
|
+
const updatedProject = await ProjectModel.update({ _id: projectId, 'credentials.id': credentialId }, { $set: { 'credentials.$': updatedCredential } });
|
|
54
|
+
if (!updatedProject) {
|
|
55
|
+
throw new Error('Failed to update credential in project.');
|
|
56
|
+
}
|
|
57
|
+
return updatedProject;
|
|
58
|
+
}
|
|
59
|
+
async function deleteCredential(config, projectId, credentialId) {
|
|
60
|
+
const ProjectModel = (0, manager_1.getModel)('projects', 'nosql');
|
|
61
|
+
const project = await ProjectModel.findOne({ _id: projectId });
|
|
62
|
+
if (!project) {
|
|
63
|
+
throw new Error('Project not found.');
|
|
64
|
+
}
|
|
65
|
+
const updatedProject = await ProjectModel.update({ _id: projectId }, { $pull: { credentials: { id: credentialId } } });
|
|
66
|
+
if (!updatedProject) {
|
|
67
|
+
throw new Error('Failed to delete credential from project.');
|
|
68
|
+
}
|
|
69
|
+
return updatedProject;
|
|
70
|
+
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { DatabaseType } from '../types';
|
|
1
|
+
import { DatabaseType, StreamByConfig } from '../types';
|
|
2
2
|
interface CreateExportResult {
|
|
3
3
|
exportId: string;
|
|
4
4
|
collectionName: string;
|
|
5
5
|
message: string;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function updateExport(config: StreamByConfig, projectId: string, exportId: string, exportName: string, collectionName: string, jsonData: any, dbType: DatabaseType, isPrivate?: boolean, allowedOrigin?: string[]): Promise<CreateExportResult>;
|
|
7
|
+
export declare function createExport(config: StreamByConfig, projectId: string, exportName: string, collectionName: string, jsonData: any, dbType: DatabaseType, exportType: 'structured' | 'raw' | 'externalApi', isPrivate?: boolean, allowedOrigin?: string[], apiUrl?: string, credentialId?: string, prefix?: string): Promise<CreateExportResult>;
|
|
8
|
+
export declare function updateExport(config: StreamByConfig, projectId: string, exportId: string, exportName: string, collectionName: string, jsonData: any, dbType: DatabaseType, exportType: 'structured' | 'raw' | 'externalApi', isPrivate?: boolean, allowedOrigin?: string[], apiUrl?: string, credentialId?: string, prefix?: string): Promise<CreateExportResult>;
|
|
10
9
|
export declare function deleteExport(config: StreamByConfig, projectId: string, exportId: string, dbType: DatabaseType, collectionName: string): Promise<{
|
|
11
10
|
message: string;
|
|
12
11
|
}>;
|
package/dist/services/export.js
CHANGED
|
@@ -8,7 +8,8 @@ const mongodb_1 = require("mongodb");
|
|
|
8
8
|
const connectionManager_1 = require("../adapters/database/connectionManager");
|
|
9
9
|
const nosql_1 = require("../adapters/database/nosql");
|
|
10
10
|
const sql_1 = require("../adapters/database/sql");
|
|
11
|
-
|
|
11
|
+
const encryption_1 = require("../utils/encryption");
|
|
12
|
+
async function createExport(config, projectId, exportName, collectionName, jsonData, dbType, exportType, isPrivate, allowedOrigin, apiUrl, credentialId, prefix) {
|
|
12
13
|
const targetDb = config.databases?.find(db => db.type === dbType && db.main) ||
|
|
13
14
|
config.databases?.find(db => db.type === dbType);
|
|
14
15
|
if (!targetDb) {
|
|
@@ -16,8 +17,36 @@ async function createExport(config, projectId, exportName, collectionName, jsonD
|
|
|
16
17
|
}
|
|
17
18
|
const connection = (0, connectionManager_1.getConnection)(targetDb.id);
|
|
18
19
|
let result;
|
|
19
|
-
if (
|
|
20
|
-
|
|
20
|
+
if (exportType === 'externalApi') {
|
|
21
|
+
if (!apiUrl) {
|
|
22
|
+
throw new Error('API URL is required for externalApi export type.');
|
|
23
|
+
}
|
|
24
|
+
const ProjectModel = (0, manager_1.getModel)('projects', 'nosql');
|
|
25
|
+
const project = await ProjectModel.findOne({ _id: projectId });
|
|
26
|
+
if (!project) {
|
|
27
|
+
throw new Error('Project not found.');
|
|
28
|
+
}
|
|
29
|
+
if (credentialId) {
|
|
30
|
+
if (!(0, encryption_1.isEncryptionKeySet)()) {
|
|
31
|
+
throw new Error('Encryption key is not set. Cannot use encrypted credentials.');
|
|
32
|
+
}
|
|
33
|
+
const credential = project.credentials?.find(cred => cred.id === credentialId);
|
|
34
|
+
if (!credential) {
|
|
35
|
+
throw new Error(`Credential with ID ${credentialId} not found.`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (dbType === 'nosql') {
|
|
39
|
+
result = await (0, nosql_1.createNoSQLRawExportCollection)(connection.client, projectId, exportName, 'GET', null);
|
|
40
|
+
}
|
|
41
|
+
else if (dbType === 'sql') {
|
|
42
|
+
result = await (0, sql_1.createSQLRawExportTable)(connection.client, projectId, exportName, null);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
throw new Error('Unsupported database type for externalApi export');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (dbType === 'nosql') {
|
|
49
|
+
result = await (0, nosql_1.createNoSQLRawExportCollection)(connection.client, projectId, exportName, 'GET', jsonData);
|
|
21
50
|
}
|
|
22
51
|
else if (dbType === 'sql') {
|
|
23
52
|
result = await (0, sql_1.createSQLRawExportTable)(connection.client, projectId, exportName, jsonData);
|
|
@@ -28,10 +57,10 @@ async function createExport(config, projectId, exportName, collectionName, jsonD
|
|
|
28
57
|
// Update the project with the new export reference
|
|
29
58
|
// Assuming project metadata is always in NoSQL (MongoDB)
|
|
30
59
|
const NoSQLProject = (0, manager_1.getModel)('projects', 'nosql');
|
|
31
|
-
await NoSQLProject.update({ _id: projectId }, { $push: { exports: { id: dbType === 'nosql' ? new mongodb_1.ObjectId(result.exportId) : result.exportId, name: exportName, collectionName: result.collectionName, type:
|
|
32
|
-
return { ...result, message:
|
|
60
|
+
await NoSQLProject.update({ _id: projectId }, { $push: { exports: { id: dbType === 'nosql' ? new mongodb_1.ObjectId(result.exportId) : result.exportId, name: exportName, collectionName: result.collectionName, type: exportType, method: 'GET', private: isPrivate, allowedOrigin: allowedOrigin, apiUrl: apiUrl, credentialId: credentialId, prefix: prefix } } });
|
|
61
|
+
return { ...result, message: `${exportType} export created successfully` };
|
|
33
62
|
}
|
|
34
|
-
async function updateExport(config, projectId, exportId, exportName, collectionName, jsonData, dbType, isPrivate, allowedOrigin) {
|
|
63
|
+
async function updateExport(config, projectId, exportId, exportName, collectionName, jsonData, dbType, exportType, isPrivate, allowedOrigin, apiUrl, credentialId, prefix) {
|
|
35
64
|
const targetDb = config.databases?.find(db => db.type === dbType && db.main) ||
|
|
36
65
|
config.databases?.find(db => db.type === dbType);
|
|
37
66
|
if (!targetDb) {
|
|
@@ -39,7 +68,33 @@ async function updateExport(config, projectId, exportId, exportName, collectionN
|
|
|
39
68
|
}
|
|
40
69
|
const connection = (0, connectionManager_1.getConnection)(targetDb.id);
|
|
41
70
|
let result;
|
|
42
|
-
if (
|
|
71
|
+
if (exportType === 'externalApi') {
|
|
72
|
+
if (!apiUrl) {
|
|
73
|
+
throw new Error('API URL is required for externalApi export type.');
|
|
74
|
+
}
|
|
75
|
+
const ProjectModel = (0, manager_1.getModel)('projects', 'nosql');
|
|
76
|
+
const project = await ProjectModel.findOne({ _id: projectId });
|
|
77
|
+
if (!project) {
|
|
78
|
+
throw new Error('Project not found.');
|
|
79
|
+
}
|
|
80
|
+
if (dbType === 'nosql') {
|
|
81
|
+
const db = connection.client.db();
|
|
82
|
+
const updateData = {
|
|
83
|
+
json: jsonData,
|
|
84
|
+
name: exportName,
|
|
85
|
+
updatedAt: new Date(),
|
|
86
|
+
apiUrl: apiUrl,
|
|
87
|
+
credentialId: credentialId,
|
|
88
|
+
prefix: prefix,
|
|
89
|
+
};
|
|
90
|
+
await db.collection(collectionName).updateOne({ _id: new mongodb_1.ObjectId(exportId) }, { $set: updateData });
|
|
91
|
+
result = { collectionName, exportId };
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
throw new Error('Unsupported database type for externalApi export update');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (dbType === 'nosql') {
|
|
43
98
|
const db = connection.client.db();
|
|
44
99
|
const updateData = {
|
|
45
100
|
json: jsonData,
|
|
@@ -56,8 +111,8 @@ async function updateExport(config, projectId, exportId, exportName, collectionN
|
|
|
56
111
|
await NoSQLProject.update({
|
|
57
112
|
_id: new mongodb_1.ObjectId(projectId),
|
|
58
113
|
'exports.id': { $in: [new mongodb_1.ObjectId(exportId), exportId] }
|
|
59
|
-
}, { $set: { 'exports.$.name': exportName, 'exports.$.collectionName': collectionName, 'exports.$.private': isPrivate, 'exports.$.allowedOrigin': allowedOrigin } });
|
|
60
|
-
return { ...result, message:
|
|
114
|
+
}, { $set: { 'exports.$.name': exportName, 'exports.$.collectionName': collectionName, 'exports.$.private': isPrivate, 'exports.$.allowedOrigin': allowedOrigin, 'exports.$.apiUrl': apiUrl, 'exports.$.credentialId': credentialId, 'exports.$.prefix': prefix } });
|
|
115
|
+
return { ...result, message: `${exportType} export updated successfully` };
|
|
61
116
|
}
|
|
62
117
|
async function deleteExport(config, projectId, exportId, dbType, collectionName) {
|
|
63
118
|
const targetDb = config.databases?.find(db => db.type === dbType && db.main) ||
|
package/dist/types/index.d.ts
CHANGED
|
@@ -43,6 +43,12 @@ export interface ProjectInfo {
|
|
|
43
43
|
allowUpload?: boolean;
|
|
44
44
|
allowSharing?: boolean;
|
|
45
45
|
};
|
|
46
|
+
credentials?: Credential[];
|
|
47
|
+
}
|
|
48
|
+
export interface Credential {
|
|
49
|
+
id: string;
|
|
50
|
+
key: string;
|
|
51
|
+
encryptedValue: string;
|
|
46
52
|
}
|
|
47
53
|
export interface ProjectListInfo {
|
|
48
54
|
id: string;
|
|
@@ -80,9 +86,12 @@ export interface Export {
|
|
|
80
86
|
projectId: string;
|
|
81
87
|
createdAt: Date;
|
|
82
88
|
updatedAt: Date;
|
|
83
|
-
type: 'structured' | 'raw';
|
|
89
|
+
type: 'structured' | 'raw' | 'externalApi';
|
|
84
90
|
fields?: FieldDefinition[];
|
|
85
91
|
jsonData?: any;
|
|
86
92
|
private?: boolean;
|
|
87
93
|
allowedOrigin?: string[];
|
|
94
|
+
apiUrl?: string;
|
|
95
|
+
credentialId?: string;
|
|
96
|
+
prefix?: string;
|
|
88
97
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.encrypt = encrypt;
|
|
7
|
+
exports.decrypt = decrypt;
|
|
8
|
+
exports.hash = hash;
|
|
9
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
10
|
+
const ALGORITHM = 'aes-256-cbc';
|
|
11
|
+
const IV_LENGTH = 16;
|
|
12
|
+
function encrypt(text, secretKey) {
|
|
13
|
+
const iv = crypto_1.default.randomBytes(IV_LENGTH);
|
|
14
|
+
const key = crypto_1.default.createHash('sha256').update(String(secretKey)).digest('base64').substr(0, 32);
|
|
15
|
+
const cipher = crypto_1.default.createCipheriv(ALGORITHM, Buffer.from(key), iv);
|
|
16
|
+
let encrypted = cipher.update(text);
|
|
17
|
+
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
18
|
+
return iv.toString('hex') + ':' + encrypted.toString('hex');
|
|
19
|
+
}
|
|
20
|
+
function decrypt(text, secretKey) {
|
|
21
|
+
const textParts = text.split(':');
|
|
22
|
+
const iv = Buffer.from(textParts.shift(), 'hex');
|
|
23
|
+
const encryptedText = Buffer.from(textParts.join(':'), 'hex');
|
|
24
|
+
const key = crypto_1.default.createHash('sha256').update(String(secretKey)).digest('base64').substr(0, 32);
|
|
25
|
+
const decipher = crypto_1.default.createDecipheriv(ALGORITHM, Buffer.from(key), iv);
|
|
26
|
+
let decrypted = decipher.update(encryptedText);
|
|
27
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
28
|
+
return decrypted.toString();
|
|
29
|
+
}
|
|
30
|
+
function hash(text) {
|
|
31
|
+
return crypto_1.default.createHash('sha256').update(text).digest('hex');
|
|
32
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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.isEncryptionKeySet = exports.decrypt = exports.encrypt = exports.setEncryptionKey = void 0;
|
|
37
|
+
const crypto = __importStar(require("crypto"));
|
|
38
|
+
const ALGORITHM = 'aes-256-cbc';
|
|
39
|
+
const IV_LENGTH = 16; // For AES, this is always 16
|
|
40
|
+
let ENCRYPTION_KEY = process.env.STREAMBY_ENCRYPTION_KEY;
|
|
41
|
+
const setEncryptionKey = (key) => {
|
|
42
|
+
if (key.length !== 64) { // 32 bytes * 2 hex characters per byte
|
|
43
|
+
throw new Error('Invalid encryption key length. Key must be 32 bytes (64 hexadecimal characters).');
|
|
44
|
+
}
|
|
45
|
+
ENCRYPTION_KEY = key;
|
|
46
|
+
};
|
|
47
|
+
exports.setEncryptionKey = setEncryptionKey;
|
|
48
|
+
const encrypt = (text) => {
|
|
49
|
+
if (!ENCRYPTION_KEY) {
|
|
50
|
+
throw new Error('Encryption key is not set. Cannot encrypt credentials.');
|
|
51
|
+
}
|
|
52
|
+
const iv = crypto.randomBytes(IV_LENGTH);
|
|
53
|
+
const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(ENCRYPTION_KEY, 'hex'), iv);
|
|
54
|
+
let encrypted = cipher.update(text);
|
|
55
|
+
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
56
|
+
return iv.toString('hex') + ':' + encrypted.toString('hex');
|
|
57
|
+
};
|
|
58
|
+
exports.encrypt = encrypt;
|
|
59
|
+
const decrypt = (text) => {
|
|
60
|
+
if (!ENCRYPTION_KEY) {
|
|
61
|
+
throw new Error('Encryption key is not set. Cannot decrypt credentials.');
|
|
62
|
+
}
|
|
63
|
+
const textParts = text.split(':');
|
|
64
|
+
const iv = Buffer.from(textParts.shift(), 'hex');
|
|
65
|
+
const encryptedText = Buffer.from(textParts.join(':'), 'hex');
|
|
66
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, Buffer.from(ENCRYPTION_KEY, 'hex'), iv);
|
|
67
|
+
let decrypted = decipher.update(encryptedText);
|
|
68
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
69
|
+
return decrypted.toString();
|
|
70
|
+
};
|
|
71
|
+
exports.decrypt = decrypt;
|
|
72
|
+
const isEncryptionKeySet = () => {
|
|
73
|
+
return !!ENCRYPTION_KEY;
|
|
74
|
+
};
|
|
75
|
+
exports.isEncryptionKeySet = isEncryptionKeySet;
|
package/package.json
CHANGED
|
@@ -1,60 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "streamby-core",
|
|
3
|
-
"version": "0.24.
|
|
4
|
-
"description": "StreamBy middleware framework for media storage management",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist"
|
|
9
|
-
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"test": "vitest",
|
|
13
|
-
"dev": "ts-node-dev --respawn --clear dev.ts",
|
|
14
|
-
"prepublishOnly": "npm run build"
|
|
15
|
-
},
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "https://github.com/GwerhDev/StreamBy-Package.git"
|
|
19
|
-
},
|
|
20
|
-
"keywords": [
|
|
21
|
-
"streamby",
|
|
22
|
-
"middleware",
|
|
23
|
-
"upload",
|
|
24
|
-
"storage",
|
|
25
|
-
"s3",
|
|
26
|
-
"express",
|
|
27
|
-
"typescript"
|
|
28
|
-
],
|
|
29
|
-
"author": "TerminalCore Labs",
|
|
30
|
-
"license": "MIT",
|
|
31
|
-
"dependencies": {
|
|
32
|
-
"@aws-sdk/client-s3": "^3.528.0",
|
|
33
|
-
"@aws-sdk/s3-request-presigner": "^3.787.0",
|
|
34
|
-
"@prisma/client": "^6.12.0",
|
|
35
|
-
"bcrypt": "^5.1.1",
|
|
36
|
-
"dotenv": "^16.5.0",
|
|
37
|
-
"express": "^4.0.0",
|
|
38
|
-
"mongodb": "^6.17.0",
|
|
39
|
-
"mongoose": "^8.13.2",
|
|
40
|
-
"pg": "^8.16.3",
|
|
41
|
-
"prisma": "^6.12.0"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"@types/
|
|
46
|
-
"@types/
|
|
47
|
-
"@types/
|
|
48
|
-
"@types/
|
|
49
|
-
"@types/
|
|
50
|
-
"@types/
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "streamby-core",
|
|
3
|
+
"version": "0.24.8",
|
|
4
|
+
"description": "StreamBy middleware framework for media storage management",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "vitest",
|
|
13
|
+
"dev": "ts-node-dev --respawn --clear dev.ts",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/GwerhDev/StreamBy-Package.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"streamby",
|
|
22
|
+
"middleware",
|
|
23
|
+
"upload",
|
|
24
|
+
"storage",
|
|
25
|
+
"s3",
|
|
26
|
+
"express",
|
|
27
|
+
"typescript"
|
|
28
|
+
],
|
|
29
|
+
"author": "TerminalCore Labs",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@aws-sdk/client-s3": "^3.528.0",
|
|
33
|
+
"@aws-sdk/s3-request-presigner": "^3.787.0",
|
|
34
|
+
"@prisma/client": "^6.12.0",
|
|
35
|
+
"bcrypt": "^5.1.1",
|
|
36
|
+
"dotenv": "^16.5.0",
|
|
37
|
+
"express": "^4.0.0",
|
|
38
|
+
"mongodb": "^6.17.0",
|
|
39
|
+
"mongoose": "^8.13.2",
|
|
40
|
+
"pg": "^8.16.3",
|
|
41
|
+
"prisma": "^6.12.0",
|
|
42
|
+
"node-fetch": "^3.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/bcrypt": "^5.0.2",
|
|
46
|
+
"@types/cors": "^2.8.18",
|
|
47
|
+
"@types/express": "^4.17.17",
|
|
48
|
+
"@types/mongodb": "^4.0.7",
|
|
49
|
+
"@types/node": "^22.15.21",
|
|
50
|
+
"@types/pg": "^8.15.4",
|
|
51
|
+
"@types/supertest": "^6.0.3",
|
|
52
|
+
"cors": "^2.8.5",
|
|
53
|
+
"supertest": "^7.1.4",
|
|
54
|
+
"ts-node-dev": "^2.0.0",
|
|
55
|
+
"typescript": "^5.8.3",
|
|
56
|
+
"vitest": "^3.1.1"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"express": "^4.0.0"
|
|
60
|
+
}
|
|
61
|
+
}
|