-
Notifications
You must be signed in to change notification settings - Fork 0
ConfigValueReading: dependency-free source-precedence value reads + explicit precedence contract #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
def859a
e1508de
c65c88c
4c5d1e1
408f24f
84acb3c
5a626f6
6cfa51b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # CLAUDE.md | ||
|
|
||
| This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. | ||
|
|
||
| ## What this is | ||
|
|
||
| ConfigKeyKit is a tiny, **dependency-free, Foundation-only** Swift 6.2 library (single `ConfigKeyKit` library product). It defines configuration keys whose base name resolves to per-source key strings — e.g. `cloudkit.container_id` on the CLI vs. `MYAPP_CLOUDKIT_CONTAINER_ID` in the environment. It deliberately does **not** depend on `apple/swift-configuration`; it produces key strings you feed into whatever provider stack you use. Keep it dependency-free — adding a dependency is a design change, not a routine edit. | ||
|
|
||
| ## Commands | ||
|
|
||
| - `make build` / `swift build` — build | ||
| - `make test` / `swift test` — run the full suite (Swift Testing, not XCTest) | ||
| - Run one test: `swift test --filter ConfigKeyTests` (suite) or `swift test --filter "ConfigKey with default"` (by `@Test` display name) | ||
| - `make lint` — runs `Scripts/lint.sh`: swift-format, SwiftLint, license-header check, and `periphery` dead-code scan | ||
| - `make clean` | ||
|
|
||
| Lint/format tooling is pinned via **mise** (`mise.toml`): swift-format 602.0.0, SwiftLint 0.62.2, periphery 3.7.4. Run `mise install` once so `Scripts/lint.sh` can find them outside CI. `Scripts/lint.sh` is env-driven: `LINT_MODE` (`STRICT` adds `--strict`/`--configuration`; `NONE`/`INSTALL` short-circuit), `FORMAT_ONLY=1` skips lint+build, and outside CI it auto-formats in place before linting. | ||
|
|
||
| ## Architecture | ||
|
|
||
| Two loosely-related feature sets live in one product: | ||
|
|
||
| **Config keys** (the core purpose) — A `ConfigurationKey` protocol exposes one method: `key(for: ConfigKeySource) -> String?`. Two concrete value types implement it: | ||
| - `ConfigKey<Value>` — has a required `defaultValue` (resolution is non-optional). | ||
| - `OptionalConfigKey<Value>` — no default (resolves to optional). | ||
|
|
||
| Both store the same three fields: `baseKey`, a `styles` map (`ConfigKeySource -> NamingStyle`), and an `explicitKeys` override map. `key(for:)` checks `explicitKeys` first, otherwise transforms `baseKey` through the source's `NamingStyle`. `ConfigKeySource` is just `.commandLine` / `.environment`. `NamingStyle` is a protocol; `StandardNamingStyle` provides `.dotSeparated` (CLI, identity) and `.screamingSnakeCase(prefix:)` (ENV, uppercases + replaces `.` with `_`, optional prefix). The convenience init `ConfigKey("base", envPrefix:, default:)` wires these two standard styles automatically. `ConfigKey+Bool.swift` adds `Bool`-specialized inits; `+Debug` files add `CustomDebugStringConvertible`. | ||
|
|
||
| **CLI scaffolding** (optional, ignore if you only need keys) — A lightweight command-dispatch layer: `Command` protocol (associated `Config: ConfigurationParseable`, static metadata, async `createInstance()`/`execute()`), the `CommandRegistry` **actor** (concurrency-safe registry, `.shared` singleton plus `internal init()` for isolated test instances), `CommandLineParser` (splits argv into command name + args), and `ConfigurationParseable` (async parse-from-sources protocol; `BaseConfig == Never` means a root config and unlocks the parentless convenience init). | ||
|
|
||
| ## Conventions | ||
|
|
||
| - **Swift 6.2** with these upcoming features enabled in `Package.swift` (apply them in new code): `ExistentialAny` (write `any NamingStyle`), `InternalImportsByDefault` (mark imports `public import` / `internal import` explicitly — e.g. Foundation is `internal import Foundation`), `MemberImportVisibility`, `FullTypedThrows`. | ||
| - Everything is `Sendable`; preserve that. | ||
| - SwiftLint runs with many opt-in rules including `explicit_acl` / `explicit_top_level_acl` (declare access control explicitly on every declaration) and `force_unwrapping` (no `!`). `file_name` is enforced — the primary type's name must match the filename; extensions use the `Type+Feature.swift` pattern. | ||
| - Every source file carries the MIT license header (copyright "Leo Dion" / "BrightDigit"); `Scripts/header.sh` enforces it. New files need it. | ||
| - `periphery.yml` sets `retain_public: true`, so public API is never flagged as dead code. | ||
|
|
||
| ## Note | ||
|
|
||
| `ConfigKeyKit.git/` in the working tree is a bare git repo (a mirror clone), not part of the package — leave it alone. | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -35,3 +35,13 @@ public enum ConfigKeySource: CaseIterable, Sendable { | |||||
| /// Environment variables (e.g., CLOUDKIT_CONTAINER_ID) | ||||||
| case environment | ||||||
| } | ||||||
|
|
||||||
| extension ConfigKeySource: PrioritizedConfigKeySource { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add explicit ACL to the extension declaration. Line 39 introduces a top-level Suggested fix-extension ConfigKeySource: PrioritizedConfigKeySource {
+public extension ConfigKeySource: PrioritizedConfigKeySource {As per coding guidelines, "Declare access control explicitly on every declaration using explicit_acl and explicit_top_level_acl rules enforced by SwiftLint." 📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSource: Coding guidelines |
||||||
| /// Sources in precedence order, highest first: command line overrides | ||||||
| /// environment. | ||||||
| /// | ||||||
| /// This order is part of the public API. `ConfigValueReading` resolution | ||||||
| /// consults sources in this sequence, and it is pinned explicitly so it stays | ||||||
| /// independent of `case` declaration order. | ||||||
| public static let priority: [ConfigKeySource] = [.commandLine, .environment] | ||||||
| } | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct the protocol name in architecture guidance.
Line 23 documents
ConfigurationKey, but the project contract usesConfigKey. This will send contributors to the wrong symbol/API naming.Based on learnings: The ConfigKey protocol has
key(for: ConfigKeySource) -> String?as its single required method.🤖 Prompt for AI Agents
Source: Learnings