@mostajs/setup 2.1.19 → 2.1.21
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/components/SetupWizard.js +124 -2
- package/dist/lib/setup.js +8 -1
- package/package.json +1 -1
|
@@ -367,6 +367,8 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
367
367
|
const [netApiKey, setNetApiKey] = useState('');
|
|
368
368
|
const [netTestResult, setNetTestResult] = useState(null);
|
|
369
369
|
const [netTesting, setNetTesting] = useState(false);
|
|
370
|
+
const [schemaUploadStatus, setSchemaUploadStatus] = useState(null);
|
|
371
|
+
const [schemasReady, setSchemasReady] = useState(false);
|
|
370
372
|
const [currentStep, setCurrentStep] = useState(0);
|
|
371
373
|
const [dialect, setDialect] = useState('mongodb');
|
|
372
374
|
const [dbConfig, setDbConfig] = useState({ ...DIALECT_DEFAULTS.mongodb, name: `${dbNamePrefix}_prod` });
|
|
@@ -771,7 +773,8 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
771
773
|
return dbConfig.name.trim() !== '';
|
|
772
774
|
return dbTestResult?.ok === true;
|
|
773
775
|
case 'net-config':
|
|
774
|
-
|
|
776
|
+
// OK si serveur connecté ET (schemas déjà chargés OU uploadés)
|
|
777
|
+
return netTestResult?.ok === true && ((netTestResult.entities?.length ?? 0) > 0 || schemasReady);
|
|
775
778
|
case 'admin':
|
|
776
779
|
return adminConfig.firstName.trim() !== '' && adminConfig.lastName.trim() !== '' &&
|
|
777
780
|
adminConfig.email.trim() !== '' && adminConfig.password.length >= 6 &&
|
|
@@ -843,7 +846,126 @@ export default function SetupWizard({ t: tProp, onComplete, endpoints = {}, dbNa
|
|
|
843
846
|
padding: 12, borderRadius: 8, marginBottom: 16,
|
|
844
847
|
backgroundColor: netTestResult.ok ? '#f0fdf4' : '#fef2f2',
|
|
845
848
|
border: `1px solid ${netTestResult.ok ? '#bbf7d0' : '#fecaca'}`,
|
|
846
|
-
}, children: netTestResult.ok ? (_jsxs("div", { children: [_jsx("div", { style: { fontWeight: 600, color: '#166534', marginBottom: 4 }, children: "\u2705 Serveur connecte" }), netTestResult.entities && (_jsxs("div", { style: { fontSize: 13, color: '#374151' }, children: [_jsx("strong", { children: netTestResult.entities.length }), " entites : ", netTestResult.entities.join(', ')] })), netTestResult.transports && (_jsxs("div", { style: { fontSize: 13, color: '#6b7280', marginTop: 4 }, children: ["Transports : ", netTestResult.transports.join(', ')] }))] })) : (_jsxs("div", { style: { color: '#991b1b' }, children: ["\u274C ", netTestResult.error || 'Connexion echouee'] })) })),
|
|
849
|
+
}, children: netTestResult.ok ? (_jsxs("div", { children: [_jsx("div", { style: { fontWeight: 600, color: '#166534', marginBottom: 4 }, children: "\u2705 Serveur connecte" }), netTestResult.entities && (_jsxs("div", { style: { fontSize: 13, color: '#374151' }, children: [_jsx("strong", { children: netTestResult.entities.length }), " entites : ", netTestResult.entities.join(', ')] })), netTestResult.transports && (_jsxs("div", { style: { fontSize: 13, color: '#6b7280', marginTop: 4 }, children: ["Transports : ", netTestResult.transports.join(', ')] }))] })) : (_jsxs("div", { style: { color: '#991b1b' }, children: ["\u274C ", netTestResult.error || 'Connexion echouee'] })) })), netTestResult?.ok && netTestResult.entities?.length === 0 && !schemasReady && (_jsxs("div", { style: {
|
|
850
|
+
padding: 16, borderRadius: 8, marginBottom: 16,
|
|
851
|
+
backgroundColor: '#fffbeb', border: '1px solid #fde68a',
|
|
852
|
+
}, children: [_jsx("div", { style: { fontWeight: 600, color: '#92400e', marginBottom: 8 }, children: "\u26A0\uFE0F Le serveur n'a aucun schema \u2014 envoyez les schemas pour continuer" }), _jsxs("div", { style: { display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 8 }, children: [_jsx("button", { style: { ...S.btn('primary'), fontSize: 13 }, onClick: () => document.getElementById('schemaFileInput')?.click(), children: "\uD83D\uDCC4 Envoyer schemas.json" }), _jsx("input", { id: "schemaFileInput", type: "file", accept: ".json", style: { display: 'none' }, onChange: async (e) => {
|
|
853
|
+
const file = e.target.files?.[0];
|
|
854
|
+
if (!file)
|
|
855
|
+
return;
|
|
856
|
+
setSchemaUploadStatus({ phase: '📤 Envoi du fichier...', color: '#2563eb' });
|
|
857
|
+
try {
|
|
858
|
+
const text = await file.text();
|
|
859
|
+
const schemas = JSON.parse(text);
|
|
860
|
+
const res = await fetch(netUrl + '/api/upload-schemas-json', {
|
|
861
|
+
method: 'POST',
|
|
862
|
+
headers: { 'Content-Type': 'application/json' },
|
|
863
|
+
body: JSON.stringify({ schemas }),
|
|
864
|
+
});
|
|
865
|
+
const data = await res.json();
|
|
866
|
+
if (data.ok) {
|
|
867
|
+
if (data.needsRestart) {
|
|
868
|
+
setSchemaUploadStatus({ phase: '⏳ Serveur redémarre...', color: '#d97706' });
|
|
869
|
+
// Poll health
|
|
870
|
+
for (let i = 0; i < 30; i++) {
|
|
871
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
872
|
+
setSchemaUploadStatus({ phase: `⏳ En attente du serveur... (${i + 1}/30)`, color: '#d97706' });
|
|
873
|
+
try {
|
|
874
|
+
const h = await fetch(netUrl + '/health');
|
|
875
|
+
if (h.ok) {
|
|
876
|
+
const hd = await h.json();
|
|
877
|
+
if (hd.entities?.length > 0) {
|
|
878
|
+
setSchemaUploadStatus({ phase: `✅ Serveur prêt — ${hd.entities.length} entités`, color: '#16a34a' });
|
|
879
|
+
setSchemasReady(true);
|
|
880
|
+
setNetTestResult({ ...netTestResult, entities: hd.entities });
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
catch { }
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
else {
|
|
889
|
+
setSchemaUploadStatus({ phase: `✅ ${data.count} schemas chargés`, color: '#16a34a' });
|
|
890
|
+
setSchemasReady(true);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
else {
|
|
894
|
+
setSchemaUploadStatus({ phase: `❌ ${data.error}`, color: '#dc2626' });
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
catch (err) {
|
|
898
|
+
setSchemaUploadStatus({ phase: `❌ ${err.message}`, color: '#dc2626' });
|
|
899
|
+
}
|
|
900
|
+
e.target.value = '';
|
|
901
|
+
} }), _jsx("button", { style: { ...S.btn('outline'), fontSize: 13 }, onClick: () => document.getElementById('schemaZipInput')?.click(), children: "\uD83D\uDCE6 Envoyer ZIP de schemas" }), _jsx("input", { id: "schemaZipInput", type: "file", accept: ".zip", style: { display: 'none' }, onChange: async (e) => {
|
|
902
|
+
const file = e.target.files?.[0];
|
|
903
|
+
if (!file)
|
|
904
|
+
return;
|
|
905
|
+
setSchemaUploadStatus({ phase: '📤 Envoi du ZIP...', color: '#2563eb' });
|
|
906
|
+
try {
|
|
907
|
+
const formData = new FormData();
|
|
908
|
+
formData.append('file', file);
|
|
909
|
+
const res = await fetch(netUrl + '/api/upload-schemas', {
|
|
910
|
+
method: 'POST',
|
|
911
|
+
body: formData,
|
|
912
|
+
});
|
|
913
|
+
const data = await res.json();
|
|
914
|
+
if (data.ok) {
|
|
915
|
+
setSchemaUploadStatus({ phase: `✅ ${data.count} schemas importés depuis ZIP`, color: '#16a34a' });
|
|
916
|
+
setSchemasReady(true);
|
|
917
|
+
// Refresh test result
|
|
918
|
+
const h = await fetch(netUrl + '/health').then(r => r.json());
|
|
919
|
+
if (h.entities)
|
|
920
|
+
setNetTestResult({ ...netTestResult, entities: h.entities });
|
|
921
|
+
}
|
|
922
|
+
else {
|
|
923
|
+
setSchemaUploadStatus({ phase: `❌ ${data.error}`, color: '#dc2626' });
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
catch (err) {
|
|
927
|
+
setSchemaUploadStatus({ phase: `❌ ${err.message}`, color: '#dc2626' });
|
|
928
|
+
}
|
|
929
|
+
e.target.value = '';
|
|
930
|
+
} }), _jsx("button", { style: { ...S.btn('outline'), fontSize: 13 }, onClick: async () => {
|
|
931
|
+
const schemasPath = prompt('Chemin vers le répertoire des schemas (*.schema.ts) :', './src/dal/schemas');
|
|
932
|
+
if (!schemasPath)
|
|
933
|
+
return;
|
|
934
|
+
setSchemaUploadStatus({ phase: '🔍 Scan en cours...', color: '#2563eb' });
|
|
935
|
+
try {
|
|
936
|
+
const res = await fetch(netUrl + '/api/scan-schemas', {
|
|
937
|
+
method: 'POST',
|
|
938
|
+
headers: { 'Content-Type': 'application/json' },
|
|
939
|
+
body: JSON.stringify({ path: schemasPath }),
|
|
940
|
+
});
|
|
941
|
+
const data = await res.json();
|
|
942
|
+
if (data.ok && data.count > 0) {
|
|
943
|
+
// Générer et appliquer
|
|
944
|
+
const genRes = await fetch(netUrl + '/api/generate-schemas', {
|
|
945
|
+
method: 'POST',
|
|
946
|
+
headers: { 'Content-Type': 'application/json' },
|
|
947
|
+
body: JSON.stringify({ path: schemasPath }),
|
|
948
|
+
});
|
|
949
|
+
const genData = await genRes.json();
|
|
950
|
+
if (genData.ok) {
|
|
951
|
+
setSchemaUploadStatus({ phase: `✅ ${genData.count} schemas scannés et générés`, color: '#16a34a' });
|
|
952
|
+
setSchemasReady(true);
|
|
953
|
+
const h = await fetch(netUrl + '/health').then(r => r.json());
|
|
954
|
+
if (h.entities)
|
|
955
|
+
setNetTestResult({ ...netTestResult, entities: h.entities });
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
else {
|
|
959
|
+
setSchemaUploadStatus({ phase: `❌ Aucun schema trouvé dans ${schemasPath}`, color: '#dc2626' });
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
catch (err) {
|
|
963
|
+
setSchemaUploadStatus({ phase: `❌ ${err.message}`, color: '#dc2626' });
|
|
964
|
+
}
|
|
965
|
+
}, children: "\uD83D\uDCC1 Scanner un r\u00E9pertoire" })] }), schemaUploadStatus && (_jsx("div", { style: { fontSize: 13, fontWeight: 500, color: schemaUploadStatus.color }, children: schemaUploadStatus.phase }))] })), netTestResult?.ok && (netTestResult.entities?.length ?? 0) > 0 && (_jsx("div", { style: {
|
|
966
|
+
padding: 12, borderRadius: 8, marginBottom: 16,
|
|
967
|
+
backgroundColor: '#f0fdf4', border: '1px solid #bbf7d0',
|
|
968
|
+
}, children: _jsxs("div", { style: { fontWeight: 600, color: '#166534' }, children: ["\u2705 Serveur pr\u00EAt \u2014 ", netTestResult.entities?.length, " entit\u00E9s charg\u00E9es"] }) })), _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: setupMode === 'net' ? 'Serveur @mostajs/net' : t('setup.summary.dbConfig') }), _jsxs("div", { style: S.summaryText, children: [_jsx("span", { style: { fontFamily: 'monospace' }, children: dbSummaryLabel() }), setupMode === 'net' && netTransport && _jsxs("span", { style: { display: 'block', marginTop: 4 }, children: ["Transport: ", netTransport] }), setupMode !== 'net' && 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 => {
|
|
847
969
|
const mod = availableModules.find(m => m.key === key);
|
|
848
970
|
return mod ? (_jsxs("span", { style: {
|
|
849
971
|
display: 'inline-flex', alignItems: 'center', gap: 4,
|
package/dist/lib/setup.js
CHANGED
|
@@ -60,12 +60,16 @@ export async function runInstall(installConfig, setupConfig) {
|
|
|
60
60
|
port: setupConfig.defaultPort,
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
|
-
// 3. Set process.env in-memory
|
|
63
|
+
// 3. Set process.env in-memory (force ORM mode even if app started as NET)
|
|
64
|
+
process.env.MOSTA_DATA = 'orm';
|
|
64
65
|
process.env.DB_DIALECT = installConfig.dialect;
|
|
65
66
|
process.env.SGBD_URI = uri;
|
|
66
67
|
if (installConfig.dialect !== 'mongodb') {
|
|
67
68
|
process.env.DB_SCHEMA_STRATEGY = 'update';
|
|
68
69
|
}
|
|
70
|
+
// Clear NET vars to avoid confusion
|
|
71
|
+
delete process.env.MOSTA_NET_URL;
|
|
72
|
+
delete process.env.MOSTA_NET_TRANSPORT;
|
|
69
73
|
// 4. Disconnect existing dialect singleton
|
|
70
74
|
const { disconnectDialect } = await import('@mostajs/orm');
|
|
71
75
|
await disconnectDialect();
|
|
@@ -118,6 +122,9 @@ export async function runInstall(installConfig, setupConfig) {
|
|
|
118
122
|
*/
|
|
119
123
|
async function runNetInstall(installConfig, setupConfig) {
|
|
120
124
|
try {
|
|
125
|
+
// Force NET mode in-memory (even if app started as ORM)
|
|
126
|
+
process.env.MOSTA_DATA = 'net';
|
|
127
|
+
process.env.MOSTA_NET_URL = installConfig.net.url;
|
|
121
128
|
const net = new NetClient({
|
|
122
129
|
url: installConfig.net.url,
|
|
123
130
|
apiKey: installConfig.net.apiKey,
|
package/package.json
CHANGED