dobo 1.0.13 → 1.0.15
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/init.js +2 -2
- package/bajo/intl/en-US.json +215 -0
- package/bajo/intl/id.json +228 -0
- package/bajo/method/attachment/copy-uploaded.js +2 -2
- package/bajo/method/attachment/create.js +2 -2
- package/bajo/method/attachment/remove.js +1 -1
- package/bajo/method/get-schema.js +1 -1
- package/bajo/method/model/exists.js +1 -1
- package/bajo/method/prep-pagination.js +1 -1
- package/bajo/method/record/create.js +1 -1
- package/bajo/method/record/remove.js +1 -1
- package/bajo/method/record/update.js +1 -1
- package/bajo/method/sanitize/date.js +1 -1
- package/bajo/method/stat/histogram.js +1 -1
- package/bajo/method/validate.js +1 -1
- package/bajo/start.js +1 -1
- package/bajoCli/applet/connection.js +4 -4
- package/bajoCli/applet/lib/post-process.js +5 -5
- package/bajoCli/applet/model-clear.js +1 -1
- package/bajoCli/applet/model-rebuild.js +14 -14
- package/bajoCli/applet/record-create.js +6 -6
- package/bajoCli/applet/record-find.js +3 -3
- package/bajoCli/applet/record-get.js +1 -1
- package/bajoCli/applet/record-remove.js +1 -1
- package/bajoCli/applet/record-update.js +8 -8
- package/bajoCli/applet/schema.js +4 -4
- package/bajoCli/applet/stat-count.js +3 -3
- package/lib/add-fixtures.js +3 -4
- package/lib/build-bulk-action.js +2 -2
- package/lib/check-unique.js +2 -2
- package/lib/collect-connections.js +2 -2
- package/lib/collect-drivers.js +3 -3
- package/lib/collect-feature.js +3 -3
- package/lib/collect-schemas.js +3 -3
- package/lib/generic-prop-sanitizer.js +2 -9
- package/lib/mem-db/instantiate.js +1 -1
- package/lib/mem-db/method/record/create.js +1 -1
- package/lib/mem-db/method/record/get.js +1 -1
- package/lib/mem-db/start.js +2 -2
- package/lib/resolve-method.js +2 -2
- package/lib/sanitize-schema.js +5 -5
- package/package.json +1 -1
- package/bajoI18N/resource/en-US.json +0 -92
- package/bajoI18N/resource/id.json +0 -185
|
@@ -9,12 +9,12 @@ async function postProcess ({ handler, params, path, processMsg, noConfirmation
|
|
|
9
9
|
params.push({ fields: this.config.fields, dataOnly: !this.config.full })
|
|
10
10
|
|
|
11
11
|
const schema = find(this.schemas, { name: params[0] })
|
|
12
|
-
if (!schema) return this.print.fatal('
|
|
12
|
+
if (!schema) return this.print.fatal('notFound%s', this.print.write('field.schema'))
|
|
13
13
|
let cont = true
|
|
14
14
|
if (!noConfirmation) {
|
|
15
|
-
const answer = await confirm({ message: this.print.write('
|
|
15
|
+
const answer = await confirm({ message: this.print.write('sureContinue'), default: false })
|
|
16
16
|
if (!answer) {
|
|
17
|
-
this.print.fail('
|
|
17
|
+
this.print.fail('aborted')
|
|
18
18
|
cont = false
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -27,7 +27,7 @@ async function postProcess ({ handler, params, path, processMsg, noConfirmation
|
|
|
27
27
|
}
|
|
28
28
|
try {
|
|
29
29
|
const resp = await this[handler](...params)
|
|
30
|
-
spin.succeed('
|
|
30
|
+
spin.succeed('done')
|
|
31
31
|
const result = this.config.pretty ? (await prettyPrint(resp)) : JSON.stringify(resp, null, 2)
|
|
32
32
|
if (this.config.save) {
|
|
33
33
|
const id = resp.id ?? get(resp, 'data.id') ?? get(resp, 'oldData.id')
|
|
@@ -39,7 +39,7 @@ async function postProcess ({ handler, params, path, processMsg, noConfirmation
|
|
|
39
39
|
if (this.config.log.applet) {
|
|
40
40
|
spin.stop()
|
|
41
41
|
console.error(err)
|
|
42
|
-
} else spin.fail('
|
|
42
|
+
} else spin.fail('error%s', err.message)
|
|
43
43
|
}
|
|
44
44
|
process.exit()
|
|
45
45
|
}
|
|
@@ -3,7 +3,7 @@ import postProcess from './lib/post-process.js'
|
|
|
3
3
|
async function modelClear (...args) {
|
|
4
4
|
const { print } = this.app.bajo
|
|
5
5
|
const { isEmpty } = this.app.bajo.lib._
|
|
6
|
-
if (isEmpty(this.schemas)) return print.fail('
|
|
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' })
|
|
9
9
|
}
|
|
@@ -8,10 +8,10 @@ async function modelRebuild (...args) {
|
|
|
8
8
|
'bajoCli:@inquirer/confirm', 'bajoCli:boxen')
|
|
9
9
|
const schemas = map(this.schemas, 'name')
|
|
10
10
|
let names = args.join(' ')
|
|
11
|
-
if (isEmpty(schemas)) return this.print.fail('
|
|
11
|
+
if (isEmpty(schemas)) return this.print.fail('notFound%s', 'schema', { exit: this.app.bajo.applet })
|
|
12
12
|
if (isEmpty(names)) {
|
|
13
13
|
names = await input({
|
|
14
|
-
message: this.print.write('
|
|
14
|
+
message: this.print.write('enterSchemaName'),
|
|
15
15
|
default: '*'
|
|
16
16
|
})
|
|
17
17
|
}
|
|
@@ -19,12 +19,12 @@ async function modelRebuild (...args) {
|
|
|
19
19
|
names = schemas.filter(isMatch)
|
|
20
20
|
if (names.length === 0) return this.print.fail('No schema matched', true, { exit: this.app.bajo.applet })
|
|
21
21
|
names = names.sort()
|
|
22
|
-
console.log(boxen(names.join(' '), { title: this.print.write('
|
|
22
|
+
console.log(boxen(names.join(' '), { title: this.print.write('schema%d', names.length), padding: 0.5, borderStyle: 'round' }))
|
|
23
23
|
const answer = await confirm({
|
|
24
|
-
message: this.print.write('
|
|
24
|
+
message: this.print.write('schemasWillBeRebuiltContinue'),
|
|
25
25
|
default: false
|
|
26
26
|
})
|
|
27
|
-
if (!answer) return this.print.fail('
|
|
27
|
+
if (!answer) return this.print.fail('aborted', { exit: this.app.bajo.applet })
|
|
28
28
|
/*
|
|
29
29
|
const conns = []
|
|
30
30
|
for (const s of names) {
|
|
@@ -36,9 +36,9 @@ async function modelRebuild (...args) {
|
|
|
36
36
|
const result = { succed: 0, failed: 0, skipped: 0 }
|
|
37
37
|
for (const s of names) {
|
|
38
38
|
const { schema, instance, connection } = this.getInfo(s)
|
|
39
|
-
const spin = this.print.spinner({ showCounter: true }).start('
|
|
39
|
+
const spin = this.print.spinner({ showCounter: true }).start('rebuilding%s', schema.name)
|
|
40
40
|
if (!instance) {
|
|
41
|
-
spin.warn('
|
|
41
|
+
spin.warn('clientInstanceNotConnected%s', schema.connection, schema.name)
|
|
42
42
|
result.skipped++
|
|
43
43
|
continue
|
|
44
44
|
}
|
|
@@ -47,33 +47,33 @@ async function modelRebuild (...args) {
|
|
|
47
47
|
if (this.app.bajo.config.force) {
|
|
48
48
|
try {
|
|
49
49
|
await this.modelDrop(schema.name, { spinner: spin })
|
|
50
|
-
spin.setText('
|
|
50
|
+
spin.setText('modelDropped%s', schema.name)
|
|
51
51
|
} catch (err) {
|
|
52
|
-
spin.fail('
|
|
52
|
+
spin.fail('errorDroppingModel%s%s', schema.name, err.message)
|
|
53
53
|
result.failed++
|
|
54
54
|
continue
|
|
55
55
|
}
|
|
56
56
|
} else {
|
|
57
|
-
spin.fail('
|
|
57
|
+
spin.fail('modelExistsNeedForce%s', schema.name)
|
|
58
58
|
result.failed++
|
|
59
59
|
continue
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
try {
|
|
63
63
|
await this.modelCreate(schema.name, { spinner: spin })
|
|
64
|
-
if (connection.memory) spin.succeed('
|
|
64
|
+
if (connection.memory) spin.succeed('modelCreated%s', schema.name)
|
|
65
65
|
else {
|
|
66
66
|
const fixture = await addFixtures.call(this, schema.name, { spinner: spin })
|
|
67
|
-
spin.succeed('
|
|
67
|
+
spin.succeed('modelCreatedWithFixture%s%s%s', schema.name, fixture.success, fixture.failed)
|
|
68
68
|
}
|
|
69
69
|
result.succed++
|
|
70
70
|
} catch (err) {
|
|
71
71
|
if (this.app.bajo.config.log.applet && this.app.bajo.config.log.level === 'trace') console.error(err)
|
|
72
|
-
spin.fail('
|
|
72
|
+
spin.fail('errorCreatingModel%s%s', schema.name, err.message)
|
|
73
73
|
result.failed++
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
this.print.info('
|
|
76
|
+
this.print.info('succeedFailSkip%d%d%d', result.succed, result.failed, result.skipped)
|
|
77
77
|
process.exit()
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -5,24 +5,24 @@ async function createRecord (path, ...args) {
|
|
|
5
5
|
const { isEmpty, map, isPlainObject } = this.app.bajo.lib._
|
|
6
6
|
const [input, select, boxen] = await importPkg('bajoCli:@inquirer/input',
|
|
7
7
|
'bajoCli:@inquirer/select', 'bajoCli:boxen')
|
|
8
|
-
if (isEmpty(this.schemas)) return this.print.fail('
|
|
8
|
+
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
|
9
9
|
let [schema, body] = args
|
|
10
10
|
if (isEmpty(schema)) {
|
|
11
11
|
schema = await select({
|
|
12
|
-
message: this.print.write('
|
|
12
|
+
message: this.print.write('selectSchema'),
|
|
13
13
|
choices: map(this.schemas, s => ({ value: s.name }))
|
|
14
14
|
})
|
|
15
15
|
}
|
|
16
16
|
if (isEmpty(body)) {
|
|
17
17
|
body = await input({
|
|
18
|
-
message: this.print.write('
|
|
18
|
+
message: this.print.write('enterJsonPayload'),
|
|
19
19
|
validate: text => {
|
|
20
|
-
if (isEmpty(text)) return this.print.write('
|
|
20
|
+
if (isEmpty(text)) return this.print.write('payloadRequired')
|
|
21
21
|
try {
|
|
22
22
|
const parsed = JSON.parse(text)
|
|
23
23
|
if (!isPlainObject(parsed)) throw new Error()
|
|
24
24
|
} catch (err) {
|
|
25
|
-
return this.print.write('
|
|
25
|
+
return this.print.write('payloadMustBeJson')
|
|
26
26
|
}
|
|
27
27
|
return true
|
|
28
28
|
}
|
|
@@ -32,7 +32,7 @@ async function createRecord (path, ...args) {
|
|
|
32
32
|
try {
|
|
33
33
|
payload = JSON.parse(body)
|
|
34
34
|
} catch (err) {
|
|
35
|
-
return this.print.fail('
|
|
35
|
+
return this.print.fail('invalidPayloadSyntax', { 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
38
|
await postProcess.call(this, { handler: 'recordCreate', params: [schema, payload], path, processMsg: 'Creating record' })
|
|
@@ -4,17 +4,17 @@ 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')
|
|
7
|
-
if (isEmpty(this.schemas)) return this.print.fail('
|
|
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
|
|
9
9
|
if (isEmpty(schema)) {
|
|
10
10
|
schema = await select({
|
|
11
|
-
message: this.print.write('
|
|
11
|
+
message: this.print.write('selectSchema'),
|
|
12
12
|
choices: map(this.schemas, s => ({ value: s.name }))
|
|
13
13
|
})
|
|
14
14
|
}
|
|
15
15
|
if (isEmpty(query)) {
|
|
16
16
|
query = await input({
|
|
17
|
-
message: this.print.write('
|
|
17
|
+
message: this.print.write('enterQueryIfAny')
|
|
18
18
|
})
|
|
19
19
|
}
|
|
20
20
|
if (isEmpty(query)) query = {}
|
|
@@ -4,7 +4,7 @@ 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')
|
|
7
|
-
if (isEmpty(this.schemas)) return this.print.fail('
|
|
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
|
|
9
9
|
if (isEmpty(schema)) {
|
|
10
10
|
schema = await select({
|
|
@@ -4,7 +4,7 @@ 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')
|
|
7
|
-
if (isEmpty(this.schemas)) return this.print.fail('
|
|
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
|
|
9
9
|
if (isEmpty(schema)) {
|
|
10
10
|
schema = await select({
|
|
@@ -5,30 +5,30 @@ async function updateRecord (path, ...args) {
|
|
|
5
5
|
const { isEmpty, map, isPlainObject } = this.app.bajo.lib._
|
|
6
6
|
const [input, select, boxen] = await importPkg('bajoCli:@inquirer/input',
|
|
7
7
|
'bajoCli:@inquirer/select', 'bajoCli:boxen')
|
|
8
|
-
if (isEmpty(this.schemas)) return this.print.fail('
|
|
8
|
+
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
|
9
9
|
let [schema, id, body] = args
|
|
10
10
|
if (isEmpty(schema)) {
|
|
11
11
|
schema = await select({
|
|
12
|
-
message: this.print.write('
|
|
12
|
+
message: this.print.write('selectSchema'),
|
|
13
13
|
choices: map(this.schemas, s => ({ value: s.name }))
|
|
14
14
|
})
|
|
15
15
|
}
|
|
16
16
|
if (isEmpty(id)) {
|
|
17
17
|
id = await input({
|
|
18
|
-
message: this.print.write('
|
|
19
|
-
validate: text => isEmpty(text) ? this.print.write('
|
|
18
|
+
message: this.print.write('enterRecordId'),
|
|
19
|
+
validate: text => isEmpty(text) ? this.print.write('idIsRequired') : true
|
|
20
20
|
})
|
|
21
21
|
}
|
|
22
22
|
if (isEmpty(body)) {
|
|
23
23
|
body = await input({
|
|
24
|
-
message: this.print.write('
|
|
24
|
+
message: this.print.write('enterJsonPayload'),
|
|
25
25
|
validate: text => {
|
|
26
|
-
if (isEmpty(text)) return this.print.write('
|
|
26
|
+
if (isEmpty(text)) return this.print.write('payloadRequired')
|
|
27
27
|
try {
|
|
28
28
|
const parsed = JSON.parse(text)
|
|
29
29
|
if (!isPlainObject(parsed)) throw new Error()
|
|
30
30
|
} catch (err) {
|
|
31
|
-
return this.print.write('
|
|
31
|
+
return this.print.write('payloadMustBeJson')
|
|
32
32
|
}
|
|
33
33
|
return true
|
|
34
34
|
}
|
|
@@ -38,7 +38,7 @@ async function updateRecord (path, ...args) {
|
|
|
38
38
|
try {
|
|
39
39
|
payload = JSON.parse(body)
|
|
40
40
|
} catch (err) {
|
|
41
|
-
return this.print.fail('
|
|
41
|
+
return this.print.fail('invalidPayloadSyntax', { 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
44
|
await postProcess.call(this, { handler: 'recordUpdate', params: [schema, id, payload], path, processMsg: 'Updating record' })
|
package/bajoCli/applet/schema.js
CHANGED
|
@@ -4,18 +4,18 @@ async function schema (path, ...args) {
|
|
|
4
4
|
const { getOutputFormat, writeOutput } = this.app.bajoCli
|
|
5
5
|
const select = await importPkg('bajoCli:@inquirer/select')
|
|
6
6
|
const format = getOutputFormat()
|
|
7
|
-
if (isEmpty(this.schemas)) return this.print.fail('
|
|
7
|
+
if (isEmpty(this.schemas)) return this.print.fail('notFound%s', this.print.write('field.schema'), { exit: this.app.bajo.applet })
|
|
8
8
|
let name = args[0]
|
|
9
9
|
if (isEmpty(name)) {
|
|
10
10
|
const choices = map(this.schemas, s => ({ value: s.name }))
|
|
11
11
|
name = await select({
|
|
12
|
-
message: this.print.write('
|
|
12
|
+
message: this.print.write('selectSchema'),
|
|
13
13
|
choices
|
|
14
14
|
})
|
|
15
15
|
}
|
|
16
16
|
const result = find(this.schemas, { name })
|
|
17
|
-
if (!result) return this.print.fail('
|
|
18
|
-
this.print.info('
|
|
17
|
+
if (!result) return this.print.fail('cantFindSchema%s', this.print.write('schema'), name, { exit: this.app.bajo.applet })
|
|
18
|
+
this.print.info('done')
|
|
19
19
|
await writeOutput(result, path, format)
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -4,17 +4,17 @@ 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')
|
|
7
|
-
if (isEmpty(this.schemas)) return this.print.fail('
|
|
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
|
|
9
9
|
if (isEmpty(schema)) {
|
|
10
10
|
schema = await select({
|
|
11
|
-
message: this.print.write('
|
|
11
|
+
message: this.print.write('selectSchema'),
|
|
12
12
|
choices: map(this.schemas, s => ({ value: s.name }))
|
|
13
13
|
})
|
|
14
14
|
}
|
|
15
15
|
if (isEmpty(query)) {
|
|
16
16
|
query = await input({
|
|
17
|
-
message: this.print.write('
|
|
17
|
+
message: this.print.write('enterQueryIfAny')
|
|
18
18
|
})
|
|
19
19
|
}
|
|
20
20
|
const filter = { query }
|
package/lib/add-fixtures.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
2
|
|
|
3
3
|
async function addFixture (name, { spinner } = {}) {
|
|
4
|
-
const { resolvePath, readConfig, eachPlugins
|
|
4
|
+
const { resolvePath, readConfig, eachPlugins } = this.app.bajo
|
|
5
5
|
const { isEmpty, isArray } = this.app.bajo.lib._
|
|
6
6
|
const { schema, connection } = this.getInfo(name)
|
|
7
7
|
if (connection.proxy) {
|
|
8
|
-
this.log.warn('
|
|
8
|
+
this.log.warn('proxiedConnBound%s', schema.name)
|
|
9
9
|
return
|
|
10
10
|
}
|
|
11
11
|
const result = { success: 0, failed: 0 }
|
|
@@ -39,12 +39,11 @@ async function addFixture (name, { spinner } = {}) {
|
|
|
39
39
|
}
|
|
40
40
|
await this.recordCreate(schema.name, item, { force: true })
|
|
41
41
|
result.success++
|
|
42
|
-
if (spinner) spinner.setText('%s
|
|
42
|
+
if (spinner) spinner.setText('recordsAdded%s%d%d', schema.name, result.success, items.length)
|
|
43
43
|
} catch (err) {
|
|
44
44
|
console.log(err)
|
|
45
45
|
err.model = schema.name
|
|
46
46
|
if (this.app.bajo.applet) this.print.fail(this.validationErrorMessage(err))
|
|
47
|
-
// else this.log.error('Add fixture \'%s@%s\' error: %s', schema.name, schema.connection, err.message)
|
|
48
47
|
result.failed++
|
|
49
48
|
}
|
|
50
49
|
}
|
package/lib/build-bulk-action.js
CHANGED
|
@@ -2,9 +2,9 @@ async function buildBulkAction (name, action, options = {}) {
|
|
|
2
2
|
const { fs, importModule } = this.app.bajo
|
|
3
3
|
const { camelCase } = this.app.bajo.lib._
|
|
4
4
|
const { schema, driver, connection } = await this.getInfo(name)
|
|
5
|
-
if (!options.force && (schema.disabled ?? []).includes(action)) throw this.error('
|
|
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`
|
|
7
|
-
if (!fs.existsSync(file)) throw this.error('
|
|
7
|
+
if (!fs.existsSync(file)) throw this.error('methodUnsupported%s%s', camelCase('bulk ' + action), name)
|
|
8
8
|
const handler = await importModule(file)
|
|
9
9
|
return { handler, schema, driver, connection }
|
|
10
10
|
}
|
package/lib/check-unique.js
CHANGED
|
@@ -11,8 +11,8 @@ async function checkUnique ({ schema, body, id }) {
|
|
|
11
11
|
const query = set({}, s, body[s])
|
|
12
12
|
const resp = await this.recordFind(schema.name, { query, limit: 1 }, opts)
|
|
13
13
|
if (resp.length !== 0) {
|
|
14
|
-
const details = [{ field: s, error: '
|
|
15
|
-
throw this.error('
|
|
14
|
+
const details = [{ field: s, error: 'uniqueConstraintError', value: id }]
|
|
15
|
+
throw this.error('uniqueConstraintError', { details })
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
const multis = filter(schema.indexes, i => i.type === 'unique')
|
|
@@ -6,10 +6,10 @@ async function collectConnections ({ item, index, options }) {
|
|
|
6
6
|
const conn = item
|
|
7
7
|
const { importModule, breakNsPath } = this.app.bajo
|
|
8
8
|
const { has, find } = this.app.bajo.lib._
|
|
9
|
-
if (!has(conn, 'type')) this.fatal('
|
|
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 })
|
|
12
|
-
if (!driver) this.fatal('
|
|
12
|
+
if (!driver) this.fatal('unsupportedDbType%s', conn.type)
|
|
13
13
|
let file = `${ns}:/${this.name}/lib/${type}/conn-sanitizer.js`
|
|
14
14
|
if (conn.type === 'dobo:memory') file = `${ns}:/lib/mem-db/conn-sanitizer.js`
|
|
15
15
|
if (driver.provider) file = `${driver.provider}:/${ns}/lib/${type}/conn-sanitizer.js`
|
package/lib/collect-drivers.js
CHANGED
|
@@ -14,15 +14,15 @@ async function collectDrivers () {
|
|
|
14
14
|
await runHook(`${this.name}:beforeCollectDrivers`)
|
|
15
15
|
await eachPlugins(async function ({ file, ns }) {
|
|
16
16
|
const info = await readConfig(file, { ns })
|
|
17
|
-
if (!info.type) this.fatal('
|
|
18
|
-
if (!info.driver) this.fatal('
|
|
17
|
+
if (!info.type) this.fatal('driverMustProvideDbType')
|
|
18
|
+
if (!info.driver) this.fatal('driverMustHaveName')
|
|
19
19
|
if (isString(info.type)) info.type = [info.type]
|
|
20
20
|
if (!info.idField) info.idField = cloneDeep(me.config.default.idField)
|
|
21
21
|
info.idField.name = 'id'
|
|
22
22
|
for (const t of info.type) {
|
|
23
23
|
const [type, provider] = t.split('@')
|
|
24
24
|
const exists = find(me.drivers, { type, ns })
|
|
25
|
-
if (exists) this.fatal('
|
|
25
|
+
if (exists) this.fatal('dbTypeAlreadySupportedByDriver%s%s', type, info.driver)
|
|
26
26
|
const driver = pick(find(me.app[ns].drivers, { name: type }) ?? {}, ['dialect', 'idField', 'lowerCaseColl', 'returning'])
|
|
27
27
|
const ext = {
|
|
28
28
|
type,
|
package/lib/collect-feature.js
CHANGED
|
@@ -8,7 +8,7 @@ async function handler ({ file, alias, ns }) {
|
|
|
8
8
|
let name = camelCase(path.basename(file, '.js'))
|
|
9
9
|
if (ns !== me.name) name = `${ns}.${name}`
|
|
10
10
|
const mod = await importModule(file)
|
|
11
|
-
if (!isFunction(mod)) this.fatal('
|
|
11
|
+
if (!isFunction(mod)) this.fatal('featureNotAsync%s', name)
|
|
12
12
|
me.feature[name] = mod
|
|
13
13
|
me.log.trace('- %s', name)
|
|
14
14
|
}
|
|
@@ -16,9 +16,9 @@ async function handler ({ file, alias, ns }) {
|
|
|
16
16
|
async function collectFeature () {
|
|
17
17
|
const { eachPlugins } = this.app.bajo
|
|
18
18
|
this.feature = {}
|
|
19
|
-
this.log.trace('
|
|
19
|
+
this.log.trace('loadingDbFeature')
|
|
20
20
|
await eachPlugins(handler, { glob: 'feature/*.js', prefix: this.name })
|
|
21
|
-
this.log.debug('
|
|
21
|
+
this.log.debug('totalLoadedFeatures%d', Object.keys(this.feature).length)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export default collectFeature
|
package/lib/collect-schemas.js
CHANGED
|
@@ -9,7 +9,7 @@ async function handler ({ file, alias, ns }) {
|
|
|
9
9
|
const base = path.basename(file, path.extname(file))
|
|
10
10
|
const defName = pascalCase(`${alias} ${base}`)
|
|
11
11
|
const mod = await readConfig(file, { ns, ignoreError: true })
|
|
12
|
-
if (!isPlainObject(mod)) this.fatal('
|
|
12
|
+
if (!isPlainObject(mod)) this.fatal('invalidSchema%s', defName)
|
|
13
13
|
const forcedConn = get(this, `app.${ns}.config.dobo.schemaConnection.${base}`)
|
|
14
14
|
if (forcedConn) mod.connection = forcedConn
|
|
15
15
|
if (!mod.connection) mod.connection = 'default'
|
|
@@ -30,7 +30,7 @@ async function handler ({ file, alias, ns }) {
|
|
|
30
30
|
})
|
|
31
31
|
}
|
|
32
32
|
mod.feature = feats
|
|
33
|
-
if ((mod.properties ?? []).length === 0) this.fatal('
|
|
33
|
+
if ((mod.properties ?? []).length === 0) this.fatal('noPropsFoundOnSchema%s', mod.name)
|
|
34
34
|
// schema extender
|
|
35
35
|
await eachPlugins(async function (opts) {
|
|
36
36
|
const glob = `${opts.dir}/dobo/extend/${mod.ns}/schema/${base}.*`
|
|
@@ -71,7 +71,7 @@ async function collectSchemas () {
|
|
|
71
71
|
const { eachPlugins } = this.app.bajo
|
|
72
72
|
const { isEmpty } = this.app.bajo.lib._
|
|
73
73
|
const result = await eachPlugins(handler, { glob: 'schema/*.*', prefix: this.name })
|
|
74
|
-
if (isEmpty(result)) this.log.warn('
|
|
74
|
+
if (isEmpty(result)) this.log.warn('notFound%s', this.print.write('schema'))
|
|
75
75
|
else await sanitizeSchema.call(this, result)
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -5,11 +5,6 @@ async function genericPropSanitizer ({ prop, schema, driver }) {
|
|
|
5
5
|
const { has, get, each } = this.app.bajo.lib._
|
|
6
6
|
const def = this.propType[prop.type]
|
|
7
7
|
// detect from drivers
|
|
8
|
-
/*
|
|
9
|
-
if (prop.name === 'id' && ['smallint', 'integer'].includes(prop.type) && driver.driver !== 'knex') {
|
|
10
|
-
fatal('Integer types of ID only supported by knex driver')
|
|
11
|
-
}
|
|
12
|
-
*/
|
|
13
8
|
if (prop.type === 'string') {
|
|
14
9
|
def.minLength = prop.minLength ?? 0
|
|
15
10
|
def.maxLength = prop.maxLength ?? 255
|
|
@@ -25,13 +20,11 @@ async function genericPropSanitizer ({ prop, schema, driver }) {
|
|
|
25
20
|
}
|
|
26
21
|
prop[p] = get(prop, p, get(this.config, `default.property.${prop.type}.${p}`, def[p]))
|
|
27
22
|
if (def.choices && !def.choices.includes(prop[p])) {
|
|
28
|
-
this.fatal('
|
|
29
|
-
p, prop[p], prop.name, schema.name, join(def.choices))
|
|
23
|
+
this.fatal('unsupportedAllowedChoices%s%s%s%s%s', p, prop[p], prop.name, schema.name, join(def.choices))
|
|
30
24
|
}
|
|
31
25
|
})
|
|
32
26
|
if (prop.index && !indexTypes.includes(prop.index.type)) {
|
|
33
|
-
this.fatal('
|
|
34
|
-
prop.index.type, prop.name, schema.name, join(indexTypes))
|
|
27
|
+
this.fatal('unsupportedIndexType%s%s%s%s', prop.index.type, prop.name, schema.name, join(indexTypes))
|
|
35
28
|
}
|
|
36
29
|
}
|
|
37
30
|
|
|
@@ -24,7 +24,7 @@ async function instantiate ({ connection, schemas, noRebuild }) {
|
|
|
24
24
|
const data = fs.readFileSync(file, 'utf8')
|
|
25
25
|
this.memDb.storage[schema.name] = JSON.parse(data)
|
|
26
26
|
} catch (err) {
|
|
27
|
-
this.fatal('
|
|
27
|
+
this.fatal('cantLoad%s%s', schema.name, err.message)
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
setInterval(() => {
|
|
@@ -3,7 +3,7 @@ import getRecord from './get.js'
|
|
|
3
3
|
async function create ({ schema, body, options = {} }) {
|
|
4
4
|
const { noResult } = options
|
|
5
5
|
const exist = await getRecord.call(this, { schema, id: body.id, options: { thrownNotFound: false } })
|
|
6
|
-
if (exist.data) throw this.error('
|
|
6
|
+
if (exist.data) throw this.error('recordExists%s%s', body.id, schema.name)
|
|
7
7
|
this.memDb.storage[schema.name].push(body)
|
|
8
8
|
if (noResult) return
|
|
9
9
|
return { data: body }
|
|
@@ -2,7 +2,7 @@ async function get ({ schema, id, options = {} }) {
|
|
|
2
2
|
const { thrownNotFound = true } = options
|
|
3
3
|
const { find } = this.app.bajo.lib._
|
|
4
4
|
const result = find(this.memDb.storage[schema.name], { id })
|
|
5
|
-
if (!result && thrownNotFound) throw this.error('
|
|
5
|
+
if (!result && thrownNotFound) throw this.error('recordNotFound%s%s', id, schema.name, { statusCode: 404 })
|
|
6
6
|
return { data: result }
|
|
7
7
|
}
|
|
8
8
|
|
package/lib/mem-db/start.js
CHANGED
|
@@ -9,10 +9,10 @@ async function start () {
|
|
|
9
9
|
return names.includes(s.connection)
|
|
10
10
|
})
|
|
11
11
|
if (schemas.length === 0) return
|
|
12
|
-
this.log.debug('
|
|
12
|
+
this.log.debug('addingFixtureToMemDb')
|
|
13
13
|
for (const schema of schemas) {
|
|
14
14
|
if (schema.persistence) {
|
|
15
|
-
this.log.warn('
|
|
15
|
+
this.log.warn('addingMemoryPersistenceIgnored', schema.name)
|
|
16
16
|
continue
|
|
17
17
|
}
|
|
18
18
|
let { success, error } = await addFixtures.call(this, schema.name)
|
package/lib/resolve-method.js
CHANGED
|
@@ -4,11 +4,11 @@ async function resolveMethod (name, method, options = {}) {
|
|
|
4
4
|
const { camelCase } = this.app.bajo.lib._
|
|
5
5
|
const { schema, driver, connection } = this.getInfo(name)
|
|
6
6
|
const [group, action] = method.split('-')
|
|
7
|
-
if (!options.force && (schema.disabled ?? []).includes(action)) throw this.error('
|
|
7
|
+
if (!options.force && (schema.disabled ?? []).includes(action)) throw this.error('methodIsDisabled%s%s', camelCase(method), name)
|
|
8
8
|
let file
|
|
9
9
|
if (connection.name === 'memory') file = `${this.app[driver.ns].dir.pkg}/lib/mem-db/method/${group}/${action}.js`
|
|
10
10
|
else file = `${this.app[driver.ns].dir.pkg}/${this.name}/method/${group}/${action}.js`
|
|
11
|
-
if (!fs.existsSync(file)) throw this.error('
|
|
11
|
+
if (!fs.existsSync(file)) throw this.error('methodUnsupported%s%s', camelCase(method), name)
|
|
12
12
|
const handler = await importModule(file)
|
|
13
13
|
return { handler, schema, driver, connection }
|
|
14
14
|
}
|
package/lib/sanitize-schema.js
CHANGED
|
@@ -4,7 +4,7 @@ async function sanitizeFeature (item) {
|
|
|
4
4
|
const { get, isPlainObject, mergeWith, isArray } = this.app.bajo.lib._
|
|
5
5
|
for (const f of item.feature) {
|
|
6
6
|
const feature = get(this.feature, f.name) // source from collectFeature
|
|
7
|
-
if (!feature) this.fatal('
|
|
7
|
+
if (!feature) this.fatal('unknownFeature%s%s', f.name, item.name)
|
|
8
8
|
let [ns, path] = f.name.split('.')
|
|
9
9
|
if (!path) ns = this.name
|
|
10
10
|
const input = await feature.call(this.app[ns], f)
|
|
@@ -22,14 +22,14 @@ async function sanitizeFeature (item) {
|
|
|
22
22
|
|
|
23
23
|
async function sanitizeIndexes (item) {
|
|
24
24
|
for (const idx of item.indexes) {
|
|
25
|
-
if (!(typeof idx.fields === 'string' || Array.isArray(idx.fields))) this.fatal('
|
|
25
|
+
if (!(typeof idx.fields === 'string' || Array.isArray(idx.fields))) this.fatal('onlyAccepFields%s%s', 'indexes', item.name)
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async function sanitizeFullText (item) {
|
|
30
30
|
for (const f of item.fullText.fields ?? []) {
|
|
31
31
|
const prop = item.properties.find(p => p.name === f)
|
|
32
|
-
if (!prop) this.fatal('
|
|
32
|
+
if (!prop) this.fatal('invalidFieldName%s%s', f, item.name)
|
|
33
33
|
// if (prop.type !== 'text') fatal.call(this, 'Fulltext index only available for field type \'text\' in \'%s@%s\'', f, item.name)
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -39,7 +39,7 @@ async function sanitizeSchema (items) {
|
|
|
39
39
|
const { map, keys, findIndex, find, each, isString, get, isPlainObject, camelCase, uniq, filter } = this.app.bajo.lib._
|
|
40
40
|
const propTypes = keys(this.propType)
|
|
41
41
|
const schemas = []
|
|
42
|
-
this.log.debug('
|
|
42
|
+
this.log.debug('loadingDbSchemas')
|
|
43
43
|
for (const k in items) {
|
|
44
44
|
this.log.trace('- %s (%d)', k, keys(items[k]).length)
|
|
45
45
|
for (const f in items[k]) {
|
|
@@ -187,7 +187,7 @@ async function sanitizeSchema (items) {
|
|
|
187
187
|
}
|
|
188
188
|
this.schemas = schemas
|
|
189
189
|
freeze(this.schemas)
|
|
190
|
-
this.log.debug('
|
|
190
|
+
this.log.debug('loadedSchemas%s', join(map(this.schemas, 'name')))
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
export default sanitizeSchema
|