@devilsdev/rag-pipeline-utils 2.1.12 → 2.2.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/.ragrc.schema.json +218 -0
- package/README.md +292 -32
- package/bin/cli.js +8 -14
- package/dist/index.d.ts +237 -0
- package/dist/index.mjs +22 -7
- package/package.json +17 -13
- package/src/ai/adaptive-retrieval.js +191 -0
- package/src/ai/federated-learning.js +214 -0
- package/src/ai/federation/federated-learning-coordinator.js +345 -0
- package/src/ai/federation.js +76 -0
- package/src/ai/index-fixed.js +509 -0
- package/src/ai/index.js +33 -0
- package/src/ai/model-trainer.js +217 -0
- package/src/ai/model-training.js +205 -0
- package/src/ai/module-template.js +37 -0
- package/src/ai/multimodal/multi-modal-processor.js +345 -0
- package/src/ai/multimodal-processing.js +268 -0
- package/src/ai/multimodal.js +71 -0
- package/src/ai/orchestrator.js +70 -0
- package/src/ai/retrieval/adaptive-retrieval-engine.js +398 -0
- package/src/ai/retrieval-engine.js +69 -0
- package/src/ai/training/model-training-orchestrator.js +228 -0
- package/src/ci/workflow-analyzer.js +71 -0
- package/src/cli/commands/ai-ml.js +967 -0
- package/src/cli/commands/docs.js +228 -0
- package/src/cli/commands/dx.js +538 -0
- package/src/cli/commands/plugin-hub.js +875 -0
- package/src/cli/doctor-command.js +639 -0
- package/src/cli/enhanced-cli-commands.js +945 -0
- package/src/cli/interactive-wizard.js +997 -0
- package/src/cli/plugin-marketplace-commands.js +869 -0
- package/src/cli.js +17 -0
- package/src/config/enhanced-ragrc-schema.js +632 -0
- package/src/config/load-config.js +54 -0
- package/src/config/load-plugin-config.js +69 -0
- package/src/config/normalize-config.js +105 -0
- package/src/config/schema-validator.js +315 -0
- package/src/config/validate-plugin-schema.js +35 -0
- package/src/config/validate-schema.js +113 -0
- package/src/contracts/plugin-contracts.js +33 -0
- package/src/core/create-pipeline.js +99 -0
- package/src/core/dependency-injection.js +242 -0
- package/src/core/observability/event-logger.js +241 -0
- package/src/core/observability/instrumented-pipeline.js +609 -0
- package/src/core/observability/metrics.js +497 -0
- package/src/core/observability/tracing.js +781 -0
- package/src/core/performance/benchmark.js +516 -0
- package/src/core/performance/parallel-processor.js +240 -0
- package/src/core/performance/streaming-safeguards.js +611 -0
- package/src/core/pipeline-factory.js +60 -0
- package/src/core/plugin-contracts.js +89 -0
- package/src/core/plugin-marketplace/plugin-metadata.js +485 -0
- package/src/core/plugin-marketplace/plugin-publisher.js +574 -0
- package/src/core/plugin-marketplace/plugin-registry-format.js +419 -0
- package/src/core/plugin-marketplace/version-resolver.js +61 -0
- package/src/core/plugin-registry.js +265 -0
- package/src/dag/dag-engine.js +954 -0
- package/src/dag/dag-node.js +76 -0
- package/src/dag/enhanced-dag-engine.js +822 -0
- package/src/dx/index.js +40 -0
- package/src/dx/integration-templates.js +665 -0
- package/src/dx/performance-profiler.js +968 -0
- package/src/dx/realtime-debugger.js +755 -0
- package/src/dx/visual-pipeline-builder.js +578 -0
- package/src/ecosystem/plugin-analytics-dashboard.js +778 -0
- package/src/ecosystem/plugin-certification.js +580 -0
- package/src/ecosystem/plugin-hub.js +821 -0
- package/src/enterprise/audit-logging.js +967 -0
- package/src/enterprise/data-governance.js +408 -0
- package/src/enterprise/multi-tenancy.js +496 -0
- package/src/enterprise/sso-integration.js +903 -0
- package/src/evaluate/evaluator.js +52 -0
- package/src/evaluate/scoring.js +91 -0
- package/src/index.js +67 -0
- package/src/ingest.js +59 -0
- package/src/loader/csv-loader.js +38 -0
- package/src/loader/directory-loader.js +48 -0
- package/src/loader/html-loader.js +62 -0
- package/src/loader/markdown-loader.js +67 -0
- package/src/mocks/openai-embedder.js +119 -0
- package/src/mocks/openai-llm.js +77 -0
- package/src/mocks/pdf-loader.js +21 -0
- package/src/mocks/pinecone-retriever.js +106 -0
- package/src/observability/audit-logger.js +758 -0
- package/src/observability/dashboard-config.json +675 -0
- package/src/observability/event-logger.js +310 -0
- package/src/observability/metrics.js +691 -0
- package/src/observability/security-monitor.js +830 -0
- package/src/observability/slo-monitor.js +319 -0
- package/src/observability/telemetry.js +686 -0
- package/src/pipeline/pipeline.js +18 -0
- package/src/plugins/sample-embedder.js +53 -0
- package/src/plugins/sample-llm.js +30 -0
- package/src/plugins/sample-loader.js +24 -0
- package/src/plugins/sample-retriever.js +84 -0
- package/src/query.js +117 -0
- package/src/reranker/llm-reranker.js +85 -0
- package/src/scripts/script-utilities.js +36 -0
- package/src/security/plugin-sandbox.js +586 -0
- package/src/security/plugin-signature-verifier.js +414 -0
- package/src/security/validator.js +36 -0
- package/src/utils/ci/diagnostic-reporter.js +57 -0
- package/src/utils/logger.js +211 -0
- package/src/utils/performance-monitor.js +561 -0
- package/src/utils/plugin-scaffolder.js +447 -0
- package/src/utils/retry-policy.js +443 -0
- package/src/utils/retry.js +107 -0
- package/src/utils/safe-expression-evaluator.js +579 -0
- package/src/utils/structured-logger.js +361 -0
- package/src/utils/validate-plugin-contract.js +42 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise Multi-tenancy Support
|
|
3
|
+
* Isolated workspaces, resource quotas, and tenant management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs').promises;
|
|
7
|
+
// eslint-disable-line global-require
|
|
8
|
+
const path = require('path');
|
|
9
|
+
// eslint-disable-line global-require
|
|
10
|
+
const crypto = require('crypto');
|
|
11
|
+
// eslint-disable-line global-require
|
|
12
|
+
const { EventEmitter } = require('events');
|
|
13
|
+
// eslint-disable-line global-require
|
|
14
|
+
|
|
15
|
+
class TenantManager extends EventEmitter {
|
|
16
|
+
constructor(_options = {}) {
|
|
17
|
+
super();
|
|
18
|
+
|
|
19
|
+
this._config = {
|
|
20
|
+
dataDir: _options.dataDir || path.join(process.cwd(), '.rag-enterprise'),
|
|
21
|
+
defaultQuotas: {
|
|
22
|
+
maxUsers: 100,
|
|
23
|
+
maxWorkspaces: 10,
|
|
24
|
+
maxStorageGB: 50,
|
|
25
|
+
maxAPICallsPerMonth: 100000,
|
|
26
|
+
maxConcurrentPipelines: 5,
|
|
27
|
+
maxPlugins: 50,
|
|
28
|
+
},
|
|
29
|
+
isolation: {
|
|
30
|
+
networkIsolation: true,
|
|
31
|
+
storageIsolation: true,
|
|
32
|
+
resourceIsolation: true,
|
|
33
|
+
},
|
|
34
|
+
..._options,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
this.tenants = new Map();
|
|
38
|
+
this.workspaces = new Map();
|
|
39
|
+
this.resourceMonitor = new ResourceMonitor(this._config);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create a new tenant with isolated resources
|
|
44
|
+
*/
|
|
45
|
+
async createTenant(tenantData) {
|
|
46
|
+
const _tenantId = crypto.randomUUID();
|
|
47
|
+
|
|
48
|
+
const tenant = {
|
|
49
|
+
id: _tenantId,
|
|
50
|
+
name: tenantData.name,
|
|
51
|
+
domain: tenantData.domain,
|
|
52
|
+
plan: tenantData.plan || 'enterprise',
|
|
53
|
+
quotas: { ...this._config.defaultQuotas, ...tenantData.quotas },
|
|
54
|
+
settings: {
|
|
55
|
+
ssoEnabled: tenantData.ssoEnabled || false,
|
|
56
|
+
auditLoggingEnabled: true,
|
|
57
|
+
dataGovernanceEnabled: true,
|
|
58
|
+
encryptionAtRest: true,
|
|
59
|
+
...tenantData.settings,
|
|
60
|
+
},
|
|
61
|
+
metadata: {
|
|
62
|
+
createdAt: new Date().toISOString(),
|
|
63
|
+
createdBy: tenantData.createdBy,
|
|
64
|
+
status: 'active',
|
|
65
|
+
lastActivity: new Date().toISOString(),
|
|
66
|
+
},
|
|
67
|
+
isolation: {
|
|
68
|
+
dataPath: path.join(this._config.dataDir, 'tenants', _tenantId),
|
|
69
|
+
networkNamespace: `tenant-${_tenantId}`,
|
|
70
|
+
resourceLimits: this._calculateResourceLimits(tenantData.plan),
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Create isolated tenant directory structure
|
|
75
|
+
await this._createTenantInfrastructure(tenant);
|
|
76
|
+
|
|
77
|
+
// Initialize tenant-specific services
|
|
78
|
+
await this._initializeTenantServices(tenant);
|
|
79
|
+
|
|
80
|
+
this.tenants.set(_tenantId, tenant);
|
|
81
|
+
|
|
82
|
+
this.emit('tenant_created', { _tenantId, tenant });
|
|
83
|
+
|
|
84
|
+
return tenant;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create isolated workspace within a tenant
|
|
89
|
+
*/
|
|
90
|
+
async createWorkspace(_tenantId, workspaceData) {
|
|
91
|
+
const tenant = this.tenants.get(_tenantId);
|
|
92
|
+
if (!tenant) {
|
|
93
|
+
throw new Error(`Tenant ${_tenantId} not found`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Check workspace quota
|
|
97
|
+
const existingWorkspaces = Array.from(this.workspaces.values()).filter(
|
|
98
|
+
(w) => w.tenantId === _tenantId,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
if (existingWorkspaces.length >= tenant.quotas.maxWorkspaces) {
|
|
102
|
+
throw new Error(`Workspace quota exceeded for tenant ${_tenantId}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const _workspaceId = crypto.randomUUID();
|
|
106
|
+
|
|
107
|
+
const workspace = {
|
|
108
|
+
id: _workspaceId,
|
|
109
|
+
_tenantId,
|
|
110
|
+
name: workspaceData.name,
|
|
111
|
+
description: workspaceData.description,
|
|
112
|
+
settings: {
|
|
113
|
+
privacy: workspaceData.privacy || 'private',
|
|
114
|
+
collaborationEnabled: workspaceData.collaborationEnabled || false,
|
|
115
|
+
pluginsEnabled: workspaceData.pluginsEnabled || true,
|
|
116
|
+
...workspaceData.settings,
|
|
117
|
+
},
|
|
118
|
+
resources: {
|
|
119
|
+
storageUsedMB: 0,
|
|
120
|
+
apiCallsThisMonth: 0,
|
|
121
|
+
activePipelines: 0,
|
|
122
|
+
installedPlugins: 0,
|
|
123
|
+
},
|
|
124
|
+
isolation: {
|
|
125
|
+
dataPath: path.join(
|
|
126
|
+
tenant.isolation.dataPath,
|
|
127
|
+
'workspaces',
|
|
128
|
+
_workspaceId,
|
|
129
|
+
),
|
|
130
|
+
configPath: path.join(
|
|
131
|
+
tenant.isolation.dataPath,
|
|
132
|
+
'workspaces',
|
|
133
|
+
_workspaceId,
|
|
134
|
+
'.ragrc.json',
|
|
135
|
+
),
|
|
136
|
+
pluginsPath: path.join(
|
|
137
|
+
tenant.isolation.dataPath,
|
|
138
|
+
'workspaces',
|
|
139
|
+
_workspaceId,
|
|
140
|
+
'plugins',
|
|
141
|
+
),
|
|
142
|
+
},
|
|
143
|
+
metadata: {
|
|
144
|
+
createdAt: new Date().toISOString(),
|
|
145
|
+
createdBy: workspaceData.createdBy,
|
|
146
|
+
lastActivity: new Date().toISOString(),
|
|
147
|
+
version: '1.0.0',
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Create isolated workspace infrastructure
|
|
152
|
+
await this._createWorkspaceInfrastructure(workspace);
|
|
153
|
+
|
|
154
|
+
this.workspaces.set(_workspaceId, workspace);
|
|
155
|
+
|
|
156
|
+
this.emit('workspace_created', { _tenantId, _workspaceId, workspace });
|
|
157
|
+
|
|
158
|
+
return workspace;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get tenant with resource usage
|
|
163
|
+
*/
|
|
164
|
+
async getTenant(_tenantId) {
|
|
165
|
+
const tenant = this.tenants.get(_tenantId);
|
|
166
|
+
if (!tenant) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Get current resource usage
|
|
171
|
+
const usage = await this.resourceMonitor.getTenantUsage(_tenantId);
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
...tenant,
|
|
175
|
+
usage,
|
|
176
|
+
quotaUtilization: this._calculateQuotaUtilization(tenant.quotas, usage),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* List workspaces for a tenant
|
|
182
|
+
*/
|
|
183
|
+
async getWorkspaces(_tenantId, _options = {}) {
|
|
184
|
+
const workspaces = Array.from(this.workspaces.values()).filter(
|
|
185
|
+
(w) => w._tenantId === _tenantId,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (_options.includeUsage) {
|
|
189
|
+
for (const workspace of workspaces) {
|
|
190
|
+
workspace.usage = await this.resourceMonitor.getWorkspaceUsage(
|
|
191
|
+
workspace.id,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return workspaces;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Update tenant quotas
|
|
201
|
+
*/
|
|
202
|
+
async updateTenantQuotas(_tenantId, newQuotas) {
|
|
203
|
+
const tenant = this.tenants.get(_tenantId);
|
|
204
|
+
if (!tenant) {
|
|
205
|
+
throw new Error(`Tenant ${_tenantId} not found`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const oldQuotas = { ...tenant.quotas };
|
|
209
|
+
tenant.quotas = { ...tenant.quotas, ...newQuotas };
|
|
210
|
+
tenant.metadata.lastUpdated = new Date().toISOString();
|
|
211
|
+
|
|
212
|
+
// Persist changes
|
|
213
|
+
await this._persistTenant(tenant);
|
|
214
|
+
|
|
215
|
+
this.emit('tenant_quotas_updated', {
|
|
216
|
+
_tenantId,
|
|
217
|
+
oldQuotas,
|
|
218
|
+
newQuotas: tenant.quotas,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return tenant;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Enforce resource quotas
|
|
226
|
+
*/
|
|
227
|
+
async enforceQuotas(_tenantId, operation, resourceType, amount) {
|
|
228
|
+
const tenant = this.tenants.get(_tenantId);
|
|
229
|
+
if (!tenant) {
|
|
230
|
+
throw new Error(`Tenant ${_tenantId} not found`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const usage = await this.resourceMonitor.getTenantUsage(_tenantId);
|
|
234
|
+
|
|
235
|
+
switch (resourceType) {
|
|
236
|
+
case 'storage':
|
|
237
|
+
if (usage.storageUsedGB + amount / 1024 > tenant.quotas.maxStorageGB) {
|
|
238
|
+
throw new Error(`Storage quota exceeded for tenant ${_tenantId}`);
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
|
|
242
|
+
case 'apiCalls':
|
|
243
|
+
if (
|
|
244
|
+
usage.apiCallsThisMonth + amount >
|
|
245
|
+
tenant.quotas.maxAPICallsPerMonth
|
|
246
|
+
) {
|
|
247
|
+
throw new Error(`API calls quota exceeded for tenant ${_tenantId}`);
|
|
248
|
+
}
|
|
249
|
+
break;
|
|
250
|
+
|
|
251
|
+
case 'concurrentPipelines':
|
|
252
|
+
if (usage.activePipelines >= tenant.quotas.maxConcurrentPipelines) {
|
|
253
|
+
throw new Error(
|
|
254
|
+
`Concurrent pipelines quota exceeded for tenant ${_tenantId}`,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
break;
|
|
258
|
+
|
|
259
|
+
case 'plugins':
|
|
260
|
+
if (usage.installedPlugins >= tenant.quotas.maxPlugins) {
|
|
261
|
+
throw new Error(`Plugins quota exceeded for tenant ${_tenantId}`);
|
|
262
|
+
}
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Delete tenant and all associated data
|
|
271
|
+
*/
|
|
272
|
+
async deleteTenant(_tenantId, _options = {}) {
|
|
273
|
+
const tenant = this.tenants.get(_tenantId);
|
|
274
|
+
if (!tenant) {
|
|
275
|
+
throw new Error(`Tenant ${_tenantId} not found`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Soft delete by default for compliance
|
|
279
|
+
if (!_options.hardDelete) {
|
|
280
|
+
tenant.metadata.status = 'deleted';
|
|
281
|
+
tenant.metadata.deletedAt = new Date().toISOString();
|
|
282
|
+
tenant.metadata.deletedBy = _options.deletedBy;
|
|
283
|
+
|
|
284
|
+
await this._persistTenant(tenant);
|
|
285
|
+
|
|
286
|
+
this.emit('tenant_soft_deleted', { _tenantId, tenant });
|
|
287
|
+
return { deleted: true, hardDelete: false };
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Hard delete - remove all data
|
|
291
|
+
const workspaces = Array.from(this.workspaces.values()).filter(
|
|
292
|
+
(w) => w.tenantId === _tenantId,
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
for (const workspace of workspaces) {
|
|
296
|
+
await this.deleteWorkspace(workspace.id, { hardDelete: true });
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Remove tenant data directory
|
|
300
|
+
await fs.rmdir(tenant.isolation.dataPath, { recursive: true });
|
|
301
|
+
|
|
302
|
+
this.tenants.delete(_tenantId);
|
|
303
|
+
|
|
304
|
+
this.emit('tenant_hard_deleted', { _tenantId });
|
|
305
|
+
return { deleted: true, hardDelete: true };
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Delete workspace
|
|
310
|
+
*/
|
|
311
|
+
async deleteWorkspace(_workspaceId, _options = {}) {
|
|
312
|
+
const workspace = this.workspaces.get(_workspaceId);
|
|
313
|
+
if (!workspace) {
|
|
314
|
+
throw new Error(`Workspace ${_workspaceId} not found`);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (!_options.hardDelete) {
|
|
318
|
+
workspace.metadata.status = 'deleted';
|
|
319
|
+
workspace.metadata.deletedAt = new Date().toISOString();
|
|
320
|
+
workspace.metadata.deletedBy = _options.deletedBy;
|
|
321
|
+
|
|
322
|
+
await this._persistWorkspace(workspace);
|
|
323
|
+
|
|
324
|
+
this.emit('workspace_soft_deleted', { _workspaceId, workspace });
|
|
325
|
+
return { deleted: true, hardDelete: false };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Hard delete
|
|
329
|
+
await fs.rmdir(workspace.isolation.dataPath, { recursive: true });
|
|
330
|
+
this.workspaces.delete(_workspaceId);
|
|
331
|
+
|
|
332
|
+
this.emit('workspace_hard_deleted', { _workspaceId });
|
|
333
|
+
return { deleted: true, hardDelete: true };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Private methods
|
|
337
|
+
async _createTenantInfrastructure(tenant) {
|
|
338
|
+
const tenantDir = tenant.isolation.dataPath;
|
|
339
|
+
|
|
340
|
+
await fs.mkdir(tenantDir, { recursive: true });
|
|
341
|
+
await fs.mkdir(path.join(tenantDir, 'workspaces'), { recursive: true });
|
|
342
|
+
await fs.mkdir(path.join(tenantDir, 'audit-logs'), { recursive: true });
|
|
343
|
+
await fs.mkdir(path.join(tenantDir, 'backups'), { recursive: true });
|
|
344
|
+
|
|
345
|
+
// Create tenant configuration
|
|
346
|
+
const tenantConfig = {
|
|
347
|
+
tenant: {
|
|
348
|
+
id: tenant.id,
|
|
349
|
+
name: tenant.name,
|
|
350
|
+
domain: tenant.domain,
|
|
351
|
+
},
|
|
352
|
+
quotas: tenant.quotas,
|
|
353
|
+
settings: tenant.settings,
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
await fs.writeFile(
|
|
357
|
+
path.join(tenantDir, 'tenant.json'),
|
|
358
|
+
JSON.stringify(tenantConfig, null, 2),
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async _createWorkspaceInfrastructure(workspace) {
|
|
363
|
+
const workspaceDir = workspace.isolation.dataPath;
|
|
364
|
+
|
|
365
|
+
await fs.mkdir(workspaceDir, { recursive: true });
|
|
366
|
+
await fs.mkdir(workspace.isolation.pluginsPath, { recursive: true });
|
|
367
|
+
await fs.mkdir(path.join(workspaceDir, 'data'), { recursive: true });
|
|
368
|
+
await fs.mkdir(path.join(workspaceDir, 'cache'), { recursive: true });
|
|
369
|
+
|
|
370
|
+
// Create default .ragrc.json for workspace
|
|
371
|
+
const defaultConfig = {
|
|
372
|
+
workspace: {
|
|
373
|
+
id: workspace.id,
|
|
374
|
+
name: workspace.name,
|
|
375
|
+
tenantId: workspace._tenantId,
|
|
376
|
+
},
|
|
377
|
+
plugins: {},
|
|
378
|
+
settings: workspace.settings,
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
await fs.writeFile(
|
|
382
|
+
workspace.isolation.configPath,
|
|
383
|
+
JSON.stringify(defaultConfig, null, 2),
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async _initializeTenantServices(tenant) {
|
|
388
|
+
// Initialize tenant-specific services
|
|
389
|
+
// This would include setting up isolated databases, message queues, etc.
|
|
390
|
+
|
|
391
|
+
// For now, we'll create service configuration files
|
|
392
|
+
const servicesConfig = {
|
|
393
|
+
database: {
|
|
394
|
+
connectionString: `tenant_${tenant.id}_db`,
|
|
395
|
+
isolation: true,
|
|
396
|
+
},
|
|
397
|
+
cache: {
|
|
398
|
+
namespace: `tenant:${tenant.id}`,
|
|
399
|
+
isolation: true,
|
|
400
|
+
},
|
|
401
|
+
messaging: {
|
|
402
|
+
topic: `tenant-${tenant.id}`,
|
|
403
|
+
isolation: true,
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
await fs.writeFile(
|
|
408
|
+
path.join(tenant.isolation.dataPath, 'services.json'),
|
|
409
|
+
JSON.stringify(servicesConfig, null, 2),
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
_calculateResourceLimits(plan) {
|
|
414
|
+
const limits = {
|
|
415
|
+
starter: {
|
|
416
|
+
cpu: '1000m',
|
|
417
|
+
memory: '2Gi',
|
|
418
|
+
storage: '10Gi',
|
|
419
|
+
},
|
|
420
|
+
professional: {
|
|
421
|
+
cpu: '2000m',
|
|
422
|
+
memory: '4Gi',
|
|
423
|
+
storage: '50Gi',
|
|
424
|
+
},
|
|
425
|
+
enterprise: {
|
|
426
|
+
cpu: '4000m',
|
|
427
|
+
memory: '8Gi',
|
|
428
|
+
storage: '200Gi',
|
|
429
|
+
},
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
return limits[plan] || limits.enterprise;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
_calculateQuotaUtilization(quotas, usage) {
|
|
436
|
+
return {
|
|
437
|
+
users: (usage.activeUsers / quotas.maxUsers) * 100,
|
|
438
|
+
workspaces: (usage.workspaces / quotas.maxWorkspaces) * 100,
|
|
439
|
+
storage: (usage.storageUsedGB / quotas.maxStorageGB) * 100,
|
|
440
|
+
apiCalls: (usage.apiCallsThisMonth / quotas.maxAPICallsPerMonth) * 100,
|
|
441
|
+
pipelines: (usage.activePipelines / quotas.maxConcurrentPipelines) * 100,
|
|
442
|
+
plugins: (usage.installedPlugins / quotas.maxPlugins) * 100,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async _persistTenant(tenant) {
|
|
447
|
+
const tenantFile = path.join(tenant.isolation.dataPath, 'tenant.json');
|
|
448
|
+
await fs.writeFile(tenantFile, JSON.stringify(tenant, null, 2));
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async _persistWorkspace(workspace) {
|
|
452
|
+
const workspaceFile = path.join(
|
|
453
|
+
workspace.isolation.dataPath,
|
|
454
|
+
'workspace.json',
|
|
455
|
+
);
|
|
456
|
+
await fs.writeFile(workspaceFile, JSON.stringify(workspace, null, 2));
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
class ResourceMonitor {
|
|
461
|
+
constructor(_config) {
|
|
462
|
+
this._config = _config;
|
|
463
|
+
this.metrics = new Map();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
async getTenantUsage(_tenantId) {
|
|
467
|
+
// Mock implementation - would integrate with actual monitoring systems
|
|
468
|
+
return {
|
|
469
|
+
activeUsers: Math.floor(Math.random() * 50),
|
|
470
|
+
workspaces: Math.floor(Math.random() * 5),
|
|
471
|
+
storageUsedGB: Math.floor(Math.random() * 30),
|
|
472
|
+
apiCallsThisMonth: Math.floor(Math.random() * 50000),
|
|
473
|
+
activePipelines: Math.floor(Math.random() * 3),
|
|
474
|
+
installedPlugins: Math.floor(Math.random() * 20),
|
|
475
|
+
lastUpdated: new Date().toISOString(),
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async getWorkspaceUsage(_workspaceId) {
|
|
480
|
+
// Mock implementation
|
|
481
|
+
return {
|
|
482
|
+
storageUsedMB: Math.floor(Math.random() * 1000),
|
|
483
|
+
apiCallsThisMonth: Math.floor(Math.random() * 5000),
|
|
484
|
+
activePipelines: Math.floor(Math.random() * 2),
|
|
485
|
+
installedPlugins: Math.floor(Math.random() * 10),
|
|
486
|
+
lastActivity: new Date().toISOString(),
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
module.exports = {
|
|
492
|
+
TenantManager,
|
|
493
|
+
ResourceMonitor,
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
// Ensure module.exports is properly defined
|