fauna / faunadb-swift Goto Github PK
View Code? Open in Web Editor NEWSwift driver for FaunaDB
Home Page: https://fauna.com
License: Other
Swift driver for FaunaDB
Home Page: https://fauna.com
License: Other
I'm opening this issue so we can discuss how the internal types are being converted to Expr
.
Right now there are places where we need to write code like this:
Create(ref: Ref.indexes, params: [
"name": "spells_by_element",
"source": Ref("classes/spells"),
"terms": [["path": "data.element"] as Obj] as Arr,
"active": true
])
[["path": "data.element"] as
Obj
] asArr
I think as Obj
and as Arr
requires previous knowledge about the internal Expr
class hierarch and exposes that fact that we have internal representations of our own. Therefore, it loses the meaning of having literal conversions.
Ideally, the user doesn't need to know about ArrayV
, ObjectV
or any other internal type. We should make them transparent to the user.
In Java, we have functions to construct objects, arrays and internal values so the user doesn't need to construct them manually. The user only works with functions at the Expr
level:
Create(Ref("indexes"), Obj(
"name", Value("spells_by_element"),
"source", Ref("classes/spells"),
"terms": Arr(Obj("path", Value("data.element"))),
"active": Value(true)
)
Since in Scala we have implicit conversions, the user needs to know even less about the internal types:
Create(Ref("indexes"), Obj(
"name" -> "spells_by_element",
"source" -> Ref("classes/spells"),
"terms" -> Arr(Obj("path", "data.element")),
"active" -> true
)
I believe that if we follow some ground rules we can make a Swift DSL a bit more fluid. What I would like to see is if we could provide a DSL similar to this:
Create(ref: "indexes", [
"name": "spells_by_element",
"source": Ref("classes/spells"),
"terms": [["path": "data.element"]],
"active": true
)
There rules for that syntax are:
Expr
, not subtypes of Value
. Perhaps, we don't need to make Value
extends `Expr.Expr
are unnamed. Named parameters are used to infer types. For example Create(ref: "indexes")
vs Create(Ref("indexes"))
.Those rules are very similar to the Scala implementation at the moment and seems to be the cleanest typed language we got so far.
Let me know you're thoughts.
These tasks only includes environment support. Driver, testing, example app code are not included in this task.
At the moment we support Int
as a Scalar type. I wonder what happens if the user wants to work with values bigger than a Int
. In Java and Scala, the DLS works with Long
type to guarantee compatibility with all possible number types.
Use the structure defined in the Create DB query
https://github.com/Carthage/Carthage#archive-prebuilt-frameworks-into-one-zip-file
Benefits:
When looking at the code, we notice that named parameters for general Expr
are quite verbose when composing expressions. For example:
Delete(refExpr: Get(refExpr: Select(...
I think, when the parameter type is Expr
, we should not required named parameters.
Delete(Get(Select(...
That would read better and we can save the named parameters for type inference like:
Delete(Get(ref: "classes/spells"))
guard let result: Value = Ref(json: dictValue) ?? Timestamp(json: dictValue) ?? Date(json: dictValue) ?? Obj(json: dictValue) else { throw Error.DecodeException(data: dictValue) }
We have enough context to decode the specific types without trying to decode and failing one by one.
We should look for the @ts
, @ref
, and so on, on the root key of the parsed dictionary.
Var is not considered a value. It's an Expr only. (code review).
I had to make Var
type extends to Value
to be able to evaluate syntax sugar closures passing var as a parameters.
I will elaborate more on this so we can discuss some alternatives.
Eventually we might want to change networking library that currently relies on NSURLSession and NSURLSessionDataTask which are specific Foundation networking abstractions.
In our current implementation we are returning the task as a result of client.query method to be able to cancel the request, which is something thats happens often in a mobile platform as Example app shows.
Maybe we should wrap it up as CancelableQueryRequest
type.
protocol CancelableQueryRequest {
func cancel()
}
extension NSURLSessionDataTask: CancelableQueryRequest {}
@erickpintor Let me know if you think this is necessary.
Not included: response object model and parsing the response into it, we will just print the json result
It has both: "https://rest.faunadb.com:403" and "https://rest.faunadb.com". We should stay with only one.
The correct version is "https://rest.faunadb.com" since 403 is the default port.
Encodable
should not be public. At the moment, all Expr
has a toJSON
method exposed. We should avoid that.
Ideally it should not depend on 3rd party dependencies. I think it should be written directly on top of NSURLSession (Foundation) and do not depend on any external networking library.
Eventually https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSURLSession.swift will be implemented and this will allow us to run on linux.
Key features:
Configuration:
Am I missing something important? Any other critical feature for the client? @freels @erickpintor
Client
class sounds a bit too generic. I think we should keep it consistent with the other driver by calling it FaunaClient
.
@erickpintor @freels
How important is to pass the lambda vars using the same name typed by the developer? Can I use another variable name?
let arr: Arr = ["My First post", "My Second Post", "My third post"]
client.query(arr.faunaMap { Create(ref: Ref("classes/posts"), params: ["data": Obj(("title", $0))]) })
Notice that in swift we don't need to give a name to closure arguments and we can reference the arguments as $0. $1, etc.
Complete example....
let db_name = "app_db_\(arc4random())"
client.rx_query(Create(ref: Ref.databases, params: Obj(("name", db_name))))
.flatMap { _ -> Observable<ValueType> in
return client.rx_query(Create(ref: Ref.keys, params: ["database": Ref("databases/\(db_name)"), "role": "server"]))
}
.mapWithField(["secret"])
.doOnNext { (secret: String) in
print(secret)
client = Client(configuration: ClientConfiguration(secret: secret))
}
.flatMap { _ -> Observable<ValueType> in
return client.rx_query(Create(ref: Ref.classes, params: ["name":"posts"]))
}
.flatMap { _ -> Observable<ValueType> in
let arr: Arr = ["My First post", "My Second Post", "My third post"]
return client.rx_query(arr.faunaMap { Create(ref: Ref("classes/posts"), params: ["data": Obj(("title", $0))]) })
}
.doOnNext({ value in
print(value)
// Arr(Obj(data: Obj(title: My First post), ref: Ref(classes/posts/135817522195726339), ts: 1.465784532467e+15, class: Ref(classes/posts)), Obj(data: Obj(title: My Second Post), ref: Ref(classes/posts/135817522195727363), ts: 1.465784532467e+15, class: Ref(classes/posts)), Obj(data: Obj(title: My third post), ref: Ref(classes/posts/135817522195728387), ts: 1.465784532467e+15, class: Ref(classes/posts)))
})
.doOnError { error in
//do something with the error
print(error)
}
.subscribe()
.addDisposableTo(disposeBag)
Xcode is able to show which part of a file has been tested. ...
I think some of them are not realistic in practical terms, for instance we are not testing Error.description method and this makes the coverage percentage be low.
@erick Do you want to test something more in deep?
Putting focus on critical code source parts were not covered.
The ClientConfiguration
struct doesn't add much to the context. It makes initialisation verbose. I think the Client
itself should receive all it's parameters.
It should include parsing body response.
Hi -- curious if this driver is dead ...?
I just want to bump this driver and suggest that with the emergence of swift-ui -- I think it is perhaps worth re-investing in this driver.
There is definitely room in the apple ecosystem for a super high quality, easy to use, zero-management data-layer for swift-ui ...
A lot of new folks jumping into swift-ui googling 'what's a good api/data store for swift-ui' or some such. I think it would be a boon to many of those developers if one of the results they found during that search was this driver and faunadb.
To improve performance, FaunaDB allows http keep-alive connections. The should drivers issue requests with keep-alive header on.
The idle timeout for http connections is 5 seconds on the server, we should set it to a bit less on the client. 4 seconds should be fine.
That represents a possible security flaw.
query
method:
NSData
NSURLSessionDataTask
handleQueryErrors
method:
NetworkException
on cast errorprint
Showing how to:
Seems to me a common user case.
Similar to scala
CollectionField
type.
I think Result
verbose and, most of the time, you're more interested on result value rather than knowing it there was an error or not.
We could provide a general error handling that you attach to the client and a version of the query
method that only call the call back if the query succeed.
That would make the code more concise and less verbose.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.