dobo 2.2.0 → 2.2.2
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/index.js +0 -12
- package/lib/collect-models.js +3 -1
- package/lib/factory/driver.js +16 -2
- package/lib/factory/model/_util.js +2 -2
- package/lib/factory/model/create-record.js +1 -1
- package/lib/factory/model/find-all-record.js +1 -1
- package/lib/factory/model/find-record.js +1 -1
- package/lib/factory/model/get-record.js +1 -1
- package/lib/factory/model/remove-record.js +1 -1
- package/lib/factory/model/sanitize-body.js +2 -8
- package/lib/factory/model/update-record.js +1 -1
- package/lib/factory/model/upsert-record.js +1 -1
- package/package.json +2 -2
- package/wiki/CHANGES.md +8 -0
package/index.js
CHANGED
|
@@ -67,22 +67,10 @@ const propertyType = {
|
|
|
67
67
|
validator: 'boolean',
|
|
68
68
|
rules: []
|
|
69
69
|
},
|
|
70
|
-
date: {
|
|
71
|
-
validator: 'date',
|
|
72
|
-
rules: []
|
|
73
|
-
},
|
|
74
70
|
datetime: {
|
|
75
71
|
validator: 'date',
|
|
76
72
|
rules: []
|
|
77
73
|
},
|
|
78
|
-
time: {
|
|
79
|
-
validator: 'date',
|
|
80
|
-
rules: []
|
|
81
|
-
},
|
|
82
|
-
timestamp: {
|
|
83
|
-
validator: 'timestamp',
|
|
84
|
-
rules: []
|
|
85
|
-
},
|
|
86
74
|
object: {
|
|
87
75
|
validator: null,
|
|
88
76
|
rules: []
|
package/lib/collect-models.js
CHANGED
|
@@ -304,13 +304,15 @@ async function collectModels () {
|
|
|
304
304
|
for (const schema of schemas) {
|
|
305
305
|
const plugin = this.app[schema.ns]
|
|
306
306
|
delete schema.ns
|
|
307
|
-
await sanitizeRef.call(this, schema, schemas, true)
|
|
308
307
|
const idProp = schema.properties.find(p => p.name === 'id')
|
|
309
308
|
if (!this.constructor.idTypes.includes(idProp.type)) this.fatal('invalidIdType%s%s', schema.name, this.constructor.idTypes.join(', '))
|
|
310
309
|
if (idProp.type === 'string' && !has(idProp, 'maxLength')) idProp.maxLength = 50
|
|
311
310
|
// schema.properties = without(schema.properties, undefined)
|
|
312
311
|
const model = new DoboModel(plugin, schema)
|
|
313
312
|
me.models.push(model)
|
|
313
|
+
}
|
|
314
|
+
for (const model of me.models) {
|
|
315
|
+
await sanitizeRef.call(this, model, me.models, true)
|
|
314
316
|
me.log.trace('- %s', model.name)
|
|
315
317
|
}
|
|
316
318
|
this.log.debug('collected%s%d', this.t('model'), this.models.length)
|
package/lib/factory/driver.js
CHANGED
|
@@ -34,7 +34,8 @@ async function driverFactory () {
|
|
|
34
34
|
array: false,
|
|
35
35
|
datetime: true
|
|
36
36
|
},
|
|
37
|
-
uniqueIndex: false
|
|
37
|
+
uniqueIndex: false,
|
|
38
|
+
nullableField: true
|
|
38
39
|
}
|
|
39
40
|
this.memory = false
|
|
40
41
|
this.options = options
|
|
@@ -57,6 +58,17 @@ async function driverFactory () {
|
|
|
57
58
|
delete item.id
|
|
58
59
|
}
|
|
59
60
|
for (const prop of model.properties) {
|
|
61
|
+
if (!isSet(item[prop.name]) && !this.support.nullableField) {
|
|
62
|
+
switch (prop.type) {
|
|
63
|
+
case 'datetime': item[prop.name] = new Date(0); break
|
|
64
|
+
case 'float':
|
|
65
|
+
case 'double': item[prop.name] = 0; break
|
|
66
|
+
case 'string':
|
|
67
|
+
case 'text': item[prop.name] = ''; break
|
|
68
|
+
case 'object': item[prop.name] = {}; break
|
|
69
|
+
case 'array': item[prop.name] = []; break
|
|
70
|
+
}
|
|
71
|
+
}
|
|
60
72
|
if (isSet(item[prop.name]) && !this.support.propType[prop.type]) {
|
|
61
73
|
if (prop.type === 'datetime') item[prop.name] = item[prop.name].toISOString()
|
|
62
74
|
else if (['object', 'array'].includes(prop.type)) item[prop.name] = JSON.stringify(item[prop.name])
|
|
@@ -200,7 +212,9 @@ async function driverFactory () {
|
|
|
200
212
|
const resp = await this.getRecord(model, id, { noHook: true })
|
|
201
213
|
if (!resp.data) throw this.plugin.error('recordNotFound%s%s', id, model.name)
|
|
202
214
|
options._data = resp.data
|
|
203
|
-
const
|
|
215
|
+
const input = this.sanitizeBody(model, body)
|
|
216
|
+
delete input.id
|
|
217
|
+
const result = await this.updateRecord(model, id, input, options)
|
|
204
218
|
if (options.noResult) return
|
|
205
219
|
result.oldData = this.sanitizeRecord(model, result.oldData)
|
|
206
220
|
result.data = this.sanitizeRecord(model, result.data)
|
|
@@ -151,7 +151,7 @@ export async function getSingleRef (record = {}, options = {}) {
|
|
|
151
151
|
if (!((typeof options.refs === 'string' && ['*', 'all'].includes(options.refs)) || options.refs.includes(key))) continue
|
|
152
152
|
const ref = prop.ref[key]
|
|
153
153
|
if (ref.fields.length === 0) continue
|
|
154
|
-
const rModel = this.
|
|
154
|
+
const rModel = this.app.dobo.getModel(ref.model)
|
|
155
155
|
const query = {}
|
|
156
156
|
query[ref.propName] = record[prop.name]
|
|
157
157
|
if (ref.propName === 'id') query[ref.propName] = this.sanitizeId(query[ref.propName])
|
|
@@ -182,7 +182,7 @@ export async function getMultiRefs (records = [], options = {}) {
|
|
|
182
182
|
const ref = prop.ref[key]
|
|
183
183
|
if (ref.fields.length === 0) continue
|
|
184
184
|
if (ref.type !== '1:1') continue
|
|
185
|
-
const rModel = this.
|
|
185
|
+
const rModel = this.app.dobo.getModel(ref.model)
|
|
186
186
|
const matches = uniq(map(records, r => {
|
|
187
187
|
let v = r[prop.name]
|
|
188
188
|
if (ref.propName === 'id') v = this.sanitizeId(v)
|
|
@@ -24,7 +24,7 @@ async function createRecord (...args) {
|
|
|
24
24
|
}
|
|
25
25
|
result = result ?? {}
|
|
26
26
|
if (!noResultSanitizer) result.data = await this.sanitizeRecord(result.data, options)
|
|
27
|
-
if (isSet(options.refs)) await getSingleRef.call(this,
|
|
27
|
+
if (isSet(options.refs)) await getSingleRef.call(this, result.data, options)
|
|
28
28
|
await handleReq.call(this, result.data.id, 'created', options)
|
|
29
29
|
await execModelHook.call(this, 'afterCreateRecord', input, result, options)
|
|
30
30
|
await execHook.call(this, 'afterCreateRecord', input, result, options)
|
|
@@ -23,7 +23,7 @@ async function native (filter, options, dataOnly) {
|
|
|
23
23
|
result.data[idx] = await this.sanitizeRecord(result.data[idx], options)
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
if (isSet(options.refs)) await getMultiRefs.call(this,
|
|
26
|
+
if (isSet(options.refs)) await getMultiRefs.call(this, result.data, options)
|
|
27
27
|
await execModelHook.call(this, 'afterFindAllRecord', filter, result, options)
|
|
28
28
|
await execHook.call(this, 'afterFindAllRecord', filter, result, options)
|
|
29
29
|
if (set && !noCache) await set({ model: this.name, filter, options, result })
|
|
@@ -93,7 +93,7 @@ async function findRecord (...args) {
|
|
|
93
93
|
result.data[idx] = await this.sanitizeRecord(result.data[idx], options)
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
if (isSet(options.refs)) await getMultiRefs.call(this,
|
|
96
|
+
if (isSet(options.refs)) await getMultiRefs.call(this, result.data, options)
|
|
97
97
|
await execModelHook.call(this, 'afterFindRecord', filter, result, options)
|
|
98
98
|
await execHook.call(this, 'afterFindRecord', filter, result, options)
|
|
99
99
|
if (!noCache) await runHook('cache:setByFilter', this, filter, result)
|
|
@@ -69,7 +69,7 @@ async function getRecord (...args) {
|
|
|
69
69
|
const result = options.record ?? (await this.driver._getRecord(this, id, options)) ?? {}
|
|
70
70
|
if (isEmpty(result.data) && !options.throwNotFound) return dataOnly ? undefined : { data: undefined }
|
|
71
71
|
if (!noResultSanitizer) result.data = await this.sanitizeRecord(result.data, options)
|
|
72
|
-
if (isSet(options.refs)) await getSingleRef.call(this,
|
|
72
|
+
if (isSet(options.refs)) await getSingleRef.call(this, result.data, options)
|
|
73
73
|
await execModelHook.call(this, 'afterGetRecord', id, result.data, options)
|
|
74
74
|
await execHook.call(this, 'afterGetRecord', id, result, options)
|
|
75
75
|
if (!noCache) await runHook('cache:setById', this, id, result)
|
|
@@ -48,7 +48,7 @@ async function removeRecord (...args) {
|
|
|
48
48
|
return
|
|
49
49
|
}
|
|
50
50
|
if (!noResultSanitizer) result.oldData = await this.sanitizeRecord(result.oldData, options)
|
|
51
|
-
if (isSet(options.refs)) await getSingleRef.call(this,
|
|
51
|
+
if (isSet(options.refs)) await getSingleRef.call(this, result.data, options)
|
|
52
52
|
await handleReq.call(this, result.oldData.id, 'removed', options)
|
|
53
53
|
await execModelHook.call(this, 'afterRemoveRecord', id, result, options)
|
|
54
54
|
await execHook.call(this, 'afterRemoveRecord', id, result, options)
|
|
@@ -16,7 +16,7 @@ async function sanitizeBody ({ body = {}, partial, strict, extFields = [], noDef
|
|
|
16
16
|
const { isSet } = this.app.lib.aneka
|
|
17
17
|
const { callHandler } = this.app.bajo
|
|
18
18
|
const { omit, has, isString, isNaN } = this.app.lib._
|
|
19
|
-
const { sanitizeBoolean, sanitizeDate, sanitizeFloat,
|
|
19
|
+
const { sanitizeBoolean, sanitizeDate, sanitizeFloat, sanitizeInt, sanitizeObject, sanitizeString } = this.app.dobo
|
|
20
20
|
const result = {}
|
|
21
21
|
|
|
22
22
|
const sanitize = (name, type) => {
|
|
@@ -25,14 +25,8 @@ async function sanitizeBody ({ body = {}, partial, strict, extFields = [], noDef
|
|
|
25
25
|
else if (type === 'boolean') result[name] = sanitizeBoolean(result[name])
|
|
26
26
|
else if (['float', 'double'].includes(type)) result[name] = sanitizeFloat(result[name], strict)
|
|
27
27
|
else if (['integer', 'smallint'].includes(type)) result[name] = sanitizeInt(result[name], strict)
|
|
28
|
-
else if (type === 'timestamp') result[name] = sanitizeTimestamp(result[name])
|
|
29
28
|
else if (['string', 'text'].includes(type)) result[name] = sanitizeString(result[name], strict)
|
|
30
|
-
else {
|
|
31
|
-
for (const t of ['datetime|native', 'date|YYYY-MM-DD', 'time|HH:mm:ss']) {
|
|
32
|
-
const [ptype, input] = t.split('|')
|
|
33
|
-
if (ptype === type) result[name] = sanitizeDate(result[name], { input })
|
|
34
|
-
}
|
|
35
|
-
}
|
|
29
|
+
else if (['datetime'].includes(type)) result[name] = sanitizeDate(result[name], { input: 'native' })
|
|
36
30
|
if (!strict && isNaN(result[name])) result[name] = null
|
|
37
31
|
if (['updateRecord', 'upsertRecord'].includes(action) && type === 'string' && result[name] === '') result[name] = null
|
|
38
32
|
}
|
|
@@ -70,7 +70,7 @@ async function updateRecord (...args) {
|
|
|
70
70
|
result.data = await this.sanitizeRecord(result.data, options)
|
|
71
71
|
result.oldData = await this.sanitizeRecord(result.oldData, options)
|
|
72
72
|
}
|
|
73
|
-
if (isSet(options.refs)) await getSingleRef.call(this,
|
|
73
|
+
if (isSet(options.refs)) await getSingleRef.call(this, result.data, options)
|
|
74
74
|
await handleReq.call(this, result.data.id, 'updated', options)
|
|
75
75
|
await execModelHook.call(this, 'afterUpdateRecord', id, input, result, options)
|
|
76
76
|
await execHook.call(this, 'afterUpdateRecord', id, input, result, options)
|
|
@@ -19,7 +19,7 @@ async function native (body = {}, opts = {}) {
|
|
|
19
19
|
return
|
|
20
20
|
}
|
|
21
21
|
if (!noResultSanitizer) result.data = await this.sanitizeRecord(result.data, options)
|
|
22
|
-
if (isSet(options.refs)) await getSingleRef.call(this,
|
|
22
|
+
if (isSet(options.refs)) await getSingleRef.call(this, result.data, options)
|
|
23
23
|
await handleReq.call(this, result.data.id, 'upserted', options)
|
|
24
24
|
await execModelHook.call(this, 'afterUpsertRecord', input, result, options)
|
|
25
25
|
await execHook.call(this, 'afterUpsertRecord', input, result, options)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dobo",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "DBMS for Bajo Framework",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@tryghost/nql": "^0.12.7",
|
|
36
36
|
"joi": "^18.0.2",
|
|
37
|
-
"mingo": "^
|
|
37
|
+
"mingo": "^6.5.1",
|
|
38
38
|
"ulid": "^3.0.2",
|
|
39
39
|
"uuid": "^13.0.0"
|
|
40
40
|
},
|
package/wiki/CHANGES.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-01-18
|
|
4
|
+
|
|
5
|
+
- [2.2.2] Revert back to ```mingo@6.5.1``` because of bugs in ```skip``` operation
|
|
6
|
+
|
|
7
|
+
## 2026-01-16
|
|
8
|
+
|
|
9
|
+
- [2.2.1] Bug fix on model references
|
|
10
|
+
|
|
3
11
|
## 2026-01-11
|
|
4
12
|
|
|
5
13
|
- [2.2.0] Any driver that support memory DB can now declare itself as in-memory DB and be handled as such
|