* Gets all of the builders that contribute logic to the given child of the parent builder. * This function recursively traverses the builder hierarchy. * @param builder The parent `AbstractLogicNodeBuilder`. * @param key The property key of the child. * @returns An array of objects, each contain
( builder: AbstractLogicNodeBuilder, key: PropertyKey, )
| 467 | * @returns An array of objects, each containing a `LogicNodeBuilder` for the child and any associated predicates. |
| 468 | */ |
| 469 | function getAllChildBuilders( |
| 470 | builder: AbstractLogicNodeBuilder, |
| 471 | key: PropertyKey, |
| 472 | ): {builder: LogicNodeBuilder; predicates: Predicate[]}[] { |
| 473 | if (builder instanceof LogicNodeBuilder) { |
| 474 | return builder.all.flatMap(({builder, predicate}) => { |
| 475 | const children = getAllChildBuilders(builder, key); |
| 476 | if (predicate) { |
| 477 | return children.map(({builder, predicates}) => ({ |
| 478 | builder, |
| 479 | predicates: [...predicates, predicate], |
| 480 | })); |
| 481 | } |
| 482 | return children; |
| 483 | }); |
| 484 | } else if (builder instanceof NonMergeableLogicNodeBuilder) { |
| 485 | return [ |
| 486 | // DYNAMIC logic always comes first for any individual `NonMergeableLogicNodeBuilder`. |
| 487 | // This assumption is guaranteed by the behavior of `LogicNodeBuilder.getChild`. |
| 488 | // Therefore we can return all of the DYNAMIC logic, followed by all of the property-specific |
| 489 | // logic. |
| 490 | ...(key !== DYNAMIC && builder.children.has(DYNAMIC) |
| 491 | ? [{builder: builder.getChild(DYNAMIC), predicates: []}] |
| 492 | : []), |
| 493 | ...(builder.children.has(key) ? [{builder: builder.getChild(key), predicates: []}] : []), |
| 494 | ]; |
| 495 | } else { |
| 496 | throw new RuntimeError( |
| 497 | RuntimeErrorCode.UNKNOWN_BUILDER_TYPE, |
| 498 | ngDevMode && 'Unknown LogicNodeBuilder type', |
| 499 | ); |
| 500 | } |
| 501 | } |
| 502 | |
| 503 | /** |
| 504 | * Creates the full `Logic` for a given builder. |