docs: function processNode(attrNode, context) {
      const isMainResource = context.attrPath.length === 0;
  
      // identify/handle options-contexts: resource/sub-resource, nested-attribute, attribute:
      if (attrNode.dataSources || attrNode.resource || isMainResource) {
          context.errorContext = getErrorContext(isMainResource ? 'resource' : 'sub-resource', context);
          context.subAttrPath = [];
          context.dataSourceAttributes = {};
  
          if (isMainResource) {
              parseNode(
                  attrNode,
                  {
                      dataSources: null,
                      subFilters: parseSubFilters,
                      resource: checkResourceName,
                      primaryKey: parsePrimaryKey,
                      depends: parseDepends,
                      deprecated: parseBoolean,
                      permission: null,
                      attributes: null,
                      defaultLimit: parseInteger,
                      maxLimit: parseInteger,
                      defaultOrder: requestParser.order
                  },
                  context
              );
          } else {
              parseNode(
                  attrNode,
                  {
                      dataSources: null,
                      subFilters: parseSubFilters,
                      resource: checkResourceName,
                      primaryKey: parsePrimaryKey,
                      parentKey: parseRelationKey,
                      childKey: parseRelationKey,
                      many: parseBoolean,
                      depends: parseDepends,
                      hidden: parseBoolean,
                      deprecated: parseBoolean,
                      permission: null,
                      joinVia: checkIdentifier,
                      attributes: null,
                      defaultLimit: parseInteger,
                      maxLimit: parseInteger,
                      defaultOrder: requestParser.order
                  },
                  context
              );
          }
  
          handleResourceContext(attrNode, context);
      } else if (attrNode.attributes) {
          context.errorContext = getErrorContext('nested-attribute', context);
  
          parseNode(
              attrNode,
              {
                  depends: parseDepends,
                  hidden: parseBoolean,
                  deprecated: parseBoolean,
                  permission: null,
                  attributes: null
              },
              context
          );
  
          // no context-specific special-cases for nested-attributes
      } else {
          context.errorContext = getErrorContext('attribute', context);
  
          // prepare standard-mapping - except for fixed values and inherited attributes:
          if (!attrNode.map && !('value' in attrNode) && attrNode.inherit !== 'inherit') {
              attrNode.map = null; // "null" means "set standard-mapping in parseMap()"
          }
  
          parseNode(
              attrNode,
              {
                  type: parseType,
                  multiValued: parseBoolean,
                  storedType: parseStoredType,
                  delimiter: null,
                  map: parseMap,
                  filter: parseFilter,
                  order: parseOrder,
                  value: parseStaticValue,
                  depends: parseDepends,
                  hidden: parseBoolean,
                  deprecated: parseBoolean,
                  permission: null,
                  inherit: parseInherit
              },
              context
          );
  
          handleAttributeContext(attrNode, context);
      }
  
      // recursion:
      if (attrNode.attributes) {
          Object.keys(attrNode.attributes).forEach(subAttrName => {
              const subAttrNode = attrNode.attributes[subAttrName];
  
              const subContext = Object.assign({}, context);
              subContext.attrPath = context.attrPath.concat([subAttrName]);
              subContext.subAttrPath = context.subAttrPath.concat([subAttrName]);
  
              processNode(subAttrNode, subContext);
          });
      }
  
      if (attrNode.dataSources) {
          if (attrNode.primaryKey) resolvePrimaryKey(attrNode, context);
          prepareDataSources(attrNode, context);
      }
  }