@dbs-portal/core-module-registry
Version:
Core module registry system for automatic module discovery and registration
257 lines • 8.26 kB
JavaScript
/**
* Platform-Agnostic Module Loader
*
* Provides a unified interface for loading platform-specific modules
* (Node.js vs Browser) with automatic fallbacks and error handling.
*/
import { ENV, loadConditionalModule, createLogger } from './environment';
const logger = createLogger('platform-modules');
/**
* Load platform-specific path utilities
*/
export async function loadPath() {
return loadConditionalModule(
// Node.js version
async () => {
try {
const path = await import('path');
logger.debug('Loaded Node.js path module');
return path;
}
catch (error) {
logger.warn('Failed to load Node.js path module, falling back to browser version');
const browserPath = await import(/* webpackChunkName: "browser-path" */ './browser-path.js');
return browserPath.default;
}
},
// Browser version
async () => {
const browserPath = await import(/* webpackChunkName: "browser-path" */ './browser-path.js');
logger.debug('Loaded browser path module');
return browserPath.default;
});
}
/**
* Load platform-specific file system utilities
*/
export async function loadFs() {
return loadConditionalModule(
// Node.js version
async () => {
try {
const fs = await import('fs/promises');
logger.debug('Loaded Node.js fs module');
return {
...fs,
exists: async (path) => {
try {
await fs.access(path);
return true;
}
catch {
return false;
}
}
};
}
catch (error) {
logger.warn('Failed to load Node.js fs module, falling back to browser version');
const browserFs = await import(/* webpackChunkName: "browser-fs" */ './browser-fs.js');
return browserFs.default;
}
},
// Browser version
async () => {
const browserFs = await import(/* webpackChunkName: "browser-fs" */ './browser-fs.js');
logger.debug('Loaded browser fs module');
return browserFs.default;
});
}
/**
* Load platform-specific glob utilities
*/
export async function loadGlob() {
return loadConditionalModule(
// Node.js version
async () => {
try {
const { glob, globSync } = await import('glob');
logger.debug('Loaded Node.js glob module');
return {
glob: async (pattern, options = {}) => {
if (Array.isArray(pattern)) {
const results = await Promise.all(pattern.map(p => glob(p, options)));
return results.flat();
}
return await glob(pattern, options);
},
globSync: (pattern, options = {}) => {
if (Array.isArray(pattern)) {
return pattern.flatMap(p => globSync(p, options));
}
return globSync(pattern, options);
}
};
}
catch (error) {
logger.warn('Failed to load Node.js glob module, falling back to browser version');
const browserGlob = await import(/* webpackChunkName: "browser-glob" */ './browser-glob.js');
return browserGlob.default;
}
},
// Browser version
async () => {
const browserGlob = await import(/* webpackChunkName: "browser-glob" */ './browser-glob.js');
logger.debug('Loaded browser glob module');
return browserGlob.default;
});
}
/**
* Platform module cache
*/
class PlatformModuleCache {
pathModule = null;
fsModule = null;
globModule = null;
async getPath() {
if (!this.pathModule) {
this.pathModule = await loadPath();
}
return this.pathModule;
}
async getFs() {
if (!this.fsModule) {
this.fsModule = await loadFs();
}
return this.fsModule;
}
async getGlob() {
if (!this.globModule) {
this.globModule = await loadGlob();
}
return this.globModule;
}
clear() {
this.pathModule = null;
this.fsModule = null;
this.globModule = null;
}
}
// Global cache instance
const moduleCache = new PlatformModuleCache();
/**
* Get cached path utilities
*/
export const getPath = () => moduleCache.getPath();
/**
* Get cached file system utilities
*/
export const getFs = () => moduleCache.getFs();
/**
* Get cached glob utilities
*/
export const getGlob = () => moduleCache.getGlob();
/**
* Clear module cache (useful for testing)
*/
export const clearModuleCache = () => moduleCache.clear();
/**
* Initialize all platform modules
*/
export async function initializePlatformModules() {
logger.info(`Initializing platform modules for ${ENV.isNode ? 'Node.js' : 'browser'} environment`);
const [path, fs, glob] = await Promise.all([
getPath(),
getFs(),
getGlob()
]);
logger.info('Platform modules initialized successfully');
return { path, fs, glob };
}
/**
* Preload browser modules with mock data (for browser usage)
*/
export async function preloadBrowserModules(mockData) {
if (!ENV.isBrowser) {
logger.warn('preloadBrowserModules called in non-browser environment');
return;
}
logger.info('Preloading browser modules with mock data');
try {
// Preload file system data
if (mockData.files || mockData.directories) {
const fs = await getFs();
const browserFs = fs;
if (mockData.files && browserFs.preloadFile) {
for (const [path, content] of Object.entries(mockData.files)) {
browserFs.preloadFile(path, content);
}
}
if (mockData.directories && browserFs.preloadDirectory) {
for (const [path, files] of Object.entries(mockData.directories)) {
browserFs.preloadDirectory(path, files);
}
}
}
// Preload glob data
if (mockData.structure) {
const glob = await getGlob();
const browserGlob = glob;
if (browserGlob.setMockStructure) {
browserGlob.setMockStructure(mockData.structure);
}
}
logger.info('Browser modules preloaded successfully');
}
catch (error) {
logger.error('Failed to preload browser modules:', error);
throw error;
}
}
/**
* Get platform-specific module information
*/
export function getPlatformInfo() {
return {
platform: ENV.isNode ? 'node' : 'browser',
canReadFiles: ENV.isNode,
canScanDirectories: ENV.isNode,
canUseGlob: ENV.isNode,
requiresPreloading: ENV.isBrowser,
features: {
fileSystem: ENV.isNode,
glob: ENV.isNode,
dynamicImport: true,
fetch: true
}
};
}
/**
* Create platform-specific error with helpful context
*/
export function createPlatformError(operation, originalError, suggestions) {
const platform = ENV.isNode ? 'Node.js' : 'browser';
const info = getPlatformInfo();
let message = `Platform operation '${operation}' failed in ${platform} environment: ${originalError.message}`;
if (suggestions?.length) {
message += `\n\nSuggestions:\n${suggestions.map(s => ` - ${s}`).join('\n')}`;
}
if (!info.canReadFiles && operation.includes('file')) {
message += '\n\nNote: File system operations are not available in browser environment. Consider using preloadBrowserModules() to provide mock data.';
}
const error = new Error(message);
error.name = 'PlatformError';
error.cause = originalError;
return error;
}
export default {
getPath,
getFs,
getGlob,
initializePlatformModules,
preloadBrowserModules,
getPlatformInfo,
createPlatformError,
clearModuleCache
};
//# sourceMappingURL=platform-modules.js.map