Skip to content

Commit e15ce94

Browse files
Refactoring, separating connection and transport layers
1 parent 1d004a0 commit e15ce94

File tree

8 files changed

+274
-281
lines changed

8 files changed

+274
-281
lines changed

src/connection-ws.ts

Lines changed: 0 additions & 110 deletions
This file was deleted.

src/connection.ts

Lines changed: 99 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

src/database.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
1212

1313
import { SQLiteCloudConnection } from './connection'
14-
import { SQLiteCloudTlsConnection } from './connection-tls'
1514
import { SQLiteCloudRowset } from './rowset'
1615
import { SQLiteCloudConfig, SQLiteCloudError, RowCountCallback, SQLiteCloudArrayType } from './types'
1716
import { prepareSql, popCallback } from './utilities'
@@ -66,7 +65,7 @@ export class Database extends EventEmitter {
6665
callback?.call(this, null, this.connections[0])
6766
} else {
6867
this.connections.push(
69-
new SQLiteCloudTlsConnection(this.config, error => {
68+
new SQLiteCloudConnection(this.config, error => {
7069
if (error) {
7170
this.handleError(this.connections[0], error, callback)
7271
} else {

src/index.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
//
2-
// index.ts - re-export all the public APIs
2+
// index.ts - re-export public APIs
33
//
44

55
export { Database } from './database'
66
export { Statement } from './statement'
7-
87
export { SQLiteCloudConfig, SQLCloudRowsetMetadata, SQLiteCloudError, ErrorCallback } from './types'
98
export { SQLiteCloudRowset, SQLiteCloudRow } from './rowset'
10-
119
export { SQLiteCloudConnection } from './connection'
12-
export { SQLiteCloudTlsConnection } from './connection-tls'
13-
export { SQLiteCloudWebsocketConnection } from './connection-ws'
14-
1510
export { escapeSqlParameter, prepareSql } from './utilities'

0 commit comments

Comments
 (0)