thrownewError(`Type '${name}' already exists (from module '${module.name}', already defined by module '${existingEntry.source.name}')`);
}else{
typeFactories[name]={
source:module,
// No context provided to type factory functions for now, since they are not allowed to be async for now anyway
// FIXME: Maybe add a warning if the user returns a Promise from a factory, asking them to file a bug if they really need it?
// func: wrapModuleFunction(module, factory)
func:factory
};
}
},
get:function(){
returntypeFactories;
}
};
}
functioncreateExtensionTracker(){
letextendedTypes={};
return{
add:function(module,type,name,method){
if(extendedTypes[type]==null){
extendedTypes[type]={};
}
letextensions=extendedTypes[type];
if(extensions[name]!=null){
letexistingEntry=extensions[name];
thrownewError(`Type '${type}' already has a method extension named '${name}' (from module '${module.name}', already defined by module '${existingEntry.source.name}')`);
}else{
extensions[name]={
source:module,
func:wrapModuleFunction(module,method)
};
}
},
get:function(){
returnextendedTypes;
}
};
}
functionwrapModuleFunction(module,func){
return{__moduleID:getModuleID(module),func:func};
}
functiondefaultContext(){
// Fallback function that generates an empty context, for when a module doesn't specify a makeContext handler
return{};
}
module.exports=function(modules){
// TODO: Eventually replace hand-crafted merging logic with merge-by-template, once it can support this usecase properly(tm)
// TODO: Fix merge-by-template so that reasonable error messages can be generated here, that are actually aware of eg. the conflicting key