Skip to content

Commit

Permalink
✨ Implement NoticeAPI and NoticeAPISupport
Browse files Browse the repository at this point in the history
  • Loading branch information
WhiteHyun committed Mar 13, 2024
1 parent 7606fc9 commit 27bfdff
Show file tree
Hide file tree
Showing 21 changed files with 360 additions and 1 deletion.
22 changes: 22 additions & 0 deletions APIService/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ let package = Package(
name: "HomeAPISupport",
targets: ["HomeAPISupport"]
),
.library(
name: "NoticeAPI",
targets: ["NoticeAPI"]
),
.library(
name: "NoticeAPISupport",
targets: ["NoticeAPISupport"]
),
.library(
name: "ProductInfoAPI",
targets: ["ProductInfoAPI"]
Expand Down Expand Up @@ -50,6 +58,20 @@ let package = Package(
],
resources: [.process("Mocks")]
),
.target(
name: "NoticeAPI",
dependencies: [
.product(name: "Network", package: "Core"),
.product(name: "Entity", package: "Entity"),
]
),
.target(
name: "NoticeAPISupport",
dependencies: [
"NoticeAPI",
],
resources: [.process("Mocks")]
),
.target(
name: "ProductInfoAPI",
dependencies: [
Expand Down
46 changes: 46 additions & 0 deletions APIService/Sources/NoticeAPI/NoticeDetailService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// NoticeDetailService.swift
//
//
// Created by 홍승현 on 3/10/24.
//

import Entity
import Foundation
import Network

// MARK: - NoticeDetailServiceRepresentable

public protocol NoticeDetailServiceRepresentable {
func fetchNoticeDetail() async throws -> NoticeDetail
}

// MARK: - NoticeDetailService

public struct NoticeDetailService {
private let network: Networking
private let id: Int

public init(network: Networking, id: Int) {
self.network = network
self.id = id
}
}

// MARK: NoticeDetailServiceRepresentable

extension NoticeDetailService: NoticeDetailServiceRepresentable {
public func fetchNoticeDetail() async throws -> NoticeDetail {
let countResponse: NoticeItemResponse = try await network.request(with: NoticeEndPoint.fetchDetail(id))
return NoticeDetail(dto: countResponse)
}
}

private extension NoticeDetail {
init(dto: NoticeItemResponse) {
self.init(
title: dto.title,
context: dto.body
)
}
}
46 changes: 46 additions & 0 deletions APIService/Sources/NoticeAPI/NoticeEndPoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// NoticeEndPoint.swift
//
//
// Created by 홍승현 on 3/10/24.
//

import Foundation
import Network

// MARK: - NoticeEndPoint

public enum NoticeEndPoint {
case fetchList(NoticeListRequest)
case fetchDetail(Int)
}

// MARK: EndPoint

extension NoticeEndPoint: EndPoint {
public var method: HTTPMethod {
.get
}

public var path: String {
switch self {
case .fetchList:
"/v2/notice"
case let .fetchDetail(id):
"/v2/notice/\(id)"
}
}

public var parameters: HTTPParameter {
switch self {
case let .fetchList(requestModel):
.query(requestModel)
case let .fetchDetail(requestModel):
.query(requestModel)
}
}

public var headers: [String: String] {
["Content-Type": "application/json"]
}
}
54 changes: 54 additions & 0 deletions APIService/Sources/NoticeAPI/NoticeService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// NoticeService.swift
//
//
// Created by 홍승현 on 1/31/24.
//

import Entity
import Foundation
import Network

// MARK: - NoticeServiceRepresentable

public protocol NoticeServiceRepresentable {
func fetchNoticeList(request: NoticeListRequest) async throws -> Paginated<Notice>
}

// MARK: - NoticeService

public struct NoticeService {
private let network: Networking

public init(network: Networking) {
self.network = network
}
}

// MARK: NoticeServiceRepresentable

extension NoticeService: NoticeServiceRepresentable {
public func fetchNoticeList(request: NoticeListRequest) async throws -> Paginated<Notice> {
let response: NoticeResponse = try await network.request(with: NoticeEndPoint.fetchList(request))
return Paginated<Notice>(dto: response)
}
}

private extension Paginated where Model == Notice {
init(dto: NoticeResponse) {
self.init(
count: dto.count,
hasMore: dto.hasMore,
results: dto.results.map(Notice.init)
)
}
}

private extension Notice {
init(dto: NoticeItemResponse) {
self.init(
date: dto.date,
title: dto.title
)
}
}
23 changes: 23 additions & 0 deletions APIService/Sources/NoticeAPI/Requests/NoticeListRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// NoticeListRequest.swift
//
//
// Created by 홍승현 on 3/10/24.
//

import Foundation

public struct NoticeListRequest: Encodable {
let pageSize: Int
let offset: Int

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

enum CodingKeys: String, CodingKey {
case pageSize = "page_size"
case offset
}
}
33 changes: 33 additions & 0 deletions APIService/Sources/NoticeAPI/Responses/NoticeResponse.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// NoticeResponse.swift
//
//
// Created by 홍승현 on 3/10/24.
//

import Entity
import Foundation

// MARK: - NoticeResponse

struct NoticeResponse: Decodable, Paginatable {
let count: Int
let hasMore: Bool

let results: [NoticeItemResponse]

enum CodingKeys: String, CodingKey {
case count
case hasMore = "has_more"
case results
}
}

// MARK: - NoticeItemResponse

struct NoticeItemResponse: Decodable {
let id: Int
let title: String
let body: String?
let date: Date
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"title": "test test",
"body": "test body",
"date": "2024-02-25T19:41:11Z",
"id": 1
}
18 changes: 18 additions & 0 deletions APIService/Sources/NoticeAPISupport/Mocks/NoticeListResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"count": 2,
"has_more": false,
"result": [
{
"title": "test test",
"body": null,
"date": "2024-02-25T19:41:11Z",
"id": 1
},
{
"title": "테스트 제목",
"body": null,
"date": "2024-02-26T20:35:48Z",
"id": 2
}
]
}
48 changes: 48 additions & 0 deletions APIService/Sources/NoticeAPISupport/NoticeURLProtocol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// NoticeURLProtocol.swift
//
//
// Created by 홍승현 on 1/25/24.
//

import Foundation
import Network
import NoticeAPI

public final class NoticeURLProtocol: URLProtocol {
private lazy var mockData: [String: Data?] = [
NoticeEndPoint.fetchList(.init(pageSize: 0, offset: 0)).path: loadMockData(fileName: "NoticeListResponse"),
NoticeEndPoint.fetchDetail(2).path: loadMockData(fileName: "NoticeDetailResponse"),
]

override public class func canInit(with _: URLRequest) -> Bool {
true
}

override public class func canonicalRequest(for request: URLRequest) -> URLRequest {
request
}

override public func startLoading() {
defer { client?.urlProtocolDidFinishLoading(self) }
if let url = request.url,
let mockData = mockData[url.path(percentEncoded: true)],
let data = mockData,
let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: nil, headerFields: nil) {
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
client?.urlProtocol(self, didLoad: data)
} else {
client?.urlProtocol(self, didFailWithError: NetworkError.urlError)
}
}

override public func stopLoading() {}

private func loadMockData(fileName: String) -> Data? {
guard let url = Bundle.module.url(forResource: fileName, withExtension: "json")
else {
return nil
}
return try? Data(contentsOf: url)
}
}
File renamed without changes.
File renamed without changes.
21 changes: 21 additions & 0 deletions Entity/Sources/Entity/Notice/Notice.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// Notice.swift
//
//
// Created by 홍승현 on 3/10/24.
//

import Foundation

public struct Notice {
/// 공지 날짜
public let date: Date

/// 공지 제목
public let title: String

public init(date: Date, title: String) {
self.date = date
self.title = title
}
}
21 changes: 21 additions & 0 deletions Entity/Sources/Entity/Notice/NoticeDetail.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// NoticeDetail.swift
//
//
// Created by 홍승현 on 3/10/24.
//

import Foundation

public struct NoticeDetail {
/// 공지 제목
public let title: String

/// 공지 내용, `markdown`으로 적혀있습니다.
public let context: String?

public init(title: String, context: String?) {
self.title = title
self.context = context
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 27bfdff

Please sign in to comment.