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

@sqlitecloud/drivers

Package Overview
Dependencies
Maintainers
2
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sqlitecloud/drivers - npm Package Compare versions

Comparing version 0.0.50 to 0.0.56

24

lib/drivers/connection-tls.d.ts
/**
* connection-tls.ts - handles low level communication with sqlitecloud server via tls socket and binary protocol
* connection-tls.ts - connection via tls socket and sqlitecloud protocol
*/
import { SQLiteCloudConfig, ErrorCallback, ResultsCallback } from './types';
import { type SQLiteCloudConfig, type ErrorCallback, type ResultsCallback } from './types';
import { SQLiteCloudConnection } from './connection';
/**
* Implementation of SQLiteCloudConnection that connects directly to the database via tls socket and raw, binary protocol.
* Connects with plain socket with no encryption is the ?insecure=1 parameter is specified.
* SQLiteCloud low-level connection, will do messaging, handle socket, authentication, etc.
* A connection socket is established when the connection is created and closed when the connection is closed.
* All operations are serialized by waiting for any pending operations to complete. Once a connection is closed,
* it cannot be reopened and you must create a new connection.
* Implementation of SQLiteCloudConnection that connects to the database using specific Bun APIs
* that connect to native sockets or tls sockets and communicates via raw, binary protocol.
*/
export declare class SQLiteCloudTlsConnection extends SQLiteCloudConnection {
/** Currently opened tls socket used to communicated with SQLiteCloud server */
/** Currently opened bun socket used to communicated with SQLiteCloud server */
private socket?;

@@ -22,5 +18,13 @@ /** True if connection is open */

transportCommands(commands: string, callback?: ResultsCallback): this;
/** Disconnect from server, release connection. */
private buffer;
private startedOn;
private executingCommands?;
private processCallback?;
/** Handles data received in response to an outbound command sent by processCommands */
private processCommandsData;
/** Completes a transaction initiated by processCommands */
private processCommandsFinish;
/** Disconnect immediately, release connection, no events. */
close(): this;
}
export default SQLiteCloudTlsConnection;
"use strict";
/**
* connection-tls.ts - handles low level communication with sqlitecloud server via tls socket and binary protocol
* connection-tls.ts - connection via tls socket and sqlitecloud protocol
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
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;
};

@@ -12,16 +32,19 @@ Object.defineProperty(exports, "__esModule", { value: true });

const connection_1 = require("./connection");
const utilities_1 = require("./utilities");
const protocol_1 = require("./protocol");
const utilities_1 = require("./utilities");
const protocol_2 = require("./protocol");
const net_1 = __importDefault(require("net"));
const tls_1 = __importDefault(require("tls"));
const tls = __importStar(require("tls"));
/**
* Implementation of SQLiteCloudConnection that connects directly to the database via tls socket and raw, binary protocol.
* Connects with plain socket with no encryption is the ?insecure=1 parameter is specified.
* SQLiteCloud low-level connection, will do messaging, handle socket, authentication, etc.
* A connection socket is established when the connection is created and closed when the connection is closed.
* All operations are serialized by waiting for any pending operations to complete. Once a connection is closed,
* it cannot be reopened and you must create a new connection.
* Implementation of SQLiteCloudConnection that connects to the database using specific Bun APIs
* that connect to native sockets or tls sockets and communicates via raw, binary protocol.
*/
class SQLiteCloudTlsConnection extends connection_1.SQLiteCloudConnection {
constructor() {
super(...arguments);
// processCommands sets up empty buffers, results callback then send the command to the server via socket.write
// onData is called when data is received, it will process the data until all data is retrieved for a response
// when response is complete or there's an error, finish is called to call the results callback set by processCommands...
// buffer to accumulate incoming data until an whole command is received and can be parsed
this.buffer = Buffer.alloc(0);
this.startedOn = new Date();
}
/** True if connection is open */

@@ -32,83 +55,49 @@ get connected() {

/* Opens a connection with the server and sends the initialization commands. Will throw in case of errors. */
/* eslint-disable @typescript-eslint/no-unused-vars */
connectTransport(config, callback) {
// connection established while we were waiting in line?
console.assert(!this.connected, 'Connection already established');
// clear all listeners and call done in the operations queue
const finish = error => {
if (this.socket) {
this.socket.removeAllListeners('data');
this.socket.removeAllListeners('error');
this.socket.removeAllListeners('close');
if (error) {
this.close();
}
}
callback === null || callback === void 0 ? void 0 : callback.call(this, error);
};
console.assert(!this.connected, 'SQLiteCloudTlsConnection.connect - connection already established');
if (this.config.verbose) {
console.debug(`-> connecting ${config === null || config === void 0 ? void 0 : config.host}:${config === null || config === void 0 ? void 0 : config.port}`);
}
this.config = config;
const initializationCommands = (0, utilities_1.getInitializationCommands)(config);
if (config.insecure) {
// connect to plain socket, without encryption, only if insecure parameter specified
// this option is mainly for testing purposes and is not available on production nodes
// which would need to connect using tls and proper certificates as per code below
const connectionOptions = {
host: config.host,
port: config.port
};
this.socket = net_1.default.connect(connectionOptions, () => {
console.warn(`TlsConnection.connectTransport - connected to ${config.host}:${config.port} using insecure protocol`);
// send initialization commands
console.assert(this.socket, 'Connection already closed');
this.transportCommands(initializationCommands, error => {
if (error && this.socket) {
this.close();
}
if (callback) {
callback === null || callback === void 0 ? void 0 : callback.call(this, error);
callback = undefined;
}
finish(error);
});
});
}
else {
// connect to tls socket, initialize connection, setup event handlers
this.socket = tls_1.default.connect(this.config.port, this.config.host, this.config.tlsOptions, () => {
const tlsSocket = this.socket;
if (!(tlsSocket === null || tlsSocket === void 0 ? void 0 : tlsSocket.authorized)) {
const anonimizedError = (0, utilities_1.anonimizeError)(tlsSocket.authorizationError);
console.error('Connection was not authorized', anonimizedError);
this.close();
finish(new types_1.SQLiteCloudError('Connection was not authorized', { cause: anonimizedError }));
// connect to plain socket, without encryption, only if insecure parameter specified
// this option is mainly for testing purposes and is not available on production nodes
// which would need to connect using tls and proper certificates as per code below
const connectionOptions = {
host: config.host,
port: config.port,
rejectUnauthorized: false,
// Server name for the SNI (Server Name Indication) TLS extension.
// https://r2.nodejs.org/docs/v6.11.4/api/tls.html#tls_class_tls_tlssocket
servername: config.host
};
this.socket = tls.connect(connectionOptions, () => {
var _a;
if (this.config.verbose) {
console.debug(`SQLiteCloudTlsConnection - connected to ${this.config.host}, authorized: ${(_a = this.socket) === null || _a === void 0 ? void 0 : _a.authorized}`);
}
this.transportCommands(initializationCommands, error => {
if (this.config.verbose) {
console.debug(`SQLiteCloudTlsConnection - initialized connection`);
}
else {
// the connection was closed before it was even opened,
// eg. client closed the connection before the server accepted it
if (this.socket === null) {
finish(new types_1.SQLiteCloudError('Connection was closed before it was done opening'));
return;
}
// send initialization commands
console.assert(this.socket, 'Connection already closed');
this.transportCommands(initializationCommands, error => {
if (error && this.socket) {
this.close();
}
if (callback) {
callback === null || callback === void 0 ? void 0 : callback.call(this, error);
callback = undefined;
}
finish(error);
});
}
callback === null || callback === void 0 ? void 0 : callback.call(this, error);
});
}
});
this.socket.on('data', data => {
this.processCommandsData(data);
});
this.socket.on('error', error => {
this.close();
this.processCommandsFinish(new types_1.SQLiteCloudError('Connection error', { errorCode: 'ERR_CONNECTION_ERROR', cause: error }));
});
this.socket.on('end', () => {
this.close();
if (this.processCallback)
this.processCommandsFinish(new types_1.SQLiteCloudError('Server ended the connection', { errorCode: 'ERR_CONNECTION_ENDED' }));
});
this.socket.on('close', () => {
this.socket = null;
finish(new types_1.SQLiteCloudError('Connection was closed'));
this.close();
this.processCommandsFinish(new types_1.SQLiteCloudError('Connection closed', { errorCode: 'ERR_CONNECTION_CLOSED' }));
});
this.socket.once('error', (error) => {
console.error('Connection error', error);
finish(new types_1.SQLiteCloudError('Connection error', { cause: error }));
});
return this;

@@ -118,3 +107,3 @@ }

transportCommands(commands, callback) {
var _a, _b, _c;
var _a, _b, _c, _d, _e;
// connection needs to be established?

@@ -125,112 +114,107 @@ if (!this.socket) {

}
// reset buffer and rowset chunks, define response callback
this.buffer = Buffer.alloc(0);
this.startedOn = new Date();
this.processCallback = callback;
this.executingCommands = commands;
// compose commands following SCPC protocol
commands = (0, protocol_1.formatCommand)(commands);
let buffer = Buffer.alloc(0);
const rowsetChunks = [];
// const startedOn = new Date()
// define what to do if an answer does not arrive within the set timeout
let socketTimeout;
// clear all listeners and call done in the operations queue
const finish = (error, result) => {
clearTimeout(socketTimeout);
if (this.socket) {
this.socket.removeAllListeners('data');
this.socket.removeAllListeners('error');
this.socket.removeAllListeners('close');
const formattedCommands = (0, protocol_1.formatCommand)(commands);
if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.verbose) {
console.debug(`-> ${formattedCommands}`);
}
const timeoutMs = (_c = (_b = this.config) === null || _b === void 0 ? void 0 : _b.timeout) !== null && _c !== void 0 ? _c : 0;
if (timeoutMs > 0) {
const timeout = setTimeout(() => {
var _a;
callback === null || callback === void 0 ? void 0 : callback.call(this, new types_1.SQLiteCloudError('Connection timeout out', { errorCode: 'ERR_CONNECTION_TIMEOUT' }));
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.destroy();
this.socket = undefined;
}, timeoutMs);
(_d = this.socket) === null || _d === void 0 ? void 0 : _d.write(formattedCommands, 'utf-8', () => {
clearTimeout(timeout); // Clear the timeout on successful write
});
}
else {
(_e = this.socket) === null || _e === void 0 ? void 0 : _e.write(formattedCommands, 'utf-8');
}
return this;
}
/** Handles data received in response to an outbound command sent by processCommands */
processCommandsData(data) {
var _a, _b, _c, _d, _e, _f;
try {
// append data to buffer as it arrives
if (data.length && data.length > 0) {
this.buffer = Buffer.concat([this.buffer, data]);
}
if (callback) {
callback === null || callback === void 0 ? void 0 : callback.call(this, error, result);
callback = undefined;
}
};
// define the Promise that waits for the server response
const readData = (data) => {
var _a, _b;
try {
// on first ondata event, dataType is read from data, on subsequent ondata event, is read from buffer that is the concatanations of data received on each ondata event
let dataType = buffer.length === 0 ? data.subarray(0, 1).toString() : buffer.subarray(0, 1).toString('utf8');
buffer = Buffer.concat([buffer, data]);
const commandLength = (0, protocol_1.hasCommandLength)(dataType);
if (commandLength) {
const commandLength = (0, protocol_1.parseCommandLength)(buffer);
const hasReceivedEntireCommand = buffer.length - buffer.indexOf(' ') - 1 >= commandLength ? true : false;
if (hasReceivedEntireCommand) {
if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.verbose) {
let bufferString = buffer.toString('utf8');
if (bufferString.length > 1000) {
bufferString = bufferString.substring(0, 100) + '...' + bufferString.substring(bufferString.length - 40);
}
// const elapsedMs = new Date().getTime() - startedOn.getTime()
// console.debug(`Receive: ${bufferString} - ${elapsedMs}ms`)
let dataType = (_a = this.buffer) === null || _a === void 0 ? void 0 : _a.subarray(0, 1).toString();
if ((0, protocol_1.hasCommandLength)(dataType)) {
const commandLength = (0, protocol_1.parseCommandLength)(this.buffer);
const hasReceivedEntireCommand = this.buffer.length - this.buffer.indexOf(' ') - 1 >= commandLength ? true : false;
if (hasReceivedEntireCommand) {
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.verbose) {
let bufferString = this.buffer.toString('utf8');
if (bufferString.length > 1000) {
bufferString = bufferString.substring(0, 100) + '...' + bufferString.substring(bufferString.length - 40);
}
// need to decompress this buffer before decoding?
if (dataType === protocol_1.CMD_COMPRESSED) {
;
({ buffer, dataType } = (0, protocol_1.decompressBuffer)(buffer));
const elapsedMs = new Date().getTime() - this.startedOn.getTime();
console.debug(`<- ${bufferString} (${elapsedMs}ms)`);
}
// need to decompress this buffer before decoding?
if (dataType === protocol_1.CMD_COMPRESSED) {
;
({ buffer: this.buffer, dataType } = (0, protocol_1.decompressBuffer)(this.buffer));
}
if (dataType !== protocol_1.CMD_ROWSET_CHUNK) {
const { data } = (0, protocol_1.popData)(this.buffer);
(_c = this.processCommandsFinish) === null || _c === void 0 ? void 0 : _c.call(this, null, data);
}
else {
// check if rowset received the ending chunk in which case it can be unpacked
if ((0, protocol_1.bufferEndsWith)(this.buffer, protocol_1.ROWSET_CHUNKS_END)) {
const parsedData = (0, protocol_1.parseRowsetChunks)([this.buffer]);
(_d = this.processCommandsFinish) === null || _d === void 0 ? void 0 : _d.call(this, null, parsedData);
}
if (dataType !== protocol_1.CMD_ROWSET_CHUNK) {
(_b = this.socket) === null || _b === void 0 ? void 0 : _b.off('data', readData);
const { data } = (0, protocol_1.popData)(buffer);
finish(null, data);
}
else {
// check if rowset received the ending chunk
if ((0, protocol_1.bufferEndsWith)(buffer, protocol_1.ROWSET_CHUNKS_END)) {
rowsetChunks.push(buffer);
const parsedData = (0, protocol_2.parseRowsetChunks)(rowsetChunks);
finish === null || finish === void 0 ? void 0 : finish.call(this, null, parsedData);
}
else {
// no ending string? ask server for another chunk
rowsetChunks.push(buffer);
buffer = Buffer.alloc(0);
}
}
}
}
else {
// command with no explicit len so make sure that the final character is a space
const lastChar = buffer.subarray(buffer.length - 1, buffer.length).toString('utf8');
if (lastChar == ' ') {
const { data } = (0, protocol_1.popData)(buffer);
finish(null, data);
}
}
}
catch (error) {
console.assert(error instanceof Error);
if (error instanceof Error) {
finish(error);
else {
// command with no explicit len so make sure that the final character is a space
const lastChar = this.buffer.subarray(this.buffer.length - 1, this.buffer.length).toString('utf8');
if (lastChar == ' ') {
const { data } = (0, protocol_1.popData)(this.buffer);
(_e = this.processCommandsFinish) === null || _e === void 0 ? void 0 : _e.call(this, null, data);
}
}
};
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.once('close', () => {
finish(new types_1.SQLiteCloudError('Connection was closed', { cause: (0, utilities_1.anonimizeCommand)(commands) }));
});
(_b = this.socket) === null || _b === void 0 ? void 0 : _b.write(commands, 'utf8', () => {
var _a, _b;
// @ts-ignore
socketTimeout = setTimeout(() => {
const timeoutError = new types_1.SQLiteCloudError('Request timed out', { cause: (0, utilities_1.anonimizeCommand)(commands) });
// console.debug(`Request timed out, config.timeout is ${this.config?.timeout as number}ms`, timeoutError)
finish(timeoutError);
}, (_a = this.config) === null || _a === void 0 ? void 0 : _a.timeout);
(_b = this.socket) === null || _b === void 0 ? void 0 : _b.on('data', readData);
});
(_c = this.socket) === null || _c === void 0 ? void 0 : _c.once('error', (error) => {
console.error('Socket error', error);
this.close();
finish(new types_1.SQLiteCloudError('Socket error', { cause: (0, utilities_1.anonimizeError)(error) }));
});
return this;
}
catch (error) {
console.assert(error instanceof Error);
if (error instanceof Error) {
(_f = this.processCommandsFinish) === null || _f === void 0 ? void 0 : _f.call(this, error);
}
}
}
/** Disconnect from server, release connection. */
/** Completes a transaction initiated by processCommands */
processCommandsFinish(error, result) {
if (error) {
if (this.processCallback) {
console.error('processCommandsFinish - error', error);
}
else {
console.warn('processCommandsFinish - error with no registered callback', error);
}
}
if (this.processCallback) {
this.processCallback(error, result);
// this.processCallback = undefined
}
}
/** Disconnect immediately, release connection, no events. */
close() {
console.assert(this.socket !== null, 'TlsConnection.close - connection already closed');
this.operations.clear();
if (this.socket) {
this.socket.removeAllListeners();
this.socket.destroy();
this.socket = null;
this.socket = undefined;
}
this.socket = undefined;
this.operations.clear();
return this;

@@ -237,0 +221,0 @@ }

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

const connectionString = this.config.connectionString;
const gatewayUrl = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.gatewayUrl) || `ws://${this.config.host}:4000`;
const gatewayUrl = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.gatewayUrl) || `${this.config.host === 'localhost' ? 'ws' : 'wss'}://${this.config.host}:4000`;
this.socket = (0, socket_io_client_1.io)(gatewayUrl, { auth: { token: connectionString } });

@@ -34,0 +34,0 @@ }

@@ -15,2 +15,4 @@ /**

protected config: SQLiteCloudConfig;
/** Returns the connection's configuration */
getConfig(): SQLiteCloudConfig;
/** Operations are serialized by waiting an any pending promises */

@@ -17,0 +19,0 @@ protected operations: OperationsQueue;

@@ -29,2 +29,6 @@ "use strict";

}
/** Returns the connection's configuration */
getConfig() {
return Object.assign({}, this.config);
}
//

@@ -41,3 +45,5 @@ // internal methods (some are implemented in concrete classes using different transport layers)

}
callback === null || callback === void 0 ? void 0 : callback.call(this, error || null);
if (callback) {
callback.call(this, error || null);
}
done(error);

@@ -67,6 +73,8 @@ });

}
this.transportCommands(commands, (error, result) => {
callback === null || callback === void 0 ? void 0 : callback.call(this, error, result);
done(error);
});
else {
this.transportCommands(commands, (error, result) => {
callback === null || callback === void 0 ? void 0 : callback.call(this, error, result);
done(error);
});
}
});

@@ -73,0 +81,0 @@ return this;

@@ -21,3 +21,3 @@ /**

passwordHashed?: boolean;
/** Host name is required unless connectionString is provided */
/** Host name is required unless connectionString is provided, eg: xxx.sqlitecloud.io */
host?: string;

@@ -51,3 +51,3 @@ /** Port number for tls socket */

useWebsocket?: boolean;
/** Url where we can connect to a SQLite Cloud Gateway that has a socket.io deamon waiting to connect, eg. ws://host:4000 */
/** Url where we can connect to a SQLite Cloud Gateway that has a socket.io deamon waiting to connect, eg. wss://host:4000 */
gatewayUrl?: string;

@@ -54,0 +54,0 @@ /** Optional identifier used for verbose logging */

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

// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
config.connectionString = `sqlitecloud://${config.username}:${config.password}@${config.host}:${config.port}/${config.database}`;
config.connectionString = `sqlitecloud://${encodeURIComponent(config.username)}:${encodeURIComponent(config.password)}@${config.host}:${config.port}/${config.database}`;
}

@@ -198,3 +198,3 @@ return config;

});
const config = Object.assign({ username: url.username, password: url.password, host: url.hostname, port: url.port ? parseInt(url.port) : undefined }, options);
const config = Object.assign({ username: decodeURIComponent(url.username), password: decodeURIComponent(url.password), host: url.hostname, port: url.port ? parseInt(url.port) : undefined }, options);
const database = url.pathname.replace('/', ''); // pathname is database name, remove the leading slash

@@ -201,0 +201,0 @@ if (database) {

export { Database } from './drivers/database';
export { Statement } from './drivers/statement';
export { SQLiteCloudConnection } from './drivers/connection';
export { type SQLiteCloudConfig, type SQLCloudRowsetMetadata, SQLiteCloudError, type ErrorCallback } from './drivers/types';
export { type SQLiteCloudConfig, type SQLCloudRowsetMetadata, SQLiteCloudError, type ResultsCallback, type ErrorCallback } from './drivers/types';
export { SQLiteCloudRowset, SQLiteCloudRow } from './drivers/rowset';
export { escapeSqlParameter, prepareSql, parseConnectionString, validateConfiguration } from './drivers/utilities';
{
"name": "@sqlitecloud/drivers",
"version": "0.0.50",
"version": "0.0.56",
"description": "SQLiteCloud drivers for Typescript/Javascript in edge, web and node clients",

@@ -20,3 +20,3 @@ "main": "./lib/index.js",

"gateway-start": "bun --smol run ./src/gateway/gateway.ts",
"gateway-test": "bun test ./src/gateway/connection-bun.test.ts --watch --coverage",
"gateway-test": "bun test ./src/gateway/connection-bun.test.ts --watch --coverage --timeout 2000",
"gateway-build": "./scripts/gateway-build.sh"

@@ -51,3 +51,2 @@ },

"eventemitter3": "^5.0.1",
"express": "^4.18.2",
"lz4js": "^0.2.0",

@@ -71,2 +70,3 @@ "socket.io": "^4.7.4",

"eslint-plugin-prettier": "^3.4.1",
"express": "^4.18.2",
"jest": "^29.7.0",

@@ -73,0 +73,0 @@ "prettier": "^2.2.1",

@@ -20,3 +20,3 @@ # @sqlitecloud/drivers

let database = new Database('sqlitecloud://user:password@xxx.sqlite.cloud:8860/chinook.db')
let database = new Database('sqlitecloud://user:password@xxx.sqlite.cloud:8860/chinook.sqlite')

@@ -23,0 +23,0 @@ let name = 'Breaking The Rules'

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc