Repository: Automattic/pocket-casts-ios
File: Modules/Server/Sources/PocketCastsServer/Public/Search/PredictiveSearchTask.swift (Swift)

Code before:
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let type = try container.decode(String.self, forKey: .type)
        switch type {
            case "term":
                let value = try container.decode(String.self, forKey: .value)
                self.type = .term(value)
            case "podcast":
                let podcast = try container.decode(PredictivePodcastSearchResult.self, forKey: .value)
                self.type = .podcast(podcast)
            default:
                let value = try container.decode(String.self, forKey: .value)
                self.type = .unknown(value)
        }
    }
}

public class PredictiveSearchTask {
    private let session: URLSession

    public init(session: URLSession = .shared) {
        self.session = session
    }

    public func search(term: String) async throws -> [PredictiveSearchResult] {
        var components = URLComponents(string: ServerConstants.Urls.search + "autocomplete/search)")
        components?.queryItems = [URLQueryItem(name: "q", value: term)]
        guard let searchURL = components?.url else {
            throw URL.URLCreationError.invalidURLString
        }
        var request = URLRequest(url: searchURL)
        request.httpMethod = "GET"

        let (data, _) = try await session.data(for: request)
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase

        let envelope = try decoder.decode(PredictiveSearchEnvelope.self, from: data)
        return envelope.results
    }
}


Review comment (suggestion):
Should this be `"autocomplete/search")`?


```suggestion
        var components = URLComponents(string: ServerConstants.Urls.search + "autocomplete/search")
```

Code after:
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let type = try container.decode(String.self, forKey: .type)
        switch type {
            case "term":
                let value = try container.decode(String.self, forKey: .value)
                self.type = .term(value)
            case "podcast":
                let podcast = try container.decode(PredictivePodcastSearchResult.self, forKey: .value)
                self.type = .podcast(podcast)
            default:
                let value = try container.decode(String.self, forKey: .value)
                self.type = .unknown(value)
        }
    }
}

public class PredictiveSearchTask {
    private let session: URLSession

    public init(session: URLSession = .shared) {
        self.session = session
    }

    public func search(term: String) async throws -> [PredictiveSearchResult] {
        var components = URLComponents(string: ServerConstants.Urls.search + "autocomplete/search")
        components?.queryItems = [URLQueryItem(name: "q", value: term)]
        guard let searchURL = components?.url else {
            throw URL.URLCreationError.invalidURLString
        }
        var request = URLRequest(url: searchURL)
        request.httpMethod = "GET"

        let (data, _) = try await session.data(for: request)
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase

        let envelope = try decoder.decode(PredictiveSearchEnvelope.self, from: data)
        return envelope.results
    }
}