@mostajs/setup 1.4.2 → 1.4.3
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.
|
@@ -12,7 +12,7 @@ export function createTestDbHandler(needsSetup) {
|
|
|
12
12
|
return Response.json({ error: 'Already installed' }, { status: 400 });
|
|
13
13
|
}
|
|
14
14
|
const body = await req.json();
|
|
15
|
-
const { dialect, host, port, name, user, password } = body;
|
|
15
|
+
const { dialect, host, port, name, user, password, createIfNotExists } = body;
|
|
16
16
|
if (!dialect || !name) {
|
|
17
17
|
return Response.json({ error: 'Missing required fields' }, { status: 400 });
|
|
18
18
|
}
|
|
@@ -23,6 +23,7 @@ export function createTestDbHandler(needsSetup) {
|
|
|
23
23
|
name,
|
|
24
24
|
user: user || '',
|
|
25
25
|
password: password || '',
|
|
26
|
+
createIfNotExists: !!createIfNotExists,
|
|
26
27
|
});
|
|
27
28
|
return Response.json(result);
|
|
28
29
|
}
|
|
@@ -70,24 +70,67 @@ export function createUploadJarHandlers() {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
|
-
* PATCH — Start
|
|
74
|
-
*
|
|
73
|
+
* PATCH — Start or stop the JDBC bridge.
|
|
74
|
+
* Start: { action: 'start', dialect: string, host: string, port: number, name: string, user?: string, password?: string }
|
|
75
|
+
* Stop: { action: 'stop', port: number }
|
|
75
76
|
* Returns: { ok: true, port: number } or { ok: false, error: string }
|
|
76
77
|
*/
|
|
77
78
|
async function PATCH(req) {
|
|
78
79
|
try {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
const body = await req.json();
|
|
81
|
+
const { action } = body;
|
|
82
|
+
if (action === 'stop') {
|
|
83
|
+
const bridgePort = body.port || 8765;
|
|
84
|
+
// Kill bridge on the given port
|
|
85
|
+
try {
|
|
86
|
+
const { BridgeManager } = await import('@mostajs/orm');
|
|
87
|
+
const manager = BridgeManager.getInstance();
|
|
88
|
+
const bridges = manager.list();
|
|
89
|
+
const bridge = bridges.find((b) => b.port === bridgePort);
|
|
90
|
+
if (bridge) {
|
|
91
|
+
await manager.stop(bridge.key);
|
|
92
|
+
return Response.json({ ok: true, message: `Bridge arrete sur le port ${bridgePort}` });
|
|
93
|
+
}
|
|
94
|
+
// Fallback: kill process on port
|
|
95
|
+
const { execSync } = await import('child_process');
|
|
96
|
+
try {
|
|
97
|
+
execSync(`fuser -k ${bridgePort}/tcp 2>/dev/null`, { stdio: 'ignore' });
|
|
98
|
+
}
|
|
99
|
+
catch { /* port may already be free */ }
|
|
100
|
+
return Response.json({ ok: true, message: `Port ${bridgePort} libere` });
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
const msg = err instanceof Error ? err.message : 'Erreur';
|
|
104
|
+
return Response.json({ ok: false, error: msg });
|
|
105
|
+
}
|
|
82
106
|
}
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
if (
|
|
86
|
-
return Response.json({ ok:
|
|
107
|
+
// Default: action === 'start'
|
|
108
|
+
const { dialect, host, port, name, user, password } = body;
|
|
109
|
+
if (!dialect) {
|
|
110
|
+
return Response.json({ ok: false, error: 'dialect requis' }, { status: 400 });
|
|
87
111
|
}
|
|
88
|
-
|
|
89
|
-
|
|
112
|
+
// Compose URI using setup's composeDbUri for consistency with test-db
|
|
113
|
+
const { composeDbUri } = await import('../lib/compose-uri');
|
|
114
|
+
const uri = composeDbUri(dialect, {
|
|
115
|
+
host: host || 'localhost',
|
|
116
|
+
port: port || 0,
|
|
117
|
+
name: name || '',
|
|
118
|
+
user: user || '',
|
|
119
|
+
password: password || '',
|
|
120
|
+
});
|
|
121
|
+
// Start bridge via BridgeManager directly (no SELECT 1 — just start the Java process)
|
|
122
|
+
const { BridgeManager } = await import('@mostajs/orm');
|
|
123
|
+
const { JdbcNormalizer } = await import('@mostajs/orm');
|
|
124
|
+
const manager = BridgeManager.getInstance();
|
|
125
|
+
// Check if JAR is available
|
|
126
|
+
if (!JdbcNormalizer.isAvailable(dialect)) {
|
|
127
|
+
return Response.json({
|
|
128
|
+
ok: false,
|
|
129
|
+
error: `Aucun JAR JDBC trouve pour ${dialect}. Uploadez le JAR d'abord.`,
|
|
130
|
+
});
|
|
90
131
|
}
|
|
132
|
+
const bridge = await manager.getOrCreate(dialect, uri);
|
|
133
|
+
return Response.json({ ok: true, port: bridge.port });
|
|
91
134
|
}
|
|
92
135
|
catch (err) {
|
|
93
136
|
const message = err instanceof Error ? err.message : 'Erreur serveur';
|
|
@@ -187,19 +187,6 @@ function resolveModuleDeps(selected, all) {
|
|
|
187
187
|
}
|
|
188
188
|
return Array.from(set);
|
|
189
189
|
}
|
|
190
|
-
function simpleDbUri(dialect, cfg) {
|
|
191
|
-
if (dialect === 'sqlite')
|
|
192
|
-
return `./data/${cfg.name}.db`;
|
|
193
|
-
if (dialect === 'mongodb')
|
|
194
|
-
return `mongodb://${cfg.user ? `${cfg.user}:${cfg.password}@` : ''}${cfg.host}:${cfg.port}/${cfg.name}`;
|
|
195
|
-
const scheme = {
|
|
196
|
-
postgres: 'postgresql', mysql: 'mysql', mariadb: 'mysql', mssql: 'mssql',
|
|
197
|
-
oracle: 'oracle:thin', cockroachdb: 'postgresql', db2: 'db2', hana: 'sap',
|
|
198
|
-
hsqldb: 'hsqldb:hsql', spanner: 'spanner', sybase: 'sybase:Tds',
|
|
199
|
-
};
|
|
200
|
-
const s = scheme[dialect] || dialect;
|
|
201
|
-
return `${s}://${cfg.user ? `${cfg.user}:${cfg.password}@` : ''}${cfg.host}:${cfg.port}/${cfg.name}`;
|
|
202
|
-
}
|
|
203
190
|
async function safeJson(res) {
|
|
204
191
|
try {
|
|
205
192
|
return JSON.parse(await res.text());
|
|
@@ -229,9 +216,10 @@ async function fetchRetry(url, init, retries = 3, delay = 2000) {
|
|
|
229
216
|
return fetch(url, init);
|
|
230
217
|
}
|
|
231
218
|
// ── JAR Upload Sub-component ─────────────────────────────────
|
|
232
|
-
function JarUploadInline({ dialect, jarEndpoint,
|
|
219
|
+
function JarUploadInline({ dialect, jarEndpoint, dbConfig }) {
|
|
233
220
|
const [uploading, setUploading] = useState(false);
|
|
234
|
-
const [
|
|
221
|
+
const [bridgeLoading, setBridgeLoading] = useState(false);
|
|
222
|
+
const [bridgePort, setBridgePort] = useState(null);
|
|
235
223
|
const [message, setMessage] = useState(null);
|
|
236
224
|
const [jarStatus, setJarStatus] = useState(null);
|
|
237
225
|
useEffect(() => {
|
|
@@ -273,21 +261,18 @@ function JarUploadInline({ dialect, jarEndpoint, dbUri }) {
|
|
|
273
261
|
}
|
|
274
262
|
};
|
|
275
263
|
const handleStartBridge = async () => {
|
|
276
|
-
|
|
277
|
-
setMessage({ ok: false, text: 'Renseignez les parametres de connexion avant de lancer le bridge' });
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
setBridgeTesting(true);
|
|
264
|
+
setBridgeLoading(true);
|
|
281
265
|
setMessage(null);
|
|
282
266
|
try {
|
|
283
267
|
const res = await fetch(jarEndpoint, {
|
|
284
268
|
method: 'PATCH',
|
|
285
269
|
headers: { 'Content-Type': 'application/json' },
|
|
286
|
-
body: JSON.stringify({ dialect,
|
|
270
|
+
body: JSON.stringify({ action: 'start', dialect, ...dbConfig }),
|
|
287
271
|
});
|
|
288
272
|
const result = await res.json();
|
|
289
273
|
if (result.ok) {
|
|
290
|
-
|
|
274
|
+
setBridgePort(result.port || 8765);
|
|
275
|
+
setMessage({ ok: true, text: `Bridge JDBC lance sur le port ${result.port || 8765}` });
|
|
291
276
|
}
|
|
292
277
|
else {
|
|
293
278
|
setMessage({ ok: false, text: result.error || 'Echec lancement du bridge' });
|
|
@@ -297,14 +282,35 @@ function JarUploadInline({ dialect, jarEndpoint, dbUri }) {
|
|
|
297
282
|
setMessage({ ok: false, text: 'Erreur reseau' });
|
|
298
283
|
}
|
|
299
284
|
finally {
|
|
300
|
-
|
|
285
|
+
setBridgeLoading(false);
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
const handleStopBridge = async () => {
|
|
289
|
+
setBridgeLoading(true);
|
|
290
|
+
setMessage(null);
|
|
291
|
+
try {
|
|
292
|
+
const res = await fetch(jarEndpoint, {
|
|
293
|
+
method: 'PATCH',
|
|
294
|
+
headers: { 'Content-Type': 'application/json' },
|
|
295
|
+
body: JSON.stringify({ action: 'stop', port: bridgePort || 8765 }),
|
|
296
|
+
});
|
|
297
|
+
const result = await res.json();
|
|
298
|
+
if (result.ok) {
|
|
299
|
+
setBridgePort(null);
|
|
300
|
+
setMessage({ ok: true, text: result.message || 'Bridge arrete' });
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
setMessage({ ok: false, text: result.error || 'Echec arret du bridge' });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
setMessage({ ok: false, text: 'Erreur reseau' });
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
setBridgeLoading(false);
|
|
301
311
|
}
|
|
302
312
|
};
|
|
303
|
-
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: { ...S.flex(
|
|
304
|
-
...S.btn('primary', bridgeTesting),
|
|
305
|
-
fontSize: 12, padding: '6px 12px',
|
|
306
|
-
backgroundColor: bridgeTesting ? '#6b7280' : '#059669',
|
|
307
|
-
}, onClick: handleStartBridge, disabled: bridgeTesting, children: bridgeTesting ? 'Lancement...' : 'Lancer le bridge' })), _jsx("span", { style: { fontSize: 11, color: '#9ca3af' }, children: "Ex: hsqldb*.jar, ojdbc*.jar, db2jcc*.jar" })] }), message && (_jsx("p", { style: { fontSize: 12, color: message.ok ? '#059669' : '#dc2626', marginTop: 8 }, children: message.text }))] }));
|
|
313
|
+
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" })), bridgePort && (_jsxs("span", { style: { fontSize: 11, color: '#059669', fontWeight: 600 }, children: ["Bridge actif port ", bridgePort] }))] }), _jsxs("div", { style: { ...S.flex(8), marginTop: 8, flexWrap: 'wrap' }, 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' } })] }), jarStatus?.hasJar && !bridgePort && (_jsx("button", { style: { ...S.btn('primary', bridgeLoading), fontSize: 12, padding: '6px 12px', backgroundColor: bridgeLoading ? '#6b7280' : '#059669' }, onClick: handleStartBridge, disabled: bridgeLoading, children: bridgeLoading ? 'Lancement...' : 'Lancer le bridge' })), bridgePort && (_jsx("button", { style: { ...S.btn('primary', bridgeLoading), fontSize: 12, padding: '6px 12px', backgroundColor: bridgeLoading ? '#6b7280' : '#dc2626' }, onClick: handleStopBridge, disabled: bridgeLoading, children: bridgeLoading ? 'Arret...' : 'Arreter le bridge' })), _jsx("span", { style: { fontSize: 11, color: '#9ca3af' }, children: "Ex: hsqldb*.jar, ojdbc*.jar, db2jcc*.jar" })] }), message && (_jsx("p", { style: { fontSize: 12, color: message.ok ? '#059669' : '#dc2626', marginTop: 8 }, children: message.text }))] }));
|
|
308
314
|
}
|
|
309
315
|
// ── Main Component ───────────────────────────────────────────
|
|
310
316
|
export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNamePrefix = 'mydb', persistState = true, }) {
|
|
@@ -328,6 +334,7 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
328
334
|
const [selectedModules, setSelectedModules] = useState([]);
|
|
329
335
|
const [detectedModules, setDetectedModules] = useState([]);
|
|
330
336
|
const [modulesDetected, setModulesDetected] = useState(false);
|
|
337
|
+
const [createIfNotExists, setCreateIfNotExists] = useState(true);
|
|
331
338
|
const [installing, setInstalling] = useState(false);
|
|
332
339
|
const [installResult, setInstallResult] = useState(null);
|
|
333
340
|
const [hydrated, setHydrated] = useState(false);
|
|
@@ -431,7 +438,7 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
431
438
|
const res = await fetch(ep.testDb, {
|
|
432
439
|
method: 'POST',
|
|
433
440
|
headers: { 'Content-Type': 'application/json' },
|
|
434
|
-
body: JSON.stringify({ dialect, ...dbConfig }),
|
|
441
|
+
body: JSON.stringify({ dialect, ...dbConfig, createIfNotExists }),
|
|
435
442
|
});
|
|
436
443
|
const data = await res.json();
|
|
437
444
|
if (data.ok) {
|
|
@@ -530,7 +537,7 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
530
537
|
const isSelected = selectedModules.includes(mod.key);
|
|
531
538
|
const isDetected = detectedModules.includes(mod.key);
|
|
532
539
|
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));
|
|
533
|
-
}) }), _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); } })] }), dialect !== 'hsqldb' && (_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); } })] }), _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 !== '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,
|
|
540
|
+
}) }), _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); } })] }), dialect !== 'hsqldb' && (_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); } })] }), _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 !== '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
|
|
534
541
|
? `✅ ${t('setup.database.success')}${dbTestResult.dbVersion ? ` (v${dbTestResult.dbVersion})` : ''}`
|
|
535
542
|
: `❌ ${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 => {
|
|
536
543
|
const mod = availableModules.find(m => m.key === key);
|
package/dist/lib/db-test.d.ts
CHANGED
package/dist/lib/db-test.js
CHANGED
|
@@ -3,7 +3,7 @@ import { composeDbUri } from './compose-uri';
|
|
|
3
3
|
* Test a database connection without affecting the global dialect singleton.
|
|
4
4
|
*/
|
|
5
5
|
export async function testDbConnection(params) {
|
|
6
|
-
const { dialect, ...dbConfig } = params;
|
|
6
|
+
const { dialect, createIfNotExists, ...dbConfig } = params;
|
|
7
7
|
try {
|
|
8
8
|
switch (dialect) {
|
|
9
9
|
case 'mongodb': {
|
|
@@ -26,7 +26,11 @@ export async function testDbConnection(params) {
|
|
|
26
26
|
default: {
|
|
27
27
|
const uri = composeDbUri(dialect, dbConfig);
|
|
28
28
|
const { testConnection } = await import('@mostajs/orm');
|
|
29
|
-
const result = await testConnection({
|
|
29
|
+
const result = await testConnection({
|
|
30
|
+
dialect,
|
|
31
|
+
uri,
|
|
32
|
+
schemaStrategy: createIfNotExists ? 'update' : 'none',
|
|
33
|
+
});
|
|
30
34
|
return result;
|
|
31
35
|
}
|
|
32
36
|
}
|
package/package.json
CHANGED