IDGenerator
February 23, 2026 · View on GitHub
A flexible, keyed registry of ID generators for Swift.
Overview
The IDGenerator package provides IDGeneratorValues, a keyed registry of generators
that lets you decouple your code from any specific ID generation strategy — so you can
swap in a deterministic generator during testing without changing the code under test.
Rather than coupling a component to a single generator type (e.g. UUID), you define a
key per use case and inject only what each component needs:
struct UserRepository {
@Dependency(\.idGenerators.userID) var userID
}
struct LogFileManager {
@Dependency(\.idGenerators.logFilename) var logFilename
}
Each component declares the minimum dependency it requires. Swapping generators in tests is scoped to that one key, leaving everything else unaffected.
The package ships two libraries:
IDGenerator— the core registry with no external dependencies.IDGeneratorDependency— optional integration with swift-dependencies by Point-Free.
Quick Start
1. Conform a Generator
Conform your generator type to IDGenerator and provide a default instance:
struct SequentialIDGenerator: IDGenerator {
static let `default` = SequentialIDGenerator()
func callAsFunction() -> Int { ... }
}
Note: If you're using
IDGeneratorDependency, aIDGeneratorconformance forUUIDGeneratoris already provided out of the box — no extra setup needed.
2. Register a Key and Accessor
Define a GeneratorKey key and an IDGeneratorValues computed property, named after
the use case — not the generator type:
extension GeneratorKey where Value == UUIDGenerator {
static let userID = Self("userID")
}
extension IDGeneratorValues {
var userID: UUIDGenerator {
get { self[.userID] }
set { self[.userID] = newValue }
}
}
3. Inject and Use
Inject the scoped generator directly into your component:
struct UserRepository {
@Dependency(\.idGenerators.userID) var userID
func createUser() -> User {
User(id: userID())
}
}
4. Override in Tests
Use withDependencies to replace a single generator with a deterministic alternative:
@Test
func createsUserWithIncrementingID() {
withDependencies {
\$0.idGenerators.userID = .incrementing
} operation: {
let repo = UserRepository()
let user = repo.createUser()
#expect(user.id == UUID(uuidString: "00000000-0000-0000-0000-000000000000"))
}
}
Installation
Add swift-id-generator to your Package.swift:
dependencies: [
.package(url: "https://github.com/ShivaHuang/swift-id-generator", from: "0.1.0"),
],
Then add the product you need to your target:
IDGenerator— core registry only, no external dependencies.IDGeneratorDependency— includesIDGeneratorand integrates with swift-dependencies.
.target(
name: "MyApp",
dependencies: [
// Core only:
.product(name: "IDGenerator", package: "swift-id-generator"),
// Or with swift-dependencies integration:
.product(name: "IDGeneratorDependency", package: "swift-id-generator"),
]
),
Credits
The IDGeneratorDependency module is designed to work with
swift-dependencies by
Point-Free. Their library provides the dependency
management infrastructure that IDGeneratorDependency builds upon.
License
This library is released under the MIT license. See LICENSE for details.