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
2 changes: 1 addition & 1 deletion Sources/StreamAttachments/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>0.6.1</string>
<string>0.6.2</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
Expand Down
2 changes: 1 addition & 1 deletion Sources/StreamCore/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>0.6.1</string>
<string>0.6.2</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
Expand Down
13 changes: 8 additions & 5 deletions Sources/StreamCore/OpenAPI/Query/Filter+Local.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,14 @@
case .exists:
return Self.exists(localRawJSONValue, filterRawJSONValue)
case .equal:
return Self.isEqual(localRawJSONValue, filterRawJSONValue)
switch value {
case is CircularRegion:
return Self.isNear(localRawJSONValue, filterRawJSONValue)
case is BoundingBox:
return Self.isWithinBounds(localRawJSONValue, filterRawJSONValue)
default:
return Self.isEqual(localRawJSONValue, filterRawJSONValue)
}
case .greater:
return Self.isGreater(localRawJSONValue, filterRawJSONValue)
case .greaterOrEqual:
Expand All @@ -123,10 +130,6 @@
return Self.isIn(localRawJSONValue, filterRawJSONValue)
case .pathExists:
return Self.pathExists(localRawJSONValue, filterRawJSONValue)
case .near:
return Self.isNear(localRawJSONValue, filterRawJSONValue)
case .withinBounds:
return Self.isWithinBounds(localRawJSONValue, filterRawJSONValue)
case .and, .or:
log.debug("Should never try to match compound operators")
return false
Expand All @@ -134,7 +137,7 @@
}

static func exists(_ localRawJSONValue: RawJSON, _ filterRawJSONValue: RawJSON) -> Bool {
switch filterRawJSONValue {

Check warning on line 140 in Sources/StreamCore/OpenAPI/Query/Filter+Local.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "switch" statement with "if" statement to increase readability.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqjHvXclxoqwtCNw&open=AZrejqjHvXclxoqwtCNw&pullRequest=41
case .bool(let exists): exists ? !localRawJSONValue.isNil : localRawJSONValue.isNil
default: false
}
Expand Down Expand Up @@ -177,7 +180,7 @@
}

static func autocomplete(_ localRawJSONValue: RawJSON, _ filterRawJSONValue: RawJSON) -> Bool {
switch (localRawJSONValue, filterRawJSONValue) {

Check warning on line 183 in Sources/StreamCore/OpenAPI/Query/Filter+Local.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "switch" statement with "if" statement to increase readability.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqjHvXclxoqwtCNx&open=AZrejqjHvXclxoqwtCNx&pullRequest=41
case (.string(let localStringValue), .string(let filterStringValue)):
Self.postgreSQLFullTextSearch(anchored: true, text: localStringValue, query: filterStringValue)
default:
Expand All @@ -186,7 +189,7 @@
}

static func query(_ localRawJSONValue: RawJSON, _ filterRawJSONValue: RawJSON) -> Bool {
switch (localRawJSONValue, filterRawJSONValue) {

Check warning on line 192 in Sources/StreamCore/OpenAPI/Query/Filter+Local.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "switch" statement with "if" statement to increase readability.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqjHvXclxoqwtCNy&open=AZrejqjHvXclxoqwtCNy&pullRequest=41
case (.string(let localStringValue), .string(let filterStringValue)):
Self.postgreSQLFullTextSearch(anchored: false, text: localStringValue, query: filterStringValue)
default:
Expand Down Expand Up @@ -219,7 +222,7 @@
}

static func isIn(_ localRawJSONValue: RawJSON, _ filterRawJSONValue: RawJSON) -> Bool {
switch filterRawJSONValue {

Check warning on line 225 in Sources/StreamCore/OpenAPI/Query/Filter+Local.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "switch" statement with "if" statement to increase readability.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqjHvXclxoqwtCNz&open=AZrejqjHvXclxoqwtCNz&pullRequest=41
case .array(let rawJSONArrayValue):
rawJSONArrayValue.contains(localRawJSONValue)
default:
Expand All @@ -228,7 +231,7 @@
}

static func pathExists(_ localRawJSONValue: RawJSON, _ filterRawJSONValue: RawJSON) -> Bool {
switch (localRawJSONValue, filterRawJSONValue) {

Check warning on line 234 in Sources/StreamCore/OpenAPI/Query/Filter+Local.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "switch" statement with "if" statement to increase readability.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqjHvXclxoqwtCN0&open=AZrejqjHvXclxoqwtCN0&pullRequest=41
case (.dictionary(let dictionaryValue), .string(let path)):
let components = path.components(separatedBy: ".")
guard !components.isEmpty else { return false }
Expand All @@ -248,7 +251,7 @@
}

static func isNear(_ localRawJSONValue: RawJSON, _ filterRawJSONValue: RawJSON) -> Bool {
switch (localRawJSONValue, filterRawJSONValue) {

Check warning on line 254 in Sources/StreamCore/OpenAPI/Query/Filter+Local.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "switch" statement with "if" statement to increase readability.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqjHvXclxoqwtCN1&open=AZrejqjHvXclxoqwtCN1&pullRequest=41
case (.dictionary(let localDictionaryValue), .dictionary(let filterDictionaryValue)):
guard let location = CLLocationCoordinate2D(from: localDictionaryValue) else { return false }
guard let filterRegion = CircularRegion(from: filterDictionaryValue) else { return false }
Expand All @@ -259,7 +262,7 @@
}

static func isWithinBounds(_ localRawJSONValue: RawJSON, _ filterRawJSONValue: RawJSON) -> Bool {
switch (localRawJSONValue, filterRawJSONValue) {

Check warning on line 265 in Sources/StreamCore/OpenAPI/Query/Filter+Local.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "switch" statement with "if" statement to increase readability.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqjHvXclxoqwtCN2&open=AZrejqjHvXclxoqwtCN2&pullRequest=41
case (.dictionary(let localDictionaryValue), .dictionary(let filterDictionaryValue)):
guard let location = CLLocationCoordinate2D(from: localDictionaryValue) else { return false }
guard let filterRegion = BoundingBox(from: filterDictionaryValue) else { return false }
Expand Down
27 changes: 0 additions & 27 deletions Sources/StreamCore/OpenAPI/Query/Filter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
/// - field: The field to check.
/// - values: An array of values to check against.
/// - Returns: A filter that matches when the field's value is in the specified array.
public static func `in`<Value>(_ field: FilterField, _ values: [Value]) -> Self where Value: FilterValue {

Check warning on line 124 in Sources/StreamCore/OpenAPI/Query/Filter.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove backticks (`) from "in" and rename it.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqj2vXclxoqwtCN3&open=AZrejqj2vXclxoqwtCN3&pullRequest=41
Self(filterOperator: .in, field: field, value: values)
}

Expand Down Expand Up @@ -195,33 +195,6 @@
Self(filterOperator: .query, field: field, value: value)
}

/// Creates a filter that uses the Haversine formula to find values
/// within the specified distance from the given coordinates.
///
/// This filter matches locations that fall within a circular region defined by a center point
/// and a radius. The distance calculation uses the Haversine formula to account for Earth's curvature.
///
/// - Parameters:
/// - field: The field containing location coordinates to query.
/// - value: The circular region defining the center point and radius to match against.
/// - Returns: A filter that matches when the location field is within the specified circular region.
public static func near(_ field: FilterField, _ value: CircularRegion) -> Self {
Self(filterOperator: .near, field: field, value: value)
}

/// Creates a filter that finds values within the specified rectangular bounding box.
///
/// This filter matches locations that fall within a rectangular geographic region defined by
/// northeast and southwest corner coordinates.
///
/// - Parameters:
/// - field: The field containing location coordinates to query.
/// - value: The bounding box defining the rectangular region to match against.
/// - Returns: A filter that matches when the location field is within the specified bounding box.
public static func withinBounds(_ field: FilterField, _ value: BoundingBox) -> Self {
Self(filterOperator: .withinBounds, field: field, value: value)
}

/// Creates a filter that combines multiple filters with a logical AND operation.
///
/// - Parameter filters: An array of filters to combine.
Expand Down
6 changes: 0 additions & 6 deletions Sources/StreamCore/OpenAPI/Query/FilterOperator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
case lessOrEqual = "$lte"

/// Matches any of the values specified in an array.
case `in` = "$in"

Check warning on line 24 in Sources/StreamCore/OpenAPI/Query/FilterOperator.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove backticks (`) from "in" and rename it.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-core-swift&issues=AZrejqkLvXclxoqwtCN4&open=AZrejqkLvXclxoqwtCN4&pullRequest=41

/// Matches values by performing text search with the specified value.
case query = "$q"
Expand All @@ -43,12 +43,6 @@

/// Matches if the value contains JSON with the given path.
case pathExists = "$path_exists"

/// Matches if the location is within the specified circular area.
case near = "$near"

/// Matches if the location is within the specified rectangular area.
case withinBounds = "$within_bounds"
}

extension FilterOperator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ extension BoundingBox: FilterValue {
}
}

extension CLLocationCoordinate2D: @unchecked Sendable, FilterValue {
extension CLLocationCoordinate2D: @unchecked @retroactive Sendable, FilterValue {
static let rawJSONLatitudeKey = "lat"
static let rawJSONLongitudeKey = "lng"

Expand Down
2 changes: 1 addition & 1 deletion Sources/StreamCore/Utils/SystemEnvironment+Version.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import Foundation

enum SystemEnvironment {
/// A Stream Core version.
public static let version: String = "0.6.1"
public static let version: String = "0.6.2"
}
2 changes: 1 addition & 1 deletion Sources/StreamCoreUI/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>0.6.1</string>
<string>0.6.2</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
Expand Down
27 changes: 14 additions & 13 deletions Tests/StreamCoreTests/OpenAPI/Query/Filter_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ struct Filter_Tests {
static let createdAt = Self("created_at", localValue: \.createdAt)
static let isActive = Self("is_active", localValue: \.isActive)
static let searchData = Self("search_data", localValue: \.searchData)
static let location = Self("location", localValue: \.location)
static let nearLocation = Self("near", localValue: \.location)
static let withinBoundsLocation = Self("within_bounds", localValue: \.location)
}

struct TestFilter: Filter {
Expand Down Expand Up @@ -261,12 +262,12 @@ struct Filter_Tests {
@Test func nearFilter() {
let center = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
let region = CircularRegion(center: center, radiusInMeters: 5000)
let filter = TestFilter.near(.location, region)
let filter = TestFilter.equal(.nearLocation, region)
let json = filter.toRawJSONDictionary()

let expected: [String: RawJSON] = [
"location": .dictionary([
"$near": .dictionary([
"near": .dictionary([
"$eq": .dictionary([
"lat": .number(37.7749),
"lng": .number(-122.4194),
"distance": .number(5.0) // 5000 meters = 5 km
Expand All @@ -281,12 +282,12 @@ struct Filter_Tests {
let northeast = CLLocationCoordinate2D(latitude: 40.7580, longitude: -73.9855)
let southwest = CLLocationCoordinate2D(latitude: 40.7128, longitude: -74.0060)
let boundingBox = BoundingBox(northeast: northeast, southwest: southwest)
let filter = TestFilter.withinBounds(.location, boundingBox)
let filter = TestFilter.equal(.withinBoundsLocation, boundingBox)
let json = filter.toRawJSONDictionary()

let expected: [String: RawJSON] = [
"location": .dictionary([
"$within_bounds": .dictionary([
"within_bounds": .dictionary([
"$eq": .dictionary([
"ne_lat": .number(40.7580),
"ne_lng": .number(-73.9855),
"sw_lat": .number(40.7128),
Expand Down Expand Up @@ -1137,7 +1138,7 @@ struct Filter_Tests {
let center = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194) // San Francisco
let region = CircularRegion(center: center, radiusInMeters: 5000) // 5 km radius

let nearFilter = TestFilter.near(.location, region)
let nearFilter = TestFilter.equal(.nearLocation, region)

// Location at center should match
#expect(nearFilter.matches(TestUser(location: center)))
Expand All @@ -1152,7 +1153,7 @@ struct Filter_Tests {

// Test with smaller radius
let smallRegion = CircularRegion(center: center, radiusInMeters: 100) // 100 meters radius
let smallNearFilter = TestFilter.near(.location, smallRegion)
let smallNearFilter = TestFilter.equal(.nearLocation, smallRegion)

// Location at center should match
#expect(smallNearFilter.matches(TestUser(location: center)))
Expand All @@ -1162,7 +1163,7 @@ struct Filter_Tests {

// Test with radius in kilometers
let regionInKM = CircularRegion(center: center, radiusInKM: 10.0) // 10 km radius
let nearFilterInKM = TestFilter.near(.location, regionInKM)
let nearFilterInKM = TestFilter.equal(.nearLocation, regionInKM)

// Location within 10 km should match
#expect(nearFilterInKM.matches(TestUser(location: nearbyLocation)))
Expand All @@ -1180,7 +1181,7 @@ struct Filter_Tests {
let southwest = CLLocationCoordinate2D(latitude: 40.7128, longitude: -74.0060) // Lower Manhattan
let boundingBox = BoundingBox(northeast: northeast, southwest: southwest)

let withinBoundsFilter = TestFilter.withinBounds(.location, boundingBox)
let withinBoundsFilter = TestFilter.equal(.withinBoundsLocation, boundingBox)

// Location at northeast corner should match
#expect(withinBoundsFilter.matches(TestUser(location: northeast)))
Expand Down Expand Up @@ -1212,7 +1213,7 @@ struct Filter_Tests {
let sfNortheast = CLLocationCoordinate2D(latitude: 37.8044, longitude: -122.4094)
let sfSouthwest = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
let sfBoundingBox = BoundingBox(northeast: sfNortheast, southwest: sfSouthwest)
let sfWithinBoundsFilter = TestFilter.withinBounds(.location, sfBoundingBox)
let sfWithinBoundsFilter = TestFilter.equal(.withinBoundsLocation, sfBoundingBox)

// Location within SF bounding box should match
let sfLocation = CLLocationCoordinate2D(latitude: 37.7897, longitude: -122.4144)
Expand All @@ -1225,7 +1226,7 @@ struct Filter_Tests {
let smallNortheast = CLLocationCoordinate2D(latitude: 37.7751, longitude: -122.4192)
let smallSouthwest = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
let smallBoundingBox = BoundingBox(northeast: smallNortheast, southwest: smallSouthwest)
let smallWithinBoundsFilter = TestFilter.withinBounds(.location, smallBoundingBox)
let smallWithinBoundsFilter = TestFilter.equal(.withinBoundsLocation, smallBoundingBox)

// Location at southwest corner should match
#expect(smallWithinBoundsFilter.matches(TestUser(location: smallSouthwest)))
Expand Down
Loading