docs: function (logicalPath, config) {
              return asyncRequire(logicalPath).spreadSync(function (beanPackage) {
                  if (!(beanPackage.$package && beanPackage.$namespaces && beanPackage.$beans) || beanPackage.$package === jv._BASE_TYPES_PACKAGE) {
                      return {
                          skip: true,
                          text: null
                      };
                  }
                  config = config || {};
                  config.removeDoc = "removeDoc" in config ? !!config.removeDoc : true;
                  config.removeMultiTypes = "removeMultiTypes" in config ? !!config.removeMultiTypes : true;
                  config.onlyFastNorm = "onlyFastNorm" in config ? !!config.onlyFastNorm : true;
                  if (!config.onlyFastNorm && !jv._options.checkEnabled) {
                      throw new Error("Aria Templates must be in debug mode for beans to be compiled without the onlyFastNorm option.");
                  }
                  if (!config.removeMultiTypes && !jv._options.checkEnabled) {
                      throw new Error("Aria Templates must be in debug mode for beans to be compiled without the removeMultiTypes option.");
                  }
                  var variables = variablesMgr();
                  var subBeansCode = [];
                  var toPostProcess = [];
                  var packagePathPrefix = beanPackage.$package + ".";
                  var packagePathPrefixLength = packagePathPrefix.length;
                  var referencedBeans = {};
                  var filterSubBeans = config.onlyFastNorm ? filterFastNormBeans : Aria.returnTrue;
                  var beanStringifyFilter = function (path) {
                      if (path.length === 1) {
                          var name = path[0];
                          if (config.onlyFastNorm) {
                              return onlyFastNormIncludedProperties.hasOwnProperty(name);
                          }
                          if (excludedProperties.hasOwnProperty(name)) {
                              return false;
                          }
                          if (config.removeDoc && docExcludedProperties.hasOwnProperty(name)) {
                              return false;
                          }
                      }
                      return true;
                  };
                  var localFnMap = new WeakMap();
                  var beanPropertiesReplacer = function (path, value, bean) {
                      if (path.length === 1 && path[0] === "$fastNormParent") {
                          return new Code(getVariable(processBean(value)));
                      }
                      if (ariaUtilsType.isFunction(value)) {
                          var varName = localFnMap.get(value);
                          if (!varName) {
                              var expression = globalFnMap.get(value);
                              if (!expression) {
                                  var parentBean = getParentBean(bean);
                                  if (value === parentBean.$fastNorm) {
                                      expression = getVariable(processBean(parentBean)) + ".$fastNorm";
                                  } else {
                                      expression = value.toString();
                                  }
                              }
                              varName = variables.createVariable(expression);
                              localFnMap.set(value, varName);
                          }
                          return new Code(varName);
                      }
                      return value;
                  };
  
                  var getVariable = function (beanInfo) {
                      if (!beanInfo.variable) {
                          throw new Error("Invalid recursive structure in " + getTypeName(beanInfo.bean));
                      }
                      return beanInfo.variable;
                  };
                  var processSubBean = function (beanInfo, key) {
                      var subBean = beanInfo.bean[key];
                      if (subBean && filterSubBeans([], subBean)) {
                          subBeansCode.push(getVariable(beanInfo), ".", key, "=", getVariable(processBean(subBean)), ";");
                      }
                  };
                  var processSubBeansCollection = function (beanInfo, key) {
                      var collection = beanInfo.bean[key];
                      if (collection) {
                          var parentBean = getParentBean(beanInfo.bean);
                          if (collection === parentBean[key]) {
                              var parentBeanInfo = processBean(parentBean);
                              subBeansCode.push(getVariable(beanInfo), ".", key, "=", getVariable(parentBeanInfo), ".", key, ";");
                          } else {
                              subBeansCode.push(getVariable(beanInfo), ".", key, "=", processBeansCollection(collection, filterSubBeans), ";");
                          }
                      }
                  };
                  var processBean = function (bean) {
                      var typeName = getTypeName(bean);
                      var beanInfo = referencedBeans[typeName];
                      if (!beanInfo) {
                          beanInfo = referencedBeans[typeName] = {
                              bean: bean
                          };
                          var value;
                          var internalBean = typeName.substr(0, packagePathPrefixLength) === packagePathPrefix;
                          if (internalBean) {
                              var processedParentBean = processBean(getParentBean(bean));
                              var out = ["registerBean(", ariaUtilsString.stringify(typeName.substr(packagePathPrefixLength)), ",", getVariable(processedParentBean)];
                              var stringifiedBean = stringify(bean, beanStringifyFilter, beanPropertiesReplacer);
                              if (stringifiedBean !== "{}") {
                                  out.push(",", stringifiedBean);
                              }
                              out.push(")");
                              value = out.join("");
                              toPostProcess.push(beanInfo);
                          } else {
                              value = "getBean(" + ariaUtilsString.stringify(typeName) + ")";
                          }
                          beanInfo.variable = variables.createVariable(value);
                      }
                      return beanInfo;
                  };
                  var postProcessBeanInfo = function (beanInfo) {
                      processSubBean(beanInfo, "$contentType");
                      processSubBean(beanInfo, "$keyType");
                      processSubBeansCollection(beanInfo, "$properties");
                      if (!config.removeMultiTypes) {
                          processSubBeansCollection(beanInfo, "$contentTypes");
                      }
                  };
                  var beanVariableReplacer = function (path, value) {
                      if (path.length === 1) {
                          return new Code(getVariable(processBean(value)));
                      }
                      return value;
                  };
                  var processBeansCollection = function (beans, filterBeans) {
                      return stringify(beans, filterBeans, beanVariableReplacer);
                  };
  
                  var output = processBeansCollection(beanPackage.$beans, Aria.returnTrue);
                  if (config.onlyFastNorm) {
                      output = "{}";
                  }
                  while (toPostProcess.length > 0) {
                      postProcessBeanInfo(toPostProcess.shift());
                  }
                  return {
                      skip: false,
                      text: [
                          'var Aria = require("ariatemplates/Aria");\n',
                          'module.exports = Aria.beanDefinitions({\n',
                              '$package:', ariaUtilsString.stringify(beanPackage.$package),',\n',
                              '$namespaces:', stringify(beanPackage.$namespaces, Aria.returnTrue, namespacesReplacer), ',\n',
                              '$compiled:function(registerBean, getBean, fastNormalizers){\n',
                                  variables.getCode(), subBeansCode.join(""), "\n",
                                  "return ", output, ";\n",
                              '}\n',
                          '});\n'
                      ].join("")
                  };
              });
          }