Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ApolloPagination] Additional conveniences for offset pagination #267

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public extension GraphQLQueryPager {
static func makeForwardOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination
queryProvider: @escaping (OffsetPagination.Forward?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Forward
) -> GraphQLQueryPager where Model == PaginationOutput<InitialQuery, InitialQuery> {
GraphQLQueryPager(pager: GraphQLQueryPagerCoordinator(
client: client,
Expand All @@ -26,11 +26,33 @@ public extension GraphQLQueryPager {
))
}

static func makeForwardOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Forward?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Forward,
transform: @escaping ([InitialQuery.Data], InitialQuery.Data, [InitialQuery.Data]) throws -> Model
) -> GraphQLQueryPager {
GraphQLQueryPager(
pager: GraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(nil),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
guard direction == .next else { return nil }
return queryProvider(page)
}
),
transform: transform
)
}

static func makeForwardOffsetQueryPager<InitialQuery: GraphQLQuery, T>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination,
queryProvider: @escaping (OffsetPagination.Forward?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Forward,
transform: @escaping (InitialQuery.Data) throws -> Model
) -> GraphQLQueryPager where Model: RangeReplaceableCollection, T == Model.Element {
GraphQLQueryPager(
Expand All @@ -52,8 +74,8 @@ public extension GraphQLQueryPager {
static func makeReverseOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination
queryProvider: @escaping (OffsetPagination.Reverse?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Reverse
) -> GraphQLQueryPager where Model == PaginationOutput<InitialQuery, InitialQuery> {
GraphQLQueryPager(pager: GraphQLQueryPagerCoordinator(
client: client,
Expand All @@ -67,11 +89,33 @@ public extension GraphQLQueryPager {
))
}

static func makeReverseOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Reverse?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Reverse,
transform: @escaping ([InitialQuery.Data], InitialQuery.Data, [InitialQuery.Data]) throws -> Model
) -> GraphQLQueryPager {
GraphQLQueryPager(
pager: GraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(nil),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
guard direction == .previous else { return nil }
return queryProvider(page)
}
),
transform: transform
)
}

static func makeReverseOffsetQueryPager<InitialQuery: GraphQLQuery, T>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination,
queryProvider: @escaping (OffsetPagination.Reverse?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Reverse,
transform: @escaping (InitialQuery.Data) throws -> Model
) -> GraphQLQueryPager where Model: RangeReplaceableCollection, T == Model.Element {
GraphQLQueryPager(
Expand All @@ -90,6 +134,87 @@ public extension GraphQLQueryPager {
)
}

static func makeBidirectionalOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
start: OffsetPagination.Bidirectional?,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
previousQueryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Bidirectional
) -> GraphQLQueryPager where Model == PaginationOutput<InitialQuery, InitialQuery> {
GraphQLQueryPager(pager: GraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(start),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
switch direction {
case .next:
return queryProvider(page)
case .previous:
return previousQueryProvider(page)
}
}
))
}

static func makeBidirectionalOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
start: OffsetPagination.Bidirectional?,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
previousQueryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Bidirectional,
transform: @escaping ([InitialQuery.Data], InitialQuery.Data, [InitialQuery.Data]) throws -> Model
) -> GraphQLQueryPager {
GraphQLQueryPager(
pager: GraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(start),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
switch direction {
case .next:
return queryProvider(page)
case .previous:
return previousQueryProvider(page)
}
}
),
transform: transform
)
}

static func makeBidirectionalOffsetQueryPager<InitialQuery: GraphQLQuery, T>(
client: ApolloClientProtocol,
start: OffsetPagination.Bidirectional?,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
previousQueryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Bidirectional,
transform: @escaping (InitialQuery.Data) throws -> Model
) -> GraphQLQueryPager where Model: RangeReplaceableCollection, T == Model.Element {
GraphQLQueryPager(
pager: GraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(start),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
switch direction {
case .next:
return queryProvider(page)
case .previous:
return previousQueryProvider(page)
}
}
),
initialTransform: transform,
pageTransform: transform
)
}

// MARK: CursorBasedPagination.Forward Initializers

/// This convenience function creates an `GraphQLQueryPager` that paginates forward with only one query and has an output type of `Result<(PaginationOutput<InitialQuery, InitialQuery>, UpdateSource), Error>`.
Expand Down Expand Up @@ -522,8 +647,8 @@ public extension AsyncGraphQLQueryPager {
static func makeForwardOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination
queryProvider: @escaping (OffsetPagination.Forward?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Forward
) async -> AsyncGraphQLQueryPager where Model == PaginationOutput<InitialQuery, InitialQuery> {
await AsyncGraphQLQueryPager(pager: AsyncGraphQLQueryPagerCoordinator(
client: client,
Expand All @@ -537,11 +662,33 @@ public extension AsyncGraphQLQueryPager {
))
}

static func makeForwardOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Forward?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Forward,
transform: @escaping ([InitialQuery.Data], InitialQuery.Data, [InitialQuery.Data]) throws -> Model
) async -> AsyncGraphQLQueryPager {
await AsyncGraphQLQueryPager(
pager: AsyncGraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(nil),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
guard direction == .next else { return nil }
return queryProvider(page)
}
),
transform: transform
)
}

static func makeForwardOffsetQueryPager<InitialQuery: GraphQLQuery, T>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination,
queryProvider: @escaping (OffsetPagination.Forward?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Forward,
transform: @escaping (InitialQuery.Data) throws -> Model
) async -> AsyncGraphQLQueryPager where Model: RangeReplaceableCollection, T == Model.Element {
await AsyncGraphQLQueryPager(
Expand All @@ -563,8 +710,8 @@ public extension AsyncGraphQLQueryPager {
static func makeReverseOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination
queryProvider: @escaping (OffsetPagination.Reverse?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Reverse
) async -> AsyncGraphQLQueryPager where Model == PaginationOutput<InitialQuery, InitialQuery> {
await AsyncGraphQLQueryPager(pager: AsyncGraphQLQueryPagerCoordinator(
client: client,
Expand All @@ -578,11 +725,33 @@ public extension AsyncGraphQLQueryPager {
))
}

static func makeReverseOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Reverse?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Reverse,
transform: @escaping ([InitialQuery.Data], InitialQuery.Data, [InitialQuery.Data]) throws -> Model
) async -> AsyncGraphQLQueryPager {
await AsyncGraphQLQueryPager(
pager: AsyncGraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(nil),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
guard direction == .previous else { return nil }
return queryProvider(page)
}
),
transform: transform
)
}

static func makeReverseOffsetQueryPager<InitialQuery: GraphQLQuery, T>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination,
queryProvider: @escaping (OffsetPagination.Reverse?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Reverse,
transform: @escaping (InitialQuery.Data) throws -> Model
) async -> AsyncGraphQLQueryPager where Model: RangeReplaceableCollection, T == Model.Element {
await AsyncGraphQLQueryPager(
Expand All @@ -601,6 +770,87 @@ public extension AsyncGraphQLQueryPager {
)
}

static func makeBidirectionalOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
start: OffsetPagination.Bidirectional?,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
previousQueryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Bidirectional
) async -> AsyncGraphQLQueryPager where Model == PaginationOutput<InitialQuery, InitialQuery> {
await AsyncGraphQLQueryPager(pager: AsyncGraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(start),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
switch direction {
case .next:
return queryProvider(page)
case .previous:
return previousQueryProvider(page)
}
}
))
}

static func makeBidirectionalOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
start: OffsetPagination.Bidirectional?,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
previousQueryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Bidirectional,
transform: @escaping ([InitialQuery.Data], InitialQuery.Data, [InitialQuery.Data]) throws -> Model
) async -> AsyncGraphQLQueryPager {
await AsyncGraphQLQueryPager(
pager: AsyncGraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(start),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
switch direction {
case .next:
return queryProvider(page)
case .previous:
return previousQueryProvider(page)
}
}
),
transform: transform
)
}

static func makeBidirectionalOffsetQueryPager<InitialQuery: GraphQLQuery, T>(
client: ApolloClientProtocol,
start: OffsetPagination.Bidirectional?,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
previousQueryProvider: @escaping (OffsetPagination.Bidirectional?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Bidirectional,
transform: @escaping (InitialQuery.Data) throws -> Model
) async -> AsyncGraphQLQueryPager where Model: RangeReplaceableCollection, T == Model.Element {
await AsyncGraphQLQueryPager(
pager: AsyncGraphQLQueryPagerCoordinator(
client: client,
initialQuery: queryProvider(start),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
switch direction {
case .next:
return queryProvider(page)
case .previous:
return previousQueryProvider(page)
}
}
),
initialTransform: transform,
pageTransform: transform
)
}

// MARK: CursorBasedPagination.Forward Initializers

/// This convenience function creates an `AsyncGraphQLQueryPager` that paginates forward with only one query and has an output type of `Result<(PaginationOutput<InitialQuery, InitialQuery>, UpdateSource), Error>`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
extension OffsetPagination {
public struct Bidirectional: PaginationInfo, Hashable {
public let offset: Int
public var canLoadNext: Bool
public let canLoadPrevious: Bool

public init(offset: Int, canLoadNext: Bool, canLoadPrevious: Bool) {
self.offset = offset
self.canLoadNext = canLoadNext
self.canLoadPrevious = canLoadPrevious
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
extension OffsetPagination {
public struct Forward: PaginationInfo, Hashable {
public let offset: Int
public let canLoadNext: Bool
public var canLoadPrevious: Bool { false }

public init(offset: Int, canLoadNext: Bool) {
self.offset = offset
self.canLoadNext = canLoadNext
}
}

}
Loading
Loading