Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@libsql/client

Package Overview
Dependencies
Maintainers
3
Versions
93
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@libsql/client - npm Package Compare versions

Comparing version 0.1.4 to 0.1.5

lib-cjs/lru.js

117

lib-cjs/hrana.js

@@ -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",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc