Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Examples/ProductionProfile/ProductionProfileExample.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation
import NovaNetworkClient

@main
struct ProductionProfileExample {
static func main() async {
let generator = NetworkClientProductionProfileGenerator()
let profile = generator.generate(
goal: .offlineFirst,
overlays: [.offlineDurability, .strictReliability],
offlineStoreConfigured: false
)

print("Goal: \(profile.goal.rawValue)")
print("Base preset: \(profile.basePreset.kind.rawValue)")
print("Overlays: \(profile.overlays.map { $0.rawValue }.joined(separator: ", "))")
print("Production ready: \(profile.validation.isProductionReady)")
if !profile.validation.issues.isEmpty {
print("Validation issues:")
for issue in profile.validation.issues {
print("- [\(issue.severity.rawValue)] \(issue.code): \(issue.message)")
print(" Recommendation: \(issue.recommendation)")
}
}

print("\nBootstrap snippet:\n")
print(profile.bootstrapSnippet(includeOfflineStore: true))
}
}
105 changes: 24 additions & 81 deletions Examples/README.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,50 @@
# Examples
# Examples Reference Cookbook

Runnable examples for `NovaNetworkClient`.
Runnable and test-backed scenarios for `NovaNetworkClient`.

## JSONPlaceholder Coalescing
## Quick Start

Uses the public API [https://jsonplaceholder.typicode.com](https://jsonplaceholder.typicode.com) to show:
- typed decoding;
- request coalescing for identical concurrent requests.

Run:
Build all examples:

```bash
swift run NovaNetworkClientJSONPlaceholderExample
swift build
```

## Batch Loading

Shows `loadBatch` with several JSONPlaceholder endpoints and typed decoding.

Run:
Run cookbook contract tests:

```bash
swift run NovaNetworkClientBatchTodosExample
swift test --filter NetworkingCoverageTests
```

## Middleware
## Cookbook Scenarios

Shows request middleware (`beforeSend`) by injecting custom headers and validating them via [https://httpbin.org/anything](https://httpbin.org/anything).
| Scenario ID | Focus | Example target | Contract test |
|---|---|---|---|
| CB-1 | Coalesced typed read | `NovaNetworkClientJSONPlaceholderExample` | `cookbookScenarioCoalescedRequestUsesSingleTransportCall` |
| CB-2 | Preset composition v2 (`base + overlays`) | `NovaNetworkClientDiagnosticsReferenceExample` | `presetV2CompositionAppliesOverlayOrder` |
| CB-3 | Production validator anti-patterns | `NovaNetworkClientProductionProfileExample` | `presetV2ValidatorFlagsOfflineQueueWithoutStoreAsBlocking` |
| CB-4 | Offline queue onboarding baseline | `NovaNetworkClientOfflineQueueExample` | `enqueueWriteQueuesWhenOfflineAndAppliesDefaultIdempotencyKey` |
| CB-5 | Telemetry onboarding baseline | `NovaNetworkClientDiagnosticsReferenceExample` | `telemetryHooksEmitCoalescerRetryAndCancellationContracts` |
| CB-6 | Production profile generator (DX 2.0) | `NovaNetworkClientProductionProfileExample` | `cookbookScenarioProductionProfileForOfflineFirstRequiresStore` |

Run:
## Run Commands

```bash
swift run NovaNetworkClientJSONPlaceholderExample
swift run NovaNetworkClientBatchTodosExample
swift run NovaNetworkClientMiddlewareExample
```

## Offline Queue

Shows `enqueueWrite` with durable `DiskOfflineWriteStore` and queue depth inspection.

Run:

```bash
swift run NovaNetworkClientOfflineQueueExample
```

## WebSocket

Shows realtime connect/send/receive over a public echo endpoint (`wss://ws.postman-echo.com/raw`) with state observation.

Run:

```bash
swift run NovaNetworkClientWebSocketExample
```

Optional endpoint override:

```bash
NOVA_WS_URL=wss://ws.ifelse.io swift run NovaNetworkClientWebSocketExample
```

## Reference: Auth Refresh

Shows a reference app flow where an expired bearer token gets a `401`, refreshes token state, and retries with `NetworkClientPreset.restHeavy`.

Run:

```bash
swift run NovaNetworkClientAuthRefreshReferenceExample
```

## Reference: Reconnect Recovery

Shows a reference app flow for WebSocket reconnect recovery with queue pressure diagnostics and telemetry stream output.

Run:

```bash
swift run NovaNetworkClientReconnectRecoveryReferenceExample
```

Optional endpoint override:

```bash
NOVA_WS_URL=wss://ws.ifelse.io swift run NovaNetworkClientReconnectRecoveryReferenceExample
```

## Reference: Offline Replay

Shows `NetworkClientPreset.offlineFirst` with durable writes and replay/metrics inspection.

Run:

```bash
swift run NovaNetworkClientOfflineReplayReferenceExample
swift run NovaNetworkClientDiagnosticsReferenceExample
swift run NovaNetworkClientProductionProfileExample
```

## Reference: Observability and Diagnostics

Shows request event stream + telemetry hooks + runtime policy update events as a diagnostics baseline.

Run:
Optional WebSocket endpoint override:

```bash
swift run NovaNetworkClientDiagnosticsReferenceExample
NOVA_WS_URL=wss://ws.ifelse.io swift run NovaNetworkClientWebSocketExample
NOVA_WS_URL=wss://ws.ifelse.io swift run NovaNetworkClientReconnectRecoveryReferenceExample
```
6 changes: 6 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ let package = Package(
.executable(name: "NovaNetworkClientReconnectRecoveryReferenceExample", targets: ["NovaNetworkClientReconnectRecoveryReferenceExample"]),
.executable(name: "NovaNetworkClientOfflineReplayReferenceExample", targets: ["NovaNetworkClientOfflineReplayReferenceExample"]),
.executable(name: "NovaNetworkClientDiagnosticsReferenceExample", targets: ["NovaNetworkClientDiagnosticsReferenceExample"]),
.executable(name: "NovaNetworkClientProductionProfileExample", targets: ["NovaNetworkClientProductionProfileExample"]),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
Expand Down Expand Up @@ -87,5 +88,10 @@ let package = Package(
dependencies: ["NovaNetworkClient"],
path: "Examples/DiagnosticsReference"
),
.executableTarget(
name: "NovaNetworkClientProductionProfileExample",
dependencies: ["NovaNetworkClient"],
path: "Examples/ProductionProfile"
),
]
)
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ When multiple callers ask for the same resource at the same time, only one under
- [Telemetry Contract v2](docs/TELEMETRY_CONTRACT_V2.md)
- [v1.15 Traceability Pack](docs/TRACEABILITY_PACK_v1.15.md)
- [v1.16 Traceability Pack](docs/TRACEABILITY_PACK_v1.16.md)
- [v1.19 Traceability Pack](docs/TRACEABILITY_PACK_v1.19.md)

## Product Delivery Templates

Expand Down Expand Up @@ -71,7 +72,14 @@ targets: [
- `NetworkClientPreset.restHeavy`
- `NetworkClientPreset.realtimeHeavy`
- `NetworkClientPreset.offlineFirst`
- Presets v2 composition model (`base preset + overlays`) via:
- `NetworkClientPreset.compose(base:overlays:)`
- `NetworkClientPresetOverlayKind`
- Safe preset override points via `NetworkClientPreset.RequestOverrides` (merge-only overrides).
- Production onboarding helpers:
- `NetworkClientProductionProfileGenerator`
- `NetworkClientPresetValidator` / `validateProductionReadiness`
- anti-pattern validation report with blocking vs warning findings.
- Testable retry behavior via injectable clock and random generator.
- Data and typed `Decodable` loading APIs.
- Typed error mapping overloads (`errorMapper`).
Expand Down Expand Up @@ -142,6 +150,35 @@ let payload = try await client.load(
)
```

## DX 2.0 Production Profile Quick Start (v1.19)

```swift
import Foundation
import NovaNetworkClient

let profile = NetworkClientProductionProfileGenerator().generate(
goal: .offlineFirst,
overlays: [.offlineDurability, .strictReliability],
offlineStoreConfigured: true
)

guard profile.validation.isProductionReady else {
for issue in profile.validation.issues {
print("[\(issue.severity.rawValue)] \(issue.code): \(issue.message)")
}
fatalError("Fix production validation issues before rollout.")
}

let preset = profile.composedPreset
let client = NetworkClient(
transport: Transport(),
retryPolicy: preset.retryPolicy,
defaultCachePolicy: preset.defaultCachePolicy,
offlineWriteStore: DiskOfflineWriteStore(directoryURL: queueURL)
)
await client.applyRuntimePolicy(from: preset)
```

## Examples

### 1) Typed GET Request
Expand Down
Loading