Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
17d65a5
Added core interfaces
halvardssm Mar 11, 2024
224f259
Added core wrappers
halvardssm Mar 11, 2024
de39bc5
Added databases and updated docs
halvardssm Mar 11, 2024
c811a3a
Fixed interface
halvardssm Mar 11, 2024
9a9596b
Improved transaction interfaces
halvardssm Mar 15, 2024
fe88599
updated package name
halvardssm Mar 16, 2024
a721660
updated version
halvardssm Mar 16, 2024
fb52d27
Added vendor
halvardssm Mar 19, 2024
a3201af
Added type improvements
halvardssm Mar 19, 2024
fd22564
bump
halvardssm Mar 19, 2024
9a4f271
Changed MySqlConnectionParamType
halvardssm Mar 19, 2024
7201483
updated tests and ci
halvardssm Mar 21, 2024
ce06200
updated coverage
halvardssm Mar 21, 2024
62fac7f
updated vendor
halvardssm Mar 28, 2024
0f68b36
refactored folder structure
halvardssm Mar 28, 2024
48a4e6e
updated docs
halvardssm Mar 28, 2024
4cc3590
added docs
halvardssm Mar 28, 2024
482edf0
bump
halvardssm Mar 28, 2024
736d51a
fixed exports
halvardssm Mar 28, 2024
721bad8
Fixed vendor
halvardssm Mar 29, 2024
c214285
Updated clients
halvardssm Mar 29, 2024
791daaa
Added events support
halvardssm Mar 31, 2024
971013f
Added lazy initiation support of pools and added info getters
halvardssm Mar 31, 2024
f23cb42
Added Query options
halvardssm Mar 31, 2024
7da204f
Added abort signal to query options, and added base database error
halvardssm Mar 31, 2024
ede0b20
updated vendor
halvardssm Apr 8, 2024
0ec9533
cleaned up types
halvardssm Apr 8, 2024
57ca92a
fixed wrappers
halvardssm Apr 8, 2024
130e787
added test wrapper
halvardssm Apr 8, 2024
83890e3
fixed clients
halvardssm Apr 8, 2024
1d1e1ea
updated readme
halvardssm Apr 8, 2024
d245b3b
bump
halvardssm Apr 8, 2024
b0fb3b1
Imporved interfaces and removed abstract classes
halvardssm Apr 8, 2024
e41e05b
Updated sqlite client
halvardssm Apr 8, 2024
c9916f8
bump
halvardssm Apr 8, 2024
8671f8c
updated postgres and mysql wrappers
halvardssm Apr 8, 2024
c633641
added version, prepared statement interface and base event
halvardssm Apr 10, 2024
e8bc514
removed clients
halvardssm Apr 21, 2024
506d146
removed vendor
halvardssm Apr 21, 2024
e58a2f1
removed wrappers
halvardssm Apr 21, 2024
76030e7
updated deps and exports
halvardssm Apr 21, 2024
08f6416
improved interfaces and testing
halvardssm Apr 21, 2024
4d99365
fixed tests
halvardssm Apr 21, 2024
a8b64bb
added isSqlxError check
halvardssm Apr 21, 2024
12c9c43
bump
halvardssm Apr 21, 2024
f91ae6d
fixed export
halvardssm Apr 21, 2024
16abaaf
Split up interfaces and cleanup
halvardssm Apr 24, 2024
ada6043
removed event target from connection
halvardssm Apr 24, 2024
8edf36d
refactored events
halvardssm Apr 24, 2024
1eee214
refactored tests
halvardssm Apr 24, 2024
3b7c43b
bump
halvardssm Apr 24, 2024
3f40d78
fixed ci
halvardssm Apr 24, 2024
b14a956
fixed check
halvardssm Apr 24, 2024
993b3ce
updated docs and tests
halvardssm Apr 26, 2024
bc09c23
removed destroy event
halvardssm Apr 28, 2024
0236bc4
bump
halvardssm Apr 28, 2024
5e107e2
fmt
halvardssm Apr 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,3 @@ jobs:

- name: Check fmt
run: deno task check

test:
name: Tests
runs-on: ubuntu-latest

steps:
- name: Clone repo
uses: actions/checkout@v3

- name: Install deno
uses: denoland/setup-deno@v1

- name: Run unit tests
run: deno task test

- name: Generate lcov
run: deno coverage --unstable --lcov ./coverage > coverage.lcov

- name: Upload coverage
uses: codecov/codecov-action@v1
with:
files: coverage.lcov
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,4 @@ $RECYCLE.BIN/
# End of https://www.toptal.com/developers/gitignore/api/deno,linux,macos,windows,intellij+all,visualstudiocode

coverage
coverage.lcov
220 changes: 220 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,223 @@ A subgoal is for this repo to live in Deno Standard Library and available in
be available under `@db/core`.

This repo is WIP and can change at any time.

## Usage

Minimal usage example:

```ts
await using db = new Client(connectionUrl, connectionOptions);
await db.connect();
await db.execute("SOME INSERT QUERY");
const res = await db.query("SELECT * FROM table");
```

SQLx provides a standard for interacting with a database.

### Client

Full compliance with SQLx provides a database client with the following methods
(see [SqlxClient](./lib/client.ts)):

- `connect` (See [SqlxConnection](./lib/connection.ts)): Creates a connection to
the database
- `close` (See [SqlxConnection](./lib/connection.ts)): Closes the connection to
the database
- `execute` (See [SqlxQueriable](./lib/core.ts)): Executes a SQL statement
- `query` (See [SqlxQueriable](./lib/core.ts)): Queries the database and returns
an array of object
- `queryOne` (See [SqlxQueriable](./lib/core.ts)): Queries the database and
returns at most one entry as an object
- `queryMany` (See [SqlxQueriable](./lib/core.ts)): Queries the database with an
async generator and yields each entry as an object
- `queryArray` (See [SqlxQueriable](./lib/core.ts)): Queries the database and
returns an array of arrays
- `queryOneArray` (See [SqlxQueriable](./lib/core.ts)): Queries the database and
returns at most one entry as an array
- `queryManyArray` (See [SqlxQueriable](./lib/core.ts)): Queries the database
with an async generator and yields each entry as an array
- `sql` (See [SqlxQueriable](./lib/core.ts)): Allows you to create a query using
template literals, and returns the entries as an array of objects. This is a
wrapper around `query`
- `sqlArray` (See [SqlxQueriable](./lib/core.ts)): Allows you to create a query
using template literals, and returns the entries as an array of arrays. This
is a wrapper around `queryArray`
- `prepare` (See [SqlxPreparable](./lib/core.ts)): Returns a prepared statement
class that contains a subset of the Queriable functions (see
[SqlxPreparedQueriable](./lib/core.ts))
- `beginTransaction` (See [SqlxTransactionable](./lib/core.ts)): Returns a
transaction class that contains implements the queriable functions, as well as
transaction related functions (see [SqlxTransactionQueriable](./lib/core.ts))
- `transaction` (See [SqlxTransactionable](./lib/core.ts)): A wrapper function
for transactions, handles the logic of beginning, committing and rollback a
transaction.

### ClientPool

Full compliance with SQLx provides a database client pool (a pool of clients)
with the following methods (see [SqlxClientPool](./lib/pool.ts)):

- `connect` (See [SqlxConnection](./lib/core.ts)): Creates the connection
classes and adds them to a connection pool, and optionally connects them to
the database
- `close` (See [SqlxConnection](./lib/core.ts)): Closes all connections in the
pool
- `acquire` (See [SqlxPoolable](./lib/core.ts)): Retrieves a
[SqlxPoolClient](./lib/pool.ts) (a subset of [Client](#client)), and connects
it if not already connected
- `release` (See [SqlxPoolable](./lib/core.ts)): Releases a connection back to
the pool

### Examples

Using const (requires manual close at the end)

```ts
const db = new Client(connectionUrl, connectionOptions);
await db.connect();
await db.execute("SOME INSERT QUERY");
const res = await db.query("SELECT * FROM table");
await db.close();
```

Query object

```ts
await using db = new Client(connectionUrl, connectionOptions);
await db.connect();
await db.execute("SOME INSERT QUERY");
const res = await db.query("SELECT * FROM table");
console.log(res);
// [{ col1: "some value" }]
```

Query array

```ts
await using db = new Client(connectionUrl, connectionOptions);
await db.connect();
await db.execute("SOME INSERT QUERY");
const res = await db.queryArray("SELECT * FROM table");
console.log(res);
// [[ "some value" ]]
```

Query with template literals

```ts
await using db = new Client(connectionUrl, connectionOptions);
await db.connect();
await db.execute("SOME INSERT QUERY");
const res = await db.sqlArray`SELECT * FROM table where id = ${id}`;
console.log(res);
// [[ "some value" ]]
```

Transaction

```ts
await using db = new Client(connectionUrl, connectionOptions);
await db.connect();
await db.execute("SOME INSERT QUERY");
const transaction = await db.beginTransaction();
await transaction.execute("SOME INSERT QUERY");
await transaction.commitTransaction();
// transaction can no longer be used
```

Transaction wrapper

```ts
await using db = new Client(connectionUrl, connectionOptions);
await db.connect();
await db.execute("SOME INSERT QUERY");
const res = await db.transaction(async (t) => {
await t.execute("SOME INSERT QUERY");
return t.query("SOME SELECT QUERY");
});
console.log(res);
// [{ col1: "some value" }]
```

Prepared statement

```ts
await using db = new Client(connectionUrl, connectionOptions);
await db.connect();
await db.execute("SOME INSERT QUERY");
const prepared = db.prepare("SOME PREPARED STATEMENT");
await prepared.query([...params]);
console.log(res);
// [{ col1: "some value" }]
```

## Implementation

To be fully compliant with SQLx, you will need to implement the following
classes for your database driver:

- `Connection` ([SqlxConnection](./lib/connection.ts)): This represents the
connection to the database. This should preferably only contain the
functionality of containing a connection, and provide a minimum query method
to be used to query the database. The query method does not need to follow any
specific spec, but must be consumable by all query functions as well as
execute functions (see `SqlxQueriable`)
- `Prepared` ([SqlxPreparedQueriable](./lib/core.ts)): This represents a
prepared statement. All queriable methods must be implemented
- `Transaction` ([SqlxTransactionQueriable](./lib/core.ts)): This represents a
transaction. All queriable methods must be implemented
- `Client` ([SqlxClient](./lib/client.ts)): This represents a database client
- `ClientPool` ([SqlxClientPool](./lib/pool.ts)): This represents a pool of
clients
- `PoolClient` ([SqlxPoolClient](./lib/pool.ts)): This represents a client to be
provided by a pool

It is also however advisable to create the following sub classes to use in other
classes:

- [SqlxQueriable](./lib/core.ts): This represents a queriable base class that
contains the standard SQLx query methods. In most cases, this serves as a base
class for all other queriable classes
- [SqlxEventTarget](./lib/events.ts): A typed event target class
- [SqlxError](./lib/errors.ts): A typed error class

### Inheritance graph

In most cases, these are the classes and the inheritance graph that should be
implemented. Notice how almost everything extends `SqlxBase` at the base.

- SqlxConnection
- SqlxBase
- SqlxPreparedQueriable
- SqlxBase
- SqlxTransactionQueriable
- SqlxPreparable
- SqlxQueriable
- SqlxBase
- SqlxClient
- SqlxTransactionable
- SqlxPreparable
- SqlxQueriable
- SqlxBase
- SqlxPoolClient
- SqlxTransactionable
- SqlxPreparable
- SqlxQueriable
- SqlxBase
- SqlxClientPool
- SqlxBase

### Other

There is also a [SqlxDeferredStack](./lib//deferred.ts) that is used by the pool
as a helper for queuing and stacking the pool clients.

### Base class

SQLx uses implementable interfaces as well as base classes that needs to be
inherited for desired functionality.

At the base layer, you will have to extend the `SqlxBase` class for all SQLx
derived classes. Alternatively, if this is not possible, you can implement
SqlxBase, and ensure that the dynamic and static properties are accessible.
33 changes: 22 additions & 11 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
{
"name": "@db/sqlx",
"version": "0.0.1",
"name": "@halvardm/sqlx",
"version": "0.0.0-13",
"lock": false,
"exports": {
".": "./mod.ts",
"./core": "./lib/core/mod.ts",
"./mysql": "./lib/mysql/mod.ts",
"./postgres": "./lib/postgres/mod.ts",
"./sqlite": "./lib/sqlite/mod.ts"
"./testing": "./lib/testing.ts"
},
"tasks": {
"check": "deno task format:check && deno task lint:check && deno task type:check",
"lint:check": "deno lint",
"format:check": "deno fmt --check",
"type:check": "deno check mod.ts",
"test": "deno task db:start && deno test -A --unstable-ffi --coverage; deno task db:stop",
"type:check": "deno check lib/*.ts",
"doc:check": "deno doc --lint lib",
"test": "deno task db:restart && deno test -A --unstable-ffi --coverage; deno task db:stop",
"test:ga": "deno task db:start && deno test -A --unstable-ffi --coverage && deno task db:stop",
"coverage:lcov": "deno coverage --exclude=vendor --lcov > coverage.lcov",
"db:restart": "deno task db:stop && deno task db:start",
"db:start": "docker compose up -d --remove-orphans --wait && sleep 2",
"db:stop": "docker compose down --remove-orphans --volumes"
},
"fmt": {
"exclude": [
"coverage",
"vendor"
]
},
"lint": {
"exclude": [
"coverage",
"vendor"
]
},
"imports": {
"@db/mysql": "https://deno.land/x/mysql@v2.12.1/mod.ts",
"@db/postgres": "https://deno.land/x/postgres@v0.19.3/mod.ts",
"@db/sqlite": "jsr:@db/sqlite@^0.11.0",
"@std/assert": "jsr:@std/assert@^0.219.1",
"@std/testing": "jsr:@std/testing@^0.219.1"
}
Expand Down
Loading