streamby-core 0.29.8 → 0.29.11
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 +27 -7
- package/dist/middleware/createRouter.js +8 -0
- package/dist/middleware/routes/dbConnection.js +115 -33
- package/dist/middleware/routes/project.js +92 -2
- package/dist/middleware/routes/storage.js +84 -49
- package/dist/middleware/routes/storageConnection.js +40 -28
- package/dist/middleware/routes/userIntegration.d.ts +3 -0
- package/dist/middleware/routes/userIntegration.js +93 -0
- package/dist/services/backfillBuiltinConnections.d.ts +2 -0
- package/dist/services/backfillBuiltinConnections.js +57 -0
- package/dist/services/projectIntegration.d.ts +13 -0
- package/dist/services/projectIntegration.js +63 -0
- package/dist/services/userIntegration.d.ts +17 -0
- package/dist/services/userIntegration.js +86 -0
- package/dist/types/index.d.ts +22 -4
- package/dist/utils/builtinAccess.d.ts +6 -0
- package/dist/utils/builtinAccess.js +32 -0
- package/dist/utils/sanitize.d.ts +1 -0
- package/dist/utils/sanitize.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { IntegrationKind, UserIntegration } from '../types';
|
|
2
|
+
export declare function listUserIntegrations(userId: string): Promise<UserIntegration[]>;
|
|
3
|
+
export declare function createUserIntegration(userId: string, input: {
|
|
4
|
+
kind: IntegrationKind;
|
|
5
|
+
provider: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
credentialValue: unknown;
|
|
9
|
+
}): Promise<UserIntegration>;
|
|
10
|
+
export declare function updateUserIntegration(userId: string, integrationId: string, updates: {
|
|
11
|
+
name?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
credentialValue?: unknown;
|
|
14
|
+
}): Promise<UserIntegration | null>;
|
|
15
|
+
export declare function deleteUserIntegration(userId: string, integrationId: string): Promise<boolean>;
|
|
16
|
+
export declare function getDecryptedIntegrationCredential(userId: string, integrationId: string): Promise<unknown | null>;
|
|
17
|
+
export declare function getDecryptedIntegrationCredentialById(integrationId: string): Promise<unknown | null>;
|
|
@@ -0,0 +1,86 @@
|
|
|
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.listUserIntegrations = listUserIntegrations;
|
|
7
|
+
exports.createUserIntegration = createUserIntegration;
|
|
8
|
+
exports.updateUserIntegration = updateUserIntegration;
|
|
9
|
+
exports.deleteUserIntegration = deleteUserIntegration;
|
|
10
|
+
exports.getDecryptedIntegrationCredential = getDecryptedIntegrationCredential;
|
|
11
|
+
exports.getDecryptedIntegrationCredentialById = getDecryptedIntegrationCredentialById;
|
|
12
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
13
|
+
const manager_1 = require("../models/manager");
|
|
14
|
+
const encryption_1 = require("../utils/encryption");
|
|
15
|
+
function encryptCredential(kind, value) {
|
|
16
|
+
return kind === 'storage' ? (0, encryption_1.encrypt)(JSON.stringify(value)) : (0, encryption_1.encrypt)(String(value));
|
|
17
|
+
}
|
|
18
|
+
async function listUserIntegrations(userId) {
|
|
19
|
+
const UserIntegrationModel = (0, manager_1.getModel)('user_integrations');
|
|
20
|
+
return UserIntegrationModel.find({ userId });
|
|
21
|
+
}
|
|
22
|
+
async function createUserIntegration(userId, input) {
|
|
23
|
+
if (!(0, encryption_1.isEncryptionKeySet)()) {
|
|
24
|
+
throw new Error('Encryption key is not set. Cannot create integration.');
|
|
25
|
+
}
|
|
26
|
+
const UserIntegrationModel = (0, manager_1.getModel)('user_integrations');
|
|
27
|
+
const now = new Date();
|
|
28
|
+
const integration = {
|
|
29
|
+
id: crypto_1.default.randomUUID(),
|
|
30
|
+
userId,
|
|
31
|
+
kind: input.kind,
|
|
32
|
+
provider: input.provider,
|
|
33
|
+
name: input.name,
|
|
34
|
+
description: input.description,
|
|
35
|
+
encryptedCredential: encryptCredential(input.kind, input.credentialValue),
|
|
36
|
+
createdAt: now,
|
|
37
|
+
updatedAt: now,
|
|
38
|
+
};
|
|
39
|
+
return UserIntegrationModel.create(integration);
|
|
40
|
+
}
|
|
41
|
+
async function updateUserIntegration(userId, integrationId, updates) {
|
|
42
|
+
const UserIntegrationModel = (0, manager_1.getModel)('user_integrations');
|
|
43
|
+
const existing = await UserIntegrationModel.findOne({ id: integrationId, userId });
|
|
44
|
+
if (!existing)
|
|
45
|
+
return null;
|
|
46
|
+
const $set = { updatedAt: new Date() };
|
|
47
|
+
if (updates.name !== undefined)
|
|
48
|
+
$set.name = updates.name;
|
|
49
|
+
if (updates.description !== undefined)
|
|
50
|
+
$set.description = updates.description;
|
|
51
|
+
if (updates.credentialValue !== undefined) {
|
|
52
|
+
if (!(0, encryption_1.isEncryptionKeySet)()) {
|
|
53
|
+
throw new Error('Encryption key is not set. Cannot update integration.');
|
|
54
|
+
}
|
|
55
|
+
$set.encryptedCredential = encryptCredential(existing.kind, updates.credentialValue);
|
|
56
|
+
}
|
|
57
|
+
return UserIntegrationModel.update({ id: integrationId, userId }, $set);
|
|
58
|
+
}
|
|
59
|
+
async function deleteUserIntegration(userId, integrationId) {
|
|
60
|
+
const UserIntegrationModel = (0, manager_1.getModel)('user_integrations');
|
|
61
|
+
const deletedCount = await UserIntegrationModel.delete({ id: integrationId, userId });
|
|
62
|
+
return deletedCount > 0;
|
|
63
|
+
}
|
|
64
|
+
async function getDecryptedIntegrationCredential(userId, integrationId) {
|
|
65
|
+
const UserIntegrationModel = (0, manager_1.getModel)('user_integrations');
|
|
66
|
+
const integration = await UserIntegrationModel.findOne({ id: integrationId, userId });
|
|
67
|
+
return decryptIntegration(integration);
|
|
68
|
+
}
|
|
69
|
+
// Used when resolving a project connection's `integrationId` at connection-use time — the
|
|
70
|
+
// project already validated ownership when the connection was created (see project.ts /
|
|
71
|
+
// dbConnection.ts POST), so there's no userId to filter by here, only the integrationId
|
|
72
|
+
// stored on the connection itself.
|
|
73
|
+
async function getDecryptedIntegrationCredentialById(integrationId) {
|
|
74
|
+
const UserIntegrationModel = (0, manager_1.getModel)('user_integrations');
|
|
75
|
+
const integration = await UserIntegrationModel.findOne({ id: integrationId });
|
|
76
|
+
return decryptIntegration(integration);
|
|
77
|
+
}
|
|
78
|
+
async function decryptIntegration(integration) {
|
|
79
|
+
if (!integration)
|
|
80
|
+
return null;
|
|
81
|
+
if (!(0, encryption_1.isEncryptionKeySet)()) {
|
|
82
|
+
throw new Error('Encryption key is not set. Cannot decrypt integration credential.');
|
|
83
|
+
}
|
|
84
|
+
const decrypted = (0, encryption_1.decrypt)(integration.encryptedCredential);
|
|
85
|
+
return integration.kind === 'storage' ? JSON.parse(decrypted) : decrypted;
|
|
86
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -17,8 +17,12 @@ export interface StorageConnection {
|
|
|
17
17
|
createdAt: Date;
|
|
18
18
|
description?: string;
|
|
19
19
|
isBuiltin?: boolean;
|
|
20
|
+
integrationId?: string;
|
|
21
|
+
source?: 'builtin' | 'integration' | 'manual';
|
|
22
|
+
available?: boolean;
|
|
20
23
|
}
|
|
21
24
|
export type StorageProvider = {
|
|
25
|
+
id: string;
|
|
22
26
|
type: StorageProviderType;
|
|
23
27
|
config: S3Config;
|
|
24
28
|
};
|
|
@@ -74,6 +78,7 @@ export interface ProjectInfo {
|
|
|
74
78
|
dbConnections?: DbConnection[];
|
|
75
79
|
storageConnections?: StorageConnection[];
|
|
76
80
|
pipelines?: PipelineRef[];
|
|
81
|
+
builtinBackfilledAt?: Date;
|
|
77
82
|
}
|
|
78
83
|
export interface Credential {
|
|
79
84
|
id: string;
|
|
@@ -107,10 +112,7 @@ export interface DatabaseCredential {
|
|
|
107
112
|
main?: boolean;
|
|
108
113
|
}
|
|
109
114
|
export interface StreamByConfig {
|
|
110
|
-
storageProviders:
|
|
111
|
-
type: StorageProviderType;
|
|
112
|
-
config: S3Config;
|
|
113
|
-
}[];
|
|
115
|
+
storageProviders: StorageProvider[];
|
|
114
116
|
authProvider: AuthProvider;
|
|
115
117
|
databases?: DatabaseCredential[];
|
|
116
118
|
adapter?: StorageAdapter;
|
|
@@ -118,6 +120,7 @@ export interface StreamByConfig {
|
|
|
118
120
|
websocket?: {
|
|
119
121
|
server: WebSocketServer;
|
|
120
122
|
};
|
|
123
|
+
canUseBuiltin?: (auth: Auth, builtinId: string, kind: 'database' | 'storage') => boolean | Promise<boolean>;
|
|
121
124
|
}
|
|
122
125
|
export interface Notification {
|
|
123
126
|
_id?: string;
|
|
@@ -154,6 +157,21 @@ export interface DbConnection {
|
|
|
154
157
|
projectId: string;
|
|
155
158
|
createdAt: Date;
|
|
156
159
|
description?: string;
|
|
160
|
+
isBuiltin?: boolean;
|
|
161
|
+
integrationId?: string;
|
|
162
|
+
source?: 'builtin' | 'integration' | 'manual';
|
|
163
|
+
}
|
|
164
|
+
export type IntegrationKind = 'database' | 'storage';
|
|
165
|
+
export interface UserIntegration {
|
|
166
|
+
id: string;
|
|
167
|
+
userId: string;
|
|
168
|
+
kind: IntegrationKind;
|
|
169
|
+
provider: ExternalDbType | StorageProviderType;
|
|
170
|
+
name: string;
|
|
171
|
+
description?: string;
|
|
172
|
+
encryptedCredential: string;
|
|
173
|
+
createdAt: Date;
|
|
174
|
+
updatedAt: Date;
|
|
157
175
|
}
|
|
158
176
|
export interface ColumnDefinition {
|
|
159
177
|
name: string;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Auth, StreamByConfig } from '../types';
|
|
2
|
+
export declare function assertBuiltinAccess(auth: Auth, builtinId: string, config: StreamByConfig, kind: 'database' | 'storage'): Promise<boolean>;
|
|
3
|
+
export declare function isBuiltinStorageId(id: string, config: StreamByConfig): boolean;
|
|
4
|
+
export declare function isBuiltinDb(id: string, config: StreamByConfig): boolean;
|
|
5
|
+
export declare const BUILTIN_STORAGE_DISPLAY: Record<string, string>;
|
|
6
|
+
export declare const BUILTIN_DB_DISPLAY: Record<string, string>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BUILTIN_DB_DISPLAY = exports.BUILTIN_STORAGE_DISPLAY = void 0;
|
|
4
|
+
exports.assertBuiltinAccess = assertBuiltinAccess;
|
|
5
|
+
exports.isBuiltinStorageId = isBuiltinStorageId;
|
|
6
|
+
exports.isBuiltinDb = isBuiltinDb;
|
|
7
|
+
// Gates access to a built-in database/storage provider. Delegates to config.canUseBuiltin
|
|
8
|
+
// when the mounting app implements it (e.g. Nhexa-API checking user_subscriptions);
|
|
9
|
+
// defaults to allow when absent, preserving pre-BYOC behavior for deploys without gating.
|
|
10
|
+
async function assertBuiltinAccess(auth, builtinId, config, kind) {
|
|
11
|
+
if (!config.canUseBuiltin)
|
|
12
|
+
return true;
|
|
13
|
+
return config.canUseBuiltin(auth, builtinId, kind);
|
|
14
|
+
}
|
|
15
|
+
function isBuiltinStorageId(id, config) {
|
|
16
|
+
return (config.storageProviders ?? []).some(p => p.id === id);
|
|
17
|
+
}
|
|
18
|
+
function isBuiltinDb(id, config) {
|
|
19
|
+
return (config.databases ?? []).some(db => db.id === id);
|
|
20
|
+
}
|
|
21
|
+
// Display names for builtin connections — never the raw config id/type. The frontend pairs
|
|
22
|
+
// this with the StreamBy icon to visually mark a connection as built-in vs BYOC.
|
|
23
|
+
exports.BUILTIN_STORAGE_DISPLAY = {
|
|
24
|
+
s3: 'AWS S3',
|
|
25
|
+
gcs: 'Google Cloud Storage',
|
|
26
|
+
r2: 'Cloudflare R2',
|
|
27
|
+
azure: 'Azure Blob Storage',
|
|
28
|
+
};
|
|
29
|
+
exports.BUILTIN_DB_DISPLAY = {
|
|
30
|
+
sql: 'PostgreSQL',
|
|
31
|
+
nosql: 'MongoDB',
|
|
32
|
+
};
|
package/dist/utils/sanitize.d.ts
CHANGED
package/dist/utils/sanitize.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sanitizeProject = sanitizeProject;
|
|
4
|
+
exports.sanitizeUserIntegration = sanitizeUserIntegration;
|
|
4
5
|
function sanitizeProject(project) {
|
|
5
6
|
if (!project)
|
|
6
7
|
return project;
|
|
@@ -9,3 +10,9 @@ function sanitizeProject(project) {
|
|
|
9
10
|
credentials: project.credentials?.map(({ id, key }) => ({ id, key })) ?? [],
|
|
10
11
|
};
|
|
11
12
|
}
|
|
13
|
+
function sanitizeUserIntegration(integration) {
|
|
14
|
+
if (!integration)
|
|
15
|
+
return integration;
|
|
16
|
+
const { encryptedCredential, ...rest } = integration;
|
|
17
|
+
return rest;
|
|
18
|
+
}
|