• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / supabase-swift / 31011736834

05 Aug 2026 01:45PM UTC coverage: 83.849% (-0.04%) from 83.888%
31011736834

push

github

web-flow
refactor(auth): deprecate customizable JSON encoder/decoder (#1165)

* refactor(auth): deprecate customizable JSON encoder/decoder

There is no real use case for customizing Auth's JSON encoding/decoding
per-instance. Deprecate `Configuration.encoder`/`.decoder` and the
init overloads that accept them, in favor of new inits that always use
the internal default. Behavior is unchanged for now (deprecated inits
still honor a custom encoder/decoder) -- this only starts the removal
path for a future major version.

Internal call sites now read a non-deprecated `resolvedEncoder`/
`resolvedDecoder` pair instead of the deprecated public properties, to
keep the SDK's own code warning-free.

* fix(auth): restore single-codec deprecated init overloads

The new encoder/decoder-accepting init required both arguments, so a
caller previously passing only encoder: (or only decoder:) on the
fuller-signature init (with logger/redirectToURL/etc.) no longer
compiled. Add encoder-only and decoder-only deprecated overloads,
alongside the existing both-codecs one, each defaulting the omitted
codec. Add compile coverage for all four single-codec call forms.

* fix(ci): add "initializers" to spell-check dictionary

Plural form was missing from all bundled cspell dictionaries, failing
CI on Sources/Auth/AuthClientConfiguration.swift.

* fix(ci): disable parallel test execution in xcodebuild test runs

withMainSerialExecutor (ConcurrencyExtras) hooks a process-wide task-enqueue
global, not just the calling suite's own tasks. Swift Testing's default
parallel execution runs unrelated suites concurrently in the same process, so
while any withMainSerialExecutor-gated suite (AuthClientTests, SessionManagerTests,
RealtimeTests, RealtimeIntegrationTests) holds that hook, every other
concurrently-running suite's tasks get silently forced onto the same serial
queue too. Under CI's loaded iOS Simulator this backs up enough to blow
through hardcoded test timeouts (e.g. AuthClientTests.ass... (continued)

87 of 93 new or added lines in 11 files covered. (93.55%)

27 existing lines in 4 files now uncovered.

8452 of 10080 relevant lines covered (83.85%)

40.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.35
/Sources/Helpers/AnyJSON/AnyJSON.swift
1
import Foundation
2

3
public typealias JSONObject = [String: AnyJSON]
4
public typealias JSONArray = [AnyJSON]
5

6
/// An enumeration that represents JSON-compatible values of various types.
7
public enum AnyJSON: Sendable, Codable, Hashable {
8
  /// Represents a `null` JSON value.
9
  case null
10
  /// Represents a JSON boolean value.
11
  case bool(Bool)
12
  /// Represents a JSON number (integer) value.
13
  case integer(Int)
14
  /// Represents a JSON number (floating-point) value.
15
  case double(Double)
16
  /// Represents a JSON string value.
17
  case string(String)
18
  /// Represents a JSON object (dictionary) value.
19
  case object(JSONObject)
20
  /// Represents a JSON array (list) value.
21
  case array(JSONArray)
22

23
  /// Returns the underlying Swift value corresponding to the `AnyJSON` instance.
24
  ///
25
  /// - Note: For `.object` and `.array` cases, the returned value contains recursively transformed `AnyJSON` instances.
26
  public var value: Any {
48✔
27
    switch self {
48✔
28
    case .null: NSNull()
48✔
29
    case .string(let string): string
48✔
30
    case .integer(let val): val
48✔
31
    case .double(let val): val
48✔
32
    case .object(let dictionary): dictionary.mapValues(\.value)
48✔
33
    case .array(let array): array.map(\.value)
48✔
34
    case .bool(let bool): bool
48✔
35
    }
48✔
36
  }
48✔
37

38
  public var isNil: Bool {
7✔
39
    if case .null = self {
7✔
40
      return true
1✔
41
    }
6✔
42

6✔
43
    return false
6✔
44
  }
7✔
45

46
  public var boolValue: Bool? {
10✔
47
    if case .bool(let val) = self {
10✔
48
      return val
4✔
49
    }
6✔
50
    return nil
6✔
51
  }
10✔
52

53
  public var objectValue: JSONObject? {
341✔
54
    if case .object(let dictionary) = self {
341✔
55
      return dictionary
333✔
56
    }
333✔
57
    return nil
8✔
58
  }
341✔
59

60
  public var arrayValue: JSONArray? {
23✔
61
    if case .array(let array) = self {
23✔
62
      return array
17✔
63
    }
17✔
64
    return nil
6✔
65
  }
23✔
66

67
  public var stringValue: String? {
761✔
68
    if case .string(let string) = self {
761✔
69
      return string
683✔
70
    }
683✔
71
    return nil
78✔
72
  }
761✔
73

74
  public var intValue: Int? {
12✔
75
    if case .integer(let val) = self {
12✔
76
      return val
6✔
77
    }
6✔
78
    return nil
6✔
79
  }
12✔
80

81
  public var doubleValue: Double? {
9✔
82
    if case .double(let val) = self {
9✔
83
      return val
3✔
84
    }
6✔
85
    return nil
6✔
86
  }
9✔
87

88
  public init(from decoder: any Decoder) throws {
4,978✔
89
    let container = try decoder.singleValueContainer()
4,978✔
90

4,978✔
91
    if container.decodeNil() {
4,978✔
92
      self = .null
315✔
93
    } else if let val = try? container.decode(Int.self) {
315✔
94
      self = .integer(val)
150✔
95
    } else if let val = try? container.decode(Double.self) {
150✔
96
      self = .double(val)
8✔
97
    } else if let val = try? container.decode(String.self) {
2,478✔
98
      self = .string(val)
2,478✔
99
    } else if let val = try? container.decode(Bool.self) {
2,478✔
100
      self = .bool(val)
756✔
101
    } else if let val = try? container.decode(JSONArray.self) {
756✔
102
      self = .array(val)
522✔
103
    } else if let val = try? container.decode(JSONObject.self) {
749✔
104
      self = .object(val)
749✔
105
    } else {
749✔
UNCOV
106
      throw DecodingError.dataCorrupted(
×
UNCOV
107
        .init(codingPath: decoder.codingPath, debugDescription: "Invalid JSON value.")
×
UNCOV
108
      )
×
109
    }
4,978✔
110
  }
4,978✔
111

112
  public func encode(to encoder: any Encoder) throws {
3,362✔
113
    var container = encoder.singleValueContainer()
3,362✔
114
    switch self {
3,362✔
115
    case .null: try container.encodeNil()
3,362✔
116
    case .array(let val): try container.encode(val)
3,362✔
117
    case .object(let val): try container.encode(val)
3,362✔
118
    case .string(let val): try container.encode(val)
3,362✔
119
    case .integer(let val): try container.encode(val)
3,362✔
120
    case .double(let val): try container.encode(val)
3,362✔
121
    case .bool(let val): try container.encode(val)
3,362✔
122
    }
3,362✔
123
  }
3,362✔
124
}
125

126
extension AnyJSON: ExpressibleByNilLiteral {
127
  public init(nilLiteral _: ()) {
68✔
128
    self = .null
68✔
129
  }
68✔
130
}
131

132
extension AnyJSON: ExpressibleByStringLiteral {
133
  public init(stringLiteral value: String) {
363✔
134
    self = .string(value)
363✔
135
  }
363✔
136
}
137

138
extension AnyJSON: ExpressibleByArrayLiteral {
139
  public init(arrayLiteral elements: AnyJSON...) {
108✔
140
    self = .array(elements)
108✔
141
  }
108✔
142
}
143

144
extension AnyJSON: ExpressibleByIntegerLiteral {
145
  public init(integerLiteral value: Int) {
480✔
146
    self = .integer(value)
480✔
147
  }
480✔
148
}
149

150
extension AnyJSON: ExpressibleByFloatLiteral {
151
  public init(floatLiteral value: Double) {
67✔
152
    self = .double(value)
67✔
153
  }
67✔
154
}
155

156
extension AnyJSON: ExpressibleByBooleanLiteral {
157
  public init(booleanLiteral value: Bool) {
74✔
158
    self = .bool(value)
74✔
159
  }
74✔
160
}
161

162
extension AnyJSON: ExpressibleByDictionaryLiteral {
163
  public init(dictionaryLiteral elements: (String, AnyJSON)...) {
247✔
164
    self = .object(Dictionary(uniqueKeysWithValues: elements))
247✔
165
  }
247✔
166
}
167

168
extension AnyJSON: CustomStringConvertible {
169
  public var description: String {
11✔
170
    String(describing: value)
11✔
171
  }
11✔
172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc