(
source: GraphSource<any>,
input: Iterable<unknown>,
context?: QueryContext,
)
| 3943 | } |
| 3944 | |
| 3945 | public *traverse( |
| 3946 | source: GraphSource<any>, |
| 3947 | input: Iterable<unknown>, |
| 3948 | context?: QueryContext, |
| 3949 | ): IterableIterator<unknown> { |
| 3950 | const { directions } = this.config; |
| 3951 | const sorted = [...input].sort((a, b) => { |
| 3952 | for (const { key, expression, direction, nulls } of directions) { |
| 3953 | const aValue = resolveOrderValue(a, key, expression, context); |
| 3954 | const bValue = resolveOrderValue(b, key, expression, context); |
| 3955 | |
| 3956 | // Handle null values according to nulls ordering |
| 3957 | const aIsNull = aValue === null || aValue === undefined; |
| 3958 | const bIsNull = bValue === null || bValue === undefined; |
| 3959 | |
| 3960 | if (aIsNull && bIsNull) { |
| 3961 | continue; // Both null, check next sort key |
| 3962 | } |
| 3963 | |
| 3964 | if (aIsNull || bIsNull) { |
| 3965 | // Determine default nulls ordering based on direction if not specified |
| 3966 | // Default: NULLS LAST for ASC, NULLS FIRST for DESC (matches PostgreSQL behavior) |
| 3967 | const effectiveNulls = nulls ?? (direction === "asc" ? "last" : "first"); |
| 3968 | |
| 3969 | if (aIsNull) { |
| 3970 | return effectiveNulls === "first" ? -1 : 1; |
| 3971 | } else { |
| 3972 | return effectiveNulls === "first" ? 1 : -1; |
| 3973 | } |
| 3974 | } |
| 3975 | |
| 3976 | const result = compare(aValue, bValue); |
| 3977 | if (result !== 0) { |
| 3978 | return direction === "asc" ? result : -result; |
| 3979 | } |
| 3980 | } |
| 3981 | return 0; |
| 3982 | }); |
| 3983 | yield* sorted; |
| 3984 | } |
| 3985 | |
| 3986 | public override clone(partial?: Partial<OrderStepConfig>) { |
| 3987 | return new OrderStep({ |
nothing calls this directly
no test coverage detected