@libsql/client
Advanced tools
Comparing version 0.1.4 to 0.1.5
@@ -34,2 +34,3 @@ "use strict"; | ||
const help_js_1 = require("./help.js"); | ||
const lru_js_1 = require("./lru.js"); | ||
const uri_js_1 = require("./uri.js"); | ||
@@ -71,18 +72,23 @@ __exportStar(require("./api.js"), exports); | ||
class HranaClient { | ||
#client; | ||
#url; | ||
#authToken; | ||
#connState; | ||
closed; | ||
/** @private */ | ||
constructor(client, url, authToken) { | ||
this.#client = client; | ||
this.#url = url; | ||
this.#authToken = authToken; | ||
this.#connState = { | ||
client, | ||
useSqlCache: undefined, | ||
sqlCache: new lru_js_1.Lru(), | ||
}; | ||
this.closed = false; | ||
} | ||
async execute(stmt) { | ||
const stream = this.#openStream(); | ||
const state = await this.#openStream(); | ||
try { | ||
const hranaStmt = stmtToHrana(stmt); | ||
const hranaRows = await stream.query(hranaStmt); | ||
const hranaStmt = applySqlCache(state, stmtToHrana(stmt)); | ||
const hranaRows = await state.stream.query(hranaStmt); | ||
evictSqlCache(state); | ||
return resultSetFromHrana(hranaRows); | ||
@@ -94,9 +100,9 @@ } | ||
finally { | ||
stream.close(); | ||
state.stream.close(); | ||
} | ||
} | ||
async batch(stmts) { | ||
const stream = this.#openStream(); | ||
const state = await this.#openStream(); | ||
try { | ||
const batch = stream.batch(); | ||
const batch = state.stream.batch(); | ||
const beginStep = batch.step(); | ||
@@ -106,3 +112,3 @@ const beginPromise = beginStep.run("BEGIN").catch(_ => undefined); | ||
const stmtPromises = stmts.map((stmt) => { | ||
const hranaStmt = stmtToHrana(stmt); | ||
const hranaStmt = applySqlCache(state, stmtToHrana(stmt)); | ||
const stmtStep = batch.step() | ||
@@ -121,2 +127,3 @@ .condition(hrana.BatchCond.ok(lastStep)); | ||
await batch.execute(); | ||
evictSqlCache(state); | ||
const resultSets = []; | ||
@@ -137,23 +144,27 @@ for (const stmtPromise of stmtPromises) { | ||
finally { | ||
stream.close(); | ||
state.stream.close(); | ||
} | ||
} | ||
async transaction() { | ||
const stream = this.#openStream(); | ||
const state = await this.#openStream(); | ||
try { | ||
await stream.run("BEGIN"); | ||
return new HranaTransaction(stream); | ||
await state.stream.run("BEGIN"); | ||
return new HranaTransaction(state); | ||
} | ||
catch (e) { | ||
stream.close(); | ||
state.stream.close(); | ||
throw mapHranaError(e); | ||
} | ||
} | ||
#openStream() { | ||
async #openStream() { | ||
if (this.closed) { | ||
throw new api_js_1.LibsqlError("The client is closed", "CLIENT_CLOSED"); | ||
} | ||
if (this.#client.closed) { | ||
if (this.#connState.client.closed) { | ||
try { | ||
this.#client = hrana.open(this.#url, this.#authToken); | ||
this.#connState = { | ||
client: hrana.open(this.#url, this.#authToken), | ||
useSqlCache: undefined, | ||
sqlCache: new lru_js_1.Lru(), | ||
}; | ||
} | ||
@@ -164,6 +175,16 @@ catch (e) { | ||
} | ||
return this.#client.openStream(); | ||
const connState = this.#connState; | ||
try { | ||
if (connState.useSqlCache === undefined) { | ||
connState.useSqlCache = await connState.client.getVersion() >= 2; | ||
} | ||
const stream = connState.client.openStream(); | ||
return { stream, ...connState }; | ||
} | ||
catch (e) { | ||
throw mapHranaError(e); | ||
} | ||
} | ||
close() { | ||
this.#client.close(); | ||
this.#connState.client.close(); | ||
this.closed = true; | ||
@@ -174,42 +195,68 @@ } | ||
class HranaTransaction { | ||
stream; | ||
#state; | ||
/** @private */ | ||
constructor(stream) { | ||
this.stream = stream; | ||
constructor(state) { | ||
this.#state = state; | ||
} | ||
async execute(stmt) { | ||
if (this.stream.closed) { | ||
if (this.#state.stream.closed) { | ||
throw new api_js_1.LibsqlError("Cannot execute a statement because the transaction is closed", "TRANSACTION_CLOSED"); | ||
} | ||
const hranaStmt = stmtToHrana(stmt); | ||
const hranaRows = await this.stream.query(hranaStmt) | ||
.catch(e => { throw mapHranaError(e); }); | ||
return resultSetFromHrana(hranaRows); | ||
try { | ||
const hranaStmt = applySqlCache(this.#state, stmtToHrana(stmt)); | ||
const hranaRows = await this.#state.stream.query(hranaStmt); | ||
evictSqlCache(this.#state); | ||
return resultSetFromHrana(hranaRows); | ||
} | ||
catch (e) { | ||
throw mapHranaError(e); | ||
} | ||
} | ||
async rollback() { | ||
if (this.stream.closed) { | ||
if (this.#state.stream.closed) { | ||
return; | ||
} | ||
const promise = this.stream.run("ROLLBACK") | ||
const promise = this.#state.stream.run("ROLLBACK") | ||
.catch(e => { throw mapHranaError(e); }); | ||
this.stream.close(); | ||
this.#state.stream.close(); | ||
await promise; | ||
} | ||
async commit() { | ||
if (this.stream.closed) { | ||
if (this.#state.stream.closed) { | ||
throw new api_js_1.LibsqlError("Cannot commit the transaction because it is already closed", "TRANSACTION_CLOSED"); | ||
} | ||
const promise = this.stream.run("COMMIT") | ||
const promise = this.#state.stream.run("COMMIT") | ||
.catch(e => { throw mapHranaError(e); }); | ||
this.stream.close(); | ||
this.#state.stream.close(); | ||
await promise; | ||
} | ||
close() { | ||
this.stream.close(); | ||
this.#state.stream.close(); | ||
} | ||
get closed() { | ||
return this.stream.closed; | ||
return this.#state.stream.closed; | ||
} | ||
} | ||
exports.HranaTransaction = HranaTransaction; | ||
const sqlCacheCapacity = 100; | ||
function applySqlCache(state, hranaStmt) { | ||
if (state.useSqlCache && typeof hranaStmt.sql === "string") { | ||
const sqlText = hranaStmt.sql; | ||
let sqlObj = state.sqlCache.get(sqlText); | ||
if (sqlObj === undefined) { | ||
sqlObj = state.client.storeSql(sqlText); | ||
state.sqlCache.set(sqlText, sqlObj); | ||
} | ||
if (sqlObj !== undefined) { | ||
hranaStmt.sql = sqlObj; | ||
} | ||
} | ||
return hranaStmt; | ||
} | ||
function evictSqlCache(state) { | ||
while (state.sqlCache.size > sqlCacheCapacity) { | ||
const sqlObj = state.sqlCache.deleteLru(); | ||
sqlObj.close(); | ||
} | ||
} | ||
function stmtToHrana(stmt) { | ||
@@ -216,0 +263,0 @@ if (typeof stmt === "string") { |
@@ -89,5 +89,9 @@ "use strict"; | ||
try { | ||
executeStmt(db, "BEGIN"); | ||
if (stmts.length > 1) { | ||
executeStmt(db, "BEGIN"); | ||
} | ||
const resultSets = stmts.map(stmt => executeStmt(db, stmt)); | ||
executeStmt(db, "COMMIT"); | ||
if (stmts.length > 1) { | ||
executeStmt(db, "COMMIT"); | ||
} | ||
return resultSets; | ||
@@ -94,0 +98,0 @@ } |
@@ -5,2 +5,3 @@ /// <reference types="node" /> | ||
import type { ExpandedConfig } from "./config.js"; | ||
import { Lru } from "./lru.js"; | ||
export * from "./api.js"; | ||
@@ -10,2 +11,10 @@ export declare function createClient(config: Config): HranaClient; | ||
export declare function _createClient(config: ExpandedConfig): HranaClient; | ||
interface ConnState { | ||
client: hrana.Client; | ||
useSqlCache: boolean | undefined; | ||
sqlCache: Lru<string, hrana.Sql>; | ||
} | ||
interface StreamState extends ConnState { | ||
stream: hrana.Stream; | ||
} | ||
export declare class HranaClient implements Client { | ||
@@ -22,5 +31,5 @@ #private; | ||
export declare class HranaTransaction implements Transaction { | ||
stream: hrana.Stream; | ||
#private; | ||
/** @private */ | ||
constructor(stream: hrana.Stream); | ||
constructor(state: StreamState); | ||
execute(stmt: InStatement): Promise<ResultSet>; | ||
@@ -27,0 +36,0 @@ rollback(): Promise<void>; |
@@ -5,2 +5,3 @@ import * as hrana from "@libsql/hrana-client"; | ||
import { supportedUrlLink } from "./help.js"; | ||
import { Lru } from "./lru.js"; | ||
import { encodeBaseUrl } from "./uri.js"; | ||
@@ -40,18 +41,23 @@ export * from "./api.js"; | ||
export class HranaClient { | ||
#client; | ||
#url; | ||
#authToken; | ||
#connState; | ||
closed; | ||
/** @private */ | ||
constructor(client, url, authToken) { | ||
this.#client = client; | ||
this.#url = url; | ||
this.#authToken = authToken; | ||
this.#connState = { | ||
client, | ||
useSqlCache: undefined, | ||
sqlCache: new Lru(), | ||
}; | ||
this.closed = false; | ||
} | ||
async execute(stmt) { | ||
const stream = this.#openStream(); | ||
const state = await this.#openStream(); | ||
try { | ||
const hranaStmt = stmtToHrana(stmt); | ||
const hranaRows = await stream.query(hranaStmt); | ||
const hranaStmt = applySqlCache(state, stmtToHrana(stmt)); | ||
const hranaRows = await state.stream.query(hranaStmt); | ||
evictSqlCache(state); | ||
return resultSetFromHrana(hranaRows); | ||
@@ -63,9 +69,9 @@ } | ||
finally { | ||
stream.close(); | ||
state.stream.close(); | ||
} | ||
} | ||
async batch(stmts) { | ||
const stream = this.#openStream(); | ||
const state = await this.#openStream(); | ||
try { | ||
const batch = stream.batch(); | ||
const batch = state.stream.batch(); | ||
const beginStep = batch.step(); | ||
@@ -75,3 +81,3 @@ const beginPromise = beginStep.run("BEGIN").catch(_ => undefined); | ||
const stmtPromises = stmts.map((stmt) => { | ||
const hranaStmt = stmtToHrana(stmt); | ||
const hranaStmt = applySqlCache(state, stmtToHrana(stmt)); | ||
const stmtStep = batch.step() | ||
@@ -90,2 +96,3 @@ .condition(hrana.BatchCond.ok(lastStep)); | ||
await batch.execute(); | ||
evictSqlCache(state); | ||
const resultSets = []; | ||
@@ -106,23 +113,27 @@ for (const stmtPromise of stmtPromises) { | ||
finally { | ||
stream.close(); | ||
state.stream.close(); | ||
} | ||
} | ||
async transaction() { | ||
const stream = this.#openStream(); | ||
const state = await this.#openStream(); | ||
try { | ||
await stream.run("BEGIN"); | ||
return new HranaTransaction(stream); | ||
await state.stream.run("BEGIN"); | ||
return new HranaTransaction(state); | ||
} | ||
catch (e) { | ||
stream.close(); | ||
state.stream.close(); | ||
throw mapHranaError(e); | ||
} | ||
} | ||
#openStream() { | ||
async #openStream() { | ||
if (this.closed) { | ||
throw new LibsqlError("The client is closed", "CLIENT_CLOSED"); | ||
} | ||
if (this.#client.closed) { | ||
if (this.#connState.client.closed) { | ||
try { | ||
this.#client = hrana.open(this.#url, this.#authToken); | ||
this.#connState = { | ||
client: hrana.open(this.#url, this.#authToken), | ||
useSqlCache: undefined, | ||
sqlCache: new Lru(), | ||
}; | ||
} | ||
@@ -133,6 +144,16 @@ catch (e) { | ||
} | ||
return this.#client.openStream(); | ||
const connState = this.#connState; | ||
try { | ||
if (connState.useSqlCache === undefined) { | ||
connState.useSqlCache = await connState.client.getVersion() >= 2; | ||
} | ||
const stream = connState.client.openStream(); | ||
return { stream, ...connState }; | ||
} | ||
catch (e) { | ||
throw mapHranaError(e); | ||
} | ||
} | ||
close() { | ||
this.#client.close(); | ||
this.#connState.client.close(); | ||
this.closed = true; | ||
@@ -142,41 +163,67 @@ } | ||
export class HranaTransaction { | ||
stream; | ||
#state; | ||
/** @private */ | ||
constructor(stream) { | ||
this.stream = stream; | ||
constructor(state) { | ||
this.#state = state; | ||
} | ||
async execute(stmt) { | ||
if (this.stream.closed) { | ||
if (this.#state.stream.closed) { | ||
throw new LibsqlError("Cannot execute a statement because the transaction is closed", "TRANSACTION_CLOSED"); | ||
} | ||
const hranaStmt = stmtToHrana(stmt); | ||
const hranaRows = await this.stream.query(hranaStmt) | ||
.catch(e => { throw mapHranaError(e); }); | ||
return resultSetFromHrana(hranaRows); | ||
try { | ||
const hranaStmt = applySqlCache(this.#state, stmtToHrana(stmt)); | ||
const hranaRows = await this.#state.stream.query(hranaStmt); | ||
evictSqlCache(this.#state); | ||
return resultSetFromHrana(hranaRows); | ||
} | ||
catch (e) { | ||
throw mapHranaError(e); | ||
} | ||
} | ||
async rollback() { | ||
if (this.stream.closed) { | ||
if (this.#state.stream.closed) { | ||
return; | ||
} | ||
const promise = this.stream.run("ROLLBACK") | ||
const promise = this.#state.stream.run("ROLLBACK") | ||
.catch(e => { throw mapHranaError(e); }); | ||
this.stream.close(); | ||
this.#state.stream.close(); | ||
await promise; | ||
} | ||
async commit() { | ||
if (this.stream.closed) { | ||
if (this.#state.stream.closed) { | ||
throw new LibsqlError("Cannot commit the transaction because it is already closed", "TRANSACTION_CLOSED"); | ||
} | ||
const promise = this.stream.run("COMMIT") | ||
const promise = this.#state.stream.run("COMMIT") | ||
.catch(e => { throw mapHranaError(e); }); | ||
this.stream.close(); | ||
this.#state.stream.close(); | ||
await promise; | ||
} | ||
close() { | ||
this.stream.close(); | ||
this.#state.stream.close(); | ||
} | ||
get closed() { | ||
return this.stream.closed; | ||
return this.#state.stream.closed; | ||
} | ||
} | ||
const sqlCacheCapacity = 100; | ||
function applySqlCache(state, hranaStmt) { | ||
if (state.useSqlCache && typeof hranaStmt.sql === "string") { | ||
const sqlText = hranaStmt.sql; | ||
let sqlObj = state.sqlCache.get(sqlText); | ||
if (sqlObj === undefined) { | ||
sqlObj = state.client.storeSql(sqlText); | ||
state.sqlCache.set(sqlText, sqlObj); | ||
} | ||
if (sqlObj !== undefined) { | ||
hranaStmt.sql = sqlObj; | ||
} | ||
} | ||
return hranaStmt; | ||
} | ||
function evictSqlCache(state) { | ||
while (state.sqlCache.size > sqlCacheCapacity) { | ||
const sqlObj = state.sqlCache.deleteLru(); | ||
sqlObj.close(); | ||
} | ||
} | ||
export function stmtToHrana(stmt) { | ||
@@ -183,0 +230,0 @@ if (typeof stmt === "string") { |
@@ -67,5 +67,9 @@ import Database from "better-sqlite3"; | ||
try { | ||
executeStmt(db, "BEGIN"); | ||
if (stmts.length > 1) { | ||
executeStmt(db, "BEGIN"); | ||
} | ||
const resultSets = stmts.map(stmt => executeStmt(db, stmt)); | ||
executeStmt(db, "COMMIT"); | ||
if (stmts.length > 1) { | ||
executeStmt(db, "COMMIT"); | ||
} | ||
return resultSets; | ||
@@ -72,0 +76,0 @@ } |
{ | ||
"name": "@libsql/client", | ||
"version": "0.1.4", | ||
"version": "0.1.5", | ||
"keywords": [ | ||
@@ -88,3 +88,3 @@ "libsql", | ||
"dependencies": { | ||
"@libsql/hrana-client": "^0.3.9", | ||
"@libsql/hrana-client": "^0.3.10", | ||
"@libsql/isomorphic-fetch": "^0.1.1", | ||
@@ -91,0 +91,0 @@ "better-sqlite3": "^8.0.1", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83307
34
2073
Updated@libsql/hrana-client@^0.3.10