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

Runtime errors when testing #14

Closed
mackoj opened this issue May 13, 2022 · 5 comments
Closed

Runtime errors when testing #14

mackoj opened this issue May 13, 2022 · 5 comments

Comments

@mackoj
Copy link

mackoj commented May 13, 2022

Hi,

I did have these runtime errors when trying to do some testing.

I will try to find a fix them and update this later.

Error raise: caught error: "L’opération n’a pas pu s’achever. (URLRouting.URLRoutingDecodingError erreur 1.)"

  func testAppBuildFetch() async throws {
    let api = URLRoutingClient<BitriseRoute>.live
    let output = try await api.request(.apps(.app("33134ce06fcbde63", .builds(.build("7ca6e226-8e30-4921-8afa-e20b397cc338", .fetch)))), as: AppBuildFetchWrappedResponse.self)
  }

Error raise: caught error: "L’opération n’a pas pu s’achever. (Parsing.PrintingError erreur 1.)"

  func testAppsFetch() async throws {
    let route : BitriseRoute = .apps(.fetch())
    let printedRoute = try bitriseRouter.print(route)
    XCTAssertEqual(URLRequest(data: printedRoute)?.url?.absoluteString, "/apps")
  }
Rest of the library code (tap to open)
import Foundation
import URLRouting

public let bitriseRequestData = URLRequestData(
  scheme: "https",
  host: "api.bitrise.io",
  path: "v0.1",
  headers: [
    "Authorization": ["SuperSecretToken"],
    "Accept" : ["application/json"]
  ]
)
import Foundation
import URLRouting

extension URLRoutingClient where Route == BitriseRoute {
  @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  public static var live: URLRoutingClient<BitriseRoute> = .live(router: bitriseRouter.baseRequestData(bitriseRequestData))
}
import Foundation

public struct AppBranchesFetchResponse: Codable {
  public let message: String?
  public let data: [String]?
}
import Foundation

public struct AppBuildFetchDataResponse: Codable {
  public let triggeredAt: Date?
  public let startedOnWorkerAt: Date?
  public let environmentPrepareFinishedAt: Date?
  public let finishedAt: Date?
  public let slug: String?
  public let status: Int?
  public let statusText: String?
  public let abortReason: String?
  public let isOnHold: Bool?
  public let isProcessed: Bool?
  public let isStatusSent: Bool?
  public let branch: String?
  public let buildNumber: Int?
  public let commitHash: String?
  public let commitMessage: String?
  public let tag: String?
  public let triggeredWorkflow: String?
  public let triggeredBy: String?
  public let machineTypeID: String?
  public let stackIdentifier: String?
  public let originalBuildParams: OriginalBuildParams?
  public let pullRequestID: Int?
  public let pullRequestTargetBranch: String?
  public let pullRequestViewURL: String?
  public let commitViewURL: String?
  public let creditCost: Int?
  
  public enum CodingKeys: String, CodingKey {
    case triggeredAt = "triggered_at"
    case startedOnWorkerAt = "started_on_worker_at"
    case environmentPrepareFinishedAt = "environment_prepare_finished_at"
    case finishedAt = "finished_at"
    case slug
    case status
    case statusText = "status_text"
    case abortReason = "abort_reason"
    case isOnHold = "is_on_hold"
    case isProcessed = "is_processed"
    case isStatusSent = "is_status_sent"
    case branch
    case buildNumber = "build_number"
    case commitHash = "commit_hash"
    case commitMessage = "commit_message"
    case tag
    case triggeredWorkflow = "triggered_workflow"
    case triggeredBy = "triggered_by"
    case machineTypeID = "machine_type_id"
    case stackIdentifier = "stack_identifier"
    case originalBuildParams = "original_build_params"
    case pullRequestID = "pull_request_id"
    case pullRequestTargetBranch = "pull_request_target_branch"
    case pullRequestViewURL = "pull_request_view_url"
    case commitViewURL = "commit_view_url"
    case creditCost = "credit_cost"
  }

  public init(triggeredAt: Date?, startedOnWorkerAt: Date?, environmentPrepareFinishedAt: Date?, finishedAt: Date?, slug: String?, status: Int?, statusText: String?, abortReason: String?, isOnHold: Bool?, isProcessed: Bool?, isStatusSent: Bool?, branch: String?, buildNumber: Int?, commitHash: String?, commitMessage: String?, tag: String?, triggeredWorkflow: String?, triggeredBy: String?, machineTypeID: String?, stackIdentifier: String?, originalBuildParams: OriginalBuildParams?, pullRequestID: Int?, pullRequestTargetBranch: String?, pullRequestViewURL: String?, commitViewURL: String?, creditCost: Int?) {
    self.triggeredAt = triggeredAt
    self.startedOnWorkerAt = startedOnWorkerAt
    self.environmentPrepareFinishedAt = environmentPrepareFinishedAt
    self.finishedAt = finishedAt
    self.slug = slug
    self.status = status
    self.statusText = statusText
    self.abortReason = abortReason
    self.isOnHold = isOnHold
    self.isProcessed = isProcessed
    self.isStatusSent = isStatusSent
    self.branch = branch
    self.buildNumber = buildNumber
    self.commitHash = commitHash
    self.commitMessage = commitMessage
    self.tag = tag
    self.triggeredWorkflow = triggeredWorkflow
    self.triggeredBy = triggeredBy
    self.machineTypeID = machineTypeID
    self.stackIdentifier = stackIdentifier
    self.originalBuildParams = originalBuildParams
    self.pullRequestID = pullRequestID
    self.pullRequestTargetBranch = pullRequestTargetBranch
    self.pullRequestViewURL = pullRequestViewURL
    self.commitViewURL = commitViewURL
    self.creditCost = creditCost
  }  
}
import Foundation

// MARK: - AppBuildFetchWrappedResponse
public struct AppBuildFetchWrappedResponse: Codable {
  public let message: String?
  public let data: AppBuildFetchDataResponse?
  
  public init(message: String?, data: AppBuildFetchDataResponse?) {
    self.message = message
    self.data = data
  }
}
import Foundation

public struct AppBuildWorkflowsFetchResponse: Codable {
  public let message: String?
  public let data: [String]?
}
import Foundation

// MARK: - AppBuildsFetchResponse
public struct AppBuildsFetchResponse: Codable {
  public let message: String?
  public let data: [AppBuildFetchDataResponse]?
  public let paging: Paging?
  
  public init(message: String?, data: [AppBuildFetchDataResponse]?, paging: Paging?) {
    self.message = message
    self.data = data
    self.paging = paging
  }
}
import Foundation

// MARK: - AppFetchResponse
public struct AppFetchResponse: Codable {
  public let message: String?
  public let data: AppFetchResponse.AppFetchDataResponse?
  
  public init(message: String?, data: AppFetchResponse.AppFetchDataResponse?) {
    self.message = message
    self.data = data
  }
  
  public struct AppFetchDataResponse: Codable {
    public let slug: String
    public let title: String
    public let projectType: String
    public let provider: String
    public let repoOwner: String
    public let repoURL: String
    public let repoSlug: String
    public let isDisabled: Bool
    public let status: Int
    public let isPublic: String
    public let isGithubChecksEnabled: Bool
    public let owner: Owner
    public let avatarURL: String?
    
    public enum CodingKeys: String, CodingKey {
      case slug, title
      case projectType = "project_type"
      case provider
      case repoOwner = "repo_owner"
      case repoURL = "repo_url"
      case repoSlug = "repo_slug"
      case isDisabled = "is_disabled"
      case status
      case isPublic = "is_public"
      case isGithubChecksEnabled = "is_github_checks_enabled"
      case owner
      case avatarURL = "avatar_url"
    }
    
    public struct Owner: Codable {
      public let accountType: String
      public let name: String
      public let slug: String
      
      public enum CodingKeys: String, CodingKey {
        case accountType = "account_type"
        case name, slug
      }
    }
  }
}
import Foundation

// MARK: - AppsFetchResponse
struct AppsFetchResponse: Codable {
  let message: String?
  let data: [AppFetchResponse.AppFetchDataResponse]?
  let paging: Paging?  
}
import Foundation

public struct OriginalBuildParams: Codable {
  public let branch: String?
  public let workflowID: String?
  public let tag: String?
  public let commitMessage: String?
  
  public enum CodingKeys: String, CodingKey {
    case branch
    case workflowID = "workflow_id"
    case tag
    case commitMessage = "commit_message"
  }
  
  public init(branch: String?, workflowID: String?, tag: String?, commitMessage: String?) {
    self.branch = branch
    self.workflowID = workflowID
    self.tag = tag
    self.commitMessage = commitMessage
  }
}
import Foundation

// MARK: - Paging
public struct Paging: Codable {
  public let next: String?
  public let totalItemCount: Int
  public let pageItemLimit: Int
  
  public enum CodingKeys: String, CodingKey {
    case totalItemCount = "total_item_count"
    case pageItemLimit = "page_item_limit"
    case next
  }
}
import Foundation

// MARK: - UserResponse
public struct UserResponse: Codable {
    public let message: String?
    public let data: UserData?
  
  public struct UserData: Codable {
    public let username: String?
    public let slug: String?
    public let email: String?
    public let avatarURL: String?
    public let createdAt: String?
    public let hasUsedOrganizationTrial: Bool?
    public let dataID: Int?
    public let paymentProcessor: String?
    public let unconfirmedEmail: String?
    
    enum CodingKeys: String, CodingKey {
      case username, slug, email
      case avatarURL = "avatar_url"
      case createdAt = "created_at"
      case unconfirmedEmail = "unconfirmed_email"
      case hasUsedOrganizationTrial = "has_used_organization_trial"
      case dataID = "data_id"
      case paymentProcessor = "payment_processor"
    }
  }
}
import Foundation
import URLRouting

// MARK: - AppRoute
public enum AppRoute: Equatable {
  /// Output is AppFetchResponse
  case fetch
  
  case buildWorkflows(BuildWorkflowsRoute = .fetch)
  case builds(BuildsRoute = .fetch())
  case branches(BranchesRoute = .fetch)
}

public let appRouter = OneOf {
  Route(.case(AppRoute.fetch))
  
  Route(.case(AppRoute.buildWorkflows)) {
    Path { "build-workflows" }
    buildWorkflowsRouter
  }

  Route(.case(AppRoute.builds)) {
    Path { "builds" }
    buildsRouter
  }

  Route(.case(AppRoute.branches)) {
    Path { "branches" }
    branchesRouter
  }
}
import Foundation
import URLRouting

// MARK: - AppsRoute
public enum AppsRoute: Equatable {
  /// Output is AppsFetchResponse
  case fetch(SearchOptions = .init())
  
  case app(String, AppRoute = .fetch)

  public struct SearchOptions: Codable, Equatable {
    let sortBy: SortByFetchSearchOptions?
    let next: String?
    let limit: Int?
    
    public init(sortBy: SearchOptions.SortByFetchSearchOptions? = nil, next: String? = nil, limit: Int? = nil) {
      self.sortBy = sortBy
      self.next = next
      self.limit = limit
    }
    
    public enum SortByFetchSearchOptions: String, CaseIterable, Codable {
      case lastBuildAt = "last_build_at"
      case createdAt = "created_at"
    }
  }
}

public let appsRouter = OneOf {
  Route(.case(AppsRoute.fetch)) {
    Parse(.memberwise(AppsRoute.SearchOptions.init)) {
      Query {
        Field("sort_by", default: nil) { AppsRoute.SearchOptions.SortByFetchSearchOptions.parser() }
        Field("next", .string, default: nil)
        Field("limit",  default: nil) { Digits() }
      }
    }
  }

  Route(.case(AppsRoute.app)) {
    Path { Parse(.string) }
    appRouter
  }
}
import Foundation
import URLRouting

// MARK: - ArtifactRoute
public enum ArtifactRoute: Equatable {
  /// Output is ⚠️
  case fetch
}

public let artifactRouter = OneOf {
  Route(.case(ArtifactRoute.fetch))
}
import Foundation
import URLRouting

// MARK: - ArtifactsRoute
public enum ArtifactsRoute: Equatable {
  /// Output is ⚠️
  case fetch
  
  case artifact(String, ArtifactRoute = .fetch)
}

public let artifactsRouter = OneOf {
  Route(.case(ArtifactsRoute.fetch))
  
  Route(.case(ArtifactsRoute.artifact)) {
    Path { Parse(.string) }
    artifactRouter
  }
}
import URLRouting
import Foundation

// MARK: - BitriseRoute
public enum BitriseRoute: Equatable {
  case user(UserRoute = .fetch)
  case builds(RootBuildsRoute = .fetch())
  case apps(AppsRoute = .fetch())
}

public let bitriseRouter = OneOf {
  Route(.case(BitriseRoute.user)) {
    Path { "me" }
    userRouter
  }
  
  Route(.case(BitriseRoute.apps)) {
    Path { "apps" }
    appsRouter
  }
  
  Route(.case(BitriseRoute.builds)) {
    Path { "builds" }
    rootBuildsRouter
  }
}
import Foundation
import URLRouting

// MARK: - BranchesRoute
public enum BranchesRoute: Equatable {
  /// Output is AppBranchesFetchResponse
  case fetch
}

public let branchesRouter = OneOf {
  Route(.case(BranchesRoute.fetch))
}
import Foundation
import URLRouting

// MARK: - BuildRoute
public enum BuildRoute: Equatable {
  /// Output is ⚠️
  case fetch
  case artifacts(ArtifactsRoute = .fetch)
  case log(LogRoute = .fetch)
  case abort(BodyParameters)
  
  public struct BodyParameters: Codable, Equatable {
    var abortReason: String = ""
    var abortWithSuccess: Bool = true
    var skipNotifications: Bool = false
    
    public enum CodingKeys: String, CodingKey {
      case abortReason = "abort_reason"
      case abortWithSuccess = "abort_with_success"
      case skipNotifications = "skip_notifications"
    }

    public init(abortReason: String = "", abortWithSuccess: Bool = true, skipNotifications: Bool = false) {
      self.abortReason = abortReason
      self.abortWithSuccess = abortWithSuccess
      self.skipNotifications = skipNotifications
    }
  }
}

public let buildRouter = OneOf {
  Route(.case(BuildRoute.fetch))
  
  Route(.case(BuildRoute.artifacts)) {
    Path { "artifacts" }
    artifactsRouter
  }
  
  Route(.case(BuildRoute.log)) {
    Path { "log" }
    logRouter
  }
  
  Route(.case(BuildRoute.abort)) {
    Method.post
    Body(.json(BuildRoute.BodyParameters.self))
  }
}
import Foundation
import URLRouting

// MARK: - BuildWorkflowsRoute
public enum BuildWorkflowsRoute: Equatable {
  /// Output is AppBuildWorkflowsFetchResponse
  case fetch
}

public let buildWorkflowsRouter = OneOf {
  Route(.case(BuildWorkflowsRoute.fetch))
}
import Foundation
import URLRouting

// MARK: - BuildsRoute
public enum BuildsRoute: Equatable {
  /// Output is ⚠️
  case trigger(BodyParameters)

  // MARK: - BodyParameters
  public struct BodyParameters: Codable, Equatable {
    public var buildParams: BuildParams?
    public var hookInfo: HookInfo?
    
    public init(buildParams: BuildParams?, hookInfo: HookInfo?) {
      self.buildParams = buildParams
      self.hookInfo = hookInfo
    }
    
    public struct BuildParams: Codable, Equatable {
      public var baseRepositoryURL: String?
      public var branch: String?
      public var branchDest: String?
      public var branchDestRepoOwner: String?
      public var branchRepoOwner: String?
      public var buildRequestSlug: String?
      public var commitHash: String?
      public var commitMessage: String?
      public var commitPaths: [CommitPath]?
      public var diffURL: String?
      public var environments: [Environment]?
      public var headRepositoryURL: String?
      public var pullRequestAuthor: String?
      public var pullRequestHeadBranch: String?
      public var pullRequestMergeBranch: String?
      public var pullRequestRepositoryURL: String?
      public var skipGitStatusReport: Bool?
      public var tag: String?
      public var workflowID: String?
      
      public init(baseRepositoryURL: String?, branch: String?, branchDest: String?, branchDestRepoOwner: String?, branchRepoOwner: String?, buildRequestSlug: String?, commitHash: String?, commitMessage: String?, commitPaths: [CommitPath]?, diffURL: String?, environments: [Environment]?, headRepositoryURL: String?, pullRequestAuthor: String?, pullRequestHeadBranch: String?, pullRequestMergeBranch: String?, pullRequestRepositoryURL: String?, skipGitStatusReport: Bool?, tag: String?, workflowID: String?) {
        self.baseRepositoryURL = baseRepositoryURL
        self.branch = branch
        self.branchDest = branchDest
        self.branchDestRepoOwner = branchDestRepoOwner
        self.branchRepoOwner = branchRepoOwner
        self.buildRequestSlug = buildRequestSlug
        self.commitHash = commitHash
        self.commitMessage = commitMessage
        self.commitPaths = commitPaths
        self.diffURL = diffURL
        self.environments = environments
        self.headRepositoryURL = headRepositoryURL
        self.pullRequestAuthor = pullRequestAuthor
        self.pullRequestHeadBranch = pullRequestHeadBranch
        self.pullRequestMergeBranch = pullRequestMergeBranch
        self.pullRequestRepositoryURL = pullRequestRepositoryURL
        self.skipGitStatusReport = skipGitStatusReport
        self.tag = tag
        self.workflowID = workflowID
      }
      
      public struct CommitPath: Codable, Equatable {
        public var added: [String]?
        public var modified: [String]?
        public var removed: [String]?
        
        public init(added: [String]?, modified: [String]?, removed: [String]?) {
          self.added = added
          self.modified = modified
          self.removed = removed
        }
      }
      public struct Environment: Codable, Equatable {
        public var isExpand: Bool?
        public var mappedTo: String?
        public var value: String?
        
        public init(isExpand: Bool?, mappedTo: String?, value: String?) {
          self.isExpand = isExpand
          self.mappedTo = mappedTo
          self.value = value
        }
      }
    }
    
    public struct HookInfo: Codable, Equatable {
      public var type: String?
      
      public init(type: String?) {
        self.type = type
      }
    }
  }

  case build(String, BuildRoute = .fetch)

  /// Output is AppBuildsFetchResponse
  case fetch(SearchOptions = .init())
  public struct SearchOptions: Codable, Equatable {
    public var sortBy: Sort?
    public var branch: String?
    public var workflow: String?
    public var commitMessage: String?
    public var triggerEventType: String?
    public var pullRequestId: Int?
    public var buildNumber: Int?
    public var after: Date?
    public var before: Date?
    public var status: Status?
    public var next: String?
    public var limit: Int?
    
    public enum Status: Int, Codable, Equatable, CaseIterable {
      case notFinished = 0
      case successful = 1
      case failed = 2
      case abortedWithFailure = 3
      case abortedWithSuccess = 4
    }
    
    public enum Sort: String, Codable, Equatable, CaseIterable {
      case runningFirst = "running_first"
      case createdAt = "created_at"
    }
    
    public init(
      sortBy: BuildsRoute.SearchOptions.Sort? = nil,
      branch: String? = nil,
      workflow: String? = nil,
      commitMessage: String? = nil,
      triggerEventType: String? = nil,
      pullRequestId: Int? = nil//,
//      buildNumber: Int? = nil,
//      after: Date? = nil,
//      before: Date? = nil,
//      status: BuildsRoute.SearchOptions.Status? = nil,
//      next: String? = nil,
//      limit: Int? = nil
    ) {
      self.sortBy = sortBy
      self.branch = branch
      self.workflow = workflow
      self.commitMessage = commitMessage
      self.triggerEventType = triggerEventType
      self.pullRequestId = pullRequestId
      self.buildNumber = nil// buildNumber
      self.after = nil // after
      self.before = nil // before
      self.status = nil // status
      self.next = nil // next
      self.limit = nil // limit
    }
  }
}

public let buildsRouter = OneOf {
  Route(.case(BuildsRoute.fetch)) {
    Parse(.memberwise(BuildsRoute.SearchOptions.init)) {
      Query {
        Field("sort_by", default: nil) { BuildsRoute.SearchOptions.Sort.parser() }
        Field("branch", .string, default: nil)
        Field("workflow", .string, default: nil)
        Field("commit_message", .string, default: nil)
        Field("trigger_event_type", .string, default: nil)
        Field("pull_request_id", default: nil) { Digits() }
//        Field("build_number", default: nil) { Digits() }
//        Field("after", default: nil) { Digits() }
//        Field("before", default: nil) { Digits() }
//        Field("status", default: nil) { BuildsRoute.SearchOptions.Status.parser() }
//        Field("next", .string, default: nil)
//        Field("limit", default: nil) { Digits() }
      }
    }
  }
  
  Route(.case(BuildsRoute.build)) {
    Path { Parse(.string) }
    buildRouter
  }
  
  Route(.case(BuildsRoute.trigger)) {
    Method.post
    Body(.json(BuildsRoute.BodyParameters.self))
  }
}
import Foundation
import URLRouting

// MARK: - LogRoute
public enum LogRoute: Equatable {
  /// Output is ⚠️
  case fetch
}

public let logRouter = OneOf {
  Route(.case(LogRoute.fetch))
}
import URLRouting
import Foundation

// MARK: - RootBuildsRoute
public enum RootBuildsRoute: Equatable {
  /// Output is ⚠️
  case fetch(SearchOptions = .init())
  
  public struct SearchOptions: Codable, Equatable {
    var isOnHold: Bool? = nil
    var status: Status? = nil
    var next: String? = nil
    var limit: Int? = nil
    
    /// The status of the build: not finished (0), successful (1), failed (2), aborted with failure (3), aborted with success (4)
    public enum Status: Int, Codable, Equatable, CaseIterable {
      case notFinished = 0
      case successful = 1
      case failed = 2
      case abortedWithFailure = 3
      case abortedWithSuccess = 4
    }
    
    public init(isOnHold: Bool? = nil, status: RootBuildsRoute.SearchOptions.Status? = nil, next: String? = nil, limit: Int? = nil) {
      self.isOnHold = isOnHold
      self.status = status
      self.next = next
      self.limit = limit
    }
  }
}

public let rootBuildsRouter = OneOf {
  Route(.case(RootBuildsRoute.fetch)) {
    Parse(.memberwise(RootBuildsRoute.SearchOptions.init)) {
      Query {
        Field("is_on_hold", default: nil) { Bool.parser() }
        Field("status", default: nil) { RootBuildsRoute.SearchOptions.Status.parser() }
        Field("next", .string, default: nil)
        Field("limit", default: nil) { Digits() }
      }
    }
  }
}
import Foundation
import URLRouting

// MARK: - UserRoute
public enum UserRoute: Equatable {
  /// Ouput is UserResponse
  case fetch
}

let userRouter = OneOf {
  Route(.case(UserRoute.fetch))
}
@mackoj
Copy link
Author

mackoj commented May 13, 2022

🕵️‍♂️ Investigation in process

For the testAppsFetch it raise three internal error but the test only show caught error: "L’opération n’a pas pu s’achever. (Parsing.PrintingError erreur 1.)"

The three errors go to the same places first here

  @inlinable
  public func unapply(_ output: Root) throws -> Value {
    guard let value = self.extract(from: output)
    else {
      throw ConvertingError(
        """
        case: Failed to extract \(Value.self) from \(output).
        """
      )
    }
    return value
  }

then in the else here

      guard
        MemoryLayout<Struct>.alignment == MemoryLayout<Values>.alignment,
        MemoryLayout<Struct>.size == MemoryLayout<Values>.size
      else {
        throw ConvertingError(
          """
          memberwise: Can't convert \(Values.self) type \(Struct.self) as their memory layouts \
          differ. This conversion should only be used with a memberwise initializer matching the \
          memory layout of the struct. The "memberwise" initializer is the internal, \
          compiler-generated initializer that specifies its arguments in the same order as the \
          struct specifies its properties.
          """
        )
      }

with this values

Value.self: BitriseClient.AllBuildsRoute.Type
output: BitriseClient.BitriseRoute
related code

public enum BitriseRoute: Equatable {
  case user(UserRoute = .fetch)
  case allBuilds(AllBuildsRoute = .fetch())
  case apps(AppsRoute = .fetch())
}

public let bitriseRouter = OneOf {
  Route(.case(BitriseRoute.user)) {
    Path { "me" }
    userRouter
  }
  
  Route(.case(BitriseRoute.apps)) {
    Path { "apps" }
    appsRouter
  }
  
  Route(.case(BitriseRoute.allBuilds)) {
    Path { "builds" }
    allBuildsRouter
  }
}

Value.self: (Swift.String, BitriseClient.AppRoute).Type
output: BitriseClient.AppsRoute
related code

public enum AppsRoute: Equatable {
  /// Output is AppsFetchResponse
  case fetch(SearchOptions = .init())
  
  case app(String, AppRoute = .fetch)

  public struct SearchOptions: Codable, Equatable {
    let sortBy: SortBy?
    let next: String?
    let limit: Int?
    
    public init(sortBy: SearchOptions.SortBy? = nil, next: String? = nil, limit: Int? = nil) {
      self.sortBy = sortBy
      self.next = next
      self.limit = limit
    }
    
    public enum SortBy: String, CaseIterable, Codable {
      case lastBuildAt = "last_build_at"
      case createdAt = "created_at"
    }
  }
}

public let appsRouter = OneOf {
  Route(.case(AppsRoute.fetch)) {
    Parse(.memberwise(AppsRoute.SearchOptions.init)) { // pas error
      Query {
        Field("sort_by", default: nil) { AppsRoute.SearchOptions.SortBy.parser() }
        Field("next", .string, default: nil)
        Field("limit",  default: nil) { Digits() }
      }
    }
  }

  Route(.case(AppsRoute.app)) {
    Path { Parse(.string) }
    appRouter
  }
}

Value.self: BitriseClient.UserRoute.Type
output: BitriseClient.BitriseRoute

related code

public enum UserRoute: Equatable {
  /// Ouput is UserResponse
  case fetch
}

let userRouter = OneOf {
  Route(.case(UserRoute.fetch))
}

In the code base I do use the Parse(.memberwise()) in five different place why only those three raise an error?

@mackoj
Copy link
Author

mackoj commented May 13, 2022

Haha found it !

@mackoj
Copy link
Author

mackoj commented May 13, 2022

The issues was due to the lack of Optionally around Field and it fix the runtime error because the I think compiler-generated initializer might have ? and not the one from the parser because of the lack of Optionally.

@mackoj mackoj closed this as completed May 13, 2022
@mackoj
Copy link
Author

mackoj commented May 13, 2022

After having fixing this issue, I think having a way to display the expected request and the one that was parsed could have help.

If I have knew that the Field wasn't parsed has optional I would I have fix it sonner. Having a way to print all the possible request for a router could have help.

@saroar
Copy link

saroar commented Sep 10, 2022

hi how do you fixed it I am having same problem @mackoj any help will appreciated
here issue I was created
#48

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants