From eacb35c0352d8e3f6cf68a4e1449f7b976a324c5 Mon Sep 17 00:00:00 2001 From: Stream Bot Date: Wed, 19 Nov 2025 11:23:59 +0000 Subject: [PATCH 1/3] Update release version to snapshot --- Sources/StreamCore/Utils/SystemEnvironment+Version.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/StreamCore/Utils/SystemEnvironment+Version.swift b/Sources/StreamCore/Utils/SystemEnvironment+Version.swift index 08c4202..c5c7a15 100644 --- a/Sources/StreamCore/Utils/SystemEnvironment+Version.swift +++ b/Sources/StreamCore/Utils/SystemEnvironment+Version.swift @@ -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.7.0-SNAPSHOT" } From 761dcad88d4654958642a29e61bd3d5c2ac2da91 Mon Sep 17 00:00:00 2001 From: Toomas Vahter Date: Tue, 2 Dec 2025 11:58:30 +0200 Subject: [PATCH 2/3] Near and within_bounds are field names with operator (#40) --- .../OpenAPI/Query/Filter+Local.swift | 13 +++++---- Sources/StreamCore/OpenAPI/Query/Filter.swift | 27 ------------------- .../OpenAPI/Query/FilterOperator.swift | 6 ----- .../OpenAPI/Query/FilterValue+Location.swift | 2 +- .../OpenAPI/Query/Filter_Tests.swift | 27 ++++++++++--------- 5 files changed, 23 insertions(+), 52 deletions(-) diff --git a/Sources/StreamCore/OpenAPI/Query/Filter+Local.swift b/Sources/StreamCore/OpenAPI/Query/Filter+Local.swift index c46d37b..be10638 100644 --- a/Sources/StreamCore/OpenAPI/Query/Filter+Local.swift +++ b/Sources/StreamCore/OpenAPI/Query/Filter+Local.swift @@ -104,7 +104,14 @@ private struct FilterMatcher: Sendable where Model: Sendable, Valu 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: @@ -123,10 +130,6 @@ private struct FilterMatcher: Sendable where Model: Sendable, Valu 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 diff --git a/Sources/StreamCore/OpenAPI/Query/Filter.swift b/Sources/StreamCore/OpenAPI/Query/Filter.swift index 55951f3..f9dcdee 100644 --- a/Sources/StreamCore/OpenAPI/Query/Filter.swift +++ b/Sources/StreamCore/OpenAPI/Query/Filter.swift @@ -195,33 +195,6 @@ extension Filter { 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. diff --git a/Sources/StreamCore/OpenAPI/Query/FilterOperator.swift b/Sources/StreamCore/OpenAPI/Query/FilterOperator.swift index 9ccca5f..0ea21d8 100644 --- a/Sources/StreamCore/OpenAPI/Query/FilterOperator.swift +++ b/Sources/StreamCore/OpenAPI/Query/FilterOperator.swift @@ -43,12 +43,6 @@ public enum FilterOperator: String, Sendable { /// 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 { diff --git a/Sources/StreamCore/OpenAPI/Query/FilterValue+Location.swift b/Sources/StreamCore/OpenAPI/Query/FilterValue+Location.swift index c0dfbc7..a1aa599 100644 --- a/Sources/StreamCore/OpenAPI/Query/FilterValue+Location.swift +++ b/Sources/StreamCore/OpenAPI/Query/FilterValue+Location.swift @@ -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" diff --git a/Tests/StreamCoreTests/OpenAPI/Query/Filter_Tests.swift b/Tests/StreamCoreTests/OpenAPI/Query/Filter_Tests.swift index 2ee98d0..945ffd8 100644 --- a/Tests/StreamCoreTests/OpenAPI/Query/Filter_Tests.swift +++ b/Tests/StreamCoreTests/OpenAPI/Query/Filter_Tests.swift @@ -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 { @@ -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 @@ -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), @@ -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))) @@ -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))) @@ -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))) @@ -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))) @@ -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) @@ -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))) From 61c57f0c18a9bfa440f19b9222029fb9c4c15dcf Mon Sep 17 00:00:00 2001 From: Stream Bot Date: Tue, 2 Dec 2025 10:02:41 +0000 Subject: [PATCH 3/3] Bump 0.6.2 --- Sources/StreamAttachments/Info.plist | 2 +- Sources/StreamCore/Info.plist | 2 +- Sources/StreamCore/Utils/SystemEnvironment+Version.swift | 2 +- Sources/StreamCoreUI/Info.plist | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/StreamAttachments/Info.plist b/Sources/StreamAttachments/Info.plist index 9d6c403..b781e87 100644 --- a/Sources/StreamAttachments/Info.plist +++ b/Sources/StreamAttachments/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 0.6.1 + 0.6.2 CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/Sources/StreamCore/Info.plist b/Sources/StreamCore/Info.plist index 9d6c403..b781e87 100644 --- a/Sources/StreamCore/Info.plist +++ b/Sources/StreamCore/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 0.6.1 + 0.6.2 CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/Sources/StreamCore/Utils/SystemEnvironment+Version.swift b/Sources/StreamCore/Utils/SystemEnvironment+Version.swift index c5c7a15..3e5113b 100644 --- a/Sources/StreamCore/Utils/SystemEnvironment+Version.swift +++ b/Sources/StreamCore/Utils/SystemEnvironment+Version.swift @@ -6,5 +6,5 @@ import Foundation enum SystemEnvironment { /// A Stream Core version. - public static let version: String = "0.7.0-SNAPSHOT" + public static let version: String = "0.6.2" } diff --git a/Sources/StreamCoreUI/Info.plist b/Sources/StreamCoreUI/Info.plist index 9d6c403..b781e87 100644 --- a/Sources/StreamCoreUI/Info.plist +++ b/Sources/StreamCoreUI/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 0.6.1 + 0.6.2 CFBundleVersion $(CURRENT_PROJECT_VERSION)