// Core modules (always included)
import * as data from "./modules/data/data.js";
import Analyze from "./modules/analyze/analyze.js";
import { HydroLangCache, cachedFetch } from "./modules/data/utils/data-cache.js";
import datasources from "./modules/data/datasources.js";
/**
* Main framework wrapper. Creates a new instance of all modules as objects.
* @class
* @namespace Hydrolang
* @returns {Object} creates a new instance of the whole library.
*/
class Hydrolang {
constructor(config = { includeVisuals: true }) {
this.config = config;
if (typeof window !== 'undefined') {
window.hydroConfig = config;
}
// Base modules are always loaded
// Clone module namespace objects to allow mutation (wrapping)
this.data = { ...data };
this.analyze = new Analyze(config.analyzeComponents);
// Attach datasources to data module
this.datasources = datasources;
// Cache system initialization
// If config.cache is explicitly false, we DO NOT instantiate the real cache
if (config.cache !== false) {
this.cache = new HydroLangCache();
this._initCache();
} else {
// Create a dummy no-op cache object to prevent crashes in wrapped modules
// This ensures this.cache.get/put calls safely do nothing
this.cache = {
init: async () => { },
get: async () => null,
put: async () => { },
putChunked: async () => { },
downloadChunked: async () => null, // Should prompt network fetch
reassembleChunks: async () => null,
delete: async () => { },
clear: async () => { },
keys: async () => []
};
// Still need to ensure globalThis.hydro is set and _originalFetch is present
// even if cache is disabled, as data modules depend on them
if (!globalThis._originalFetch) {
globalThis._originalFetch = globalThis.fetch;
}
globalThis.hydro = this;
console.log('HydroLang Cache disabled by configuration.');
}
// Only load visual modules if requested (after cache is ready/mocked)
if (config.includeVisuals) {
this._loadVisualModules();
}
}
async _initCache() {
try {
await this.cache.init();
// Make sure _originalFetch is valid for internal use in data-cache.js
// But DO NOT override globalThis.fetch
if (!globalThis._originalFetch) {
globalThis._originalFetch = globalThis.fetch;
}
// Make HydroLang instance globally available after cache is ready
globalThis.hydro = this;
} catch (error) {
console.error('Failed to initialize HydroLang cache:', error);
// Still make instance available even if cache fails
globalThis.hydro = this;
}
}
async _loadVisualModules() {
try {
const [visualize, map] = await Promise.all([
import(/* webpackChunkName: "visualize" */ "./modules/visualize/visualize.js"),
import(/* webpackChunkName: "map" */ "./modules/map/map.js")
]);
// Clone to allow wrapping
this.visualize = { ...visualize.default };
this.map = { ...map.default };
} catch (error) {
console.warn('Visual modules could not be loaded:', error);
}
}
}
if (typeof window !== "undefined") {
window.Hydrolang = Hydrolang;
}
export default Hydrolang;