Project updates from Template #1
@@ -26,8 +26,13 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
shouldAutocreateTestPlan = "YES">
|
<TestPlans>
|
||||||
|
<TestPlanReference
|
||||||
|
reference = "container:Tests/Website.xctestplan"
|
||||||
|
default = "YES">
|
||||||
|
</TestPlanReference>
|
||||||
|
</TestPlans>
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
skipped = "NO">
|
skipped = "NO">
|
||||||
|
|||||||
+2
-2
@@ -18,8 +18,8 @@
|
|||||||
skipped = "NO">
|
skipped = "NO">
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "WebsiteCoreTests"
|
BlueprintIdentifier = "WebsiteLibraryTests"
|
||||||
BuildableName = "WebsiteCoreTests"
|
BuildableName = "WebsiteLibraryTests"
|
||||||
ReferencedContainer = "container:">
|
ReferencedContainer = "container:">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</TestableReference>
|
</TestableReference>
|
||||||
@@ -15,7 +15,7 @@ let package = Package(
|
|||||||
name: "Website",
|
name: "Website",
|
||||||
targets: [
|
targets: [
|
||||||
"Website",
|
"Website",
|
||||||
"WebsiteCore",
|
"WebsiteLibrary",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -56,7 +56,7 @@ let package = Package(
|
|||||||
name: "Website",
|
name: "Website",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.byName(name: "Persistence"),
|
.byName(name: "Persistence"),
|
||||||
.byName(name: "WebsiteCore"),
|
.byName(name: "WebsiteLibrary"),
|
||||||
.product(
|
.product(
|
||||||
name: "Configuration",
|
name: "Configuration",
|
||||||
package: "swift-configuration"
|
package: "swift-configuration"
|
||||||
@@ -73,7 +73,7 @@ let package = Package(
|
|||||||
path: "Sources/App"
|
path: "Sources/App"
|
||||||
),
|
),
|
||||||
.target(
|
.target(
|
||||||
name: "WebsiteCore",
|
name: "WebsiteLibrary",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.byName(name: "Localization"),
|
.byName(name: "Localization"),
|
||||||
.byName(name: "Persistence"),
|
.byName(name: "Persistence"),
|
||||||
@@ -113,9 +113,9 @@ let package = Package(
|
|||||||
path: "Tests/App"
|
path: "Tests/App"
|
||||||
),
|
),
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "WebsiteCoreTests",
|
name: "WebsiteLibraryTests",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.byName(name: "WebsiteCore"),
|
.byName(name: "WebsiteLibrary"),
|
||||||
.product(
|
.product(
|
||||||
name: "Elementary",
|
name: "Elementary",
|
||||||
package: "elementary"
|
package: "elementary"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ The **Loud** public website service — a [Hummingbird](https://github.com/hummi
|
|||||||
## Overview
|
## Overview
|
||||||
The service:
|
The service:
|
||||||
- Serves the landing page at `GET /` (rendered once per supported language with [Elementary](https://github.com/elementary-swift/elementary) and cached).
|
- Serves the landing page at `GET /` (rendered once per supported language with [Elementary](https://github.com/elementary-swift/elementary) and cached).
|
||||||
- Negotiates each request's language from its `Accept-Language` header against the languages in the `WebsiteCore` String Catalog, falling back to the default (`en`); pages are served from the per-language cache with `Content-Language` and `Vary: Accept-Language` headers.
|
- Negotiates each request's language from its `Accept-Language` header against the languages in the `WebsiteLibrary` String Catalog, falling back to the default (`en`); pages are served from the per-language cache with `Content-Language` and `Vary: Accept-Language` headers.
|
||||||
- Answers a liveness check at `GET /health` with a static JSON payload, and a readiness check at `GET /health/ready` that reports whether the database is reachable (`200` ready / `503` unavailable).
|
- Answers a liveness check at `GET /health` with a static JSON payload, and a readiness check at `GET /health/ready` that reports whether the database is reachable (`200` ready / `503` unavailable).
|
||||||
- Serves static files (CSS, JS, icons, manifest, `robots.txt`) from `Resources/Static` via Hummingbird's `FileMiddleware`, tagged with media-type-specific `Cache-Control`.
|
- Serves static files (CSS, JS, icons, manifest, `robots.txt`) from `Resources/Static` via Hummingbird's `FileMiddleware`, tagged with media-type-specific `Cache-Control`.
|
||||||
- Returns a custom HTML 404 page, localized like the landing page, for any request that matches neither a route nor a static file.
|
- Returns a custom HTML 404 page, localized like the landing page, for any request that matches neither a route nor a static file.
|
||||||
@@ -22,10 +22,10 @@ Two SwiftPM targets:
|
|||||||
| Target | Kind | Path | Role |
|
| Target | Kind | Path | Role |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `Website` | executable | `Sources/App` | Entry point: reads configuration, builds the persistence service, and either serves the website or runs the migrate-and-exit mode. |
|
| `Website` | executable | `Sources/App` | Entry point: reads configuration, builds the persistence service, and either serves the website or runs the migrate-and-exit mode. |
|
||||||
| `WebsiteCore` | library | `Sources/Library` | Controllers, middlewares, pages, cached responses, and configuration helpers. |
|
| `WebsiteLibrary` | library | `Sources/Library` | Controllers, middlewares, pages, cached responses, and configuration helpers. |
|
||||||
|
|
||||||
The `Website` executable depends on two local packages:
|
The `Website` executable depends on two local packages:
|
||||||
- `Localization` (`Packages/Localization`) — the `Localize` and `Negotiate` helpers and the `LanguageList` of catalog languages (used by `WebsiteCore`).
|
- `Localization` (`Packages/Localization`) — the `Localize` and `Negotiate` helpers and the `LanguageList` of catalog languages (used by `WebsiteLibrary`).
|
||||||
- `Persistence` (`Packages/Persistence`) — the Fluent-based data layer: the `Driver` selector, the `Service` factory that builds the `Fluent` service, the `PrepareDB` registrar that declares the migrations, and the `Probe` consulted by the readiness check; the models, migrations, and repositories stay internal to the package. It has no dependency on `swift-configuration`; the executable maps the `database.*` keys onto the driver.
|
- `Persistence` (`Packages/Persistence`) — the Fluent-based data layer: the `Driver` selector, the `Service` factory that builds the `Fluent` service, the `PrepareDB` registrar that declares the migrations, and the `Probe` consulted by the readiness check; the models, migrations, and repositories stay internal to the package. It has no dependency on `swift-configuration`; the executable maps the `database.*` keys onto the driver.
|
||||||
|
|
||||||
The persistence backend runs as a `Fluent` service inside the application's ServiceLifecycle group, so it starts and stops alongside the HTTP server (which owns its connection-pool shutdown on graceful termination).
|
The persistence backend runs as a `Fluent` service inside the application's ServiceLifecycle group, so it starts and stops alongside the HTTP server (which owns its connection-pool shutdown on graceful termination).
|
||||||
@@ -164,7 +164,7 @@ make pkg-test
|
|||||||
# = swift test --disable-xctest --enable-code-coverage --enable-swift-testing --parallel
|
# = swift test --disable-xctest --enable-code-coverage --enable-swift-testing --parallel
|
||||||
```
|
```
|
||||||
|
|
||||||
Tests use the [Swift Testing](https://developer.apple.com/documentation/testing/) framework. The `Website.xctestplan` covers two targets: `WebsiteTests` (the executable/integration tests) and `WebsiteCoreTests` (the library unit tests).
|
Tests use the [Swift Testing](https://developer.apple.com/documentation/testing/) framework. The `Website.xctestplan` covers two targets: `WebsiteTests` (the executable/integration tests) and `WebsiteLibraryTests` (the library unit tests).
|
||||||
|
|
||||||
The `Persistence` package has its own suite (run it from `Packages/Persistence`). Its tests run against the in-memory backend by default; the MySQL integration test is skipped unless a database is pointed at via `MYSQL_TEST_HOST` (with optional `MYSQL_TEST_PORT`/`NAME`/`USERNAME`/`PASSWORD`), so `swift test` stays runnable with no database:
|
The `Persistence` package has its own suite (run it from `Packages/Persistence`). Its tests run against the in-memory backend by default; the MySQL integration test is skipped unless a database is pointed at via `MYSQL_TEST_HOST` (with optional `MYSQL_TEST_PORT`/`NAME`/`USERNAME`/`PASSWORD`), so `swift test` stays runnable with no database:
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import Hummingbird
|
|||||||
import HummingbirdCompression
|
import HummingbirdCompression
|
||||||
import Logging
|
import Logging
|
||||||
import Persistence
|
import Persistence
|
||||||
import WebsiteCore
|
import WebsiteLibrary
|
||||||
|
|
||||||
/// Builds the website application.
|
/// Builds the website application.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Configuration
|
|||||||
import Hummingbird
|
import Hummingbird
|
||||||
import Logging
|
import Logging
|
||||||
import Persistence
|
import Persistence
|
||||||
import WebsiteCore
|
import WebsiteLibrary
|
||||||
|
|
||||||
package extension ConfigReader {
|
package extension ConfigReader {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import NIOCore
|
|||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import Website
|
@testable import Website
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("App executable")
|
@Suite("App executable")
|
||||||
struct AppTests {
|
struct AppTests {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("StaticFile enumeration")
|
@Suite("StaticFile enumeration")
|
||||||
struct StaticFileTests {
|
struct StaticFileTests {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Elementary
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("ErrorPage page")
|
@Suite("ErrorPage page")
|
||||||
struct ErrorPageTests {
|
struct ErrorPageTests {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Elementary
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("IndexPage page")
|
@Suite("IndexPage page")
|
||||||
struct IndexPageTests {
|
struct IndexPageTests {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import NIOCore
|
|||||||
import Persistence
|
import Persistence
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("HealthController controller")
|
@Suite("HealthController controller")
|
||||||
struct HealthControllerTests {
|
struct HealthControllerTests {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import HummingbirdTesting
|
|||||||
import NIOCore
|
import NIOCore
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("RootController controller")
|
@Suite("RootController controller")
|
||||||
struct RootControllerTests {
|
struct RootControllerTests {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import HummingbirdTesting
|
|||||||
import NIOCore
|
import NIOCore
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("LocalizationMiddleware middleware")
|
@Suite("LocalizationMiddleware middleware")
|
||||||
struct LocalizationMiddlewareTests {
|
struct LocalizationMiddlewareTests {
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ import HummingbirdTesting
|
|||||||
import NIOCore
|
import NIOCore
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("NotFoundMiddleware middleware")
|
@Suite("NotFoundMiddleware middleware")
|
||||||
struct NotFoundMiddlewareTests {
|
struct NotFoundMiddlewareTests {
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ import Hummingbird
|
|||||||
import HummingbirdTesting
|
import HummingbirdTesting
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
@testable import WebsiteCore
|
@testable import WebsiteLibrary
|
||||||
|
|
||||||
@Suite("SecurityHeadersMiddleware middleware")
|
@Suite("SecurityHeadersMiddleware middleware")
|
||||||
struct SecurityHeadersMiddlewareTests {
|
struct SecurityHeadersMiddlewareTests {
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
{
|
{
|
||||||
"target" : {
|
"target" : {
|
||||||
"containerPath" : "container:",
|
"containerPath" : "container:",
|
||||||
"identifier" : "WebsiteCoreTests",
|
"identifier" : "WebsiteLibraryTests",
|
||||||
"name" : "WebsiteCoreTests"
|
"name" : "WebsiteLibraryTests"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
Reference in New Issue
Block a user