Initial commit: New MoreminiMore website with fresh design
This commit is contained in:
48
node_modules/@libsql/hrana-client/lib-esm/ws/client.d.ts
generated
vendored
Normal file
48
node_modules/@libsql/hrana-client/lib-esm/ws/client.d.ts
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/// <reference types="ws" />
|
||||
import { WebSocket } from "@libsql/isomorphic-ws";
|
||||
import type { ProtocolVersion, ProtocolEncoding } from "../client.js";
|
||||
import { Client } from "../client.js";
|
||||
import { IdAlloc } from "../id_alloc.js";
|
||||
import { Sql, SqlOwner } from "../sql.js";
|
||||
import type * as proto from "./proto.js";
|
||||
import { WsStream } from "./stream.js";
|
||||
export type Subprotocol = {
|
||||
version: ProtocolVersion;
|
||||
encoding: ProtocolEncoding;
|
||||
};
|
||||
export declare const subprotocolsV2: Map<string, Subprotocol>;
|
||||
export declare const subprotocolsV3: Map<string, Subprotocol>;
|
||||
/** A client for the Hrana protocol over a WebSocket. */
|
||||
export declare class WsClient extends Client implements SqlOwner {
|
||||
#private;
|
||||
/** @private */
|
||||
_streamIdAlloc: IdAlloc;
|
||||
/** @private */
|
||||
_cursorIdAlloc: IdAlloc;
|
||||
/** @private */
|
||||
constructor(socket: WebSocket, jwt: string | undefined);
|
||||
/** 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 WsStream}, a stream for executing SQL statements. */
|
||||
openStream(): WsStream;
|
||||
/** Cache a SQL text on the server. This requires protocol version 2 or higher. */
|
||||
storeSql(sql: string): Sql;
|
||||
/** @private */
|
||||
_closeSql(sqlId: number): void;
|
||||
/** Close the client and the WebSocket. */
|
||||
close(): void;
|
||||
/** True if the client is closed. */
|
||||
get closed(): boolean;
|
||||
}
|
||||
export interface OpenCallbacks {
|
||||
openCallback: () => void;
|
||||
errorCallback: (_: Error) => void;
|
||||
}
|
||||
export interface ResponseCallbacks {
|
||||
responseCallback: (_: proto.Response) => void;
|
||||
errorCallback: (_: Error) => void;
|
||||
}
|
||||
318
node_modules/@libsql/hrana-client/lib-esm/ws/client.js
generated
vendored
Normal file
318
node_modules/@libsql/hrana-client/lib-esm/ws/client.js
generated
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
import { Client } from "../client.js";
|
||||
import { readJsonObject, writeJsonObject, readProtobufMessage, writeProtobufMessage, } from "../encoding/index.js";
|
||||
import { ClientError, ProtoError, ClosedError, WebSocketError, ProtocolVersionError, InternalError, } from "../errors.js";
|
||||
import { IdAlloc } from "../id_alloc.js";
|
||||
import { errorFromProto } from "../result.js";
|
||||
import { Sql } from "../sql.js";
|
||||
import { impossible } from "../util.js";
|
||||
import { WsStream } from "./stream.js";
|
||||
import { ClientMsg as json_ClientMsg } from "./json_encode.js";
|
||||
import { ClientMsg as protobuf_ClientMsg } from "./protobuf_encode.js";
|
||||
import { ServerMsg as json_ServerMsg } from "./json_decode.js";
|
||||
import { ServerMsg as protobuf_ServerMsg } from "./protobuf_decode.js";
|
||||
export const subprotocolsV2 = new Map([
|
||||
["hrana2", { version: 2, encoding: "json" }],
|
||||
["hrana1", { version: 1, encoding: "json" }],
|
||||
]);
|
||||
export const subprotocolsV3 = new Map([
|
||||
["hrana3-protobuf", { version: 3, encoding: "protobuf" }],
|
||||
["hrana3", { version: 3, encoding: "json" }],
|
||||
["hrana2", { version: 2, encoding: "json" }],
|
||||
["hrana1", { version: 1, encoding: "json" }],
|
||||
]);
|
||||
/** A client for the Hrana protocol over a WebSocket. */
|
||||
export class WsClient extends Client {
|
||||
#socket;
|
||||
// List of callbacks that we queue until the socket transitions from the CONNECTING to the OPEN state.
|
||||
#openCallbacks;
|
||||
// Have we already transitioned from CONNECTING to OPEN and fired the callbacks in #openCallbacks?
|
||||
#opened;
|
||||
// Stores the error that caused us to close the client (and the socket). If we are not closed, this is
|
||||
// `undefined`.
|
||||
#closed;
|
||||
// Have we received a response to our "hello" from the server?
|
||||
#recvdHello;
|
||||
// Subprotocol negotiated with the server. It is only available after the socket transitions to the OPEN
|
||||
// state.
|
||||
#subprotocol;
|
||||
// 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.
|
||||
#responseMap;
|
||||
// An allocator of request ids.
|
||||
#requestIdAlloc;
|
||||
// An allocator of stream ids.
|
||||
/** @private */
|
||||
_streamIdAlloc;
|
||||
// An allocator of cursor ids.
|
||||
/** @private */
|
||||
_cursorIdAlloc;
|
||||
// An allocator of SQL text ids.
|
||||
#sqlIdAlloc;
|
||||
/** @private */
|
||||
constructor(socket, jwt) {
|
||||
super();
|
||||
this.#socket = socket;
|
||||
this.#openCallbacks = [];
|
||||
this.#opened = false;
|
||||
this.#closed = undefined;
|
||||
this.#recvdHello = false;
|
||||
this.#subprotocol = undefined;
|
||||
this.#getVersionCalled = false;
|
||||
this.#responseMap = new Map();
|
||||
this.#requestIdAlloc = new IdAlloc();
|
||||
this._streamIdAlloc = new IdAlloc();
|
||||
this._cursorIdAlloc = new IdAlloc();
|
||||
this.#sqlIdAlloc = new IdAlloc();
|
||||
this.#socket.binaryType = "arraybuffer";
|
||||
this.#socket.addEventListener("open", () => this.#onSocketOpen());
|
||||
this.#socket.addEventListener("close", (event) => this.#onSocketClose(event));
|
||||
this.#socket.addEventListener("error", (event) => this.#onSocketError(event));
|
||||
this.#socket.addEventListener("message", (event) => this.#onSocketMessage(event));
|
||||
this.#send({ type: "hello", jwt });
|
||||
}
|
||||
// Send (or enqueue to send) a message to the server.
|
||||
#send(msg) {
|
||||
if (this.#closed !== undefined) {
|
||||
throw new InternalError("Trying to send a message on a closed client");
|
||||
}
|
||||
if (this.#opened) {
|
||||
this.#sendToSocket(msg);
|
||||
}
|
||||
else {
|
||||
const openCallback = () => this.#sendToSocket(msg);
|
||||
const errorCallback = () => undefined;
|
||||
this.#openCallbacks.push({ openCallback, errorCallback });
|
||||
}
|
||||
}
|
||||
// The socket transitioned from CONNECTING to OPEN
|
||||
#onSocketOpen() {
|
||||
const protocol = this.#socket.protocol;
|
||||
if (protocol === undefined) {
|
||||
this.#setClosed(new ClientError("The `WebSocket.protocol` property is undefined. This most likely means that the WebSocket " +
|
||||
"implementation provided by the environment is broken. If you are using Miniflare 2, " +
|
||||
"please update to Miniflare 3, which fixes this problem."));
|
||||
return;
|
||||
}
|
||||
else if (protocol === "") {
|
||||
this.#subprotocol = { version: 1, encoding: "json" };
|
||||
}
|
||||
else {
|
||||
this.#subprotocol = subprotocolsV3.get(protocol);
|
||||
if (this.#subprotocol === undefined) {
|
||||
this.#setClosed(new ProtoError(`Unrecognized WebSocket subprotocol: ${JSON.stringify(protocol)}`));
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (const callbacks of this.#openCallbacks) {
|
||||
callbacks.openCallback();
|
||||
}
|
||||
this.#openCallbacks.length = 0;
|
||||
this.#opened = true;
|
||||
}
|
||||
#sendToSocket(msg) {
|
||||
const encoding = this.#subprotocol.encoding;
|
||||
if (encoding === "json") {
|
||||
const jsonMsg = writeJsonObject(msg, json_ClientMsg);
|
||||
this.#socket.send(jsonMsg);
|
||||
}
|
||||
else if (encoding === "protobuf") {
|
||||
const protobufMsg = writeProtobufMessage(msg, protobuf_ClientMsg);
|
||||
this.#socket.send(protobufMsg);
|
||||
}
|
||||
else {
|
||||
throw impossible(encoding, "Impossible encoding");
|
||||
}
|
||||
}
|
||||
/** 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.#opened) {
|
||||
const openCallback = () => versionCallback(this.#subprotocol.version);
|
||||
this.#openCallbacks.push({ openCallback, errorCallback });
|
||||
}
|
||||
else {
|
||||
versionCallback(this.#subprotocol.version);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Make sure that the negotiated version is at least `minVersion`.
|
||||
/** @private */
|
||||
_ensureVersion(minVersion, feature) {
|
||||
if (this.#subprotocol === undefined || !this.#getVersionCalled) {
|
||||
throw new ProtocolVersionError(`${feature} is supported only on protocol version ${minVersion} and higher, ` +
|
||||
"but the version supported by the WebSocket server is not yet known. " +
|
||||
"Use Client.getVersion() to wait until the version is available.");
|
||||
}
|
||||
else if (this.#subprotocol.version < minVersion) {
|
||||
throw new ProtocolVersionError(`${feature} is supported on protocol version ${minVersion} and higher, ` +
|
||||
`but the WebSocket server only supports version ${this.#subprotocol.version}`);
|
||||
}
|
||||
}
|
||||
// Send a request to the server and invoke a callback when we get the response.
|
||||
/** @private */
|
||||
_sendRequest(request, callbacks) {
|
||||
if (this.#closed !== undefined) {
|
||||
callbacks.errorCallback(new ClosedError("Client is closed", this.#closed));
|
||||
return;
|
||||
}
|
||||
const requestId = this.#requestIdAlloc.alloc();
|
||||
this.#responseMap.set(requestId, { ...callbacks, type: request.type });
|
||||
this.#send({ type: "request", requestId, request });
|
||||
}
|
||||
// The socket encountered an error.
|
||||
#onSocketError(event) {
|
||||
const eventMessage = event.message;
|
||||
const message = eventMessage ?? "WebSocket was closed due to an error";
|
||||
this.#setClosed(new WebSocketError(message));
|
||||
}
|
||||
// The socket was closed.
|
||||
#onSocketClose(event) {
|
||||
let message = `WebSocket was closed with code ${event.code}`;
|
||||
if (event.reason) {
|
||||
message += `: ${event.reason}`;
|
||||
}
|
||||
this.#setClosed(new WebSocketError(message));
|
||||
}
|
||||
// Close the client with the given error.
|
||||
#setClosed(error) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
this.#closed = error;
|
||||
for (const callbacks of this.#openCallbacks) {
|
||||
callbacks.errorCallback(error);
|
||||
}
|
||||
this.#openCallbacks.length = 0;
|
||||
for (const [requestId, responseState] of this.#responseMap.entries()) {
|
||||
responseState.errorCallback(error);
|
||||
this.#requestIdAlloc.free(requestId);
|
||||
}
|
||||
this.#responseMap.clear();
|
||||
this.#socket.close();
|
||||
}
|
||||
// We received a message from the socket.
|
||||
#onSocketMessage(event) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let msg;
|
||||
const encoding = this.#subprotocol.encoding;
|
||||
if (encoding === "json") {
|
||||
if (typeof event.data !== "string") {
|
||||
this.#socket.close(3003, "Only text messages are accepted with JSON encoding");
|
||||
this.#setClosed(new ProtoError("Received non-text message from server with JSON encoding"));
|
||||
return;
|
||||
}
|
||||
msg = readJsonObject(JSON.parse(event.data), json_ServerMsg);
|
||||
}
|
||||
else if (encoding === "protobuf") {
|
||||
if (!(event.data instanceof ArrayBuffer)) {
|
||||
this.#socket.close(3003, "Only binary messages are accepted with Protobuf encoding");
|
||||
this.#setClosed(new ProtoError("Received non-binary message from server with Protobuf encoding"));
|
||||
return;
|
||||
}
|
||||
msg = readProtobufMessage(new Uint8Array(event.data), protobuf_ServerMsg);
|
||||
}
|
||||
else {
|
||||
throw impossible(encoding, "Impossible encoding");
|
||||
}
|
||||
this.#handleMsg(msg);
|
||||
}
|
||||
catch (e) {
|
||||
this.#socket.close(3007, "Could not handle message");
|
||||
this.#setClosed(e);
|
||||
}
|
||||
}
|
||||
// Handle a message from the server.
|
||||
#handleMsg(msg) {
|
||||
if (msg.type === "none") {
|
||||
throw new ProtoError("Received an unrecognized ServerMsg");
|
||||
}
|
||||
else if (msg.type === "hello_ok" || msg.type === "hello_error") {
|
||||
if (this.#recvdHello) {
|
||||
throw new ProtoError("Received a duplicated hello response");
|
||||
}
|
||||
this.#recvdHello = true;
|
||||
if (msg.type === "hello_error") {
|
||||
throw errorFromProto(msg.error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (!this.#recvdHello) {
|
||||
throw new ProtoError("Received a non-hello message before a hello response");
|
||||
}
|
||||
if (msg.type === "response_ok") {
|
||||
const requestId = msg.requestId;
|
||||
const responseState = this.#responseMap.get(requestId);
|
||||
this.#responseMap.delete(requestId);
|
||||
if (responseState === undefined) {
|
||||
throw new ProtoError("Received unexpected OK response");
|
||||
}
|
||||
this.#requestIdAlloc.free(requestId);
|
||||
try {
|
||||
if (responseState.type !== msg.response.type) {
|
||||
console.dir({ responseState, msg });
|
||||
throw new ProtoError("Received unexpected type of response");
|
||||
}
|
||||
responseState.responseCallback(msg.response);
|
||||
}
|
||||
catch (e) {
|
||||
responseState.errorCallback(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else if (msg.type === "response_error") {
|
||||
const requestId = msg.requestId;
|
||||
const responseState = this.#responseMap.get(requestId);
|
||||
this.#responseMap.delete(requestId);
|
||||
if (responseState === undefined) {
|
||||
throw new ProtoError("Received unexpected error response");
|
||||
}
|
||||
this.#requestIdAlloc.free(requestId);
|
||||
responseState.errorCallback(errorFromProto(msg.error));
|
||||
}
|
||||
else {
|
||||
throw impossible(msg, "Impossible ServerMsg type");
|
||||
}
|
||||
}
|
||||
/** Open a {@link WsStream}, a stream for executing SQL statements. */
|
||||
openStream() {
|
||||
return WsStream.open(this);
|
||||
}
|
||||
/** 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 sqlObj = new Sql(this, sqlId);
|
||||
const responseCallback = () => undefined;
|
||||
const errorCallback = (e) => sqlObj._setClosed(e);
|
||||
const request = { type: "store_sql", sqlId, sql };
|
||||
this._sendRequest(request, { responseCallback, errorCallback });
|
||||
return sqlObj;
|
||||
}
|
||||
/** @private */
|
||||
_closeSql(sqlId) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
const responseCallback = () => this.#sqlIdAlloc.free(sqlId);
|
||||
const errorCallback = (e) => this.#setClosed(e);
|
||||
const request = { type: "close_sql", sqlId };
|
||||
this._sendRequest(request, { responseCallback, errorCallback });
|
||||
}
|
||||
/** Close the client and the WebSocket. */
|
||||
close() {
|
||||
this.#setClosed(new ClientError("Client was manually closed"));
|
||||
}
|
||||
/** True if the client is closed. */
|
||||
get closed() {
|
||||
return this.#closed !== undefined;
|
||||
}
|
||||
}
|
||||
17
node_modules/@libsql/hrana-client/lib-esm/ws/cursor.d.ts
generated
vendored
Normal file
17
node_modules/@libsql/hrana-client/lib-esm/ws/cursor.d.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Cursor } from "../cursor.js";
|
||||
import type { WsClient } from "./client.js";
|
||||
import type * as proto from "./proto.js";
|
||||
import type { WsStream } from "./stream.js";
|
||||
export declare class WsCursor extends Cursor {
|
||||
#private;
|
||||
/** @private */
|
||||
constructor(client: WsClient, stream: WsStream, cursorId: number);
|
||||
/** Fetch the next entry from the cursor. */
|
||||
next(): Promise<proto.CursorEntry | undefined>;
|
||||
/** @private */
|
||||
_setClosed(error: Error): void;
|
||||
/** Close the cursor. */
|
||||
close(): void;
|
||||
/** True if the cursor is closed. */
|
||||
get closed(): boolean;
|
||||
}
|
||||
80
node_modules/@libsql/hrana-client/lib-esm/ws/cursor.js
generated
vendored
Normal file
80
node_modules/@libsql/hrana-client/lib-esm/ws/cursor.js
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
import { ClientError, ClosedError } from "../errors.js";
|
||||
import { Cursor } from "../cursor.js";
|
||||
import { Queue } from "../queue.js";
|
||||
const fetchChunkSize = 1000;
|
||||
const fetchQueueSize = 10;
|
||||
export class WsCursor extends Cursor {
|
||||
#client;
|
||||
#stream;
|
||||
#cursorId;
|
||||
#entryQueue;
|
||||
#fetchQueue;
|
||||
#closed;
|
||||
#done;
|
||||
/** @private */
|
||||
constructor(client, stream, cursorId) {
|
||||
super();
|
||||
this.#client = client;
|
||||
this.#stream = stream;
|
||||
this.#cursorId = cursorId;
|
||||
this.#entryQueue = new Queue();
|
||||
this.#fetchQueue = new Queue();
|
||||
this.#closed = undefined;
|
||||
this.#done = false;
|
||||
}
|
||||
/** Fetch the next entry from the cursor. */
|
||||
async next() {
|
||||
for (;;) {
|
||||
if (this.#closed !== undefined) {
|
||||
throw new ClosedError("Cursor is closed", this.#closed);
|
||||
}
|
||||
while (!this.#done && this.#fetchQueue.length < fetchQueueSize) {
|
||||
this.#fetchQueue.push(this.#fetch());
|
||||
}
|
||||
const entry = this.#entryQueue.shift();
|
||||
if (this.#done || entry !== undefined) {
|
||||
return entry;
|
||||
}
|
||||
// we assume that `Cursor.next()` is never called concurrently
|
||||
await this.#fetchQueue.shift().then((response) => {
|
||||
if (response === undefined) {
|
||||
return;
|
||||
}
|
||||
for (const entry of response.entries) {
|
||||
this.#entryQueue.push(entry);
|
||||
}
|
||||
this.#done ||= response.done;
|
||||
});
|
||||
}
|
||||
}
|
||||
#fetch() {
|
||||
return this.#stream._sendCursorRequest(this, {
|
||||
type: "fetch_cursor",
|
||||
cursorId: this.#cursorId,
|
||||
maxCount: fetchChunkSize,
|
||||
}).then((resp) => resp, (error) => {
|
||||
this._setClosed(error);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_setClosed(error) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
this.#closed = error;
|
||||
this.#stream._sendCursorRequest(this, {
|
||||
type: "close_cursor",
|
||||
cursorId: this.#cursorId,
|
||||
}).catch(() => undefined);
|
||||
this.#stream._cursorClosed(this);
|
||||
}
|
||||
/** Close the cursor. */
|
||||
close() {
|
||||
this._setClosed(new ClientError("Cursor was manually closed"));
|
||||
}
|
||||
/** True if the cursor is closed. */
|
||||
get closed() {
|
||||
return this.#closed !== undefined;
|
||||
}
|
||||
}
|
||||
3
node_modules/@libsql/hrana-client/lib-esm/ws/json_decode.d.ts
generated
vendored
Normal file
3
node_modules/@libsql/hrana-client/lib-esm/ws/json_decode.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import * as d from "../encoding/json/decode.js";
|
||||
import * as proto from "./proto.js";
|
||||
export declare function ServerMsg(obj: d.Obj): proto.ServerMsg;
|
||||
74
node_modules/@libsql/hrana-client/lib-esm/ws/json_decode.js
generated
vendored
Normal file
74
node_modules/@libsql/hrana-client/lib-esm/ws/json_decode.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import { ProtoError } from "../errors.js";
|
||||
import * as d from "../encoding/json/decode.js";
|
||||
import { Error, StmtResult, BatchResult, CursorEntry, DescribeResult } from "../shared/json_decode.js";
|
||||
export function ServerMsg(obj) {
|
||||
const type = d.string(obj["type"]);
|
||||
if (type === "hello_ok") {
|
||||
return { type: "hello_ok" };
|
||||
}
|
||||
else if (type === "hello_error") {
|
||||
const error = Error(d.object(obj["error"]));
|
||||
return { type: "hello_error", error };
|
||||
}
|
||||
else if (type === "response_ok") {
|
||||
const requestId = d.number(obj["request_id"]);
|
||||
const response = Response(d.object(obj["response"]));
|
||||
return { type: "response_ok", requestId, response };
|
||||
}
|
||||
else if (type === "response_error") {
|
||||
const requestId = d.number(obj["request_id"]);
|
||||
const error = Error(d.object(obj["error"]));
|
||||
return { type: "response_error", requestId, error };
|
||||
}
|
||||
else {
|
||||
throw new ProtoError("Unexpected type of ServerMsg");
|
||||
}
|
||||
}
|
||||
function Response(obj) {
|
||||
const type = d.string(obj["type"]);
|
||||
if (type === "open_stream") {
|
||||
return { type: "open_stream" };
|
||||
}
|
||||
else if (type === "close_stream") {
|
||||
return { type: "close_stream" };
|
||||
}
|
||||
else if (type === "execute") {
|
||||
const result = StmtResult(d.object(obj["result"]));
|
||||
return { type: "execute", result };
|
||||
}
|
||||
else if (type === "batch") {
|
||||
const result = BatchResult(d.object(obj["result"]));
|
||||
return { type: "batch", result };
|
||||
}
|
||||
else if (type === "open_cursor") {
|
||||
return { type: "open_cursor" };
|
||||
}
|
||||
else if (type === "close_cursor") {
|
||||
return { type: "close_cursor" };
|
||||
}
|
||||
else if (type === "fetch_cursor") {
|
||||
const entries = d.arrayObjectsMap(obj["entries"], CursorEntry);
|
||||
const done = d.boolean(obj["done"]);
|
||||
return { type: "fetch_cursor", entries, done };
|
||||
}
|
||||
else if (type === "sequence") {
|
||||
return { type: "sequence" };
|
||||
}
|
||||
else if (type === "describe") {
|
||||
const result = DescribeResult(d.object(obj["result"]));
|
||||
return { type: "describe", result };
|
||||
}
|
||||
else if (type === "store_sql") {
|
||||
return { type: "store_sql" };
|
||||
}
|
||||
else if (type === "close_sql") {
|
||||
return { type: "close_sql" };
|
||||
}
|
||||
else if (type === "get_autocommit") {
|
||||
const isAutocommit = d.boolean(obj["is_autocommit"]);
|
||||
return { type: "get_autocommit", isAutocommit };
|
||||
}
|
||||
else {
|
||||
throw new ProtoError("Unexpected type of Response");
|
||||
}
|
||||
}
|
||||
3
node_modules/@libsql/hrana-client/lib-esm/ws/json_encode.d.ts
generated
vendored
Normal file
3
node_modules/@libsql/hrana-client/lib-esm/ws/json_encode.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import * as e from "../encoding/json/encode.js";
|
||||
import * as proto from "./proto.js";
|
||||
export declare function ClientMsg(w: e.ObjectWriter, msg: proto.ClientMsg): void;
|
||||
77
node_modules/@libsql/hrana-client/lib-esm/ws/json_encode.js
generated
vendored
Normal file
77
node_modules/@libsql/hrana-client/lib-esm/ws/json_encode.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Stmt, Batch } from "../shared/json_encode.js";
|
||||
import { impossible } from "../util.js";
|
||||
export function ClientMsg(w, msg) {
|
||||
w.stringRaw("type", msg.type);
|
||||
if (msg.type === "hello") {
|
||||
if (msg.jwt !== undefined) {
|
||||
w.string("jwt", msg.jwt);
|
||||
}
|
||||
}
|
||||
else if (msg.type === "request") {
|
||||
w.number("request_id", msg.requestId);
|
||||
w.object("request", msg.request, Request);
|
||||
}
|
||||
else {
|
||||
throw impossible(msg, "Impossible type of ClientMsg");
|
||||
}
|
||||
}
|
||||
function Request(w, msg) {
|
||||
w.stringRaw("type", msg.type);
|
||||
if (msg.type === "open_stream") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
}
|
||||
else if (msg.type === "close_stream") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
}
|
||||
else if (msg.type === "execute") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
w.object("stmt", msg.stmt, Stmt);
|
||||
}
|
||||
else if (msg.type === "batch") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
w.object("batch", msg.batch, Batch);
|
||||
}
|
||||
else if (msg.type === "open_cursor") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
w.number("cursor_id", msg.cursorId);
|
||||
w.object("batch", msg.batch, Batch);
|
||||
}
|
||||
else if (msg.type === "close_cursor") {
|
||||
w.number("cursor_id", msg.cursorId);
|
||||
}
|
||||
else if (msg.type === "fetch_cursor") {
|
||||
w.number("cursor_id", msg.cursorId);
|
||||
w.number("max_count", msg.maxCount);
|
||||
}
|
||||
else if (msg.type === "sequence") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
if (msg.sql !== undefined) {
|
||||
w.string("sql", msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.number("sql_id", msg.sqlId);
|
||||
}
|
||||
}
|
||||
else if (msg.type === "describe") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
if (msg.sql !== undefined) {
|
||||
w.string("sql", msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.number("sql_id", msg.sqlId);
|
||||
}
|
||||
}
|
||||
else if (msg.type === "store_sql") {
|
||||
w.number("sql_id", msg.sqlId);
|
||||
w.string("sql", msg.sql);
|
||||
}
|
||||
else if (msg.type === "close_sql") {
|
||||
w.number("sql_id", msg.sqlId);
|
||||
}
|
||||
else if (msg.type === "get_autocommit") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
}
|
||||
else {
|
||||
throw impossible(msg, "Impossible type of Request");
|
||||
}
|
||||
}
|
||||
136
node_modules/@libsql/hrana-client/lib-esm/ws/proto.d.ts
generated
vendored
Normal file
136
node_modules/@libsql/hrana-client/lib-esm/ws/proto.d.ts
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
export * from "../shared/proto.js";
|
||||
import { int32, uint32, Error, Stmt, StmtResult, Batch, BatchResult, CursorEntry, DescribeResult } from "../shared/proto.js";
|
||||
export type ClientMsg = HelloMsg | RequestMsg;
|
||||
export type ServerMsg = {
|
||||
type: "none";
|
||||
} | HelloOkMsg | HelloErrorMsg | ResponseOkMsg | ResponseErrorMsg;
|
||||
export type HelloMsg = {
|
||||
type: "hello";
|
||||
jwt: string | undefined;
|
||||
};
|
||||
export type HelloOkMsg = {
|
||||
type: "hello_ok";
|
||||
};
|
||||
export type HelloErrorMsg = {
|
||||
type: "hello_error";
|
||||
error: Error;
|
||||
};
|
||||
export type RequestMsg = {
|
||||
type: "request";
|
||||
requestId: int32;
|
||||
request: Request;
|
||||
};
|
||||
export type ResponseOkMsg = {
|
||||
type: "response_ok";
|
||||
requestId: int32;
|
||||
response: Response;
|
||||
};
|
||||
export type ResponseErrorMsg = {
|
||||
type: "response_error";
|
||||
requestId: int32;
|
||||
error: Error;
|
||||
};
|
||||
export type Request = OpenStreamReq | CloseStreamReq | ExecuteReq | BatchReq | OpenCursorReq | CloseCursorReq | FetchCursorReq | SequenceReq | DescribeReq | StoreSqlReq | CloseSqlReq | GetAutocommitReq;
|
||||
export type Response = {
|
||||
type: "none";
|
||||
} | OpenStreamResp | CloseStreamResp | ExecuteResp | BatchResp | OpenCursorResp | CloseCursorResp | FetchCursorResp | SequenceResp | DescribeResp | StoreSqlResp | CloseSqlResp | GetAutocommitResp;
|
||||
export type OpenStreamReq = {
|
||||
type: "open_stream";
|
||||
streamId: int32;
|
||||
};
|
||||
export type OpenStreamResp = {
|
||||
type: "open_stream";
|
||||
};
|
||||
export type CloseStreamReq = {
|
||||
type: "close_stream";
|
||||
streamId: int32;
|
||||
};
|
||||
export type CloseStreamResp = {
|
||||
type: "close_stream";
|
||||
};
|
||||
export type ExecuteReq = {
|
||||
type: "execute";
|
||||
streamId: int32;
|
||||
stmt: Stmt;
|
||||
};
|
||||
export type ExecuteResp = {
|
||||
type: "execute";
|
||||
result: StmtResult;
|
||||
};
|
||||
export type BatchReq = {
|
||||
type: "batch";
|
||||
streamId: int32;
|
||||
batch: Batch;
|
||||
};
|
||||
export type BatchResp = {
|
||||
type: "batch";
|
||||
result: BatchResult;
|
||||
};
|
||||
export type OpenCursorReq = {
|
||||
type: "open_cursor";
|
||||
streamId: int32;
|
||||
cursorId: int32;
|
||||
batch: Batch;
|
||||
};
|
||||
export type OpenCursorResp = {
|
||||
type: "open_cursor";
|
||||
};
|
||||
export type CloseCursorReq = {
|
||||
type: "close_cursor";
|
||||
cursorId: int32;
|
||||
};
|
||||
export type CloseCursorResp = {
|
||||
type: "close_cursor";
|
||||
};
|
||||
export type FetchCursorReq = {
|
||||
type: "fetch_cursor";
|
||||
cursorId: int32;
|
||||
maxCount: uint32;
|
||||
};
|
||||
export type FetchCursorResp = {
|
||||
type: "fetch_cursor";
|
||||
entries: Array<CursorEntry>;
|
||||
done: boolean;
|
||||
};
|
||||
export type DescribeReq = {
|
||||
type: "describe";
|
||||
streamId: int32;
|
||||
sql: string | undefined;
|
||||
sqlId: int32 | undefined;
|
||||
};
|
||||
export type DescribeResp = {
|
||||
type: "describe";
|
||||
result: DescribeResult;
|
||||
};
|
||||
export type SequenceReq = {
|
||||
type: "sequence";
|
||||
streamId: int32;
|
||||
sql: string | undefined;
|
||||
sqlId: int32 | undefined;
|
||||
};
|
||||
export type SequenceResp = {
|
||||
type: "sequence";
|
||||
};
|
||||
export type StoreSqlReq = {
|
||||
type: "store_sql";
|
||||
sqlId: int32;
|
||||
sql: string;
|
||||
};
|
||||
export type StoreSqlResp = {
|
||||
type: "store_sql";
|
||||
};
|
||||
export type CloseSqlReq = {
|
||||
type: "close_sql";
|
||||
sqlId: int32;
|
||||
};
|
||||
export type CloseSqlResp = {
|
||||
type: "close_sql";
|
||||
};
|
||||
export type GetAutocommitReq = {
|
||||
type: "get_autocommit";
|
||||
streamId: int32;
|
||||
};
|
||||
export type GetAutocommitResp = {
|
||||
type: "get_autocommit";
|
||||
isAutocommit: boolean;
|
||||
};
|
||||
2
node_modules/@libsql/hrana-client/lib-esm/ws/proto.js
generated
vendored
Normal file
2
node_modules/@libsql/hrana-client/lib-esm/ws/proto.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Types for the structures specific to Hrana over WebSockets.
|
||||
export * from "../shared/proto.js";
|
||||
3
node_modules/@libsql/hrana-client/lib-esm/ws/protobuf_decode.d.ts
generated
vendored
Normal file
3
node_modules/@libsql/hrana-client/lib-esm/ws/protobuf_decode.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import * as d from "../encoding/protobuf/decode.js";
|
||||
import * as proto from "./proto.js";
|
||||
export declare const ServerMsg: d.MessageDef<proto.ServerMsg>;
|
||||
60
node_modules/@libsql/hrana-client/lib-esm/ws/protobuf_decode.js
generated
vendored
Normal file
60
node_modules/@libsql/hrana-client/lib-esm/ws/protobuf_decode.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Error, StmtResult, BatchResult, CursorEntry, DescribeResult } from "../shared/protobuf_decode.js";
|
||||
export const ServerMsg = {
|
||||
default() { return { type: "none" }; },
|
||||
1(r) { return { type: "hello_ok" }; },
|
||||
2(r) { return r.message(HelloErrorMsg); },
|
||||
3(r) { return r.message(ResponseOkMsg); },
|
||||
4(r) { return r.message(ResponseErrorMsg); },
|
||||
};
|
||||
const HelloErrorMsg = {
|
||||
default() { return { type: "hello_error", error: Error.default() }; },
|
||||
1(r, msg) { msg.error = r.message(Error); },
|
||||
};
|
||||
const ResponseErrorMsg = {
|
||||
default() { return { type: "response_error", requestId: 0, error: Error.default() }; },
|
||||
1(r, msg) { msg.requestId = r.int32(); },
|
||||
2(r, msg) { msg.error = r.message(Error); },
|
||||
};
|
||||
const ResponseOkMsg = {
|
||||
default() {
|
||||
return {
|
||||
type: "response_ok",
|
||||
requestId: 0,
|
||||
response: { type: "none" },
|
||||
};
|
||||
},
|
||||
1(r, msg) { msg.requestId = r.int32(); },
|
||||
2(r, msg) { msg.response = { type: "open_stream" }; },
|
||||
3(r, msg) { msg.response = { type: "close_stream" }; },
|
||||
4(r, msg) { msg.response = r.message(ExecuteResp); },
|
||||
5(r, msg) { msg.response = r.message(BatchResp); },
|
||||
6(r, msg) { msg.response = { type: "open_cursor" }; },
|
||||
7(r, msg) { msg.response = { type: "close_cursor" }; },
|
||||
8(r, msg) { msg.response = r.message(FetchCursorResp); },
|
||||
9(r, msg) { msg.response = { type: "sequence" }; },
|
||||
10(r, msg) { msg.response = r.message(DescribeResp); },
|
||||
11(r, msg) { msg.response = { type: "store_sql" }; },
|
||||
12(r, msg) { msg.response = { type: "close_sql" }; },
|
||||
13(r, msg) { msg.response = r.message(GetAutocommitResp); },
|
||||
};
|
||||
const ExecuteResp = {
|
||||
default() { return { type: "execute", result: StmtResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(StmtResult); },
|
||||
};
|
||||
const BatchResp = {
|
||||
default() { return { type: "batch", result: BatchResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(BatchResult); },
|
||||
};
|
||||
const FetchCursorResp = {
|
||||
default() { return { type: "fetch_cursor", entries: [], done: false }; },
|
||||
1(r, msg) { msg.entries.push(r.message(CursorEntry)); },
|
||||
2(r, msg) { msg.done = r.bool(); },
|
||||
};
|
||||
const DescribeResp = {
|
||||
default() { return { type: "describe", result: DescribeResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(DescribeResult); },
|
||||
};
|
||||
const GetAutocommitResp = {
|
||||
default() { return { type: "get_autocommit", isAutocommit: false }; },
|
||||
1(r, msg) { msg.isAutocommit = r.bool(); },
|
||||
};
|
||||
3
node_modules/@libsql/hrana-client/lib-esm/ws/protobuf_encode.d.ts
generated
vendored
Normal file
3
node_modules/@libsql/hrana-client/lib-esm/ws/protobuf_encode.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import * as e from "../encoding/protobuf/encode.js";
|
||||
import * as proto from "./proto.js";
|
||||
export declare function ClientMsg(w: e.MessageWriter, msg: proto.ClientMsg): void;
|
||||
115
node_modules/@libsql/hrana-client/lib-esm/ws/protobuf_encode.js
generated
vendored
Normal file
115
node_modules/@libsql/hrana-client/lib-esm/ws/protobuf_encode.js
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
import { Stmt, Batch } from "../shared/protobuf_encode.js";
|
||||
import { impossible } from "../util.js";
|
||||
export function ClientMsg(w, msg) {
|
||||
if (msg.type === "hello") {
|
||||
w.message(1, msg, HelloMsg);
|
||||
}
|
||||
else if (msg.type === "request") {
|
||||
w.message(2, msg, RequestMsg);
|
||||
}
|
||||
else {
|
||||
throw impossible(msg, "Impossible type of ClientMsg");
|
||||
}
|
||||
}
|
||||
function HelloMsg(w, msg) {
|
||||
if (msg.jwt !== undefined) {
|
||||
w.string(1, msg.jwt);
|
||||
}
|
||||
}
|
||||
function RequestMsg(w, msg) {
|
||||
w.int32(1, msg.requestId);
|
||||
const request = msg.request;
|
||||
if (request.type === "open_stream") {
|
||||
w.message(2, request, OpenStreamReq);
|
||||
}
|
||||
else if (request.type === "close_stream") {
|
||||
w.message(3, request, CloseStreamReq);
|
||||
}
|
||||
else if (request.type === "execute") {
|
||||
w.message(4, request, ExecuteReq);
|
||||
}
|
||||
else if (request.type === "batch") {
|
||||
w.message(5, request, BatchReq);
|
||||
}
|
||||
else if (request.type === "open_cursor") {
|
||||
w.message(6, request, OpenCursorReq);
|
||||
}
|
||||
else if (request.type === "close_cursor") {
|
||||
w.message(7, request, CloseCursorReq);
|
||||
}
|
||||
else if (request.type === "fetch_cursor") {
|
||||
w.message(8, request, FetchCursorReq);
|
||||
}
|
||||
else if (request.type === "sequence") {
|
||||
w.message(9, request, SequenceReq);
|
||||
}
|
||||
else if (request.type === "describe") {
|
||||
w.message(10, request, DescribeReq);
|
||||
}
|
||||
else if (request.type === "store_sql") {
|
||||
w.message(11, request, StoreSqlReq);
|
||||
}
|
||||
else if (request.type === "close_sql") {
|
||||
w.message(12, request, CloseSqlReq);
|
||||
}
|
||||
else if (request.type === "get_autocommit") {
|
||||
w.message(13, request, GetAutocommitReq);
|
||||
}
|
||||
else {
|
||||
throw impossible(request, "Impossible type of Request");
|
||||
}
|
||||
}
|
||||
function OpenStreamReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
}
|
||||
function CloseStreamReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
}
|
||||
function ExecuteReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
w.message(2, msg.stmt, Stmt);
|
||||
}
|
||||
function BatchReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
w.message(2, msg.batch, Batch);
|
||||
}
|
||||
function OpenCursorReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
w.int32(2, msg.cursorId);
|
||||
w.message(3, msg.batch, Batch);
|
||||
}
|
||||
function CloseCursorReq(w, msg) {
|
||||
w.int32(1, msg.cursorId);
|
||||
}
|
||||
function FetchCursorReq(w, msg) {
|
||||
w.int32(1, msg.cursorId);
|
||||
w.uint32(2, msg.maxCount);
|
||||
}
|
||||
function SequenceReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
if (msg.sql !== undefined) {
|
||||
w.string(2, msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.int32(3, msg.sqlId);
|
||||
}
|
||||
}
|
||||
function DescribeReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
if (msg.sql !== undefined) {
|
||||
w.string(2, msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.int32(3, msg.sqlId);
|
||||
}
|
||||
}
|
||||
function StoreSqlReq(w, msg) {
|
||||
w.int32(1, msg.sqlId);
|
||||
w.string(2, msg.sql);
|
||||
}
|
||||
function CloseSqlReq(w, msg) {
|
||||
w.int32(1, msg.sqlId);
|
||||
}
|
||||
function GetAutocommitReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
}
|
||||
40
node_modules/@libsql/hrana-client/lib-esm/ws/stream.d.ts
generated
vendored
Normal file
40
node_modules/@libsql/hrana-client/lib-esm/ws/stream.d.ts
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import type { SqlOwner, ProtoSql } from "../sql.js";
|
||||
import { Stream } from "../stream.js";
|
||||
import type { WsClient } from "./client.js";
|
||||
import { WsCursor } from "./cursor.js";
|
||||
import type * as proto from "./proto.js";
|
||||
export declare class WsStream extends Stream {
|
||||
#private;
|
||||
/** @private */
|
||||
static open(client: WsClient): WsStream;
|
||||
/** @private */
|
||||
constructor(client: WsClient, streamId: number);
|
||||
/** Get the {@link WsClient} object that this stream belongs to. */
|
||||
client(): WsClient;
|
||||
/** @private */
|
||||
_sqlOwner(): SqlOwner;
|
||||
/** @private */
|
||||
_execute(stmt: proto.Stmt): Promise<proto.StmtResult>;
|
||||
/** @private */
|
||||
_batch(batch: proto.Batch): Promise<proto.BatchResult>;
|
||||
/** @private */
|
||||
_describe(protoSql: ProtoSql): Promise<proto.DescribeResult>;
|
||||
/** @private */
|
||||
_sequence(protoSql: ProtoSql): Promise<void>;
|
||||
/** Check whether the SQL connection underlying this stream is in autocommit state (i.e., outside of an
|
||||
* explicit transaction). This requires protocol version 3 or higher.
|
||||
*/
|
||||
getAutocommit(): Promise<boolean>;
|
||||
/** @private */
|
||||
_openCursor(batch: proto.Batch): Promise<WsCursor>;
|
||||
/** @private */
|
||||
_sendCursorRequest(cursor: WsCursor, request: proto.Request): Promise<proto.Response>;
|
||||
/** @private */
|
||||
_cursorClosed(cursor: WsCursor): void;
|
||||
/** Immediately close the stream. */
|
||||
close(): void;
|
||||
/** Gracefully close the stream. */
|
||||
closeGracefully(): void;
|
||||
/** True if the stream is closed or closing. */
|
||||
get closed(): boolean;
|
||||
}
|
||||
211
node_modules/@libsql/hrana-client/lib-esm/ws/stream.js
generated
vendored
Normal file
211
node_modules/@libsql/hrana-client/lib-esm/ws/stream.js
generated
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
import { ClientError, ClosedError, InternalError } from "../errors.js";
|
||||
import { Queue } from "../queue.js";
|
||||
import { Stream } from "../stream.js";
|
||||
import { WsCursor } from "./cursor.js";
|
||||
export class WsStream extends Stream {
|
||||
#client;
|
||||
#streamId;
|
||||
#queue;
|
||||
#cursor;
|
||||
#closing;
|
||||
#closed;
|
||||
/** @private */
|
||||
static open(client) {
|
||||
const streamId = client._streamIdAlloc.alloc();
|
||||
const stream = new WsStream(client, streamId);
|
||||
const responseCallback = () => undefined;
|
||||
const errorCallback = (e) => stream.#setClosed(e);
|
||||
const request = { type: "open_stream", streamId };
|
||||
client._sendRequest(request, { responseCallback, errorCallback });
|
||||
return stream;
|
||||
}
|
||||
/** @private */
|
||||
constructor(client, streamId) {
|
||||
super(client.intMode);
|
||||
this.#client = client;
|
||||
this.#streamId = streamId;
|
||||
this.#queue = new Queue();
|
||||
this.#cursor = undefined;
|
||||
this.#closing = false;
|
||||
this.#closed = undefined;
|
||||
}
|
||||
/** Get the {@link WsClient} object that this stream belongs to. */
|
||||
client() {
|
||||
return this.#client;
|
||||
}
|
||||
/** @private */
|
||||
_sqlOwner() {
|
||||
return this.#client;
|
||||
}
|
||||
/** @private */
|
||||
_execute(stmt) {
|
||||
return this.#sendStreamRequest({
|
||||
type: "execute",
|
||||
streamId: this.#streamId,
|
||||
stmt,
|
||||
}).then((response) => {
|
||||
return response.result;
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_batch(batch) {
|
||||
return this.#sendStreamRequest({
|
||||
type: "batch",
|
||||
streamId: this.#streamId,
|
||||
batch,
|
||||
}).then((response) => {
|
||||
return response.result;
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_describe(protoSql) {
|
||||
this.#client._ensureVersion(2, "describe()");
|
||||
return this.#sendStreamRequest({
|
||||
type: "describe",
|
||||
streamId: this.#streamId,
|
||||
sql: protoSql.sql,
|
||||
sqlId: protoSql.sqlId,
|
||||
}).then((response) => {
|
||||
return response.result;
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_sequence(protoSql) {
|
||||
this.#client._ensureVersion(2, "sequence()");
|
||||
return this.#sendStreamRequest({
|
||||
type: "sequence",
|
||||
streamId: this.#streamId,
|
||||
sql: protoSql.sql,
|
||||
sqlId: protoSql.sqlId,
|
||||
}).then((_response) => {
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
/** Check whether the SQL connection underlying this stream is in autocommit state (i.e., outside of an
|
||||
* explicit transaction). This requires protocol version 3 or higher.
|
||||
*/
|
||||
getAutocommit() {
|
||||
this.#client._ensureVersion(3, "getAutocommit()");
|
||||
return this.#sendStreamRequest({
|
||||
type: "get_autocommit",
|
||||
streamId: this.#streamId,
|
||||
}).then((response) => {
|
||||
return response.isAutocommit;
|
||||
});
|
||||
}
|
||||
#sendStreamRequest(request) {
|
||||
return new Promise((responseCallback, errorCallback) => {
|
||||
this.#pushToQueue({ type: "request", request, responseCallback, errorCallback });
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_openCursor(batch) {
|
||||
this.#client._ensureVersion(3, "cursor");
|
||||
return new Promise((cursorCallback, errorCallback) => {
|
||||
this.#pushToQueue({ type: "cursor", batch, cursorCallback, errorCallback });
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_sendCursorRequest(cursor, request) {
|
||||
if (cursor !== this.#cursor) {
|
||||
throw new InternalError("Cursor not associated with the stream attempted to execute a request");
|
||||
}
|
||||
return new Promise((responseCallback, errorCallback) => {
|
||||
if (this.#closed !== undefined) {
|
||||
errorCallback(new ClosedError("Stream is closed", this.#closed));
|
||||
}
|
||||
else {
|
||||
this.#client._sendRequest(request, { responseCallback, errorCallback });
|
||||
}
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_cursorClosed(cursor) {
|
||||
if (cursor !== this.#cursor) {
|
||||
throw new InternalError("Cursor was closed, but it was not associated with the stream");
|
||||
}
|
||||
this.#cursor = undefined;
|
||||
this.#flushQueue();
|
||||
}
|
||||
#pushToQueue(entry) {
|
||||
if (this.#closed !== undefined) {
|
||||
entry.errorCallback(new ClosedError("Stream is closed", this.#closed));
|
||||
}
|
||||
else if (this.#closing) {
|
||||
entry.errorCallback(new ClosedError("Stream is closing", undefined));
|
||||
}
|
||||
else {
|
||||
this.#queue.push(entry);
|
||||
this.#flushQueue();
|
||||
}
|
||||
}
|
||||
#flushQueue() {
|
||||
for (;;) {
|
||||
const entry = this.#queue.first();
|
||||
if (entry === undefined && this.#cursor === undefined && this.#closing) {
|
||||
this.#setClosed(new ClientError("Stream was gracefully closed"));
|
||||
break;
|
||||
}
|
||||
else if (entry?.type === "request" && this.#cursor === undefined) {
|
||||
const { request, responseCallback, errorCallback } = entry;
|
||||
this.#queue.shift();
|
||||
this.#client._sendRequest(request, { responseCallback, errorCallback });
|
||||
}
|
||||
else if (entry?.type === "cursor" && this.#cursor === undefined) {
|
||||
const { batch, cursorCallback } = entry;
|
||||
this.#queue.shift();
|
||||
const cursorId = this.#client._cursorIdAlloc.alloc();
|
||||
const cursor = new WsCursor(this.#client, this, cursorId);
|
||||
const request = {
|
||||
type: "open_cursor",
|
||||
streamId: this.#streamId,
|
||||
cursorId,
|
||||
batch,
|
||||
};
|
||||
const responseCallback = () => undefined;
|
||||
const errorCallback = (e) => cursor._setClosed(e);
|
||||
this.#client._sendRequest(request, { responseCallback, errorCallback });
|
||||
this.#cursor = cursor;
|
||||
cursorCallback(cursor);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#setClosed(error) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
this.#closed = error;
|
||||
if (this.#cursor !== undefined) {
|
||||
this.#cursor._setClosed(error);
|
||||
}
|
||||
for (;;) {
|
||||
const entry = this.#queue.shift();
|
||||
if (entry !== undefined) {
|
||||
entry.errorCallback(error);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const request = { type: "close_stream", streamId: this.#streamId };
|
||||
const responseCallback = () => this.#client._streamIdAlloc.free(this.#streamId);
|
||||
const errorCallback = () => undefined;
|
||||
this.#client._sendRequest(request, { responseCallback, errorCallback });
|
||||
}
|
||||
/** Immediately close the stream. */
|
||||
close() {
|
||||
this.#setClosed(new ClientError("Stream was manually closed"));
|
||||
}
|
||||
/** Gracefully close the stream. */
|
||||
closeGracefully() {
|
||||
this.#closing = true;
|
||||
this.#flushQueue();
|
||||
}
|
||||
/** True if the stream is closed or closing. */
|
||||
get closed() {
|
||||
return this.#closed !== undefined || this.#closing;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user