@@ -16,20 +16,25 @@ export const DEFAULT_PORT = 9960
1616 * Base class for SQLiteCloudConnection handles basics and defines methods.
1717 * Actual connection management and communication with the server in concrete classes.
1818 */
19- export abstract class SQLiteCloudConnection {
19+ export class SQLiteCloudConnection {
2020 /** Parse and validate provided connectionString or configuration */
2121 constructor ( config : SQLiteCloudConfig | string , callback ?: ErrorCallback ) {
2222 if ( typeof config === 'string' ) {
2323 this . config = this . validateConfiguration ( { connectionString : config } )
2424 } else {
2525 this . config = this . validateConfiguration ( config )
2626 }
27+
28+ // connect transport layer to server
2729 this . connect ( callback )
2830 }
2931
3032 /** Configuration passed by client or extracted from connection string */
3133 protected config : SQLiteCloudConfig
3234
35+ /** Transport used to communicate with server */
36+ protected transport ?: ConnectionTransport
37+
3338 /** Operations are serialized by waiting an any pending promises */
3439 protected operations = new OperationsQueue ( )
3540
@@ -38,7 +43,32 @@ export abstract class SQLiteCloudConnection {
3843 //
3944
4045 /** True if connection is open */
41- public abstract get connected ( ) : boolean
46+ public get connected ( ) : boolean {
47+ return this . transport ?. connected || false
48+ }
49+
50+ protected connect ( callback ?: ErrorCallback ) : this {
51+ this . operations . enqueue ( done => {
52+ if ( false ) {
53+ const transport = require ( './transport-ws' )
54+ this . transport = new transport . WebSocketTransport ( )
55+ } else {
56+ const transport = require ( './transport-tls' )
57+ this . transport = new transport . TlsSocketTransport ( )
58+ }
59+
60+ // ask transport layer to connect
61+ this . transport ?. connect ( this . config , error => {
62+ if ( error ) {
63+ this . close ( )
64+ }
65+ callback ?. call ( this , error )
66+ done ( error )
67+ } )
68+ } )
69+
70+ return this
71+ }
4272
4373 //
4474 // private methods
@@ -80,49 +110,6 @@ export abstract class SQLiteCloudConnection {
80110 }
81111 }
82112
83- /** Initialization commands sent to database when connection is established */
84- protected get initializationCommands ( ) : string {
85- // first user authentication, then all other commands
86- const config = this . config
87- let commands = `AUTH USER ${ config . username || '' } ${ config . passwordHashed ? 'HASH' : 'PASSWORD' } ${ config . password || '' } ; `
88-
89- if ( config . database ) {
90- if ( config . createDatabase && ! config . dbMemory ) {
91- commands += `CREATE DATABASE ${ config . database } IF NOT EXISTS; `
92- }
93- commands += `USE DATABASE ${ config . database } ; `
94- }
95- if ( config . sqliteMode ) {
96- commands += 'SET CLIENT KEY SQLITE TO 1; '
97- }
98- if ( config . compression ) {
99- commands += 'SET CLIENT KEY COMPRESSION TO 1; '
100- }
101- if ( config . nonlinearizable ) {
102- commands += 'SET CLIENT KEY NONLINEARIZABLE TO 1; '
103- }
104- if ( config . noBlob ) {
105- commands += 'SET CLIENT KEY NOBLOB TO 1; '
106- }
107- if ( config . maxData ) {
108- commands += `SET CLIENT KEY MAXDATA TO ${ config . maxData } ; `
109- }
110- if ( config . maxRows ) {
111- commands += `SET CLIENT KEY MAXROWS TO ${ config . maxRows } ; `
112- }
113- if ( config . maxRowset ) {
114- commands += `SET CLIENT KEY MAXROWSET TO ${ config . maxRowset } ; `
115- }
116-
117- return commands
118- }
119-
120- /* Opens a connection with the server and sends the initialization commands. Will throw in case of errors. */
121- protected abstract connect ( callback ?: ErrorCallback ) : this
122-
123- /** Will send a command immediately (no queueing), return the rowset/result or throw an error */
124- protected abstract processCommands ( commands : string , callback ?: ResultsCallback ) : this
125-
126113 //
127114 // public methods
128115 //
@@ -135,17 +122,28 @@ export abstract class SQLiteCloudConnection {
135122 /** Will enquee a command to be executed and callback with the resulting rowset/result/error */
136123 public sendCommands ( commands : string , callback ?: ResultsCallback ) : this {
137124 this . operations . enqueue ( done => {
138- this . processCommands ( commands , ( error , result ) => {
139- callback ?. call ( this , error , result )
125+ if ( this . transport ) {
126+ this . transport . processCommands ( commands , ( error , result ) => {
127+ callback ?. call ( this , error , result )
128+ done ( error )
129+ } )
130+ } else {
131+ const error = new SQLiteCloudError ( 'Connection not established' , { errorCode : 'ERR_CONNECTION_NOT_ESTABLISHED' } )
132+ callback ?. call ( this , error )
140133 done ( error )
141- } )
134+ }
142135 } )
143136
144137 return this
145138 }
146139
147140 /** Disconnect from server, release connection. */
148- public abstract close ( ) : this
141+ public close ( ) : this {
142+ this . operations . clear ( )
143+ this . transport ?. close ( )
144+ this . transport = undefined
145+ return this
146+ }
149147}
150148
151149//
@@ -214,3 +212,55 @@ export function anonimizeError(error: Error): Error {
214212 }
215213 return error
216214}
215+
216+ /** Initialization commands sent to database when connection is established */
217+ export function getInitializationCommands ( config : SQLiteCloudConfig ) : string {
218+ // first user authentication, then all other commands
219+ let commands = `AUTH USER ${ config . username || '' } ${ config . passwordHashed ? 'HASH' : 'PASSWORD' } ${ config . password || '' } ; `
220+
221+ if ( config . database ) {
222+ if ( config . createDatabase && ! config . dbMemory ) {
223+ commands += `CREATE DATABASE ${ config . database } IF NOT EXISTS; `
224+ }
225+ commands += `USE DATABASE ${ config . database } ; `
226+ }
227+ if ( config . sqliteMode ) {
228+ commands += 'SET CLIENT KEY SQLITE TO 1; '
229+ }
230+ if ( config . compression ) {
231+ commands += 'SET CLIENT KEY COMPRESSION TO 1; '
232+ }
233+ if ( config . nonlinearizable ) {
234+ commands += 'SET CLIENT KEY NONLINEARIZABLE TO 1; '
235+ }
236+ if ( config . noBlob ) {
237+ commands += 'SET CLIENT KEY NOBLOB TO 1; '
238+ }
239+ if ( config . maxData ) {
240+ commands += `SET CLIENT KEY MAXDATA TO ${ config . maxData } ; `
241+ }
242+ if ( config . maxRows ) {
243+ commands += `SET CLIENT KEY MAXROWS TO ${ config . maxRows } ; `
244+ }
245+ if ( config . maxRowset ) {
246+ commands += `SET CLIENT KEY MAXROWSET TO ${ config . maxRowset } ; `
247+ }
248+
249+ return commands
250+ }
251+
252+ //
253+ // ConnectionTransport
254+ //
255+
256+ /** ConnectionTransport implements the underlying transport layer for the connection */
257+ export interface ConnectionTransport {
258+ /** True if connection is currently open */
259+ get connected ( ) : boolean
260+ /* Opens a connection with the server and sends the initialization commands. Will throw in case of errors. */
261+ connect ( config : SQLiteCloudConfig , callback ?: ErrorCallback ) : this
262+ /** Send a command, return the rowset/result or throw an error */
263+ processCommands ( commands : string , callback ?: ResultsCallback ) : this
264+ /** Disconnect from server, release transport. */
265+ close ( ) : this
266+ }
0 commit comments