ueberdb2 4.0.10 → 4.0.15

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.
Files changed (47) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +44 -5
  3. package/databases/{cassandra_db.js → cassandra_db.ts} +45 -30
  4. package/databases/{couch_db.js → couch_db.ts} +78 -31
  5. package/databases/{dirty_db.js → dirty_db.ts} +19 -14
  6. package/databases/{dirty_git_db.js → dirty_git_db.ts} +19 -15
  7. package/databases/{elasticsearch_db.js → elasticsearch_db.ts} +30 -21
  8. package/databases/{memory_db.js → memory_db.ts} +8 -8
  9. package/databases/mock_db.ts +43 -0
  10. package/databases/{mongodb_db.js → mongodb_db.ts} +22 -16
  11. package/databases/{mssql_db.js → mssql_db.ts} +29 -21
  12. package/databases/{mysql_db.js → mysql_db.ts} +20 -15
  13. package/databases/{postgres_db.js → postgres_db.ts} +37 -22
  14. package/databases/{postgrespool_db.js → postgrespool_db.ts} +3 -3
  15. package/databases/redis_db.ts +129 -0
  16. package/databases/{rethink_db.js → rethink_db.ts} +35 -19
  17. package/databases/{sqlite_db.js → sqlite_db.ts} +37 -36
  18. package/docker-compose.yml +44 -0
  19. package/{index.js → index.ts} +76 -25
  20. package/lib/AbstractDatabase.ts +79 -0
  21. package/lib/{CacheAndBufferLayer.js → CacheAndBufferLayer.ts} +17 -16
  22. package/lib/{logging.js → logging.ts} +10 -6
  23. package/package.json +17 -3
  24. package/test/lib/{databases.js → databases.ts} +8 -5
  25. package/test/test.ts +328 -0
  26. package/test/test_bulk.ts +69 -0
  27. package/test/{test_elasticsearch.js → test_elasticsearch.ts} +48 -53
  28. package/test/{test_findKeys.js → test_findKeys.ts} +15 -17
  29. package/test/{test_flush.js → test_flush.ts} +16 -22
  30. package/test/test_getSub.ts +28 -0
  31. package/test/test_lru.ts +151 -0
  32. package/test/test_memory.ts +32 -0
  33. package/test/{test_metrics.js → test_metrics.ts} +73 -68
  34. package/test/{test_mysql.js → test_mysql.ts} +16 -22
  35. package/test/test_postgres.ts +16 -0
  36. package/test/{test_setSub.js → test_setSub.ts} +8 -12
  37. package/test/test_tojson.ts +34 -0
  38. package/databases/mock_db.js +0 -42
  39. package/databases/redis_db.js +0 -96
  40. package/lib/AbstractDatabase.js +0 -37
  41. package/test/test.js +0 -328
  42. package/test/test_bulk.js +0 -69
  43. package/test/test_getSub.js +0 -31
  44. package/test/test_lru.js +0 -145
  45. package/test/test_memory.js +0 -31
  46. package/test/test_postgres.js +0 -16
  47. package/test/test_tojson.js +0 -37
@@ -1,4 +1,3 @@
1
- 'use strict';
2
1
  /**
3
2
  * 2011 Peter 'Pita' Martischka
4
3
  *
@@ -15,12 +14,15 @@
15
14
  * limitations under the License.
16
15
  */
17
16
 
18
- const AbstractDatabase = require('../lib/AbstractDatabase');
19
- const async = require('async');
20
- const pg = require('pg');
17
+ import AbstractDatabase, {Settings} from '../lib/AbstractDatabase';
18
+ import async from 'async';
19
+ import pg, {Pool, QueryResult} from 'pg';
20
+ import {BulkObject} from './cassandra_db';
21
21
 
22
- exports.Database = class extends AbstractDatabase {
23
- constructor(settings) {
22
+ export const Database = class extends AbstractDatabase {
23
+ private db: Pool;
24
+ private upsertStatement: string | null | undefined;
25
+ constructor(settings:Settings | string) {
24
26
  super();
25
27
  if (typeof settings === 'string') settings = {connectionString: settings};
26
28
  this.settings = settings;
@@ -34,10 +36,11 @@ exports.Database = class extends AbstractDatabase {
34
36
  this.settings.min = this.settings.min || 4;
35
37
  this.settings.idleTimeoutMillis = this.settings.idleTimeoutMillis || 1000;
36
38
 
39
+ // @ts-ignore
37
40
  this.db = new pg.Pool(this.settings);
38
41
  }
39
42
 
40
- init(callback) {
43
+ init(callback: (err: Error)=>{}) {
41
44
  const testTableExists = "SELECT 1 as exists FROM pg_tables WHERE tablename = 'store'";
42
45
 
43
46
  const createTable = 'CREATE TABLE IF NOT EXISTS store (' +
@@ -58,7 +61,7 @@ exports.Database = class extends AbstractDatabase {
58
61
  * statement that needs to be used, based on the detection result
59
62
  * - calls the callback
60
63
  */
61
- const detectUpsertMethod = (callback) => {
64
+ const detectUpsertMethod = (callback: (err?: Error) => {}) => {
62
65
  const upsertViaFunction = 'SELECT ueberdb_insert_or_update($1,$2)';
63
66
  const upsertNatively =
64
67
  'INSERT INTO store(key, value) VALUES ($1, $2) ' +
@@ -102,15 +105,17 @@ exports.Database = class extends AbstractDatabase {
102
105
  if (result.rows.length === 0) {
103
106
  this.db.query(createTable, (err) => {
104
107
  if (err != null) return callback(err);
108
+ // @ts-ignore
105
109
  detectUpsertMethod(callback);
106
110
  });
107
111
  } else {
112
+ // @ts-ignore
108
113
  detectUpsertMethod(callback);
109
114
  }
110
115
  });
111
116
  }
112
117
 
113
- get(key, callback) {
118
+ get(key:string, callback: (err: Error | null, value: any)=>{}) {
114
119
  this.db.query('SELECT value FROM store WHERE key=$1', [key], (err, results) => {
115
120
  let value = null;
116
121
 
@@ -122,7 +127,7 @@ exports.Database = class extends AbstractDatabase {
122
127
  });
123
128
  }
124
129
 
125
- findKeys(key, notKey, callback) {
130
+ findKeys(key:string, notKey:string, callback: (err: Error | null, value: any)=>{}) {
126
131
  let query = 'SELECT key FROM store WHERE key LIKE $1';
127
132
  const params = [];
128
133
  // desired keys are %key:%, e.g. pad:%
@@ -136,7 +141,7 @@ exports.Database = class extends AbstractDatabase {
136
141
  params.push(notKey);
137
142
  }
138
143
  this.db.query(query, params, (err, results) => {
139
- const value = [];
144
+ const value:string[] = [];
140
145
 
141
146
  if (!err && results.rows.length > 0) {
142
147
  results.rows.forEach((val) => {
@@ -148,22 +153,23 @@ exports.Database = class extends AbstractDatabase {
148
153
  });
149
154
  }
150
155
 
151
- set(key, value, callback) {
156
+ set(key:string, value:string, callback:(err: Error, result: QueryResult<any>) => void) {
152
157
  if (key.length > 100) {
153
- callback('Your Key can only be 100 chars');
154
- } else {
158
+ const val = '' as any;
159
+ callback(Error('Your Key can only be 100 chars'), val);
160
+ } else if (this.upsertStatement != null) {
155
161
  this.db.query(this.upsertStatement, [key, value], callback);
156
162
  }
157
163
  }
158
164
 
159
- remove(key, callback) {
165
+ remove(key:string, callback:()=>{}) {
160
166
  this.db.query('DELETE FROM store WHERE key=$1', [key], callback);
161
167
  }
162
168
 
163
- doBulk(bulk, callback) {
169
+ doBulk(bulk:BulkObject[], callback:()=>{}) {
164
170
  const replaceVALs = [];
165
171
  let removeSQL = 'DELETE FROM store WHERE key IN (';
166
- const removeVALs = [];
172
+ const removeVALs: string[] = [];
167
173
 
168
174
  let removeCount = 0;
169
175
 
@@ -181,18 +187,27 @@ exports.Database = class extends AbstractDatabase {
181
187
 
182
188
  removeSQL += ');';
183
189
 
184
- const functions = replaceVALs.map((v) => (cb) => this.db.query(this.upsertStatement, v, cb));
190
+ if (!this.upsertStatement) {
191
+ return;
192
+ }
193
+
194
+
195
+ // @ts-ignore
196
+ const functions = replaceVALs.map((v) => (cb:()=>{}) => this.db.query(this.upsertStatement, v, cb));
185
197
 
186
- const removeFunction = (callback) => {
187
- if (!removeVALs.length < 1) this.db.query(removeSQL, removeVALs, callback);
188
- else callback();
198
+ const removeFunction = (callback: ()=>{}) => {
199
+ // @ts-ignore
200
+ if (!(removeVALs.length) > 1) {
201
+ this.db.query(removeSQL, removeVALs, callback);
202
+ } else { callback(); }
189
203
  };
190
204
  functions.push(removeFunction);
191
205
 
206
+ // @ts-ignore
192
207
  async.parallel(functions, callback);
193
208
  }
194
209
 
195
- close(callback) {
210
+ close(callback:()=>{}) {
196
211
  this.db.end(callback);
197
212
  }
198
213
  };
@@ -1,9 +1,9 @@
1
- 'use strict';
1
+ import {Settings} from '../lib/AbstractDatabase';
2
2
 
3
3
  const postgres = require('./postgres_db');
4
4
 
5
- exports.Database = class extends postgres.Database {
6
- constructor(settings) {
5
+ export const Database = class PostgresDB extends postgres.Database {
6
+ constructor(settings:Settings) {
7
7
  console.warn('ueberdb: The postgrespool database driver is deprecated ' +
8
8
  'and will be removed in a future version. Use postgres instead.');
9
9
  super(settings);
@@ -0,0 +1,129 @@
1
+ /**
2
+ * 2011 Peter 'Pita' Martischka
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS-IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import AbstractDatabase, {Settings} from '../lib/AbstractDatabase';
18
+ import {createClient, RedisScripts, RedisFunctions, RedisModules} from 'redis';
19
+ import {BulkObject} from './cassandra_db';
20
+ import {RedisClientType} from '@redis/client';
21
+
22
+ export const Database = class RedisDB extends AbstractDatabase {
23
+ private _client: RedisClientType<{graph:
24
+ {CONFIG_GET: typeof import('@redis/graph/dist/commands/CONFIG_GET');
25
+ configGet: typeof import('@redis/graph/dist/commands/CONFIG_GET');
26
+ CONFIG_SET: typeof import('@redis/graph/dist/commands/CONFIG_SET');
27
+ configSet: typeof import('@redis/graph/dist/commands/CONFIG_SET');
28
+ DELETE: typeof import('@redis/graph/dist/commands/DELETE');
29
+ delete: typeof import('@redis/graph/dist/commands/DELETE');
30
+ EXPLAIN: typeof import('@redis/graph/dist/commands/EXPLAIN');
31
+ explain: typeof import('@redis/graph/dist/commands/EXPLAIN');
32
+ LIST: typeof import('@redis/graph/dist/commands/LIST');
33
+ list: typeof import('@redis/graph/dist/commands/LIST');
34
+ PROFILE: typeof import('@redis/graph/dist/commands/PROFILE');
35
+ profile: typeof import('@redis/graph/dist/commands/PROFILE');
36
+ QUERY: typeof import('@redis/graph/dist/commands/QUERY');
37
+ query: typeof import('@redis/graph/dist/commands/QUERY');
38
+ RO_QUERY: typeof import('@redis/graph/dist/commands/RO_QUERY');
39
+ roQuery: typeof import('@redis/graph/dist/commands/RO_QUERY');
40
+ SLOWLOG: typeof import('@redis/graph/dist/commands/SLOWLOG');
41
+ slowLog: typeof import('@redis/graph/dist/commands/SLOWLOG');};
42
+ json: {ARRAPPEND: typeof import('@redis/json/dist/commands/ARRAPPEND');
43
+ arrAppend: typeof import('@redis/json/dist/commands/ARRAPPEND');
44
+ ARRINDEX: typeof import('@redis/json/dist/commands/ARRINDEX');
45
+ arrIndex: typeof import('@redis/json/dist/commands/ARRINDEX');
46
+ ARRINSERT: typeof import('@redis/json/dist/commands/ARRINSERT');
47
+ arrInsert: typeof import('@redis/json/dist/commands/ARRINSERT'); ARRLEN: typeof import('@redis/json/dist/commands/ARRLEN'); arrLen: typeof import('@redis/json/dist/commands/ARRLEN'); ARRPOP: typeof import('@redis/json/dist/commands/ARRPOP'); arrPop: typeof import('@redis/json/dist/commands/ARRPOP'); ARRTRIM: typeof import('@redis/json/dist/commands/ARRTRIM'); arrTrim: typeof import('@redis/json/dist/commands/ARRTRIM'); DEBUG_MEMORY: typeof import('@redis/json/dist/commands/DEBUG_MEMORY'); debugMemory: typeof import('@redis/json/dist/commands/DEBUG_MEMORY'); DEL: typeof import('@redis/json/dist/commands/DEL'); del: typeof import('@redis/json/dist/commands/DEL'); FORGET: typeof import('@redis/json/dist/commands/FORGET'); forget: typeof import('@redis/json/dist/commands/FORGET'); GET: typeof import('@redis/json/dist/commands/GET'); get: typeof import('@redis/json/dist/commands/GET'); MGET: typeof import('@redis/json/dist/commands/MGET'); mGet: typeof import('@redis/json/dist/commands/MGET'); NUMINCRBY: typeof import('@redis/json/dist/commands/NUMINCRBY'); numIncrBy: typeof import('@redis/json/dist/commands/NUMINCRBY'); NUMMULTBY: typeof import('@redis/json/dist/commands/NUMMULTBY'); numMultBy: typeof import('@redis/json/dist/commands/NUMMULTBY'); OBJKEYS: typeof import('@redis/json/dist/commands/OBJKEYS'); objKeys: typeof import('@redis/json/dist/commands/OBJKEYS'); OBJLEN: typeof import('@redis/json/dist/commands/OBJLEN'); objLen: typeof import('@redis/json/dist/commands/OBJLEN'); RESP: typeof import('@redis/json/dist/commands/RESP'); resp: typeof import('@redis/json/dist/commands/RESP'); SET: typeof import('@redis/json/dist/commands/SET'); set: typeof import('@redis/json/dist/commands/SET'); STRAPPEND: typeof import('@redis/json/dist/commands/STRAPPEND'); strAppend: typeof import('@redis/json/dist/commands/STRAPPEND'); STRLEN: typeof import('@redis/json/dist/commands/STRLEN'); strLen: typeof import('@redis/json/dist/commands/STRLEN'); TYPE: typeof import('@redis/json/dist/commands/TYPE'); type: typeof import('@redis/json/dist/commands/TYPE');}; ft: {_LIST: typeof import('@redis/search/dist/commands/_LIST'); _list: typeof import('@redis/search/dist/commands/_LIST'); ALTER: typeof import('@redis/search/dist/commands/ALTER'); alter: typeof import('@redis/search/dist/commands/ALTER'); AGGREGATE_WITHCURSOR: typeof import('@redis/search/dist/commands/AGGREGATE_WITHCURSOR'); aggregateWithCursor: typeof import('@redis/search/dist/commands/AGGREGATE_WITHCURSOR'); AGGREGATE: typeof import('@redis/search/dist/commands/AGGREGATE'); aggregate: typeof import('@redis/search/dist/commands/AGGREGATE'); ALIASADD: typeof import('@redis/search/dist/commands/ALIASADD'); aliasAdd: typeof import('@redis/search/dist/commands/ALIASADD'); ALIASDEL: typeof import('@redis/search/dist/commands/ALIASDEL'); aliasDel: typeof import('@redis/search/dist/commands/ALIASDEL'); ALIASUPDATE: typeof import('@redis/search/dist/commands/ALIASUPDATE'); aliasUpdate: typeof import('@redis/search/dist/commands/ALIASUPDATE'); CONFIG_GET: typeof import('@redis/search/dist/commands/CONFIG_GET'); configGet: typeof import('@redis/search/dist/commands/CONFIG_GET'); CONFIG_SET: typeof import('@redis/search/dist/commands/CONFIG_SET'); configSet: typeof import('@redis/search/dist/commands/CONFIG_SET'); CREATE: typeof import('@redis/search/dist/commands/CREATE'); create: typeof import('@redis/search/dist/commands/CREATE'); CURSOR_DEL: typeof import('@redis/search/dist/commands/CURSOR_DEL'); cursorDel: typeof import('@redis/search/dist/commands/CURSOR_DEL'); CURSOR_READ: typeof import('@redis/search/dist/commands/CURSOR_READ'); cursorRead: typeof import('@redis/search/dist/commands/CURSOR_READ'); DICTADD: typeof import('@redis/search/dist/commands/DICTADD'); dictAdd: typeof import('@redis/search/dist/commands/DICTADD'); DICTDEL: typeof import('@redis/search/dist/commands/DICTDEL'); dictDel: typeof import('@redis/search/dist/commands/DICTDEL'); DICTDUMP: typeof import('@redis/search/dist/commands/DICTDUMP'); dictDump: typeof import('@redis/search/dist/commands/DICTDUMP'); DROPINDEX: typeof import('@redis/search/dist/commands/DROPINDEX'); dropIndex: typeof import('@redis/search/dist/commands/DROPINDEX'); EXPLAIN: typeof import('@redis/search/dist/commands/EXPLAIN'); explain: typeof import('@redis/search/dist/commands/EXPLAIN'); EXPLAINCLI: typeof import('@redis/search/dist/commands/EXPLAINCLI'); explainCli: typeof import('@redis/search/dist/commands/EXPLAINCLI'); INFO: typeof import('@redis/search/dist/commands/INFO'); info: typeof import('@redis/search/dist/commands/INFO'); PROFILESEARCH: typeof import('@redis/search/dist/commands/PROFILE_SEARCH'); profileSearch: typeof import('@redis/search/dist/commands/PROFILE_SEARCH'); PROFILEAGGREGATE: typeof import('@redis/search/dist/commands/PROFILE_AGGREGATE'); profileAggregate: typeof import('@redis/search/dist/commands/PROFILE_AGGREGATE'); SEARCH: typeof import('@redis/search/dist/commands/SEARCH'); search: typeof import('@redis/search/dist/commands/SEARCH'); SPELLCHECK: typeof import('@redis/search/dist/commands/SPELLCHECK'); spellCheck: typeof import('@redis/search/dist/commands/SPELLCHECK'); SUGADD: typeof import('@redis/search/dist/commands/SUGADD'); sugAdd: typeof import('@redis/search/dist/commands/SUGADD'); SUGDEL: typeof import('@redis/search/dist/commands/SUGDEL'); sugDel: typeof import('@redis/search/dist/commands/SUGDEL'); SUGGET_WITHPAYLOADS: typeof import('@redis/search/dist/commands/SUGGET_WITHPAYLOADS'); sugGetWithPayloads: typeof import('@redis/search/dist/commands/SUGGET_WITHPAYLOADS'); SUGGET_WITHSCORES_WITHPAYLOADS: typeof import('@redis/search/dist/commands/SUGGET_WITHSCORES_WITHPAYLOADS'); sugGetWithScoresWithPayloads: typeof import('@redis/search/dist/commands/SUGGET_WITHSCORES_WITHPAYLOADS'); SUGGET_WITHSCORES: typeof import('@redis/search/dist/commands/SUGGET_WITHSCORES'); sugGetWithScores: typeof import('@redis/search/dist/commands/SUGGET_WITHSCORES'); SUGGET: typeof import('@redis/search/dist/commands/SUGGET'); sugGet: typeof import('@redis/search/dist/commands/SUGGET'); SUGLEN: typeof import('@redis/search/dist/commands/SUGLEN'); sugLen: typeof import('@redis/search/dist/commands/SUGLEN'); SYNDUMP: typeof import('@redis/search/dist/commands/SYNDUMP'); synDump: typeof import('@redis/search/dist/commands/SYNDUMP'); SYNUPDATE: typeof import('@redis/search/dist/commands/SYNUPDATE'); synUpdate: typeof import('@redis/search/dist/commands/SYNUPDATE'); TAGVALS: typeof import('@redis/search/dist/commands/TAGVALS'); tagVals: typeof import('@redis/search/dist/commands/TAGVALS');}; ts: {ADD: typeof import('@redis/time-series/dist/commands/ADD'); add: typeof import('@redis/time-series/dist/commands/ADD'); ALTER: typeof import('@redis/time-series/dist/commands/ALTER'); alter: typeof import('@redis/time-series/dist/commands/ALTER'); CREATE: typeof import('@redis/time-series/dist/commands/CREATE'); create: typeof import('@redis/time-series/dist/commands/CREATE'); CREATERULE: typeof import('@redis/time-series/dist/commands/CREATERULE'); createRule: typeof import('@redis/time-series/dist/commands/CREATERULE'); DECRBY: typeof import('@redis/time-series/dist/commands/DECRBY'); decrBy: typeof import('@redis/time-series/dist/commands/DECRBY'); DEL: typeof import('@redis/time-series/dist/commands/DEL'); del: typeof import('@redis/time-series/dist/commands/DEL'); DELETERULE: typeof import('@redis/time-series/dist/commands/DELETERULE'); deleteRule: typeof import('@redis/time-series/dist/commands/DELETERULE'); GET: typeof import('@redis/time-series/dist/commands/GET'); get: typeof import('@redis/time-series/dist/commands/GET'); INCRBY: typeof import('@redis/time-series/dist/commands/INCRBY'); incrBy: typeof import('@redis/time-series/dist/commands/INCRBY'); INFO_DEBUG: typeof import('@redis/time-series/dist/commands/INFO_DEBUG'); infoDebug: typeof import('@redis/time-series/dist/commands/INFO_DEBUG'); INFO: typeof import('@redis/time-series/dist/commands/INFO'); info: typeof import('@redis/time-series/dist/commands/INFO'); MADD: typeof import('@redis/time-series/dist/commands/MADD'); mAdd: typeof import('@redis/time-series/dist/commands/MADD'); MGET: typeof import('@redis/time-series/dist/commands/MGET'); mGet: typeof import('@redis/time-series/dist/commands/MGET'); MGET_WITHLABELS: typeof import('@redis/time-series/dist/commands/MGET_WITHLABELS'); mGetWithLabels: typeof import('@redis/time-series/dist/commands/MGET_WITHLABELS'); QUERYINDEX: typeof import('@redis/time-series/dist/commands/QUERYINDEX'); queryIndex: typeof import('@redis/time-series/dist/commands/QUERYINDEX'); RANGE: typeof import('@redis/time-series/dist/commands/RANGE'); range: typeof import('@redis/time-series/dist/commands/RANGE'); REVRANGE: typeof import('@redis/time-series/dist/commands/REVRANGE'); revRange: typeof import('@redis/time-series/dist/commands/REVRANGE'); MRANGE: typeof import('@redis/time-series/dist/commands/MRANGE'); mRange: typeof import('@redis/time-series/dist/commands/MRANGE'); MRANGE_WITHLABELS: typeof import('@redis/time-series/dist/commands/MRANGE_WITHLABELS'); mRangeWithLabels: typeof import('@redis/time-series/dist/commands/MRANGE_WITHLABELS'); MREVRANGE: typeof import('@redis/time-series/dist/commands/MREVRANGE'); mRevRange: typeof import('@redis/time-series/dist/commands/MREVRANGE'); MREVRANGE_WITHLABELS: typeof import('@redis/time-series/dist/commands/MREVRANGE_WITHLABELS'); mRevRangeWithLabels: typeof import('@redis/time-series/dist/commands/MREVRANGE_WITHLABELS');}; bf: {ADD: typeof import('@redis/bloom/dist/commands/bloom/ADD'); add: typeof import('@redis/bloom/dist/commands/bloom/ADD'); CARD: typeof import('@redis/bloom/dist/commands/bloom/CARD'); card: typeof import('@redis/bloom/dist/commands/bloom/CARD'); EXISTS: typeof import('@redis/bloom/dist/commands/bloom/EXISTS'); exists: typeof import('@redis/bloom/dist/commands/bloom/EXISTS'); INFO: typeof import('@redis/bloom/dist/commands/bloom/INFO'); info: typeof import('@redis/bloom/dist/commands/bloom/INFO'); INSERT: typeof import('@redis/bloom/dist/commands/bloom/INSERT'); insert: typeof import('@redis/bloom/dist/commands/bloom/INSERT'); LOADCHUNK: typeof import('@redis/bloom/dist/commands/bloom/LOADCHUNK'); loadChunk: typeof import('@redis/bloom/dist/commands/bloom/LOADCHUNK'); MADD: typeof import('@redis/bloom/dist/commands/bloom/MADD'); mAdd: typeof import('@redis/bloom/dist/commands/bloom/MADD'); MEXISTS: typeof import('@redis/bloom/dist/commands/bloom/MEXISTS'); mExists: typeof import('@redis/bloom/dist/commands/bloom/MEXISTS'); RESERVE: typeof import('@redis/bloom/dist/commands/bloom/RESERVE'); reserve: typeof import('@redis/bloom/dist/commands/bloom/RESERVE'); SCANDUMP: typeof import('@redis/bloom/dist/commands/bloom/SCANDUMP'); scanDump: typeof import('@redis/bloom/dist/commands/bloom/SCANDUMP');}; cms: {INCRBY: typeof import('@redis/bloom/dist/commands/count-min-sketch/INCRBY'); incrBy: typeof import('@redis/bloom/dist/commands/count-min-sketch/INCRBY'); INFO: typeof import('@redis/bloom/dist/commands/count-min-sketch/INFO'); info: typeof import('@redis/bloom/dist/commands/count-min-sketch/INFO'); INITBYDIM: typeof import('@redis/bloom/dist/commands/count-min-sketch/INITBYDIM'); initByDim: typeof import('@redis/bloom/dist/commands/count-min-sketch/INITBYDIM'); INITBYPROB: typeof import('@redis/bloom/dist/commands/count-min-sketch/INITBYPROB'); initByProb: typeof import('@redis/bloom/dist/commands/count-min-sketch/INITBYPROB'); MERGE: typeof import('@redis/bloom/dist/commands/count-min-sketch/MERGE'); merge: typeof import('@redis/bloom/dist/commands/count-min-sketch/MERGE'); QUERY: typeof import('@redis/bloom/dist/commands/count-min-sketch/QUERY'); query: typeof import('@redis/bloom/dist/commands/count-min-sketch/QUERY');}; cf: {ADD: typeof import('@redis/bloom/dist/commands/cuckoo/ADD'); add: typeof import('@redis/bloom/dist/commands/cuckoo/ADD'); ADDNX: typeof import('@redis/bloom/dist/commands/cuckoo/ADDNX'); addNX: typeof import('@redis/bloom/dist/commands/cuckoo/ADDNX'); COUNT: typeof import('@redis/bloom/dist/commands/cuckoo/COUNT'); count: typeof import('@redis/bloom/dist/commands/cuckoo/COUNT'); DEL: typeof import('@redis/bloom/dist/commands/cuckoo/DEL'); del: typeof import('@redis/bloom/dist/commands/cuckoo/DEL'); EXISTS: typeof import('@redis/bloom/dist/commands/cuckoo/EXISTS'); exists: typeof import('@redis/bloom/dist/commands/cuckoo/EXISTS'); INFO: typeof import('@redis/bloom/dist/commands/cuckoo/INFO'); info: typeof import('@redis/bloom/dist/commands/cuckoo/INFO'); INSERT: typeof import('@redis/bloom/dist/commands/cuckoo/INSERT'); insert: typeof import('@redis/bloom/dist/commands/cuckoo/INSERT'); INSERTNX: typeof import('@redis/bloom/dist/commands/cuckoo/INSERTNX'); insertNX: typeof import('@redis/bloom/dist/commands/cuckoo/INSERTNX'); LOADCHUNK: typeof import('@redis/bloom/dist/commands/cuckoo/LOADCHUNK'); loadChunk: typeof import('@redis/bloom/dist/commands/cuckoo/LOADCHUNK'); RESERVE: typeof import('@redis/bloom/dist/commands/cuckoo/RESERVE'); reserve: typeof import('@redis/bloom/dist/commands/cuckoo/RESERVE'); SCANDUMP: typeof import('@redis/bloom/dist/commands/cuckoo/SCANDUMP'); scanDump: typeof import('@redis/bloom/dist/commands/cuckoo/SCANDUMP');}; tDigest: {ADD: typeof import('@redis/bloom/dist/commands/t-digest/ADD'); add: typeof import('@redis/bloom/dist/commands/t-digest/ADD'); BYRANK: typeof import('@redis/bloom/dist/commands/t-digest/BYRANK'); byRank: typeof import('@redis/bloom/dist/commands/t-digest/BYRANK'); BYREVRANK: typeof import('@redis/bloom/dist/commands/t-digest/BYREVRANK'); byRevRank: typeof import('@redis/bloom/dist/commands/t-digest/BYREVRANK'); CDF: typeof import('@redis/bloom/dist/commands/t-digest/CDF'); cdf: typeof import('@redis/bloom/dist/commands/t-digest/CDF'); CREATE: typeof import('@redis/bloom/dist/commands/t-digest/CREATE'); create: typeof import('@redis/bloom/dist/commands/t-digest/CREATE'); INFO: typeof import('@redis/bloom/dist/commands/t-digest/INFO'); info: typeof import('@redis/bloom/dist/commands/t-digest/INFO'); MAX: typeof import('@redis/bloom/dist/commands/t-digest/MAX'); max: typeof import('@redis/bloom/dist/commands/t-digest/MAX'); MERGE: typeof import('@redis/bloom/dist/commands/t-digest/MERGE'); merge: typeof import('@redis/bloom/dist/commands/t-digest/MERGE'); MIN: typeof import('@redis/bloom/dist/commands/t-digest/MIN'); min: typeof import('@redis/bloom/dist/commands/t-digest/MIN'); QUANTILE: typeof import('@redis/bloom/dist/commands/t-digest/QUANTILE'); quantile: typeof import('@redis/bloom/dist/commands/t-digest/QUANTILE'); RANK: typeof import('@redis/bloom/dist/commands/t-digest/RANK'); rank: typeof import('@redis/bloom/dist/commands/t-digest/RANK'); RESET: typeof import('@redis/bloom/dist/commands/t-digest/RESET'); reset: typeof import('@redis/bloom/dist/commands/t-digest/RESET'); REVRANK: typeof import('@redis/bloom/dist/commands/t-digest/REVRANK'); revRank: typeof import('@redis/bloom/dist/commands/t-digest/REVRANK'); TRIMMED_MEAN: typeof import('@redis/bloom/dist/commands/t-digest/TRIMMED_MEAN'); trimmedMean: typeof import('@redis/bloom/dist/commands/t-digest/TRIMMED_MEAN');}; topK: {ADD: typeof import('@redis/bloom/dist/commands/top-k/ADD'); add: typeof import('@redis/bloom/dist/commands/top-k/ADD'); COUNT: typeof import('@redis/bloom/dist/commands/top-k/COUNT'); count: typeof import('@redis/bloom/dist/commands/top-k/COUNT'); INCRBY: typeof import('@redis/bloom/dist/commands/top-k/INCRBY'); incrBy: typeof import('@redis/bloom/dist/commands/top-k/INCRBY'); INFO: typeof import('@redis/bloom/dist/commands/top-k/INFO'); info: typeof import('@redis/bloom/dist/commands/top-k/INFO'); LIST_WITHCOUNT: typeof import('@redis/bloom/dist/commands/top-k/LIST_WITHCOUNT'); listWithCount: typeof import('@redis/bloom/dist/commands/top-k/LIST_WITHCOUNT'); LIST: typeof import('@redis/bloom/dist/commands/top-k/LIST'); list: typeof import('@redis/bloom/dist/commands/top-k/LIST'); QUERY: typeof import('@redis/bloom/dist/commands/top-k/QUERY'); query: typeof import('@redis/bloom/dist/commands/top-k/QUERY'); RESERVE: typeof import('@redis/bloom/dist/commands/top-k/RESERVE'); reserve: typeof import('@redis/bloom/dist/commands/top-k/RESERVE');};} & RedisModules, RedisFunctions, RedisScripts> | null;
48
+ constructor(settings:Settings) {
49
+ super();
50
+ this._client = null;
51
+ this.settings = settings || {};
52
+ }
53
+
54
+ get isAsync() { return true; }
55
+
56
+ async init() {
57
+ this._client = createClient({url: this.settings.url});
58
+ if (this._client) {
59
+ await this._client.connect();
60
+ await this._client.ping();
61
+ }
62
+ }
63
+
64
+ async get(key:string) {
65
+ if (this._client == null) return null;
66
+ return await this._client.get(key);
67
+ }
68
+
69
+ async findKeys(key:string, notKey:string) {
70
+ if (this._client == null) return null;
71
+ const [type] = /^([^:*]+):\*$/.exec(key) || [];
72
+ if (type != null && ['*:*:*', `${key}:*`].includes(notKey)) {
73
+ // Performance optimization for a common Etherpad case.
74
+ return await this._client.sMembers(`ueberDB:keys:${type}`);
75
+ }
76
+ let keys = await this._client.keys(key.replace(/[?[\]\\]/g, '\\$&'));
77
+ if (notKey != null) {
78
+ const regex = this.createFindRegex(key, notKey);
79
+ keys = keys.filter((k:string) => regex.test(k));
80
+ }
81
+ return keys;
82
+ }
83
+
84
+ async set(key:string, value:string) {
85
+ if (this._client == null) return null;
86
+ const matches = /^([^:]+):([^:]+)$/.exec(key);
87
+ await Promise.all([
88
+ matches && this._client.sAdd(`ueberDB:keys:${matches[1]}`, matches[0]),
89
+ this._client.set(key, value),
90
+ ]);
91
+ }
92
+
93
+ async remove(key:string) {
94
+ if (this._client == null) return null;
95
+ const matches = /^([^:]+):([^:]+)$/.exec(key);
96
+ await Promise.all([
97
+ matches && this._client.sRem(`ueberDB:keys:${matches[1]}`, matches[0]),
98
+ this._client.del(key),
99
+ ]);
100
+ }
101
+
102
+ async doBulk(bulk: BulkObject[]) {
103
+ if (this._client == null) return null;
104
+ const multi = this._client.multi();
105
+
106
+ for (const {key, type, value} of bulk) {
107
+ const matches = /^([^:]+):([^:]+)$/.exec(key);
108
+ if (type === 'set') {
109
+ if (matches) {
110
+ multi.sAdd(`ueberDB:keys:${matches[1]}`, matches[0]);
111
+ }
112
+ multi.set(key, value as string);
113
+ } else if (type === 'remove') {
114
+ if (matches) {
115
+ multi.sRem(`ueberDB:keys:${matches[1]}`, matches[0]);
116
+ }
117
+ multi.del(key);
118
+ }
119
+ }
120
+
121
+ await multi.exec();
122
+ }
123
+
124
+ async close() {
125
+ if (this._client == null) return null;
126
+ await this._client.quit();
127
+ this._client = null;
128
+ }
129
+ };
@@ -1,4 +1,3 @@
1
- 'use strict';
2
1
  /**
3
2
  * 2016 Remi Arnaud
4
3
  *
@@ -15,12 +14,18 @@
15
14
  * limitations under the License.
16
15
  */
17
16
 
18
- const AbstractDatabase = require('../lib/AbstractDatabase');
19
- const r = require('rethinkdb');
20
- const async = require('async');
17
+ import AbstractDatabase, {Settings} from '../lib/AbstractDatabase';
18
+ import r from 'rethinkdb';
19
+ import async from 'async';
20
+ import {BulkObject} from './cassandra_db';
21
21
 
22
- exports.Database = class extends AbstractDatabase {
23
- constructor(settings) {
22
+ export const Database = class extends AbstractDatabase {
23
+ private host: string;
24
+ private db: string;
25
+ private port: number | string;
26
+ private table: string;
27
+ private connection: r.Connection | null;
28
+ constructor(settings:Settings) {
24
29
  super();
25
30
  if (!settings) settings = {};
26
31
  if (!settings.host) { settings.host = 'localhost'; }
@@ -35,7 +40,8 @@ exports.Database = class extends AbstractDatabase {
35
40
  this.connection = null;
36
41
  }
37
42
 
38
- init(callback) {
43
+ init(callback: (p: any, cursor: any)=>{}) {
44
+ // @ts-ignore
39
45
  r.connect(this, (err, conn) => {
40
46
  if (err) throw err;
41
47
  this.connection = conn;
@@ -43,21 +49,25 @@ exports.Database = class extends AbstractDatabase {
43
49
  r.table(this.table).run(this.connection, (err, cursor) => {
44
50
  if (err) {
45
51
  // assuming table does not exists
52
+ // @ts-ignore
46
53
  r.tableCreate(this.table).run(this.connection, callback);
47
54
  } else if (callback) { callback(null, cursor); }
48
55
  });
49
56
  });
50
57
  }
51
58
 
52
- get(key, callback) {
59
+ get(key:string, callback: (err: Error, p: any)=>{}) {
60
+ // @ts-ignore
53
61
  r.table(this.table).get(key).run(this.connection, (err, item) => {
62
+ // @ts-ignore
54
63
  callback(err, (item ? item.content : item));
55
64
  });
56
65
  }
57
66
 
58
- findKeys(key, notKey, callback) {
67
+ findKeys(key:string, notKey:string, callback:()=>{}) {
59
68
  const keys = [];
60
69
  const regex = this.createFindRegex(key, notKey);
70
+ // @ts-ignore
61
71
  r.filter((item) => {
62
72
  if (item.id.search(regex) !== -1) {
63
73
  keys.push(item.id);
@@ -65,15 +75,15 @@ exports.Database = class extends AbstractDatabase {
65
75
  }).run(this.connection, callback);
66
76
  }
67
77
 
68
- set(key, value, callback) {
78
+ set(key:string, value:string, callback:()=>{}) {
69
79
  r.table(this.table)
70
80
  .insert({id: key, content: value}, {conflict: 'replace'})
71
- .run(this.connection, callback);
81
+ .run(this.connection as r.Connection, callback);
72
82
  }
73
83
 
74
- doBulk(bulk, callback) {
75
- const _in = [];
76
- const _out = [];
84
+ doBulk(bulk: BulkObject[], callback: ()=>{}) {
85
+ const _in: any[] = [];
86
+ const _out: string | string[] | r.Expression<any> = [];
77
87
 
78
88
  for (const i in bulk) {
79
89
  if (bulk[i].type === 'set') {
@@ -82,17 +92,23 @@ exports.Database = class extends AbstractDatabase {
82
92
  _out.push(bulk[i].key);
83
93
  }
84
94
  }
95
+
85
96
  async.parallel([
86
- (cb) => { r.table(this.table).insert(_in, {conflict: 'replace'}).run(this.connection, cb); },
87
- (cb) => { r.table(this.table).getAll(_out).delete().run(this.connection, cb); },
97
+ (cb) => { // @ts-ignore
98
+ r.table(this.table).insert(_in, {conflict: 'replace'}).run(this.connection, cb);
99
+ },
100
+ (cb) => { // @ts-ignore
101
+ r.table(this.table).getAll(_out).delete().run(this.connection, cb);
102
+ },
88
103
  ], callback);
89
104
  }
90
105
 
91
- remove(key, callback) {
106
+ remove(key:string, callback:()=>{}) {
107
+ // @ts-ignore
92
108
  r.table(this.table).get(key).delete().run(this.connection, callback);
93
109
  }
94
110
 
95
- close(callback) {
96
- this.connection.close(callback);
111
+ close(callback:()=>{}) {
112
+ if (this.connection) { this.connection.close(callback); }
97
113
  }
98
114
  };
@@ -1,4 +1,7 @@
1
1
  'use strict';
2
+ import {BulkObject} from "./cassandra_db";
3
+ import {Settings} from "../lib/AbstractDatabase";
4
+
2
5
  /**
3
6
  * 2011 Peter 'Pita' Martischka
4
7
  *
@@ -15,9 +18,9 @@
15
18
  * limitations under the License.
16
19
  */
17
20
 
18
- let sqlite3;
21
+ let SQDB: any;
19
22
  try {
20
- sqlite3 = require('sqlite3');
23
+ SQDB = require('sqlite3').Database;
21
24
  } catch (err) {
22
25
  throw new Error(
23
26
  'sqlite3 not found. It was removed from ueberdb\'s dependencies because it requires ' +
@@ -25,13 +28,14 @@ try {
25
28
  '"npm install sqlite3" in your etherpad-lite ./src directory.');
26
29
  }
27
30
 
28
- const AbstractDatabase = require('../lib/AbstractDatabase');
29
- const util = require('util');
31
+ import AbstractDatabase from '../lib/AbstractDatabase';
32
+ import util from 'util';
30
33
 
31
- const escape = (val) => `'${val.replace(/'/g, "''")}'`;
34
+ const escape = (val:string) => `'${val.replace(/'/g, "''")}'`;
32
35
 
33
- exports.Database = class extends AbstractDatabase {
34
- constructor(settings) {
36
+ export const Database = class SQLiteDB extends AbstractDatabase {
37
+ private db: typeof SQDB|null;
38
+ constructor(settings:Settings) {
35
39
  super();
36
40
  this.db = null;
37
41
 
@@ -53,7 +57,15 @@ exports.Database = class extends AbstractDatabase {
53
57
  }
54
58
  }
55
59
 
56
- async _query(sql, params = []) {
60
+ init(callback:Function) {
61
+ util.callbackify(async () => {
62
+ this.db = new SQDB(this.settings.filename as string)
63
+ await this._query('CREATE TABLE IF NOT EXISTS store (key TEXT PRIMARY KEY, value TEXT)');
64
+ // @ts-ignore
65
+ })(callback);
66
+ }
67
+
68
+ async _query(sql:string, params = []) {
57
69
  // It is unclear how util.promisify() deals with variadic functions, so it is not used here.
58
70
  return await new Promise((resolve, reject) => {
59
71
  // According to sqlite3's documentation, .run() method (and maybe .all() and .get(); the
@@ -61,7 +73,7 @@ exports.Database = class extends AbstractDatabase {
61
73
  // guarantees that it is safe to call a Promise executor's resolve and reject functions
62
74
  // multiple times. The subsequent calls are ignored, except Node.js's 'process' object emits a
63
75
  // 'multipleResolves' event to aid in debugging.
64
- this.db.all(sql, params, (err, rows) => {
76
+ this.db&&this.db.all(sql, params, (err:Error, rows:any) => {
65
77
  if (err != null) return reject(err);
66
78
  resolve(rows);
67
79
  });
@@ -70,33 +82,21 @@ exports.Database = class extends AbstractDatabase {
70
82
 
71
83
  // Temporary callbackified version of _query. This will be removed once all database objects are
72
84
  // asyncified.
73
- _queryCb(sql, params, callback) {
85
+ _queryCb(sql: string, params: string[], callback: Function) {
74
86
  // It is unclear how util.callbackify() handles optional parameters, so it is not used here.
75
- const p = this._query(sql, params);
87
+ const p = this._query(sql, params as []);
76
88
  if (callback) p.then((rows) => callback(null, rows), (err) => callback(err || new Error(err)));
77
89
  }
78
90
 
79
- init(callback) {
80
- util.callbackify(async () => {
81
- this.db = await new Promise((resolve, reject) => {
82
- new sqlite3.Database(this.settings.filename, function (err) {
83
- if (err != null) return reject(err);
84
- // The use of `this` relies on an undocumented feature of sqlite3:
85
- // https://github.com/mapbox/node-sqlite3/issues/1408
86
- resolve(this);
87
- });
88
- });
89
- await this._query('CREATE TABLE IF NOT EXISTS store (key TEXT PRIMARY KEY, value TEXT)');
90
- })(callback);
91
- }
92
91
 
93
- get(key, callback) {
92
+
93
+ get(key:string, callback:Function) {
94
94
  this._queryCb(
95
95
  'SELECT value FROM store WHERE key = ?', [key],
96
- (err, rows) => callback(err, err == null && rows && rows.length ? rows[0].value : null));
96
+ (err:Error, rows:any) => callback(err, err == null && rows && rows.length ? rows[0].value : null));
97
97
  }
98
98
 
99
- findKeys(key, notKey, callback) {
99
+ findKeys(key:string, notKey:string, callback:Function) {
100
100
  let query = 'SELECT key FROM store WHERE key LIKE ?';
101
101
  const params = [];
102
102
  // desired keys are %key:%, e.g. pad:%
@@ -110,8 +110,8 @@ exports.Database = class extends AbstractDatabase {
110
110
  params.push(notKey);
111
111
  }
112
112
 
113
- this._queryCb(query, params, (err, results) => {
114
- const value = [];
113
+ this._queryCb(query, params, (err: Error, results: { val: string, key: string }[]) => {
114
+ const value: string[] = [];
115
115
 
116
116
  if (!err && Object.keys(results).length > 0) {
117
117
  results.forEach((val) => {
@@ -123,26 +123,26 @@ exports.Database = class extends AbstractDatabase {
123
123
  });
124
124
  }
125
125
 
126
- set(key, value, callback) {
126
+ set(key:string, value:string, callback:Function) {
127
127
  this._queryCb('REPLACE INTO store VALUES (?,?)', [key, value], callback);
128
128
  }
129
129
 
130
- remove(key, callback) {
130
+ remove(key:string, callback:Function) {
131
131
  this._queryCb('DELETE FROM store WHERE key = ?', [key], callback);
132
132
  }
133
133
 
134
- doBulk(bulk, callback) {
134
+ doBulk(bulk:BulkObject[], callback:Function) {
135
135
  let sql = 'BEGIN TRANSACTION;\n';
136
136
  for (const i in bulk) {
137
137
  if (bulk[i].type === 'set') {
138
- sql += `REPLACE INTO store VALUES (${escape(bulk[i].key)}, ${escape(bulk[i].value)});\n`;
138
+ sql += `REPLACE INTO store VALUES (${escape(bulk[i].key)}, ${escape(bulk[i].value as string)});\n`;
139
139
  } else if (bulk[i].type === 'remove') {
140
140
  sql += `DELETE FROM store WHERE key = ${escape(bulk[i].key)};\n`;
141
141
  }
142
142
  }
143
143
  sql += 'END TRANSACTION;';
144
144
 
145
- this.db.exec(sql, (err) => {
145
+ this.db&&this.db.exec(sql, (err:any) => {
146
146
  if (err) {
147
147
  console.error('ERROR WITH SQL: ');
148
148
  console.error(sql);
@@ -152,7 +152,8 @@ exports.Database = class extends AbstractDatabase {
152
152
  });
153
153
  }
154
154
 
155
- close(callback) {
156
- this.db.close(callback);
155
+ close(callback: Function) {
156
+ callback()
157
+ this.db&&this.db.close((err:any) => callback(err));
157
158
  }
158
159
  };
@@ -0,0 +1,44 @@
1
+ # Docker compose setup for testing with multiple databases
2
+ version: '3.8'
3
+ services:
4
+ couchdb:
5
+ image: couchdb
6
+ ports:
7
+ - "5984:5984"
8
+ environment:
9
+ COUCHDB_USER: ueberdb
10
+ COUCHDB_PASSWORD: ueberdb
11
+ elasticsearch:
12
+ image: elasticsearch:7.17.3
13
+ ports:
14
+ - 9200:9200
15
+ environment:
16
+ discovery.type: single-node
17
+ mongo:
18
+ image: mongo
19
+ ports:
20
+ - 27017:27017
21
+ environment:
22
+ MONGO_INITDB_DATABASE: mydb_test
23
+ mysql:
24
+ image: mariadb
25
+ ports:
26
+ - 3306:3306
27
+ environment:
28
+ MYSQL_ROOT_PASSWORD: password
29
+ MYSQL_USER: ueberdb
30
+ MYSQL_PASSWORD: ueberdb
31
+ MYSQL_DATABASE: ueberdb
32
+ postgres:
33
+ image: postgres:14-alpine
34
+ ports:
35
+ - 5432:5432
36
+ environment:
37
+ POSTGRES_USER: ueberdb
38
+ POSTGRES_PASSWORD: ueberdb
39
+ POSTGRES_DB: ueberdb
40
+ POSTGRES_HOST_AUTH_METHOD: "trust"
41
+ redis:
42
+ image: redis
43
+ ports:
44
+ - "6379:6379"