dobo 2.6.5 → 2.7.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/index.js CHANGED
@@ -81,7 +81,7 @@ const propertyType = {
81
81
  }
82
82
  }
83
83
 
84
- const commonPropertyTypes = ['name', 'type', 'required', 'rules', 'validator', 'ref', 'default']
84
+ const commonPropertyTypes = ['name', 'type', 'required', 'rules', 'validator', 'ref', 'default', 'values', 'rulesMsg']
85
85
 
86
86
  /**
87
87
  * Plugin factory
@@ -10,7 +10,7 @@ import actionFactory from './factory/action.js'
10
10
  * @param {Array} [indexes] - Container array to fill up found index
11
11
  */
12
12
  async function sanitizeProp (model, prop, indexes) {
13
- const { isEmpty, isString, keys, pick } = this.app.lib._
13
+ const { isEmpty, isString, keys, pick, isArray, isPlainObject, camelCase } = this.app.lib._
14
14
  const allPropKeys = this.getAllPropertyKeys(model.connection.driver)
15
15
  const propType = this.constructor.propertyType
16
16
  if (isString(prop)) {
@@ -22,6 +22,12 @@ async function sanitizeProp (model, prop, indexes) {
22
22
  prop.required = required === 'true'
23
23
  }
24
24
  prop.type = prop.type ?? 'string'
25
+ if (isArray(prop.values)) {
26
+ prop.values = prop.values.map(item => {
27
+ if (isPlainObject(item)) return pick(item, ['value', 'text'])
28
+ return { value: item, text: camelCase(item) }
29
+ })
30
+ } else if (!isString(prop.values)) delete prop.values
25
31
  if (prop.index) {
26
32
  if (prop.index === true || prop.index === 'true') prop.index = 'index'
27
33
  const [idx, idxName] = prop.index.split(':')
@@ -110,15 +116,15 @@ async function findAllFeats (model, inputs = [], indexes = [], isExtender) {
110
116
  * @param {Object} model - Model
111
117
  * @param {Array} [inputs] - Array of properties
112
118
  */
113
- async function findAllIndexes (model, inputs = []) {
114
- const indexes = []
119
+ async function findAllIndexes (model, inputs = [], indexes = []) {
120
+ const items = []
115
121
  for (const index of inputs) {
116
122
  index.type = index.type ?? 'index'
117
123
  index.fields = index.fields ?? []
118
124
  if (!index.name) index.name = `${model.name}_${index.fields.join('_')}_${index.type}`
119
- indexes.push(index)
125
+ items.push(index)
120
126
  }
121
- model.indexes = indexes
127
+ model.indexes = [...items, ...indexes]
122
128
  }
123
129
 
124
130
  /**
@@ -262,7 +268,7 @@ async function createSchema (item) {
262
268
  if (!isPlainObject(extender)) this.plugin.fatal('invalidModelExtender%s%s', ns, item.name)
263
269
  await findAllProps.call(this, item, extender.properties ?? [], indexes, true)
264
270
  await findAllFeats.call(this, item, extender.features ?? [], indexes, true)
265
- await findAllIndexes.call(this, item, extender.indexes ?? [], true)
271
+ await findAllIndexes.call(this, item, extender.indexes ?? [], indexes, true)
266
272
  }
267
273
  }
268
274
  }
@@ -305,9 +311,9 @@ async function collectModels () {
305
311
  item.name = item.name ?? defName
306
312
  item.collName = item.collName ?? item.name
307
313
  item.file = file
314
+ item.ns = this.ns
308
315
  const schema = await createSchema.call(me, item)
309
- schema.ns = this.ns
310
- schemas.push(item)
316
+ schemas.push(schema)
311
317
  }, { glob: 'model/*.*', prefix: this.ns })
312
318
  schemas = orderBy(schemas, ['buildLevel', 'name'])
313
319
  for (const schema of schemas) {
@@ -89,8 +89,9 @@ const validator = {
89
89
  timestamp: ['timestamp']
90
90
  }
91
91
 
92
- function buildFromDbModel (opts = {}) {
92
+ async function buildFromDbModel (opts = {}) {
93
93
  const { isPlainObject, get, isEmpty, isString, keys, find, has, without } = this.app.lib._
94
+ const { callHandler } = this.app.bajo
94
95
  const { fields = [], rule = {}, extFields = [] } = opts
95
96
  const obj = {}
96
97
  const { propertyType: propType } = this.app.baseClass.Dobo
@@ -110,7 +111,7 @@ function buildFromDbModel (opts = {}) {
110
111
  return { key, value, columns }
111
112
  }
112
113
 
113
- function applyFieldRules (prop, obj) {
114
+ async function applyFieldRules (prop, obj) {
114
115
  const minMax = { min: false, max: false }
115
116
  const rules = get(rule, prop.name, prop.rules ?? [])
116
117
  if (!Array.isArray(rules)) return rules
@@ -133,8 +134,23 @@ function buildFromDbModel (opts = {}) {
133
134
  if (has(prop, `${k}Length`)) obj = obj[k](prop[`${k}Length`])
134
135
  }
135
136
  }
136
- if (Array.isArray(prop.values)) obj = obj.valid(...prop.values)
137
137
  if (!['id'].includes(prop.name) && prop.required) obj = obj.required()
138
+ if (prop.values) {
139
+ let items = []
140
+ if (Array.isArray(prop.values)) items = prop.values.map(item => item.value)
141
+ else if (typeof prop.values === 'string') {
142
+ const resp = await callHandler(prop.values)
143
+ items = resp.map(item => item.value)
144
+ }
145
+ obj = obj.valid(...items)
146
+ }
147
+ if (prop.rulesMsg) {
148
+ const msgs = {}
149
+ for (const k in prop.rulesMsg) {
150
+ msgs[k] = '~' + prop.rulesMsg[k] // note: to tell bajo error formatter that this is a custom error message
151
+ }
152
+ obj = obj.messages(msgs)
153
+ }
138
154
  return obj
139
155
  }
140
156
 
@@ -147,28 +163,28 @@ function buildFromDbModel (opts = {}) {
147
163
  switch (p.type) {
148
164
  case 'text':
149
165
  case 'string': {
150
- item = applyFieldRules(p, joi.string())
166
+ item = await applyFieldRules(p, joi.string())
151
167
  break
152
168
  }
153
169
  case 'smallint':
154
170
  case 'integer':
155
- item = applyFieldRules(p, joi.number().integer())
171
+ item = await applyFieldRules(p, joi.number().integer())
156
172
  break
157
173
  case 'float':
158
174
  case 'double':
159
- if (p.precision) item = applyFieldRules(p, joi.number().precision(p.precision))
160
- else item = applyFieldRules(p, joi.number())
175
+ if (p.precision) item = await applyFieldRules(p, joi.number().precision(p.precision))
176
+ else item = await applyFieldRules(p, joi.number())
161
177
  break
162
178
  case 'time':
163
179
  case 'date':
164
180
  case 'datetime':
165
- item = applyFieldRules(p, joi.date())
181
+ item = await applyFieldRules(p, joi.date())
166
182
  break
167
183
  case 'timestamp':
168
- item = applyFieldRules(p, joi.number().integer())
184
+ item = await applyFieldRules(p, joi.number().integer())
169
185
  break
170
186
  case 'boolean':
171
- item = applyFieldRules(p, joi.boolean())
187
+ item = await applyFieldRules(p, joi.boolean())
172
188
  break
173
189
  }
174
190
  if (item) {
@@ -218,7 +234,7 @@ async function validate (body, joiModel, opts = {}) {
218
234
  params = defaultsDeep(params, this.app.dobo.config.validationParams)
219
235
  const { rule = {} } = params
220
236
  delete params.rule
221
- if (isEmpty(joiModel)) joiModel = buildFromDbModel.call(this, { fields, rule, extFields, partial })
237
+ if (isEmpty(joiModel)) joiModel = await buildFromDbModel.call(this, { fields, rule, extFields, partial })
222
238
  if (!joiModel) return { value: body }
223
239
  try {
224
240
  return await joiModel.validateAsync(body, params)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dobo",
3
- "version": "2.6.5",
3
+ "version": "2.7.0",
4
4
  "description": "DBMS for Bajo Framework",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wiki/CHANGES.md CHANGED
@@ -1,9 +1,16 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-02-20
4
+
5
+ - [2.7.0] Add ```prop.values``` support
6
+ - [2.7.0] Add ```prop.rulesMsg``` support
7
+ - [2.7.0] Change ```buildFromDbModel()``` on validation to async function
8
+
3
9
  ## 2026-02-17
4
10
 
5
11
  - [2.6.5] Bug fix on model extender
6
12
  - [2.6.5] Bug fix on trace logging
13
+ - [2.6.6] Bug fix on extender indexes
7
14
 
8
15
  ## 2026-02-05
9
16