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
6 changes: 3 additions & 3 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ let package = Package(
.macOS(.v13)
],
dependencies: [
.package(url: "https://github.com/featurevisor/featurevisor-swift2.git", from: "2.0.0")
.package(url: "https://github.com/featurevisor/featurevisor-swift2.git", from: "3.0.0")
],
targets: [
.executableTarget(
Expand Down
41 changes: 35 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,50 @@
# featurevisor-example-swift

Example application using Featurevisor [Swift SDK](https://github.com/featurevisor/featurevisor-swift2).
A small command line application showing how to use the [Featurevisor Swift SDK](https://github.com/featurevisor/featurevisor-swift2).

Learn more about Featurevisor [here](https://featurevisor.com).

## Installation
It fetches a production datafile, creates a Featurevisor instance with customer context, then evaluates a flag, a variation, feature variables, and global variables.

```bash
## Requirements

Swift 6.0 or newer.

## Run the example

```sh
swift package resolve
swift run featurevisor-example-swift
```

The application evaluates `commerce_platform`, `checkout_experience`, `max_items`, `payment_methods`, `serviceEndpoints`, and `supportContact` from this datafile:

```text
https://featurevisor-example-cloudflare.pages.dev/production/featurevisor-sdk-v3.json
```

Expected output:

```text
Commerce platform enabled: true
Checkout variation: express
Maximum checkout items: 25
Payment methods: [card, wallet]
Service endpoint: https://api.eu.example.com (timeout: 1200 ms, retries: 4)
Support contact: support-nl@example.com
```

## Usage
Change the context in `Sources/featurevisor-example-swift/main.swift` to see how Featurevisor selects different rules, variations, and global variable overrides.

## Checks

```bash
```sh
swift build
swift run featurevisor-example-swift
```

## Featurevisor project

Uses this Featurevisor project to fetch the datafile from: [https://github.com/featurevisor/featurevisor-example-cloudflare](https://github.com/featurevisor/featurevisor-example-cloudflare)
The datafile is generated by the [Featurevisor Cloudflare example](https://github.com/featurevisor/featurevisor-example-cloudflare).

Learn more in the [Featurevisor Swift SDK documentation](https://featurevisor.com/docs/sdks/swift/).
54 changes: 43 additions & 11 deletions Sources/featurevisor-example-swift/main.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
import Foundation
import Featurevisor
import Foundation

let datafileURL = URL(
string: "https://featurevisor-example-cloudflare.pages.dev/production/featurevisor-sdk-v3.json"
)!

let datafileURL = URL(string: "https://featurevisor-example-cloudflare.pages.dev/production/featurevisor-tag-all.json")!
var request = URLRequest(url: datafileURL)
request.timeoutInterval = 10
request.setValue("application/json", forHTTPHeaderField: "Accept")

let data = try Data(contentsOf: datafileURL)
let datafileContent = try DatafileContent.fromData(data)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200..<300).contains(httpResponse.statusCode) else {
throw URLError(.badServerResponse)
}

let datafile = try DatafileContent.fromData(data)
let f = createFeaturevisor(
FeaturevisorOptions(
datafile: datafileContent,
datafile: datafile,
context: [
"userId": .string("123"),
"deviceId": .string("device-23456"),
"country": .string("nl")
]
"userId": .string("customer-123"),
"country": .string("nl"),
"locale": .string("nl-NL"),
"accountPlan": .string("pro")
],
logLevel: .error
)
)

let featureIsEnabled = f.isEnabled("my_feature")
print("Feature is enabled: \(featureIsEnabled)")
let commerceEnabled = f.isEnabled("commerce_platform")
let checkoutVariation = f.getVariation("checkout_experience")
let maxItems = f.getVariableInteger("checkout_experience", "max_items")
let paymentMethods = f.getVariableArray("checkout_experience", "payment_methods")
let endpoints = f.getVariableObject("serviceEndpoints")
let supportContact = f.getVariableString("supportContact")

let methods = paymentMethods?
.compactMap { $0.asString() }
.joined(separator: ", ") ?? ""
let baseURL = endpoints?["baseUrl"]?.asString() ?? "unavailable"
let timeoutMS = endpoints?["timeoutMs"]?.asInt() ?? 0
let retries = endpoints?["retries"]?.asInt() ?? 0

print("Commerce platform enabled: \(commerceEnabled)")
print("Checkout variation: \(checkoutVariation ?? "unavailable")")
print("Maximum checkout items: \(maxItems.map(String.init) ?? "unavailable")")
print("Payment methods: [\(methods)]")
print("Service endpoint: \(baseURL) (timeout: \(timeoutMS) ms, retries: \(retries))")
print("Support contact: \(supportContact ?? "unavailable")")

f.close()
Loading