@sqlitecloud/drivers 0.0.56 → 1.0.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/drivers/connection-ws.js +3 -3
- package/lib/drivers/connection.d.ts +11 -1
- package/lib/drivers/connection.js +58 -3
- package/lib/drivers/database.js +3 -3
- package/lib/drivers/types.d.ts +24 -17
- package/lib/drivers/utilities.d.ts +10 -2
- package/lib/drivers/utilities.js +87 -28
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -2
- package/lib/sqlitecloud.drivers.dev.js +6 -6
- package/lib/sqlitecloud.drivers.js +1 -1
- package/package.json +6 -8
|
@@ -27,9 +27,9 @@ class SQLiteCloudWebsocketConnection extends connection_1.SQLiteCloudConnection
|
|
|
27
27
|
console.assert(!this.connected, 'Connection already established');
|
|
28
28
|
if (!this.socket) {
|
|
29
29
|
this.config = config;
|
|
30
|
-
const
|
|
31
|
-
const gatewayUrl = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.
|
|
32
|
-
this.socket = (0, socket_io_client_1.io)(gatewayUrl, { auth: { token:
|
|
30
|
+
const connectionstring = this.config.connectionstring;
|
|
31
|
+
const gatewayUrl = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.gatewayurl) || `${this.config.host === 'localhost' ? 'ws' : 'wss'}://${this.config.host}:4000`;
|
|
32
|
+
this.socket = (0, socket_io_client_1.io)(gatewayUrl, { auth: { token: connectionstring } });
|
|
33
33
|
}
|
|
34
34
|
callback === null || callback === void 0 ? void 0 : callback.call(this, null);
|
|
35
35
|
}
|
|
@@ -8,7 +8,7 @@ import { OperationsQueue } from './queue';
|
|
|
8
8
|
* Actual connection management and communication with the server in concrete classes.
|
|
9
9
|
*/
|
|
10
10
|
export declare abstract class SQLiteCloudConnection {
|
|
11
|
-
/** Parse and validate provided
|
|
11
|
+
/** Parse and validate provided connectionstring or configuration */
|
|
12
12
|
constructor(config: SQLiteCloudConfig | string, callback?: ErrorCallback);
|
|
13
13
|
/** Configuration passed by client or extracted from connection string */
|
|
14
14
|
protected config: SQLiteCloudConfig;
|
|
@@ -29,6 +29,16 @@ export declare abstract class SQLiteCloudConnection {
|
|
|
29
29
|
verbose(): void;
|
|
30
30
|
/** Will enquee a command to be executed and callback with the resulting rowset/result/error */
|
|
31
31
|
sendCommands(commands: string, callback?: ResultsCallback): this;
|
|
32
|
+
/**
|
|
33
|
+
* Sql is a promise based API for executing SQL statements. You can
|
|
34
|
+
* pass a simple string with a SQL statement or a template string
|
|
35
|
+
* using backticks and parameters in ${parameter} format. These parameters
|
|
36
|
+
* will be properly escaped and quoted like when using a prepared statement.
|
|
37
|
+
* @param sql A sql string or a template string in `backticks` format
|
|
38
|
+
* @returns An array of rows in case of selections or an object with
|
|
39
|
+
* metadata in case of insert, update, delete.
|
|
40
|
+
*/
|
|
41
|
+
sql(sql: TemplateStringsArray | string, ...values: any[]): Promise<any>;
|
|
32
42
|
/** Disconnect from server, release transport. */
|
|
33
43
|
abstract close(): this;
|
|
34
44
|
}
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* connection.ts - base abstract class for sqlitecloud server connections
|
|
4
4
|
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
5
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
15
|
exports.SQLiteCloudConnection = void 0;
|
|
7
16
|
const types_1 = require("./types");
|
|
@@ -13,12 +22,12 @@ const utilities_2 = require("./utilities");
|
|
|
13
22
|
* Actual connection management and communication with the server in concrete classes.
|
|
14
23
|
*/
|
|
15
24
|
class SQLiteCloudConnection {
|
|
16
|
-
/** Parse and validate provided
|
|
25
|
+
/** Parse and validate provided connectionstring or configuration */
|
|
17
26
|
constructor(config, callback) {
|
|
18
27
|
/** Operations are serialized by waiting an any pending promises */
|
|
19
28
|
this.operations = new queue_1.OperationsQueue();
|
|
20
29
|
if (typeof config === 'string') {
|
|
21
|
-
this.config = (0, utilities_1.validateConfiguration)({
|
|
30
|
+
this.config = (0, utilities_1.validateConfiguration)({ connectionstring: config });
|
|
22
31
|
}
|
|
23
32
|
else {
|
|
24
33
|
this.config = (0, utilities_1.validateConfiguration)(config);
|
|
@@ -53,7 +62,7 @@ class SQLiteCloudConnection {
|
|
|
53
62
|
log(message, ...optionalParams) {
|
|
54
63
|
if (this.config.verbose) {
|
|
55
64
|
message = (0, utilities_2.anonimizeCommand)(message);
|
|
56
|
-
console.log(`${new Date().toISOString()} ${this.config.
|
|
65
|
+
console.log(`${new Date().toISOString()} ${this.config.clientid}: ${message}`, ...optionalParams);
|
|
57
66
|
}
|
|
58
67
|
}
|
|
59
68
|
/** Enable verbose logging for debug purposes */
|
|
@@ -77,5 +86,51 @@ class SQLiteCloudConnection {
|
|
|
77
86
|
});
|
|
78
87
|
return this;
|
|
79
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Sql is a promise based API for executing SQL statements. You can
|
|
91
|
+
* pass a simple string with a SQL statement or a template string
|
|
92
|
+
* using backticks and parameters in ${parameter} format. These parameters
|
|
93
|
+
* will be properly escaped and quoted like when using a prepared statement.
|
|
94
|
+
* @param sql A sql string or a template string in `backticks` format
|
|
95
|
+
* @returns An array of rows in case of selections or an object with
|
|
96
|
+
* metadata in case of insert, update, delete.
|
|
97
|
+
*/
|
|
98
|
+
sql(sql, ...values) {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
let preparedSql = '';
|
|
101
|
+
// sql is a TemplateStringsArray, the 'raw' property is specific to TemplateStringsArray
|
|
102
|
+
if (Array.isArray(sql) && 'raw' in sql) {
|
|
103
|
+
sql.forEach((string, i) => {
|
|
104
|
+
preparedSql += string + (i < values.length ? '?' : '');
|
|
105
|
+
});
|
|
106
|
+
preparedSql = (0, utilities_1.prepareSql)(preparedSql, ...values);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
if (typeof sql === 'string') {
|
|
110
|
+
if ((values === null || values === void 0 ? void 0 : values.length) > 0) {
|
|
111
|
+
preparedSql = (0, utilities_1.prepareSql)(sql, ...values);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
preparedSql = sql;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
throw new Error('Invalid sql');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return new Promise((resolve, reject) => {
|
|
122
|
+
this.sendCommands(preparedSql, (error, results) => {
|
|
123
|
+
if (error) {
|
|
124
|
+
reject(error);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// metadata for operations like insert, update, delete?
|
|
128
|
+
const context = (0, utilities_2.getUpdateResults)(results);
|
|
129
|
+
resolve(context ? context : results);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
}
|
|
80
135
|
}
|
|
81
136
|
exports.SQLiteCloudConnection = SQLiteCloudConnection;
|
package/lib/drivers/database.js
CHANGED
|
@@ -58,7 +58,7 @@ class Database extends eventemitter3_1.default {
|
|
|
58
58
|
super();
|
|
59
59
|
/** Database connections */
|
|
60
60
|
this.connections = [];
|
|
61
|
-
this.config = typeof config === 'string' ? {
|
|
61
|
+
this.config = typeof config === 'string' ? { connectionstring: config } : config;
|
|
62
62
|
// mode is optional and so is callback
|
|
63
63
|
// https://github.com/TryGhost/node-sqlite3/wiki/API#new-sqlite3databasefilename--mode--callback
|
|
64
64
|
if (typeof mode === 'function') {
|
|
@@ -85,7 +85,7 @@ class Database extends eventemitter3_1.default {
|
|
|
85
85
|
}
|
|
86
86
|
else {
|
|
87
87
|
// connect using websocket if tls is not supported or if explicitly requested
|
|
88
|
-
const useWebsocket = utilities_2.isBrowser || ((_b = this.config) === null || _b === void 0 ? void 0 : _b.
|
|
88
|
+
const useWebsocket = utilities_2.isBrowser || ((_b = this.config) === null || _b === void 0 ? void 0 : _b.usewebsocket) || ((_c = this.config) === null || _c === void 0 ? void 0 : _c.gatewayurl);
|
|
89
89
|
if (useWebsocket) {
|
|
90
90
|
// socket.io transport works in both node.js and browser environments and connects via SQLite Cloud Gateway
|
|
91
91
|
Promise.resolve().then(() => __importStar(require('./connection-ws'))).then(module => {
|
|
@@ -210,7 +210,7 @@ class Database extends eventemitter3_1.default {
|
|
|
210
210
|
else {
|
|
211
211
|
// context may include id of last row inserted, total changes, etc...
|
|
212
212
|
const context = this.processContext(results);
|
|
213
|
-
callback === null || callback === void 0 ? void 0 : callback.call(context || this, null, context ?
|
|
213
|
+
callback === null || callback === void 0 ? void 0 : callback.call(context || this, null, context ? context : results);
|
|
214
214
|
}
|
|
215
215
|
});
|
|
216
216
|
}
|
package/lib/drivers/types.d.ts
CHANGED
|
@@ -8,17 +8,22 @@ import tls from 'tls';
|
|
|
8
8
|
export declare const DEFAULT_TIMEOUT: number;
|
|
9
9
|
/** Default tls connection port */
|
|
10
10
|
export declare const DEFAULT_PORT = 9960;
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for SQLite cloud connection
|
|
13
|
+
* @note Options are all lowecase so they 1:1 compatible with C SDK
|
|
14
|
+
*/
|
|
12
15
|
export interface SQLiteCloudConfig {
|
|
13
16
|
/** Connection string in the form of sqlitecloud://user:password@host:port/database?options */
|
|
14
|
-
|
|
15
|
-
/** User name is required unless
|
|
17
|
+
connectionstring?: string;
|
|
18
|
+
/** User name is required unless connectionstring is provided */
|
|
16
19
|
username?: string;
|
|
17
20
|
/** Password is required unless connection string is provided */
|
|
18
21
|
password?: string;
|
|
19
22
|
/** True if password is hashed, default is false */
|
|
20
|
-
|
|
21
|
-
/**
|
|
23
|
+
password_hashed?: boolean;
|
|
24
|
+
/** API key can be provided instead of username and password */
|
|
25
|
+
apikey?: string;
|
|
26
|
+
/** Host name is required unless connectionstring is provided, eg: xxx.sqlitecloud.io */
|
|
22
27
|
host?: string;
|
|
23
28
|
/** Port number for tls socket */
|
|
24
29
|
port?: number;
|
|
@@ -28,29 +33,31 @@ export interface SQLiteCloudConfig {
|
|
|
28
33
|
timeout?: number;
|
|
29
34
|
/** Name of database to open */
|
|
30
35
|
database?: string;
|
|
36
|
+
/** Flag to tell the server to zero-terminate strings */
|
|
37
|
+
zerotext?: boolean;
|
|
31
38
|
/** Create the database if it doesn't exist? */
|
|
32
|
-
|
|
39
|
+
create?: boolean;
|
|
33
40
|
/** Database will be created in memory */
|
|
34
|
-
|
|
41
|
+
memory?: boolean;
|
|
35
42
|
compression?: boolean;
|
|
36
43
|
/** Request for immediate responses from the server node without waiting for linerizability guarantees */
|
|
37
|
-
|
|
44
|
+
non_linearizable?: boolean;
|
|
38
45
|
/** Server should send BLOB columns */
|
|
39
|
-
|
|
46
|
+
noblob?: boolean;
|
|
40
47
|
/** Do not send columns with more than max_data bytes */
|
|
41
|
-
|
|
48
|
+
maxdata?: number;
|
|
42
49
|
/** Server should chunk responses with more than maxRows */
|
|
43
|
-
|
|
50
|
+
maxrows?: number;
|
|
44
51
|
/** Server should limit total number of rows in a set to maxRowset */
|
|
45
|
-
|
|
52
|
+
maxrowset?: number;
|
|
46
53
|
/** Custom options and configurations for tls socket, eg: additional certificates */
|
|
47
|
-
|
|
54
|
+
tlsoptions?: tls.ConnectionOptions;
|
|
48
55
|
/** True if we should force use of SQLite Cloud Gateway and websocket connections, default: true in browsers, false in node.js */
|
|
49
|
-
|
|
56
|
+
usewebsocket?: boolean;
|
|
50
57
|
/** Url where we can connect to a SQLite Cloud Gateway that has a socket.io deamon waiting to connect, eg. wss://host:4000 */
|
|
51
|
-
|
|
58
|
+
gatewayurl?: string;
|
|
52
59
|
/** Optional identifier used for verbose logging */
|
|
53
|
-
|
|
60
|
+
clientid?: string;
|
|
54
61
|
/** True if connection should enable debug logs */
|
|
55
62
|
verbose?: boolean;
|
|
56
63
|
}
|
|
@@ -83,7 +90,7 @@ export interface SQLCloudRowsetMetadata {
|
|
|
83
90
|
}[];
|
|
84
91
|
}
|
|
85
92
|
/** Basic types that can be returned by SQLiteCloud APIs */
|
|
86
|
-
export type SQLiteCloudDataTypes = string | number | boolean | Record<string | number, unknown> | Buffer | null | undefined;
|
|
93
|
+
export type SQLiteCloudDataTypes = string | number | bigint | boolean | Record<string | number, unknown> | Buffer | null | undefined;
|
|
87
94
|
/** Custom error reported by SQLiteCloud drivers */
|
|
88
95
|
export declare class SQLiteCloudError extends Error {
|
|
89
96
|
constructor(message: string, args?: Partial<SQLiteCloudError>);
|
|
@@ -11,6 +11,8 @@ export declare function getInitializationCommands(config: SQLiteCloudConfig): st
|
|
|
11
11
|
export declare function escapeSqlParameter(param: SQLiteCloudDataTypes): string;
|
|
12
12
|
/** Take a sql statement and replaces ? or $named parameters that are properly serialized and escaped. */
|
|
13
13
|
export declare function prepareSql(sql: string, ...params: (SQLiteCloudDataTypes | SQLiteCloudDataTypes[])[]): string;
|
|
14
|
+
/** Converts results of an update or insert call into a more meaning full result set */
|
|
15
|
+
export declare function getUpdateResults(results?: any): Record<string, any> | undefined;
|
|
14
16
|
/**
|
|
15
17
|
* Many of the methods in our API may contain a callback as their last argument.
|
|
16
18
|
* This method will take the arguments array passed to the method and return an object
|
|
@@ -25,7 +27,13 @@ export declare function popCallback<T extends ErrorCallback = ErrorCallback>(arg
|
|
|
25
27
|
};
|
|
26
28
|
/** Validate configuration, apply defaults, throw if something is missing or misconfigured */
|
|
27
29
|
export declare function validateConfiguration(config: SQLiteCloudConfig): SQLiteCloudConfig;
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Parse connectionstring like sqlitecloud://username:password@host:port/database?option1=xxx&option2=xxx
|
|
32
|
+
* or sqlitecloud://host.sqlite.cloud:8860/chinook.sqlite?apikey=mIiLARzKm9XBVllbAzkB1wqrgijJ3Gx0X5z1Agm3xBo
|
|
33
|
+
* into its basic components.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseconnectionstring(connectionstring: string): SQLiteCloudConfig;
|
|
30
36
|
/** Returns true if value is 1 or true */
|
|
31
37
|
export declare function parseBoolean(value: string | boolean | null | undefined): boolean;
|
|
38
|
+
/** Returns true if value is 1 or true */
|
|
39
|
+
export declare function parseBooleanToZeroOne(value: string | boolean | null | undefined): 0 | 1;
|
package/lib/drivers/utilities.js
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
// utilities.ts - utility methods to manipulate SQL statements
|
|
4
4
|
//
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.parseBoolean = exports.
|
|
6
|
+
exports.parseBooleanToZeroOne = exports.parseBoolean = exports.parseconnectionstring = exports.validateConfiguration = exports.popCallback = exports.getUpdateResults = exports.prepareSql = exports.escapeSqlParameter = exports.getInitializationCommands = exports.anonimizeError = exports.anonimizeCommand = exports.isNode = exports.isBrowser = void 0;
|
|
7
7
|
const types_1 = require("./types");
|
|
8
|
+
const types_2 = require("./types");
|
|
8
9
|
//
|
|
9
10
|
// determining running environment, thanks to browser-or-node
|
|
10
11
|
// https://www.npmjs.com/package/browser-or-node
|
|
@@ -34,9 +35,15 @@ exports.anonimizeError = anonimizeError;
|
|
|
34
35
|
/** Initialization commands sent to database when connection is established */
|
|
35
36
|
function getInitializationCommands(config) {
|
|
36
37
|
// first user authentication, then all other commands
|
|
37
|
-
let commands =
|
|
38
|
+
let commands = '';
|
|
39
|
+
if (config.apikey) {
|
|
40
|
+
commands = `AUTH APIKEY ${config.apikey}; `;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
commands = `AUTH USER ${config.username || ''} ${config.password_hashed ? 'HASH' : 'PASSWORD'} ${config.password || ''}; `;
|
|
44
|
+
}
|
|
38
45
|
if (config.database) {
|
|
39
|
-
if (config.
|
|
46
|
+
if (config.create && !config.memory) {
|
|
40
47
|
commands += `CREATE DATABASE ${config.database} IF NOT EXISTS; `;
|
|
41
48
|
}
|
|
42
49
|
commands += `USE DATABASE ${config.database}; `;
|
|
@@ -44,20 +51,23 @@ function getInitializationCommands(config) {
|
|
|
44
51
|
if (config.compression) {
|
|
45
52
|
commands += 'SET CLIENT KEY COMPRESSION TO 1; ';
|
|
46
53
|
}
|
|
47
|
-
if (config.
|
|
54
|
+
if (config.zerotext) {
|
|
55
|
+
commands += 'SET CLIENT KEY ZEROTEXT TO 1; ';
|
|
56
|
+
}
|
|
57
|
+
if (config.non_linearizable) {
|
|
48
58
|
commands += 'SET CLIENT KEY NONLINEARIZABLE TO 1; ';
|
|
49
59
|
}
|
|
50
|
-
if (config.
|
|
60
|
+
if (config.noblob) {
|
|
51
61
|
commands += 'SET CLIENT KEY NOBLOB TO 1; ';
|
|
52
62
|
}
|
|
53
|
-
if (config.
|
|
54
|
-
commands += `SET CLIENT KEY MAXDATA TO ${config.
|
|
63
|
+
if (config.maxdata) {
|
|
64
|
+
commands += `SET CLIENT KEY MAXDATA TO ${config.maxdata}; `;
|
|
55
65
|
}
|
|
56
|
-
if (config.
|
|
57
|
-
commands += `SET CLIENT KEY MAXROWS TO ${config.
|
|
66
|
+
if (config.maxrows) {
|
|
67
|
+
commands += `SET CLIENT KEY MAXROWS TO ${config.maxrows}; `;
|
|
58
68
|
}
|
|
59
|
-
if (config.
|
|
60
|
-
commands += `SET CLIENT KEY MAXROWSET TO ${config.
|
|
69
|
+
if (config.maxrowset) {
|
|
70
|
+
commands += `SET CLIENT KEY MAXROWSET TO ${config.maxrowset}; `;
|
|
61
71
|
}
|
|
62
72
|
return commands;
|
|
63
73
|
}
|
|
@@ -72,7 +82,7 @@ function escapeSqlParameter(param) {
|
|
|
72
82
|
param = param.replace(/'/g, "''");
|
|
73
83
|
return `'${param}'`;
|
|
74
84
|
}
|
|
75
|
-
if (typeof param === 'number') {
|
|
85
|
+
if (typeof param === 'number' || typeof param === 'bigint') {
|
|
76
86
|
return param.toString();
|
|
77
87
|
}
|
|
78
88
|
if (typeof param === 'boolean') {
|
|
@@ -128,6 +138,28 @@ function prepareSql(sql, ...params) {
|
|
|
128
138
|
return preparedSql;
|
|
129
139
|
}
|
|
130
140
|
exports.prepareSql = prepareSql;
|
|
141
|
+
/** Converts results of an update or insert call into a more meaning full result set */
|
|
142
|
+
function getUpdateResults(results) {
|
|
143
|
+
if (results) {
|
|
144
|
+
if (Array.isArray(results) && results.length > 0) {
|
|
145
|
+
switch (results[0]) {
|
|
146
|
+
case types_2.SQLiteCloudArrayType.ARRAY_TYPE_SQLITE_EXEC:
|
|
147
|
+
return {
|
|
148
|
+
type: results[0],
|
|
149
|
+
index: results[1],
|
|
150
|
+
lastID: results[2],
|
|
151
|
+
changes: results[3],
|
|
152
|
+
totalChanges: results[4],
|
|
153
|
+
finalized: results[5],
|
|
154
|
+
//
|
|
155
|
+
rowId: results[2] // same as lastId
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
exports.getUpdateResults = getUpdateResults;
|
|
131
163
|
/**
|
|
132
164
|
* Many of the methods in our API may contain a callback as their last argument.
|
|
133
165
|
* This method will take the arguments array passed to the method and return an object
|
|
@@ -154,47 +186,66 @@ exports.popCallback = popCallback;
|
|
|
154
186
|
/** Validate configuration, apply defaults, throw if something is missing or misconfigured */
|
|
155
187
|
function validateConfiguration(config) {
|
|
156
188
|
console.assert(config, 'SQLiteCloudConnection.validateConfiguration - missing config');
|
|
157
|
-
if (config.
|
|
158
|
-
config = Object.assign(Object.assign(Object.assign({}, config),
|
|
189
|
+
if (config.connectionstring) {
|
|
190
|
+
config = Object.assign(Object.assign(Object.assign({}, config), parseconnectionstring(config.connectionstring)), { connectionstring: config.connectionstring // keep original connection string
|
|
159
191
|
});
|
|
160
192
|
}
|
|
161
193
|
// apply defaults where needed
|
|
162
194
|
config.port || (config.port = types_1.DEFAULT_PORT);
|
|
163
195
|
config.timeout = config.timeout && config.timeout > 0 ? config.timeout : types_1.DEFAULT_TIMEOUT;
|
|
164
|
-
config.
|
|
196
|
+
config.clientid || (config.clientid = 'SQLiteCloud');
|
|
165
197
|
config.verbose = parseBoolean(config.verbose);
|
|
166
|
-
config.
|
|
198
|
+
config.noblob = parseBoolean(config.noblob);
|
|
167
199
|
config.compression = parseBoolean(config.compression);
|
|
168
|
-
config.
|
|
169
|
-
config.
|
|
200
|
+
config.create = parseBoolean(config.create);
|
|
201
|
+
config.non_linearizable = parseBoolean(config.non_linearizable);
|
|
170
202
|
config.insecure = parseBoolean(config.insecure);
|
|
171
|
-
|
|
203
|
+
const hasCredentials = (config.username && config.password) || config.apikey;
|
|
204
|
+
if (!config.host || !hasCredentials) {
|
|
172
205
|
console.error('SQLiteCloudConnection.validateConfiguration - missing arguments', config);
|
|
173
|
-
throw new types_1.SQLiteCloudError('The user, password and host arguments must be specified.', { errorCode: 'ERR_MISSING_ARGS' });
|
|
206
|
+
throw new types_1.SQLiteCloudError('The user, password and host arguments or the ?apikey= must be specified.', { errorCode: 'ERR_MISSING_ARGS' });
|
|
174
207
|
}
|
|
175
|
-
if (!config.
|
|
208
|
+
if (!config.connectionstring) {
|
|
176
209
|
// build connection string from configuration, values are already validated
|
|
177
210
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
178
|
-
|
|
211
|
+
if (config.apikey) {
|
|
212
|
+
config.connectionstring = `sqlitecloud://${config.host}:${config.port}/${config.database || ''}?apikey=${config.apikey}`;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
config.connectionstring = `sqlitecloud://${encodeURIComponent(config.username || '')}:${encodeURIComponent(config.password || '')}@${config.host}:${config.port}/${config.database}`;
|
|
216
|
+
}
|
|
179
217
|
}
|
|
180
218
|
return config;
|
|
181
219
|
}
|
|
182
220
|
exports.validateConfiguration = validateConfiguration;
|
|
183
|
-
/**
|
|
184
|
-
|
|
221
|
+
/**
|
|
222
|
+
* Parse connectionstring like sqlitecloud://username:password@host:port/database?option1=xxx&option2=xxx
|
|
223
|
+
* or sqlitecloud://host.sqlite.cloud:8860/chinook.sqlite?apikey=mIiLARzKm9XBVllbAzkB1wqrgijJ3Gx0X5z1Agm3xBo
|
|
224
|
+
* into its basic components.
|
|
225
|
+
*/
|
|
226
|
+
function parseconnectionstring(connectionstring) {
|
|
185
227
|
try {
|
|
186
228
|
// The URL constructor throws a TypeError if the URL is not valid.
|
|
187
229
|
// in spite of having the same structure as a regular url
|
|
188
230
|
// protocol://username:password@host:port/database?option1=xxx&option2=xxx)
|
|
189
231
|
// the sqlitecloud: protocol is not recognized by the URL constructor in browsers
|
|
190
232
|
// so we need to replace it with https: to make it work
|
|
191
|
-
const knownProtocolUrl =
|
|
233
|
+
const knownProtocolUrl = connectionstring.replace('sqlitecloud:', 'https:');
|
|
192
234
|
const url = new URL(knownProtocolUrl);
|
|
235
|
+
// all lowecase options
|
|
193
236
|
const options = {};
|
|
194
237
|
url.searchParams.forEach((value, key) => {
|
|
195
|
-
options[key] = value;
|
|
238
|
+
options[key.toLowerCase().replaceAll('-', '_')] = value;
|
|
196
239
|
});
|
|
197
240
|
const config = Object.assign({ username: decodeURIComponent(url.username), password: decodeURIComponent(url.password), host: url.hostname, port: url.port ? parseInt(url.port) : undefined }, options);
|
|
241
|
+
// either you use an apikey or username and password
|
|
242
|
+
if (config.apikey) {
|
|
243
|
+
if (config.username || config.password) {
|
|
244
|
+
console.warn('SQLiteCloudConnection.parseconnectionstring - apikey and username/password are both specified, using apikey');
|
|
245
|
+
}
|
|
246
|
+
delete config.username;
|
|
247
|
+
delete config.password;
|
|
248
|
+
}
|
|
198
249
|
const database = url.pathname.replace('/', ''); // pathname is database name, remove the leading slash
|
|
199
250
|
if (database) {
|
|
200
251
|
config.database = database;
|
|
@@ -202,10 +253,10 @@ function parseConnectionString(connectionString) {
|
|
|
202
253
|
return config;
|
|
203
254
|
}
|
|
204
255
|
catch (error) {
|
|
205
|
-
throw new types_1.SQLiteCloudError(`Invalid connection string: ${
|
|
256
|
+
throw new types_1.SQLiteCloudError(`Invalid connection string: ${connectionstring}`);
|
|
206
257
|
}
|
|
207
258
|
}
|
|
208
|
-
exports.
|
|
259
|
+
exports.parseconnectionstring = parseconnectionstring;
|
|
209
260
|
/** Returns true if value is 1 or true */
|
|
210
261
|
function parseBoolean(value) {
|
|
211
262
|
if (typeof value === 'string') {
|
|
@@ -214,3 +265,11 @@ function parseBoolean(value) {
|
|
|
214
265
|
return value ? true : false;
|
|
215
266
|
}
|
|
216
267
|
exports.parseBoolean = parseBoolean;
|
|
268
|
+
/** Returns true if value is 1 or true */
|
|
269
|
+
function parseBooleanToZeroOne(value) {
|
|
270
|
+
if (typeof value === 'string') {
|
|
271
|
+
return value.toLowerCase() === 'true' || value === '1' ? 1 : 0;
|
|
272
|
+
}
|
|
273
|
+
return value ? 1 : 0;
|
|
274
|
+
}
|
|
275
|
+
exports.parseBooleanToZeroOne = parseBooleanToZeroOne;
|
package/lib/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { Statement } from './drivers/statement';
|
|
|
3
3
|
export { SQLiteCloudConnection } from './drivers/connection';
|
|
4
4
|
export { type SQLiteCloudConfig, type SQLCloudRowsetMetadata, SQLiteCloudError, type ResultsCallback, type ErrorCallback } from './drivers/types';
|
|
5
5
|
export { SQLiteCloudRowset, SQLiteCloudRow } from './drivers/rowset';
|
|
6
|
-
export { escapeSqlParameter, prepareSql,
|
|
6
|
+
export { escapeSqlParameter, prepareSql, parseconnectionstring, validateConfiguration } from './drivers/utilities';
|
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// index.ts - export drivers classes, utilities, types
|
|
4
4
|
//
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.validateConfiguration = exports.
|
|
6
|
+
exports.validateConfiguration = exports.parseconnectionstring = exports.prepareSql = exports.escapeSqlParameter = exports.SQLiteCloudRow = exports.SQLiteCloudRowset = exports.SQLiteCloudError = exports.SQLiteCloudConnection = exports.Statement = exports.Database = void 0;
|
|
7
7
|
// include ONLY packages used by drivers
|
|
8
8
|
// do NOT include anything related to gateway or bun or express
|
|
9
9
|
// connection-tls does not want/need to load on browser and is loaded dynamically by Database
|
|
@@ -22,5 +22,5 @@ Object.defineProperty(exports, "SQLiteCloudRow", { enumerable: true, get: functi
|
|
|
22
22
|
var utilities_1 = require("./drivers/utilities");
|
|
23
23
|
Object.defineProperty(exports, "escapeSqlParameter", { enumerable: true, get: function () { return utilities_1.escapeSqlParameter; } });
|
|
24
24
|
Object.defineProperty(exports, "prepareSql", { enumerable: true, get: function () { return utilities_1.prepareSql; } });
|
|
25
|
-
Object.defineProperty(exports, "
|
|
25
|
+
Object.defineProperty(exports, "parseconnectionstring", { enumerable: true, get: function () { return utilities_1.parseconnectionstring; } });
|
|
26
26
|
Object.defineProperty(exports, "validateConfiguration", { enumerable: true, get: function () { return utilities_1.validateConfiguration; } });
|