feat(modules): add external module registration and defineModule support

- Add `./modules/define` export path pointing to `defineModule.js`
- Implement `registerExternalModules()` to handle modules passed via `zen.config.js`, with env var gating (`ZEN_MODULE_<NAME>=true`)
- Extract `buildAdminConfig()` helper to consolidate admin navigation/page config building
- Refactor `loadModuleConfig()` to use `buildAdminConfig()` and simplify public routes check
- Improve `initializeModuleTables()` to gracefully skip modules without `db.js` instead of erroring
- Update module discovery JSDoc to reflect external module registration support
This commit is contained in:
2026-04-12 13:39:56 -04:00
parent 4983a24325
commit 99a56d2c39
13 changed files with 871 additions and 146 deletions
+27 -7
View File
@@ -1,12 +1,32 @@
'use client';
import { useState } from 'react';
import { ToastProvider, ToastContainer } from '@hykocx/zen/toast';
import { registerExternalModulePages } from '../../modules/modules.pages.js';
export function ZenProvider({ children }) {
return (
<ToastProvider>
{children}
<ToastContainer />
</ToastProvider>
);
/**
* ZenProvider — root client provider for the ZEN CMS.
*
* Pass external module configs via the `modules` prop so their
* admin pages and public pages are available to the client router.
*
* @param {Object} props
* @param {Array} props.modules - External module configs from zen.config.js
* @param {ReactNode} props.children
*/
export function ZenProvider({ modules = [], children }) {
// Register external module pages once, synchronously, before first render.
// useState initializer runs exactly once and does not cause a re-render.
useState(() => {
if (modules.length > 0) {
registerExternalModulePages(modules);
}
});
return (
<ToastProvider>
{children}
<ToastContainer />
</ToastProvider>
);
}