
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
bs-sql-common
Advanced tools
A common interface for SQL-based Node.js drivers.
To provide a common interface for MySQL, PostgreSQL and sqlite implementations.
A rewrite of the entire package to expose it as a Functor that can accept
any module which implements the Queryable interface.
Use Belt.Result for responses so to better integrate with then BuckleScript ecosystem.
Provide response decoding and inspection functions so that the user has a consistent view into responses from any library.
Provide an ID type that properly encodes large integers as strings.
Provide batch inserts and queries
The standard things are there and this library is being used live within several production projects.
Inside of a BuckleScript project:
yarn install --save bs-sql-common
Then add bs-sql-common to your bs-dependencies in your bsconfig.json
{
"bs-dependencies": [ "bs-sql-common" ]
}
Then add a bs-sql-common compatible package to your repository or create your
own. All of the examples use the bs-mysql2 package, here are the
requirements to use that package:
yarn install --save bs-mysql2Â
{
"bs-dependencies": [ "bs-sql-common", "bs-mysql2" ]
}
module Sql = SqlCommon.Make(MySql2)
let db = Sql.Connection.connect
~host="127.0.0.1"
~port=3306
~user="root"
()
Sql.query ~db ~sql:"SHOW DATABASES" (fun res ->
match res with
| Belt.Result.Error e -> raise e
| Belt.Result.Ok select ->
select
|. Sql.Response.Select.flatMap (Json.Decode.dict Json.Decode.string)
|. Belt.Array.map (fun x -> Js.dict.unsafeGet x "Database")
|. Expect.expect
|> Expect.toContain @@ "test"
)
Note: All of the examples use the bs-mysql2 package as the
connection provider. Any other provider should have the same behavior with
differing connection creation requirements.
The following connection and module will be use within the rest of the examples.
module Sql = SqlCommon.Make(MySql2);
let db = Sql.Connection.connect(~host="127.0.0.1", ~port=3306, ~user="root", ());
Assume the following statement occurs at the end of each example.
Sql.Connection.close(conn);
Sql.query(~db, ~sql="SHOW DATABASES",
fun
| Belt.Result.Error e => Js.log2("ERROR: ", e)
| Belt.Result.Ok select =>
select
|. Sql.Response.Select.rows
|. Js.log2("RESPONSE ROWS: ", _)
);
Sql.mutate(
~db,
~sql="INSERT INTO test (foo) VALUES (?)",
~params=Sql.Params.positional(Json.Encode.([|string("bar")|] |. array)),
(res) =>
fun
| Belt.Result.Error => Js.log2("ERROR: ", e)
| Belt.Result.Ok mutation =>
mutation
|. Sql.Response.Mutation.insertId
|. Js.log2("INSERT ID: ", _)
);
let json = Sql.Params.named(
Json.Encode.(object_([
("x", int(1)),
("y", int(2)),
]))
));
let decoder = Json.Encode.array(Json.Encode.int)
Sql.query(~db, ~sql:"SELECT :x + :y AS z", ~params, (res) =>
switch res {
| Belt.Result.Error => Js.log2("ERROR: ", e)
| Belt.Result.Ok select =>
select
|. Sql.Response.flatMap(decoder)
|. Js.log2("DECODED ROWS: ", _)
}
);
Sql.mutate(~db, ~sql:"INSERT INTO test (foo, bar) VALUES (:x, :y)", ~params, (res) =>
switch res {
| Belt.Result.Error => Js.log2("ERROR: ", e)
| Belt.Result.Ok mutation =>
mutation
|. Sql.Response.Mutation.insertId
|. Js.log2("INSERT ID: ", _)
}
);
let params = Sql.Params.positional(
Json.Encode.(array(int, [|5,6|]))
));
Sql.query(~db, ~sql:"SELECT 1 + ? + ? AS result", ~params, (res) =>
switch res {
| Belt.Result.Error => Js.log2("ERROR: ", e)
| Belt.Result.Ok select =>
select
|. Sql.Response.rows
|. Js.log2("RAW ROWS: ", _)
}
);
Sql.mutate(~db, ~sql:"INSERT INTO test (foo, bar) VALUES (?, ?)", ~params, (res) =>
switch res {
| Belt.Result.Error => Js.log2("ERROR: ", e)
| Belt.Result.Ok mutation =>
mutation
|. Sql.Response.Mutation.insertId
|. Js.log2("INSERT ID: ", _)
}
);
let params = Sql.Params.positional(
Json.Encode.(array(int, [|"%schema"|]))
));
Sql.query(~db, ~params, ~sql="SELECT ? AS search")
|> Js.Promise.then_(select =>
select
|. Sql.Response.rows
|. Js.log2("RAW ROWS: ", _)
|. ignore
)
|> Js.Promise.catch(err =>
Js.log2("Failure!!!", err)
|. ignore
)
module Id: sig
type t = Driver.Id.t
val fromJson : Js.Json.t -> Driver.Id.t
val toJson : Driver.Id.t -> Js.Json.t
val toString : Driver.Id.t -> string
end
module Response: sig
module Mutation: sig
val insertId : Driver.Mutation.t -> Id.t option
val affectedRows: Driver.Mutation.t -> int
end
module Select: sig
module Meta : sig
val schema : Driver.Select.Meta.t -> string
val name : Driver.Select.Meta.t -> string
val table : Driver.Select.Meta.t -> string
end
val meta : Driver.Select.t -> Driver.Select.Meta.t array
val concat : Driver.Select.t -> Driver.Select.t -> Driver.Select.t
val count : Driver.Select.t -> int
val flatMap :
Driver.Select.t ->
(Js.Json.t -> Driver.Select.Meta.t array -> 'a) ->
'a array
val flatMap : Driver.Select.t -> (Js.Json.t -> 'a) -> 'a array
val rows : Driver.Select.t -> Js.Json.t array
end
end
module type Queryable = sig
module Connection : sig
type t
val connect :
?host:string ->
?port:int ->
?user:string ->
?password:string ->
?database:string ->
unit -> t
val close : t -> unit
end
module Exn : sig
val fromJs : Js.Json.t -> exn
end
module Id : sig
type t
val fromJson : Js.Json.t -> t
val toJson : t -> Js.Json.t
val toString : t -> string
end
module Mutation : sig
type t
val insertId : t -> Id.t option
val affectedRows : t -> int
end
module Params : sig
type t
val named : Js.Json.t -> t
val positional : Js.Json.t -> t
end
module Select : sig
type t
module Meta : sig
type t
val schema : t -> string
val name : t -> string
val table : t -> string
end
val meta : t -> Meta.t array
val concat : t -> t -> t
val count : t -> int
val flatMapWithMeta : t -> (Js.Json.t -> Meta.t array -> 'a) -> 'a array
val flatMap : t -> (Js.Json.t -> 'a) -> 'a array
val rows : t -> Js.Json.t array
end
type response =
[
| `Error of exn
| `Mutation of Mutation.t
| `Select of Select.t
]
type callback = response -> unit
val execute : Connection.t -> string -> Params.t option -> callback -> unit
end
FAQs
A common interface common for SQL drivers.
The npm package bs-sql-common receives a total of 63 weekly downloads. As such, bs-sql-common popularity was classified as not popular.
We found that bs-sql-common demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.