sorla-db 1.0.0
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/Brainstorming.md +22 -0
- package/LICENSE +21 -0
- package/README.md +31 -0
- package/debug-not.js +24 -0
- package/dist/sorla.min.js +1 -0
- package/example/simple_data_example.html +196 -0
- package/index.js +62 -0
- package/package.json +42 -0
- package/src/collections/collection.js +47 -0
- package/src/dbs/database.js +72 -0
- package/src/documents/cursor.js +144 -0
- package/src/documents/document.js +88 -0
- package/src/helper.js +41 -0
- package/src/query_language/index.js +0 -0
- package/src/query_language/manipulation.js +161 -0
- package/src/query_language/operators.js +289 -0
- package/src/query_language/query.js +104 -0
- package/src/sorla.js +123 -0
- package/src/utils.js +41 -0
- package/test/feature_collection.test.js +73 -0
- package/test/feature_collection_queries.test.js +269 -0
- package/test/unit_database.test.js +36 -0
- package/test/unit_document_test.js +39 -0
- package/test/unit_sorla.test.js +42 -0
- package/test/unit_test.test.js +25 -0
- package/webpack.config.js +11 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const documents = require('../documents/document.js');
|
|
2
|
+
const operatorsCheck = require('./operators.js');
|
|
3
|
+
|
|
4
|
+
class manipulation {
|
|
5
|
+
constructor(validationSchema = null) {
|
|
6
|
+
this.validationSchema = validationSchema;
|
|
7
|
+
this._index = {};
|
|
8
|
+
this._prohibitedCharacters = ['$', '.'];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generates a unique key as a uuid
|
|
13
|
+
* @return string
|
|
14
|
+
*/
|
|
15
|
+
_generateKey() {
|
|
16
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
17
|
+
var r = Math.random() * 16 | 0,
|
|
18
|
+
v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
19
|
+
return v.toString(16)
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Valid and set validation schema for collection
|
|
25
|
+
* @author Anderson Arruda < anderson@sysborg.com.br >
|
|
26
|
+
* @version 1.0.0
|
|
27
|
+
* @param validationSchema
|
|
28
|
+
* @return void
|
|
29
|
+
**/
|
|
30
|
+
set validationSchema(validationSchema)
|
|
31
|
+
{
|
|
32
|
+
if(typeof schemaValidation === 'undefined' || schemaValidation === null)
|
|
33
|
+
return;
|
|
34
|
+
|
|
35
|
+
if(['object', 'function'].indexOf(typeof schemaValidation) == -1)
|
|
36
|
+
{
|
|
37
|
+
throw new Error('Invalid schema validation');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this._validationSchema = validationSchema;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Validate data
|
|
45
|
+
* @param object data
|
|
46
|
+
* @return boolean
|
|
47
|
+
*/
|
|
48
|
+
_validate(data)
|
|
49
|
+
{
|
|
50
|
+
//under construction
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Verify if exists some document that is not object
|
|
56
|
+
* @param array documents
|
|
57
|
+
* @return boolean
|
|
58
|
+
*/
|
|
59
|
+
_validateDocumentsType(documents)
|
|
60
|
+
{
|
|
61
|
+
const count = documents.reduce((acc, doc) => {
|
|
62
|
+
return typeof doc !== 'object' ? ++acc : acc;
|
|
63
|
+
}, 0);
|
|
64
|
+
|
|
65
|
+
return count;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Verify if keys has prohibited characters
|
|
70
|
+
* @param object document
|
|
71
|
+
* @return boolean
|
|
72
|
+
*/
|
|
73
|
+
_validateKeys(document)
|
|
74
|
+
{
|
|
75
|
+
const keys = Object.keys(document);
|
|
76
|
+
const operators = new operatorsCheck();
|
|
77
|
+
for(let key of keys)
|
|
78
|
+
{
|
|
79
|
+
const hasProhibitedCharacters = this._prohibitedCharacters.reduce((acc, char) => {
|
|
80
|
+
return key.indexOf(char) > -1 ? ++acc : acc;
|
|
81
|
+
}, 0);
|
|
82
|
+
|
|
83
|
+
if(hasProhibitedCharacters > 0 && !operators.isOperator(key))
|
|
84
|
+
return false;
|
|
85
|
+
|
|
86
|
+
if(typeof document[key] === 'object')
|
|
87
|
+
return this._validateKeys(document[key]);
|
|
88
|
+
|
|
89
|
+
if(Array.isArray(document[key]))
|
|
90
|
+
{
|
|
91
|
+
for(let value of document[key])
|
|
92
|
+
{
|
|
93
|
+
if(typeof value === 'object')
|
|
94
|
+
return this._validateKeys(value);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Inserts one document to the collection
|
|
104
|
+
* @author Anderson Arruda < anderson@sysborg.com.br >
|
|
105
|
+
* @version 1.0.0
|
|
106
|
+
* @param object document
|
|
107
|
+
* @param function callback - under construction
|
|
108
|
+
* @return void
|
|
109
|
+
**/
|
|
110
|
+
insertOne(document, callback)
|
|
111
|
+
{
|
|
112
|
+
if(typeof document !== 'object' || Array.isArray(document))
|
|
113
|
+
throw new Error('Invalid document type');
|
|
114
|
+
|
|
115
|
+
if(!this._validateKeys(document))
|
|
116
|
+
throw new Error('Invalid document keys');
|
|
117
|
+
|
|
118
|
+
if(typeof document._id === 'undefined')
|
|
119
|
+
{
|
|
120
|
+
let _idKey = '';
|
|
121
|
+
do {
|
|
122
|
+
_idKey = this._generateKey();
|
|
123
|
+
} while(this._documents.find(doc => doc._id === document._id));
|
|
124
|
+
|
|
125
|
+
document._id = _idKey;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if(!this._validate(document))
|
|
129
|
+
throw new Error('Invalid document');
|
|
130
|
+
|
|
131
|
+
this._documents.push(new documents(document));
|
|
132
|
+
|
|
133
|
+
if(typeof callback === 'function')
|
|
134
|
+
callback();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Insert many documents
|
|
139
|
+
* @author Anderson Arruda < anderson@sysborg.com.br >
|
|
140
|
+
* @version 1.0.0
|
|
141
|
+
* @param array documents
|
|
142
|
+
* @param function callback
|
|
143
|
+
* @return void
|
|
144
|
+
*/
|
|
145
|
+
insertMany(documents, callback) {
|
|
146
|
+
console.info(this._validateDocumentsType(documents));
|
|
147
|
+
if(!Array.isArray(documents) || this._validateDocumentsType(documents) > 0)
|
|
148
|
+
throw new Error('Documents must be an array of objects');
|
|
149
|
+
|
|
150
|
+
for(let document of documents)
|
|
151
|
+
this.insertOne(document);
|
|
152
|
+
|
|
153
|
+
if(typeof callback === 'function')
|
|
154
|
+
callback();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
//create index
|
|
158
|
+
//create indexes
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
module.exports = manipulation;
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
class operators {
|
|
2
|
+
/**
|
|
3
|
+
* Constructs the class and creates a property to store fieldname
|
|
4
|
+
*/
|
|
5
|
+
constructor() {
|
|
6
|
+
this._currentField = null;
|
|
7
|
+
this._logicalOperators = ['$or', '$and', '$not', '$nor'];
|
|
8
|
+
this._comparisonOperators = ['$lt', '$lte', '$gt', '$gte', '$eq', '$ne', '$in', '$nin'];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Set current field
|
|
13
|
+
* @param string field
|
|
14
|
+
* @return void
|
|
15
|
+
*/
|
|
16
|
+
set currentField(field) {
|
|
17
|
+
this._currentField = field;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Check if is any operator
|
|
22
|
+
* @param string operator
|
|
23
|
+
* @return boolean
|
|
24
|
+
*/
|
|
25
|
+
isAnyOperator(operator) {
|
|
26
|
+
return this.isLogicalOperator(operator) || this.isOperator(operator);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* check if is logical operator
|
|
31
|
+
* @param string operator
|
|
32
|
+
* @return boolean
|
|
33
|
+
*/
|
|
34
|
+
isLogicalOperator(operator) {
|
|
35
|
+
return this._logicalOperators.indexOf(operator) > -1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Is operators
|
|
40
|
+
* @param string operator
|
|
41
|
+
* @return boolean
|
|
42
|
+
*/
|
|
43
|
+
isOperator(operator) {
|
|
44
|
+
return this._comparisonOperators.indexOf(operator) > -1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Or operator
|
|
49
|
+
* @param array queries
|
|
50
|
+
* @param object doc
|
|
51
|
+
* @return array
|
|
52
|
+
*/
|
|
53
|
+
get $or() {
|
|
54
|
+
return (queries, doc) => {
|
|
55
|
+
if(!Array.isArray(queries))
|
|
56
|
+
throw new Error('The $or operator must be an array');
|
|
57
|
+
|
|
58
|
+
let result = false;
|
|
59
|
+
queryLoop: for(const query of queries) {
|
|
60
|
+
for(const attr of Object.keys(query)) {
|
|
61
|
+
if(this.isLogicalOperator(attr) && this[attr](query[attr], doc))
|
|
62
|
+
{
|
|
63
|
+
result = true;
|
|
64
|
+
continue queryLoop;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if(this.handleComparison(attr, query[attr], doc))
|
|
68
|
+
{
|
|
69
|
+
result = true;
|
|
70
|
+
continue queryLoop;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return result;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* And operator
|
|
81
|
+
* @param array queries
|
|
82
|
+
* @param object doc
|
|
83
|
+
* @return array
|
|
84
|
+
*/
|
|
85
|
+
get $and() {
|
|
86
|
+
return (queries, doc) => {
|
|
87
|
+
if(!Array.isArray(queries))
|
|
88
|
+
throw new Error('The $and operator must be an array');
|
|
89
|
+
|
|
90
|
+
let result = true;
|
|
91
|
+
queryLoop: for(const query of queries) {
|
|
92
|
+
for(const attr of Object.keys(query)) {
|
|
93
|
+
if(this.isLogicalOperator(attr) && !this[attr](query[attr], doc))
|
|
94
|
+
{
|
|
95
|
+
result = false;
|
|
96
|
+
continue queryLoop;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if(!this.handleComparison(attr, query[attr], doc))
|
|
100
|
+
{
|
|
101
|
+
result = false;
|
|
102
|
+
continue queryLoop;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return result;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Not operator
|
|
113
|
+
* @param array queries
|
|
114
|
+
* @param object doc
|
|
115
|
+
* @return array
|
|
116
|
+
*/
|
|
117
|
+
get $not() {
|
|
118
|
+
const self = this;
|
|
119
|
+
return (queries, doc) => {
|
|
120
|
+
if(typeof queries !== 'object')
|
|
121
|
+
throw new Error('The $not operator must be an object');
|
|
122
|
+
|
|
123
|
+
const handledComparison = self.handleComparison(this._currentField, queries, doc);
|
|
124
|
+
return !handledComparison;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Nor operator
|
|
130
|
+
* @param array queries
|
|
131
|
+
* @param object doc
|
|
132
|
+
* @return array
|
|
133
|
+
*/
|
|
134
|
+
get $nor() {
|
|
135
|
+
return (queries, doc) => {
|
|
136
|
+
if(!Array.isArray(queries))
|
|
137
|
+
throw new Error('The $nor operator must be an array');
|
|
138
|
+
|
|
139
|
+
for(const query of queries) {
|
|
140
|
+
for(const attr of Object.keys(query)) {
|
|
141
|
+
if(this.isLogicalOperator(attr) && this[attr](query[attr], doc))
|
|
142
|
+
return false;
|
|
143
|
+
|
|
144
|
+
if(this.handleComparison(attr, query[attr], doc))
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return true;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Not in operator
|
|
155
|
+
* @param mixed doc_value
|
|
156
|
+
* @param array queries
|
|
157
|
+
* @return boolean
|
|
158
|
+
*/
|
|
159
|
+
get $nin() {
|
|
160
|
+
return (doc_value, queries) => {
|
|
161
|
+
if(!Array.isArray(queries))
|
|
162
|
+
throw new Error('The $nin operator must be an array');
|
|
163
|
+
|
|
164
|
+
return !this.$in(doc_value, queries);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* In operator
|
|
170
|
+
* @param mixed doc_value
|
|
171
|
+
* @param array queries
|
|
172
|
+
* @return boolean
|
|
173
|
+
*/
|
|
174
|
+
get $in() {
|
|
175
|
+
return (doc_value, queries) => {
|
|
176
|
+
if(!Array.isArray(queries))
|
|
177
|
+
throw new Error('The $in operator must be an array');
|
|
178
|
+
|
|
179
|
+
if(Array.isArray(doc_value))
|
|
180
|
+
{
|
|
181
|
+
for(const value of queries)
|
|
182
|
+
{
|
|
183
|
+
if(doc_value.indexOf(value) > -1)
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return queries.indexOf(doc_value) > -1;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* less than
|
|
194
|
+
* @param mixed doc_value
|
|
195
|
+
* @param mixed query
|
|
196
|
+
* @return boolean
|
|
197
|
+
*/
|
|
198
|
+
get $lt() {
|
|
199
|
+
return (doc_value, query) => {
|
|
200
|
+
return !Array.isArray(query) ? doc_value < query : false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* less than or equal
|
|
206
|
+
* @param mixed doc_value
|
|
207
|
+
* @param mixed query
|
|
208
|
+
* @return boolean
|
|
209
|
+
*/
|
|
210
|
+
get $lte() {
|
|
211
|
+
return (doc_value, query) => {
|
|
212
|
+
return !Array.isArray(query) ? doc_value <= query : false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* greater than
|
|
218
|
+
* @param mixed doc_value
|
|
219
|
+
* @param mixed query
|
|
220
|
+
* @return boolean
|
|
221
|
+
*/
|
|
222
|
+
get $gt() {
|
|
223
|
+
return (doc_value, query) => {
|
|
224
|
+
return !Array.isArray(query) ? doc_value > query : false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* greater than or equal
|
|
230
|
+
* @param mixed doc_value
|
|
231
|
+
* @param mixed query
|
|
232
|
+
* @return boolean
|
|
233
|
+
*/
|
|
234
|
+
get $gte() {
|
|
235
|
+
return (doc_value, query) => {
|
|
236
|
+
return !Array.isArray(query) ? doc_value >= query : false;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* not equal
|
|
242
|
+
* @param mixed doc_value
|
|
243
|
+
* @param mixed query
|
|
244
|
+
* @return boolean
|
|
245
|
+
*/
|
|
246
|
+
get $ne() {
|
|
247
|
+
return (doc_value, query) => {
|
|
248
|
+
return !Array.isArray(query) ? doc_value !== query : false;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* equal
|
|
254
|
+
* @param mixed doc_value
|
|
255
|
+
* @param mixed query
|
|
256
|
+
* @return boolean
|
|
257
|
+
*/
|
|
258
|
+
get $eq() {
|
|
259
|
+
return (doc_value, query) => {
|
|
260
|
+
return !Array.isArray(query) ? doc_value === query : false;
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Handling with comparison of columns
|
|
266
|
+
* @param string field
|
|
267
|
+
* @param mixed query
|
|
268
|
+
* @param object doc
|
|
269
|
+
* @return boolean
|
|
270
|
+
*/
|
|
271
|
+
handleComparison(field, query, doc) {
|
|
272
|
+
if(typeof doc[field] === 'undefined' && typeof doc[this._currentField] === 'undefined')
|
|
273
|
+
return false;
|
|
274
|
+
|
|
275
|
+
if(this.isOperator(field))
|
|
276
|
+
return this[field](doc[this._currentField], query);
|
|
277
|
+
|
|
278
|
+
if(typeof query === 'object')
|
|
279
|
+
{
|
|
280
|
+
const operator = Object.keys(query)[0];
|
|
281
|
+
field = typeof field === 'undefined' ? this._currentField : field;
|
|
282
|
+
return this[operator](doc[field], query[operator]);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return this.$eq(doc[field], query);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
module.exports = operators;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const manipulation = require('./manipulation.js');
|
|
2
|
+
const operators = require('./operators.js');
|
|
3
|
+
const cursor = require('../documents/cursor.js');
|
|
4
|
+
|
|
5
|
+
class query extends manipulation
|
|
6
|
+
{
|
|
7
|
+
constructor(validationSchema)
|
|
8
|
+
{
|
|
9
|
+
super(validationSchema);
|
|
10
|
+
this._operators = new operators();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Count documents
|
|
15
|
+
* @return int
|
|
16
|
+
*/
|
|
17
|
+
count()
|
|
18
|
+
{
|
|
19
|
+
return this._documents.length;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Deeps find in object
|
|
24
|
+
* @param object query
|
|
25
|
+
* @param object projection
|
|
26
|
+
* @param bool firstOne
|
|
27
|
+
* @return array
|
|
28
|
+
*/
|
|
29
|
+
_deepFind(query, projection, single=false)
|
|
30
|
+
{
|
|
31
|
+
const c = new cursor();
|
|
32
|
+
const find = (documents, query, single, debug=false) => {
|
|
33
|
+
let finded = [];
|
|
34
|
+
const queryKeys = Object.keys(query);
|
|
35
|
+
docsLoop: for(let doc of documents)
|
|
36
|
+
{
|
|
37
|
+
for(let k of queryKeys)
|
|
38
|
+
{
|
|
39
|
+
if(!this._operators.isAnyOperator(k))
|
|
40
|
+
{
|
|
41
|
+
this._operators.currentField = k;
|
|
42
|
+
|
|
43
|
+
if(typeof query[k] === 'object')
|
|
44
|
+
{
|
|
45
|
+
if(find([doc], query[k], single).length === 0)
|
|
46
|
+
{
|
|
47
|
+
continue docsLoop;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const isLogicalOperator = this._operators.isLogicalOperator(k);
|
|
55
|
+
if((isLogicalOperator && !this._operators[k](query[k], doc)) || (!isLogicalOperator && !this._operators.handleComparison(k, query[k], doc)))
|
|
56
|
+
{
|
|
57
|
+
continue docsLoop;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
finded.push(doc.clone());
|
|
62
|
+
if(single) break;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return finded;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const result = find(this._documents, query, single);
|
|
69
|
+
const finded = new cursor(result, projection);
|
|
70
|
+
|
|
71
|
+
return finded;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Find one document
|
|
76
|
+
* @param query
|
|
77
|
+
* @param projection
|
|
78
|
+
* @return object
|
|
79
|
+
*/
|
|
80
|
+
findOne(query, projection = null)
|
|
81
|
+
{
|
|
82
|
+
const finded = this._deepFind(query, projection, true);
|
|
83
|
+
return finded.first();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Find documents
|
|
88
|
+
* @param query
|
|
89
|
+
* @param projection
|
|
90
|
+
* @return array
|
|
91
|
+
*/
|
|
92
|
+
find(query, projection = null)
|
|
93
|
+
{
|
|
94
|
+
const finded = this._deepFind(query, projection);
|
|
95
|
+
return finded;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//find
|
|
99
|
+
//find one and delete
|
|
100
|
+
//find one and update
|
|
101
|
+
//find one and replace
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = query;
|
package/src/sorla.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const database = require('./dbs/database.js');
|
|
2
|
+
|
|
3
|
+
class sorla{
|
|
4
|
+
/**
|
|
5
|
+
* Constructs class Sorla to manage databases
|
|
6
|
+
* @author Anderson Arruda < andmarruda@gmail.com >
|
|
7
|
+
* @version 1.0.0
|
|
8
|
+
* @param
|
|
9
|
+
* @return void
|
|
10
|
+
*/
|
|
11
|
+
constructor()
|
|
12
|
+
{
|
|
13
|
+
this._dbs = [];
|
|
14
|
+
this._selectedDb = null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Search a database`s position in the list of databases by its name and mark it as selected
|
|
19
|
+
* @author Anderson Arruda < andmarruda@gmail.com >
|
|
20
|
+
* @version
|
|
21
|
+
* @param
|
|
22
|
+
* @return
|
|
23
|
+
**/
|
|
24
|
+
_findDbIndex(name)
|
|
25
|
+
{
|
|
26
|
+
return this._dbs.findIndex(db => db.name == name);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Verify if a database name already exists in the list of databases
|
|
31
|
+
* @author Anderson Arruda < andmarruda@gmail.com >
|
|
32
|
+
* @version 1.0.0
|
|
33
|
+
* @param string name
|
|
34
|
+
* @return boolean
|
|
35
|
+
*/
|
|
36
|
+
dbExists(name)
|
|
37
|
+
{
|
|
38
|
+
return this._findDbIndex(name) > -1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Mark a database as selected
|
|
43
|
+
* @author Anderson Arruda < andmarruda@gmail.com >
|
|
44
|
+
* @version 1.0.0
|
|
45
|
+
* @param
|
|
46
|
+
* @return
|
|
47
|
+
**/
|
|
48
|
+
_selectDb(pos)
|
|
49
|
+
{
|
|
50
|
+
if(!this._dbs.hasOwnProperty(pos))
|
|
51
|
+
{
|
|
52
|
+
throw new Error('Database does not exists');
|
|
53
|
+
}
|
|
54
|
+
this._selectedDb = this._dbs[pos];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Creates a new database
|
|
59
|
+
* @author Anderson Arruda < andmarruda@gmail.com >
|
|
60
|
+
* @version 1.0.0
|
|
61
|
+
* @param string name
|
|
62
|
+
* @return int "The position of the new database in the list of databases"
|
|
63
|
+
**/
|
|
64
|
+
createDb(name)
|
|
65
|
+
{
|
|
66
|
+
if(this.dbExists(name))
|
|
67
|
+
{
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let pos = this._dbs.length;
|
|
72
|
+
this._dbs.push(new database(name));
|
|
73
|
+
return pos;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Selects a database by its name or creates a new one if it does not exists and then selects it
|
|
78
|
+
* @author Anderson Arruda < andmarruda@gmail.com >
|
|
79
|
+
* @version 1.0.0
|
|
80
|
+
* @param string name
|
|
81
|
+
* @return void
|
|
82
|
+
**/
|
|
83
|
+
useDb(name)
|
|
84
|
+
{
|
|
85
|
+
let pos = null;
|
|
86
|
+
if(!this.dbExists(name))
|
|
87
|
+
{
|
|
88
|
+
pos = this.createDb(name);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
this._selectDb(pos === null ? this._findDbIndex(name) : pos);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get the number of created databases
|
|
96
|
+
* @author Anderson Arruda < andmarruda@gmail.com >
|
|
97
|
+
* @version 1.0.0
|
|
98
|
+
* @param
|
|
99
|
+
* @return int
|
|
100
|
+
**/
|
|
101
|
+
countDb()
|
|
102
|
+
{
|
|
103
|
+
return this._dbs.length;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Return selected db
|
|
108
|
+
* @author Anderson Arruda < anderson@sysborg.com.br >
|
|
109
|
+
* @version 1.0.0
|
|
110
|
+
* @param
|
|
111
|
+
* @return instanceof database
|
|
112
|
+
**/
|
|
113
|
+
get db()
|
|
114
|
+
{
|
|
115
|
+
return this._selectedDb;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = sorla;
|
|
120
|
+
if(typeof window !== 'undefined')
|
|
121
|
+
{
|
|
122
|
+
window.sorla = sorla;
|
|
123
|
+
}
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
class utils
|
|
2
|
+
{
|
|
3
|
+
/**
|
|
4
|
+
* Get a uuid v4 string
|
|
5
|
+
* @author Anderson Arruda < anderson@sysborg.com.br >
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
* @param
|
|
8
|
+
* @return string
|
|
9
|
+
**/
|
|
10
|
+
get uuid()
|
|
11
|
+
{
|
|
12
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c)
|
|
13
|
+
{
|
|
14
|
+
let r = Math.random() * 16 | 0,
|
|
15
|
+
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
16
|
+
|
|
17
|
+
return v.toString(16);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get data using dots to access subfields
|
|
23
|
+
* @param object data
|
|
24
|
+
* @param string field
|
|
25
|
+
*/
|
|
26
|
+
getDotData(data, field)
|
|
27
|
+
{
|
|
28
|
+
let fields = field.split('.');
|
|
29
|
+
|
|
30
|
+
fields.forEach(field => {
|
|
31
|
+
if(typeof data[field] !== 'undefined')
|
|
32
|
+
{
|
|
33
|
+
data = data[field];
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = utils;
|