mirror of
https://github.com/trailbaseio/trailbase.git
synced 2026-01-05 17:30:13 -06:00
Add documentation for new Swift client.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "trailbase",
|
||||
name: "TrailBase",
|
||||
platforms: [
|
||||
.iOS(.v13),
|
||||
.macCatalyst(.v13),
|
||||
@@ -14,15 +14,15 @@ let package = Package(
|
||||
],
|
||||
products: [
|
||||
.library(
|
||||
name: "trailbase",
|
||||
targets: ["trailbase"]),
|
||||
name: "TrailBase",
|
||||
targets: ["TrailBase"]),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "trailbase"),
|
||||
name: "TrailBase"),
|
||||
.testTarget(
|
||||
name: "trailbaseTests",
|
||||
dependencies: ["trailbase"]
|
||||
name: "TrailBaseTests",
|
||||
dependencies: ["TrailBase"]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -8,16 +8,22 @@ public struct User: Hashable, Equatable {
|
||||
}
|
||||
|
||||
// NOTE: Making this explicitly public breaks compiler.
|
||||
struct Tokens: Codable, Hashable {
|
||||
public struct Tokens: Codable, Hashable, Equatable, Sendable {
|
||||
let auth_token: String
|
||||
let refresh_token: String?
|
||||
let csrf_token: String?
|
||||
}
|
||||
|
||||
public struct Pagination {
|
||||
var cursor: String? = nil
|
||||
var limit: UInt? = nil
|
||||
var offset: UInt? = nil
|
||||
public var cursor: String? = nil
|
||||
public var limit: UInt? = nil
|
||||
public var offset: UInt? = nil
|
||||
|
||||
public init(cursor: String? = nil, limit: UInt? = nil, offset: UInt? = nil) {
|
||||
self.cursor = cursor
|
||||
self.limit = limit
|
||||
self.offset = offset
|
||||
}
|
||||
}
|
||||
|
||||
private struct JwtTokenClaims: Decodable, Hashable {
|
||||
@@ -70,7 +76,7 @@ public struct ListResponse<T: Decodable>: Decodable {
|
||||
let records: [T]
|
||||
}
|
||||
|
||||
class RecordApi {
|
||||
public class RecordApi {
|
||||
let client: Client
|
||||
let name: String
|
||||
|
||||
@@ -231,12 +237,12 @@ private class ThinClient {
|
||||
}
|
||||
}
|
||||
|
||||
class Client {
|
||||
public class Client {
|
||||
private let base: URL
|
||||
private let client: ThinClient
|
||||
private let tokenState: Mutex<TokenState>
|
||||
|
||||
public init(site: URL, tokens: Tokens?) throws {
|
||||
public init(site: URL, tokens: Tokens? = nil) throws {
|
||||
self.base = site
|
||||
self.client = ThinClient(base: site)
|
||||
self.tokenState = Mutex(try TokenState(tokens: tokens))
|
||||
@@ -264,8 +270,8 @@ class Client {
|
||||
})
|
||||
}
|
||||
|
||||
public func records(apiName: String) -> RecordApi {
|
||||
return RecordApi(client: self, name: apiName)
|
||||
public func records(_ name: String) -> RecordApi {
|
||||
return RecordApi(client: self, name: name)
|
||||
}
|
||||
|
||||
public func refresh() async throws {
|
||||
@@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import trailbase
|
||||
@testable import TrailBase
|
||||
|
||||
struct SimpleStrict: Codable, Equatable {
|
||||
var id: String? = nil
|
||||
@@ -33,7 +33,7 @@ func connect() async throws -> Client {
|
||||
|
||||
@Test func recordTest() async throws {
|
||||
let client = try await connect()
|
||||
let api = client.records(apiName: "simple_strict_table")
|
||||
let api = client.records("simple_strict_table")
|
||||
|
||||
let now = NSDate().timeIntervalSince1970
|
||||
|
||||
8
docs/examples/record_api_swift/.gitignore
vendored
Normal file
8
docs/examples/record_api_swift/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/configuration/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
||||
28
docs/examples/record_api_swift/Package.swift
Normal file
28
docs/examples/record_api_swift/Package.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
// swift-tools-version: 6.1
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "RecordApiDocs",
|
||||
products: [
|
||||
.library(
|
||||
name: "RecordApiDocs",
|
||||
targets: ["RecordApiDocs"])
|
||||
],
|
||||
dependencies: [
|
||||
.package(path: "../../../client/trailbase-swift")
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "RecordApiDocs",
|
||||
dependencies: [
|
||||
.product(name: "TrailBase", package: "trailbase-swift")
|
||||
]
|
||||
),
|
||||
.testTarget(
|
||||
name: "RecordApiDocsTests",
|
||||
dependencies: ["RecordApiDocs"]
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
import TrailBase
|
||||
|
||||
func create(client: Client) async throws -> RecordId {
|
||||
try await client.records("simple_strict_table").create(
|
||||
record: ["text_not_null": "test"])
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import TrailBase
|
||||
|
||||
func delete(client: Client, id: RecordId) async throws {
|
||||
try await client.records("simple_strict_table").delete(recordId: id)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import Foundation
|
||||
import TrailBase
|
||||
|
||||
func list(client: Client) async throws -> ListResponse<SimpleStrict> {
|
||||
try await client
|
||||
.records("movies")
|
||||
.list(
|
||||
pagination: Pagination(limit: 3),
|
||||
order: ["rank"],
|
||||
filters: ["watch_time[lt]=120", "description[like]=%love%"]
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import TrailBase
|
||||
|
||||
func read(client: Client, id: RecordId) async throws -> SimpleStrict {
|
||||
try await client.records("simple_strict_table").read(recordId: id)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
struct SimpleStrict: Codable, Equatable {
|
||||
var id: String? = nil
|
||||
|
||||
var text_null: String? = nil
|
||||
var text_default: String? = nil
|
||||
let text_not_null: String
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import TrailBase
|
||||
|
||||
func update(client: Client, id: RecordId) async throws {
|
||||
try await client.records("simple_strict_table").update(
|
||||
recordId: id, record: ["text_not_null": "updated"])
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
import TrailBase
|
||||
|
||||
@testable import RecordApiDocs
|
||||
|
||||
@Test func testDocs() async throws {
|
||||
let client = try Client(site: URL(string: "http://localhost:4000")!)
|
||||
let _ = try await client.login(email: "admin@localhost", password: "secret")
|
||||
|
||||
let _ = try await list(client: client)
|
||||
|
||||
let id = try await create(client: client)
|
||||
try await update(client: client, id: id)
|
||||
let record = try await read(client: client, id: id)
|
||||
|
||||
assert(record.text_not_null == "updated")
|
||||
|
||||
try await delete(client: client, id: id)
|
||||
}
|
||||
22
docs/src/assets/swift_logo.svg
Normal file
22
docs/src/assets/swift_logo.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="106.1px" height="106.1px" viewBox="-252 343.9 106.1 106.1" enable-background="new -252 343.9 106.1 106.1"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#F05138" d="M-145.9,373.3c0-1.1,0-2.1,0-3.2c-0.1-2.3-0.2-4.7-0.6-7c-0.4-2.3-1.1-4.5-2.2-6.6c-1.1-2.1-2.4-4-4.1-5.6
|
||||
c-1.7-1.7-3.6-3-5.6-4.1c-2.1-1.1-4.3-1.8-6.6-2.2c-2.3-0.4-4.6-0.6-7-0.6c-1.1,0-2.1,0-3.2,0c-1.3,0-2.5,0-3.8,0h-28.1h-11.6
|
||||
c-1.3,0-2.5,0-3.8,0c-1.1,0-2.1,0-3.2,0c-0.6,0-1.2,0-1.7,0.1c-1.7,0.1-3.5,0.2-5.2,0.5c-1.7,0.3-3.4,0.8-5,1.4
|
||||
c-0.5,0.2-1.1,0.5-1.6,0.7c-1.6,0.8-3,1.8-4.4,2.9c-0.4,0.4-0.9,0.8-1.3,1.2c-1.7,1.7-3,3.6-4.1,5.6c-1.1,2.1-1.8,4.3-2.2,6.6
|
||||
c-0.4,2.3-0.5,4.6-0.6,7c0,1.1,0,2.1,0,3.2c0,1.3,0,2.5,0,3.8v17.3v22.4c0,1.3,0,2.5,0,3.8c0,1.1,0,2.1,0,3.2
|
||||
c0.1,2.3,0.2,4.7,0.6,7c0.4,2.3,1.1,4.5,2.2,6.6c1.1,2.1,2.4,4,4.1,5.6c1.7,1.7,3.6,3,5.6,4.1c2.1,1.1,4.3,1.8,6.6,2.2
|
||||
c2.3,0.4,4.6,0.6,7,0.6c1.1,0,2.1,0,3.2,0c1.3,0,2.5,0,3.8,0h39.7c1.3,0,2.5,0,3.8,0c1.1,0,2.1,0,3.2,0c2.3-0.1,4.7-0.2,7-0.6
|
||||
c2.3-0.4,4.5-1.1,6.6-2.2c2.1-1.1,4-2.4,5.6-4.1c1.7-1.7,3-3.6,4.1-5.6c1.1-2.1,1.8-4.3,2.2-6.6c0.4-2.3,0.6-4.6,0.6-7
|
||||
c0-1.1,0-2.1,0-3.2c0-1.3,0-2.5,0-3.8v-39.7C-145.9,375.8-145.9,374.6-145.9,373.3z"/>
|
||||
<path fill="#FFFFFF" d="M-168,409.4c0.1-0.4,0.2-0.8,0.3-1.2c4.4-17.5-6.3-38.3-24.5-49.2c8,10.8,11.5,23.9,8.4,35.3
|
||||
c-0.3,1-0.6,2-1,3c-0.4-0.3-0.9-0.6-1.6-0.9c0,0-18.1-11.2-37.7-30.9c-0.5-0.5,10.5,15.7,22.9,28.8c-5.9-3.3-22.2-15.2-32.6-24.6
|
||||
c1.3,2.1,2.8,4.2,4.4,6.1c8.6,11,19.9,24.5,33.4,34.9c-9.5,5.8-22.9,6.3-36.2,0c-3.3-1.5-6.4-3.4-9.3-5.5
|
||||
c5.6,9,14.3,16.8,24.9,21.4c12.6,5.4,25.2,5.1,34.5,0.1l0,0c0,0,0.1,0,0.1-0.1c0.4-0.2,0.8-0.5,1.2-0.7c4.5-2.3,13.3-4.6,18.1,4.6
|
||||
C-161.3,432.6-158.8,420.6-168,409.4C-168,409.4-168,409.4-168,409.4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -151,6 +151,7 @@ existing ones depending on conflict resolution strategy.
|
||||
|
||||
import createDartCode from "@examples/record_api_dart/lib/src/create.dart?raw";
|
||||
import createTsCode from "@examples/record_api_ts/src/create.ts?raw";
|
||||
import createSwiftCode from "@examples/record_api_swift/Sources/RecordApiDocs/Create.swift?raw";
|
||||
import createDotnetCode from "@examples/record_api_dotnet/Create.cs?raw";
|
||||
import createRustCode from "@examples/record_api_rs/src/create.rs?raw";
|
||||
import createCurlCode from "@examples/record_api_curl/create.sh?raw";
|
||||
@@ -164,6 +165,10 @@ import createCurlCode from "@examples/record_api_curl/create.sh?raw";
|
||||
<Code lang="dart" code={createDartCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Swift">
|
||||
<Code lang="swift" code={createSwiftCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="C#/.NET">
|
||||
<Code lang="cs" code={createDotnetCode} />
|
||||
</TabItem>
|
||||
@@ -184,6 +189,7 @@ The read endpoint lets you read specific records given their id.
|
||||
|
||||
import readDartCode from "@examples/record_api_dart/lib/src/read.dart?raw";
|
||||
import readTsCode from "@examples/record_api_ts/src/read.ts?raw";
|
||||
import readSwiftCode from "@examples/record_api_swift/Sources/RecordApiDocs/Read.swift?raw";
|
||||
import readDotnetCode from "@examples/record_api_dotnet/Read.cs?raw";
|
||||
import readRustCode from "@examples/record_api_rs/src/read.rs?raw";
|
||||
import readCurlCode from "@examples/record_api_curl/read.sh?raw";
|
||||
@@ -197,6 +203,10 @@ import readCurlCode from "@examples/record_api_curl/read.sh?raw";
|
||||
<Code lang="dart" code={readDartCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Swift">
|
||||
<Code lang="swift" code={readSwiftCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="C#/.NET">
|
||||
<Code lang="cs" code={readDotnetCode} />
|
||||
</TabItem>
|
||||
@@ -216,6 +226,7 @@ The update endpoint lets you modify, i.e. partially update, existing records giv
|
||||
|
||||
import updateDartCode from "@examples/record_api_dart/lib/src/update.dart?raw";
|
||||
import updateTsCode from "@examples/record_api_ts/src/update.ts?raw";
|
||||
import updateSwiftCode from "@examples/record_api_swift/Sources/RecordApiDocs/Update.swift?raw";
|
||||
import updateDotnetCode from "@examples/record_api_dotnet/Update.cs?raw";
|
||||
import updateRustCode from "@examples/record_api_rs/src/update.rs?raw";
|
||||
import updateCurlCode from "@examples/record_api_curl/update.sh?raw";
|
||||
@@ -229,6 +240,10 @@ import updateCurlCode from "@examples/record_api_curl/update.sh?raw";
|
||||
<Code lang="dart" code={updateDartCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Swift">
|
||||
<Code lang="swift" code={updateSwiftCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="C#/.NET">
|
||||
<Code lang="cs" code={updateDotnetCode} />
|
||||
</TabItem>
|
||||
@@ -246,6 +261,7 @@ import updateCurlCode from "@examples/record_api_curl/update.sh?raw";
|
||||
|
||||
import deleteDartCode from "@examples/record_api_dart/lib/src/delete.dart?raw";
|
||||
import deleteTsCode from "@examples/record_api_ts/src/delete.ts?raw";
|
||||
import deleteSwiftCode from "@examples/record_api_swift/Sources/RecordApiDocs/Delete.swift?raw";
|
||||
import deleteDotnetCode from "@examples/record_api_dotnet/Delete.cs?raw";
|
||||
import deleteRustCode from "@examples/record_api_rs/src/delete.rs?raw";
|
||||
import deleteCurlCode from "@examples/record_api_curl/delete.sh?raw";
|
||||
@@ -259,6 +275,10 @@ import deleteCurlCode from "@examples/record_api_curl/delete.sh?raw";
|
||||
<Code lang="dart" code={deleteDartCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Swift">
|
||||
<Code lang="swift" code={deleteSwiftCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="C#/.NET">
|
||||
<Code lang="cs" code={deleteDotnetCode} />
|
||||
</TabItem>
|
||||
@@ -315,6 +335,7 @@ and "love" in their description:
|
||||
|
||||
import listDartCode from "@examples/record_api_dart/lib/src/list.dart?raw";
|
||||
import listTsCode from "@examples/record_api_ts/src/list.ts?raw";
|
||||
import listSwiftCode from "@examples/record_api_swift/Sources/RecordApiDocs/List.swift?raw";
|
||||
import listRustCode from "@examples/record_api_rs/src/list.rs?raw";
|
||||
import listDotnetCode from "@examples/record_api_dotnet/List.cs?raw";
|
||||
import listCurlCode from "@examples/record_api_curl/list.sh?raw";
|
||||
@@ -328,6 +349,10 @@ import listCurlCode from "@examples/record_api_curl/list.sh?raw";
|
||||
<Code lang="dart" code={listDartCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Swift">
|
||||
<Code lang="swift" code={listSwiftCode} />
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="C#/.NET">
|
||||
<Code lang="cs" code={listDotnetCode} />
|
||||
</TabItem>
|
||||
|
||||
@@ -48,8 +48,9 @@ import shelve from "@/assets/shelve.webp";
|
||||
import dotnetLogo from "@/assets/dotnet_logo.svg";
|
||||
import flutterLogo from "@/assets/flutter_logo.svg";
|
||||
import pythonLogo from "@/assets/python_logo.svg";
|
||||
import tsLogo from "@/assets/ts_logo.svg";
|
||||
import rustLogo from "@/assets/rust_unofficial_logo.svg";
|
||||
import swiftLogo from "@/assets/swift_logo.svg";
|
||||
import tsLogo from "@/assets/ts_logo.svg";
|
||||
|
||||
import { Duration100kInsertsChart } from "./reference/_benchmarks/benchmarks.tsx";
|
||||
|
||||
@@ -155,7 +156,7 @@ import { Duration100kInsertsChart } from "./reference/_benchmarks/benchmarks.tsx
|
||||
Clients as well as code-generation examples for TypeScript,
|
||||
Dart/Flutter, Python, C#/.NET and Rust are provided out of the box.
|
||||
|
||||
<div class="m-0 flex justify-center items-start gap-8">
|
||||
<div class="pt-4 m-0 flex justify-center items-start gap-8">
|
||||
<a href="https://www.npmjs.com/package/trailbase">
|
||||
<Image class="p-0 m-0" height={52} src={tsLogo} alt="TypeScript" />
|
||||
</a>
|
||||
@@ -164,6 +165,10 @@ import { Duration100kInsertsChart } from "./reference/_benchmarks/benchmarks.tsx
|
||||
<Image margin={0} class="p-0 m-0" width={42} height={52} src={flutterLogo} alt="Flutter" />
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/trailbaseio/trailbase/tree/main/client/trailbase-swift">
|
||||
<Image margin={0} class="p-0 m-0" width={52} height={52} src={swiftLogo} alt="Swift" />
|
||||
</a>
|
||||
|
||||
<a href="https://pypi.org/project/trailbase/">
|
||||
<Image margin={0} class="p-0 m-0" width={52} height={52} src={pythonLogo} alt="Dotnet" />
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user