@mostajs/setup 2.1.1 → 2.1.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.
|
@@ -28,6 +28,13 @@ export function createSetupJsonHandler(needsSetup) {
|
|
|
28
28
|
dbNamePrefix: json.app?.dbNamePrefix,
|
|
29
29
|
hasRbac: !!(json.rbac?.roles?.length || json.rbac?.permissions?.length),
|
|
30
30
|
seedCount: json.seeds?.length ?? 0,
|
|
31
|
+
seeds: (json.seeds ?? []).map(s => ({
|
|
32
|
+
key: s.key,
|
|
33
|
+
label: s.label,
|
|
34
|
+
description: s.description ?? '',
|
|
35
|
+
icon: s.icon,
|
|
36
|
+
default: s.default ?? false,
|
|
37
|
+
})),
|
|
31
38
|
modules: json.modules ?? [],
|
|
32
39
|
},
|
|
33
40
|
});
|
|
@@ -17,6 +17,8 @@ export interface SetupWizardProps {
|
|
|
17
17
|
preflight?: string;
|
|
18
18
|
/** Create database endpoint */
|
|
19
19
|
createDb?: string;
|
|
20
|
+
/** Setup JSON endpoint (GET returns seeds list) */
|
|
21
|
+
setupJson?: string;
|
|
20
22
|
};
|
|
21
23
|
/** Default database name prefix (e.g. 'secuaccessdb') */
|
|
22
24
|
dbNamePrefix?: string;
|
|
@@ -361,6 +361,7 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
361
361
|
seed: endpoints.seed || '',
|
|
362
362
|
preflight: endpoints.preflight || '/api/setup/preflight',
|
|
363
363
|
createDb: endpoints.createDb || '/api/setup/create-db',
|
|
364
|
+
setupJson: endpoints.setupJson || '/api/setup/setup-json',
|
|
364
365
|
};
|
|
365
366
|
// --- State ---
|
|
366
367
|
const [currentStep, setCurrentStep] = useState(0);
|
|
@@ -369,7 +370,8 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
369
370
|
const [dbTestResult, setDbTestResult] = useState(null);
|
|
370
371
|
const [dbTesting, setDbTesting] = useState(false);
|
|
371
372
|
const [adminConfig, setAdminConfig] = useState({ firstName: '', lastName: '', email: '', password: '', confirmPassword: '' });
|
|
372
|
-
const [seedOptions, setSeedOptions] = useState({
|
|
373
|
+
const [seedOptions, setSeedOptions] = useState({});
|
|
374
|
+
const [availableSeeds, setAvailableSeeds] = useState([]);
|
|
373
375
|
const [availableModules, setAvailableModules] = useState([]);
|
|
374
376
|
const [selectedModules, setSelectedModules] = useState([]);
|
|
375
377
|
const [detectedModules, setDetectedModules] = useState([]);
|
|
@@ -423,6 +425,27 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
423
425
|
}
|
|
424
426
|
catch { }
|
|
425
427
|
}, [hydrated, persistState, currentStep, dialect, dbConfig, adminConfig, seedOptions, selectedModules]);
|
|
428
|
+
// --- Load seeds from setup.json ---
|
|
429
|
+
useEffect(() => {
|
|
430
|
+
if (!hydrated)
|
|
431
|
+
return;
|
|
432
|
+
fetch(ep.setupJson)
|
|
433
|
+
.then(r => r.json())
|
|
434
|
+
.then((data) => {
|
|
435
|
+
const seeds = data.config?.seeds ?? [];
|
|
436
|
+
setAvailableSeeds(seeds);
|
|
437
|
+
// Initialize seedOptions from defaults (only if not already restored from session)
|
|
438
|
+
setSeedOptions(prev => {
|
|
439
|
+
if (Object.keys(prev).length > 0)
|
|
440
|
+
return prev;
|
|
441
|
+
const defaults = {};
|
|
442
|
+
for (const s of seeds)
|
|
443
|
+
defaults[s.key] = s.default;
|
|
444
|
+
return defaults;
|
|
445
|
+
});
|
|
446
|
+
})
|
|
447
|
+
.catch(() => { });
|
|
448
|
+
}, [hydrated]);
|
|
426
449
|
// --- Detect modules ---
|
|
427
450
|
useEffect(() => {
|
|
428
451
|
const declaredKeys = new Set((declaredModules ?? []).map(m => m.key));
|
|
@@ -777,7 +800,7 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
777
800
|
fontSize: 12, backgroundColor: '#f0f9ff', color: '#0369a1',
|
|
778
801
|
border: '1px solid #bae6fd', borderRadius: 16, padding: '4px 10px',
|
|
779
802
|
}, children: [mod.icon, " ", mod.label] }, key)) : null;
|
|
780
|
-
}) })] }), _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') }),
|
|
803
|
+
}) })] }), availableSeeds.length > 0 && (_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') }), availableSeeds.map(seed => (_jsxs("div", { style: S.checkRow, children: [_jsx("input", { type: "checkbox", style: S.checkbox, checked: seedOptions[seed.key] ?? false, onChange: e => setSeedOptions({ ...seedOptions, [seed.key]: e.target.checked }), disabled: installing || !!installResult?.ok }), _jsxs("div", { children: [_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: seed.label }), _jsx("div", { style: { fontSize: 12, color: '#9ca3af' }, children: seed.description })] })] }, seed.key)))] })), 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: {
|
|
781
804
|
fontSize: 10, fontWeight: 600, padding: '2px 6px', borderRadius: 4,
|
|
782
805
|
backgroundColor: mod.type === 'business' ? '#dbeafe' : '#f3e8ff',
|
|
783
806
|
color: mod.type === 'business' ? '#1e40af' : '#6b21a8',
|
|
@@ -102,6 +102,22 @@ function buildConfig(json, repoFactory) {
|
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
|
+
// ── createAdmin (generic — uses repoFactory for 'user' + 'role') ──
|
|
106
|
+
config.createAdmin = async ({ email, hashedPassword, firstName, lastName }) => {
|
|
107
|
+
const getRepo = repoFactory ?? defaultRepoFactory;
|
|
108
|
+
const userRepo = await getRepo('user');
|
|
109
|
+
const roleRepo = await getRepo('role');
|
|
110
|
+
// Resolve admin role (seeded in RBAC step just before)
|
|
111
|
+
const adminRole = await roleRepo.findOne({ name: 'admin' });
|
|
112
|
+
await userRepo.create({
|
|
113
|
+
email,
|
|
114
|
+
password: hashedPassword,
|
|
115
|
+
firstName,
|
|
116
|
+
lastName,
|
|
117
|
+
status: 'active',
|
|
118
|
+
roles: adminRole ? [adminRole.id] : [],
|
|
119
|
+
});
|
|
120
|
+
};
|
|
105
121
|
// ── optionalSeeds ──────────────────────────────────────
|
|
106
122
|
if (json.seeds?.length) {
|
|
107
123
|
config.optionalSeeds = json.seeds.map(seedDef => buildSeedDefinition(seedDef, repoFactory));
|
package/package.json
CHANGED