dobo 2.25.0 → 2.26.1
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/extend/bajo/intl/en-US.json +1 -0
- package/extend/bajo/intl/id.json +1 -0
- package/extend/dobo/driver/memory.js +6 -0
- package/lib/collect-models.js +26 -24
- package/lib/factory/driver.js +26 -26
- package/lib/factory/model/load-fixtures.js +2 -4
- package/package.json +1 -1
- package/wiki/CHANGES.md +7 -0
|
@@ -151,6 +151,7 @@
|
|
|
151
151
|
"duplicateRefKeys%s%s": "Duplicate reference keys found in '%s' (%s)",
|
|
152
152
|
"sanitizeBodyError": "Error sanitizing body",
|
|
153
153
|
"virtualFieldIn%s%s%s": "Virtual field '%s' can't be used in '%s' on %s",
|
|
154
|
+
"noFunctionAllowed%s%s": "Use name handler instead of function in '%s.%s'",
|
|
154
155
|
"field": {
|
|
155
156
|
"id": "ID",
|
|
156
157
|
"code": "Kode",
|
package/extend/bajo/intl/id.json
CHANGED
|
@@ -150,6 +150,7 @@
|
|
|
150
150
|
"duplicateRefKeys%s%s": "Ditemukan kunci referensi duplikat di '%s' (%s)",
|
|
151
151
|
"sanitizeBodyError": "Kesalahan saat sanitasi body",
|
|
152
152
|
"virtualFieldIn%s%s%s": "Kolom virtual '%s' tidak bisa digunakan di '%s' pada %s",
|
|
153
|
+
"noFunctionAllowed%s%s": "Gunakan nama handler, bukan fungsi di '%s.%s'",
|
|
153
154
|
"field": {
|
|
154
155
|
"id": "ID",
|
|
155
156
|
"code": "Kode",
|
|
@@ -129,6 +129,12 @@ async function memoryDriverFactory () {
|
|
|
129
129
|
return result
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
async findOneRecord (model, filter = {}, options = {}) {
|
|
133
|
+
filter.limit = 1
|
|
134
|
+
const result = await this.findRecord(model, filter, options)
|
|
135
|
+
return { data: result.data[0] }
|
|
136
|
+
}
|
|
137
|
+
|
|
132
138
|
async findAllRecord (model, filter = {}, options = {}) {
|
|
133
139
|
const { sort } = filter
|
|
134
140
|
const { data: count = 0 } = await this.countRecord(model, filter, options)
|
package/lib/collect-models.js
CHANGED
|
@@ -290,7 +290,6 @@ async function createSchema (item) {
|
|
|
290
290
|
}
|
|
291
291
|
item.hooks = orderBy(item.hooks, ['name', 'level'])
|
|
292
292
|
delete item.features
|
|
293
|
-
delete item.base
|
|
294
293
|
await sanitizeAll.call(this, item)
|
|
295
294
|
return item
|
|
296
295
|
}
|
|
@@ -304,8 +303,8 @@ async function createSchema (item) {
|
|
|
304
303
|
* @see Dobo#init
|
|
305
304
|
*/
|
|
306
305
|
async function collectModels () {
|
|
307
|
-
const { eachPlugins } = this.app.bajo
|
|
308
|
-
const { orderBy, has,
|
|
306
|
+
const { eachPlugins, callHandler } = this.app.bajo
|
|
307
|
+
const { orderBy, has, omit } = this.app.lib._
|
|
309
308
|
await actionFactory.call(this)
|
|
310
309
|
await modelFactory.call(this)
|
|
311
310
|
|
|
@@ -313,28 +312,31 @@ async function collectModels () {
|
|
|
313
312
|
const me = this
|
|
314
313
|
let schemas = []
|
|
315
314
|
await eachPlugins(async function ({ file }) {
|
|
316
|
-
const { readConfig } = this.app.bajo
|
|
315
|
+
const { readConfig, callHandler } = this.app.bajo
|
|
317
316
|
const { pascalCase } = this.app.lib.aneka
|
|
318
|
-
const { isPlainObject, isEmpty } = this.app.lib._
|
|
317
|
+
const { isPlainObject, isEmpty, isArray } = this.app.lib._
|
|
319
318
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
319
|
+
let items = await readConfig(file, { ns: this.ns, baseNs: me.ns, merge: true })
|
|
320
|
+
if (isEmpty(items)) return undefined
|
|
321
|
+
if (isPlainObject(items)) {
|
|
322
|
+
items.baseName = items.baseName ?? path.basename(file, path.extname(file))
|
|
323
|
+
items.name = items.name ?? pascalCase(`${this.alias} ${items.baseName}`)
|
|
324
|
+
}
|
|
325
|
+
if (!isArray(items)) items = [items]
|
|
326
|
+
for (const item of items) {
|
|
327
|
+
if (!item.baseName) me.fatal('missing%s%s', 'baseName', file)
|
|
328
|
+
item.name = item.name ?? pascalCase(`${this.alias} ${item.baseName}`)
|
|
329
|
+
me.log.trace('- %s', item.name)
|
|
330
|
+
item.collName = item.collName ?? item.name
|
|
331
|
+
item.options = item.options ?? {}
|
|
332
|
+
item.options.attachment = item.options.attachment ?? true
|
|
333
|
+
item.options.persistence = item.options.persistence ?? true
|
|
334
|
+
item.ns = this.ns
|
|
335
|
+
if (item.buildStart) await callHandler(this, item.buildStart, item)
|
|
336
|
+
const schema = await createSchema.call(me, item)
|
|
337
|
+
schemas.push(schema)
|
|
338
|
+
}
|
|
339
|
+
}, { glob: ['model/*.*', 'model.*'], prefix: this.ns })
|
|
338
340
|
schemas = orderBy(schemas, ['buildLevel', 'name'])
|
|
339
341
|
for (const schema of schemas) {
|
|
340
342
|
const plugin = this.app[schema.ns]
|
|
@@ -360,7 +362,7 @@ async function collectModels () {
|
|
|
360
362
|
const prop = model.properties.find(p => p.name === field)
|
|
361
363
|
if (!prop || (prop && prop.virtual)) throw this.error('virtualFieldIn%s%s%s', field, 'scanable', model.name)
|
|
362
364
|
}
|
|
363
|
-
if (
|
|
365
|
+
if (schema.buildEnd) await callHandler(this.app[schema.ns], schema.buildEnd, model)
|
|
364
366
|
}
|
|
365
367
|
schemas = []
|
|
366
368
|
this.log.debug('collected%s%d', this.t('model'), this.models.length)
|
package/lib/factory/driver.js
CHANGED
|
@@ -130,8 +130,8 @@ async function driverFactory () {
|
|
|
130
130
|
const { ns } = this.app.dobo
|
|
131
131
|
const options = last(args)
|
|
132
132
|
if (!options.noDriverHook) {
|
|
133
|
-
await runHook(`${ns}:${name}`, model, ...args)
|
|
134
|
-
await runHook(`${ns}.${camelCase(model.name)}:${name}`, model, ...args)
|
|
133
|
+
await runHook(`${ns}.driver:${name}`, model, ...args)
|
|
134
|
+
await runHook(`${ns}.driver.${camelCase(model.name)}:${name}`, model, ...args)
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -257,9 +257,9 @@ async function driverFactory () {
|
|
|
257
257
|
}
|
|
258
258
|
body = this.sanitizeBody(model, body)
|
|
259
259
|
|
|
260
|
-
await this._attachHook('
|
|
260
|
+
await this._attachHook('beforeCreateRecord', model, body, options)
|
|
261
261
|
const result = await this.createRecord(model, body, options)
|
|
262
|
-
await this._attachHook('
|
|
262
|
+
await this._attachHook('afterCreateRecord', model, body, result, options)
|
|
263
263
|
|
|
264
264
|
if (options.noResult) return
|
|
265
265
|
result.data = this.sanitizeRecord(model, result.data)
|
|
@@ -277,18 +277,18 @@ async function driverFactory () {
|
|
|
277
277
|
bodies[idx] = this.sanitizeBody(model, body)
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
await this._attachHook('
|
|
280
|
+
await this._attachHook('beforeBulkCreateRecord', model, bodies, options)
|
|
281
281
|
const items = chunk(bodies, chunkSize)
|
|
282
282
|
for (const item of items) {
|
|
283
283
|
await this.bulkCreateRecord(model, item, options)
|
|
284
284
|
}
|
|
285
|
-
await this._attachHook('
|
|
285
|
+
await this._attachHook('afterBulkCreateRecord', model, bodies, [], options)
|
|
286
286
|
}
|
|
287
287
|
|
|
288
288
|
async _getRecord (model, id, options = {}) {
|
|
289
|
-
await this._attachHook('
|
|
289
|
+
await this._attachHook('beforeGetRecord', model, id, options)
|
|
290
290
|
const result = await this.getRecord(model, id, options)
|
|
291
|
-
await this._attachHook('
|
|
291
|
+
await this._attachHook('afterGetRecord', model, id, result, options)
|
|
292
292
|
|
|
293
293
|
if (isEmpty(result.data) && options.throwNotFound) throw this.plugin.error('recordNotFound%s%s', id, model.name)
|
|
294
294
|
result.data = this.sanitizeRecord(model, result.data)
|
|
@@ -309,9 +309,9 @@ async function driverFactory () {
|
|
|
309
309
|
body = this.sanitizeBody(model, body, true)
|
|
310
310
|
delete body.id
|
|
311
311
|
|
|
312
|
-
await this._attachHook('
|
|
312
|
+
await this._attachHook('beforeUpdateRecord', model, id, body, options)
|
|
313
313
|
const result = await this.updateRecord(model, id, body, options)
|
|
314
|
-
await this._attachHook('
|
|
314
|
+
await this._attachHook('afterUpdateRecord', model, id, body, result, options)
|
|
315
315
|
|
|
316
316
|
if (options.noResult) return
|
|
317
317
|
result.oldData = this.sanitizeRecord(model, result.oldData)
|
|
@@ -334,9 +334,9 @@ async function driverFactory () {
|
|
|
334
334
|
}
|
|
335
335
|
body = this.sanitizeBody(model, body)
|
|
336
336
|
|
|
337
|
-
await this._attachHook('
|
|
337
|
+
await this._attachHook('beforeUpsertRecord', model, body, options)
|
|
338
338
|
const result = await this.upsertRecord(model, body, options)
|
|
339
|
-
await this._attachHook('
|
|
339
|
+
await this._attachHook('afterUpsertRecord', model, body, result, options)
|
|
340
340
|
|
|
341
341
|
if (options.noResult) return
|
|
342
342
|
if (result.oldData) result.oldData = this.sanitizeRecord(model, result.oldData)
|
|
@@ -352,9 +352,9 @@ async function driverFactory () {
|
|
|
352
352
|
options._data = resp.data
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
await this._attachHook('
|
|
355
|
+
await this._attachHook('beforeRemoveRecord', model, id, options)
|
|
356
356
|
const result = await this.removeRecord(model, id, options)
|
|
357
|
-
await this._attachHook('
|
|
357
|
+
await this._attachHook('afterRemoveRecord', model, id, result, options)
|
|
358
358
|
|
|
359
359
|
if (options.noResult) return
|
|
360
360
|
result.oldData = this.sanitizeRecord(model, result.oldData)
|
|
@@ -363,9 +363,9 @@ async function driverFactory () {
|
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
async _clearRecord (model, options = {}) {
|
|
366
|
-
await this._attachHook('
|
|
366
|
+
await this._attachHook('beforeClearRecord', model, options)
|
|
367
367
|
const result = await this.clearRecord(model, options)
|
|
368
|
-
await this._attachHook('
|
|
368
|
+
await this._attachHook('afterClearRecord', model, result, options)
|
|
369
369
|
|
|
370
370
|
this._injectMeta(result, options)
|
|
371
371
|
return result
|
|
@@ -374,9 +374,9 @@ async function driverFactory () {
|
|
|
374
374
|
async _findRecord (model, filter = {}, options = {}) {
|
|
375
375
|
let result
|
|
376
376
|
try {
|
|
377
|
-
await this._attachHook('
|
|
377
|
+
await this._attachHook('beforeFindRecord', model, filter, options)
|
|
378
378
|
result = await this.findRecord(model, filter, options)
|
|
379
|
-
await this._attachHook('
|
|
379
|
+
await this._attachHook('afterFindRecord', model, filter, result, options)
|
|
380
380
|
} catch (err) {
|
|
381
381
|
if (err.message !== '_emptyColumnQuery') throw err
|
|
382
382
|
result = {
|
|
@@ -396,9 +396,9 @@ async function driverFactory () {
|
|
|
396
396
|
async _findAllRecord (model, filter = {}, options = {}) {
|
|
397
397
|
let result
|
|
398
398
|
try {
|
|
399
|
-
await this._attachHook('
|
|
399
|
+
await this._attachHook('beforeFindAllRecord', model, filter, options)
|
|
400
400
|
result = await this.findAllRecord(model, filter, options)
|
|
401
|
-
await this._attachHook('
|
|
401
|
+
await this._attachHook('afterFindAllRecord', model, filter, result, options)
|
|
402
402
|
} catch (err) {
|
|
403
403
|
if (err.message !== '_emptyColumnQuery') throw err
|
|
404
404
|
result = {
|
|
@@ -418,9 +418,9 @@ async function driverFactory () {
|
|
|
418
418
|
async _countRecord (model, filter = {}, options = {}) {
|
|
419
419
|
let result
|
|
420
420
|
try {
|
|
421
|
-
await this._attachHook('
|
|
421
|
+
await this._attachHook('beforeCountRecord', model, filter, options)
|
|
422
422
|
result = await this.countRecord(model, filter, options)
|
|
423
|
-
await this._attachHook('
|
|
423
|
+
await this._attachHook('afterCountRecord', model, filter, result, options)
|
|
424
424
|
} catch (err) {
|
|
425
425
|
if (err.message !== '_emptyColumnQuery') throw err
|
|
426
426
|
result = { data: 0 }
|
|
@@ -445,9 +445,9 @@ async function driverFactory () {
|
|
|
445
445
|
|
|
446
446
|
let result
|
|
447
447
|
try {
|
|
448
|
-
await this._attachHook('
|
|
448
|
+
await this._attachHook('beforeCreateAggregate', model, filter, params, options)
|
|
449
449
|
result = await this.createAggregate(model, filter, params, options)
|
|
450
|
-
await this._attachHook('
|
|
450
|
+
await this._attachHook('afterCreateAggregate', model, filter, params, result, options)
|
|
451
451
|
} catch (err) {
|
|
452
452
|
if (err.message !== '_emptyColumnQuery') throw err
|
|
453
453
|
result = { data: [] }
|
|
@@ -475,9 +475,9 @@ async function driverFactory () {
|
|
|
475
475
|
|
|
476
476
|
let result
|
|
477
477
|
try {
|
|
478
|
-
await this._attachHook('
|
|
478
|
+
await this._attachHook('beforeCreateHistogram', model, filter, params, options)
|
|
479
479
|
result = await this.createHistogram(model, filter, params, options)
|
|
480
|
-
await this._attachHook('
|
|
480
|
+
await this._attachHook('afterCreateHistogram', model, filter, params, result, options)
|
|
481
481
|
} catch (err) {
|
|
482
482
|
if (err.message !== '_emptyColumnQuery') throw err
|
|
483
483
|
result = { data: [] }
|
|
@@ -26,16 +26,14 @@ async function exec ({ item, spinner, options, result, items } = {}) {
|
|
|
26
26
|
|
|
27
27
|
async function loadFixtures ({ spinner, ignoreError = true, collectItems = false, noLookup = false } = {}, options = {}) {
|
|
28
28
|
const { readConfig } = this.app.bajo
|
|
29
|
-
const {
|
|
29
|
+
const { isSet } = this.app.lib.aneka
|
|
30
30
|
const { isEmpty, isString, isArray, pullAt } = this.app.lib._
|
|
31
31
|
if (this.connection.proxy) {
|
|
32
32
|
this.log.warn('proxiedConnBound%s', this.name)
|
|
33
33
|
return
|
|
34
34
|
}
|
|
35
35
|
const result = { success: 0, failed: 0 }
|
|
36
|
-
const
|
|
37
|
-
const pattern = resolvePath(`${path.dirname(this.options.file)}/../fixture/${base}.*`)
|
|
38
|
-
const items = await readConfig(pattern, { ns: this.plugin.ns, baseNs: 'dobo', checkOverride: true, defValue: [] })
|
|
36
|
+
const items = await readConfig(`${this.plugin.ns}:/extend/dobo/fixture/${this.baseName}.*`, { ns: this.plugin.ns, baseNs: 'dobo', checkOverride: true, defValue: [] })
|
|
39
37
|
const opts = { ...options, noMagic: true }
|
|
40
38
|
for (const item of items) {
|
|
41
39
|
const lv = {}
|
package/package.json
CHANGED
package/wiki/CHANGES.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-05-26
|
|
4
|
+
|
|
5
|
+
- [2.26.0] Add loading multiple model schema as in one ```model.js``` file
|
|
6
|
+
- [2.26.0] Remove caching feature of model schema
|
|
7
|
+
- [2.26.0] Change driver hook name with this syntax: ```dobo.driver:<action>```
|
|
8
|
+
- [2.26.1] Bug fix in ```memory.js```
|
|
9
|
+
|
|
3
10
|
## 2026-05-22
|
|
4
11
|
|
|
5
12
|
- [2.25.0] Add ```array``` & ```object``` validator handling
|