( query: QueryIR, ref: PropRef<any>, collection: Collection, )
| 1709 | * @returns The collection, its alias, and the path to the root field in this collection |
| 1710 | */ |
| 1711 | export function followRef( |
| 1712 | query: QueryIR, |
| 1713 | ref: PropRef<any>, |
| 1714 | collection: Collection, |
| 1715 | ): { collection: Collection; path: Array<string> } | void { |
| 1716 | if (ref.path.length === 0) { |
| 1717 | return |
| 1718 | } |
| 1719 | |
| 1720 | if (ref.path.length === 1) { |
| 1721 | // This field should be part of this collection |
| 1722 | const field = ref.path[0]! |
| 1723 | // is it part of the select clause? |
| 1724 | if (query.select) { |
| 1725 | const selectedField = query.select[field] |
| 1726 | if (selectedField && selectedField.type === `ref`) { |
| 1727 | return followRef(query, selectedField, collection) |
| 1728 | } |
| 1729 | } |
| 1730 | |
| 1731 | // Either this field is not part of the select clause |
| 1732 | // and thus it must be part of the collection itself |
| 1733 | // or it is part of the select but is not a reference |
| 1734 | // so we can stop here and don't have to follow it |
| 1735 | return { collection, path: [field] } |
| 1736 | } |
| 1737 | |
| 1738 | if (ref.path.length > 1) { |
| 1739 | // This is a nested field |
| 1740 | const [alias, ...rest] = ref.path |
| 1741 | const aliasRef = getRefFromAlias(query, alias!) |
| 1742 | if (!aliasRef) { |
| 1743 | return |
| 1744 | } |
| 1745 | |
| 1746 | if (aliasRef.type === `queryRef`) { |
| 1747 | return followRef(aliasRef.query, new PropRef(rest), collection) |
| 1748 | } else { |
| 1749 | // This is a reference to a collection |
| 1750 | // we can't follow it further |
| 1751 | // so the field must be on the collection itself |
| 1752 | return { collection: aliasRef.collection, path: rest } |
| 1753 | } |
| 1754 | } |
| 1755 | } |
| 1756 | |
| 1757 | /** |
| 1758 | * Walks a Select object to find IncludesSubquery entries. |
no test coverage detected