docs: function resolveDependencies(req, attrNode, context, dependency, dependencyContext) {
      let isDep = !!dependency;
      dependency = dependency || {};
      dependencyContext = Object.assign({}, dependencyContext || {});
      dependencyContext.inheritDepth = dependencyContext.inheritDepth || 0;
  
      // remember all contexts for absolute "depends" for included/merged sub-resources:
      while (dependencyContext.inheritDepth < attrNode._origNodes.length) {
          dependencyContext.absolute = dependencyContext.absolute ? dependencyContext.absolute.slice() : [];
          dependencyContext.absolute[dependencyContext.inheritDepth] = { req, attrNode, context };
          dependencyContext.inheritDepth++;
      }
  
      if (attrNode.dataSources || !dependencyContext.relative) {
          dependencyContext.relative = { req, attrNode, context };
      }
  
      // always select primaryKey:
      if (attrNode.primaryKey) {
          attrNode.primaryKey.forEach(primaryKeyAttrPath => {
              let primaryKeyAttrNode = getAttribute(primaryKeyAttrPath, attrNode, context);
  
              primaryKeyAttrPath.reduce((subReq, subAttrName) => {
                  // Object.assign-"hack" for correct attribute order (primary key always first):
                  subReq.select = Object.assign({ [subAttrName]: {} }, subReq.select || {});
                  subReq.select[subAttrName].isPrimary = true;
  
                  if (primaryKeyAttrNode.hidden) subReq.select[subAttrName].internal = true;
              }, req);
          });
      }
  
      if ((!isDep && req.select) || (isDep && dependency.select)) {
          let subContext = Object.assign({}, context);
          let subDependencyContext = Object.assign({}, dependencyContext);
  
          Object.keys(isDep ? dependency.select : req.select).forEach(subAttrName => {
              let subAttrNode = getAttribute([subAttrName], attrNode, context);
              subContext.attrPath = context.attrPath.concat([subAttrName]);
              subDependencyContext.skipDepends = false;
  
              if (isDep) {
                  if (!req.select) req.select = {};
                  if (!req.select[subAttrName]) req.select[subAttrName] = { internal: true };
                  else subDependencyContext.skipDepends = true; // no re-entry for cyclic dependencys
              }
  
              resolveDependencies(
                  req.select[subAttrName],
                  subAttrNode,
                  subContext,
                  isDep ? dependency.select[subAttrName] : null,
                  subDependencyContext
              );
          });
      }
  
      if (attrNode.depends && !dependencyContext.skipDepends) {
          dependencyContext.skipDepends = true; // relative/absolute context root-node is always already processed
  
          Object.keys(attrNode.depends).forEach(subAttrName => {
              let refContext = dependencyContext.relative;
              let dependency = { select: { [subAttrName]: attrNode.depends[subAttrName] } };
  
              if (subAttrName === '{root}') {
                  // use correct absolute context for included/merged sub-resources based on where "depends" was specified:
                  // TODO: maybe process ALL original "depends"-options here (even when "overwritten" by merge):
                  let inheritDepth = attrNode._origNodes.findIndex(origNode => origNode && 'depends' in origNode);
                  refContext = dependencyContext.absolute[inheritDepth];
                  dependency = attrNode.depends[subAttrName];
              }
  
              try {
                  resolveDependencies(
                      refContext.req,
                      refContext.attrNode,
                      refContext.context,
                      dependency,
                      dependencyContext
                  );
              } catch (err) {
                  throw new ImplementationError(err.message + ' in "depends" in ' + context.attrPath.join('.'));
              }
          });
      }
  }