├── .github
└── workflows
│ └── tests.yml
├── .gitignore
├── .swiftpm
└── xcode
│ └── xcshareddata
│ └── xcschemes
│ └── Typesense.xcscheme
├── LICENSE
├── Package.resolved
├── Package.swift
├── README.md
├── Sources
└── Typesense
│ ├── Alias.swift
│ ├── Analytics.swift
│ ├── AnalyticsEvents.swift
│ ├── AnalyticsRule.swift
│ ├── AnalyticsRules.swift
│ ├── ApiCall.swift
│ ├── ApiKeys.swift
│ ├── Client.swift
│ ├── Collection.swift
│ ├── Collections.swift
│ ├── Configuration.swift
│ ├── ConversationModel.swift
│ ├── ConversationModels.swift
│ ├── Conversations.swift
│ ├── Document.swift
│ ├── Documents.swift
│ ├── Errors.swift
│ ├── Models
│ ├── AnalyticsEventCreateResponse.swift
│ ├── AnalyticsEventCreateSchema.swift
│ ├── AnalyticsRuleDeleteResponse.swift
│ ├── AnalyticsRuleParameters.swift
│ ├── AnalyticsRuleParametersDestination.swift
│ ├── AnalyticsRuleParametersSource.swift
│ ├── AnalyticsRuleParametersSourceEvents.swift
│ ├── AnalyticsRuleSchema.swift
│ ├── AnalyticsRuleUpsertSchema.swift
│ ├── AnalyticsRulesRetrieveSchema.swift
│ ├── ApiKey.swift
│ ├── ApiKeySchema.swift
│ ├── ApiKeysResponse.swift
│ ├── ApiResponse.swift
│ ├── CollectionAlias.swift
│ ├── CollectionAliasSchema.swift
│ ├── CollectionAliasesResponse.swift
│ ├── CollectionResponse.swift
│ ├── CollectionSchema.swift
│ ├── CollectionUpdateSchema.swift
│ ├── ConversationModelCreateSchema.swift
│ ├── ConversationModelSchema.swift
│ ├── ConversationModelUpdateSchema.swift
│ ├── DebugRetrieveSchema.swift
│ ├── DeleteDocumentsParameters.swift
│ ├── DeleteDocumentsResponse.swift
│ ├── DocumentIndexParameters.swift
│ ├── ExportDocumentsParameters.swift
│ ├── FacetCounts.swift
│ ├── FacetCountsCounts.swift
│ ├── FacetCountsStats.swift
│ ├── Field.swift
│ ├── FieldEmbed.swift
│ ├── FieldEmbedModelConfig.swift
│ ├── HealthStatus.swift
│ ├── ImportDocumentsParameters.swift
│ ├── InlineResponse2002.swift
│ ├── ModelErrorResponse.swift
│ ├── MultiSearchCollectionParameters.swift
│ ├── MultiSearchParameters.swift
│ ├── MultiSearchResult.swift
│ ├── MultiSearchSearchesParameter.swift
│ ├── PresetDeleteSchema.swift
│ ├── PresetSchema.swift
│ ├── PresetUpsertSchema.swift
│ ├── PresetValue.swift
│ ├── PresetsRetrieveSchema.swift
│ ├── ScopedKeyParameters.swift
│ ├── SearchGroupedHit.swift
│ ├── SearchHighlight.swift
│ ├── SearchOverride.swift
│ ├── SearchOverrideDeleteResponse.swift
│ ├── SearchOverrideExclude.swift
│ ├── SearchOverrideInclude.swift
│ ├── SearchOverrideRule.swift
│ ├── SearchOverrideSchema.swift
│ ├── SearchOverridesResponse.swift
│ ├── SearchParameters.swift
│ ├── SearchResult.swift
│ ├── SearchResultConversation.swift
│ ├── SearchResultHit.swift
│ ├── SearchResultRequestParams.swift
│ ├── SearchResultRequestParamsVoiceQuery.swift
│ ├── SearchSynonym.swift
│ ├── SearchSynonymSchema.swift
│ ├── SearchSynonymsResponse.swift
│ ├── SnapshotParameters.swift
│ ├── StopwordsSetDeleteSchema.swift
│ ├── StopwordsSetRetrieveSchema.swift
│ ├── StopwordsSetSchema.swift
│ ├── StopwordsSetUpsertSchema.swift
│ ├── StopwordsSetsRetrieveAllSchema.swift
│ ├── SuccessStatus.swift
│ ├── UpdateByFilterResponse.swift
│ ├── UpdateDocumentsByFilterParameters.swift
│ └── VoiceQueryModelCollectionConfig.swift
│ ├── MultiSearch.swift
│ ├── Node.swift
│ ├── Operations.swift
│ ├── Override.swift
│ ├── Overrides.swift
│ ├── Preset.swift
│ ├── Presets.swift
│ ├── RequestTypes.swift
│ ├── Shared
│ ├── Coders.swift
│ ├── Enums.swift
│ ├── Logger.swift
│ └── RequestNumber.swift
│ ├── Stopword.swift
│ ├── Stopwords.swift
│ ├── Synonyms.swift
│ └── utils
│ ├── CreateURLQueryParams.swift
│ └── Extensions.swift
├── Tests
└── TypesenseTests
│ ├── AnalyticsTests.swift
│ ├── ApiCallTests.swift
│ ├── ApiKeyTests.swift
│ ├── CollectionAliasTests.swift
│ ├── CollectionTests.swift
│ ├── ConfigurationTests.swift
│ ├── ConversationModelTests.swift
│ ├── CreateURLQueryParamsTests.swift
│ ├── DocumentTests.swift
│ ├── MultiSearchTests.swift
│ ├── OperationTests.swift
│ ├── OverrideTests.swift
│ ├── OverridesTests.swift
│ ├── PresetTests.swift
│ ├── PresetsTests.swift
│ ├── StopwordTests.swift
│ ├── StopwordsTests.swift
│ ├── SynonymTests.swift
│ └── TestUtils.swift
├── example
├── README.md
├── SwiftUI
│ └── RecipeSearchSwiftUI
│ │ ├── README.md
│ │ ├── RecipeSearch.gif
│ │ ├── RecipeSearchSwiftUI.xcodeproj
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── swiftpm
│ │ │ └── Package.resolved
│ │ └── RecipeSearchSwiftUI
│ │ ├── Assets.xcassets
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── appstore1024.png
│ │ │ ├── ipad152.png
│ │ │ ├── ipad76.png
│ │ │ ├── ipadNotification20.png
│ │ │ ├── ipadNotification40.png
│ │ │ ├── ipadPro167.png
│ │ │ ├── ipadSettings29.png
│ │ │ ├── ipadSettings58.png
│ │ │ ├── ipadSpotlight40.png
│ │ │ ├── ipadSpotlight80.png
│ │ │ ├── iphone120.png
│ │ │ ├── iphone180.png
│ │ │ ├── mac1024.png
│ │ │ ├── mac128.png
│ │ │ ├── mac16.png
│ │ │ ├── mac256.png
│ │ │ ├── mac32.png
│ │ │ ├── mac512.png
│ │ │ ├── mac64.png
│ │ │ ├── notification40.png
│ │ │ ├── notification60.png
│ │ │ ├── settings58.png
│ │ │ ├── settings87.png
│ │ │ ├── spotlight120.png
│ │ │ └── spotlight80.png
│ │ └── Contents.json
│ │ ├── ContentView.swift
│ │ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ │ ├── Recipe.swift
│ │ ├── RecipeDetailView.swift
│ │ └── RecipeSearchSwiftUIApp.swift
└── UIKit
│ └── RecipeSearchUIKit
│ ├── README.md
│ ├── RecipeSearch.gif
│ ├── RecipeSearchUIKit.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
│ └── RecipeSearchUIKit
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── Contents.json
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── Recipe.swift
│ ├── SceneDelegate.swift
│ └── ViewController.swift
└── get-models.sh
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: tests
2 |
3 | on:
4 | push:
5 | paths-ignore:
6 | - '**/*.md'
7 | pull_request:
8 | paths-ignore:
9 | - '**/*.md'
10 |
11 | # Cancel previous running if a new push is made
12 | # Source: https://stackoverflow.com/a/72408109/123545
13 | concurrency:
14 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
15 | cancel-in-progress: true
16 |
17 | jobs:
18 | test:
19 | runs-on: macos-latest
20 | steps:
21 | - uses: actions/checkout@v4
22 | - name: Install and start dependencies
23 | run: |
24 | brew install docker
25 | brew install qemu
26 | brew install colima
27 | # https://github.com/abiosoft/colima/issues/424#issuecomment-1335912905
28 | colima delete
29 | colima start --arch x86_64
30 |
31 | - name: Run Typesense
32 | run: |
33 | mkdir $(pwd)/typesense-data
34 | docker run -p 8108:8108 \
35 | -d \
36 | -v$(pwd)/typesense-data:/data typesense/typesense:28.0 \
37 | --data-dir /data \
38 | --api-key=xyz \
39 | --enable-cors
40 | shell: bash
41 |
42 | - name: Set up Xcode
43 | uses: maxim-lobanov/setup-xcode@v1.2.1
44 | with:
45 | xcode-version: latest-stable
46 |
47 | - name: Run tests
48 | run: swift test
49 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 | DerivedData/
7 | .swiftpm
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/xcshareddata/xcschemes/Typesense.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
43 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
61 |
67 |
68 |
69 |
71 |
77 |
78 |
79 |
80 |
81 |
91 |
92 |
98 |
99 |
105 |
106 |
107 |
108 |
110 |
111 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "AnyCodable",
6 | "repositoryURL": "https://github.com/Flight-School/AnyCodable",
7 | "state": {
8 | "branch": null,
9 | "revision": "862808b2070cd908cb04f9aafe7de83d35f81b05",
10 | "version": "0.6.7"
11 | }
12 | }
13 | ]
14 | },
15 | "version": 1
16 | }
17 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.5.0
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "Typesense",
8 | platforms: [
9 | .iOS(.v13), .macOS(.v10_15)
10 | ],
11 | products: [
12 | // Products define the executables and libraries a package produces, and make them visible to other packages.
13 | .library(
14 | name: "Typesense",
15 | targets: ["Typesense"]),
16 | ],
17 | dependencies: [
18 | // Dependencies declare other packages that this package depends on.
19 | // .package(url: /* package url */, from: "1.0.0"),
20 | .package(
21 | url: "https://github.com/Flight-School/AnyCodable",
22 | from: "0.6.0"
23 | ),
24 | ],
25 | targets: [
26 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
27 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
28 | .target(
29 | name: "Typesense",
30 | dependencies: ["AnyCodable"]),
31 | .testTarget(
32 | name: "TypesenseTests",
33 | dependencies: ["Typesense"]),
34 | ]
35 | )
36 |
--------------------------------------------------------------------------------
/Sources/Typesense/Alias.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct Alias {
7 | var apiCall: ApiCall
8 | let RESOURCEPATH = "aliases"
9 |
10 | init(apiCall: ApiCall) {
11 | self.apiCall = apiCall
12 | }
13 |
14 | public func upsert(name: String, collection: CollectionAliasSchema) async throws -> (CollectionAlias?, URLResponse?) {
15 | let schemaData = try encoder.encode(collection)
16 | let (data, response) = try await apiCall.put(endPoint: endpointPath(name), body: schemaData)
17 | if let result = data {
18 | let alias = try decoder.decode(CollectionAlias.self, from: result)
19 | return (alias, response)
20 | }
21 | return (nil, response)
22 | }
23 |
24 | public func retrieve(name: String) async throws -> (CollectionAlias?, URLResponse?) {
25 | let (data, response) = try await apiCall.get(endPoint: endpointPath(name))
26 | if let result = data {
27 | let alias = try decoder.decode(CollectionAlias.self, from: result)
28 | return (alias, response)
29 | }
30 | return (nil, response)
31 | }
32 |
33 | public func retrieve() async throws -> (CollectionAliasesResponse?, URLResponse?) {
34 | let (data, response) = try await apiCall.get(endPoint: endpointPath())
35 | if let result = data {
36 | let aliases = try decoder.decode(CollectionAliasesResponse.self, from: result)
37 | return (aliases, response)
38 | }
39 | return (nil, response)
40 | }
41 |
42 | public func delete(name: String) async throws -> (CollectionAlias?, URLResponse?) {
43 | let (data, response) = try await apiCall.delete(endPoint: endpointPath(name))
44 | if let result = data {
45 | let alias = try decoder.decode(CollectionAlias.self, from: result)
46 | return (alias, response)
47 | }
48 | return (nil, response)
49 | }
50 |
51 | private func endpointPath(_ operation: String? = nil) throws -> String {
52 | if let operation: String = operation {
53 | return try "\(RESOURCEPATH)/\(operation.encodeURL())"
54 | } else {
55 | return RESOURCEPATH
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Sources/Typesense/Analytics.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct Analytics {
4 | static let resourcePath: String = "/analytics"
5 |
6 | private var analyticsRules: AnalyticsRules
7 | var apiCall: ApiCall
8 |
9 | init(apiCall: ApiCall) {
10 | self.apiCall = apiCall
11 | self.analyticsRules = AnalyticsRules(apiCall: apiCall)
12 | }
13 |
14 | public func events() -> AnalyticsEvents {
15 | return AnalyticsEvents(apiCall: self.apiCall)
16 | }
17 |
18 | public func rule(id: String) -> AnalyticsRule {
19 | return AnalyticsRule(name: id, apiCall: self.apiCall)
20 | }
21 |
22 | public func rules() -> AnalyticsRules {
23 | return AnalyticsRules(apiCall: self.apiCall)
24 | }
25 | }
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Sources/Typesense/AnalyticsEvents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct AnalyticsEvents {
7 | static var resourcePath: String = "\(Analytics.resourcePath)/events"
8 | var apiCall: ApiCall
9 |
10 | init(apiCall: ApiCall) {
11 | self.apiCall = apiCall
12 | }
13 |
14 | public func create(params: AnalyticsEventCreateSchema) async throws -> (AnalyticsEventCreateResponse?, URLResponse?) {
15 | let json = try encoder.encode(params)
16 | let (data, response) = try await self.apiCall.post(endPoint: AnalyticsEvents.resourcePath, body: json)
17 | if let result = data {
18 | let validData = try decoder.decode(AnalyticsEventCreateResponse.self, from: result)
19 | return (validData, response)
20 | }
21 | return (nil, response)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Typesense/AnalyticsRule.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct AnalyticsRule {
7 | var name: String
8 | private var apiCall: ApiCall
9 | init(name: String, apiCall: ApiCall) {
10 | self.name = name
11 | self.apiCall = apiCall
12 | }
13 |
14 | public func retrieve() async throws -> (AnalyticsRuleSchema?, URLResponse?) {
15 | let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
16 | if let result = data {
17 | let fetchedRule = try decoder.decode(AnalyticsRuleSchema.self, from: result)
18 | return (fetchedRule, response)
19 | }
20 | return (nil, response)
21 | }
22 |
23 | public func delete() async throws -> (AnalyticsRuleDeleteResponse?, URLResponse?) {
24 | let (data, response) = try await self.apiCall.delete(endPoint: endpointPath())
25 | if let result = data {
26 | let deletedRule = try decoder.decode(AnalyticsRuleDeleteResponse.self, from: result)
27 | return (deletedRule, response)
28 | }
29 | return (nil, response)
30 | }
31 |
32 | private func endpointPath() throws -> String {
33 | return try "\(AnalyticsRules.resourcePath)/\(name.encodeURL())"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/Typesense/AnalyticsRules.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 |
7 | public struct AnalyticsRules {
8 | private var apiCall: ApiCall
9 | static var resourcePath: String = "\(Analytics.resourcePath)/rules"
10 |
11 | init(apiCall: ApiCall) {
12 | self.apiCall = apiCall
13 | }
14 |
15 | public func upsert(params: AnalyticsRuleSchema) async throws -> (AnalyticsRuleSchema?, URLResponse?) {
16 | let ruleData = try encoder.encode(params)
17 | let (data, response) = try await self.apiCall.put(endPoint: endpointPath(params.name), body: ruleData)
18 | if let result = data {
19 | let ruleResult = try decoder.decode(AnalyticsRuleSchema.self, from: result)
20 | return (ruleResult, response)
21 | }
22 |
23 | return (nil, response)
24 | }
25 |
26 | public func retrieveAll() async throws -> (AnalyticsRulesRetrieveSchema?, URLResponse?) {
27 | let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
28 | if let result = data {
29 | let rules = try decoder.decode(AnalyticsRulesRetrieveSchema.self, from: result)
30 | return (rules, response)
31 | }
32 |
33 | return (nil, response)
34 | }
35 |
36 | private func endpointPath(_ operation: String? = nil) throws -> String {
37 | if let operation = operation {
38 | return try "\(AnalyticsRules.resourcePath)/\(operation.encodeURL())"
39 | } else {
40 | return AnalyticsRules.resourcePath
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Typesense/ApiKeys.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 |
7 | public struct ApiKeys {
8 | var apiCall: ApiCall
9 | let RESOURCEPATH = "keys"
10 |
11 | init(apiCall: ApiCall) {
12 | self.apiCall = apiCall
13 | }
14 |
15 | public func create(_ keySchema: ApiKeySchema) async throws -> (ApiKey?, URLResponse?) {
16 | var schemaData: Data? = nil
17 |
18 | schemaData = try encoder.encode(keySchema)
19 |
20 | if let validSchema = schemaData {
21 | let (data, response) = try await apiCall.post(endPoint: "\(RESOURCEPATH)", body: validSchema)
22 | if let result = data {
23 | let keyResponse = try decoder.decode(ApiKey.self, from: result)
24 | return (keyResponse, response)
25 | }
26 | }
27 |
28 | return (nil, nil)
29 | }
30 |
31 | public func retrieve(id: Int) async throws -> (ApiKey?, URLResponse?) {
32 |
33 | let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)/\(id)")
34 | if let result = data {
35 | let keyResponse = try decoder.decode(ApiKey.self, from: result)
36 | return (keyResponse, response)
37 | }
38 |
39 | return (nil, nil)
40 | }
41 |
42 | public func retrieve() async throws -> (ApiKeysResponse?, URLResponse?) {
43 |
44 | let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)")
45 | if let result = data {
46 | let keyResponse = try decoder.decode(ApiKeysResponse.self, from: result)
47 | return (keyResponse, response)
48 | }
49 |
50 | return (nil, nil)
51 | }
52 |
53 | public func delete(id: Int) async throws -> (Data?, URLResponse?) {
54 |
55 | let (data, response) = try await apiCall.delete(endPoint: "\(RESOURCEPATH)/\(id)")
56 | return (data, response)
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Sources/Typesense/Client.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct Client {
4 |
5 | var configuration: Configuration
6 | var apiCall: ApiCall
7 | public var collections: Collections
8 |
9 | public init(config: Configuration) {
10 | self.configuration = config
11 | self.apiCall = ApiCall(config: config)
12 | self.collections = Collections(apiCall: apiCall)
13 | }
14 |
15 | public func collection(name: String) -> Collection {
16 | return Collection(apiCall: apiCall, collectionName: name)
17 | }
18 |
19 | public func conversations() -> Conversations {
20 | return Conversations(apiCall: apiCall)
21 | }
22 |
23 | public func keys() -> ApiKeys {
24 | return ApiKeys(apiCall: apiCall)
25 | }
26 |
27 | public func aliases() -> Alias {
28 | return Alias(apiCall: apiCall)
29 | }
30 |
31 | public func operations() -> Operations {
32 | return Operations(apiCall: apiCall)
33 | }
34 |
35 | public func multiSearch() -> MultiSearch {
36 | return MultiSearch(apiCall: apiCall)
37 | }
38 |
39 | public func analytics() -> Analytics {
40 | return Analytics(apiCall: apiCall)
41 | }
42 |
43 | public func presets() -> Presets {
44 | return Presets(apiCall: apiCall)
45 | }
46 |
47 | public func preset(_ presetName: String) -> Preset {
48 | return Preset(apiCall: apiCall, presetName: presetName)
49 | }
50 |
51 | public func stopwords() -> Stopwords {
52 | return Stopwords(apiCall: apiCall)
53 | }
54 |
55 | public func stopword(_ stopwordsSetId: String) -> Stopword {
56 | return Stopword(apiCall: apiCall, stopwordsSetId: stopwordsSetId)
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Sources/Typesense/Collection.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 |
7 | public struct Collection {
8 | var apiCall: ApiCall
9 | var collectionName: String
10 |
11 | init(apiCall: ApiCall, collectionName: String) {
12 | self.apiCall = apiCall
13 | self.collectionName = collectionName
14 | }
15 |
16 | public func documents() -> Documents {
17 | return Documents(apiCall: apiCall, collectionName: self.collectionName)
18 | }
19 |
20 | public func document(id: String) -> Document {
21 | return Document(apiCall: apiCall, collectionName: self.collectionName, id: id)
22 | }
23 |
24 | public func delete() async throws -> (CollectionResponse?, URLResponse?) {
25 | let (data, response) = try await apiCall.delete(endPoint: endpointPath())
26 | if let result = data {
27 | let fetchedCollection = try decoder.decode(CollectionResponse.self, from: result)
28 | return (fetchedCollection, response)
29 | }
30 | return (nil, response)
31 | }
32 |
33 | public func retrieve() async throws -> (CollectionResponse?, URLResponse?) {
34 | let (data, response) = try await apiCall.get(endPoint: endpointPath())
35 | if let result = data {
36 | let fetchedCollection = try decoder.decode(CollectionResponse.self, from: result)
37 | return (fetchedCollection, response)
38 | }
39 | return (nil, response)
40 | }
41 |
42 | public func synonyms() -> Synonyms {
43 | return Synonyms(apiCall: apiCall, collectionName: self.collectionName)
44 | }
45 |
46 | public func overrides() -> Overrides{
47 | return Overrides(apiCall: self.apiCall, collectionName: self.collectionName)
48 | }
49 |
50 | public func override(_ overrideId: String) -> Override{
51 | return Override(apiCall: self.apiCall, collectionName: self.collectionName, overrideId: overrideId)
52 | }
53 |
54 | private func endpointPath() throws -> String {
55 | return "\(Collections.RESOURCEPATH)/\(try collectionName.encodeURL())"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/Typesense/Collections.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 |
7 | public struct Collections {
8 | var apiCall: ApiCall
9 | static let RESOURCEPATH = "collections"
10 |
11 | init(apiCall: ApiCall) {
12 | self.apiCall = apiCall
13 | }
14 |
15 | public func create(schema: CollectionSchema) async throws -> (CollectionResponse?, URLResponse?) {
16 | var schemaData: Data? = nil
17 |
18 | schemaData = try encoder.encode(schema)
19 |
20 | if let validSchema = schemaData {
21 | let (data, response) = try await apiCall.post(endPoint: Collections.RESOURCEPATH, body: validSchema)
22 | if let result = data {
23 | let fetchedCollection = try decoder.decode(CollectionResponse.self, from: result)
24 | return (fetchedCollection, response)
25 | }
26 | }
27 | return (nil, nil)
28 | }
29 |
30 | public func retrieveAll() async throws -> ([CollectionResponse]?, URLResponse?) {
31 | let (data, response) = try await apiCall.get(endPoint: Collections.RESOURCEPATH)
32 |
33 | if let result = data {
34 | let fetchedCollections = try decoder.decode([CollectionResponse].self, from: result)
35 | return (fetchedCollections, response)
36 | }
37 | return (nil, response)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Typesense/Configuration.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct Configuration {
4 |
5 | //Required Config
6 | var nodes: [Node]
7 | var apiKey: String
8 |
9 | //Optional Config
10 | var nearestNode: Node? = nil
11 | var connectionTimeoutSeconds: Int = 10
12 | var healthcheckIntervalSeconds: Int = 15
13 | var numRetries: Int = 3
14 | var retryIntervalSeconds: Float = 0.1
15 | var sendApiKeyAsQueryParam: Bool = false
16 | var cacheSearchResultsForSeconds: Int = 0
17 | var useServerSideSearchCache: Bool = false
18 | var logger: Logger = Logger(debugMode: false)
19 |
20 | //Quick configurations
21 | public init(nodes: [Node], apiKey: String) {
22 | self.nodes = nodes
23 | self.apiKey = apiKey
24 | }
25 |
26 | public init(nodes: [Node], apiKey: String, connectionTimeoutSeconds: Int = 10, nearestNode: Node?) {
27 | self.nodes = nodes
28 | self.apiKey = apiKey
29 | self.connectionTimeoutSeconds = connectionTimeoutSeconds
30 | self.nearestNode = nearestNode
31 | }
32 |
33 | //Advanced configurations
34 | public init(nodes: [Node], apiKey: String, connectionTimeoutSeconds: Int = 10, nearestNode: Node? = nil, healthcheckIntervalSeconds: Int = 15, numRetries: Int = 3, retryIntervalSeconds: Float = 0.1, sendApiKeyAsQueryParam: Bool = false, cacheSearchResultsForSeconds: Int = 0, useServerSideSearchCache: Bool = false, logger: Logger = Logger(debugMode: false)) {
35 | self.nodes = nodes
36 | self.apiKey = apiKey
37 | self.connectionTimeoutSeconds = connectionTimeoutSeconds
38 | self.nearestNode = nearestNode
39 | self.healthcheckIntervalSeconds = healthcheckIntervalSeconds
40 | self.numRetries = numRetries
41 | self.retryIntervalSeconds = retryIntervalSeconds
42 | self.sendApiKeyAsQueryParam = sendApiKeyAsQueryParam
43 | self.cacheSearchResultsForSeconds = cacheSearchResultsForSeconds
44 | self.useServerSideSearchCache = useServerSideSearchCache
45 | self.logger = logger
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/Typesense/ConversationModel.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct ConversationModel {
7 | private var apiCall: ApiCall
8 | var modelId: String
9 |
10 | init(apiCall: ApiCall, modelId: String) {
11 | self.apiCall = apiCall
12 | self.modelId = modelId
13 | }
14 |
15 | public func update(params: ConversationModelUpdateSchema) async throws -> (ConversationModelSchema?, URLResponse?) {
16 | let schemaData = try encoder.encode(params)
17 | let (data, response) = try await self.apiCall.put(endPoint: endpointPath(), body: schemaData)
18 | if let result = data {
19 | let decodedData = try decoder.decode(ConversationModelSchema.self, from: result)
20 | return (decodedData, response)
21 | }
22 | return (nil, response)
23 | }
24 |
25 | public func retrieve() async throws -> (ConversationModelSchema?, URLResponse?) {
26 | let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
27 | if let result = data {
28 | let decodedData = try decoder.decode(ConversationModelSchema.self, from: result)
29 | return (decodedData, response)
30 | }
31 | return (nil, response)
32 | }
33 |
34 | public func delete() async throws -> (ConversationModelSchema?, URLResponse?) {
35 | let (data, response) = try await self.apiCall.delete(endPoint: endpointPath())
36 | if let result = data {
37 | let decodedData = try decoder.decode(ConversationModelSchema.self, from: result)
38 | return (decodedData, response)
39 | }
40 | return (nil, response)
41 | }
42 |
43 | private func endpointPath() throws -> String {
44 | return try "\(Conversations.RESOURCE_PATH)/\(ConversationModels.RESOURCE_PATH)/\(modelId.encodeURL())"
45 | }
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/Typesense/ConversationModels.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct ConversationModels {
7 | static let RESOURCE_PATH = "models"
8 | private var apiCall: ApiCall
9 |
10 |
11 | init(apiCall: ApiCall) {
12 | self.apiCall = apiCall
13 | }
14 |
15 | public func create(params: ConversationModelCreateSchema) async throws -> (ConversationModelSchema?, URLResponse?) {
16 | let schemaData = try encoder.encode(params)
17 | let (data, response) = try await self.apiCall.post(endPoint: endpointPath(), body: schemaData)
18 | if let result = data {
19 | let decodedData = try decoder.decode(ConversationModelSchema.self, from: result)
20 | return (decodedData, response)
21 | }
22 | return (nil, response)
23 | }
24 |
25 | public func retrieve() async throws -> ([ConversationModelSchema]?, URLResponse?) {
26 | let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
27 | if let result = data {
28 | let decodedData = try decoder.decode([ConversationModelSchema].self, from: result)
29 | return (decodedData, response)
30 | }
31 | return (nil, response)
32 | }
33 |
34 | private func endpointPath() throws -> String {
35 | return "\(Conversations.RESOURCE_PATH)/\(ConversationModels.RESOURCE_PATH)"
36 | }
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Typesense/Conversations.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct Conversations {
4 | static let RESOURCE_PATH = "conversations"
5 | private var apiCall: ApiCall
6 |
7 |
8 | init(apiCall: ApiCall) {
9 | self.apiCall = apiCall
10 | }
11 |
12 | public func models() -> ConversationModels {
13 | return ConversationModels(apiCall: apiCall)
14 | }
15 |
16 | public func model(modelId: String) -> ConversationModel {
17 | return ConversationModel(apiCall: apiCall, modelId: modelId)
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/Typesense/Document.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 |
7 | public struct Document {
8 | var apiCall: ApiCall
9 | var collectionName: String
10 | var id: String
11 |
12 | init(apiCall: ApiCall, collectionName: String, id: String) {
13 | self.apiCall = apiCall
14 | self.collectionName = collectionName
15 | self.id = id
16 | }
17 |
18 | public func delete() async throws -> (Data?, URLResponse?) {
19 | let (data, response) = try await apiCall.delete(endPoint: endpointPath())
20 | return (data, response)
21 | }
22 |
23 | public func retrieve() async throws -> (Data?, URLResponse?) {
24 | let (data, response) = try await apiCall.get(endPoint: endpointPath())
25 | return (data, response)
26 | }
27 |
28 | public func update(newDocument: Data, options: DocumentIndexParameters? = nil) async throws -> (Data?, URLResponse?) {
29 | let queryParams = try createURLQuery(forSchema: options)
30 | let (data, response) = try await apiCall.patch(endPoint: endpointPath(), body: newDocument, queryParameters: queryParams)
31 | return (data, response)
32 | }
33 |
34 | private func endpointPath() throws -> String {
35 | return try "\(Collections.RESOURCEPATH)/\(collectionName.encodeURL())/documents/\(id.encodeURL())"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/Typesense/Errors.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public enum HTTPError: Error {
4 | case serverError(code: Int, desc: String)
5 | case clientError(code: Int, desc: String)
6 | }
7 |
8 | extension HTTPError: LocalizedError {
9 | public var errorDescription: String? {
10 | func errorMessage(_ code: Int, _ desc: String) -> String{
11 | return NSLocalizedString("Request to server failed with code \(code). Message: \(desc)", comment: "Typesense error")
12 | }
13 | switch self {
14 | case .serverError(let code, let desc):
15 | return errorMessage(code, desc)
16 | case .clientError(let code, let desc):
17 | return errorMessage(code, desc)
18 | }
19 | }
20 | }
21 |
22 | public enum URLError: Error {
23 | case invalidURL
24 | case encodingError(message: String)
25 | }
26 |
27 | public enum DataError: Error {
28 | case unableToParse(message: String)
29 | case dataNotFound
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsEventCreateResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyticsEventCreateResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct AnalyticsEventCreateResponse: Codable {
13 |
14 | public var ok: Bool
15 |
16 | public init(ok: Bool) {
17 | self.ok = ok
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsEventCreateSchema.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct AnalyticsEventCreateSchema: Encodable {
6 |
7 | public var type: String
8 | public var name: String
9 | public var data: T
10 |
11 | public init(type: String, name: String, data: T) {
12 | self.type = type
13 | self.name = name
14 | self.data = data
15 | }
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsRuleDeleteResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyticsRuleDeleteResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct AnalyticsRuleDeleteResponse: Codable {
13 |
14 | public var name: String
15 |
16 | public init(name: String) {
17 | self.name = name
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsRuleParameters.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyticsRuleParameters.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct AnalyticsRuleParameters: Codable {
13 |
14 | public var source: AnalyticsRuleParametersSource
15 | public var destination: AnalyticsRuleParametersDestination
16 | public var limit: Int?
17 | public var expandQuery: Bool?
18 |
19 | public init(source: AnalyticsRuleParametersSource, destination: AnalyticsRuleParametersDestination, limit: Int? = nil, expandQuery: Bool? = nil) {
20 | self.source = source
21 | self.destination = destination
22 | self.limit = limit
23 | self.expandQuery = expandQuery
24 | }
25 |
26 | public enum CodingKeys: String, CodingKey {
27 | case source
28 | case destination
29 | case limit
30 | case expandQuery = "expand_query"
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsRuleParametersDestination.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyticsRuleParametersDestination.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct AnalyticsRuleParametersDestination: Codable {
13 |
14 | public var collection: String
15 | public var counterField: String?
16 |
17 | public init(collection: String, counterField: String? = nil) {
18 | self.collection = collection
19 | self.counterField = counterField
20 | }
21 |
22 | public enum CodingKeys: String, CodingKey {
23 | case collection
24 | case counterField = "counter_field"
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsRuleParametersSource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyticsRuleParametersSource.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct AnalyticsRuleParametersSource: Codable {
13 |
14 | public var collections: [String]
15 | public var events: [AnalyticsRuleParametersSourceEvents]?
16 |
17 | public init(collections: [String], events: [AnalyticsRuleParametersSourceEvents]? = nil) {
18 | self.collections = collections
19 | self.events = events
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsRuleParametersSourceEvents.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyticsRuleParametersSourceEvents.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct AnalyticsRuleParametersSourceEvents: Codable {
13 |
14 | public var type: String
15 | public var weight: Float
16 | public var name: String
17 |
18 | public init(type: String, weight: Float, name: String) {
19 | self.type = type
20 | self.weight = weight
21 | self.name = name
22 | }
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsRuleSchema.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct AnalyticsRuleSchema: Codable {
6 |
7 | public enum RuleType: String, Codable {
8 | case popularQueries = "popular_queries"
9 | case nohitsQueries = "nohits_queries"
10 | case counter = "counter"
11 | }
12 | public var name: String
13 | public var type: RuleType
14 | public var params: AnalyticsRuleParameters
15 |
16 | public init(name: String, type: RuleType, params: AnalyticsRuleParameters) {
17 | self.name = name
18 | self.type = type
19 | self.params = params
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsRuleUpsertSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyticsRuleUpsertSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct AnalyticsRuleUpsertSchema: Codable {
13 |
14 | public enum ModelType: String, Codable {
15 | case popularQueries = "popular_queries"
16 | case nohitsQueries = "nohits_queries"
17 | case counter = "counter"
18 | }
19 | public var type: ModelType
20 | public var params: AnalyticsRuleParameters
21 |
22 | public init(type: ModelType, params: AnalyticsRuleParameters) {
23 | self.type = type
24 | self.params = params
25 | }
26 |
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/AnalyticsRulesRetrieveSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyticsRulesRetrieveSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct AnalyticsRulesRetrieveSchema: Codable {
13 |
14 | public var rules: [AnalyticsRuleSchema]?
15 |
16 | public init(rules: [AnalyticsRuleSchema]? = nil) {
17 | self.rules = rules
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ApiKey.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ApiKey.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ApiKey: Codable {
13 |
14 | public var value: String?
15 | public var _description: String
16 | public var actions: [String]
17 | public var collections: [String]
18 | public var expiresAt: Int64?
19 | public var _id: Int
20 | public var valuePrefix: String?
21 |
22 | public init(value: String? = nil, _description: String, actions: [String], collections: [String], expiresAt: Int64? = nil, _id: Int, valuePrefix: String? = nil) {
23 | self.value = value
24 | self._description = _description
25 | self.actions = actions
26 | self.collections = collections
27 | self.expiresAt = expiresAt
28 | self._id = _id
29 | self.valuePrefix = valuePrefix
30 | }
31 |
32 | public enum CodingKeys: String, CodingKey {
33 | case value
34 | case _description = "description"
35 | case actions
36 | case collections
37 | case expiresAt = "expires_at"
38 | case _id = "id"
39 | case valuePrefix = "value_prefix"
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ApiKeySchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ApiKeySchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ApiKeySchema: Codable {
13 |
14 | public var value: String?
15 | public var _description: String
16 | public var actions: [String]
17 | public var collections: [String]
18 | public var expiresAt: Int64?
19 |
20 | public init(value: String? = nil, _description: String, actions: [String], collections: [String], expiresAt: Int64? = nil) {
21 | self.value = value
22 | self._description = _description
23 | self.actions = actions
24 | self.collections = collections
25 | self.expiresAt = expiresAt
26 | }
27 |
28 | public enum CodingKeys: String, CodingKey {
29 | case value
30 | case _description = "description"
31 | case actions
32 | case collections
33 | case expiresAt = "expires_at"
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ApiKeysResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ApiKeysResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ApiKeysResponse: Codable {
13 |
14 | public var keys: [ApiKey]
15 |
16 | public init(keys: [ApiKey]) {
17 | self.keys = keys
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ApiResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ApiResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ApiResponse: Codable {
13 |
14 | public var message: String
15 |
16 | public init(message: String) {
17 | self.message = message
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/CollectionAlias.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionAlias.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct CollectionAlias: Codable {
13 |
14 | /** Name of the collection alias */
15 | public var name: String
16 | /** Name of the collection the alias mapped to */
17 | public var collectionName: String
18 |
19 | public init(name: String, collectionName: String) {
20 | self.name = name
21 | self.collectionName = collectionName
22 | }
23 |
24 | public enum CodingKeys: String, CodingKey {
25 | case name
26 | case collectionName = "collection_name"
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/CollectionAliasSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionAliasSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct CollectionAliasSchema: Codable {
13 |
14 | /** Name of the collection you wish to map the alias to */
15 | public var collectionName: String
16 |
17 | public init(collectionName: String) {
18 | self.collectionName = collectionName
19 | }
20 |
21 | public enum CodingKeys: String, CodingKey {
22 | case collectionName = "collection_name"
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/CollectionAliasesResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionAliasesResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct CollectionAliasesResponse: Codable {
13 |
14 | public var aliases: [CollectionAlias]
15 |
16 | public init(aliases: [CollectionAlias]) {
17 | self.aliases = aliases
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/CollectionResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct CollectionResponse: Codable {
13 |
14 | /** Name of the collection */
15 | public var name: String
16 | /** A list of fields for querying, filtering and faceting */
17 | public var fields: [Field]
18 | /** The name of an int32 / float field that determines the order in which the search results are ranked when a sort_by clause is not provided during searching. This field must indicate some kind of popularity. */
19 | public var defaultSortingField: String?
20 | /** List of symbols or special characters to be used for splitting the text into individual words in addition to space and new-line characters. */
21 | public var tokenSeparators: [String]?
22 | /** Enables experimental support at a collection level for nested object or object array fields. This field is only available if the Typesense server is version `0.24.0.rcn34` or later. */
23 | public var enableNestedFields: Bool?
24 | /** List of symbols or special characters to be indexed. */
25 | public var symbolsToIndex: [String]?
26 | /** Number of documents in the collection */
27 | public var numDocuments: Int64
28 | /** Timestamp of when the collection was created (Unix epoch in seconds) */
29 | public var createdAt: Int64
30 | public var voiceQueryModel: VoiceQueryModelCollectionConfig?
31 |
32 |
33 | public init(name: String, fields: [Field], defaultSortingField: String? = nil, tokenSeparators: [String]? = nil, enableNestedFields: Bool? = nil, symbolsToIndex: [String]? = nil, numDocuments: Int64, createdAt: Int64, voiceQueryModel: VoiceQueryModelCollectionConfig? = nil) {
34 | self.name = name
35 | self.fields = fields
36 | self.defaultSortingField = defaultSortingField
37 | self.tokenSeparators = tokenSeparators
38 | self.enableNestedFields = enableNestedFields
39 | self.symbolsToIndex = symbolsToIndex
40 | self.numDocuments = numDocuments
41 | self.createdAt = createdAt
42 | self.voiceQueryModel = voiceQueryModel
43 | }
44 |
45 | public enum CodingKeys: String, CodingKey {
46 | case name
47 | case fields
48 | case defaultSortingField = "default_sorting_field"
49 | case tokenSeparators = "token_separators"
50 | case enableNestedFields = "enable_nested_fields"
51 | case symbolsToIndex = "symbols_to_index"
52 | case numDocuments = "num_documents"
53 | case createdAt = "created_at"
54 | case voiceQueryModel = "voice_query_model"
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/CollectionSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct CollectionSchema: Codable {
13 |
14 | /** Name of the collection */
15 | public var name: String
16 | /** A list of fields for querying, filtering and faceting */
17 | public var fields: [Field]
18 | /** The name of an int32 / float field that determines the order in which the search results are ranked when a sort_by clause is not provided during searching. This field must indicate some kind of popularity. */
19 | public var defaultSortingField: String?
20 | /** List of symbols or special characters to be used for splitting the text into individual words in addition to space and new-line characters. */
21 | public var tokenSeparators: [String]?
22 | /** Enables experimental support at a collection level for nested object or object array fields. This field is only available if the Typesense server is version `0.24.0.rcn34` or later. */
23 | public var enableNestedFields: Bool?
24 | /** List of symbols or special characters to be indexed. */
25 | public var symbolsToIndex: [String]?
26 | public var voiceQueryModel: VoiceQueryModelCollectionConfig?
27 |
28 | public init(name: String, fields: [Field], defaultSortingField: String? = nil, tokenSeparators: [String]? = nil, enableNestedFields: Bool? = nil, symbolsToIndex: [String]? = nil, voiceQueryModel: VoiceQueryModelCollectionConfig? = nil) {
29 | self.name = name
30 | self.fields = fields
31 | self.defaultSortingField = defaultSortingField
32 | self.tokenSeparators = tokenSeparators
33 | self.enableNestedFields = enableNestedFields
34 | self.symbolsToIndex = symbolsToIndex
35 | self.voiceQueryModel = voiceQueryModel
36 | }
37 |
38 | public enum CodingKeys: String, CodingKey {
39 | case name
40 | case fields
41 | case defaultSortingField = "default_sorting_field"
42 | case tokenSeparators = "token_separators"
43 | case enableNestedFields = "enable_nested_fields"
44 | case symbolsToIndex = "symbols_to_index"
45 | case voiceQueryModel = "voice_query_model"
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/CollectionUpdateSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionUpdateSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct CollectionUpdateSchema: Codable {
13 |
14 | /** A list of fields for querying, filtering and faceting */
15 | public var fields: [Field]
16 |
17 | public init(fields: [Field]) {
18 | self.fields = fields
19 | }
20 |
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ConversationModelCreateSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ConversationModelCreateSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ConversationModelCreateSchema: Codable {
13 |
14 | /** An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. */
15 | public var _id: String?
16 | /** Name of the LLM model offered by OpenAI, Cloudflare or vLLM */
17 | public var modelName: String
18 | /** The LLM service's API Key */
19 | public var apiKey: String?
20 | /** Typesense collection that stores the historical conversations */
21 | public var historyCollection: String?
22 | /** LLM service's account ID (only applicable for Cloudflare) */
23 | public var accountId: String?
24 | /** The system prompt that contains special instructions to the LLM */
25 | public var systemPrompt: String?
26 | /** Time interval in seconds after which the messages would be deleted. Default: 86400 (24 hours) */
27 | public var ttl: Int?
28 | /** The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. */
29 | public var maxBytes: Int
30 | /** URL of vLLM service */
31 | public var vllmUrl: String?
32 |
33 | public init(_id: String? = nil, modelName: String, apiKey: String? = nil, historyCollection: String? = nil, accountId: String? = nil, systemPrompt: String? = nil, ttl: Int? = nil, maxBytes: Int, vllmUrl: String? = nil) {
34 | self._id = _id
35 | self.modelName = modelName
36 | self.apiKey = apiKey
37 | self.historyCollection = historyCollection
38 | self.accountId = accountId
39 | self.systemPrompt = systemPrompt
40 | self.ttl = ttl
41 | self.maxBytes = maxBytes
42 | self.vllmUrl = vllmUrl
43 | }
44 |
45 | public enum CodingKeys: String, CodingKey {
46 | case _id = "id"
47 | case modelName = "model_name"
48 | case apiKey = "api_key"
49 | case historyCollection = "history_collection"
50 | case accountId = "account_id"
51 | case systemPrompt = "system_prompt"
52 | case ttl
53 | case maxBytes = "max_bytes"
54 | case vllmUrl = "vllm_url"
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ConversationModelSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ConversationModelSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ConversationModelSchema: Codable {
13 |
14 | /** An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. */
15 | public var _id: String
16 | /** Name of the LLM model offered by OpenAI, Cloudflare or vLLM */
17 | public var modelName: String?
18 | /** The LLM service's API Key */
19 | public var apiKey: String?
20 | /** Typesense collection that stores the historical conversations */
21 | public var historyCollection: String?
22 | /** LLM service's account ID (only applicable for Cloudflare) */
23 | public var accountId: String?
24 | /** The system prompt that contains special instructions to the LLM */
25 | public var systemPrompt: String?
26 | /** Time interval in seconds after which the messages would be deleted. Default: 86400 (24 hours) */
27 | public var ttl: Int?
28 | /** The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. */
29 | public var maxBytes: Int?
30 | /** URL of vLLM service */
31 | public var vllmUrl: String?
32 |
33 | public init(_id: String, modelName: String? = nil, apiKey: String? = nil, historyCollection: String? = nil, accountId: String? = nil, systemPrompt: String? = nil, ttl: Int? = nil, maxBytes: Int? = nil, vllmUrl: String? = nil) {
34 | self._id = _id
35 | self.modelName = modelName
36 | self.apiKey = apiKey
37 | self.historyCollection = historyCollection
38 | self.accountId = accountId
39 | self.systemPrompt = systemPrompt
40 | self.ttl = ttl
41 | self.maxBytes = maxBytes
42 | self.vllmUrl = vllmUrl
43 | }
44 |
45 | public enum CodingKeys: String, CodingKey {
46 | case _id = "id"
47 | case modelName = "model_name"
48 | case apiKey = "api_key"
49 | case historyCollection = "history_collection"
50 | case accountId = "account_id"
51 | case systemPrompt = "system_prompt"
52 | case ttl
53 | case maxBytes = "max_bytes"
54 | case vllmUrl = "vllm_url"
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ConversationModelUpdateSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ConversationModelUpdateSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ConversationModelUpdateSchema: Codable {
13 |
14 | /** An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. */
15 | public var _id: String?
16 | /** Name of the LLM model offered by OpenAI, Cloudflare or vLLM */
17 | public var modelName: String?
18 | /** The LLM service's API Key */
19 | public var apiKey: String?
20 | /** Typesense collection that stores the historical conversations */
21 | public var historyCollection: String?
22 | /** LLM service's account ID (only applicable for Cloudflare) */
23 | public var accountId: String?
24 | /** The system prompt that contains special instructions to the LLM */
25 | public var systemPrompt: String?
26 | /** Time interval in seconds after which the messages would be deleted. Default: 86400 (24 hours) */
27 | public var ttl: Int?
28 | /** The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. */
29 | public var maxBytes: Int?
30 | /** URL of vLLM service */
31 | public var vllmUrl: String?
32 |
33 | public init(_id: String? = nil, modelName: String? = nil, apiKey: String? = nil, historyCollection: String? = nil, accountId: String? = nil, systemPrompt: String? = nil, ttl: Int? = nil, maxBytes: Int? = nil, vllmUrl: String? = nil) {
34 | self._id = _id
35 | self.modelName = modelName
36 | self.apiKey = apiKey
37 | self.historyCollection = historyCollection
38 | self.accountId = accountId
39 | self.systemPrompt = systemPrompt
40 | self.ttl = ttl
41 | self.maxBytes = maxBytes
42 | self.vllmUrl = vllmUrl
43 | }
44 |
45 | public enum CodingKeys: String, CodingKey {
46 | case _id = "id"
47 | case modelName = "model_name"
48 | case apiKey = "api_key"
49 | case historyCollection = "history_collection"
50 | case accountId = "account_id"
51 | case systemPrompt = "system_prompt"
52 | case ttl
53 | case maxBytes = "max_bytes"
54 | case vllmUrl = "vllm_url"
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/DebugRetrieveSchema.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct DebugRetrieveSchema: Codable {
6 |
7 | public var state: Int
8 | public var version: String
9 |
10 | public init(state: Int, version: String) {
11 | self.state = state
12 | self.version = version
13 | }
14 |
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/DeleteDocumentsParameters.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DeleteDocumentsParameters.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct DeleteDocumentsParameters: Codable {
13 |
14 | public var filterBy: String
15 | /** Batch size parameter controls the number of documents that should be deleted at a time. A larger value will speed up deletions, but will impact performance of other operations running on the server. */
16 | public var batchSize: Int?
17 | public var ignoreNotFound: Bool?
18 |
19 | public init(filterBy: String, batchSize: Int? = nil, ignoreNotFound: Bool? = nil) {
20 | self.filterBy = filterBy
21 | self.batchSize = batchSize
22 | self.ignoreNotFound = ignoreNotFound
23 | }
24 |
25 | public enum CodingKeys: String, CodingKey {
26 | case filterBy = "filter_by"
27 | case batchSize = "batch_size"
28 | case ignoreNotFound = "ignore_not_found"
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/DeleteDocumentsResponse.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct DeleteDocumentsResponse: Codable {
6 |
7 | public var numDeleted: Int
8 |
9 | public init(numDeleted: Int) {
10 | self.numDeleted = numDeleted
11 | }
12 |
13 | public enum CodingKeys: String, CodingKey {
14 | case numDeleted = "num_deleted"
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/DocumentIndexParameters.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct DocumentIndexParameters: Codable {
6 |
7 | public var dirtyValues: DirtyValues?
8 |
9 | public init(dirtyValues: DirtyValues? = nil) {
10 | self.dirtyValues = dirtyValues
11 | }
12 |
13 | public enum CodingKeys: String, CodingKey {
14 | case dirtyValues = "dirty_values"
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ExportDocumentsParameters.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExportDocumentsParameters.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ExportDocumentsParameters: Codable {
13 |
14 | /** Filter conditions for refining your search results. Separate multiple conditions with &&. */
15 | public var filterBy: String?
16 | /** List of fields from the document to include in the search result */
17 | public var includeFields: String?
18 | /** List of fields from the document to exclude in the search result */
19 | public var excludeFields: String?
20 |
21 | public init(filterBy: String? = nil, includeFields: String? = nil, excludeFields: String? = nil) {
22 | self.filterBy = filterBy
23 | self.includeFields = includeFields
24 | self.excludeFields = excludeFields
25 | }
26 |
27 | public enum CodingKeys: String, CodingKey {
28 | case filterBy = "filter_by"
29 | case includeFields = "include_fields"
30 | case excludeFields = "exclude_fields"
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/FacetCounts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FacetCounts.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct FacetCounts: Codable {
13 |
14 | public var counts: [FacetCountsCounts]?
15 | public var fieldName: String?
16 | public var stats: FacetCountsStats?
17 |
18 | public init(counts: [FacetCountsCounts]? = nil, fieldName: String? = nil, stats: FacetCountsStats? = nil) {
19 | self.counts = counts
20 | self.fieldName = fieldName
21 | self.stats = stats
22 | }
23 |
24 | public enum CodingKeys: String, CodingKey {
25 | case counts
26 | case fieldName = "field_name"
27 | case stats
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/FacetCountsCounts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FacetCountsCounts.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct FacetCountsCounts: Codable {
13 |
14 | public var count: Int?
15 | public var highlighted: String?
16 | public var value: String?
17 |
18 | public init(count: Int? = nil, highlighted: String? = nil, value: String? = nil) {
19 | self.count = count
20 | self.highlighted = highlighted
21 | self.value = value
22 | }
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/FacetCountsStats.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FacetCountsStats.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct FacetCountsStats: Codable {
13 |
14 | public var max: Double?
15 | public var min: Double?
16 | public var sum: Double?
17 | public var totalValues: Int?
18 | public var avg: Double?
19 |
20 | public init(max: Double? = nil, min: Double? = nil, sum: Double? = nil, totalValues: Int? = nil, avg: Double? = nil) {
21 | self.max = max
22 | self.min = min
23 | self.sum = sum
24 | self.totalValues = totalValues
25 | self.avg = avg
26 | }
27 |
28 | public enum CodingKeys: String, CodingKey {
29 | case max
30 | case min
31 | case sum
32 | case totalValues = "total_values"
33 | case avg
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/Field.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Field.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct Field: Codable {
13 |
14 | public var name: String
15 | public var type: String
16 | public var _optional: Bool?
17 | public var facet: Bool?
18 | public var index: Bool?
19 | public var locale: String?
20 | public var sort: Bool?
21 | public var _infix: Bool?
22 | public var reference: String?
23 | public var numDim: Int?
24 | public var drop: Bool?
25 | /** Whether to store the image on disk. */
26 | public var store: Bool?
27 | public var embed: FieldEmbed?
28 |
29 | public init(name: String, type: String, _optional: Bool? = nil, facet: Bool? = nil, index: Bool? = nil, locale: String? = nil, sort: Bool? = nil, _infix: Bool? = nil, reference: String? = nil, numDim: Int? = nil, drop: Bool? = nil, store: Bool? = nil, embed: FieldEmbed? = nil) {
30 | self.name = name
31 | self.type = type
32 | self._optional = _optional
33 | self.facet = facet
34 | self.index = index
35 | self.locale = locale
36 | self.sort = sort
37 | self._infix = _infix
38 | self.reference = reference
39 | self.numDim = numDim
40 | self.drop = drop
41 | self.store = store
42 | self.embed = embed
43 | }
44 |
45 | public enum CodingKeys: String, CodingKey {
46 | case name
47 | case type
48 | case _optional = "optional"
49 | case facet
50 | case index
51 | case locale
52 | case sort
53 | case _infix = "infix"
54 | case reference
55 | case numDim = "num_dim"
56 | case drop
57 | case store
58 | case embed
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/FieldEmbed.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FieldEmbed.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct FieldEmbed: Codable {
13 |
14 | public var from: [String]
15 | public var modelConfig: FieldEmbedModelConfig
16 |
17 | public init(from: [String], modelConfig: FieldEmbedModelConfig) {
18 | self.from = from
19 | self.modelConfig = modelConfig
20 | }
21 |
22 | public enum CodingKeys: String, CodingKey {
23 | case from
24 | case modelConfig = "model_config"
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/FieldEmbedModelConfig.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FieldEmbedModelConfig.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct FieldEmbedModelConfig: Codable {
13 |
14 | public var modelName: String
15 | public var apiKey: String?
16 | public var accessToken: String?
17 | public var clientId: String?
18 | public var clientSecret: String?
19 | public var projectId: String?
20 |
21 | public init(modelName: String, apiKey: String? = nil, accessToken: String? = nil, clientId: String? = nil, clientSecret: String? = nil, projectId: String? = nil) {
22 | self.modelName = modelName
23 | self.apiKey = apiKey
24 | self.accessToken = accessToken
25 | self.clientId = clientId
26 | self.clientSecret = clientSecret
27 | self.projectId = projectId
28 | }
29 |
30 | public enum CodingKeys: String, CodingKey {
31 | case modelName = "model_name"
32 | case apiKey = "api_key"
33 | case accessToken = "access_token"
34 | case clientId = "client_id"
35 | case clientSecret = "client_secret"
36 | case projectId = "project_id"
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/HealthStatus.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HealthStatus.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct HealthStatus: Codable {
13 |
14 | public var ok: Bool
15 |
16 | public init(ok: Bool) {
17 | self.ok = ok
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ImportDocumentsParameters.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImportDocumentsParameters.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ImportDocumentsParameters: Codable {
13 |
14 | public var action: IndexAction?
15 | public var batchSize: Int?
16 | public var dirtyValues: DirtyValues?
17 | public var remoteEmbeddingBatchSize: Int?
18 | public var returnDoc: Bool?
19 | public var returnId: Bool?
20 |
21 | public init(action: IndexAction? = nil, batchSize: Int? = nil, dirtyValues: DirtyValues? = nil, remoteEmbeddingBatchSize: Int? = nil, returnDoc: Bool? = nil, returnId: Bool? = nil) {
22 | self.action = action
23 | self.batchSize = batchSize
24 | self.dirtyValues = dirtyValues
25 | self.remoteEmbeddingBatchSize = remoteEmbeddingBatchSize
26 | self.returnDoc = returnDoc
27 | self.returnId = returnId
28 | }
29 |
30 | public enum CodingKeys: String, CodingKey {
31 | case action
32 | case batchSize = "batch_size"
33 | case dirtyValues = "dirty_values"
34 | case remoteEmbeddingBatchSize = "remote_embedding_batch_size"
35 | case returnDoc = "return_doc"
36 | case returnId = "return_id"
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/InlineResponse2002.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InlineResponse2002.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct InlineResponse2002: Codable {
13 |
14 | public var version: String?
15 |
16 | public init(version: String? = nil) {
17 | self.version = version
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ModelErrorResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ModelErrorResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ModelErrorResponse: Codable {
13 |
14 | public var message: String?
15 |
16 | public init(message: String? = nil) {
17 | self.message = message
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/MultiSearchResult.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultiSearchResult.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct MultiSearchResult: Decodable {
13 |
14 | public var results: [SearchResult]
15 | public var conversation: SearchResultConversation?
16 |
17 | public init(results: [SearchResult], conversation: SearchResultConversation? = nil) {
18 | self.results = results
19 | self.conversation = conversation
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/MultiSearchSearchesParameter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultiSearchSearchesParameter.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 | public struct MultiSearchSearchesParameter: Codable {
11 | public var searches: [MultiSearchCollectionParameters]
12 |
13 | public init(searches: [MultiSearchCollectionParameters]) {
14 | self.searches = searches
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/PresetDeleteSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PresetDeleteSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct PresetDeleteSchema: Codable {
13 |
14 | public var name: String
15 |
16 | public init(name: String) {
17 | self.name = name
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/PresetSchema.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct PresetSchema: Codable {
6 | public var name: String
7 | public var value: PresetValue
8 |
9 | public init(name: String, value: PresetValue) {
10 | self.name = name
11 | self.value = value
12 | }
13 |
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/PresetUpsertSchema.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct PresetUpsertSchema: Codable {
6 |
7 | public var value: PresetValue
8 |
9 | public init(value: PresetValue) {
10 | self.value = value
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/PresetValue.swift:
--------------------------------------------------------------------------------
1 | public enum PresetValue: Codable {
2 | case multiSearch(MultiSearchSearchesParameter)
3 | case singleCollectionSearch(SearchParameters)
4 |
5 | public init (from decoder: Decoder) throws {
6 | if let multiSearch = try? MultiSearchSearchesParameter(from: decoder) {
7 | self = .multiSearch(multiSearch)
8 | }
9 | else if let singleCollectionSearch = try? SearchParameters(from: decoder) {
10 | self = .singleCollectionSearch(singleCollectionSearch)
11 | } else {
12 | throw DecodingError.dataCorrupted(DecodingError.Context(
13 | codingPath: decoder.codingPath,
14 | debugDescription: "Unable to decode value for preset `value`"
15 | )
16 | )
17 | }
18 | }
19 |
20 | public func encode(to encoder: Encoder) throws {
21 | switch self {
22 | case .multiSearch(let multiSearch):
23 | try multiSearch.encode(to: encoder)
24 | case .singleCollectionSearch(let singleCollectionSearch):
25 | try singleCollectionSearch.encode(to: encoder)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/PresetsRetrieveSchema.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct PresetsRetrieveSchema: Codable {
6 |
7 | public var presets: [PresetSchema]
8 |
9 | public init(presets: [PresetSchema]) {
10 | self.presets = presets
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/ScopedKeyParameters.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ScopedKeyParameters.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct ScopedKeyParameters: Codable {
13 |
14 | public var filterBy: String?
15 | public var expiresAt: Decimal?
16 |
17 | public init(filterBy: String? = nil, expiresAt: Decimal? = nil) {
18 | self.filterBy = filterBy
19 | self.expiresAt = expiresAt
20 | }
21 |
22 | public enum CodingKeys: String, CodingKey {
23 | case filterBy = "filter_by"
24 | case expiresAt = "expires_at"
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchGroupedHit.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchGroupedHit.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 | import AnyCodable
10 |
11 | public struct SearchGroupedHit: Decodable {
12 |
13 | public var found: Int?
14 | public var groupKey: [AnyCodable]
15 | /** The documents that matched the search query */
16 | public var hits: [SearchResultHit]
17 |
18 | public init(found: Int? = nil, groupKey: [AnyCodable], hits: [SearchResultHit]) {
19 | self.found = found
20 | self.groupKey = groupKey
21 | self.hits = hits
22 | }
23 |
24 | public enum CodingKeys: String, CodingKey {
25 | case found
26 | case groupKey = "group_key"
27 | case hits
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchHighlight.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchHighlight.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchHighlight: Codable {
13 |
14 | public var field: String?
15 | /** Present only for (non-array) string fields */
16 | public var snippet: String?
17 | /** Present only for (array) string[] fields */
18 | public var snippets: [String]?
19 | /** Full field value with highlighting, present only for (non-array) string fields */
20 | public var value: String?
21 | /** Full field value with highlighting, present only for (array) string[] fields */
22 | public var values: [String]?
23 | /** The indices property will be present only for string[] fields and will contain the corresponding indices of the snippets in the search field */
24 | public var indices: [Int]?
25 | public var matchedTokens: StringQuantum?
26 |
27 | public init(field: String? = nil, snippet: String? = nil, snippets: [String]? = nil, value: String? = nil, values: [String]? = nil, indices: [Int]? = nil, matchedTokens: StringQuantum? = nil) {
28 | self.field = field
29 | self.snippet = snippet
30 | self.snippets = snippets
31 | self.value = value
32 | self.values = values
33 | self.indices = indices
34 | self.matchedTokens = matchedTokens
35 | }
36 |
37 | public enum CodingKeys: String, CodingKey {
38 | case field
39 | case snippet
40 | case snippets
41 | case value
42 | case values
43 | case indices
44 | case matchedTokens = "matched_tokens"
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchOverride.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchOverride.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchOverride: Codable {
13 |
14 | public var _id: String
15 | public var rule: SearchOverrideRule
16 | /** List of document `id`s that should be included in the search results with their corresponding `position`s. */
17 | public var includes: [SearchOverrideInclude]?
18 | /** List of document `id`s that should be excluded from the search results. */
19 | public var excludes: [SearchOverrideExclude]?
20 | /** A filter by clause that is applied to any search query that matches the override rule. */
21 | public var filterBy: String?
22 | /** Indicates whether search query tokens that exist in the override's rule should be removed from the search query. */
23 | public var removeMatchedTokens: Bool?
24 | /** Return a custom JSON object in the Search API response, when this rule is triggered. This can can be used to display a pre-defined message (eg: a promotion banner) on the front-end when a particular rule is triggered. */
25 | public var metadata: T?
26 | /** A sort by clause that is applied to any search query that matches the override rule. */
27 | public var sortBy: String?
28 | /** Replaces the current search query with this value, when the search query matches the override rule. */
29 | public var replaceQuery: String?
30 | /** When set to true, the filter conditions of the query is applied to the curated records as well. Default: false. */
31 | public var filterCuratedHits: Bool?
32 | /** A Unix timestamp that indicates the date/time from which the override will be active. You can use this to create override rules that start applying from a future point in time. */
33 | public var effectiveFromTs: Int?
34 | /** A Unix timestamp that indicates the date/time until which the override will be active. You can use this to create override rules that stop applying after a period of time. */
35 | public var effectiveToTs: Int?
36 | /** When set to true, override processing will stop at the first matching rule. When set to false override processing will continue and multiple override actions will be triggered in sequence. Overrides are processed in the lexical sort order of their id field. Default: true. */
37 | public var stopProcessing: Bool?
38 |
39 | public init(_id: String, rule: SearchOverrideRule, includes: [SearchOverrideInclude]? = nil, excludes: [SearchOverrideExclude]? = nil, filterBy: String? = nil, removeMatchedTokens: Bool? = nil, metadata: T? = nil, sortBy: String? = nil, replaceQuery: String? = nil, filterCuratedHits: Bool? = nil, effectiveFromTs: Int? = nil, effectiveToTs: Int? = nil, stopProcessing: Bool? = nil) {
40 | self._id = _id
41 | self.rule = rule
42 | self.includes = includes
43 | self.excludes = excludes
44 | self.filterBy = filterBy
45 | self.removeMatchedTokens = removeMatchedTokens
46 | self.metadata = metadata
47 | self.sortBy = sortBy
48 | self.replaceQuery = replaceQuery
49 | self.filterCuratedHits = filterCuratedHits
50 | self.effectiveFromTs = effectiveFromTs
51 | self.effectiveToTs = effectiveToTs
52 | self.stopProcessing = stopProcessing
53 | }
54 |
55 | public enum CodingKeys: String, CodingKey {
56 | case _id = "id"
57 | case rule
58 | case includes
59 | case excludes
60 | case filterBy = "filter_by"
61 | case removeMatchedTokens = "remove_matched_tokens"
62 | case metadata
63 | case sortBy = "sort_by"
64 | case replaceQuery = "replace_query"
65 | case filterCuratedHits = "filter_curated_hits"
66 | case effectiveFromTs = "effective_from_ts"
67 | case effectiveToTs = "effective_to_ts"
68 | case stopProcessing = "stop_processing"
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchOverrideDeleteResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchOverrideDeleteResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchOverrideDeleteResponse: Codable {
13 |
14 | /** The id of a deleted override. */
15 | public var _id: String
16 |
17 | public init(_id: String) {
18 | self._id = _id
19 | }
20 |
21 | public enum CodingKeys: String, CodingKey {
22 | case _id = "id"
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchOverrideExclude.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchOverrideExclude.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchOverrideExclude: Codable {
13 |
14 | /** document id that should be excluded from the search results. */
15 | public var _id: String
16 |
17 | public init(_id: String) {
18 | self._id = _id
19 | }
20 |
21 | public enum CodingKeys: String, CodingKey {
22 | case _id = "id"
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchOverrideInclude.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchOverrideInclude.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchOverrideInclude: Codable {
13 |
14 | /** document id that should be included */
15 | public var _id: String
16 | /** position number where document should be included in the search results */
17 | public var position: Int
18 |
19 | public init(_id: String, position: Int) {
20 | self._id = _id
21 | self.position = position
22 | }
23 |
24 | public enum CodingKeys: String, CodingKey {
25 | case _id = "id"
26 | case position
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchOverrideRule.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchOverrideRule.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchOverrideRule: Codable {
13 |
14 | public enum Match: String, Codable {
15 | case exact = "exact"
16 | case contains = "contains"
17 | }
18 | /** List of tag values to associate with this override rule. */
19 | public var tags: [String]?
20 | /** Indicates what search queries should be overridden */
21 | public var query: String?
22 | /** Indicates whether the match on the query term should be `exact` or `contains`. If we want to match all queries that contained the word `apple`, we will use the `contains` match instead. */
23 | public var match: Match?
24 | /** Indicates that the override should apply when the filter_by parameter in a search query exactly matches the string specified here (including backticks, spaces, brackets, etc). */
25 | public var filterBy: String?
26 |
27 | public init(tags: [String]? = nil, query: String? = nil, match: Match? = nil, filterBy: String? = nil) {
28 | self.tags = tags
29 | self.query = query
30 | self.match = match
31 | self.filterBy = filterBy
32 | }
33 |
34 | public enum CodingKeys: String, CodingKey {
35 | case tags
36 | case query
37 | case match
38 | case filterBy = "filter_by"
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchOverrideSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchOverrideSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchOverrideSchema: Codable {
13 |
14 | public var rule: SearchOverrideRule
15 | /** List of document `id`s that should be included in the search results with their corresponding `position`s. */
16 | public var includes: [SearchOverrideInclude]?
17 | /** List of document `id`s that should be excluded from the search results. */
18 | public var excludes: [SearchOverrideExclude]?
19 | /** A filter by clause that is applied to any search query that matches the override rule. */
20 | public var filterBy: String?
21 | /** Indicates whether search query tokens that exist in the override's rule should be removed from the search query. */
22 | public var removeMatchedTokens: Bool?
23 | /** Return a custom JSON object in the Search API response, when this rule is triggered. This can can be used to display a pre-defined message (eg: a promotion banner) on the front-end when a particular rule is triggered. */
24 | public var metadata: T?
25 | /** A sort by clause that is applied to any search query that matches the override rule. */
26 | public var sortBy: String?
27 | /** Replaces the current search query with this value, when the search query matches the override rule. */
28 | public var replaceQuery: String?
29 | /** When set to true, the filter conditions of the query is applied to the curated records as well. Default: false. */
30 | public var filterCuratedHits: Bool?
31 | /** A Unix timestamp that indicates the date/time from which the override will be active. You can use this to create override rules that start applying from a future point in time. */
32 | public var effectiveFromTs: Int?
33 | /** A Unix timestamp that indicates the date/time until which the override will be active. You can use this to create override rules that stop applying after a period of time. */
34 | public var effectiveToTs: Int?
35 | /** When set to true, override processing will stop at the first matching rule. When set to false override processing will continue and multiple override actions will be triggered in sequence. Overrides are processed in the lexical sort order of their id field. Default: true. */
36 | public var stopProcessing: Bool?
37 |
38 | public init(rule: SearchOverrideRule, includes: [SearchOverrideInclude]? = nil, excludes: [SearchOverrideExclude]? = nil, filterBy: String? = nil, removeMatchedTokens: Bool? = nil, metadata: T? = nil, sortBy: String? = nil, replaceQuery: String? = nil, filterCuratedHits: Bool? = nil, effectiveFromTs: Int? = nil, effectiveToTs: Int? = nil, stopProcessing: Bool? = nil) {
39 | self.rule = rule
40 | self.includes = includes
41 | self.excludes = excludes
42 | self.filterBy = filterBy
43 | self.removeMatchedTokens = removeMatchedTokens
44 | self.metadata = metadata
45 | self.sortBy = sortBy
46 | self.replaceQuery = replaceQuery
47 | self.filterCuratedHits = filterCuratedHits
48 | self.effectiveFromTs = effectiveFromTs
49 | self.effectiveToTs = effectiveToTs
50 | self.stopProcessing = stopProcessing
51 | }
52 |
53 | public enum CodingKeys: String, CodingKey {
54 | case rule
55 | case includes
56 | case excludes
57 | case filterBy = "filter_by"
58 | case removeMatchedTokens = "remove_matched_tokens"
59 | case metadata
60 | case sortBy = "sort_by"
61 | case replaceQuery = "replace_query"
62 | case filterCuratedHits = "filter_curated_hits"
63 | case effectiveFromTs = "effective_from_ts"
64 | case effectiveToTs = "effective_to_ts"
65 | case stopProcessing = "stop_processing"
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchOverridesResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchOverridesResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchOverridesResponse: Codable {
13 |
14 | public var overrides: [SearchOverride]
15 |
16 | public init(overrides: [SearchOverride]) {
17 | self.overrides = overrides
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchResult.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResult.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchResult: Decodable {
13 |
14 | public var facetCounts: [FacetCounts]?
15 | /** The number of documents found */
16 | public var found: Int?
17 | /** The number of milliseconds the search took */
18 | public var searchTimeMs: Int?
19 | /** The total number of documents in the collection */
20 | public var outOf: Int?
21 | /** Whether the search was cut off */
22 | public var searchCutoff: Bool?
23 | /** The search result page number */
24 | public var page: Int?
25 | public var groupedHits: [SearchGroupedHit]?
26 | /** The documents that matched the search query */
27 | public var hits: [SearchResultHit]?
28 | public var requestParams: SearchResultRequestParams?
29 | public var conversation: SearchResultConversation?
30 |
31 | public init(facetCounts: [FacetCounts]? = nil, found: Int? = nil, searchTimeMs: Int? = nil, outOf: Int? = nil, searchCutoff: Bool? = nil, page: Int? = nil, groupedHits: [SearchGroupedHit]? = nil, hits: [SearchResultHit]? = nil, requestParams: SearchResultRequestParams? = nil, conversation: SearchResultConversation? = nil) {
32 | self.facetCounts = facetCounts
33 | self.found = found
34 | self.searchTimeMs = searchTimeMs
35 | self.outOf = outOf
36 | self.searchCutoff = searchCutoff
37 | self.page = page
38 | self.groupedHits = groupedHits
39 | self.hits = hits
40 | self.requestParams = requestParams
41 | self.conversation = conversation
42 | }
43 |
44 | public enum CodingKeys: String, CodingKey {
45 | case facetCounts = "facet_counts"
46 | case found
47 | case searchTimeMs = "search_time_ms"
48 | case outOf = "out_of"
49 | case searchCutoff = "search_cutoff"
50 | case page
51 | case groupedHits = "grouped_hits"
52 | case hits
53 | case requestParams = "request_params"
54 | case conversation
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchResultConversation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResultConversation.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchResultConversation: Codable {
13 |
14 | public var answer: String
15 | public var conversationHistory: [[String: String]]
16 | public var conversationId: String
17 | public var query: String
18 |
19 | public init(answer: String, conversationHistory: [[String: String]], conversationId: String, query: String) {
20 | self.answer = answer
21 | self.conversationHistory = conversationHistory
22 | self.conversationId = conversationId
23 | self.query = query
24 | }
25 |
26 | public enum CodingKeys: String, CodingKey {
27 | case answer
28 | case conversationHistory = "conversation_history"
29 | case conversationId = "conversation_id"
30 | case query
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchResultHit.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResultHit.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchResultHit: Decodable {
13 |
14 | /** (Deprecated) Contains highlighted portions of the search fields */
15 | public var highlights: [SearchHighlight]?
16 | public var document: T?
17 | public var textMatch: Int64?
18 | public var geoDistanceMeters: [String:Int]?
19 | /** Distance between the query vector and matching document's vector value */
20 | public var vectorDistance: Float?
21 |
22 | public init(highlights: [SearchHighlight]? = nil, document: T? = nil, textMatch: Int64? = nil, geoDistanceMeters: [String:Int]? = nil, vectorDistance: Float? = nil) {
23 | self.highlights = highlights
24 | // self.highlightData = highlight
25 | self.document = document
26 | self.textMatch = textMatch
27 | self.geoDistanceMeters = geoDistanceMeters
28 | self.vectorDistance = vectorDistance
29 | }
30 |
31 | public init(from decoder: Decoder) throws {
32 | let container: KeyedDecodingContainer.CodingKeys> = try decoder.container(keyedBy: SearchResultHit.CodingKeys.self)
33 | self.highlights = try container.decodeIfPresent([SearchHighlight].self, forKey: SearchResultHit.CodingKeys.highlights)
34 | self.document = try container.decodeIfPresent(T.self, forKey: SearchResultHit.CodingKeys.document)
35 | self.textMatch = try container.decodeIfPresent(Int64.self, forKey: SearchResultHit.CodingKeys.textMatch)
36 | self.geoDistanceMeters = try container.decodeIfPresent([String : Int].self, forKey: SearchResultHit.CodingKeys.geoDistanceMeters)
37 | self.vectorDistance = try container.decodeIfPresent(Float.self, forKey: SearchResultHit.CodingKeys.vectorDistance)
38 | }
39 |
40 | public enum CodingKeys: String, CodingKey {
41 | case highlights
42 | case highlight
43 | case document
44 | case textMatch = "text_match"
45 | case geoDistanceMeters = "geo_distance_meters"
46 | case vectorDistance = "vector_distance"
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchResultRequestParams.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResultRequestParams.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchResultRequestParams: Codable {
13 |
14 | public var collectionName: String
15 | public var q: String
16 | public var perPage: Int
17 | public var voiceQuery: SearchResultRequestParamsVoiceQuery?
18 |
19 | public init(collectionName: String, q: String, perPage: Int, voiceQuery: SearchResultRequestParamsVoiceQuery? = nil) {
20 | self.collectionName = collectionName
21 | self.q = q
22 | self.perPage = perPage
23 | self.voiceQuery = voiceQuery
24 | }
25 |
26 | public enum CodingKeys: String, CodingKey {
27 | case collectionName = "collection_name"
28 | case q
29 | case perPage = "per_page"
30 | case voiceQuery = "voice_query"
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchResultRequestParamsVoiceQuery.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResultRequestParamsVoiceQuery.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchResultRequestParamsVoiceQuery: Codable {
13 |
14 | public var transcribedQuery: String?
15 |
16 | public init(transcribedQuery: String? = nil) {
17 | self.transcribedQuery = transcribedQuery
18 | }
19 |
20 | public enum CodingKeys: String, CodingKey {
21 | case transcribedQuery = "transcribed_query"
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchSynonym.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchSynonym.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchSynonym: Codable {
13 |
14 | /** For 1-way synonyms, indicates the root word that words in the `synonyms` parameter map to. */
15 | public var root: String?
16 | /** Array of words that should be considered as synonyms. */
17 | public var synonyms: [String]
18 | public var _id: String
19 | /** Locale for the synonym, leave blank to use the standard tokenizer. */
20 | public var locale: String?
21 | /** By default, special characters are dropped from synonyms. Use this attribute to specify which special characters should be indexed as is. */
22 | public var symbolsToIndex: [String]?
23 |
24 | public init(root: String? = nil, synonyms: [String], _id: String, locale: String? = nil, symbolsToIndex: [String]? = nil) {
25 | self.root = root
26 | self.synonyms = synonyms
27 | self._id = _id
28 | self.locale = locale
29 | self.symbolsToIndex = symbolsToIndex
30 | }
31 |
32 | public enum CodingKeys: String, CodingKey {
33 | case _id = "id"
34 | case root
35 | case synonyms
36 | case locale
37 | case symbolsToIndex = "symbols_to_index"
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchSynonymSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchSynonymSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchSynonymSchema: Codable {
13 |
14 | /** For 1-way synonyms, indicates the root word that words in the `synonyms` parameter map to. */
15 | public var root: String?
16 | /** Array of words that should be considered as synonyms. */
17 | public var synonyms: [String]
18 | /** Locale for the synonym, leave blank to use the standard tokenizer. */
19 | public var locale: String?
20 | /** By default, special characters are dropped from synonyms. Use this attribute to specify which special characters should be indexed as is. */
21 | public var symbolsToIndex: [String]?
22 |
23 | public init(root: String? = nil, synonyms: [String], locale: String? = nil, symbolsToIndex: [String]? = nil) {
24 | self.root = root
25 | self.synonyms = synonyms
26 | self.locale = locale
27 | self.symbolsToIndex = symbolsToIndex
28 | }
29 |
30 | public enum CodingKeys: String, CodingKey {
31 | case root
32 | case synonyms
33 | case locale
34 | case symbolsToIndex = "symbols_to_index"
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SearchSynonymsResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchSynonymsResponse.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SearchSynonymsResponse: Codable {
13 |
14 | public var synonyms: [SearchSynonym]
15 |
16 | public init(synonyms: [SearchSynonym]) {
17 | self.synonyms = synonyms
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SnapshotParameters.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapshotParameters.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SnapshotParameters: Codable {
13 |
14 | public var snapshotPath: String?
15 |
16 | public init(snapshotPath: String? = nil) {
17 | self.snapshotPath = snapshotPath
18 | }
19 |
20 | public enum CodingKeys: String, CodingKey {
21 | case snapshotPath = "snapshot_path"
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/StopwordsSetDeleteSchema.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 |
5 | public struct StopwordsSetDeleteSchema: Codable {
6 | public var _id: String
7 |
8 | public init(_id: String) {
9 | self._id = _id
10 | }
11 |
12 | public enum CodingKeys: String, CodingKey {
13 | case _id = "id"
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/StopwordsSetRetrieveSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StopwordsSetRetrieveSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct StopwordsSetRetrieveSchema: Codable {
13 |
14 | public var stopwords: StopwordsSetSchema
15 |
16 | public init(stopwords: StopwordsSetSchema) {
17 | self.stopwords = stopwords
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/StopwordsSetSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StopwordsSetSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct StopwordsSetSchema: Codable {
13 |
14 | public var _id: String
15 | public var stopwords: [String]
16 | public var locale: String?
17 |
18 | public init(_id: String, stopwords: [String], locale: String? = nil) {
19 | self._id = _id
20 | self.stopwords = stopwords
21 | self.locale = locale
22 | }
23 |
24 | public enum CodingKeys: String, CodingKey {
25 | case _id = "id"
26 | case stopwords
27 | case locale
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/StopwordsSetUpsertSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StopwordsSetUpsertSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct StopwordsSetUpsertSchema: Codable {
13 |
14 | public var stopwords: [String]
15 | public var locale: String?
16 |
17 | public init(stopwords: [String], locale: String? = nil) {
18 | self.stopwords = stopwords
19 | self.locale = locale
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/StopwordsSetsRetrieveAllSchema.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StopwordsSetsRetrieveAllSchema.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct StopwordsSetsRetrieveAllSchema: Codable {
13 |
14 | public var stopwords: [StopwordsSetSchema]
15 |
16 | public init(stopwords: [StopwordsSetSchema]) {
17 | self.stopwords = stopwords
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/SuccessStatus.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SuccessStatus.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct SuccessStatus: Codable {
13 |
14 | public var success: Bool
15 |
16 | public init(success: Bool) {
17 | self.success = success
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/UpdateByFilterResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InlineResponse2001.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct UpdateByFilterResponse: Codable {
13 |
14 | /** The number of documents that have been updated */
15 | public var numUpdated: Int
16 |
17 | public init(numUpdated: Int) {
18 | self.numUpdated = numUpdated
19 | }
20 |
21 | public enum CodingKeys: String, CodingKey {
22 | case numUpdated = "num_updated"
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/UpdateDocumentsByFilterParameters.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UpdateDocumentsParameters.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 |
12 | public struct UpdateDocumentsByFilterParameters: Codable {
13 |
14 | public var filterBy: String?
15 |
16 | public init(filterBy: String? = nil) {
17 | self.filterBy = filterBy
18 | }
19 |
20 | public enum CodingKeys: String, CodingKey {
21 | case filterBy = "filter_by"
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Typesense/Models/VoiceQueryModelCollectionConfig.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VoiceQueryModelCollectionConfig.swift
3 | //
4 | // Generated by swagger-codegen
5 | // https://github.com/swagger-api/swagger-codegen
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | /** Configuration for the voice query model */
12 |
13 | public struct VoiceQueryModelCollectionConfig: Codable {
14 |
15 | public var modelName: String?
16 |
17 | public init(modelName: String? = nil) {
18 | self.modelName = modelName
19 | }
20 |
21 | public enum CodingKeys: String, CodingKey {
22 | case modelName = "model_name"
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Typesense/Node.swift:
--------------------------------------------------------------------------------
1 | public struct Node: CustomStringConvertible {
2 | var host: String?
3 | var port: String?
4 | var nodeProtocol: String?
5 | var url: String?
6 | var isHealthy: Bool = false
7 | var lastAccessTimeStamp: Int64 = 0
8 |
9 | public init(host: String? = nil, port: String? = nil, nodeProtocol: String? = nil, url: String? = nil) {
10 | if url == nil && (host == nil || port == nil || nodeProtocol == nil) {
11 | fatalError("Node `url` or `nodeProtocol` and `host` and `port` must be set!")
12 | }
13 | self.host = host
14 | self.port = port
15 | self.nodeProtocol = nodeProtocol
16 | self.url = url
17 | }
18 |
19 | public var description: String {
20 | if let url = self.url {
21 | return "Node: \(url)"
22 | }
23 | return "Node: \(nodeProtocol!)://\(host!):\(port!)"
24 | }
25 |
26 | public var healthStatus: String {
27 | return isHealthy ? "Healthy" : "Unhealthy"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Typesense/Operations.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 |
7 | public struct Operations {
8 | var apiCall: ApiCall
9 | var RESOURCEPATH = "operations"
10 |
11 | init(apiCall: ApiCall) {
12 | self.apiCall = apiCall
13 | }
14 |
15 | public func getHealth() async throws -> (HealthStatus?, URLResponse?) {
16 | let (data, response) = try await apiCall.get(endPoint: "health")
17 | if let result = data {
18 | let health = try decoder.decode(HealthStatus.self, from: result)
19 | return (health, response)
20 | }
21 | return (nil, nil)
22 | }
23 |
24 | public func getStats() async throws -> (Data?, URLResponse?) {
25 | let (data, response) = try await apiCall.get(endPoint: "stats.json")
26 | return (data, response)
27 | }
28 |
29 | public func getMetrics() async throws -> (Data?, URLResponse?) {
30 | let (data, response) = try await apiCall.get(endPoint: "metrics.json")
31 | return (data, response)
32 | }
33 |
34 | public func getDebug() async throws -> (DebugRetrieveSchema?, URLResponse?) {
35 | let (data, response) = try await apiCall.get(endPoint: "debug")
36 | if let result = data {
37 | let decodedData = try decoder.decode(DebugRetrieveSchema.self, from: result)
38 | return (decodedData, response)
39 | }
40 | return (nil, response)
41 | }
42 |
43 | public func vote() async throws -> (SuccessStatus?, URLResponse?) {
44 | let (data, response) = try await apiCall.post(endPoint: "\(RESOURCEPATH)/vote", body: Data())
45 | if let result = data {
46 | let success = try decoder.decode(SuccessStatus.self, from: result)
47 | return (success, response)
48 | }
49 | return (nil, nil)
50 | }
51 |
52 | public func snapshot(path: String? = "/tmp/typesense-data-snapshot") async throws -> (SuccessStatus?, URLResponse?) {
53 | let snapshotQueryParam = URLQueryItem(name: "snapshot_path", value: path)
54 | let (data, response) = try await apiCall.post(endPoint: "\(RESOURCEPATH)/snapshot", body: Data(), queryParameters: [snapshotQueryParam])
55 | if let result = data {
56 | let success = try decoder.decode(SuccessStatus.self, from: result)
57 | return (success, response)
58 | }
59 | return (nil, nil)
60 | }
61 |
62 | public func toggleSlowRequestLog(seconds: Float) async throws -> (SuccessStatus?, URLResponse?) {
63 | let durationInMs = seconds * 1000
64 | let slowReq = SlowRequest(durationInMs)
65 | let slowReqData = try encoder.encode(slowReq)
66 | let (data, response) = try await apiCall.post(endPoint: "/config", body: slowReqData)
67 | if let result = data {
68 | let success = try decoder.decode(SuccessStatus.self, from: result)
69 | return (success, response)
70 | }
71 | return (nil, nil)
72 | }
73 |
74 | public func clearCache() async throws -> (SuccessStatus?, URLResponse?) {
75 | let (data, response) = try await apiCall.post(endPoint: "\(RESOURCEPATH)/cache/clear", body: Data())
76 | if let result = data {
77 | let success = try decoder.decode(SuccessStatus.self, from: result)
78 | return (success, response)
79 | }
80 | return (nil, response)
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/Sources/Typesense/Override.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct Override {
7 | private var apiCall: ApiCall
8 | private var collectionName: String
9 | private var overrideId: String
10 |
11 |
12 | init(apiCall: ApiCall, collectionName: String, overrideId: String) {
13 | self.apiCall = apiCall
14 | self.collectionName = collectionName
15 | self.overrideId = overrideId
16 | }
17 |
18 | public func retrieve(metadataType: T.Type) async throws -> (SearchOverride?, URLResponse?) {
19 | let (data, response) = try await apiCall.get(endPoint: endpointPath())
20 | if let result = data {
21 | let override = try decoder.decode(SearchOverride.self, from: result)
22 | return (override, response)
23 | }
24 |
25 | return (nil, response)
26 | }
27 |
28 | public func delete() async throws -> (SearchOverrideDeleteResponse?, URLResponse?) {
29 | let (data, response) = try await apiCall.delete(endPoint: endpointPath())
30 | if let result = data {
31 | let decodedData = try decoder.decode(SearchOverrideDeleteResponse.self, from: result)
32 | return (decodedData, response)
33 | }
34 | return (nil, response)
35 | }
36 |
37 | private func endpointPath() throws -> String {
38 | return try "\(Collections.RESOURCEPATH)/\(collectionName.encodeURL())/\(Overrides.RESOURCEPATH)/\(overrideId.encodeURL())"
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Sources/Typesense/Overrides.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct Overrides {
7 | static let RESOURCEPATH = "overrides"
8 | private var apiCall: ApiCall
9 | private var collectionName: String
10 |
11 |
12 | init(apiCall: ApiCall, collectionName: String) {
13 | self.apiCall = apiCall
14 | self.collectionName = collectionName
15 | }
16 |
17 | public func upsert(overrideId: String, params: SearchOverrideSchema) async throws -> (SearchOverride?, URLResponse?) {
18 | let schemaData = try encoder.encode(params)
19 | let (data, response) = try await self.apiCall.put(endPoint: endpointPath(overrideId), body: schemaData)
20 |
21 | if let result = data {
22 | let override = try decoder.decode(SearchOverride.self, from: result)
23 | return (override, response)
24 | }
25 |
26 | return (nil, response)
27 | }
28 |
29 | public func retrieve(metadataType: T.Type) async throws -> (SearchOverridesResponse?, URLResponse?) {
30 | let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
31 | if let result = data {
32 | let overrides = try decoder.decode(SearchOverridesResponse.self, from: result)
33 | return (overrides, response)
34 | }
35 | return (nil, nil)
36 | }
37 |
38 | private func endpointPath(_ operation: String? = nil) throws -> String {
39 | let baseEndpoint = try "\(Collections.RESOURCEPATH)/\(collectionName.encodeURL())/\(Overrides.RESOURCEPATH)"
40 | if let operation = operation {
41 | return try "\(baseEndpoint)/\(operation.encodeURL())"
42 | } else {
43 | return baseEndpoint
44 | }
45 | }
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/Typesense/Preset.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct Preset {
7 | private var apiCall: ApiCall
8 | private var presetName: String
9 |
10 |
11 | init(apiCall: ApiCall, presetName: String) {
12 | self.apiCall = apiCall
13 | self.presetName = presetName
14 | }
15 |
16 | public func retrieve() async throws -> (PresetSchema?, URLResponse?) {
17 | let (data, response) = try await apiCall.get(endPoint: endpointPath())
18 | if let result = data {
19 | let preset = try decoder.decode(PresetSchema.self, from: result)
20 | return (preset, response)
21 | }
22 | return (nil, response)
23 | }
24 |
25 | public func delete() async throws -> (PresetDeleteSchema?, URLResponse?) {
26 | let (data, response) = try await apiCall.delete(endPoint: endpointPath())
27 | if let result = data {
28 | let decodedData = try decoder.decode(PresetDeleteSchema.self, from: result)
29 | return (decodedData, response)
30 | }
31 | return (nil, response)
32 | }
33 |
34 | private func endpointPath() throws -> String {
35 | return try "\(Presets.RESOURCEPATH)/\(presetName.encodeURL())"
36 | }
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Typesense/Presets.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct Presets {
7 | static let RESOURCEPATH = "presets"
8 | private var apiCall: ApiCall
9 |
10 |
11 | init(apiCall: ApiCall) {
12 | self.apiCall = apiCall
13 | }
14 |
15 | public func upsert(presetName: String, params: PresetUpsertSchema) async throws -> (PresetSchema?, URLResponse?) {
16 | let schemaData = try encoder.encode(params)
17 | let (data, response) = try await self.apiCall.put(endPoint: endpointPath(presetName), body: schemaData)
18 | if let result = data {
19 | let decodedData = try decoder.decode(PresetSchema.self, from: result)
20 | return (decodedData, response)
21 | }
22 | return (nil, response)
23 | }
24 |
25 | public func retrieve() async throws -> (PresetsRetrieveSchema?, URLResponse?) {
26 | let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
27 | if let result = data {
28 | let decodedData = try decoder.decode(PresetsRetrieveSchema.self, from: result)
29 | return (decodedData, response)
30 | }
31 | return (nil, response)
32 | }
33 |
34 | private func endpointPath(_ operation: String? = nil) throws -> String {
35 | let baseEndpoint = "\(Presets.RESOURCEPATH)"
36 | if let operation = operation {
37 | return try "\(baseEndpoint)/\(operation.encodeURL())"
38 | } else {
39 | return baseEndpoint
40 | }
41 | }
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/Typesense/RequestTypes.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | enum RequestType: String {
4 | case get = "GET"
5 | case post = "POST"
6 | case delete = "DELETE"
7 | case put = "PUT"
8 | case patch = "PATCH"
9 | }
10 |
--------------------------------------------------------------------------------
/Sources/Typesense/Shared/Coders.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public let encoder = JSONEncoder()
7 | public let decoder = JSONDecoder()
8 |
9 | public enum StringQuantum: Codable {
10 |
11 | public var arrStr : [String]? {
12 | guard case .arrOfStrings(let arrOfStrings) = self else { return nil }
13 | return arrOfStrings
14 | }
15 |
16 | public var arrArrStr : [[String]]? {
17 | guard case .arrOfArrOfStrings(let arrOfArrOfStrings) = self else { return nil }
18 | return arrOfArrOfStrings
19 | }
20 |
21 | case arrOfStrings([String]), arrOfArrOfStrings([[String]])
22 |
23 | public init(from decoder: Decoder) throws {
24 | if let arrS = try? decoder.singleValueContainer().decode([String].self) {
25 | self = .arrOfStrings(arrS)
26 | return
27 | }
28 |
29 | if let arrArrS = try? decoder.singleValueContainer().decode([[String]].self) {
30 | self = .arrOfArrOfStrings(arrArrS)
31 | return
32 | }
33 |
34 | throw QuantumError.missingValue
35 | }
36 |
37 | public enum QuantumError:Error {
38 | case missingValue
39 | }
40 | }
41 |
42 | public enum ActionModes: String {
43 | case create = "create"
44 | case upsert = "upsert"
45 | case update = "update"
46 | }
47 |
48 | public struct SlowRequest: Codable {
49 | public var logSlowRequestsTimeMs: Float?
50 |
51 | public init(_ timeInMS: Float? = nil) {
52 | self.logSlowRequestsTimeMs = timeInMS
53 | }
54 |
55 | public enum CodingKeys: String, CodingKey {
56 | case logSlowRequestsTimeMs = "log-slow-requests-time-ms"
57 | }
58 | }
59 |
60 | @available(iOS, deprecated: 15.0, message: "Use the built-in API instead")
61 | extension URLSession {
62 | func data(for req: URLRequest) async throws -> (Data, URLResponse) {
63 | try await withCheckedThrowingContinuation { continuation in
64 | let task = self.dataTask(with: req) { data, response, error in
65 | guard let data = data, let response = response else {
66 | let error = error ?? URLError.invalidURL
67 | return continuation.resume(throwing: error)
68 | }
69 |
70 | continuation.resume(returning: (data, response))
71 | }
72 |
73 | task.resume()
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Sources/Typesense/Shared/Enums.swift:
--------------------------------------------------------------------------------
1 | public enum IndexAction: String, Codable {
2 | case create = "create"
3 | case update = "update"
4 | case upsert = "upsert"
5 | case emplace = "emplace"
6 | }
7 |
8 | public enum DirtyValues: String, Codable {
9 | case coerceOrReject = "coerce_or_reject"
10 | case coerceOrDrop = "coerce_or_drop"
11 | case drop = "drop"
12 | case reject = "reject"
13 | }
--------------------------------------------------------------------------------
/Sources/Typesense/Shared/Logger.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct Logger {
4 | var isDebug: Bool
5 |
6 | public init(debugMode: Bool = false) {
7 | isDebug = debugMode
8 | }
9 |
10 | func log(_ content: String) {
11 | if(isDebug) {
12 | print(content)
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/Typesense/Shared/RequestNumber.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Date {
4 | var millisecondsSince1970:Int64 {
5 | return Int64((self.timeIntervalSince1970 * 1000.0).rounded())
6 | }
7 |
8 | init(milliseconds:Int64) {
9 | self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/Typesense/Stopword.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct Stopword {
7 | private var apiCall: ApiCall
8 | private var stopwordsSetId: String
9 |
10 |
11 | init(apiCall: ApiCall, stopwordsSetId: String) {
12 | self.apiCall = apiCall
13 | self.stopwordsSetId = stopwordsSetId
14 | }
15 |
16 | public func retrieve() async throws -> (StopwordsSetSchema?, URLResponse?) {
17 | let (data, response) = try await apiCall.get(endPoint: endpointPath())
18 | if let result = data {
19 | let decodedData = try decoder.decode(StopwordsSetRetrieveSchema.self, from: result)
20 | return (decodedData.stopwords, response)
21 | }
22 | return (nil, response)
23 | }
24 |
25 | public func delete() async throws -> (StopwordsSetDeleteSchema?, URLResponse?) {
26 | let (data, response) = try await apiCall.delete(endPoint: endpointPath())
27 | if let result = data {
28 | let decodedData = try decoder.decode(StopwordsSetDeleteSchema.self, from: result)
29 | return (decodedData, response)
30 | }
31 | return (nil, response)
32 | }
33 |
34 | private func endpointPath() throws -> String {
35 | return try "\(Stopwords.RESOURCEPATH)/\(stopwordsSetId.encodeURL())"
36 | }
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Typesense/Stopwords.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct Stopwords {
7 | static let RESOURCEPATH = "stopwords"
8 | private var apiCall: ApiCall
9 |
10 |
11 | init(apiCall: ApiCall) {
12 | self.apiCall = apiCall
13 | }
14 |
15 | public func upsert(stopwordsSetId: String, params: StopwordsSetUpsertSchema) async throws -> (StopwordsSetSchema?, URLResponse?) {
16 | let schemaData = try encoder.encode(params)
17 | let (data, response) = try await self.apiCall.put(endPoint: endpointPath(stopwordsSetId), body: schemaData)
18 | if let result = data {
19 | let decodedData = try decoder.decode(StopwordsSetSchema.self, from: result)
20 | return (decodedData, response)
21 | }
22 | return (nil, response)
23 | }
24 |
25 | public func retrieve() async throws -> ([StopwordsSetSchema]?, URLResponse?) {
26 | let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
27 | if let result = data {
28 | let decodedData = try decoder.decode(StopwordsSetsRetrieveAllSchema.self, from: result)
29 | return (decodedData.stopwords, response)
30 | }
31 | return (nil, response)
32 | }
33 |
34 | private func endpointPath(_ operation: String? = nil) throws -> String {
35 | let baseEndpoint = "\(Stopwords.RESOURCEPATH)"
36 | if let operation = operation {
37 | return try "\(baseEndpoint)/\(operation.encodeURL())"
38 | } else {
39 | return baseEndpoint
40 | }
41 | }
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/Typesense/Synonyms.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | public struct Synonyms {
7 | var apiCall: ApiCall
8 | var collectionName: String
9 |
10 | init(apiCall: ApiCall, collectionName: String) {
11 | self.apiCall = apiCall
12 | self.collectionName = collectionName
13 | }
14 |
15 | public func upsert(id: String, _ searchSynonym: SearchSynonymSchema) async throws -> (SearchSynonym?, URLResponse?) {
16 | var schemaData: Data? = nil
17 | schemaData = try encoder.encode(searchSynonym)
18 |
19 | if let validSchema = schemaData {
20 | let (data, response) = try await apiCall.put(endPoint: endpointPath(id), body: validSchema)
21 | if let result = data {
22 | let synonym = try decoder.decode(SearchSynonym.self, from: result)
23 | return (synonym, response)
24 | }
25 |
26 | }
27 | return (nil, nil)
28 | }
29 |
30 | public func retrieve(id: String) async throws -> (SearchSynonym?, URLResponse?) {
31 | let (data, response) = try await apiCall.get(endPoint: endpointPath(id))
32 | if let result = data {
33 | let synonym = try decoder.decode(SearchSynonym.self, from: result)
34 | return (synonym, response)
35 | }
36 | return (nil, nil)
37 | }
38 |
39 | public func retrieve() async throws -> (SearchSynonymsResponse?, URLResponse?) {
40 | let (data, response) = try await apiCall.get(endPoint: endpointPath())
41 | if let result = data {
42 | let synonym = try decoder.decode(SearchSynonymsResponse.self, from: result)
43 | return (synonym, response)
44 | }
45 | return (nil, nil)
46 | }
47 |
48 | public func delete(id: String) async throws -> (Data?, URLResponse?) {
49 | let (data, response) = try await apiCall.get(endPoint: endpointPath())
50 | return (data, response)
51 | }
52 |
53 | private func endpointPath(_ operation: String? = nil) throws -> String {
54 | let baseEndpoint = try "\(Collections.RESOURCEPATH)/\(collectionName.encodeURL())/synonyms"
55 | if let operation: String = operation {
56 | return "\(baseEndpoint)/\(try operation.encodeURL())"
57 | } else {
58 | return baseEndpoint
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Sources/Typesense/utils/CreateURLQueryParams.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if canImport(FoundationNetworking)
3 | import FoundationNetworking
4 | #endif
5 |
6 | func createURLQuery(forSchema: T?) throws -> [URLQueryItem]{
7 | var searchQueryParams: [URLQueryItem] = []
8 |
9 | guard let schema = forSchema else{
10 | return searchQueryParams
11 | }
12 |
13 | let jsonData = try encoder.encode(schema)
14 | let json = try JSONSerialization.jsonObject(with: jsonData, options: [])
15 |
16 | guard let dictionary = json as? [String : Any] else {
17 | throw DataError.unableToParse(message: "Unable to create query params for \(type(of: schema))")
18 | }
19 |
20 | for (key, val) in dictionary {
21 | var stringVal = ""
22 | if let str = val as? String {
23 | stringVal = str
24 | } else if type(of: val) == type(of: NSNumber(booleanLiteral: true)) || type(of: val) == type(of: NSNumber(booleanLiteral: false)), let bool = val as? Bool{
25 | stringVal = String(bool)
26 | } else if let int = val as? Int {
27 | stringVal = String(int)
28 | } else if let double = val as? Double {
29 | stringVal = String(double)
30 | } else{
31 | throw DataError.unableToParse(message: "Unknown data type for key: `\(key)`, type: `\(type(of: val))` of `\(type(of: schema))`")
32 | }
33 | searchQueryParams.append(URLQueryItem(name: key, value: stringVal))
34 | }
35 | return searchQueryParams
36 | }
--------------------------------------------------------------------------------
/Sources/Typesense/utils/Extensions.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | private let urlAllowed: CharacterSet = .alphanumerics.union(.init(charactersIn: "-._~"))
4 |
5 | internal extension String {
6 | func encodeURL() throws -> String {
7 | let percentEncoded = self.addingPercentEncoding(withAllowedCharacters: urlAllowed)
8 | guard let valid = percentEncoded else{
9 | throw URLError.encodingError(message: "Failed to encode URL for string `\(self)`")
10 | }
11 | return valid
12 | }
13 | }
14 |
15 | extension MultiSearchSearchesParameter {
16 | public init(searches: [MultiSearchParameters]) {
17 | self.searches = searches.map { params in
18 | var collectionParams = MultiSearchCollectionParameters()
19 | collectionParams.q = params.q
20 | collectionParams.queryBy = params.queryBy
21 | collectionParams.queryByWeights = params.queryByWeights
22 | collectionParams.textMatchType = params.textMatchType
23 | collectionParams._prefix = params._prefix
24 | collectionParams._infix = params._infix
25 | collectionParams.maxExtraPrefix = params.maxExtraPrefix
26 | collectionParams.maxExtraSuffix = params.maxExtraSuffix
27 | collectionParams.filterBy = params.filterBy
28 | collectionParams.sortBy = params.sortBy
29 | collectionParams.facetBy = params.facetBy
30 | collectionParams.maxFacetValues = params.maxFacetValues
31 | collectionParams.facetQuery = params.facetQuery
32 | collectionParams.numTypos = params.numTypos
33 | collectionParams.page = params.page
34 | collectionParams.perPage = params.perPage
35 | collectionParams.limit = params.limit
36 | collectionParams.offset = params.offset
37 | collectionParams.groupBy = params.groupBy
38 | collectionParams.groupLimit = params.groupLimit
39 | collectionParams.groupMissingValues = params.groupMissingValues
40 | collectionParams.includeFields = params.includeFields
41 | collectionParams.excludeFields = params.excludeFields
42 | collectionParams.highlightFullFields = params.highlightFullFields
43 | collectionParams.highlightAffixNumTokens = params.highlightAffixNumTokens
44 | collectionParams.highlightStartTag = params.highlightStartTag
45 | collectionParams.highlightEndTag = params.highlightEndTag
46 | collectionParams.snippetThreshold = params.snippetThreshold
47 | collectionParams.dropTokensThreshold = params.dropTokensThreshold
48 | collectionParams.typoTokensThreshold = params.typoTokensThreshold
49 | collectionParams.pinnedHits = params.pinnedHits
50 | collectionParams.hiddenHits = params.hiddenHits
51 | collectionParams.overrideTags = params.overrideTags
52 | collectionParams.highlightFields = params.highlightFields
53 | collectionParams.preSegmentedQuery = params.preSegmentedQuery
54 | collectionParams.preset = params.preset
55 | collectionParams.enableOverrides = params.enableOverrides
56 | collectionParams.prioritizeExactMatch = params.prioritizeExactMatch
57 | collectionParams.prioritizeTokenPosition = params.prioritizeTokenPosition
58 | collectionParams.prioritizeNumMatchingFields = params.prioritizeNumMatchingFields
59 | collectionParams.enableTyposForNumericalTokens = params.enableTyposForNumericalTokens
60 | collectionParams.exhaustiveSearch = params.exhaustiveSearch
61 | collectionParams.searchCutoffMs = params.searchCutoffMs
62 | collectionParams.useCache = params.useCache
63 | collectionParams.cacheTtl = params.cacheTtl
64 | collectionParams.minLen1typo = params.minLen1typo
65 | collectionParams.minLen2typo = params.minLen2typo
66 | collectionParams.vectorQuery = params.vectorQuery
67 | collectionParams.remoteEmbeddingTimeoutMs = params.remoteEmbeddingTimeoutMs
68 | collectionParams.remoteEmbeddingNumTries = params.remoteEmbeddingNumTries
69 | collectionParams.facetStrategy = params.facetStrategy
70 | collectionParams.stopwords = params.stopwords
71 | collectionParams.facetReturnParent = params.facetReturnParent
72 | collectionParams.voiceQuery = params.voiceQuery
73 | collectionParams.rerankHybridMatches = params.rerankHybridMatches
74 | collectionParams.xTypesenseApiKey = params.xTypesenseApiKey
75 | return collectionParams
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/AnalyticsTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class AnalyticsTests: XCTestCase {
5 | override func setUp() async throws {
6 | try await createCollection()
7 | try await createAnalyticRule()
8 | }
9 |
10 | override func tearDown() async throws {
11 | try await tearDownAnalyticsRules()
12 | try await tearDownCollections()
13 | }
14 |
15 | func testAnalyticsRuleCreate() async {
16 | let destination = AnalyticsRuleParametersDestination(collection: "product_queries")
17 | let source = AnalyticsRuleParametersSource(collections: ["products"])
18 | let schema = AnalyticsRuleSchema(name: "product_queries_aggregation", type: .popularQueries, params: AnalyticsRuleParameters(source: source, destination: destination, limit: 1000))
19 | do {
20 | let (rule, _) = try await client.analytics().rules().upsert(params: schema)
21 | XCTAssertNotNil(rule)
22 | guard let validRule = rule else {
23 | throw DataError.dataNotFound
24 | }
25 | print(validRule)
26 | XCTAssertEqual(validRule.name, schema.name)
27 | XCTAssertEqual(validRule.params.limit, schema.params.limit)
28 | XCTAssertEqual(validRule.params.destination.collection, schema.params.destination.collection)
29 | } catch (let error) {
30 | print(error.localizedDescription)
31 | XCTAssertTrue(false)
32 | }
33 | }
34 |
35 | func testAnalyticsRuleRetrieve() async {
36 | do {
37 | let (rule, _) = try await client.analytics().rule(id: "product_queries_aggregation").retrieve()
38 | guard let validRule = rule else {
39 | throw DataError.dataNotFound
40 | }
41 | print(validRule)
42 | XCTAssertEqual(validRule.name, "product_queries_aggregation")
43 | } catch (let error) {
44 | print(error.localizedDescription)
45 | XCTAssertTrue(false)
46 | }
47 | }
48 |
49 | func testAnalyticsRuleRetrieveAll() async {
50 | do {
51 | let (rules, _) = try await client.analytics().rules().retrieveAll()
52 | XCTAssertNotNil(rules)
53 | guard let validRules = rules?.rules else {
54 | throw DataError.dataNotFound
55 | }
56 | print(validRules)
57 | XCTAssertEqual(validRules[0].name, "product_queries_aggregation")
58 | } catch (let error) {
59 | print(error.localizedDescription)
60 | XCTAssertTrue(false)
61 | }
62 | }
63 |
64 | func testAnalyticsRuleDelete() async {
65 | do {
66 | let (deletedRule, _) = try await client.analytics().rule(id: "product_queries_aggregation").delete()
67 | XCTAssertNotNil(deletedRule)
68 | guard let validRule = deletedRule else {
69 | throw DataError.dataNotFound
70 | }
71 | print(validRule)
72 | XCTAssertEqual(validRule.name, "product_queries_aggregation")
73 | } catch (let error) {
74 | print(error.localizedDescription)
75 | XCTAssertTrue(false)
76 | }
77 | }
78 |
79 | func testAnalyticsEventsCreate() async {
80 | do {
81 | let (res, _) = try await client.analytics().events().create(params: AnalyticsEventCreateSchema(
82 | type: "click",
83 | name: "products_click_event",
84 | data: [
85 | "q": "nike shoes",
86 | "doc_id": "1024",
87 | "user_id": "111112"
88 | ]
89 | ))
90 | guard let validRes = res else {
91 | throw DataError.dataNotFound
92 | }
93 | print(validRes)
94 | XCTAssertTrue(validRes.ok)
95 | } catch (let error) {
96 | print(error.localizedDescription)
97 | XCTAssertTrue(false)
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/ApiKeyTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class ApiKeyTests: XCTestCase {
5 | override func tearDown() async throws {
6 | try await tearDownAPIKeys()
7 | }
8 |
9 | func testKeyCreate() async {
10 | do {
11 | let adminKey = ApiKeySchema(_description: "Test key with all privileges", actions: ["*"], collections: ["*"])
12 | let (data, _) = try await client.keys().create(adminKey)
13 | XCTAssertNotNil(data)
14 | guard let validData = data else {
15 | throw DataError.dataNotFound
16 | }
17 | print(validData)
18 | XCTAssertEqual(validData._description, "Test key with all privileges")
19 | XCTAssertEqual(validData.actions, ["*"])
20 | XCTAssertEqual(validData.collections, ["*"])
21 | } catch (let error) {
22 | print(error.localizedDescription)
23 | XCTAssertTrue(false) //To prevent this, check availability of Typesense Server and retry
24 | }
25 | }
26 |
27 | func testKeyRetrieve() async {
28 | do {
29 | let key = try await createAPIKey()
30 | let (data, _) = try await client.keys().retrieve(id: key._id)
31 | XCTAssertNotNil(data)
32 | guard let validData = data else {
33 | throw DataError.dataNotFound
34 | }
35 | print(validData)
36 | XCTAssertEqual(validData._description, "Test key with all privileges")
37 | XCTAssertEqual(validData.actions, ["*"])
38 | XCTAssertEqual(validData.collections, ["*"])
39 | } catch (let error) {
40 | print(error.localizedDescription)
41 | XCTAssertTrue(false) //To prevent this, check availability of Typesense Server and retry
42 | }
43 | }
44 |
45 | func testKeyRetrieveAll() async {
46 | do {
47 | let key = try await createAPIKey()
48 | let (data, _) = try await client.keys().retrieve()
49 | XCTAssertNotNil(data)
50 | guard let validData = data?.keys else {
51 | throw DataError.dataNotFound
52 | }
53 | print(validData)
54 | XCTAssertEqual(validData[0]._id, key._id)
55 | } catch (let error) {
56 | print(error.localizedDescription)
57 | XCTAssertTrue(false) //To prevent this, check availability of Typesense Server and retry
58 | }
59 | }
60 |
61 | func testKeyDelete() async {
62 | do {
63 | let key = try await createAPIKey()
64 | let (data, _) = try await client.keys().delete(id: key._id)
65 | XCTAssertNotNil(data)
66 | guard let validData = data else {
67 | throw DataError.dataNotFound
68 | }
69 | print(validData)
70 | } catch (let error) {
71 | print(error.localizedDescription)
72 | XCTAssertTrue(false) //To prevent this, check availability of Typesense Server and retry
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/CollectionAliasTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class CollectionAliasTests: XCTestCase {
5 | override func tearDown() async throws {
6 | try await tearDownAliases()
7 | }
8 |
9 | func testAliasUpsert() async {
10 | do {
11 | let aliasCollection = CollectionAliasSchema(collectionName: "companies_june")
12 | let (data, _) = try await client.aliases().upsert(name: "companies-_-~.?test=&123 + # /h/()", collection: aliasCollection)
13 | XCTAssertNotNil(data)
14 | guard let validData = data else {
15 | throw DataError.dataNotFound
16 | }
17 | print(validData)
18 | XCTAssertEqual(validData.name, "companies-_-~.?test=&123 + # /h/()")
19 | XCTAssertEqual(validData.collectionName, "companies_june")
20 | } catch (let error) {
21 | print(error.localizedDescription)
22 | XCTAssertTrue(false)
23 | }
24 | }
25 |
26 | func testAliasRetrieve() async {
27 | do {
28 | try await createAlias()
29 | let (data, _) = try await client.aliases().retrieve(name: "companies")
30 | XCTAssertNotNil(data)
31 | guard let validData = data else {
32 | throw DataError.dataNotFound
33 | }
34 | print(validData)
35 | XCTAssertEqual(validData.name, "companies")
36 | XCTAssertEqual(validData.collectionName, "companies_june")
37 | } catch (let error) {
38 | print(error.localizedDescription)
39 | XCTAssertTrue(false)
40 | }
41 | }
42 |
43 | func testAliasRetrieveAll() async {
44 | do {
45 | try await createAlias()
46 | let (data, _) = try await client.aliases().retrieve()
47 | XCTAssertNotNil(data)
48 | guard let validData = data?.aliases else {
49 | throw DataError.dataNotFound
50 | }
51 | XCTAssertEqual(validData.count, 1)
52 | XCTAssertEqual(validData[0].collectionName, "companies_june")
53 | XCTAssertEqual(validData[0].name, "companies")
54 | } catch (let error) {
55 | print(error.localizedDescription)
56 | XCTAssertTrue(false)
57 | }
58 | }
59 |
60 | func testAliasDelete() async {
61 | do {
62 | try await createAlias()
63 | let (data, _) = try await client.aliases().delete(name: "companies")
64 | XCTAssertNotNil(data)
65 | guard let validData = data else {
66 | throw DataError.dataNotFound
67 | }
68 | print(validData)
69 | XCTAssertEqual(validData.name, "companies")
70 | XCTAssertEqual(validData.collectionName, "companies_june")
71 | } catch (let error) {
72 | print(error.localizedDescription)
73 | XCTAssertTrue(false)
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/CollectionTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class CollectionTests: XCTestCase {
5 | override func tearDown() async throws {
6 | try await tearDownCollections()
7 | }
8 |
9 | func testCollectionCreate() async {
10 | let schema = CollectionSchema(name: "companies", fields: [Field(name: "company_name", type: "string"), Field(name: "num_employees", type: "int32"), Field(name: "country", type: "string", facet: true)], defaultSortingField: "num_employees")
11 | do {
12 | let (collResp, _) = try await client.collections.create(schema: schema)
13 | XCTAssertNotNil(collResp)
14 | guard let validData = collResp else {
15 | throw DataError.dataNotFound
16 | }
17 | print(validData)
18 | XCTAssertEqual(validData.name, "companies")
19 | XCTAssertNotNil(validData.fields)
20 | XCTAssertEqual(validData.fields.count, 3)
21 | XCTAssertEqual(validData.defaultSortingField, "num_employees")
22 | } catch (let error) {
23 | print(error.localizedDescription)
24 | XCTAssertTrue(false) //To prevent this, check availability of Typesense Server and retry
25 | }
26 | }
27 |
28 | func testCollectionDelete() async {
29 | do {
30 | try await createCollection()
31 | let (collResp, _) = try await client.collection(name: "companies").delete()
32 | XCTAssertNotNil(collResp)
33 | guard let validData = collResp else {
34 | throw DataError.dataNotFound
35 | }
36 | print(validData)
37 | XCTAssertEqual(validData.name, "companies")
38 | } catch (let error) {
39 | print(error.localizedDescription)
40 | XCTAssertTrue(false)
41 | }
42 | }
43 |
44 | func testCollectionRetrieveAll() async {
45 | do {
46 | try await createCollection()
47 | let (collResp, _) = try await client.collections.retrieveAll()
48 | XCTAssertNotNil(collResp)
49 | guard let validData = collResp else {
50 | throw DataError.dataNotFound
51 | }
52 | print(validData)
53 | XCTAssertEqual(validData.count, 1)
54 | XCTAssertEqual(validData[0].name, "companies")
55 | } catch (let error) {
56 | print(error.localizedDescription)
57 | XCTAssertTrue(false)
58 | }
59 | }
60 |
61 | func testCollectionRetrieveOne() async {
62 | do {
63 | try await createCollection()
64 | let (collResp, _) = try await client.collection(name: "companies").retrieve()
65 | XCTAssertNotNil(collResp)
66 | guard let validData = collResp else {
67 | throw DataError.dataNotFound
68 | }
69 | print(validData)
70 | XCTAssertEqual(validData.name, "companies")
71 | } catch (let error) {
72 | print(error.localizedDescription)
73 | XCTAssertTrue(false)
74 | }
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/ConfigurationTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class ConfigurationTests: XCTestCase {
5 | func testQuickConfig() {
6 | let newConfig = Configuration(nodes: [Node(host: "localhost", port: "8108", nodeProtocol: "http")], apiKey: "xyz")
7 | let myClient = Client(config: newConfig)
8 |
9 | XCTAssertFalse(myClient.configuration.nodes.isEmpty)
10 | }
11 |
12 | func testQuickConfigConnectionTimeout() {
13 | let newConfig = Configuration(nodes: [Node(host: "localhost", port: "8108", nodeProtocol: "http")], apiKey: "xyz", connectionTimeoutSeconds: 8)
14 | let myClient = Client(config: newConfig)
15 |
16 | XCTAssertFalse(myClient.configuration.nodes.isEmpty)
17 | XCTAssertEqual(myClient.configuration.connectionTimeoutSeconds, 8)
18 | }
19 |
20 | func testQuickConfigNearestNode() {
21 | let newConfig = Configuration(nodes: [Node(host: "localhost", port: "8108", nodeProtocol: "http")], apiKey: "xyz", nearestNode: Node(host: "localhost", port: "8108", nodeProtocol: "http"))
22 | let myClient = Client(config: newConfig)
23 |
24 | XCTAssertFalse(myClient.configuration.nodes.isEmpty)
25 | XCTAssertNotNil(myClient.configuration.nearestNode)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/ConversationModelTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class ConversationModelTests: XCTestCase {
5 | func testConversationModelsCreate() async {
6 | let schema = ConversationModelCreateSchema(
7 | _id: "conv-model-1",
8 | modelName: "test/gpt-3.5-turbo",
9 | apiKey: "sk",
10 | historyCollection: "conversation_store",
11 | systemPrompt: "You are an assistant for question-answering.",
12 | ttl: 123,
13 | maxBytes: 16384
14 | )
15 | do {
16 | try await createConversationCollection()
17 | let _ = try await client.conversations().models().create(params: schema)
18 | } catch HTTPError.clientError(let code, let desc){
19 | print(desc)
20 | XCTAssertEqual(code, 400)
21 | XCTAssertTrue(desc.contains("Model namespace `test` is not supported."))
22 | } catch (let error) {
23 | print(error.localizedDescription)
24 | XCTAssertTrue(false)
25 | }
26 | try? await tearDownCollections()
27 | }
28 |
29 | func testConversationModelsRetrieve() async {
30 | do {
31 | let (data, _) = try await client.conversations().models().retrieve()
32 | guard let validData = data else {
33 | throw DataError.dataNotFound
34 | }
35 | XCTAssertEqual(0, validData.count)
36 | } catch (let error) {
37 | print(error)
38 | XCTAssertTrue(false)
39 | }
40 | }
41 |
42 | func testConversationModelUpdate() async {
43 | do {
44 | let _ = try await client.conversations().model(modelId: "conv-model-1").update(params: ConversationModelUpdateSchema())
45 | } catch HTTPError.clientError(let code, let desc){
46 | print(desc)
47 | XCTAssertEqual(code, 404)
48 | XCTAssertTrue(desc.contains("Model not found"))
49 | } catch (let error) {
50 | print(error)
51 | XCTAssertTrue(false)
52 | }
53 | }
54 |
55 | func testConversationModelRetrieve() async {
56 | do {
57 | let _ = try await client.conversations().model(modelId: "conv-model-1").retrieve()
58 | } catch HTTPError.clientError(let code, let desc){
59 | print(desc)
60 | XCTAssertEqual(code, 404)
61 | XCTAssertTrue(desc.contains("Model not found"))
62 | } catch (let error) {
63 | print(error)
64 | XCTAssertTrue(false)
65 | }
66 | }
67 |
68 | func testConversationModelDelete() async {
69 | do {
70 | let _ = try await client.conversations().model(modelId: "conv-model-1").delete()
71 | } catch HTTPError.clientError(let code, let desc){
72 | print(desc)
73 | XCTAssertEqual(code, 404)
74 | XCTAssertTrue(desc.contains("Model not found"))
75 | } catch (let error) {
76 | print(error)
77 | XCTAssertTrue(false)
78 | }
79 | }
80 |
81 | func testConversationSearch() async {
82 | do {
83 | let string = """
84 | {
85 | "conversation": {
86 | "answer": " context information, I' unable to suggest an is information given about specific context action as,, specific titles If a preference for particular genre length of, please that information and I' try my best to suggestions.",
87 | "conversation_history": [
88 | {
89 | "user": "can you suggest an action series"
90 | },
91 | {
92 | "assistant": " context information, I' unable to suggest an is information given about specific context action as,, specific titles If a preference for particular genre length of, please that information and I' try my best to suggestions."
93 | }
94 | ],
95 | "conversation_id": "123",
96 | "query": "can you suggest an action series"
97 | },
98 | "results": [
99 | {
100 | "code": 404,
101 | "error": "Not found."
102 | }
103 | ]
104 | }
105 | """
106 | let data = string.data(using: .utf8)!
107 | let _ = try decoder.decode(MultiSearchResult.self, from: data)
108 | XCTAssertTrue(true)
109 | }catch (let error) {
110 | print(error)
111 | XCTAssertTrue(false)
112 | }
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/CreateURLQueryParamsTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class CreateURLQueryParamsTests: XCTestCase {
5 | struct Car: Codable {
6 | var name = "Fast"
7 | var age: Int = 20
8 | var price: Int64 = 2000
9 | var page: Int? = 1
10 | var groupLimit: Int64? = 0
11 | var speed: Double = 120.555
12 | var mileage: Float = 120.5
13 | var isElectric = true
14 | var inStock: Bool = false
15 | var empty: String? = nil
16 |
17 | enum CodingKeys: String, CodingKey {
18 | case name
19 | case age
20 | case price
21 | case page
22 | case groupLimit = "group_limit"
23 | case speed
24 | case mileage
25 | case isElectric = "is_electric"
26 | case inStock = "in_stock"
27 | case empty
28 | }
29 | }
30 | func testCreateURLQueryParams() {
31 | do {
32 | let queryParams = try createURLQuery(forSchema: Car())
33 | print(queryParams)
34 | XCTAssertEqual(queryParams.count, 9)
35 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "name", value: "Fast")))
36 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "age", value: "20")))
37 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "price", value: "2000")))
38 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "page", value: "1")))
39 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "group_limit", value: "0")))
40 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "speed", value: "120.555")))
41 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "mileage", value: "120.5")))
42 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "is_electric", value: "true")))
43 | XCTAssertTrue(queryParams.contains(URLQueryItem(name: "in_stock", value: "false")))
44 | XCTAssertFalse(queryParams.contains(URLQueryItem(name: "empty", value: "null")))
45 | } catch (let error) {
46 | print(error)
47 | XCTAssertTrue(false)
48 | }
49 | }
50 |
51 | struct People: Codable {
52 | var obj = ["isHooman": true]
53 | }
54 |
55 | func testCreateURLQueryParamsThrowsError() {
56 | do {
57 | let _ = try createURLQuery(forSchema: People())
58 | } catch DataError.unableToParse(let msg){
59 | if !msg.contains("Unknown data type"){
60 | XCTAssertTrue(false)
61 | }
62 | } catch (let error) {
63 | print(error)
64 | XCTAssertTrue(false)
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/OverrideTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class OverrideTests: XCTestCase {
5 | override func setUp() async throws {
6 | try await createCollection()
7 | try await createAnOverride()
8 | }
9 |
10 | override func tearDown() async throws {
11 | try await tearDownCollections()
12 | }
13 |
14 | func testOverrideRetrieve() async {
15 | do {
16 | let (result, _) = try await client.collection(name: "companies").override("test-id").retrieve(metadataType: SearchOverrideExclude.self )
17 | guard let validOverride = result else {
18 | throw DataError.dataNotFound
19 | }
20 | print(validOverride)
21 | XCTAssertEqual("test-id", validOverride._id)
22 | XCTAssertEqual("exclude-id", validOverride.metadata?._id)
23 | } catch HTTPError.serverError(let code, let desc) {
24 | print(desc)
25 | print("The response status code is \(code)")
26 | XCTAssertTrue(false)
27 | } catch (let error) {
28 | print(error)
29 | XCTAssertTrue(false)
30 | }
31 | }
32 |
33 | func testOverrideDelete() async {
34 | do {
35 | let (result, _) = try await client.collection(name: "companies").override("test-id").delete()
36 | guard let validOverride = result else {
37 | throw DataError.dataNotFound
38 | }
39 | print(validOverride)
40 | XCTAssertEqual("test-id", validOverride._id)
41 | } catch HTTPError.serverError(let code, let desc) {
42 | print(desc)
43 | print("The response status code is \(code)")
44 | XCTAssertTrue(false)
45 | } catch (let error) {
46 | print(error)
47 | XCTAssertTrue(false)
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/OverridesTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class OverridesTests: XCTestCase {
5 | override func setUp() async throws {
6 | try await createCollection()
7 | }
8 |
9 | override func tearDown() async throws {
10 | try await tearDownCollections()
11 | }
12 |
13 | func testOverridesUpsert() async {
14 | let schema = SearchOverrideSchema(
15 | rule: SearchOverrideRule(tags: ["test"], query: "test", match: SearchOverrideRule.Match.exact, filterBy: "employees:=50"),
16 | includes: [SearchOverrideInclude(_id: "include-id", position: 1)],
17 | excludes: [SearchOverrideExclude(_id: "exclude-id")],
18 | filterBy: "test:=true",
19 | removeMatchedTokens: false,
20 | metadata: SearchOverrideExclude(_id: "test-json"),
21 | sortBy: "asc",
22 | replaceQuery: "test",
23 | filterCuratedHits: false,
24 | effectiveFromTs: 123,
25 | effectiveToTs: 456,
26 | stopProcessing: false
27 | )
28 | do {
29 | let (result, _) = try await client.collection(name: "companies").overrides().upsert(overrideId: "test-id", params: schema)
30 | XCTAssertNotNil(result)
31 | guard let validOverride = result else {
32 | throw DataError.dataNotFound
33 | }
34 | print(validOverride)
35 | XCTAssertEqual("test-id", validOverride._id)
36 | XCTAssertEqual("test", validOverride.rule.query)
37 | XCTAssertEqual("test-json", validOverride.metadata?._id)
38 | XCTAssertEqual("include-id", validOverride.includes?[0]._id)
39 | XCTAssertEqual("exclude-id", validOverride.excludes?[0]._id)
40 | XCTAssertEqual("test:=true", validOverride.filterBy)
41 | XCTAssertEqual(false, validOverride.removeMatchedTokens)
42 | XCTAssertEqual("asc", validOverride.sortBy)
43 | XCTAssertEqual("test", validOverride.replaceQuery)
44 | XCTAssertEqual(false, validOverride.filterCuratedHits)
45 | XCTAssertEqual(123, validOverride.effectiveFromTs)
46 | XCTAssertEqual(456, validOverride.effectiveToTs)
47 | XCTAssertEqual(false, validOverride.stopProcessing)
48 | } catch (let error) {
49 | print(error.localizedDescription)
50 | XCTAssertTrue(false)
51 | }
52 | }
53 |
54 | func testOverridesRetrieve() async {
55 | do {
56 | try await createAnOverride()
57 | let (overrides, _) = try await client.collection(name: "companies").overrides().retrieve(metadataType: SearchOverrideExclude.self )
58 | guard let validOverrides = overrides else {
59 | throw DataError.dataNotFound
60 | }
61 | print(validOverrides)
62 | XCTAssertEqual(1, validOverrides.overrides.count)
63 | XCTAssertEqual("test-id", validOverrides.overrides[0]._id)
64 | } catch HTTPError.serverError(let code, let desc) {
65 | print(desc)
66 | print("The response status code is \(code)")
67 | XCTAssertTrue(false)
68 | } catch (let error) {
69 | print(error)
70 | XCTAssertTrue(false)
71 | }
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/PresetTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class PresetTests: XCTestCase {
5 | override func setUp() async throws {
6 | try await createSingleCollectionSearchPreset()
7 | }
8 | override func tearDown() async throws {
9 | try await tearDownPresets()
10 | }
11 |
12 | func testPresetRetrieve() async {
13 | do {
14 | let (result, _) = try await client.preset("test-id").retrieve()
15 | XCTAssertNotNil(result)
16 | guard let validResult = result else {
17 | throw DataError.dataNotFound
18 | }
19 | print(validResult)
20 | XCTAssertEqual("test-id", validResult.name)
21 | switch validResult.value {
22 | case .singleCollectionSearch(let value):
23 | XCTAssertEqual("apple", value.q)
24 | default:
25 | XCTAssertTrue(false)
26 | }
27 | } catch (let error) {
28 | print(error.localizedDescription)
29 | XCTAssertTrue(false)
30 | }
31 | }
32 |
33 | func testPresetDelete() async {
34 | do {
35 | let (result, _) = try await client.preset("test-id").delete()
36 | XCTAssertNotNil(result)
37 | guard let validResult = result else {
38 | throw DataError.dataNotFound
39 | }
40 | print(validResult)
41 | XCTAssertEqual("test-id", validResult.name)
42 | } catch (let error) {
43 | print(error.localizedDescription)
44 | XCTAssertTrue(false)
45 | }
46 |
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/PresetsTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class PresetsTests: XCTestCase {
5 | override func tearDown() async throws {
6 | try await tearDownPresets()
7 | }
8 |
9 | func testPresetsUpsertSearchParameters() async {
10 | let schema = PresetUpsertSchema(
11 | value: PresetValue.singleCollectionSearch(SearchParameters(q: "apple"))
12 | )
13 | do {
14 | let (result, _) = try await client.presets().upsert(presetName: "test-id", params: schema)
15 | XCTAssertNotNil(result)
16 | guard let validResult = result else {
17 | throw DataError.dataNotFound
18 | }
19 | print(validResult)
20 | XCTAssertEqual("test-id", validResult.name)
21 | switch validResult.value {
22 | case .singleCollectionSearch(let value):
23 | XCTAssertEqual("apple", value.q)
24 | default:
25 | XCTAssertTrue(false)
26 | }
27 | } catch (let error) {
28 | print(error.localizedDescription)
29 | XCTAssertTrue(false)
30 | }
31 | }
32 |
33 | func testPresetsUpsertMultiSearchSearchesParameter() async {
34 | let schema = PresetUpsertSchema(
35 | value: PresetValue.multiSearch(MultiSearchSearchesParameter(searches: [MultiSearchCollectionParameters(q: "apple")]))
36 | )
37 | do {
38 | let (result, _) = try await client.presets().upsert(presetName: "test-id", params: schema)
39 | XCTAssertNotNil(result)
40 | guard let validResult = result else {
41 | throw DataError.dataNotFound
42 | }
43 | print(validResult)
44 | XCTAssertEqual("test-id", validResult.name)
45 | switch validResult.value {
46 | case .multiSearch(let value):
47 | XCTAssertEqual("apple", value.searches[0].q)
48 | default:
49 | XCTAssertTrue(false)
50 | }
51 | } catch (let error) {
52 | print(error.localizedDescription)
53 | XCTAssertTrue(false)
54 | }
55 | }
56 |
57 | func testPresetsRetrieveAll() async {
58 | do {
59 | try await createSingleCollectionSearchPreset();
60 | try await createMultiSearchPreset();
61 | let (result, _) = try await client.presets().retrieve()
62 | guard let validResult = result else {
63 | throw DataError.dataNotFound
64 | }
65 | print(validResult)
66 | XCTAssertEqual(2, validResult.presets.count)
67 | for preset in validResult.presets{
68 | switch preset.value {
69 | case .singleCollectionSearch(let value):
70 | XCTAssertEqual("test-id", preset.name)
71 | XCTAssertEqual("apple", value.q)
72 | case .multiSearch(let value):
73 | XCTAssertEqual("test-id-preset-multi-search", preset.name)
74 | XCTAssertEqual("banana", value.searches[0].q)
75 | }
76 | }
77 | } catch (let error) {
78 | print(error)
79 | XCTAssertTrue(false)
80 | }
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/StopwordTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class StopwordTests: XCTestCase {
5 | override func tearDown() async throws {
6 | try await tearDownStopwords()
7 | }
8 |
9 | func testStopwordRetrieve() async {
10 | do {
11 | try await createStopwordSet()
12 | let (result, _) = try await client.stopword("test-id-stopword-set").retrieve()
13 | XCTAssertNotNil(result)
14 | guard let validResult = result else {
15 | throw DataError.dataNotFound
16 | }
17 | print(validResult)
18 | XCTAssertEqual("test-id-stopword-set", validResult._id)
19 | XCTAssertEqual(["states","united"], validResult.stopwords)
20 | XCTAssertEqual("en", validResult.locale)
21 | } catch (let error) {
22 | print(error.localizedDescription)
23 | XCTAssertTrue(false)
24 | }
25 | }
26 |
27 | func testStopwordDelete() async {
28 | do {
29 | try await createStopwordSet()
30 | let (result, _) = try await client.stopword("test-id-stopword-set").delete()
31 | guard let validResult = result else {
32 | throw DataError.dataNotFound
33 | }
34 | print(validResult)
35 | XCTAssertEqual("test-id-stopword-set", validResult._id)
36 | } catch (let error) {
37 | print(error)
38 | XCTAssertTrue(false)
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Tests/TypesenseTests/StopwordsTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Typesense
3 |
4 | final class StopwordsTests: XCTestCase {
5 | override func tearDown() async throws {
6 | try await tearDownStopwords()
7 | }
8 |
9 | func testStopwordsUpsert() async {
10 | let schema = StopwordsSetUpsertSchema(
11 | stopwords: ["states","united"],
12 | locale: "en"
13 | )
14 | do {
15 | let (result, _) = try await client.stopwords().upsert(stopwordsSetId: "test-id", params: schema)
16 | XCTAssertNotNil(result)
17 | guard let validResult = result else {
18 | throw DataError.dataNotFound
19 | }
20 | print(validResult)
21 | XCTAssertEqual("test-id", validResult._id)
22 | XCTAssertEqual(["states","united"], validResult.stopwords)
23 | XCTAssertEqual("en", validResult.locale)
24 | } catch (let error) {
25 | print(error.localizedDescription)
26 | XCTAssertTrue(false)
27 | }
28 | }
29 |
30 | func testStopwordsRetrieveAll() async {
31 | do {
32 | try await createStopwordSet()
33 | let (result, _) = try await client.stopwords().retrieve()
34 | guard let validResult = result else {
35 | throw DataError.dataNotFound
36 | }
37 | print(validResult)
38 | XCTAssertEqual(1, validResult.count)
39 | XCTAssertEqual("test-id-stopword-set", validResult[0]._id)
40 | } catch (let error) {
41 | print(error)
42 | XCTAssertTrue(false)
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Typesense swift example
2 |
3 | I have created two simple apps to demonstrate how typesense-swift works. There's a SwifUI version and a UIKit version. The SwiftUI Version is a much more elaborate application than the UIKit version but both illustrate the intended usage of the typesense-swift package.
4 |
5 | The application is a Recipe Search 🥘 app and typesense manages to search through over 2 Million records in no time ⚡️ You can checkout the web variant of typesense recipe search [here](https://recipe-search.typesense.org)
6 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/README.md:
--------------------------------------------------------------------------------
1 | # RecipeSearch (SwiftUI)
2 |
3 | This is a tiny demo-app made with SwiftUI, implementing the typesense-swift client. This demonstrates how typesense can easily breeze through around 2 Million records to find out the most relevant recipes for you and your search query.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearch.gif
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "typesense-swift",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/typesense/typesense-swift",
7 | "state" : {
8 | "revision" : "9454327b9a8c19f7e37a8f27865439add0cb5618",
9 | "version" : "0.1.2"
10 | }
11 | }
12 | ],
13 | "version" : 2
14 | }
15 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "notification40.png",
5 | "idiom" : "iphone",
6 | "scale" : "2x",
7 | "size" : "20x20"
8 | },
9 | {
10 | "filename" : "notification60.png",
11 | "idiom" : "iphone",
12 | "scale" : "3x",
13 | "size" : "20x20"
14 | },
15 | {
16 | "filename" : "settings58.png",
17 | "idiom" : "iphone",
18 | "scale" : "2x",
19 | "size" : "29x29"
20 | },
21 | {
22 | "filename" : "settings87.png",
23 | "idiom" : "iphone",
24 | "scale" : "3x",
25 | "size" : "29x29"
26 | },
27 | {
28 | "filename" : "spotlight80.png",
29 | "idiom" : "iphone",
30 | "scale" : "2x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "filename" : "spotlight120.png",
35 | "idiom" : "iphone",
36 | "scale" : "3x",
37 | "size" : "40x40"
38 | },
39 | {
40 | "filename" : "iphone120.png",
41 | "idiom" : "iphone",
42 | "scale" : "2x",
43 | "size" : "60x60"
44 | },
45 | {
46 | "filename" : "iphone180.png",
47 | "idiom" : "iphone",
48 | "scale" : "3x",
49 | "size" : "60x60"
50 | },
51 | {
52 | "filename" : "ipadNotification20.png",
53 | "idiom" : "ipad",
54 | "scale" : "1x",
55 | "size" : "20x20"
56 | },
57 | {
58 | "filename" : "ipadNotification40.png",
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "20x20"
62 | },
63 | {
64 | "filename" : "ipadSettings29.png",
65 | "idiom" : "ipad",
66 | "scale" : "1x",
67 | "size" : "29x29"
68 | },
69 | {
70 | "filename" : "ipadSettings58.png",
71 | "idiom" : "ipad",
72 | "scale" : "2x",
73 | "size" : "29x29"
74 | },
75 | {
76 | "filename" : "ipadSpotlight40.png",
77 | "idiom" : "ipad",
78 | "scale" : "1x",
79 | "size" : "40x40"
80 | },
81 | {
82 | "filename" : "ipadSpotlight80.png",
83 | "idiom" : "ipad",
84 | "scale" : "2x",
85 | "size" : "40x40"
86 | },
87 | {
88 | "filename" : "ipad76.png",
89 | "idiom" : "ipad",
90 | "scale" : "1x",
91 | "size" : "76x76"
92 | },
93 | {
94 | "filename" : "ipad152.png",
95 | "idiom" : "ipad",
96 | "scale" : "2x",
97 | "size" : "76x76"
98 | },
99 | {
100 | "filename" : "ipadPro167.png",
101 | "idiom" : "ipad",
102 | "scale" : "2x",
103 | "size" : "83.5x83.5"
104 | },
105 | {
106 | "filename" : "appstore1024.png",
107 | "idiom" : "ios-marketing",
108 | "scale" : "1x",
109 | "size" : "1024x1024"
110 | },
111 | {
112 | "filename" : "mac16.png",
113 | "idiom" : "mac",
114 | "scale" : "1x",
115 | "size" : "16x16"
116 | },
117 | {
118 | "filename" : "mac32.png",
119 | "idiom" : "mac",
120 | "scale" : "2x",
121 | "size" : "16x16"
122 | },
123 | {
124 | "filename" : "mac32.png",
125 | "idiom" : "mac",
126 | "scale" : "1x",
127 | "size" : "32x32"
128 | },
129 | {
130 | "filename" : "mac64.png",
131 | "idiom" : "mac",
132 | "scale" : "2x",
133 | "size" : "32x32"
134 | },
135 | {
136 | "filename" : "mac128.png",
137 | "idiom" : "mac",
138 | "scale" : "1x",
139 | "size" : "128x128"
140 | },
141 | {
142 | "filename" : "mac256.png",
143 | "idiom" : "mac",
144 | "scale" : "2x",
145 | "size" : "128x128"
146 | },
147 | {
148 | "filename" : "mac256.png",
149 | "idiom" : "mac",
150 | "scale" : "1x",
151 | "size" : "256x256"
152 | },
153 | {
154 | "filename" : "mac512.png",
155 | "idiom" : "mac",
156 | "scale" : "2x",
157 | "size" : "256x256"
158 | },
159 | {
160 | "filename" : "mac512.png",
161 | "idiom" : "mac",
162 | "scale" : "1x",
163 | "size" : "512x512"
164 | },
165 | {
166 | "filename" : "mac1024.png",
167 | "idiom" : "mac",
168 | "scale" : "2x",
169 | "size" : "512x512"
170 | }
171 | ],
172 | "info" : {
173 | "author" : "xcode",
174 | "version" : 1
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/appstore1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/appstore1024.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipad152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipad152.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipad76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipad76.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadNotification20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadNotification20.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadNotification40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadNotification40.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadPro167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadPro167.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadSettings29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadSettings29.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadSettings58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadSettings58.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadSpotlight40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadSpotlight40.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadSpotlight80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/ipadSpotlight80.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/iphone120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/iphone120.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/iphone180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/iphone180.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac1024.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac128.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac16.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac256.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac32.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac512.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/mac64.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/notification40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/notification40.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/notification60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/notification60.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/settings58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/settings58.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/settings87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/settings87.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/spotlight120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/spotlight120.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/spotlight80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/AppIcon.appiconset/spotlight80.png
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // RecipeSearchSwiftUI
4 | //
5 | // Created by Sabesh Bharathi on 16/01/22.
6 | //
7 |
8 | import SwiftUI
9 | import Typesense
10 |
11 | struct ContentView: View {
12 | @State private var queryString = ""
13 | @State private var hits: [SearchResultHit] = []
14 | @State private var showingSheet = false
15 | @State private var selectedRecipe: Recipe? = nil
16 | @Environment(\.colorScheme) private var colorScheme
17 |
18 | let client: Client
19 |
20 | init() {
21 | let config = Configuration(nodes: [Node(host: "qtg5aekc2iosjh93p.a1.typesense.net", port: "443", nodeProtocol: "https")], apiKey: "8hLCPSQTYcBuK29zY5q6Xhin7ONxHy99")
22 | client = Client(config: config)
23 | }
24 |
25 | var body: some View {
26 | NavigationView {
27 | ScrollView {
28 | ForEach(hits, id: \.document){ hit in
29 | HStack {
30 | Button {
31 | selectedRecipe = hit.document
32 | } label: {
33 | VStack(alignment: .leading) {
34 | Text(hit.document!.title)
35 | .font(.headline)
36 | HStack{
37 | Text("From " + getFoodProvider(link: hit.document?.link ?? "N/A"))
38 | }
39 | .font(.caption)
40 |
41 |
42 | Text(attachIngredients(recipe: hit.document))
43 | .padding(.top, 5)
44 | }
45 | .padding(.vertical, 2)
46 | }
47 | .buttonStyle(.plain)
48 | Spacer()
49 | }
50 | .padding()
51 | .background(colorScheme == .dark ? Color.gray.opacity(0.2) : Color.white)
52 | .cornerRadius(20)
53 | .padding(.horizontal, 20)
54 | .padding(.vertical, 10)
55 | .shadow(color: .black.opacity(0.2), radius: 20, x: 0, y: 10)
56 | }
57 |
58 | }
59 | .navigationTitle("Search Recipes 🥘")
60 | }
61 | .background(Color.red)
62 | .sheet(item: $selectedRecipe) { chosenItem in
63 | RecipeDetailView(recipe: chosenItem)
64 | }
65 | .searchable(text: $queryString)
66 | .onChange(of: queryString) { quer in
67 | fetchRecipes(searchQuery: quer, quer == "" ? true : false)
68 | }
69 | .onAppear {
70 | fetchRecipes(searchQuery: "", true)
71 | }
72 | }
73 |
74 | private func fetchRecipes(searchQuery: String, _ initialRecipes: Bool = false) {
75 | let collectionParams = MultiSearchCollectionParameters(q: searchQuery, collection: "r")
76 | let searchParams = MultiSearchParameters(queryBy: "title", perPage: initialRecipes ? 8 : 25)
77 | Task {
78 | do {
79 | let (data, _) = try await client.multiSearch().perform(searchRequests: [collectionParams], commonParameters: searchParams, for: Recipe.self)
80 | hits = (data?.results[0].hits) ?? []
81 | } catch (let error) {
82 | print(error.localizedDescription)
83 | }
84 | }
85 | }
86 |
87 | private func getFoodProvider(link: String) -> String {
88 | let first = link.split(separator: ".")[0]
89 | if first.contains("www") {
90 | let second = link.split(separator: ".")[1]
91 | return String(second + ".com")
92 | }
93 | return String(first + ".com")
94 | }
95 |
96 | private func attachIngredients(recipe: Recipe?) -> String {
97 |
98 | guard let recipe = recipe else {
99 | return ""
100 | }
101 |
102 | var displayString = ""
103 | let list = recipe.ingredient_names
104 | for index in 0.. 5 {
113 | displayString.append(contentsOf: " and more!")
114 | }
115 |
116 | return displayString
117 | }
118 | }
119 |
120 | struct ContentView_Previews: PreviewProvider {
121 | static var previews: some View {
122 | ContentView()
123 | .previewDevice("iPhone 13 Pro")
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/Recipe.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Recipe.swift
3 | // RecipeSearchSwiftUI
4 | //
5 | // Created by Sabesh Bharathi on 16/01/22.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct Recipe: Codable, Hashable, Identifiable {
11 | var directions: [String]
12 | public var id: String
13 | var ingredient_names: [String]
14 | var ingredients_with_measurements: [String]
15 | var link: String
16 | var recipe_id: Int
17 | var title: String
18 | }
19 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/RecipeDetailView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecipeDetailView.swift
3 | // RecipeSearchSwiftUI
4 | //
5 | // Created by Sabesh Bharathi on 08/05/22.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct RecipeDetailView: View {
11 | @Environment(\.dismiss) var dismiss
12 |
13 | var recipe: Recipe?
14 | var body: some View {
15 | if let recipe = recipe {
16 | List {
17 |
18 | HStack {
19 | Text(recipe.title)
20 | .font(.title)
21 | .bold()
22 | Spacer()
23 | Text("🍴")
24 | .font(.system(size: 60))
25 | }
26 |
27 | .padding(10)
28 |
29 | Section(header: Text("Ingredients")) {
30 | ForEach(recipe.ingredients_with_measurements, id: \.self) { ingredient in
31 | Text(ingredient)
32 | }
33 | }
34 |
35 | Section(header: Text("Cooking Directions")) {
36 | ForEach(recipe.directions, id: \.self) { direction in
37 | Text("\(recipe.directions.firstIndex(of: direction)! + 1). " + direction)
38 | }
39 | }
40 |
41 | HStack {
42 | Spacer()
43 | Button {
44 | if let url = URL(string: recipe.link) {
45 | if UIApplication.shared.canOpenURL(url) {
46 | UIApplication.shared.open(url, options: [:])
47 | }
48 | }
49 | } label: {
50 | Text("Explore")
51 | }
52 | Spacer()
53 | }
54 |
55 | }
56 | }
57 | }
58 | }
59 |
60 | struct RecipeDetailView_Previews: PreviewProvider {
61 | static var previews: some View {
62 | RecipeDetailView()
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/example/SwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUI/RecipeSearchSwiftUIApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecipeSearchSwiftUIApp.swift
3 | // RecipeSearchSwiftUI
4 | //
5 | // Created by Sabesh Bharathi on 16/01/22.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct RecipeSearchSwiftUIApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/README.md:
--------------------------------------------------------------------------------
1 | # RecipeSearch (UIKit)
2 |
3 | This is a tiny demo-app made with UIKit, implementing the typesense-swift client. This demonstrates how typesense can easily breeze through around 2 Million records to find out the most relevant recipes for you and your search query.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typesense/typesense-swift/8057f2ca81471be207ca1d4e6e46ad0336faffe0/example/UIKit/RecipeSearchUIKit/RecipeSearch.gif
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "typesense-swift",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/typesense/typesense-swift",
7 | "state" : {
8 | "revision" : "9454327b9a8c19f7e37a8f27865439add0cb5618",
9 | "version" : "0.1.2"
10 | }
11 | }
12 | ],
13 | "version" : 2
14 | }
15 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // RecipeSearchUIKit
4 | //
5 | // Created by Sabesh Bharathi on 04/01/22.
6 | //
7 |
8 | import UIKit
9 |
10 | @main
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/Recipe.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Recipe.swift
3 | // RecipeSearchUIKit
4 | //
5 | // Created by Sabesh Bharathi on 04/01/22.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct Recipe: Codable, Hashable, Identifiable {
11 | var directions: [String]
12 | public var id: String
13 | var ingredient_names: [String]
14 | var ingredients_with_measurements: [String]
15 | var link: String
16 | var recipe_id: Int
17 | var title: String
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // RecipeSearchUIKit
4 | //
5 | // Created by Sabesh Bharathi on 04/01/22.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/example/UIKit/RecipeSearchUIKit/RecipeSearchUIKit/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // RecipeSearchUIKit
4 | //
5 | // Created by Sabesh Bharathi on 04/01/22.
6 | //
7 |
8 | import UIKit
9 | import Typesense
10 |
11 | class ViewController: UIViewController, UISearchResultsUpdating {
12 |
13 | @IBOutlet weak var hitsTableView: UITableView!
14 |
15 | var hits:[SearchResultHit]
16 |
17 | class HitsViewController: UIViewController {
18 | override func viewDidLoad() {
19 | super.viewDidLoad()
20 | }
21 | }
22 |
23 | let searchController = UISearchController(searchResultsController: HitsViewController())
24 | let client: Client
25 |
26 | required init?(coder aDecoder: NSCoder) {
27 | let config = Configuration(nodes: [Node(host: "qtg5aekc2iosjh93p.a1.typesense.net", port: "443", nodeProtocol: "https")], apiKey: "8hLCPSQTYcBuK29zY5q6Xhin7ONxHy99")
28 | self.client = Client(config: config)
29 | self.hits = []
30 | super.init(coder: aDecoder)
31 | }
32 |
33 | override func viewDidLoad() {
34 | super.viewDidLoad()
35 | title = "Search Recipes 🥘"
36 | searchController.searchResultsUpdater = self
37 | navigationItem.searchController = searchController
38 | hitsTableView.delegate = self
39 | hitsTableView.dataSource = self
40 | updateSearchResults(for: UISearchController())
41 | }
42 |
43 | func updateSearchResults(for searchController: UISearchController) {
44 | guard let text = searchController.searchBar.text else {
45 | return
46 | }
47 |
48 | let collectionParams = MultiSearchCollectionParameters(q: text, collection: "r")
49 | let searchParams = MultiSearchParameters(queryBy: "title", perPage: 25)
50 |
51 | Task {
52 | do {
53 | let (data, _) = try await client.multiSearch().perform(searchRequests: [collectionParams], commonParameters: searchParams, for: Recipe.self)
54 | self.hits = (data?.results[0].hits) ?? []
55 | self.hitsTableView.reloadData()
56 | } catch (let error) {
57 | print(error.localizedDescription)
58 | }
59 | }
60 |
61 | }
62 | }
63 |
64 | extension ViewController: UITableViewDelegate, UITableViewDataSource {
65 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
66 | return hits.count
67 | }
68 |
69 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
70 | let recipe = hits[indexPath.row].document
71 | var cell = hitsTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
72 | if #available(iOS 14.0, *) {
73 | var content = cell.defaultContentConfiguration()
74 | content.text = recipe?.title
75 | cell.contentConfiguration = content
76 | } else {
77 | cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle,
78 | reuseIdentifier: "cell")
79 | cell.textLabel?.text = recipe?.title
80 | }
81 |
82 | return cell
83 | }
84 | }
85 |
86 |
87 |
--------------------------------------------------------------------------------
/get-models.sh:
--------------------------------------------------------------------------------
1 | curl https://raw.githubusercontent.com/typesense/typesense-api-spec/master/openapi.yml > openapi.yml
2 | swagger-codegen generate -i openapi.yml -l swift5 -o output
3 | rm -rf Models
4 | cd output/SwaggerClient/Classes/Swaggers
5 | mv ./Models ../../../../
6 | cd ../../../../
7 | rm -rf output
8 |
9 | cd Models
10 |
11 | # Delete useless structs generated as a mistake by the code-gen
12 | rm OneOfSearchParametersMaxHits.swift
13 | rm OneOfMultisearchParametersMaxHits.swift
14 |
15 | # Fix the maxHits type by defining it as a String Optional
16 | find . -name "SearchParameters.swift" -exec sed -i '' 's/maxHits: OneOfSearchParametersMaxHits\?/maxHits: String\?/g' {} \;
17 | find . -name "MultiSearchParameters.swift" -exec sed -i '' 's/maxHits: OneOfMultiSearchParametersMaxHits\?/maxHits: String\?/g' {} \;
18 | find . -name "MultiSearchCollectionParameters.swift" -exec sed -i '' 's/maxHits: Any\?/maxHits: String\?/g' {} \;
19 |
20 | # Add Generics to SearchResult
21 | find . -name "SearchResult.swift" -exec sed -i '' 's/SearchResult:/SearchResult:/g' {} \;
22 | find . -name "SearchResult.swift" -exec sed -i '' 's/groupedHits: \[SearchGroupedHit\]\?/groupedHits: \[SearchGroupedHit\]\?/g' {} \;
23 | find . -name "SearchResult.swift" -exec sed -i '' 's/hits: \[SearchResultHit\]\?/hits: \[SearchResultHit\]\?/g' {} \;
24 |
25 | # Add Generics to MultiSearchResult
26 | find . -name "MultiSearchResult.swift" -exec sed -i '' 's/results: \[SearchResult\]/results: \[SearchResult\]/g' {} \;
27 | find . -name "MultiSearchResult.swift" -exec sed -i '' 's/MultiSearchResult:/MultiSearchResult:/g' {} \;
28 |
29 | # Add Generics to SearchResultHit
30 | find . -name "SearchResultHit.swift" -exec sed -i '' 's/SearchResultHit:/SearchResultHit:/g' {} \;
31 |
32 | # Convert document parameter to a generic T
33 | find . -name "SearchResultHit.swift" -exec sed -i '' 's/document: \[String:Any\]\?/document: T?/g' {} \;
34 |
35 | # Add Generics to SearchGroupedHit
36 | find . -name "SearchGroupedHit.swift" -exec sed -i '' 's/SearchGroupedHit:/SearchGroupedHit:/g' {} \;
37 | find . -name "SearchGroupedHit.swift" -exec sed -i '' 's/hits: \[SearchResultHit\]/hits: \[SearchResultHit\]/g' {} \;
38 |
39 | # Convert matchedTokens to custom defined StringQuantum
40 | find . -name "SearchHighlight.swift" -exec sed -i '' 's/matchedTokens: \[Any\]\?/matchedTokens: StringQuantum\?/g' {} \;
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------