dobo 1.1.0 → 1.1.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/bajo/intl/en-US.json +5 -1
- package/bajo/intl/id.json +0 -1
- package/bajoCli/applet/connection.js +1 -1
- package/bajoCli/applet/lib/post-process.js +1 -1
- package/bajoCli/applet/model-clear.js +1 -1
- package/bajoCli/applet/model-rebuild.js +27 -7
- package/bajoCli/applet/record-create.js +1 -1
- package/bajoCli/applet/record-find.js +1 -1
- package/bajoCli/applet/record-get.js +1 -1
- package/bajoCli/applet/record-remove.js +1 -1
- package/bajoCli/applet/record-update.js +1 -1
- package/bajoCli/applet/schema.js +1 -1
- package/bajoCli/applet/stat-count.js +1 -1
- package/dobo/feature/removed-at.js +85 -0
- package/lib/add-fixtures.js +1 -1
- package/lib/build-bulk-action.js +1 -1
- package/lib/check-unique.js +5 -5
- package/lib/collect-connections.js +1 -1
- package/lib/collect-drivers.js +1 -1
- package/lib/collect-feature.js +1 -1
- package/lib/collect-schemas.js +3 -3
- package/lib/exec-feature-hook.js +4 -3
- package/lib/exec-validation.js +1 -1
- package/lib/generic-prop-sanitizer.js +1 -1
- package/lib/handle-attachment-upload.js +1 -1
- package/lib/mem-db/conn-sanitizer.js +1 -1
- package/lib/mem-db/instantiate.js +2 -2
- package/lib/mem-db/method/record/find.js +1 -1
- package/lib/mem-db/method/record/get.js +1 -1
- package/lib/mem-db/method/record/remove.js +1 -1
- package/lib/mem-db/method/record/update.js +1 -1
- package/lib/mem-db/start.js +1 -1
- package/lib/merge-attachment-info.js +2 -2
- package/lib/resolve-method.js +2 -2
- package/lib/sanitize-schema.js +3 -3
- package/package.json +1 -1
- package/plugin/factory.js +324 -0
- package/plugin/method/attachment/copy-uploaded.js +1 -1
- package/plugin/method/attachment/create.js +1 -1
- package/plugin/method/attachment/find.js +1 -1
- package/plugin/method/attachment/get-path.js +1 -1
- package/plugin/method/attachment/get.js +1 -1
- package/plugin/method/attachment/remove.js +1 -1
- package/plugin/method/bulk/create.js +1 -1
- package/plugin/method/model/clear.js +1 -1
- package/plugin/method/model/create.js +1 -1
- package/plugin/method/model/drop.js +1 -1
- package/plugin/method/model/exists.js +1 -1
- package/plugin/method/record/clear.js +1 -1
- package/plugin/method/record/count.js +13 -8
- package/plugin/method/record/create.js +9 -8
- package/plugin/method/record/find-one.js +11 -4
- package/plugin/method/record/find.js +10 -4
- package/plugin/method/record/get.js +10 -4
- package/plugin/method/record/remove.js +9 -4
- package/plugin/method/record/update.js +6 -4
- package/plugin/method/record/upsert.js +20 -6
- package/plugin/method/sanitize/body.js +1 -1
- package/plugin/method/sanitize/date.js +1 -1
- package/plugin/method/validate.js +2 -2
- package/waibuMpa/route/attachment/@model/@id/@field/@file.js +9 -2
- package/plugin/.alias +0 -1
- package/plugin/config.json +0 -36
- package/plugin/init.js +0 -29
- package/plugin/method/aggregate-types.js +0 -1
- package/plugin/method/build-match.js +0 -34
- package/plugin/method/build-query.js +0 -14
- package/plugin/method/get-connection.js +0 -6
- package/plugin/method/get-info.js +0 -14
- package/plugin/method/get-schema.js +0 -10
- package/plugin/method/pick-record.js +0 -36
- package/plugin/method/prep-pagination.js +0 -63
- package/plugin/method/prop-type.js +0 -43
- package/plugin/method/validation-error-message.js +0 -12
- package/plugin/start.js +0 -20
package/bajo/intl/en-US.json
CHANGED
|
@@ -107,7 +107,6 @@
|
|
|
107
107
|
"unknownFeature%s%s": "'Unknown feature '%s@%s'",
|
|
108
108
|
"onlyAcceptFields%s%s": "Only accept array of field names or single string of field name '%s@%s'",
|
|
109
109
|
"invalidFieldName%s%s": "Invalid field name '%s@%s'",
|
|
110
|
-
"error%s": "Error: %s",
|
|
111
110
|
"succeedFailSkip%d%d%d": "Done! Succeded: %d, failed: %s, skipped: %d",
|
|
112
111
|
"chooseConn": "Please choose a connection:",
|
|
113
112
|
"sureContinue": "Are you sure to continue?",
|
|
@@ -117,6 +116,11 @@
|
|
|
117
116
|
"addingFixtureToMemDb": "Adding fixture for memory database",
|
|
118
117
|
"recordsAdded%s%d%d": "%s: %d of %d records added",
|
|
119
118
|
"driverInstantiated%s%s": "- Driver '%s:%s' instantiated",
|
|
119
|
+
"cantContinueAddFixture": "Can't continue with fixture adding because one or more models failed to rebuilt",
|
|
120
|
+
"addingFixture%s": "Adding fixture '%s'...",
|
|
121
|
+
"fixtureAdded%s%s%s": "Fixture on '%s': added %s, rejected: %s",
|
|
122
|
+
"errorAddingFixture%s%s": "Error adding fixture on model '%s': %s",
|
|
123
|
+
"memoryDbSkipped%s": "'%s' is a memory DB, skipped",
|
|
120
124
|
"field": {
|
|
121
125
|
"id": "ID",
|
|
122
126
|
"code": "Kode",
|
package/bajo/intl/id.json
CHANGED
|
@@ -105,7 +105,6 @@
|
|
|
105
105
|
"unknownFeature%s%s": "'Unknown feature '%s@%s'",
|
|
106
106
|
"onlyAcceptFields%s%s": "Only accept array of field names or single string of field name '%s@%s'",
|
|
107
107
|
"invalidFieldName%s%s": "Invalid field name '%s@%s'",
|
|
108
|
-
"error%s": "Error: %s",
|
|
109
108
|
"succeedFailSkip%d%d%d": "Done! Succeded: %d, failed: %s, skipped: %d",
|
|
110
109
|
"chooseConn": "Please choose a connection:",
|
|
111
110
|
"sureContinue": "Are you sure to continue?",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
async function connection (path, ...args) {
|
|
2
2
|
const { importPkg } = this.app.bajo
|
|
3
|
-
const { isEmpty, map, find } = this.
|
|
3
|
+
const { isEmpty, map, find } = this.lib._
|
|
4
4
|
const select = await importPkg('bajoCli:@inquirer/select')
|
|
5
5
|
const { getOutputFormat, writeOutput } = this.app.bajoCli
|
|
6
6
|
const format = getOutputFormat()
|
|
@@ -3,7 +3,7 @@ const conns = []
|
|
|
3
3
|
async function postProcess ({ handler, params, path, processMsg, noConfirmation } = {}) {
|
|
4
4
|
const { saveAsDownload, importPkg } = this.app.bajo
|
|
5
5
|
const { prettyPrint } = this.app.bajoCli.helper
|
|
6
|
-
const { find, get } = this.
|
|
6
|
+
const { find, get } = this.lib._
|
|
7
7
|
const [stripAnsi, confirm] = await importPkg('bajoCli:strip-ansi', 'bajoCli:@inquirer/confirm')
|
|
8
8
|
if (!noConfirmation && this.config.confirmation === false) noConfirmation = true
|
|
9
9
|
params.push({ fields: this.config.fields, dataOnly: !this.config.full })
|
|
@@ -2,7 +2,7 @@ import postProcess from './lib/post-process.js'
|
|
|
2
2
|
|
|
3
3
|
async function modelClear (...args) {
|
|
4
4
|
const { print } = this.app.bajo
|
|
5
|
-
const { isEmpty } = this.
|
|
5
|
+
const { isEmpty } = this.lib._
|
|
6
6
|
if (isEmpty(this.schemas)) return print.fail('notFound%s', 'schema', { exit: this.app.bajo.applet })
|
|
7
7
|
const [schema] = args
|
|
8
8
|
await postProcess.call(this, { handler: 'modelClear', params: [schema], path: 'modelClear', processMsg: 'Clear records' })
|
|
@@ -2,8 +2,8 @@ import addFixtures from '../../lib/add-fixtures.js'
|
|
|
2
2
|
|
|
3
3
|
async function modelRebuild (...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
|
-
const { outmatch } = this.
|
|
6
|
-
const { isEmpty, map, trim } = this.
|
|
5
|
+
const { outmatch } = this.lib
|
|
6
|
+
const { isEmpty, map, trim, without } = this.lib._
|
|
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')
|
|
@@ -34,14 +34,20 @@ async function modelRebuild (...args) {
|
|
|
34
34
|
*/
|
|
35
35
|
await this.start('all')
|
|
36
36
|
const result = { succed: 0, failed: 0, skipped: 0 }
|
|
37
|
+
const skipped = []
|
|
37
38
|
for (const s of names) {
|
|
38
39
|
const { schema, instance, connection } = this.getInfo(s)
|
|
39
40
|
const spin = this.print.spinner({ showCounter: true }).start('rebuilding%s', schema.name)
|
|
40
41
|
if (!instance) {
|
|
41
42
|
spin.warn('clientInstanceNotConnected%s', schema.connection, schema.name)
|
|
43
|
+
skipped.push(schema.name)
|
|
42
44
|
result.skipped++
|
|
43
45
|
continue
|
|
44
46
|
}
|
|
47
|
+
if (connection.memory) {
|
|
48
|
+
spin.warn('memoryDbSkipped%s', schema.name)
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
45
51
|
const exists = await this.modelExists(schema.name, false, { spinner: spin })
|
|
46
52
|
if (exists) {
|
|
47
53
|
if (this.app.bajo.config.force) {
|
|
@@ -61,11 +67,7 @@ async function modelRebuild (...args) {
|
|
|
61
67
|
}
|
|
62
68
|
try {
|
|
63
69
|
await this.modelCreate(schema.name, { spinner: spin })
|
|
64
|
-
|
|
65
|
-
else {
|
|
66
|
-
const fixture = await addFixtures.call(this, schema.name, { spinner: spin })
|
|
67
|
-
spin.succeed('modelCreatedWithFixture%s%s%s', schema.name, fixture.success, fixture.failed)
|
|
68
|
-
}
|
|
70
|
+
spin.succeed('modelCreated%s', schema.name)
|
|
69
71
|
result.succed++
|
|
70
72
|
} catch (err) {
|
|
71
73
|
if (this.app.bajo.config.log.applet && this.app.bajo.config.log.level === 'trace') console.error(err)
|
|
@@ -74,6 +76,24 @@ async function modelRebuild (...args) {
|
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
this.print.info('succeedFailSkip%d%d%d', result.succed, result.failed, result.skipped)
|
|
79
|
+
if (result.failed > 0) this.print.fatal('cantContinueAddFixture')
|
|
80
|
+
for (const s of without(names, ...skipped)) {
|
|
81
|
+
const { schema, connection } = this.getInfo(s)
|
|
82
|
+
const spin = this.print.spinner({ showCounter: true }).start('addingFixture%s', schema.name)
|
|
83
|
+
if (connection.memory) {
|
|
84
|
+
spin.warn('memoryDbSkipped%s', schema.name)
|
|
85
|
+
continue
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const fixture = await addFixtures.call(this, schema.name, { spinner: spin })
|
|
89
|
+
spin.succeed('fixtureAdded%s%s%s', schema.name, fixture.success, fixture.failed)
|
|
90
|
+
result.succed++
|
|
91
|
+
} catch (err) {
|
|
92
|
+
if (this.app.bajo.config.log.applet && this.app.bajo.config.log.level === 'trace') console.error(err)
|
|
93
|
+
spin.fail('errorAddingFixture%s%s', schema.name, err.message)
|
|
94
|
+
result.failed++
|
|
95
|
+
}
|
|
96
|
+
}
|
|
77
97
|
process.exit()
|
|
78
98
|
}
|
|
79
99
|
|
|
@@ -2,7 +2,7 @@ import postProcess from './lib/post-process.js'
|
|
|
2
2
|
|
|
3
3
|
async function createRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
|
-
const { isEmpty, map, isPlainObject } = this.
|
|
5
|
+
const { isEmpty, map, isPlainObject } = this.lib._
|
|
6
6
|
const [input, select, boxen] = await importPkg('bajoCli:@inquirer/input',
|
|
7
7
|
'bajoCli:@inquirer/select', 'bajoCli:boxen')
|
|
8
8
|
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
|
@@ -2,7 +2,7 @@ import postProcess from './lib/post-process.js'
|
|
|
2
2
|
|
|
3
3
|
async function findRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
|
-
const { isEmpty, map, pick } = this.
|
|
5
|
+
const { isEmpty, map, pick } = this.lib._
|
|
6
6
|
const [select, input] = await importPkg('bajoCli:@inquirer/select', 'bajoCli:@inquirer/input')
|
|
7
7
|
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
|
8
8
|
let [schema, query] = args
|
|
@@ -2,7 +2,7 @@ import postProcess from './lib/post-process.js'
|
|
|
2
2
|
|
|
3
3
|
async function getRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
|
-
const { isEmpty, map } = this.
|
|
5
|
+
const { isEmpty, map } = this.lib._
|
|
6
6
|
const [input, select] = await importPkg('bajoCli:@inquirer/input', 'bajoCli:@inquirer/select')
|
|
7
7
|
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
|
8
8
|
let [schema, id] = args
|
|
@@ -2,7 +2,7 @@ import postProcess from './lib/post-process.js'
|
|
|
2
2
|
|
|
3
3
|
async function removeRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
|
-
const { isEmpty, map } = this.
|
|
5
|
+
const { isEmpty, map } = this.lib._
|
|
6
6
|
const [input, select] = await importPkg('bajoCli:@inquirer/input', 'bajoCli:@inquirer/select')
|
|
7
7
|
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
|
8
8
|
let [schema, id] = args
|
|
@@ -2,7 +2,7 @@ import postProcess from './lib/post-process.js'
|
|
|
2
2
|
|
|
3
3
|
async function updateRecord (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
|
-
const { isEmpty, map, isPlainObject } = this.
|
|
5
|
+
const { isEmpty, map, isPlainObject } = this.lib._
|
|
6
6
|
const [input, select, boxen] = await importPkg('bajoCli:@inquirer/input',
|
|
7
7
|
'bajoCli:@inquirer/select', 'bajoCli:boxen')
|
|
8
8
|
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
package/bajoCli/applet/schema.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
async function schema (path, ...args) {
|
|
2
2
|
const { importPkg } = this.app.bajo
|
|
3
|
-
const { isEmpty, map, find } = this.
|
|
3
|
+
const { isEmpty, map, find } = this.lib._
|
|
4
4
|
const { getOutputFormat, writeOutput } = this.app.bajoCli
|
|
5
5
|
const select = await importPkg('bajoCli:@inquirer/select')
|
|
6
6
|
const format = getOutputFormat()
|
|
@@ -2,7 +2,7 @@ import postProcess from './lib/post-process.js'
|
|
|
2
2
|
|
|
3
3
|
async function statCount (path, ...args) {
|
|
4
4
|
const { importPkg } = this.app.bajo
|
|
5
|
-
const { isEmpty, map } = this.
|
|
5
|
+
const { isEmpty, map } = this.lib._
|
|
6
6
|
const [select, input] = await importPkg('bajoCli:@inquirer/select', 'bajoCli:@inquirer/input')
|
|
7
7
|
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
|
8
8
|
let [schema, query] = args
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
async function beforeFind ({ filter = {}, options }, opts) {
|
|
2
|
+
filter.query = filter.query ?? {}
|
|
3
|
+
const { isEmpty, set } = this.lib._
|
|
4
|
+
const q = { $and: [] }
|
|
5
|
+
if (!isEmpty(filter.query)) {
|
|
6
|
+
if (filter.query.$and) q.$and.push(...filter.query.$and)
|
|
7
|
+
else q.$and.push(filter.query)
|
|
8
|
+
}
|
|
9
|
+
q.$and.push(set({}, opts.fieldName, null))
|
|
10
|
+
filter.query = q
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function afterFind ({ records }, opts) {
|
|
14
|
+
for (const rec of records.data) {
|
|
15
|
+
delete rec[opts.fieldName]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function afterGet ({ schema, id, record }, opts) {
|
|
20
|
+
const { isEmpty } = this.lib._
|
|
21
|
+
if (!isEmpty(record.data[opts.fieldName])) throw this.error('recordNotFound%s%s', id, schema.name, { statusCode: 404 })
|
|
22
|
+
delete record.data[opts.fieldName]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function beforeCreate ({ body }, opts) {
|
|
26
|
+
delete body[opts.fieldName]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function afterCreate ({ record }, opts) {
|
|
30
|
+
delete record.data[opts.fieldName]
|
|
31
|
+
if (record.oldData) delete record.oldData[opts.fieldName]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function removedAt (opts = {}) {
|
|
35
|
+
opts.fieldName = opts.fieldName ?? 'removedAt'
|
|
36
|
+
return {
|
|
37
|
+
properties: {
|
|
38
|
+
name: opts.fieldName,
|
|
39
|
+
type: 'datetime',
|
|
40
|
+
index: true
|
|
41
|
+
},
|
|
42
|
+
hook: {
|
|
43
|
+
beforeFind: async function ({ filter, options }) {
|
|
44
|
+
await beforeFind.call(this, { filter, options }, opts)
|
|
45
|
+
},
|
|
46
|
+
beforeFindOne: async function ({ filter, options }) {
|
|
47
|
+
await beforeFind.call(this, { filter, options }, opts)
|
|
48
|
+
},
|
|
49
|
+
afterFind: async function ({ records }) {
|
|
50
|
+
await afterFind.call(this, { records }, opts)
|
|
51
|
+
},
|
|
52
|
+
afterFindOne: async function ({ record }) {
|
|
53
|
+
await afterGet.call(this, { record }, opts)
|
|
54
|
+
},
|
|
55
|
+
afterGet: async function ({ record }) {
|
|
56
|
+
await afterGet.call(this, { record }, opts)
|
|
57
|
+
},
|
|
58
|
+
beforeCreate: async function ({ body }) {
|
|
59
|
+
await beforeCreate.call(this, { body }, opts)
|
|
60
|
+
},
|
|
61
|
+
afterCreate: async function ({ record }) {
|
|
62
|
+
await afterCreate.call(this, { record }, opts)
|
|
63
|
+
},
|
|
64
|
+
beforeUpdate: async function ({ schema, id, body, options }) {
|
|
65
|
+
await beforeCreate.call(this, { body }, opts)
|
|
66
|
+
},
|
|
67
|
+
afterUpdate: async function ({ record }) {
|
|
68
|
+
await afterCreate.call(this, { record }, opts)
|
|
69
|
+
},
|
|
70
|
+
beforeRemove: async function ({ schema, id, options }) {
|
|
71
|
+
const { recordUpdate, recordGet } = this.app.dobo
|
|
72
|
+
await recordGet(schema.name, id, options)
|
|
73
|
+
const { set } = this.lib._
|
|
74
|
+
const body = set({}, opts.fieldName, new Date())
|
|
75
|
+
const record = await recordUpdate(schema.name, id, body, { dataOnly: false, noValidation: true, noFeatureHook: true })
|
|
76
|
+
options.record = { oldData: record.oldData }
|
|
77
|
+
},
|
|
78
|
+
afterRemove: async function ({ record }) {
|
|
79
|
+
delete record.oldData[opts.fieldName]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default removedAt
|
package/lib/add-fixtures.js
CHANGED
|
@@ -2,7 +2,7 @@ import path from 'path'
|
|
|
2
2
|
|
|
3
3
|
async function addFixture (name, { spinner } = {}) {
|
|
4
4
|
const { resolvePath, readConfig, eachPlugins } = this.app.bajo
|
|
5
|
-
const { isEmpty, isArray } = this.
|
|
5
|
+
const { isEmpty, isArray } = this.lib._
|
|
6
6
|
const { schema, connection } = this.getInfo(name)
|
|
7
7
|
if (connection.proxy) {
|
|
8
8
|
this.log.warn('proxiedConnBound%s', schema.name)
|
package/lib/build-bulk-action.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
async function buildBulkAction (name, action, options = {}) {
|
|
2
2
|
const { fs, importModule } = this.app.bajo
|
|
3
|
-
const { camelCase } = this.
|
|
3
|
+
const { camelCase } = this.lib._
|
|
4
4
|
const { schema, driver, connection } = await this.getInfo(name)
|
|
5
5
|
if (!options.force && (schema.disabled ?? []).includes(action)) throw this.error('methodIsDisabled%s%s', camelCase('bulk ' + action), name)
|
|
6
6
|
const file = `${driver.plugin}:/${this.name}/method/bulk/${action}.js`
|
package/lib/check-unique.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
async function checkUnique ({ schema, body, id }) {
|
|
2
2
|
const { isSet } = this.app.bajo
|
|
3
|
-
const { filter, map, set } = this.
|
|
3
|
+
const { filter, map, set } = this.lib._
|
|
4
4
|
const singles = map(filter(schema.properties, p => (p.index ?? {}).type === 'unique'), 'name')
|
|
5
|
-
const opts = { noHook: true, noCache: true, thrownNotFound: false,
|
|
5
|
+
const opts = { noHook: true, noCache: true, thrownNotFound: false, forceNoHidden: true }
|
|
6
6
|
let old = {}
|
|
7
7
|
if (id) old = (await this.recordGet(schema.name, id, opts)) ?? {}
|
|
8
8
|
for (const s of singles) {
|
|
@@ -12,7 +12,7 @@ async function checkUnique ({ schema, body, id }) {
|
|
|
12
12
|
const resp = await this.recordFind(schema.name, { query, limit: 1 }, opts)
|
|
13
13
|
if (resp.length !== 0) {
|
|
14
14
|
const details = [{ field: s, error: 'uniqueConstraintError', value: id }]
|
|
15
|
-
throw this.error('uniqueConstraintError', { details })
|
|
15
|
+
throw this.error('uniqueConstraintError', { details, body })
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
const multis = filter(schema.indexes, i => i.type === 'unique')
|
|
@@ -26,12 +26,12 @@ async function checkUnique ({ schema, body, id }) {
|
|
|
26
26
|
query[f] = body[f]
|
|
27
27
|
}
|
|
28
28
|
if (empty || same) continue
|
|
29
|
-
const resp = await this.recordFind(schema.name, { query, limit: 1 }, { noHook: true, noCache: true,
|
|
29
|
+
const resp = await this.recordFind(schema.name, { query, limit: 1 }, { noHook: true, noCache: true, forceNoHidden: true })
|
|
30
30
|
if (resp.length !== 0) {
|
|
31
31
|
const details = map(m.fields, f => {
|
|
32
32
|
return { field: f, error: 'Unique constraint error' }
|
|
33
33
|
})
|
|
34
|
-
throw this.error('Unique constraint error', { details })
|
|
34
|
+
throw this.error('Unique constraint error', { details, body })
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -5,7 +5,7 @@ async function defSanitizer (item) {
|
|
|
5
5
|
async function collectConnections ({ item, index, options }) {
|
|
6
6
|
const conn = item
|
|
7
7
|
const { importModule, breakNsPath } = this.app.bajo
|
|
8
|
-
const { has, find } = this.
|
|
8
|
+
const { has, find } = this.lib._
|
|
9
9
|
if (!has(conn, 'type')) this.fatal('mustValidDbType')
|
|
10
10
|
const { ns, path: type } = breakNsPath(conn.type)
|
|
11
11
|
const driver = find(this.drivers, { ns, type })
|
package/lib/collect-drivers.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
async function collectDrivers () {
|
|
2
2
|
const { eachPlugins, readConfig, runHook } = this.app.bajo
|
|
3
|
-
const { isString, find, pick, merge, cloneDeep } = this.
|
|
3
|
+
const { isString, find, pick, merge, cloneDeep } = this.lib._
|
|
4
4
|
const me = this
|
|
5
5
|
me.drivers = []
|
|
6
6
|
// built-in memory driver
|
package/lib/collect-feature.js
CHANGED
|
@@ -2,7 +2,7 @@ import path from 'path'
|
|
|
2
2
|
|
|
3
3
|
async function handler ({ file, alias, ns }) {
|
|
4
4
|
const { importModule } = this.app.bajo
|
|
5
|
-
const { camelCase, isFunction } = this.
|
|
5
|
+
const { camelCase, isFunction } = this.lib._
|
|
6
6
|
const me = this.app.dobo
|
|
7
7
|
|
|
8
8
|
let name = camelCase(path.basename(file, '.js'))
|
package/lib/collect-schemas.js
CHANGED
|
@@ -3,8 +3,8 @@ import sanitizeSchema from './sanitize-schema.js'
|
|
|
3
3
|
|
|
4
4
|
async function handler ({ file, alias, ns }) {
|
|
5
5
|
const { readConfig, pascalCase, eachPlugins } = this.app.bajo
|
|
6
|
-
const { get, isPlainObject, each, find, has, isArray, forOwn, isString, merge } = this.
|
|
7
|
-
const { fastGlob } = this.
|
|
6
|
+
const { get, isPlainObject, each, find, has, isArray, forOwn, isString, merge } = this.lib._
|
|
7
|
+
const { fastGlob } = this.lib
|
|
8
8
|
|
|
9
9
|
const base = path.basename(file, path.extname(file))
|
|
10
10
|
const defName = pascalCase(`${alias} ${base}`)
|
|
@@ -70,7 +70,7 @@ async function handler ({ file, alias, ns }) {
|
|
|
70
70
|
|
|
71
71
|
async function collectSchemas () {
|
|
72
72
|
const { eachPlugins } = this.app.bajo
|
|
73
|
-
const { isEmpty } = this.
|
|
73
|
+
const { isEmpty } = this.lib._
|
|
74
74
|
const result = await eachPlugins(handler, { glob: 'schema/*.*', prefix: this.name })
|
|
75
75
|
if (isEmpty(result)) this.log.warn('notFound%s', this.print.write('schema'))
|
|
76
76
|
else await sanitizeSchema.call(this, result)
|
package/lib/exec-feature-hook.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
async function execFeatureHook (name,
|
|
2
|
-
const { get } = this.
|
|
1
|
+
async function execFeatureHook (name, params = {}) {
|
|
2
|
+
const { get } = this.lib._
|
|
3
|
+
const { schema } = params
|
|
3
4
|
for (const f of schema.feature) {
|
|
4
5
|
const fn = get(this.feature, f.name)
|
|
5
6
|
if (!fn) continue
|
|
6
7
|
const input = await fn.call(this, f)
|
|
7
8
|
const hook = get(input, 'hook.' + name)
|
|
8
|
-
if (hook) await hook.call(this,
|
|
9
|
+
if (hook) await hook.call(this, params)
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
12
|
|
package/lib/exec-validation.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
async function execValidation ({ name, body, options, partial }) {
|
|
2
2
|
const { runHook } = this.app.bajo
|
|
3
|
-
const { keys, camelCase } = this.
|
|
3
|
+
const { keys, camelCase } = this.lib._
|
|
4
4
|
const { noHook } = options
|
|
5
5
|
if (!noHook) {
|
|
6
6
|
await runHook(`${this.name}:beforeRecordValidation`, name, body, options)
|
|
@@ -2,7 +2,7 @@ const indexTypes = ['default', 'unique', 'primary', 'fulltext']
|
|
|
2
2
|
|
|
3
3
|
async function genericPropSanitizer ({ prop, schema, driver }) {
|
|
4
4
|
const { join } = this.app.bajo
|
|
5
|
-
const { has, get, each } = this.
|
|
5
|
+
const { has, get, each } = this.lib._
|
|
6
6
|
const def = this.propType[prop.type]
|
|
7
7
|
// detect from drivers
|
|
8
8
|
if (prop.type === 'string') {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
async function handleAttachmentUpload ({ action, name, id, options = {} } = {}) {
|
|
2
2
|
const { getPluginDataDir } = this.app.bajo
|
|
3
|
-
const { fs } = this.
|
|
3
|
+
const { fs } = this.lib
|
|
4
4
|
const { req, mimeType, stats, setFile, setField } = options
|
|
5
5
|
|
|
6
6
|
name = this.attachmentPreCheck(name)
|
|
@@ -2,8 +2,8 @@ let saving = false
|
|
|
2
2
|
|
|
3
3
|
async function instantiate ({ connection, schemas, noRebuild }) {
|
|
4
4
|
const { getPluginDataDir } = this.app.bajo
|
|
5
|
-
const { fs } = this.
|
|
6
|
-
const { pick } = this.
|
|
5
|
+
const { fs } = this.lib
|
|
6
|
+
const { pick } = this.lib._
|
|
7
7
|
this.memDb = this.memDb ?? {}
|
|
8
8
|
this.memDb.storage = this.memDb.storage ?? {}
|
|
9
9
|
this.memDb.instances = this.memDb.instances ?? []
|
|
@@ -2,7 +2,7 @@ import { Query } from 'mingo'
|
|
|
2
2
|
|
|
3
3
|
async function find ({ schema, filter = {}, options = {} }) {
|
|
4
4
|
const { prepPagination } = this.app.dobo
|
|
5
|
-
const { omit } = this.
|
|
5
|
+
const { omit } = this.lib._
|
|
6
6
|
const { limit, skip, sort, page } = await prepPagination(filter, schema)
|
|
7
7
|
const criteria = filter.query ?? {}
|
|
8
8
|
const q = new Query(criteria, { idKey: 'id' })
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
async function get ({ schema, id, options = {} }) {
|
|
2
2
|
const { thrownNotFound = true } = options
|
|
3
|
-
const { find } = this.
|
|
3
|
+
const { find } = this.lib._
|
|
4
4
|
const result = find(this.memDb.storage[schema.name], { id })
|
|
5
5
|
if (!result && thrownNotFound) throw this.error('recordNotFound%s%s', id, schema.name, { statusCode: 404 })
|
|
6
6
|
return { data: result }
|
|
@@ -2,7 +2,7 @@ import getRecord from './get.js'
|
|
|
2
2
|
|
|
3
3
|
async function remove ({ schema, id, options = {} }) {
|
|
4
4
|
const { noResult } = options
|
|
5
|
-
const { findIndex, pullAt } = this.
|
|
5
|
+
const { findIndex, pullAt } = this.lib._
|
|
6
6
|
const rec = noResult ? undefined : await getRecord.call(this, { schema, id })
|
|
7
7
|
const idx = findIndex(this.memDb.storage[schema.name], { id })
|
|
8
8
|
pullAt(this.memDb.storage[schema.name], [idx])
|
|
@@ -2,7 +2,7 @@ import getRecord from './get.js'
|
|
|
2
2
|
|
|
3
3
|
async function update ({ schema, id, body, options }) {
|
|
4
4
|
const { noResult } = options
|
|
5
|
-
const { findIndex, merge } = this.
|
|
5
|
+
const { findIndex, merge } = this.lib._
|
|
6
6
|
const old = noResult ? undefined : await getRecord.call(this, { schema, id })
|
|
7
7
|
const idx = findIndex(this.memDb.storage[schema.name], { id })
|
|
8
8
|
const current = this.memDb.storage[schema.name][idx]
|
package/lib/mem-db/start.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import addFixtures from '../add-fixtures.js'
|
|
2
2
|
|
|
3
3
|
async function start () {
|
|
4
|
-
const { filter, map } = this.
|
|
4
|
+
const { filter, map } = this.lib._
|
|
5
5
|
|
|
6
6
|
const conns = filter(this.connections, { type: 'dobo:memory' })
|
|
7
7
|
const schemas = filter(this.schemas, s => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
async function mergeAttachmentInfo (rec, source, { mimeType, stats, fullPath }) {
|
|
2
2
|
const { importPkg } = this.app.bajo
|
|
3
|
-
const { fs } = this.
|
|
4
|
-
const { pick } = this.
|
|
3
|
+
const { fs } = this.lib
|
|
4
|
+
const { pick } = this.lib._
|
|
5
5
|
if (!this.app.waibu) return
|
|
6
6
|
const mime = await importPkg('waibu:mime')
|
|
7
7
|
|
package/lib/resolve-method.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
async function resolveMethod (name, method, options = {}) {
|
|
2
2
|
const { importModule } = this.app.bajo
|
|
3
|
-
const { fs } = this.
|
|
4
|
-
const { camelCase } = this.
|
|
3
|
+
const { fs } = this.lib
|
|
4
|
+
const { camelCase } = this.lib._
|
|
5
5
|
const { schema, driver, connection } = this.getInfo(name)
|
|
6
6
|
const [group, action] = method.split('-')
|
|
7
7
|
if (!options.force && (schema.disabled ?? []).includes(action)) throw this.error('methodIsDisabled%s%s', camelCase(method), name)
|
package/lib/sanitize-schema.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import genericPropSanitizer from './generic-prop-sanitizer.js'
|
|
2
2
|
|
|
3
3
|
async function sanitizeFeature (item) {
|
|
4
|
-
const { get, isPlainObject, mergeWith, isArray } = this.
|
|
4
|
+
const { get, isPlainObject, mergeWith, isArray } = this.lib._
|
|
5
5
|
for (const f of item.feature) {
|
|
6
6
|
const feature = get(this.feature, f.name) // source from collectFeature
|
|
7
7
|
if (!feature) this.fatal('unknownFeature%s%s', f.name, item.name)
|
|
@@ -36,7 +36,7 @@ async function sanitizeFullText (item) {
|
|
|
36
36
|
|
|
37
37
|
async function sanitizeSchema (items) {
|
|
38
38
|
const { freeze, fatal, importModule, defaultsDeep, join, breakNsPath, runHook } = this.app.bajo
|
|
39
|
-
const { map, keys, findIndex, find, each, isString, get, isPlainObject, camelCase, uniq, filter } = this.
|
|
39
|
+
const { map, keys, findIndex, find, each, isString, get, isPlainObject, camelCase, uniq, filter } = this.lib._
|
|
40
40
|
const propTypes = keys(this.propType)
|
|
41
41
|
const schemas = []
|
|
42
42
|
this.log.debug('loadingDbSchemas')
|
|
@@ -151,7 +151,7 @@ async function sanitizeSchema (items) {
|
|
|
151
151
|
}
|
|
152
152
|
const rprop = find(rel.properties, { name: def.propName })
|
|
153
153
|
if (!rprop) fatal.call(this, 'No property found for relationship \'%s@%s:%s\'', `${def.schema}:${def.propName}`, schema.name, prop.name)
|
|
154
|
-
def.fields = def.fields ??
|
|
154
|
+
def.fields = def.fields ?? '*'
|
|
155
155
|
if (['*', 'all'].includes(def.fields)) {
|
|
156
156
|
const relschema = find(schemas, { name: def.schema })
|
|
157
157
|
def.fields = relschema.properties.map(p => p.name)
|