Initial commit: New MoreminiMore website with fresh design
This commit is contained in:
126
node_modules/@libsql/client/README.md
generated
vendored
Normal file
126
node_modules/@libsql/client/README.md
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
<p align="center">
|
||||
<a href="https://tur.so/turso-ts">
|
||||
<picture>
|
||||
<img src="/.github/cover.png" alt="libSQL TypeScript" />
|
||||
</picture>
|
||||
</a>
|
||||
<h1 align="center">libSQL TypeScript</h1>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Databases for all TypeScript and JS multi-tenant apps.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://tur.so/turso-ts"><strong>Turso</strong></a> ·
|
||||
<a href="https://docs.turso.tech"><strong>Docs</strong></a> ·
|
||||
<a href="https://docs.turso.tech/sdk/ts/quickstart"><strong>Quickstart</strong></a> ·
|
||||
<a href="https://docs.turso.tech/sdk/ts/reference"><strong>SDK Reference</strong></a> ·
|
||||
<a href="https://turso.tech/blog"><strong>Blog & Tutorials</strong></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="LICENSE">
|
||||
<picture>
|
||||
<img src="https://img.shields.io/github/license/tursodatabase/libsql-client-ts?color=0F624B" alt="MIT License" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://tur.so/discord-ts">
|
||||
<picture>
|
||||
<img src="https://img.shields.io/discord/933071162680958986?color=0F624B" alt="Discord" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="#contributors">
|
||||
<picture>
|
||||
<img src="https://img.shields.io/github/contributors/tursodatabase/libsql-client-ts?color=0F624B" alt="Contributors" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/@libsql/client">
|
||||
<picture>
|
||||
<img src="https://img.shields.io/npm/dw/%40libsql%2Fclient?color=0F624B" alt="Weekly downloads" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="/examples">
|
||||
<picture>
|
||||
<img src="https://img.shields.io/badge/browse-examples-0F624B" alt="Examples" />
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Features
|
||||
|
||||
- 🔌 Works offline with [Embedded Replicas](https://docs.turso.tech/features/embedded-replicas/introduction)
|
||||
- 🌎 Works with remote Turso databases
|
||||
- ✨ Works with Turso [AI & Vector Search](https://docs.turso.tech/features/ai-and-embeddings)
|
||||
- 🔐 Supports [encryption at rest](https://docs.turso.tech/libsql#encryption-at-rest)
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install @libsql/client
|
||||
```
|
||||
|
||||
## Quickstart
|
||||
|
||||
The example below uses Embedded Replicas and syncs every minute from Turso.
|
||||
|
||||
```ts
|
||||
import { createClient } from "@libsql/client";
|
||||
|
||||
export const turso = createClient({
|
||||
url: "file:local.db",
|
||||
syncUrl: process.env.TURSO_DATABASE_URL,
|
||||
authToken: process.env.TURSO_AUTH_TOKEN,
|
||||
syncInterval: 60000,
|
||||
});
|
||||
|
||||
await turso.batch(
|
||||
[
|
||||
"CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)",
|
||||
{
|
||||
sql: "INSERT INTO users(name) VALUES (?)",
|
||||
args: ["Iku"],
|
||||
},
|
||||
],
|
||||
"write",
|
||||
);
|
||||
|
||||
await turso.execute({
|
||||
sql: "SELECT * FROM users WHERE id = ?",
|
||||
args: [1],
|
||||
});
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
| Example | Description |
|
||||
| ------------------------------------- | --------------------------------------------------------------------------------------- |
|
||||
| [local](examples/local) | Uses libsql with a local SQLite file. Creates database, inserts data, and queries. |
|
||||
| [remote](examples/remote) | Connects to a remote database. Requires environment variables for URL and auth token. |
|
||||
| [sync](examples/sync) | Demonstrates synchronization between local and remote databases. |
|
||||
| [batch](examples/batch) | Executes multiple SQL statements in a single batch operation. |
|
||||
| [transactions](examples/transactions) | Shows transaction usage: starting, performing operations, and committing/rolling back. |
|
||||
| [memory](examples/memory) | Uses an in-memory SQLite database for temporary storage or fast access. |
|
||||
| [vector](examples/vector) | Works with vector embeddings, storing and querying for similarity search. |
|
||||
| [encryption](examples/encryption) | Creates and uses an encrypted SQLite database, demonstrating setup and data operations. |
|
||||
| [ollama](examples/ollama) | Similarity search with Ollama and Mistral. |
|
||||
|
||||
## Documentation
|
||||
|
||||
Visit our [official documentation](https://docs.turso.tech/sdk/ts).
|
||||
|
||||
## Support
|
||||
|
||||
Join us [on Discord](https://tur.so/discord-ts) to get help using this SDK. Report security issues [via email](mailto:security@turso.tech).
|
||||
|
||||
## Contributors
|
||||
|
||||
See the [contributing guide](CONTRIBUTING.md) to learn how to get involved.
|
||||
|
||||

|
||||
|
||||
<a href="https://github.com/tursodatabase/libsql-client-ts/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22">
|
||||
<picture>
|
||||
<img src="https://img.shields.io/github/issues-search/tursodatabase/libsql-client-ts?label=good%20first%20issue&query=label%3A%22good%20first%20issue%22%20&color=0F624B" alt="good first issue" />
|
||||
</picture>
|
||||
</a>
|
||||
341
node_modules/@libsql/client/lib-cjs/hrana.js
generated
vendored
Normal file
341
node_modules/@libsql/client/lib-cjs/hrana.js
generated
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.mapHranaError = exports.resultSetFromHrana = exports.stmtToHrana = exports.executeHranaBatch = exports.HranaTransaction = void 0;
|
||||
const hrana = __importStar(require("@libsql/hrana-client"));
|
||||
const api_1 = require("@libsql/core/api");
|
||||
const util_1 = require("@libsql/core/util");
|
||||
class HranaTransaction {
|
||||
#mode;
|
||||
#version;
|
||||
// Promise that is resolved when the BEGIN statement completes, or `undefined` if we haven't executed the
|
||||
// BEGIN statement yet.
|
||||
#started;
|
||||
/** @private */
|
||||
constructor(mode, version) {
|
||||
this.#mode = mode;
|
||||
this.#version = version;
|
||||
this.#started = undefined;
|
||||
}
|
||||
execute(stmt) {
|
||||
return this.batch([stmt]).then((results) => results[0]);
|
||||
}
|
||||
async batch(stmts) {
|
||||
const stream = this._getStream();
|
||||
if (stream.closed) {
|
||||
throw new api_1.LibsqlError("Cannot execute statements because the transaction is closed", "TRANSACTION_CLOSED");
|
||||
}
|
||||
try {
|
||||
const hranaStmts = stmts.map(stmtToHrana);
|
||||
let rowsPromises;
|
||||
if (this.#started === undefined) {
|
||||
// The transaction hasn't started yet, so we need to send the BEGIN statement in a batch with
|
||||
// `hranaStmts`.
|
||||
this._getSqlCache().apply(hranaStmts);
|
||||
const batch = stream.batch(this.#version >= 3);
|
||||
const beginStep = batch.step();
|
||||
const beginPromise = beginStep.run((0, util_1.transactionModeToBegin)(this.#mode));
|
||||
// Execute the `hranaStmts` only if the BEGIN succeeded, to make sure that we don't execute it
|
||||
// outside of a transaction.
|
||||
let lastStep = beginStep;
|
||||
rowsPromises = hranaStmts.map((hranaStmt) => {
|
||||
const stmtStep = batch
|
||||
.step()
|
||||
.condition(hrana.BatchCond.ok(lastStep));
|
||||
if (this.#version >= 3) {
|
||||
// If the Hrana version supports it, make sure that we are still in a transaction
|
||||
stmtStep.condition(hrana.BatchCond.not(hrana.BatchCond.isAutocommit(batch)));
|
||||
}
|
||||
const rowsPromise = stmtStep.query(hranaStmt);
|
||||
rowsPromise.catch(() => undefined); // silence Node warning
|
||||
lastStep = stmtStep;
|
||||
return rowsPromise;
|
||||
});
|
||||
// `this.#started` is resolved successfully only if the batch and the BEGIN statement inside
|
||||
// of the batch are both successful.
|
||||
this.#started = batch
|
||||
.execute()
|
||||
.then(() => beginPromise)
|
||||
.then(() => undefined);
|
||||
try {
|
||||
await this.#started;
|
||||
}
|
||||
catch (e) {
|
||||
// If the BEGIN failed, the transaction is unusable and we must close it. However, if the
|
||||
// BEGIN suceeds and `hranaStmts` fail, the transaction is _not_ closed.
|
||||
this.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.#version < 3) {
|
||||
// The transaction has started, so we must wait until the BEGIN statement completed to make
|
||||
// sure that we don't execute `hranaStmts` outside of a transaction.
|
||||
await this.#started;
|
||||
}
|
||||
else {
|
||||
// The transaction has started, but we will use `hrana.BatchCond.isAutocommit()` to make
|
||||
// sure that we don't execute `hranaStmts` outside of a transaction, so we don't have to
|
||||
// wait for `this.#started`
|
||||
}
|
||||
this._getSqlCache().apply(hranaStmts);
|
||||
const batch = stream.batch(this.#version >= 3);
|
||||
let lastStep = undefined;
|
||||
rowsPromises = hranaStmts.map((hranaStmt) => {
|
||||
const stmtStep = batch.step();
|
||||
if (lastStep !== undefined) {
|
||||
stmtStep.condition(hrana.BatchCond.ok(lastStep));
|
||||
}
|
||||
if (this.#version >= 3) {
|
||||
stmtStep.condition(hrana.BatchCond.not(hrana.BatchCond.isAutocommit(batch)));
|
||||
}
|
||||
const rowsPromise = stmtStep.query(hranaStmt);
|
||||
rowsPromise.catch(() => undefined); // silence Node warning
|
||||
lastStep = stmtStep;
|
||||
return rowsPromise;
|
||||
});
|
||||
await batch.execute();
|
||||
}
|
||||
const resultSets = [];
|
||||
for (const rowsPromise of rowsPromises) {
|
||||
const rows = await rowsPromise;
|
||||
if (rows === undefined) {
|
||||
throw new api_1.LibsqlError("Statement in a transaction was not executed, " +
|
||||
"probably because the transaction has been rolled back", "TRANSACTION_CLOSED");
|
||||
}
|
||||
resultSets.push(resultSetFromHrana(rows));
|
||||
}
|
||||
return resultSets;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
const stream = this._getStream();
|
||||
if (stream.closed) {
|
||||
throw new api_1.LibsqlError("Cannot execute statements because the transaction is closed", "TRANSACTION_CLOSED");
|
||||
}
|
||||
try {
|
||||
if (this.#started === undefined) {
|
||||
// If the transaction hasn't started yet, start it now
|
||||
this.#started = stream
|
||||
.run((0, util_1.transactionModeToBegin)(this.#mode))
|
||||
.then(() => undefined);
|
||||
try {
|
||||
await this.#started;
|
||||
}
|
||||
catch (e) {
|
||||
this.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Wait until the transaction has started
|
||||
await this.#started;
|
||||
}
|
||||
await stream.sequence(sql);
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
}
|
||||
async rollback() {
|
||||
try {
|
||||
const stream = this._getStream();
|
||||
if (stream.closed) {
|
||||
return;
|
||||
}
|
||||
if (this.#started !== undefined) {
|
||||
// We don't have to wait for the BEGIN statement to complete. If the BEGIN fails, we will
|
||||
// execute a ROLLBACK outside of an active transaction, which should be harmless.
|
||||
}
|
||||
else {
|
||||
// We did nothing in the transaction, so there is nothing to rollback.
|
||||
return;
|
||||
}
|
||||
// Pipeline the ROLLBACK statement and the stream close.
|
||||
const promise = stream.run("ROLLBACK").catch((e) => {
|
||||
throw mapHranaError(e);
|
||||
});
|
||||
stream.closeGracefully();
|
||||
await promise;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
finally {
|
||||
// `this.close()` may close the `hrana.Client`, which aborts all pending stream requests, so we
|
||||
// must call it _after_ we receive the ROLLBACK response.
|
||||
// Also note that the current stream should already be closed, but we need to call `this.close()`
|
||||
// anyway, because it may need to do more cleanup.
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
async commit() {
|
||||
// (this method is analogous to `rollback()`)
|
||||
try {
|
||||
const stream = this._getStream();
|
||||
if (stream.closed) {
|
||||
throw new api_1.LibsqlError("Cannot commit the transaction because it is already closed", "TRANSACTION_CLOSED");
|
||||
}
|
||||
if (this.#started !== undefined) {
|
||||
// Make sure to execute the COMMIT only if the BEGIN was successful.
|
||||
await this.#started;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
const promise = stream.run("COMMIT").catch((e) => {
|
||||
throw mapHranaError(e);
|
||||
});
|
||||
stream.closeGracefully();
|
||||
await promise;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
finally {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.HranaTransaction = HranaTransaction;
|
||||
async function executeHranaBatch(mode, version, batch, hranaStmts, disableForeignKeys = false) {
|
||||
if (disableForeignKeys) {
|
||||
batch.step().run("PRAGMA foreign_keys=off");
|
||||
}
|
||||
const beginStep = batch.step();
|
||||
const beginPromise = beginStep.run((0, util_1.transactionModeToBegin)(mode));
|
||||
let lastStep = beginStep;
|
||||
const stmtPromises = hranaStmts.map((hranaStmt) => {
|
||||
const stmtStep = batch.step().condition(hrana.BatchCond.ok(lastStep));
|
||||
if (version >= 3) {
|
||||
stmtStep.condition(hrana.BatchCond.not(hrana.BatchCond.isAutocommit(batch)));
|
||||
}
|
||||
const stmtPromise = stmtStep.query(hranaStmt);
|
||||
lastStep = stmtStep;
|
||||
return stmtPromise;
|
||||
});
|
||||
const commitStep = batch.step().condition(hrana.BatchCond.ok(lastStep));
|
||||
if (version >= 3) {
|
||||
commitStep.condition(hrana.BatchCond.not(hrana.BatchCond.isAutocommit(batch)));
|
||||
}
|
||||
const commitPromise = commitStep.run("COMMIT");
|
||||
const rollbackStep = batch
|
||||
.step()
|
||||
.condition(hrana.BatchCond.not(hrana.BatchCond.ok(commitStep)));
|
||||
rollbackStep.run("ROLLBACK").catch((_) => undefined);
|
||||
if (disableForeignKeys) {
|
||||
batch.step().run("PRAGMA foreign_keys=on");
|
||||
}
|
||||
await batch.execute();
|
||||
const resultSets = [];
|
||||
await beginPromise;
|
||||
for (const stmtPromise of stmtPromises) {
|
||||
const hranaRows = await stmtPromise;
|
||||
if (hranaRows === undefined) {
|
||||
throw new api_1.LibsqlError("Statement in a batch was not executed, probably because the transaction has been rolled back", "TRANSACTION_CLOSED");
|
||||
}
|
||||
resultSets.push(resultSetFromHrana(hranaRows));
|
||||
}
|
||||
await commitPromise;
|
||||
return resultSets;
|
||||
}
|
||||
exports.executeHranaBatch = executeHranaBatch;
|
||||
function stmtToHrana(stmt) {
|
||||
let sql;
|
||||
let args;
|
||||
if (Array.isArray(stmt)) {
|
||||
[sql, args] = stmt;
|
||||
}
|
||||
else if (typeof stmt === "string") {
|
||||
sql = stmt;
|
||||
}
|
||||
else {
|
||||
sql = stmt.sql;
|
||||
args = stmt.args;
|
||||
}
|
||||
const hranaStmt = new hrana.Stmt(sql);
|
||||
if (args) {
|
||||
if (Array.isArray(args)) {
|
||||
hranaStmt.bindIndexes(args);
|
||||
}
|
||||
else {
|
||||
for (const [key, value] of Object.entries(args)) {
|
||||
hranaStmt.bindName(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hranaStmt;
|
||||
}
|
||||
exports.stmtToHrana = stmtToHrana;
|
||||
function resultSetFromHrana(hranaRows) {
|
||||
const columns = hranaRows.columnNames.map((c) => c ?? "");
|
||||
const columnTypes = hranaRows.columnDecltypes.map((c) => c ?? "");
|
||||
const rows = hranaRows.rows;
|
||||
const rowsAffected = hranaRows.affectedRowCount;
|
||||
const lastInsertRowid = hranaRows.lastInsertRowid !== undefined
|
||||
? hranaRows.lastInsertRowid
|
||||
: undefined;
|
||||
return new util_1.ResultSetImpl(columns, columnTypes, rows, rowsAffected, lastInsertRowid);
|
||||
}
|
||||
exports.resultSetFromHrana = resultSetFromHrana;
|
||||
function mapHranaError(e) {
|
||||
if (e instanceof hrana.ClientError) {
|
||||
const code = mapHranaErrorCode(e);
|
||||
return new api_1.LibsqlError(e.message, code, undefined, e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
exports.mapHranaError = mapHranaError;
|
||||
function mapHranaErrorCode(e) {
|
||||
if (e instanceof hrana.ResponseError && e.code !== undefined) {
|
||||
return e.code;
|
||||
}
|
||||
else if (e instanceof hrana.ProtoError) {
|
||||
return "HRANA_PROTO_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.ClosedError) {
|
||||
return e.cause instanceof hrana.ClientError
|
||||
? mapHranaErrorCode(e.cause)
|
||||
: "HRANA_CLOSED_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.WebSocketError) {
|
||||
return "HRANA_WEBSOCKET_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.HttpServerError) {
|
||||
return "SERVER_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.ProtocolVersionError) {
|
||||
return "PROTOCOL_VERSION_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.InternalError) {
|
||||
return "INTERNAL_ERROR";
|
||||
}
|
||||
else {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
266
node_modules/@libsql/client/lib-cjs/http.js
generated
vendored
Normal file
266
node_modules/@libsql/client/lib-cjs/http.js
generated
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HttpTransaction = exports.HttpClient = exports._createClient = exports.createClient = void 0;
|
||||
const hrana = __importStar(require("@libsql/hrana-client"));
|
||||
const api_1 = require("@libsql/core/api");
|
||||
const config_1 = require("@libsql/core/config");
|
||||
const hrana_js_1 = require("./hrana.js");
|
||||
const sql_cache_js_1 = require("./sql_cache.js");
|
||||
const uri_1 = require("@libsql/core/uri");
|
||||
const util_1 = require("@libsql/core/util");
|
||||
const promise_limit_1 = __importDefault(require("promise-limit"));
|
||||
__exportStar(require("@libsql/core/api"), exports);
|
||||
function createClient(config) {
|
||||
return _createClient((0, config_1.expandConfig)(config, true));
|
||||
}
|
||||
exports.createClient = createClient;
|
||||
/** @private */
|
||||
function _createClient(config) {
|
||||
if (config.scheme !== "https" && config.scheme !== "http") {
|
||||
throw new api_1.LibsqlError('The HTTP client supports only "libsql:", "https:" and "http:" URLs, ' +
|
||||
`got ${JSON.stringify(config.scheme + ":")}. For more information, please read ${util_1.supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
if (config.encryptionKey !== undefined) {
|
||||
throw new api_1.LibsqlError("Encryption key is not supported by the remote client.", "ENCRYPTION_KEY_NOT_SUPPORTED");
|
||||
}
|
||||
if (config.scheme === "http" && config.tls) {
|
||||
throw new api_1.LibsqlError(`A "http:" URL cannot opt into TLS by using ?tls=1`, "URL_INVALID");
|
||||
}
|
||||
else if (config.scheme === "https" && !config.tls) {
|
||||
throw new api_1.LibsqlError(`A "https:" URL cannot opt out of TLS by using ?tls=0`, "URL_INVALID");
|
||||
}
|
||||
const url = (0, uri_1.encodeBaseUrl)(config.scheme, config.authority, config.path);
|
||||
return new HttpClient(url, config.authToken, config.intMode, config.fetch, config.concurrency);
|
||||
}
|
||||
exports._createClient = _createClient;
|
||||
const sqlCacheCapacity = 30;
|
||||
class HttpClient {
|
||||
#client;
|
||||
protocol;
|
||||
#url;
|
||||
#intMode;
|
||||
#customFetch;
|
||||
#concurrency;
|
||||
#authToken;
|
||||
#promiseLimitFunction;
|
||||
/** @private */
|
||||
constructor(url, authToken, intMode, customFetch, concurrency) {
|
||||
this.#url = url;
|
||||
this.#authToken = authToken;
|
||||
this.#intMode = intMode;
|
||||
this.#customFetch = customFetch;
|
||||
this.#concurrency = concurrency;
|
||||
this.#client = hrana.openHttp(this.#url, this.#authToken, this.#customFetch);
|
||||
this.#client.intMode = this.#intMode;
|
||||
this.protocol = "http";
|
||||
this.#promiseLimitFunction = (0, promise_limit_1.default)(this.#concurrency);
|
||||
}
|
||||
async limit(fn) {
|
||||
return this.#promiseLimitFunction(fn);
|
||||
}
|
||||
async execute(stmtOrSql, args) {
|
||||
let stmt;
|
||||
if (typeof stmtOrSql === "string") {
|
||||
stmt = {
|
||||
sql: stmtOrSql,
|
||||
args: args || [],
|
||||
};
|
||||
}
|
||||
else {
|
||||
stmt = stmtOrSql;
|
||||
}
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
const hranaStmt = (0, hrana_js_1.stmtToHrana)(stmt);
|
||||
// Pipeline all operations, so `hrana.HttpClient` can open the stream, execute the statement and
|
||||
// close the stream in a single HTTP request.
|
||||
let rowsPromise;
|
||||
const stream = this.#client.openStream();
|
||||
try {
|
||||
rowsPromise = stream.query(hranaStmt);
|
||||
}
|
||||
finally {
|
||||
stream.closeGracefully();
|
||||
}
|
||||
const rowsResult = await rowsPromise;
|
||||
return (0, hrana_js_1.resultSetFromHrana)(rowsResult);
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async batch(stmts, mode = "deferred") {
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
const normalizedStmts = stmts.map((stmt) => {
|
||||
if (Array.isArray(stmt)) {
|
||||
return {
|
||||
sql: stmt[0],
|
||||
args: stmt[1] || [],
|
||||
};
|
||||
}
|
||||
return stmt;
|
||||
});
|
||||
const hranaStmts = normalizedStmts.map(hrana_js_1.stmtToHrana);
|
||||
const version = await this.#client.getVersion();
|
||||
// Pipeline all operations, so `hrana.HttpClient` can open the stream, execute the batch and
|
||||
// close the stream in a single HTTP request.
|
||||
let resultsPromise;
|
||||
const stream = this.#client.openStream();
|
||||
try {
|
||||
// It makes sense to use a SQL cache even for a single batch, because it may contain the same
|
||||
// statement repeated multiple times.
|
||||
const sqlCache = new sql_cache_js_1.SqlCache(stream, sqlCacheCapacity);
|
||||
sqlCache.apply(hranaStmts);
|
||||
// TODO: we do not use a cursor here, because it would cause three roundtrips:
|
||||
// 1. pipeline request to store SQL texts
|
||||
// 2. cursor request
|
||||
// 3. pipeline request to close the stream
|
||||
const batch = stream.batch(false);
|
||||
resultsPromise = (0, hrana_js_1.executeHranaBatch)(mode, version, batch, hranaStmts);
|
||||
}
|
||||
finally {
|
||||
stream.closeGracefully();
|
||||
}
|
||||
const results = await resultsPromise;
|
||||
return results;
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async migrate(stmts) {
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
const hranaStmts = stmts.map(hrana_js_1.stmtToHrana);
|
||||
const version = await this.#client.getVersion();
|
||||
// Pipeline all operations, so `hrana.HttpClient` can open the stream, execute the batch and
|
||||
// close the stream in a single HTTP request.
|
||||
let resultsPromise;
|
||||
const stream = this.#client.openStream();
|
||||
try {
|
||||
const batch = stream.batch(false);
|
||||
resultsPromise = (0, hrana_js_1.executeHranaBatch)("deferred", version, batch, hranaStmts, true);
|
||||
}
|
||||
finally {
|
||||
stream.closeGracefully();
|
||||
}
|
||||
const results = await resultsPromise;
|
||||
return results;
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async transaction(mode = "write") {
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
const version = await this.#client.getVersion();
|
||||
return new HttpTransaction(this.#client.openStream(), mode, version);
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
// Pipeline all operations, so `hrana.HttpClient` can open the stream, execute the sequence and
|
||||
// close the stream in a single HTTP request.
|
||||
let promise;
|
||||
const stream = this.#client.openStream();
|
||||
try {
|
||||
promise = stream.sequence(sql);
|
||||
}
|
||||
finally {
|
||||
stream.closeGracefully();
|
||||
}
|
||||
await promise;
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
sync() {
|
||||
throw new api_1.LibsqlError("sync not supported in http mode", "SYNC_NOT_SUPPORTED");
|
||||
}
|
||||
close() {
|
||||
this.#client.close();
|
||||
}
|
||||
async reconnect() {
|
||||
try {
|
||||
if (!this.closed) {
|
||||
// Abort in-flight ops and free resources
|
||||
this.#client.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Recreate the underlying hrana client
|
||||
this.#client = hrana.openHttp(this.#url, this.#authToken, this.#customFetch);
|
||||
this.#client.intMode = this.#intMode;
|
||||
}
|
||||
}
|
||||
get closed() {
|
||||
return this.#client.closed;
|
||||
}
|
||||
}
|
||||
exports.HttpClient = HttpClient;
|
||||
class HttpTransaction extends hrana_js_1.HranaTransaction {
|
||||
#stream;
|
||||
#sqlCache;
|
||||
/** @private */
|
||||
constructor(stream, mode, version) {
|
||||
super(mode, version);
|
||||
this.#stream = stream;
|
||||
this.#sqlCache = new sql_cache_js_1.SqlCache(stream, sqlCacheCapacity);
|
||||
}
|
||||
/** @private */
|
||||
_getStream() {
|
||||
return this.#stream;
|
||||
}
|
||||
/** @private */
|
||||
_getSqlCache() {
|
||||
return this.#sqlCache;
|
||||
}
|
||||
close() {
|
||||
this.#stream.close();
|
||||
}
|
||||
get closed() {
|
||||
return this.#stream.closed;
|
||||
}
|
||||
}
|
||||
exports.HttpTransaction = HttpTransaction;
|
||||
41
node_modules/@libsql/client/lib-cjs/node.js
generated
vendored
Normal file
41
node_modules/@libsql/client/lib-cjs/node.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createClient = void 0;
|
||||
const config_1 = require("@libsql/core/config");
|
||||
const sqlite3_js_1 = require("./sqlite3.js");
|
||||
const ws_js_1 = require("./ws.js");
|
||||
const http_js_1 = require("./http.js");
|
||||
__exportStar(require("@libsql/core/api"), exports);
|
||||
/** Creates a {@link Client} object.
|
||||
*
|
||||
* You must pass at least an `url` in the {@link Config} object.
|
||||
*/
|
||||
function createClient(config) {
|
||||
return _createClient((0, config_1.expandConfig)(config, true));
|
||||
}
|
||||
exports.createClient = createClient;
|
||||
function _createClient(config) {
|
||||
if (config.scheme === "wss" || config.scheme === "ws") {
|
||||
return (0, ws_js_1._createClient)(config);
|
||||
}
|
||||
else if (config.scheme === "https" || config.scheme === "http") {
|
||||
return (0, http_js_1._createClient)(config);
|
||||
}
|
||||
else {
|
||||
return (0, sqlite3_js_1._createClient)(config);
|
||||
}
|
||||
}
|
||||
3
node_modules/@libsql/client/lib-cjs/package.json
generated
vendored
Normal file
3
node_modules/@libsql/client/lib-cjs/package.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
91
node_modules/@libsql/client/lib-cjs/sql_cache.js
generated
vendored
Normal file
91
node_modules/@libsql/client/lib-cjs/sql_cache.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SqlCache = void 0;
|
||||
class SqlCache {
|
||||
#owner;
|
||||
#sqls;
|
||||
capacity;
|
||||
constructor(owner, capacity) {
|
||||
this.#owner = owner;
|
||||
this.#sqls = new Lru();
|
||||
this.capacity = capacity;
|
||||
}
|
||||
// Replaces SQL strings with cached `hrana.Sql` objects in the statements in `hranaStmts`. After this
|
||||
// function returns, we guarantee that all `hranaStmts` refer to valid (not closed) `hrana.Sql` objects,
|
||||
// but _we may invalidate any other `hrana.Sql` objects_ (by closing them, thus removing them from the
|
||||
// server).
|
||||
//
|
||||
// In practice, this means that after calling this function, you can use the statements only up to the
|
||||
// first `await`, because concurrent code may also use the cache and invalidate those statements.
|
||||
apply(hranaStmts) {
|
||||
if (this.capacity <= 0) {
|
||||
return;
|
||||
}
|
||||
const usedSqlObjs = new Set();
|
||||
for (const hranaStmt of hranaStmts) {
|
||||
if (typeof hranaStmt.sql !== "string") {
|
||||
continue;
|
||||
}
|
||||
const sqlText = hranaStmt.sql;
|
||||
// Stored SQL cannot exceed 5kb.
|
||||
// https://github.com/tursodatabase/libsql/blob/e9d637e051685f92b0da43849507b5ef4232fbeb/libsql-server/src/hrana/http/request.rs#L10
|
||||
if (sqlText.length >= 5000) {
|
||||
continue;
|
||||
}
|
||||
let sqlObj = this.#sqls.get(sqlText);
|
||||
if (sqlObj === undefined) {
|
||||
while (this.#sqls.size + 1 > this.capacity) {
|
||||
const [evictSqlText, evictSqlObj] = this.#sqls.peekLru();
|
||||
if (usedSqlObjs.has(evictSqlObj)) {
|
||||
// The SQL object that we are trying to evict is already in use in this batch, so we
|
||||
// must not evict and close it.
|
||||
break;
|
||||
}
|
||||
evictSqlObj.close();
|
||||
this.#sqls.delete(evictSqlText);
|
||||
}
|
||||
if (this.#sqls.size + 1 <= this.capacity) {
|
||||
sqlObj = this.#owner.storeSql(sqlText);
|
||||
this.#sqls.set(sqlText, sqlObj);
|
||||
}
|
||||
}
|
||||
if (sqlObj !== undefined) {
|
||||
hranaStmt.sql = sqlObj;
|
||||
usedSqlObjs.add(sqlObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.SqlCache = SqlCache;
|
||||
class Lru {
|
||||
// This maps keys to the cache values. The entries are ordered by their last use (entires that were used
|
||||
// most recently are at the end).
|
||||
#cache;
|
||||
constructor() {
|
||||
this.#cache = new Map();
|
||||
}
|
||||
get(key) {
|
||||
const value = this.#cache.get(key);
|
||||
if (value !== undefined) {
|
||||
// move the entry to the back of the Map
|
||||
this.#cache.delete(key);
|
||||
this.#cache.set(key, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
set(key, value) {
|
||||
this.#cache.set(key, value);
|
||||
}
|
||||
peekLru() {
|
||||
for (const entry of this.#cache.entries()) {
|
||||
return entry;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
delete(key) {
|
||||
this.#cache.delete(key);
|
||||
}
|
||||
get size() {
|
||||
return this.#cache.size;
|
||||
}
|
||||
}
|
||||
419
node_modules/@libsql/client/lib-cjs/sqlite3.js
generated
vendored
Normal file
419
node_modules/@libsql/client/lib-cjs/sqlite3.js
generated
vendored
Normal file
@@ -0,0 +1,419 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Sqlite3Transaction = exports.Sqlite3Client = exports._createClient = exports.createClient = void 0;
|
||||
const libsql_1 = __importDefault(require("libsql"));
|
||||
const node_buffer_1 = require("node:buffer");
|
||||
const api_1 = require("@libsql/core/api");
|
||||
const config_1 = require("@libsql/core/config");
|
||||
const util_1 = require("@libsql/core/util");
|
||||
__exportStar(require("@libsql/core/api"), exports);
|
||||
function createClient(config) {
|
||||
return _createClient((0, config_1.expandConfig)(config, true));
|
||||
}
|
||||
exports.createClient = createClient;
|
||||
/** @private */
|
||||
function _createClient(config) {
|
||||
if (config.scheme !== "file") {
|
||||
throw new api_1.LibsqlError(`URL scheme ${JSON.stringify(config.scheme + ":")} is not supported by the local sqlite3 client. ` +
|
||||
`For more information, please read ${util_1.supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
const authority = config.authority;
|
||||
if (authority !== undefined) {
|
||||
const host = authority.host.toLowerCase();
|
||||
if (host !== "" && host !== "localhost") {
|
||||
throw new api_1.LibsqlError(`Invalid host in file URL: ${JSON.stringify(authority.host)}. ` +
|
||||
'A "file:" URL with an absolute path should start with one slash ("file:/absolute/path.db") ' +
|
||||
'or with three slashes ("file:///absolute/path.db"). ' +
|
||||
`For more information, please read ${util_1.supportedUrlLink}`, "URL_INVALID");
|
||||
}
|
||||
if (authority.port !== undefined) {
|
||||
throw new api_1.LibsqlError("File URL cannot have a port", "URL_INVALID");
|
||||
}
|
||||
if (authority.userinfo !== undefined) {
|
||||
throw new api_1.LibsqlError("File URL cannot have username and password", "URL_INVALID");
|
||||
}
|
||||
}
|
||||
let isInMemory = (0, config_1.isInMemoryConfig)(config);
|
||||
if (isInMemory && config.syncUrl) {
|
||||
throw new api_1.LibsqlError(`Embedded replica must use file for local db but URI with in-memory mode were provided instead: ${config.path}`, "URL_INVALID");
|
||||
}
|
||||
let path = config.path;
|
||||
if (isInMemory) {
|
||||
// note: we should prepend file scheme in order for SQLite3 to recognize :memory: connection query parameters
|
||||
path = `${config.scheme}:${config.path}`;
|
||||
}
|
||||
const options = {
|
||||
authToken: config.authToken,
|
||||
encryptionKey: config.encryptionKey,
|
||||
syncUrl: config.syncUrl,
|
||||
syncPeriod: config.syncInterval,
|
||||
readYourWrites: config.readYourWrites,
|
||||
offline: config.offline,
|
||||
};
|
||||
const db = new libsql_1.default(path, options);
|
||||
executeStmt(db, "SELECT 1 AS checkThatTheDatabaseCanBeOpened", config.intMode);
|
||||
return new Sqlite3Client(path, options, db, config.intMode);
|
||||
}
|
||||
exports._createClient = _createClient;
|
||||
class Sqlite3Client {
|
||||
#path;
|
||||
#options;
|
||||
#db;
|
||||
#intMode;
|
||||
closed;
|
||||
protocol;
|
||||
/** @private */
|
||||
constructor(path, options, db, intMode) {
|
||||
this.#path = path;
|
||||
this.#options = options;
|
||||
this.#db = db;
|
||||
this.#intMode = intMode;
|
||||
this.closed = false;
|
||||
this.protocol = "file";
|
||||
}
|
||||
async execute(stmtOrSql, args) {
|
||||
let stmt;
|
||||
if (typeof stmtOrSql === "string") {
|
||||
stmt = {
|
||||
sql: stmtOrSql,
|
||||
args: args || [],
|
||||
};
|
||||
}
|
||||
else {
|
||||
stmt = stmtOrSql;
|
||||
}
|
||||
this.#checkNotClosed();
|
||||
return executeStmt(this.#getDb(), stmt, this.#intMode);
|
||||
}
|
||||
async batch(stmts, mode = "deferred") {
|
||||
this.#checkNotClosed();
|
||||
const db = this.#getDb();
|
||||
try {
|
||||
executeStmt(db, (0, util_1.transactionModeToBegin)(mode), this.#intMode);
|
||||
const resultSets = stmts.map((stmt) => {
|
||||
if (!db.inTransaction) {
|
||||
throw new api_1.LibsqlError("The transaction has been rolled back", "TRANSACTION_CLOSED");
|
||||
}
|
||||
const normalizedStmt = Array.isArray(stmt)
|
||||
? { sql: stmt[0], args: stmt[1] || [] }
|
||||
: stmt;
|
||||
return executeStmt(db, normalizedStmt, this.#intMode);
|
||||
});
|
||||
executeStmt(db, "COMMIT", this.#intMode);
|
||||
return resultSets;
|
||||
}
|
||||
finally {
|
||||
if (db.inTransaction) {
|
||||
executeStmt(db, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
async migrate(stmts) {
|
||||
this.#checkNotClosed();
|
||||
const db = this.#getDb();
|
||||
try {
|
||||
executeStmt(db, "PRAGMA foreign_keys=off", this.#intMode);
|
||||
executeStmt(db, (0, util_1.transactionModeToBegin)("deferred"), this.#intMode);
|
||||
const resultSets = stmts.map((stmt) => {
|
||||
if (!db.inTransaction) {
|
||||
throw new api_1.LibsqlError("The transaction has been rolled back", "TRANSACTION_CLOSED");
|
||||
}
|
||||
return executeStmt(db, stmt, this.#intMode);
|
||||
});
|
||||
executeStmt(db, "COMMIT", this.#intMode);
|
||||
return resultSets;
|
||||
}
|
||||
finally {
|
||||
if (db.inTransaction) {
|
||||
executeStmt(db, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
executeStmt(db, "PRAGMA foreign_keys=on", this.#intMode);
|
||||
}
|
||||
}
|
||||
async transaction(mode = "write") {
|
||||
const db = this.#getDb();
|
||||
executeStmt(db, (0, util_1.transactionModeToBegin)(mode), this.#intMode);
|
||||
this.#db = null; // A new connection will be lazily created on next use
|
||||
return new Sqlite3Transaction(db, this.#intMode);
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
this.#checkNotClosed();
|
||||
const db = this.#getDb();
|
||||
try {
|
||||
return executeMultiple(db, sql);
|
||||
}
|
||||
finally {
|
||||
if (db.inTransaction) {
|
||||
executeStmt(db, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
async sync() {
|
||||
this.#checkNotClosed();
|
||||
const rep = await this.#getDb().sync();
|
||||
return {
|
||||
frames_synced: rep.frames_synced,
|
||||
frame_no: rep.frame_no,
|
||||
};
|
||||
}
|
||||
async reconnect() {
|
||||
try {
|
||||
if (!this.closed && this.#db !== null) {
|
||||
this.#db.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.#db = new libsql_1.default(this.#path, this.#options);
|
||||
this.closed = false;
|
||||
}
|
||||
}
|
||||
close() {
|
||||
this.closed = true;
|
||||
if (this.#db !== null) {
|
||||
this.#db.close();
|
||||
this.#db = null;
|
||||
}
|
||||
}
|
||||
#checkNotClosed() {
|
||||
if (this.closed) {
|
||||
throw new api_1.LibsqlError("The client is closed", "CLIENT_CLOSED");
|
||||
}
|
||||
}
|
||||
// Lazily creates the database connection and returns it
|
||||
#getDb() {
|
||||
if (this.#db === null) {
|
||||
this.#db = new libsql_1.default(this.#path, this.#options);
|
||||
}
|
||||
return this.#db;
|
||||
}
|
||||
}
|
||||
exports.Sqlite3Client = Sqlite3Client;
|
||||
class Sqlite3Transaction {
|
||||
#database;
|
||||
#intMode;
|
||||
/** @private */
|
||||
constructor(database, intMode) {
|
||||
this.#database = database;
|
||||
this.#intMode = intMode;
|
||||
}
|
||||
async execute(stmtOrSql, args) {
|
||||
let stmt;
|
||||
if (typeof stmtOrSql === "string") {
|
||||
stmt = {
|
||||
sql: stmtOrSql,
|
||||
args: args || [],
|
||||
};
|
||||
}
|
||||
else {
|
||||
stmt = stmtOrSql;
|
||||
}
|
||||
this.#checkNotClosed();
|
||||
return executeStmt(this.#database, stmt, this.#intMode);
|
||||
}
|
||||
async batch(stmts) {
|
||||
return stmts.map((stmt) => {
|
||||
this.#checkNotClosed();
|
||||
const normalizedStmt = Array.isArray(stmt)
|
||||
? { sql: stmt[0], args: stmt[1] || [] }
|
||||
: stmt;
|
||||
return executeStmt(this.#database, normalizedStmt, this.#intMode);
|
||||
});
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
this.#checkNotClosed();
|
||||
return executeMultiple(this.#database, sql);
|
||||
}
|
||||
async rollback() {
|
||||
if (!this.#database.open) {
|
||||
return;
|
||||
}
|
||||
this.#checkNotClosed();
|
||||
executeStmt(this.#database, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
async commit() {
|
||||
this.#checkNotClosed();
|
||||
executeStmt(this.#database, "COMMIT", this.#intMode);
|
||||
}
|
||||
close() {
|
||||
if (this.#database.inTransaction) {
|
||||
executeStmt(this.#database, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
}
|
||||
get closed() {
|
||||
return !this.#database.inTransaction;
|
||||
}
|
||||
#checkNotClosed() {
|
||||
if (this.closed) {
|
||||
throw new api_1.LibsqlError("The transaction is closed", "TRANSACTION_CLOSED");
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Sqlite3Transaction = Sqlite3Transaction;
|
||||
function executeStmt(db, stmt, intMode) {
|
||||
let sql;
|
||||
let args;
|
||||
if (typeof stmt === "string") {
|
||||
sql = stmt;
|
||||
args = [];
|
||||
}
|
||||
else {
|
||||
sql = stmt.sql;
|
||||
if (Array.isArray(stmt.args)) {
|
||||
args = stmt.args.map((value) => valueToSql(value, intMode));
|
||||
}
|
||||
else {
|
||||
args = {};
|
||||
for (const name in stmt.args) {
|
||||
const argName = name[0] === "@" || name[0] === "$" || name[0] === ":"
|
||||
? name.substring(1)
|
||||
: name;
|
||||
args[argName] = valueToSql(stmt.args[name], intMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
const sqlStmt = db.prepare(sql);
|
||||
sqlStmt.safeIntegers(true);
|
||||
let returnsData = true;
|
||||
try {
|
||||
sqlStmt.raw(true);
|
||||
}
|
||||
catch {
|
||||
// raw() throws an exception if the statement does not return data
|
||||
returnsData = false;
|
||||
}
|
||||
if (returnsData) {
|
||||
const columns = Array.from(sqlStmt.columns().map((col) => col.name));
|
||||
const columnTypes = Array.from(sqlStmt.columns().map((col) => col.type ?? ""));
|
||||
const rows = sqlStmt.all(args).map((sqlRow) => {
|
||||
return rowFromSql(sqlRow, columns, intMode);
|
||||
});
|
||||
// TODO: can we get this info from better-sqlite3?
|
||||
const rowsAffected = 0;
|
||||
const lastInsertRowid = undefined;
|
||||
return new util_1.ResultSetImpl(columns, columnTypes, rows, rowsAffected, lastInsertRowid);
|
||||
}
|
||||
else {
|
||||
const info = sqlStmt.run(args);
|
||||
const rowsAffected = info.changes;
|
||||
const lastInsertRowid = BigInt(info.lastInsertRowid);
|
||||
return new util_1.ResultSetImpl([], [], [], rowsAffected, lastInsertRowid);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw mapSqliteError(e);
|
||||
}
|
||||
}
|
||||
function rowFromSql(sqlRow, columns, intMode) {
|
||||
const row = {};
|
||||
// make sure that the "length" property is not enumerable
|
||||
Object.defineProperty(row, "length", { value: sqlRow.length });
|
||||
for (let i = 0; i < sqlRow.length; ++i) {
|
||||
const value = valueFromSql(sqlRow[i], intMode);
|
||||
Object.defineProperty(row, i, { value });
|
||||
const column = columns[i];
|
||||
if (!Object.hasOwn(row, column)) {
|
||||
Object.defineProperty(row, column, {
|
||||
value,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
function valueFromSql(sqlValue, intMode) {
|
||||
if (typeof sqlValue === "bigint") {
|
||||
if (intMode === "number") {
|
||||
if (sqlValue < minSafeBigint || sqlValue > maxSafeBigint) {
|
||||
throw new RangeError("Received integer which cannot be safely represented as a JavaScript number");
|
||||
}
|
||||
return Number(sqlValue);
|
||||
}
|
||||
else if (intMode === "bigint") {
|
||||
return sqlValue;
|
||||
}
|
||||
else if (intMode === "string") {
|
||||
return "" + sqlValue;
|
||||
}
|
||||
else {
|
||||
throw new Error("Invalid value for IntMode");
|
||||
}
|
||||
}
|
||||
else if (sqlValue instanceof node_buffer_1.Buffer) {
|
||||
return sqlValue.buffer;
|
||||
}
|
||||
return sqlValue;
|
||||
}
|
||||
const minSafeBigint = -9007199254740991n;
|
||||
const maxSafeBigint = 9007199254740991n;
|
||||
function valueToSql(value, intMode) {
|
||||
if (typeof value === "number") {
|
||||
if (!Number.isFinite(value)) {
|
||||
throw new RangeError("Only finite numbers (not Infinity or NaN) can be passed as arguments");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "bigint") {
|
||||
if (value < minInteger || value > maxInteger) {
|
||||
throw new RangeError("bigint is too large to be represented as a 64-bit integer and passed as argument");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
switch (intMode) {
|
||||
case "bigint":
|
||||
return value ? 1n : 0n;
|
||||
case "string":
|
||||
return value ? "1" : "0";
|
||||
default:
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
}
|
||||
else if (value instanceof ArrayBuffer) {
|
||||
return node_buffer_1.Buffer.from(value);
|
||||
}
|
||||
else if (value instanceof Date) {
|
||||
return value.valueOf();
|
||||
}
|
||||
else if (value === undefined) {
|
||||
throw new TypeError("undefined cannot be passed as argument to the database");
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
const minInteger = -9223372036854775808n;
|
||||
const maxInteger = 9223372036854775807n;
|
||||
function executeMultiple(db, sql) {
|
||||
try {
|
||||
db.exec(sql);
|
||||
}
|
||||
catch (e) {
|
||||
throw mapSqliteError(e);
|
||||
}
|
||||
}
|
||||
function mapSqliteError(e) {
|
||||
if (e instanceof libsql_1.default.SqliteError) {
|
||||
return new api_1.LibsqlError(e.message, e.code, e.rawCode, e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
41
node_modules/@libsql/client/lib-cjs/web.js
generated
vendored
Normal file
41
node_modules/@libsql/client/lib-cjs/web.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports._createClient = exports.createClient = void 0;
|
||||
const api_1 = require("@libsql/core/api");
|
||||
const config_1 = require("@libsql/core/config");
|
||||
const util_1 = require("@libsql/core/util");
|
||||
const ws_js_1 = require("./ws.js");
|
||||
const http_js_1 = require("./http.js");
|
||||
__exportStar(require("@libsql/core/api"), exports);
|
||||
function createClient(config) {
|
||||
return _createClient((0, config_1.expandConfig)(config, true));
|
||||
}
|
||||
exports.createClient = createClient;
|
||||
/** @private */
|
||||
function _createClient(config) {
|
||||
if (config.scheme === "ws" || config.scheme === "wss") {
|
||||
return (0, ws_js_1._createClient)(config);
|
||||
}
|
||||
else if (config.scheme === "http" || config.scheme === "https") {
|
||||
return (0, http_js_1._createClient)(config);
|
||||
}
|
||||
else {
|
||||
throw new api_1.LibsqlError('The client that uses Web standard APIs supports only "libsql:", "wss:", "ws:", "https:" and "http:" URLs, ' +
|
||||
`got ${JSON.stringify(config.scheme + ":")}. For more information, please read ${util_1.supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
}
|
||||
exports._createClient = _createClient;
|
||||
395
node_modules/@libsql/client/lib-cjs/ws.js
generated
vendored
Normal file
395
node_modules/@libsql/client/lib-cjs/ws.js
generated
vendored
Normal file
@@ -0,0 +1,395 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WsTransaction = exports.WsClient = exports._createClient = exports.createClient = void 0;
|
||||
const hrana = __importStar(require("@libsql/hrana-client"));
|
||||
const api_1 = require("@libsql/core/api");
|
||||
const config_1 = require("@libsql/core/config");
|
||||
const hrana_js_1 = require("./hrana.js");
|
||||
const sql_cache_js_1 = require("./sql_cache.js");
|
||||
const uri_1 = require("@libsql/core/uri");
|
||||
const util_1 = require("@libsql/core/util");
|
||||
const promise_limit_1 = __importDefault(require("promise-limit"));
|
||||
__exportStar(require("@libsql/core/api"), exports);
|
||||
function createClient(config) {
|
||||
return _createClient((0, config_1.expandConfig)(config, false));
|
||||
}
|
||||
exports.createClient = createClient;
|
||||
/** @private */
|
||||
function _createClient(config) {
|
||||
if (config.scheme !== "wss" && config.scheme !== "ws") {
|
||||
throw new api_1.LibsqlError('The WebSocket client supports only "libsql:", "wss:" and "ws:" URLs, ' +
|
||||
`got ${JSON.stringify(config.scheme + ":")}. For more information, please read ${util_1.supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
if (config.encryptionKey !== undefined) {
|
||||
throw new api_1.LibsqlError("Encryption key is not supported by the remote client.", "ENCRYPTION_KEY_NOT_SUPPORTED");
|
||||
}
|
||||
if (config.scheme === "ws" && config.tls) {
|
||||
throw new api_1.LibsqlError(`A "ws:" URL cannot opt into TLS by using ?tls=1`, "URL_INVALID");
|
||||
}
|
||||
else if (config.scheme === "wss" && !config.tls) {
|
||||
throw new api_1.LibsqlError(`A "wss:" URL cannot opt out of TLS by using ?tls=0`, "URL_INVALID");
|
||||
}
|
||||
const url = (0, uri_1.encodeBaseUrl)(config.scheme, config.authority, config.path);
|
||||
let client;
|
||||
try {
|
||||
client = hrana.openWs(url, config.authToken);
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof hrana.WebSocketUnsupportedError) {
|
||||
const suggestedScheme = config.scheme === "wss" ? "https" : "http";
|
||||
const suggestedUrl = (0, uri_1.encodeBaseUrl)(suggestedScheme, config.authority, config.path);
|
||||
throw new api_1.LibsqlError("This environment does not support WebSockets, please switch to the HTTP client by using " +
|
||||
`a "${suggestedScheme}:" URL (${JSON.stringify(suggestedUrl)}). ` +
|
||||
`For more information, please read ${util_1.supportedUrlLink}`, "WEBSOCKETS_NOT_SUPPORTED");
|
||||
}
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
return new WsClient(client, url, config.authToken, config.intMode, config.concurrency);
|
||||
}
|
||||
exports._createClient = _createClient;
|
||||
const maxConnAgeMillis = 60 * 1000;
|
||||
const sqlCacheCapacity = 100;
|
||||
class WsClient {
|
||||
#url;
|
||||
#authToken;
|
||||
#intMode;
|
||||
// State of the current connection. The `hrana.WsClient` inside may be closed at any moment due to an
|
||||
// asynchronous error.
|
||||
#connState;
|
||||
// If defined, this is a connection that will be used in the future, once it is ready.
|
||||
#futureConnState;
|
||||
closed;
|
||||
protocol;
|
||||
#isSchemaDatabase;
|
||||
#promiseLimitFunction;
|
||||
/** @private */
|
||||
constructor(client, url, authToken, intMode, concurrency) {
|
||||
this.#url = url;
|
||||
this.#authToken = authToken;
|
||||
this.#intMode = intMode;
|
||||
this.#connState = this.#openConn(client);
|
||||
this.#futureConnState = undefined;
|
||||
this.closed = false;
|
||||
this.protocol = "ws";
|
||||
this.#promiseLimitFunction = (0, promise_limit_1.default)(concurrency);
|
||||
}
|
||||
async limit(fn) {
|
||||
return this.#promiseLimitFunction(fn);
|
||||
}
|
||||
async execute(stmtOrSql, args) {
|
||||
let stmt;
|
||||
if (typeof stmtOrSql === "string") {
|
||||
stmt = {
|
||||
sql: stmtOrSql,
|
||||
args: args || [],
|
||||
};
|
||||
}
|
||||
else {
|
||||
stmt = stmtOrSql;
|
||||
}
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
const hranaStmt = (0, hrana_js_1.stmtToHrana)(stmt);
|
||||
// Schedule all operations synchronously, so they will be pipelined and executed in a single
|
||||
// network roundtrip.
|
||||
streamState.conn.sqlCache.apply([hranaStmt]);
|
||||
const hranaRowsPromise = streamState.stream.query(hranaStmt);
|
||||
streamState.stream.closeGracefully();
|
||||
const hranaRowsResult = await hranaRowsPromise;
|
||||
return (0, hrana_js_1.resultSetFromHrana)(hranaRowsResult);
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
finally {
|
||||
this._closeStream(streamState);
|
||||
}
|
||||
});
|
||||
}
|
||||
async batch(stmts, mode = "deferred") {
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
const normalizedStmts = stmts.map((stmt) => {
|
||||
if (Array.isArray(stmt)) {
|
||||
return {
|
||||
sql: stmt[0],
|
||||
args: stmt[1] || [],
|
||||
};
|
||||
}
|
||||
return stmt;
|
||||
});
|
||||
const hranaStmts = normalizedStmts.map(hrana_js_1.stmtToHrana);
|
||||
const version = await streamState.conn.client.getVersion();
|
||||
// Schedule all operations synchronously, so they will be pipelined and executed in a single
|
||||
// network roundtrip.
|
||||
streamState.conn.sqlCache.apply(hranaStmts);
|
||||
const batch = streamState.stream.batch(version >= 3);
|
||||
const resultsPromise = (0, hrana_js_1.executeHranaBatch)(mode, version, batch, hranaStmts);
|
||||
const results = await resultsPromise;
|
||||
return results;
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
finally {
|
||||
this._closeStream(streamState);
|
||||
}
|
||||
});
|
||||
}
|
||||
async migrate(stmts) {
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
const hranaStmts = stmts.map(hrana_js_1.stmtToHrana);
|
||||
const version = await streamState.conn.client.getVersion();
|
||||
// Schedule all operations synchronously, so they will be pipelined and executed in a single
|
||||
// network roundtrip.
|
||||
const batch = streamState.stream.batch(version >= 3);
|
||||
const resultsPromise = (0, hrana_js_1.executeHranaBatch)("deferred", version, batch, hranaStmts, true);
|
||||
const results = await resultsPromise;
|
||||
return results;
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
finally {
|
||||
this._closeStream(streamState);
|
||||
}
|
||||
});
|
||||
}
|
||||
async transaction(mode = "write") {
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
const version = await streamState.conn.client.getVersion();
|
||||
// the BEGIN statement will be batched with the first statement on the transaction to save a
|
||||
// network roundtrip
|
||||
return new WsTransaction(this, streamState, mode, version);
|
||||
}
|
||||
catch (e) {
|
||||
this._closeStream(streamState);
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
// Schedule all operations synchronously, so they will be pipelined and executed in a single
|
||||
// network roundtrip.
|
||||
const promise = streamState.stream.sequence(sql);
|
||||
streamState.stream.closeGracefully();
|
||||
await promise;
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
finally {
|
||||
this._closeStream(streamState);
|
||||
}
|
||||
});
|
||||
}
|
||||
sync() {
|
||||
throw new api_1.LibsqlError("sync not supported in ws mode", "SYNC_NOT_SUPPORTED");
|
||||
}
|
||||
async #openStream() {
|
||||
if (this.closed) {
|
||||
throw new api_1.LibsqlError("The client is closed", "CLIENT_CLOSED");
|
||||
}
|
||||
const now = new Date();
|
||||
const ageMillis = now.valueOf() - this.#connState.openTime.valueOf();
|
||||
if (ageMillis > maxConnAgeMillis &&
|
||||
this.#futureConnState === undefined) {
|
||||
// The existing connection is too old, let's open a new one.
|
||||
const futureConnState = this.#openConn();
|
||||
this.#futureConnState = futureConnState;
|
||||
// However, if we used `futureConnState` immediately, we would introduce additional latency,
|
||||
// because we would have to wait for the WebSocket handshake to complete, even though we may a
|
||||
// have perfectly good existing connection in `this.#connState`!
|
||||
//
|
||||
// So we wait until the `hrana.Client.getVersion()` operation completes (which happens when the
|
||||
// WebSocket hanshake completes), and only then we replace `this.#connState` with
|
||||
// `futureConnState`, which is stored in `this.#futureConnState` in the meantime.
|
||||
futureConnState.client.getVersion().then((_version) => {
|
||||
if (this.#connState !== futureConnState) {
|
||||
// We need to close `this.#connState` before we replace it. However, it is possible
|
||||
// that `this.#connState` has already been replaced: see the code below.
|
||||
if (this.#connState.streamStates.size === 0) {
|
||||
this.#connState.client.close();
|
||||
}
|
||||
else {
|
||||
// If there are existing streams on the connection, we must not close it, because
|
||||
// these streams would be broken. The last stream to be closed will also close the
|
||||
// connection in `_closeStream()`.
|
||||
}
|
||||
}
|
||||
this.#connState = futureConnState;
|
||||
this.#futureConnState = undefined;
|
||||
}, (_e) => {
|
||||
// If the new connection could not be established, let's just ignore the error and keep
|
||||
// using the existing connection.
|
||||
this.#futureConnState = undefined;
|
||||
});
|
||||
}
|
||||
if (this.#connState.client.closed) {
|
||||
// An error happened on this connection and it has been closed. Let's try to seamlessly reconnect.
|
||||
try {
|
||||
if (this.#futureConnState !== undefined) {
|
||||
// We are already in the process of opening a new connection, so let's just use it
|
||||
// immediately.
|
||||
this.#connState = this.#futureConnState;
|
||||
}
|
||||
else {
|
||||
this.#connState = this.#openConn();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
}
|
||||
const connState = this.#connState;
|
||||
try {
|
||||
// Now we wait for the WebSocket handshake to complete (if it hasn't completed yet). Note that
|
||||
// this does not increase latency, because any messages that we would send on the WebSocket before
|
||||
// the handshake would be queued until the handshake is completed anyway.
|
||||
if (connState.useSqlCache === undefined) {
|
||||
connState.useSqlCache =
|
||||
(await connState.client.getVersion()) >= 2;
|
||||
if (connState.useSqlCache) {
|
||||
connState.sqlCache.capacity = sqlCacheCapacity;
|
||||
}
|
||||
}
|
||||
const stream = connState.client.openStream();
|
||||
stream.intMode = this.#intMode;
|
||||
const streamState = { conn: connState, stream };
|
||||
connState.streamStates.add(streamState);
|
||||
return streamState;
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
}
|
||||
#openConn(client) {
|
||||
try {
|
||||
client ??= hrana.openWs(this.#url, this.#authToken);
|
||||
return {
|
||||
client,
|
||||
useSqlCache: undefined,
|
||||
sqlCache: new sql_cache_js_1.SqlCache(client, 0),
|
||||
openTime: new Date(),
|
||||
streamStates: new Set(),
|
||||
};
|
||||
}
|
||||
catch (e) {
|
||||
throw (0, hrana_js_1.mapHranaError)(e);
|
||||
}
|
||||
}
|
||||
async reconnect() {
|
||||
try {
|
||||
for (const st of Array.from(this.#connState.streamStates)) {
|
||||
try {
|
||||
st.stream.close();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
this.#connState.client.close();
|
||||
}
|
||||
catch { }
|
||||
if (this.#futureConnState) {
|
||||
try {
|
||||
this.#futureConnState.client.close();
|
||||
}
|
||||
catch { }
|
||||
this.#futureConnState = undefined;
|
||||
}
|
||||
const next = this.#openConn();
|
||||
const version = await next.client.getVersion();
|
||||
next.useSqlCache = version >= 2;
|
||||
if (next.useSqlCache) {
|
||||
next.sqlCache.capacity = sqlCacheCapacity;
|
||||
}
|
||||
this.#connState = next;
|
||||
this.closed = false;
|
||||
}
|
||||
_closeStream(streamState) {
|
||||
streamState.stream.close();
|
||||
const connState = streamState.conn;
|
||||
connState.streamStates.delete(streamState);
|
||||
if (connState.streamStates.size === 0 &&
|
||||
connState !== this.#connState) {
|
||||
// We are not using this connection anymore and this is the last stream that was using it, so we
|
||||
// must close it now.
|
||||
connState.client.close();
|
||||
}
|
||||
}
|
||||
close() {
|
||||
this.#connState.client.close();
|
||||
this.closed = true;
|
||||
if (this.#futureConnState) {
|
||||
try {
|
||||
this.#futureConnState.client.close();
|
||||
}
|
||||
catch { }
|
||||
this.#futureConnState = undefined;
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
}
|
||||
exports.WsClient = WsClient;
|
||||
class WsTransaction extends hrana_js_1.HranaTransaction {
|
||||
#client;
|
||||
#streamState;
|
||||
/** @private */
|
||||
constructor(client, state, mode, version) {
|
||||
super(mode, version);
|
||||
this.#client = client;
|
||||
this.#streamState = state;
|
||||
}
|
||||
/** @private */
|
||||
_getStream() {
|
||||
return this.#streamState.stream;
|
||||
}
|
||||
/** @private */
|
||||
_getSqlCache() {
|
||||
return this.#streamState.conn.sqlCache;
|
||||
}
|
||||
close() {
|
||||
this.#client._closeStream(this.#streamState);
|
||||
}
|
||||
get closed() {
|
||||
return this.#streamState.stream.closed;
|
||||
}
|
||||
}
|
||||
exports.WsTransaction = WsTransaction;
|
||||
23
node_modules/@libsql/client/lib-esm/hrana.d.ts
generated
vendored
Normal file
23
node_modules/@libsql/client/lib-esm/hrana.d.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import * as hrana from "@libsql/hrana-client";
|
||||
import type { InStatement, ResultSet, Transaction, TransactionMode, InArgs } from "@libsql/core/api";
|
||||
import type { SqlCache } from "./sql_cache.js";
|
||||
export declare abstract class HranaTransaction implements Transaction {
|
||||
#private;
|
||||
/** @private */
|
||||
constructor(mode: TransactionMode, version: hrana.ProtocolVersion);
|
||||
/** @private */
|
||||
abstract _getStream(): hrana.Stream;
|
||||
/** @private */
|
||||
abstract _getSqlCache(): SqlCache;
|
||||
abstract close(): void;
|
||||
abstract get closed(): boolean;
|
||||
execute(stmt: InStatement): Promise<ResultSet>;
|
||||
batch(stmts: Array<InStatement>): Promise<Array<ResultSet>>;
|
||||
executeMultiple(sql: string): Promise<void>;
|
||||
rollback(): Promise<void>;
|
||||
commit(): Promise<void>;
|
||||
}
|
||||
export declare function executeHranaBatch(mode: TransactionMode, version: hrana.ProtocolVersion, batch: hrana.Batch, hranaStmts: Array<hrana.Stmt>, disableForeignKeys?: boolean): Promise<Array<ResultSet>>;
|
||||
export declare function stmtToHrana(stmt: InStatement | [string, InArgs?]): hrana.Stmt;
|
||||
export declare function resultSetFromHrana(hranaRows: hrana.RowsResult): ResultSet;
|
||||
export declare function mapHranaError(e: unknown): unknown;
|
||||
310
node_modules/@libsql/client/lib-esm/hrana.js
generated
vendored
Normal file
310
node_modules/@libsql/client/lib-esm/hrana.js
generated
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
import * as hrana from "@libsql/hrana-client";
|
||||
import { LibsqlError } from "@libsql/core/api";
|
||||
import { transactionModeToBegin, ResultSetImpl } from "@libsql/core/util";
|
||||
export class HranaTransaction {
|
||||
#mode;
|
||||
#version;
|
||||
// Promise that is resolved when the BEGIN statement completes, or `undefined` if we haven't executed the
|
||||
// BEGIN statement yet.
|
||||
#started;
|
||||
/** @private */
|
||||
constructor(mode, version) {
|
||||
this.#mode = mode;
|
||||
this.#version = version;
|
||||
this.#started = undefined;
|
||||
}
|
||||
execute(stmt) {
|
||||
return this.batch([stmt]).then((results) => results[0]);
|
||||
}
|
||||
async batch(stmts) {
|
||||
const stream = this._getStream();
|
||||
if (stream.closed) {
|
||||
throw new LibsqlError("Cannot execute statements because the transaction is closed", "TRANSACTION_CLOSED");
|
||||
}
|
||||
try {
|
||||
const hranaStmts = stmts.map(stmtToHrana);
|
||||
let rowsPromises;
|
||||
if (this.#started === undefined) {
|
||||
// The transaction hasn't started yet, so we need to send the BEGIN statement in a batch with
|
||||
// `hranaStmts`.
|
||||
this._getSqlCache().apply(hranaStmts);
|
||||
const batch = stream.batch(this.#version >= 3);
|
||||
const beginStep = batch.step();
|
||||
const beginPromise = beginStep.run(transactionModeToBegin(this.#mode));
|
||||
// Execute the `hranaStmts` only if the BEGIN succeeded, to make sure that we don't execute it
|
||||
// outside of a transaction.
|
||||
let lastStep = beginStep;
|
||||
rowsPromises = hranaStmts.map((hranaStmt) => {
|
||||
const stmtStep = batch
|
||||
.step()
|
||||
.condition(hrana.BatchCond.ok(lastStep));
|
||||
if (this.#version >= 3) {
|
||||
// If the Hrana version supports it, make sure that we are still in a transaction
|
||||
stmtStep.condition(hrana.BatchCond.not(hrana.BatchCond.isAutocommit(batch)));
|
||||
}
|
||||
const rowsPromise = stmtStep.query(hranaStmt);
|
||||
rowsPromise.catch(() => undefined); // silence Node warning
|
||||
lastStep = stmtStep;
|
||||
return rowsPromise;
|
||||
});
|
||||
// `this.#started` is resolved successfully only if the batch and the BEGIN statement inside
|
||||
// of the batch are both successful.
|
||||
this.#started = batch
|
||||
.execute()
|
||||
.then(() => beginPromise)
|
||||
.then(() => undefined);
|
||||
try {
|
||||
await this.#started;
|
||||
}
|
||||
catch (e) {
|
||||
// If the BEGIN failed, the transaction is unusable and we must close it. However, if the
|
||||
// BEGIN suceeds and `hranaStmts` fail, the transaction is _not_ closed.
|
||||
this.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.#version < 3) {
|
||||
// The transaction has started, so we must wait until the BEGIN statement completed to make
|
||||
// sure that we don't execute `hranaStmts` outside of a transaction.
|
||||
await this.#started;
|
||||
}
|
||||
else {
|
||||
// The transaction has started, but we will use `hrana.BatchCond.isAutocommit()` to make
|
||||
// sure that we don't execute `hranaStmts` outside of a transaction, so we don't have to
|
||||
// wait for `this.#started`
|
||||
}
|
||||
this._getSqlCache().apply(hranaStmts);
|
||||
const batch = stream.batch(this.#version >= 3);
|
||||
let lastStep = undefined;
|
||||
rowsPromises = hranaStmts.map((hranaStmt) => {
|
||||
const stmtStep = batch.step();
|
||||
if (lastStep !== undefined) {
|
||||
stmtStep.condition(hrana.BatchCond.ok(lastStep));
|
||||
}
|
||||
if (this.#version >= 3) {
|
||||
stmtStep.condition(hrana.BatchCond.not(hrana.BatchCond.isAutocommit(batch)));
|
||||
}
|
||||
const rowsPromise = stmtStep.query(hranaStmt);
|
||||
rowsPromise.catch(() => undefined); // silence Node warning
|
||||
lastStep = stmtStep;
|
||||
return rowsPromise;
|
||||
});
|
||||
await batch.execute();
|
||||
}
|
||||
const resultSets = [];
|
||||
for (const rowsPromise of rowsPromises) {
|
||||
const rows = await rowsPromise;
|
||||
if (rows === undefined) {
|
||||
throw new LibsqlError("Statement in a transaction was not executed, " +
|
||||
"probably because the transaction has been rolled back", "TRANSACTION_CLOSED");
|
||||
}
|
||||
resultSets.push(resultSetFromHrana(rows));
|
||||
}
|
||||
return resultSets;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
const stream = this._getStream();
|
||||
if (stream.closed) {
|
||||
throw new LibsqlError("Cannot execute statements because the transaction is closed", "TRANSACTION_CLOSED");
|
||||
}
|
||||
try {
|
||||
if (this.#started === undefined) {
|
||||
// If the transaction hasn't started yet, start it now
|
||||
this.#started = stream
|
||||
.run(transactionModeToBegin(this.#mode))
|
||||
.then(() => undefined);
|
||||
try {
|
||||
await this.#started;
|
||||
}
|
||||
catch (e) {
|
||||
this.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Wait until the transaction has started
|
||||
await this.#started;
|
||||
}
|
||||
await stream.sequence(sql);
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
}
|
||||
async rollback() {
|
||||
try {
|
||||
const stream = this._getStream();
|
||||
if (stream.closed) {
|
||||
return;
|
||||
}
|
||||
if (this.#started !== undefined) {
|
||||
// We don't have to wait for the BEGIN statement to complete. If the BEGIN fails, we will
|
||||
// execute a ROLLBACK outside of an active transaction, which should be harmless.
|
||||
}
|
||||
else {
|
||||
// We did nothing in the transaction, so there is nothing to rollback.
|
||||
return;
|
||||
}
|
||||
// Pipeline the ROLLBACK statement and the stream close.
|
||||
const promise = stream.run("ROLLBACK").catch((e) => {
|
||||
throw mapHranaError(e);
|
||||
});
|
||||
stream.closeGracefully();
|
||||
await promise;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
finally {
|
||||
// `this.close()` may close the `hrana.Client`, which aborts all pending stream requests, so we
|
||||
// must call it _after_ we receive the ROLLBACK response.
|
||||
// Also note that the current stream should already be closed, but we need to call `this.close()`
|
||||
// anyway, because it may need to do more cleanup.
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
async commit() {
|
||||
// (this method is analogous to `rollback()`)
|
||||
try {
|
||||
const stream = this._getStream();
|
||||
if (stream.closed) {
|
||||
throw new LibsqlError("Cannot commit the transaction because it is already closed", "TRANSACTION_CLOSED");
|
||||
}
|
||||
if (this.#started !== undefined) {
|
||||
// Make sure to execute the COMMIT only if the BEGIN was successful.
|
||||
await this.#started;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
const promise = stream.run("COMMIT").catch((e) => {
|
||||
throw mapHranaError(e);
|
||||
});
|
||||
stream.closeGracefully();
|
||||
await promise;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
finally {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
export async function executeHranaBatch(mode, version, batch, hranaStmts, disableForeignKeys = false) {
|
||||
if (disableForeignKeys) {
|
||||
batch.step().run("PRAGMA foreign_keys=off");
|
||||
}
|
||||
const beginStep = batch.step();
|
||||
const beginPromise = beginStep.run(transactionModeToBegin(mode));
|
||||
let lastStep = beginStep;
|
||||
const stmtPromises = hranaStmts.map((hranaStmt) => {
|
||||
const stmtStep = batch.step().condition(hrana.BatchCond.ok(lastStep));
|
||||
if (version >= 3) {
|
||||
stmtStep.condition(hrana.BatchCond.not(hrana.BatchCond.isAutocommit(batch)));
|
||||
}
|
||||
const stmtPromise = stmtStep.query(hranaStmt);
|
||||
lastStep = stmtStep;
|
||||
return stmtPromise;
|
||||
});
|
||||
const commitStep = batch.step().condition(hrana.BatchCond.ok(lastStep));
|
||||
if (version >= 3) {
|
||||
commitStep.condition(hrana.BatchCond.not(hrana.BatchCond.isAutocommit(batch)));
|
||||
}
|
||||
const commitPromise = commitStep.run("COMMIT");
|
||||
const rollbackStep = batch
|
||||
.step()
|
||||
.condition(hrana.BatchCond.not(hrana.BatchCond.ok(commitStep)));
|
||||
rollbackStep.run("ROLLBACK").catch((_) => undefined);
|
||||
if (disableForeignKeys) {
|
||||
batch.step().run("PRAGMA foreign_keys=on");
|
||||
}
|
||||
await batch.execute();
|
||||
const resultSets = [];
|
||||
await beginPromise;
|
||||
for (const stmtPromise of stmtPromises) {
|
||||
const hranaRows = await stmtPromise;
|
||||
if (hranaRows === undefined) {
|
||||
throw new LibsqlError("Statement in a batch was not executed, probably because the transaction has been rolled back", "TRANSACTION_CLOSED");
|
||||
}
|
||||
resultSets.push(resultSetFromHrana(hranaRows));
|
||||
}
|
||||
await commitPromise;
|
||||
return resultSets;
|
||||
}
|
||||
export function stmtToHrana(stmt) {
|
||||
let sql;
|
||||
let args;
|
||||
if (Array.isArray(stmt)) {
|
||||
[sql, args] = stmt;
|
||||
}
|
||||
else if (typeof stmt === "string") {
|
||||
sql = stmt;
|
||||
}
|
||||
else {
|
||||
sql = stmt.sql;
|
||||
args = stmt.args;
|
||||
}
|
||||
const hranaStmt = new hrana.Stmt(sql);
|
||||
if (args) {
|
||||
if (Array.isArray(args)) {
|
||||
hranaStmt.bindIndexes(args);
|
||||
}
|
||||
else {
|
||||
for (const [key, value] of Object.entries(args)) {
|
||||
hranaStmt.bindName(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hranaStmt;
|
||||
}
|
||||
export function resultSetFromHrana(hranaRows) {
|
||||
const columns = hranaRows.columnNames.map((c) => c ?? "");
|
||||
const columnTypes = hranaRows.columnDecltypes.map((c) => c ?? "");
|
||||
const rows = hranaRows.rows;
|
||||
const rowsAffected = hranaRows.affectedRowCount;
|
||||
const lastInsertRowid = hranaRows.lastInsertRowid !== undefined
|
||||
? hranaRows.lastInsertRowid
|
||||
: undefined;
|
||||
return new ResultSetImpl(columns, columnTypes, rows, rowsAffected, lastInsertRowid);
|
||||
}
|
||||
export function mapHranaError(e) {
|
||||
if (e instanceof hrana.ClientError) {
|
||||
const code = mapHranaErrorCode(e);
|
||||
return new LibsqlError(e.message, code, undefined, e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
function mapHranaErrorCode(e) {
|
||||
if (e instanceof hrana.ResponseError && e.code !== undefined) {
|
||||
return e.code;
|
||||
}
|
||||
else if (e instanceof hrana.ProtoError) {
|
||||
return "HRANA_PROTO_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.ClosedError) {
|
||||
return e.cause instanceof hrana.ClientError
|
||||
? mapHranaErrorCode(e.cause)
|
||||
: "HRANA_CLOSED_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.WebSocketError) {
|
||||
return "HRANA_WEBSOCKET_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.HttpServerError) {
|
||||
return "SERVER_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.ProtocolVersionError) {
|
||||
return "PROTOCOL_VERSION_ERROR";
|
||||
}
|
||||
else if (e instanceof hrana.InternalError) {
|
||||
return "INTERNAL_ERROR";
|
||||
}
|
||||
else {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
39
node_modules/@libsql/client/lib-esm/http.d.ts
generated
vendored
Normal file
39
node_modules/@libsql/client/lib-esm/http.d.ts
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/// <reference types="node" />
|
||||
import * as hrana from "@libsql/hrana-client";
|
||||
import type { Config, Client } from "@libsql/core/api";
|
||||
import type { InStatement, ResultSet, Transaction, IntMode, InArgs, Replicated } from "@libsql/core/api";
|
||||
import { TransactionMode } from "@libsql/core/api";
|
||||
import type { ExpandedConfig } from "@libsql/core/config";
|
||||
import { HranaTransaction } from "./hrana.js";
|
||||
import { SqlCache } from "./sql_cache.js";
|
||||
export * from "@libsql/core/api";
|
||||
export declare function createClient(config: Config): Client;
|
||||
/** @private */
|
||||
export declare function _createClient(config: ExpandedConfig): Client;
|
||||
export declare class HttpClient implements Client {
|
||||
#private;
|
||||
protocol: "http";
|
||||
/** @private */
|
||||
constructor(url: URL, authToken: string | undefined, intMode: IntMode, customFetch: Function | undefined, concurrency: number);
|
||||
private limit;
|
||||
execute(stmtOrSql: InStatement | string, args?: InArgs): Promise<ResultSet>;
|
||||
batch(stmts: Array<InStatement | [string, InArgs?]>, mode?: TransactionMode): Promise<Array<ResultSet>>;
|
||||
migrate(stmts: Array<InStatement>): Promise<Array<ResultSet>>;
|
||||
transaction(mode?: TransactionMode): Promise<HttpTransaction>;
|
||||
executeMultiple(sql: string): Promise<void>;
|
||||
sync(): Promise<Replicated>;
|
||||
close(): void;
|
||||
reconnect(): Promise<void>;
|
||||
get closed(): boolean;
|
||||
}
|
||||
export declare class HttpTransaction extends HranaTransaction implements Transaction {
|
||||
#private;
|
||||
/** @private */
|
||||
constructor(stream: hrana.HttpStream, mode: TransactionMode, version: hrana.ProtocolVersion);
|
||||
/** @private */
|
||||
_getStream(): hrana.Stream;
|
||||
/** @private */
|
||||
_getSqlCache(): SqlCache;
|
||||
close(): void;
|
||||
get closed(): boolean;
|
||||
}
|
||||
230
node_modules/@libsql/client/lib-esm/http.js
generated
vendored
Normal file
230
node_modules/@libsql/client/lib-esm/http.js
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
import * as hrana from "@libsql/hrana-client";
|
||||
import { LibsqlError } from "@libsql/core/api";
|
||||
import { expandConfig } from "@libsql/core/config";
|
||||
import { HranaTransaction, executeHranaBatch, stmtToHrana, resultSetFromHrana, mapHranaError, } from "./hrana.js";
|
||||
import { SqlCache } from "./sql_cache.js";
|
||||
import { encodeBaseUrl } from "@libsql/core/uri";
|
||||
import { supportedUrlLink } from "@libsql/core/util";
|
||||
import promiseLimit from "promise-limit";
|
||||
export * from "@libsql/core/api";
|
||||
export function createClient(config) {
|
||||
return _createClient(expandConfig(config, true));
|
||||
}
|
||||
/** @private */
|
||||
export function _createClient(config) {
|
||||
if (config.scheme !== "https" && config.scheme !== "http") {
|
||||
throw new LibsqlError('The HTTP client supports only "libsql:", "https:" and "http:" URLs, ' +
|
||||
`got ${JSON.stringify(config.scheme + ":")}. For more information, please read ${supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
if (config.encryptionKey !== undefined) {
|
||||
throw new LibsqlError("Encryption key is not supported by the remote client.", "ENCRYPTION_KEY_NOT_SUPPORTED");
|
||||
}
|
||||
if (config.scheme === "http" && config.tls) {
|
||||
throw new LibsqlError(`A "http:" URL cannot opt into TLS by using ?tls=1`, "URL_INVALID");
|
||||
}
|
||||
else if (config.scheme === "https" && !config.tls) {
|
||||
throw new LibsqlError(`A "https:" URL cannot opt out of TLS by using ?tls=0`, "URL_INVALID");
|
||||
}
|
||||
const url = encodeBaseUrl(config.scheme, config.authority, config.path);
|
||||
return new HttpClient(url, config.authToken, config.intMode, config.fetch, config.concurrency);
|
||||
}
|
||||
const sqlCacheCapacity = 30;
|
||||
export class HttpClient {
|
||||
#client;
|
||||
protocol;
|
||||
#url;
|
||||
#intMode;
|
||||
#customFetch;
|
||||
#concurrency;
|
||||
#authToken;
|
||||
#promiseLimitFunction;
|
||||
/** @private */
|
||||
constructor(url, authToken, intMode, customFetch, concurrency) {
|
||||
this.#url = url;
|
||||
this.#authToken = authToken;
|
||||
this.#intMode = intMode;
|
||||
this.#customFetch = customFetch;
|
||||
this.#concurrency = concurrency;
|
||||
this.#client = hrana.openHttp(this.#url, this.#authToken, this.#customFetch);
|
||||
this.#client.intMode = this.#intMode;
|
||||
this.protocol = "http";
|
||||
this.#promiseLimitFunction = promiseLimit(this.#concurrency);
|
||||
}
|
||||
async limit(fn) {
|
||||
return this.#promiseLimitFunction(fn);
|
||||
}
|
||||
async execute(stmtOrSql, args) {
|
||||
let stmt;
|
||||
if (typeof stmtOrSql === "string") {
|
||||
stmt = {
|
||||
sql: stmtOrSql,
|
||||
args: args || [],
|
||||
};
|
||||
}
|
||||
else {
|
||||
stmt = stmtOrSql;
|
||||
}
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
const hranaStmt = stmtToHrana(stmt);
|
||||
// Pipeline all operations, so `hrana.HttpClient` can open the stream, execute the statement and
|
||||
// close the stream in a single HTTP request.
|
||||
let rowsPromise;
|
||||
const stream = this.#client.openStream();
|
||||
try {
|
||||
rowsPromise = stream.query(hranaStmt);
|
||||
}
|
||||
finally {
|
||||
stream.closeGracefully();
|
||||
}
|
||||
const rowsResult = await rowsPromise;
|
||||
return resultSetFromHrana(rowsResult);
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async batch(stmts, mode = "deferred") {
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
const normalizedStmts = stmts.map((stmt) => {
|
||||
if (Array.isArray(stmt)) {
|
||||
return {
|
||||
sql: stmt[0],
|
||||
args: stmt[1] || [],
|
||||
};
|
||||
}
|
||||
return stmt;
|
||||
});
|
||||
const hranaStmts = normalizedStmts.map(stmtToHrana);
|
||||
const version = await this.#client.getVersion();
|
||||
// Pipeline all operations, so `hrana.HttpClient` can open the stream, execute the batch and
|
||||
// close the stream in a single HTTP request.
|
||||
let resultsPromise;
|
||||
const stream = this.#client.openStream();
|
||||
try {
|
||||
// It makes sense to use a SQL cache even for a single batch, because it may contain the same
|
||||
// statement repeated multiple times.
|
||||
const sqlCache = new SqlCache(stream, sqlCacheCapacity);
|
||||
sqlCache.apply(hranaStmts);
|
||||
// TODO: we do not use a cursor here, because it would cause three roundtrips:
|
||||
// 1. pipeline request to store SQL texts
|
||||
// 2. cursor request
|
||||
// 3. pipeline request to close the stream
|
||||
const batch = stream.batch(false);
|
||||
resultsPromise = executeHranaBatch(mode, version, batch, hranaStmts);
|
||||
}
|
||||
finally {
|
||||
stream.closeGracefully();
|
||||
}
|
||||
const results = await resultsPromise;
|
||||
return results;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async migrate(stmts) {
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
const hranaStmts = stmts.map(stmtToHrana);
|
||||
const version = await this.#client.getVersion();
|
||||
// Pipeline all operations, so `hrana.HttpClient` can open the stream, execute the batch and
|
||||
// close the stream in a single HTTP request.
|
||||
let resultsPromise;
|
||||
const stream = this.#client.openStream();
|
||||
try {
|
||||
const batch = stream.batch(false);
|
||||
resultsPromise = executeHranaBatch("deferred", version, batch, hranaStmts, true);
|
||||
}
|
||||
finally {
|
||||
stream.closeGracefully();
|
||||
}
|
||||
const results = await resultsPromise;
|
||||
return results;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async transaction(mode = "write") {
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
const version = await this.#client.getVersion();
|
||||
return new HttpTransaction(this.#client.openStream(), mode, version);
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
return this.limit(async () => {
|
||||
try {
|
||||
// Pipeline all operations, so `hrana.HttpClient` can open the stream, execute the sequence and
|
||||
// close the stream in a single HTTP request.
|
||||
let promise;
|
||||
const stream = this.#client.openStream();
|
||||
try {
|
||||
promise = stream.sequence(sql);
|
||||
}
|
||||
finally {
|
||||
stream.closeGracefully();
|
||||
}
|
||||
await promise;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
sync() {
|
||||
throw new LibsqlError("sync not supported in http mode", "SYNC_NOT_SUPPORTED");
|
||||
}
|
||||
close() {
|
||||
this.#client.close();
|
||||
}
|
||||
async reconnect() {
|
||||
try {
|
||||
if (!this.closed) {
|
||||
// Abort in-flight ops and free resources
|
||||
this.#client.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Recreate the underlying hrana client
|
||||
this.#client = hrana.openHttp(this.#url, this.#authToken, this.#customFetch);
|
||||
this.#client.intMode = this.#intMode;
|
||||
}
|
||||
}
|
||||
get closed() {
|
||||
return this.#client.closed;
|
||||
}
|
||||
}
|
||||
export class HttpTransaction extends HranaTransaction {
|
||||
#stream;
|
||||
#sqlCache;
|
||||
/** @private */
|
||||
constructor(stream, mode, version) {
|
||||
super(mode, version);
|
||||
this.#stream = stream;
|
||||
this.#sqlCache = new SqlCache(stream, sqlCacheCapacity);
|
||||
}
|
||||
/** @private */
|
||||
_getStream() {
|
||||
return this.#stream;
|
||||
}
|
||||
/** @private */
|
||||
_getSqlCache() {
|
||||
return this.#sqlCache;
|
||||
}
|
||||
close() {
|
||||
this.#stream.close();
|
||||
}
|
||||
get closed() {
|
||||
return this.#stream.closed;
|
||||
}
|
||||
}
|
||||
7
node_modules/@libsql/client/lib-esm/node.d.ts
generated
vendored
Normal file
7
node_modules/@libsql/client/lib-esm/node.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { Config, Client } from "@libsql/core/api";
|
||||
export * from "@libsql/core/api";
|
||||
/** Creates a {@link Client} object.
|
||||
*
|
||||
* You must pass at least an `url` in the {@link Config} object.
|
||||
*/
|
||||
export declare function createClient(config: Config): Client;
|
||||
23
node_modules/@libsql/client/lib-esm/node.js
generated
vendored
Normal file
23
node_modules/@libsql/client/lib-esm/node.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { expandConfig } from "@libsql/core/config";
|
||||
import { _createClient as _createSqlite3Client } from "./sqlite3.js";
|
||||
import { _createClient as _createWsClient } from "./ws.js";
|
||||
import { _createClient as _createHttpClient } from "./http.js";
|
||||
export * from "@libsql/core/api";
|
||||
/** Creates a {@link Client} object.
|
||||
*
|
||||
* You must pass at least an `url` in the {@link Config} object.
|
||||
*/
|
||||
export function createClient(config) {
|
||||
return _createClient(expandConfig(config, true));
|
||||
}
|
||||
function _createClient(config) {
|
||||
if (config.scheme === "wss" || config.scheme === "ws") {
|
||||
return _createWsClient(config);
|
||||
}
|
||||
else if (config.scheme === "https" || config.scheme === "http") {
|
||||
return _createHttpClient(config);
|
||||
}
|
||||
else {
|
||||
return _createSqlite3Client(config);
|
||||
}
|
||||
}
|
||||
7
node_modules/@libsql/client/lib-esm/sql_cache.d.ts
generated
vendored
Normal file
7
node_modules/@libsql/client/lib-esm/sql_cache.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type * as hrana from "@libsql/hrana-client";
|
||||
export declare class SqlCache {
|
||||
#private;
|
||||
capacity: number;
|
||||
constructor(owner: hrana.SqlOwner, capacity: number);
|
||||
apply(hranaStmts: Array<hrana.Stmt>): void;
|
||||
}
|
||||
87
node_modules/@libsql/client/lib-esm/sql_cache.js
generated
vendored
Normal file
87
node_modules/@libsql/client/lib-esm/sql_cache.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
export class SqlCache {
|
||||
#owner;
|
||||
#sqls;
|
||||
capacity;
|
||||
constructor(owner, capacity) {
|
||||
this.#owner = owner;
|
||||
this.#sqls = new Lru();
|
||||
this.capacity = capacity;
|
||||
}
|
||||
// Replaces SQL strings with cached `hrana.Sql` objects in the statements in `hranaStmts`. After this
|
||||
// function returns, we guarantee that all `hranaStmts` refer to valid (not closed) `hrana.Sql` objects,
|
||||
// but _we may invalidate any other `hrana.Sql` objects_ (by closing them, thus removing them from the
|
||||
// server).
|
||||
//
|
||||
// In practice, this means that after calling this function, you can use the statements only up to the
|
||||
// first `await`, because concurrent code may also use the cache and invalidate those statements.
|
||||
apply(hranaStmts) {
|
||||
if (this.capacity <= 0) {
|
||||
return;
|
||||
}
|
||||
const usedSqlObjs = new Set();
|
||||
for (const hranaStmt of hranaStmts) {
|
||||
if (typeof hranaStmt.sql !== "string") {
|
||||
continue;
|
||||
}
|
||||
const sqlText = hranaStmt.sql;
|
||||
// Stored SQL cannot exceed 5kb.
|
||||
// https://github.com/tursodatabase/libsql/blob/e9d637e051685f92b0da43849507b5ef4232fbeb/libsql-server/src/hrana/http/request.rs#L10
|
||||
if (sqlText.length >= 5000) {
|
||||
continue;
|
||||
}
|
||||
let sqlObj = this.#sqls.get(sqlText);
|
||||
if (sqlObj === undefined) {
|
||||
while (this.#sqls.size + 1 > this.capacity) {
|
||||
const [evictSqlText, evictSqlObj] = this.#sqls.peekLru();
|
||||
if (usedSqlObjs.has(evictSqlObj)) {
|
||||
// The SQL object that we are trying to evict is already in use in this batch, so we
|
||||
// must not evict and close it.
|
||||
break;
|
||||
}
|
||||
evictSqlObj.close();
|
||||
this.#sqls.delete(evictSqlText);
|
||||
}
|
||||
if (this.#sqls.size + 1 <= this.capacity) {
|
||||
sqlObj = this.#owner.storeSql(sqlText);
|
||||
this.#sqls.set(sqlText, sqlObj);
|
||||
}
|
||||
}
|
||||
if (sqlObj !== undefined) {
|
||||
hranaStmt.sql = sqlObj;
|
||||
usedSqlObjs.add(sqlObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class Lru {
|
||||
// This maps keys to the cache values. The entries are ordered by their last use (entires that were used
|
||||
// most recently are at the end).
|
||||
#cache;
|
||||
constructor() {
|
||||
this.#cache = new Map();
|
||||
}
|
||||
get(key) {
|
||||
const value = this.#cache.get(key);
|
||||
if (value !== undefined) {
|
||||
// move the entry to the back of the Map
|
||||
this.#cache.delete(key);
|
||||
this.#cache.set(key, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
set(key, value) {
|
||||
this.#cache.set(key, value);
|
||||
}
|
||||
peekLru() {
|
||||
for (const entry of this.#cache.entries()) {
|
||||
return entry;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
delete(key) {
|
||||
this.#cache.delete(key);
|
||||
}
|
||||
get size() {
|
||||
return this.#cache.size;
|
||||
}
|
||||
}
|
||||
35
node_modules/@libsql/client/lib-esm/sqlite3.d.ts
generated
vendored
Normal file
35
node_modules/@libsql/client/lib-esm/sqlite3.d.ts
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import Database from "libsql";
|
||||
import type { Config, IntMode, Client, Transaction, TransactionMode, ResultSet, InStatement, InArgs, Replicated } from "@libsql/core/api";
|
||||
import type { ExpandedConfig } from "@libsql/core/config";
|
||||
export * from "@libsql/core/api";
|
||||
export declare function createClient(config: Config): Client;
|
||||
/** @private */
|
||||
export declare function _createClient(config: ExpandedConfig): Client;
|
||||
export declare class Sqlite3Client implements Client {
|
||||
#private;
|
||||
closed: boolean;
|
||||
protocol: "file";
|
||||
/** @private */
|
||||
constructor(path: string, options: Database.Options, db: Database.Database, intMode: IntMode);
|
||||
execute(stmtOrSql: InStatement | string, args?: InArgs): Promise<ResultSet>;
|
||||
batch(stmts: Array<InStatement | [string, InArgs?]>, mode?: TransactionMode): Promise<Array<ResultSet>>;
|
||||
migrate(stmts: Array<InStatement>): Promise<Array<ResultSet>>;
|
||||
transaction(mode?: TransactionMode): Promise<Transaction>;
|
||||
executeMultiple(sql: string): Promise<void>;
|
||||
sync(): Promise<Replicated>;
|
||||
reconnect(): Promise<void>;
|
||||
close(): void;
|
||||
}
|
||||
export declare class Sqlite3Transaction implements Transaction {
|
||||
#private;
|
||||
/** @private */
|
||||
constructor(database: Database.Database, intMode: IntMode);
|
||||
execute(stmt: InStatement): Promise<ResultSet>;
|
||||
execute(sql: string, args?: InArgs): Promise<ResultSet>;
|
||||
batch(stmts: Array<InStatement | [string, InArgs?]>): Promise<Array<ResultSet>>;
|
||||
executeMultiple(sql: string): Promise<void>;
|
||||
rollback(): Promise<void>;
|
||||
commit(): Promise<void>;
|
||||
close(): void;
|
||||
get closed(): boolean;
|
||||
}
|
||||
395
node_modules/@libsql/client/lib-esm/sqlite3.js
generated
vendored
Normal file
395
node_modules/@libsql/client/lib-esm/sqlite3.js
generated
vendored
Normal file
@@ -0,0 +1,395 @@
|
||||
import Database from "libsql";
|
||||
import { Buffer } from "node:buffer";
|
||||
import { LibsqlError } from "@libsql/core/api";
|
||||
import { expandConfig, isInMemoryConfig } from "@libsql/core/config";
|
||||
import { supportedUrlLink, transactionModeToBegin, ResultSetImpl, } from "@libsql/core/util";
|
||||
export * from "@libsql/core/api";
|
||||
export function createClient(config) {
|
||||
return _createClient(expandConfig(config, true));
|
||||
}
|
||||
/** @private */
|
||||
export function _createClient(config) {
|
||||
if (config.scheme !== "file") {
|
||||
throw new LibsqlError(`URL scheme ${JSON.stringify(config.scheme + ":")} is not supported by the local sqlite3 client. ` +
|
||||
`For more information, please read ${supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
const authority = config.authority;
|
||||
if (authority !== undefined) {
|
||||
const host = authority.host.toLowerCase();
|
||||
if (host !== "" && host !== "localhost") {
|
||||
throw new LibsqlError(`Invalid host in file URL: ${JSON.stringify(authority.host)}. ` +
|
||||
'A "file:" URL with an absolute path should start with one slash ("file:/absolute/path.db") ' +
|
||||
'or with three slashes ("file:///absolute/path.db"). ' +
|
||||
`For more information, please read ${supportedUrlLink}`, "URL_INVALID");
|
||||
}
|
||||
if (authority.port !== undefined) {
|
||||
throw new LibsqlError("File URL cannot have a port", "URL_INVALID");
|
||||
}
|
||||
if (authority.userinfo !== undefined) {
|
||||
throw new LibsqlError("File URL cannot have username and password", "URL_INVALID");
|
||||
}
|
||||
}
|
||||
let isInMemory = isInMemoryConfig(config);
|
||||
if (isInMemory && config.syncUrl) {
|
||||
throw new LibsqlError(`Embedded replica must use file for local db but URI with in-memory mode were provided instead: ${config.path}`, "URL_INVALID");
|
||||
}
|
||||
let path = config.path;
|
||||
if (isInMemory) {
|
||||
// note: we should prepend file scheme in order for SQLite3 to recognize :memory: connection query parameters
|
||||
path = `${config.scheme}:${config.path}`;
|
||||
}
|
||||
const options = {
|
||||
authToken: config.authToken,
|
||||
encryptionKey: config.encryptionKey,
|
||||
syncUrl: config.syncUrl,
|
||||
syncPeriod: config.syncInterval,
|
||||
readYourWrites: config.readYourWrites,
|
||||
offline: config.offline,
|
||||
};
|
||||
const db = new Database(path, options);
|
||||
executeStmt(db, "SELECT 1 AS checkThatTheDatabaseCanBeOpened", config.intMode);
|
||||
return new Sqlite3Client(path, options, db, config.intMode);
|
||||
}
|
||||
export class Sqlite3Client {
|
||||
#path;
|
||||
#options;
|
||||
#db;
|
||||
#intMode;
|
||||
closed;
|
||||
protocol;
|
||||
/** @private */
|
||||
constructor(path, options, db, intMode) {
|
||||
this.#path = path;
|
||||
this.#options = options;
|
||||
this.#db = db;
|
||||
this.#intMode = intMode;
|
||||
this.closed = false;
|
||||
this.protocol = "file";
|
||||
}
|
||||
async execute(stmtOrSql, args) {
|
||||
let stmt;
|
||||
if (typeof stmtOrSql === "string") {
|
||||
stmt = {
|
||||
sql: stmtOrSql,
|
||||
args: args || [],
|
||||
};
|
||||
}
|
||||
else {
|
||||
stmt = stmtOrSql;
|
||||
}
|
||||
this.#checkNotClosed();
|
||||
return executeStmt(this.#getDb(), stmt, this.#intMode);
|
||||
}
|
||||
async batch(stmts, mode = "deferred") {
|
||||
this.#checkNotClosed();
|
||||
const db = this.#getDb();
|
||||
try {
|
||||
executeStmt(db, transactionModeToBegin(mode), this.#intMode);
|
||||
const resultSets = stmts.map((stmt) => {
|
||||
if (!db.inTransaction) {
|
||||
throw new LibsqlError("The transaction has been rolled back", "TRANSACTION_CLOSED");
|
||||
}
|
||||
const normalizedStmt = Array.isArray(stmt)
|
||||
? { sql: stmt[0], args: stmt[1] || [] }
|
||||
: stmt;
|
||||
return executeStmt(db, normalizedStmt, this.#intMode);
|
||||
});
|
||||
executeStmt(db, "COMMIT", this.#intMode);
|
||||
return resultSets;
|
||||
}
|
||||
finally {
|
||||
if (db.inTransaction) {
|
||||
executeStmt(db, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
async migrate(stmts) {
|
||||
this.#checkNotClosed();
|
||||
const db = this.#getDb();
|
||||
try {
|
||||
executeStmt(db, "PRAGMA foreign_keys=off", this.#intMode);
|
||||
executeStmt(db, transactionModeToBegin("deferred"), this.#intMode);
|
||||
const resultSets = stmts.map((stmt) => {
|
||||
if (!db.inTransaction) {
|
||||
throw new LibsqlError("The transaction has been rolled back", "TRANSACTION_CLOSED");
|
||||
}
|
||||
return executeStmt(db, stmt, this.#intMode);
|
||||
});
|
||||
executeStmt(db, "COMMIT", this.#intMode);
|
||||
return resultSets;
|
||||
}
|
||||
finally {
|
||||
if (db.inTransaction) {
|
||||
executeStmt(db, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
executeStmt(db, "PRAGMA foreign_keys=on", this.#intMode);
|
||||
}
|
||||
}
|
||||
async transaction(mode = "write") {
|
||||
const db = this.#getDb();
|
||||
executeStmt(db, transactionModeToBegin(mode), this.#intMode);
|
||||
this.#db = null; // A new connection will be lazily created on next use
|
||||
return new Sqlite3Transaction(db, this.#intMode);
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
this.#checkNotClosed();
|
||||
const db = this.#getDb();
|
||||
try {
|
||||
return executeMultiple(db, sql);
|
||||
}
|
||||
finally {
|
||||
if (db.inTransaction) {
|
||||
executeStmt(db, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
async sync() {
|
||||
this.#checkNotClosed();
|
||||
const rep = await this.#getDb().sync();
|
||||
return {
|
||||
frames_synced: rep.frames_synced,
|
||||
frame_no: rep.frame_no,
|
||||
};
|
||||
}
|
||||
async reconnect() {
|
||||
try {
|
||||
if (!this.closed && this.#db !== null) {
|
||||
this.#db.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.#db = new Database(this.#path, this.#options);
|
||||
this.closed = false;
|
||||
}
|
||||
}
|
||||
close() {
|
||||
this.closed = true;
|
||||
if (this.#db !== null) {
|
||||
this.#db.close();
|
||||
this.#db = null;
|
||||
}
|
||||
}
|
||||
#checkNotClosed() {
|
||||
if (this.closed) {
|
||||
throw new LibsqlError("The client is closed", "CLIENT_CLOSED");
|
||||
}
|
||||
}
|
||||
// Lazily creates the database connection and returns it
|
||||
#getDb() {
|
||||
if (this.#db === null) {
|
||||
this.#db = new Database(this.#path, this.#options);
|
||||
}
|
||||
return this.#db;
|
||||
}
|
||||
}
|
||||
export class Sqlite3Transaction {
|
||||
#database;
|
||||
#intMode;
|
||||
/** @private */
|
||||
constructor(database, intMode) {
|
||||
this.#database = database;
|
||||
this.#intMode = intMode;
|
||||
}
|
||||
async execute(stmtOrSql, args) {
|
||||
let stmt;
|
||||
if (typeof stmtOrSql === "string") {
|
||||
stmt = {
|
||||
sql: stmtOrSql,
|
||||
args: args || [],
|
||||
};
|
||||
}
|
||||
else {
|
||||
stmt = stmtOrSql;
|
||||
}
|
||||
this.#checkNotClosed();
|
||||
return executeStmt(this.#database, stmt, this.#intMode);
|
||||
}
|
||||
async batch(stmts) {
|
||||
return stmts.map((stmt) => {
|
||||
this.#checkNotClosed();
|
||||
const normalizedStmt = Array.isArray(stmt)
|
||||
? { sql: stmt[0], args: stmt[1] || [] }
|
||||
: stmt;
|
||||
return executeStmt(this.#database, normalizedStmt, this.#intMode);
|
||||
});
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
this.#checkNotClosed();
|
||||
return executeMultiple(this.#database, sql);
|
||||
}
|
||||
async rollback() {
|
||||
if (!this.#database.open) {
|
||||
return;
|
||||
}
|
||||
this.#checkNotClosed();
|
||||
executeStmt(this.#database, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
async commit() {
|
||||
this.#checkNotClosed();
|
||||
executeStmt(this.#database, "COMMIT", this.#intMode);
|
||||
}
|
||||
close() {
|
||||
if (this.#database.inTransaction) {
|
||||
executeStmt(this.#database, "ROLLBACK", this.#intMode);
|
||||
}
|
||||
}
|
||||
get closed() {
|
||||
return !this.#database.inTransaction;
|
||||
}
|
||||
#checkNotClosed() {
|
||||
if (this.closed) {
|
||||
throw new LibsqlError("The transaction is closed", "TRANSACTION_CLOSED");
|
||||
}
|
||||
}
|
||||
}
|
||||
function executeStmt(db, stmt, intMode) {
|
||||
let sql;
|
||||
let args;
|
||||
if (typeof stmt === "string") {
|
||||
sql = stmt;
|
||||
args = [];
|
||||
}
|
||||
else {
|
||||
sql = stmt.sql;
|
||||
if (Array.isArray(stmt.args)) {
|
||||
args = stmt.args.map((value) => valueToSql(value, intMode));
|
||||
}
|
||||
else {
|
||||
args = {};
|
||||
for (const name in stmt.args) {
|
||||
const argName = name[0] === "@" || name[0] === "$" || name[0] === ":"
|
||||
? name.substring(1)
|
||||
: name;
|
||||
args[argName] = valueToSql(stmt.args[name], intMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
const sqlStmt = db.prepare(sql);
|
||||
sqlStmt.safeIntegers(true);
|
||||
let returnsData = true;
|
||||
try {
|
||||
sqlStmt.raw(true);
|
||||
}
|
||||
catch {
|
||||
// raw() throws an exception if the statement does not return data
|
||||
returnsData = false;
|
||||
}
|
||||
if (returnsData) {
|
||||
const columns = Array.from(sqlStmt.columns().map((col) => col.name));
|
||||
const columnTypes = Array.from(sqlStmt.columns().map((col) => col.type ?? ""));
|
||||
const rows = sqlStmt.all(args).map((sqlRow) => {
|
||||
return rowFromSql(sqlRow, columns, intMode);
|
||||
});
|
||||
// TODO: can we get this info from better-sqlite3?
|
||||
const rowsAffected = 0;
|
||||
const lastInsertRowid = undefined;
|
||||
return new ResultSetImpl(columns, columnTypes, rows, rowsAffected, lastInsertRowid);
|
||||
}
|
||||
else {
|
||||
const info = sqlStmt.run(args);
|
||||
const rowsAffected = info.changes;
|
||||
const lastInsertRowid = BigInt(info.lastInsertRowid);
|
||||
return new ResultSetImpl([], [], [], rowsAffected, lastInsertRowid);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw mapSqliteError(e);
|
||||
}
|
||||
}
|
||||
function rowFromSql(sqlRow, columns, intMode) {
|
||||
const row = {};
|
||||
// make sure that the "length" property is not enumerable
|
||||
Object.defineProperty(row, "length", { value: sqlRow.length });
|
||||
for (let i = 0; i < sqlRow.length; ++i) {
|
||||
const value = valueFromSql(sqlRow[i], intMode);
|
||||
Object.defineProperty(row, i, { value });
|
||||
const column = columns[i];
|
||||
if (!Object.hasOwn(row, column)) {
|
||||
Object.defineProperty(row, column, {
|
||||
value,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
function valueFromSql(sqlValue, intMode) {
|
||||
if (typeof sqlValue === "bigint") {
|
||||
if (intMode === "number") {
|
||||
if (sqlValue < minSafeBigint || sqlValue > maxSafeBigint) {
|
||||
throw new RangeError("Received integer which cannot be safely represented as a JavaScript number");
|
||||
}
|
||||
return Number(sqlValue);
|
||||
}
|
||||
else if (intMode === "bigint") {
|
||||
return sqlValue;
|
||||
}
|
||||
else if (intMode === "string") {
|
||||
return "" + sqlValue;
|
||||
}
|
||||
else {
|
||||
throw new Error("Invalid value for IntMode");
|
||||
}
|
||||
}
|
||||
else if (sqlValue instanceof Buffer) {
|
||||
return sqlValue.buffer;
|
||||
}
|
||||
return sqlValue;
|
||||
}
|
||||
const minSafeBigint = -9007199254740991n;
|
||||
const maxSafeBigint = 9007199254740991n;
|
||||
function valueToSql(value, intMode) {
|
||||
if (typeof value === "number") {
|
||||
if (!Number.isFinite(value)) {
|
||||
throw new RangeError("Only finite numbers (not Infinity or NaN) can be passed as arguments");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "bigint") {
|
||||
if (value < minInteger || value > maxInteger) {
|
||||
throw new RangeError("bigint is too large to be represented as a 64-bit integer and passed as argument");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
switch (intMode) {
|
||||
case "bigint":
|
||||
return value ? 1n : 0n;
|
||||
case "string":
|
||||
return value ? "1" : "0";
|
||||
default:
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
}
|
||||
else if (value instanceof ArrayBuffer) {
|
||||
return Buffer.from(value);
|
||||
}
|
||||
else if (value instanceof Date) {
|
||||
return value.valueOf();
|
||||
}
|
||||
else if (value === undefined) {
|
||||
throw new TypeError("undefined cannot be passed as argument to the database");
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
const minInteger = -9223372036854775808n;
|
||||
const maxInteger = 9223372036854775807n;
|
||||
function executeMultiple(db, sql) {
|
||||
try {
|
||||
db.exec(sql);
|
||||
}
|
||||
catch (e) {
|
||||
throw mapSqliteError(e);
|
||||
}
|
||||
}
|
||||
function mapSqliteError(e) {
|
||||
if (e instanceof Database.SqliteError) {
|
||||
return new LibsqlError(e.message, e.code, e.rawCode, e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
6
node_modules/@libsql/client/lib-esm/web.d.ts
generated
vendored
Normal file
6
node_modules/@libsql/client/lib-esm/web.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { Config, Client } from "@libsql/core/api";
|
||||
import type { ExpandedConfig } from "@libsql/core/config";
|
||||
export * from "@libsql/core/api";
|
||||
export declare function createClient(config: Config): Client;
|
||||
/** @private */
|
||||
export declare function _createClient(config: ExpandedConfig): Client;
|
||||
22
node_modules/@libsql/client/lib-esm/web.js
generated
vendored
Normal file
22
node_modules/@libsql/client/lib-esm/web.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { LibsqlError } from "@libsql/core/api";
|
||||
import { expandConfig } from "@libsql/core/config";
|
||||
import { supportedUrlLink } from "@libsql/core/util";
|
||||
import { _createClient as _createWsClient } from "./ws.js";
|
||||
import { _createClient as _createHttpClient } from "./http.js";
|
||||
export * from "@libsql/core/api";
|
||||
export function createClient(config) {
|
||||
return _createClient(expandConfig(config, true));
|
||||
}
|
||||
/** @private */
|
||||
export function _createClient(config) {
|
||||
if (config.scheme === "ws" || config.scheme === "wss") {
|
||||
return _createWsClient(config);
|
||||
}
|
||||
else if (config.scheme === "http" || config.scheme === "https") {
|
||||
return _createHttpClient(config);
|
||||
}
|
||||
else {
|
||||
throw new LibsqlError('The client that uses Web standard APIs supports only "libsql:", "wss:", "ws:", "https:" and "http:" URLs, ' +
|
||||
`got ${JSON.stringify(config.scheme + ":")}. For more information, please read ${supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
}
|
||||
50
node_modules/@libsql/client/lib-esm/ws.d.ts
generated
vendored
Normal file
50
node_modules/@libsql/client/lib-esm/ws.d.ts
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/// <reference types="node" />
|
||||
import * as hrana from "@libsql/hrana-client";
|
||||
import type { Config, IntMode, Client, Transaction, ResultSet, InStatement, InArgs, Replicated } from "@libsql/core/api";
|
||||
import { TransactionMode } from "@libsql/core/api";
|
||||
import type { ExpandedConfig } from "@libsql/core/config";
|
||||
import { HranaTransaction } from "./hrana.js";
|
||||
import { SqlCache } from "./sql_cache.js";
|
||||
export * from "@libsql/core/api";
|
||||
export declare function createClient(config: Config): WsClient;
|
||||
/** @private */
|
||||
export declare function _createClient(config: ExpandedConfig): WsClient;
|
||||
interface ConnState {
|
||||
client: hrana.WsClient;
|
||||
useSqlCache: boolean | undefined;
|
||||
sqlCache: SqlCache;
|
||||
openTime: Date;
|
||||
streamStates: Set<StreamState>;
|
||||
}
|
||||
interface StreamState {
|
||||
conn: ConnState;
|
||||
stream: hrana.WsStream;
|
||||
}
|
||||
export declare class WsClient implements Client {
|
||||
#private;
|
||||
closed: boolean;
|
||||
protocol: "ws";
|
||||
/** @private */
|
||||
constructor(client: hrana.WsClient, url: URL, authToken: string | undefined, intMode: IntMode, concurrency: number | undefined);
|
||||
private limit;
|
||||
execute(stmtOrSql: InStatement | string, args?: InArgs): Promise<ResultSet>;
|
||||
batch(stmts: Array<InStatement | [string, InArgs?]>, mode?: TransactionMode): Promise<Array<ResultSet>>;
|
||||
migrate(stmts: Array<InStatement>): Promise<Array<ResultSet>>;
|
||||
transaction(mode?: TransactionMode): Promise<WsTransaction>;
|
||||
executeMultiple(sql: string): Promise<void>;
|
||||
sync(): Promise<Replicated>;
|
||||
reconnect(): Promise<void>;
|
||||
_closeStream(streamState: StreamState): void;
|
||||
close(): void;
|
||||
}
|
||||
export declare class WsTransaction extends HranaTransaction implements Transaction {
|
||||
#private;
|
||||
/** @private */
|
||||
constructor(client: WsClient, state: StreamState, mode: TransactionMode, version: hrana.ProtocolVersion);
|
||||
/** @private */
|
||||
_getStream(): hrana.Stream;
|
||||
/** @private */
|
||||
_getSqlCache(): SqlCache;
|
||||
close(): void;
|
||||
get closed(): boolean;
|
||||
}
|
||||
359
node_modules/@libsql/client/lib-esm/ws.js
generated
vendored
Normal file
359
node_modules/@libsql/client/lib-esm/ws.js
generated
vendored
Normal file
@@ -0,0 +1,359 @@
|
||||
import * as hrana from "@libsql/hrana-client";
|
||||
import { LibsqlError } from "@libsql/core/api";
|
||||
import { expandConfig } from "@libsql/core/config";
|
||||
import { HranaTransaction, executeHranaBatch, stmtToHrana, resultSetFromHrana, mapHranaError, } from "./hrana.js";
|
||||
import { SqlCache } from "./sql_cache.js";
|
||||
import { encodeBaseUrl } from "@libsql/core/uri";
|
||||
import { supportedUrlLink } from "@libsql/core/util";
|
||||
import promiseLimit from "promise-limit";
|
||||
export * from "@libsql/core/api";
|
||||
export function createClient(config) {
|
||||
return _createClient(expandConfig(config, false));
|
||||
}
|
||||
/** @private */
|
||||
export function _createClient(config) {
|
||||
if (config.scheme !== "wss" && config.scheme !== "ws") {
|
||||
throw new LibsqlError('The WebSocket client supports only "libsql:", "wss:" and "ws:" URLs, ' +
|
||||
`got ${JSON.stringify(config.scheme + ":")}. For more information, please read ${supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
if (config.encryptionKey !== undefined) {
|
||||
throw new LibsqlError("Encryption key is not supported by the remote client.", "ENCRYPTION_KEY_NOT_SUPPORTED");
|
||||
}
|
||||
if (config.scheme === "ws" && config.tls) {
|
||||
throw new LibsqlError(`A "ws:" URL cannot opt into TLS by using ?tls=1`, "URL_INVALID");
|
||||
}
|
||||
else if (config.scheme === "wss" && !config.tls) {
|
||||
throw new LibsqlError(`A "wss:" URL cannot opt out of TLS by using ?tls=0`, "URL_INVALID");
|
||||
}
|
||||
const url = encodeBaseUrl(config.scheme, config.authority, config.path);
|
||||
let client;
|
||||
try {
|
||||
client = hrana.openWs(url, config.authToken);
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof hrana.WebSocketUnsupportedError) {
|
||||
const suggestedScheme = config.scheme === "wss" ? "https" : "http";
|
||||
const suggestedUrl = encodeBaseUrl(suggestedScheme, config.authority, config.path);
|
||||
throw new LibsqlError("This environment does not support WebSockets, please switch to the HTTP client by using " +
|
||||
`a "${suggestedScheme}:" URL (${JSON.stringify(suggestedUrl)}). ` +
|
||||
`For more information, please read ${supportedUrlLink}`, "WEBSOCKETS_NOT_SUPPORTED");
|
||||
}
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
return new WsClient(client, url, config.authToken, config.intMode, config.concurrency);
|
||||
}
|
||||
const maxConnAgeMillis = 60 * 1000;
|
||||
const sqlCacheCapacity = 100;
|
||||
export class WsClient {
|
||||
#url;
|
||||
#authToken;
|
||||
#intMode;
|
||||
// State of the current connection. The `hrana.WsClient` inside may be closed at any moment due to an
|
||||
// asynchronous error.
|
||||
#connState;
|
||||
// If defined, this is a connection that will be used in the future, once it is ready.
|
||||
#futureConnState;
|
||||
closed;
|
||||
protocol;
|
||||
#isSchemaDatabase;
|
||||
#promiseLimitFunction;
|
||||
/** @private */
|
||||
constructor(client, url, authToken, intMode, concurrency) {
|
||||
this.#url = url;
|
||||
this.#authToken = authToken;
|
||||
this.#intMode = intMode;
|
||||
this.#connState = this.#openConn(client);
|
||||
this.#futureConnState = undefined;
|
||||
this.closed = false;
|
||||
this.protocol = "ws";
|
||||
this.#promiseLimitFunction = promiseLimit(concurrency);
|
||||
}
|
||||
async limit(fn) {
|
||||
return this.#promiseLimitFunction(fn);
|
||||
}
|
||||
async execute(stmtOrSql, args) {
|
||||
let stmt;
|
||||
if (typeof stmtOrSql === "string") {
|
||||
stmt = {
|
||||
sql: stmtOrSql,
|
||||
args: args || [],
|
||||
};
|
||||
}
|
||||
else {
|
||||
stmt = stmtOrSql;
|
||||
}
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
const hranaStmt = stmtToHrana(stmt);
|
||||
// Schedule all operations synchronously, so they will be pipelined and executed in a single
|
||||
// network roundtrip.
|
||||
streamState.conn.sqlCache.apply([hranaStmt]);
|
||||
const hranaRowsPromise = streamState.stream.query(hranaStmt);
|
||||
streamState.stream.closeGracefully();
|
||||
const hranaRowsResult = await hranaRowsPromise;
|
||||
return resultSetFromHrana(hranaRowsResult);
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
finally {
|
||||
this._closeStream(streamState);
|
||||
}
|
||||
});
|
||||
}
|
||||
async batch(stmts, mode = "deferred") {
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
const normalizedStmts = stmts.map((stmt) => {
|
||||
if (Array.isArray(stmt)) {
|
||||
return {
|
||||
sql: stmt[0],
|
||||
args: stmt[1] || [],
|
||||
};
|
||||
}
|
||||
return stmt;
|
||||
});
|
||||
const hranaStmts = normalizedStmts.map(stmtToHrana);
|
||||
const version = await streamState.conn.client.getVersion();
|
||||
// Schedule all operations synchronously, so they will be pipelined and executed in a single
|
||||
// network roundtrip.
|
||||
streamState.conn.sqlCache.apply(hranaStmts);
|
||||
const batch = streamState.stream.batch(version >= 3);
|
||||
const resultsPromise = executeHranaBatch(mode, version, batch, hranaStmts);
|
||||
const results = await resultsPromise;
|
||||
return results;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
finally {
|
||||
this._closeStream(streamState);
|
||||
}
|
||||
});
|
||||
}
|
||||
async migrate(stmts) {
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
const hranaStmts = stmts.map(stmtToHrana);
|
||||
const version = await streamState.conn.client.getVersion();
|
||||
// Schedule all operations synchronously, so they will be pipelined and executed in a single
|
||||
// network roundtrip.
|
||||
const batch = streamState.stream.batch(version >= 3);
|
||||
const resultsPromise = executeHranaBatch("deferred", version, batch, hranaStmts, true);
|
||||
const results = await resultsPromise;
|
||||
return results;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
finally {
|
||||
this._closeStream(streamState);
|
||||
}
|
||||
});
|
||||
}
|
||||
async transaction(mode = "write") {
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
const version = await streamState.conn.client.getVersion();
|
||||
// the BEGIN statement will be batched with the first statement on the transaction to save a
|
||||
// network roundtrip
|
||||
return new WsTransaction(this, streamState, mode, version);
|
||||
}
|
||||
catch (e) {
|
||||
this._closeStream(streamState);
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
async executeMultiple(sql) {
|
||||
return this.limit(async () => {
|
||||
const streamState = await this.#openStream();
|
||||
try {
|
||||
// Schedule all operations synchronously, so they will be pipelined and executed in a single
|
||||
// network roundtrip.
|
||||
const promise = streamState.stream.sequence(sql);
|
||||
streamState.stream.closeGracefully();
|
||||
await promise;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
finally {
|
||||
this._closeStream(streamState);
|
||||
}
|
||||
});
|
||||
}
|
||||
sync() {
|
||||
throw new LibsqlError("sync not supported in ws mode", "SYNC_NOT_SUPPORTED");
|
||||
}
|
||||
async #openStream() {
|
||||
if (this.closed) {
|
||||
throw new LibsqlError("The client is closed", "CLIENT_CLOSED");
|
||||
}
|
||||
const now = new Date();
|
||||
const ageMillis = now.valueOf() - this.#connState.openTime.valueOf();
|
||||
if (ageMillis > maxConnAgeMillis &&
|
||||
this.#futureConnState === undefined) {
|
||||
// The existing connection is too old, let's open a new one.
|
||||
const futureConnState = this.#openConn();
|
||||
this.#futureConnState = futureConnState;
|
||||
// However, if we used `futureConnState` immediately, we would introduce additional latency,
|
||||
// because we would have to wait for the WebSocket handshake to complete, even though we may a
|
||||
// have perfectly good existing connection in `this.#connState`!
|
||||
//
|
||||
// So we wait until the `hrana.Client.getVersion()` operation completes (which happens when the
|
||||
// WebSocket hanshake completes), and only then we replace `this.#connState` with
|
||||
// `futureConnState`, which is stored in `this.#futureConnState` in the meantime.
|
||||
futureConnState.client.getVersion().then((_version) => {
|
||||
if (this.#connState !== futureConnState) {
|
||||
// We need to close `this.#connState` before we replace it. However, it is possible
|
||||
// that `this.#connState` has already been replaced: see the code below.
|
||||
if (this.#connState.streamStates.size === 0) {
|
||||
this.#connState.client.close();
|
||||
}
|
||||
else {
|
||||
// If there are existing streams on the connection, we must not close it, because
|
||||
// these streams would be broken. The last stream to be closed will also close the
|
||||
// connection in `_closeStream()`.
|
||||
}
|
||||
}
|
||||
this.#connState = futureConnState;
|
||||
this.#futureConnState = undefined;
|
||||
}, (_e) => {
|
||||
// If the new connection could not be established, let's just ignore the error and keep
|
||||
// using the existing connection.
|
||||
this.#futureConnState = undefined;
|
||||
});
|
||||
}
|
||||
if (this.#connState.client.closed) {
|
||||
// An error happened on this connection and it has been closed. Let's try to seamlessly reconnect.
|
||||
try {
|
||||
if (this.#futureConnState !== undefined) {
|
||||
// We are already in the process of opening a new connection, so let's just use it
|
||||
// immediately.
|
||||
this.#connState = this.#futureConnState;
|
||||
}
|
||||
else {
|
||||
this.#connState = this.#openConn();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
}
|
||||
const connState = this.#connState;
|
||||
try {
|
||||
// Now we wait for the WebSocket handshake to complete (if it hasn't completed yet). Note that
|
||||
// this does not increase latency, because any messages that we would send on the WebSocket before
|
||||
// the handshake would be queued until the handshake is completed anyway.
|
||||
if (connState.useSqlCache === undefined) {
|
||||
connState.useSqlCache =
|
||||
(await connState.client.getVersion()) >= 2;
|
||||
if (connState.useSqlCache) {
|
||||
connState.sqlCache.capacity = sqlCacheCapacity;
|
||||
}
|
||||
}
|
||||
const stream = connState.client.openStream();
|
||||
stream.intMode = this.#intMode;
|
||||
const streamState = { conn: connState, stream };
|
||||
connState.streamStates.add(streamState);
|
||||
return streamState;
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
}
|
||||
#openConn(client) {
|
||||
try {
|
||||
client ??= hrana.openWs(this.#url, this.#authToken);
|
||||
return {
|
||||
client,
|
||||
useSqlCache: undefined,
|
||||
sqlCache: new SqlCache(client, 0),
|
||||
openTime: new Date(),
|
||||
streamStates: new Set(),
|
||||
};
|
||||
}
|
||||
catch (e) {
|
||||
throw mapHranaError(e);
|
||||
}
|
||||
}
|
||||
async reconnect() {
|
||||
try {
|
||||
for (const st of Array.from(this.#connState.streamStates)) {
|
||||
try {
|
||||
st.stream.close();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
this.#connState.client.close();
|
||||
}
|
||||
catch { }
|
||||
if (this.#futureConnState) {
|
||||
try {
|
||||
this.#futureConnState.client.close();
|
||||
}
|
||||
catch { }
|
||||
this.#futureConnState = undefined;
|
||||
}
|
||||
const next = this.#openConn();
|
||||
const version = await next.client.getVersion();
|
||||
next.useSqlCache = version >= 2;
|
||||
if (next.useSqlCache) {
|
||||
next.sqlCache.capacity = sqlCacheCapacity;
|
||||
}
|
||||
this.#connState = next;
|
||||
this.closed = false;
|
||||
}
|
||||
_closeStream(streamState) {
|
||||
streamState.stream.close();
|
||||
const connState = streamState.conn;
|
||||
connState.streamStates.delete(streamState);
|
||||
if (connState.streamStates.size === 0 &&
|
||||
connState !== this.#connState) {
|
||||
// We are not using this connection anymore and this is the last stream that was using it, so we
|
||||
// must close it now.
|
||||
connState.client.close();
|
||||
}
|
||||
}
|
||||
close() {
|
||||
this.#connState.client.close();
|
||||
this.closed = true;
|
||||
if (this.#futureConnState) {
|
||||
try {
|
||||
this.#futureConnState.client.close();
|
||||
}
|
||||
catch { }
|
||||
this.#futureConnState = undefined;
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
}
|
||||
export class WsTransaction extends HranaTransaction {
|
||||
#client;
|
||||
#streamState;
|
||||
/** @private */
|
||||
constructor(client, state, mode, version) {
|
||||
super(mode, version);
|
||||
this.#client = client;
|
||||
this.#streamState = state;
|
||||
}
|
||||
/** @private */
|
||||
_getStream() {
|
||||
return this.#streamState.stream;
|
||||
}
|
||||
/** @private */
|
||||
_getSqlCache() {
|
||||
return this.#streamState.conn.sqlCache;
|
||||
}
|
||||
close() {
|
||||
this.#client._closeStream(this.#streamState);
|
||||
}
|
||||
get closed() {
|
||||
return this.#streamState.stream.closed;
|
||||
}
|
||||
}
|
||||
123
node_modules/@libsql/client/package.json
generated
vendored
Normal file
123
node_modules/@libsql/client/package.json
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"name": "@libsql/client",
|
||||
"version": "0.15.15",
|
||||
"keywords": [
|
||||
"libsql",
|
||||
"database",
|
||||
"sqlite",
|
||||
"serverless",
|
||||
"vercel",
|
||||
"netlify",
|
||||
"lambda"
|
||||
],
|
||||
"description": "libSQL driver for TypeScript and JavaScript",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/libsql/libsql-client-ts",
|
||||
"directory": "packages/libsql-client"
|
||||
},
|
||||
"authors": [
|
||||
"Jan Špaček <honza@chiselstrike.com>",
|
||||
"Pekka Enberg <penberg@chiselstrike.com>",
|
||||
"Jan Plhak <jp@chiselstrike.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"main": "lib-cjs/node.js",
|
||||
"types": "lib-esm/node.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib-esm/node.d.ts",
|
||||
"import": {
|
||||
"workerd": "./lib-esm/web.js",
|
||||
"deno": "./lib-esm/node.js",
|
||||
"edge-light": "./lib-esm/web.js",
|
||||
"netlify": "./lib-esm/web.js",
|
||||
"node": "./lib-esm/node.js",
|
||||
"browser": "./lib-esm/web.js",
|
||||
"default": "./lib-esm/node.js"
|
||||
},
|
||||
"require": "./lib-cjs/node.js"
|
||||
},
|
||||
"./node": {
|
||||
"types": "./lib-esm/node.d.ts",
|
||||
"import": "./lib-esm/node.js",
|
||||
"require": "./lib-cjs/node.js"
|
||||
},
|
||||
"./http": {
|
||||
"types": "./lib-esm/http.d.ts",
|
||||
"import": "./lib-esm/http.js",
|
||||
"require": "./lib-cjs/http.js"
|
||||
},
|
||||
"./ws": {
|
||||
"types": "./lib-esm/ws.d.ts",
|
||||
"import": "./lib-esm/ws.js",
|
||||
"require": "./lib-cjs/ws.js"
|
||||
},
|
||||
"./sqlite3": {
|
||||
"types": "./lib-esm/sqlite3.d.ts",
|
||||
"import": "./lib-esm/sqlite3.js",
|
||||
"require": "./lib-cjs/sqlite3.js"
|
||||
},
|
||||
"./web": {
|
||||
"types": "./lib-esm/web.d.ts",
|
||||
"import": "./lib-esm/web.js",
|
||||
"require": "./lib-cjs/web.js"
|
||||
}
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
".": [
|
||||
"./lib-esm/node.d.ts"
|
||||
],
|
||||
"http": [
|
||||
"./lib-esm/http.d.ts"
|
||||
],
|
||||
"hrana": [
|
||||
"./lib-esm/hrana.d.ts"
|
||||
],
|
||||
"sqlite3": [
|
||||
"./lib-esm/sqlite3.d.ts"
|
||||
],
|
||||
"web": [
|
||||
"./lib-esm/web.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"lib-cjs/**",
|
||||
"lib-esm/**",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
"prebuild": "rm -rf ./lib-cjs ./lib-esm",
|
||||
"build": "npm run build:cjs && npm run build:esm",
|
||||
"build:cjs": "tsc -p tsconfig.build-cjs.json",
|
||||
"build:esm": "tsc -p tsconfig.build-esm.json",
|
||||
"format:check": "prettier --check .",
|
||||
"postbuild": "cp package-cjs.json ./lib-cjs/package.json",
|
||||
"test": "jest --runInBand",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"typedoc": "rm -rf ./docs && typedoc",
|
||||
"lint-staged": "lint-staged"
|
||||
},
|
||||
"dependencies": {
|
||||
"@libsql/core": "^0.15.14",
|
||||
"@libsql/hrana-client": "^0.7.0",
|
||||
"js-base64": "^3.7.5",
|
||||
"libsql": "^0.5.22",
|
||||
"promise-limit": "^2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.2.5",
|
||||
"@types/node": "^18.15.5",
|
||||
"jest": "^29.3.1",
|
||||
"lint-staged": "^15.2.2",
|
||||
"msw": "^2.3.0",
|
||||
"prettier": "3.2.5",
|
||||
"ts-jest": "^29.0.5",
|
||||
"typedoc": "^0.23.28",
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
||||
20
node_modules/@libsql/core/lib-cjs/api.js
generated
vendored
Normal file
20
node_modules/@libsql/core/lib-cjs/api.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LibsqlError = void 0;
|
||||
/** Error thrown by the client. */
|
||||
class LibsqlError extends Error {
|
||||
/** Machine-readable error code. */
|
||||
code;
|
||||
/** Raw numeric error code */
|
||||
rawCode;
|
||||
constructor(message, code, rawCode, cause) {
|
||||
if (code !== undefined) {
|
||||
message = `${code}: ${message}`;
|
||||
}
|
||||
super(message, { cause });
|
||||
this.code = code;
|
||||
this.rawCode = rawCode;
|
||||
this.name = "LibsqlError";
|
||||
}
|
||||
}
|
||||
exports.LibsqlError = LibsqlError;
|
||||
141
node_modules/@libsql/core/lib-cjs/config.js
generated
vendored
Normal file
141
node_modules/@libsql/core/lib-cjs/config.js
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.expandConfig = exports.isInMemoryConfig = void 0;
|
||||
const api_js_1 = require("./api.js");
|
||||
const uri_js_1 = require("./uri.js");
|
||||
const util_js_1 = require("./util.js");
|
||||
const inMemoryMode = ":memory:";
|
||||
function isInMemoryConfig(config) {
|
||||
return (config.scheme === "file" &&
|
||||
(config.path === ":memory:" || config.path.startsWith(":memory:?")));
|
||||
}
|
||||
exports.isInMemoryConfig = isInMemoryConfig;
|
||||
function expandConfig(config, preferHttp) {
|
||||
if (typeof config !== "object") {
|
||||
// produce a reasonable error message in the common case where users type
|
||||
// `createClient("libsql://...")` instead of `createClient({url: "libsql://..."})`
|
||||
throw new TypeError(`Expected client configuration as object, got ${typeof config}`);
|
||||
}
|
||||
let { url, authToken, tls, intMode, concurrency } = config;
|
||||
// fill simple defaults right here
|
||||
concurrency = Math.max(0, concurrency || 20);
|
||||
intMode ??= "number";
|
||||
let connectionQueryParams = []; // recognized query parameters which we sanitize through white list of valid key-value pairs
|
||||
// convert plain :memory: url to URI format to make logic more uniform
|
||||
if (url === inMemoryMode) {
|
||||
url = "file::memory:";
|
||||
}
|
||||
// parse url parameters first and override config with update values
|
||||
const uri = (0, uri_js_1.parseUri)(url);
|
||||
const originalUriScheme = uri.scheme.toLowerCase();
|
||||
const isInMemoryMode = originalUriScheme === "file" &&
|
||||
uri.path === inMemoryMode &&
|
||||
uri.authority === undefined;
|
||||
let queryParamsDef;
|
||||
if (isInMemoryMode) {
|
||||
queryParamsDef = {
|
||||
cache: {
|
||||
values: ["shared", "private"],
|
||||
update: (key, value) => connectionQueryParams.push(`${key}=${value}`),
|
||||
},
|
||||
};
|
||||
}
|
||||
else {
|
||||
queryParamsDef = {
|
||||
tls: {
|
||||
values: ["0", "1"],
|
||||
update: (_, value) => (tls = value === "1"),
|
||||
},
|
||||
authToken: {
|
||||
update: (_, value) => (authToken = value),
|
||||
},
|
||||
};
|
||||
}
|
||||
for (const { key, value } of uri.query?.pairs ?? []) {
|
||||
if (!Object.hasOwn(queryParamsDef, key)) {
|
||||
throw new api_js_1.LibsqlError(`Unsupported URL query parameter ${JSON.stringify(key)}`, "URL_PARAM_NOT_SUPPORTED");
|
||||
}
|
||||
const queryParamDef = queryParamsDef[key];
|
||||
if (queryParamDef.values !== undefined &&
|
||||
!queryParamDef.values.includes(value)) {
|
||||
throw new api_js_1.LibsqlError(`Unknown value for the "${key}" query argument: ${JSON.stringify(value)}. Supported values are: [${queryParamDef.values.map((x) => '"' + x + '"').join(", ")}]`, "URL_INVALID");
|
||||
}
|
||||
if (queryParamDef.update !== undefined) {
|
||||
queryParamDef?.update(key, value);
|
||||
}
|
||||
}
|
||||
// fill complex defaults & validate config
|
||||
const connectionQueryParamsString = connectionQueryParams.length === 0
|
||||
? ""
|
||||
: `?${connectionQueryParams.join("&")}`;
|
||||
const path = uri.path + connectionQueryParamsString;
|
||||
let scheme;
|
||||
if (originalUriScheme === "libsql") {
|
||||
if (tls === false) {
|
||||
if (uri.authority?.port === undefined) {
|
||||
throw new api_js_1.LibsqlError('A "libsql:" URL with ?tls=0 must specify an explicit port', "URL_INVALID");
|
||||
}
|
||||
scheme = preferHttp ? "http" : "ws";
|
||||
}
|
||||
else {
|
||||
scheme = preferHttp ? "https" : "wss";
|
||||
}
|
||||
}
|
||||
else {
|
||||
scheme = originalUriScheme;
|
||||
}
|
||||
if (scheme === "http" || scheme === "ws") {
|
||||
tls ??= false;
|
||||
}
|
||||
else {
|
||||
tls ??= true;
|
||||
}
|
||||
if (scheme !== "http" &&
|
||||
scheme !== "ws" &&
|
||||
scheme !== "https" &&
|
||||
scheme !== "wss" &&
|
||||
scheme !== "file") {
|
||||
throw new api_js_1.LibsqlError('The client supports only "libsql:", "wss:", "ws:", "https:", "http:" and "file:" URLs, ' +
|
||||
`got ${JSON.stringify(uri.scheme + ":")}. ` +
|
||||
`For more information, please read ${util_js_1.supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
if (intMode !== "number" && intMode !== "bigint" && intMode !== "string") {
|
||||
throw new TypeError(`Invalid value for intMode, expected "number", "bigint" or "string", got ${JSON.stringify(intMode)}`);
|
||||
}
|
||||
if (uri.fragment !== undefined) {
|
||||
throw new api_js_1.LibsqlError(`URL fragments are not supported: ${JSON.stringify("#" + uri.fragment)}`, "URL_INVALID");
|
||||
}
|
||||
if (isInMemoryMode) {
|
||||
return {
|
||||
scheme: "file",
|
||||
tls: false,
|
||||
path,
|
||||
intMode,
|
||||
concurrency,
|
||||
syncUrl: config.syncUrl,
|
||||
syncInterval: config.syncInterval,
|
||||
readYourWrites: config.readYourWrites,
|
||||
offline: config.offline,
|
||||
fetch: config.fetch,
|
||||
authToken: undefined,
|
||||
encryptionKey: undefined,
|
||||
authority: undefined,
|
||||
};
|
||||
}
|
||||
return {
|
||||
scheme,
|
||||
tls,
|
||||
authority: uri.authority,
|
||||
path,
|
||||
authToken,
|
||||
intMode,
|
||||
concurrency,
|
||||
encryptionKey: config.encryptionKey,
|
||||
syncUrl: config.syncUrl,
|
||||
syncInterval: config.syncInterval,
|
||||
readYourWrites: config.readYourWrites,
|
||||
offline: config.offline,
|
||||
fetch: config.fetch,
|
||||
};
|
||||
}
|
||||
exports.expandConfig = expandConfig;
|
||||
3
node_modules/@libsql/core/lib-cjs/package.json
generated
vendored
Normal file
3
node_modules/@libsql/core/lib-cjs/package.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
125
node_modules/@libsql/core/lib-cjs/uri.js
generated
vendored
Normal file
125
node_modules/@libsql/core/lib-cjs/uri.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
"use strict";
|
||||
// URI parser based on RFC 3986
|
||||
// We can't use the standard `URL` object, because we want to support relative `file:` URLs like
|
||||
// `file:relative/path/database.db`, which are not correct according to RFC 8089, which standardizes the
|
||||
// `file` scheme.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.encodeBaseUrl = exports.parseUri = void 0;
|
||||
const api_js_1 = require("./api.js");
|
||||
function parseUri(text) {
|
||||
const match = URI_RE.exec(text);
|
||||
if (match === null) {
|
||||
throw new api_js_1.LibsqlError(`The URL '${text}' is not in a valid format`, "URL_INVALID");
|
||||
}
|
||||
const groups = match.groups;
|
||||
const scheme = groups["scheme"];
|
||||
const authority = groups["authority"] !== undefined
|
||||
? parseAuthority(groups["authority"])
|
||||
: undefined;
|
||||
const path = percentDecode(groups["path"]);
|
||||
const query = groups["query"] !== undefined ? parseQuery(groups["query"]) : undefined;
|
||||
const fragment = groups["fragment"] !== undefined
|
||||
? percentDecode(groups["fragment"])
|
||||
: undefined;
|
||||
return { scheme, authority, path, query, fragment };
|
||||
}
|
||||
exports.parseUri = parseUri;
|
||||
const URI_RE = (() => {
|
||||
const SCHEME = "(?<scheme>[A-Za-z][A-Za-z.+-]*)";
|
||||
const AUTHORITY = "(?<authority>[^/?#]*)";
|
||||
const PATH = "(?<path>[^?#]*)";
|
||||
const QUERY = "(?<query>[^#]*)";
|
||||
const FRAGMENT = "(?<fragment>.*)";
|
||||
return new RegExp(`^${SCHEME}:(//${AUTHORITY})?${PATH}(\\?${QUERY})?(#${FRAGMENT})?$`, "su");
|
||||
})();
|
||||
function parseAuthority(text) {
|
||||
const match = AUTHORITY_RE.exec(text);
|
||||
if (match === null) {
|
||||
throw new api_js_1.LibsqlError("The authority part of the URL is not in a valid format", "URL_INVALID");
|
||||
}
|
||||
const groups = match.groups;
|
||||
const host = percentDecode(groups["host_br"] ?? groups["host"]);
|
||||
const port = groups["port"] ? parseInt(groups["port"], 10) : undefined;
|
||||
const userinfo = groups["username"] !== undefined
|
||||
? {
|
||||
username: percentDecode(groups["username"]),
|
||||
password: groups["password"] !== undefined
|
||||
? percentDecode(groups["password"])
|
||||
: undefined,
|
||||
}
|
||||
: undefined;
|
||||
return { host, port, userinfo };
|
||||
}
|
||||
const AUTHORITY_RE = (() => {
|
||||
return new RegExp(`^((?<username>[^:]*)(:(?<password>.*))?@)?((?<host>[^:\\[\\]]*)|(\\[(?<host_br>[^\\[\\]]*)\\]))(:(?<port>[0-9]*))?$`, "su");
|
||||
})();
|
||||
// Query string is parsed as application/x-www-form-urlencoded according to the Web URL standard:
|
||||
// https://url.spec.whatwg.org/#urlencoded-parsing
|
||||
function parseQuery(text) {
|
||||
const sequences = text.split("&");
|
||||
const pairs = [];
|
||||
for (const sequence of sequences) {
|
||||
if (sequence === "") {
|
||||
continue;
|
||||
}
|
||||
let key;
|
||||
let value;
|
||||
const splitIdx = sequence.indexOf("=");
|
||||
if (splitIdx < 0) {
|
||||
key = sequence;
|
||||
value = "";
|
||||
}
|
||||
else {
|
||||
key = sequence.substring(0, splitIdx);
|
||||
value = sequence.substring(splitIdx + 1);
|
||||
}
|
||||
pairs.push({
|
||||
key: percentDecode(key.replaceAll("+", " ")),
|
||||
value: percentDecode(value.replaceAll("+", " ")),
|
||||
});
|
||||
}
|
||||
return { pairs };
|
||||
}
|
||||
function percentDecode(text) {
|
||||
try {
|
||||
return decodeURIComponent(text);
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof URIError) {
|
||||
throw new api_js_1.LibsqlError(`URL component has invalid percent encoding: ${e}`, "URL_INVALID", undefined, e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
function encodeBaseUrl(scheme, authority, path) {
|
||||
if (authority === undefined) {
|
||||
throw new api_js_1.LibsqlError(`URL with scheme ${JSON.stringify(scheme + ":")} requires authority (the "//" part)`, "URL_INVALID");
|
||||
}
|
||||
const schemeText = `${scheme}:`;
|
||||
const hostText = encodeHost(authority.host);
|
||||
const portText = encodePort(authority.port);
|
||||
const userinfoText = encodeUserinfo(authority.userinfo);
|
||||
const authorityText = `//${userinfoText}${hostText}${portText}`;
|
||||
let pathText = path.split("/").map(encodeURIComponent).join("/");
|
||||
if (pathText !== "" && !pathText.startsWith("/")) {
|
||||
pathText = "/" + pathText;
|
||||
}
|
||||
return new URL(`${schemeText}${authorityText}${pathText}`);
|
||||
}
|
||||
exports.encodeBaseUrl = encodeBaseUrl;
|
||||
function encodeHost(host) {
|
||||
return host.includes(":") ? `[${encodeURI(host)}]` : encodeURI(host);
|
||||
}
|
||||
function encodePort(port) {
|
||||
return port !== undefined ? `:${port}` : "";
|
||||
}
|
||||
function encodeUserinfo(userinfo) {
|
||||
if (userinfo === undefined) {
|
||||
return "";
|
||||
}
|
||||
const usernameText = encodeURIComponent(userinfo.username);
|
||||
const passwordText = userinfo.password !== undefined
|
||||
? `:${encodeURIComponent(userinfo.password)}`
|
||||
: "";
|
||||
return `${usernameText}${passwordText}@`;
|
||||
}
|
||||
60
node_modules/@libsql/core/lib-cjs/util.js
generated
vendored
Normal file
60
node_modules/@libsql/core/lib-cjs/util.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ResultSetImpl = exports.transactionModeToBegin = exports.supportedUrlLink = void 0;
|
||||
const js_base64_1 = require("js-base64");
|
||||
exports.supportedUrlLink = "https://github.com/libsql/libsql-client-ts#supported-urls";
|
||||
function transactionModeToBegin(mode) {
|
||||
if (mode === "write") {
|
||||
return "BEGIN IMMEDIATE";
|
||||
}
|
||||
else if (mode === "read") {
|
||||
return "BEGIN TRANSACTION READONLY";
|
||||
}
|
||||
else if (mode === "deferred") {
|
||||
return "BEGIN DEFERRED";
|
||||
}
|
||||
else {
|
||||
throw RangeError('Unknown transaction mode, supported values are "write", "read" and "deferred"');
|
||||
}
|
||||
}
|
||||
exports.transactionModeToBegin = transactionModeToBegin;
|
||||
class ResultSetImpl {
|
||||
columns;
|
||||
columnTypes;
|
||||
rows;
|
||||
rowsAffected;
|
||||
lastInsertRowid;
|
||||
constructor(columns, columnTypes, rows, rowsAffected, lastInsertRowid) {
|
||||
this.columns = columns;
|
||||
this.columnTypes = columnTypes;
|
||||
this.rows = rows;
|
||||
this.rowsAffected = rowsAffected;
|
||||
this.lastInsertRowid = lastInsertRowid;
|
||||
}
|
||||
toJSON() {
|
||||
return {
|
||||
columns: this.columns,
|
||||
columnTypes: this.columnTypes,
|
||||
rows: this.rows.map(rowToJson),
|
||||
rowsAffected: this.rowsAffected,
|
||||
lastInsertRowid: this.lastInsertRowid !== undefined
|
||||
? "" + this.lastInsertRowid
|
||||
: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.ResultSetImpl = ResultSetImpl;
|
||||
function rowToJson(row) {
|
||||
return Array.prototype.map.call(row, valueToJson);
|
||||
}
|
||||
function valueToJson(value) {
|
||||
if (typeof value === "bigint") {
|
||||
return "" + value;
|
||||
}
|
||||
else if (value instanceof ArrayBuffer) {
|
||||
return js_base64_1.Base64.fromUint8Array(new Uint8Array(value));
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
449
node_modules/@libsql/core/lib-esm/api.d.ts
generated
vendored
Normal file
449
node_modules/@libsql/core/lib-esm/api.d.ts
generated
vendored
Normal file
@@ -0,0 +1,449 @@
|
||||
/** Configuration object for {@link createClient}. */
|
||||
export interface Config {
|
||||
/** The database URL.
|
||||
*
|
||||
* The client supports `libsql:`, `http:`/`https:`, `ws:`/`wss:` and `file:` URL. For more infomation,
|
||||
* please refer to the project README:
|
||||
*
|
||||
* https://github.com/libsql/libsql-client-ts#supported-urls
|
||||
*/
|
||||
url: string;
|
||||
/** Authentication token for the database. */
|
||||
authToken?: string;
|
||||
/** Encryption key for the database. */
|
||||
encryptionKey?: string;
|
||||
/** URL of a remote server to synchronize database with. */
|
||||
syncUrl?: string;
|
||||
/** Sync interval in seconds. */
|
||||
syncInterval?: number;
|
||||
/** Read your writes */
|
||||
readYourWrites?: boolean;
|
||||
/** Enable offline writes */
|
||||
offline?: boolean;
|
||||
/** Enables or disables TLS for `libsql:` URLs.
|
||||
*
|
||||
* By default, `libsql:` URLs use TLS. You can set this option to `false` to disable TLS.
|
||||
*/
|
||||
tls?: boolean;
|
||||
/** How to convert SQLite integers to JavaScript values:
|
||||
*
|
||||
* - `"number"` (default): returns SQLite integers as JavaScript `number`-s (double precision floats).
|
||||
* `number` cannot precisely represent integers larger than 2^53-1 in absolute value, so attempting to read
|
||||
* larger integers will throw a `RangeError`.
|
||||
* - `"bigint"`: returns SQLite integers as JavaScript `bigint`-s (arbitrary precision integers). Bigints can
|
||||
* precisely represent all SQLite integers.
|
||||
* - `"string"`: returns SQLite integers as strings.
|
||||
*/
|
||||
intMode?: IntMode;
|
||||
/** Custom `fetch` function to use for the HTTP client.
|
||||
*
|
||||
* By default, the HTTP client uses `fetch` from the `@libsql/isomorphic-fetch` package, but you can pass
|
||||
* your own function here. The argument to this function will be `Request` from
|
||||
* `@libsql/isomorphic-fetch`, and it must return a promise that resolves to an object that is compatible
|
||||
* with the Web `Response`.
|
||||
*/
|
||||
fetch?: Function;
|
||||
/** Concurrency limit.
|
||||
*
|
||||
* By default, the client performs up to 20 concurrent requests. You can set this option to a higher
|
||||
* number to increase the concurrency limit or set it to 0 to disable concurrency limits completely.
|
||||
*/
|
||||
concurrency?: number | undefined;
|
||||
}
|
||||
/** Representation of integers from database as JavaScript values. See {@link Config.intMode}. */
|
||||
export type IntMode = "number" | "bigint" | "string";
|
||||
/** Client object for a remote or local database.
|
||||
*
|
||||
* After you are done with the client, you **should** close it by calling {@link close}.
|
||||
*/
|
||||
export interface Client {
|
||||
/** Execute a single SQL statement.
|
||||
*
|
||||
* Every statement executed with this method is executed in its own logical database connection. If you
|
||||
* want to execute a group of statements in a transaction, use the {@link batch} or the {@link
|
||||
* transaction} methods.
|
||||
*
|
||||
* ```javascript
|
||||
* // execute a statement without arguments
|
||||
* const rs = await client.execute("SELECT * FROM books");
|
||||
*
|
||||
* // execute a statement with positional arguments
|
||||
* const rs = await client.execute({
|
||||
* sql: "SELECT * FROM books WHERE author = ?",
|
||||
* args: ["Jane Austen"],
|
||||
* });
|
||||
*
|
||||
* // execute a statement with named arguments
|
||||
* const rs = await client.execute({
|
||||
* sql: "SELECT * FROM books WHERE published_at > $year",
|
||||
* args: {year: 1719},
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
execute(stmt: InStatement): Promise<ResultSet>;
|
||||
execute(sql: string, args?: InArgs): Promise<ResultSet>;
|
||||
/** Execute a batch of SQL statements in a transaction.
|
||||
*
|
||||
* The batch is executed in its own logical database connection and the statements are wrapped in a
|
||||
* transaction. This ensures that the batch is applied atomically: either all or no changes are applied.
|
||||
*
|
||||
* The `mode` parameter selects the transaction mode for the batch; please see {@link TransactionMode} for
|
||||
* details. The default transaction mode is `"deferred"`.
|
||||
*
|
||||
* If any of the statements in the batch fails with an error, the batch is aborted, the transaction is
|
||||
* rolled back and the returned promise is rejected.
|
||||
*
|
||||
* This method provides non-interactive transactions. If you need interactive transactions, please use the
|
||||
* {@link transaction} method.
|
||||
*
|
||||
* ```javascript
|
||||
* const rss = await client.batch([
|
||||
* // batch statement without arguments
|
||||
* "DELETE FROM books WHERE name LIKE '%Crusoe'",
|
||||
*
|
||||
* // batch statement with positional arguments
|
||||
* {
|
||||
* sql: "INSERT INTO books (name, author, published_at) VALUES (?, ?, ?)",
|
||||
* args: ["First Impressions", "Jane Austen", 1813],
|
||||
* },
|
||||
*
|
||||
* // batch statement with named arguments
|
||||
* {
|
||||
* sql: "UPDATE books SET name = $new WHERE name = $old",
|
||||
* args: {old: "First Impressions", new: "Pride and Prejudice"},
|
||||
* },
|
||||
* ], "write");
|
||||
* ```
|
||||
*/
|
||||
batch(stmts: Array<InStatement | [string, InArgs?]>, mode?: TransactionMode): Promise<Array<ResultSet>>;
|
||||
/** Execute a batch of SQL statements in a transaction with PRAGMA foreign_keys=off; before and PRAGMA foreign_keys=on; after.
|
||||
*
|
||||
* The batch is executed in its own logical database connection and the statements are wrapped in a
|
||||
* transaction. This ensures that the batch is applied atomically: either all or no changes are applied.
|
||||
*
|
||||
* The transaction mode is `"deferred"`.
|
||||
*
|
||||
* If any of the statements in the batch fails with an error, the batch is aborted, the transaction is
|
||||
* rolled back and the returned promise is rejected.
|
||||
*
|
||||
* ```javascript
|
||||
* const rss = await client.migrate([
|
||||
* // statement without arguments
|
||||
* "CREATE TABLE test (a INT)",
|
||||
*
|
||||
* // statement with positional arguments
|
||||
* {
|
||||
* sql: "INSERT INTO books (name, author, published_at) VALUES (?, ?, ?)",
|
||||
* args: ["First Impressions", "Jane Austen", 1813],
|
||||
* },
|
||||
*
|
||||
* // statement with named arguments
|
||||
* {
|
||||
* sql: "UPDATE books SET name = $new WHERE name = $old",
|
||||
* args: {old: "First Impressions", new: "Pride and Prejudice"},
|
||||
* },
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
migrate(stmts: Array<InStatement>): Promise<Array<ResultSet>>;
|
||||
/** Start an interactive transaction.
|
||||
*
|
||||
* Interactive transactions allow you to interleave execution of SQL statements with your application
|
||||
* logic. They can be used if the {@link batch} method is too restrictive, but please note that
|
||||
* interactive transactions have higher latency.
|
||||
*
|
||||
* The `mode` parameter selects the transaction mode for the interactive transaction; please see {@link
|
||||
* TransactionMode} for details. The default transaction mode is `"deferred"`.
|
||||
*
|
||||
* You **must** make sure that the returned {@link Transaction} object is closed, by calling {@link
|
||||
* Transaction.close}, {@link Transaction.commit} or {@link Transaction.rollback}. The best practice is
|
||||
* to call {@link Transaction.close} in a `finally` block, as follows:
|
||||
*
|
||||
* ```javascript
|
||||
* const transaction = client.transaction("write");
|
||||
* try {
|
||||
* // do some operations with the transaction here
|
||||
* await transaction.execute({
|
||||
* sql: "INSERT INTO books (name, author) VALUES (?, ?)",
|
||||
* args: ["First Impressions", "Jane Austen"],
|
||||
* });
|
||||
* await transaction.execute({
|
||||
* sql: "UPDATE books SET name = ? WHERE name = ?",
|
||||
* args: ["Pride and Prejudice", "First Impressions"],
|
||||
* });
|
||||
*
|
||||
* // if all went well, commit the transaction
|
||||
* await transaction.commit();
|
||||
* } finally {
|
||||
* // make sure to close the transaction, even if an exception was thrown
|
||||
* transaction.close();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
transaction(mode?: TransactionMode): Promise<Transaction>;
|
||||
/** Start an interactive transaction in `"write"` mode.
|
||||
*
|
||||
* Please see {@link transaction} for details.
|
||||
*
|
||||
* @deprecated Please specify the `mode` explicitly. The default `"write"` will be removed in the next
|
||||
* major release.
|
||||
*/
|
||||
transaction(): Promise<Transaction>;
|
||||
/** Execute a sequence of SQL statements separated by semicolons.
|
||||
*
|
||||
* The statements are executed sequentially on a new logical database connection. If a statement fails,
|
||||
* further statements are not executed and this method throws an error. All results from the statements
|
||||
* are ignored.
|
||||
*
|
||||
* We do not wrap the statements in a transaction, but the SQL can contain explicit transaction-control
|
||||
* statements such as `BEGIN` and `COMMIT`.
|
||||
*
|
||||
* This method is intended to be used with existing SQL scripts, such as migrations or small database
|
||||
* dumps. If you want to execute a sequence of statements programmatically, please use {@link batch}
|
||||
* instead.
|
||||
*
|
||||
* ```javascript
|
||||
* await client.executeMultiple(`
|
||||
* CREATE TABLE books (id INTEGER PRIMARY KEY, title TEXT NOT NULL, author_id INTEGER NOT NULL);
|
||||
* CREATE TABLE authors (id INTEGER PRIMARY KEY, name TEXT NOT NULL);
|
||||
* `);
|
||||
* ```
|
||||
*/
|
||||
executeMultiple(sql: string): Promise<void>;
|
||||
sync(): Promise<Replicated>;
|
||||
/** Close the client and release resources.
|
||||
*
|
||||
* This method closes the client (aborting any operations that are currently in progress) and releases any
|
||||
* resources associated with the client (such as a WebSocket connection).
|
||||
*/
|
||||
close(): void;
|
||||
/** Reconnect after the client has been closed.
|
||||
*/
|
||||
reconnect(): void;
|
||||
/** Is the client closed?
|
||||
*
|
||||
* This is set to `true` after a call to {@link close} or if the client encounters an unrecoverable
|
||||
* error.
|
||||
*/
|
||||
closed: boolean;
|
||||
/** Which protocol does the client use?
|
||||
*
|
||||
* - `"http"` if the client connects over HTTP
|
||||
* - `"ws"` if the client connects over WebSockets
|
||||
* - `"file"` if the client works with a local file
|
||||
*/
|
||||
protocol: string;
|
||||
}
|
||||
/** Interactive transaction.
|
||||
*
|
||||
* A transaction groups multiple SQL statements together, so that they are applied atomically: either all
|
||||
* changes are applied, or none are. Other SQL statements on the database (including statements executed on
|
||||
* the same {@link Client} object outside of this transaction) will not see any changes from the transaction
|
||||
* until the transaction is committed by calling {@link commit}. You can also use {@link rollback} to abort
|
||||
* the transaction and roll back the changes.
|
||||
*
|
||||
* You **must** make sure that the {@link Transaction} object is closed, by calling {@link close}, {@link
|
||||
* commit} or {@link rollback}. The best practice is to call {@link close} in a `finally` block, as follows:
|
||||
*
|
||||
* ```javascript
|
||||
* const transaction = client.transaction("write");
|
||||
* try {
|
||||
* // do some operations with the transaction here
|
||||
* await transaction.execute({
|
||||
* sql: "INSERT INTO books (name, author) VALUES (?, ?)",
|
||||
* args: ["First Impressions", "Jane Austen"],
|
||||
* });
|
||||
* await transaction.execute({
|
||||
* sql: "UPDATE books SET name = ? WHERE name = ?",
|
||||
* args: ["Pride and Prejudice", "First Impressions"],
|
||||
* });
|
||||
*
|
||||
* // if all went well, commit the transaction
|
||||
* await transaction.commit();
|
||||
* } finally {
|
||||
* // make sure to close the transaction, even if an exception was thrown
|
||||
* transaction.close();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export interface Transaction {
|
||||
/** Execute an SQL statement in this transaction.
|
||||
*
|
||||
* If the statement makes any changes to the database, these changes won't be visible to statements
|
||||
* outside of this transaction until you call {@link rollback}.
|
||||
*
|
||||
* ```javascript
|
||||
* await transaction.execute({
|
||||
* sql: "INSERT INTO books (name, author) VALUES (?, ?)",
|
||||
* args: ["First Impressions", "Jane Austen"],
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
execute(stmt: InStatement): Promise<ResultSet>;
|
||||
/** Execute a batch of SQL statements in this transaction.
|
||||
*
|
||||
* If any of the statements in the batch fails with an error, further statements are not executed and the
|
||||
* returned promise is rejected with an error, but the transaction is not rolled back.
|
||||
*/
|
||||
batch(stmts: Array<InStatement>): Promise<Array<ResultSet>>;
|
||||
/** Execute a sequence of SQL statements separated by semicolons.
|
||||
*
|
||||
* The statements are executed sequentially in the transaction. If a statement fails, further statements
|
||||
* are not executed and this method throws an error, but the transaction won't be rolled back. All results
|
||||
* from the statements are ignored.
|
||||
*
|
||||
* This method is intended to be used with existing SQL scripts, such as migrations or small database
|
||||
* dumps. If you want to execute statements programmatically, please use {@link batch} instead.
|
||||
*/
|
||||
executeMultiple(sql: string): Promise<void>;
|
||||
/** Roll back any changes from this transaction.
|
||||
*
|
||||
* This method closes the transaction and undoes any changes done by the previous SQL statements on this
|
||||
* transaction. You cannot call this method after calling {@link commit}, though.
|
||||
*/
|
||||
rollback(): Promise<void>;
|
||||
/** Commit changes from this transaction to the database.
|
||||
*
|
||||
* This method closes the transaction and applies all changes done by the previous SQL statement on this
|
||||
* transaction. Once the returned promise is resolved successfully, the database guarantees that the
|
||||
* changes were applied.
|
||||
*/
|
||||
commit(): Promise<void>;
|
||||
/** Close the transaction.
|
||||
*
|
||||
* This method closes the transaction and releases any resources associated with the transaction. If the
|
||||
* transaction is already closed (perhaps by a previous call to {@link commit} or {@link rollback}), then
|
||||
* this method does nothing.
|
||||
*
|
||||
* If the transaction wasn't already committed by calling {@link commit}, the transaction is rolled
|
||||
* back.
|
||||
*/
|
||||
close(): void;
|
||||
/** Is the transaction closed?
|
||||
*
|
||||
* This is set to `true` after a call to {@link close}, {@link commit} or {@link rollback}, or if we
|
||||
* encounter an unrecoverable error.
|
||||
*/
|
||||
closed: boolean;
|
||||
}
|
||||
/** Transaction mode.
|
||||
*
|
||||
* The client supports multiple modes for transactions:
|
||||
*
|
||||
* - `"write"` is a read-write transaction, started with `BEGIN IMMEDIATE`. This transaction mode supports
|
||||
* both read statements (`SELECT`) and write statements (`INSERT`, `UPDATE`, `CREATE TABLE`, etc). The libSQL
|
||||
* server cannot process multiple write transactions concurrently, so if there is another write transaction
|
||||
* already started, our transaction will wait in a queue before it can begin.
|
||||
*
|
||||
* - `"read"` is a read-only transaction, started with `BEGIN TRANSACTION READONLY` (a libSQL extension). This
|
||||
* transaction mode supports only reads (`SELECT`) and will not accept write statements. The libSQL server can
|
||||
* handle multiple read transactions at the same time, so we don't need to wait for other transactions to
|
||||
* complete. A read-only transaction can also be executed on a local replica, so it provides lower latency.
|
||||
*
|
||||
* - `"deferred"` is a transaction started with `BEGIN DEFERRED`, which starts as a read transaction, but the
|
||||
* first write statement will try to upgrade it to a write transaction. However, this upgrade may fail if
|
||||
* there already is a write transaction executing on the server, so you should be ready to handle these
|
||||
* failures.
|
||||
*
|
||||
* If your transaction includes only read statements, `"read"` is always preferred over `"deferred"` or
|
||||
* `"write"`, because `"read"` transactions can be executed more efficiently and don't block other
|
||||
* transactions.
|
||||
*
|
||||
* If your transaction includes both read and write statements, you should be using the `"write"` mode most of
|
||||
* the time. Use the `"deferred"` mode only if you prefer to fail the write transaction instead of waiting for
|
||||
* the previous write transactions to complete.
|
||||
*/
|
||||
export type TransactionMode = "write" | "read" | "deferred";
|
||||
/** Result of executing an SQL statement.
|
||||
*
|
||||
* ```javascript
|
||||
* const rs = await client.execute("SELECT name, title FROM books");
|
||||
* console.log(`Found ${rs.rows.length} books`);
|
||||
* for (const row in rs.rows) {
|
||||
* console.log(`Book ${row[0]} by ${row[1]}`);
|
||||
* }
|
||||
*
|
||||
* const rs = await client.execute("DELETE FROM books WHERE author = 'Jane Austen'");
|
||||
* console.log(`Deleted ${rs.rowsAffected} books`);
|
||||
* ```
|
||||
*/
|
||||
export interface ResultSet {
|
||||
/** Names of columns.
|
||||
*
|
||||
* Names of columns can be defined using the `AS` keyword in SQL:
|
||||
*
|
||||
* ```sql
|
||||
* SELECT author AS author, COUNT(*) AS count FROM books GROUP BY author
|
||||
* ```
|
||||
*/
|
||||
columns: Array<string>;
|
||||
/** Types of columns.
|
||||
*
|
||||
* The types are currently shown for types declared in a SQL table. For
|
||||
* column types of function calls, for example, an empty string is
|
||||
* returned.
|
||||
*/
|
||||
columnTypes: Array<string>;
|
||||
/** Rows produced by the statement. */
|
||||
rows: Array<Row>;
|
||||
/** Number of rows that were affected by an UPDATE, INSERT or DELETE operation.
|
||||
*
|
||||
* This value is not specified for other SQL statements.
|
||||
*/
|
||||
rowsAffected: number;
|
||||
/** ROWID of the last inserted row.
|
||||
*
|
||||
* This value is not specified if the SQL statement was not an INSERT or if the table was not a ROWID
|
||||
* table.
|
||||
*/
|
||||
lastInsertRowid: bigint | undefined;
|
||||
/** Converts the result set to JSON.
|
||||
*
|
||||
* This is used automatically by `JSON.stringify()`, but you can also call it explicitly.
|
||||
*/
|
||||
toJSON(): any;
|
||||
}
|
||||
/** Row returned from an SQL statement.
|
||||
*
|
||||
* The row object can be used as an `Array` or as an object:
|
||||
*
|
||||
* ```javascript
|
||||
* const rs = await client.execute("SELECT name, title FROM books");
|
||||
* for (const row in rs.rows) {
|
||||
* // Get the value from column `name`
|
||||
* console.log(row.name);
|
||||
* // Get the value from second column (`title`)
|
||||
* console.log(row[1]);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export interface Row {
|
||||
/** Number of columns in this row.
|
||||
*
|
||||
* All rows in one {@link ResultSet} have the same number and names of columns.
|
||||
*/
|
||||
length: number;
|
||||
/** Columns can be accessed like an array by numeric indexes. */
|
||||
[index: number]: Value;
|
||||
/** Columns can be accessed like an object by column names. */
|
||||
[name: string]: Value;
|
||||
}
|
||||
export type Replicated = {
|
||||
frame_no: number;
|
||||
frames_synced: number;
|
||||
} | undefined;
|
||||
export type Value = null | string | number | bigint | ArrayBuffer;
|
||||
export type InValue = Value | boolean | Uint8Array | Date;
|
||||
export type InStatement = {
|
||||
sql: string;
|
||||
args?: InArgs;
|
||||
} | string;
|
||||
export type InArgs = Array<InValue> | Record<string, InValue>;
|
||||
/** Error thrown by the client. */
|
||||
export declare class LibsqlError extends Error {
|
||||
/** Machine-readable error code. */
|
||||
code: string;
|
||||
/** Raw numeric error code */
|
||||
rawCode?: number;
|
||||
constructor(message: string, code: string, rawCode?: number, cause?: Error);
|
||||
}
|
||||
16
node_modules/@libsql/core/lib-esm/api.js
generated
vendored
Normal file
16
node_modules/@libsql/core/lib-esm/api.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/** Error thrown by the client. */
|
||||
export class LibsqlError extends Error {
|
||||
/** Machine-readable error code. */
|
||||
code;
|
||||
/** Raw numeric error code */
|
||||
rawCode;
|
||||
constructor(message, code, rawCode, cause) {
|
||||
if (code !== undefined) {
|
||||
message = `${code}: ${message}`;
|
||||
}
|
||||
super(message, { cause });
|
||||
this.code = code;
|
||||
this.rawCode = rawCode;
|
||||
this.name = "LibsqlError";
|
||||
}
|
||||
}
|
||||
20
node_modules/@libsql/core/lib-esm/config.d.ts
generated
vendored
Normal file
20
node_modules/@libsql/core/lib-esm/config.d.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { Config, IntMode } from "./api.js";
|
||||
import type { Authority } from "./uri.js";
|
||||
export interface ExpandedConfig {
|
||||
scheme: ExpandedScheme;
|
||||
tls: boolean;
|
||||
authority: Authority | undefined;
|
||||
path: string;
|
||||
authToken: string | undefined;
|
||||
encryptionKey: string | undefined;
|
||||
syncUrl: string | undefined;
|
||||
syncInterval: number | undefined;
|
||||
readYourWrites: boolean | undefined;
|
||||
offline: boolean | undefined;
|
||||
intMode: IntMode;
|
||||
fetch: Function | undefined;
|
||||
concurrency: number;
|
||||
}
|
||||
export type ExpandedScheme = "wss" | "ws" | "https" | "http" | "file";
|
||||
export declare function isInMemoryConfig(config: ExpandedConfig): boolean;
|
||||
export declare function expandConfig(config: Readonly<Config>, preferHttp: boolean): ExpandedConfig;
|
||||
136
node_modules/@libsql/core/lib-esm/config.js
generated
vendored
Normal file
136
node_modules/@libsql/core/lib-esm/config.js
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
import { LibsqlError } from "./api.js";
|
||||
import { parseUri } from "./uri.js";
|
||||
import { supportedUrlLink } from "./util.js";
|
||||
const inMemoryMode = ":memory:";
|
||||
export function isInMemoryConfig(config) {
|
||||
return (config.scheme === "file" &&
|
||||
(config.path === ":memory:" || config.path.startsWith(":memory:?")));
|
||||
}
|
||||
export function expandConfig(config, preferHttp) {
|
||||
if (typeof config !== "object") {
|
||||
// produce a reasonable error message in the common case where users type
|
||||
// `createClient("libsql://...")` instead of `createClient({url: "libsql://..."})`
|
||||
throw new TypeError(`Expected client configuration as object, got ${typeof config}`);
|
||||
}
|
||||
let { url, authToken, tls, intMode, concurrency } = config;
|
||||
// fill simple defaults right here
|
||||
concurrency = Math.max(0, concurrency || 20);
|
||||
intMode ??= "number";
|
||||
let connectionQueryParams = []; // recognized query parameters which we sanitize through white list of valid key-value pairs
|
||||
// convert plain :memory: url to URI format to make logic more uniform
|
||||
if (url === inMemoryMode) {
|
||||
url = "file::memory:";
|
||||
}
|
||||
// parse url parameters first and override config with update values
|
||||
const uri = parseUri(url);
|
||||
const originalUriScheme = uri.scheme.toLowerCase();
|
||||
const isInMemoryMode = originalUriScheme === "file" &&
|
||||
uri.path === inMemoryMode &&
|
||||
uri.authority === undefined;
|
||||
let queryParamsDef;
|
||||
if (isInMemoryMode) {
|
||||
queryParamsDef = {
|
||||
cache: {
|
||||
values: ["shared", "private"],
|
||||
update: (key, value) => connectionQueryParams.push(`${key}=${value}`),
|
||||
},
|
||||
};
|
||||
}
|
||||
else {
|
||||
queryParamsDef = {
|
||||
tls: {
|
||||
values: ["0", "1"],
|
||||
update: (_, value) => (tls = value === "1"),
|
||||
},
|
||||
authToken: {
|
||||
update: (_, value) => (authToken = value),
|
||||
},
|
||||
};
|
||||
}
|
||||
for (const { key, value } of uri.query?.pairs ?? []) {
|
||||
if (!Object.hasOwn(queryParamsDef, key)) {
|
||||
throw new LibsqlError(`Unsupported URL query parameter ${JSON.stringify(key)}`, "URL_PARAM_NOT_SUPPORTED");
|
||||
}
|
||||
const queryParamDef = queryParamsDef[key];
|
||||
if (queryParamDef.values !== undefined &&
|
||||
!queryParamDef.values.includes(value)) {
|
||||
throw new LibsqlError(`Unknown value for the "${key}" query argument: ${JSON.stringify(value)}. Supported values are: [${queryParamDef.values.map((x) => '"' + x + '"').join(", ")}]`, "URL_INVALID");
|
||||
}
|
||||
if (queryParamDef.update !== undefined) {
|
||||
queryParamDef?.update(key, value);
|
||||
}
|
||||
}
|
||||
// fill complex defaults & validate config
|
||||
const connectionQueryParamsString = connectionQueryParams.length === 0
|
||||
? ""
|
||||
: `?${connectionQueryParams.join("&")}`;
|
||||
const path = uri.path + connectionQueryParamsString;
|
||||
let scheme;
|
||||
if (originalUriScheme === "libsql") {
|
||||
if (tls === false) {
|
||||
if (uri.authority?.port === undefined) {
|
||||
throw new LibsqlError('A "libsql:" URL with ?tls=0 must specify an explicit port', "URL_INVALID");
|
||||
}
|
||||
scheme = preferHttp ? "http" : "ws";
|
||||
}
|
||||
else {
|
||||
scheme = preferHttp ? "https" : "wss";
|
||||
}
|
||||
}
|
||||
else {
|
||||
scheme = originalUriScheme;
|
||||
}
|
||||
if (scheme === "http" || scheme === "ws") {
|
||||
tls ??= false;
|
||||
}
|
||||
else {
|
||||
tls ??= true;
|
||||
}
|
||||
if (scheme !== "http" &&
|
||||
scheme !== "ws" &&
|
||||
scheme !== "https" &&
|
||||
scheme !== "wss" &&
|
||||
scheme !== "file") {
|
||||
throw new LibsqlError('The client supports only "libsql:", "wss:", "ws:", "https:", "http:" and "file:" URLs, ' +
|
||||
`got ${JSON.stringify(uri.scheme + ":")}. ` +
|
||||
`For more information, please read ${supportedUrlLink}`, "URL_SCHEME_NOT_SUPPORTED");
|
||||
}
|
||||
if (intMode !== "number" && intMode !== "bigint" && intMode !== "string") {
|
||||
throw new TypeError(`Invalid value for intMode, expected "number", "bigint" or "string", got ${JSON.stringify(intMode)}`);
|
||||
}
|
||||
if (uri.fragment !== undefined) {
|
||||
throw new LibsqlError(`URL fragments are not supported: ${JSON.stringify("#" + uri.fragment)}`, "URL_INVALID");
|
||||
}
|
||||
if (isInMemoryMode) {
|
||||
return {
|
||||
scheme: "file",
|
||||
tls: false,
|
||||
path,
|
||||
intMode,
|
||||
concurrency,
|
||||
syncUrl: config.syncUrl,
|
||||
syncInterval: config.syncInterval,
|
||||
readYourWrites: config.readYourWrites,
|
||||
offline: config.offline,
|
||||
fetch: config.fetch,
|
||||
authToken: undefined,
|
||||
encryptionKey: undefined,
|
||||
authority: undefined,
|
||||
};
|
||||
}
|
||||
return {
|
||||
scheme,
|
||||
tls,
|
||||
authority: uri.authority,
|
||||
path,
|
||||
authToken,
|
||||
intMode,
|
||||
concurrency,
|
||||
encryptionKey: config.encryptionKey,
|
||||
syncUrl: config.syncUrl,
|
||||
syncInterval: config.syncInterval,
|
||||
readYourWrites: config.readYourWrites,
|
||||
offline: config.offline,
|
||||
fetch: config.fetch,
|
||||
};
|
||||
}
|
||||
30
node_modules/@libsql/core/lib-esm/uri.d.ts
generated
vendored
Normal file
30
node_modules/@libsql/core/lib-esm/uri.d.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/// <reference types="node" />
|
||||
export interface Uri {
|
||||
scheme: string;
|
||||
authority: Authority | undefined;
|
||||
path: string;
|
||||
query: Query | undefined;
|
||||
fragment: string | undefined;
|
||||
}
|
||||
export interface HierPart {
|
||||
authority: Authority | undefined;
|
||||
path: string;
|
||||
}
|
||||
export interface Authority {
|
||||
host: string;
|
||||
port: number | undefined;
|
||||
userinfo: Userinfo | undefined;
|
||||
}
|
||||
export interface Userinfo {
|
||||
username: string;
|
||||
password: string | undefined;
|
||||
}
|
||||
export interface Query {
|
||||
pairs: Array<KeyValue>;
|
||||
}
|
||||
export interface KeyValue {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
export declare function parseUri(text: string): Uri;
|
||||
export declare function encodeBaseUrl(scheme: string, authority: Authority | undefined, path: string): URL;
|
||||
120
node_modules/@libsql/core/lib-esm/uri.js
generated
vendored
Normal file
120
node_modules/@libsql/core/lib-esm/uri.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
// URI parser based on RFC 3986
|
||||
// We can't use the standard `URL` object, because we want to support relative `file:` URLs like
|
||||
// `file:relative/path/database.db`, which are not correct according to RFC 8089, which standardizes the
|
||||
// `file` scheme.
|
||||
import { LibsqlError } from "./api.js";
|
||||
export function parseUri(text) {
|
||||
const match = URI_RE.exec(text);
|
||||
if (match === null) {
|
||||
throw new LibsqlError(`The URL '${text}' is not in a valid format`, "URL_INVALID");
|
||||
}
|
||||
const groups = match.groups;
|
||||
const scheme = groups["scheme"];
|
||||
const authority = groups["authority"] !== undefined
|
||||
? parseAuthority(groups["authority"])
|
||||
: undefined;
|
||||
const path = percentDecode(groups["path"]);
|
||||
const query = groups["query"] !== undefined ? parseQuery(groups["query"]) : undefined;
|
||||
const fragment = groups["fragment"] !== undefined
|
||||
? percentDecode(groups["fragment"])
|
||||
: undefined;
|
||||
return { scheme, authority, path, query, fragment };
|
||||
}
|
||||
const URI_RE = (() => {
|
||||
const SCHEME = "(?<scheme>[A-Za-z][A-Za-z.+-]*)";
|
||||
const AUTHORITY = "(?<authority>[^/?#]*)";
|
||||
const PATH = "(?<path>[^?#]*)";
|
||||
const QUERY = "(?<query>[^#]*)";
|
||||
const FRAGMENT = "(?<fragment>.*)";
|
||||
return new RegExp(`^${SCHEME}:(//${AUTHORITY})?${PATH}(\\?${QUERY})?(#${FRAGMENT})?$`, "su");
|
||||
})();
|
||||
function parseAuthority(text) {
|
||||
const match = AUTHORITY_RE.exec(text);
|
||||
if (match === null) {
|
||||
throw new LibsqlError("The authority part of the URL is not in a valid format", "URL_INVALID");
|
||||
}
|
||||
const groups = match.groups;
|
||||
const host = percentDecode(groups["host_br"] ?? groups["host"]);
|
||||
const port = groups["port"] ? parseInt(groups["port"], 10) : undefined;
|
||||
const userinfo = groups["username"] !== undefined
|
||||
? {
|
||||
username: percentDecode(groups["username"]),
|
||||
password: groups["password"] !== undefined
|
||||
? percentDecode(groups["password"])
|
||||
: undefined,
|
||||
}
|
||||
: undefined;
|
||||
return { host, port, userinfo };
|
||||
}
|
||||
const AUTHORITY_RE = (() => {
|
||||
return new RegExp(`^((?<username>[^:]*)(:(?<password>.*))?@)?((?<host>[^:\\[\\]]*)|(\\[(?<host_br>[^\\[\\]]*)\\]))(:(?<port>[0-9]*))?$`, "su");
|
||||
})();
|
||||
// Query string is parsed as application/x-www-form-urlencoded according to the Web URL standard:
|
||||
// https://url.spec.whatwg.org/#urlencoded-parsing
|
||||
function parseQuery(text) {
|
||||
const sequences = text.split("&");
|
||||
const pairs = [];
|
||||
for (const sequence of sequences) {
|
||||
if (sequence === "") {
|
||||
continue;
|
||||
}
|
||||
let key;
|
||||
let value;
|
||||
const splitIdx = sequence.indexOf("=");
|
||||
if (splitIdx < 0) {
|
||||
key = sequence;
|
||||
value = "";
|
||||
}
|
||||
else {
|
||||
key = sequence.substring(0, splitIdx);
|
||||
value = sequence.substring(splitIdx + 1);
|
||||
}
|
||||
pairs.push({
|
||||
key: percentDecode(key.replaceAll("+", " ")),
|
||||
value: percentDecode(value.replaceAll("+", " ")),
|
||||
});
|
||||
}
|
||||
return { pairs };
|
||||
}
|
||||
function percentDecode(text) {
|
||||
try {
|
||||
return decodeURIComponent(text);
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof URIError) {
|
||||
throw new LibsqlError(`URL component has invalid percent encoding: ${e}`, "URL_INVALID", undefined, e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
export function encodeBaseUrl(scheme, authority, path) {
|
||||
if (authority === undefined) {
|
||||
throw new LibsqlError(`URL with scheme ${JSON.stringify(scheme + ":")} requires authority (the "//" part)`, "URL_INVALID");
|
||||
}
|
||||
const schemeText = `${scheme}:`;
|
||||
const hostText = encodeHost(authority.host);
|
||||
const portText = encodePort(authority.port);
|
||||
const userinfoText = encodeUserinfo(authority.userinfo);
|
||||
const authorityText = `//${userinfoText}${hostText}${portText}`;
|
||||
let pathText = path.split("/").map(encodeURIComponent).join("/");
|
||||
if (pathText !== "" && !pathText.startsWith("/")) {
|
||||
pathText = "/" + pathText;
|
||||
}
|
||||
return new URL(`${schemeText}${authorityText}${pathText}`);
|
||||
}
|
||||
function encodeHost(host) {
|
||||
return host.includes(":") ? `[${encodeURI(host)}]` : encodeURI(host);
|
||||
}
|
||||
function encodePort(port) {
|
||||
return port !== undefined ? `:${port}` : "";
|
||||
}
|
||||
function encodeUserinfo(userinfo) {
|
||||
if (userinfo === undefined) {
|
||||
return "";
|
||||
}
|
||||
const usernameText = encodeURIComponent(userinfo.username);
|
||||
const passwordText = userinfo.password !== undefined
|
||||
? `:${encodeURIComponent(userinfo.password)}`
|
||||
: "";
|
||||
return `${usernameText}${passwordText}@`;
|
||||
}
|
||||
12
node_modules/@libsql/core/lib-esm/util.d.ts
generated
vendored
Normal file
12
node_modules/@libsql/core/lib-esm/util.d.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ResultSet, Row, TransactionMode } from "./api";
|
||||
export declare const supportedUrlLink = "https://github.com/libsql/libsql-client-ts#supported-urls";
|
||||
export declare function transactionModeToBegin(mode: TransactionMode): string;
|
||||
export declare class ResultSetImpl implements ResultSet {
|
||||
columns: Array<string>;
|
||||
columnTypes: Array<string>;
|
||||
rows: Array<Row>;
|
||||
rowsAffected: number;
|
||||
lastInsertRowid: bigint | undefined;
|
||||
constructor(columns: Array<string>, columnTypes: Array<string>, rows: Array<Row>, rowsAffected: number, lastInsertRowid: bigint | undefined);
|
||||
toJSON(): any;
|
||||
}
|
||||
55
node_modules/@libsql/core/lib-esm/util.js
generated
vendored
Normal file
55
node_modules/@libsql/core/lib-esm/util.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Base64 } from "js-base64";
|
||||
export const supportedUrlLink = "https://github.com/libsql/libsql-client-ts#supported-urls";
|
||||
export function transactionModeToBegin(mode) {
|
||||
if (mode === "write") {
|
||||
return "BEGIN IMMEDIATE";
|
||||
}
|
||||
else if (mode === "read") {
|
||||
return "BEGIN TRANSACTION READONLY";
|
||||
}
|
||||
else if (mode === "deferred") {
|
||||
return "BEGIN DEFERRED";
|
||||
}
|
||||
else {
|
||||
throw RangeError('Unknown transaction mode, supported values are "write", "read" and "deferred"');
|
||||
}
|
||||
}
|
||||
export class ResultSetImpl {
|
||||
columns;
|
||||
columnTypes;
|
||||
rows;
|
||||
rowsAffected;
|
||||
lastInsertRowid;
|
||||
constructor(columns, columnTypes, rows, rowsAffected, lastInsertRowid) {
|
||||
this.columns = columns;
|
||||
this.columnTypes = columnTypes;
|
||||
this.rows = rows;
|
||||
this.rowsAffected = rowsAffected;
|
||||
this.lastInsertRowid = lastInsertRowid;
|
||||
}
|
||||
toJSON() {
|
||||
return {
|
||||
columns: this.columns,
|
||||
columnTypes: this.columnTypes,
|
||||
rows: this.rows.map(rowToJson),
|
||||
rowsAffected: this.rowsAffected,
|
||||
lastInsertRowid: this.lastInsertRowid !== undefined
|
||||
? "" + this.lastInsertRowid
|
||||
: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
function rowToJson(row) {
|
||||
return Array.prototype.map.call(row, valueToJson);
|
||||
}
|
||||
function valueToJson(value) {
|
||||
if (typeof value === "bigint") {
|
||||
return "" + value;
|
||||
}
|
||||
else if (value instanceof ArrayBuffer) {
|
||||
return Base64.fromUint8Array(new Uint8Array(value));
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
91
node_modules/@libsql/core/package.json
generated
vendored
Normal file
91
node_modules/@libsql/core/package.json
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"name": "@libsql/core",
|
||||
"version": "0.15.15",
|
||||
"keywords": [
|
||||
"libsql",
|
||||
"database",
|
||||
"sqlite",
|
||||
"serverless",
|
||||
"vercel",
|
||||
"netlify",
|
||||
"lambda"
|
||||
],
|
||||
"description": "libSQL driver for TypeScript and JavaScript",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/libsql/libsql-client-ts",
|
||||
"directory": "packages/libsql-core"
|
||||
},
|
||||
"authors": [
|
||||
"Jan Špaček <honza@chiselstrike.com>",
|
||||
"Pekka Enberg <penberg@chiselstrike.com>",
|
||||
"Jan Plhak <jp@chiselstrike.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./api": {
|
||||
"types": "./lib-esm/api.d.ts",
|
||||
"import": "./lib-esm/api.js",
|
||||
"require": "./lib-cjs/api.js"
|
||||
},
|
||||
"./config": {
|
||||
"types": "./lib-esm/config.d.ts",
|
||||
"import": "./lib-esm/config.js",
|
||||
"require": "./lib-cjs/config.js"
|
||||
},
|
||||
"./uri": {
|
||||
"types": "./lib-esm/uri.d.ts",
|
||||
"import": "./lib-esm/uri.js",
|
||||
"require": "./lib-cjs/uri.js"
|
||||
},
|
||||
"./util": {
|
||||
"types": "./lib-esm/util.d.ts",
|
||||
"import": "./lib-esm/util.js",
|
||||
"require": "./lib-cjs/util.js"
|
||||
}
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"api": [
|
||||
"./lib-esm/api.d.ts"
|
||||
],
|
||||
"config": [
|
||||
"./lib-esm/config.d.ts"
|
||||
],
|
||||
"uri": [
|
||||
"./lib-esm/uri.d.ts"
|
||||
],
|
||||
"util": [
|
||||
"./lib-esm/util.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"lib-cjs/**",
|
||||
"lib-esm/**"
|
||||
],
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
"prebuild": "rm -rf ./lib-cjs ./lib-esm",
|
||||
"build": "npm run build:cjs && npm run build:esm",
|
||||
"build:cjs": "tsc -p tsconfig.build-cjs.json",
|
||||
"build:esm": "tsc -p tsconfig.build-esm.json",
|
||||
"format:check": "prettier --check .",
|
||||
"postbuild": "cp package-cjs.json ./lib-cjs/package.json",
|
||||
"test": "jest --runInBand",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"typedoc": "rm -rf ./docs && typedoc"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-base64": "^3.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.2.5",
|
||||
"@types/node": "^18.15.5",
|
||||
"jest": "^29.3.1",
|
||||
"ts-jest": "^29.0.5",
|
||||
"typedoc": "^0.23.28",
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
||||
3
node_modules/@libsql/darwin-arm64/README.md
generated
vendored
Normal file
3
node_modules/@libsql/darwin-arm64/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# `@libsql/darwin-arm64`
|
||||
|
||||
Prebuilt binary package for `libsql` on `darwin-arm64`.
|
||||
BIN
node_modules/@libsql/darwin-arm64/index.node
generated
vendored
Executable file
BIN
node_modules/@libsql/darwin-arm64/index.node
generated
vendored
Executable file
Binary file not shown.
36
node_modules/@libsql/darwin-arm64/package.json
generated
vendored
Normal file
36
node_modules/@libsql/darwin-arm64/package.json
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "@libsql/darwin-arm64",
|
||||
"description": "Prebuilt binary package for `libsql` on `darwin-arm64`.",
|
||||
"version": "0.5.29",
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"main": "index.node",
|
||||
"files": [
|
||||
"index.node"
|
||||
],
|
||||
"neon": {
|
||||
"type": "binary",
|
||||
"rust": "aarch64-apple-darwin",
|
||||
"node": "darwin-arm64",
|
||||
"platform": "darwin",
|
||||
"arch": "arm64",
|
||||
"abi": null
|
||||
},
|
||||
"author": "Pekka Enberg <penberg@iki.fi>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tursodatabase/libsql-js.git"
|
||||
},
|
||||
"keywords": [
|
||||
"libsql"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/tursodatabase/libsql-js/issues"
|
||||
},
|
||||
"homepage": "https://github.com/tursodatabase/libsql-js",
|
||||
"license": "MIT"
|
||||
}
|
||||
20
node_modules/@libsql/hrana-client/LICENSE
generated
vendored
Normal file
20
node_modules/@libsql/hrana-client/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
MIT License
|
||||
|
||||
Copyright 2023 the sqld authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
59
node_modules/@libsql/hrana-client/README.md
generated
vendored
Normal file
59
node_modules/@libsql/hrana-client/README.md
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
# Hrana client for TypeScript
|
||||
|
||||
**[API docs][docs] | [Github][github] | [npm][npm]**
|
||||
|
||||
[docs]: https://libsql.org/hrana-client-ts/
|
||||
[github]: https://github.com/libsql/hrana-client-ts/
|
||||
[npm]: https://www.npmjs.com/package/@libsql/hrana-client
|
||||
|
||||
This package implements a Hrana client for TypeScript. Hrana is the protocol for connecting to sqld using WebSocket or HTTP.
|
||||
|
||||
> This package is intended mostly for internal use. Consider using the [`@libsql/client`][libsql-client] package, which will use Hrana automatically.
|
||||
|
||||
[libsql-client]: https://www.npmjs.com/package/@libsql/client
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import * as hrana from "@libsql/hrana-client";
|
||||
|
||||
// Open a `hrana.Client`, which works like a connection pool in standard SQL
|
||||
// databases.
|
||||
const url = process.env.URL ?? "ws://localhost:8080"; // Address of the sqld server
|
||||
const jwt = process.env.JWT; // JWT token for authentication
|
||||
// Here we are using Hrana over WebSocket:
|
||||
const client = hrana.openWs(url, jwt);
|
||||
// But we can also use Hrana over HTTP:
|
||||
// const client = hrana.openHttp(url, jwt);
|
||||
|
||||
// Open a `hrana.Stream`, which is an interactive SQL stream. This corresponds
|
||||
// to a "connection" from other SQL databases
|
||||
const stream = client.openStream();
|
||||
|
||||
// Fetch all rows returned by a SQL statement
|
||||
const books = await stream.query("SELECT title, year FROM book WHERE author = 'Jane Austen'");
|
||||
// The rows are returned in an Array...
|
||||
for (const book of books.rows) {
|
||||
// every returned row works as an array (`book[1]`) and as an object (`book.year`)
|
||||
console.log(`${book.title} from ${book.year}`);
|
||||
}
|
||||
|
||||
// Fetch a single row
|
||||
const book = await stream.queryRow("SELECT title, MIN(year) FROM book");
|
||||
if (book.row !== undefined) {
|
||||
console.log(`The oldest book is ${book.row.title} from year ${book.row[1]}`);
|
||||
}
|
||||
|
||||
// Fetch a single value, using a bound parameter
|
||||
const year = await stream.queryValue(["SELECT MAX(year) FROM book WHERE author = ?", ["Jane Austen"]]);
|
||||
if (year.value !== undefined) {
|
||||
console.log(`Last book from Jane Austen was published in ${year.value}`);
|
||||
}
|
||||
|
||||
// Execute a statement that does not return any rows
|
||||
const res = await stream.run(["DELETE FROM book WHERE author = ?", ["J. K. Rowling"]])
|
||||
console.log(`${res.affectedRowCount} books have been cancelled`);
|
||||
|
||||
// When you are done, remember to close the client
|
||||
client.close();
|
||||
```
|
||||
277
node_modules/@libsql/hrana-client/lib-cjs/batch.js
generated
vendored
Normal file
277
node_modules/@libsql/hrana-client/lib-cjs/batch.js
generated
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BatchCond = exports.BatchStep = exports.Batch = void 0;
|
||||
const errors_js_1 = require("./errors.js");
|
||||
const result_js_1 = require("./result.js");
|
||||
const stmt_js_1 = require("./stmt.js");
|
||||
const util_js_1 = require("./util.js");
|
||||
/** A builder for creating a batch and executing it on the server. */
|
||||
class Batch {
|
||||
/** @private */
|
||||
_stream;
|
||||
#useCursor;
|
||||
/** @private */
|
||||
_steps;
|
||||
#executed;
|
||||
/** @private */
|
||||
constructor(stream, useCursor) {
|
||||
this._stream = stream;
|
||||
this.#useCursor = useCursor;
|
||||
this._steps = [];
|
||||
this.#executed = false;
|
||||
}
|
||||
/** Return a builder for adding a step to the batch. */
|
||||
step() {
|
||||
return new BatchStep(this);
|
||||
}
|
||||
/** Execute the batch. */
|
||||
execute() {
|
||||
if (this.#executed) {
|
||||
throw new errors_js_1.MisuseError("This batch has already been executed");
|
||||
}
|
||||
this.#executed = true;
|
||||
const batch = {
|
||||
steps: this._steps.map((step) => step.proto),
|
||||
};
|
||||
if (this.#useCursor) {
|
||||
return executeCursor(this._stream, this._steps, batch);
|
||||
}
|
||||
else {
|
||||
return executeRegular(this._stream, this._steps, batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Batch = Batch;
|
||||
function executeRegular(stream, steps, batch) {
|
||||
return stream._batch(batch).then((result) => {
|
||||
for (let step = 0; step < steps.length; ++step) {
|
||||
const stepResult = result.stepResults.get(step);
|
||||
const stepError = result.stepErrors.get(step);
|
||||
steps[step].callback(stepResult, stepError);
|
||||
}
|
||||
});
|
||||
}
|
||||
async function executeCursor(stream, steps, batch) {
|
||||
const cursor = await stream._openCursor(batch);
|
||||
try {
|
||||
let nextStep = 0;
|
||||
let beginEntry = undefined;
|
||||
let rows = [];
|
||||
for (;;) {
|
||||
const entry = await cursor.next();
|
||||
if (entry === undefined) {
|
||||
break;
|
||||
}
|
||||
if (entry.type === "step_begin") {
|
||||
if (entry.step < nextStep || entry.step >= steps.length) {
|
||||
throw new errors_js_1.ProtoError("Server produced StepBeginEntry for unexpected step");
|
||||
}
|
||||
else if (beginEntry !== undefined) {
|
||||
throw new errors_js_1.ProtoError("Server produced StepBeginEntry before terminating previous step");
|
||||
}
|
||||
for (let step = nextStep; step < entry.step; ++step) {
|
||||
steps[step].callback(undefined, undefined);
|
||||
}
|
||||
nextStep = entry.step + 1;
|
||||
beginEntry = entry;
|
||||
rows = [];
|
||||
}
|
||||
else if (entry.type === "step_end") {
|
||||
if (beginEntry === undefined) {
|
||||
throw new errors_js_1.ProtoError("Server produced StepEndEntry but no step is active");
|
||||
}
|
||||
const stmtResult = {
|
||||
cols: beginEntry.cols,
|
||||
rows,
|
||||
affectedRowCount: entry.affectedRowCount,
|
||||
lastInsertRowid: entry.lastInsertRowid,
|
||||
};
|
||||
steps[beginEntry.step].callback(stmtResult, undefined);
|
||||
beginEntry = undefined;
|
||||
rows = [];
|
||||
}
|
||||
else if (entry.type === "step_error") {
|
||||
if (beginEntry === undefined) {
|
||||
if (entry.step >= steps.length) {
|
||||
throw new errors_js_1.ProtoError("Server produced StepErrorEntry for unexpected step");
|
||||
}
|
||||
for (let step = nextStep; step < entry.step; ++step) {
|
||||
steps[step].callback(undefined, undefined);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (entry.step !== beginEntry.step) {
|
||||
throw new errors_js_1.ProtoError("Server produced StepErrorEntry for unexpected step");
|
||||
}
|
||||
beginEntry = undefined;
|
||||
rows = [];
|
||||
}
|
||||
steps[entry.step].callback(undefined, entry.error);
|
||||
nextStep = entry.step + 1;
|
||||
}
|
||||
else if (entry.type === "row") {
|
||||
if (beginEntry === undefined) {
|
||||
throw new errors_js_1.ProtoError("Server produced RowEntry but no step is active");
|
||||
}
|
||||
rows.push(entry.row);
|
||||
}
|
||||
else if (entry.type === "error") {
|
||||
throw (0, result_js_1.errorFromProto)(entry.error);
|
||||
}
|
||||
else if (entry.type === "none") {
|
||||
throw new errors_js_1.ProtoError("Server produced unrecognized CursorEntry");
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(entry, "Impossible CursorEntry");
|
||||
}
|
||||
}
|
||||
if (beginEntry !== undefined) {
|
||||
throw new errors_js_1.ProtoError("Server closed Cursor before terminating active step");
|
||||
}
|
||||
for (let step = nextStep; step < steps.length; ++step) {
|
||||
steps[step].callback(undefined, undefined);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
/** A builder for adding a step to the batch. */
|
||||
class BatchStep {
|
||||
/** @private */
|
||||
_batch;
|
||||
#conds;
|
||||
/** @private */
|
||||
_index;
|
||||
/** @private */
|
||||
constructor(batch) {
|
||||
this._batch = batch;
|
||||
this.#conds = [];
|
||||
this._index = undefined;
|
||||
}
|
||||
/** Add the condition that needs to be satisfied to execute the statement. If you use this method multiple
|
||||
* times, we join the conditions with a logical AND. */
|
||||
condition(cond) {
|
||||
this.#conds.push(cond._proto);
|
||||
return this;
|
||||
}
|
||||
/** Add a statement that returns rows. */
|
||||
query(stmt) {
|
||||
return this.#add(stmt, true, result_js_1.rowsResultFromProto);
|
||||
}
|
||||
/** Add a statement that returns at most a single row. */
|
||||
queryRow(stmt) {
|
||||
return this.#add(stmt, true, result_js_1.rowResultFromProto);
|
||||
}
|
||||
/** Add a statement that returns at most a single value. */
|
||||
queryValue(stmt) {
|
||||
return this.#add(stmt, true, result_js_1.valueResultFromProto);
|
||||
}
|
||||
/** Add a statement without returning rows. */
|
||||
run(stmt) {
|
||||
return this.#add(stmt, false, result_js_1.stmtResultFromProto);
|
||||
}
|
||||
#add(inStmt, wantRows, fromProto) {
|
||||
if (this._index !== undefined) {
|
||||
throw new errors_js_1.MisuseError("This BatchStep has already been added to the batch");
|
||||
}
|
||||
const stmt = (0, stmt_js_1.stmtToProto)(this._batch._stream._sqlOwner(), inStmt, wantRows);
|
||||
let condition;
|
||||
if (this.#conds.length === 0) {
|
||||
condition = undefined;
|
||||
}
|
||||
else if (this.#conds.length === 1) {
|
||||
condition = this.#conds[0];
|
||||
}
|
||||
else {
|
||||
condition = { type: "and", conds: this.#conds.slice() };
|
||||
}
|
||||
const proto = { stmt, condition };
|
||||
return new Promise((outputCallback, errorCallback) => {
|
||||
const callback = (stepResult, stepError) => {
|
||||
if (stepResult !== undefined && stepError !== undefined) {
|
||||
errorCallback(new errors_js_1.ProtoError("Server returned both result and error"));
|
||||
}
|
||||
else if (stepError !== undefined) {
|
||||
errorCallback((0, result_js_1.errorFromProto)(stepError));
|
||||
}
|
||||
else if (stepResult !== undefined) {
|
||||
outputCallback(fromProto(stepResult, this._batch._stream.intMode));
|
||||
}
|
||||
else {
|
||||
outputCallback(undefined);
|
||||
}
|
||||
};
|
||||
this._index = this._batch._steps.length;
|
||||
this._batch._steps.push({ proto, callback });
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.BatchStep = BatchStep;
|
||||
class BatchCond {
|
||||
/** @private */
|
||||
_batch;
|
||||
/** @private */
|
||||
_proto;
|
||||
/** @private */
|
||||
constructor(batch, proto) {
|
||||
this._batch = batch;
|
||||
this._proto = proto;
|
||||
}
|
||||
/** Create a condition that evaluates to true when the given step executes successfully.
|
||||
*
|
||||
* If the given step fails error or is skipped because its condition evaluated to false, this
|
||||
* condition evaluates to false.
|
||||
*/
|
||||
static ok(step) {
|
||||
return new BatchCond(step._batch, { type: "ok", step: stepIndex(step) });
|
||||
}
|
||||
/** Create a condition that evaluates to true when the given step fails.
|
||||
*
|
||||
* If the given step succeeds or is skipped because its condition evaluated to false, this condition
|
||||
* evaluates to false.
|
||||
*/
|
||||
static error(step) {
|
||||
return new BatchCond(step._batch, { type: "error", step: stepIndex(step) });
|
||||
}
|
||||
/** Create a condition that is a logical negation of another condition.
|
||||
*/
|
||||
static not(cond) {
|
||||
return new BatchCond(cond._batch, { type: "not", cond: cond._proto });
|
||||
}
|
||||
/** Create a condition that is a logical AND of other conditions.
|
||||
*/
|
||||
static and(batch, conds) {
|
||||
for (const cond of conds) {
|
||||
checkCondBatch(batch, cond);
|
||||
}
|
||||
return new BatchCond(batch, { type: "and", conds: conds.map(e => e._proto) });
|
||||
}
|
||||
/** Create a condition that is a logical OR of other conditions.
|
||||
*/
|
||||
static or(batch, conds) {
|
||||
for (const cond of conds) {
|
||||
checkCondBatch(batch, cond);
|
||||
}
|
||||
return new BatchCond(batch, { type: "or", conds: conds.map(e => e._proto) });
|
||||
}
|
||||
/** Create a condition that evaluates to true when the SQL connection is in autocommit mode (not inside an
|
||||
* explicit transaction). This requires protocol version 3 or higher.
|
||||
*/
|
||||
static isAutocommit(batch) {
|
||||
batch._stream.client()._ensureVersion(3, "BatchCond.isAutocommit()");
|
||||
return new BatchCond(batch, { type: "is_autocommit" });
|
||||
}
|
||||
}
|
||||
exports.BatchCond = BatchCond;
|
||||
function stepIndex(step) {
|
||||
if (step._index === undefined) {
|
||||
throw new errors_js_1.MisuseError("Cannot add a condition referencing a step that has not been added to the batch");
|
||||
}
|
||||
return step._index;
|
||||
}
|
||||
function checkCondBatch(expectedBatch, cond) {
|
||||
if (cond._batch !== expectedBatch) {
|
||||
throw new errors_js_1.MisuseError("Cannot mix BatchCond objects for different Batch objects");
|
||||
}
|
||||
}
|
||||
49
node_modules/@libsql/hrana-client/lib-cjs/byte_queue.js
generated
vendored
Normal file
49
node_modules/@libsql/hrana-client/lib-cjs/byte_queue.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ByteQueue = void 0;
|
||||
class ByteQueue {
|
||||
#array;
|
||||
#shiftPos;
|
||||
#pushPos;
|
||||
constructor(initialCap) {
|
||||
this.#array = new Uint8Array(new ArrayBuffer(initialCap));
|
||||
this.#shiftPos = 0;
|
||||
this.#pushPos = 0;
|
||||
}
|
||||
get length() {
|
||||
return this.#pushPos - this.#shiftPos;
|
||||
}
|
||||
data() {
|
||||
return this.#array.slice(this.#shiftPos, this.#pushPos);
|
||||
}
|
||||
push(chunk) {
|
||||
this.#ensurePush(chunk.byteLength);
|
||||
this.#array.set(chunk, this.#pushPos);
|
||||
this.#pushPos += chunk.byteLength;
|
||||
}
|
||||
#ensurePush(pushLength) {
|
||||
if (this.#pushPos + pushLength <= this.#array.byteLength) {
|
||||
return;
|
||||
}
|
||||
const filledLength = this.#pushPos - this.#shiftPos;
|
||||
if (filledLength + pushLength <= this.#array.byteLength &&
|
||||
2 * this.#pushPos >= this.#array.byteLength) {
|
||||
this.#array.copyWithin(0, this.#shiftPos, this.#pushPos);
|
||||
}
|
||||
else {
|
||||
let newCap = this.#array.byteLength;
|
||||
do {
|
||||
newCap *= 2;
|
||||
} while (filledLength + pushLength > newCap);
|
||||
const newArray = new Uint8Array(new ArrayBuffer(newCap));
|
||||
newArray.set(this.#array.slice(this.#shiftPos, this.#pushPos), 0);
|
||||
this.#array = newArray;
|
||||
}
|
||||
this.#pushPos = filledLength;
|
||||
this.#shiftPos = 0;
|
||||
}
|
||||
shift(length) {
|
||||
this.#shiftPos += length;
|
||||
}
|
||||
}
|
||||
exports.ByteQueue = ByteQueue;
|
||||
17
node_modules/@libsql/hrana-client/lib-cjs/client.js
generated
vendored
Normal file
17
node_modules/@libsql/hrana-client/lib-cjs/client.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Client = void 0;
|
||||
/** A client for the Hrana protocol (a "database connection pool"). */
|
||||
class Client {
|
||||
/** @private */
|
||||
constructor() {
|
||||
this.intMode = "number";
|
||||
}
|
||||
/** Representation of integers returned from the database. See {@link IntMode}.
|
||||
*
|
||||
* This value is inherited by {@link Stream} objects created with {@link openStream}, but you can
|
||||
* override the integer mode for every stream by setting {@link Stream.intMode} on the stream.
|
||||
*/
|
||||
intMode;
|
||||
}
|
||||
exports.Client = Client;
|
||||
6
node_modules/@libsql/hrana-client/lib-cjs/cursor.js
generated
vendored
Normal file
6
node_modules/@libsql/hrana-client/lib-cjs/cursor.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Cursor = void 0;
|
||||
class Cursor {
|
||||
}
|
||||
exports.Cursor = Cursor;
|
||||
12
node_modules/@libsql/hrana-client/lib-cjs/describe.js
generated
vendored
Normal file
12
node_modules/@libsql/hrana-client/lib-cjs/describe.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.describeResultFromProto = void 0;
|
||||
function describeResultFromProto(result) {
|
||||
return {
|
||||
paramNames: result.params.map((p) => p.name),
|
||||
columns: result.cols,
|
||||
isExplain: result.isExplain,
|
||||
isReadonly: result.isReadonly,
|
||||
};
|
||||
}
|
||||
exports.describeResultFromProto = describeResultFromProto;
|
||||
11
node_modules/@libsql/hrana-client/lib-cjs/encoding/index.js
generated
vendored
Normal file
11
node_modules/@libsql/hrana-client/lib-cjs/encoding/index.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.writeProtobufMessage = exports.readProtobufMessage = exports.writeJsonObject = exports.readJsonObject = void 0;
|
||||
var decode_js_1 = require("./json/decode.js");
|
||||
Object.defineProperty(exports, "readJsonObject", { enumerable: true, get: function () { return decode_js_1.readJsonObject; } });
|
||||
var encode_js_1 = require("./json/encode.js");
|
||||
Object.defineProperty(exports, "writeJsonObject", { enumerable: true, get: function () { return encode_js_1.writeJsonObject; } });
|
||||
var decode_js_2 = require("./protobuf/decode.js");
|
||||
Object.defineProperty(exports, "readProtobufMessage", { enumerable: true, get: function () { return decode_js_2.readProtobufMessage; } });
|
||||
var encode_js_2 = require("./protobuf/encode.js");
|
||||
Object.defineProperty(exports, "writeProtobufMessage", { enumerable: true, get: function () { return encode_js_2.writeProtobufMessage; } });
|
||||
70
node_modules/@libsql/hrana-client/lib-cjs/encoding/json/decode.js
generated
vendored
Normal file
70
node_modules/@libsql/hrana-client/lib-cjs/encoding/json/decode.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.readJsonObject = exports.arrayObjectsMap = exports.object = exports.array = exports.boolean = exports.number = exports.stringOpt = exports.string = void 0;
|
||||
const errors_js_1 = require("../../errors.js");
|
||||
function string(value) {
|
||||
if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
throw typeError(value, "string");
|
||||
}
|
||||
exports.string = string;
|
||||
function stringOpt(value) {
|
||||
if (value === null || value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
else if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
throw typeError(value, "string or null");
|
||||
}
|
||||
exports.stringOpt = stringOpt;
|
||||
function number(value) {
|
||||
if (typeof value === "number") {
|
||||
return value;
|
||||
}
|
||||
throw typeError(value, "number");
|
||||
}
|
||||
exports.number = number;
|
||||
function boolean(value) {
|
||||
if (typeof value === "boolean") {
|
||||
return value;
|
||||
}
|
||||
throw typeError(value, "boolean");
|
||||
}
|
||||
exports.boolean = boolean;
|
||||
function array(value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value;
|
||||
}
|
||||
throw typeError(value, "array");
|
||||
}
|
||||
exports.array = array;
|
||||
function object(value) {
|
||||
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
||||
return value;
|
||||
}
|
||||
throw typeError(value, "object");
|
||||
}
|
||||
exports.object = object;
|
||||
function arrayObjectsMap(value, fun) {
|
||||
return array(value).map((elemValue) => fun(object(elemValue)));
|
||||
}
|
||||
exports.arrayObjectsMap = arrayObjectsMap;
|
||||
function typeError(value, expected) {
|
||||
if (value === undefined) {
|
||||
return new errors_js_1.ProtoError(`Expected ${expected}, but the property was missing`);
|
||||
}
|
||||
let received = typeof value;
|
||||
if (value === null) {
|
||||
received = "null";
|
||||
}
|
||||
else if (Array.isArray(value)) {
|
||||
received = "array";
|
||||
}
|
||||
return new errors_js_1.ProtoError(`Expected ${expected}, received ${received}`);
|
||||
}
|
||||
function readJsonObject(value, fun) {
|
||||
return fun(object(value));
|
||||
}
|
||||
exports.readJsonObject = readJsonObject;
|
||||
77
node_modules/@libsql/hrana-client/lib-cjs/encoding/json/encode.js
generated
vendored
Normal file
77
node_modules/@libsql/hrana-client/lib-cjs/encoding/json/encode.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.writeJsonObject = exports.ObjectWriter = void 0;
|
||||
class ObjectWriter {
|
||||
#output;
|
||||
#isFirst;
|
||||
constructor(output) {
|
||||
this.#output = output;
|
||||
this.#isFirst = false;
|
||||
}
|
||||
begin() {
|
||||
this.#output.push('{');
|
||||
this.#isFirst = true;
|
||||
}
|
||||
end() {
|
||||
this.#output.push('}');
|
||||
this.#isFirst = false;
|
||||
}
|
||||
#key(name) {
|
||||
if (this.#isFirst) {
|
||||
this.#output.push('"');
|
||||
this.#isFirst = false;
|
||||
}
|
||||
else {
|
||||
this.#output.push(',"');
|
||||
}
|
||||
this.#output.push(name);
|
||||
this.#output.push('":');
|
||||
}
|
||||
string(name, value) {
|
||||
this.#key(name);
|
||||
this.#output.push(JSON.stringify(value));
|
||||
}
|
||||
stringRaw(name, value) {
|
||||
this.#key(name);
|
||||
this.#output.push('"');
|
||||
this.#output.push(value);
|
||||
this.#output.push('"');
|
||||
}
|
||||
number(name, value) {
|
||||
this.#key(name);
|
||||
this.#output.push("" + value);
|
||||
}
|
||||
boolean(name, value) {
|
||||
this.#key(name);
|
||||
this.#output.push(value ? "true" : "false");
|
||||
}
|
||||
object(name, value, valueFun) {
|
||||
this.#key(name);
|
||||
this.begin();
|
||||
valueFun(this, value);
|
||||
this.end();
|
||||
}
|
||||
arrayObjects(name, values, valueFun) {
|
||||
this.#key(name);
|
||||
this.#output.push('[');
|
||||
for (let i = 0; i < values.length; ++i) {
|
||||
if (i !== 0) {
|
||||
this.#output.push(',');
|
||||
}
|
||||
this.begin();
|
||||
valueFun(this, values[i]);
|
||||
this.end();
|
||||
}
|
||||
this.#output.push(']');
|
||||
}
|
||||
}
|
||||
exports.ObjectWriter = ObjectWriter;
|
||||
function writeJsonObject(value, fun) {
|
||||
const output = [];
|
||||
const writer = new ObjectWriter(output);
|
||||
writer.begin();
|
||||
fun(writer, value);
|
||||
writer.end();
|
||||
return output.join("");
|
||||
}
|
||||
exports.writeJsonObject = writeJsonObject;
|
||||
155
node_modules/@libsql/hrana-client/lib-cjs/encoding/protobuf/decode.js
generated
vendored
Normal file
155
node_modules/@libsql/hrana-client/lib-cjs/encoding/protobuf/decode.js
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.readProtobufMessage = exports.FieldReader = void 0;
|
||||
const errors_js_1 = require("../../errors.js");
|
||||
const util_js_1 = require("./util.js");
|
||||
class MessageReader {
|
||||
#array;
|
||||
#view;
|
||||
#pos;
|
||||
constructor(array) {
|
||||
this.#array = array;
|
||||
this.#view = new DataView(array.buffer, array.byteOffset, array.byteLength);
|
||||
this.#pos = 0;
|
||||
}
|
||||
varint() {
|
||||
let value = 0;
|
||||
for (let shift = 0;; shift += 7) {
|
||||
const byte = this.#array[this.#pos++];
|
||||
value |= (byte & 0x7f) << shift;
|
||||
if (!(byte & 0x80)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
varintBig() {
|
||||
let value = 0n;
|
||||
for (let shift = 0n;; shift += 7n) {
|
||||
const byte = this.#array[this.#pos++];
|
||||
value |= BigInt(byte & 0x7f) << shift;
|
||||
if (!(byte & 0x80)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
bytes(length) {
|
||||
const array = new Uint8Array(this.#array.buffer, this.#array.byteOffset + this.#pos, length);
|
||||
this.#pos += length;
|
||||
return array;
|
||||
}
|
||||
double() {
|
||||
const value = this.#view.getFloat64(this.#pos, true);
|
||||
this.#pos += 8;
|
||||
return value;
|
||||
}
|
||||
skipVarint() {
|
||||
for (;;) {
|
||||
const byte = this.#array[this.#pos++];
|
||||
if (!(byte & 0x80)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
skip(count) {
|
||||
this.#pos += count;
|
||||
}
|
||||
eof() {
|
||||
return this.#pos >= this.#array.byteLength;
|
||||
}
|
||||
}
|
||||
class FieldReader {
|
||||
#reader;
|
||||
#wireType;
|
||||
constructor(reader) {
|
||||
this.#reader = reader;
|
||||
this.#wireType = -1;
|
||||
}
|
||||
setup(wireType) {
|
||||
this.#wireType = wireType;
|
||||
}
|
||||
#expect(expectedWireType) {
|
||||
if (this.#wireType !== expectedWireType) {
|
||||
throw new errors_js_1.ProtoError(`Expected wire type ${expectedWireType}, got ${this.#wireType}`);
|
||||
}
|
||||
this.#wireType = -1;
|
||||
}
|
||||
bytes() {
|
||||
this.#expect(util_js_1.LENGTH_DELIMITED);
|
||||
const length = this.#reader.varint();
|
||||
return this.#reader.bytes(length);
|
||||
}
|
||||
string() {
|
||||
return new TextDecoder().decode(this.bytes());
|
||||
}
|
||||
message(def) {
|
||||
return readProtobufMessage(this.bytes(), def);
|
||||
}
|
||||
int32() {
|
||||
this.#expect(util_js_1.VARINT);
|
||||
return this.#reader.varint();
|
||||
}
|
||||
uint32() {
|
||||
return this.int32();
|
||||
}
|
||||
bool() {
|
||||
return this.int32() !== 0;
|
||||
}
|
||||
uint64() {
|
||||
this.#expect(util_js_1.VARINT);
|
||||
return this.#reader.varintBig();
|
||||
}
|
||||
sint64() {
|
||||
const value = this.uint64();
|
||||
return (value >> 1n) ^ (-(value & 1n));
|
||||
}
|
||||
double() {
|
||||
this.#expect(util_js_1.FIXED_64);
|
||||
return this.#reader.double();
|
||||
}
|
||||
maybeSkip() {
|
||||
if (this.#wireType < 0) {
|
||||
return;
|
||||
}
|
||||
else if (this.#wireType === util_js_1.VARINT) {
|
||||
this.#reader.skipVarint();
|
||||
}
|
||||
else if (this.#wireType === util_js_1.FIXED_64) {
|
||||
this.#reader.skip(8);
|
||||
}
|
||||
else if (this.#wireType === util_js_1.LENGTH_DELIMITED) {
|
||||
const length = this.#reader.varint();
|
||||
this.#reader.skip(length);
|
||||
}
|
||||
else if (this.#wireType === util_js_1.FIXED_32) {
|
||||
this.#reader.skip(4);
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.ProtoError(`Unexpected wire type ${this.#wireType}`);
|
||||
}
|
||||
this.#wireType = -1;
|
||||
}
|
||||
}
|
||||
exports.FieldReader = FieldReader;
|
||||
function readProtobufMessage(data, def) {
|
||||
const msgReader = new MessageReader(data);
|
||||
const fieldReader = new FieldReader(msgReader);
|
||||
let value = def.default();
|
||||
while (!msgReader.eof()) {
|
||||
const key = msgReader.varint();
|
||||
const tag = key >> 3;
|
||||
const wireType = key & 0x7;
|
||||
fieldReader.setup(wireType);
|
||||
const tagFun = def[tag];
|
||||
if (tagFun !== undefined) {
|
||||
const returnedValue = tagFun(fieldReader, value);
|
||||
if (returnedValue !== undefined) {
|
||||
value = returnedValue;
|
||||
}
|
||||
}
|
||||
fieldReader.maybeSkip();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
exports.readProtobufMessage = readProtobufMessage;
|
||||
100
node_modules/@libsql/hrana-client/lib-cjs/encoding/protobuf/encode.js
generated
vendored
Normal file
100
node_modules/@libsql/hrana-client/lib-cjs/encoding/protobuf/encode.js
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.writeProtobufMessage = exports.MessageWriter = void 0;
|
||||
const util_js_1 = require("./util.js");
|
||||
class MessageWriter {
|
||||
#buf;
|
||||
#array;
|
||||
#view;
|
||||
#pos;
|
||||
constructor() {
|
||||
this.#buf = new ArrayBuffer(256);
|
||||
this.#array = new Uint8Array(this.#buf);
|
||||
this.#view = new DataView(this.#buf);
|
||||
this.#pos = 0;
|
||||
}
|
||||
#ensure(extra) {
|
||||
if (this.#pos + extra <= this.#buf.byteLength) {
|
||||
return;
|
||||
}
|
||||
let newCap = this.#buf.byteLength;
|
||||
while (newCap < this.#pos + extra) {
|
||||
newCap *= 2;
|
||||
}
|
||||
const newBuf = new ArrayBuffer(newCap);
|
||||
const newArray = new Uint8Array(newBuf);
|
||||
const newView = new DataView(newBuf);
|
||||
newArray.set(new Uint8Array(this.#buf, 0, this.#pos));
|
||||
this.#buf = newBuf;
|
||||
this.#array = newArray;
|
||||
this.#view = newView;
|
||||
}
|
||||
#varint(value) {
|
||||
this.#ensure(5);
|
||||
value = 0 | value;
|
||||
do {
|
||||
let byte = value & 0x7f;
|
||||
value >>>= 7;
|
||||
byte |= (value ? 0x80 : 0);
|
||||
this.#array[this.#pos++] = byte;
|
||||
} while (value);
|
||||
}
|
||||
#varintBig(value) {
|
||||
this.#ensure(10);
|
||||
value = value & 0xffffffffffffffffn;
|
||||
do {
|
||||
let byte = Number(value & 0x7fn);
|
||||
value >>= 7n;
|
||||
byte |= (value ? 0x80 : 0);
|
||||
this.#array[this.#pos++] = byte;
|
||||
} while (value);
|
||||
}
|
||||
#tag(tag, wireType) {
|
||||
this.#varint((tag << 3) | wireType);
|
||||
}
|
||||
bytes(tag, value) {
|
||||
this.#tag(tag, util_js_1.LENGTH_DELIMITED);
|
||||
this.#varint(value.byteLength);
|
||||
this.#ensure(value.byteLength);
|
||||
this.#array.set(value, this.#pos);
|
||||
this.#pos += value.byteLength;
|
||||
}
|
||||
string(tag, value) {
|
||||
this.bytes(tag, new TextEncoder().encode(value));
|
||||
}
|
||||
message(tag, value, fun) {
|
||||
const writer = new MessageWriter();
|
||||
fun(writer, value);
|
||||
this.bytes(tag, writer.data());
|
||||
}
|
||||
int32(tag, value) {
|
||||
this.#tag(tag, util_js_1.VARINT);
|
||||
this.#varint(value);
|
||||
}
|
||||
uint32(tag, value) {
|
||||
this.int32(tag, value);
|
||||
}
|
||||
bool(tag, value) {
|
||||
this.int32(tag, value ? 1 : 0);
|
||||
}
|
||||
sint64(tag, value) {
|
||||
this.#tag(tag, util_js_1.VARINT);
|
||||
this.#varintBig((value << 1n) ^ (value >> 63n));
|
||||
}
|
||||
double(tag, value) {
|
||||
this.#tag(tag, util_js_1.FIXED_64);
|
||||
this.#ensure(8);
|
||||
this.#view.setFloat64(this.#pos, value, true);
|
||||
this.#pos += 8;
|
||||
}
|
||||
data() {
|
||||
return new Uint8Array(this.#buf, 0, this.#pos);
|
||||
}
|
||||
}
|
||||
exports.MessageWriter = MessageWriter;
|
||||
function writeProtobufMessage(value, fun) {
|
||||
const w = new MessageWriter();
|
||||
fun(w, value);
|
||||
return w.data();
|
||||
}
|
||||
exports.writeProtobufMessage = writeProtobufMessage;
|
||||
9
node_modules/@libsql/hrana-client/lib-cjs/encoding/protobuf/util.js
generated
vendored
Normal file
9
node_modules/@libsql/hrana-client/lib-cjs/encoding/protobuf/util.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FIXED_32 = exports.GROUP_END = exports.GROUP_START = exports.LENGTH_DELIMITED = exports.FIXED_64 = exports.VARINT = void 0;
|
||||
exports.VARINT = 0;
|
||||
exports.FIXED_64 = 1;
|
||||
exports.LENGTH_DELIMITED = 2;
|
||||
exports.GROUP_START = 3;
|
||||
exports.GROUP_END = 4;
|
||||
exports.FIXED_32 = 5;
|
||||
116
node_modules/@libsql/hrana-client/lib-cjs/errors.js
generated
vendored
Normal file
116
node_modules/@libsql/hrana-client/lib-cjs/errors.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MisuseError = exports.InternalError = exports.ProtocolVersionError = exports.LibsqlUrlParseError = exports.HttpServerError = exports.WebSocketError = exports.WebSocketUnsupportedError = exports.ClosedError = exports.ResponseError = exports.ProtoError = exports.ClientError = void 0;
|
||||
/** Generic error produced by the Hrana client. */
|
||||
class ClientError extends Error {
|
||||
/** @private */
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "ClientError";
|
||||
}
|
||||
}
|
||||
exports.ClientError = ClientError;
|
||||
/** Error thrown when the server violates the protocol. */
|
||||
class ProtoError extends ClientError {
|
||||
/** @private */
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "ProtoError";
|
||||
}
|
||||
}
|
||||
exports.ProtoError = ProtoError;
|
||||
/** Error thrown when the server returns an error response. */
|
||||
class ResponseError extends ClientError {
|
||||
code;
|
||||
/** @internal */
|
||||
proto;
|
||||
/** @private */
|
||||
constructor(message, protoError) {
|
||||
super(message);
|
||||
this.name = "ResponseError";
|
||||
this.code = protoError.code;
|
||||
this.proto = protoError;
|
||||
this.stack = undefined;
|
||||
}
|
||||
}
|
||||
exports.ResponseError = ResponseError;
|
||||
/** Error thrown when the client or stream is closed. */
|
||||
class ClosedError extends ClientError {
|
||||
/** @private */
|
||||
constructor(message, cause) {
|
||||
if (cause !== undefined) {
|
||||
super(`${message}: ${cause}`);
|
||||
this.cause = cause;
|
||||
}
|
||||
else {
|
||||
super(message);
|
||||
}
|
||||
this.name = "ClosedError";
|
||||
}
|
||||
}
|
||||
exports.ClosedError = ClosedError;
|
||||
/** Error thrown when the environment does not seem to support WebSockets. */
|
||||
class WebSocketUnsupportedError extends ClientError {
|
||||
/** @private */
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "WebSocketUnsupportedError";
|
||||
}
|
||||
}
|
||||
exports.WebSocketUnsupportedError = WebSocketUnsupportedError;
|
||||
/** Error thrown when we encounter a WebSocket error. */
|
||||
class WebSocketError extends ClientError {
|
||||
/** @private */
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "WebSocketError";
|
||||
}
|
||||
}
|
||||
exports.WebSocketError = WebSocketError;
|
||||
/** Error thrown when the HTTP server returns an error response. */
|
||||
class HttpServerError extends ClientError {
|
||||
status;
|
||||
/** @private */
|
||||
constructor(message, status) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
this.name = "HttpServerError";
|
||||
}
|
||||
}
|
||||
exports.HttpServerError = HttpServerError;
|
||||
/** Error thrown when a libsql URL is not valid. */
|
||||
class LibsqlUrlParseError extends ClientError {
|
||||
/** @private */
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "LibsqlUrlParseError";
|
||||
}
|
||||
}
|
||||
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;
|
||||
/** Error thrown when an internal client error happens. */
|
||||
class InternalError extends ClientError {
|
||||
/** @private */
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "InternalError";
|
||||
}
|
||||
}
|
||||
exports.InternalError = InternalError;
|
||||
/** Error thrown when the API is misused. */
|
||||
class MisuseError extends ClientError {
|
||||
/** @private */
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "MisuseError";
|
||||
}
|
||||
}
|
||||
exports.MisuseError = MisuseError;
|
||||
128
node_modules/@libsql/hrana-client/lib-cjs/http/client.js
generated
vendored
Normal file
128
node_modules/@libsql/hrana-client/lib-cjs/http/client.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HttpClient = exports.checkEndpoints = void 0;
|
||||
const isomorphic_fetch_1 = require("@libsql/isomorphic-fetch");
|
||||
const client_js_1 = require("../client.js");
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const stream_js_1 = require("./stream.js");
|
||||
exports.checkEndpoints = [
|
||||
{
|
||||
versionPath: "v3-protobuf",
|
||||
pipelinePath: "v3-protobuf/pipeline",
|
||||
cursorPath: "v3-protobuf/cursor",
|
||||
version: 3,
|
||||
encoding: "protobuf",
|
||||
},
|
||||
/*
|
||||
{
|
||||
versionPath: "v3",
|
||||
pipelinePath: "v3/pipeline",
|
||||
cursorPath: "v3/cursor",
|
||||
version: 3,
|
||||
encoding: "json",
|
||||
},
|
||||
*/
|
||||
];
|
||||
const fallbackEndpoint = {
|
||||
versionPath: "v2",
|
||||
pipelinePath: "v2/pipeline",
|
||||
cursorPath: undefined,
|
||||
version: 2,
|
||||
encoding: "json",
|
||||
};
|
||||
/** A client for the Hrana protocol over HTTP. */
|
||||
class HttpClient extends client_js_1.Client {
|
||||
#url;
|
||||
#jwt;
|
||||
#fetch;
|
||||
#closed;
|
||||
#streams;
|
||||
/** @private */
|
||||
_endpointPromise;
|
||||
/** @private */
|
||||
_endpoint;
|
||||
/** @private */
|
||||
constructor(url, jwt, customFetch, protocolVersion = 2) {
|
||||
super();
|
||||
this.#url = url;
|
||||
this.#jwt = jwt;
|
||||
this.#fetch = customFetch ?? isomorphic_fetch_1.fetch;
|
||||
this.#closed = undefined;
|
||||
this.#streams = new Set();
|
||||
if (protocolVersion == 3) {
|
||||
this._endpointPromise = findEndpoint(this.#fetch, this.#url);
|
||||
this._endpointPromise.then((endpoint) => this._endpoint = endpoint, (error) => this.#setClosed(error));
|
||||
}
|
||||
else {
|
||||
this._endpointPromise = Promise.resolve(fallbackEndpoint);
|
||||
this._endpointPromise.then((endpoint) => this._endpoint = endpoint, (error) => this.#setClosed(error));
|
||||
}
|
||||
}
|
||||
/** Get the protocol version supported by the server. */
|
||||
async getVersion() {
|
||||
if (this._endpoint !== undefined) {
|
||||
return this._endpoint.version;
|
||||
}
|
||||
return (await this._endpointPromise).version;
|
||||
}
|
||||
// Make sure that the negotiated version is at least `minVersion`.
|
||||
/** @private */
|
||||
_ensureVersion(minVersion, feature) {
|
||||
if (minVersion <= fallbackEndpoint.version) {
|
||||
return;
|
||||
}
|
||||
else if (this._endpoint === undefined) {
|
||||
throw new errors_js_1.ProtocolVersionError(`${feature} is supported only on protocol version ${minVersion} and higher, ` +
|
||||
"but the version supported by the HTTP server is not yet known. " +
|
||||
"Use Client.getVersion() to wait until the version is available.");
|
||||
}
|
||||
else if (this._endpoint.version < minVersion) {
|
||||
throw new errors_js_1.ProtocolVersionError(`${feature} is supported only on protocol version ${minVersion} and higher, ` +
|
||||
`but the HTTP server only supports version ${this._endpoint.version}.`);
|
||||
}
|
||||
}
|
||||
/** Open a {@link HttpStream}, a stream for executing SQL statements. */
|
||||
openStream() {
|
||||
if (this.#closed !== undefined) {
|
||||
throw new errors_js_1.ClosedError("Client is closed", this.#closed);
|
||||
}
|
||||
const stream = new stream_js_1.HttpStream(this, this.#url, this.#jwt, this.#fetch);
|
||||
this.#streams.add(stream);
|
||||
return stream;
|
||||
}
|
||||
/** @private */
|
||||
_streamClosed(stream) {
|
||||
this.#streams.delete(stream);
|
||||
}
|
||||
/** Close the client and all its streams. */
|
||||
close() {
|
||||
this.#setClosed(new errors_js_1.ClientError("Client was manually closed"));
|
||||
}
|
||||
/** True if the client is closed. */
|
||||
get closed() {
|
||||
return this.#closed !== undefined;
|
||||
}
|
||||
#setClosed(error) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
this.#closed = error;
|
||||
for (const stream of Array.from(this.#streams)) {
|
||||
stream._setClosed(new errors_js_1.ClosedError("Client was closed", error));
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.HttpClient = HttpClient;
|
||||
async function findEndpoint(customFetch, clientUrl) {
|
||||
const fetch = customFetch;
|
||||
for (const endpoint of exports.checkEndpoints) {
|
||||
const url = new URL(endpoint.versionPath, clientUrl);
|
||||
const request = new isomorphic_fetch_1.Request(url.toString(), { method: "GET" });
|
||||
const response = await fetch(request);
|
||||
await response.arrayBuffer();
|
||||
if (response.ok) {
|
||||
return endpoint;
|
||||
}
|
||||
}
|
||||
return fallbackEndpoint;
|
||||
}
|
||||
162
node_modules/@libsql/hrana-client/lib-cjs/http/cursor.js
generated
vendored
Normal file
162
node_modules/@libsql/hrana-client/lib-cjs/http/cursor.js
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HttpCursor = void 0;
|
||||
const byte_queue_js_1 = require("../byte_queue.js");
|
||||
const cursor_js_1 = require("../cursor.js");
|
||||
const jsond = __importStar(require("../encoding/json/decode.js"));
|
||||
const protobufd = __importStar(require("../encoding/protobuf/decode.js"));
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const util_js_1 = require("../util.js");
|
||||
const json_decode_js_1 = require("./json_decode.js");
|
||||
const protobuf_decode_js_1 = require("./protobuf_decode.js");
|
||||
const json_decode_js_2 = require("../shared/json_decode.js");
|
||||
const protobuf_decode_js_2 = require("../shared/protobuf_decode.js");
|
||||
class HttpCursor extends cursor_js_1.Cursor {
|
||||
#stream;
|
||||
#encoding;
|
||||
#reader;
|
||||
#queue;
|
||||
#closed;
|
||||
#done;
|
||||
/** @private */
|
||||
constructor(stream, encoding) {
|
||||
super();
|
||||
this.#stream = stream;
|
||||
this.#encoding = encoding;
|
||||
this.#reader = undefined;
|
||||
this.#queue = new byte_queue_js_1.ByteQueue(16 * 1024);
|
||||
this.#closed = undefined;
|
||||
this.#done = false;
|
||||
}
|
||||
async open(response) {
|
||||
if (response.body === null) {
|
||||
throw new errors_js_1.ProtoError("No response body for cursor request");
|
||||
}
|
||||
this.#reader = response.body.getReader();
|
||||
const respBody = await this.#nextItem(json_decode_js_1.CursorRespBody, protobuf_decode_js_1.CursorRespBody);
|
||||
if (respBody === undefined) {
|
||||
throw new errors_js_1.ProtoError("Empty response to cursor request");
|
||||
}
|
||||
return respBody;
|
||||
}
|
||||
/** Fetch the next entry from the cursor. */
|
||||
next() {
|
||||
return this.#nextItem(json_decode_js_2.CursorEntry, protobuf_decode_js_2.CursorEntry);
|
||||
}
|
||||
/** Close the cursor. */
|
||||
close() {
|
||||
this._setClosed(new errors_js_1.ClientError("Cursor was manually closed"));
|
||||
}
|
||||
/** @private */
|
||||
_setClosed(error) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
this.#closed = error;
|
||||
this.#stream._cursorClosed(this);
|
||||
if (this.#reader !== undefined) {
|
||||
this.#reader.cancel();
|
||||
}
|
||||
}
|
||||
/** True if the cursor is closed. */
|
||||
get closed() {
|
||||
return this.#closed !== undefined;
|
||||
}
|
||||
async #nextItem(jsonFun, protobufDef) {
|
||||
for (;;) {
|
||||
if (this.#done) {
|
||||
return undefined;
|
||||
}
|
||||
else if (this.#closed !== undefined) {
|
||||
throw new errors_js_1.ClosedError("Cursor is closed", this.#closed);
|
||||
}
|
||||
if (this.#encoding === "json") {
|
||||
const jsonData = this.#parseItemJson();
|
||||
if (jsonData !== undefined) {
|
||||
const jsonText = new TextDecoder().decode(jsonData);
|
||||
const jsonValue = JSON.parse(jsonText);
|
||||
return jsond.readJsonObject(jsonValue, jsonFun);
|
||||
}
|
||||
}
|
||||
else if (this.#encoding === "protobuf") {
|
||||
const protobufData = this.#parseItemProtobuf();
|
||||
if (protobufData !== undefined) {
|
||||
return protobufd.readProtobufMessage(protobufData, protobufDef);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(this.#encoding, "Impossible encoding");
|
||||
}
|
||||
if (this.#reader === undefined) {
|
||||
throw new errors_js_1.InternalError("Attempted to read from HTTP cursor before it was opened");
|
||||
}
|
||||
const { value, done } = await this.#reader.read();
|
||||
if (done && this.#queue.length === 0) {
|
||||
this.#done = true;
|
||||
}
|
||||
else if (done) {
|
||||
throw new errors_js_1.ProtoError("Unexpected end of cursor stream");
|
||||
}
|
||||
else {
|
||||
this.#queue.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#parseItemJson() {
|
||||
const data = this.#queue.data();
|
||||
const newlineByte = 10;
|
||||
const newlinePos = data.indexOf(newlineByte);
|
||||
if (newlinePos < 0) {
|
||||
return undefined;
|
||||
}
|
||||
const jsonData = data.slice(0, newlinePos);
|
||||
this.#queue.shift(newlinePos + 1);
|
||||
return jsonData;
|
||||
}
|
||||
#parseItemProtobuf() {
|
||||
const data = this.#queue.data();
|
||||
let varintValue = 0;
|
||||
let varintLength = 0;
|
||||
for (;;) {
|
||||
if (varintLength >= data.byteLength) {
|
||||
return undefined;
|
||||
}
|
||||
const byte = data[varintLength];
|
||||
varintValue |= (byte & 0x7f) << (7 * varintLength);
|
||||
varintLength += 1;
|
||||
if (!(byte & 0x80)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data.byteLength < varintLength + varintValue) {
|
||||
return undefined;
|
||||
}
|
||||
const protobufData = data.slice(varintLength, varintLength + varintValue);
|
||||
this.#queue.shift(varintLength + varintValue);
|
||||
return protobufData;
|
||||
}
|
||||
}
|
||||
exports.HttpCursor = HttpCursor;
|
||||
90
node_modules/@libsql/hrana-client/lib-cjs/http/json_decode.js
generated
vendored
Normal file
90
node_modules/@libsql/hrana-client/lib-cjs/http/json_decode.js
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CursorRespBody = exports.PipelineRespBody = void 0;
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const d = __importStar(require("../encoding/json/decode.js"));
|
||||
const json_decode_js_1 = require("../shared/json_decode.js");
|
||||
function PipelineRespBody(obj) {
|
||||
const baton = d.stringOpt(obj["baton"]);
|
||||
const baseUrl = d.stringOpt(obj["base_url"]);
|
||||
const results = d.arrayObjectsMap(obj["results"], StreamResult);
|
||||
return { baton, baseUrl, results };
|
||||
}
|
||||
exports.PipelineRespBody = PipelineRespBody;
|
||||
function StreamResult(obj) {
|
||||
const type = d.string(obj["type"]);
|
||||
if (type === "ok") {
|
||||
const response = StreamResponse(d.object(obj["response"]));
|
||||
return { type: "ok", response };
|
||||
}
|
||||
else if (type === "error") {
|
||||
const error = (0, json_decode_js_1.Error)(d.object(obj["error"]));
|
||||
return { type: "error", error };
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.ProtoError("Unexpected type of StreamResult");
|
||||
}
|
||||
}
|
||||
function StreamResponse(obj) {
|
||||
const type = d.string(obj["type"]);
|
||||
if (type === "close") {
|
||||
return { type: "close" };
|
||||
}
|
||||
else if (type === "execute") {
|
||||
const result = (0, json_decode_js_1.StmtResult)(d.object(obj["result"]));
|
||||
return { type: "execute", result };
|
||||
}
|
||||
else if (type === "batch") {
|
||||
const result = (0, json_decode_js_1.BatchResult)(d.object(obj["result"]));
|
||||
return { type: "batch", result };
|
||||
}
|
||||
else if (type === "sequence") {
|
||||
return { type: "sequence" };
|
||||
}
|
||||
else if (type === "describe") {
|
||||
const result = (0, json_decode_js_1.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 errors_js_1.ProtoError("Unexpected type of StreamResponse");
|
||||
}
|
||||
}
|
||||
function CursorRespBody(obj) {
|
||||
const baton = d.stringOpt(obj["baton"]);
|
||||
const baseUrl = d.stringOpt(obj["base_url"]);
|
||||
return { baton, baseUrl };
|
||||
}
|
||||
exports.CursorRespBody = CursorRespBody;
|
||||
60
node_modules/@libsql/hrana-client/lib-cjs/http/json_encode.js
generated
vendored
Normal file
60
node_modules/@libsql/hrana-client/lib-cjs/http/json_encode.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CursorReqBody = exports.PipelineReqBody = void 0;
|
||||
const json_encode_js_1 = require("../shared/json_encode.js");
|
||||
const util_js_1 = require("../util.js");
|
||||
function PipelineReqBody(w, msg) {
|
||||
if (msg.baton !== undefined) {
|
||||
w.string("baton", msg.baton);
|
||||
}
|
||||
w.arrayObjects("requests", msg.requests, StreamRequest);
|
||||
}
|
||||
exports.PipelineReqBody = PipelineReqBody;
|
||||
function StreamRequest(w, msg) {
|
||||
w.stringRaw("type", msg.type);
|
||||
if (msg.type === "close") {
|
||||
// do nothing
|
||||
}
|
||||
else if (msg.type === "execute") {
|
||||
w.object("stmt", msg.stmt, json_encode_js_1.Stmt);
|
||||
}
|
||||
else if (msg.type === "batch") {
|
||||
w.object("batch", msg.batch, json_encode_js_1.Batch);
|
||||
}
|
||||
else if (msg.type === "sequence") {
|
||||
if (msg.sql !== undefined) {
|
||||
w.string("sql", msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.number("sql_id", msg.sqlId);
|
||||
}
|
||||
}
|
||||
else if (msg.type === "describe") {
|
||||
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") {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(msg, "Impossible type of StreamRequest");
|
||||
}
|
||||
}
|
||||
function CursorReqBody(w, msg) {
|
||||
if (msg.baton !== undefined) {
|
||||
w.string("baton", msg.baton);
|
||||
}
|
||||
w.object("batch", msg.batch, json_encode_js_1.Batch);
|
||||
}
|
||||
exports.CursorReqBody = CursorReqBody;
|
||||
18
node_modules/@libsql/hrana-client/lib-cjs/http/proto.js
generated
vendored
Normal file
18
node_modules/@libsql/hrana-client/lib-cjs/http/proto.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
// Types for the structures specific to Hrana over HTTP.
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("../shared/proto.js"), exports);
|
||||
47
node_modules/@libsql/hrana-client/lib-cjs/http/protobuf_decode.js
generated
vendored
Normal file
47
node_modules/@libsql/hrana-client/lib-cjs/http/protobuf_decode.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CursorRespBody = exports.PipelineRespBody = void 0;
|
||||
const protobuf_decode_js_1 = require("../shared/protobuf_decode.js");
|
||||
exports.PipelineRespBody = {
|
||||
default() { return { baton: undefined, baseUrl: undefined, results: [] }; },
|
||||
1(r, msg) { msg.baton = r.string(); },
|
||||
2(r, msg) { msg.baseUrl = r.string(); },
|
||||
3(r, msg) { msg.results.push(r.message(StreamResult)); },
|
||||
};
|
||||
const StreamResult = {
|
||||
default() { return { type: "none" }; },
|
||||
1(r) { return { type: "ok", response: r.message(StreamResponse) }; },
|
||||
2(r) { return { type: "error", error: r.message(protobuf_decode_js_1.Error) }; },
|
||||
};
|
||||
const StreamResponse = {
|
||||
default() { return { type: "none" }; },
|
||||
1(r) { return { type: "close" }; },
|
||||
2(r) { return r.message(ExecuteStreamResp); },
|
||||
3(r) { return r.message(BatchStreamResp); },
|
||||
4(r) { return { type: "sequence" }; },
|
||||
5(r) { return r.message(DescribeStreamResp); },
|
||||
6(r) { return { type: "store_sql" }; },
|
||||
7(r) { return { type: "close_sql" }; },
|
||||
8(r) { return r.message(GetAutocommitStreamResp); },
|
||||
};
|
||||
const ExecuteStreamResp = {
|
||||
default() { return { type: "execute", result: protobuf_decode_js_1.StmtResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(protobuf_decode_js_1.StmtResult); },
|
||||
};
|
||||
const BatchStreamResp = {
|
||||
default() { return { type: "batch", result: protobuf_decode_js_1.BatchResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(protobuf_decode_js_1.BatchResult); },
|
||||
};
|
||||
const DescribeStreamResp = {
|
||||
default() { return { type: "describe", result: protobuf_decode_js_1.DescribeResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(protobuf_decode_js_1.DescribeResult); },
|
||||
};
|
||||
const GetAutocommitStreamResp = {
|
||||
default() { return { type: "get_autocommit", isAutocommit: false }; },
|
||||
1(r, msg) { msg.isAutocommit = r.bool(); },
|
||||
};
|
||||
exports.CursorRespBody = {
|
||||
default() { return { baton: undefined, baseUrl: undefined }; },
|
||||
1(r, msg) { msg.baton = r.string(); },
|
||||
2(r, msg) { msg.baseUrl = r.string(); },
|
||||
};
|
||||
83
node_modules/@libsql/hrana-client/lib-cjs/http/protobuf_encode.js
generated
vendored
Normal file
83
node_modules/@libsql/hrana-client/lib-cjs/http/protobuf_encode.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CursorReqBody = exports.PipelineReqBody = void 0;
|
||||
const protobuf_encode_js_1 = require("../shared/protobuf_encode.js");
|
||||
const util_js_1 = require("../util.js");
|
||||
function PipelineReqBody(w, msg) {
|
||||
if (msg.baton !== undefined) {
|
||||
w.string(1, msg.baton);
|
||||
}
|
||||
for (const req of msg.requests) {
|
||||
w.message(2, req, StreamRequest);
|
||||
}
|
||||
}
|
||||
exports.PipelineReqBody = PipelineReqBody;
|
||||
function StreamRequest(w, msg) {
|
||||
if (msg.type === "close") {
|
||||
w.message(1, msg, CloseStreamReq);
|
||||
}
|
||||
else if (msg.type === "execute") {
|
||||
w.message(2, msg, ExecuteStreamReq);
|
||||
}
|
||||
else if (msg.type === "batch") {
|
||||
w.message(3, msg, BatchStreamReq);
|
||||
}
|
||||
else if (msg.type === "sequence") {
|
||||
w.message(4, msg, SequenceStreamReq);
|
||||
}
|
||||
else if (msg.type === "describe") {
|
||||
w.message(5, msg, DescribeStreamReq);
|
||||
}
|
||||
else if (msg.type === "store_sql") {
|
||||
w.message(6, msg, StoreSqlStreamReq);
|
||||
}
|
||||
else if (msg.type === "close_sql") {
|
||||
w.message(7, msg, CloseSqlStreamReq);
|
||||
}
|
||||
else if (msg.type === "get_autocommit") {
|
||||
w.message(8, msg, GetAutocommitStreamReq);
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(msg, "Impossible type of StreamRequest");
|
||||
}
|
||||
}
|
||||
function CloseStreamReq(_w, _msg) {
|
||||
}
|
||||
function ExecuteStreamReq(w, msg) {
|
||||
w.message(1, msg.stmt, protobuf_encode_js_1.Stmt);
|
||||
}
|
||||
function BatchStreamReq(w, msg) {
|
||||
w.message(1, msg.batch, protobuf_encode_js_1.Batch);
|
||||
}
|
||||
function SequenceStreamReq(w, msg) {
|
||||
if (msg.sql !== undefined) {
|
||||
w.string(1, msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.int32(2, msg.sqlId);
|
||||
}
|
||||
}
|
||||
function DescribeStreamReq(w, msg) {
|
||||
if (msg.sql !== undefined) {
|
||||
w.string(1, msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.int32(2, msg.sqlId);
|
||||
}
|
||||
}
|
||||
function StoreSqlStreamReq(w, msg) {
|
||||
w.int32(1, msg.sqlId);
|
||||
w.string(2, msg.sql);
|
||||
}
|
||||
function CloseSqlStreamReq(w, msg) {
|
||||
w.int32(1, msg.sqlId);
|
||||
}
|
||||
function GetAutocommitStreamReq(_w, _msg) {
|
||||
}
|
||||
function CursorReqBody(w, msg) {
|
||||
if (msg.baton !== undefined) {
|
||||
w.string(1, msg.baton);
|
||||
}
|
||||
w.message(2, msg.batch, protobuf_encode_js_1.Batch);
|
||||
}
|
||||
exports.CursorReqBody = CursorReqBody;
|
||||
367
node_modules/@libsql/hrana-client/lib-cjs/http/stream.js
generated
vendored
Normal file
367
node_modules/@libsql/hrana-client/lib-cjs/http/stream.js
generated
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HttpStream = void 0;
|
||||
const isomorphic_fetch_1 = require("@libsql/isomorphic-fetch");
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const index_js_1 = require("../encoding/index.js");
|
||||
const id_alloc_js_1 = require("../id_alloc.js");
|
||||
const queue_js_1 = require("../queue.js");
|
||||
const queue_microtask_js_1 = require("../queue_microtask.js");
|
||||
const result_js_1 = require("../result.js");
|
||||
const sql_js_1 = require("../sql.js");
|
||||
const stream_js_1 = require("../stream.js");
|
||||
const util_js_1 = require("../util.js");
|
||||
const cursor_js_1 = require("./cursor.js");
|
||||
const json_encode_js_1 = require("./json_encode.js");
|
||||
const protobuf_encode_js_1 = require("./protobuf_encode.js");
|
||||
const json_encode_js_2 = require("./json_encode.js");
|
||||
const protobuf_encode_js_2 = require("./protobuf_encode.js");
|
||||
const json_decode_js_1 = require("./json_decode.js");
|
||||
const protobuf_decode_js_1 = require("./protobuf_decode.js");
|
||||
class HttpStream extends stream_js_1.Stream {
|
||||
#client;
|
||||
#baseUrl;
|
||||
#jwt;
|
||||
#fetch;
|
||||
#baton;
|
||||
#queue;
|
||||
#flushing;
|
||||
#cursor;
|
||||
#closing;
|
||||
#closeQueued;
|
||||
#closed;
|
||||
#sqlIdAlloc;
|
||||
/** @private */
|
||||
constructor(client, baseUrl, jwt, customFetch) {
|
||||
super(client.intMode);
|
||||
this.#client = client;
|
||||
this.#baseUrl = baseUrl.toString();
|
||||
this.#jwt = jwt;
|
||||
this.#fetch = customFetch;
|
||||
this.#baton = undefined;
|
||||
this.#queue = new queue_js_1.Queue();
|
||||
this.#flushing = false;
|
||||
this.#closing = false;
|
||||
this.#closeQueued = false;
|
||||
this.#closed = undefined;
|
||||
this.#sqlIdAlloc = new id_alloc_js_1.IdAlloc();
|
||||
}
|
||||
/** Get the {@link HttpClient} object that this stream belongs to. */
|
||||
client() {
|
||||
return this.#client;
|
||||
}
|
||||
/** @private */
|
||||
_sqlOwner() {
|
||||
return this;
|
||||
}
|
||||
/** Cache a SQL text on the server. */
|
||||
storeSql(sql) {
|
||||
const sqlId = this.#sqlIdAlloc.alloc();
|
||||
this.#sendStreamRequest({ type: "store_sql", sqlId, sql }).then(() => undefined, (error) => this._setClosed(error));
|
||||
return new sql_js_1.Sql(this, sqlId);
|
||||
}
|
||||
/** @private */
|
||||
_closeSql(sqlId) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
this.#sendStreamRequest({ type: "close_sql", sqlId }).then(() => this.#sqlIdAlloc.free(sqlId), (error) => this._setClosed(error));
|
||||
}
|
||||
/** @private */
|
||||
_execute(stmt) {
|
||||
return this.#sendStreamRequest({ type: "execute", stmt }).then((response) => {
|
||||
return response.result;
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_batch(batch) {
|
||||
return this.#sendStreamRequest({ type: "batch", batch }).then((response) => {
|
||||
return response.result;
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_describe(protoSql) {
|
||||
return this.#sendStreamRequest({
|
||||
type: "describe",
|
||||
sql: protoSql.sql,
|
||||
sqlId: protoSql.sqlId
|
||||
}).then((response) => {
|
||||
return response.result;
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_sequence(protoSql) {
|
||||
return this.#sendStreamRequest({
|
||||
type: "sequence",
|
||||
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",
|
||||
}).then((response) => {
|
||||
return response.isAutocommit;
|
||||
});
|
||||
}
|
||||
#sendStreamRequest(request) {
|
||||
return new Promise((responseCallback, errorCallback) => {
|
||||
this.#pushToQueue({ type: "pipeline", request, responseCallback, errorCallback });
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_openCursor(batch) {
|
||||
return new Promise((cursorCallback, errorCallback) => {
|
||||
this.#pushToQueue({ type: "cursor", batch, cursorCallback, errorCallback });
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_cursorClosed(cursor) {
|
||||
if (cursor !== this.#cursor) {
|
||||
throw new errors_js_1.InternalError("Cursor was closed, but it was not associated with the stream");
|
||||
}
|
||||
this.#cursor = undefined;
|
||||
(0, queue_microtask_js_1.queueMicrotask)(() => this.#flushQueue());
|
||||
}
|
||||
/** Immediately close the stream. */
|
||||
close() {
|
||||
this._setClosed(new errors_js_1.ClientError("Stream was manually closed"));
|
||||
}
|
||||
/** Gracefully close the stream. */
|
||||
closeGracefully() {
|
||||
this.#closing = true;
|
||||
(0, queue_microtask_js_1.queueMicrotask)(() => this.#flushQueue());
|
||||
}
|
||||
/** True if the stream is closed. */
|
||||
get closed() {
|
||||
return this.#closed !== undefined || this.#closing;
|
||||
}
|
||||
/** @private */
|
||||
_setClosed(error) {
|
||||
if (this.#closed !== undefined) {
|
||||
return;
|
||||
}
|
||||
this.#closed = error;
|
||||
if (this.#cursor !== undefined) {
|
||||
this.#cursor._setClosed(error);
|
||||
}
|
||||
this.#client._streamClosed(this);
|
||||
for (;;) {
|
||||
const entry = this.#queue.shift();
|
||||
if (entry !== undefined) {
|
||||
entry.errorCallback(error);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((this.#baton !== undefined || this.#flushing) && !this.#closeQueued) {
|
||||
this.#queue.push({
|
||||
type: "pipeline",
|
||||
request: { type: "close" },
|
||||
responseCallback: () => undefined,
|
||||
errorCallback: () => undefined,
|
||||
});
|
||||
this.#closeQueued = true;
|
||||
(0, queue_microtask_js_1.queueMicrotask)(() => this.#flushQueue());
|
||||
}
|
||||
}
|
||||
#pushToQueue(entry) {
|
||||
if (this.#closed !== undefined) {
|
||||
throw new errors_js_1.ClosedError("Stream is closed", this.#closed);
|
||||
}
|
||||
else if (this.#closing) {
|
||||
throw new errors_js_1.ClosedError("Stream is closing", undefined);
|
||||
}
|
||||
else {
|
||||
this.#queue.push(entry);
|
||||
(0, queue_microtask_js_1.queueMicrotask)(() => this.#flushQueue());
|
||||
}
|
||||
}
|
||||
#flushQueue() {
|
||||
if (this.#flushing || this.#cursor !== undefined) {
|
||||
return;
|
||||
}
|
||||
if (this.#closing && this.#queue.length === 0) {
|
||||
this._setClosed(new errors_js_1.ClientError("Stream was gracefully closed"));
|
||||
return;
|
||||
}
|
||||
const endpoint = this.#client._endpoint;
|
||||
if (endpoint === undefined) {
|
||||
this.#client._endpointPromise.then(() => this.#flushQueue(), (error) => this._setClosed(error));
|
||||
return;
|
||||
}
|
||||
const firstEntry = this.#queue.shift();
|
||||
if (firstEntry === undefined) {
|
||||
return;
|
||||
}
|
||||
else if (firstEntry.type === "pipeline") {
|
||||
const pipeline = [firstEntry];
|
||||
for (;;) {
|
||||
const entry = this.#queue.first();
|
||||
if (entry !== undefined && entry.type === "pipeline") {
|
||||
pipeline.push(entry);
|
||||
this.#queue.shift();
|
||||
}
|
||||
else if (entry === undefined && this.#closing && !this.#closeQueued) {
|
||||
pipeline.push({
|
||||
type: "pipeline",
|
||||
request: { type: "close" },
|
||||
responseCallback: () => undefined,
|
||||
errorCallback: () => undefined,
|
||||
});
|
||||
this.#closeQueued = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.#flushPipeline(endpoint, pipeline);
|
||||
}
|
||||
else if (firstEntry.type === "cursor") {
|
||||
this.#flushCursor(endpoint, firstEntry);
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(firstEntry, "Impossible type of QueueEntry");
|
||||
}
|
||||
}
|
||||
#flushPipeline(endpoint, pipeline) {
|
||||
this.#flush(() => this.#createPipelineRequest(pipeline, endpoint), (resp) => decodePipelineResponse(resp, endpoint.encoding), (respBody) => respBody.baton, (respBody) => respBody.baseUrl, (respBody) => handlePipelineResponse(pipeline, respBody), (error) => pipeline.forEach((entry) => entry.errorCallback(error)));
|
||||
}
|
||||
#flushCursor(endpoint, entry) {
|
||||
const cursor = new cursor_js_1.HttpCursor(this, endpoint.encoding);
|
||||
this.#cursor = cursor;
|
||||
this.#flush(() => this.#createCursorRequest(entry, endpoint), (resp) => cursor.open(resp), (respBody) => respBody.baton, (respBody) => respBody.baseUrl, (_respBody) => entry.cursorCallback(cursor), (error) => entry.errorCallback(error));
|
||||
}
|
||||
#flush(createRequest, decodeResponse, getBaton, getBaseUrl, handleResponse, handleError) {
|
||||
let promise;
|
||||
try {
|
||||
const request = createRequest();
|
||||
const fetch = this.#fetch;
|
||||
promise = fetch(request);
|
||||
}
|
||||
catch (error) {
|
||||
promise = Promise.reject(error);
|
||||
}
|
||||
this.#flushing = true;
|
||||
promise.then((resp) => {
|
||||
if (!resp.ok) {
|
||||
return errorFromResponse(resp).then((error) => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
return decodeResponse(resp);
|
||||
}).then((r) => {
|
||||
this.#baton = getBaton(r);
|
||||
this.#baseUrl = getBaseUrl(r) ?? this.#baseUrl;
|
||||
handleResponse(r);
|
||||
}).catch((error) => {
|
||||
this._setClosed(error);
|
||||
handleError(error);
|
||||
}).finally(() => {
|
||||
this.#flushing = false;
|
||||
this.#flushQueue();
|
||||
});
|
||||
}
|
||||
#createPipelineRequest(pipeline, endpoint) {
|
||||
return this.#createRequest(new URL(endpoint.pipelinePath, this.#baseUrl), {
|
||||
baton: this.#baton,
|
||||
requests: pipeline.map((entry) => entry.request),
|
||||
}, endpoint.encoding, json_encode_js_1.PipelineReqBody, protobuf_encode_js_1.PipelineReqBody);
|
||||
}
|
||||
#createCursorRequest(entry, endpoint) {
|
||||
if (endpoint.cursorPath === undefined) {
|
||||
throw new errors_js_1.ProtocolVersionError("Cursors are supported only on protocol version 3 and higher, " +
|
||||
`but the HTTP server only supports version ${endpoint.version}.`);
|
||||
}
|
||||
return this.#createRequest(new URL(endpoint.cursorPath, this.#baseUrl), {
|
||||
baton: this.#baton,
|
||||
batch: entry.batch,
|
||||
}, endpoint.encoding, json_encode_js_2.CursorReqBody, protobuf_encode_js_2.CursorReqBody);
|
||||
}
|
||||
#createRequest(url, reqBody, encoding, jsonFun, protobufFun) {
|
||||
let bodyData;
|
||||
let contentType;
|
||||
if (encoding === "json") {
|
||||
bodyData = (0, index_js_1.writeJsonObject)(reqBody, jsonFun);
|
||||
contentType = "application/json";
|
||||
}
|
||||
else if (encoding === "protobuf") {
|
||||
bodyData = (0, index_js_1.writeProtobufMessage)(reqBody, protobufFun);
|
||||
contentType = "application/x-protobuf";
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(encoding, "Impossible encoding");
|
||||
}
|
||||
const headers = new isomorphic_fetch_1.Headers();
|
||||
headers.set("content-type", contentType);
|
||||
if (this.#jwt !== undefined) {
|
||||
headers.set("authorization", `Bearer ${this.#jwt}`);
|
||||
}
|
||||
return new isomorphic_fetch_1.Request(url.toString(), { method: "POST", headers, body: bodyData });
|
||||
}
|
||||
}
|
||||
exports.HttpStream = HttpStream;
|
||||
function handlePipelineResponse(pipeline, respBody) {
|
||||
if (respBody.results.length !== pipeline.length) {
|
||||
throw new errors_js_1.ProtoError("Server returned unexpected number of pipeline results");
|
||||
}
|
||||
for (let i = 0; i < pipeline.length; ++i) {
|
||||
const result = respBody.results[i];
|
||||
const entry = pipeline[i];
|
||||
if (result.type === "ok") {
|
||||
if (result.response.type !== entry.request.type) {
|
||||
throw new errors_js_1.ProtoError("Received unexpected type of response");
|
||||
}
|
||||
entry.responseCallback(result.response);
|
||||
}
|
||||
else if (result.type === "error") {
|
||||
entry.errorCallback((0, result_js_1.errorFromProto)(result.error));
|
||||
}
|
||||
else if (result.type === "none") {
|
||||
throw new errors_js_1.ProtoError("Received unrecognized type of StreamResult");
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(result, "Received impossible type of StreamResult");
|
||||
}
|
||||
}
|
||||
}
|
||||
async function decodePipelineResponse(resp, encoding) {
|
||||
if (encoding === "json") {
|
||||
const respJson = await resp.json();
|
||||
return (0, index_js_1.readJsonObject)(respJson, json_decode_js_1.PipelineRespBody);
|
||||
}
|
||||
if (encoding === "protobuf") {
|
||||
const respData = await resp.arrayBuffer();
|
||||
return (0, index_js_1.readProtobufMessage)(new Uint8Array(respData), protobuf_decode_js_1.PipelineRespBody);
|
||||
}
|
||||
await resp.body?.cancel();
|
||||
throw (0, util_js_1.impossible)(encoding, "Impossible encoding");
|
||||
}
|
||||
async function errorFromResponse(resp) {
|
||||
const respType = resp.headers.get("content-type") ?? "text/plain";
|
||||
let message = `Server returned HTTP status ${resp.status}`;
|
||||
if (respType === "application/json") {
|
||||
const respBody = await resp.json();
|
||||
if ("message" in respBody) {
|
||||
return (0, result_js_1.errorFromProto)(respBody);
|
||||
}
|
||||
return new errors_js_1.HttpServerError(message, resp.status);
|
||||
}
|
||||
if (respType === "text/plain") {
|
||||
const respBody = (await resp.text()).trim();
|
||||
if (respBody !== "") {
|
||||
message += `: ${respBody}`;
|
||||
}
|
||||
return new errors_js_1.HttpServerError(message, resp.status);
|
||||
}
|
||||
await resp.body?.cancel();
|
||||
return new errors_js_1.HttpServerError(message, resp.status);
|
||||
}
|
||||
51
node_modules/@libsql/hrana-client/lib-cjs/id_alloc.js
generated
vendored
Normal file
51
node_modules/@libsql/hrana-client/lib-cjs/id_alloc.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.IdAlloc = void 0;
|
||||
const errors_js_1 = require("./errors.js");
|
||||
// An allocator of non-negative integer ids.
|
||||
//
|
||||
// This clever data structure has these "ideal" properties:
|
||||
// - It consumes memory proportional to the number of used ids (which is optimal).
|
||||
// - All operations are O(1) time.
|
||||
// - The allocated ids are small (with a slight modification, we could always provide the smallest possible
|
||||
// id).
|
||||
class IdAlloc {
|
||||
// Set of all allocated ids
|
||||
#usedIds;
|
||||
// Set of all free ids lower than `#usedIds.size`
|
||||
#freeIds;
|
||||
constructor() {
|
||||
this.#usedIds = new Set();
|
||||
this.#freeIds = new Set();
|
||||
}
|
||||
// Returns an id that was free, and marks it as used.
|
||||
alloc() {
|
||||
// this "loop" is just a way to pick an arbitrary element from the `#freeIds` set
|
||||
for (const freeId of this.#freeIds) {
|
||||
this.#freeIds.delete(freeId);
|
||||
this.#usedIds.add(freeId);
|
||||
// maintain the invariant of `#freeIds`
|
||||
if (!this.#usedIds.has(this.#usedIds.size - 1)) {
|
||||
this.#freeIds.add(this.#usedIds.size - 1);
|
||||
}
|
||||
return freeId;
|
||||
}
|
||||
// the `#freeIds` set is empty, so there are no free ids lower than `#usedIds.size`
|
||||
// this means that `#usedIds` is a set that contains all numbers from 0 to `#usedIds.size - 1`,
|
||||
// so `#usedIds.size` is free
|
||||
const freeId = this.#usedIds.size;
|
||||
this.#usedIds.add(freeId);
|
||||
return freeId;
|
||||
}
|
||||
free(id) {
|
||||
if (!this.#usedIds.delete(id)) {
|
||||
throw new errors_js_1.InternalError("Freeing an id that is not allocated");
|
||||
}
|
||||
// maintain the invariant of `#freeIds`
|
||||
this.#freeIds.delete(this.#usedIds.size);
|
||||
if (id < this.#usedIds.size) {
|
||||
this.#freeIds.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.IdAlloc = IdAlloc;
|
||||
77
node_modules/@libsql/hrana-client/lib-cjs/index.js
generated
vendored
Normal file
77
node_modules/@libsql/hrana-client/lib-cjs/index.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.openHttp = exports.openWs = exports.WsStream = exports.WsClient = exports.HttpStream = exports.HttpClient = exports.Stream = exports.Stmt = exports.Sql = exports.parseLibsqlUrl = exports.BatchCond = exports.BatchStep = exports.Batch = exports.Client = exports.Headers = exports.Request = exports.fetch = exports.WebSocket = void 0;
|
||||
const isomorphic_ws_1 = require("@libsql/isomorphic-ws");
|
||||
const client_js_1 = require("./ws/client.js");
|
||||
const errors_js_1 = require("./errors.js");
|
||||
const client_js_2 = require("./http/client.js");
|
||||
const client_js_3 = require("./ws/client.js");
|
||||
var isomorphic_ws_2 = require("@libsql/isomorphic-ws");
|
||||
Object.defineProperty(exports, "WebSocket", { enumerable: true, get: function () { return isomorphic_ws_2.WebSocket; } });
|
||||
var isomorphic_fetch_1 = require("@libsql/isomorphic-fetch");
|
||||
Object.defineProperty(exports, "fetch", { enumerable: true, get: function () { return isomorphic_fetch_1.fetch; } });
|
||||
Object.defineProperty(exports, "Request", { enumerable: true, get: function () { return isomorphic_fetch_1.Request; } });
|
||||
Object.defineProperty(exports, "Headers", { enumerable: true, get: function () { return isomorphic_fetch_1.Headers; } });
|
||||
var client_js_4 = require("./client.js");
|
||||
Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return client_js_4.Client; } });
|
||||
__exportStar(require("./errors.js"), exports);
|
||||
var batch_js_1 = require("./batch.js");
|
||||
Object.defineProperty(exports, "Batch", { enumerable: true, get: function () { return batch_js_1.Batch; } });
|
||||
Object.defineProperty(exports, "BatchStep", { enumerable: true, get: function () { return batch_js_1.BatchStep; } });
|
||||
Object.defineProperty(exports, "BatchCond", { enumerable: true, get: function () { return batch_js_1.BatchCond; } });
|
||||
var libsql_url_js_1 = require("./libsql_url.js");
|
||||
Object.defineProperty(exports, "parseLibsqlUrl", { enumerable: true, get: function () { return libsql_url_js_1.parseLibsqlUrl; } });
|
||||
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");
|
||||
Object.defineProperty(exports, "Stmt", { enumerable: true, get: function () { return stmt_js_1.Stmt; } });
|
||||
var stream_js_1 = require("./stream.js");
|
||||
Object.defineProperty(exports, "Stream", { enumerable: true, get: function () { return stream_js_1.Stream; } });
|
||||
var client_js_5 = require("./http/client.js");
|
||||
Object.defineProperty(exports, "HttpClient", { enumerable: true, get: function () { return client_js_5.HttpClient; } });
|
||||
var stream_js_2 = require("./http/stream.js");
|
||||
Object.defineProperty(exports, "HttpStream", { enumerable: true, get: function () { return stream_js_2.HttpStream; } });
|
||||
var client_js_6 = require("./ws/client.js");
|
||||
Object.defineProperty(exports, "WsClient", { enumerable: true, get: function () { return client_js_6.WsClient; } });
|
||||
var stream_js_3 = require("./ws/stream.js");
|
||||
Object.defineProperty(exports, "WsStream", { enumerable: true, get: function () { return stream_js_3.WsStream; } });
|
||||
/** Open a Hrana client over WebSocket connected to the given `url`. */
|
||||
function openWs(url, jwt, protocolVersion = 2) {
|
||||
if (typeof isomorphic_ws_1.WebSocket === "undefined") {
|
||||
throw new errors_js_1.WebSocketUnsupportedError("WebSockets are not supported in this environment");
|
||||
}
|
||||
var subprotocols = undefined;
|
||||
if (protocolVersion == 3) {
|
||||
subprotocols = Array.from(client_js_1.subprotocolsV3.keys());
|
||||
}
|
||||
else {
|
||||
subprotocols = Array.from(client_js_1.subprotocolsV2.keys());
|
||||
}
|
||||
const socket = new isomorphic_ws_1.WebSocket(url, subprotocols);
|
||||
return new client_js_3.WsClient(socket, jwt);
|
||||
}
|
||||
exports.openWs = openWs;
|
||||
/** Open a Hrana client over HTTP connected to the given `url`.
|
||||
*
|
||||
* If the `customFetch` argument is passed and not `undefined`, it is used in place of the `fetch` function
|
||||
* from `@libsql/isomorphic-fetch`. This function is always called with a `Request` object from
|
||||
* `@libsql/isomorphic-fetch`.
|
||||
*/
|
||||
function openHttp(url, jwt, customFetch, protocolVersion = 2) {
|
||||
return new client_js_2.HttpClient(url instanceof URL ? url : new URL(url), jwt, customFetch, protocolVersion);
|
||||
}
|
||||
exports.openHttp = openHttp;
|
||||
79
node_modules/@libsql/hrana-client/lib-cjs/libsql_url.js
generated
vendored
Normal file
79
node_modules/@libsql/hrana-client/lib-cjs/libsql_url.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseLibsqlUrl = void 0;
|
||||
const errors_js_1 = require("./errors.js");
|
||||
;
|
||||
/** Parses a URL compatible with the libsql client (`@libsql/client`). This URL may have the "libsql:" scheme
|
||||
* and may contain query parameters. */
|
||||
function parseLibsqlUrl(urlStr) {
|
||||
const url = new URL(urlStr);
|
||||
let authToken = undefined;
|
||||
let tls = undefined;
|
||||
for (const [key, value] of url.searchParams.entries()) {
|
||||
if (key === "authToken") {
|
||||
authToken = value;
|
||||
}
|
||||
else if (key === "tls") {
|
||||
if (value === "0") {
|
||||
tls = false;
|
||||
}
|
||||
else if (value === "1") {
|
||||
tls = true;
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.LibsqlUrlParseError(`Unknown value for the "tls" query argument: ${JSON.stringify(value)}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.LibsqlUrlParseError(`Unknown URL query argument ${JSON.stringify(key)}`);
|
||||
}
|
||||
}
|
||||
let hranaWsScheme;
|
||||
let hranaHttpScheme;
|
||||
if ((url.protocol === "http:" || url.protocol === "ws:") && (tls === true)) {
|
||||
throw new errors_js_1.LibsqlUrlParseError(`A ${JSON.stringify(url.protocol)} URL cannot opt into TLS using ?tls=1`);
|
||||
}
|
||||
else if ((url.protocol === "https:" || url.protocol === "wss:") && (tls === false)) {
|
||||
throw new errors_js_1.LibsqlUrlParseError(`A ${JSON.stringify(url.protocol)} URL cannot opt out of TLS using ?tls=0`);
|
||||
}
|
||||
if (url.protocol === "http:" || url.protocol === "https:") {
|
||||
hranaHttpScheme = url.protocol;
|
||||
}
|
||||
else if (url.protocol === "ws:" || url.protocol === "wss:") {
|
||||
hranaWsScheme = url.protocol;
|
||||
}
|
||||
else if (url.protocol === "libsql:") {
|
||||
if (tls === false) {
|
||||
if (!url.port) {
|
||||
throw new errors_js_1.LibsqlUrlParseError(`A "libsql:" URL with ?tls=0 must specify an explicit port`);
|
||||
}
|
||||
hranaHttpScheme = "http:";
|
||||
hranaWsScheme = "ws:";
|
||||
}
|
||||
else {
|
||||
hranaHttpScheme = "https:";
|
||||
hranaWsScheme = "wss:";
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.LibsqlUrlParseError(`This client does not support ${JSON.stringify(url.protocol)} URLs. ` +
|
||||
'Please use a "libsql:", "ws:", "wss:", "http:" or "https:" URL instead.');
|
||||
}
|
||||
if (url.username || url.password) {
|
||||
throw new errors_js_1.LibsqlUrlParseError("This client does not support HTTP Basic authentication with a username and password. " +
|
||||
'You can authenticate using a token passed in the "authToken" URL query parameter.');
|
||||
}
|
||||
if (url.hash) {
|
||||
throw new errors_js_1.LibsqlUrlParseError("URL fragments are not supported");
|
||||
}
|
||||
let hranaPath = url.pathname;
|
||||
if (hranaPath === "/") {
|
||||
hranaPath = "";
|
||||
}
|
||||
const hranaWsUrl = hranaWsScheme !== undefined
|
||||
? `${hranaWsScheme}//${url.host}${hranaPath}` : undefined;
|
||||
const hranaHttpUrl = hranaHttpScheme !== undefined
|
||||
? `${hranaHttpScheme}//${url.host}${hranaPath}` : undefined;
|
||||
return { hranaWsUrl, hranaHttpUrl, authToken };
|
||||
}
|
||||
exports.parseLibsqlUrl = parseLibsqlUrl;
|
||||
3
node_modules/@libsql/hrana-client/lib-cjs/package.json
generated
vendored
Normal file
3
node_modules/@libsql/hrana-client/lib-cjs/package.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
30
node_modules/@libsql/hrana-client/lib-cjs/queue.js
generated
vendored
Normal file
30
node_modules/@libsql/hrana-client/lib-cjs/queue.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Queue = void 0;
|
||||
class Queue {
|
||||
#pushStack;
|
||||
#shiftStack;
|
||||
constructor() {
|
||||
this.#pushStack = [];
|
||||
this.#shiftStack = [];
|
||||
}
|
||||
get length() {
|
||||
return this.#pushStack.length + this.#shiftStack.length;
|
||||
}
|
||||
push(elem) {
|
||||
this.#pushStack.push(elem);
|
||||
}
|
||||
shift() {
|
||||
if (this.#shiftStack.length === 0 && this.#pushStack.length > 0) {
|
||||
this.#shiftStack = this.#pushStack.reverse();
|
||||
this.#pushStack = [];
|
||||
}
|
||||
return this.#shiftStack.pop();
|
||||
}
|
||||
first() {
|
||||
return this.#shiftStack.length !== 0
|
||||
? this.#shiftStack[this.#shiftStack.length - 1]
|
||||
: this.#pushStack[0];
|
||||
}
|
||||
}
|
||||
exports.Queue = Queue;
|
||||
15
node_modules/@libsql/hrana-client/lib-cjs/queue_microtask.js
generated
vendored
Normal file
15
node_modules/@libsql/hrana-client/lib-cjs/queue_microtask.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.queueMicrotask = void 0;
|
||||
// queueMicrotask() ponyfill
|
||||
// https://github.com/libsql/libsql-client-ts/issues/47
|
||||
let _queueMicrotask;
|
||||
if (typeof queueMicrotask !== "undefined") {
|
||||
exports.queueMicrotask = _queueMicrotask = queueMicrotask;
|
||||
}
|
||||
else {
|
||||
const resolved = Promise.resolve();
|
||||
exports.queueMicrotask = _queueMicrotask = (callback) => {
|
||||
resolved.then(callback);
|
||||
};
|
||||
}
|
||||
56
node_modules/@libsql/hrana-client/lib-cjs/result.js
generated
vendored
Normal file
56
node_modules/@libsql/hrana-client/lib-cjs/result.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.errorFromProto = exports.valueResultFromProto = exports.rowResultFromProto = exports.rowsResultFromProto = exports.stmtResultFromProto = void 0;
|
||||
const errors_js_1 = require("./errors.js");
|
||||
const value_js_1 = require("./value.js");
|
||||
function stmtResultFromProto(result) {
|
||||
return {
|
||||
affectedRowCount: result.affectedRowCount,
|
||||
lastInsertRowid: result.lastInsertRowid,
|
||||
columnNames: result.cols.map(col => col.name),
|
||||
columnDecltypes: result.cols.map(col => col.decltype),
|
||||
};
|
||||
}
|
||||
exports.stmtResultFromProto = stmtResultFromProto;
|
||||
function rowsResultFromProto(result, intMode) {
|
||||
const stmtResult = stmtResultFromProto(result);
|
||||
const rows = result.rows.map(row => rowFromProto(stmtResult.columnNames, row, intMode));
|
||||
return { ...stmtResult, rows };
|
||||
}
|
||||
exports.rowsResultFromProto = rowsResultFromProto;
|
||||
function rowResultFromProto(result, intMode) {
|
||||
const stmtResult = stmtResultFromProto(result);
|
||||
let row;
|
||||
if (result.rows.length > 0) {
|
||||
row = rowFromProto(stmtResult.columnNames, result.rows[0], intMode);
|
||||
}
|
||||
return { ...stmtResult, row };
|
||||
}
|
||||
exports.rowResultFromProto = rowResultFromProto;
|
||||
function valueResultFromProto(result, intMode) {
|
||||
const stmtResult = stmtResultFromProto(result);
|
||||
let value;
|
||||
if (result.rows.length > 0 && stmtResult.columnNames.length > 0) {
|
||||
value = (0, value_js_1.valueFromProto)(result.rows[0][0], intMode);
|
||||
}
|
||||
return { ...stmtResult, value };
|
||||
}
|
||||
exports.valueResultFromProto = valueResultFromProto;
|
||||
function rowFromProto(colNames, values, intMode) {
|
||||
const row = {};
|
||||
// make sure that the "length" property is not enumerable
|
||||
Object.defineProperty(row, "length", { value: values.length });
|
||||
for (let i = 0; i < values.length; ++i) {
|
||||
const value = (0, value_js_1.valueFromProto)(values[i], intMode);
|
||||
Object.defineProperty(row, i, { value });
|
||||
const colName = colNames[i];
|
||||
if (colName !== undefined && !Object.hasOwn(row, colName)) {
|
||||
Object.defineProperty(row, colName, { value, enumerable: true, configurable: true, writable: true });
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
function errorFromProto(error) {
|
||||
return new errors_js_1.ResponseError(error.message, error);
|
||||
}
|
||||
exports.errorFromProto = errorFromProto;
|
||||
138
node_modules/@libsql/hrana-client/lib-cjs/shared/json_decode.js
generated
vendored
Normal file
138
node_modules/@libsql/hrana-client/lib-cjs/shared/json_decode.js
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Value = exports.DescribeResult = exports.CursorEntry = exports.BatchResult = exports.StmtResult = exports.Error = void 0;
|
||||
const js_base64_1 = require("js-base64");
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const d = __importStar(require("../encoding/json/decode.js"));
|
||||
function Error(obj) {
|
||||
const message = d.string(obj["message"]);
|
||||
const code = d.stringOpt(obj["code"]);
|
||||
return { message, code };
|
||||
}
|
||||
exports.Error = Error;
|
||||
function StmtResult(obj) {
|
||||
const cols = d.arrayObjectsMap(obj["cols"], Col);
|
||||
const rows = d.array(obj["rows"]).map((rowObj) => d.arrayObjectsMap(rowObj, Value));
|
||||
const affectedRowCount = d.number(obj["affected_row_count"]);
|
||||
const lastInsertRowidStr = d.stringOpt(obj["last_insert_rowid"]);
|
||||
const lastInsertRowid = lastInsertRowidStr !== undefined
|
||||
? BigInt(lastInsertRowidStr) : undefined;
|
||||
return { cols, rows, affectedRowCount, lastInsertRowid };
|
||||
}
|
||||
exports.StmtResult = StmtResult;
|
||||
function Col(obj) {
|
||||
const name = d.stringOpt(obj["name"]);
|
||||
const decltype = d.stringOpt(obj["decltype"]);
|
||||
return { name, decltype };
|
||||
}
|
||||
function BatchResult(obj) {
|
||||
const stepResults = new Map();
|
||||
d.array(obj["step_results"]).forEach((value, i) => {
|
||||
if (value !== null) {
|
||||
stepResults.set(i, StmtResult(d.object(value)));
|
||||
}
|
||||
});
|
||||
const stepErrors = new Map();
|
||||
d.array(obj["step_errors"]).forEach((value, i) => {
|
||||
if (value !== null) {
|
||||
stepErrors.set(i, Error(d.object(value)));
|
||||
}
|
||||
});
|
||||
return { stepResults, stepErrors };
|
||||
}
|
||||
exports.BatchResult = BatchResult;
|
||||
function CursorEntry(obj) {
|
||||
const type = d.string(obj["type"]);
|
||||
if (type === "step_begin") {
|
||||
const step = d.number(obj["step"]);
|
||||
const cols = d.arrayObjectsMap(obj["cols"], Col);
|
||||
return { type: "step_begin", step, cols };
|
||||
}
|
||||
else if (type === "step_end") {
|
||||
const affectedRowCount = d.number(obj["affected_row_count"]);
|
||||
const lastInsertRowidStr = d.stringOpt(obj["last_insert_rowid"]);
|
||||
const lastInsertRowid = lastInsertRowidStr !== undefined
|
||||
? BigInt(lastInsertRowidStr) : undefined;
|
||||
return { type: "step_end", affectedRowCount, lastInsertRowid };
|
||||
}
|
||||
else if (type === "step_error") {
|
||||
const step = d.number(obj["step"]);
|
||||
const error = Error(d.object(obj["error"]));
|
||||
return { type: "step_error", step, error };
|
||||
}
|
||||
else if (type === "row") {
|
||||
const row = d.arrayObjectsMap(obj["row"], Value);
|
||||
return { type: "row", row };
|
||||
}
|
||||
else if (type === "error") {
|
||||
const error = Error(d.object(obj["error"]));
|
||||
return { type: "error", error };
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.ProtoError("Unexpected type of CursorEntry");
|
||||
}
|
||||
}
|
||||
exports.CursorEntry = CursorEntry;
|
||||
function DescribeResult(obj) {
|
||||
const params = d.arrayObjectsMap(obj["params"], DescribeParam);
|
||||
const cols = d.arrayObjectsMap(obj["cols"], DescribeCol);
|
||||
const isExplain = d.boolean(obj["is_explain"]);
|
||||
const isReadonly = d.boolean(obj["is_readonly"]);
|
||||
return { params, cols, isExplain, isReadonly };
|
||||
}
|
||||
exports.DescribeResult = DescribeResult;
|
||||
function DescribeParam(obj) {
|
||||
const name = d.stringOpt(obj["name"]);
|
||||
return { name };
|
||||
}
|
||||
function DescribeCol(obj) {
|
||||
const name = d.string(obj["name"]);
|
||||
const decltype = d.stringOpt(obj["decltype"]);
|
||||
return { name, decltype };
|
||||
}
|
||||
function Value(obj) {
|
||||
const type = d.string(obj["type"]);
|
||||
if (type === "null") {
|
||||
return null;
|
||||
}
|
||||
else if (type === "integer") {
|
||||
const value = d.string(obj["value"]);
|
||||
return BigInt(value);
|
||||
}
|
||||
else if (type === "float") {
|
||||
return d.number(obj["value"]);
|
||||
}
|
||||
else if (type === "text") {
|
||||
return d.string(obj["value"]);
|
||||
}
|
||||
else if (type === "blob") {
|
||||
return js_base64_1.Base64.toUint8Array(d.string(obj["base64"]));
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.ProtoError("Unexpected type of Value");
|
||||
}
|
||||
}
|
||||
exports.Value = Value;
|
||||
76
node_modules/@libsql/hrana-client/lib-cjs/shared/json_encode.js
generated
vendored
Normal file
76
node_modules/@libsql/hrana-client/lib-cjs/shared/json_encode.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Batch = exports.Stmt = void 0;
|
||||
const js_base64_1 = require("js-base64");
|
||||
const util_js_1 = require("../util.js");
|
||||
function Stmt(w, msg) {
|
||||
if (msg.sql !== undefined) {
|
||||
w.string("sql", msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.number("sql_id", msg.sqlId);
|
||||
}
|
||||
w.arrayObjects("args", msg.args, Value);
|
||||
w.arrayObjects("named_args", msg.namedArgs, NamedArg);
|
||||
w.boolean("want_rows", msg.wantRows);
|
||||
}
|
||||
exports.Stmt = Stmt;
|
||||
function NamedArg(w, msg) {
|
||||
w.string("name", msg.name);
|
||||
w.object("value", msg.value, Value);
|
||||
}
|
||||
function Batch(w, msg) {
|
||||
w.arrayObjects("steps", msg.steps, BatchStep);
|
||||
}
|
||||
exports.Batch = Batch;
|
||||
function BatchStep(w, msg) {
|
||||
if (msg.condition !== undefined) {
|
||||
w.object("condition", msg.condition, BatchCond);
|
||||
}
|
||||
w.object("stmt", msg.stmt, Stmt);
|
||||
}
|
||||
function BatchCond(w, msg) {
|
||||
w.stringRaw("type", msg.type);
|
||||
if (msg.type === "ok" || msg.type === "error") {
|
||||
w.number("step", msg.step);
|
||||
}
|
||||
else if (msg.type === "not") {
|
||||
w.object("cond", msg.cond, BatchCond);
|
||||
}
|
||||
else if (msg.type === "and" || msg.type === "or") {
|
||||
w.arrayObjects("conds", msg.conds, BatchCond);
|
||||
}
|
||||
else if (msg.type === "is_autocommit") {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(msg, "Impossible type of BatchCond");
|
||||
}
|
||||
}
|
||||
function Value(w, msg) {
|
||||
if (msg === null) {
|
||||
w.stringRaw("type", "null");
|
||||
}
|
||||
else if (typeof msg === "bigint") {
|
||||
w.stringRaw("type", "integer");
|
||||
w.stringRaw("value", "" + msg);
|
||||
}
|
||||
else if (typeof msg === "number") {
|
||||
w.stringRaw("type", "float");
|
||||
w.number("value", msg);
|
||||
}
|
||||
else if (typeof msg === "string") {
|
||||
w.stringRaw("type", "text");
|
||||
w.string("value", msg);
|
||||
}
|
||||
else if (msg instanceof Uint8Array) {
|
||||
w.stringRaw("type", "blob");
|
||||
w.stringRaw("base64", js_base64_1.Base64.fromUint8Array(msg));
|
||||
}
|
||||
else if (msg === undefined) {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(msg, "Impossible type of Value");
|
||||
}
|
||||
}
|
||||
3
node_modules/@libsql/hrana-client/lib-cjs/shared/proto.js
generated
vendored
Normal file
3
node_modules/@libsql/hrana-client/lib-cjs/shared/proto.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
// Types for the protocol structures that are shared for WebSocket and HTTP
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
118
node_modules/@libsql/hrana-client/lib-cjs/shared/protobuf_decode.js
generated
vendored
Normal file
118
node_modules/@libsql/hrana-client/lib-cjs/shared/protobuf_decode.js
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DescribeResult = exports.CursorEntry = exports.BatchResult = exports.StmtResult = exports.Error = void 0;
|
||||
exports.Error = {
|
||||
default() { return { message: "", code: undefined }; },
|
||||
1(r, msg) { msg.message = r.string(); },
|
||||
2(r, msg) { msg.code = r.string(); },
|
||||
};
|
||||
exports.StmtResult = {
|
||||
default() {
|
||||
return {
|
||||
cols: [],
|
||||
rows: [],
|
||||
affectedRowCount: 0,
|
||||
lastInsertRowid: undefined,
|
||||
};
|
||||
},
|
||||
1(r, msg) { msg.cols.push(r.message(Col)); },
|
||||
2(r, msg) { msg.rows.push(r.message(Row)); },
|
||||
3(r, msg) { msg.affectedRowCount = Number(r.uint64()); },
|
||||
4(r, msg) { msg.lastInsertRowid = r.sint64(); },
|
||||
};
|
||||
const Col = {
|
||||
default() { return { name: undefined, decltype: undefined }; },
|
||||
1(r, msg) { msg.name = r.string(); },
|
||||
2(r, msg) { msg.decltype = r.string(); },
|
||||
};
|
||||
const Row = {
|
||||
default() { return []; },
|
||||
1(r, msg) { msg.push(r.message(Value)); },
|
||||
};
|
||||
exports.BatchResult = {
|
||||
default() { return { stepResults: new Map(), stepErrors: new Map() }; },
|
||||
1(r, msg) {
|
||||
const [key, value] = r.message(BatchResultStepResult);
|
||||
msg.stepResults.set(key, value);
|
||||
},
|
||||
2(r, msg) {
|
||||
const [key, value] = r.message(BatchResultStepError);
|
||||
msg.stepErrors.set(key, value);
|
||||
},
|
||||
};
|
||||
const BatchResultStepResult = {
|
||||
default() { return [0, exports.StmtResult.default()]; },
|
||||
1(r, msg) { msg[0] = r.uint32(); },
|
||||
2(r, msg) { msg[1] = r.message(exports.StmtResult); },
|
||||
};
|
||||
const BatchResultStepError = {
|
||||
default() { return [0, exports.Error.default()]; },
|
||||
1(r, msg) { msg[0] = r.uint32(); },
|
||||
2(r, msg) { msg[1] = r.message(exports.Error); },
|
||||
};
|
||||
exports.CursorEntry = {
|
||||
default() { return { type: "none" }; },
|
||||
1(r) { return r.message(StepBeginEntry); },
|
||||
2(r) { return r.message(StepEndEntry); },
|
||||
3(r) { return r.message(StepErrorEntry); },
|
||||
4(r) { return { type: "row", row: r.message(Row) }; },
|
||||
5(r) { return { type: "error", error: r.message(exports.Error) }; },
|
||||
};
|
||||
const StepBeginEntry = {
|
||||
default() { return { type: "step_begin", step: 0, cols: [] }; },
|
||||
1(r, msg) { msg.step = r.uint32(); },
|
||||
2(r, msg) { msg.cols.push(r.message(Col)); },
|
||||
};
|
||||
const StepEndEntry = {
|
||||
default() {
|
||||
return {
|
||||
type: "step_end",
|
||||
affectedRowCount: 0,
|
||||
lastInsertRowid: undefined,
|
||||
};
|
||||
},
|
||||
1(r, msg) { msg.affectedRowCount = r.uint32(); },
|
||||
2(r, msg) { msg.lastInsertRowid = r.uint64(); },
|
||||
};
|
||||
const StepErrorEntry = {
|
||||
default() {
|
||||
return {
|
||||
type: "step_error",
|
||||
step: 0,
|
||||
error: exports.Error.default(),
|
||||
};
|
||||
},
|
||||
1(r, msg) { msg.step = r.uint32(); },
|
||||
2(r, msg) { msg.error = r.message(exports.Error); },
|
||||
};
|
||||
exports.DescribeResult = {
|
||||
default() {
|
||||
return {
|
||||
params: [],
|
||||
cols: [],
|
||||
isExplain: false,
|
||||
isReadonly: false,
|
||||
};
|
||||
},
|
||||
1(r, msg) { msg.params.push(r.message(DescribeParam)); },
|
||||
2(r, msg) { msg.cols.push(r.message(DescribeCol)); },
|
||||
3(r, msg) { msg.isExplain = r.bool(); },
|
||||
4(r, msg) { msg.isReadonly = r.bool(); },
|
||||
};
|
||||
const DescribeParam = {
|
||||
default() { return { name: undefined }; },
|
||||
1(r, msg) { msg.name = r.string(); },
|
||||
};
|
||||
const DescribeCol = {
|
||||
default() { return { name: "", decltype: undefined }; },
|
||||
1(r, msg) { msg.name = r.string(); },
|
||||
2(r, msg) { msg.decltype = r.string(); },
|
||||
};
|
||||
const Value = {
|
||||
default() { return undefined; },
|
||||
1(r) { return null; },
|
||||
2(r) { return r.sint64(); },
|
||||
3(r) { return r.double(); },
|
||||
4(r) { return r.string(); },
|
||||
5(r) { return r.bytes(); },
|
||||
};
|
||||
90
node_modules/@libsql/hrana-client/lib-cjs/shared/protobuf_encode.js
generated
vendored
Normal file
90
node_modules/@libsql/hrana-client/lib-cjs/shared/protobuf_encode.js
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Batch = exports.Stmt = void 0;
|
||||
const util_js_1 = require("../util.js");
|
||||
function Stmt(w, msg) {
|
||||
if (msg.sql !== undefined) {
|
||||
w.string(1, msg.sql);
|
||||
}
|
||||
if (msg.sqlId !== undefined) {
|
||||
w.int32(2, msg.sqlId);
|
||||
}
|
||||
for (const arg of msg.args) {
|
||||
w.message(3, arg, Value);
|
||||
}
|
||||
for (const arg of msg.namedArgs) {
|
||||
w.message(4, arg, NamedArg);
|
||||
}
|
||||
w.bool(5, msg.wantRows);
|
||||
}
|
||||
exports.Stmt = Stmt;
|
||||
function NamedArg(w, msg) {
|
||||
w.string(1, msg.name);
|
||||
w.message(2, msg.value, Value);
|
||||
}
|
||||
function Batch(w, msg) {
|
||||
for (const step of msg.steps) {
|
||||
w.message(1, step, BatchStep);
|
||||
}
|
||||
}
|
||||
exports.Batch = Batch;
|
||||
function BatchStep(w, msg) {
|
||||
if (msg.condition !== undefined) {
|
||||
w.message(1, msg.condition, BatchCond);
|
||||
}
|
||||
w.message(2, msg.stmt, Stmt);
|
||||
}
|
||||
function BatchCond(w, msg) {
|
||||
if (msg.type === "ok") {
|
||||
w.uint32(1, msg.step);
|
||||
}
|
||||
else if (msg.type === "error") {
|
||||
w.uint32(2, msg.step);
|
||||
}
|
||||
else if (msg.type === "not") {
|
||||
w.message(3, msg.cond, BatchCond);
|
||||
}
|
||||
else if (msg.type === "and") {
|
||||
w.message(4, msg.conds, BatchCondList);
|
||||
}
|
||||
else if (msg.type === "or") {
|
||||
w.message(5, msg.conds, BatchCondList);
|
||||
}
|
||||
else if (msg.type === "is_autocommit") {
|
||||
w.message(6, undefined, Empty);
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(msg, "Impossible type of BatchCond");
|
||||
}
|
||||
}
|
||||
function BatchCondList(w, msg) {
|
||||
for (const cond of msg) {
|
||||
w.message(1, cond, BatchCond);
|
||||
}
|
||||
}
|
||||
function Value(w, msg) {
|
||||
if (msg === null) {
|
||||
w.message(1, undefined, Empty);
|
||||
}
|
||||
else if (typeof msg === "bigint") {
|
||||
w.sint64(2, msg);
|
||||
}
|
||||
else if (typeof msg === "number") {
|
||||
w.double(3, msg);
|
||||
}
|
||||
else if (typeof msg === "string") {
|
||||
w.string(4, msg);
|
||||
}
|
||||
else if (msg instanceof Uint8Array) {
|
||||
w.bytes(5, msg);
|
||||
}
|
||||
else if (msg === undefined) {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(msg, "Impossible type of Value");
|
||||
}
|
||||
}
|
||||
function Empty(_w, _msg) {
|
||||
// do nothing
|
||||
}
|
||||
51
node_modules/@libsql/hrana-client/lib-cjs/sql.js
generated
vendored
Normal file
51
node_modules/@libsql/hrana-client/lib-cjs/sql.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sqlToProto = exports.Sql = void 0;
|
||||
const errors_js_1 = require("./errors.js");
|
||||
/** Text of an SQL statement cached on the server. */
|
||||
class Sql {
|
||||
#owner;
|
||||
#sqlId;
|
||||
#closed;
|
||||
/** @private */
|
||||
constructor(owner, sqlId) {
|
||||
this.#owner = owner;
|
||||
this.#sqlId = sqlId;
|
||||
this.#closed = undefined;
|
||||
}
|
||||
/** @private */
|
||||
_getSqlId(owner) {
|
||||
if (this.#owner !== owner) {
|
||||
throw new errors_js_1.MisuseError("Attempted to use SQL text opened with other object");
|
||||
}
|
||||
else if (this.#closed !== undefined) {
|
||||
throw new errors_js_1.ClosedError("SQL text is closed", this.#closed);
|
||||
}
|
||||
return this.#sqlId;
|
||||
}
|
||||
/** Remove the SQL text from the server, releasing resouces. */
|
||||
close() {
|
||||
this._setClosed(new errors_js_1.ClientError("SQL text was manually closed"));
|
||||
}
|
||||
/** @private */
|
||||
_setClosed(error) {
|
||||
if (this.#closed === undefined) {
|
||||
this.#closed = error;
|
||||
this.#owner._closeSql(this.#sqlId);
|
||||
}
|
||||
}
|
||||
/** True if the SQL text is closed (removed from the server). */
|
||||
get closed() {
|
||||
return this.#closed !== undefined;
|
||||
}
|
||||
}
|
||||
exports.Sql = Sql;
|
||||
function sqlToProto(owner, sql) {
|
||||
if (sql instanceof Sql) {
|
||||
return { sqlId: sql._getSqlId(owner) };
|
||||
}
|
||||
else {
|
||||
return { sql: "" + sql };
|
||||
}
|
||||
}
|
||||
exports.sqlToProto = sqlToProto;
|
||||
81
node_modules/@libsql/hrana-client/lib-cjs/stmt.js
generated
vendored
Normal file
81
node_modules/@libsql/hrana-client/lib-cjs/stmt.js
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
"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");
|
||||
/** A statement that can be evaluated by the database. Besides the SQL text, it also contains the positional
|
||||
* and named arguments. */
|
||||
class Stmt {
|
||||
/** The SQL statement text. */
|
||||
sql;
|
||||
/** @private */
|
||||
_args;
|
||||
/** @private */
|
||||
_namedArgs;
|
||||
/** Initialize the statement with given SQL text. */
|
||||
constructor(sql) {
|
||||
this.sql = sql;
|
||||
this._args = [];
|
||||
this._namedArgs = new Map();
|
||||
}
|
||||
/** Binds positional parameters from the given `values`. All previous positional bindings are cleared. */
|
||||
bindIndexes(values) {
|
||||
this._args.length = 0;
|
||||
for (const value of values) {
|
||||
this._args.push((0, value_js_1.valueToProto)(value));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
/** Binds a parameter by a 1-based index. */
|
||||
bindIndex(index, value) {
|
||||
if (index !== (index | 0) || index <= 0) {
|
||||
throw new RangeError("Index of a positional argument must be positive integer");
|
||||
}
|
||||
while (this._args.length < index) {
|
||||
this._args.push(null);
|
||||
}
|
||||
this._args[index - 1] = (0, value_js_1.valueToProto)(value);
|
||||
return this;
|
||||
}
|
||||
/** Binds a parameter by name. */
|
||||
bindName(name, value) {
|
||||
this._namedArgs.set(name, (0, value_js_1.valueToProto)(value));
|
||||
return this;
|
||||
}
|
||||
/** Clears all bindings. */
|
||||
unbindAll() {
|
||||
this._args.length = 0;
|
||||
this._namedArgs.clear();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
exports.Stmt = Stmt;
|
||||
function stmtToProto(sqlOwner, stmt, wantRows) {
|
||||
let inSql;
|
||||
let args = [];
|
||||
let namedArgs = [];
|
||||
if (stmt instanceof Stmt) {
|
||||
inSql = stmt.sql;
|
||||
args = stmt._args;
|
||||
for (const [name, value] of stmt._namedArgs.entries()) {
|
||||
namedArgs.push({ name, value });
|
||||
}
|
||||
}
|
||||
else if (Array.isArray(stmt)) {
|
||||
inSql = stmt[0];
|
||||
if (Array.isArray(stmt[1])) {
|
||||
args = stmt[1].map((arg) => (0, value_js_1.valueToProto)(arg));
|
||||
}
|
||||
else {
|
||||
namedArgs = Object.entries(stmt[1]).map(([name, value]) => {
|
||||
return { name, value: (0, value_js_1.valueToProto)(value) };
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
inSql = stmt;
|
||||
}
|
||||
const { sql, sqlId } = (0, sql_js_1.sqlToProto)(sqlOwner, inSql);
|
||||
return { sql, sqlId, args, namedArgs, wantRows };
|
||||
}
|
||||
exports.stmtToProto = stmtToProto;
|
||||
61
node_modules/@libsql/hrana-client/lib-cjs/stream.js
generated
vendored
Normal file
61
node_modules/@libsql/hrana-client/lib-cjs/stream.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
"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 result_js_1 = require("./result.js");
|
||||
const sql_js_1 = require("./sql.js");
|
||||
const stmt_js_1 = require("./stmt.js");
|
||||
/** A stream for executing SQL statements (a "database connection"). */
|
||||
class Stream {
|
||||
/** @private */
|
||||
constructor(intMode) {
|
||||
this.intMode = intMode;
|
||||
}
|
||||
/** Execute a statement and return rows. */
|
||||
query(stmt) {
|
||||
return this.#execute(stmt, true, result_js_1.rowsResultFromProto);
|
||||
}
|
||||
/** Execute a statement and return at most a single row. */
|
||||
queryRow(stmt) {
|
||||
return this.#execute(stmt, true, result_js_1.rowResultFromProto);
|
||||
}
|
||||
/** Execute a statement and return at most a single value. */
|
||||
queryValue(stmt) {
|
||||
return this.#execute(stmt, true, result_js_1.valueResultFromProto);
|
||||
}
|
||||
/** Execute a statement without returning rows. */
|
||||
run(stmt) {
|
||||
return this.#execute(stmt, false, result_js_1.stmtResultFromProto);
|
||||
}
|
||||
#execute(inStmt, wantRows, fromProto) {
|
||||
const stmt = (0, stmt_js_1.stmtToProto)(this._sqlOwner(), inStmt, wantRows);
|
||||
return this._execute(stmt).then((r) => fromProto(r, this.intMode));
|
||||
}
|
||||
/** Return a builder for creating and executing a batch.
|
||||
*
|
||||
* If `useCursor` is true, the batch will be executed using a Hrana cursor, which will stream results from
|
||||
* the server to the client, which consumes less memory on the server. This requires protocol version 3 or
|
||||
* higher.
|
||||
*/
|
||||
batch(useCursor = false) {
|
||||
return new batch_js_1.Batch(this, useCursor);
|
||||
}
|
||||
/** Parse and analyze a statement. This requires protocol version 2 or higher. */
|
||||
describe(inSql) {
|
||||
const protoSql = (0, sql_js_1.sqlToProto)(this._sqlOwner(), inSql);
|
||||
return this._describe(protoSql).then(describe_js_1.describeResultFromProto);
|
||||
}
|
||||
/** Execute a sequence of statements separated by semicolons. This requires protocol version 2 or higher.
|
||||
* */
|
||||
sequence(inSql) {
|
||||
const protoSql = (0, sql_js_1.sqlToProto)(this._sqlOwner(), inSql);
|
||||
return this._sequence(protoSql);
|
||||
}
|
||||
/** Representation of integers returned from the database. See {@link IntMode}.
|
||||
*
|
||||
* This value affects the results of all operations on this stream.
|
||||
*/
|
||||
intMode;
|
||||
}
|
||||
exports.Stream = Stream;
|
||||
8
node_modules/@libsql/hrana-client/lib-cjs/util.js
generated
vendored
Normal file
8
node_modules/@libsql/hrana-client/lib-cjs/util.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.impossible = void 0;
|
||||
const errors_js_1 = require("./errors.js");
|
||||
function impossible(value, message) {
|
||||
throw new errors_js_1.InternalError(message);
|
||||
}
|
||||
exports.impossible = impossible;
|
||||
88
node_modules/@libsql/hrana-client/lib-cjs/value.js
generated
vendored
Normal file
88
node_modules/@libsql/hrana-client/lib-cjs/value.js
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.valueFromProto = exports.valueToProto = void 0;
|
||||
const errors_js_1 = require("./errors.js");
|
||||
const util_js_1 = require("./util.js");
|
||||
function valueToProto(value) {
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
else if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "number") {
|
||||
if (!Number.isFinite(value)) {
|
||||
throw new RangeError("Only finite numbers (not Infinity or NaN) can be passed as arguments");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "bigint") {
|
||||
if (value < minInteger || value > maxInteger) {
|
||||
throw new RangeError("This bigint value is too large to be represented as a 64-bit integer and passed as argument");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
return value ? 1n : 0n;
|
||||
}
|
||||
else if (value instanceof ArrayBuffer) {
|
||||
return new Uint8Array(value);
|
||||
}
|
||||
else if (value instanceof Uint8Array) {
|
||||
return value;
|
||||
}
|
||||
else if (value instanceof Date) {
|
||||
return +value.valueOf();
|
||||
}
|
||||
else if (typeof value === "object") {
|
||||
return "" + value.toString();
|
||||
}
|
||||
else {
|
||||
throw new TypeError("Unsupported type of value");
|
||||
}
|
||||
}
|
||||
exports.valueToProto = valueToProto;
|
||||
const minInteger = -9223372036854775808n;
|
||||
const maxInteger = 9223372036854775807n;
|
||||
function valueFromProto(value, intMode) {
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
else if (typeof value === "number") {
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
else if (typeof value === "bigint") {
|
||||
if (intMode === "number") {
|
||||
const num = Number(value);
|
||||
if (!Number.isSafeInteger(num)) {
|
||||
throw new RangeError("Received integer which is too large to be safely represented as a JavaScript number");
|
||||
}
|
||||
return num;
|
||||
}
|
||||
else if (intMode === "bigint") {
|
||||
return value;
|
||||
}
|
||||
else if (intMode === "string") {
|
||||
return "" + value;
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.MisuseError("Invalid value for IntMode");
|
||||
}
|
||||
}
|
||||
else if (value instanceof Uint8Array) {
|
||||
// TODO: we need to copy data from `Uint8Array` to return an `ArrayBuffer`. Perhaps we should add a
|
||||
// `blobMode` parameter, similar to `intMode`, which would allow the user to choose between receiving
|
||||
// `ArrayBuffer` (default, convenient) and `Uint8Array` (zero copy)?
|
||||
return value.slice().buffer;
|
||||
}
|
||||
else if (value === undefined) {
|
||||
throw new errors_js_1.ProtoError("Received unrecognized type of Value");
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(value, "Impossible type of Value");
|
||||
}
|
||||
}
|
||||
exports.valueFromProto = valueFromProto;
|
||||
322
node_modules/@libsql/hrana-client/lib-cjs/ws/client.js
generated
vendored
Normal file
322
node_modules/@libsql/hrana-client/lib-cjs/ws/client.js
generated
vendored
Normal file
@@ -0,0 +1,322 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WsClient = exports.subprotocolsV3 = exports.subprotocolsV2 = void 0;
|
||||
const client_js_1 = require("../client.js");
|
||||
const index_js_1 = require("../encoding/index.js");
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const id_alloc_js_1 = require("../id_alloc.js");
|
||||
const result_js_1 = require("../result.js");
|
||||
const sql_js_1 = require("../sql.js");
|
||||
const util_js_1 = require("../util.js");
|
||||
const stream_js_1 = require("./stream.js");
|
||||
const json_encode_js_1 = require("./json_encode.js");
|
||||
const protobuf_encode_js_1 = require("./protobuf_encode.js");
|
||||
const json_decode_js_1 = require("./json_decode.js");
|
||||
const protobuf_decode_js_1 = require("./protobuf_decode.js");
|
||||
exports.subprotocolsV2 = new Map([
|
||||
["hrana2", { version: 2, encoding: "json" }],
|
||||
["hrana1", { version: 1, encoding: "json" }],
|
||||
]);
|
||||
exports.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. */
|
||||
class WsClient extends client_js_1.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 id_alloc_js_1.IdAlloc();
|
||||
this._streamIdAlloc = new id_alloc_js_1.IdAlloc();
|
||||
this._cursorIdAlloc = new id_alloc_js_1.IdAlloc();
|
||||
this.#sqlIdAlloc = new id_alloc_js_1.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 errors_js_1.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 errors_js_1.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 = exports.subprotocolsV3.get(protocol);
|
||||
if (this.#subprotocol === undefined) {
|
||||
this.#setClosed(new errors_js_1.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 = (0, index_js_1.writeJsonObject)(msg, json_encode_js_1.ClientMsg);
|
||||
this.#socket.send(jsonMsg);
|
||||
}
|
||||
else if (encoding === "protobuf") {
|
||||
const protobufMsg = (0, index_js_1.writeProtobufMessage)(msg, protobuf_encode_js_1.ClientMsg);
|
||||
this.#socket.send(protobufMsg);
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.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 errors_js_1.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 errors_js_1.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 errors_js_1.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 errors_js_1.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 errors_js_1.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 errors_js_1.ProtoError("Received non-text message from server with JSON encoding"));
|
||||
return;
|
||||
}
|
||||
msg = (0, index_js_1.readJsonObject)(JSON.parse(event.data), json_decode_js_1.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 errors_js_1.ProtoError("Received non-binary message from server with Protobuf encoding"));
|
||||
return;
|
||||
}
|
||||
msg = (0, index_js_1.readProtobufMessage)(new Uint8Array(event.data), protobuf_decode_js_1.ServerMsg);
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.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 errors_js_1.ProtoError("Received an unrecognized ServerMsg");
|
||||
}
|
||||
else if (msg.type === "hello_ok" || msg.type === "hello_error") {
|
||||
if (this.#recvdHello) {
|
||||
throw new errors_js_1.ProtoError("Received a duplicated hello response");
|
||||
}
|
||||
this.#recvdHello = true;
|
||||
if (msg.type === "hello_error") {
|
||||
throw (0, result_js_1.errorFromProto)(msg.error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (!this.#recvdHello) {
|
||||
throw new errors_js_1.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 errors_js_1.ProtoError("Received unexpected OK response");
|
||||
}
|
||||
this.#requestIdAlloc.free(requestId);
|
||||
try {
|
||||
if (responseState.type !== msg.response.type) {
|
||||
console.dir({ responseState, msg });
|
||||
throw new errors_js_1.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 errors_js_1.ProtoError("Received unexpected error response");
|
||||
}
|
||||
this.#requestIdAlloc.free(requestId);
|
||||
responseState.errorCallback((0, result_js_1.errorFromProto)(msg.error));
|
||||
}
|
||||
else {
|
||||
throw (0, util_js_1.impossible)(msg, "Impossible ServerMsg type");
|
||||
}
|
||||
}
|
||||
/** Open a {@link WsStream}, a stream for executing SQL statements. */
|
||||
openStream() {
|
||||
return stream_js_1.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_js_1.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 errors_js_1.ClientError("Client was manually closed"));
|
||||
}
|
||||
/** True if the client is closed. */
|
||||
get closed() {
|
||||
return this.#closed !== undefined;
|
||||
}
|
||||
}
|
||||
exports.WsClient = WsClient;
|
||||
84
node_modules/@libsql/hrana-client/lib-cjs/ws/cursor.js
generated
vendored
Normal file
84
node_modules/@libsql/hrana-client/lib-cjs/ws/cursor.js
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WsCursor = void 0;
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const cursor_js_1 = require("../cursor.js");
|
||||
const queue_js_1 = require("../queue.js");
|
||||
const fetchChunkSize = 1000;
|
||||
const fetchQueueSize = 10;
|
||||
class WsCursor extends cursor_js_1.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_js_1.Queue();
|
||||
this.#fetchQueue = new queue_js_1.Queue();
|
||||
this.#closed = undefined;
|
||||
this.#done = false;
|
||||
}
|
||||
/** Fetch the next entry from the cursor. */
|
||||
async next() {
|
||||
for (;;) {
|
||||
if (this.#closed !== undefined) {
|
||||
throw new errors_js_1.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 errors_js_1.ClientError("Cursor was manually closed"));
|
||||
}
|
||||
/** True if the cursor is closed. */
|
||||
get closed() {
|
||||
return this.#closed !== undefined;
|
||||
}
|
||||
}
|
||||
exports.WsCursor = WsCursor;
|
||||
101
node_modules/@libsql/hrana-client/lib-cjs/ws/json_decode.js
generated
vendored
Normal file
101
node_modules/@libsql/hrana-client/lib-cjs/ws/json_decode.js
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ServerMsg = void 0;
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const d = __importStar(require("../encoding/json/decode.js"));
|
||||
const json_decode_js_1 = require("../shared/json_decode.js");
|
||||
function ServerMsg(obj) {
|
||||
const type = d.string(obj["type"]);
|
||||
if (type === "hello_ok") {
|
||||
return { type: "hello_ok" };
|
||||
}
|
||||
else if (type === "hello_error") {
|
||||
const error = (0, json_decode_js_1.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 = (0, json_decode_js_1.Error)(d.object(obj["error"]));
|
||||
return { type: "response_error", requestId, error };
|
||||
}
|
||||
else {
|
||||
throw new errors_js_1.ProtoError("Unexpected type of ServerMsg");
|
||||
}
|
||||
}
|
||||
exports.ServerMsg = 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 = (0, json_decode_js_1.StmtResult)(d.object(obj["result"]));
|
||||
return { type: "execute", result };
|
||||
}
|
||||
else if (type === "batch") {
|
||||
const result = (0, json_decode_js_1.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"], json_decode_js_1.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 = (0, json_decode_js_1.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 errors_js_1.ProtoError("Unexpected type of Response");
|
||||
}
|
||||
}
|
||||
81
node_modules/@libsql/hrana-client/lib-cjs/ws/json_encode.js
generated
vendored
Normal file
81
node_modules/@libsql/hrana-client/lib-cjs/ws/json_encode.js
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ClientMsg = void 0;
|
||||
const json_encode_js_1 = require("../shared/json_encode.js");
|
||||
const util_js_1 = require("../util.js");
|
||||
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 (0, util_js_1.impossible)(msg, "Impossible type of ClientMsg");
|
||||
}
|
||||
}
|
||||
exports.ClientMsg = 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, json_encode_js_1.Stmt);
|
||||
}
|
||||
else if (msg.type === "batch") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
w.object("batch", msg.batch, json_encode_js_1.Batch);
|
||||
}
|
||||
else if (msg.type === "open_cursor") {
|
||||
w.number("stream_id", msg.streamId);
|
||||
w.number("cursor_id", msg.cursorId);
|
||||
w.object("batch", msg.batch, json_encode_js_1.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 (0, util_js_1.impossible)(msg, "Impossible type of Request");
|
||||
}
|
||||
}
|
||||
18
node_modules/@libsql/hrana-client/lib-cjs/ws/proto.js
generated
vendored
Normal file
18
node_modules/@libsql/hrana-client/lib-cjs/ws/proto.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
// Types for the structures specific to Hrana over WebSockets.
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("../shared/proto.js"), exports);
|
||||
63
node_modules/@libsql/hrana-client/lib-cjs/ws/protobuf_decode.js
generated
vendored
Normal file
63
node_modules/@libsql/hrana-client/lib-cjs/ws/protobuf_decode.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ServerMsg = void 0;
|
||||
const protobuf_decode_js_1 = require("../shared/protobuf_decode.js");
|
||||
exports.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: protobuf_decode_js_1.Error.default() }; },
|
||||
1(r, msg) { msg.error = r.message(protobuf_decode_js_1.Error); },
|
||||
};
|
||||
const ResponseErrorMsg = {
|
||||
default() { return { type: "response_error", requestId: 0, error: protobuf_decode_js_1.Error.default() }; },
|
||||
1(r, msg) { msg.requestId = r.int32(); },
|
||||
2(r, msg) { msg.error = r.message(protobuf_decode_js_1.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: protobuf_decode_js_1.StmtResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(protobuf_decode_js_1.StmtResult); },
|
||||
};
|
||||
const BatchResp = {
|
||||
default() { return { type: "batch", result: protobuf_decode_js_1.BatchResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(protobuf_decode_js_1.BatchResult); },
|
||||
};
|
||||
const FetchCursorResp = {
|
||||
default() { return { type: "fetch_cursor", entries: [], done: false }; },
|
||||
1(r, msg) { msg.entries.push(r.message(protobuf_decode_js_1.CursorEntry)); },
|
||||
2(r, msg) { msg.done = r.bool(); },
|
||||
};
|
||||
const DescribeResp = {
|
||||
default() { return { type: "describe", result: protobuf_decode_js_1.DescribeResult.default() }; },
|
||||
1(r, msg) { msg.result = r.message(protobuf_decode_js_1.DescribeResult); },
|
||||
};
|
||||
const GetAutocommitResp = {
|
||||
default() { return { type: "get_autocommit", isAutocommit: false }; },
|
||||
1(r, msg) { msg.isAutocommit = r.bool(); },
|
||||
};
|
||||
119
node_modules/@libsql/hrana-client/lib-cjs/ws/protobuf_encode.js
generated
vendored
Normal file
119
node_modules/@libsql/hrana-client/lib-cjs/ws/protobuf_encode.js
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ClientMsg = void 0;
|
||||
const protobuf_encode_js_1 = require("../shared/protobuf_encode.js");
|
||||
const util_js_1 = require("../util.js");
|
||||
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 (0, util_js_1.impossible)(msg, "Impossible type of ClientMsg");
|
||||
}
|
||||
}
|
||||
exports.ClientMsg = 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 (0, util_js_1.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, protobuf_encode_js_1.Stmt);
|
||||
}
|
||||
function BatchReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
w.message(2, msg.batch, protobuf_encode_js_1.Batch);
|
||||
}
|
||||
function OpenCursorReq(w, msg) {
|
||||
w.int32(1, msg.streamId);
|
||||
w.int32(2, msg.cursorId);
|
||||
w.message(3, msg.batch, protobuf_encode_js_1.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);
|
||||
}
|
||||
215
node_modules/@libsql/hrana-client/lib-cjs/ws/stream.js
generated
vendored
Normal file
215
node_modules/@libsql/hrana-client/lib-cjs/ws/stream.js
generated
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WsStream = void 0;
|
||||
const errors_js_1 = require("../errors.js");
|
||||
const queue_js_1 = require("../queue.js");
|
||||
const stream_js_1 = require("../stream.js");
|
||||
const cursor_js_1 = require("./cursor.js");
|
||||
class WsStream extends stream_js_1.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_js_1.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 errors_js_1.InternalError("Cursor not associated with the stream attempted to execute a request");
|
||||
}
|
||||
return new Promise((responseCallback, errorCallback) => {
|
||||
if (this.#closed !== undefined) {
|
||||
errorCallback(new errors_js_1.ClosedError("Stream is closed", this.#closed));
|
||||
}
|
||||
else {
|
||||
this.#client._sendRequest(request, { responseCallback, errorCallback });
|
||||
}
|
||||
});
|
||||
}
|
||||
/** @private */
|
||||
_cursorClosed(cursor) {
|
||||
if (cursor !== this.#cursor) {
|
||||
throw new errors_js_1.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 errors_js_1.ClosedError("Stream is closed", this.#closed));
|
||||
}
|
||||
else if (this.#closing) {
|
||||
entry.errorCallback(new errors_js_1.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 errors_js_1.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 cursor_js_1.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 errors_js_1.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;
|
||||
}
|
||||
}
|
||||
exports.WsStream = WsStream;
|
||||
77
node_modules/@libsql/hrana-client/lib-esm/batch.d.ts
generated
vendored
Normal file
77
node_modules/@libsql/hrana-client/lib-esm/batch.d.ts
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import type { RowsResult, RowResult, ValueResult, StmtResult } from "./result.js";
|
||||
import type * as proto from "./shared/proto.js";
|
||||
import type { InStmt } from "./stmt.js";
|
||||
import { Stream } from "./stream.js";
|
||||
/** A builder for creating a batch and executing it on the server. */
|
||||
export declare class Batch {
|
||||
#private;
|
||||
/** @private */
|
||||
_stream: Stream;
|
||||
/** @private */
|
||||
_steps: Array<BatchStepState>;
|
||||
/** @private */
|
||||
constructor(stream: Stream, useCursor: boolean);
|
||||
/** Return a builder for adding a step to the batch. */
|
||||
step(): BatchStep;
|
||||
/** Execute the batch. */
|
||||
execute(): Promise<void>;
|
||||
}
|
||||
interface BatchStepState {
|
||||
proto: proto.BatchStep;
|
||||
callback(stepResult: proto.StmtResult | undefined, stepError: proto.Error | undefined): void;
|
||||
}
|
||||
/** A builder for adding a step to the batch. */
|
||||
export declare class BatchStep {
|
||||
#private;
|
||||
/** @private */
|
||||
_batch: Batch;
|
||||
/** @private */
|
||||
_index: number | undefined;
|
||||
/** @private */
|
||||
constructor(batch: Batch);
|
||||
/** Add the condition that needs to be satisfied to execute the statement. If you use this method multiple
|
||||
* times, we join the conditions with a logical AND. */
|
||||
condition(cond: BatchCond): this;
|
||||
/** Add a statement that returns rows. */
|
||||
query(stmt: InStmt): Promise<RowsResult | undefined>;
|
||||
/** Add a statement that returns at most a single row. */
|
||||
queryRow(stmt: InStmt): Promise<RowResult | undefined>;
|
||||
/** Add a statement that returns at most a single value. */
|
||||
queryValue(stmt: InStmt): Promise<ValueResult | undefined>;
|
||||
/** Add a statement without returning rows. */
|
||||
run(stmt: InStmt): Promise<StmtResult | undefined>;
|
||||
}
|
||||
export declare class BatchCond {
|
||||
/** @private */
|
||||
_batch: Batch;
|
||||
/** @private */
|
||||
_proto: proto.BatchCond;
|
||||
/** @private */
|
||||
constructor(batch: Batch, proto: proto.BatchCond);
|
||||
/** Create a condition that evaluates to true when the given step executes successfully.
|
||||
*
|
||||
* If the given step fails error or is skipped because its condition evaluated to false, this
|
||||
* condition evaluates to false.
|
||||
*/
|
||||
static ok(step: BatchStep): BatchCond;
|
||||
/** Create a condition that evaluates to true when the given step fails.
|
||||
*
|
||||
* If the given step succeeds or is skipped because its condition evaluated to false, this condition
|
||||
* evaluates to false.
|
||||
*/
|
||||
static error(step: BatchStep): BatchCond;
|
||||
/** Create a condition that is a logical negation of another condition.
|
||||
*/
|
||||
static not(cond: BatchCond): BatchCond;
|
||||
/** Create a condition that is a logical AND of other conditions.
|
||||
*/
|
||||
static and(batch: Batch, conds: Array<BatchCond>): BatchCond;
|
||||
/** Create a condition that is a logical OR of other conditions.
|
||||
*/
|
||||
static or(batch: Batch, conds: Array<BatchCond>): BatchCond;
|
||||
/** Create a condition that evaluates to true when the SQL connection is in autocommit mode (not inside an
|
||||
* explicit transaction). This requires protocol version 3 or higher.
|
||||
*/
|
||||
static isAutocommit(batch: Batch): BatchCond;
|
||||
}
|
||||
export {};
|
||||
271
node_modules/@libsql/hrana-client/lib-esm/batch.js
generated
vendored
Normal file
271
node_modules/@libsql/hrana-client/lib-esm/batch.js
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
import { ProtoError, MisuseError } from "./errors.js";
|
||||
import { stmtResultFromProto, rowsResultFromProto, rowResultFromProto, valueResultFromProto, errorFromProto, } from "./result.js";
|
||||
import { stmtToProto } from "./stmt.js";
|
||||
import { impossible } from "./util.js";
|
||||
/** A builder for creating a batch and executing it on the server. */
|
||||
export class Batch {
|
||||
/** @private */
|
||||
_stream;
|
||||
#useCursor;
|
||||
/** @private */
|
||||
_steps;
|
||||
#executed;
|
||||
/** @private */
|
||||
constructor(stream, useCursor) {
|
||||
this._stream = stream;
|
||||
this.#useCursor = useCursor;
|
||||
this._steps = [];
|
||||
this.#executed = false;
|
||||
}
|
||||
/** Return a builder for adding a step to the batch. */
|
||||
step() {
|
||||
return new BatchStep(this);
|
||||
}
|
||||
/** Execute the batch. */
|
||||
execute() {
|
||||
if (this.#executed) {
|
||||
throw new MisuseError("This batch has already been executed");
|
||||
}
|
||||
this.#executed = true;
|
||||
const batch = {
|
||||
steps: this._steps.map((step) => step.proto),
|
||||
};
|
||||
if (this.#useCursor) {
|
||||
return executeCursor(this._stream, this._steps, batch);
|
||||
}
|
||||
else {
|
||||
return executeRegular(this._stream, this._steps, batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
function executeRegular(stream, steps, batch) {
|
||||
return stream._batch(batch).then((result) => {
|
||||
for (let step = 0; step < steps.length; ++step) {
|
||||
const stepResult = result.stepResults.get(step);
|
||||
const stepError = result.stepErrors.get(step);
|
||||
steps[step].callback(stepResult, stepError);
|
||||
}
|
||||
});
|
||||
}
|
||||
async function executeCursor(stream, steps, batch) {
|
||||
const cursor = await stream._openCursor(batch);
|
||||
try {
|
||||
let nextStep = 0;
|
||||
let beginEntry = undefined;
|
||||
let rows = [];
|
||||
for (;;) {
|
||||
const entry = await cursor.next();
|
||||
if (entry === undefined) {
|
||||
break;
|
||||
}
|
||||
if (entry.type === "step_begin") {
|
||||
if (entry.step < nextStep || entry.step >= steps.length) {
|
||||
throw new ProtoError("Server produced StepBeginEntry for unexpected step");
|
||||
}
|
||||
else if (beginEntry !== undefined) {
|
||||
throw new ProtoError("Server produced StepBeginEntry before terminating previous step");
|
||||
}
|
||||
for (let step = nextStep; step < entry.step; ++step) {
|
||||
steps[step].callback(undefined, undefined);
|
||||
}
|
||||
nextStep = entry.step + 1;
|
||||
beginEntry = entry;
|
||||
rows = [];
|
||||
}
|
||||
else if (entry.type === "step_end") {
|
||||
if (beginEntry === undefined) {
|
||||
throw new ProtoError("Server produced StepEndEntry but no step is active");
|
||||
}
|
||||
const stmtResult = {
|
||||
cols: beginEntry.cols,
|
||||
rows,
|
||||
affectedRowCount: entry.affectedRowCount,
|
||||
lastInsertRowid: entry.lastInsertRowid,
|
||||
};
|
||||
steps[beginEntry.step].callback(stmtResult, undefined);
|
||||
beginEntry = undefined;
|
||||
rows = [];
|
||||
}
|
||||
else if (entry.type === "step_error") {
|
||||
if (beginEntry === undefined) {
|
||||
if (entry.step >= steps.length) {
|
||||
throw new ProtoError("Server produced StepErrorEntry for unexpected step");
|
||||
}
|
||||
for (let step = nextStep; step < entry.step; ++step) {
|
||||
steps[step].callback(undefined, undefined);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (entry.step !== beginEntry.step) {
|
||||
throw new ProtoError("Server produced StepErrorEntry for unexpected step");
|
||||
}
|
||||
beginEntry = undefined;
|
||||
rows = [];
|
||||
}
|
||||
steps[entry.step].callback(undefined, entry.error);
|
||||
nextStep = entry.step + 1;
|
||||
}
|
||||
else if (entry.type === "row") {
|
||||
if (beginEntry === undefined) {
|
||||
throw new ProtoError("Server produced RowEntry but no step is active");
|
||||
}
|
||||
rows.push(entry.row);
|
||||
}
|
||||
else if (entry.type === "error") {
|
||||
throw errorFromProto(entry.error);
|
||||
}
|
||||
else if (entry.type === "none") {
|
||||
throw new ProtoError("Server produced unrecognized CursorEntry");
|
||||
}
|
||||
else {
|
||||
throw impossible(entry, "Impossible CursorEntry");
|
||||
}
|
||||
}
|
||||
if (beginEntry !== undefined) {
|
||||
throw new ProtoError("Server closed Cursor before terminating active step");
|
||||
}
|
||||
for (let step = nextStep; step < steps.length; ++step) {
|
||||
steps[step].callback(undefined, undefined);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
/** A builder for adding a step to the batch. */
|
||||
export class BatchStep {
|
||||
/** @private */
|
||||
_batch;
|
||||
#conds;
|
||||
/** @private */
|
||||
_index;
|
||||
/** @private */
|
||||
constructor(batch) {
|
||||
this._batch = batch;
|
||||
this.#conds = [];
|
||||
this._index = undefined;
|
||||
}
|
||||
/** Add the condition that needs to be satisfied to execute the statement. If you use this method multiple
|
||||
* times, we join the conditions with a logical AND. */
|
||||
condition(cond) {
|
||||
this.#conds.push(cond._proto);
|
||||
return this;
|
||||
}
|
||||
/** Add a statement that returns rows. */
|
||||
query(stmt) {
|
||||
return this.#add(stmt, true, rowsResultFromProto);
|
||||
}
|
||||
/** Add a statement that returns at most a single row. */
|
||||
queryRow(stmt) {
|
||||
return this.#add(stmt, true, rowResultFromProto);
|
||||
}
|
||||
/** Add a statement that returns at most a single value. */
|
||||
queryValue(stmt) {
|
||||
return this.#add(stmt, true, valueResultFromProto);
|
||||
}
|
||||
/** Add a statement without returning rows. */
|
||||
run(stmt) {
|
||||
return this.#add(stmt, false, stmtResultFromProto);
|
||||
}
|
||||
#add(inStmt, wantRows, fromProto) {
|
||||
if (this._index !== undefined) {
|
||||
throw new MisuseError("This BatchStep has already been added to the batch");
|
||||
}
|
||||
const stmt = stmtToProto(this._batch._stream._sqlOwner(), inStmt, wantRows);
|
||||
let condition;
|
||||
if (this.#conds.length === 0) {
|
||||
condition = undefined;
|
||||
}
|
||||
else if (this.#conds.length === 1) {
|
||||
condition = this.#conds[0];
|
||||
}
|
||||
else {
|
||||
condition = { type: "and", conds: this.#conds.slice() };
|
||||
}
|
||||
const proto = { stmt, condition };
|
||||
return new Promise((outputCallback, errorCallback) => {
|
||||
const callback = (stepResult, stepError) => {
|
||||
if (stepResult !== undefined && stepError !== undefined) {
|
||||
errorCallback(new ProtoError("Server returned both result and error"));
|
||||
}
|
||||
else if (stepError !== undefined) {
|
||||
errorCallback(errorFromProto(stepError));
|
||||
}
|
||||
else if (stepResult !== undefined) {
|
||||
outputCallback(fromProto(stepResult, this._batch._stream.intMode));
|
||||
}
|
||||
else {
|
||||
outputCallback(undefined);
|
||||
}
|
||||
};
|
||||
this._index = this._batch._steps.length;
|
||||
this._batch._steps.push({ proto, callback });
|
||||
});
|
||||
}
|
||||
}
|
||||
export class BatchCond {
|
||||
/** @private */
|
||||
_batch;
|
||||
/** @private */
|
||||
_proto;
|
||||
/** @private */
|
||||
constructor(batch, proto) {
|
||||
this._batch = batch;
|
||||
this._proto = proto;
|
||||
}
|
||||
/** Create a condition that evaluates to true when the given step executes successfully.
|
||||
*
|
||||
* If the given step fails error or is skipped because its condition evaluated to false, this
|
||||
* condition evaluates to false.
|
||||
*/
|
||||
static ok(step) {
|
||||
return new BatchCond(step._batch, { type: "ok", step: stepIndex(step) });
|
||||
}
|
||||
/** Create a condition that evaluates to true when the given step fails.
|
||||
*
|
||||
* If the given step succeeds or is skipped because its condition evaluated to false, this condition
|
||||
* evaluates to false.
|
||||
*/
|
||||
static error(step) {
|
||||
return new BatchCond(step._batch, { type: "error", step: stepIndex(step) });
|
||||
}
|
||||
/** Create a condition that is a logical negation of another condition.
|
||||
*/
|
||||
static not(cond) {
|
||||
return new BatchCond(cond._batch, { type: "not", cond: cond._proto });
|
||||
}
|
||||
/** Create a condition that is a logical AND of other conditions.
|
||||
*/
|
||||
static and(batch, conds) {
|
||||
for (const cond of conds) {
|
||||
checkCondBatch(batch, cond);
|
||||
}
|
||||
return new BatchCond(batch, { type: "and", conds: conds.map(e => e._proto) });
|
||||
}
|
||||
/** Create a condition that is a logical OR of other conditions.
|
||||
*/
|
||||
static or(batch, conds) {
|
||||
for (const cond of conds) {
|
||||
checkCondBatch(batch, cond);
|
||||
}
|
||||
return new BatchCond(batch, { type: "or", conds: conds.map(e => e._proto) });
|
||||
}
|
||||
/** Create a condition that evaluates to true when the SQL connection is in autocommit mode (not inside an
|
||||
* explicit transaction). This requires protocol version 3 or higher.
|
||||
*/
|
||||
static isAutocommit(batch) {
|
||||
batch._stream.client()._ensureVersion(3, "BatchCond.isAutocommit()");
|
||||
return new BatchCond(batch, { type: "is_autocommit" });
|
||||
}
|
||||
}
|
||||
function stepIndex(step) {
|
||||
if (step._index === undefined) {
|
||||
throw new MisuseError("Cannot add a condition referencing a step that has not been added to the batch");
|
||||
}
|
||||
return step._index;
|
||||
}
|
||||
function checkCondBatch(expectedBatch, cond) {
|
||||
if (cond._batch !== expectedBatch) {
|
||||
throw new MisuseError("Cannot mix BatchCond objects for different Batch objects");
|
||||
}
|
||||
}
|
||||
8
node_modules/@libsql/hrana-client/lib-esm/byte_queue.d.ts
generated
vendored
Normal file
8
node_modules/@libsql/hrana-client/lib-esm/byte_queue.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export declare class ByteQueue {
|
||||
#private;
|
||||
constructor(initialCap: number);
|
||||
get length(): number;
|
||||
data(): Uint8Array;
|
||||
push(chunk: Uint8Array): void;
|
||||
shift(length: number): void;
|
||||
}
|
||||
45
node_modules/@libsql/hrana-client/lib-esm/byte_queue.js
generated
vendored
Normal file
45
node_modules/@libsql/hrana-client/lib-esm/byte_queue.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
export class ByteQueue {
|
||||
#array;
|
||||
#shiftPos;
|
||||
#pushPos;
|
||||
constructor(initialCap) {
|
||||
this.#array = new Uint8Array(new ArrayBuffer(initialCap));
|
||||
this.#shiftPos = 0;
|
||||
this.#pushPos = 0;
|
||||
}
|
||||
get length() {
|
||||
return this.#pushPos - this.#shiftPos;
|
||||
}
|
||||
data() {
|
||||
return this.#array.slice(this.#shiftPos, this.#pushPos);
|
||||
}
|
||||
push(chunk) {
|
||||
this.#ensurePush(chunk.byteLength);
|
||||
this.#array.set(chunk, this.#pushPos);
|
||||
this.#pushPos += chunk.byteLength;
|
||||
}
|
||||
#ensurePush(pushLength) {
|
||||
if (this.#pushPos + pushLength <= this.#array.byteLength) {
|
||||
return;
|
||||
}
|
||||
const filledLength = this.#pushPos - this.#shiftPos;
|
||||
if (filledLength + pushLength <= this.#array.byteLength &&
|
||||
2 * this.#pushPos >= this.#array.byteLength) {
|
||||
this.#array.copyWithin(0, this.#shiftPos, this.#pushPos);
|
||||
}
|
||||
else {
|
||||
let newCap = this.#array.byteLength;
|
||||
do {
|
||||
newCap *= 2;
|
||||
} while (filledLength + pushLength > newCap);
|
||||
const newArray = new Uint8Array(new ArrayBuffer(newCap));
|
||||
newArray.set(this.#array.slice(this.#shiftPos, this.#pushPos), 0);
|
||||
this.#array = newArray;
|
||||
}
|
||||
this.#pushPos = filledLength;
|
||||
this.#shiftPos = 0;
|
||||
}
|
||||
shift(length) {
|
||||
this.#shiftPos += length;
|
||||
}
|
||||
}
|
||||
28
node_modules/@libsql/hrana-client/lib-esm/client.d.ts
generated
vendored
Normal file
28
node_modules/@libsql/hrana-client/lib-esm/client.d.ts
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { Stream } from "./stream.js";
|
||||
import type { IntMode } from "./value.js";
|
||||
export type ProtocolVersion = 1 | 2 | 3;
|
||||
export type ProtocolEncoding = "json" | "protobuf";
|
||||
/** A client for the Hrana protocol (a "database connection pool"). */
|
||||
export declare abstract class Client {
|
||||
/** @private */
|
||||
constructor();
|
||||
/** Get the protocol version negotiated with the server. */
|
||||
abstract getVersion(): Promise<ProtocolVersion>;
|
||||
/** @private */
|
||||
abstract _ensureVersion(minVersion: ProtocolVersion, feature: string): void;
|
||||
/** Open a {@link Stream}, a stream for executing SQL statements. */
|
||||
abstract openStream(): Stream;
|
||||
/** Immediately close the client.
|
||||
*
|
||||
* This closes the client immediately, aborting any pending operations.
|
||||
*/
|
||||
abstract close(): void;
|
||||
/** True if the client is closed. */
|
||||
abstract get closed(): boolean;
|
||||
/** Representation of integers returned from the database. See {@link IntMode}.
|
||||
*
|
||||
* This value is inherited by {@link Stream} objects created with {@link openStream}, but you can
|
||||
* override the integer mode for every stream by setting {@link Stream.intMode} on the stream.
|
||||
*/
|
||||
intMode: IntMode;
|
||||
}
|
||||
13
node_modules/@libsql/hrana-client/lib-esm/client.js
generated
vendored
Normal file
13
node_modules/@libsql/hrana-client/lib-esm/client.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/** A client for the Hrana protocol (a "database connection pool"). */
|
||||
export class Client {
|
||||
/** @private */
|
||||
constructor() {
|
||||
this.intMode = "number";
|
||||
}
|
||||
/** Representation of integers returned from the database. See {@link IntMode}.
|
||||
*
|
||||
* This value is inherited by {@link Stream} objects created with {@link openStream}, but you can
|
||||
* override the integer mode for every stream by setting {@link Stream.intMode} on the stream.
|
||||
*/
|
||||
intMode;
|
||||
}
|
||||
9
node_modules/@libsql/hrana-client/lib-esm/cursor.d.ts
generated
vendored
Normal file
9
node_modules/@libsql/hrana-client/lib-esm/cursor.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import type * as proto from "./shared/proto.js";
|
||||
export declare abstract class Cursor {
|
||||
/** Fetch the next entry from the cursor. */
|
||||
abstract next(): Promise<proto.CursorEntry | undefined>;
|
||||
/** Close the cursor. */
|
||||
abstract close(): void;
|
||||
/** True if the cursor is closed. */
|
||||
abstract get closed(): boolean;
|
||||
}
|
||||
2
node_modules/@libsql/hrana-client/lib-esm/cursor.js
generated
vendored
Normal file
2
node_modules/@libsql/hrana-client/lib-esm/cursor.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export class Cursor {
|
||||
}
|
||||
12
node_modules/@libsql/hrana-client/lib-esm/describe.d.ts
generated
vendored
Normal file
12
node_modules/@libsql/hrana-client/lib-esm/describe.d.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import type * as proto from "./shared/proto.js";
|
||||
export interface DescribeResult {
|
||||
paramNames: Array<string | undefined>;
|
||||
columns: Array<DescribeColumn>;
|
||||
isExplain: boolean;
|
||||
isReadonly: boolean;
|
||||
}
|
||||
export interface DescribeColumn {
|
||||
name: string;
|
||||
decltype: string | undefined;
|
||||
}
|
||||
export declare function describeResultFromProto(result: proto.DescribeResult): DescribeResult;
|
||||
8
node_modules/@libsql/hrana-client/lib-esm/describe.js
generated
vendored
Normal file
8
node_modules/@libsql/hrana-client/lib-esm/describe.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export function describeResultFromProto(result) {
|
||||
return {
|
||||
paramNames: result.params.map((p) => p.name),
|
||||
columns: result.cols,
|
||||
isExplain: result.isExplain,
|
||||
isReadonly: result.isReadonly,
|
||||
};
|
||||
}
|
||||
4
node_modules/@libsql/hrana-client/lib-esm/encoding/index.d.ts
generated
vendored
Normal file
4
node_modules/@libsql/hrana-client/lib-esm/encoding/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export { readJsonObject } from "./json/decode.js";
|
||||
export { writeJsonObject } from "./json/encode.js";
|
||||
export { readProtobufMessage } from "./protobuf/decode.js";
|
||||
export { writeProtobufMessage } from "./protobuf/encode.js";
|
||||
4
node_modules/@libsql/hrana-client/lib-esm/encoding/index.js
generated
vendored
Normal file
4
node_modules/@libsql/hrana-client/lib-esm/encoding/index.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export { readJsonObject } from "./json/decode.js";
|
||||
export { writeJsonObject } from "./json/encode.js";
|
||||
export { readProtobufMessage } from "./protobuf/decode.js";
|
||||
export { writeProtobufMessage } from "./protobuf/encode.js";
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user