function resolveReference()

in packages/cdk-graph/src/core/compute.ts [332:440]


function resolveReference(
  store: Graph.Store,
  unresolved: SerializedGraph.SGUnresolvedReference
): Graph.Reference | undefined {
  const source = store.getNode(unresolved.source);
  if (source.stack == null) {
    console.warn(String(source), source);
    throw new Error(`Node ${source} is not within stack`);
  }

  let target: Graph.Node;

  switch (unresolved.referenceType) {
    case ReferenceTypeEnum.REF: {
      // ref logicalId is only unique in the stack
      target = store.findNodeByLogicalId(source.stack, unresolved.target);
      return new Graph.Reference({
        store,
        uuid: generateConsistentUUID(unresolved, Graph.Reference.PREFIX),
        referenceType: ReferenceTypeEnum.REF,
        source,
        target,
      });
    }
    case ReferenceTypeEnum.IMPORT: {
      // imports already contain the stack id (stack:logicalId)
      target = store.findNodeByLogicalUniversalId(
        unresolved.target as LOGICAL_UNIVERSAL_ID
      );
      return new Graph.ImportReference({
        store,
        uuid: generateConsistentUUID(unresolved, Graph.ImportReference.PREFIX),
        source,
        target,
      });
    }
    case ReferenceTypeEnum.IMPORT_ARN: {
      const resolvedImportArnNode = store.findNodeByImportArn(
        unresolved.target
      );
      if (!resolvedImportArnNode) {
        // ImportArn tokens are not direct matches, so we can safely ignore misses.
        // We only care about resources directly imported into the CDK app.
        return undefined;
      }

      return new Graph.ImportReference({
        store,
        uuid: generateConsistentUUID(unresolved, Graph.ImportReference.PREFIX),
        source,
        target: resolvedImportArnNode,
      });
    }
    case ReferenceTypeEnum.ATTRIBUTE: {
      const attribute = unresolved.value as string;
      if (attribute && attribute.startsWith("Outputs.")) {
        // Stack output reference
        const stacksToSearch = source.rootStack?.stage?.stacks || store.stacks;
        const potentialRefStacks = Object.values(stacksToSearch).filter(
          (_stack) => _stack.logicalId === unresolved.target
        );
        if (potentialRefStacks.length === 1) {
          const refStack = potentialRefStacks[0];
          target = refStack.findOutput(attribute.replace("Outputs.", ""));
        } else {
          console.warn(
            "Failed to find logical id from attribute reference:",
            unresolved.target
          );
          if (potentialRefStacks.length) {
            console.warn(
              "Found multiple matching stacks:",
              Object.values(potentialRefStacks).map(
                (stack) => `${String(stack)}:${stack.logicalId || "ROOT"}`
              )
            );
          } else {
            console.warn(
              "Available stacks:",
              Object.values(store.stacks).map(
                (stack) => `${String(stack)}:${stack.logicalId || "ROOT"}`
              )
            );
          }
          throw new Error(
            `Failed to find Fn::GetAtt stack for output reference "${unresolved.target}": ${potentialRefStacks.length}`
          );
        }
      } else {
        target = store.findNodeByLogicalId(source.stack, unresolved.target);
      }

      if (target) {
        return new Graph.AttributeReference({
          store,
          uuid: generateConsistentUUID(
            unresolved,
            Graph.AttributeReference.PREFIX
          ),
          source,
          target,
          value: attribute,
        });
      }
    }
  }

  throw new Error(`Failed to resolve reference: ${JSON.stringify(unresolved)}`);
}