@mostajs/setup 1.1.4 → 1.3.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.
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates handlers for JAR file management API.
|
|
3
|
+
*
|
|
4
|
+
* GET — list uploaded JARs and JDBC dialect status
|
|
5
|
+
* POST — upload a new JAR file (multipart/form-data)
|
|
6
|
+
* DELETE — remove a JAR file
|
|
7
|
+
*/
|
|
8
|
+
export declare function createUploadJarHandlers(): {
|
|
9
|
+
GET: () => Promise<Response>;
|
|
10
|
+
POST: (req: Request) => Promise<Response>;
|
|
11
|
+
DELETE: (req: Request) => Promise<Response>;
|
|
12
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// @mostajs/setup — API Route factory for JAR file upload/list/delete
|
|
2
|
+
// Delegates to @mostajs/orm jar-upload module
|
|
3
|
+
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
4
|
+
/**
|
|
5
|
+
* Creates handlers for JAR file management API.
|
|
6
|
+
*
|
|
7
|
+
* GET — list uploaded JARs and JDBC dialect status
|
|
8
|
+
* POST — upload a new JAR file (multipart/form-data)
|
|
9
|
+
* DELETE — remove a JAR file
|
|
10
|
+
*/
|
|
11
|
+
export function createUploadJarHandlers() {
|
|
12
|
+
async function GET() {
|
|
13
|
+
try {
|
|
14
|
+
const { listJarFiles, getJdbcDialectStatus } = await import('@mostajs/orm');
|
|
15
|
+
return Response.json({
|
|
16
|
+
ok: true,
|
|
17
|
+
jars: listJarFiles(),
|
|
18
|
+
dialects: getJdbcDialectStatus(),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
const message = err instanceof Error ? err.message : 'Erreur serveur';
|
|
23
|
+
return Response.json({ ok: false, error: message }, { status: 500 });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function POST(req) {
|
|
27
|
+
try {
|
|
28
|
+
const { saveJarFile } = await import('@mostajs/orm');
|
|
29
|
+
const formData = await req.formData();
|
|
30
|
+
const file = formData.get('jar');
|
|
31
|
+
if (!file) {
|
|
32
|
+
return Response.json({ ok: false, error: 'Aucun fichier JAR fourni. Utilisez le champ "jar".' }, { status: 400 });
|
|
33
|
+
}
|
|
34
|
+
if (!file.name.endsWith('.jar')) {
|
|
35
|
+
return Response.json({ ok: false, error: 'Le fichier doit etre un .jar' }, { status: 400 });
|
|
36
|
+
}
|
|
37
|
+
// Max 50MB
|
|
38
|
+
if (file.size > 50 * 1024 * 1024) {
|
|
39
|
+
return Response.json({ ok: false, error: 'Le fichier JAR depasse la limite de 50 MB' }, { status: 400 });
|
|
40
|
+
}
|
|
41
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
42
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
43
|
+
const result = saveJarFile(file.name, buffer);
|
|
44
|
+
if (!result.ok) {
|
|
45
|
+
return Response.json(result, { status: 400 });
|
|
46
|
+
}
|
|
47
|
+
return Response.json(result);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const message = err instanceof Error ? err.message : 'Erreur serveur';
|
|
51
|
+
return Response.json({ ok: false, error: message }, { status: 500 });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function DELETE(req) {
|
|
55
|
+
try {
|
|
56
|
+
const { deleteJarFile } = await import('@mostajs/orm');
|
|
57
|
+
const { fileName } = await req.json();
|
|
58
|
+
if (!fileName) {
|
|
59
|
+
return Response.json({ ok: false, error: 'fileName requis' }, { status: 400 });
|
|
60
|
+
}
|
|
61
|
+
const result = deleteJarFile(fileName);
|
|
62
|
+
if (!result.ok) {
|
|
63
|
+
return Response.json(result, { status: 404 });
|
|
64
|
+
}
|
|
65
|
+
return Response.json(result);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const message = err instanceof Error ? err.message : 'Erreur serveur';
|
|
69
|
+
return Response.json({ ok: false, error: message }, { status: 500 });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return { GET, POST, DELETE };
|
|
73
|
+
}
|
|
@@ -3,6 +3,8 @@ export interface ReconfigPanelProps {
|
|
|
3
3
|
apiEndpoint?: string;
|
|
4
4
|
/** API endpoint for module detection (default: '/api/setup/detect-modules') */
|
|
5
5
|
detectEndpoint?: string;
|
|
6
|
+
/** API endpoint for JAR upload (default: '/api/setup/upload-jar') */
|
|
7
|
+
jarEndpoint?: string;
|
|
6
8
|
/** Translate function */
|
|
7
9
|
t?: (key: string) => string;
|
|
8
10
|
/** Called after successful DB change */
|
|
@@ -14,4 +16,4 @@ export interface ReconfigPanelProps {
|
|
|
14
16
|
/** Callback to run seed after DB change */
|
|
15
17
|
onSeedRequested?: () => Promise<void>;
|
|
16
18
|
}
|
|
17
|
-
export default function ReconfigPanel({ apiEndpoint, detectEndpoint, t, onDbChanged, onModulesChanged, showSeedOption, onSeedRequested, }: ReconfigPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export default function ReconfigPanel({ apiEndpoint, detectEndpoint, jarEndpoint, t, onDbChanged, onModulesChanged, showSeedOption, onSeedRequested, }: ReconfigPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
'use client';
|
|
4
4
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { useState, useEffect, useCallback } from 'react';
|
|
6
|
+
/** Dialects that require a JDBC bridge JAR */
|
|
7
|
+
const JDBC_DIALECTS = ['hsqldb', 'oracle', 'db2', 'sybase', 'hana'];
|
|
6
8
|
const DIALECTS = [
|
|
7
9
|
{ key: 'mongodb', name: 'MongoDB', icon: '🍃', defaultPort: 27017, defaultUser: '', defaultHost: 'localhost', requiresAuth: false },
|
|
8
10
|
{ key: 'sqlite', name: 'SQLite', icon: '📄', defaultPort: 0, defaultUser: '', defaultHost: '', requiresAuth: false },
|
|
@@ -10,8 +12,13 @@ const DIALECTS = [
|
|
|
10
12
|
{ key: 'mysql', name: 'MySQL', icon: '🐬', defaultPort: 3306, defaultUser: 'root', defaultHost: 'localhost', requiresAuth: true },
|
|
11
13
|
{ key: 'mariadb', name: 'MariaDB', icon: '🦭', defaultPort: 3306, defaultUser: 'root', defaultHost: 'localhost', requiresAuth: true },
|
|
12
14
|
{ key: 'mssql', name: 'SQL Server', icon: '🟦', defaultPort: 1433, defaultUser: 'sa', defaultHost: 'localhost', requiresAuth: true },
|
|
13
|
-
{ key: 'oracle', name: 'Oracle', icon: '🔴', defaultPort: 1521, defaultUser: 'system', defaultHost: 'localhost', requiresAuth: true },
|
|
15
|
+
{ key: 'oracle', name: 'Oracle', icon: '🔴', defaultPort: 1521, defaultUser: 'system', defaultHost: 'localhost', requiresAuth: true, premium: true, jdbc: true },
|
|
14
16
|
{ key: 'cockroachdb', name: 'CockroachDB', icon: '🪳', defaultPort: 26257, defaultUser: 'root', defaultHost: 'localhost', requiresAuth: true },
|
|
17
|
+
{ key: 'db2', name: 'IBM DB2', icon: '🏢', defaultPort: 50000, defaultUser: 'db2inst1', defaultHost: 'localhost', requiresAuth: true, premium: true, jdbc: true },
|
|
18
|
+
{ key: 'hana', name: 'SAP HANA', icon: '💎', defaultPort: 39013, defaultUser: 'SYSTEM', defaultHost: 'localhost', requiresAuth: true, premium: true, jdbc: true },
|
|
19
|
+
{ key: 'hsqldb', name: 'HyperSQL', icon: '⚡', defaultPort: 9001, defaultUser: 'SA', defaultHost: 'localhost', requiresAuth: false, jdbc: true },
|
|
20
|
+
{ key: 'spanner', name: 'Cloud Spanner', icon: '☁️', defaultPort: 0, defaultUser: '', defaultHost: '', requiresAuth: false, premium: true },
|
|
21
|
+
{ key: 'sybase', name: 'Sybase ASE', icon: '🔷', defaultPort: 5000, defaultUser: 'sa', defaultHost: 'localhost', requiresAuth: true, premium: true, jdbc: true },
|
|
15
22
|
];
|
|
16
23
|
// ── Styles ────────────────────────────────────────────────────
|
|
17
24
|
const S = {
|
|
@@ -103,7 +110,7 @@ const S = {
|
|
|
103
110
|
},
|
|
104
111
|
};
|
|
105
112
|
// ── Component ────────────────────────────────────────────────
|
|
106
|
-
export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', detectEndpoint = '/api/setup/detect-modules', t = (k) => k, onDbChanged, onModulesChanged, showSeedOption = true, onSeedRequested, }) {
|
|
113
|
+
export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', detectEndpoint = '/api/setup/detect-modules', jarEndpoint = '/api/setup/upload-jar', t = (k) => k, onDbChanged, onModulesChanged, showSeedOption = true, onSeedRequested, }) {
|
|
107
114
|
// --- State ---
|
|
108
115
|
const [loading, setLoading] = useState(true);
|
|
109
116
|
const [currentDialect, setCurrentDialect] = useState('');
|
|
@@ -120,6 +127,11 @@ export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', det
|
|
|
120
127
|
const [dbMessage, setDbMessage] = useState(null);
|
|
121
128
|
const [wantSeed, setWantSeed] = useState(true);
|
|
122
129
|
const [seeding, setSeeding] = useState(false);
|
|
130
|
+
// JAR upload
|
|
131
|
+
const [jarUploading, setJarUploading] = useState(false);
|
|
132
|
+
const [jarMessage, setJarMessage] = useState(null);
|
|
133
|
+
const [jarFiles, setJarFiles] = useState([]);
|
|
134
|
+
const [jdbcStatus, setJdbcStatus] = useState([]);
|
|
123
135
|
// Module saving
|
|
124
136
|
const [moduleSaving, setModuleSaving] = useState(false);
|
|
125
137
|
const [moduleMessage, setModuleMessage] = useState(null);
|
|
@@ -154,6 +166,18 @@ export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', det
|
|
|
154
166
|
password: '',
|
|
155
167
|
});
|
|
156
168
|
}
|
|
169
|
+
// Load JAR status
|
|
170
|
+
try {
|
|
171
|
+
const jarRes = await fetch(jarEndpoint);
|
|
172
|
+
const jarData = await jarRes.json();
|
|
173
|
+
if (jarData.ok) {
|
|
174
|
+
setJarFiles(jarData.jars || []);
|
|
175
|
+
setJdbcStatus(jarData.dialects || []);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// JAR endpoint may not exist — ignore
|
|
180
|
+
}
|
|
157
181
|
}
|
|
158
182
|
catch {
|
|
159
183
|
// ignore
|
|
@@ -161,8 +185,72 @@ export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', det
|
|
|
161
185
|
finally {
|
|
162
186
|
setLoading(false);
|
|
163
187
|
}
|
|
164
|
-
}, [apiEndpoint, detectEndpoint]);
|
|
188
|
+
}, [apiEndpoint, detectEndpoint, jarEndpoint]);
|
|
165
189
|
useEffect(() => { loadConfig(); }, [loadConfig]);
|
|
190
|
+
// --- JAR upload ---
|
|
191
|
+
const handleJarUpload = async (e) => {
|
|
192
|
+
const file = e.target.files?.[0];
|
|
193
|
+
if (!file)
|
|
194
|
+
return;
|
|
195
|
+
if (!file.name.endsWith('.jar')) {
|
|
196
|
+
setJarMessage({ type: 'error', text: 'Le fichier doit etre un .jar' });
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
setJarUploading(true);
|
|
200
|
+
setJarMessage(null);
|
|
201
|
+
try {
|
|
202
|
+
const formData = new FormData();
|
|
203
|
+
formData.append('jar', file);
|
|
204
|
+
const res = await fetch(jarEndpoint, { method: 'POST', body: formData });
|
|
205
|
+
const result = await res.json();
|
|
206
|
+
if (result.ok) {
|
|
207
|
+
const msg = result.replaced
|
|
208
|
+
? `${result.fileName} uploade (remplace ${result.replaced})`
|
|
209
|
+
: `${result.fileName} uploade`;
|
|
210
|
+
setJarMessage({ type: 'success', text: result.dialect ? `${msg} — dialect: ${result.dialect}` : msg });
|
|
211
|
+
// Refresh JAR list
|
|
212
|
+
const jarRes = await fetch(jarEndpoint);
|
|
213
|
+
const jarData = await jarRes.json();
|
|
214
|
+
if (jarData.ok) {
|
|
215
|
+
setJarFiles(jarData.jars || []);
|
|
216
|
+
setJdbcStatus(jarData.dialects || []);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
setJarMessage({ type: 'error', text: result.error || 'Erreur upload' });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
setJarMessage({ type: 'error', text: 'Erreur reseau' });
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
setJarUploading(false);
|
|
228
|
+
// Reset input
|
|
229
|
+
e.target.value = '';
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
const handleJarDelete = async (fileName) => {
|
|
233
|
+
try {
|
|
234
|
+
const res = await fetch(jarEndpoint, {
|
|
235
|
+
method: 'DELETE',
|
|
236
|
+
headers: { 'Content-Type': 'application/json' },
|
|
237
|
+
body: JSON.stringify({ fileName }),
|
|
238
|
+
});
|
|
239
|
+
const result = await res.json();
|
|
240
|
+
if (result.ok) {
|
|
241
|
+
setJarMessage({ type: 'success', text: `${fileName} supprime` });
|
|
242
|
+
const jarRes = await fetch(jarEndpoint);
|
|
243
|
+
const jarData = await jarRes.json();
|
|
244
|
+
if (jarData.ok) {
|
|
245
|
+
setJarFiles(jarData.jars || []);
|
|
246
|
+
setJdbcStatus(jarData.dialects || []);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
// ignore
|
|
252
|
+
}
|
|
253
|
+
};
|
|
166
254
|
// --- Dialect change ---
|
|
167
255
|
const handleDialectChange = (dialect) => {
|
|
168
256
|
setSelectedDialect(dialect);
|
|
@@ -323,5 +411,21 @@ export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', det
|
|
|
323
411
|
...S.moduleCard(isActive, isRequired || !isInstalled),
|
|
324
412
|
opacity: isInstalled ? 1 : 0.5,
|
|
325
413
|
}, onClick: () => isInstalled && toggleModule(mod.key), children: [_jsxs("div", { style: S.moduleHeader, children: [_jsx("span", { style: S.moduleIcon, children: mod.icon }), _jsx("span", { style: S.moduleName, children: mod.label }), isRequired && _jsx("span", { style: S.moduleBadge('required'), children: "requis" }), isActive && !isRequired && _jsx("span", { style: S.moduleBadge('active'), children: "actif" }), !isInstalled && _jsx("span", { style: S.moduleBadge('dep'), children: "non installe" })] }), _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));
|
|
326
|
-
}) }), _jsx("div", { style: { marginTop: 16, display: 'flex', gap: 8 }, children: _jsx("button", { style: S.btn('primary'), onClick: handleSaveModules, disabled: moduleSaving, children: moduleSaving ? 'Enregistrement...' : 'Enregistrer les modules' }) })] }), _jsxs("div", { style: S.section, children: [_jsxs("div", { style: S.sectionTitle, children: [_jsx("span", { children: "\
|
|
414
|
+
}) }), _jsx("div", { style: { marginTop: 16, display: 'flex', gap: 8 }, children: _jsx("button", { style: S.btn('primary'), onClick: handleSaveModules, disabled: moduleSaving, children: moduleSaving ? 'Enregistrement...' : 'Enregistrer les modules' }) })] }), _jsxs("div", { style: S.section, children: [_jsxs("div", { style: S.sectionTitle, children: [_jsx("span", { children: "\u2615" }), " Drivers JDBC"] }), _jsx("div", { style: S.sectionDesc, children: "Uploadez les fichiers JAR des drivers JDBC pour les bases de donnees enterprise. Les dialects JDBC (HyperSQL, Oracle, DB2, SAP HANA, Sybase) utilisent un bridge Java pour se connecter." }), jarMessage && (_jsx("div", { style: S.alert(jarMessage.type), children: jarMessage.text })), jdbcStatus.length > 0 && (_jsx("div", { style: { marginBottom: 16 }, children: _jsxs("table", { style: { width: '100%', borderCollapse: 'collapse', fontSize: 13 }, children: [_jsx("thead", { children: _jsxs("tr", { style: { borderBottom: '2px solid #e5e7eb', textAlign: 'left' }, children: [_jsx("th", { style: { padding: '8px 12px', fontWeight: 600 }, children: "Dialect" }), _jsx("th", { style: { padding: '8px 12px', fontWeight: 600 }, children: "Statut" }), _jsx("th", { style: { padding: '8px 12px', fontWeight: 600 }, children: "Fichier JAR" }), _jsx("th", { style: { padding: '8px 12px', fontWeight: 600 } })] }) }), _jsx("tbody", { children: jdbcStatus.map((s) => (_jsxs("tr", { style: { borderBottom: '1px solid #f3f4f6' }, children: [_jsx("td", { style: { padding: '8px 12px', fontWeight: 500 }, children: s.label }), _jsx("td", { style: { padding: '8px 12px' }, children: s.hasJar ? (_jsx("span", { style: { color: '#059669', fontWeight: 600, fontSize: 12 }, children: "Pret" })) : (_jsx("span", { style: { color: '#9ca3af', fontSize: 12 }, children: "Non installe" })) }), _jsx("td", { style: { padding: '8px 12px', fontSize: 12, color: '#6b7280', fontFamily: 'monospace' }, children: s.jarFile || '—' }), _jsx("td", { style: { padding: '8px 12px' }, children: s.hasJar && s.jarFile && (_jsx("button", { style: { ...S.btn('danger'), padding: '3px 8px', fontSize: 11 }, onClick: () => handleJarDelete(s.jarFile), children: "Supprimer" })) })] }, s.dialect))) })] }) })), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 12 }, children: [_jsxs("label", { style: {
|
|
415
|
+
...S.btn('primary'),
|
|
416
|
+
cursor: jarUploading ? 'wait' : 'pointer',
|
|
417
|
+
opacity: jarUploading ? 0.6 : 1,
|
|
418
|
+
}, children: [jarUploading ? 'Upload en cours...' : 'Uploader un fichier .jar', _jsx("input", { type: "file", accept: ".jar", onChange: handleJarUpload, disabled: jarUploading, style: { display: 'none' } })] }), _jsx("span", { style: { fontSize: 12, color: '#9ca3af' }, children: "Formats acceptes : hsqldb*.jar, ojdbc*.jar, db2jcc*.jar, ngdbc*.jar, jconn*.jar" })] })] }), _jsxs("div", { style: S.section, children: [_jsxs("div", { style: S.sectionTitle, children: [_jsx("span", { children: "\uD83D\uDDC4\uFE0F" }), " Base de donnees", currentDialect && (_jsxs("span", { style: S.currentBadge, children: ["Actuelle : ", DIALECTS.find((d) => d.key === currentDialect)?.name || currentDialect] }))] }), _jsx("div", { style: S.sectionDesc, children: "Changez le dialecte ou les parametres de connexion. La connexion sera testee avant application." }), dbMessage && (_jsx("div", { style: S.alert(dbMessage.type), children: dbMessage.text })), _jsxs("div", { style: { marginBottom: 20 }, children: [_jsx("div", { style: { ...S.label, marginBottom: 8, fontSize: 13 }, children: "Dialecte" }), _jsx("div", { style: S.dialectGrid, children: DIALECTS.map((d) => (_jsxs("div", { style: {
|
|
419
|
+
...S.dialectCard(selectedDialect === d.key && !d.premium),
|
|
420
|
+
...(d.premium ? { opacity: 0.45, cursor: 'not-allowed', filter: 'grayscale(0.5)' } : {}),
|
|
421
|
+
}, onClick: () => !d.premium && handleDialectChange(d.key), title: d.premium ? `${d.name} — disponible en version Premium` : d.name, children: [_jsx("div", { style: S.dialectIcon, children: d.icon }), _jsxs("div", { style: S.dialectName, children: [d.name, d.key === currentDialect && _jsx("span", { style: { fontSize: 9, color: '#059669' }, children: " (actuel)" }), d.premium && (_jsx("div", { style: {
|
|
422
|
+
fontSize: 9,
|
|
423
|
+
fontWeight: 700,
|
|
424
|
+
color: '#b45309',
|
|
425
|
+
backgroundColor: '#fef3c7',
|
|
426
|
+
padding: '1px 5px',
|
|
427
|
+
borderRadius: 4,
|
|
428
|
+
marginTop: 3,
|
|
429
|
+
display: 'inline-block',
|
|
430
|
+
}, children: "Premium" }))] })] }, d.key))) })] }), !isSqlite && (_jsxs("div", { style: { maxWidth: 500 }, children: [_jsxs("div", { style: S.formRow, children: [_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: "Hote" }), _jsx("input", { style: S.input, value: dbForm.host, onChange: (e) => setDbForm({ ...dbForm, host: e.target.value }), placeholder: "localhost" })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: "Port" }), _jsx("input", { style: S.input, type: "number", value: dbForm.port, onChange: (e) => setDbForm({ ...dbForm, port: Number(e.target.value) }) })] })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: "Nom de la base" }), _jsx("input", { style: S.input, value: dbForm.name, onChange: (e) => setDbForm({ ...dbForm, name: e.target.value }), placeholder: "ma_base_de_donnees" })] }), dialectInfo?.requiresAuth && (_jsxs("div", { style: S.formRow, children: [_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: "Utilisateur" }), _jsx("input", { style: S.input, value: dbForm.user, onChange: (e) => setDbForm({ ...dbForm, user: e.target.value }) })] }), _jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: "Mot de passe" }), _jsx("input", { style: S.input, type: "password", value: dbForm.password, onChange: (e) => setDbForm({ ...dbForm, password: e.target.value }) })] })] }))] })), isSqlite && (_jsxs("div", { style: S.formGroup, children: [_jsx("label", { style: S.label, children: "Nom du fichier (sans extension)" }), _jsx("input", { style: { ...S.input, maxWidth: 300 }, value: dbForm.name, onChange: (e) => setDbForm({ ...dbForm, name: e.target.value }), placeholder: "ma_base" }), _jsxs("div", { style: { fontSize: 11, color: '#9ca3af', marginTop: 4 }, children: ["Le fichier sera cree dans ./data/", dbForm.name || 'ma_base', ".db"] })] })), dbTestResult && (_jsx("div", { style: S.alert(dbTestResult.ok ? 'success' : 'error'), children: dbTestResult.ok ? 'Connexion reussie !' : `Echec : ${dbTestResult.error}` })), showSeedOption && onSeedRequested && (selectedDialect !== currentDialect || dbForm.name) && (_jsx("div", { style: { marginBottom: 12, padding: 12, backgroundColor: '#fffbeb', border: '1px solid #fde68a', borderRadius: 8 }, children: _jsxs("label", { style: S.checkboxLabel, children: [_jsx("input", { type: "checkbox", checked: wantSeed, onChange: (e) => setWantSeed(e.target.checked), style: S.checkbox }), _jsxs("div", { children: [_jsx("div", { style: { fontWeight: 600, fontSize: 13 }, children: "Initialiser la nouvelle base (seed)" }), _jsx("div", { style: { fontSize: 12, color: '#92400e' }, children: "Cree les tables/collections, permissions, roles et categories dans la nouvelle base. Recommande si vous changez vers une base vide." })] })] }) })), _jsxs("div", { style: { display: 'flex', gap: 8, marginTop: 16 }, children: [_jsx("button", { style: S.btn('secondary'), onClick: handleTestDb, disabled: dbTesting || (!isSqlite && !dbForm.name), children: dbTesting ? 'Test en cours...' : 'Tester la connexion' }), _jsx("button", { style: S.btn('primary'), onClick: handleApplyDb, disabled: dbSaving || seeding || (!isSqlite && !dbForm.name) || (dbTestResult !== null && !dbTestResult.ok), children: seeding ? 'Seed en cours...' : dbSaving ? 'Application...' : 'Appliquer' })] })] })] }));
|
|
327
431
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export { createStatusHandler } from './api/status.route';
|
|
|
11
11
|
export { createDetectModulesHandler } from './api/detect-modules.route';
|
|
12
12
|
export { createInstallModulesHandler } from './api/install-modules.route';
|
|
13
13
|
export { createReconfigHandlers } from './api/reconfig.route';
|
|
14
|
+
export { createUploadJarHandlers } from './api/upload-jar.route';
|
|
14
15
|
export { default as ReconfigPanel } from './components/ReconfigPanel';
|
|
15
16
|
export { setupMenuContribution } from './lib/menu';
|
|
16
17
|
export type { DialectType, DialectInfo, DbConfig, InstallConfig, SeedOptions, SeedDefinition, MostaSetupConfig, ModuleDefinition, } from './types/index';
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export { createStatusHandler } from './api/status.route';
|
|
|
17
17
|
export { createDetectModulesHandler } from './api/detect-modules.route';
|
|
18
18
|
export { createInstallModulesHandler } from './api/install-modules.route';
|
|
19
19
|
export { createReconfigHandlers } from './api/reconfig.route';
|
|
20
|
+
export { createUploadJarHandlers } from './api/upload-jar.route';
|
|
20
21
|
// Components
|
|
21
22
|
export { default as ReconfigPanel } from './components/ReconfigPanel';
|
|
22
23
|
// Menu contribution
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/setup",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Reusable setup wizard module — multi-dialect DB configuration, .env.local writer, seed runner",
|
|
5
5
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,6 +47,11 @@
|
|
|
47
47
|
"types": "./dist/api/reconfig.route.d.ts",
|
|
48
48
|
"import": "./dist/api/reconfig.route.js",
|
|
49
49
|
"default": "./dist/api/reconfig.route.js"
|
|
50
|
+
},
|
|
51
|
+
"./api/upload-jar": {
|
|
52
|
+
"types": "./dist/api/upload-jar.route.d.ts",
|
|
53
|
+
"import": "./dist/api/upload-jar.route.js",
|
|
54
|
+
"default": "./dist/api/upload-jar.route.js"
|
|
50
55
|
}
|
|
51
56
|
},
|
|
52
57
|
"files": [
|
|
@@ -76,7 +81,7 @@
|
|
|
76
81
|
"prepublishOnly": "npm run build"
|
|
77
82
|
},
|
|
78
83
|
"dependencies": {
|
|
79
|
-
"@mostajs/orm": "^1.
|
|
84
|
+
"@mostajs/orm": "^1.3.0",
|
|
80
85
|
"bcryptjs": "^2.4.3"
|
|
81
86
|
},
|
|
82
87
|
"devDependencies": {
|