Initial commit: New MoreminiMore website with fresh design

This commit is contained in:
MoreminiMore
2026-04-22 01:59:05 +07:00
commit 76409638cc
14010 changed files with 2052041 additions and 0 deletions

View 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
View 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;
}
}

View 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
View 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;
}
}

View 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;

View 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");
}
}

View 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;

View 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
View 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;
};

View File

@@ -0,0 +1,2 @@
// Types for the structures specific to Hrana over WebSockets.
export * from "../shared/proto.js";

View 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>;

View 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(); },
};

View 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;

View 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);
}

View 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
View 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;
}
}