initial commit
This commit is contained in:
commit
8de962eeb8
44 changed files with 4843 additions and 0 deletions
70
APIQuery.swift
Normal file
70
APIQuery.swift
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import Foundation
|
||||
|
||||
/// Builder for the MCMS list-endpoint query parameters.
|
||||
///
|
||||
/// Supported by most list endpoints: `query`, `projection`, `sort`, `limit`
|
||||
/// (server default 1000), `skip`, `next` (cursor = a document `_id`), `distinct`.
|
||||
/// Stats/log endpoints additionally require `start-time` and accept `end-time`
|
||||
/// (UTC `yyyy-MM-dd HH:mm:ss`).
|
||||
struct APIQuery {
|
||||
/// Custom Mongo query as `key=value` pairs (joined with commas by the API).
|
||||
var query: [String: String] = [:]
|
||||
/// Field inclusion/exclusion: `1` include, `0` exclude.
|
||||
var projection: [String: Int] = [:]
|
||||
/// Sort field → direction (`1` asc, `-1` desc).
|
||||
var sort: [String: Int] = [:]
|
||||
var limit: Int?
|
||||
var skip: Int?
|
||||
/// Pagination cursor: excludes all items at/before this `_id`.
|
||||
var next: String?
|
||||
/// Attribute to fetch unique values for.
|
||||
var distinct: String?
|
||||
var startTime: Date?
|
||||
var endTime: Date?
|
||||
|
||||
static let empty = APIQuery()
|
||||
|
||||
private static let timeFormatter: DateFormatter = {
|
||||
let f = DateFormatter()
|
||||
f.locale = Locale(identifier: "en_US_POSIX")
|
||||
f.timeZone = TimeZone(identifier: "UTC")
|
||||
f.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
||||
return f
|
||||
}()
|
||||
|
||||
func queryItems() -> [URLQueryItem] {
|
||||
var items: [URLQueryItem] = []
|
||||
|
||||
if !query.isEmpty {
|
||||
let joined = query.map { "\($0)=\($1)" }.joined(separator: ",")
|
||||
items.append(.init(name: "query", value: joined))
|
||||
}
|
||||
if !projection.isEmpty {
|
||||
let joined = projection.map { "\($0)=\($1)" }.joined(separator: ",")
|
||||
items.append(.init(name: "projection", value: joined))
|
||||
}
|
||||
if !sort.isEmpty {
|
||||
let joined = sort.map { "\($0)=\($1)" }.joined(separator: ",")
|
||||
items.append(.init(name: "sort", value: joined))
|
||||
}
|
||||
if let limit { items.append(.init(name: "limit", value: "\(limit)")) }
|
||||
if let skip { items.append(.init(name: "skip", value: "\(skip)")) }
|
||||
if let next { items.append(.init(name: "next", value: next)) }
|
||||
if let distinct { items.append(.init(name: "distinct", value: distinct)) }
|
||||
if let startTime {
|
||||
items.append(.init(name: "start-time", value: Self.timeFormatter.string(from: startTime)))
|
||||
}
|
||||
if let endTime {
|
||||
items.append(.init(name: "end-time", value: Self.timeFormatter.string(from: endTime)))
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
/// Convenience for a recent time window on stats/log endpoints.
|
||||
static func window(lastHours hours: Int, limit: Int? = nil) -> APIQuery {
|
||||
var q = APIQuery()
|
||||
q.startTime = Calendar.current.date(byAdding: .hour, value: -hours, to: Date())
|
||||
q.limit = limit
|
||||
return q
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue