Initial extraction from other project
This commit is contained in:
parent
81c4890897
commit
a54aa3ba0c
54
LICENSE
54
LICENSE
@ -1,21 +1,43 @@
|
||||
MIT License
|
||||
This is a modified Apache License:
|
||||
|
||||
You are permitted to use, compile, execute, the code in this repository,
|
||||
as long as this driver's protocol output is not sent over the SSL/TLS
|
||||
protocol. You are prohibited from connecting this driver to Compose.IO
|
||||
or to any other SSL/TLS endpoint without a commercial license.
|
||||
|
||||
To remove this limitation and permit usage over SSL/TLS, a commercial
|
||||
license must be purchased. The commercial license permitting use over
|
||||
SSL/TLS and Compose.IO is available from Bit Armory Inc and can
|
||||
be purchased here:
|
||||
|
||||
https://www.bitarmory.com/payments/rethinkdb
|
||||
|
||||
Copyright 2010-2012 RethinkDB
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
|
||||
Copyright (c) Daniel Cannon.
|
||||
|
||||
Copyright (c) 2015 Bitly.
|
||||
|
||||
Copyright 2010-2014 MongoDB Inc.
|
||||
|
||||
Copyright (c) 2016 Bit Armory Inc.
|
||||
|
||||
Copyright (c) 2016 Brian Chavez
|
||||
* http://github.com/bchavez
|
||||
* http://bchavez.bitarmory.com
|
||||
|
||||
Copyright (c) 2017 Daniel J. Summers
|
||||
* http://github.com/danieljsummers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
these files except in compliance with the License. You may obtain a copy of the
|
||||
License at
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Unless required by applicable law or agreed to in writing, software distributed
|
||||
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
67
README.md
67
README.md
@ -1,2 +1,69 @@
|
||||
# RethinkDb.Driver.FSharp
|
||||
Idiomatic F# extensions for the C# RethinkDB driver
|
||||
|
||||
## Licensing
|
||||
|
||||
While no specific additional license restrictions exist for this project, there are modifications to the Apache v2
|
||||
license on this project's dependencies. Please see [the heading on the C# driver page][license] for details.
|
||||
|
||||
## Using
|
||||
|
||||
It is still early days on this project; however, AppVeyor CI provides a [NuGet feed][nuget] that builds packages for
|
||||
each commit.
|
||||
|
||||
## Goals
|
||||
|
||||
The goal is to provide:
|
||||
- A composable pipeline for creating ReQL statements:
|
||||
|
||||
```fsharp
|
||||
/// string -> (IConnection -> Async<Post>)
|
||||
let fetchPost (postId : string) =
|
||||
fromDb "Blog"
|
||||
|> table "Post"
|
||||
|> get postId
|
||||
|> asyncResult<Post>
|
||||
```
|
||||
|
||||
- An F# domain-specific language (DSL) using a `rethink` computation expression:
|
||||
|
||||
```fsharp
|
||||
/// string -> (IConnection -> Async<Post>)
|
||||
let fetchPost (postId : string) =
|
||||
rethink {
|
||||
fromDb "Blog"
|
||||
table "Post"
|
||||
get postId
|
||||
asyncResult<Post>
|
||||
}
|
||||
```
|
||||
|
||||
- A standard way to translate JSON into a strongly-typed configuration:
|
||||
|
||||
```fsharp
|
||||
/// type: DataConfig
|
||||
let config = DataConfig.fromJsonFile "data-config.json"
|
||||
|
||||
/// type: IConnection
|
||||
let conn = config.Connect ()
|
||||
|
||||
/// type: Post (utilizing either example above)
|
||||
let post = fetchPost "the-post-id" conn |> Async.RunSynchronously
|
||||
```
|
||||
|
||||
- Only rename functions/methods where required
|
||||
|
||||
```fsharp
|
||||
// Function names cannot be polymorphic the way object-oriented methods can, so filter's three overloads become
|
||||
filter r.HashMap("age", 30)
|
||||
// and
|
||||
filterFunc (fun row -> row.["age"].Eq(30))
|
||||
// and
|
||||
filterJS "function (row) { return 30 == row['age'] }"
|
||||
```
|
||||
|
||||
The composable pipeline and the JSON configuration are the early goals, as the computation expression will utilize the
|
||||
same composition as those functions.
|
||||
|
||||
[license]: https://github.com/bchavez/RethinkDb.Driver#open-source-and-commercial-licensing
|
||||
[nuget]: https://ci.appveyor.com/nuget/danieljsummers-rethinkdb-driver-fsharp
|
11
appveyor.yml
Normal file
11
appveyor.yml
Normal file
@ -0,0 +1,11 @@
|
||||
os: Visual Studio 2017
|
||||
|
||||
build_script:
|
||||
- cmd: dotnet restore src\RethinkDb.Driver.FSharp.fsproj
|
||||
- cmd: dotnet build -v n src\RethinkDb.Driver.FSharp.fsproj
|
||||
- cmd: dotnet pack src\RethinkDb.Driver.FSharp.fsproj -o %CD%\artifacts\nupkg
|
||||
|
||||
artifacts:
|
||||
- path: artifacts\nupkg\*.nupkg
|
||||
|
||||
tests: off
|
95
src/RethinkDb.Driver.FSharp/Config.fs
Normal file
95
src/RethinkDb.Driver.FSharp/Config.fs
Normal file
@ -0,0 +1,95 @@
|
||||
namespace RethinkDb.Driver.FSharp
|
||||
|
||||
open Newtonsoft.Json.Linq
|
||||
open RethinkDb.Driver
|
||||
open RethinkDb.Driver.Net
|
||||
|
||||
/// Parameters for the RethinkDB configuration
|
||||
type DataConfigParameter =
|
||||
| Hostname of string
|
||||
| Port of int
|
||||
| User of string * string
|
||||
| AuthKey of string
|
||||
| Timeout of int
|
||||
| Database of string
|
||||
|
||||
/// RethinDB configuration
|
||||
type DataConfig =
|
||||
{ Parameters : DataConfigParameter list }
|
||||
with
|
||||
static member empty =
|
||||
{ Parameters = [] }
|
||||
/// Create a RethinkDB connection
|
||||
member this.CreateConnection () : IConnection =
|
||||
let folder (builder : Connection.Builder) block =
|
||||
match block with
|
||||
| Hostname x -> builder.Hostname x
|
||||
| Port x -> builder.Port x
|
||||
| User (x, y) -> builder.User (x, y)
|
||||
| AuthKey x -> builder.AuthKey x
|
||||
| Timeout x -> builder.Timeout x
|
||||
| Database x -> builder.Db x
|
||||
let bldr =
|
||||
this.Parameters
|
||||
|> Seq.fold folder (RethinkDB.R.Connection ())
|
||||
upcast bldr.Connect ()
|
||||
/// The effective hostname
|
||||
member this.Hostname =
|
||||
match this.Parameters
|
||||
|> List.tryPick (fun x -> match x with Hostname _ -> Some x | _ -> None) with
|
||||
| Some (Hostname x) -> x
|
||||
| _ -> RethinkDBConstants.DefaultHostname
|
||||
/// The effective port
|
||||
member this.Port =
|
||||
match this.Parameters
|
||||
|> List.tryPick (fun x -> match x with Port _ -> Some x | _ -> None) with
|
||||
| Some (Port x) -> x
|
||||
| _ -> RethinkDBConstants.DefaultPort
|
||||
/// The effective connection timeout
|
||||
member this.Timeout =
|
||||
match this.Parameters
|
||||
|> List.tryPick (fun x -> match x with Timeout _ -> Some x | _ -> None) with
|
||||
| Some (Timeout x) -> x
|
||||
| _ -> RethinkDBConstants.DefaultTimeout
|
||||
/// The effective database
|
||||
member this.Database =
|
||||
match this.Parameters
|
||||
|> List.tryPick (fun x -> match x with Database _ -> Some x | _ -> None) with
|
||||
| Some (Database x) -> x
|
||||
| _ -> RethinkDBConstants.DefaultDbName
|
||||
/// Parse settings from JSON
|
||||
///
|
||||
/// A sample JSON object with all the possible properties filled in:
|
||||
/// {
|
||||
/// "hostname" : "my-host",
|
||||
/// "port" : 12345,
|
||||
/// "username" : "my-user-name",
|
||||
/// "password" : "my-password",
|
||||
/// "auth-key" : "my-auth-key",
|
||||
/// "timeout" : 77,
|
||||
/// "database" : "default-db"
|
||||
/// }
|
||||
///
|
||||
/// None of these properties are required, and properties not matching any of the above listed ones will be ignored.
|
||||
static member FromJson json =
|
||||
let isNotNull = not << isNull
|
||||
let parsed = JObject.Parse json
|
||||
let config =
|
||||
seq {
|
||||
match parsed.["hostname"] with x when isNotNull x -> yield Hostname <| x.Value<string> () | _ -> ()
|
||||
match parsed.["port"] with x when isNotNull x -> yield Port <| x.Value<int> () | _ -> ()
|
||||
match parsed.["auth-key"] with x when isNotNull x -> yield AuthKey <| x.Value<string> () | _ -> ()
|
||||
match parsed.["timeout"] with x when isNotNull x -> yield Timeout <| x.Value<int> () | _ -> ()
|
||||
match parsed.["database"] with x when isNotNull x -> yield Database <| x.Value<string> () | _ -> ()
|
||||
let userName = parsed.["username"]
|
||||
let password = parsed.["password"]
|
||||
match isNotNull userName && isNotNull password with
|
||||
| true -> yield User (userName.Value<string> (), password.Value<string> ())
|
||||
| _ -> ()
|
||||
}
|
||||
|> List.ofSeq
|
||||
{ Parameters = config }
|
||||
/// Parse settings from a JSON text file
|
||||
///
|
||||
/// See doc for FromJson for the expected JSON format.
|
||||
static member FromJsonFile = System.IO.File.ReadAllText >> DataConfig.FromJson
|
80
src/RethinkDb.Driver.FSharp/Functions.fs
Normal file
80
src/RethinkDb.Driver.FSharp/Functions.fs
Normal file
@ -0,0 +1,80 @@
|
||||
[<AutoOpen>]
|
||||
module RethinkDb.Driver.FSharp.Functions
|
||||
|
||||
open RethinkDb.Driver
|
||||
|
||||
let private r = RethinkDB.R
|
||||
|
||||
/// Get a connection builder that can be used to create one RethinkDB connection
|
||||
let connection () =
|
||||
r.Connection ()
|
||||
|
||||
/// Get the results of an expression
|
||||
let asyncResult<'T> conn (expr : Ast.ReqlExpr) =
|
||||
expr.RunResultAsync<'T> conn
|
||||
|> Async.AwaitTask
|
||||
|
||||
/// Get the result of a non-select ReQL expression
|
||||
let asyncReqlResult conn (expr : Ast.ReqlExpr) =
|
||||
expr.RunResultAsync conn
|
||||
|> Async.AwaitTask
|
||||
|
||||
/// Get a list of databases
|
||||
let dbList conn =
|
||||
r.DbList ()
|
||||
|> asyncResult<string list> conn
|
||||
|
||||
/// Create a database
|
||||
let dbCreate dbName conn =
|
||||
r.DbCreate dbName
|
||||
|> asyncReqlResult conn
|
||||
|
||||
/// Reference a database
|
||||
let db dbName =
|
||||
r.Db dbName
|
||||
|
||||
/// Reference the default database
|
||||
let defaultDb =
|
||||
(fun () -> r.Db ()) ()
|
||||
|
||||
/// Get a list of tables for the given database
|
||||
let tableList conn (db : Ast.Db) =
|
||||
db.TableList ()
|
||||
|> asyncResult<string list> conn
|
||||
|
||||
/// Create a table in the given database
|
||||
let tableCreate tableName conn (db : Ast.Db) =
|
||||
db.TableCreate tableName
|
||||
|> asyncReqlResult conn
|
||||
|
||||
/// Return all documents in a table (may be further refined)
|
||||
let table tableName (db : Ast.Db) =
|
||||
db.Table tableName
|
||||
|
||||
/// Return all documents in a table from the default database (may be further refined)
|
||||
let fromTable tableName =
|
||||
table tableName defaultDb
|
||||
|
||||
/// Get a list of indexes for the given table
|
||||
let indexList conn (table : Ast.Table) =
|
||||
table.IndexList ()
|
||||
|> asyncResult<string list> conn
|
||||
|
||||
/// Create an index on the given table
|
||||
let indexCreate indexName conn (table : Ast.Table) =
|
||||
table.IndexCreate indexName
|
||||
|> asyncReqlResult conn
|
||||
|
||||
/// Get a document by its primary key
|
||||
let get documentId (table : Ast.Table) =
|
||||
table.Get documentId
|
||||
|
||||
/// Get all documents matching keys in the given index
|
||||
let getAll (ids : 'T seq) indexName (table : Ast.Table) =
|
||||
table.GetAll(ids |> Array.ofSeq).OptArg("index", indexName)
|
||||
|
||||
|
||||
/// Get a cursor with the results of an expression
|
||||
let asyncCursor<'T> conn (expr : Ast.ReqlExpr) =
|
||||
expr.RunCursorAsync<'T> conn
|
||||
|> Async.AwaitTask
|
29
src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj
Normal file
29
src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj
Normal file
@ -0,0 +1,29 @@
|
||||
<Project Sdk="FSharp.NET.Sdk;Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net45;netstandard1.6</TargetFrameworks>
|
||||
<Description>Idiomatic F# extentions to the official RethinkDB C# driver</Description>
|
||||
<Authors>Daniel J. Summers</Authors>
|
||||
<PackageLicenseUrl>https://github.com/danieljsummers/RethinkDb.Driver.FSharp/blob/master/LICENSE</PackageLicenseUrl>
|
||||
<PackageProjectUrl>https://github.com/danieljsummers/RethinkDb.Driver.FSharp</PackageProjectUrl>
|
||||
<!-- PackageIconUrl>https://github.com/danieljsummers/RethinkDb.Driver.FSharp/raw/master/icon/icon.png</PackageIconUrl -->
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<PackageReleaseNotes>Alpha; use at your own risk</PackageReleaseNotes>
|
||||
<Copyright>See LICENSE</Copyright>
|
||||
<PackageTags>RethinkDB document F#</PackageTags>
|
||||
<VersionPrefix>0.7.0</VersionPrefix>
|
||||
<VersionSuffix>alpha-0001</VersionSuffix>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Functions.fs" />
|
||||
<Compile Include="Config.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FSharp.Core" Version="4.2.*" />
|
||||
<PackageReference Include="FSharp.NET.Sdk" Version="1.0.*" PrivateAssets="All" />
|
||||
<PackageReference Include="RethinkDb.Driver" Version="2.*" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user