@mostajs/setup 1.4.10 → 1.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/wire-module.route.d.ts +11 -0
- package/dist/api/wire-module.route.js +126 -0
- package/dist/components/ReconfigPanel.d.ts +3 -1
- package/dist/components/ReconfigPanel.js +98 -2
- package/dist/components/SetupWizard.d.ts +1 -0
- package/dist/components/SetupWizard.js +106 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +11 -1
- package/setup.wire.json +11 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory for POST /api/setup/wire-module
|
|
3
|
+
* Calls @mostajs/socle installModule() or uninstallModule()
|
|
4
|
+
*
|
|
5
|
+
* Body: { action: 'install' | 'uninstall', module: string }
|
|
6
|
+
* Response: { data: { ok: boolean, module: string, steps: [...] } }
|
|
7
|
+
*/
|
|
8
|
+
export declare function createWireModuleHandler(): {
|
|
9
|
+
GET: () => Promise<Response>;
|
|
10
|
+
POST: (req: Request) => Promise<Response>;
|
|
11
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// @mostajs/setup — Wire module API route factory
|
|
2
|
+
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
3
|
+
/**
|
|
4
|
+
* Factory for POST /api/setup/wire-module
|
|
5
|
+
* Calls @mostajs/socle installModule() or uninstallModule()
|
|
6
|
+
*
|
|
7
|
+
* Body: { action: 'install' | 'uninstall', module: string }
|
|
8
|
+
* Response: { data: { ok: boolean, module: string, steps: [...] } }
|
|
9
|
+
*/
|
|
10
|
+
export function createWireModuleHandler() {
|
|
11
|
+
async function POST(req) {
|
|
12
|
+
let body;
|
|
13
|
+
try {
|
|
14
|
+
body = await req.json();
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return Response.json({ error: { code: 'VALIDATION_ERROR', message: 'JSON invalide' } }, { status: 400 });
|
|
18
|
+
}
|
|
19
|
+
const { action, module: moduleName } = body;
|
|
20
|
+
if (!action || !moduleName) {
|
|
21
|
+
return Response.json({ error: { code: 'VALIDATION_ERROR', message: 'action et module requis' } }, { status: 400 });
|
|
22
|
+
}
|
|
23
|
+
if (!['install', 'uninstall'].includes(action)) {
|
|
24
|
+
return Response.json({ error: { code: 'VALIDATION_ERROR', message: "action doit etre 'install' ou 'uninstall'" } }, { status: 400 });
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
// Dynamic import to avoid hard dependency on @mostajs/socle
|
|
28
|
+
// Dynamic import — string indirection to avoid TS static resolution
|
|
29
|
+
const pkg = '@mostajs' + '/socle';
|
|
30
|
+
const socle = await import(/* webpackIgnore: true */ pkg);
|
|
31
|
+
const logs = [];
|
|
32
|
+
const opts = {
|
|
33
|
+
projectRoot: process.cwd(),
|
|
34
|
+
log: (msg) => logs.push(msg),
|
|
35
|
+
};
|
|
36
|
+
const result = action === 'install'
|
|
37
|
+
? socle.installModule(moduleName, opts)
|
|
38
|
+
: socle.uninstallModule(moduleName, opts);
|
|
39
|
+
return Response.json({
|
|
40
|
+
data: {
|
|
41
|
+
ok: result.success,
|
|
42
|
+
action,
|
|
43
|
+
module: moduleName,
|
|
44
|
+
steps: result.steps,
|
|
45
|
+
logs,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
51
|
+
return Response.json({ error: { code: 'WIRE_ERROR', message } }, { status: 500 });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// GET — list available wire manifests
|
|
55
|
+
async function GET() {
|
|
56
|
+
try {
|
|
57
|
+
const fs = await import('fs');
|
|
58
|
+
const path = await import('path');
|
|
59
|
+
const root = process.cwd();
|
|
60
|
+
const found = [];
|
|
61
|
+
// Check modules/ directory (host overrides)
|
|
62
|
+
const modulesDir = path.join(root, 'modules');
|
|
63
|
+
if (fs.existsSync(modulesDir)) {
|
|
64
|
+
for (const f of fs.readdirSync(modulesDir).filter((f) => f.endsWith('.wire.json'))) {
|
|
65
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(modulesDir, f), 'utf8'));
|
|
66
|
+
const name = f.replace('.wire.json', '');
|
|
67
|
+
// Check if already wired (has the package in package.json deps or schemas wired)
|
|
68
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
69
|
+
const installed = !!pkg.dependencies?.[manifest.package];
|
|
70
|
+
found.push({
|
|
71
|
+
name,
|
|
72
|
+
source: 'modules/',
|
|
73
|
+
package: manifest.package,
|
|
74
|
+
version: manifest.version,
|
|
75
|
+
type: manifest.type || 'functional',
|
|
76
|
+
installed,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Check node_modules/@mostajs/*/<name>.wire.json
|
|
81
|
+
const mostaDir = path.join(root, 'node_modules', '@mostajs');
|
|
82
|
+
if (fs.existsSync(mostaDir)) {
|
|
83
|
+
for (const dir of fs.readdirSync(mostaDir)) {
|
|
84
|
+
if (found.some(f => f.name === dir))
|
|
85
|
+
continue;
|
|
86
|
+
const wireFile = path.join(mostaDir, dir, `${dir}.wire.json`);
|
|
87
|
+
if (fs.existsSync(wireFile)) {
|
|
88
|
+
const manifest = JSON.parse(fs.readFileSync(wireFile, 'utf8'));
|
|
89
|
+
// Check if already wired by looking at schemas or permissions in host files
|
|
90
|
+
const permFile = path.join(root, 'src/lib/permissions.ts');
|
|
91
|
+
let installed = false;
|
|
92
|
+
if (manifest.permissions?.permissionsConst && fs.existsSync(permFile)) {
|
|
93
|
+
installed = fs.readFileSync(permFile, 'utf8').includes(manifest.permissions.permissionsConst);
|
|
94
|
+
}
|
|
95
|
+
else if (manifest.schemas?.exports?.[0]) {
|
|
96
|
+
const regFile = path.join(root, 'src/dal/registry.ts');
|
|
97
|
+
if (fs.existsSync(regFile)) {
|
|
98
|
+
installed = fs.readFileSync(regFile, 'utf8').includes(manifest.schemas.exports[0]);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (manifest.menu?.name) {
|
|
102
|
+
const sidebarFile = path.join(root, 'src/components/layout/Sidebar.tsx');
|
|
103
|
+
if (fs.existsSync(sidebarFile)) {
|
|
104
|
+
installed = fs.readFileSync(sidebarFile, 'utf8').includes(manifest.menu.name);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
found.push({
|
|
108
|
+
name: dir,
|
|
109
|
+
source: `@mostajs/${dir}/`,
|
|
110
|
+
package: manifest.package,
|
|
111
|
+
version: manifest.version,
|
|
112
|
+
type: manifest.type || 'functional',
|
|
113
|
+
installed,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return Response.json({ data: found });
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
122
|
+
return Response.json({ error: { code: 'LIST_ERROR', message } }, { status: 500 });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return { GET, POST };
|
|
126
|
+
}
|
|
@@ -5,6 +5,8 @@ export interface ReconfigPanelProps {
|
|
|
5
5
|
detectEndpoint?: string;
|
|
6
6
|
/** API endpoint for JAR upload (default: '/api/setup/upload-jar') */
|
|
7
7
|
jarEndpoint?: string;
|
|
8
|
+
/** API endpoint for wire module install/uninstall (default: '/api/setup/wire-module') */
|
|
9
|
+
wireEndpoint?: string;
|
|
8
10
|
/** Translate function */
|
|
9
11
|
t?: (key: string) => string;
|
|
10
12
|
/** Called after successful DB change */
|
|
@@ -16,4 +18,4 @@ export interface ReconfigPanelProps {
|
|
|
16
18
|
/** Callback to run seed after DB change */
|
|
17
19
|
onSeedRequested?: () => Promise<void>;
|
|
18
20
|
}
|
|
19
|
-
export default function ReconfigPanel({ apiEndpoint, detectEndpoint, jarEndpoint, t, onDbChanged, onModulesChanged, showSeedOption, onSeedRequested, }: ReconfigPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export default function ReconfigPanel({ apiEndpoint, detectEndpoint, jarEndpoint, wireEndpoint, t, onDbChanged, onModulesChanged, showSeedOption, onSeedRequested, }: ReconfigPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -98,6 +98,38 @@ const S = {
|
|
|
98
98
|
}),
|
|
99
99
|
checkbox: { marginRight: 8, width: 16, height: 16, cursor: 'pointer' },
|
|
100
100
|
checkboxLabel: { display: 'flex', alignItems: 'center', fontSize: 13, cursor: 'pointer', padding: '8px 0' },
|
|
101
|
+
toggleBtn: (installed, busy) => ({
|
|
102
|
+
padding: '6px 16px',
|
|
103
|
+
border: 'none',
|
|
104
|
+
borderRadius: 6,
|
|
105
|
+
fontSize: 12,
|
|
106
|
+
fontWeight: 700,
|
|
107
|
+
cursor: busy ? 'wait' : 'pointer',
|
|
108
|
+
opacity: busy ? 0.6 : 1,
|
|
109
|
+
backgroundColor: installed ? '#dc2626' : '#059669',
|
|
110
|
+
color: '#fff',
|
|
111
|
+
transition: 'all 0.2s',
|
|
112
|
+
minWidth: 90,
|
|
113
|
+
}),
|
|
114
|
+
wireCard: (installed) => ({
|
|
115
|
+
padding: 16,
|
|
116
|
+
border: `2px solid ${installed ? '#059669' : '#e5e7eb'}`,
|
|
117
|
+
borderRadius: 10,
|
|
118
|
+
backgroundColor: installed ? '#f0fdf4' : '#fafafa',
|
|
119
|
+
transition: 'all 0.2s',
|
|
120
|
+
display: 'flex',
|
|
121
|
+
flexDirection: 'column',
|
|
122
|
+
gap: 8,
|
|
123
|
+
}),
|
|
124
|
+
wireStatus: (installed) => ({
|
|
125
|
+
display: 'inline-block',
|
|
126
|
+
width: 10,
|
|
127
|
+
height: 10,
|
|
128
|
+
borderRadius: '50%',
|
|
129
|
+
backgroundColor: installed ? '#22c55e' : '#ef4444',
|
|
130
|
+
marginRight: 6,
|
|
131
|
+
flexShrink: 0,
|
|
132
|
+
}),
|
|
101
133
|
currentBadge: {
|
|
102
134
|
display: 'inline-block',
|
|
103
135
|
padding: '2px 8px',
|
|
@@ -110,7 +142,7 @@ const S = {
|
|
|
110
142
|
},
|
|
111
143
|
};
|
|
112
144
|
// ── Component ────────────────────────────────────────────────
|
|
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, }) {
|
|
145
|
+
export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', detectEndpoint = '/api/setup/detect-modules', jarEndpoint = '/api/setup/upload-jar', wireEndpoint = '/api/setup/wire-module', t = (k) => k, onDbChanged, onModulesChanged, showSeedOption = true, onSeedRequested, }) {
|
|
114
146
|
// --- State ---
|
|
115
147
|
const [loading, setLoading] = useState(true);
|
|
116
148
|
const [currentDialect, setCurrentDialect] = useState('');
|
|
@@ -140,6 +172,10 @@ export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', det
|
|
|
140
172
|
// Module saving
|
|
141
173
|
const [moduleSaving, setModuleSaving] = useState(false);
|
|
142
174
|
const [moduleMessage, setModuleMessage] = useState(null);
|
|
175
|
+
const [wireModules, setWireModules] = useState([]);
|
|
176
|
+
const [wireLoading, setWireLoading] = useState(true);
|
|
177
|
+
const [wireBusy, setWireBusy] = useState(null);
|
|
178
|
+
const [wireMessage, setWireMessage] = useState(null);
|
|
143
179
|
// --- Load current config ---
|
|
144
180
|
const loadConfig = useCallback(async () => {
|
|
145
181
|
setLoading(true);
|
|
@@ -197,6 +233,57 @@ export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', det
|
|
|
197
233
|
}
|
|
198
234
|
}, [apiEndpoint, detectEndpoint, jarEndpoint]);
|
|
199
235
|
useEffect(() => { loadConfig(); }, [loadConfig]);
|
|
236
|
+
// --- Load wire modules ---
|
|
237
|
+
const loadWireModules = useCallback(async () => {
|
|
238
|
+
setWireLoading(true);
|
|
239
|
+
try {
|
|
240
|
+
const res = await fetch(wireEndpoint);
|
|
241
|
+
const data = await res.json();
|
|
242
|
+
if (data.data)
|
|
243
|
+
setWireModules(data.data);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// wire endpoint may not exist
|
|
247
|
+
}
|
|
248
|
+
finally {
|
|
249
|
+
setWireLoading(false);
|
|
250
|
+
}
|
|
251
|
+
}, [wireEndpoint]);
|
|
252
|
+
useEffect(() => { loadWireModules(); }, [loadWireModules]);
|
|
253
|
+
// --- Toggle wire module install/uninstall ---
|
|
254
|
+
const handleWireToggle = async (mod) => {
|
|
255
|
+
const action = mod.installed ? 'uninstall' : 'install';
|
|
256
|
+
setWireBusy(mod.name);
|
|
257
|
+
setWireMessage(null);
|
|
258
|
+
try {
|
|
259
|
+
const res = await fetch(wireEndpoint, {
|
|
260
|
+
method: 'POST',
|
|
261
|
+
headers: { 'Content-Type': 'application/json' },
|
|
262
|
+
body: JSON.stringify({ action, module: mod.name }),
|
|
263
|
+
});
|
|
264
|
+
const data = await res.json();
|
|
265
|
+
if (data.data?.ok) {
|
|
266
|
+
setWireMessage({
|
|
267
|
+
type: 'success',
|
|
268
|
+
text: action === 'install'
|
|
269
|
+
? `${mod.package} cable avec succes`
|
|
270
|
+
: `${mod.package} decable avec succes`,
|
|
271
|
+
module: mod.name,
|
|
272
|
+
});
|
|
273
|
+
await loadWireModules();
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
const errMsg = data.error?.message || data.data?.steps?.find((s) => s.status === 'error')?.detail || 'Erreur';
|
|
277
|
+
setWireMessage({ type: 'error', text: `${action} ${mod.package}: ${errMsg}`, module: mod.name });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
setWireMessage({ type: 'error', text: 'Erreur reseau', module: mod.name });
|
|
282
|
+
}
|
|
283
|
+
finally {
|
|
284
|
+
setWireBusy(null);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
200
287
|
// --- JAR upload ---
|
|
201
288
|
const handleJarUpload = async (e) => {
|
|
202
289
|
const file = e.target.files?.[0];
|
|
@@ -413,7 +500,16 @@ export default function ReconfigPanel({ apiEndpoint = '/api/setup/reconfig', det
|
|
|
413
500
|
}
|
|
414
501
|
const dialectInfo = DIALECTS.find((d) => d.key === selectedDialect);
|
|
415
502
|
const isSqlite = selectedDialect === 'sqlite';
|
|
416
|
-
return (_jsxs("div", { style: S.panel, children: [_jsxs("div", { style: S.section, children: [_jsxs("div", { style: S.sectionTitle, children: [_jsx("span", { children: "\uD83D\
|
|
503
|
+
return (_jsxs("div", { style: S.panel, children: [_jsxs("div", { style: S.section, children: [_jsxs("div", { style: S.sectionTitle, children: [_jsx("span", { children: "\uD83D\uDD0C" }), " Cablage des modules"] }), _jsx("div", { style: S.sectionDesc, children: "Installez ou desinstallez les modules @mostajs. Un module cable injecte ses schemas, routes API, pages, permissions et menus dans l'application hote. Les modules business (schemas + repos) sont marques." }), wireMessage && (_jsx("div", { style: S.alert(wireMessage.type), children: wireMessage.text })), wireLoading ? (_jsx("div", { style: { textAlign: 'center', padding: 20, color: '#6b7280' }, children: "Chargement des manifestes..." })) : wireModules.length === 0 ? (_jsx("div", { style: { textAlign: 'center', padding: 20, color: '#9ca3af' }, children: "Aucun manifeste de cablage trouve" })) : (_jsx("div", { style: S.grid, children: wireModules.map((mod) => (_jsxs("div", { style: S.wireCard(mod.installed), children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("span", { style: S.wireStatus(mod.installed) }), _jsxs("span", { style: { fontWeight: 700, fontSize: 14 }, children: ["@mostajs/", mod.name] })] }), _jsx("span", { style: {
|
|
504
|
+
fontSize: 10,
|
|
505
|
+
fontWeight: 600,
|
|
506
|
+
padding: '2px 6px',
|
|
507
|
+
borderRadius: 4,
|
|
508
|
+
backgroundColor: mod.type === 'business' ? '#dbeafe' : '#f3e8ff',
|
|
509
|
+
color: mod.type === 'business' ? '#1e40af' : '#6b21a8',
|
|
510
|
+
}, children: mod.type })] }), _jsxs("div", { style: { fontSize: 12, color: '#6b7280', fontFamily: 'monospace' }, children: ["v", mod.version, " \u2014 ", mod.source] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 4 }, children: [_jsx("span", { style: { fontSize: 12, fontWeight: 600, color: mod.installed ? '#059669' : '#6b7280' }, children: mod.installed ? 'Cable' : 'Non cable' }), _jsx("button", { style: S.toggleBtn(mod.installed, wireBusy === mod.name), onClick: () => handleWireToggle(mod), disabled: wireBusy !== null, children: wireBusy === mod.name
|
|
511
|
+
? (mod.installed ? 'Decablage...' : 'Cablage...')
|
|
512
|
+
: (mod.installed ? 'Desinstaller' : 'Installer') })] })] }, mod.name))) }))] }), _jsxs("div", { style: S.section, children: [_jsxs("div", { style: S.sectionTitle, children: [_jsx("span", { children: "\uD83D\uDCE6" }), " Modules actifs"] }), _jsx("div", { style: S.sectionDesc, children: "Activez ou desactivez les modules @mostajs. Les modules requis ne peuvent pas etre desactives. Seuls les modules installes (dans node_modules) peuvent etre actives." }), moduleMessage && (_jsx("div", { style: S.alert(moduleMessage.type), children: moduleMessage.text })), _jsx("div", { style: S.grid, children: allModules.map((mod) => {
|
|
417
513
|
const isInstalled = installedModules.includes(mod.key);
|
|
418
514
|
const isActive = activeModules.has(mod.key);
|
|
419
515
|
const isRequired = !!mod.required;
|
|
@@ -167,6 +167,40 @@ const S = {
|
|
|
167
167
|
flex: (gap = 8) => ({ display: 'flex', alignItems: 'center', gap }),
|
|
168
168
|
flexBetween: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' },
|
|
169
169
|
flexWrap: { display: 'flex', flexWrap: 'wrap', gap: 8 },
|
|
170
|
+
// Wire module styles
|
|
171
|
+
wireGrid: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 12, marginTop: 16 },
|
|
172
|
+
wireCard: (installed) => ({
|
|
173
|
+
padding: 16,
|
|
174
|
+
border: `2px solid ${installed ? '#059669' : '#e5e7eb'}`,
|
|
175
|
+
borderRadius: 10,
|
|
176
|
+
backgroundColor: installed ? '#f0fdf4' : '#fafafa',
|
|
177
|
+
transition: 'all 0.2s',
|
|
178
|
+
display: 'flex',
|
|
179
|
+
flexDirection: 'column',
|
|
180
|
+
gap: 8,
|
|
181
|
+
}),
|
|
182
|
+
wireStatus: (installed) => ({
|
|
183
|
+
display: 'inline-block',
|
|
184
|
+
width: 10,
|
|
185
|
+
height: 10,
|
|
186
|
+
borderRadius: '50%',
|
|
187
|
+
backgroundColor: installed ? '#22c55e' : '#ef4444',
|
|
188
|
+
marginRight: 6,
|
|
189
|
+
flexShrink: 0,
|
|
190
|
+
}),
|
|
191
|
+
toggleBtn: (installed, busy) => ({
|
|
192
|
+
padding: '6px 16px',
|
|
193
|
+
border: 'none',
|
|
194
|
+
borderRadius: 6,
|
|
195
|
+
fontSize: 12,
|
|
196
|
+
fontWeight: 700,
|
|
197
|
+
cursor: busy ? 'wait' : 'pointer',
|
|
198
|
+
opacity: busy ? 0.6 : 1,
|
|
199
|
+
backgroundColor: installed ? '#dc2626' : '#059669',
|
|
200
|
+
color: '#fff',
|
|
201
|
+
transition: 'all 0.2s',
|
|
202
|
+
minWidth: 90,
|
|
203
|
+
}),
|
|
170
204
|
};
|
|
171
205
|
// ── Helpers ──────────────────────────────────────────────────
|
|
172
206
|
function resolveModuleDeps(selected, all) {
|
|
@@ -318,6 +352,7 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
318
352
|
installModules: endpoints.installModules || '/api/setup/install-modules',
|
|
319
353
|
install: endpoints.install || '/api/setup/install',
|
|
320
354
|
uploadJar: endpoints.uploadJar || '/api/setup/upload-jar',
|
|
355
|
+
wireModule: endpoints.wireModule || '/api/setup/wire-module',
|
|
321
356
|
};
|
|
322
357
|
// --- State ---
|
|
323
358
|
const [currentStep, setCurrentStep] = useState(0);
|
|
@@ -335,6 +370,10 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
335
370
|
const [installing, setInstalling] = useState(false);
|
|
336
371
|
const [installResult, setInstallResult] = useState(null);
|
|
337
372
|
const [hydrated, setHydrated] = useState(false);
|
|
373
|
+
const [wireModules, setWireModules] = useState([]);
|
|
374
|
+
const [wireLoading, setWireLoading] = useState(false);
|
|
375
|
+
const [wireBusy, setWireBusy] = useState(null);
|
|
376
|
+
const [wireMessage, setWireMessage] = useState(null);
|
|
338
377
|
const step = STEPS[currentStep];
|
|
339
378
|
// --- Persist / Restore ---
|
|
340
379
|
useEffect(() => {
|
|
@@ -420,6 +459,59 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
420
459
|
}
|
|
421
460
|
});
|
|
422
461
|
}, [availableModules]);
|
|
462
|
+
// --- Wire modules (load after installation success) ---
|
|
463
|
+
const loadWireModules = useCallback(async () => {
|
|
464
|
+
setWireLoading(true);
|
|
465
|
+
try {
|
|
466
|
+
const res = await fetch(ep.wireModule);
|
|
467
|
+
const data = await res.json();
|
|
468
|
+
if (data.data)
|
|
469
|
+
setWireModules(data.data);
|
|
470
|
+
}
|
|
471
|
+
catch {
|
|
472
|
+
// wire endpoint may not exist
|
|
473
|
+
}
|
|
474
|
+
finally {
|
|
475
|
+
setWireLoading(false);
|
|
476
|
+
}
|
|
477
|
+
}, [ep.wireModule]);
|
|
478
|
+
// Auto-load wire modules on modules step and after install
|
|
479
|
+
useEffect(() => {
|
|
480
|
+
if (step === 'modules' || installResult?.ok)
|
|
481
|
+
loadWireModules();
|
|
482
|
+
}, [step, installResult?.ok, loadWireModules]);
|
|
483
|
+
const handleWireToggle = async (mod) => {
|
|
484
|
+
const action = mod.installed ? 'uninstall' : 'install';
|
|
485
|
+
setWireBusy(mod.name);
|
|
486
|
+
setWireMessage(null);
|
|
487
|
+
try {
|
|
488
|
+
const res = await fetch(ep.wireModule, {
|
|
489
|
+
method: 'POST',
|
|
490
|
+
headers: { 'Content-Type': 'application/json' },
|
|
491
|
+
body: JSON.stringify({ action, module: mod.name }),
|
|
492
|
+
});
|
|
493
|
+
const data = await res.json();
|
|
494
|
+
if (data.data?.ok) {
|
|
495
|
+
setWireMessage({
|
|
496
|
+
type: 'success',
|
|
497
|
+
text: action === 'install'
|
|
498
|
+
? `${mod.package} cable avec succes`
|
|
499
|
+
: `${mod.package} decable avec succes`,
|
|
500
|
+
});
|
|
501
|
+
await loadWireModules();
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
const errMsg = data.error?.message || 'Erreur';
|
|
505
|
+
setWireMessage({ type: 'error', text: `${action} ${mod.package}: ${errMsg}` });
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
catch {
|
|
509
|
+
setWireMessage({ type: 'error', text: 'Erreur reseau' });
|
|
510
|
+
}
|
|
511
|
+
finally {
|
|
512
|
+
setWireBusy(null);
|
|
513
|
+
}
|
|
514
|
+
};
|
|
423
515
|
// --- Dialect select ---
|
|
424
516
|
function selectDialect(d) {
|
|
425
517
|
setDialect(d);
|
|
@@ -534,7 +626,13 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
534
626
|
const isSelected = selectedModules.includes(mod.key);
|
|
535
627
|
const isDetected = detectedModules.includes(mod.key);
|
|
536
628
|
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));
|
|
537
|
-
}) }), _jsxs("div", { style:
|
|
629
|
+
}) }), _jsxs("div", { style: { marginTop: 28, paddingTop: 20, borderTop: '1px solid #e5e7eb' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }, children: [_jsx("span", { style: { fontSize: 18 }, children: "\uD83D\uDD0C" }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 16, fontWeight: 700, color: '#111827' }, children: "Cablage des modules" }), _jsx("div", { style: { fontSize: 12, color: '#6b7280' }, children: "Cablez les modules pour injecter schemas, routes API, pages et permissions." })] })] }), wireMessage && (_jsx("div", { style: S.alert(wireMessage.type), children: wireMessage.text })), wireLoading ? (_jsx("div", { style: { textAlign: 'center', padding: 12, color: '#6b7280' }, children: "Chargement des manifestes..." })) : wireModules.length === 0 ? (_jsx("div", { style: { textAlign: 'center', padding: 12, color: '#9ca3af', fontSize: 13 }, children: "Aucun manifeste de cablage trouve. Les manifestes seront disponibles apres l'installation." })) : (_jsx("div", { style: S.wireGrid, children: wireModules.map((mod) => (_jsxs("div", { style: S.wireCard(mod.installed), children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("span", { style: S.wireStatus(mod.installed) }), _jsxs("span", { style: { fontWeight: 700, fontSize: 14 }, children: ["@mostajs/", mod.name] })] }), _jsx("span", { style: {
|
|
630
|
+
fontSize: 10, fontWeight: 600, padding: '2px 6px', borderRadius: 4,
|
|
631
|
+
backgroundColor: mod.type === 'business' ? '#dbeafe' : '#f3e8ff',
|
|
632
|
+
color: mod.type === 'business' ? '#1e40af' : '#6b21a8',
|
|
633
|
+
}, children: mod.type })] }), _jsxs("div", { style: { fontSize: 12, color: '#6b7280', fontFamily: 'monospace' }, children: ["v", mod.version] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 4 }, children: [_jsx("span", { style: { fontSize: 12, fontWeight: 600, color: mod.installed ? '#059669' : '#6b7280' }, children: mod.installed ? 'ON' : 'OFF' }), _jsx("button", { style: S.toggleBtn(mod.installed, wireBusy === mod.name), onClick: (e) => { e.stopPropagation(); handleWireToggle(mod); }, disabled: wireBusy !== null, children: wireBusy === mod.name
|
|
634
|
+
? (mod.installed ? 'Decablage...' : 'Cablage...')
|
|
635
|
+
: (mod.installed ? 'Desinstaller' : 'Installer') })] })] }, mod.name))) }))] }), _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
|
|
538
636
|
? `✅ ${t('setup.database.success')}${dbTestResult.dbVersion ? ` (v${dbTestResult.dbVersion})` : ''}`
|
|
539
637
|
: `❌ ${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 => {
|
|
540
638
|
const mod = availableModules.find(m => m.key === key);
|
|
@@ -543,5 +641,11 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
543
641
|
fontSize: 12, backgroundColor: '#f0f9ff', color: '#0369a1',
|
|
544
642
|
border: '1px solid #bae6fd', borderRadius: 16, padding: '4px 10px',
|
|
545
643
|
}, children: [mod.icon, " ", mod.label] }, key)) : null;
|
|
546
|
-
}) })] }), _jsxs("div", { style: S.summaryCard, children: [_jsx("div", { style: S.summaryTitle, children: t('setup.summary.seedTitle') }), _jsx("p", { style: { ...S.summaryText, marginBottom: 12 }, children: t('setup.summary.seedInfo') }), _jsxs("div", { style: S.checkRow, children: [_jsx("input", { type: "checkbox", style: S.checkbox, checked: seedOptions.activities, onChange: e => setSeedOptions({ ...seedOptions, activities: e.target.checked, demoData: e.target.checked ? seedOptions.demoData : false }), disabled: installing || !!installResult?.ok }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: t('setup.summary.seedActivities') }), _jsx("div", { style: { fontSize: 12, color: '#9ca3af' }, children: t('setup.summary.seedActivitiesDesc') })] })] }), _jsxs("div", { style: S.checkRow, children: [_jsx("input", { type: "checkbox", style: S.checkbox, checked: seedOptions.demoUsers, onChange: e => setSeedOptions({ ...seedOptions, demoUsers: e.target.checked }), disabled: installing || !!installResult?.ok }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: t('setup.summary.seedDemoUsers') }), _jsx("div", { style: { fontSize: 12, color: '#9ca3af' }, children: t('setup.summary.seedDemoUsersDesc') })] })] }), _jsxs("div", { style: S.checkRow, children: [_jsx("input", { type: "checkbox", style: S.checkbox, checked: seedOptions.demoData, onChange: e => setSeedOptions({ ...seedOptions, demoData: e.target.checked, activities: e.target.checked ? true : seedOptions.activities }), disabled: installing || !!installResult?.ok }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: t('setup.summary.seedDemoData') }), _jsx("div", { style: { fontSize: 12, color: '#9ca3af' }, children: t('setup.summary.seedDemoDataDesc') })] })] })] }), installResult && (_jsx("div", { style: S.alert(installResult.ok ? 'success' : 'error'), children: installResult.ok ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: { fontWeight: 600, marginBottom: 4 }, children: ["\u2705 ", t('setup.summary.success')] }), _jsx("div", { children: t('setup.summary.successDesc') }), installResult.needsRestart && (_jsx("div", { style: { color: '#92400e', fontWeight: 500, marginTop: 8 }, children: t('setup.summary.needsRestart') }))] })) : (_jsxs("div", { children: ["\u274C ", installResult.error] })) })),
|
|
644
|
+
}) })] }), _jsxs("div", { style: S.summaryCard, children: [_jsx("div", { style: S.summaryTitle, children: t('setup.summary.seedTitle') }), _jsx("p", { style: { ...S.summaryText, marginBottom: 12 }, children: t('setup.summary.seedInfo') }), _jsxs("div", { style: S.checkRow, children: [_jsx("input", { type: "checkbox", style: S.checkbox, checked: seedOptions.activities, onChange: e => setSeedOptions({ ...seedOptions, activities: e.target.checked, demoData: e.target.checked ? seedOptions.demoData : false }), disabled: installing || !!installResult?.ok }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: t('setup.summary.seedActivities') }), _jsx("div", { style: { fontSize: 12, color: '#9ca3af' }, children: t('setup.summary.seedActivitiesDesc') })] })] }), _jsxs("div", { style: S.checkRow, children: [_jsx("input", { type: "checkbox", style: S.checkbox, checked: seedOptions.demoUsers, onChange: e => setSeedOptions({ ...seedOptions, demoUsers: e.target.checked }), disabled: installing || !!installResult?.ok }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: t('setup.summary.seedDemoUsers') }), _jsx("div", { style: { fontSize: 12, color: '#9ca3af' }, children: t('setup.summary.seedDemoUsersDesc') })] })] }), _jsxs("div", { style: S.checkRow, children: [_jsx("input", { type: "checkbox", style: S.checkbox, checked: seedOptions.demoData, onChange: e => setSeedOptions({ ...seedOptions, demoData: e.target.checked, activities: e.target.checked ? true : seedOptions.activities }), disabled: installing || !!installResult?.ok }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: t('setup.summary.seedDemoData') }), _jsx("div", { style: { fontSize: 12, color: '#9ca3af' }, children: t('setup.summary.seedDemoDataDesc') })] })] })] }), installResult && (_jsx("div", { style: S.alert(installResult.ok ? 'success' : 'error'), children: installResult.ok ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: { fontWeight: 600, marginBottom: 4 }, children: ["\u2705 ", t('setup.summary.success')] }), _jsx("div", { children: t('setup.summary.successDesc') }), installResult.needsRestart && (_jsx("div", { style: { color: '#92400e', fontWeight: 500, marginTop: 8 }, children: t('setup.summary.needsRestart') }))] })) : (_jsxs("div", { children: ["\u274C ", installResult.error] })) })), installResult?.ok && (_jsxs("div", { style: { ...S.summaryCard, marginTop: 16 }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }, children: [_jsx("span", { style: { fontSize: 18 }, children: "\uD83D\uDD0C" }), _jsx("div", { style: S.summaryTitle, children: "Cablage des modules" })] }), _jsx("div", { style: { fontSize: 13, color: '#6b7280', marginBottom: 12 }, children: "Cablez les modules pour injecter schemas, routes API, pages et permissions dans l'application." }), wireMessage && (_jsx("div", { style: S.alert(wireMessage.type), children: wireMessage.text })), wireLoading ? (_jsx("div", { style: { textAlign: 'center', padding: 12, color: '#6b7280' }, children: "Chargement..." })) : wireModules.length === 0 ? (_jsx("div", { style: { textAlign: 'center', padding: 12, color: '#9ca3af' }, children: "Aucun manifeste de cablage trouve" })) : (_jsx("div", { style: S.wireGrid, children: wireModules.map((mod) => (_jsxs("div", { style: S.wireCard(mod.installed), children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("span", { style: S.wireStatus(mod.installed) }), _jsxs("span", { style: { fontWeight: 700, fontSize: 14 }, children: ["@mostajs/", mod.name] })] }), _jsx("span", { style: {
|
|
645
|
+
fontSize: 10, fontWeight: 600, padding: '2px 6px', borderRadius: 4,
|
|
646
|
+
backgroundColor: mod.type === 'business' ? '#dbeafe' : '#f3e8ff',
|
|
647
|
+
color: mod.type === 'business' ? '#1e40af' : '#6b21a8',
|
|
648
|
+
}, children: mod.type })] }), _jsxs("div", { style: { fontSize: 12, color: '#6b7280', fontFamily: 'monospace' }, children: ["v", mod.version, " \u2014 ", mod.source] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 4 }, children: [_jsx("span", { style: { fontSize: 12, fontWeight: 600, color: mod.installed ? '#059669' : '#6b7280' }, children: mod.installed ? 'Cable' : 'Non cable' }), _jsx("button", { style: S.toggleBtn(mod.installed, wireBusy === mod.name), onClick: () => handleWireToggle(mod), disabled: wireBusy !== null, children: wireBusy === mod.name
|
|
649
|
+
? (mod.installed ? 'Decablage...' : 'Cablage...')
|
|
650
|
+
: (mod.installed ? 'Desinstaller' : 'Installer') })] })] }, mod.name))) }))] })), _jsx("div", { style: S.navRow, children: !installResult?.ok ? (_jsxs(_Fragment, { children: [_jsxs("button", { style: S.btn('outline', installing), onClick: goBack, disabled: installing, children: ["\u2190 ", t('setup.back')] }), _jsxs("button", { style: S.btn('primary', installing), onClick: runInstallation, disabled: installing, children: [installing ? '⏳ ' : '⚙️ ', installing ? t('setup.summary.installing') : t('setup.summary.install')] })] })) : (_jsx("div", { style: { width: '100%', textAlign: 'center' }, children: _jsxs("button", { style: S.btn('lg'), onClick: handleComplete, children: [t('setup.summary.goToLogin'), " \u2192"] }) })) })] }))] })] }) }));
|
|
547
651
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ 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
14
|
export { createUploadJarHandlers } from './api/upload-jar.route';
|
|
15
|
+
export { createWireModuleHandler } from './api/wire-module.route';
|
|
15
16
|
export { default as ReconfigPanel } from './components/ReconfigPanel';
|
|
16
17
|
export { default as SetupWizard } from './components/SetupWizard';
|
|
17
18
|
export { setupMenuContribution } from './lib/menu';
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ 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
20
|
export { createUploadJarHandlers } from './api/upload-jar.route';
|
|
21
|
+
export { createWireModuleHandler } from './api/wire-module.route';
|
|
21
22
|
// Components
|
|
22
23
|
export { default as ReconfigPanel } from './components/ReconfigPanel';
|
|
23
24
|
export { default as SetupWizard } from './components/SetupWizard';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/setup",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.12",
|
|
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",
|
|
@@ -57,10 +57,16 @@
|
|
|
57
57
|
"types": "./dist/api/upload-jar.route.d.ts",
|
|
58
58
|
"import": "./dist/api/upload-jar.route.js",
|
|
59
59
|
"default": "./dist/api/upload-jar.route.js"
|
|
60
|
+
},
|
|
61
|
+
"./api/wire-module": {
|
|
62
|
+
"types": "./dist/api/wire-module.route.d.ts",
|
|
63
|
+
"import": "./dist/api/wire-module.route.js",
|
|
64
|
+
"default": "./dist/api/wire-module.route.js"
|
|
60
65
|
}
|
|
61
66
|
},
|
|
62
67
|
"files": [
|
|
63
68
|
"dist",
|
|
69
|
+
"setup.wire.json",
|
|
64
70
|
"LICENSE",
|
|
65
71
|
"README.md"
|
|
66
72
|
],
|
|
@@ -98,12 +104,16 @@
|
|
|
98
104
|
},
|
|
99
105
|
"peerDependencies": {
|
|
100
106
|
"@mostajs/menu": ">=1.0.2",
|
|
107
|
+
"@mostajs/socle": ">=1.0.0",
|
|
101
108
|
"react": ">=18.0.0"
|
|
102
109
|
},
|
|
103
110
|
"peerDependenciesMeta": {
|
|
104
111
|
"@mostajs/menu": {
|
|
105
112
|
"optional": true
|
|
106
113
|
},
|
|
114
|
+
"@mostajs/socle": {
|
|
115
|
+
"optional": true
|
|
116
|
+
},
|
|
107
117
|
"react": {
|
|
108
118
|
"optional": true
|
|
109
119
|
}
|