ReasonML model and query generator for CRUD actions
npm install bs-crud-functors@7.1.2
ReasonML model and query generator for CRUD actions based upon bs-sql-common and bs-sql-composer.
This is a SQL wrapper that provides many convenience features and a "light" ORM interface that uses plain SQL as the underlying language. Currently it is only compatible with the [bs-mysql2] client.
Inside of a BuckleScript project:
yarn add @glennsl/bs-json bs-crud-functors bs-mysql2 bs-node-debug bs-sql-common bs-sql-composer
Then add @glennsl/bs-json
, bs-crud-functors
, bs-mysql2
, bs-node-debug
,
bs-sql-common
and bs-sql-composer
to your bs-dependencies
in
bsconfig.json
:
{
"bs-dependencies": [
"@glennsl/bs-json",
"bs-crud-functors",
"bs-mysql2",
"bs-node-debug",
"bs-sql-common",
"bs-sql-composer"
]
}
The way you should access modules in CrudFunctors
is as follows:
CrudFunctors.<Module>
Of course you can always directly call the internal files, namespaced with
CrudFunctors_
, but that is not recommended since these files are
implementation details.
Below are the requirements necessary to use the FactoryModel. Each requirement is documented with examples below. The requirements include: creating the connection, creating the config, and creating the model.
module Sql = SqlCommon.Make_sql(MySql2);
module CrudFunctorImpl = CrudFunctor.Make(Sql)
let conn = Sql.connect(
~host="127.0.0.1",
~port=3306,
~user="root",
~database="example",
()
);
Creating the Config is quite simple, below is a brief explanation for each field in the Config:
let table = "animal";
type animal = {
id: int,
type_: string,
deleted: int,
};
module Config = {
type t = animal;
let table = table;
let decoder = json =>
Json.Decode.{
id: field("id", int, json),
type_: field("type_", string, json),
deleted: field("deleted", int, json),
};
let base =
SqlComposer.Select.(
select
|> field({j|$table.`id`|j})
|> field({j|$table.`type_`|j})
|> field({j|$table.`deleted`|j})
|> order_by(`Desc({j|$table.`id`|j}))
);
};
Creating the model is quite simple once the Config is setup:
module Model = CrudFunctorImpl.Model.Make(Config);
Below are a few examples on how to use the model, refer to the documentation below for the full list of functions/methods:
Model.Create.one(
type_ => Json.Encode.([ ("type_", string @@ type_) ] |. object_),
"my cat",
conn
)
|. Future.mapOk(maybeCat =>
switch(maybeCat) {
| Some(cat) => Js.log2("Your New Cat: ", cat)
| None => Js.log("Oh the noes, we lost your cat")
}
)
|. Future.flatMapError(error => Js.Console.error(error))
|. ignore;
Model.Read.where(
(base) => base |. SqlComposer.Select.where({j|AND $table.type_ = ?|j}),
Json.Encode.([| string @@ "cat" |]),
conn
)
|. Future.mapOk(cats => Js.log2("Your Cats:", cats))
|. Future.flatMapError(error => Js.Console.error(error))
|. ignore;
Creating an ID can be a pain-point, but it's abstracted away to ensure proper handling and formatting.
let id = 42 |. Json.Encode.int |. string_of_int |. CrudFunctorImpl.Id.fromJson;
Model.Read.one_by_id(id, db)
|. Future.mapOk(maybeCat =>
switch(maybeCat) {
| Some(cat) => Js.log2("Your Cat: ", cat)
| None => Js.log("Oh the noes, we couldn't find your cat")
}
)
|. Future.flatMapError(error => Js.Console.error(error))
|. ignore;
Note: you will notice that some methods will return Result.Ok(None)
, this means that the row(s)
were altered successfully but when an attempt to fetch the same row(s) was made the operation failed;
this is because the Model's base query filters out the row(s) after update.
Everything not checked...
id
column - must fit PrimaryId
interfaceObjectHash
interfaceid
column - must fit the Counter
and PrimaryId
interfacesPrimaryId
interfaceid
column - must fit the Activated
and
PrimaryId
interfacesid
column - must fit the Archive
interfaceArchiveCompound
interfaceid
column - must fit the
ArchiveCompound
and PrimaryId
interfacesid
column - must fit PrimaryId
interfaceid
column - must fit PrimaryId
interfaceObjectHash
interfaceid
column - must fit PrimaryId
interfaceid
column - must fit the Counter
and PrimaryId
interfacesPrimaryId
interfaceid
column - must fit the Activated
and
PrimaryId
interfacesid
column - must fit the Archive
interfaceArchiveCompound
interfaceid
column - must fit the
ArchiveCompound
and PrimaryId
interfacesid
column - must fit PrimaryId
interfaceid
column - must fit PrimaryId
interfaceObjectHash
interfaceObjectHash
interface interpolation