Compare commits
5 Commits
main
...
5440024038
| Author | SHA1 | Date | |
|---|---|---|---|
|
5440024038
|
|||
|
f005b43936
|
|||
|
f44b35ab3d
|
|||
|
bbf9a8b390
|
|||
|
c52cee212f
|
31
.gitea/workflows/ci.yaml
Normal file
31
.gitea/workflows/ci.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ubuntu:
|
||||||
|
name: Linux Tests
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
- name: Setup buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Build test image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: docker/Dockerfile.test
|
||||||
|
push: false
|
||||||
|
load: true
|
||||||
|
tags: michael/ductcalc:test
|
||||||
|
- name: Run Tests
|
||||||
|
run: |
|
||||||
|
docker run --rm michael/ductcalc:test swift test
|
||||||
@@ -120,11 +120,10 @@ let package = Package(
|
|||||||
.target(name: "HTMLSnapshotTesting"),
|
.target(name: "HTMLSnapshotTesting"),
|
||||||
.target(name: "PdfClient"),
|
.target(name: "PdfClient"),
|
||||||
.product(name: "SnapshotTesting", package: "swift-snapshot-testing"),
|
.product(name: "SnapshotTesting", package: "swift-snapshot-testing"),
|
||||||
|
],
|
||||||
|
resources: [
|
||||||
|
.copy("__Snapshots__")
|
||||||
]
|
]
|
||||||
// ,
|
|
||||||
// resources: [
|
|
||||||
// .copy("__Snapshots__")
|
|
||||||
// ]
|
|
||||||
),
|
),
|
||||||
.target(
|
.target(
|
||||||
name: "ProjectClient",
|
name: "ProjectClient",
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import ManualDCore
|
|||||||
extension DatabaseClient {
|
extension DatabaseClient {
|
||||||
@DependencyClient
|
@DependencyClient
|
||||||
public struct EffectiveLengthClient: Sendable {
|
public struct EffectiveLengthClient: Sendable {
|
||||||
public var create: @Sendable (EffectiveLength.Create) async throws -> EffectiveLength
|
public var create: @Sendable (EquivalentLength.Create) async throws -> EquivalentLength
|
||||||
public var delete: @Sendable (EffectiveLength.ID) async throws -> Void
|
public var delete: @Sendable (EquivalentLength.ID) async throws -> Void
|
||||||
public var fetch: @Sendable (Project.ID) async throws -> [EffectiveLength]
|
public var fetch: @Sendable (Project.ID) async throws -> [EquivalentLength]
|
||||||
public var fetchMax: @Sendable (Project.ID) async throws -> EffectiveLength.MaxContainer
|
public var fetchMax: @Sendable (Project.ID) async throws -> EquivalentLength.MaxContainer
|
||||||
public var get: @Sendable (EffectiveLength.ID) async throws -> EffectiveLength?
|
public var get: @Sendable (EquivalentLength.ID) async throws -> EquivalentLength?
|
||||||
public var update:
|
public var update:
|
||||||
@Sendable (EffectiveLength.ID, EffectiveLength.Update) async throws -> EffectiveLength
|
@Sendable (EquivalentLength.ID, EquivalentLength.Update) async throws -> EquivalentLength
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ extension DatabaseClient.EffectiveLengthClient: TestDependencyKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EffectiveLength.Create {
|
extension EquivalentLength.Create {
|
||||||
|
|
||||||
func toModel() throws -> EffectiveLengthModel {
|
func toModel() throws -> EffectiveLengthModel {
|
||||||
try validate()
|
try validate()
|
||||||
@@ -94,7 +94,7 @@ extension EffectiveLength.Create {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EffectiveLength {
|
extension EquivalentLength {
|
||||||
|
|
||||||
struct Migrate: AsyncMigration {
|
struct Migrate: AsyncMigration {
|
||||||
let name = "CreateEffectiveLength"
|
let name = "CreateEffectiveLength"
|
||||||
@@ -173,20 +173,20 @@ final class EffectiveLengthModel: Model, @unchecked Sendable {
|
|||||||
$project.id = projectID
|
$project.id = projectID
|
||||||
}
|
}
|
||||||
|
|
||||||
func toDTO() throws -> EffectiveLength {
|
func toDTO() throws -> EquivalentLength {
|
||||||
try .init(
|
try .init(
|
||||||
id: requireID(),
|
id: requireID(),
|
||||||
projectID: $project.id,
|
projectID: $project.id,
|
||||||
name: name,
|
name: name,
|
||||||
type: .init(rawValue: type)!,
|
type: .init(rawValue: type)!,
|
||||||
straightLengths: straightLengths,
|
straightLengths: straightLengths,
|
||||||
groups: JSONDecoder().decode([EffectiveLength.Group].self, from: groups),
|
groups: JSONDecoder().decode([EquivalentLength.Group].self, from: groups),
|
||||||
createdAt: createdAt!,
|
createdAt: createdAt!,
|
||||||
updatedAt: updatedAt!
|
updatedAt: updatedAt!
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyUpdates(_ updates: EffectiveLength.Update) throws {
|
func applyUpdates(_ updates: EquivalentLength.Update) throws {
|
||||||
if let name = updates.name, name != self.name {
|
if let name = updates.name, name != self.name {
|
||||||
self.name = name
|
self.name = name
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ extension DatabaseClient.Migrations: DependencyKey {
|
|||||||
ComponentPressureLoss.Migrate(),
|
ComponentPressureLoss.Migrate(),
|
||||||
EquipmentInfo.Migrate(),
|
EquipmentInfo.Migrate(),
|
||||||
Room.Migrate(),
|
Room.Migrate(),
|
||||||
EffectiveLength.Migrate(),
|
EquivalentLength.Migrate(),
|
||||||
TrunkSize.Migrate(),
|
TrunkSize.Migrate(),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Foundation
|
|||||||
// TODO: Not sure how to model effective length groups in the database.
|
// TODO: Not sure how to model effective length groups in the database.
|
||||||
// thinking perhaps just have a 'data' field that encoded / decodes
|
// thinking perhaps just have a 'data' field that encoded / decodes
|
||||||
// to swift types??
|
// to swift types??
|
||||||
public struct EffectiveLength: Codable, Equatable, Identifiable, Sendable {
|
public struct EquivalentLength: Codable, Equatable, Identifiable, Sendable {
|
||||||
|
|
||||||
public let id: UUID
|
public let id: UUID
|
||||||
public let projectID: Project.ID
|
public let projectID: Project.ID
|
||||||
@@ -19,9 +19,9 @@ public struct EffectiveLength: Codable, Equatable, Identifiable, Sendable {
|
|||||||
id: UUID,
|
id: UUID,
|
||||||
projectID: Project.ID,
|
projectID: Project.ID,
|
||||||
name: String,
|
name: String,
|
||||||
type: EffectiveLength.EffectiveLengthType,
|
type: EquivalentLength.EffectiveLengthType,
|
||||||
straightLengths: [Int],
|
straightLengths: [Int],
|
||||||
groups: [EffectiveLength.Group],
|
groups: [EquivalentLength.Group],
|
||||||
createdAt: Date,
|
createdAt: Date,
|
||||||
updatedAt: Date
|
updatedAt: Date
|
||||||
) {
|
) {
|
||||||
@@ -36,7 +36,7 @@ public struct EffectiveLength: Codable, Equatable, Identifiable, Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EffectiveLength {
|
extension EquivalentLength {
|
||||||
|
|
||||||
public struct Create: Codable, Equatable, Sendable {
|
public struct Create: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ extension EffectiveLength {
|
|||||||
public init(
|
public init(
|
||||||
projectID: Project.ID,
|
projectID: Project.ID,
|
||||||
name: String,
|
name: String,
|
||||||
type: EffectiveLength.EffectiveLengthType,
|
type: EquivalentLength.EffectiveLengthType,
|
||||||
straightLengths: [Int],
|
straightLengths: [Int],
|
||||||
groups: [EffectiveLength.Group]
|
groups: [EquivalentLength.Group]
|
||||||
) {
|
) {
|
||||||
self.projectID = projectID
|
self.projectID = projectID
|
||||||
self.name = name
|
self.name = name
|
||||||
@@ -70,9 +70,9 @@ extension EffectiveLength {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
name: String? = nil,
|
name: String? = nil,
|
||||||
type: EffectiveLength.EffectiveLengthType? = nil,
|
type: EquivalentLength.EffectiveLengthType? = nil,
|
||||||
straightLengths: [Int]? = nil,
|
straightLengths: [Int]? = nil,
|
||||||
groups: [EffectiveLength.Group]? = nil
|
groups: [EquivalentLength.Group]? = nil
|
||||||
) {
|
) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = type
|
self.type = type
|
||||||
@@ -107,8 +107,8 @@ extension EffectiveLength {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct MaxContainer: Codable, Equatable, Sendable {
|
public struct MaxContainer: Codable, Equatable, Sendable {
|
||||||
public let supply: EffectiveLength?
|
public let supply: EquivalentLength?
|
||||||
public let `return`: EffectiveLength?
|
public let `return`: EquivalentLength?
|
||||||
|
|
||||||
public var total: Double? {
|
public var total: Double? {
|
||||||
guard let supply else { return nil }
|
guard let supply else { return nil }
|
||||||
@@ -116,21 +116,21 @@ extension EffectiveLength {
|
|||||||
return supply.totalEquivalentLength + `return`.totalEquivalentLength
|
return supply.totalEquivalentLength + `return`.totalEquivalentLength
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(supply: EffectiveLength? = nil, return: EffectiveLength? = nil) {
|
public init(supply: EquivalentLength? = nil, return: EquivalentLength? = nil) {
|
||||||
self.supply = supply
|
self.supply = supply
|
||||||
self.return = `return`
|
self.return = `return`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EffectiveLength {
|
extension EquivalentLength {
|
||||||
public var totalEquivalentLength: Double {
|
public var totalEquivalentLength: Double {
|
||||||
straightLengths.reduce(into: 0.0) { $0 += Double($1) }
|
straightLengths.reduce(into: 0.0) { $0 += Double($1) }
|
||||||
+ groups.totalEquivalentLength
|
+ groups.totalEquivalentLength
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Array where Element == EffectiveLength.Group {
|
extension Array where Element == EquivalentLength.Group {
|
||||||
|
|
||||||
public var totalEquivalentLength: Double {
|
public var totalEquivalentLength: Double {
|
||||||
reduce(into: 0.0) {
|
reduce(into: 0.0) {
|
||||||
@@ -141,7 +141,7 @@ extension Array where Element == EffectiveLength.Group {
|
|||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
||||||
extension EffectiveLength {
|
extension EquivalentLength {
|
||||||
|
|
||||||
public static func mock(projectID: Project.ID) -> [Self] {
|
public static func mock(projectID: Project.ID) -> [Self] {
|
||||||
@Dependency(\.uuid) var uuid
|
@Dependency(\.uuid) var uuid
|
||||||
@@ -89,7 +89,7 @@ extension Project {
|
|||||||
public let project: Project
|
public let project: Project
|
||||||
public let componentLosses: [ComponentPressureLoss]
|
public let componentLosses: [ComponentPressureLoss]
|
||||||
public let equipmentInfo: EquipmentInfo
|
public let equipmentInfo: EquipmentInfo
|
||||||
public let equivalentLengths: [EffectiveLength]
|
public let equivalentLengths: [EquivalentLength]
|
||||||
public let rooms: [Room]
|
public let rooms: [Room]
|
||||||
public let trunks: [TrunkSize]
|
public let trunks: [TrunkSize]
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ extension Project {
|
|||||||
project: Project,
|
project: Project,
|
||||||
componentLosses: [ComponentPressureLoss],
|
componentLosses: [ComponentPressureLoss],
|
||||||
equipmentInfo: EquipmentInfo,
|
equipmentInfo: EquipmentInfo,
|
||||||
equivalentLengths: [EffectiveLength],
|
equivalentLengths: [EquivalentLength],
|
||||||
rooms: [Room],
|
rooms: [Room],
|
||||||
trunks: [TrunkSize]
|
trunks: [TrunkSize]
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -226,10 +226,10 @@ extension SiteRoute.Api {
|
|||||||
|
|
||||||
extension SiteRoute.Api {
|
extension SiteRoute.Api {
|
||||||
public enum EffectiveLengthRoute: Equatable, Sendable {
|
public enum EffectiveLengthRoute: Equatable, Sendable {
|
||||||
case create(EffectiveLength.Create)
|
case create(EquivalentLength.Create)
|
||||||
case delete(id: EffectiveLength.ID)
|
case delete(id: EquivalentLength.ID)
|
||||||
case fetch(projectID: Project.ID)
|
case fetch(projectID: Project.ID)
|
||||||
case get(id: EffectiveLength.ID)
|
case get(id: EquivalentLength.ID)
|
||||||
|
|
||||||
static let rootPath = "effectiveLength"
|
static let rootPath = "effectiveLength"
|
||||||
|
|
||||||
@@ -240,12 +240,12 @@ extension SiteRoute.Api {
|
|||||||
"create"
|
"create"
|
||||||
}
|
}
|
||||||
Method.post
|
Method.post
|
||||||
Body(.json(EffectiveLength.Create.self))
|
Body(.json(EquivalentLength.Create.self))
|
||||||
}
|
}
|
||||||
Route(.case(Self.delete(id:))) {
|
Route(.case(Self.delete(id:))) {
|
||||||
Path {
|
Path {
|
||||||
rootPath
|
rootPath
|
||||||
EffectiveLength.ID.parser()
|
EquivalentLength.ID.parser()
|
||||||
}
|
}
|
||||||
Method.delete
|
Method.delete
|
||||||
}
|
}
|
||||||
@@ -261,7 +261,7 @@ extension SiteRoute.Api {
|
|||||||
Route(.case(Self.get(id:))) {
|
Route(.case(Self.get(id:))) {
|
||||||
Path {
|
Path {
|
||||||
rootPath
|
rootPath
|
||||||
EffectiveLength.ID.parser()
|
EquivalentLength.ID.parser()
|
||||||
}
|
}
|
||||||
Method.get
|
Method.get
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -394,11 +394,11 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum EquivalentLengthRoute: Equatable, Sendable {
|
public enum EquivalentLengthRoute: Equatable, Sendable {
|
||||||
case delete(id: EffectiveLength.ID)
|
case delete(id: EquivalentLength.ID)
|
||||||
case field(FieldType, style: EffectiveLength.EffectiveLengthType? = nil)
|
case field(FieldType, style: EquivalentLength.EffectiveLengthType? = nil)
|
||||||
case index
|
case index
|
||||||
case submit(FormStep)
|
case submit(FormStep)
|
||||||
case update(EffectiveLength.ID, StepThree)
|
case update(EquivalentLength.ID, StepThree)
|
||||||
|
|
||||||
static let rootPath = "effective-lengths"
|
static let rootPath = "effective-lengths"
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Route(.case(Self.delete(id:))) {
|
Route(.case(Self.delete(id:))) {
|
||||||
Path {
|
Path {
|
||||||
rootPath
|
rootPath
|
||||||
EffectiveLength.ID.parser()
|
EquivalentLength.ID.parser()
|
||||||
}
|
}
|
||||||
Method.delete
|
Method.delete
|
||||||
}
|
}
|
||||||
@@ -424,7 +424,7 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Field("type") { FieldType.parser() }
|
Field("type") { FieldType.parser() }
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("style", default: nil) {
|
Field("style", default: nil) {
|
||||||
EffectiveLength.EffectiveLengthType.parser()
|
EquivalentLength.EffectiveLengthType.parser()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -437,16 +437,16 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Route(.case(Self.update)) {
|
Route(.case(Self.update)) {
|
||||||
Path {
|
Path {
|
||||||
rootPath
|
rootPath
|
||||||
EffectiveLength.ID.parser()
|
EquivalentLength.ID.parser()
|
||||||
}
|
}
|
||||||
Method.patch
|
Method.patch
|
||||||
Body {
|
Body {
|
||||||
FormData {
|
FormData {
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("id", default: nil) { EffectiveLength.ID.parser() }
|
Field("id", default: nil) { EquivalentLength.ID.parser() }
|
||||||
}
|
}
|
||||||
Field("name", .string)
|
Field("name", .string)
|
||||||
Field("type") { EffectiveLength.EffectiveLengthType.parser() }
|
Field("type") { EquivalentLength.EffectiveLengthType.parser() }
|
||||||
Many {
|
Many {
|
||||||
Field("straightLengths") {
|
Field("straightLengths") {
|
||||||
Int.parser()
|
Int.parser()
|
||||||
@@ -490,10 +490,10 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Body {
|
Body {
|
||||||
FormData {
|
FormData {
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("id", default: nil) { EffectiveLength.ID.parser() }
|
Field("id", default: nil) { EquivalentLength.ID.parser() }
|
||||||
}
|
}
|
||||||
Field("name", .string)
|
Field("name", .string)
|
||||||
Field("type") { EffectiveLength.EffectiveLengthType.parser() }
|
Field("type") { EquivalentLength.EffectiveLengthType.parser() }
|
||||||
}
|
}
|
||||||
.map(.memberwise(StepOne.init))
|
.map(.memberwise(StepOne.init))
|
||||||
}
|
}
|
||||||
@@ -505,10 +505,10 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Body {
|
Body {
|
||||||
FormData {
|
FormData {
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("id", default: nil) { EffectiveLength.ID.parser() }
|
Field("id", default: nil) { EquivalentLength.ID.parser() }
|
||||||
}
|
}
|
||||||
Field("name", .string)
|
Field("name", .string)
|
||||||
Field("type") { EffectiveLength.EffectiveLengthType.parser() }
|
Field("type") { EquivalentLength.EffectiveLengthType.parser() }
|
||||||
Many {
|
Many {
|
||||||
Field("straightLengths") {
|
Field("straightLengths") {
|
||||||
Int.parser()
|
Int.parser()
|
||||||
@@ -525,10 +525,10 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Body {
|
Body {
|
||||||
FormData {
|
FormData {
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("id", default: nil) { EffectiveLength.ID.parser() }
|
Field("id", default: nil) { EquivalentLength.ID.parser() }
|
||||||
}
|
}
|
||||||
Field("name", .string)
|
Field("name", .string)
|
||||||
Field("type") { EffectiveLength.EffectiveLengthType.parser() }
|
Field("type") { EquivalentLength.EffectiveLengthType.parser() }
|
||||||
Many {
|
Many {
|
||||||
Field("straightLengths") {
|
Field("straightLengths") {
|
||||||
Int.parser()
|
Int.parser()
|
||||||
@@ -567,22 +567,22 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct StepOne: Codable, Equatable, Sendable {
|
public struct StepOne: Codable, Equatable, Sendable {
|
||||||
public let id: EffectiveLength.ID?
|
public let id: EquivalentLength.ID?
|
||||||
public let name: String
|
public let name: String
|
||||||
public let type: EffectiveLength.EffectiveLengthType
|
public let type: EquivalentLength.EffectiveLengthType
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct StepTwo: Codable, Equatable, Sendable {
|
public struct StepTwo: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
public let id: EffectiveLength.ID?
|
public let id: EquivalentLength.ID?
|
||||||
public let name: String
|
public let name: String
|
||||||
public let type: EffectiveLength.EffectiveLengthType
|
public let type: EquivalentLength.EffectiveLengthType
|
||||||
public let straightLengths: [Int]
|
public let straightLengths: [Int]
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
id: EffectiveLength.ID? = nil,
|
id: EquivalentLength.ID? = nil,
|
||||||
name: String,
|
name: String,
|
||||||
type: EffectiveLength.EffectiveLengthType,
|
type: EquivalentLength.EffectiveLengthType,
|
||||||
straightLengths: [Int]
|
straightLengths: [Int]
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
@@ -593,9 +593,9 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct StepThree: Codable, Equatable, Sendable {
|
public struct StepThree: Codable, Equatable, Sendable {
|
||||||
public let id: EffectiveLength.ID?
|
public let id: EquivalentLength.ID?
|
||||||
public let name: String
|
public let name: String
|
||||||
public let type: EffectiveLength.EffectiveLengthType
|
public let type: EquivalentLength.EffectiveLengthType
|
||||||
public let straightLengths: [Int]
|
public let straightLengths: [Int]
|
||||||
public let groupGroups: [Int]
|
public let groupGroups: [Int]
|
||||||
public let groupLetters: [String]
|
public let groupLetters: [String]
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ extension PdfClient {
|
|||||||
public let componentLosses: [ComponentPressureLoss]
|
public let componentLosses: [ComponentPressureLoss]
|
||||||
public let ductSizes: DuctSizes
|
public let ductSizes: DuctSizes
|
||||||
public let equipmentInfo: EquipmentInfo
|
public let equipmentInfo: EquipmentInfo
|
||||||
public let maxSupplyTEL: EffectiveLength
|
public let maxSupplyTEL: EquivalentLength
|
||||||
public let maxReturnTEL: EffectiveLength
|
public let maxReturnTEL: EquivalentLength
|
||||||
public let frictionRate: FrictionRate
|
public let frictionRate: FrictionRate
|
||||||
public let projectSHR: Double
|
public let projectSHR: Double
|
||||||
|
|
||||||
@@ -99,8 +99,8 @@ extension PdfClient {
|
|||||||
componentLosses: [ComponentPressureLoss],
|
componentLosses: [ComponentPressureLoss],
|
||||||
ductSizes: DuctSizes,
|
ductSizes: DuctSizes,
|
||||||
equipmentInfo: EquipmentInfo,
|
equipmentInfo: EquipmentInfo,
|
||||||
maxSupplyTEL: EffectiveLength,
|
maxSupplyTEL: EquivalentLength,
|
||||||
maxReturnTEL: EffectiveLength,
|
maxReturnTEL: EquivalentLength,
|
||||||
frictionRate: FrictionRate,
|
frictionRate: FrictionRate,
|
||||||
projectSHR: Double
|
projectSHR: Double
|
||||||
) {
|
) {
|
||||||
@@ -134,7 +134,7 @@ extension PdfClient {
|
|||||||
let rooms = Room.mock(projectID: project.id)
|
let rooms = Room.mock(projectID: project.id)
|
||||||
let trunks = TrunkSize.mock(projectID: project.id, rooms: rooms)
|
let trunks = TrunkSize.mock(projectID: project.id, rooms: rooms)
|
||||||
let equipmentInfo = EquipmentInfo.mock(projectID: project.id)
|
let equipmentInfo = EquipmentInfo.mock(projectID: project.id)
|
||||||
let equivalentLengths = EffectiveLength.mock(projectID: project.id)
|
let equivalentLengths = EquivalentLength.mock(projectID: project.id)
|
||||||
|
|
||||||
return .init(
|
return .init(
|
||||||
project: project,
|
project: project,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Elementary
|
|||||||
import ManualDCore
|
import ManualDCore
|
||||||
|
|
||||||
struct EffectiveLengthsTable: HTML, Sendable {
|
struct EffectiveLengthsTable: HTML, Sendable {
|
||||||
let effectiveLengths: [EffectiveLength]
|
let effectiveLengths: [EquivalentLength]
|
||||||
|
|
||||||
var body: some HTML<HTMLTag.table> {
|
var body: some HTML<HTMLTag.table> {
|
||||||
table {
|
table {
|
||||||
@@ -41,7 +41,7 @@ struct EffectiveLengthsTable: HTML, Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct EffectiveLengthGroupTable: HTML, Sendable {
|
struct EffectiveLengthGroupTable: HTML, Sendable {
|
||||||
let groups: [EffectiveLength.Group]
|
let groups: [EquivalentLength.Group]
|
||||||
|
|
||||||
var body: some HTML<HTMLTag.table> {
|
var body: some HTML<HTMLTag.table> {
|
||||||
table {
|
table {
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ extension ProjectClient {
|
|||||||
public struct FrictionRateResponse: Codable, Equatable, Sendable {
|
public struct FrictionRateResponse: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
public let componentLosses: [ComponentPressureLoss]
|
public let componentLosses: [ComponentPressureLoss]
|
||||||
public let equivalentLengths: EffectiveLength.MaxContainer
|
public let equivalentLengths: EquivalentLength.MaxContainer
|
||||||
public let frictionRate: FrictionRate?
|
public let frictionRate: FrictionRate?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
componentLosses: [ComponentPressureLoss],
|
componentLosses: [ComponentPressureLoss],
|
||||||
equivalentLengths: EffectiveLength.MaxContainer,
|
equivalentLengths: EquivalentLength.MaxContainer,
|
||||||
frictionRate: FrictionRate? = nil
|
frictionRate: FrictionRate? = nil
|
||||||
) {
|
) {
|
||||||
self.componentLosses = componentLosses
|
self.componentLosses = componentLosses
|
||||||
|
|||||||
@@ -144,11 +144,11 @@ extension DatabaseClient {
|
|||||||
// Internal container.
|
// Internal container.
|
||||||
struct DesignFrictionRateResponse: Equatable, Sendable {
|
struct DesignFrictionRateResponse: Equatable, Sendable {
|
||||||
|
|
||||||
typealias EnsuredTEL = (supply: EffectiveLength, return: EffectiveLength)
|
typealias EnsuredTEL = (supply: EquivalentLength, return: EquivalentLength)
|
||||||
|
|
||||||
let designFrictionRate: Double
|
let designFrictionRate: Double
|
||||||
let equipmentInfo: EquipmentInfo
|
let equipmentInfo: EquipmentInfo
|
||||||
let telMaxContainer: EffectiveLength.MaxContainer
|
let telMaxContainer: EquivalentLength.MaxContainer
|
||||||
|
|
||||||
func ensureMaxContainer() throws -> EnsuredTEL {
|
func ensureMaxContainer() throws -> EnsuredTEL {
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ extension DatabaseClient {
|
|||||||
func designFrictionRate(
|
func designFrictionRate(
|
||||||
componentLosses: [ComponentPressureLoss],
|
componentLosses: [ComponentPressureLoss],
|
||||||
equipmentInfo: EquipmentInfo,
|
equipmentInfo: EquipmentInfo,
|
||||||
equivalentLengths: EffectiveLength.MaxContainer
|
equivalentLengths: EquivalentLength.MaxContainer
|
||||||
) -> DesignFrictionRateResponse? {
|
) -> DesignFrictionRateResponse? {
|
||||||
guard let tel = equivalentLengths.total,
|
guard let tel = equivalentLengths.total,
|
||||||
componentLosses.count > 0
|
componentLosses.count > 0
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import ManualDCore
|
|||||||
|
|
||||||
struct DuctSizeSharedRequest {
|
struct DuctSizeSharedRequest {
|
||||||
let equipmentInfo: EquipmentInfo
|
let equipmentInfo: EquipmentInfo
|
||||||
let maxSupplyLength: EffectiveLength
|
let maxSupplyLength: EquivalentLength
|
||||||
let maxReturnLenght: EffectiveLength
|
let maxReturnLenght: EquivalentLength
|
||||||
let designFrictionRate: Double
|
let designFrictionRate: Double
|
||||||
let projectSHR: Double
|
let projectSHR: Double
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import ManualDCore
|
import ManualDCore
|
||||||
|
|
||||||
extension Project.Detail {
|
extension Project.Detail {
|
||||||
var maxContainer: EffectiveLength.MaxContainer {
|
var maxContainer: EquivalentLength.MaxContainer {
|
||||||
.init(
|
.init(
|
||||||
supply: equivalentLengths.filter({ $0.type == .supply })
|
supply: equivalentLengths.filter({ $0.type == .supply })
|
||||||
.sorted(by: { $0.totalEquivalentLength > $1.totalEquivalentLength })
|
.sorted(by: { $0.totalEquivalentLength > $1.totalEquivalentLength })
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ extension SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepThree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var groups: [EffectiveLength.Group] {
|
var groups: [EquivalentLength.Group] {
|
||||||
var groups = [EffectiveLength.Group]()
|
var groups = [EquivalentLength.Group]()
|
||||||
for (n, group) in groupGroups.enumerated() {
|
for (n, group) in groupGroups.enumerated() {
|
||||||
groups.append(
|
groups.append(
|
||||||
.init(
|
.init(
|
||||||
@@ -29,7 +29,7 @@ extension SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepThree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EffectiveLength.Create {
|
extension EquivalentLength.Create {
|
||||||
|
|
||||||
init(
|
init(
|
||||||
form: SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepThree,
|
form: SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepThree,
|
||||||
@@ -45,7 +45,7 @@ extension EffectiveLength.Create {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EffectiveLength.Update {
|
extension EquivalentLength.Update {
|
||||||
init(
|
init(
|
||||||
form: SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepThree,
|
form: SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepThree,
|
||||||
projectID: Project.ID
|
projectID: Project.ID
|
||||||
|
|||||||
@@ -488,7 +488,7 @@ extension SiteRoute.View.ProjectRoute.EquivalentLengthRoute {
|
|||||||
switch step {
|
switch step {
|
||||||
case .one(let stepOne):
|
case .one(let stepOne):
|
||||||
return await ResultView {
|
return await ResultView {
|
||||||
var effectiveLength: EffectiveLength? = nil
|
var effectiveLength: EquivalentLength? = nil
|
||||||
if let id = stepOne.id {
|
if let id = stepOne.id {
|
||||||
effectiveLength = try await database.effectiveLength.get(id)
|
effectiveLength = try await database.effectiveLength.get(id)
|
||||||
}
|
}
|
||||||
@@ -503,7 +503,7 @@ extension SiteRoute.View.ProjectRoute.EquivalentLengthRoute {
|
|||||||
case .two(let stepTwo):
|
case .two(let stepTwo):
|
||||||
return await ResultView {
|
return await ResultView {
|
||||||
request.logger.debug("ViewController: Got step two...")
|
request.logger.debug("ViewController: Got step two...")
|
||||||
var effectiveLength: EffectiveLength? = nil
|
var effectiveLength: EquivalentLength? = nil
|
||||||
if let id = stepTwo.id {
|
if let id = stepTwo.id {
|
||||||
effectiveLength = try await database.effectiveLength.get(id)
|
effectiveLength = try await database.effectiveLength.get(id)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import Styleguide
|
|||||||
|
|
||||||
struct EffectiveLengthForm: HTML, Sendable {
|
struct EffectiveLengthForm: HTML, Sendable {
|
||||||
|
|
||||||
static func id(_ equivalentLength: EffectiveLength?) -> String {
|
static func id(_ equivalentLength: EquivalentLength?) -> String {
|
||||||
let base = "equivalentLengthForm"
|
let base = "equivalentLengthForm"
|
||||||
guard let equivalentLength else { return base }
|
guard let equivalentLength else { return base }
|
||||||
return "\(base)_\(equivalentLength.id.uuidString.replacing("-", with: ""))"
|
return "\(base)_\(equivalentLength.id.uuidString.replacing("-", with: ""))"
|
||||||
@@ -15,15 +15,15 @@ struct EffectiveLengthForm: HTML, Sendable {
|
|||||||
|
|
||||||
let projectID: Project.ID
|
let projectID: Project.ID
|
||||||
let dismiss: Bool
|
let dismiss: Bool
|
||||||
let type: EffectiveLength.EffectiveLengthType
|
let type: EquivalentLength.EffectiveLengthType
|
||||||
let effectiveLength: EffectiveLength?
|
let effectiveLength: EquivalentLength?
|
||||||
|
|
||||||
var id: String { Self.id(effectiveLength) }
|
var id: String { Self.id(effectiveLength) }
|
||||||
|
|
||||||
init(
|
init(
|
||||||
projectID: Project.ID,
|
projectID: Project.ID,
|
||||||
dismiss: Bool,
|
dismiss: Bool,
|
||||||
type: EffectiveLength.EffectiveLengthType = .supply
|
type: EquivalentLength.EffectiveLengthType = .supply
|
||||||
) {
|
) {
|
||||||
self.projectID = projectID
|
self.projectID = projectID
|
||||||
self.dismiss = dismiss
|
self.dismiss = dismiss
|
||||||
@@ -32,7 +32,7 @@ struct EffectiveLengthForm: HTML, Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(
|
init(
|
||||||
effectiveLength: EffectiveLength
|
effectiveLength: EquivalentLength
|
||||||
) {
|
) {
|
||||||
self.dismiss = true
|
self.dismiss = true
|
||||||
self.type = effectiveLength.type
|
self.type = effectiveLength.type
|
||||||
@@ -55,7 +55,7 @@ struct EffectiveLengthForm: HTML, Sendable {
|
|||||||
|
|
||||||
struct StepOne: HTML, Sendable {
|
struct StepOne: HTML, Sendable {
|
||||||
let projectID: Project.ID
|
let projectID: Project.ID
|
||||||
let effectiveLength: EffectiveLength?
|
let effectiveLength: EquivalentLength?
|
||||||
|
|
||||||
var route: String {
|
var route: String {
|
||||||
let baseRoute = SiteRoute.View.router.path(
|
let baseRoute = SiteRoute.View.router.path(
|
||||||
@@ -97,7 +97,7 @@ struct EffectiveLengthForm: HTML, Sendable {
|
|||||||
struct StepTwo: HTML, Sendable {
|
struct StepTwo: HTML, Sendable {
|
||||||
let projectID: Project.ID
|
let projectID: Project.ID
|
||||||
let stepOne: SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepOne
|
let stepOne: SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepOne
|
||||||
let effectiveLength: EffectiveLength?
|
let effectiveLength: EquivalentLength?
|
||||||
|
|
||||||
var route: String {
|
var route: String {
|
||||||
let baseRoute = SiteRoute.View.router.path(
|
let baseRoute = SiteRoute.View.router.path(
|
||||||
@@ -152,7 +152,7 @@ struct EffectiveLengthForm: HTML, Sendable {
|
|||||||
|
|
||||||
struct StepThree: HTML, Sendable {
|
struct StepThree: HTML, Sendable {
|
||||||
let projectID: Project.ID
|
let projectID: Project.ID
|
||||||
let effectiveLength: EffectiveLength?
|
let effectiveLength: EquivalentLength?
|
||||||
let stepTwo: SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepTwo
|
let stepTwo: SiteRoute.View.ProjectRoute.EquivalentLengthRoute.StepTwo
|
||||||
|
|
||||||
var route: String {
|
var route: String {
|
||||||
@@ -254,10 +254,10 @@ struct StraightLengthField: HTML, Sendable {
|
|||||||
|
|
||||||
struct GroupField: HTML, Sendable {
|
struct GroupField: HTML, Sendable {
|
||||||
|
|
||||||
let style: EffectiveLength.EffectiveLengthType
|
let style: EquivalentLength.EffectiveLengthType
|
||||||
let group: EffectiveLength.Group?
|
let group: EquivalentLength.Group?
|
||||||
|
|
||||||
init(style: EffectiveLength.EffectiveLengthType, group: EffectiveLength.Group? = nil) {
|
init(style: EquivalentLength.EffectiveLengthType, group: EquivalentLength.Group? = nil) {
|
||||||
self.style = style
|
self.style = style
|
||||||
self.group = group
|
self.group = group
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ struct GroupField: HTML, Sendable {
|
|||||||
|
|
||||||
struct GroupSelect: HTML, Sendable {
|
struct GroupSelect: HTML, Sendable {
|
||||||
|
|
||||||
let style: EffectiveLength.EffectiveLengthType
|
let style: EquivalentLength.EffectiveLengthType
|
||||||
|
|
||||||
var body: some HTML {
|
var body: some HTML {
|
||||||
label(.class("select")) {
|
label(.class("select")) {
|
||||||
@@ -328,13 +328,13 @@ struct GroupSelect: HTML, Sendable {
|
|||||||
struct GroupTypeSelect: HTML, Sendable {
|
struct GroupTypeSelect: HTML, Sendable {
|
||||||
|
|
||||||
let projectID: Project.ID
|
let projectID: Project.ID
|
||||||
let selected: EffectiveLength.EffectiveLengthType
|
let selected: EquivalentLength.EffectiveLengthType
|
||||||
|
|
||||||
var body: some HTML<HTMLTag.label> {
|
var body: some HTML<HTMLTag.label> {
|
||||||
label(.class("select w-full")) {
|
label(.class("select w-full")) {
|
||||||
span(.class("label")) { "Type" }
|
span(.class("label")) { "Type" }
|
||||||
select(.name("type"), .id("type")) {
|
select(.name("type"), .id("type")) {
|
||||||
for value in EffectiveLength.EffectiveLengthType.allCases {
|
for value in EquivalentLength.EffectiveLengthType.allCases {
|
||||||
option(
|
option(
|
||||||
.value("\(value.rawValue)"),
|
.value("\(value.rawValue)"),
|
||||||
) { value.title }
|
) { value.title }
|
||||||
@@ -345,7 +345,7 @@ struct GroupTypeSelect: HTML, Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EffectiveLength.EffectiveLengthType {
|
extension EquivalentLength.EffectiveLengthType {
|
||||||
|
|
||||||
var title: String { rawValue.capitalized }
|
var title: String { rawValue.capitalized }
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import Styleguide
|
|||||||
|
|
||||||
struct EffectiveLengthsTable: HTML, Sendable {
|
struct EffectiveLengthsTable: HTML, Sendable {
|
||||||
|
|
||||||
let effectiveLengths: [EffectiveLength]
|
let effectiveLengths: [EquivalentLength]
|
||||||
|
|
||||||
private var sortedLengths: [EffectiveLength] {
|
private var sortedLengths: [EquivalentLength] {
|
||||||
effectiveLengths.sorted {
|
effectiveLengths.sorted {
|
||||||
$0.totalEquivalentLength > $1.totalEquivalentLength
|
$0.totalEquivalentLength > $1.totalEquivalentLength
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ struct EffectiveLengthsTable: HTML, Sendable {
|
|||||||
|
|
||||||
struct EffectiveLenghtRow: HTML, Sendable {
|
struct EffectiveLenghtRow: HTML, Sendable {
|
||||||
|
|
||||||
let effectiveLength: EffectiveLength
|
let effectiveLength: EquivalentLength
|
||||||
|
|
||||||
private var deleteRoute: SiteRoute.View {
|
private var deleteRoute: SiteRoute.View {
|
||||||
.project(
|
.project(
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ struct EffectiveLengthsView: HTML, Sendable {
|
|||||||
|
|
||||||
@Environment(ProjectViewValue.$projectID) var projectID
|
@Environment(ProjectViewValue.$projectID) var projectID
|
||||||
|
|
||||||
let effectiveLengths: [EffectiveLength]
|
let effectiveLengths: [EquivalentLength]
|
||||||
|
|
||||||
var supplies: [EffectiveLength] {
|
var supplies: [EquivalentLength] {
|
||||||
effectiveLengths.filter({ $0.type == .supply })
|
effectiveLengths.filter({ $0.type == .supply })
|
||||||
.sorted { $0.totalEquivalentLength > $1.totalEquivalentLength }
|
.sorted { $0.totalEquivalentLength > $1.totalEquivalentLength }
|
||||||
}
|
}
|
||||||
|
|
||||||
var returns: [EffectiveLength] {
|
var returns: [EquivalentLength] {
|
||||||
effectiveLengths.filter({ $0.type == .return })
|
effectiveLengths.filter({ $0.type == .return })
|
||||||
.sorted { $0.totalEquivalentLength > $1.totalEquivalentLength }
|
.sorted { $0.totalEquivalentLength > $1.totalEquivalentLength }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ struct FrictionRateView: HTML, Sendable {
|
|||||||
@Environment(ProjectViewValue.$projectID) var projectID
|
@Environment(ProjectViewValue.$projectID) var projectID
|
||||||
|
|
||||||
let componentLosses: [ComponentPressureLoss]
|
let componentLosses: [ComponentPressureLoss]
|
||||||
let equivalentLengths: EffectiveLength.MaxContainer
|
let equivalentLengths: EquivalentLength.MaxContainer
|
||||||
let frictionRate: FrictionRate?
|
let frictionRate: FrictionRate?
|
||||||
|
|
||||||
private var availableStaticPressure: Double? {
|
private var availableStaticPressure: Double? {
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ extension ManualDClient {
|
|||||||
func frictionRate(
|
func frictionRate(
|
||||||
equipmentInfo: EquipmentInfo?,
|
equipmentInfo: EquipmentInfo?,
|
||||||
componentLosses: [ComponentPressureLoss],
|
componentLosses: [ComponentPressureLoss],
|
||||||
effectiveLength: EffectiveLength.MaxContainer
|
effectiveLength: EquivalentLength.MaxContainer
|
||||||
) async throws -> FrictionRate? {
|
) async throws -> FrictionRate? {
|
||||||
guard let staticPressure = equipmentInfo?.staticPressure else {
|
guard let staticPressure = equipmentInfo?.staticPressure else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
2
TODO.md
2
TODO.md
@@ -1,7 +1,7 @@
|
|||||||
# TODO's
|
# TODO's
|
||||||
|
|
||||||
- [x] Fix theme not working when selected upon signup.
|
- [x] Fix theme not working when selected upon signup.
|
||||||
- [ ] Pdf generation
|
- [x] Pdf generation
|
||||||
- [ ] Add postgres / mysql support
|
- [ ] Add postgres / mysql support
|
||||||
- [ ] Opensource / license ??
|
- [ ] Opensource / license ??
|
||||||
- [ ] Figure out domain to host (currently thinking ductcalc.pro)
|
- [ ] Figure out domain to host (currently thinking ductcalc.pro)
|
||||||
|
|||||||
@@ -78,10 +78,10 @@ struct ProjectRouteTests {
|
|||||||
let p = Body {
|
let p = Body {
|
||||||
FormData {
|
FormData {
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("id", default: nil) { EffectiveLength.ID.parser() }
|
Field("id", default: nil) { EquivalentLength.ID.parser() }
|
||||||
}
|
}
|
||||||
Field("name", .string)
|
Field("name", .string)
|
||||||
Field("type") { EffectiveLength.EffectiveLengthType.parser() }
|
Field("type") { EquivalentLength.EffectiveLengthType.parser() }
|
||||||
Many {
|
Many {
|
||||||
Field("straightLengths") {
|
Field("straightLengths") {
|
||||||
Int.parser()
|
Int.parser()
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ struct ViewControllerTests {
|
|||||||
let project = Project.mock
|
let project = Project.mock
|
||||||
let rooms = Room.mock(projectID: project.id)
|
let rooms = Room.mock(projectID: project.id)
|
||||||
let equipment = EquipmentInfo.mock(projectID: project.id)
|
let equipment = EquipmentInfo.mock(projectID: project.id)
|
||||||
let tels = EffectiveLength.mock(projectID: project.id)
|
let tels = EquivalentLength.mock(projectID: project.id)
|
||||||
let componentLosses = ComponentPressureLoss.mock(projectID: project.id)
|
let componentLosses = ComponentPressureLoss.mock(projectID: project.id)
|
||||||
let trunks = TrunkSize.mock(projectID: project.id, rooms: rooms)
|
let trunks = TrunkSize.mock(projectID: project.id, rooms: rooms)
|
||||||
|
|
||||||
|
|||||||
36
docker/Dockerfile.test
Normal file
36
docker/Dockerfile.test
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
FROM docker.io/swift:6.2-noble
|
||||||
|
|
||||||
|
# Make sure all system packages are up to date, and install only essential packages.
|
||||||
|
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
|
||||||
|
&& apt-get -q update \
|
||||||
|
&& apt-get -q dist-upgrade -y \
|
||||||
|
&& apt-get -q install -y \
|
||||||
|
libjemalloc2 \
|
||||||
|
ca-certificates \
|
||||||
|
tzdata \
|
||||||
|
# If your app or its dependencies import FoundationNetworking, also install `libcurl4`.
|
||||||
|
libcurl4 \
|
||||||
|
# If your app or its dependencies import FoundationXML, also install `libxml2`.
|
||||||
|
# libxml2 \
|
||||||
|
sqlite3 \
|
||||||
|
&& rm -r /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Set up a build area
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# First just resolve dependencies.
|
||||||
|
# This creates a cached layer that can be reused
|
||||||
|
# as long as your Package.swift/Package.resolved
|
||||||
|
# files do not change.
|
||||||
|
COPY ./Package.* ./
|
||||||
|
RUN swift package resolve \
|
||||||
|
$([ -f ./Package.resolved ] && echo "--force-resolved-versions" || true)
|
||||||
|
|
||||||
|
# Copy entire repo into container
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ENV SWIFT_BACKTRACE=enable=no
|
||||||
|
ENV LOG_LEVEL=debug
|
||||||
|
|
||||||
|
CMD ["swift", "test"]
|
||||||
|
|
||||||
7
justfile
7
justfile
@@ -14,7 +14,10 @@ run:
|
|||||||
@swift run App serve --log debug
|
@swift run App serve --log debug
|
||||||
|
|
||||||
build-docker file="docker/Dockerfile":
|
build-docker file="docker/Dockerfile":
|
||||||
@podman build -f {{file}} -t {{docker_image}}:{{docker_tag}} .
|
@docker build -f {{file}} -t {{docker_image}}:{{docker_tag}} .
|
||||||
|
|
||||||
run-docker:
|
run-docker:
|
||||||
@podman run -it --rm -v $PWD:/app -p 8080:8080 {{docker_image}}:{{docker_tag}}
|
@docker run -it --rm -v $PWD:/app -p 8080:8080 {{docker_image}}:{{docker_tag}}
|
||||||
|
|
||||||
|
test-docker: (build-docker "docker/Dockerfile.test")
|
||||||
|
@docker run --rm {{docker_image}}:{{docker_tag}} swift test
|
||||||
|
|||||||
Reference in New Issue
Block a user