dobo 1.0.2 → 1.0.4
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/bajo/.alias +1 -0
- package/bajo/config.json +12 -2
- package/bajo/init.js +14 -3
- package/bajo/method/attachment/create.js +1 -1
- package/bajo/method/attachment/get-path.js +1 -1
- package/bajo/method/attachment/get.js +1 -1
- package/bajo/method/attachment/remove.js +1 -1
- package/bajo/method/build-query.js +1 -0
- package/bajo/method/bulk/create.js +6 -6
- package/bajo/method/get-connection.js +6 -0
- package/bajo/method/get-info.js +2 -2
- package/bajo/method/get-schema.js +2 -2
- package/bajo/method/model/clear.js +7 -5
- package/bajo/method/model/create.js +10 -2
- package/bajo/method/model/drop.js +10 -2
- package/bajo/method/model/exists.js +9 -2
- package/bajo/method/pick-record.js +14 -8
- package/bajo/method/prep-pagination.js +5 -9
- package/bajo/method/record/clear.js +8 -7
- package/bajo/method/record/create.js +26 -28
- package/bajo/method/record/find-one.js +10 -9
- package/bajo/method/record/find.js +11 -9
- package/bajo/method/record/get.js +10 -9
- package/bajo/method/record/remove.js +13 -12
- package/bajo/method/record/update.js +22 -25
- package/bajo/method/record/upsert.js +4 -3
- package/bajo/method/sanitize/body.js +8 -9
- package/bajo/method/stat/aggregate.js +6 -6
- package/bajo/method/stat/histogram.js +5 -5
- package/bajo/method/validate.js +23 -20
- package/bajo/start.js +6 -2
- package/bajoCli/applet/connection.js +1 -1
- package/bajoCli/applet/lib/post-process.js +13 -13
- package/bajoCli/applet/model-clear.js +2 -2
- package/bajoCli/applet/model-rebuild.js +12 -9
- package/bajoCli/applet/record-create.js +2 -2
- package/bajoCli/applet/record-find.js +2 -2
- package/bajoCli/applet/record-get.js +2 -2
- package/bajoCli/applet/record-remove.js +2 -2
- package/bajoCli/applet/record-update.js +2 -2
- package/bajoCli/applet/schema.js +1 -1
- package/bajoCli/applet/stat-count.js +2 -2
- package/bajoI18N/resource/en-US.json +28 -27
- package/bajoI18N/resource/id.json +60 -27
- package/lib/add-fixtures.js +5 -4
- package/lib/check-unique.js +2 -2
- package/lib/collect-connections.js +3 -4
- package/lib/collect-drivers.js +11 -3
- package/lib/collect-feature.js +6 -5
- package/lib/collect-schemas.js +9 -8
- package/lib/exec-validation.js +8 -14
- package/lib/generic-prop-sanitizer.js +1 -1
- package/lib/mem-db/conn-sanitizer.js +8 -0
- package/lib/mem-db/instantiate.js +41 -0
- package/lib/mem-db/method/model/clear.js +6 -0
- package/lib/mem-db/method/model/create.js +5 -0
- package/lib/mem-db/method/model/drop.js +5 -0
- package/lib/mem-db/method/model/exists.js +5 -0
- package/lib/mem-db/method/record/create.js +12 -0
- package/lib/mem-db/method/record/find.js +20 -0
- package/lib/mem-db/method/record/get.js +9 -0
- package/lib/mem-db/method/record/remove.js +13 -0
- package/lib/mem-db/method/record/update.js +15 -0
- package/lib/mem-db/method/stat/count.js +11 -0
- package/lib/mem-db/start.js +25 -0
- package/lib/resolve-method.js +4 -3
- package/lib/sanitize-schema.js +21 -9
- package/package.json +4 -3
- package/bajo/hook/bajoI18N@before-init.js +0 -6
- package/bajoCli/applet/shell.js +0 -48
- /package/bajo/hook/{bajoI18N.db@before-resource-merge.js → bajo-i18n.db@before-resource-merge.js} +0 -0
|
@@ -6,54 +6,51 @@ import execFeatureHook from '../../../lib/exec-feature-hook.js'
|
|
|
6
6
|
|
|
7
7
|
async function update (name, id, input, opts = {}) {
|
|
8
8
|
const { runHook, isSet } = this.app.bajo
|
|
9
|
-
const {
|
|
10
|
-
const {
|
|
11
|
-
const options = cloneDeep(opts)
|
|
9
|
+
const { clearModel } = this.cache ?? {}
|
|
10
|
+
const { forOwn, find, cloneDeep, camelCase, omit, get } = this.app.bajo.lib._
|
|
11
|
+
const options = cloneDeep(omit(opts, ['req']))
|
|
12
|
+
options.req = opts.req
|
|
12
13
|
options.dataOnly = options.dataOnly ?? true
|
|
13
14
|
input = cloneDeep(input)
|
|
14
|
-
const { fields, dataOnly, noHook, noValidation, noCheckUnique, noFeatureHook, noResult, noSanitize, partial = true, hidden } = options
|
|
15
|
+
const { fields, dataOnly, noHook, noValidation, noCheckUnique, noFeatureHook, noResult, noSanitize, partial = true, hidden, forceNoHidden } = options
|
|
15
16
|
options.dataOnly = true
|
|
16
17
|
options.truncateString = options.truncateString ?? true
|
|
17
18
|
await this.modelExists(name, true)
|
|
18
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'record-update')
|
|
19
|
+
const { handler, schema, driver } = await resolveMethod.call(this, name, 'record-update', options)
|
|
19
20
|
id = this.sanitizeId(id, schema)
|
|
20
|
-
|
|
21
|
+
const extFields = get(options, 'validation.extFields', [])
|
|
22
|
+
let body = noSanitize ? input : await this.sanitizeBody({ body: input, schema, partial, strict: true, extFields })
|
|
21
23
|
delete body.id
|
|
22
24
|
if (!noHook) {
|
|
23
|
-
await runHook(`${this.name}:
|
|
24
|
-
await runHook(`${this.name}.${name}:
|
|
25
|
+
await runHook(`${this.name}:beforeRecordUpdate`, name, id, body, options)
|
|
26
|
+
await runHook(`${this.name}.${camelCase(name)}:beforeRecordUpdate`, id, body, options)
|
|
25
27
|
}
|
|
26
28
|
if (!noFeatureHook) await execFeatureHook.call(this, 'beforeUpdate', { schema, body })
|
|
27
|
-
if (!noValidation) body = await execValidation.call(this, {
|
|
29
|
+
if (!noValidation) body = await execValidation.call(this, { name, body, options, partial })
|
|
28
30
|
if (!noCheckUnique) await checkUnique.call(this, { schema, body, id })
|
|
29
|
-
let record
|
|
30
31
|
const nbody = {}
|
|
31
32
|
forOwn(body, (v, k) => {
|
|
32
33
|
if (v === undefined) return undefined
|
|
33
34
|
const prop = find(schema.properties, { name: k })
|
|
34
|
-
if (
|
|
35
|
+
if (!prop) return undefined
|
|
36
|
+
if (options.truncateString && isSet(v) && ['string', 'text'].includes(prop.type)) v = v.slice(0, prop.maxLength)
|
|
35
37
|
nbody[k] = v
|
|
36
38
|
})
|
|
37
39
|
delete nbody.id
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (options.req) {
|
|
41
|
-
|
|
42
|
-
if (options.req.flash) options.req.flash('dbsuccess', { message: this.print.write('Record successfully updated'), record })
|
|
43
|
-
}
|
|
44
|
-
} catch (err) {
|
|
45
|
-
if (get(options, 'req.flash')) options.req.flash('dberr', err)
|
|
46
|
-
throw err
|
|
40
|
+
const record = await handler.call(this.app[driver.ns], { schema, id, body: nbody, options })
|
|
41
|
+
if (options.req) {
|
|
42
|
+
if (options.req.file) await handleAttachmentUpload.call(this, { name: schema.name, id, body, options, action: 'update' })
|
|
43
|
+
if (options.req.flash && !options.noFlash) options.req.flash('notify', options.req.t('Record successfully updated'))
|
|
47
44
|
}
|
|
48
45
|
if (!noFeatureHook) await execFeatureHook.call(this, 'afterUpdate', { schema, body: nbody, record })
|
|
49
46
|
if (!noHook) {
|
|
50
|
-
await runHook(`${this.name}.${name}:
|
|
51
|
-
await runHook(`${this.name}:
|
|
47
|
+
await runHook(`${this.name}.${camelCase(name)}:afterRecordUpdate`, id, nbody, options, record)
|
|
48
|
+
await runHook(`${this.name}:afterRecordUpdate`, name, id, nbody, options, record)
|
|
52
49
|
}
|
|
53
|
-
if (
|
|
50
|
+
if (clearModel) await clearModel({ model: name, id, body: nbody, options, record })
|
|
54
51
|
if (noResult) return
|
|
55
|
-
record.oldData = await this.pickRecord({ record: record.oldData, fields, schema, hidden })
|
|
56
|
-
record.data = await this.pickRecord({ record: record.data, fields, schema, hidden })
|
|
52
|
+
record.oldData = await this.pickRecord({ record: record.oldData, fields, schema, hidden, forceNoHidden })
|
|
53
|
+
record.data = await this.pickRecord({ record: record.data, fields, schema, hidden, forceNoHidden })
|
|
57
54
|
return dataOnly ? record.data : record
|
|
58
55
|
}
|
|
59
56
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
async function upsert (name, input, opts = {}) {
|
|
2
2
|
const { generateId } = this.app.bajo
|
|
3
3
|
const { find } = this.app.bajo.lib._
|
|
4
|
-
const { cloneDeep } = this.app.bajo.lib._
|
|
5
|
-
const options = cloneDeep(opts)
|
|
4
|
+
const { cloneDeep, omit } = this.app.bajo.lib._
|
|
5
|
+
const options = cloneDeep(omit(opts, ['req']))
|
|
6
|
+
options.req = opts.req
|
|
6
7
|
options.dataOnly = options.dataOnly ?? true
|
|
7
8
|
await this.modelExists(name, true)
|
|
8
9
|
const { schema } = this.getInfo(name)
|
|
@@ -11,7 +12,7 @@ async function upsert (name, input, opts = {}) {
|
|
|
11
12
|
if (idField.type === 'string') id = input.id ?? generateId()
|
|
12
13
|
else if (idField.type === 'integer') id = input.id ?? generateId('int')
|
|
13
14
|
id = this.sanitizeId(id, schema)
|
|
14
|
-
const old = await this.recordGet(name, id, { thrownNotFound: false, dataOnly: true, noHook: true, noCache: true })
|
|
15
|
+
const old = await this.recordGet(name, id, { thrownNotFound: false, dataOnly: true, noHook: true, noCache: true, force: true, hidden: options.hidden, forceNoHidden: options.forceNoHidden })
|
|
15
16
|
if (old) return await this.recordUpdate(name, id, input, options)
|
|
16
17
|
return await this.recordCreate(name, input, options)
|
|
17
18
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
async function sanitizeBody ({ body = {}, schema = {}, partial, strict }) {
|
|
2
|
-
const { isSet, dayjs } = this.app.bajo
|
|
3
|
-
const { has,
|
|
1
|
+
async function sanitizeBody ({ body = {}, schema = {}, partial, strict, extFields = [] }) {
|
|
2
|
+
const { isSet, dayjs, callHandler } = this.app.bajo
|
|
3
|
+
const { has, isString, isNumber, concat } = this.app.bajo.lib._
|
|
4
4
|
const result = {}
|
|
5
|
-
for (const p of schema.properties) {
|
|
5
|
+
for (const p of concat(schema.properties, extFields)) {
|
|
6
6
|
if (partial && !has(body, p.name)) continue
|
|
7
7
|
if (['object', 'array'].includes(p.type)) {
|
|
8
8
|
if (isString(body[p.name])) {
|
|
@@ -18,7 +18,7 @@ async function sanitizeBody ({ body = {}, schema = {}, partial, strict }) {
|
|
|
18
18
|
}
|
|
19
19
|
} else result[p.name] = body[p.name]
|
|
20
20
|
if (isSet(body[p.name])) {
|
|
21
|
-
if (p.type === 'boolean') result[p.name] = result[p.name] === null ? null : (
|
|
21
|
+
if (p.type === 'boolean') result[p.name] = result[p.name] === null ? null : (['true', true].includes(result[p.name]))
|
|
22
22
|
if (['float', 'double'].includes(p.type)) {
|
|
23
23
|
if (isNumber(body[p.name])) result[p.name] = body[p.name]
|
|
24
24
|
else if (strict) {
|
|
@@ -50,10 +50,9 @@ async function sanitizeBody ({ body = {}, schema = {}, partial, strict }) {
|
|
|
50
50
|
} else {
|
|
51
51
|
if (p.default) {
|
|
52
52
|
result[p.name] = p.default
|
|
53
|
-
if (isString(p.default) && p.default.startsWith('
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
if (method) result[p.name] = await this[method]()
|
|
53
|
+
if (isString(p.default) && p.default.startsWith('handler:')) {
|
|
54
|
+
const [, ...args] = p.default.split(':')
|
|
55
|
+
if (args.length > 0) result[p.name] = await callHandler(args.join(':'))
|
|
57
56
|
} else {
|
|
58
57
|
if (['float', 'double'].includes(p.type)) result[p.name] = parseFloat(result[p.name]) || null
|
|
59
58
|
if (['integer', 'smallint'].includes(p.type)) result[p.name] = parseInt(result[p.name]) || null
|
|
@@ -5,17 +5,17 @@ async function aggregate (name, filter = {}, options = {}) {
|
|
|
5
5
|
const { dataOnly = true, noHook, aggregate } = options
|
|
6
6
|
options.dataOnly = false
|
|
7
7
|
await this.modelExists(name, true)
|
|
8
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'stat-aggregate')
|
|
8
|
+
const { handler, schema, driver } = await resolveMethod.call(this, name, 'stat-aggregate', options)
|
|
9
9
|
if (!noHook) {
|
|
10
|
-
await runHook(`${this.name}:
|
|
11
|
-
await runHook(`${this.name}.${name}:
|
|
10
|
+
await runHook(`${this.name}:beforeStatAggregate`, name, aggregate, filter, options)
|
|
11
|
+
await runHook(`${this.name}.${name}:beforeStatAggregate`, aggregate, filter, options)
|
|
12
12
|
}
|
|
13
|
-
const rec = await handler.call(this.app[driver.ns], { schema, filter, options })
|
|
14
13
|
filter.query = await this.buildQuery({ filter, schema, options }) ?? {}
|
|
15
14
|
filter.match = this.buildMatch({ input: filter.match, schema, options }) ?? {}
|
|
15
|
+
const rec = await handler.call(this.app[driver.ns], { schema, filter, options })
|
|
16
16
|
if (!noHook) {
|
|
17
|
-
await runHook(`${this.name}.${name}:
|
|
18
|
-
await runHook(`${this.name}:
|
|
17
|
+
await runHook(`${this.name}.${name}:afterStatAggregate`, aggregate, filter, options, rec)
|
|
18
|
+
await runHook(`${this.name}:afterStatAggregate`, name, aggregate, filter, options, rec)
|
|
19
19
|
}
|
|
20
20
|
return dataOnly ? rec.data : rec
|
|
21
21
|
}
|
|
@@ -8,17 +8,17 @@ async function histogram (name, filter = {}, options = {}) {
|
|
|
8
8
|
options.dataOnly = false
|
|
9
9
|
if (!types.includes(type)) throw this.error('Histogram type must be one of these: %s', join(types))
|
|
10
10
|
await this.modelExists(name, true)
|
|
11
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'stat-histogram')
|
|
11
|
+
const { handler, schema, driver } = await resolveMethod.call(this, name, 'stat-histogram', options)
|
|
12
12
|
filter.query = await this.buildQuery({ filter, schema, options }) ?? {}
|
|
13
13
|
filter.match = this.buildMatch({ input: filter.match, schema, options }) ?? {}
|
|
14
14
|
if (!noHook) {
|
|
15
|
-
await runHook(`${this.name}:
|
|
16
|
-
await runHook(`${this.name}.${name}:
|
|
15
|
+
await runHook(`${this.name}:beforeStatHistogram`, name, type, filter, options)
|
|
16
|
+
await runHook(`${this.name}.${name}:beforeStatHistogram`, type, filter, options)
|
|
17
17
|
}
|
|
18
18
|
const rec = await handler.call(this.app[driver.ns], { schema, type, filter, options })
|
|
19
19
|
if (!noHook) {
|
|
20
|
-
await runHook(`${this.name}.${name}:
|
|
21
|
-
await runHook(`${this.name}:
|
|
20
|
+
await runHook(`${this.name}.${name}:afterStatHistogram`, type, filter, options, rec)
|
|
21
|
+
await runHook(`${this.name}:afterStatHistogram`, name, type, filter, options, rec)
|
|
22
22
|
}
|
|
23
23
|
return dataOnly ? rec.data : rec
|
|
24
24
|
}
|
package/bajo/method/validate.js
CHANGED
|
@@ -15,25 +15,26 @@ const validator = {
|
|
|
15
15
|
timestamp: ['timestamp']
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function buildFromDbSchema (schema, { fields = [], rule = {},
|
|
18
|
+
function buildFromDbSchema (schema, { fields = [], rule = {}, extFields = [] } = {}) {
|
|
19
19
|
// if (schema.validation) return schema.validation
|
|
20
20
|
const {
|
|
21
21
|
isPlainObject, get, each, isEmpty, isString, forOwn, keys,
|
|
22
|
-
find, isArray, has, cloneDeep, concat
|
|
22
|
+
find, isArray, has, cloneDeep, concat, without
|
|
23
23
|
} = this.app.bajo.lib._
|
|
24
24
|
const obj = {}
|
|
25
25
|
const me = this
|
|
26
|
+
const refs = []
|
|
26
27
|
|
|
27
|
-
function getRuleKv (
|
|
28
|
+
function getRuleKv (kvRule) {
|
|
28
29
|
let key
|
|
29
30
|
let value
|
|
30
31
|
let columns
|
|
31
|
-
if (isPlainObject(
|
|
32
|
-
key =
|
|
33
|
-
value =
|
|
34
|
-
columns =
|
|
35
|
-
} else if (isString(
|
|
36
|
-
[key, value, columns] =
|
|
32
|
+
if (isPlainObject(kvRule)) {
|
|
33
|
+
key = kvRule.rule
|
|
34
|
+
value = kvRule.params
|
|
35
|
+
columns = kvRule.fields
|
|
36
|
+
} else if (isString(kvRule)) {
|
|
37
|
+
[key, value, columns] = kvRule.split(':')
|
|
37
38
|
}
|
|
38
39
|
return { key, value, columns }
|
|
39
40
|
}
|
|
@@ -42,30 +43,31 @@ function buildFromDbSchema (schema, { fields = [], rule = {}, extProperties = []
|
|
|
42
43
|
const minMax = { min: false, max: false }
|
|
43
44
|
const rules = get(rule, prop.name, prop.rules ?? [])
|
|
44
45
|
if (!isArray(rules)) return rules
|
|
45
|
-
let isRef
|
|
46
46
|
each(rules, r => {
|
|
47
47
|
const types = validator[me.propType[prop.type].validator]
|
|
48
48
|
const { key, value } = getRuleKv(r)
|
|
49
|
+
if (keys(minMax).includes(key)) minMax[key] = true
|
|
49
50
|
if (key === 'ref') {
|
|
50
|
-
|
|
51
|
+
refs.push(prop.name)
|
|
51
52
|
obj = joi.ref(value)
|
|
52
53
|
return undefined
|
|
53
54
|
}
|
|
54
55
|
if (!key || !types.includes(key)) return undefined
|
|
55
|
-
if (keys(minMax).includes(key)) minMax[key] = true
|
|
56
56
|
obj = obj[key](value)
|
|
57
57
|
})
|
|
58
|
-
if (
|
|
58
|
+
if (refs.includes(prop.name)) return obj
|
|
59
|
+
if (['string', 'text'].includes(prop.type)) {
|
|
59
60
|
forOwn(minMax, (v, k) => {
|
|
60
61
|
if (v) return undefined
|
|
61
62
|
if (has(prop, `${k}Length`)) obj = obj[k](prop[`${k}Length`])
|
|
62
63
|
})
|
|
63
64
|
}
|
|
64
|
-
if (
|
|
65
|
+
if (isArray(prop.values)) obj = obj.valid(...prop.values)
|
|
66
|
+
if (!['id'].includes(prop.name) && prop.required) obj = obj.required()
|
|
65
67
|
return obj
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
const props = concat(cloneDeep(schema.properties),
|
|
70
|
+
const props = concat(cloneDeep(schema.properties), extFields)
|
|
69
71
|
|
|
70
72
|
for (const p of props) {
|
|
71
73
|
if (excludedTypes.includes(p.type) || excludedNames.includes(p.name)) continue
|
|
@@ -105,7 +107,7 @@ function buildFromDbSchema (schema, { fields = [], rule = {}, extProperties = []
|
|
|
105
107
|
}
|
|
106
108
|
if (isEmpty(obj)) return false
|
|
107
109
|
each(get(schema, 'globalRules', []), r => {
|
|
108
|
-
each(keys(obj), k => {
|
|
110
|
+
each(without(keys(obj), ...refs), k => {
|
|
109
111
|
const prop = find(props, { name: k })
|
|
110
112
|
if (!prop) return undefined
|
|
111
113
|
const types = validator[me.propType[prop.type].validator]
|
|
@@ -123,13 +125,14 @@ function buildFromDbSchema (schema, { fields = [], rule = {}, extProperties = []
|
|
|
123
125
|
return result
|
|
124
126
|
}
|
|
125
127
|
|
|
126
|
-
async function validate (value, joiSchema, { ns, fields,
|
|
128
|
+
async function validate (value, joiSchema, { ns, fields, extFields, params } = {}) {
|
|
127
129
|
const { defaultsDeep, isSet } = this.app.bajo
|
|
128
130
|
const { isString, forOwn, find } = this.app.bajo.lib._
|
|
129
131
|
|
|
130
132
|
ns = ns ?? [this.name]
|
|
131
|
-
params = defaultsDeep(params,
|
|
132
|
-
const { rule } = params
|
|
133
|
+
params = defaultsDeep(params, this.config.validationParams)
|
|
134
|
+
const { rule = {} } = params
|
|
135
|
+
delete params.rule
|
|
133
136
|
if (isString(joiSchema)) {
|
|
134
137
|
const { schema } = this.getInfo(joiSchema)
|
|
135
138
|
forOwn(value, (v, k) => {
|
|
@@ -141,7 +144,7 @@ async function validate (value, joiSchema, { ns, fields, extProperties, params }
|
|
|
141
144
|
if (p.type === type) value[k] = this.sanitizeDate(value[k], { input, output: 'native' })
|
|
142
145
|
}
|
|
143
146
|
})
|
|
144
|
-
joiSchema = buildFromDbSchema.call(this, schema, { fields, rule,
|
|
147
|
+
joiSchema = buildFromDbSchema.call(this, schema, { fields, rule, extFields })
|
|
145
148
|
}
|
|
146
149
|
if (!joiSchema) return value
|
|
147
150
|
try {
|
package/bajo/start.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import memDbStart from '../lib/mem-db/start.js'
|
|
2
|
+
import memDbInstantiate from '../lib/mem-db/instantiate.js'
|
|
3
|
+
|
|
1
4
|
async function start (conns = 'all', noRebuild = true) {
|
|
2
5
|
const { importModule, breakNsPath } = this.app.bajo
|
|
3
6
|
const { find, filter, isString, map } = this.app.bajo.lib._
|
|
@@ -5,12 +8,13 @@ async function start (conns = 'all', noRebuild = true) {
|
|
|
5
8
|
else if (isString(conns)) conns = filter(this.connections, { name: conns })
|
|
6
9
|
else conns = map(conns, c => find(this.connections, { name: c }))
|
|
7
10
|
for (const c of conns) {
|
|
8
|
-
const
|
|
11
|
+
const { ns } = breakNsPath(c.type)
|
|
9
12
|
const schemas = filter(this.schemas, { connection: c.name })
|
|
10
|
-
const mod = await importModule(`${ns}:/${this.name}/boot/instantiate.js`)
|
|
13
|
+
const mod = c.type === 'dobo:memory' ? memDbInstantiate : await importModule(`${ns}:/${this.name}/boot/instantiate.js`)
|
|
11
14
|
await mod.call(this.app[ns], { connection: c, noRebuild, schemas })
|
|
12
15
|
this.log.trace('- Driver \'%s:%s\' instantiated', c.driver, c.name)
|
|
13
16
|
}
|
|
17
|
+
await memDbStart.call(this)
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export default start
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
const conns = []
|
|
2
2
|
|
|
3
|
-
async function postProcess ({ handler, params, path, processMsg, noConfirmation
|
|
4
|
-
const {
|
|
3
|
+
async function postProcess ({ handler, params, path, processMsg, noConfirmation } = {}) {
|
|
4
|
+
const { saveAsDownload, importPkg } = this.app.bajo
|
|
5
5
|
const { prettyPrint } = this.app.bajoCli.helper
|
|
6
6
|
const { find, get } = this.app.bajo.lib._
|
|
7
7
|
const [stripAnsi, confirm] = await importPkg('bajoCli:strip-ansi', 'bajoCli:@inquirer/confirm')
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
params.push({ fields: config.fields, dataOnly: !config.full })
|
|
8
|
+
if (!noConfirmation && this.config.confirmation === false) noConfirmation = true
|
|
9
|
+
params.push({ fields: this.config.fields, dataOnly: !this.config.full })
|
|
11
10
|
|
|
12
11
|
const schema = find(this.schemas, { name: params[0] })
|
|
13
|
-
if (!schema) return print.
|
|
12
|
+
if (!schema) return this.print.fatal('No schema found!')
|
|
14
13
|
let cont = true
|
|
15
14
|
if (!noConfirmation) {
|
|
16
|
-
const answer = await confirm({ message: print.write('Are you sure to continue?'), default: false })
|
|
15
|
+
const answer = await confirm({ message: this.print.write('Are you sure to continue?'), default: false })
|
|
17
16
|
if (!answer) {
|
|
18
|
-
print.fail('Aborted!')
|
|
17
|
+
this.print.fail('Aborted!')
|
|
19
18
|
cont = false
|
|
20
19
|
}
|
|
21
20
|
}
|
|
22
21
|
if (!cont) return
|
|
23
|
-
const spin = spinner().start(`${processMsg}...`)
|
|
22
|
+
const spin = this.print.spinner().start(`${processMsg}...`)
|
|
24
23
|
const { connection } = this.getInfo(schema)
|
|
25
24
|
if (!conns.includes(connection.name)) {
|
|
26
25
|
await this.start(connection.name)
|
|
@@ -29,19 +28,20 @@ async function postProcess ({ handler, params, path, processMsg, noConfirmation,
|
|
|
29
28
|
try {
|
|
30
29
|
const resp = await this[handler](...params)
|
|
31
30
|
spin.succeed('Done!')
|
|
32
|
-
const result = config.pretty ? (await prettyPrint(resp)) : JSON.stringify(resp, null, 2)
|
|
33
|
-
if (config.save) {
|
|
31
|
+
const result = this.config.pretty ? (await prettyPrint(resp)) : JSON.stringify(resp, null, 2)
|
|
32
|
+
if (this.config.save) {
|
|
34
33
|
const id = resp.id ?? get(resp, 'data.id') ?? get(resp, 'oldData.id')
|
|
35
34
|
const base = path === 'recordFind' ? params[0] : (params[0] + '/' + id)
|
|
36
|
-
const file = `/${path}/${base}.${config.pretty ? 'txt' : 'json'}`
|
|
35
|
+
const file = `/${path}/${base}.${this.config.pretty ? 'txt' : 'json'}`
|
|
37
36
|
await saveAsDownload(file, stripAnsi(result))
|
|
38
37
|
} else console.log(result)
|
|
39
38
|
} catch (err) {
|
|
40
|
-
if (config.log.
|
|
39
|
+
if (this.config.log.applet) {
|
|
41
40
|
spin.stop()
|
|
42
41
|
console.error(err)
|
|
43
42
|
} else spin.fail('Error: %s', err.message)
|
|
44
43
|
}
|
|
44
|
+
process.exit()
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export default postProcess
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import postProcess from './lib/post-process.js'
|
|
2
2
|
|
|
3
|
-
async function modelClear (
|
|
3
|
+
async function modelClear (...args) {
|
|
4
4
|
const { print } = this.app.bajo
|
|
5
5
|
const { isEmpty } = this.app.bajo.lib._
|
|
6
6
|
if (isEmpty(this.schemas)) return print.fail('No schema found!', { exit: this.app.bajo.applet })
|
|
7
7
|
const [schema] = args
|
|
8
|
-
await postProcess.call(this, { handler: 'modelClear', params: [schema], path, processMsg: 'Clear records'
|
|
8
|
+
await postProcess.call(this, { handler: 'modelClear', params: [schema], path: 'modelClear', processMsg: 'Clear records' })
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export default modelClear
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import addFixtures from '../../lib/add-fixtures.js'
|
|
2
2
|
|
|
3
|
-
async function modelRebuild (
|
|
4
|
-
const { importPkg
|
|
3
|
+
async function modelRebuild (...args) {
|
|
4
|
+
const { importPkg } = this.app.bajo
|
|
5
|
+
const { outmatch } = this.app.bajo.lib
|
|
5
6
|
const { isEmpty, map, trim } = this.app.bajo.lib._
|
|
6
|
-
const spinner = this.print.spinner
|
|
7
7
|
const [input, confirm, boxen] = await importPkg('bajoCli:@inquirer/input',
|
|
8
8
|
'bajoCli:@inquirer/confirm', 'bajoCli:boxen')
|
|
9
9
|
const schemas = map(this.schemas, 'name')
|
|
@@ -25,26 +25,28 @@ async function modelRebuild ({ path, args }) {
|
|
|
25
25
|
default: false
|
|
26
26
|
})
|
|
27
27
|
if (!answer) return this.print.fail('Aborted!', { exit: this.app.bajo.applet })
|
|
28
|
+
/*
|
|
28
29
|
const conns = []
|
|
29
30
|
for (const s of names) {
|
|
30
31
|
const { connection } = this.getInfo(s)
|
|
31
32
|
if (!conns.includes(connection.name)) conns.push(connection.name)
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
*/
|
|
35
|
+
await this.start('all')
|
|
34
36
|
const result = { succed: 0, failed: 0, skipped: 0 }
|
|
35
37
|
for (const s of names) {
|
|
36
38
|
const { schema, instance, connection } = this.getInfo(s)
|
|
37
|
-
const spin = spinner({ showCounter: true }).start('Rebuilding \'%s\'...', schema.name)
|
|
39
|
+
const spin = this.print.spinner({ showCounter: true }).start('Rebuilding \'%s\'...', schema.name)
|
|
38
40
|
if (!instance) {
|
|
39
41
|
spin.warn('Client instance not connected \'%s@%s\'. Skipped!', schema.connection, schema.name)
|
|
40
42
|
result.skipped++
|
|
41
43
|
continue
|
|
42
44
|
}
|
|
43
|
-
const exists = await this.modelExists(schema, false, spinner)
|
|
45
|
+
const exists = await this.modelExists(schema.name, false, { spinner: spin })
|
|
44
46
|
if (exists) {
|
|
45
47
|
if (this.app.bajo.config.force) {
|
|
46
48
|
try {
|
|
47
|
-
await this.modelDrop(schema, spinner)
|
|
49
|
+
await this.modelDrop(schema.name, { spinner: spin })
|
|
48
50
|
spin.setText('Model \'%s\' successfully dropped', schema.name)
|
|
49
51
|
} catch (err) {
|
|
50
52
|
spin.fail('Error on dropping model \'%s\': %s', schema.name, err.message)
|
|
@@ -58,10 +60,10 @@ async function modelRebuild ({ path, args }) {
|
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
try {
|
|
61
|
-
await this.modelCreate(schema, spinner)
|
|
63
|
+
await this.modelCreate(schema.name, { spinner: spin })
|
|
62
64
|
if (connection.memory) spin.succeed('Model \'%s\' successfully created', schema.name)
|
|
63
65
|
else {
|
|
64
|
-
const fixture = await addFixtures.call(this, schema, spin)
|
|
66
|
+
const fixture = await addFixtures.call(this, schema.name, { spinner: spin })
|
|
65
67
|
spin.succeed('Model \'%s\' successfully created, with fixture: added %d, rejected: %s', schema.name, fixture.success, fixture.failed)
|
|
66
68
|
}
|
|
67
69
|
result.succed++
|
|
@@ -72,6 +74,7 @@ async function modelRebuild ({ path, args }) {
|
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
this.print.info('Done! Succeded: %d, failed: %s, skipped: %d', result.succed, result.failed, result.skipped)
|
|
77
|
+
process.exit()
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
export default modelRebuild
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import postProcess from './lib/post-process.js'
|
|
2
2
|
|
|
3
|
-
async function createRecord (
|
|
3
|
+
async function createRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
5
|
const { isEmpty, map, isPlainObject } = this.app.bajo.lib._
|
|
6
6
|
const [input, select, boxen] = await importPkg('bajoCli:@inquirer/input',
|
|
@@ -35,7 +35,7 @@ async function createRecord ({ path, args, options }) {
|
|
|
35
35
|
return this.print.fail('Invalid payload syntax', { exit: this.app.bajo.applet })
|
|
36
36
|
}
|
|
37
37
|
console.log(boxen(JSON.stringify(payload, null, 2), { title: schema, padding: 0.5, borderStyle: 'round' }))
|
|
38
|
-
await postProcess.call(this, { handler: 'recordCreate', params: [schema, payload], path, processMsg: 'Creating record'
|
|
38
|
+
await postProcess.call(this, { handler: 'recordCreate', params: [schema, payload], path, processMsg: 'Creating record' })
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export default createRecord
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import postProcess from './lib/post-process.js'
|
|
2
2
|
|
|
3
|
-
async function findRecord (
|
|
3
|
+
async function findRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
5
|
const { isEmpty, map, pick } = this.app.bajo.lib._
|
|
6
6
|
const [select, input] = await importPkg('bajoCli:@inquirer/select', 'bajoCli:@inquirer/input')
|
|
@@ -21,7 +21,7 @@ async function findRecord ({ path, args, options }) {
|
|
|
21
21
|
const filter = pick(this.app.bajo.config, ['page', 'offset', 'pageSize', 'sort', 'limit'])
|
|
22
22
|
filter.pageSize = filter.pageSize ?? filter.limit
|
|
23
23
|
filter.query = query
|
|
24
|
-
await postProcess.call(this, { noConfirmation: true, handler: 'recordFind', params: [schema, filter], path, processMsg: 'Finding record(s)'
|
|
24
|
+
await postProcess.call(this, { noConfirmation: true, handler: 'recordFind', params: [schema, filter], path, processMsg: 'Finding record(s)' })
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export default findRecord
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import postProcess from './lib/post-process.js'
|
|
2
2
|
|
|
3
|
-
async function getRecord (
|
|
3
|
+
async function getRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
5
|
const { isEmpty, map } = this.app.bajo.lib._
|
|
6
6
|
const [input, select] = await importPkg('bajoCli:@inquirer/input', 'bajoCli:@inquirer/select')
|
|
@@ -18,7 +18,7 @@ async function getRecord ({ path, args, options }) {
|
|
|
18
18
|
validate: text => isEmpty(text) ? this.print.write('ID is required') : true
|
|
19
19
|
})
|
|
20
20
|
}
|
|
21
|
-
await postProcess.call(this, { noConfirmation: true, handler: 'recordGet', params: [schema, id], path, processMsg: 'Getting record'
|
|
21
|
+
await postProcess.call(this, { noConfirmation: true, handler: 'recordGet', params: [schema, id], path, processMsg: 'Getting record' })
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export default getRecord
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import postProcess from './lib/post-process.js'
|
|
2
2
|
|
|
3
|
-
async function removeRecord (
|
|
3
|
+
async function removeRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
5
|
const { isEmpty, map } = this.app.bajo.lib._
|
|
6
6
|
const [input, select] = await importPkg('bajoCli:@inquirer/input', 'bajoCli:@inquirer/select')
|
|
@@ -18,7 +18,7 @@ async function removeRecord ({ path, args, options }) {
|
|
|
18
18
|
validate: text => isEmpty(text) ? this.print.write('ID is required') : true
|
|
19
19
|
})
|
|
20
20
|
}
|
|
21
|
-
await postProcess.call(this, { handler: 'recordRemove', params: [schema, id], path, processMsg: 'Removing record'
|
|
21
|
+
await postProcess.call(this, { handler: 'recordRemove', params: [schema, id], path, processMsg: 'Removing record' })
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export default removeRecord
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import postProcess from './lib/post-process.js'
|
|
2
2
|
|
|
3
|
-
async function updateRecord (
|
|
3
|
+
async function updateRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
5
|
const { isEmpty, map, isPlainObject } = this.app.bajo.lib._
|
|
6
6
|
const [input, select, boxen] = await importPkg('bajoCli:@inquirer/input',
|
|
@@ -41,7 +41,7 @@ async function updateRecord ({ path, args, options }) {
|
|
|
41
41
|
return this.print.fail('Invalid payload syntax', { exit: this.app.bajo.applet })
|
|
42
42
|
}
|
|
43
43
|
console.log(boxen(JSON.stringify(payload, null, 2), { title: schema, padding: 0.5, borderStyle: 'round' }))
|
|
44
|
-
await postProcess.call(this, { handler: 'recordUpdate', params: [schema, id, payload], path, processMsg: 'Updating record'
|
|
44
|
+
await postProcess.call(this, { handler: 'recordUpdate', params: [schema, id, payload], path, processMsg: 'Updating record' })
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export default updateRecord
|
package/bajoCli/applet/schema.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import postProcess from './lib/post-process.js'
|
|
2
2
|
|
|
3
|
-
async function statCount (
|
|
3
|
+
async function statCount (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
5
|
const { isEmpty, map } = this.app.bajo.lib._
|
|
6
6
|
const [select, input] = await importPkg('bajoCli:@inquirer/select', 'bajoCli:@inquirer/input')
|
|
@@ -18,7 +18,7 @@ async function statCount ({ path, args, options }) {
|
|
|
18
18
|
})
|
|
19
19
|
}
|
|
20
20
|
const filter = { query }
|
|
21
|
-
await postProcess.call(this, { noConfirmation: true, handler: 'statCount', params: [schema, filter], path, processMsg: 'Counting record(s)'
|
|
21
|
+
await postProcess.call(this, { noConfirmation: true, handler: 'statCount', params: [schema, filter], path, processMsg: 'Counting record(s)' })
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export default statCount
|