Initial extraction from other project

This commit is contained in:
Daniel J. Summers 2017-07-16 20:18:47 -05:00
parent 81c4890897
commit a54aa3ba0c
6 changed files with 320 additions and 16 deletions

54
LICENSE
View File

@ -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.

View File

@ -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
View 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

View 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

View 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

View 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>