-
Notifications
You must be signed in to change notification settings - Fork 352
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #211 from penberg/javascript
Improve JavaScript bindings
- Loading branch information
Showing
14 changed files
with
234 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
## Developing | ||
|
||
```sh | ||
$ npm install | ||
$ cargo build | ||
$ npm link | ||
$ node example.js | ||
``` |
2 changes: 1 addition & 1 deletion
2
crates/bindings/js/example.js → crates/bindings/js/examples/example.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
var libsql = require('.'); | ||
import libsql from 'libsql-js'; | ||
|
||
var db = new libsql.Database(':memory:'); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"name": "libsql-examples", | ||
"type": "module", | ||
"private": true, | ||
"dependencies": { | ||
"libsql-js": "^0.0.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "libsql-js-integration-tests", | ||
"type": "module", | ||
"private": true, | ||
"scripts": { | ||
"test": "ava" | ||
}, | ||
"devDependencies": { | ||
"ava": "^5.3.0" | ||
}, | ||
"dependencies": { | ||
"better-sqlite3": "^8.4.0", | ||
"libsql-js": "^0" | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
crates/bindings/js/integration-tests/tests/better-sqlite3.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Database from "better-sqlite3"; | ||
import test from "ava"; | ||
|
||
test("basic usage", (t) => { | ||
const options = {}; | ||
const db = new Database(":memory:", options); | ||
|
||
db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"); | ||
|
||
db.exec("INSERT INTO users (id, name, email) VALUES (1, 'Alice', '[email protected]')"); | ||
|
||
const userId = 1; | ||
|
||
const row = db.prepare("SELECT * FROM users WHERE id = ?").get(userId); | ||
|
||
t.is(row.name, "Alice"); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import libsql from "libsql-js"; | ||
import test from "ava"; | ||
|
||
test("basic usage", (t) => { | ||
const options = {}; | ||
const db = new libsql.Database(":memory:", options); | ||
|
||
db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"); | ||
|
||
db.exec("INSERT INTO users (id, name, email) VALUES (1, 'Alice', '[email protected]')"); | ||
|
||
const userId = 1; | ||
|
||
const row = db.prepare("SELECT * FROM users WHERE id = ?").get(userId, "foo"); | ||
|
||
t.is(row.name, "Alice"); | ||
}); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,101 @@ | ||
use std::any::Any; | ||
|
||
use libsql; | ||
use neon::prelude::*; | ||
|
||
struct Database { | ||
_db: libsql::Database, | ||
db: libsql::Database, | ||
conn: libsql::Connection, | ||
} | ||
|
||
impl Finalize for Database {} | ||
|
||
impl Database { | ||
fn new(db: libsql::Database) -> Self { | ||
Database { _db: db } | ||
fn new(db: libsql::Database, conn: libsql::Connection) -> Self { | ||
Database { db, conn } | ||
} | ||
|
||
fn js_new(mut cx: FunctionContext) -> JsResult<JsBox<Database>> { | ||
let url = cx.argument::<JsString>(0)?.value(&mut cx); | ||
let db = libsql::Database::open(url); | ||
let db = Database::new(db); | ||
let db = libsql::Database::open(url.clone()); | ||
let conn = db.connect().unwrap(); | ||
let db = Database::new(db, conn); | ||
Ok(cx.boxed(db)) | ||
} | ||
|
||
fn js_exec(mut cx: FunctionContext) -> JsResult<JsUndefined> { | ||
let db = cx.this().downcast_or_throw::<JsBox<Database>, _>(&mut cx)?; | ||
let sql = cx.argument::<JsString>(0)?.value(&mut cx); | ||
db.conn.execute(sql, ()).unwrap(); | ||
Ok(cx.undefined()) | ||
} | ||
|
||
fn js_prepare(mut cx: FunctionContext) -> JsResult<JsBox<Statement>> { | ||
let db = cx.this().downcast_or_throw::<JsBox<Database>, _>(&mut cx)?; | ||
let sql = cx.argument::<JsString>(0)?.value(&mut cx); | ||
let stmt = db.conn.prepare(sql).unwrap(); | ||
let stmt = Statement { stmt }; | ||
Ok(cx.boxed(stmt)) | ||
} | ||
} | ||
|
||
struct Statement { | ||
stmt: libsql::Statement, | ||
} | ||
|
||
impl Finalize for Statement {} | ||
|
||
fn js_value_to_value(cx: &mut FunctionContext, v: Handle<'_, JsValue>) -> libsql::Value { | ||
if v.is_a::<JsNumber, _>(cx) { | ||
let v = v.downcast_or_throw::<JsNumber, _>(cx).unwrap(); | ||
let v = v.value(cx); | ||
libsql::Value::Integer(v as i64) | ||
} else if v.is_a::<JsString, _>(cx) { | ||
let v = v.downcast_or_throw::<JsString, _>(cx).unwrap(); | ||
let v = v.value(cx); | ||
libsql::Value::Text(v) | ||
} else { | ||
todo!("unsupported type"); | ||
} | ||
} | ||
|
||
impl Statement { | ||
fn js_get(mut cx: FunctionContext) -> JsResult<JsObject> { | ||
let stmt = cx | ||
.this() | ||
.downcast_or_throw::<JsBox<Statement>, _>(&mut cx)?; | ||
let mut params = vec![]; | ||
for i in 0..cx.len() { | ||
let v = cx.argument::<JsValue>(i)?; | ||
let v = js_value_to_value(&mut cx, v); | ||
params.push(v); | ||
} | ||
let params = libsql::Params::Positional(params); | ||
let rows = stmt.stmt.execute(¶ms).unwrap(); | ||
let row = rows.next().unwrap().unwrap(); | ||
let result = cx.empty_object(); | ||
for idx in 0..rows.column_count() { | ||
let v = row.get_value(idx).unwrap(); | ||
let column_name = rows.column_name(idx); | ||
let key = cx.string(column_name); | ||
let v: Handle<'_, JsValue> = match v { | ||
libsql::Value::Null => cx.null().upcast(), | ||
libsql::Value::Integer(v) => cx.number(v as f64).upcast(), | ||
libsql::Value::Float(v) => cx.number(v).upcast(), | ||
libsql::Value::Text(v) => cx.string(v).upcast(), | ||
libsql::Value::Blob(v) => todo!("unsupported type"), | ||
}; | ||
result.set(&mut cx, key, v)?; | ||
} | ||
Ok(result) | ||
} | ||
} | ||
|
||
#[neon::main] | ||
fn main(mut cx: ModuleContext) -> NeonResult<()> { | ||
cx.export_function("databaseNew", Database::js_new)?; | ||
cx.export_function("databaseExec", Database::js_exec)?; | ||
cx.export_function("databasePrepare", Database::js_prepare)?; | ||
cx.export_function("statementGet", Statement::js_get)?; | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.