Files
core/src/features/init.js
T
hykocx b460ed0619 docs(modules): update server/client boundary docs and client manifest generation
- update MODULES.md to document dual-entry pattern (main vs ./client) and explain why client entry must not import server-only code
- filter client manifest to only include modules exposing a `./client` subpath export
- add `moduleHasClientEntry` helper in discover.server.js to check package.json exports
- update cli.js to use `moduleHasClientEntry` when rendering the client manifest
- update init.js and modules/index.js to align with new client entry convention
2026-04-25 14:43:00 -04:00

104 lines
3.5 KiB
JavaScript

/**
* Database initialization for features and modules.
*
* - Features core : auth (et tout futur core ayant un db.js).
* - Modules externes : découverts via discoverModules() ; chaque module
* exporte ses propres createTables/dropTables.
*
* Les permissions des modules (manifest.permissions) sont enregistrées AVANT
* le seed de la BD pour qu'elles soient persistées et auto-attribuées au rôle
* admin. register() n'est PAS appelé ici — les enregistrements runtime (pages,
* nav, routes) ne sont pas nécessaires pour l'init BD et tireraient des imports
* Next.js incompatibles avec le contexte CLI.
*/
import { createTables as authCreate, dropTables as authDrop } from './auth/db.js';
import { done, fail, info, step } from '@zen/core/shared/logger';
import { loadModulesForCli, validateModuleEnvVars } from '../core/modules/discover.server.js';
import { getRegisteredModules } from '../core/modules/registry.js';
import { registerPermissions } from '../core/users/permissions-registry.js';
const CORE_FEATURES = [
{ name: 'auth', createTables: authCreate, dropTables: authDrop },
];
async function loadModules() {
await loadModulesForCli();
const modules = getRegisteredModules();
validateModuleEnvVars(modules);
// Enregistre les permissions déclarées dans le manifest de chaque module.
// register() n'est PAS appelé ici : les enregistrements runtime (pages, nav,
// routes, storage) ne servent à rien dans le contexte CLI et tireraient des
// imports Next.js (next/headers, JSX) qui ne sont pas disponibles en Node.js.
for (const mod of modules) {
if (Array.isArray(mod.manifest?.permissions)) {
registerPermissions(mod.manifest.permissions);
}
}
return modules;
}
export async function initFeatures() {
const created = [];
const skipped = [];
step('Initializing feature databases...');
// Charger les modules d'abord pour que leurs permissions soient connues
// au moment du seed (et donc auto-attribuées au rôle admin).
const modules = await loadModules();
const targets = [
...CORE_FEATURES,
...modules
.filter(m => typeof m.createTables === 'function')
.map(m => ({ name: m.manifest.name, createTables: m.createTables, dropTables: m.dropTables })),
];
for (const { name, createTables } of targets) {
try {
step(`Initializing ${name}...`);
if (typeof createTables !== 'function') {
info(`${name} has no createTables function`);
continue;
}
const result = await createTables();
if (result?.created) created.push(...result.created);
if (result?.skipped) skipped.push(...result.skipped);
done(`${name} initialized`);
} catch (error) {
fail(`${name}: ${error.message}`);
throw error;
}
}
return { created, skipped };
}
export async function dropFeatures() {
const modules = await loadModules();
// Ordre de création : core, puis modules. Drop = ordre inverse pour que
// les tables modules (qui peuvent avoir des FK vers core) tombent d'abord.
const targets = [
...CORE_FEATURES,
...modules
.filter(m => typeof m.dropTables === 'function')
.map(m => ({ name: m.manifest.name, dropTables: m.dropTables })),
];
for (const { name, dropTables } of [...targets].reverse()) {
try {
if (typeof dropTables !== 'function') {
info(`${name} has no dropTables function`);
continue;
}
await dropTables();
} catch (error) {
fail(`${name}: ${error.message}`);
throw error;
}
}
}