@axiom-lattice/gateway 2.1.28 → 2.1.30
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/.turbo/turbo-build.log +12 -8
- package/AGENTS.md +50 -0
- package/CHANGELOG.md +20 -0
- package/dist/chunk-FSASG3SB.mjs +94 -0
- package/dist/chunk-FSASG3SB.mjs.map +1 -0
- package/dist/config-F3FCBSPH.mjs +9 -0
- package/dist/config-F3FCBSPH.mjs.map +1 -0
- package/dist/index.js +1996 -209
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1878 -186
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/controllers/auth.ts +443 -0
- package/src/controllers/database-configs.ts +432 -0
- package/src/controllers/metrics-configs.ts +989 -0
- package/src/controllers/run.ts +6 -0
- package/src/controllers/tenants.ts +121 -0
- package/src/controllers/users.ts +135 -0
- package/src/controllers/workspace.ts +598 -0
- package/src/index.ts +2 -10
- package/src/routes/index.ts +21 -0
- package/src/services/agent_service.ts +71 -5
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import { FastifyRequest, FastifyReply } from "fastify";
|
|
2
|
+
import {
|
|
3
|
+
getStoreLattice,
|
|
4
|
+
sqlDatabaseManager,
|
|
5
|
+
} from "@axiom-lattice/core";
|
|
6
|
+
import type {
|
|
7
|
+
DatabaseConfigStore,
|
|
8
|
+
DatabaseConfigEntry,
|
|
9
|
+
CreateDatabaseConfigRequest,
|
|
10
|
+
UpdateDatabaseConfigRequest,
|
|
11
|
+
DatabaseConfig,
|
|
12
|
+
} from "@axiom-lattice/protocols";
|
|
13
|
+
import { randomUUID } from "crypto";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Database Config Controller
|
|
17
|
+
* Handles database configuration CRUD operations
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get tenant ID from request headers
|
|
22
|
+
*/
|
|
23
|
+
function getTenantId(request: FastifyRequest): string {
|
|
24
|
+
return (request.headers["x-tenant-id"] as string) || "default";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Database config list response
|
|
29
|
+
*/
|
|
30
|
+
interface DatabaseConfigListResponse {
|
|
31
|
+
success: boolean;
|
|
32
|
+
message: string;
|
|
33
|
+
data: {
|
|
34
|
+
records: DatabaseConfigEntry[];
|
|
35
|
+
total: number;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Database config response
|
|
41
|
+
*/
|
|
42
|
+
interface DatabaseConfigResponse {
|
|
43
|
+
success: boolean;
|
|
44
|
+
message: string;
|
|
45
|
+
data?: DatabaseConfigEntry;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Test connection response
|
|
50
|
+
*/
|
|
51
|
+
interface TestConnectionResponse {
|
|
52
|
+
success: boolean;
|
|
53
|
+
message: string;
|
|
54
|
+
data?: {
|
|
55
|
+
connected: boolean;
|
|
56
|
+
latency?: number;
|
|
57
|
+
error?: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get all database configs for a tenant
|
|
63
|
+
*/
|
|
64
|
+
export async function getDatabaseConfigList(
|
|
65
|
+
request: FastifyRequest,
|
|
66
|
+
reply: FastifyReply
|
|
67
|
+
): Promise<DatabaseConfigListResponse> {
|
|
68
|
+
const tenantId = getTenantId(request);
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const storeLattice = getStoreLattice("default", "database");
|
|
72
|
+
const store: DatabaseConfigStore = storeLattice.store;
|
|
73
|
+
|
|
74
|
+
const configs = await store.getAllConfigs(tenantId);
|
|
75
|
+
|
|
76
|
+
console.log('Backend: getAllConfigs returned:', configs);
|
|
77
|
+
if (configs.length > 0) {
|
|
78
|
+
console.log('Backend: First config key:', configs[0].key);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
success: true,
|
|
83
|
+
message: "Database configurations retrieved successfully",
|
|
84
|
+
data: {
|
|
85
|
+
records: configs,
|
|
86
|
+
total: configs.length,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error("Failed to get database configs:", error);
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
message: "Failed to retrieve database configurations",
|
|
94
|
+
data: {
|
|
95
|
+
records: [],
|
|
96
|
+
total: 0,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get database config by key
|
|
104
|
+
*/
|
|
105
|
+
export async function getDatabaseConfig(
|
|
106
|
+
request: FastifyRequest,
|
|
107
|
+
reply: FastifyReply
|
|
108
|
+
): Promise<DatabaseConfigResponse> {
|
|
109
|
+
const tenantId = getTenantId(request);
|
|
110
|
+
const { key } = request.params as { key: string };
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const storeLattice = getStoreLattice("default", "database");
|
|
114
|
+
const store: DatabaseConfigStore = storeLattice.store;
|
|
115
|
+
|
|
116
|
+
const config = await store.getConfigByKey(tenantId, key);
|
|
117
|
+
|
|
118
|
+
if (!config) {
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
message: "Database configuration not found",
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
success: true,
|
|
127
|
+
message: "Database configuration retrieved successfully",
|
|
128
|
+
data: config,
|
|
129
|
+
};
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error("Failed to get database config:", error);
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
message: "Failed to retrieve database configuration",
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Create new database config
|
|
141
|
+
*/
|
|
142
|
+
export async function createDatabaseConfig(
|
|
143
|
+
request: FastifyRequest,
|
|
144
|
+
reply: FastifyReply
|
|
145
|
+
): Promise<DatabaseConfigResponse> {
|
|
146
|
+
const tenantId = getTenantId(request);
|
|
147
|
+
const body = request.body as CreateDatabaseConfigRequest & { id?: string };
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
const storeLattice = getStoreLattice("default", "database");
|
|
151
|
+
const store: DatabaseConfigStore = storeLattice.store;
|
|
152
|
+
|
|
153
|
+
// Check if key already exists
|
|
154
|
+
const existing = await store.getConfigByKey(tenantId, body.key);
|
|
155
|
+
if (existing) {
|
|
156
|
+
reply.code(409);
|
|
157
|
+
return {
|
|
158
|
+
success: false,
|
|
159
|
+
message: "Database configuration with this key already exists",
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const id = body.id || randomUUID();
|
|
164
|
+
const config = await store.createConfig(tenantId, id, body);
|
|
165
|
+
|
|
166
|
+
// Auto-register to SqlDatabaseManager
|
|
167
|
+
try {
|
|
168
|
+
sqlDatabaseManager.registerDatabase(config.key, config.config);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.warn("Failed to auto-register database:", error);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
reply.code(201);
|
|
174
|
+
return {
|
|
175
|
+
success: true,
|
|
176
|
+
message: "Database configuration created successfully",
|
|
177
|
+
data: config,
|
|
178
|
+
};
|
|
179
|
+
} catch (error) {
|
|
180
|
+
console.error("Failed to create database config:", error);
|
|
181
|
+
return {
|
|
182
|
+
success: false,
|
|
183
|
+
message: "Failed to create database configuration",
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Update database config
|
|
190
|
+
*/
|
|
191
|
+
export async function updateDatabaseConfig(
|
|
192
|
+
request: FastifyRequest,
|
|
193
|
+
reply: FastifyReply
|
|
194
|
+
): Promise<DatabaseConfigResponse> {
|
|
195
|
+
const tenantId = getTenantId(request);
|
|
196
|
+
const { key } = request.params as { key: string };
|
|
197
|
+
const updates = request.body as Partial<UpdateDatabaseConfigRequest>;
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
const storeLattice = getStoreLattice("default", "database");
|
|
201
|
+
const store: DatabaseConfigStore = storeLattice.store;
|
|
202
|
+
|
|
203
|
+
const existing = await store.getConfigByKey(tenantId, key);
|
|
204
|
+
if (!existing) {
|
|
205
|
+
reply.code(404);
|
|
206
|
+
return {
|
|
207
|
+
success: false,
|
|
208
|
+
message: "Database configuration not found",
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const updated = await store.updateConfig(tenantId, existing.id, updates);
|
|
213
|
+
|
|
214
|
+
if (!updated) {
|
|
215
|
+
return {
|
|
216
|
+
success: false,
|
|
217
|
+
message: "Failed to update database configuration",
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Re-register to SqlDatabaseManager if config changed
|
|
222
|
+
if (updates.config) {
|
|
223
|
+
try {
|
|
224
|
+
sqlDatabaseManager.registerDatabase(updated.key, updated.config);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.warn("Failed to re-register database:", error);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
success: true,
|
|
232
|
+
message: "Database configuration updated successfully",
|
|
233
|
+
data: updated,
|
|
234
|
+
};
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.error("Failed to update database config:", error);
|
|
237
|
+
return {
|
|
238
|
+
success: false,
|
|
239
|
+
message: "Failed to update database configuration",
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Delete database config by key or id
|
|
246
|
+
*/
|
|
247
|
+
export async function deleteDatabaseConfig(
|
|
248
|
+
request: FastifyRequest,
|
|
249
|
+
reply: FastifyReply
|
|
250
|
+
): Promise<DatabaseConfigResponse> {
|
|
251
|
+
const tenantId = getTenantId(request);
|
|
252
|
+
const { keyOrId } = request.params as { keyOrId: string };
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
const storeLattice = getStoreLattice("default", "database");
|
|
256
|
+
const store: DatabaseConfigStore = storeLattice.store;
|
|
257
|
+
|
|
258
|
+
console.log('Delete request - keyOrId:', keyOrId);
|
|
259
|
+
|
|
260
|
+
// Try to find by key first, then by id
|
|
261
|
+
let config = await store.getConfigByKey(tenantId, keyOrId);
|
|
262
|
+
let configKey = keyOrId;
|
|
263
|
+
|
|
264
|
+
if (!config) {
|
|
265
|
+
// Try to find by id
|
|
266
|
+
config = await store.getConfigById(tenantId, keyOrId);
|
|
267
|
+
if (config) {
|
|
268
|
+
configKey = config.key;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (!config) {
|
|
273
|
+
reply.code(404);
|
|
274
|
+
return {
|
|
275
|
+
success: false,
|
|
276
|
+
message: "Database configuration not found",
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
console.log('Found config to delete:', { id: config.id, key: config.key });
|
|
281
|
+
|
|
282
|
+
const deleted = await store.deleteConfig(tenantId, config.id);
|
|
283
|
+
|
|
284
|
+
if (!deleted) {
|
|
285
|
+
return {
|
|
286
|
+
success: false,
|
|
287
|
+
message: "Failed to delete database configuration",
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Remove from SqlDatabaseManager
|
|
292
|
+
try {
|
|
293
|
+
if (sqlDatabaseManager.hasDatabase(configKey)) {
|
|
294
|
+
await sqlDatabaseManager.removeDatabase(configKey);
|
|
295
|
+
}
|
|
296
|
+
} catch (error) {
|
|
297
|
+
console.warn("Failed to remove from SqlDatabaseManager:", error);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
success: true,
|
|
302
|
+
message: "Database configuration deleted successfully",
|
|
303
|
+
};
|
|
304
|
+
} catch (error) {
|
|
305
|
+
console.error("Failed to delete database config:", error);
|
|
306
|
+
return {
|
|
307
|
+
success: false,
|
|
308
|
+
message: "Failed to delete database configuration",
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Test database connection
|
|
315
|
+
*/
|
|
316
|
+
export async function testDatabaseConnection(
|
|
317
|
+
request: FastifyRequest,
|
|
318
|
+
reply: FastifyReply
|
|
319
|
+
): Promise<TestConnectionResponse> {
|
|
320
|
+
const tenantId = getTenantId(request);
|
|
321
|
+
const { key } = request.params as { key: string };
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
const storeLattice = getStoreLattice("default", "database");
|
|
325
|
+
const store: DatabaseConfigStore = storeLattice.store;
|
|
326
|
+
|
|
327
|
+
const config = await store.getConfigByKey(tenantId, key);
|
|
328
|
+
if (!config) {
|
|
329
|
+
reply.code(404);
|
|
330
|
+
return {
|
|
331
|
+
success: false,
|
|
332
|
+
message: "Database configuration not found",
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Register temporarily for testing
|
|
337
|
+
const testKey = `__test_${key}_${Date.now()}`;
|
|
338
|
+
sqlDatabaseManager.registerDatabase(testKey, config.config);
|
|
339
|
+
|
|
340
|
+
const startTime = Date.now();
|
|
341
|
+
const db = sqlDatabaseManager.getDatabase(testKey);
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
// Try to connect and list tables
|
|
345
|
+
await db.connect();
|
|
346
|
+
await db.listTables();
|
|
347
|
+
const latency = Date.now() - startTime;
|
|
348
|
+
|
|
349
|
+
// Disconnect gracefully with delay to ensure all operations complete
|
|
350
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
351
|
+
await db.disconnect();
|
|
352
|
+
|
|
353
|
+
// Cleanup
|
|
354
|
+
await sqlDatabaseManager.removeDatabase(testKey);
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
success: true,
|
|
358
|
+
message: "Connection test successful",
|
|
359
|
+
data: {
|
|
360
|
+
connected: true,
|
|
361
|
+
latency,
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
} catch (error) {
|
|
365
|
+
// Cleanup on error
|
|
366
|
+
try {
|
|
367
|
+
await db.disconnect();
|
|
368
|
+
await sqlDatabaseManager.removeDatabase(testKey);
|
|
369
|
+
} catch {}
|
|
370
|
+
|
|
371
|
+
return {
|
|
372
|
+
success: true,
|
|
373
|
+
message: "Connection test failed",
|
|
374
|
+
data: {
|
|
375
|
+
connected: false,
|
|
376
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
377
|
+
},
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
} catch (error) {
|
|
381
|
+
console.error("Failed to test database connection:", error);
|
|
382
|
+
return {
|
|
383
|
+
success: false,
|
|
384
|
+
message: "Failed to test database connection",
|
|
385
|
+
data: {
|
|
386
|
+
connected: false,
|
|
387
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Register database config routes
|
|
395
|
+
*/
|
|
396
|
+
export function registerDatabaseConfigRoutes(app: any): void {
|
|
397
|
+
// Get all configs
|
|
398
|
+
app.get(
|
|
399
|
+
"/api/database-configs",
|
|
400
|
+
getDatabaseConfigList
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
// Get config by key
|
|
404
|
+
app.get(
|
|
405
|
+
"/api/database-configs/:key",
|
|
406
|
+
getDatabaseConfig
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
// Create config
|
|
410
|
+
app.post(
|
|
411
|
+
"/api/database-configs",
|
|
412
|
+
createDatabaseConfig
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
// Update config
|
|
416
|
+
app.put(
|
|
417
|
+
"/api/database-configs/:key",
|
|
418
|
+
updateDatabaseConfig
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
// Delete config by key or id
|
|
422
|
+
app.delete(
|
|
423
|
+
"/api/database-configs/:keyOrId",
|
|
424
|
+
deleteDatabaseConfig
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
// Test connection
|
|
428
|
+
app.post(
|
|
429
|
+
"/api/database-configs/:key/test",
|
|
430
|
+
testDatabaseConnection
|
|
431
|
+
);
|
|
432
|
+
}
|