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

@libsql/hrana-client

Package Overview
Dependencies
Maintainers
3
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@libsql/hrana-client - npm Package Compare versions

Comparing version 0.3.9 to 0.3.10

lib-cjs/describe.js

24

lib-cjs/batch.js

@@ -11,2 +11,3 @@ "use strict";

#streamState;
#executed;
/** @private */

@@ -20,2 +21,3 @@ _steps;

this.#streamState = streamState;
this.#executed = false;
this._steps = [];

@@ -30,12 +32,22 @@ this._resultCallbacks = [];

execute() {
if (this.#executed) {
throw new Error("The Batch has already been executed");
}
this.#executed = true;
return new Promise((doneCallback, errorCallback) => {
const batchState = {
batch: {
const request = {
"type": "batch",
"stream_id": this.#streamState.streamId,
"batch": {
"steps": this._steps,
},
resultCallbacks: this._resultCallbacks,
doneCallback,
errorCallback,
};
this.#client._batch(this.#streamState, batchState);
const responseCallback = (response) => {
const result = response["result"];
for (const callback of this._resultCallbacks) {
callback(result);
}
doneCallback();
};
this.#client._sendStreamRequest(this.#streamState, request, { responseCallback, errorCallback });
});

@@ -42,0 +54,0 @@ }

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Client = void 0;
exports.Client = exports.protocolVersions = void 0;
const isomorphic_ws_1 = require("@libsql/isomorphic-ws");

@@ -8,8 +8,13 @@ const id_alloc_js_1 = require("./id_alloc.js");

const result_js_1 = require("./result.js");
const sql_js_1 = require("./sql.js");
const stream_js_1 = require("./stream.js");
exports.protocolVersions = new Map([
["hrana2", 2],
["hrana1", 1],
]);
/** A client that talks to a SQL server using the Hrana protocol over a WebSocket. */
class Client {
#socket;
// List of messages that we queue until the socket transitions from the CONNECTING to the OPEN state.
#msgsWaitingToOpen;
// List of callbacks that we queue until the socket transitions from the CONNECTING to the OPEN state.
#openCallbacks;
// Stores the error that caused us to close the client (and the socket). If we are not closed, this is

@@ -20,2 +25,8 @@ // `undefined`.

#recvdHello;
// Protocol version negotiated with the server. It is only available after the socket transitions to the
// OPEN state.
#version;
// Has the `getVersion()` function been called? This is only used to validate that the API is used
// correctly.
#getVersionCalled;
// A map from request id to the responses that we expect to receive from the server.

@@ -27,2 +38,4 @@ #responseMap;

#streamIdAlloc;
// An allocator of SQL text ids.
#sqlIdAlloc;
/** @private */

@@ -32,8 +45,11 @@ constructor(socket, jwt) {

this.#socket.binaryType = "arraybuffer";
this.#msgsWaitingToOpen = [];
this.#openCallbacks = [];
this.#closed = undefined;
this.#recvdHello = false;
this.#version = undefined;
this.#getVersionCalled = false;
this.#responseMap = new Map();
this.#requestIdAlloc = new id_alloc_js_1.IdAlloc();
this.#streamIdAlloc = new id_alloc_js_1.IdAlloc();
this.#sqlIdAlloc = new id_alloc_js_1.IdAlloc();
this.#socket.addEventListener("open", () => this.#onSocketOpen());

@@ -54,3 +70,5 @@ this.#socket.addEventListener("close", (event) => this.#onSocketClose(event));

else {
this.#msgsWaitingToOpen.push(msg);
const openCallback = () => this.#sendToSocket(msg);
const errorCallback = (_) => undefined;
this.#openCallbacks.push({ openCallback, errorCallback });
}

@@ -60,6 +78,16 @@ }

#onSocketOpen() {
for (const msg of this.#msgsWaitingToOpen) {
this.#sendToSocket(msg);
const protocol = this.#socket.protocol;
if (protocol === "") {
this.#version = 1;
}
this.#msgsWaitingToOpen.length = 0;
else {
this.#version = exports.protocolVersions.get(protocol);
if (this.#version === undefined) {
this.#setClosed(new errors_js_1.ProtoError(`Unrecognized WebSocket subprotocol: ${JSON.stringify(protocol)}`));
}
}
for (const callbacks of this.#openCallbacks) {
callbacks.openCallback();
}
this.#openCallbacks.length = 0;
}

@@ -69,4 +97,34 @@ #sendToSocket(msg) {

}
/** Get the protocol version negotiated with the server, possibly waiting until the socket is open. */
getVersion() {
return new Promise((versionCallback, errorCallback) => {
this.#getVersionCalled = true;
if (this.#closed !== undefined) {
errorCallback(this.#closed);
}
else if (this.#version !== undefined) {
versionCallback(this.#version);
}
else {
const openCallback = () => versionCallback(this.#version);
this.#openCallbacks.push({ openCallback, errorCallback });
}
});
}
// Make sure that the negotiated version is at least `minVersion`.
/** @private */
_ensureVersion(minVersion, feature) {
if (this.#version === undefined || !this.#getVersionCalled) {
throw new errors_js_1.ProtocolVersionError(`${feature} is supported only on protocol version ${minVersion} and higher, ` +
"but the version supported by the server is not yet known. Use Client.getVersion() " +
"to wait until the version is available.");
}
else if (this.#version < minVersion) {
throw new errors_js_1.ProtocolVersionError(`${feature} is supported on protocol version ${minVersion} and higher, ` +
`but the server only supports version ${this.#version}`);
}
}
// Send a request to the server and invoke a callback when we get the response.
#sendRequest(request, callbacks) {
/** @private */
_sendRequest(request, callbacks) {
if (this.#closed !== undefined) {

@@ -100,2 +158,6 @@ callbacks.errorCallback(new errors_js_1.ClosedError("Client is closed", this.#closed));

this.#closed = error;
for (const callbacks of this.#openCallbacks) {
callbacks.errorCallback(error);
}
this.#openCallbacks.length = 0;
for (const [requestId, responseState] of this.#responseMap.entries()) {

@@ -185,3 +247,3 @@ responseState.errorCallback(error);

};
this.#sendRequest(request, { responseCallback, errorCallback });
this._sendRequest(request, { responseCallback, errorCallback });
return new stream_js_1.Stream(this, streamState);

@@ -203,49 +265,46 @@ }

};
this.#sendRequest(request, { responseCallback: callback, errorCallback: callback });
this._sendRequest(request, { responseCallback: callback, errorCallback: callback });
}
// Execute a statement on a stream and invoke callbacks in `stmtCallbacks` when we get the results (or an
// error).
// Send a stream-specific request to the server and invoke a callback when we get the response.
/** @private */
_execute(streamState, stmtCallbacks) {
const responseCallback = (response) => {
stmtCallbacks.resultCallback(response["result"]);
};
const errorCallback = (error) => {
stmtCallbacks.errorCallback(error);
};
_sendStreamRequest(streamState, request, callbacks) {
if (streamState.closed !== undefined) {
errorCallback(new errors_js_1.ClosedError("Stream was closed", streamState.closed));
callbacks.errorCallback(new errors_js_1.ClosedError("Stream is closed", streamState.closed));
return;
}
this._sendRequest(request, callbacks);
}
/** Cache a SQL text on the server. This requires protocol version 2 or higher. */
storeSql(sql) {
this._ensureVersion(2, "storeSql()");
const sqlId = this.#sqlIdAlloc.alloc();
const sqlState = {
sqlId,
closed: undefined,
};
const responseCallback = () => undefined;
const errorCallback = (e) => this._closeSql(sqlState, e);
const request = {
"type": "execute",
"stream_id": streamState.streamId,
"stmt": stmtCallbacks.stmt,
"type": "store_sql",
"sql_id": sqlId,
"sql": sql,
};
this.#sendRequest(request, { responseCallback, errorCallback });
this._sendRequest(request, { responseCallback, errorCallback });
return new sql_js_1.Sql(this, sqlState);
}
// Execute a batch on a stream and invoke callbacks in `batchCallbacks` when we get the results (or an
// error).
// Make sure that the SQL text is closed.
/** @private */
_batch(streamState, batchCallbacks) {
const responseCallback = (response) => {
const result = response["result"];
for (const callback of batchCallbacks.resultCallbacks) {
callback(result);
}
batchCallbacks.doneCallback();
};
const errorCallback = (error) => {
batchCallbacks.errorCallback(error);
};
if (streamState.closed !== undefined) {
errorCallback(new errors_js_1.ClosedError("Stream was closed", streamState.closed));
_closeSql(sqlState, error) {
if (sqlState.closed !== undefined || this.#closed !== undefined) {
return;
}
sqlState.closed = error;
const callback = () => {
this.#sqlIdAlloc.free(sqlState.sqlId);
};
const request = {
"type": "batch",
"stream_id": streamState.streamId,
"batch": batchCallbacks.batch,
"type": "close_sql",
"sql_id": sqlState.sqlId,
};
this.#sendRequest(request, { responseCallback, errorCallback });
this._sendRequest(request, { responseCallback: callback, errorCallback: callback });
}

@@ -252,0 +311,0 @@ /** Close the client and the WebSocket. */

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LibsqlUrlParseError = exports.WebSocketError = exports.WebSocketUnsupportedError = exports.ClosedError = exports.ResponseError = exports.ProtoError = exports.ClientError = void 0;
exports.ProtocolVersionError = exports.LibsqlUrlParseError = exports.WebSocketError = exports.WebSocketUnsupportedError = exports.ClosedError = exports.ResponseError = exports.ProtoError = exports.ClientError = void 0;
/** Generic error produced by the Hrana client. */

@@ -73,1 +73,10 @@ class ClientError extends Error {

exports.LibsqlUrlParseError = LibsqlUrlParseError;
/** Error thrown when the protocol version is too low to support a feature. */
class ProtocolVersionError extends ClientError {
/** @private */
constructor(message) {
super(message);
this.name = "ProtocolVersionError";
}
}
exports.ProtocolVersionError = ProtocolVersionError;

@@ -29,3 +29,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.open = exports.Stream = exports.Stmt = exports.raw = exports.parseLibsqlUrl = exports.BatchCond = exports.BatchStep = exports.Batch = exports.Client = void 0;
exports.open = exports.Stream = exports.Stmt = exports.Sql = exports.raw = exports.parseLibsqlUrl = exports.BatchCond = exports.BatchStep = exports.Batch = exports.Client = void 0;
const isomorphic_ws_1 = require("@libsql/isomorphic-ws");

@@ -45,2 +45,4 @@ const client_js_1 = require("./client.js");

exports.raw = __importStar(require("./raw.js"));
var sql_js_1 = require("./sql.js");
Object.defineProperty(exports, "Sql", { enumerable: true, get: function () { return sql_js_1.Sql; } });
var stmt_js_1 = require("./stmt.js");

@@ -55,5 +57,5 @@ Object.defineProperty(exports, "Stmt", { enumerable: true, get: function () { return stmt_js_1.Stmt; } });

}
const socket = new isomorphic_ws_1.WebSocket(url, ["hrana1"]);
const socket = new isomorphic_ws_1.WebSocket(url, Array.from(client_js_1.protocolVersions.keys()));
return new client_js_1.Client(socket, jwt ?? null);
}
exports.open = open;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.valueFromProto = exports.valueToProto = exports.stmtToProto = exports.errorFromProto = exports.valueResultFromProto = exports.rowResultFromProto = exports.rowsResultFromProto = exports.stmtResultFromProto = void 0;
exports.valueFromProto = exports.valueToProto = exports.stmtToProto = exports.errorFromProto = exports.valueResultFromProto = exports.rowResultFromProto = exports.rowsResultFromProto = exports.stmtResultFromProto = exports.describeResultFromProto = void 0;
var describe_js_1 = require("./describe.js");
Object.defineProperty(exports, "describeResultFromProto", { enumerable: true, get: function () { return describe_js_1.describeResultFromProto; } });
var result_js_1 = require("./result.js");

@@ -5,0 +7,0 @@ Object.defineProperty(exports, "stmtResultFromProto", { enumerable: true, get: function () { return result_js_1.stmtResultFromProto; } });

@@ -10,3 +10,4 @@ "use strict";

lastInsertRowid: result["last_insert_rowid"] ?? undefined,
columnNames: result["cols"].map(col => col.name ?? undefined),
columnNames: result["cols"].map(col => col["name"] ?? undefined),
columnDecltypes: result["cols"].map(col => col["decltype"] ?? undefined),
};

@@ -13,0 +14,0 @@ }

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stmtToProto = exports.Stmt = void 0;
const sql_js_1 = require("./sql.js");
const value_js_1 = require("./value.js");

@@ -8,3 +9,3 @@ /** A statement that can be evaluated by the database. Besides the SQL text, it also contains the positional

class Stmt {
/** The SQL statement string. */
/** The SQL statement text. */
sql;

@@ -54,7 +55,7 @@ /** @private */

function stmtToProto(stmt, wantRows) {
let sql;
let inSql;
let args = [];
let namedArgs = [];
if (stmt instanceof Stmt) {
sql = stmt.sql;
inSql = stmt.sql;
args = stmt._args;

@@ -66,3 +67,3 @@ for (const [name, value] of stmt._namedArgs.entries()) {

else if (Array.isArray(stmt)) {
sql = stmt[0];
inSql = stmt[0];
if (Array.isArray(stmt[1])) {

@@ -79,6 +80,13 @@ args = stmt[1].map(value_js_1.valueToProto);

else {
sql = "" + stmt;
inSql = stmt;
}
return { "sql": sql, "args": args, "named_args": namedArgs, "want_rows": wantRows };
const { sql, sqlId } = (0, sql_js_1.sqlToProto)(inSql);
return {
"sql": sql,
"sql_id": sqlId,
"args": args,
"named_args": namedArgs,
"want_rows": wantRows,
};
}
exports.stmtToProto = stmtToProto;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Stream = void 0;
const batch_js_1 = require("./batch.js");
const describe_js_1 = require("./describe.js");
const errors_js_1 = require("./errors.js");
const batch_js_1 = require("./batch.js");
const result_js_1 = require("./result.js");
const sql_js_1 = require("./sql.js");
const stmt_js_1 = require("./stmt.js");

@@ -35,9 +37,12 @@ /** A stream for executing SQL statements (a "database connection"). */

return new Promise((doneCallback, errorCallback) => {
this.#client._execute(this.#state, {
stmt,
resultCallback(result) {
doneCallback(fromProto(result));
},
errorCallback,
});
const request = {
"type": "execute",
"stream_id": this.#state.streamId,
"stmt": stmt,
};
const responseCallback = (response) => {
const result = response["result"];
doneCallback(fromProto(result));
};
this.#client._sendStreamRequest(this.#state, request, { responseCallback, errorCallback });
});

@@ -49,2 +54,38 @@ }

}
/** Parse and analyze a statement. This requires protocol version 2 or higher. */
describe(inSql) {
this.#client._ensureVersion(2, "describe()");
const { sql, sqlId } = (0, sql_js_1.sqlToProto)(inSql);
return new Promise((doneCallback, errorCallback) => {
const request = {
"type": "describe",
"stream_id": this.#state.streamId,
"sql": sql,
"sql_id": sqlId,
};
const responseCallback = (response) => {
const result = response["result"];
doneCallback((0, describe_js_1.describeResultFromProto)(result));
};
this.#client._sendStreamRequest(this.#state, request, { responseCallback, errorCallback });
});
}
/** Execute a sequence of statements separated by semicolons. This requires protocol version 2 or higher.
* */
sequence(inSql) {
this.#client._ensureVersion(2, "sequence()");
const { sql, sqlId } = (0, sql_js_1.sqlToProto)(inSql);
return new Promise((doneCallback, errorCallback) => {
const request = {
"type": "sequence",
"stream_id": this.#state.streamId,
"sql": sql,
"sql_id": sqlId,
};
const responseCallback = (_response) => {
doneCallback();
};
this.#client._sendStreamRequest(this.#state, request, { responseCallback, errorCallback });
});
}
/** Close the stream. */

@@ -51,0 +92,0 @@ close() {

@@ -8,2 +8,3 @@ import { ProtoError } from "./errors.js";

#streamState;
#executed;
/** @private */

@@ -17,2 +18,3 @@ _steps;

this.#streamState = streamState;
this.#executed = false;
this._steps = [];

@@ -27,12 +29,22 @@ this._resultCallbacks = [];

execute() {
if (this.#executed) {
throw new Error("The Batch has already been executed");
}
this.#executed = true;
return new Promise((doneCallback, errorCallback) => {
const batchState = {
batch: {
const request = {
"type": "batch",
"stream_id": this.#streamState.streamId,
"batch": {
"steps": this._steps,
},
resultCallbacks: this._resultCallbacks,
doneCallback,
errorCallback,
};
this.#client._batch(this.#streamState, batchState);
const responseCallback = (response) => {
const result = response["result"];
for (const callback of this._resultCallbacks) {
callback(result);
}
doneCallback();
};
this.#client._sendStreamRequest(this.#streamState, request, { responseCallback, errorCallback });
});

@@ -39,0 +51,0 @@ }

/// <reference types="ws" />
import { WebSocket } from "@libsql/isomorphic-ws";
import type * as proto from "./proto.js";
import { Sql } from "./sql.js";
import { Stream } from "./stream.js";
export type ProtocolVersion = 1 | 2;
export declare const protocolVersions: Map<string, ProtocolVersion>;
/** A client that talks to a SQL server using the Hrana protocol over a WebSocket. */

@@ -10,2 +13,8 @@ export declare class Client {

constructor(socket: WebSocket, jwt: string | null);
/** Get the protocol version negotiated with the server, possibly waiting until the socket is open. */
getVersion(): Promise<ProtocolVersion>;
/** @private */
_ensureVersion(minVersion: ProtocolVersion, feature: string): void;
/** @private */
_sendRequest(request: proto.Request, callbacks: ResponseCallbacks): void;
/** Open a {@link Stream}, a stream for executing SQL statements. */

@@ -16,5 +25,7 @@ openStream(): Stream;

/** @private */
_execute(streamState: StreamState, stmtCallbacks: StmtCallbacks): void;
_sendStreamRequest(streamState: StreamState, request: proto.Request, callbacks: ResponseCallbacks): void;
/** Cache a SQL text on the server. This requires protocol version 2 or higher. */
storeSql(sql: string): Sql;
/** @private */
_batch(streamState: StreamState, batchCallbacks: BatchCallbacks): void;
_closeSql(sqlState: SqlState, error: Error): void;
/** Close the client and the WebSocket. */

@@ -25,7 +36,10 @@ close(): void;

}
export interface StmtCallbacks {
stmt: proto.Stmt;
resultCallback: (_: proto.StmtResult) => void;
export interface OpenCallbacks {
openCallback: () => void;
errorCallback: (_: Error) => void;
}
export interface ResponseCallbacks {
responseCallback: (_: proto.Response) => void;
errorCallback: (_: Error) => void;
}
export interface StreamState {

@@ -35,7 +49,5 @@ streamId: number;

}
export interface BatchCallbacks {
batch: proto.Batch;
resultCallbacks: Array<(_: proto.BatchResult) => void>;
doneCallback: () => void;
errorCallback: (_: Error) => void;
export interface SqlState {
sqlId: number;
closed: Error | undefined;
}
import { WebSocket } from "@libsql/isomorphic-ws";
import { IdAlloc } from "./id_alloc.js";
import { ClientError, ProtoError, ClosedError, WebSocketError } from "./errors.js";
import { ClientError, ProtoError, ClosedError, WebSocketError, ProtocolVersionError } from "./errors.js";
import { errorFromProto } from "./result.js";
import { Sql } from "./sql.js";
import { Stream } from "./stream.js";
export const protocolVersions = new Map([
["hrana2", 2],
["hrana1", 1],
]);
/** A client that talks to a SQL server using the Hrana protocol over a WebSocket. */
export class Client {
#socket;
// List of messages that we queue until the socket transitions from the CONNECTING to the OPEN state.
#msgsWaitingToOpen;
// List of callbacks that we queue until the socket transitions from the CONNECTING to the OPEN state.
#openCallbacks;
// Stores the error that caused us to close the client (and the socket). If we are not closed, this is

@@ -16,2 +21,8 @@ // `undefined`.

#recvdHello;
// Protocol version negotiated with the server. It is only available after the socket transitions to the
// OPEN state.
#version;
// Has the `getVersion()` function been called? This is only used to validate that the API is used
// correctly.
#getVersionCalled;
// A map from request id to the responses that we expect to receive from the server.

@@ -23,2 +34,4 @@ #responseMap;

#streamIdAlloc;
// An allocator of SQL text ids.
#sqlIdAlloc;
/** @private */

@@ -28,8 +41,11 @@ constructor(socket, jwt) {

this.#socket.binaryType = "arraybuffer";
this.#msgsWaitingToOpen = [];
this.#openCallbacks = [];
this.#closed = undefined;
this.#recvdHello = false;
this.#version = undefined;
this.#getVersionCalled = false;
this.#responseMap = new Map();
this.#requestIdAlloc = new IdAlloc();
this.#streamIdAlloc = new IdAlloc();
this.#sqlIdAlloc = new IdAlloc();
this.#socket.addEventListener("open", () => this.#onSocketOpen());

@@ -50,3 +66,5 @@ this.#socket.addEventListener("close", (event) => this.#onSocketClose(event));

else {
this.#msgsWaitingToOpen.push(msg);
const openCallback = () => this.#sendToSocket(msg);
const errorCallback = (_) => undefined;
this.#openCallbacks.push({ openCallback, errorCallback });
}

@@ -56,6 +74,16 @@ }

#onSocketOpen() {
for (const msg of this.#msgsWaitingToOpen) {
this.#sendToSocket(msg);
const protocol = this.#socket.protocol;
if (protocol === "") {
this.#version = 1;
}
this.#msgsWaitingToOpen.length = 0;
else {
this.#version = protocolVersions.get(protocol);
if (this.#version === undefined) {
this.#setClosed(new ProtoError(`Unrecognized WebSocket subprotocol: ${JSON.stringify(protocol)}`));
}
}
for (const callbacks of this.#openCallbacks) {
callbacks.openCallback();
}
this.#openCallbacks.length = 0;
}

@@ -65,4 +93,34 @@ #sendToSocket(msg) {

}
/** Get the protocol version negotiated with the server, possibly waiting until the socket is open. */
getVersion() {
return new Promise((versionCallback, errorCallback) => {
this.#getVersionCalled = true;
if (this.#closed !== undefined) {
errorCallback(this.#closed);
}
else if (this.#version !== undefined) {
versionCallback(this.#version);
}
else {
const openCallback = () => versionCallback(this.#version);
this.#openCallbacks.push({ openCallback, errorCallback });
}
});
}
// Make sure that the negotiated version is at least `minVersion`.
/** @private */
_ensureVersion(minVersion, feature) {
if (this.#version === undefined || !this.#getVersionCalled) {
throw new ProtocolVersionError(`${feature} is supported only on protocol version ${minVersion} and higher, ` +
"but the version supported by the server is not yet known. Use Client.getVersion() " +
"to wait until the version is available.");
}
else if (this.#version < minVersion) {
throw new ProtocolVersionError(`${feature} is supported on protocol version ${minVersion} and higher, ` +
`but the server only supports version ${this.#version}`);
}
}
// Send a request to the server and invoke a callback when we get the response.
#sendRequest(request, callbacks) {
/** @private */
_sendRequest(request, callbacks) {
if (this.#closed !== undefined) {

@@ -96,2 +154,6 @@ callbacks.errorCallback(new ClosedError("Client is closed", this.#closed));

this.#closed = error;
for (const callbacks of this.#openCallbacks) {
callbacks.errorCallback(error);
}
this.#openCallbacks.length = 0;
for (const [requestId, responseState] of this.#responseMap.entries()) {

@@ -181,3 +243,3 @@ responseState.errorCallback(error);

};
this.#sendRequest(request, { responseCallback, errorCallback });
this._sendRequest(request, { responseCallback, errorCallback });
return new Stream(this, streamState);

@@ -199,49 +261,46 @@ }

};
this.#sendRequest(request, { responseCallback: callback, errorCallback: callback });
this._sendRequest(request, { responseCallback: callback, errorCallback: callback });
}
// Execute a statement on a stream and invoke callbacks in `stmtCallbacks` when we get the results (or an
// error).
// Send a stream-specific request to the server and invoke a callback when we get the response.
/** @private */
_execute(streamState, stmtCallbacks) {
const responseCallback = (response) => {
stmtCallbacks.resultCallback(response["result"]);
};
const errorCallback = (error) => {
stmtCallbacks.errorCallback(error);
};
_sendStreamRequest(streamState, request, callbacks) {
if (streamState.closed !== undefined) {
errorCallback(new ClosedError("Stream was closed", streamState.closed));
callbacks.errorCallback(new ClosedError("Stream is closed", streamState.closed));
return;
}
this._sendRequest(request, callbacks);
}
/** Cache a SQL text on the server. This requires protocol version 2 or higher. */
storeSql(sql) {
this._ensureVersion(2, "storeSql()");
const sqlId = this.#sqlIdAlloc.alloc();
const sqlState = {
sqlId,
closed: undefined,
};
const responseCallback = () => undefined;
const errorCallback = (e) => this._closeSql(sqlState, e);
const request = {
"type": "execute",
"stream_id": streamState.streamId,
"stmt": stmtCallbacks.stmt,
"type": "store_sql",
"sql_id": sqlId,
"sql": sql,
};
this.#sendRequest(request, { responseCallback, errorCallback });
this._sendRequest(request, { responseCallback, errorCallback });
return new Sql(this, sqlState);
}
// Execute a batch on a stream and invoke callbacks in `batchCallbacks` when we get the results (or an
// error).
// Make sure that the SQL text is closed.
/** @private */
_batch(streamState, batchCallbacks) {
const responseCallback = (response) => {
const result = response["result"];
for (const callback of batchCallbacks.resultCallbacks) {
callback(result);
}
batchCallbacks.doneCallback();
};
const errorCallback = (error) => {
batchCallbacks.errorCallback(error);
};
if (streamState.closed !== undefined) {
errorCallback(new ClosedError("Stream was closed", streamState.closed));
_closeSql(sqlState, error) {
if (sqlState.closed !== undefined || this.#closed !== undefined) {
return;
}
sqlState.closed = error;
const callback = () => {
this.#sqlIdAlloc.free(sqlState.sqlId);
};
const request = {
"type": "batch",
"stream_id": streamState.streamId,
"batch": batchCallbacks.batch,
"type": "close_sql",
"sql_id": sqlState.sqlId,
};
this.#sendRequest(request, { responseCallback, errorCallback });
this._sendRequest(request, { responseCallback: callback, errorCallback: callback });
}

@@ -248,0 +307,0 @@ /** Close the client and the WebSocket. */

@@ -40,1 +40,6 @@ import type * as proto from "./proto.js";

}
/** Error thrown when the protocol version is too low to support a feature. */
export declare class ProtocolVersionError extends ClientError {
/** @private */
constructor(message: string);
}

@@ -63,1 +63,9 @@ /** Generic error produced by the Hrana client. */

}
/** Error thrown when the protocol version is too low to support a feature. */
export class ProtocolVersionError extends ClientError {
/** @private */
constructor(message) {
super(message);
this.name = "ProtocolVersionError";
}
}
/// <reference types="node" />
import { Client } from "./client.js";
import type * as proto from "./proto.js";
export type { ProtocolVersion } from "./client.js";
export { Client } from "./client.js";

@@ -12,2 +13,4 @@ export * from "./errors.js";

export type { StmtResult, RowsResult, RowResult, ValueResult, Row } from "./result.js";
export type { InSql } from "./sql.js";
export { Sql } from "./sql.js";
export type { InStmt, InStmtArgs } from "./stmt.js";

@@ -14,0 +17,0 @@ export { Stmt } from "./stmt.js";

import { WebSocket } from "@libsql/isomorphic-ws";
import { Client } from "./client.js";
import { Client, protocolVersions } from "./client.js";
import { WebSocketUnsupportedError } from "./errors.js";

@@ -10,2 +10,3 @@ export { Client } from "./client.js";

export * as raw from "./raw.js";
export { Sql } from "./sql.js";
export { Stmt } from "./stmt.js";

@@ -18,4 +19,4 @@ export { Stream } from "./stream.js";

}
const socket = new WebSocket(url, ["hrana1"]);
const socket = new WebSocket(url, Array.from(protocolVersions.keys()));
return new Client(socket, jwt ?? null);
}

@@ -34,4 +34,4 @@ export type int32 = number;

};
export type Request = OpenStreamReq | CloseStreamReq | ExecuteReq | BatchReq;
export type Response = OpenStreamResp | CloseStreamResp | ExecuteResp | BatchResp;
export type Request = OpenStreamReq | CloseStreamReq | ExecuteReq | BatchReq | DescribeReq | SequenceReq | StoreSqlReq | CloseSqlReq;
export type Response = OpenStreamResp | CloseStreamResp | ExecuteResp | BatchResp | DescribeResp | SequenceResp | StoreSqlResp | CloseSqlResp;
export type OpenStreamReq = {

@@ -61,3 +61,4 @@ "type": "open_stream";

export type Stmt = {
"sql": string;
"sql"?: string | undefined;
"sql_id"?: int32 | undefined;
"args"?: Array<Value>;

@@ -79,2 +80,3 @@ "named_args"?: Array<NamedArg>;

"name": string | null;
"decltype"?: string | null;
};

@@ -117,2 +119,49 @@ export type BatchReq = {

};
export type DescribeReq = {
"type": "describe";
"stream_id": int32;
"sql"?: string | undefined;
"sql_id"?: int32 | undefined;
};
export type DescribeResp = {
"type": "describe";
"result": DescribeResult;
};
export type DescribeResult = {
"params": Array<DescribeParam>;
"cols": Array<DescribeCol>;
"is_explain": boolean;
"is_readonly": boolean;
};
export type DescribeParam = {
"name": string | null;
};
export type DescribeCol = {
"name": string;
"decltype": string | null;
};
export type SequenceReq = {
"type": "sequence";
"stream_id": int32;
"sql"?: string | null;
"sql_id"?: int32 | null;
};
export type SequenceResp = {
"type": "sequence";
};
export type StoreSqlReq = {
"type": "store_sql";
"sql_id": int32;
"sql": string;
};
export type StoreSqlResp = {
"type": "store_sql";
};
export type CloseSqlReq = {
"type": "close_sql";
"sql_id": int32;
};
export type CloseSqlResp = {
"type": "close_sql";
};
export type Value = {

@@ -119,0 +168,0 @@ "type": "null";

@@ -0,3 +1,4 @@

export { describeResultFromProto } from "./describe.js";
export { stmtResultFromProto, rowsResultFromProto, rowResultFromProto, valueResultFromProto, errorFromProto, } from "./result.js";
export { stmtToProto } from "./stmt.js";
export { valueToProto, valueFromProto } from "./value.js";

@@ -0,3 +1,4 @@

export { describeResultFromProto } from "./describe.js";
export { stmtResultFromProto, rowsResultFromProto, rowResultFromProto, valueResultFromProto, errorFromProto, } from "./result.js";
export { stmtToProto } from "./stmt.js";
export { valueToProto, valueFromProto } from "./value.js";

@@ -14,2 +14,4 @@ import { ResponseError } from "./errors.js";

columnNames: Array<string | undefined>;
/** Declared types of columns in the result. */
columnDecltypes: Array<string | undefined>;
}

@@ -16,0 +18,0 @@ /** An array of rows returned by a database statement. */

@@ -7,3 +7,4 @@ import { ResponseError } from "./errors.js";

lastInsertRowid: result["last_insert_rowid"] ?? undefined,
columnNames: result["cols"].map(col => col.name ?? undefined),
columnNames: result["cols"].map(col => col["name"] ?? undefined),
columnDecltypes: result["cols"].map(col => col["decltype"] ?? undefined),
};

@@ -10,0 +11,0 @@ }

import type * as proto from "./proto.js";
import type { InSql } from "./sql.js";
import type { InValue } from "./value.js";
/** A statement that you can send to the database. Statements are represented by the {@link Stmt} class, but
* as a shorthand, you can specify an SQL string without arguments, or a tuple with the SQL string and
* positional or named arguments.
* as a shorthand, you can specify an SQL text without arguments, or a tuple with the SQL text and positional
* or named arguments.
*/
export type InStmt = Stmt | string | [string, InStmtArgs];
export type InStmt = Stmt | InSql | [InSql, InStmtArgs];
/** Arguments for a statement. Either an array that is bound to parameters by position, or an object with

@@ -14,4 +15,4 @@ * values that are bound to parameters by name. */

export declare class Stmt {
/** The SQL statement string. */
readonly sql: string;
/** The SQL statement text. */
sql: InSql;
/** @private */

@@ -22,3 +23,3 @@ _args: Array<proto.Value>;

/** Initialize the statement with given SQL text. */
constructor(sql: string);
constructor(sql: InSql);
/** Binds positional parameters from the given `values`. All previous positional bindings are cleared. */

@@ -25,0 +26,0 @@ bindIndexes(values: Iterable<InValue>): this;

@@ -0,1 +1,2 @@

import { sqlToProto } from "./sql.js";
import { valueToProto, protoNull } from "./value.js";

@@ -5,3 +6,3 @@ /** A statement that can be evaluated by the database. Besides the SQL text, it also contains the positional

export class Stmt {
/** The SQL statement string. */
/** The SQL statement text. */
sql;

@@ -50,7 +51,7 @@ /** @private */

export function stmtToProto(stmt, wantRows) {
let sql;
let inSql;
let args = [];
let namedArgs = [];
if (stmt instanceof Stmt) {
sql = stmt.sql;
inSql = stmt.sql;
args = stmt._args;

@@ -62,3 +63,3 @@ for (const [name, value] of stmt._namedArgs.entries()) {

else if (Array.isArray(stmt)) {
sql = stmt[0];
inSql = stmt[0];
if (Array.isArray(stmt[1])) {

@@ -75,5 +76,12 @@ args = stmt[1].map(valueToProto);

else {
sql = "" + stmt;
inSql = stmt;
}
return { "sql": sql, "args": args, "named_args": namedArgs, "want_rows": wantRows };
const { sql, sqlId } = sqlToProto(inSql);
return {
"sql": sql,
"sql_id": sqlId,
"args": args,
"named_args": namedArgs,
"want_rows": wantRows,
};
}
import type { Client, StreamState } from "./client.js";
import type { DescribeResult } from "./describe.js";
import { Batch } from "./batch.js";
import type { RowsResult, RowResult, ValueResult, StmtResult } from "./result.js";
import type { InSql } from "./sql.js";
import type { InStmt } from "./stmt.js";

@@ -20,2 +22,7 @@ /** A stream for executing SQL statements (a "database connection"). */

batch(): Batch;
/** Parse and analyze a statement. This requires protocol version 2 or higher. */
describe(inSql: InSql): Promise<DescribeResult>;
/** Execute a sequence of statements separated by semicolons. This requires protocol version 2 or higher.
* */
sequence(inSql: InSql): Promise<void>;
/** Close the stream. */

@@ -22,0 +29,0 @@ close(): void;

@@ -0,4 +1,6 @@

import { Batch } from "./batch.js";
import { describeResultFromProto } from "./describe.js";
import { ClientError } from "./errors.js";
import { Batch } from "./batch.js";
import { stmtResultFromProto, rowsResultFromProto, rowResultFromProto, valueResultFromProto, } from "./result.js";
import { sqlToProto } from "./sql.js";
import { stmtToProto } from "./stmt.js";

@@ -32,9 +34,12 @@ /** A stream for executing SQL statements (a "database connection"). */

return new Promise((doneCallback, errorCallback) => {
this.#client._execute(this.#state, {
stmt,
resultCallback(result) {
doneCallback(fromProto(result));
},
errorCallback,
});
const request = {
"type": "execute",
"stream_id": this.#state.streamId,
"stmt": stmt,
};
const responseCallback = (response) => {
const result = response["result"];
doneCallback(fromProto(result));
};
this.#client._sendStreamRequest(this.#state, request, { responseCallback, errorCallback });
});

@@ -46,2 +51,38 @@ }

}
/** Parse and analyze a statement. This requires protocol version 2 or higher. */
describe(inSql) {
this.#client._ensureVersion(2, "describe()");
const { sql, sqlId } = sqlToProto(inSql);
return new Promise((doneCallback, errorCallback) => {
const request = {
"type": "describe",
"stream_id": this.#state.streamId,
"sql": sql,
"sql_id": sqlId,
};
const responseCallback = (response) => {
const result = response["result"];
doneCallback(describeResultFromProto(result));
};
this.#client._sendStreamRequest(this.#state, request, { responseCallback, errorCallback });
});
}
/** Execute a sequence of statements separated by semicolons. This requires protocol version 2 or higher.
* */
sequence(inSql) {
this.#client._ensureVersion(2, "sequence()");
const { sql, sqlId } = sqlToProto(inSql);
return new Promise((doneCallback, errorCallback) => {
const request = {
"type": "sequence",
"stream_id": this.#state.streamId,
"sql": sql,
"sql_id": sqlId,
};
const responseCallback = (_response) => {
doneCallback();
};
this.#client._sendStreamRequest(this.#state, request, { responseCallback, errorCallback });
});
}
/** Close the stream. */

@@ -48,0 +89,0 @@ close() {

{
"name": "@libsql/hrana-client",
"version": "0.3.9",
"version": "0.3.10",
"keywords": [

@@ -5,0 +5,0 @@ "hrana",

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