diff --git a/cozo-lib-c/cozo_c.h b/cozo-lib-c/cozo_c.h index 985adf13..0827bfaa 100644 --- a/cozo-lib-c/cozo_c.h +++ b/cozo-lib-c/cozo_c.h @@ -1,4 +1,10 @@ -/* Copyright 2022, The Cozo Project Authors. Licensed under MIT/Apache-2.0/BSD-3-Clause. */ +/* + Copyright 2022, The Cozo Project Authors. + + This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. + If a copy of the MPL was not distributed with this file, + You can obtain one at https://mozilla.org/MPL/2.0/. +*/ #ifndef COZO_C_H #define COZO_C_H diff --git a/cozo-lib-nodejs/README.md b/cozo-lib-nodejs/README.md index b650046b..233d5543 100644 --- a/cozo-lib-nodejs/README.md +++ b/cozo-lib-nodejs/README.md @@ -72,9 +72,8 @@ class CozoDb { * Export several relations * * @param relations: names of relations to export, in an array. - * @param as_objects: defaults to `false`, changes the return format. */ - async exportRelations(relations: Array, as_objects: boolean): object; + async exportRelations(relations: Array): object; /** * Import several relations diff --git a/cozo-lib-swift/CozoDB.swift b/cozo-lib-swift/CozoDB.swift new file mode 100644 index 00000000..3113fab9 --- /dev/null +++ b/cozo-lib-swift/CozoDB.swift @@ -0,0 +1,165 @@ +/* + * Copyright 2022, The Cozo Project Authors. + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import Foundation +import SwiftyJSON + +public enum CozoError: Error { + case system(String) + case query(JSON) +} + +public class RowHeaders { + public let headers: [String] + init(headers: [String]) { + self.headers = headers + } + lazy var invertedKeys: [String:Int] = { + var ret: [String:Int] = [:] + for i in 0.. JSON { + return self.fields[idx] + } + public func get(key: String) -> JSON? { + if let idx = self.headers.invertedKeys[key] { + return self.fields[idx] + } else { + return nil + } + } +} + +extension [NamedRow] { + public func toString() -> String { + var ret = "[" + var isFirst = true + for field in self { + if !isFirst { + ret += ", " + } else { + isFirst = false + } + ret += field.toString() + } + ret += "]" + return ret + } +} + +extension NamedRow { + public func toString() -> String { + var ret = "{" + for i in 0.. [NamedRow] { + let payload = params.rawString(.utf8, options: .init(rawValue: 0))! + return try self.run(query, stringParams: payload) + } + public func run(_ query: String) throws -> [NamedRow] { + return try self.run(query, stringParams: "") + } + func run(_ query: String, stringParams: String) throws -> [NamedRow] { + let resStr = self.db.run_script_str(query, stringParams).toString() + let dataFromString = resStr.data(using: .utf8, allowLossyConversion: false)! + let json = JSON(dataFromString); + if json["ok"].boolValue { + let jHeaders = json["headers"].arrayValue.map{(j) -> String in + return j.stringValue + } + let headers = RowHeaders(headers: jHeaders) + return json["rows"].arrayValue.map{(j) -> NamedRow in + let fields = j.arrayValue + return NamedRow(headers: headers, fields: fields) + } + } else { + throw CozoError.query(json) + } + } + public func exportRelations(relations: [String]) throws -> JSON { + let payload = JSON(["relations": relations]).rawString(.utf8, options: .init(rawValue: 0))! + let resStr = self.db.export_relations_str(payload).toString() + let dataFromString = resStr.data(using: .utf8, allowLossyConversion: false)! + let json = JSON(dataFromString); + if json["ok"].boolValue { + return json["data"] + } else { + throw CozoError.query(json) + } + } + public func importRelations(data: JSON) throws { + let payload = data.rawString(.utf8, options: .init(rawValue: 0))! + let resStr = self.db.import_relations_str(payload).toString() + let dataFromString = resStr.data(using: .utf8, allowLossyConversion: false)! + let json = JSON(dataFromString); + if !json["ok"].boolValue { + throw CozoError.query(json) + } + } + public func backup(path: String) throws { + let resStr = self.db.backup_db_str(path).toString() + let dataFromString = resStr.data(using: .utf8, allowLossyConversion: false)! + let json = JSON(dataFromString); + + if !json["ok"].boolValue { + throw CozoError.query(json) + } + } + public func restore(path: String) throws { + let resStr = self.db.restore_backup_str(path).toString() + let dataFromString = resStr.data(using: .utf8, allowLossyConversion: false)! + let json = JSON(dataFromString); + + if !json["ok"].boolValue { + throw CozoError.query(json) + } + } + public func importRelationsFromBackup(path: String, relations: [String]) throws { + let payload = JSON(["relations": relations, "path": path]).rawString(.utf8, options: .init(rawValue: 0))! + let resStr = self.db.import_relations_str(payload).toString() + let dataFromString = resStr.data(using: .utf8, allowLossyConversion: false)! + let json = JSON(dataFromString); + if !json["ok"].boolValue { + throw CozoError.query(json) + } + } +} diff --git a/cozo-lib-swift/CozoSwiftBridge.podspec b/cozo-lib-swift/CozoSwiftBridge.podspec new file mode 100644 index 00000000..c8ad4b30 --- /dev/null +++ b/cozo-lib-swift/CozoSwiftBridge.podspec @@ -0,0 +1,17 @@ +Pod::Spec.new do |spec| + spec.name = "CozoSwiftBridge" + spec.version = "0.2.1" + spec.summary = "CozoDB for Swift" + spec.description = "This library allows you to use CozoDB embedded in your Swift application" + spec.homepage = "https://github.com/cozodb/cozo/" + spec.license = "MPL-2.0" + spec.author = { "Ziyang Hu" => "hu.ziyang@cantab.net" } + spec.source = { :http => "http://127.0.0.1:3000/CozoSwiftBridge.tgz" } + spec.source_files = "Sources/CozoSwiftBridge/*" + spec.vendored_frameworks = "RustXcframework.xcframework" + spec.requires_arc = true + spec.swift_version = "5.0" + spec.osx.deployment_target = "10.9" + spec.ios.deployment_target = "9.0" + spec.dependency "SwiftyJSON", "~> 4.0" +end diff --git a/cozo-lib-swift/Package.swift b/cozo-lib-swift/Package.swift new file mode 100644 index 00000000..3f35d7e1 --- /dev/null +++ b/cozo-lib-swift/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version:5.5.0 +import PackageDescription +let package = Package( + name: "CozoSwiftBridge", + products: [ + .library( + name: "CozoSwiftBridge", + targets: ["CozoSwiftBridge"]), + ], + dependencies: [ + .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"), + ], + targets: [ + .binaryTarget( + name: "RustXcframework", + path: "RustXcframework.xcframework" + ), + .target( + name: "CozoSwiftBridge", + dependencies: ["RustXcframework", "SwiftyJSON"]) + ] +) + \ No newline at end of file diff --git a/cozo-lib-swift/README.md b/cozo-lib-swift/README.md index 2e6a8fa4..bbeae38e 100644 --- a/cozo-lib-swift/README.md +++ b/cozo-lib-swift/README.md @@ -14,6 +14,18 @@ see the Building section below. ## Installation +### CocoaPods + +```ruby +target 'YourApp' do + use_frameworks! + + pod 'CozoSwiftBridge', '~> 0.2.1' +end +``` + +### Swift Package Manager (SPM) + The package is published as an archive containing a Swift package. Download it from the [release page] (look for `CozoSwiftBridge-.tgz`). Uncompress. @@ -131,14 +143,3 @@ click the plus sign, search for `libc++`, then add `libc++.tbd` found under Appl Similar same process goes if you want to enable other features. Note that building the RocksDB engine for mobile is a very demanding task! - -## Calling for help - -We are no experts on Swift/iOS development. In fact, we learned Swift just enough to produce -this package. Everything from packaging, distribution to the ergonomics of the Swift API is -far from ideal, but is as good as we can produce now. If you like Cozo and you can improve -its user experience on Swift, feel free to open an issue for discussion, or file a pull request. - -By the way, the reason that we did not publish the Swift package directly to a GitHub repo is -that the package contains very large binary artefacts, and GitHub will not like it if we put it -directly in the repo. \ No newline at end of file diff --git a/cozo-lib-swift/build-rust.sh b/cozo-lib-swift/build-rust.sh index 91894c33..64775f08 100755 --- a/cozo-lib-swift/build-rust.sh +++ b/cozo-lib-swift/build-rust.sh @@ -32,4 +32,16 @@ swift-bridge-cli create-package \ --ios ../target/aarch64-apple-ios/release/libcozo_swift.a \ --simulator ../target/universal-ios/release/libcozo_swift.a \ --macos ../target/universal-macos/release/libcozo_swift.a \ - --name CozoSwiftBridge \ No newline at end of file + --name CozoSwiftBridge + +cp CozoDB.swift CozoSwiftBridge/Sources/CozoSwiftBridge +cp Package.swift CozoSwiftBridge/ +cp CozoSwiftBridge.podspec CozoSwiftBridge/ + +VERSION=$(cat ../VERSION) + +cd CozoSwiftBridge + +tar cvzf ../../release/CozoSwiftBridge-$VERSION.tgz . + +cd .. \ No newline at end of file diff --git a/scripts/compress.sh b/scripts/compress.sh index 12a27647..6cc9a4c0 100755 --- a/scripts/compress.sh +++ b/scripts/compress.sh @@ -14,10 +14,6 @@ done cd .. -cd cozo-lib-swift -tar cvzf ../release/CozoSwiftBridge-$VERSION.tgz CozoSwiftBridge -cd .. - gzip release/*.a release/*.so release/*.dylib release/*-darwin release/*-gnu release/*-musl mkdir -p cozo-lib-nodejs/build/stage/$VERSION/