@mostajs/setup 1.4.5 → 1.4.7
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.
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Creates handlers for JAR file management API.
|
|
3
3
|
*
|
|
4
|
-
* GET — list uploaded JARs
|
|
4
|
+
* GET — list uploaded JARs, JDBC dialect status, active bridges, HSQLDB server status
|
|
5
5
|
* POST — upload a new JAR file (multipart/form-data)
|
|
6
6
|
* DELETE — remove a JAR file
|
|
7
|
+
* PATCH — start/stop HSQLDB server and JDBC bridge
|
|
7
8
|
*/
|
|
8
9
|
export declare function createUploadJarHandlers(): {
|
|
9
10
|
GET: () => Promise<Response>;
|
|
@@ -1,20 +1,49 @@
|
|
|
1
1
|
// @mostajs/setup — API Route factory for JAR file upload/list/delete
|
|
2
2
|
// Delegates to @mostajs/orm jar-upload module
|
|
3
3
|
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
4
|
+
/**
|
|
5
|
+
* Check if a TCP port is open (non-HTTP — raw socket connect).
|
|
6
|
+
*/
|
|
7
|
+
async function isPortOpen(port, host = 'localhost', timeoutMs = 800) {
|
|
8
|
+
const net = await import('net');
|
|
9
|
+
return new Promise(resolve => {
|
|
10
|
+
const socket = new net.Socket();
|
|
11
|
+
socket.setTimeout(timeoutMs);
|
|
12
|
+
socket.once('connect', () => { socket.destroy(); resolve(true); });
|
|
13
|
+
socket.once('timeout', () => { socket.destroy(); resolve(false); });
|
|
14
|
+
socket.once('error', () => { socket.destroy(); resolve(false); });
|
|
15
|
+
socket.connect(port, host);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get PID of process listening on a port via fuser.
|
|
20
|
+
*/
|
|
21
|
+
async function getPidOnPort(port) {
|
|
22
|
+
try {
|
|
23
|
+
const { execSync } = await import('child_process');
|
|
24
|
+
const out = execSync(`fuser ${port}/tcp 2>/dev/null`, { encoding: 'utf-8' }).trim();
|
|
25
|
+
const pid = parseInt(out);
|
|
26
|
+
return isNaN(pid) ? 0 : pid;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
4
32
|
/**
|
|
5
33
|
* Creates handlers for JAR file management API.
|
|
6
34
|
*
|
|
7
|
-
* GET — list uploaded JARs
|
|
35
|
+
* GET — list uploaded JARs, JDBC dialect status, active bridges, HSQLDB server status
|
|
8
36
|
* POST — upload a new JAR file (multipart/form-data)
|
|
9
37
|
* DELETE — remove a JAR file
|
|
38
|
+
* PATCH — start/stop HSQLDB server and JDBC bridge
|
|
10
39
|
*/
|
|
11
40
|
export function createUploadJarHandlers() {
|
|
12
41
|
async function GET() {
|
|
13
42
|
try {
|
|
14
43
|
const { listJarFiles, getJdbcDialectStatus } = await import('@mostajs/orm');
|
|
15
|
-
// Scan active bridges
|
|
44
|
+
// Scan active bridges
|
|
16
45
|
const bridges = [];
|
|
17
|
-
// 1.
|
|
46
|
+
// 1. BridgeManager known bridges
|
|
18
47
|
try {
|
|
19
48
|
const { BridgeManager } = await import('@mostajs/orm');
|
|
20
49
|
const manager = BridgeManager.getInstance();
|
|
@@ -23,7 +52,7 @@ export function createUploadJarHandlers() {
|
|
|
23
52
|
}
|
|
24
53
|
}
|
|
25
54
|
catch { /* ignore */ }
|
|
26
|
-
// 2.
|
|
55
|
+
// 2. PID files for orphan bridges
|
|
27
56
|
try {
|
|
28
57
|
const { existsSync, readdirSync, readFileSync } = await import('fs');
|
|
29
58
|
const { join } = await import('path');
|
|
@@ -35,14 +64,12 @@ export function createUploadJarHandlers() {
|
|
|
35
64
|
if (!portMatch)
|
|
36
65
|
continue;
|
|
37
66
|
const port = parseInt(portMatch[1]);
|
|
38
|
-
// Skip if already known from BridgeManager
|
|
39
67
|
if (bridges.some(b => b.port === port))
|
|
40
68
|
continue;
|
|
41
69
|
const pidStr = readFileSync(join(jarDir, file), 'utf-8').trim();
|
|
42
70
|
const pid = parseInt(pidStr);
|
|
43
71
|
if (isNaN(pid))
|
|
44
72
|
continue;
|
|
45
|
-
// Check if process is alive
|
|
46
73
|
let alive = false;
|
|
47
74
|
try {
|
|
48
75
|
process.kill(pid, 0);
|
|
@@ -50,23 +77,28 @@ export function createUploadJarHandlers() {
|
|
|
50
77
|
}
|
|
51
78
|
catch { /* dead */ }
|
|
52
79
|
if (alive) {
|
|
53
|
-
// Probe health
|
|
54
80
|
let jdbcUrl;
|
|
55
81
|
try {
|
|
56
82
|
const res = await fetch(`http://localhost:${port}/health`, { signal: AbortSignal.timeout(1000) });
|
|
57
83
|
if (res.ok) {
|
|
58
|
-
|
|
59
|
-
jdbcUrl = h.jdbcUrl;
|
|
84
|
+
jdbcUrl = (await res.json()).jdbcUrl;
|
|
60
85
|
}
|
|
61
86
|
}
|
|
62
87
|
catch { /* not responding */ }
|
|
63
88
|
bridges.push({ port, pid, status: jdbcUrl ? 'active' : 'orphan', jdbcUrl });
|
|
64
89
|
}
|
|
90
|
+
else {
|
|
91
|
+
// Clean stale PID file
|
|
92
|
+
try {
|
|
93
|
+
(await import('fs')).unlinkSync(join(jarDir, file));
|
|
94
|
+
}
|
|
95
|
+
catch { /* ignore */ }
|
|
96
|
+
}
|
|
65
97
|
}
|
|
66
98
|
}
|
|
67
99
|
}
|
|
68
100
|
catch { /* ignore */ }
|
|
69
|
-
// 3. Probe common bridge ports
|
|
101
|
+
// 3. Probe common bridge ports (HTTP — bridges speak HTTP)
|
|
70
102
|
const basePort = parseInt(process.env.MOSTA_BRIDGE_PORT_BASE || '8765');
|
|
71
103
|
for (let port = basePort; port < basePort + 5; port++) {
|
|
72
104
|
if (bridges.some(b => b.port === port))
|
|
@@ -74,17 +106,64 @@ export function createUploadJarHandlers() {
|
|
|
74
106
|
try {
|
|
75
107
|
const res = await fetch(`http://localhost:${port}/health`, { signal: AbortSignal.timeout(500) });
|
|
76
108
|
if (res.ok) {
|
|
77
|
-
const h = await res.json();
|
|
78
|
-
|
|
109
|
+
const h = (await res.json());
|
|
110
|
+
const pid = await getPidOnPort(port);
|
|
111
|
+
bridges.push({ port, pid, status: 'active', jdbcUrl: h.jdbcUrl });
|
|
79
112
|
}
|
|
80
113
|
}
|
|
81
114
|
catch { /* not a bridge */ }
|
|
82
115
|
}
|
|
116
|
+
// Check HSQLDB server status (TCP probe, NOT HTTP)
|
|
117
|
+
let hsqldbServer = null;
|
|
118
|
+
try {
|
|
119
|
+
const { existsSync, readdirSync, readFileSync } = await import('fs');
|
|
120
|
+
const { join } = await import('path');
|
|
121
|
+
const jarDir = process.env.MOSTA_JAR_DIR || join(process.cwd(), 'jar_files');
|
|
122
|
+
// Check PID files first
|
|
123
|
+
if (existsSync(jarDir)) {
|
|
124
|
+
const serverPidFiles = readdirSync(jarDir).filter((f) => f.startsWith('.hsqldb-server-') && f.endsWith('.pid'));
|
|
125
|
+
for (const file of serverPidFiles) {
|
|
126
|
+
const portMatch = file.match(/\.hsqldb-server-(\d+)\.pid/);
|
|
127
|
+
if (!portMatch)
|
|
128
|
+
continue;
|
|
129
|
+
const port = parseInt(portMatch[1]);
|
|
130
|
+
const pidStr = readFileSync(join(jarDir, file), 'utf-8').trim();
|
|
131
|
+
const pid = parseInt(pidStr);
|
|
132
|
+
let alive = false;
|
|
133
|
+
if (pid > 0) {
|
|
134
|
+
try {
|
|
135
|
+
process.kill(pid, 0);
|
|
136
|
+
alive = true;
|
|
137
|
+
}
|
|
138
|
+
catch { /* dead */ }
|
|
139
|
+
}
|
|
140
|
+
if (alive) {
|
|
141
|
+
hsqldbServer = { running: true, port, pid };
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
try {
|
|
145
|
+
(await import('fs')).unlinkSync(join(jarDir, file));
|
|
146
|
+
}
|
|
147
|
+
catch { /* ignore */ }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Fallback: check port 9001 via TCP
|
|
152
|
+
if (!hsqldbServer) {
|
|
153
|
+
const open = await isPortOpen(9001);
|
|
154
|
+
if (open) {
|
|
155
|
+
const pid = await getPidOnPort(9001);
|
|
156
|
+
hsqldbServer = { running: true, port: 9001, pid };
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch { /* ignore */ }
|
|
83
161
|
return Response.json({
|
|
84
162
|
ok: true,
|
|
85
163
|
jars: listJarFiles(),
|
|
86
164
|
dialects: getJdbcDialectStatus(),
|
|
87
165
|
bridges,
|
|
166
|
+
hsqldbServer,
|
|
88
167
|
});
|
|
89
168
|
}
|
|
90
169
|
catch (err) {
|
|
@@ -139,40 +218,144 @@ export function createUploadJarHandlers() {
|
|
|
139
218
|
}
|
|
140
219
|
}
|
|
141
220
|
/**
|
|
142
|
-
* PATCH —
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
221
|
+
* PATCH — Manage JDBC bridge and HSQLDB server.
|
|
222
|
+
* start-server: { action: 'start-server', dialect, name, host?, port? }
|
|
223
|
+
* stop-server: { action: 'stop-server', port? }
|
|
224
|
+
* start: { action: 'start', dialect, host, port, name, user?, password? }
|
|
225
|
+
* stop: { action: 'stop', port, pid? }
|
|
146
226
|
*/
|
|
147
227
|
async function PATCH(req) {
|
|
148
228
|
try {
|
|
149
229
|
const body = await req.json();
|
|
150
230
|
const { action } = body;
|
|
231
|
+
// ── Start HSQLDB server ──
|
|
232
|
+
if (action === 'start-server') {
|
|
233
|
+
const { dialect, name, host, port: sgbdPort } = body;
|
|
234
|
+
if (dialect !== 'hsqldb') {
|
|
235
|
+
return Response.json({ ok: false, error: 'start-server supporte uniquement hsqldb' }, { status: 400 });
|
|
236
|
+
}
|
|
237
|
+
const actualPort = sgbdPort || 9001;
|
|
238
|
+
// Check if already running (TCP probe, not HTTP)
|
|
239
|
+
if (await isPortOpen(actualPort, host || 'localhost')) {
|
|
240
|
+
const pid = await getPidOnPort(actualPort);
|
|
241
|
+
return Response.json({ ok: true, message: `Serveur HSQLDB deja en marche sur le port ${actualPort}`, port: actualPort, pid, alreadyRunning: true });
|
|
242
|
+
}
|
|
243
|
+
// Find JAR
|
|
244
|
+
const { JdbcNormalizer } = await import('@mostajs/orm');
|
|
245
|
+
const jarPath = JdbcNormalizer.findJar('hsqldb');
|
|
246
|
+
if (!jarPath) {
|
|
247
|
+
return Response.json({ ok: false, error: 'JAR HSQLDB non trouve. Uploadez hsqldb*.jar d\'abord.' });
|
|
248
|
+
}
|
|
249
|
+
// Launch server
|
|
250
|
+
const { spawn: spawnChild } = await import('child_process');
|
|
251
|
+
const { join } = await import('path');
|
|
252
|
+
const { writeFileSync, existsSync, mkdirSync } = await import('fs');
|
|
253
|
+
const dataDir = join(process.cwd(), 'data');
|
|
254
|
+
if (!existsSync(dataDir))
|
|
255
|
+
mkdirSync(dataDir, { recursive: true });
|
|
256
|
+
const dbAlias = name || 'mydb';
|
|
257
|
+
const serverProc = spawnChild('java', [
|
|
258
|
+
'-cp', jarPath,
|
|
259
|
+
'org.hsqldb.server.Server',
|
|
260
|
+
'--database.0', `file:${join(dataDir, dbAlias)}`,
|
|
261
|
+
'--dbname.0', dbAlias,
|
|
262
|
+
'--port', String(actualPort),
|
|
263
|
+
], {
|
|
264
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
265
|
+
detached: true,
|
|
266
|
+
});
|
|
267
|
+
serverProc.unref();
|
|
268
|
+
const serverPid = serverProc.pid || 0;
|
|
269
|
+
// Save PID file
|
|
270
|
+
const jarDir = process.env.MOSTA_JAR_DIR || join(process.cwd(), 'jar_files');
|
|
271
|
+
if (existsSync(jarDir)) {
|
|
272
|
+
writeFileSync(join(jarDir, `.hsqldb-server-${actualPort}.pid`), String(serverPid));
|
|
273
|
+
}
|
|
274
|
+
// Log stderr
|
|
275
|
+
serverProc.stderr?.on('data', (data) => {
|
|
276
|
+
const msg = data.toString().trim();
|
|
277
|
+
if (msg)
|
|
278
|
+
console.error(`[HSQLDB:server] ${msg}`);
|
|
279
|
+
});
|
|
280
|
+
// Wait for server to be ready (TCP probe)
|
|
281
|
+
let serverReady = false;
|
|
282
|
+
for (let i = 0; i < 16; i++) {
|
|
283
|
+
await new Promise(r => setTimeout(r, 500));
|
|
284
|
+
if (await isPortOpen(actualPort, host || 'localhost')) {
|
|
285
|
+
serverReady = true;
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
// Also check process is still alive
|
|
289
|
+
try {
|
|
290
|
+
process.kill(serverPid, 0);
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
break; /* process died */
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (!serverReady) {
|
|
297
|
+
return Response.json({ ok: false, error: 'Le serveur HSQLDB n\'a pas demarre dans le delai imparti' });
|
|
298
|
+
}
|
|
299
|
+
return Response.json({ ok: true, port: actualPort, pid: serverPid, message: `Serveur HSQLDB lance (port ${actualPort}, PID ${serverPid}, alias: ${dbAlias})` });
|
|
300
|
+
}
|
|
301
|
+
// ── Stop HSQLDB server ──
|
|
302
|
+
if (action === 'stop-server') {
|
|
303
|
+
const sgbdPort = body.port || 9001;
|
|
304
|
+
try {
|
|
305
|
+
const { execSync } = await import('child_process');
|
|
306
|
+
const { existsSync, unlinkSync, readFileSync } = await import('fs');
|
|
307
|
+
const { join } = await import('path');
|
|
308
|
+
const jarDir = process.env.MOSTA_JAR_DIR || join(process.cwd(), 'jar_files');
|
|
309
|
+
// Kill by PID file
|
|
310
|
+
const pidFile = join(jarDir, `.hsqldb-server-${sgbdPort}.pid`);
|
|
311
|
+
if (existsSync(pidFile)) {
|
|
312
|
+
const pid = parseInt(readFileSync(pidFile, 'utf-8').trim());
|
|
313
|
+
if (pid > 0) {
|
|
314
|
+
try {
|
|
315
|
+
process.kill(pid, 'SIGKILL');
|
|
316
|
+
}
|
|
317
|
+
catch { /* dead */ }
|
|
318
|
+
}
|
|
319
|
+
unlinkSync(pidFile);
|
|
320
|
+
}
|
|
321
|
+
// Also kill anything on the port
|
|
322
|
+
try {
|
|
323
|
+
execSync(`fuser -k ${sgbdPort}/tcp 2>/dev/null`, { stdio: 'ignore' });
|
|
324
|
+
}
|
|
325
|
+
catch { /* already free */ }
|
|
326
|
+
return Response.json({ ok: true, message: `Serveur HSQLDB arrete (port ${sgbdPort})` });
|
|
327
|
+
}
|
|
328
|
+
catch (err) {
|
|
329
|
+
return Response.json({ ok: false, error: err instanceof Error ? err.message : 'Erreur' });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// ── Stop bridge ──
|
|
151
333
|
if (action === 'stop') {
|
|
152
334
|
const bridgePort = body.port || 8765;
|
|
153
335
|
const bridgePid = body.pid || 0;
|
|
154
336
|
try {
|
|
155
337
|
// 1. Try BridgeManager
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
338
|
+
try {
|
|
339
|
+
const { BridgeManager } = await import('@mostajs/orm');
|
|
340
|
+
const manager = BridgeManager.getInstance();
|
|
341
|
+
const bridge = manager.list().find((b) => b.port === bridgePort);
|
|
342
|
+
if (bridge)
|
|
343
|
+
await manager.stop(bridge.key);
|
|
162
344
|
}
|
|
163
|
-
|
|
345
|
+
catch { /* ignore */ }
|
|
346
|
+
// 2. Kill by PID
|
|
164
347
|
if (bridgePid > 0) {
|
|
165
348
|
try {
|
|
166
349
|
process.kill(bridgePid, 'SIGKILL');
|
|
167
350
|
}
|
|
168
|
-
catch { /*
|
|
351
|
+
catch { /* dead */ }
|
|
169
352
|
}
|
|
170
|
-
// 3. Fallback:
|
|
171
|
-
const { execSync } = await import('child_process');
|
|
353
|
+
// 3. Fallback: fuser
|
|
172
354
|
try {
|
|
355
|
+
const { execSync } = await import('child_process');
|
|
173
356
|
execSync(`fuser -k ${bridgePort}/tcp 2>/dev/null`, { stdio: 'ignore' });
|
|
174
357
|
}
|
|
175
|
-
catch { /*
|
|
358
|
+
catch { /* already free */ }
|
|
176
359
|
// 4. Clean PID file
|
|
177
360
|
try {
|
|
178
361
|
const { existsSync, unlinkSync } = await import('fs');
|
|
@@ -185,16 +368,14 @@ export function createUploadJarHandlers() {
|
|
|
185
368
|
return Response.json({ ok: true, message: `Bridge arrete (port ${bridgePort})` });
|
|
186
369
|
}
|
|
187
370
|
catch (err) {
|
|
188
|
-
|
|
189
|
-
return Response.json({ ok: false, error: msg });
|
|
371
|
+
return Response.json({ ok: false, error: err instanceof Error ? err.message : 'Erreur' });
|
|
190
372
|
}
|
|
191
373
|
}
|
|
192
|
-
//
|
|
374
|
+
// ── Start bridge ──
|
|
193
375
|
const { dialect, host, port, name, user, password } = body;
|
|
194
376
|
if (!dialect) {
|
|
195
377
|
return Response.json({ ok: false, error: 'dialect requis' }, { status: 400 });
|
|
196
378
|
}
|
|
197
|
-
// Compose URI using setup's composeDbUri for consistency with test-db
|
|
198
379
|
const { composeDbUri } = await import('../lib/compose-uri');
|
|
199
380
|
const uri = composeDbUri(dialect, {
|
|
200
381
|
host: host || 'localhost',
|
|
@@ -203,11 +384,9 @@ export function createUploadJarHandlers() {
|
|
|
203
384
|
user: user || '',
|
|
204
385
|
password: password || '',
|
|
205
386
|
});
|
|
206
|
-
// Start bridge via BridgeManager directly (no SELECT 1 — just start the Java process)
|
|
207
387
|
const { BridgeManager } = await import('@mostajs/orm');
|
|
208
388
|
const { JdbcNormalizer } = await import('@mostajs/orm');
|
|
209
389
|
const manager = BridgeManager.getInstance();
|
|
210
|
-
// Check if JAR is available
|
|
211
390
|
if (!JdbcNormalizer.isAvailable(dialect)) {
|
|
212
391
|
return Response.json({
|
|
213
392
|
ok: false,
|
|
@@ -217,12 +217,12 @@ async function fetchRetry(url, init, retries = 3, delay = 2000) {
|
|
|
217
217
|
}
|
|
218
218
|
function JarUploadInline({ dialect, jarEndpoint, dbConfig }) {
|
|
219
219
|
const [uploading, setUploading] = useState(false);
|
|
220
|
-
const [
|
|
220
|
+
const [loading, setLoading] = useState(null); // tracks which action is loading
|
|
221
221
|
const [bridgePort, setBridgePort] = useState(null);
|
|
222
222
|
const [message, setMessage] = useState(null);
|
|
223
223
|
const [jarStatus, setJarStatus] = useState(null);
|
|
224
224
|
const [bridges, setBridges] = useState([]);
|
|
225
|
-
const [
|
|
225
|
+
const [serverInfo, setServerInfo] = useState(null);
|
|
226
226
|
const loadStatus = useCallback(() => {
|
|
227
227
|
fetch(jarEndpoint)
|
|
228
228
|
.then(r => r.json())
|
|
@@ -231,10 +231,15 @@ function JarUploadInline({ dialect, jarEndpoint, dbConfig }) {
|
|
|
231
231
|
const s = data.dialects?.find((d) => d.dialect === dialect);
|
|
232
232
|
setJarStatus(s || { hasJar: false, jarFile: null });
|
|
233
233
|
setBridges(data.bridges || []);
|
|
234
|
-
|
|
234
|
+
if (data.hsqldbServer)
|
|
235
|
+
setServerInfo(data.hsqldbServer);
|
|
236
|
+
else
|
|
237
|
+
setServerInfo(null);
|
|
235
238
|
const active = (data.bridges || []).find((b) => b.status === 'active');
|
|
236
239
|
if (active)
|
|
237
240
|
setBridgePort(active.port);
|
|
241
|
+
else
|
|
242
|
+
setBridgePort(null);
|
|
238
243
|
}
|
|
239
244
|
})
|
|
240
245
|
.catch(() => { });
|
|
@@ -267,63 +272,42 @@ function JarUploadInline({ dialect, jarEndpoint, dbConfig }) {
|
|
|
267
272
|
e.target.value = '';
|
|
268
273
|
}
|
|
269
274
|
};
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
setMessage(null);
|
|
273
|
-
try {
|
|
274
|
-
const res = await fetch(jarEndpoint, {
|
|
275
|
-
method: 'PATCH',
|
|
276
|
-
headers: { 'Content-Type': 'application/json' },
|
|
277
|
-
body: JSON.stringify({ action: 'start', dialect, ...dbConfig }),
|
|
278
|
-
});
|
|
279
|
-
const result = await res.json();
|
|
280
|
-
if (result.ok) {
|
|
281
|
-
setBridgePort(result.port || 8765);
|
|
282
|
-
setMessage({ ok: true, text: `Bridge JDBC lance sur le port ${result.port || 8765}` });
|
|
283
|
-
loadStatus();
|
|
284
|
-
}
|
|
285
|
-
else {
|
|
286
|
-
setMessage({ ok: false, text: result.error || 'Echec lancement du bridge' });
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
catch {
|
|
290
|
-
setMessage({ ok: false, text: 'Erreur reseau' });
|
|
291
|
-
}
|
|
292
|
-
finally {
|
|
293
|
-
setBridgeLoading(false);
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
const handleStopBridge = async (port, pid) => {
|
|
297
|
-
setKillingPort(port);
|
|
275
|
+
const patchAction = async (payload, actionLabel) => {
|
|
276
|
+
setLoading(actionLabel);
|
|
298
277
|
setMessage(null);
|
|
299
278
|
try {
|
|
300
279
|
const res = await fetch(jarEndpoint, {
|
|
301
280
|
method: 'PATCH',
|
|
302
281
|
headers: { 'Content-Type': 'application/json' },
|
|
303
|
-
body: JSON.stringify(
|
|
282
|
+
body: JSON.stringify(payload),
|
|
304
283
|
});
|
|
305
284
|
const result = await res.json();
|
|
306
285
|
if (result.ok) {
|
|
307
|
-
|
|
286
|
+
setMessage({ ok: true, text: result.message || actionLabel + ' OK' });
|
|
287
|
+
if (result.port && payload.action === 'start')
|
|
288
|
+
setBridgePort(result.port);
|
|
289
|
+
if (payload.action === 'stop')
|
|
308
290
|
setBridgePort(null);
|
|
309
|
-
setMessage({ ok: true, text: result.message || 'Bridge arrete' });
|
|
310
|
-
loadStatus();
|
|
311
291
|
}
|
|
312
292
|
else {
|
|
313
|
-
setMessage({ ok: false, text: result.error || 'Echec
|
|
293
|
+
setMessage({ ok: false, text: result.error || 'Echec ' + actionLabel });
|
|
314
294
|
}
|
|
295
|
+
loadStatus();
|
|
315
296
|
}
|
|
316
297
|
catch {
|
|
317
298
|
setMessage({ ok: false, text: 'Erreur reseau' });
|
|
318
299
|
}
|
|
319
300
|
finally {
|
|
320
|
-
|
|
301
|
+
setLoading(null);
|
|
321
302
|
}
|
|
322
303
|
};
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
304
|
+
const isHsqldb = dialect === 'hsqldb';
|
|
305
|
+
const btnSmall = (color, disabled) => ({
|
|
306
|
+
...S.btn('primary', disabled), fontSize: 12, padding: '6px 14px',
|
|
307
|
+
backgroundColor: disabled ? '#9ca3af' : color, cursor: disabled ? 'not-allowed' : 'pointer',
|
|
308
|
+
borderRadius: 6, border: 'none', color: '#fff', fontWeight: 600,
|
|
309
|
+
});
|
|
310
|
+
return (_jsxs("div", { style: S.jarBox, children: [_jsxs("div", { style: S.flex(8), children: [_jsx("span", { style: S.jarTitle, children: "Driver JDBC" }), jarStatus?.hasJar ? (_jsx("span", { style: { ...S.badge('installed'), marginLeft: 0 }, children: jarStatus.jarFile })) : (_jsx("span", { style: { fontSize: 12, color: '#6b7280' }, children: "Aucun JAR installe" }))] }), _jsxs("div", { style: { marginTop: 8 }, children: [_jsxs("label", { style: { ...S.btn('primary', uploading), cursor: uploading ? 'wait' : 'pointer', fontSize: 12, padding: '6px 12px' }, children: [uploading ? 'Upload...' : 'Uploader un .jar', _jsx("input", { type: "file", accept: ".jar", onChange: handleUpload, disabled: uploading, style: { display: 'none' } })] }), _jsx("span", { style: { fontSize: 11, color: '#9ca3af', marginLeft: 8 }, children: "Ex: hsqldb*.jar, ojdbc*.jar" })] }), isHsqldb && jarStatus?.hasJar && (_jsxs("div", { style: { marginTop: 10, padding: '10px 12px', backgroundColor: '#fef9c3', borderRadius: 6, border: '1px solid #fde68a' }, children: [_jsxs("div", { style: { fontSize: 12, fontWeight: 600, color: '#92400e', marginBottom: 6 }, children: ["Serveur HSQLDB", serverInfo?.running && (_jsxs("span", { style: { fontWeight: 400, color: '#059669', marginLeft: 8 }, children: ["En marche (port ", serverInfo.port, serverInfo.pid > 0 ? `, PID ${serverInfo.pid}` : '', ")"] })), !serverInfo?.running && (_jsx("span", { style: { fontWeight: 400, color: '#dc2626', marginLeft: 8 }, children: "Arrete" }))] }), _jsxs("div", { style: { display: 'flex', gap: 8 }, children: [_jsx("button", { style: btnSmall('#059669', loading === 'start-server' || serverInfo?.running), onClick: () => patchAction({ action: 'start-server', dialect, name: dbConfig.name, host: dbConfig.host, port: dbConfig.port }, 'start-server'), disabled: loading === 'start-server' || !!serverInfo?.running, children: loading === 'start-server' ? 'Demarrage...' : 'Demarrer le serveur' }), _jsx("button", { style: btnSmall('#dc2626', loading === 'stop-server' || !serverInfo?.running), onClick: () => patchAction({ action: 'stop-server', port: serverInfo?.port || dbConfig.port || 9001 }, 'stop-server'), disabled: loading === 'stop-server' || !serverInfo?.running, children: loading === 'stop-server' ? 'Arret...' : 'Arreter le serveur' })] })] })), jarStatus?.hasJar && (_jsxs("div", { style: { marginTop: 10, padding: '10px 12px', backgroundColor: '#f0fdf4', borderRadius: 6, border: '1px solid #bbf7d0' }, children: [_jsxs("div", { style: { fontSize: 12, fontWeight: 600, color: '#166534', marginBottom: 6 }, children: ["Bridge JDBC", bridgePort && _jsxs("span", { style: { fontWeight: 400, marginLeft: 8 }, children: ["Actif port ", bridgePort] }), !bridgePort && bridges.length === 0 && _jsx("span", { style: { fontWeight: 400, color: '#6b7280', marginLeft: 8 }, children: "Inactif" })] }), _jsx("div", { style: { display: 'flex', gap: 8, marginBottom: bridges.length > 0 ? 8 : 0 }, children: _jsx("button", { style: btnSmall('#059669', loading === 'start-bridge' || bridges.length > 0), onClick: () => patchAction({ action: 'start', dialect, ...dbConfig }, 'start-bridge'), disabled: loading === 'start-bridge' || bridges.length > 0, children: loading === 'start-bridge' ? 'Lancement...' : 'Lancer le bridge' }) }), bridges.map(b => (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, padding: '4px 0', fontSize: 12 }, children: [_jsx("span", { style: { width: 8, height: 8, borderRadius: '50%', backgroundColor: b.status === 'active' ? '#22c55e' : '#f59e0b', flexShrink: 0 } }), _jsxs("span", { style: { color: '#374151', fontFamily: 'monospace', fontSize: 11 }, children: [":", b.port, " ", b.pid > 0 ? `(PID ${b.pid})` : '', " ", b.jdbcUrl ? `— ${b.jdbcUrl}` : ''] }), _jsx("button", { style: { ...btnSmall('#dc2626', loading === `kill-${b.port}`), fontSize: 11, padding: '2px 8px', marginLeft: 'auto' }, onClick: () => patchAction({ action: 'stop', port: b.port, pid: b.pid }, `kill-${b.port}`), disabled: loading === `kill-${b.port}`, children: loading === `kill-${b.port}` ? '...' : 'Kill' })] }, b.port)))] })), message && (_jsx("p", { style: { fontSize: 12, color: message.ok ? '#059669' : '#dc2626', marginTop: 8 }, children: message.text }))] }));
|
|
327
311
|
}
|
|
328
312
|
// ── Main Component ───────────────────────────────────────────
|
|
329
313
|
export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNamePrefix = 'mydb', persistState = true, }) {
|
|
@@ -550,7 +534,7 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
550
534
|
const isSelected = selectedModules.includes(mod.key);
|
|
551
535
|
const isDetected = detectedModules.includes(mod.key);
|
|
552
536
|
return (_jsxs("div", { style: S.moduleCard(isSelected, !!mod.required), onClick: () => toggleModule(mod.key), children: [_jsxs("div", { style: S.moduleHeader, children: [_jsxs("div", { style: S.moduleLeft, children: [_jsx("span", { style: { fontSize: 20 }, children: mod.icon }), _jsx("span", { style: S.moduleName, children: mod.label })] }), _jsxs("div", { style: S.moduleBadges, children: [mod.discovered && _jsx("span", { style: S.badge('new'), children: "Nouveau" }), isDetected && _jsx("span", { style: S.badge('installed'), children: t('setup.modules.installed') }), mod.required && _jsx("span", { style: S.badge('required'), children: t('setup.modules.required') }), _jsx("input", { type: "checkbox", checked: isSelected, disabled: mod.required, readOnly: true, style: S.checkbox })] })] }), _jsx("div", { style: S.moduleDesc, children: mod.description }), mod.dependsOn?.length ? (_jsxs("div", { style: { fontSize: 11, color: '#9ca3af', marginTop: 4 }, children: ["Depend de : ", mod.dependsOn.join(', ')] })) : null] }, mod.key));
|
|
553
|
-
}) }), _jsxs("div", { style: S.navRow, children: [_jsxs("button", { style: S.btn('outline'), onClick: goBack, children: ["\u2190 ", t('setup.back')] }), _jsxs("button", { style: S.btn('primary', !canGoNext()), onClick: goNext, disabled: !canGoNext(), children: [t('setup.next'), " \u2192"] })] })] })), step === 'dialect' && (_jsxs("div", { children: [_jsxs("div", { style: S.sectionHeader, children: [_jsx("span", { style: S.sectionIcon, children: "\uD83D\uDCBE" }), _jsxs("div", { children: [_jsx("div", { style: S.sectionTitle, children: t('setup.dialect.title') }), _jsx("div", { style: S.sectionDesc, children: t('setup.dialect.description') })] })] }), _jsx("div", { style: S.grid3, children: DIALECT_INFO.map(d => (_jsxs("div", { style: S.dialectCard(dialect === d.key, !!d.premium), onClick: () => !d.premium && selectDialect(d.key), title: d.premium ? `${d.name} — disponible en version Premium` : d.name, children: [_jsx("div", { style: S.dialectIcon, children: d.icon }), _jsx("div", { style: S.dialectName, children: d.name }), d.premium && (_jsx("span", { style: { ...S.badge('premium'), marginLeft: 0, marginTop: 4 }, children: "Premium" }))] }, d.key))) }), _jsxs("div", { style: S.navRow, children: [_jsxs("button", { style: S.btn('outline'), onClick: goBack, children: ["\u2190 ", t('setup.back')] }), _jsxs("button", { style: S.btn('primary'), onClick: goNext, children: [t('setup.next'), " \u2192"] })] })] })), step === 'database' && (_jsxs("div", { children: [_jsxs("div", { style: S.sectionHeader, children: [_jsx("span", { style: S.sectionIcon, children: "\uD83D\uDDC4\uFE0F" }), _jsxs("div", { children: [_jsx("div", { style: S.sectionTitle, children: t('setup.database.title') }), _jsx("div", { style: S.sectionDesc, children: t('setup.database.description') })] })] }), dialect === 'sqlite' ? (_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.name') }), _jsx("input", { style: S.input, value: dbConfig.name, onChange: e => { setDbConfig({ ...dbConfig, name: e.target.value }); setDbTestResult(null); }, placeholder: dbNamePrefix }), _jsxs("p", { style: { fontSize: 11, color: '#9ca3af', marginTop: 4 }, children: [t('setup.database.sqliteInfo'), " ", _jsxs("code", { style: { fontFamily: 'monospace', backgroundColor: '#f3f4f6', padding: '1px 4px', borderRadius: 3 }, children: ["./data/", dbConfig.name, ".db"] })] })] })) : dialect === 'spanner' ? (_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.spannerPath') }), _jsx("input", { style: S.input, value: dbConfig.name, onChange: e => { setDbConfig({ ...dbConfig, name: e.target.value }); setDbTestResult(null); }, placeholder: "my-project/my-instance/mydb" }), _jsx("p", { style: { fontSize: 11, color: '#9ca3af', marginTop: 4 }, children: t('setup.database.spannerInfo') })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { style: S.formRow, children: [_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.host') }), _jsx("input", { style: S.input, value: dbConfig.host, onChange: e => { setDbConfig({ ...dbConfig, host: e.target.value }); setDbTestResult(null); } })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.port') }), _jsx("input", { style: S.input, type: "number", value: dbConfig.port, onChange: e => { setDbConfig({ ...dbConfig, port: parseInt(e.target.value) || 0 }); setDbTestResult(null); } })] })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.name') }), _jsx("input", { style: S.input, value: dbConfig.name, onChange: e => { setDbConfig({ ...dbConfig, name: e.target.value }); setDbTestResult(null); } })] }),
|
|
537
|
+
}) }), _jsxs("div", { style: S.navRow, children: [_jsxs("button", { style: S.btn('outline'), onClick: goBack, children: ["\u2190 ", t('setup.back')] }), _jsxs("button", { style: S.btn('primary', !canGoNext()), onClick: goNext, disabled: !canGoNext(), children: [t('setup.next'), " \u2192"] })] })] })), step === 'dialect' && (_jsxs("div", { children: [_jsxs("div", { style: S.sectionHeader, children: [_jsx("span", { style: S.sectionIcon, children: "\uD83D\uDCBE" }), _jsxs("div", { children: [_jsx("div", { style: S.sectionTitle, children: t('setup.dialect.title') }), _jsx("div", { style: S.sectionDesc, children: t('setup.dialect.description') })] })] }), _jsx("div", { style: S.grid3, children: DIALECT_INFO.map(d => (_jsxs("div", { style: S.dialectCard(dialect === d.key, !!d.premium), onClick: () => !d.premium && selectDialect(d.key), title: d.premium ? `${d.name} — disponible en version Premium` : d.name, children: [_jsx("div", { style: S.dialectIcon, children: d.icon }), _jsx("div", { style: S.dialectName, children: d.name }), d.premium && (_jsx("span", { style: { ...S.badge('premium'), marginLeft: 0, marginTop: 4 }, children: "Premium" }))] }, d.key))) }), _jsxs("div", { style: S.navRow, children: [_jsxs("button", { style: S.btn('outline'), onClick: goBack, children: ["\u2190 ", t('setup.back')] }), _jsxs("button", { style: S.btn('primary'), onClick: goNext, children: [t('setup.next'), " \u2192"] })] })] })), step === 'database' && (_jsxs("div", { children: [_jsxs("div", { style: S.sectionHeader, children: [_jsx("span", { style: S.sectionIcon, children: "\uD83D\uDDC4\uFE0F" }), _jsxs("div", { children: [_jsx("div", { style: S.sectionTitle, children: t('setup.database.title') }), _jsx("div", { style: S.sectionDesc, children: t('setup.database.description') })] })] }), dialect === 'sqlite' ? (_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.name') }), _jsx("input", { style: S.input, value: dbConfig.name, onChange: e => { setDbConfig({ ...dbConfig, name: e.target.value }); setDbTestResult(null); }, placeholder: dbNamePrefix }), _jsxs("p", { style: { fontSize: 11, color: '#9ca3af', marginTop: 4 }, children: [t('setup.database.sqliteInfo'), " ", _jsxs("code", { style: { fontFamily: 'monospace', backgroundColor: '#f3f4f6', padding: '1px 4px', borderRadius: 3 }, children: ["./data/", dbConfig.name, ".db"] })] })] })) : dialect === 'spanner' ? (_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.spannerPath') }), _jsx("input", { style: S.input, value: dbConfig.name, onChange: e => { setDbConfig({ ...dbConfig, name: e.target.value }); setDbTestResult(null); }, placeholder: "my-project/my-instance/mydb" }), _jsx("p", { style: { fontSize: 11, color: '#9ca3af', marginTop: 4 }, children: t('setup.database.spannerInfo') })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { style: S.formRow, children: [_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.host') }), _jsx("input", { style: S.input, value: dbConfig.host, onChange: e => { setDbConfig({ ...dbConfig, host: e.target.value }); setDbTestResult(null); } })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.port') }), _jsx("input", { style: S.input, type: "number", value: dbConfig.port, onChange: e => { setDbConfig({ ...dbConfig, port: parseInt(e.target.value) || 0 }); setDbTestResult(null); } })] })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.name') }), _jsx("input", { style: S.input, value: dbConfig.name, onChange: e => { setDbConfig({ ...dbConfig, name: e.target.value }); setDbTestResult(null); } })] }), _jsxs("div", { style: S.formRow, children: [_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.user') }), _jsx("input", { style: S.input, value: dbConfig.user, onChange: e => { setDbConfig({ ...dbConfig, user: e.target.value }); setDbTestResult(null); }, placeholder: dialect === 'hsqldb' ? 'SA' : '' })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.database.password') }), _jsx("input", { style: S.input, type: "password", value: dbConfig.password, onChange: e => { setDbConfig({ ...dbConfig, password: e.target.value }); setDbTestResult(null); } })] })] })] })), dialect === 'hsqldb' && (_jsxs("div", { style: { ...S.alert('warning'), marginTop: 12, fontSize: 12 }, children: [_jsx("strong", { children: "Prerequis :" }), " Le serveur HSQLDB doit etre lance avant le bridge.", _jsx("br", {}), _jsxs("code", { style: { fontFamily: 'monospace', backgroundColor: '#fef3c7', padding: '2px 6px', borderRadius: 3, display: 'inline-block', marginTop: 4, fontSize: 11 }, children: ["java -cp hsqldb*.jar org.hsqldb.server.Server --database.0 file:./data/", dbConfig.name, " --dbname.0 ", dbConfig.name] })] })), dialect !== 'mongodb' && dialect !== 'sqlite' && (_jsxs("div", { style: { ...S.alert('warning'), marginTop: 12 }, children: [t('setup.database.driverHint'), ' ', _jsx("code", { style: { fontFamily: 'monospace', backgroundColor: '#fef3c7', padding: '1px 4px', borderRadius: 3 }, children: DRIVER_HINTS[dialect] })] })), JDBC_DIALECTS.includes(dialect) && (_jsx(JarUploadInline, { dialect: dialect, jarEndpoint: ep.uploadJar, dbConfig: dbConfig })), dialect !== 'sqlite' && dialect !== 'spanner' && (_jsxs("div", { style: { ...S.checkRow, marginTop: 12, padding: '10px 14px', backgroundColor: '#fffbeb', border: '1px solid #fde68a', borderRadius: 8 }, children: [_jsx("input", { type: "checkbox", style: S.checkbox, checked: createIfNotExists, onChange: e => setCreateIfNotExists(e.target.checked) }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: t('setup.database.createIfNotExists') }), _jsx("div", { style: { fontSize: 12, color: '#92400e' }, children: t('setup.database.createIfNotExistsDesc') })] })] })), dialect !== 'sqlite' && dialect !== 'spanner' && (_jsxs("div", { style: { ...S.flex(16), marginTop: 16 }, children: [_jsxs("button", { style: S.btn('outline', dbTesting), onClick: testDb, disabled: dbTesting, children: [dbTesting ? '⏳ ' : '🗄️ ', dbTesting ? t('setup.database.testing') : t('setup.database.test')] }), dbTestResult && (_jsx("span", { style: { fontSize: 13, color: dbTestResult.ok ? '#059669' : '#dc2626' }, children: dbTestResult.ok
|
|
554
538
|
? `✅ ${t('setup.database.success')}${dbTestResult.dbVersion ? ` (v${dbTestResult.dbVersion})` : ''}`
|
|
555
539
|
: `❌ ${t('setup.database.error')}: ${dbTestResult.error}` }))] })), _jsxs("div", { style: S.navRow, children: [_jsxs("button", { style: S.btn('outline'), onClick: goBack, children: ["\u2190 ", t('setup.back')] }), _jsxs("button", { style: S.btn('primary', !canGoNext()), onClick: goNext, disabled: !canGoNext(), children: [t('setup.next'), " \u2192"] })] })] })), step === 'admin' && (_jsxs("div", { children: [_jsxs("div", { style: S.sectionHeader, children: [_jsx("span", { style: S.sectionIcon, children: "\uD83D\uDC64" }), _jsxs("div", { children: [_jsx("div", { style: S.sectionTitle, children: t('setup.admin.title') }), _jsx("div", { style: S.sectionDesc, children: t('setup.admin.description') })] })] }), _jsxs("div", { style: S.formRow, children: [_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.admin.firstName') }), _jsx("input", { style: S.input, value: adminConfig.firstName, onChange: e => setAdminConfig({ ...adminConfig, firstName: e.target.value }) })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.admin.lastName') }), _jsx("input", { style: S.input, value: adminConfig.lastName, onChange: e => setAdminConfig({ ...adminConfig, lastName: e.target.value }) })] })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.admin.email') }), _jsx("input", { style: S.input, type: "email", value: adminConfig.email, onChange: e => setAdminConfig({ ...adminConfig, email: e.target.value }), placeholder: "admin@example.com" })] }), _jsxs("div", { style: S.formRow, children: [_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.admin.password') }), _jsx("input", { style: S.input, type: "password", value: adminConfig.password, onChange: e => setAdminConfig({ ...adminConfig, password: e.target.value }) })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: t('setup.admin.confirmPassword') }), _jsx("input", { style: S.input, type: "password", value: adminConfig.confirmPassword, onChange: e => setAdminConfig({ ...adminConfig, confirmPassword: e.target.value }) })] })] }), adminConfig.password && adminConfig.confirmPassword && adminConfig.password !== adminConfig.confirmPassword && (_jsx("p", { style: { fontSize: 13, color: '#dc2626' }, children: t('setup.admin.passwordMismatch') })), _jsxs("div", { style: S.navRow, children: [_jsxs("button", { style: S.btn('outline'), onClick: goBack, children: ["\u2190 ", t('setup.back')] }), _jsxs("button", { style: S.btn('primary', !canGoNext()), onClick: goNext, disabled: !canGoNext(), children: [t('setup.next'), " \u2192"] })] })] })), step === 'summary' && (_jsxs("div", { children: [_jsxs("div", { style: S.sectionHeader, children: [_jsx("span", { style: S.sectionIcon, children: "\u2699\uFE0F" }), _jsxs("div", { children: [_jsx("div", { style: S.sectionTitle, children: t('setup.summary.title') }), _jsx("div", { style: S.sectionDesc, children: t('setup.summary.description') })] })] }), _jsxs("div", { style: S.summaryCard, children: [_jsx("div", { style: S.summaryTitle, children: t('setup.summary.dbConfig') }), _jsxs("div", { style: S.summaryText, children: [_jsx("span", { style: { fontFamily: 'monospace' }, children: dbSummaryLabel() }), dialect !== 'sqlite' && dbConfig.user && _jsxs("span", { style: { display: 'block', marginTop: 4 }, children: ["Utilisateur: ", dbConfig.user] })] })] }), _jsxs("div", { style: S.summaryCard, children: [_jsx("div", { style: S.summaryTitle, children: t('setup.summary.adminConfig') }), _jsxs("div", { style: S.summaryText, children: [_jsxs("div", { children: [adminConfig.firstName, " ", adminConfig.lastName] }), _jsx("div", { children: adminConfig.email })] })] }), _jsxs("div", { style: S.summaryCard, children: [_jsx("div", { style: S.summaryTitle, children: t('setup.modules.title') }), _jsx("div", { style: S.flexWrap, children: selectedModules.map(key => {
|
|
556
540
|
const mod = availableModules.find(m => m.key === key);
|
package/dist/lib/compose-uri.js
CHANGED
|
@@ -28,6 +28,8 @@ export function composeDbUri(dialect, config) {
|
|
|
28
28
|
case 'hana':
|
|
29
29
|
return `hana://${eu}:${ep}@${host}:${port}`;
|
|
30
30
|
case 'hsqldb':
|
|
31
|
+
if (user)
|
|
32
|
+
return `hsqldb:hsql://${eu}:${ep}@${host}:${port}/${name}`;
|
|
31
33
|
return `hsqldb:hsql://${host}:${port}/${name}`;
|
|
32
34
|
case 'spanner':
|
|
33
35
|
return `spanner://projects/${name}`;
|
package/package.json
CHANGED