feat(core)!: introduce runtime extension registry and flat module conventions

BREAKING CHANGE: sup config now derives entries from package.json#exports and a server/client glob instead of manual lists; module structure follows flat + barrel convention with .server.js/.client.js runtime suffixes
This commit is contained in:
2026-04-22 14:13:30 -04:00
parent 61388f04a6
commit 0106bc4ea0
35 changed files with 917 additions and 528 deletions
+24 -34
View File
@@ -1,41 +1,37 @@
/**
* Core Feature Database Initialization (CLI)
*
* Initializes and drops DB tables for each core feature.
* Features are discovered from CORE_FEATURES — no manual wiring needed
* when adding a new feature.
* Initialise et supprime les tables des features core. La liste est aujourd'hui
* limitée à auth — le seul feature avec un schéma. Ajouter ici si un autre
* feature gagne un db.js avec createTables()/dropTables().
*/
import { CORE_FEATURES } from './features.registry.js';
import { createTables as authCreate, dropTables as authDrop } from './auth/db.js';
import { done, fail, info, step } from '@zen/core/shared/logger';
/**
* Initialize all core feature databases.
* @returns {Promise<{ created: string[], skipped: string[] }>}
*/
const FEATURES = [
{ name: 'auth', createTables: authCreate, dropTables: authDrop },
];
export async function initFeatures() {
const created = [];
const skipped = [];
step('Initializing feature databases...');
for (const featureName of CORE_FEATURES) {
for (const { name, createTables } of FEATURES) {
try {
step(`Initializing ${featureName}...`);
const db = await import(`./${featureName}/db.js`);
if (typeof db.createTables === 'function') {
const result = await db.createTables();
if (result?.created) created.push(...result.created);
if (result?.skipped) skipped.push(...result.skipped);
done(`${featureName} initialized`);
} else {
info(`${featureName} has no createTables function`);
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(`${featureName}: ${error.message}`);
fail(`${name}: ${error.message}`);
throw error;
}
}
@@ -43,22 +39,16 @@ export async function initFeatures() {
return { created, skipped };
}
/**
* Drop all core feature databases in reverse order.
* @returns {Promise<void>}
*/
export async function dropFeatures() {
for (const featureName of [...CORE_FEATURES].reverse()) {
for (const { name, dropTables } of [...FEATURES].reverse()) {
try {
const db = await import(`./${featureName}/db.js`);
if (typeof db.dropTables === 'function') {
await db.dropTables();
} else {
info(`${featureName} has no dropTables function`);
if (typeof dropTables !== 'function') {
info(`${name} has no dropTables function`);
continue;
}
await dropTables();
} catch (error) {
fail(`${featureName}: ${error.message}`);
fail(`${name}: ${error.message}`);
throw error;
}
}