feat: Adds EnvClient
This commit is contained in:
@@ -9,6 +9,7 @@ let package = Package(
|
||||
.library(name: "ApiController", targets: ["ApiController"]),
|
||||
.library(name: "AuthClient", targets: ["AuthClient"]),
|
||||
.library(name: "DatabaseClient", targets: ["DatabaseClient"]),
|
||||
.library(name: "EnvClient", targets: ["EnvClient"]),
|
||||
.library(name: "FileClient", targets: ["FileClient"]),
|
||||
.library(name: "HTMLSnapshotTesting", targets: ["HTMLSnapshotTesting"]),
|
||||
.library(name: "PdfClient", targets: ["PdfClient"]),
|
||||
@@ -79,6 +80,14 @@ let package = Package(
|
||||
.product(name: "Vapor", package: "vapor"),
|
||||
]
|
||||
),
|
||||
|
||||
.target(
|
||||
name: "EnvClient",
|
||||
dependencies: [
|
||||
.product(name: "Dependencies", package: "swift-dependencies"),
|
||||
.product(name: "DependenciesMacros", package: "swift-dependencies"),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "FileClient",
|
||||
dependencies: [
|
||||
|
||||
67
Sources/EnvClient/Interface.swift
Normal file
67
Sources/EnvClient/Interface.swift
Normal file
@@ -0,0 +1,67 @@
|
||||
import Dependencies
|
||||
import DependenciesMacros
|
||||
import Foundation
|
||||
|
||||
extension DependencyValues {
|
||||
|
||||
/// Holds values defined in the process environment that are needed.
|
||||
///
|
||||
/// These are generally loaded from a `.env` file, but also have default values,
|
||||
/// if not found.
|
||||
public var env: @Sendable () throws -> EnvVars {
|
||||
get { self[EnvClient.self].env }
|
||||
set { self[EnvClient.self].env = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
@DependencyClient
|
||||
struct EnvClient: Sendable {
|
||||
|
||||
public var env: @Sendable () throws -> EnvVars
|
||||
}
|
||||
|
||||
public struct EnvVars: Codable, Equatable, Sendable {
|
||||
|
||||
public let pandocPath: String
|
||||
public let pdfEngine: String
|
||||
|
||||
public init(
|
||||
pandocPath: String = "/bin/pandoc",
|
||||
pdfEngine: String = "weasyprint"
|
||||
) {
|
||||
self.pandocPath = pandocPath
|
||||
self.pdfEngine = pdfEngine
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case pandocPath = "PANDOC_PATH"
|
||||
case pdfEngine = "PDF_ENGINE"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension EnvClient: DependencyKey {
|
||||
static let testValue = Self()
|
||||
static let liveValue = Self(env: {
|
||||
// Convert default values into a dictionary.
|
||||
let defaults =
|
||||
(try? encoder.encode(EnvVars()))
|
||||
.flatMap { try? decoder.decode([String: String].self, from: $0) }
|
||||
?? [:]
|
||||
|
||||
// Merge the default values with values found in process environment.
|
||||
let assigned = defaults.merging(ProcessInfo.processInfo.environment, uniquingKeysWith: { $1 })
|
||||
|
||||
return (try? JSONSerialization.data(withJSONObject: assigned))
|
||||
.flatMap { try? decoder.decode(EnvVars.self, from: $0) }
|
||||
?? .init()
|
||||
})
|
||||
}
|
||||
|
||||
private let encoder: JSONEncoder = {
|
||||
JSONEncoder()
|
||||
}()
|
||||
|
||||
private let decoder: JSONDecoder = {
|
||||
JSONDecoder()
|
||||
}()
|
||||
@@ -14,7 +14,6 @@ extension DependencyValues {
|
||||
@DependencyClient
|
||||
public struct PdfClient: Sendable {
|
||||
public var html: @Sendable (Request) async throws -> (any HTML & Sendable)
|
||||
public var markdown: @Sendable (Request) async throws -> String
|
||||
}
|
||||
|
||||
extension PdfClient: DependencyKey {
|
||||
@@ -23,9 +22,6 @@ extension PdfClient: DependencyKey {
|
||||
public static let liveValue = Self(
|
||||
html: { request in
|
||||
request.toHTML()
|
||||
},
|
||||
markdown: { request in
|
||||
request.toMarkdown()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
import Foundation
|
||||
import ManualDCore
|
||||
|
||||
extension PdfClient.Request {
|
||||
|
||||
func toMarkdown() -> String {
|
||||
var retval = """
|
||||
# Duct Calc
|
||||
|
||||
**Name:** \(project.name)
|
||||
**Address:** \(project.streetAddress)
|
||||
\(project.city), \(project.state) \(project.zipCode)
|
||||
|
||||
## Equipment
|
||||
|
||||
| | Value |
|
||||
|:----------------|:--------------------------------|
|
||||
| Static Pressure | \(equipmentInfo.staticPressure.string()) |
|
||||
| Heating CFM | \(equipmentInfo.heatingCFM.string()) |
|
||||
| Cooling CFM | \(equipmentInfo.coolingCFM.string()) |
|
||||
|
||||
## Friction Rate
|
||||
|
||||
| Component Loss | Value |
|
||||
|:----------------|:--------------------------------|
|
||||
|
||||
"""
|
||||
for row in componentLosses {
|
||||
retval += "\(componentLossRow(row))\n"
|
||||
}
|
||||
|
||||
retval += """
|
||||
|
||||
|
||||
| Results | Value |
|
||||
|:-----------------|:---------------------------------|
|
||||
| Available Static Pressure | \(frictionRate.availableStaticPressure.string()) |
|
||||
| Total Equivalent Length | \(totalEquivalentLength.string()) |
|
||||
| Friction Rate Design Value | \(frictionRate.value.string()) |
|
||||
|
||||
## Duct Sizes
|
||||
|
||||
| Register | Dsn CFM | Round Size | Velocity | Final Size | Flex Size | Height | Width |
|
||||
|:---------|:--------|:----------------|:---------|:-----------|:----------|:-------|:------|
|
||||
|
||||
"""
|
||||
for row in ductSizes.rooms {
|
||||
retval += "\(registerRow(row))\n"
|
||||
}
|
||||
|
||||
retval += """
|
||||
|
||||
## Trunk Sizes
|
||||
|
||||
### Supply Trunks
|
||||
|
||||
| Name | Associated Supplies | Dsn CFM | Velocity | Final Size | Flex Size | Height | Width |
|
||||
|:---------|:--------------------|:--------|:---------|:-----------|:----------|:-------|:------|
|
||||
|
||||
"""
|
||||
for row in ductSizes.trunks.filter({ $0.type == .supply }) {
|
||||
retval += "\(trunkRow(row))\n"
|
||||
}
|
||||
|
||||
retval += """
|
||||
|
||||
### Return Trunks / Run Outs
|
||||
|
||||
| Name | Associated Supplies | Dsn CFM | Velocity | Final Size | Flex Size | Height | Width |
|
||||
|:---------|:--------------------|:--------|:---------|:-----------|:----------|:-------|:------|
|
||||
|
||||
"""
|
||||
for row in ductSizes.trunks.filter({ $0.type == .return }) {
|
||||
retval += "\(trunkRow(row))\n"
|
||||
}
|
||||
|
||||
return retval
|
||||
}
|
||||
|
||||
func registerRow(_ row: DuctSizes.RoomContainer) -> String {
|
||||
return """
|
||||
| \(row.roomName) | \(row.designCFM.value.string(digits: 0)) | \(row.roundSize.string()) | \(row.velocity.string()) | \(row.finalSize.string()) | \(row.flexSize.string()) | \(row.height?.string() ?? "") | \(row.width?.string() ?? "") |
|
||||
"""
|
||||
}
|
||||
|
||||
func trunkRow(_ row: DuctSizes.TrunkContainer) -> String {
|
||||
return """
|
||||
| \(row.name ?? "") | \(associatedSupplyString(row)) | \(row.designCFM.value.string(digits: 0)) | \(row.roundSize.string()) | \(row.velocity.string()) | \(row.finalSize.string()) | \(row.flexSize.string()) | \(row.ductSize.height?.string() ?? "") | \(row.width?.string() ?? "") |
|
||||
"""
|
||||
}
|
||||
|
||||
func componentLossRow(_ row: ComponentPressureLoss) -> String {
|
||||
return """
|
||||
| \(row.name) | \(row.value.string()) |
|
||||
"""
|
||||
}
|
||||
|
||||
var totalEquivalentLength: Double {
|
||||
maxSupplyTEL.totalEquivalentLength + maxReturnTEL.totalEquivalentLength
|
||||
}
|
||||
|
||||
func associatedSupplyString(_ row: DuctSizes.TrunkContainer) -> String {
|
||||
row.associatedSupplyString(rooms: ductSizes.rooms)
|
||||
}
|
||||
}
|
||||
|
||||
extension DuctSizes.TrunkContainer {
|
||||
|
||||
func associatedSupplyString(rooms: [DuctSizes.RoomContainer]) -> String {
|
||||
self.registerIDS(rooms: rooms)
|
||||
.joined(separator: ", ")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user